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