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