xref: /netbsd-src/sys/altq/altq_conf.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: altq_conf.c,v 1.21 2014/07/25 08:10:31 dholland 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.21 2014/07/25 08:10:31 dholland 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 	.d_open = altqopen,
172 	.d_close = altqclose,
173 	.d_read = noread,
174 	.d_write = nowrite,
175 	.d_ioctl = altqioctl,
176 	.d_stop = nostop,
177 	.d_tty = notty,
178 	.d_poll = nopoll,
179 	.d_mmap = nommap,
180 	.d_kqfilter = nokqfilter,
181 	.d_discard = nodiscard,
182 	.d_flag = D_OTHER,
183 };
184 
185 int
186 altqopen(dev_t dev, int flag, int fmt, struct lwp *l)
187 {
188 	int unit = minor(dev);
189 
190 	if (unit == 0)
191 		return (0);
192 	if (unit < naltqsw)
193 		return (*altqsw[unit].d_open)(dev, flag, fmt, l);
194 
195 	return ENXIO;
196 }
197 
198 int
199 altqclose(dev_t dev, int flag, int fmt, struct lwp *l)
200 {
201 	int unit = minor(dev);
202 
203 	if (unit == 0)
204 		return (0);
205 	if (unit < naltqsw)
206 		return (*altqsw[unit].d_close)(dev, flag, fmt, l);
207 
208 	return ENXIO;
209 }
210 
211 int
212 altqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l)
213 {
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 = kauth_authorize_network(l->l_cred,
232 			    KAUTH_NETWORK_ALTQ, KAUTH_REQ_NETWORK_ALTQ_CONF,
233 			    NULL, NULL, NULL)) != 0)
234 				return (error);
235 #endif
236 			break;
237 		}
238 
239 		switch (cmd) {
240 		case ALTQGTYPE:
241 			typereq = (struct altqreq *)addr;
242 			if ((ifp = ifunit(typereq->ifname)) == NULL)
243 				return (EINVAL);
244 			typereq->arg = (u_long)ifp->if_snd.altq_type;
245 			return (0);
246 		case ALTQTBRSET:
247 			tbrreq = (struct tbrreq *)addr;
248 			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
249 				return (EINVAL);
250 			return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
251 		case ALTQTBRGET:
252 			tbrreq = (struct tbrreq *)addr;
253 			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
254 				return (EINVAL);
255 			return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
256 		default:
257 			return (EINVAL);
258 		}
259 	}
260 	if (unit < naltqsw)
261 		return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);
262 
263 	return ENXIO;
264 }
265 
266 #ifdef __FreeBSD__
267 static int altq_devsw_installed = 0;
268 #endif
269 
270 #ifdef __FreeBSD__
271 static void
272 altq_drvinit(void *unused)
273 {
274 	int unit;
275 
276 #if 0
277 	mtx_init(&altq_mtx, "altq global lock", MTX_DEF);
278 #endif
279 	altq_devsw_installed = 1;
280 	printf("altq: attached. Major number assigned automatically.\n");
281 
282 	/* create minor devices */
283 	for (unit = 0; unit < naltqsw; unit++) {
284 		if (unit == 0 || altqsw[unit].d_open != NULL)
285 			altqsw[unit].dev = make_dev(&altq_cdevsw, unit,
286 			    UID_ROOT, GID_WHEEL, 0644, "altq/%s",
287 			    altqsw[unit].d_name);
288 	}
289 }
290 
291 SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
292 
293 #endif /* FreeBSD */
294 
295 #ifdef ALTQ_KLD
296 /*
297  * KLD support
298  */
299 static int altq_module_register(struct altq_module_data *);
300 static int altq_module_deregister(struct altq_module_data *);
301 
302 static struct altq_module_data *altq_modules[ALTQT_MAX];
303 #if __FreeBSD_version < 502103
304 static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
305 #else
306 static struct altqsw noqdisc = {"noq"};
307 #endif
308 
309 void altq_module_incref(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(int type)
318 {
319 	if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
320 		return;
321 
322 	altq_modules[type]->ref--;
323 }
324 
325 static int
326 altq_module_register(struct altq_module_data *mdata)
327 {
328 	int type = mdata->type;
329 
330 	if (type < 0 || type >= ALTQT_MAX)
331 		return (EINVAL);
332 #if (__FreeBSD_version < 502103)
333 	if (altqsw[type].d_open != noopen)
334 #else
335 	if (altqsw[type].d_open != NULL)
336 #endif
337 		return (EBUSY);
338 	altqsw[type] = *mdata->altqsw;	/* set discipline functions */
339 	altq_modules[type] = mdata;	/* save module data pointer */
340 #if (__FreeBSD_version < 502103)
341 	make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644,
342 		 "altq/%s", altqsw[type].d_name);
343 #else
344 	altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL,
345 	    0644, "altq/%s", altqsw[type].d_name);
346 #endif
347 	return (0);
348 }
349 
350 static int
351 altq_module_deregister(struct altq_module_data *mdata)
352 {
353 	int type = mdata->type;
354 
355 	if (type < 0 || type >= ALTQT_MAX)
356 		return (EINVAL);
357 	if (mdata != altq_modules[type])
358 		return (EINVAL);
359 	if (altq_modules[type]->ref > 0)
360 		return (EBUSY);
361 #if (__FreeBSD_version < 502103)
362 	destroy_dev(makedev(CDEV_MAJOR, type));
363 #else
364 	destroy_dev(altqsw[type].dev);
365 #endif
366 	altqsw[type] = noqdisc;
367 	altq_modules[type] = NULL;
368 	return (0);
369 }
370 
371 int
372 altq_module_handler(module_t mod, int cmd, void *arg)
373 {
374 	struct altq_module_data *data = (struct altq_module_data *)arg;
375 	int	error = 0;
376 
377 	switch (cmd) {
378 	case MOD_LOAD:
379 		error = altq_module_register(data);
380 		break;
381 
382 	case MOD_UNLOAD:
383 		error = altq_module_deregister(data);
384 		break;
385 
386 	default:
387 		error = EINVAL;
388 		break;
389 	}
390 
391 	return (error);
392 }
393 
394 #endif  /* ALTQ_KLD */
395 #endif /* ALTQ3_COMPAT */
396