altq_conf.c revision 1.14 1 /* $NetBSD: altq_conf.c,v 1.14 2006/05/15 00:05:39 christos 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.14 2006/05/15 00:05:39 christos 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 struct proc *p = l->l_proc;
262 int unit = minor(dev);
263
264 if (unit == 0) {
265 struct ifnet *ifp;
266 struct altqreq *typereq;
267 struct tbrreq *tbrreq;
268 int error;
269
270 switch (cmd) {
271 case ALTQGTYPE:
272 case ALTQTBRGET:
273 break;
274 default:
275 #if (__FreeBSD_version > 400000)
276 if ((error = suser(p)) != 0)
277 return (error);
278 #else
279 if ((error = kauth_authorize_generic(p->p_cred,
280 KAUTH_GENERIC_ISSUSER,
281 &p->p_acflag)) != 0)
282 return (error);
283 #endif
284 break;
285 }
286
287 switch (cmd) {
288 case ALTQGTYPE:
289 typereq = (struct altqreq *)addr;
290 if ((ifp = ifunit(typereq->ifname)) == NULL)
291 return (EINVAL);
292 typereq->arg = (u_long)ifp->if_snd.altq_type;
293 return (0);
294 case ALTQTBRSET:
295 tbrreq = (struct tbrreq *)addr;
296 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
297 return (EINVAL);
298 return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
299 case ALTQTBRGET:
300 tbrreq = (struct tbrreq *)addr;
301 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
302 return (EINVAL);
303 return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
304 default:
305 return (EINVAL);
306 }
307 }
308 if (unit < naltqsw)
309 return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);
310
311 return ENXIO;
312 }
313
314 #if !defined(__NetBSD__)
315 static int altq_devsw_installed = 0;
316 #endif
317
318 #ifdef __FreeBSD__
319 #if (__FreeBSD_version < 400000)
320 #ifdef DEVFS
321 static void *altq_devfs_token[sizeof (altqsw) / sizeof (altqsw[0])];
322 #endif
323
324 static void
325 altq_drvinit(unused)
326 void *unused;
327 {
328 dev_t dev;
329 #ifdef DEVFS
330 int i;
331 #endif
332
333 if (!altq_devsw_installed) {
334 dev = makedev(CDEV_MAJOR,0);
335 cdevsw_add(&dev,&altq_cdevsw,NULL);
336 altq_devsw_installed = 1;
337 #ifdef DEVFS
338 for (i=0; i<naltqsw; i++)
339 altq_devfs_token[i] =
340 devfs_add_devswf(&altq_cdevsw, i, DV_CHR,
341 0, 0, 0644, altqsw[i].d_name);
342 #endif
343 printf("altq: major number is %d\n", CDEV_MAJOR);
344 }
345 }
346
347 #else /* FreeBSD 4.x */
348
349 static void
350 altq_drvinit(unused)
351 void *unused;
352 {
353 int unit;
354
355 cdevsw_add(&altq_cdevsw);
356 altq_devsw_installed = 1;
357 printf("altq: major number is %d\n", CDEV_MAJOR);
358
359 /* create minor devices */
360 for (unit = 0; unit < naltqsw; unit++)
361 make_dev(&altq_cdevsw, unit, 0, 0, 0644,
362 altqsw[unit].d_name);
363 }
364
365 #endif /* FreeBSD 4.x */
366
367 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
368
369 #endif
370
371 #ifdef ALTQ_KLD
372 /*
373 * KLD support
374 */
375 static int altq_module_register __P((struct altq_module_data *));
376 static int altq_module_deregister __P((struct altq_module_data *));
377
378 static struct altq_module_data *altq_modules[ALTQT_MAX];
379 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
380
381 void altq_module_incref(type)
382 int type;
383 {
384 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
385 return;
386
387 altq_modules[type]->ref++;
388 }
389
390 void altq_module_declref(type)
391 int type;
392 {
393 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
394 return;
395
396 altq_modules[type]->ref--;
397 }
398
399 static int
400 altq_module_register(mdata)
401 struct altq_module_data *mdata;
402 {
403 int type = mdata->type;
404
405 if (type < 0 || type >= ALTQT_MAX)
406 return (EINVAL);
407 if (altqsw[type].d_open != noopen)
408 return (EBUSY);
409 altqsw[type] = *mdata->altqsw; /* set discipline functions */
410 altq_modules[type] = mdata; /* save module data pointer */
411 return (0);
412 }
413
414 static int
415 altq_module_deregister(mdata)
416 struct altq_module_data *mdata;
417 {
418 int type = mdata->type;
419
420 if (type < 0 || type >= ALTQT_MAX)
421 return (EINVAL);
422 if (mdata != altq_modules[type])
423 return (EINVAL);
424 if (altq_modules[type]->ref > 0)
425 return (EBUSY);
426 altqsw[type] = noqdisc;
427 altq_modules[type] = NULL;
428 return (0);
429 }
430
431 int
432 altq_module_handler(mod, cmd, arg)
433 module_t mod;
434 int cmd;
435 void * arg;
436 {
437 struct altq_module_data *data = (struct altq_module_data *)arg;
438 int error = 0;
439
440 switch (cmd) {
441 case MOD_LOAD:
442 error = altq_module_register(data);
443 break;
444
445 case MOD_UNLOAD:
446 error = altq_module_deregister(data);
447 break;
448
449 default:
450 error = EINVAL;
451 break;
452 }
453
454 return(error);
455 }
456
457 #endif /* ALTQ_KLD */
458