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