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