1 /* $NetBSD: altq_conf.c,v 1.6 2002/03/05 04:12:57 itojun 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.6 2002/03/05 04:12:57 itojun 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/altq_conf.h> 59 60 #ifdef ALTQ_CBQ 61 altqdev_decl(cbq); 62 #endif 63 #ifdef ALTQ_WFQ 64 altqdev_decl(wfq); 65 #endif 66 #ifdef ALTQ_AFMAP 67 altqdev_decl(afm); 68 #endif 69 #ifdef ALTQ_FIFOQ 70 altqdev_decl(fifoq); 71 #endif 72 #ifdef ALTQ_RED 73 altqdev_decl(red); 74 #endif 75 #ifdef ALTQ_RIO 76 altqdev_decl(rio); 77 #endif 78 #ifdef ALTQ_LOCALQ 79 altqdev_decl(localq); 80 #endif 81 #ifdef ALTQ_HFSC 82 altqdev_decl(hfsc); 83 #endif 84 #ifdef ALTQ_CDNR 85 altqdev_decl(cdnr); 86 #endif 87 #ifdef ALTQ_BLUE 88 altqdev_decl(blue); 89 #endif 90 #ifdef ALTQ_PRIQ 91 altqdev_decl(priq); 92 #endif 93 94 /* 95 * altq minor device (discipline) table 96 */ 97 static struct altqsw altqsw[] = { /* minor */ 98 {"noq", noopen, noclose, noioctl}, /* 0 (reserved) */ 99 #ifdef ALTQ_CBQ 100 {"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */ 101 #else 102 {"noq", noopen, noclose, noioctl}, /* 1 */ 103 #endif 104 #ifdef ALTQ_WFQ 105 {"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */ 106 #else 107 {"noq", noopen, noclose, noioctl}, /* 2 */ 108 #endif 109 #ifdef ALTQ_AFMAP 110 {"afm", afmopen, afmclose, afmioctl}, /* 3 */ 111 #else 112 {"noq", noopen, noclose, noioctl}, /* 3 */ 113 #endif 114 #ifdef ALTQ_FIFOQ 115 {"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */ 116 #else 117 {"noq", noopen, noclose, noioctl}, /* 4 */ 118 #endif 119 #ifdef ALTQ_RED 120 {"red", redopen, redclose, redioctl}, /* 5 */ 121 #else 122 {"noq", noopen, noclose, noioctl}, /* 5 */ 123 #endif 124 #ifdef ALTQ_RIO 125 {"rio", rioopen, rioclose, rioioctl}, /* 6 */ 126 #else 127 {"noq", noopen, noclose, noioctl}, /* 6 */ 128 #endif 129 #ifdef ALTQ_LOCALQ 130 {"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */ 131 #else 132 {"noq", noopen, noclose, noioctl}, /* 7 (local use) */ 133 #endif 134 #ifdef ALTQ_HFSC 135 {"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */ 136 #else 137 {"noq", noopen, noclose, noioctl}, /* 8 */ 138 #endif 139 #ifdef ALTQ_CDNR 140 {"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */ 141 #else 142 {"noq", noopen, noclose, noioctl}, /* 9 */ 143 #endif 144 #ifdef ALTQ_BLUE 145 {"blue",blueopen, blueclose, blueioctl}, /* 10 */ 146 #else 147 {"noq", noopen, noclose, noioctl}, /* 10 */ 148 #endif 149 #ifdef ALTQ_PRIQ 150 {"priq",priqopen, priqclose, priqioctl}, /* 11 */ 151 #else 152 {"noq", noopen, noclose, noioctl}, /* 11 */ 153 #endif 154 }; 155 156 /* 157 * altq major device support 158 */ 159 int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]); 160 161 #if !defined(__NetBSD__) && defined(__OpenBSD__) 162 static d_open_t altqopen; 163 static d_close_t altqclose; 164 static d_ioctl_t altqioctl; 165 #endif 166 #ifdef __FreeBSD__ 167 static void altq_drvinit __P((void *)); 168 #else 169 void altqattach __P((int)); 170 #endif 171 172 #if defined(__FreeBSD__) 173 #define CDEV_MAJOR 96 /* FreeBSD official number */ 174 #elif defined(__OpenBSD__) 175 #if defined(__i386__) 176 #define CDEV_MAJOR 74 /* OpenBSD i386 (official) */ 177 #elif defined(__alpha__) 178 #define CDEV_MAJOR 53 /* OpenBSD alpha (official) */ 179 #else 180 #error arch not supported 181 #endif 182 #endif 183 184 #if defined(__FreeBSD__) 185 #if (__FreeBSD_version < 400000) 186 static struct cdevsw altq_cdevsw = 187 { altqopen, altqclose, noread, nowrite, 188 altqioctl, nostop, nullreset, nodevtotty, 189 seltrue, nommap, NULL, "altq", NULL, -1 }; 190 #else 191 static struct cdevsw altq_cdevsw = 192 { altqopen, altqclose, noread, nowrite, 193 altqioctl, seltrue, nommap, nostrategy, 194 "altq", CDEV_MAJOR, nodump, nopsize, 0, -1 }; 195 #endif 196 #endif 197 198 #if !defined(__NetBSD__) && !defined(__OpenBSD__) 199 static 200 #endif 201 int 202 altqopen(dev, flag, fmt, p) 203 dev_t dev; 204 int flag, fmt; 205 struct proc *p; 206 { 207 int unit = minor(dev); 208 209 if (unit == 0) 210 return (0); 211 if (unit < naltqsw) 212 return (*altqsw[unit].d_open)(dev, flag, fmt, p); 213 214 return ENXIO; 215 } 216 217 #if !defined(__NetBSD__) && !defined(__OpenBSD__) 218 static 219 #endif 220 int 221 altqclose(dev, flag, fmt, p) 222 dev_t dev; 223 int flag, fmt; 224 struct proc *p; 225 { 226 int unit = minor(dev); 227 228 if (unit == 0) 229 return (0); 230 if (unit < naltqsw) 231 return (*altqsw[unit].d_close)(dev, flag, fmt, p); 232 233 return ENXIO; 234 } 235 236 #if !defined(__NetBSD__) && !defined(__OpenBSD__) 237 static 238 #endif 239 int 240 altqioctl(dev, cmd, addr, flag, p) 241 dev_t dev; 242 ioctlcmd_t cmd; 243 caddr_t addr; 244 int flag; 245 struct proc *p; 246 { 247 int unit = minor(dev); 248 249 if (unit == 0) { 250 struct ifnet *ifp; 251 struct altqreq *typereq; 252 struct tbrreq *tbrreq; 253 int error; 254 255 switch (cmd) { 256 case ALTQGTYPE: 257 case ALTQTBRGET: 258 break; 259 default: 260 #if (__FreeBSD_version > 400000) 261 if ((error = suser(p)) != 0) 262 return (error); 263 #else 264 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 265 return (error); 266 #endif 267 break; 268 } 269 270 switch (cmd) { 271 case ALTQGTYPE: 272 typereq = (struct altqreq *)addr; 273 if ((ifp = ifunit(typereq->ifname)) == NULL) 274 return (EINVAL); 275 typereq->arg = (u_long)ifp->if_snd.altq_type; 276 return (0); 277 case ALTQTBRSET: 278 tbrreq = (struct tbrreq *)addr; 279 if ((ifp = ifunit(tbrreq->ifname)) == NULL) 280 return (EINVAL); 281 return tbr_set(&ifp->if_snd, &tbrreq->tb_prof); 282 case ALTQTBRGET: 283 tbrreq = (struct tbrreq *)addr; 284 if ((ifp = ifunit(tbrreq->ifname)) == NULL) 285 return (EINVAL); 286 return tbr_get(&ifp->if_snd, &tbrreq->tb_prof); 287 default: 288 return (EINVAL); 289 } 290 } 291 if (unit < naltqsw) 292 return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, p); 293 294 return ENXIO; 295 } 296 297 #if !defined(__NetBSD__) 298 static int altq_devsw_installed = 0; 299 #endif 300 301 #ifdef __FreeBSD__ 302 #if (__FreeBSD_version < 400000) 303 #ifdef DEVFS 304 static void *altq_devfs_token[sizeof (altqsw) / sizeof (altqsw[0])]; 305 #endif 306 307 static void 308 altq_drvinit(unused) 309 void *unused; 310 { 311 dev_t dev; 312 #ifdef DEVFS 313 int i; 314 #endif 315 316 if (!altq_devsw_installed) { 317 dev = makedev(CDEV_MAJOR,0); 318 cdevsw_add(&dev,&altq_cdevsw,NULL); 319 altq_devsw_installed = 1; 320 #ifdef DEVFS 321 for (i=0; i<naltqsw; i++) 322 altq_devfs_token[i] = 323 devfs_add_devswf(&altq_cdevsw, i, DV_CHR, 324 0, 0, 0644, altqsw[i].d_name); 325 #endif 326 printf("altq: major number is %d\n", CDEV_MAJOR); 327 } 328 } 329 330 #else /* FreeBSD 4.x */ 331 332 static void 333 altq_drvinit(unused) 334 void *unused; 335 { 336 int unit; 337 338 cdevsw_add(&altq_cdevsw); 339 altq_devsw_installed = 1; 340 printf("altq: major number is %d\n", CDEV_MAJOR); 341 342 /* create minor devices */ 343 for (unit = 0; unit < naltqsw; unit++) 344 make_dev(&altq_cdevsw, unit, 0, 0, 0644, 345 altqsw[unit].d_name); 346 } 347 348 #endif /* FreeBSD 4.x */ 349 350 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL) 351 352 #endif 353 354 #ifdef ALTQ_KLD 355 /* 356 * KLD support 357 */ 358 static int altq_module_register __P((struct altq_module_data *)); 359 static int altq_module_deregister __P((struct altq_module_data *)); 360 361 static struct altq_module_data *altq_modules[ALTQT_MAX]; 362 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl}; 363 364 void altq_module_incref(type) 365 int type; 366 { 367 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 368 return; 369 370 altq_modules[type]->ref++; 371 } 372 373 void altq_module_declref(type) 374 int type; 375 { 376 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL) 377 return; 378 379 altq_modules[type]->ref--; 380 } 381 382 static int 383 altq_module_register(mdata) 384 struct altq_module_data *mdata; 385 { 386 int type = mdata->type; 387 388 if (type < 0 || type >= ALTQT_MAX) 389 return (EINVAL); 390 if (altqsw[type].d_open != noopen) 391 return (EBUSY); 392 altqsw[type] = *mdata->altqsw; /* set discipline functions */ 393 altq_modules[type] = mdata; /* save module data pointer */ 394 return (0); 395 } 396 397 static int 398 altq_module_deregister(mdata) 399 struct altq_module_data *mdata; 400 { 401 int type = mdata->type; 402 403 if (type < 0 || type >= ALTQT_MAX) 404 return (EINVAL); 405 if (mdata != altq_modules[type]) 406 return (EINVAL); 407 if (altq_modules[type]->ref > 0) 408 return (EBUSY); 409 altqsw[type] = noqdisc; 410 altq_modules[type] = NULL; 411 return (0); 412 } 413 414 int 415 altq_module_handler(mod, cmd, arg) 416 module_t mod; 417 int cmd; 418 void * arg; 419 { 420 struct altq_module_data *data = (struct altq_module_data *)arg; 421 int error = 0; 422 423 switch (cmd) { 424 case MOD_LOAD: 425 error = altq_module_register(data); 426 break; 427 428 case MOD_UNLOAD: 429 error = altq_module_deregister(data); 430 break; 431 432 default: 433 error = EINVAL; 434 break; 435 } 436 437 return(error); 438 } 439 440 #endif /* ALTQ_KLD */ 441