1185029Spjd/* $NetBSD: altq_conf.c,v 1.22 2021/09/21 14:30:15 christos Exp $ */ 2185029Spjd/* $KAME: altq_conf.c,v 1.24 2005/04/13 03:44:24 suz Exp $ */ 3185029Spjd 4185029Spjd/* 5185029Spjd * Copyright (C) 1997-2003 6185029Spjd * Sony Computer Science Laboratories Inc. All rights reserved. 7185029Spjd * 8185029Spjd * Redistribution and use in source and binary forms, with or without 9185029Spjd * modification, are permitted provided that the following conditions 10185029Spjd * are met: 11185029Spjd * 1. Redistributions of source code must retain the above copyright 12185029Spjd * notice, this list of conditions and the following disclaimer. 13185029Spjd * 2. Redistributions in binary form must reproduce the above copyright 14185029Spjd * notice, this list of conditions and the following disclaimer in the 15185029Spjd * documentation and/or other materials provided with the distribution. 16185029Spjd * 17185029Spjd * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND 18185029Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19185029Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20185029Spjd * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 21185029Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22185029Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24185029Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25185029Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26185029Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27185029Spjd * SUCH DAMAGE. 28185029Spjd */ 29185029Spjd 30185029Spjd#include <sys/cdefs.h> 31185029Spjd__KERNEL_RCSID(0, "$NetBSD: altq_conf.c,v 1.22 2021/09/21 14:30:15 christos Exp $"); 32185029Spjd 33185029Spjd#ifdef _KERNEL_OPT 34219089Spjd#include "opt_altq.h" 35235361Savg#include "opt_inet.h" 36219089Spjd#endif 37185029Spjd 38185029Spjd/* 39185029Spjd * altq device interface. 40235329Savg */ 41235329Savg#include <sys/param.h> 42235390Savg#include <sys/systm.h> 43235329Savg#include <sys/socket.h> 44235329Savg#include <sys/kernel.h> 45235329Savg#include <sys/proc.h> 46235329Savg#include <sys/errno.h> 47185029Spjd#include <sys/kauth.h> 48185029Spjd 49185029Spjd#include <net/if.h> 50185029Spjd 51185029Spjd#include <altq/altq.h> 52236884Smm#include <altq/altqconf.h> 53236884Smm#include <altq/altq_conf.h> 54236884Smm 55236884Smm#ifdef ALTQ3_COMPAT 56263397Sdelphij 57263397Sdelphij#ifdef ALTQ_CBQ 58263397Sdelphijaltqdev_decl(cbq); 59268649Sdelphij#endif 60236884Smm#ifdef ALTQ_WFQ 61236884Smmaltqdev_decl(wfq); 62236884Smm#endif 63185029Spjd#ifdef ALTQ_AFMAP 64185029Spjdaltqdev_decl(afm); 65185029Spjd#endif 66185029Spjd#ifdef ALTQ_FIFOQ 67185029Spjdaltqdev_decl(fifoq); 68185029Spjd#endif 69185029Spjd#ifdef ALTQ_RED 70185029Spjdaltqdev_decl(red); 71185029Spjd#endif 72185029Spjd#ifdef ALTQ_RIO 73192194Sdfraltqdev_decl(rio); 74185029Spjd#endif 75200309Sjhb#ifdef ALTQ_LOCALQ 76185029Spjdaltqdev_decl(localq); 77235390Savg#endif 78241291Savg#ifdef ALTQ_HFSC 79241291Savgaltqdev_decl(hfsc); 80198420Srnoland#endif 81185029Spjd#ifdef ALTQ_CDNR 82185029Spjdaltqdev_decl(cdnr); 83185029Spjd#endif 84185029Spjd#ifdef ALTQ_BLUE 85185029Spjdaltqdev_decl(blue); 86185029Spjd#endif 87192194Sdfr#ifdef ALTQ_PRIQ 88192194Sdfraltqdev_decl(priq); 89192194Sdfr#endif 90192194Sdfr#ifdef ALTQ_JOBS 91192194Sdfraltqdev_decl(jobs); 92185029Spjd#endif 93185029Spjd 94185029Spjd/* 95185029Spjd * altq minor device (discipline) table 96219089Spjd */ 97219089Spjdstatic struct altqsw altqsw[] = { /* minor */ 98192194Sdfr {"altq", noopen, noclose, noioctl}, /* 0 (reserved) */ 99219089Spjd#ifdef ALTQ_CBQ 100192194Sdfr {"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */ 101219089Spjd#else 102192194Sdfr {"noq", noopen, noclose, noioctl}, /* 1 */ 103192194Sdfr#endif 104192194Sdfr#ifdef ALTQ_WFQ 105219089Spjd {"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */ 106219089Spjd#else 107192194Sdfr {"noq", noopen, noclose, noioctl}, /* 2 */ 108219089Spjd#endif 109192194Sdfr#ifdef ALTQ_AFMAP 110192194Sdfr {"afm", afmopen, afmclose, afmioctl}, /* 3 */ 111192194Sdfr#else 112219089Spjd {"noq", noopen, noclose, noioctl}, /* 3 */ 113192194Sdfr#endif 114192194Sdfr#ifdef ALTQ_FIFOQ 115219089Spjd {"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */ 116219089Spjd#else 117219089Spjd {"noq", noopen, noclose, noioctl}, /* 4 */ 118219089Spjd#endif 119219089Spjd#ifdef ALTQ_RED 120192194Sdfr {"red", redopen, redclose, redioctl}, /* 5 */ 121192194Sdfr#else 122185029Spjd {"noq", noopen, noclose, noioctl}, /* 5 */ 123185029Spjd#endif 124185029Spjd#ifdef ALTQ_RIO 125185029Spjd {"rio", rioopen, rioclose, rioioctl}, /* 6 */ 126185029Spjd#else 127185029Spjd {"noq", noopen, noclose, noioctl}, /* 6 */ 128185029Spjd#endif 129185029Spjd#ifdef ALTQ_LOCALQ 130185029Spjd {"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */ 131185029Spjd#else 132185029Spjd {"noq", noopen, noclose, noioctl}, /* 7 (local use) */ 133185029Spjd#endif 134185029Spjd#ifdef ALTQ_HFSC 135185029Spjd {"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */ 136185029Spjd#else 137185029Spjd {"noq", noopen, noclose, noioctl}, /* 8 */ 138185029Spjd#endif 139185029Spjd#ifdef ALTQ_CDNR 140185029Spjd {"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */ 141185029Spjd#else 142185029Spjd {"noq", noopen, noclose, noioctl}, /* 9 */ 143185029Spjd#endif 144185029Spjd#ifdef ALTQ_BLUE 145185029Spjd {"blue",blueopen, blueclose, blueioctl}, /* 10 */ 146185029Spjd#else 147185029Spjd {"noq", noopen, noclose, noioctl}, /* 10 */ 148185029Spjd#endif 149185029Spjd#ifdef ALTQ_PRIQ 150185029Spjd {"priq",priqopen, priqclose, priqioctl}, /* 11 */ 151185029Spjd#else 152185029Spjd {"noq", noopen, noclose, noioctl}, /* 11 */ 153185029Spjd#endif 154185029Spjd#ifdef ALTQ_JOBS 155185029Spjd {"jobs",jobsopen, jobsclose, jobsioctl}, /* 12 */ 156185029Spjd#else 157185029Spjd {"noq", noopen, noclose, noioctl}, /* 12 */ 158185029Spjd#endif 159185029Spjd}; 160185029Spjd 161185029Spjd/* 162185029Spjd * altq major device support 163185029Spjd */ 164185029Spjdint naltqsw = sizeof (altqsw) / sizeof (altqsw[0]); 165185029Spjd 166185029Spjddev_type_open(altqopen); 167185029Spjddev_type_close(altqclose); 168185029Spjddev_type_ioctl(altqioctl); 169185029Spjd 170185029Spjdconst struct cdevsw altq_cdevsw = { 171185029Spjd .d_open = altqopen, 172185029Spjd .d_close = altqclose, 173185029Spjd .d_read = noread, 174185029Spjd .d_write = nowrite, 175185029Spjd .d_ioctl = altqioctl, 176185029Spjd .d_stop = nostop, 177185029Spjd .d_tty = notty, 178185029Spjd .d_poll = nopoll, 179185029Spjd .d_mmap = nommap, 180185029Spjd .d_kqfilter = nokqfilter, 181185029Spjd .d_discard = nodiscard, 182185029Spjd .d_flag = D_OTHER, 183185029Spjd}; 184185029Spjd 185185029Spjdint 186185029Spjdaltqopen(dev_t dev, int flag, int fmt, struct lwp *l) 187185029Spjd{ 188185029Spjd int unit = minor(dev); 189185029Spjd 190185029Spjd if (unit == 0) 191185029Spjd return (0); 192185029Spjd if (unit < naltqsw) 193185029Spjd return (*altqsw[unit].d_open)(dev, flag, fmt, l); 194185029Spjd 195185029Spjd return ENXIO; 196185029Spjd} 197185029Spjd 198185029Spjdint 199185029Spjdaltqclose(dev_t dev, int flag, int fmt, struct lwp *l) 200185029Spjd{ 201185029Spjd int unit = minor(dev); 202185029Spjd 203185029Spjd if (unit == 0) 204185029Spjd return (0); 205185029Spjd if (unit < naltqsw) 206185029Spjd return (*altqsw[unit].d_close)(dev, flag, fmt, l); 207185029Spjd 208185029Spjd return ENXIO; 209185029Spjd} 210185029Spjd 211185029Spjdint 212185029Spjdaltqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l) 213185029Spjd{ 214236884Smm int unit = minor(dev); 215236884Smm 216236884Smm if (unit == 0) { 217236884Smm struct ifnet *ifp; 218236884Smm struct altqreq *typereq; 219236884Smm struct tbrreq *tbrreq; 220236884Smm int error; 221236884Smm 222236884Smm switch (cmd) { 223236884Smm case ALTQGTYPE: 224236884Smm case ALTQTBRGET: 225236884Smm break; 226236884Smm default: 227236884Smm if ((error = kauth_authorize_network( 228236884Smm l->l_cred, KAUTH_NETWORK_ALTQ, 229236884Smm KAUTH_REQ_NETWORK_ALTQ_CONF, NULL, NULL, 230236884Smm NULL)) != 0) 231236884Smm return (error); 232236884Smm break; 233236884Smm } 234236884Smm 235236884Smm switch (cmd) { 236236884Smm case ALTQGTYPE: 237236884Smm typereq = (struct altqreq *)addr; 238236884Smm if ((ifp = ifunit(typereq->ifname)) == NULL) 239236884Smm return (EINVAL); 240236884Smm typereq->arg = (u_long)ifp->if_snd.altq_type; 241236884Smm return (0); 242236884Smm case ALTQTBRSET: 243236884Smm tbrreq = (struct tbrreq *)addr; 244236884Smm if ((ifp = ifunit(tbrreq->ifname)) == NULL) 245236884Smm return (EINVAL); 246236884Smm return tbr_set(&ifp->if_snd, &tbrreq->tb_prof); 247236884Smm case ALTQTBRGET: 248236884Smm tbrreq = (struct tbrreq *)addr; 249236884Smm if ((ifp = ifunit(tbrreq->ifname)) == NULL) 250236884Smm return (EINVAL); 251236884Smm return tbr_get(&ifp->if_snd, &tbrreq->tb_prof); 252236884Smm default: 253236884Smm return (EINVAL); 254236884Smm } 255236884Smm } 256236884Smm if (unit < naltqsw) 257236884Smm return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l); 258236884Smm 259236884Smm return ENXIO; 260236884Smm} 261236884Smm 262236884Smm#ifdef __FreeBSD__ 263236884Smmstatic int altq_devsw_installed = 0; 264236884Smm#endif 265185029Spjd 266185029Spjd#ifdef __FreeBSD__ 267185029Spjdstatic void 268185029Spjdaltq_drvinit(void *unused) 269185029Spjd{ 270185029Spjd int unit; 271185029Spjd 272185029Spjd#if 0 273185029Spjd mtx_init(&altq_mtx, "altq global lock", MTX_DEF); 274185029Spjd#endif 275185029Spjd altq_devsw_installed = 1; 276185029Spjd printf("altq: attached. Major number assigned automatically.\n"); 277185029Spjd 278185029Spjd /* create minor devices */ 279185029Spjd for (unit = 0; unit < naltqsw; unit++) { 280185029Spjd if (unit == 0 || altqsw[unit].d_open != NULL) 281185029Spjd altqsw[unit].dev = make_dev(&altq_cdevsw, unit, 282185029Spjd UID_ROOT, GID_WHEEL, 0644, "altq/%s", 283185029Spjd altqsw[unit].d_name); 284185029Spjd } 285185029Spjd} 286185029Spjd 287185029SpjdSYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL) 288185029Spjd 289185029Spjd#endif /* FreeBSD */ 290185029Spjd 291185029Spjd#ifdef ALTQ_KLD 292185029Spjd/* 293185029Spjd * KLD support 294185029Spjd */ 295185029Spjdstatic int altq_module_register(struct altq_module_data *); 296185029Spjdstatic int altq_module_deregister(struct altq_module_data *); 297185029Spjd 298185029Spjdstatic struct altq_module_data *altq_modules[ALTQT_MAX]; 299185029Spjd#if __FreeBSD_version < 502103 300185029Spjdstatic struct altqsw noqdisc = {"noq", noopen, noclose, noioctl}; 301185029Spjd#else 302185029Spjdstatic struct altqsw noqdisc = {"noq"}; 303185029Spjd#endif 304185029Spjd 305185029Spjdvoid altq_module_incref(int type) 306185029Spjd{ 307185029Spjd if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 308185029Spjd return; 309185029Spjd 310185029Spjd altq_modules[type]->ref++; 311185029Spjd} 312185029Spjd 313185029Spjdvoid altq_module_declref(int type) 314185029Spjd{ 315185029Spjd if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 316185029Spjd return; 317185029Spjd 318185029Spjd altq_modules[type]->ref--; 319185029Spjd} 320185029Spjd 321185029Spjdstatic int 322185029Spjdaltq_module_register(struct altq_module_data *mdata) 323185029Spjd{ 324185029Spjd int type = mdata->type; 325185029Spjd 326185029Spjd if (type < 0 || type >= ALTQT_MAX) 327185029Spjd return (EINVAL); 328185029Spjd#if (__FreeBSD_version < 502103) 329185029Spjd if (altqsw[type].d_open != noopen) 330185029Spjd#else 331185029Spjd if (altqsw[type].d_open != NULL) 332185029Spjd#endif 333185029Spjd return (EBUSY); 334185029Spjd altqsw[type] = *mdata->altqsw; /* set discipline functions */ 335185029Spjd altq_modules[type] = mdata; /* save module data pointer */ 336185029Spjd#if (__FreeBSD_version < 502103) 337185029Spjd make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644, 338185029Spjd "altq/%s", altqsw[type].d_name); 339185029Spjd#else 340185029Spjd altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 341185029Spjd 0644, "altq/%s", altqsw[type].d_name); 342185029Spjd#endif 343185029Spjd return (0); 344185029Spjd} 345185029Spjd 346185029Spjdstatic int 347185029Spjdaltq_module_deregister(struct altq_module_data *mdata) 348185029Spjd{ 349185029Spjd int type = mdata->type; 350185029Spjd 351185029Spjd if (type < 0 || type >= ALTQT_MAX) 352185029Spjd return (EINVAL); 353185029Spjd if (mdata != altq_modules[type]) 354185029Spjd return (EINVAL); 355185029Spjd if (altq_modules[type]->ref > 0) 356185029Spjd return (EBUSY); 357185029Spjd#if (__FreeBSD_version < 502103) 358235361Savg destroy_dev(makedev(CDEV_MAJOR, type)); 359185029Spjd#else 360185029Spjd destroy_dev(altqsw[type].dev); 361185029Spjd#endif 362185029Spjd altqsw[type] = noqdisc; 363185029Spjd altq_modules[type] = NULL; 364185029Spjd return (0); 365185029Spjd} 366185029Spjd 367185029Spjdint 368185029Spjdaltq_module_handler(module_t mod, int cmd, void *arg) 369185029Spjd{ 370185029Spjd struct altq_module_data *data = (struct altq_module_data *)arg; 371185029Spjd int error = 0; 372185029Spjd 373185029Spjd switch (cmd) { 374185029Spjd case MOD_LOAD: 375185029Spjd error = altq_module_register(data); 376185029Spjd break; 377185029Spjd 378185029Spjd case MOD_UNLOAD: 379185029Spjd error = altq_module_deregister(data); 380185029Spjd break; 381185029Spjd 382185029Spjd default: 383185029Spjd error = EINVAL; 384185029Spjd break; 385185029Spjd } 386185029Spjd 387185029Spjd return (error); 388185029Spjd} 389185029Spjd 390185029Spjd#endif /* ALTQ_KLD */ 391185029Spjd#endif /* ALTQ3_COMPAT */ 392185029Spjd