1 1.23 joe /* $NetBSD: altq_conf.c,v 1.23 2025/01/08 13:00:04 joe Exp $ */ 2 1.17 peter /* $KAME: altq_conf.c,v 1.24 2005/04/13 03:44:24 suz Exp $ */ 3 1.1 thorpej 4 1.1 thorpej /* 5 1.17 peter * Copyright (C) 1997-2003 6 1.1 thorpej * Sony Computer Science Laboratories Inc. All rights reserved. 7 1.1 thorpej * 8 1.1 thorpej * Redistribution and use in source and binary forms, with or without 9 1.1 thorpej * modification, are permitted provided that the following conditions 10 1.1 thorpej * are met: 11 1.1 thorpej * 1. Redistributions of source code must retain the above copyright 12 1.1 thorpej * notice, this list of conditions and the following disclaimer. 13 1.1 thorpej * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 thorpej * notice, this list of conditions and the following disclaimer in the 15 1.1 thorpej * documentation and/or other materials provided with the distribution. 16 1.1 thorpej * 17 1.1 thorpej * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND 18 1.1 thorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 1.1 thorpej * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 1.1 thorpej * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 21 1.1 thorpej * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 1.1 thorpej * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 1.1 thorpej * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 1.1 thorpej * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 1.1 thorpej * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 1.1 thorpej * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 1.1 thorpej * SUCH DAMAGE. 28 1.1 thorpej */ 29 1.5 lukem 30 1.5 lukem #include <sys/cdefs.h> 31 1.23 joe __KERNEL_RCSID(0, "$NetBSD: altq_conf.c,v 1.23 2025/01/08 13:00:04 joe Exp $"); 32 1.1 thorpej 33 1.17 peter #ifdef _KERNEL_OPT 34 1.1 thorpej #include "opt_altq.h" 35 1.1 thorpej #include "opt_inet.h" 36 1.1 thorpej #endif 37 1.1 thorpej 38 1.1 thorpej /* 39 1.1 thorpej * altq device interface. 40 1.1 thorpej */ 41 1.1 thorpej #include <sys/param.h> 42 1.1 thorpej #include <sys/systm.h> 43 1.1 thorpej #include <sys/socket.h> 44 1.1 thorpej #include <sys/kernel.h> 45 1.1 thorpej #include <sys/proc.h> 46 1.1 thorpej #include <sys/errno.h> 47 1.14 christos #include <sys/kauth.h> 48 1.17 peter 49 1.1 thorpej #include <net/if.h> 50 1.1 thorpej 51 1.1 thorpej #include <altq/altq.h> 52 1.9 jdolecek #include <altq/altqconf.h> 53 1.1 thorpej #include <altq/altq_conf.h> 54 1.1 thorpej 55 1.17 peter #ifdef ALTQ3_COMPAT 56 1.17 peter 57 1.1 thorpej #ifdef ALTQ_CBQ 58 1.1 thorpej altqdev_decl(cbq); 59 1.1 thorpej #endif 60 1.1 thorpej #ifdef ALTQ_WFQ 61 1.1 thorpej altqdev_decl(wfq); 62 1.1 thorpej #endif 63 1.1 thorpej #ifdef ALTQ_AFMAP 64 1.1 thorpej altqdev_decl(afm); 65 1.1 thorpej #endif 66 1.1 thorpej #ifdef ALTQ_FIFOQ 67 1.1 thorpej altqdev_decl(fifoq); 68 1.1 thorpej #endif 69 1.1 thorpej #ifdef ALTQ_RED 70 1.1 thorpej altqdev_decl(red); 71 1.1 thorpej #endif 72 1.1 thorpej #ifdef ALTQ_RIO 73 1.1 thorpej altqdev_decl(rio); 74 1.1 thorpej #endif 75 1.1 thorpej #ifdef ALTQ_LOCALQ 76 1.1 thorpej altqdev_decl(localq); 77 1.1 thorpej #endif 78 1.1 thorpej #ifdef ALTQ_HFSC 79 1.1 thorpej altqdev_decl(hfsc); 80 1.1 thorpej #endif 81 1.1 thorpej #ifdef ALTQ_CDNR 82 1.1 thorpej altqdev_decl(cdnr); 83 1.1 thorpej #endif 84 1.1 thorpej #ifdef ALTQ_BLUE 85 1.1 thorpej altqdev_decl(blue); 86 1.1 thorpej #endif 87 1.1 thorpej #ifdef ALTQ_PRIQ 88 1.1 thorpej altqdev_decl(priq); 89 1.1 thorpej #endif 90 1.17 peter #ifdef ALTQ_JOBS 91 1.17 peter altqdev_decl(jobs); 92 1.17 peter #endif 93 1.1 thorpej 94 1.1 thorpej /* 95 1.1 thorpej * altq minor device (discipline) table 96 1.1 thorpej */ 97 1.1 thorpej static struct altqsw altqsw[] = { /* minor */ 98 1.17 peter {"altq", noopen, noclose, noioctl}, /* 0 (reserved) */ 99 1.1 thorpej #ifdef ALTQ_CBQ 100 1.1 thorpej {"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */ 101 1.1 thorpej #else 102 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 1 */ 103 1.1 thorpej #endif 104 1.1 thorpej #ifdef ALTQ_WFQ 105 1.1 thorpej {"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */ 106 1.1 thorpej #else 107 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 2 */ 108 1.1 thorpej #endif 109 1.1 thorpej #ifdef ALTQ_AFMAP 110 1.1 thorpej {"afm", afmopen, afmclose, afmioctl}, /* 3 */ 111 1.1 thorpej #else 112 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 3 */ 113 1.1 thorpej #endif 114 1.1 thorpej #ifdef ALTQ_FIFOQ 115 1.1 thorpej {"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */ 116 1.1 thorpej #else 117 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 4 */ 118 1.1 thorpej #endif 119 1.1 thorpej #ifdef ALTQ_RED 120 1.1 thorpej {"red", redopen, redclose, redioctl}, /* 5 */ 121 1.1 thorpej #else 122 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 5 */ 123 1.1 thorpej #endif 124 1.1 thorpej #ifdef ALTQ_RIO 125 1.1 thorpej {"rio", rioopen, rioclose, rioioctl}, /* 6 */ 126 1.1 thorpej #else 127 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 6 */ 128 1.1 thorpej #endif 129 1.1 thorpej #ifdef ALTQ_LOCALQ 130 1.1 thorpej {"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */ 131 1.1 thorpej #else 132 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 7 (local use) */ 133 1.1 thorpej #endif 134 1.1 thorpej #ifdef ALTQ_HFSC 135 1.1 thorpej {"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */ 136 1.1 thorpej #else 137 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 8 */ 138 1.1 thorpej #endif 139 1.1 thorpej #ifdef ALTQ_CDNR 140 1.1 thorpej {"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */ 141 1.1 thorpej #else 142 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 9 */ 143 1.1 thorpej #endif 144 1.1 thorpej #ifdef ALTQ_BLUE 145 1.1 thorpej {"blue",blueopen, blueclose, blueioctl}, /* 10 */ 146 1.1 thorpej #else 147 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 10 */ 148 1.1 thorpej #endif 149 1.1 thorpej #ifdef ALTQ_PRIQ 150 1.1 thorpej {"priq",priqopen, priqclose, priqioctl}, /* 11 */ 151 1.1 thorpej #else 152 1.1 thorpej {"noq", noopen, noclose, noioctl}, /* 11 */ 153 1.1 thorpej #endif 154 1.17 peter #ifdef ALTQ_JOBS 155 1.17 peter {"jobs",jobsopen, jobsclose, jobsioctl}, /* 12 */ 156 1.17 peter #else 157 1.17 peter {"noq", noopen, noclose, noioctl}, /* 12 */ 158 1.17 peter #endif 159 1.1 thorpej }; 160 1.1 thorpej 161 1.1 thorpej /* 162 1.1 thorpej * altq major device support 163 1.1 thorpej */ 164 1.1 thorpej int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]); 165 1.1 thorpej 166 1.8 gehenna dev_type_open(altqopen); 167 1.8 gehenna dev_type_close(altqclose); 168 1.8 gehenna dev_type_ioctl(altqioctl); 169 1.1 thorpej 170 1.7 gehenna const struct cdevsw altq_cdevsw = { 171 1.20 dholland .d_open = altqopen, 172 1.20 dholland .d_close = altqclose, 173 1.20 dholland .d_read = noread, 174 1.20 dholland .d_write = nowrite, 175 1.20 dholland .d_ioctl = altqioctl, 176 1.20 dholland .d_stop = nostop, 177 1.20 dholland .d_tty = notty, 178 1.20 dholland .d_poll = nopoll, 179 1.20 dholland .d_mmap = nommap, 180 1.20 dholland .d_kqfilter = nokqfilter, 181 1.21 dholland .d_discard = nodiscard, 182 1.20 dholland .d_flag = D_OTHER, 183 1.7 gehenna }; 184 1.1 thorpej 185 1.1 thorpej int 186 1.17 peter altqopen(dev_t dev, int flag, int fmt, struct lwp *l) 187 1.1 thorpej { 188 1.1 thorpej int unit = minor(dev); 189 1.1 thorpej 190 1.1 thorpej if (unit == 0) 191 1.23 joe return 0; 192 1.1 thorpej if (unit < naltqsw) 193 1.12 christos return (*altqsw[unit].d_open)(dev, flag, fmt, l); 194 1.1 thorpej 195 1.1 thorpej return ENXIO; 196 1.1 thorpej } 197 1.1 thorpej 198 1.1 thorpej int 199 1.17 peter altqclose(dev_t dev, int flag, int fmt, struct lwp *l) 200 1.1 thorpej { 201 1.1 thorpej int unit = minor(dev); 202 1.1 thorpej 203 1.1 thorpej if (unit == 0) 204 1.23 joe return 0; 205 1.1 thorpej if (unit < naltqsw) 206 1.12 christos return (*altqsw[unit].d_close)(dev, flag, fmt, l); 207 1.1 thorpej 208 1.1 thorpej return ENXIO; 209 1.1 thorpej } 210 1.1 thorpej 211 1.1 thorpej int 212 1.19 christos altqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l) 213 1.1 thorpej { 214 1.1 thorpej int unit = minor(dev); 215 1.1 thorpej 216 1.1 thorpej if (unit == 0) { 217 1.1 thorpej struct ifnet *ifp; 218 1.1 thorpej struct altqreq *typereq; 219 1.1 thorpej struct tbrreq *tbrreq; 220 1.1 thorpej int error; 221 1.1 thorpej 222 1.1 thorpej switch (cmd) { 223 1.1 thorpej case ALTQGTYPE: 224 1.1 thorpej case ALTQTBRGET: 225 1.1 thorpej break; 226 1.1 thorpej default: 227 1.22 christos if ((error = kauth_authorize_network( 228 1.22 christos l->l_cred, KAUTH_NETWORK_ALTQ, 229 1.22 christos KAUTH_REQ_NETWORK_ALTQ_CONF, NULL, NULL, 230 1.22 christos NULL)) != 0) 231 1.23 joe return error; 232 1.1 thorpej break; 233 1.1 thorpej } 234 1.1 thorpej 235 1.1 thorpej switch (cmd) { 236 1.1 thorpej case ALTQGTYPE: 237 1.1 thorpej typereq = (struct altqreq *)addr; 238 1.1 thorpej if ((ifp = ifunit(typereq->ifname)) == NULL) 239 1.1 thorpej return (EINVAL); 240 1.1 thorpej typereq->arg = (u_long)ifp->if_snd.altq_type; 241 1.23 joe return 0; 242 1.1 thorpej case ALTQTBRSET: 243 1.1 thorpej tbrreq = (struct tbrreq *)addr; 244 1.1 thorpej if ((ifp = ifunit(tbrreq->ifname)) == NULL) 245 1.23 joe return EINVAL; 246 1.1 thorpej return tbr_set(&ifp->if_snd, &tbrreq->tb_prof); 247 1.1 thorpej case ALTQTBRGET: 248 1.1 thorpej tbrreq = (struct tbrreq *)addr; 249 1.1 thorpej if ((ifp = ifunit(tbrreq->ifname)) == NULL) 250 1.23 joe return EINVAL; 251 1.1 thorpej return tbr_get(&ifp->if_snd, &tbrreq->tb_prof); 252 1.1 thorpej default: 253 1.23 joe return EINVAL; 254 1.1 thorpej } 255 1.1 thorpej } 256 1.1 thorpej if (unit < naltqsw) 257 1.12 christos return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l); 258 1.1 thorpej 259 1.1 thorpej return ENXIO; 260 1.1 thorpej } 261 1.1 thorpej 262 1.17 peter #ifdef __FreeBSD__ 263 1.1 thorpej static int altq_devsw_installed = 0; 264 1.4 thorpej #endif 265 1.1 thorpej 266 1.1 thorpej #ifdef __FreeBSD__ 267 1.1 thorpej static void 268 1.17 peter altq_drvinit(void *unused) 269 1.1 thorpej { 270 1.1 thorpej int unit; 271 1.1 thorpej 272 1.17 peter #if 0 273 1.17 peter mtx_init(&altq_mtx, "altq global lock", MTX_DEF); 274 1.17 peter #endif 275 1.1 thorpej altq_devsw_installed = 1; 276 1.17 peter printf("altq: attached. Major number assigned automatically.\n"); 277 1.1 thorpej 278 1.1 thorpej /* create minor devices */ 279 1.17 peter for (unit = 0; unit < naltqsw; unit++) { 280 1.17 peter if (unit == 0 || altqsw[unit].d_open != NULL) 281 1.17 peter altqsw[unit].dev = make_dev(&altq_cdevsw, unit, 282 1.17 peter UID_ROOT, GID_WHEEL, 0644, "altq/%s", 283 1.17 peter altqsw[unit].d_name); 284 1.17 peter } 285 1.1 thorpej } 286 1.1 thorpej 287 1.1 thorpej SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL) 288 1.1 thorpej 289 1.17 peter #endif /* FreeBSD */ 290 1.1 thorpej 291 1.1 thorpej #ifdef ALTQ_KLD 292 1.1 thorpej /* 293 1.1 thorpej * KLD support 294 1.1 thorpej */ 295 1.17 peter static int altq_module_register(struct altq_module_data *); 296 1.17 peter static int altq_module_deregister(struct altq_module_data *); 297 1.1 thorpej 298 1.1 thorpej static struct altq_module_data *altq_modules[ALTQT_MAX]; 299 1.17 peter #if __FreeBSD_version < 502103 300 1.1 thorpej static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl}; 301 1.17 peter #else 302 1.17 peter static struct altqsw noqdisc = {"noq"}; 303 1.17 peter #endif 304 1.1 thorpej 305 1.17 peter void altq_module_incref(int type) 306 1.1 thorpej { 307 1.1 thorpej if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 308 1.1 thorpej return; 309 1.1 thorpej 310 1.1 thorpej altq_modules[type]->ref++; 311 1.1 thorpej } 312 1.1 thorpej 313 1.17 peter void altq_module_declref(int type) 314 1.1 thorpej { 315 1.1 thorpej if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 316 1.1 thorpej return; 317 1.1 thorpej 318 1.1 thorpej altq_modules[type]->ref--; 319 1.1 thorpej } 320 1.1 thorpej 321 1.11 perry static int 322 1.17 peter altq_module_register(struct altq_module_data *mdata) 323 1.1 thorpej { 324 1.1 thorpej int type = mdata->type; 325 1.1 thorpej 326 1.1 thorpej if (type < 0 || type >= ALTQT_MAX) 327 1.23 joe return EINVAL; 328 1.17 peter #if (__FreeBSD_version < 502103) 329 1.1 thorpej if (altqsw[type].d_open != noopen) 330 1.17 peter #else 331 1.17 peter if (altqsw[type].d_open != NULL) 332 1.17 peter #endif 333 1.23 joe return EBUSY; 334 1.1 thorpej altqsw[type] = *mdata->altqsw; /* set discipline functions */ 335 1.1 thorpej altq_modules[type] = mdata; /* save module data pointer */ 336 1.17 peter #if (__FreeBSD_version < 502103) 337 1.17 peter make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644, 338 1.17 peter "altq/%s", altqsw[type].d_name); 339 1.17 peter #else 340 1.17 peter altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 341 1.17 peter 0644, "altq/%s", altqsw[type].d_name); 342 1.17 peter #endif 343 1.23 joe return 0; 344 1.1 thorpej } 345 1.1 thorpej 346 1.11 perry static int 347 1.17 peter altq_module_deregister(struct altq_module_data *mdata) 348 1.1 thorpej { 349 1.1 thorpej int type = mdata->type; 350 1.1 thorpej 351 1.1 thorpej if (type < 0 || type >= ALTQT_MAX) 352 1.23 joe return EINVAL; 353 1.1 thorpej if (mdata != altq_modules[type]) 354 1.23 joe return EINVAL; 355 1.1 thorpej if (altq_modules[type]->ref > 0) 356 1.23 joe return EBUSY; 357 1.17 peter #if (__FreeBSD_version < 502103) 358 1.17 peter destroy_dev(makedev(CDEV_MAJOR, type)); 359 1.17 peter #else 360 1.17 peter destroy_dev(altqsw[type].dev); 361 1.17 peter #endif 362 1.1 thorpej altqsw[type] = noqdisc; 363 1.1 thorpej altq_modules[type] = NULL; 364 1.23 joe return 0; 365 1.1 thorpej } 366 1.1 thorpej 367 1.1 thorpej int 368 1.17 peter altq_module_handler(module_t mod, int cmd, void *arg) 369 1.1 thorpej { 370 1.1 thorpej struct altq_module_data *data = (struct altq_module_data *)arg; 371 1.1 thorpej int error = 0; 372 1.1 thorpej 373 1.1 thorpej switch (cmd) { 374 1.1 thorpej case MOD_LOAD: 375 1.1 thorpej error = altq_module_register(data); 376 1.1 thorpej break; 377 1.1 thorpej 378 1.1 thorpej case MOD_UNLOAD: 379 1.1 thorpej error = altq_module_deregister(data); 380 1.1 thorpej break; 381 1.1 thorpej 382 1.1 thorpej default: 383 1.1 thorpej error = EINVAL; 384 1.1 thorpej break; 385 1.1 thorpej } 386 1.1 thorpej 387 1.23 joe return error; 388 1.1 thorpej } 389 1.6 itojun 390 1.1 thorpej #endif /* ALTQ_KLD */ 391 1.17 peter #endif /* ALTQ3_COMPAT */ 392