altq_conf.c revision 1.12.12.1 1 /* $NetBSD: altq_conf.c,v 1.12.12.1 2006/03/18 12:08:18 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.1 2006/03/18 12:08:18 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 <net/if.h>
48
49 #include <altq/altq.h>
50 #include <altq/altqconf.h>
51 #include <altq/altq_conf.h>
52
53 #ifdef ALTQ3_COMPAT
54
55 #ifdef ALTQ_CBQ
56 altqdev_decl(cbq);
57 #endif
58 #ifdef ALTQ_WFQ
59 altqdev_decl(wfq);
60 #endif
61 #ifdef ALTQ_AFMAP
62 altqdev_decl(afm);
63 #endif
64 #ifdef ALTQ_FIFOQ
65 altqdev_decl(fifoq);
66 #endif
67 #ifdef ALTQ_RED
68 altqdev_decl(red);
69 #endif
70 #ifdef ALTQ_RIO
71 altqdev_decl(rio);
72 #endif
73 #ifdef ALTQ_LOCALQ
74 altqdev_decl(localq);
75 #endif
76 #ifdef ALTQ_HFSC
77 altqdev_decl(hfsc);
78 #endif
79 #ifdef ALTQ_CDNR
80 altqdev_decl(cdnr);
81 #endif
82 #ifdef ALTQ_BLUE
83 altqdev_decl(blue);
84 #endif
85 #ifdef ALTQ_PRIQ
86 altqdev_decl(priq);
87 #endif
88 #ifdef ALTQ_JOBS
89 altqdev_decl(jobs);
90 #endif
91
92 /*
93 * altq minor device (discipline) table
94 */
95 static struct altqsw altqsw[] = { /* minor */
96 {"altq", noopen, noclose, noioctl}, /* 0 (reserved) */
97 #ifdef ALTQ_CBQ
98 {"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */
99 #else
100 {"noq", noopen, noclose, noioctl}, /* 1 */
101 #endif
102 #ifdef ALTQ_WFQ
103 {"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */
104 #else
105 {"noq", noopen, noclose, noioctl}, /* 2 */
106 #endif
107 #ifdef ALTQ_AFMAP
108 {"afm", afmopen, afmclose, afmioctl}, /* 3 */
109 #else
110 {"noq", noopen, noclose, noioctl}, /* 3 */
111 #endif
112 #ifdef ALTQ_FIFOQ
113 {"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */
114 #else
115 {"noq", noopen, noclose, noioctl}, /* 4 */
116 #endif
117 #ifdef ALTQ_RED
118 {"red", redopen, redclose, redioctl}, /* 5 */
119 #else
120 {"noq", noopen, noclose, noioctl}, /* 5 */
121 #endif
122 #ifdef ALTQ_RIO
123 {"rio", rioopen, rioclose, rioioctl}, /* 6 */
124 #else
125 {"noq", noopen, noclose, noioctl}, /* 6 */
126 #endif
127 #ifdef ALTQ_LOCALQ
128 {"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */
129 #else
130 {"noq", noopen, noclose, noioctl}, /* 7 (local use) */
131 #endif
132 #ifdef ALTQ_HFSC
133 {"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */
134 #else
135 {"noq", noopen, noclose, noioctl}, /* 8 */
136 #endif
137 #ifdef ALTQ_CDNR
138 {"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */
139 #else
140 {"noq", noopen, noclose, noioctl}, /* 9 */
141 #endif
142 #ifdef ALTQ_BLUE
143 {"blue",blueopen, blueclose, blueioctl}, /* 10 */
144 #else
145 {"noq", noopen, noclose, noioctl}, /* 10 */
146 #endif
147 #ifdef ALTQ_PRIQ
148 {"priq",priqopen, priqclose, priqioctl}, /* 11 */
149 #else
150 {"noq", noopen, noclose, noioctl}, /* 11 */
151 #endif
152 #ifdef ALTQ_JOBS
153 {"jobs",jobsopen, jobsclose, jobsioctl}, /* 12 */
154 #else
155 {"noq", noopen, noclose, noioctl}, /* 12 */
156 #endif
157 };
158
159 /*
160 * altq major device support
161 */
162 int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
163
164 dev_type_open(altqopen);
165 dev_type_close(altqclose);
166 dev_type_ioctl(altqioctl);
167
168 const struct cdevsw altq_cdevsw = {
169 altqopen, altqclose, noread, nowrite, altqioctl,
170 nostop, notty, nopoll, nommap, nokqfilter
171 };
172
173 int
174 altqopen(dev, flag, fmt, l)
175 dev_t dev;
176 int flag, fmt;
177 struct lwp *l;
178 {
179 int unit = minor(dev);
180
181 if (unit == 0)
182 return (0);
183 if (unit < naltqsw)
184 return (*altqsw[unit].d_open)(dev, flag, fmt, l);
185
186 return ENXIO;
187 }
188
189 int
190 altqclose(dev, flag, fmt, l)
191 dev_t dev;
192 int flag, fmt;
193 struct lwp *l;
194 {
195 int unit = minor(dev);
196
197 if (unit == 0)
198 return (0);
199 if (unit < naltqsw)
200 return (*altqsw[unit].d_close)(dev, flag, fmt, l);
201
202 return ENXIO;
203 }
204
205 int
206 altqioctl(dev, cmd, addr, flag, l)
207 dev_t dev;
208 ioctlcmd_t cmd;
209 caddr_t addr;
210 int flag;
211 struct lwp *l;
212 {
213 struct proc *p = l->l_proc;
214 int unit = minor(dev);
215
216 if (unit == 0) {
217 struct ifnet *ifp;
218 struct altqreq *typereq;
219 struct tbrreq *tbrreq;
220 int error;
221
222 switch (cmd) {
223 case ALTQGTYPE:
224 case ALTQTBRGET:
225 break;
226 default:
227 #if (__FreeBSD_version > 400000)
228 if ((error = suser(p)) != 0)
229 return (error);
230 #else
231 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
232 return (error);
233 #endif
234 break;
235 }
236
237 switch (cmd) {
238 case ALTQGTYPE:
239 typereq = (struct altqreq *)addr;
240 if ((ifp = ifunit(typereq->ifname)) == NULL)
241 return (EINVAL);
242 typereq->arg = (u_long)ifp->if_snd.altq_type;
243 return (0);
244 case ALTQTBRSET:
245 tbrreq = (struct tbrreq *)addr;
246 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
247 return (EINVAL);
248 return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
249 case ALTQTBRGET:
250 tbrreq = (struct tbrreq *)addr;
251 if ((ifp = ifunit(tbrreq->ifname)) == NULL)
252 return (EINVAL);
253 return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
254 default:
255 return (EINVAL);
256 }
257 }
258 if (unit < naltqsw)
259 return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);
260
261 return ENXIO;
262 }
263
264 #ifdef __FreeBSD__
265 static int altq_devsw_installed = 0;
266 #endif
267
268 #ifdef __FreeBSD__
269 static void
270 altq_drvinit(unused)
271 void *unused;
272 {
273 int unit;
274
275 #if 0
276 mtx_init(&altq_mtx, "altq global lock", MTX_DEF);
277 #endif
278 altq_devsw_installed = 1;
279 printf("altq: attached. Major number assigned automatically.\n");
280
281 /* create minor devices */
282 for (unit = 0; unit < naltqsw; unit++) {
283 if (unit == 0 || altqsw[unit].d_open != NULL)
284 altqsw[unit].dev = make_dev(&altq_cdevsw, unit,
285 UID_ROOT, GID_WHEEL, 0644, "altq/%s",
286 altqsw[unit].d_name);
287 }
288 }
289
290 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
291
292 #endif /* FreeBSD */
293
294 #ifdef ALTQ_KLD
295 /*
296 * KLD support
297 */
298 static int altq_module_register(struct altq_module_data *);
299 static int altq_module_deregister(struct altq_module_data *);
300
301 static struct altq_module_data *altq_modules[ALTQT_MAX];
302 #if __FreeBSD_version < 502103
303 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
304 #else
305 static struct altqsw noqdisc = {"noq"};
306 #endif
307
308 void altq_module_incref(type)
309 int type;
310 {
311 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
312 return;
313
314 altq_modules[type]->ref++;
315 }
316
317 void altq_module_declref(type)
318 int type;
319 {
320 if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
321 return;
322
323 altq_modules[type]->ref--;
324 }
325
326 static int
327 altq_module_register(mdata)
328 struct altq_module_data *mdata;
329 {
330 int type = mdata->type;
331
332 if (type < 0 || type >= ALTQT_MAX)
333 return (EINVAL);
334 #if (__FreeBSD_version < 502103)
335 if (altqsw[type].d_open != noopen)
336 #else
337 if (altqsw[type].d_open != NULL)
338 #endif
339 return (EBUSY);
340 altqsw[type] = *mdata->altqsw; /* set discipline functions */
341 altq_modules[type] = mdata; /* save module data pointer */
342 #if (__FreeBSD_version < 502103)
343 make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644,
344 "altq/%s", altqsw[type].d_name);
345 #else
346 altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL,
347 0644, "altq/%s", altqsw[type].d_name);
348 #endif
349 return (0);
350 }
351
352 static int
353 altq_module_deregister(mdata)
354 struct altq_module_data *mdata;
355 {
356 int type = mdata->type;
357
358 if (type < 0 || type >= ALTQT_MAX)
359 return (EINVAL);
360 if (mdata != altq_modules[type])
361 return (EINVAL);
362 if (altq_modules[type]->ref > 0)
363 return (EBUSY);
364 #if (__FreeBSD_version < 502103)
365 destroy_dev(makedev(CDEV_MAJOR, type));
366 #else
367 destroy_dev(altqsw[type].dev);
368 #endif
369 altqsw[type] = noqdisc;
370 altq_modules[type] = NULL;
371 return (0);
372 }
373
374 int
375 altq_module_handler(mod, cmd, arg)
376 module_t mod;
377 int cmd;
378 void * arg;
379 {
380 struct altq_module_data *data = (struct altq_module_data *)arg;
381 int error = 0;
382
383 switch (cmd) {
384 case MOD_LOAD:
385 error = altq_module_register(data);
386 break;
387
388 case MOD_UNLOAD:
389 error = altq_module_deregister(data);
390 break;
391
392 default:
393 error = EINVAL;
394 break;
395 }
396
397 return(error);
398 }
399
400 #endif /* ALTQ_KLD */
401 #endif /* ALTQ3_COMPAT */
402