altq_conf.c revision 1.5 1 /* $NetBSD: altq_conf.c,v 1.5 2001/11/12 23:14:21 lukem Exp $ */
2 /* $KAME: altq_conf.c,v 1.10 2000/12/14 08:12:45 thorpej 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.5 2001/11/12 23:14:21 lukem 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 67 /* OpenBSD i386 (not official) */
177 #elif defined(__alpha__)
178 #define CDEV_MAJOR 52 /* OpenBSD alpha (not 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 #elif defined(__OpenBSD__)
197 static struct cdevsw altq_cdevsw = {
198 altqopen, altqclose, 0, 0, altqioctl, 0,
199 0, 0, 0, 0 };
200 #endif
201
202 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
203 static
204 #endif
205 int
206 altqopen(dev, flag, fmt, p)
207 dev_t dev;
208 int flag, fmt;
209 struct proc *p;
210 {
211 int unit = minor(dev);
212
213 if (unit == 0)
214 return (0);
215 if (unit < naltqsw)
216 return (*altqsw[unit].d_open)(dev, flag, fmt, p);
217
218 return ENXIO;
219 }
220
221 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
222 static
223 #endif
224 int
225 altqclose(dev, flag, fmt, p)
226 dev_t dev;
227 int flag, fmt;
228 struct proc *p;
229 {
230 int unit = minor(dev);
231
232 if (unit == 0)
233 return (0);
234 if (unit < naltqsw)
235 return (*altqsw[unit].d_close)(dev, flag, fmt, p);
236
237 return ENXIO;
238 }
239
240 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
241 static
242 #endif
243 int
244 altqioctl(dev, cmd, addr, flag, p)
245 dev_t dev;
246 ioctlcmd_t cmd;
247 caddr_t addr;
248 int flag;
249 struct proc *p;
250 {
251 int unit = minor(dev);
252
253 if (unit == 0) {
254 struct ifnet *ifp;
255 struct altqreq *typereq;
256 struct tbrreq *tbrreq;
257 int error;
258
259 switch (cmd) {
260 case ALTQGTYPE:
261 case ALTQTBRGET:
262 break;
263 default:
264 #if (__FreeBSD_version > 400000)
265 if ((error = suser(p)) != 0)
266 return (error);
267 #else
268 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
269 return (error);
270 #endif
271 break;
272 }
273
274 switch (cmd) {
275 case ALTQGTYPE:
276 typereq = (struct altqreq *)addr;
277 if ((ifp = ifunit(typereq->ifname)) == NULL)
278 return (EINVAL);
279 typereq->arg = (u_long)ifp->if_snd.altq_type;
280 return (0);
281 case ALTQTBRSET:
282 tbrreq = (struct tbrreq *)addr;
283 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
284 return (EINVAL);
285 return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
286 case ALTQTBRGET:
287 tbrreq = (struct tbrreq *)addr;
288 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
289 return (EINVAL);
290 return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
291 default:
292 return (EINVAL);
293 }
294 }
295 if (unit < naltqsw)
296 return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, p);
297
298 return ENXIO;
299 }
300
301
302 #if !defined(__NetBSD__)
303 static int altq_devsw_installed = 0;
304 #endif
305
306 #ifdef __FreeBSD__
307 #if (__FreeBSD_version < 400000)
308 #ifdef DEVFS
309 static void *altq_devfs_token[sizeof (altqsw) / sizeof (altqsw[0])];
310 #endif
311
312 static void
313 altq_drvinit(unused)
314 void *unused;
315 {
316 dev_t dev;
317 #ifdef DEVFS
318 int i;
319 #endif
320
321 if (!altq_devsw_installed) {
322 dev = makedev(CDEV_MAJOR,0);
323 cdevsw_add(&dev,&altq_cdevsw,NULL);
324 altq_devsw_installed = 1;
325 #ifdef DEVFS
326 for (i=0; i<naltqsw; i++)
327 altq_devfs_token[i] =
328 devfs_add_devswf(&altq_cdevsw, i, DV_CHR,
329 0, 0, 0644, altqsw[i].d_name);
330 #endif
331 printf("altq: major number is %d\n", CDEV_MAJOR);
332 }
333 }
334
335 #else /* FreeBSD 4.x */
336
337 static void
338 altq_drvinit(unused)
339 void *unused;
340 {
341 int unit;
342
343 cdevsw_add(&altq_cdevsw);
344 altq_devsw_installed = 1;
345 printf("altq: major number is %d\n", CDEV_MAJOR);
346
347 /* create minor devices */
348 for (unit = 0; unit < naltqsw; unit++)
349 make_dev(&altq_cdevsw, unit, 0, 0, 0644,
350 altqsw[unit].d_name);
351 }
352
353 #endif /* FreeBSD 4.x */
354
355 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
356
357 #elif defined(__OpenBSD__)
358
359 void
360 altqattach(int unused)
361 {
362 if (!altq_devsw_installed) {
363 bcopy(&altq_cdevsw,
364 &cdevsw[CDEV_MAJOR],
365 sizeof(struct cdevsw));
366 altq_devsw_installed = 1;
367 printf("altq: major number is %d\n", CDEV_MAJOR);
368 }
369 }
370 #elif defined(__NetBSD__)
371 /* NetBSD requires no altqattach() */
372 #else
373 #error altqattach()??
374 #endif
375
376 #ifdef ALTQ_KLD
377 /*
378 * KLD support
379 */
380 static int altq_module_register __P((struct altq_module_data *));
381 static int altq_module_deregister __P((struct altq_module_data *));
382
383 static struct altq_module_data *altq_modules[ALTQT_MAX];
384 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
385
386 void altq_module_incref(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 void altq_module_declref(type)
396 int type;
397 {
398 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
399 return;
400
401 altq_modules[type]->ref--;
402 }
403
404 static int
405 altq_module_register(mdata)
406 struct altq_module_data *mdata;
407 {
408 int type = mdata->type;
409
410 if (type < 0 || type >= ALTQT_MAX)
411 return (EINVAL);
412 if (altqsw[type].d_open != noopen)
413 return (EBUSY);
414 altqsw[type] = *mdata->altqsw; /* set discipline functions */
415 altq_modules[type] = mdata; /* save module data pointer */
416 return (0);
417 }
418
419 static int
420 altq_module_deregister(mdata)
421 struct altq_module_data *mdata;
422 {
423 int type = mdata->type;
424
425 if (type < 0 || type >= ALTQT_MAX)
426 return (EINVAL);
427 if (mdata != altq_modules[type])
428 return (EINVAL);
429 if (altq_modules[type]->ref > 0)
430 return (EBUSY);
431 altqsw[type] = noqdisc;
432 altq_modules[type] = NULL;
433 return (0);
434 }
435
436 int
437 altq_module_handler(mod, cmd, arg)
438 module_t mod;
439 int cmd;
440 void * arg;
441 {
442 struct altq_module_data *data = (struct altq_module_data *)arg;
443 int error = 0;
444
445 switch (cmd) {
446 case MOD_LOAD:
447 error = altq_module_register(data);
448 break;
449
450 case MOD_UNLOAD:
451 error = altq_module_deregister(data);
452 break;
453
454 default:
455 error = EINVAL;
456 break;
457 }
458
459 return(error);
460 }
461
462 #endif /* ALTQ_KLD */
463