altq_conf.c revision 1.12.12.2 1 /* $NetBSD: altq_conf.c,v 1.12.12.2 2006/06/09 19:52:35 peter Exp $ */
2 /* $KAME: altq_conf.c,v 1.24 2005/04/13 03:44:24 suz Exp $ */
3
4 /*
5 * Copyright (C) 1997-2003
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.12.12.2 2006/06/09 19:52:35 peter Exp $");
32
33 #ifdef _KERNEL_OPT
34 #include "opt_altq.h"
35 #include "opt_inet.h"
36 #endif
37
38 /*
39 * altq device interface.
40 */
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/socket.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/errno.h>
47 #include <sys/kauth.h>
48
49 #include <net/if.h>
50
51 #include <altq/altq.h>
52 #include <altq/altqconf.h>
53 #include <altq/altq_conf.h>
54
55 #ifdef ALTQ3_COMPAT
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 #ifdef ALTQ_JOBS
91 altqdev_decl(jobs);
92 #endif
93
94 /*
95 * altq minor device (discipline) table
96 */
97 static struct altqsw altqsw[] = { /* minor */
98 {"altq", 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 #ifdef ALTQ_JOBS
155 {"jobs",jobsopen, jobsclose, jobsioctl}, /* 12 */
156 #else
157 {"noq", noopen, noclose, noioctl}, /* 12 */
158 #endif
159 };
160
161 /*
162 * altq major device support
163 */
164 int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
165
166 dev_type_open(altqopen);
167 dev_type_close(altqclose);
168 dev_type_ioctl(altqioctl);
169
170 const struct cdevsw altq_cdevsw = {
171 altqopen, altqclose, noread, nowrite, altqioctl,
172 nostop, notty, nopoll, nommap, nokqfilter
173 };
174
175 int
176 altqopen(dev, flag, fmt, l)
177 dev_t dev;
178 int flag, fmt;
179 struct lwp *l;
180 {
181 int unit = minor(dev);
182
183 if (unit == 0)
184 return (0);
185 if (unit < naltqsw)
186 return (*altqsw[unit].d_open)(dev, flag, fmt, l);
187
188 return ENXIO;
189 }
190
191 int
192 altqclose(dev, flag, fmt, l)
193 dev_t dev;
194 int flag, fmt;
195 struct lwp *l;
196 {
197 int unit = minor(dev);
198
199 if (unit == 0)
200 return (0);
201 if (unit < naltqsw)
202 return (*altqsw[unit].d_close)(dev, flag, fmt, l);
203
204 return ENXIO;
205 }
206
207 int
208 altqioctl(dev, cmd, addr, flag, l)
209 dev_t dev;
210 ioctlcmd_t cmd;
211 caddr_t addr;
212 int flag;
213 struct lwp *l;
214 {
215 struct proc *p = l->l_proc;
216 int unit = minor(dev);
217
218 if (unit == 0) {
219 struct ifnet *ifp;
220 struct altqreq *typereq;
221 struct tbrreq *tbrreq;
222 int error;
223
224 switch (cmd) {
225 case ALTQGTYPE:
226 case ALTQTBRGET:
227 break;
228 default:
229 #if (__FreeBSD_version > 400000)
230 if ((error = suser(p)) != 0)
231 return (error);
232 #else
233 if ((error = kauth_authorize_generic(p->p_cred,
234 KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
235 return (error);
236 #endif
237 break;
238 }
239
240 switch (cmd) {
241 case ALTQGTYPE:
242 typereq = (struct altqreq *)addr;
243 if ((ifp = ifunit(typereq->ifname)) == NULL)
244 return (EINVAL);
245 typereq->arg = (u_long)ifp->if_snd.altq_type;
246 return (0);
247 case ALTQTBRSET:
248 tbrreq = (struct tbrreq *)addr;
249 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
250 return (EINVAL);
251 return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
252 case ALTQTBRGET:
253 tbrreq = (struct tbrreq *)addr;
254 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
255 return (EINVAL);
256 return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
257 default:
258 return (EINVAL);
259 }
260 }
261 if (unit < naltqsw)
262 return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);
263
264 return ENXIO;
265 }
266
267 #ifdef __FreeBSD__
268 static int altq_devsw_installed = 0;
269 #endif
270
271 #ifdef __FreeBSD__
272 static void
273 altq_drvinit(unused)
274 void *unused;
275 {
276 int unit;
277
278 #if 0
279 mtx_init(&altq_mtx, "altq global lock", MTX_DEF);
280 #endif
281 altq_devsw_installed = 1;
282 printf("altq: attached. Major number assigned automatically.\n");
283
284 /* create minor devices */
285 for (unit = 0; unit < naltqsw; unit++) {
286 if (unit == 0 || altqsw[unit].d_open != NULL)
287 altqsw[unit].dev = make_dev(&altq_cdevsw, unit,
288 UID_ROOT, GID_WHEEL, 0644, "altq/%s",
289 altqsw[unit].d_name);
290 }
291 }
292
293 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
294
295 #endif /* FreeBSD */
296
297 #ifdef ALTQ_KLD
298 /*
299 * KLD support
300 */
301 static int altq_module_register(struct altq_module_data *);
302 static int altq_module_deregister(struct altq_module_data *);
303
304 static struct altq_module_data *altq_modules[ALTQT_MAX];
305 #if __FreeBSD_version < 502103
306 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
307 #else
308 static struct altqsw noqdisc = {"noq"};
309 #endif
310
311 void altq_module_incref(type)
312 int type;
313 {
314 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
315 return;
316
317 altq_modules[type]->ref++;
318 }
319
320 void altq_module_declref(type)
321 int type;
322 {
323 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
324 return;
325
326 altq_modules[type]->ref--;
327 }
328
329 static int
330 altq_module_register(mdata)
331 struct altq_module_data *mdata;
332 {
333 int type = mdata->type;
334
335 if (type < 0 || type >= ALTQT_MAX)
336 return (EINVAL);
337 #if (__FreeBSD_version < 502103)
338 if (altqsw[type].d_open != noopen)
339 #else
340 if (altqsw[type].d_open != NULL)
341 #endif
342 return (EBUSY);
343 altqsw[type] = *mdata->altqsw; /* set discipline functions */
344 altq_modules[type] = mdata; /* save module data pointer */
345 #if (__FreeBSD_version < 502103)
346 make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644,
347 "altq/%s", altqsw[type].d_name);
348 #else
349 altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL,
350 0644, "altq/%s", altqsw[type].d_name);
351 #endif
352 return (0);
353 }
354
355 static int
356 altq_module_deregister(mdata)
357 struct altq_module_data *mdata;
358 {
359 int type = mdata->type;
360
361 if (type < 0 || type >= ALTQT_MAX)
362 return (EINVAL);
363 if (mdata != altq_modules[type])
364 return (EINVAL);
365 if (altq_modules[type]->ref > 0)
366 return (EBUSY);
367 #if (__FreeBSD_version < 502103)
368 destroy_dev(makedev(CDEV_MAJOR, type));
369 #else
370 destroy_dev(altqsw[type].dev);
371 #endif
372 altqsw[type] = noqdisc;
373 altq_modules[type] = NULL;
374 return (0);
375 }
376
377 int
378 altq_module_handler(mod, cmd, arg)
379 module_t mod;
380 int cmd;
381 void * arg;
382 {
383 struct altq_module_data *data = (struct altq_module_data *)arg;
384 int error = 0;
385
386 switch (cmd) {
387 case MOD_LOAD:
388 error = altq_module_register(data);
389 break;
390
391 case MOD_UNLOAD:
392 error = altq_module_deregister(data);
393 break;
394
395 default:
396 error = EINVAL;
397 break;
398 }
399
400 return(error);
401 }
402
403 #endif /* ALTQ_KLD */
404 #endif /* ALTQ3_COMPAT */
405