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