1185029Spjd/*	$NetBSD: altq_conf.c,v 1.22 2021/09/21 14:30:15 christos Exp $	*/
2185029Spjd/*	$KAME: altq_conf.c,v 1.24 2005/04/13 03:44:24 suz Exp $	*/
3185029Spjd
4185029Spjd/*
5185029Spjd * Copyright (C) 1997-2003
6185029Spjd *	Sony Computer Science Laboratories Inc.  All rights reserved.
7185029Spjd *
8185029Spjd * Redistribution and use in source and binary forms, with or without
9185029Spjd * modification, are permitted provided that the following conditions
10185029Spjd * are met:
11185029Spjd * 1. Redistributions of source code must retain the above copyright
12185029Spjd *    notice, this list of conditions and the following disclaimer.
13185029Spjd * 2. Redistributions in binary form must reproduce the above copyright
14185029Spjd *    notice, this list of conditions and the following disclaimer in the
15185029Spjd *    documentation and/or other materials provided with the distribution.
16185029Spjd *
17185029Spjd * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
18185029Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19185029Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20185029Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
21185029Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22185029Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24185029Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25185029Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26185029Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27185029Spjd * SUCH DAMAGE.
28185029Spjd */
29185029Spjd
30185029Spjd#include <sys/cdefs.h>
31185029Spjd__KERNEL_RCSID(0, "$NetBSD: altq_conf.c,v 1.22 2021/09/21 14:30:15 christos Exp $");
32185029Spjd
33185029Spjd#ifdef _KERNEL_OPT
34219089Spjd#include "opt_altq.h"
35235361Savg#include "opt_inet.h"
36219089Spjd#endif
37185029Spjd
38185029Spjd/*
39185029Spjd * altq device interface.
40235329Savg */
41235329Savg#include <sys/param.h>
42235390Savg#include <sys/systm.h>
43235329Savg#include <sys/socket.h>
44235329Savg#include <sys/kernel.h>
45235329Savg#include <sys/proc.h>
46235329Savg#include <sys/errno.h>
47185029Spjd#include <sys/kauth.h>
48185029Spjd
49185029Spjd#include <net/if.h>
50185029Spjd
51185029Spjd#include <altq/altq.h>
52236884Smm#include <altq/altqconf.h>
53236884Smm#include <altq/altq_conf.h>
54236884Smm
55236884Smm#ifdef ALTQ3_COMPAT
56263397Sdelphij
57263397Sdelphij#ifdef ALTQ_CBQ
58263397Sdelphijaltqdev_decl(cbq);
59268649Sdelphij#endif
60236884Smm#ifdef ALTQ_WFQ
61236884Smmaltqdev_decl(wfq);
62236884Smm#endif
63185029Spjd#ifdef ALTQ_AFMAP
64185029Spjdaltqdev_decl(afm);
65185029Spjd#endif
66185029Spjd#ifdef ALTQ_FIFOQ
67185029Spjdaltqdev_decl(fifoq);
68185029Spjd#endif
69185029Spjd#ifdef ALTQ_RED
70185029Spjdaltqdev_decl(red);
71185029Spjd#endif
72185029Spjd#ifdef ALTQ_RIO
73192194Sdfraltqdev_decl(rio);
74185029Spjd#endif
75200309Sjhb#ifdef ALTQ_LOCALQ
76185029Spjdaltqdev_decl(localq);
77235390Savg#endif
78241291Savg#ifdef ALTQ_HFSC
79241291Savgaltqdev_decl(hfsc);
80198420Srnoland#endif
81185029Spjd#ifdef ALTQ_CDNR
82185029Spjdaltqdev_decl(cdnr);
83185029Spjd#endif
84185029Spjd#ifdef ALTQ_BLUE
85185029Spjdaltqdev_decl(blue);
86185029Spjd#endif
87192194Sdfr#ifdef ALTQ_PRIQ
88192194Sdfraltqdev_decl(priq);
89192194Sdfr#endif
90192194Sdfr#ifdef ALTQ_JOBS
91192194Sdfraltqdev_decl(jobs);
92185029Spjd#endif
93185029Spjd
94185029Spjd/*
95185029Spjd * altq minor device (discipline) table
96219089Spjd */
97219089Spjdstatic struct altqsw altqsw[] = {				/* minor */
98192194Sdfr	{"altq", noopen,	noclose,	noioctl},  /* 0 (reserved) */
99219089Spjd#ifdef ALTQ_CBQ
100192194Sdfr	{"cbq",	cbqopen,	cbqclose,	cbqioctl},	/* 1 */
101219089Spjd#else
102192194Sdfr	{"noq",	noopen,		noclose,	noioctl},	/* 1 */
103192194Sdfr#endif
104192194Sdfr#ifdef ALTQ_WFQ
105219089Spjd	{"wfq",	wfqopen,	wfqclose,	wfqioctl},	/* 2 */
106219089Spjd#else
107192194Sdfr	{"noq",	noopen,		noclose,	noioctl},	/* 2 */
108219089Spjd#endif
109192194Sdfr#ifdef ALTQ_AFMAP
110192194Sdfr	{"afm",	afmopen,	afmclose,	afmioctl},	/* 3 */
111192194Sdfr#else
112219089Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 3 */
113192194Sdfr#endif
114192194Sdfr#ifdef ALTQ_FIFOQ
115219089Spjd	{"fifoq", fifoqopen,	fifoqclose,	fifoqioctl},	/* 4 */
116219089Spjd#else
117219089Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 4 */
118219089Spjd#endif
119219089Spjd#ifdef ALTQ_RED
120192194Sdfr	{"red", redopen,	redclose,	redioctl},	/* 5 */
121192194Sdfr#else
122185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 5 */
123185029Spjd#endif
124185029Spjd#ifdef ALTQ_RIO
125185029Spjd	{"rio", rioopen,	rioclose,	rioioctl},	/* 6 */
126185029Spjd#else
127185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 6 */
128185029Spjd#endif
129185029Spjd#ifdef ALTQ_LOCALQ
130185029Spjd	{"localq",localqopen,	localqclose,	localqioctl}, /* 7 (local use) */
131185029Spjd#else
132185029Spjd	{"noq",	noopen,		noclose,	noioctl},  /* 7 (local use) */
133185029Spjd#endif
134185029Spjd#ifdef ALTQ_HFSC
135185029Spjd	{"hfsc",hfscopen,	hfscclose,	hfscioctl},	/* 8 */
136185029Spjd#else
137185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 8 */
138185029Spjd#endif
139185029Spjd#ifdef ALTQ_CDNR
140185029Spjd	{"cdnr",cdnropen,	cdnrclose,	cdnrioctl},	/* 9 */
141185029Spjd#else
142185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 9 */
143185029Spjd#endif
144185029Spjd#ifdef ALTQ_BLUE
145185029Spjd	{"blue",blueopen,	blueclose,	blueioctl},	/* 10 */
146185029Spjd#else
147185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 10 */
148185029Spjd#endif
149185029Spjd#ifdef ALTQ_PRIQ
150185029Spjd	{"priq",priqopen,	priqclose,	priqioctl},	/* 11 */
151185029Spjd#else
152185029Spjd	{"noq",	noopen,		noclose,	noioctl},	/* 11 */
153185029Spjd#endif
154185029Spjd#ifdef ALTQ_JOBS
155185029Spjd	{"jobs",jobsopen,	jobsclose,	jobsioctl},	/* 12 */
156185029Spjd#else
157185029Spjd	{"noq", noopen,		noclose,	noioctl},	/* 12 */
158185029Spjd#endif
159185029Spjd};
160185029Spjd
161185029Spjd/*
162185029Spjd * altq major device support
163185029Spjd */
164185029Spjdint	naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
165185029Spjd
166185029Spjddev_type_open(altqopen);
167185029Spjddev_type_close(altqclose);
168185029Spjddev_type_ioctl(altqioctl);
169185029Spjd
170185029Spjdconst struct cdevsw altq_cdevsw = {
171185029Spjd	.d_open = altqopen,
172185029Spjd	.d_close = altqclose,
173185029Spjd	.d_read = noread,
174185029Spjd	.d_write = nowrite,
175185029Spjd	.d_ioctl = altqioctl,
176185029Spjd	.d_stop = nostop,
177185029Spjd	.d_tty = notty,
178185029Spjd	.d_poll = nopoll,
179185029Spjd	.d_mmap = nommap,
180185029Spjd	.d_kqfilter = nokqfilter,
181185029Spjd	.d_discard = nodiscard,
182185029Spjd	.d_flag = D_OTHER,
183185029Spjd};
184185029Spjd
185185029Spjdint
186185029Spjdaltqopen(dev_t dev, int flag, int fmt, struct lwp *l)
187185029Spjd{
188185029Spjd	int unit = minor(dev);
189185029Spjd
190185029Spjd	if (unit == 0)
191185029Spjd		return (0);
192185029Spjd	if (unit < naltqsw)
193185029Spjd		return (*altqsw[unit].d_open)(dev, flag, fmt, l);
194185029Spjd
195185029Spjd	return ENXIO;
196185029Spjd}
197185029Spjd
198185029Spjdint
199185029Spjdaltqclose(dev_t dev, int flag, int fmt, struct lwp *l)
200185029Spjd{
201185029Spjd	int unit = minor(dev);
202185029Spjd
203185029Spjd	if (unit == 0)
204185029Spjd		return (0);
205185029Spjd	if (unit < naltqsw)
206185029Spjd		return (*altqsw[unit].d_close)(dev, flag, fmt, l);
207185029Spjd
208185029Spjd	return ENXIO;
209185029Spjd}
210185029Spjd
211185029Spjdint
212185029Spjdaltqioctl(dev_t dev, ioctlcmd_t cmd, void *addr, int flag, struct lwp *l)
213185029Spjd{
214236884Smm	int unit = minor(dev);
215236884Smm
216236884Smm	if (unit == 0) {
217236884Smm		struct ifnet *ifp;
218236884Smm		struct altqreq *typereq;
219236884Smm		struct tbrreq *tbrreq;
220236884Smm		int error;
221236884Smm
222236884Smm		switch (cmd) {
223236884Smm		case ALTQGTYPE:
224236884Smm		case ALTQTBRGET:
225236884Smm			break;
226236884Smm		default:
227236884Smm			if ((error = kauth_authorize_network(
228236884Smm			    l->l_cred, KAUTH_NETWORK_ALTQ,
229236884Smm			    KAUTH_REQ_NETWORK_ALTQ_CONF, NULL, NULL,
230236884Smm			    NULL)) != 0)
231236884Smm				return (error);
232236884Smm			break;
233236884Smm		}
234236884Smm
235236884Smm		switch (cmd) {
236236884Smm		case ALTQGTYPE:
237236884Smm			typereq = (struct altqreq *)addr;
238236884Smm			if ((ifp = ifunit(typereq->ifname)) == NULL)
239236884Smm				return (EINVAL);
240236884Smm			typereq->arg = (u_long)ifp->if_snd.altq_type;
241236884Smm			return (0);
242236884Smm		case ALTQTBRSET:
243236884Smm			tbrreq = (struct tbrreq *)addr;
244236884Smm			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
245236884Smm				return (EINVAL);
246236884Smm			return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
247236884Smm		case ALTQTBRGET:
248236884Smm			tbrreq = (struct tbrreq *)addr;
249236884Smm			if ((ifp = ifunit(tbrreq->ifname)) == NULL)
250236884Smm				return (EINVAL);
251236884Smm			return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
252236884Smm		default:
253236884Smm			return (EINVAL);
254236884Smm		}
255236884Smm	}
256236884Smm	if (unit < naltqsw)
257236884Smm		return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, l);
258236884Smm
259236884Smm	return ENXIO;
260236884Smm}
261236884Smm
262236884Smm#ifdef __FreeBSD__
263236884Smmstatic int altq_devsw_installed = 0;
264236884Smm#endif
265185029Spjd
266185029Spjd#ifdef __FreeBSD__
267185029Spjdstatic void
268185029Spjdaltq_drvinit(void *unused)
269185029Spjd{
270185029Spjd	int unit;
271185029Spjd
272185029Spjd#if 0
273185029Spjd	mtx_init(&altq_mtx, "altq global lock", MTX_DEF);
274185029Spjd#endif
275185029Spjd	altq_devsw_installed = 1;
276185029Spjd	printf("altq: attached. Major number assigned automatically.\n");
277185029Spjd
278185029Spjd	/* create minor devices */
279185029Spjd	for (unit = 0; unit < naltqsw; unit++) {
280185029Spjd		if (unit == 0 || altqsw[unit].d_open != NULL)
281185029Spjd			altqsw[unit].dev = make_dev(&altq_cdevsw, unit,
282185029Spjd			    UID_ROOT, GID_WHEEL, 0644, "altq/%s",
283185029Spjd			    altqsw[unit].d_name);
284185029Spjd	}
285185029Spjd}
286185029Spjd
287185029SpjdSYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
288185029Spjd
289185029Spjd#endif /* FreeBSD */
290185029Spjd
291185029Spjd#ifdef ALTQ_KLD
292185029Spjd/*
293185029Spjd * KLD support
294185029Spjd */
295185029Spjdstatic int altq_module_register(struct altq_module_data *);
296185029Spjdstatic int altq_module_deregister(struct altq_module_data *);
297185029Spjd
298185029Spjdstatic struct altq_module_data *altq_modules[ALTQT_MAX];
299185029Spjd#if __FreeBSD_version < 502103
300185029Spjdstatic struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
301185029Spjd#else
302185029Spjdstatic struct altqsw noqdisc = {"noq"};
303185029Spjd#endif
304185029Spjd
305185029Spjdvoid altq_module_incref(int type)
306185029Spjd{
307185029Spjd	if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
308185029Spjd		return;
309185029Spjd
310185029Spjd	altq_modules[type]->ref++;
311185029Spjd}
312185029Spjd
313185029Spjdvoid altq_module_declref(int type)
314185029Spjd{
315185029Spjd	if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
316185029Spjd		return;
317185029Spjd
318185029Spjd	altq_modules[type]->ref--;
319185029Spjd}
320185029Spjd
321185029Spjdstatic int
322185029Spjdaltq_module_register(struct altq_module_data *mdata)
323185029Spjd{
324185029Spjd	int type = mdata->type;
325185029Spjd
326185029Spjd	if (type < 0 || type >= ALTQT_MAX)
327185029Spjd		return (EINVAL);
328185029Spjd#if (__FreeBSD_version < 502103)
329185029Spjd	if (altqsw[type].d_open != noopen)
330185029Spjd#else
331185029Spjd	if (altqsw[type].d_open != NULL)
332185029Spjd#endif
333185029Spjd		return (EBUSY);
334185029Spjd	altqsw[type] = *mdata->altqsw;	/* set discipline functions */
335185029Spjd	altq_modules[type] = mdata;	/* save module data pointer */
336185029Spjd#if (__FreeBSD_version < 502103)
337185029Spjd	make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL, 0644,
338185029Spjd		 "altq/%s", altqsw[type].d_name);
339185029Spjd#else
340185029Spjd	altqsw[type].dev = make_dev(&altq_cdevsw, type, UID_ROOT, GID_WHEEL,
341185029Spjd	    0644, "altq/%s", altqsw[type].d_name);
342185029Spjd#endif
343185029Spjd	return (0);
344185029Spjd}
345185029Spjd
346185029Spjdstatic int
347185029Spjdaltq_module_deregister(struct altq_module_data *mdata)
348185029Spjd{
349185029Spjd	int type = mdata->type;
350185029Spjd
351185029Spjd	if (type < 0 || type >= ALTQT_MAX)
352185029Spjd		return (EINVAL);
353185029Spjd	if (mdata != altq_modules[type])
354185029Spjd		return (EINVAL);
355185029Spjd	if (altq_modules[type]->ref > 0)
356185029Spjd		return (EBUSY);
357185029Spjd#if (__FreeBSD_version < 502103)
358235361Savg	destroy_dev(makedev(CDEV_MAJOR, type));
359185029Spjd#else
360185029Spjd	destroy_dev(altqsw[type].dev);
361185029Spjd#endif
362185029Spjd	altqsw[type] = noqdisc;
363185029Spjd	altq_modules[type] = NULL;
364185029Spjd	return (0);
365185029Spjd}
366185029Spjd
367185029Spjdint
368185029Spjdaltq_module_handler(module_t mod, int cmd, void *arg)
369185029Spjd{
370185029Spjd	struct altq_module_data *data = (struct altq_module_data *)arg;
371185029Spjd	int	error = 0;
372185029Spjd
373185029Spjd	switch (cmd) {
374185029Spjd	case MOD_LOAD:
375185029Spjd		error = altq_module_register(data);
376185029Spjd		break;
377185029Spjd
378185029Spjd	case MOD_UNLOAD:
379185029Spjd		error = altq_module_deregister(data);
380185029Spjd		break;
381185029Spjd
382185029Spjd	default:
383185029Spjd		error = EINVAL;
384185029Spjd		break;
385185029Spjd	}
386185029Spjd
387185029Spjd	return (error);
388185029Spjd}
389185029Spjd
390185029Spjd#endif  /* ALTQ_KLD */
391185029Spjd#endif /* ALTQ3_COMPAT */
392185029Spjd