e0cc03a09b
kqueue provides a stateful and efficient event notification framework currently supported events include socket, file, directory, fifo, pipe, tty and device changes, and monitoring of processes and signals kqueue is supported by all writable filesystems in NetBSD tree (with exception of Coda) and all device drivers supporting poll(2) based on work done by Jonathan Lemon for FreeBSD initial NetBSD port done by Luke Mewburn and Jason Thorpe
454 lines
10 KiB
C
454 lines
10 KiB
C
/* $NetBSD: altq_conf.c,v 1.10 2002/10/23 09:10:25 jdolecek Exp $ */
|
|
/* $KAME: altq_conf.c,v 1.13 2002/01/29 10:16:01 kjc Exp $ */
|
|
|
|
/*
|
|
* Copyright (C) 1997-2000
|
|
* Sony Computer Science Laboratories Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: altq_conf.c,v 1.10 2002/10/23 09:10:25 jdolecek Exp $");
|
|
|
|
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
|
#include "opt_altq.h"
|
|
#if (__FreeBSD__ != 2)
|
|
#include "opt_inet.h"
|
|
#ifdef __FreeBSD__
|
|
#include "opt_inet6.h"
|
|
#endif
|
|
#endif
|
|
#endif /* __FreeBSD__ || __NetBSD__ */
|
|
|
|
/*
|
|
* altq device interface.
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <sys/systm.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/kernel.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/errno.h>
|
|
#if defined(__FreeBSD__) && (__FreeBSD_version < 400000) && defined(DEVFS)
|
|
#include <sys/devfsext.h>
|
|
#endif /*DEVFS*/
|
|
#include <net/if.h>
|
|
|
|
#include <altq/altq.h>
|
|
#include <altq/altqconf.h>
|
|
#include <altq/altq_conf.h>
|
|
|
|
#ifdef ALTQ_CBQ
|
|
altqdev_decl(cbq);
|
|
#endif
|
|
#ifdef ALTQ_WFQ
|
|
altqdev_decl(wfq);
|
|
#endif
|
|
#ifdef ALTQ_AFMAP
|
|
altqdev_decl(afm);
|
|
#endif
|
|
#ifdef ALTQ_FIFOQ
|
|
altqdev_decl(fifoq);
|
|
#endif
|
|
#ifdef ALTQ_RED
|
|
altqdev_decl(red);
|
|
#endif
|
|
#ifdef ALTQ_RIO
|
|
altqdev_decl(rio);
|
|
#endif
|
|
#ifdef ALTQ_LOCALQ
|
|
altqdev_decl(localq);
|
|
#endif
|
|
#ifdef ALTQ_HFSC
|
|
altqdev_decl(hfsc);
|
|
#endif
|
|
#ifdef ALTQ_CDNR
|
|
altqdev_decl(cdnr);
|
|
#endif
|
|
#ifdef ALTQ_BLUE
|
|
altqdev_decl(blue);
|
|
#endif
|
|
#ifdef ALTQ_PRIQ
|
|
altqdev_decl(priq);
|
|
#endif
|
|
|
|
/*
|
|
* altq minor device (discipline) table
|
|
*/
|
|
static struct altqsw altqsw[] = { /* minor */
|
|
{"noq", noopen, noclose, noioctl}, /* 0 (reserved) */
|
|
#ifdef ALTQ_CBQ
|
|
{"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 1 */
|
|
#endif
|
|
#ifdef ALTQ_WFQ
|
|
{"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 2 */
|
|
#endif
|
|
#ifdef ALTQ_AFMAP
|
|
{"afm", afmopen, afmclose, afmioctl}, /* 3 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 3 */
|
|
#endif
|
|
#ifdef ALTQ_FIFOQ
|
|
{"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 4 */
|
|
#endif
|
|
#ifdef ALTQ_RED
|
|
{"red", redopen, redclose, redioctl}, /* 5 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 5 */
|
|
#endif
|
|
#ifdef ALTQ_RIO
|
|
{"rio", rioopen, rioclose, rioioctl}, /* 6 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 6 */
|
|
#endif
|
|
#ifdef ALTQ_LOCALQ
|
|
{"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 7 (local use) */
|
|
#endif
|
|
#ifdef ALTQ_HFSC
|
|
{"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 8 */
|
|
#endif
|
|
#ifdef ALTQ_CDNR
|
|
{"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 9 */
|
|
#endif
|
|
#ifdef ALTQ_BLUE
|
|
{"blue",blueopen, blueclose, blueioctl}, /* 10 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 10 */
|
|
#endif
|
|
#ifdef ALTQ_PRIQ
|
|
{"priq",priqopen, priqclose, priqioctl}, /* 11 */
|
|
#else
|
|
{"noq", noopen, noclose, noioctl}, /* 11 */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* altq major device support
|
|
*/
|
|
int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
|
|
|
|
#if defined(__NetBSD__)
|
|
dev_type_open(altqopen);
|
|
dev_type_close(altqclose);
|
|
dev_type_ioctl(altqioctl);
|
|
#endif
|
|
#if defined(__OpenBSD__)
|
|
static d_open_t altqopen;
|
|
static d_close_t altqclose;
|
|
static d_ioctl_t altqioctl;
|
|
#endif
|
|
#ifdef __FreeBSD__
|
|
static void altq_drvinit __P((void *));
|
|
#else
|
|
void altqattach __P((int));
|
|
#endif
|
|
|
|
#if defined(__FreeBSD__)
|
|
#define CDEV_MAJOR 96 /* FreeBSD official number */
|
|
#elif defined(__OpenBSD__)
|
|
#if defined(__i386__)
|
|
#define CDEV_MAJOR 74 /* OpenBSD i386 (official) */
|
|
#elif defined(__alpha__)
|
|
#define CDEV_MAJOR 53 /* OpenBSD alpha (official) */
|
|
#else
|
|
#error arch not supported
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(__FreeBSD__)
|
|
#if (__FreeBSD_version < 400000)
|
|
static struct cdevsw altq_cdevsw =
|
|
{ altqopen, altqclose, noread, nowrite,
|
|
altqioctl, nostop, nullreset, nodevtotty,
|
|
seltrue, nommap, NULL, "altq", NULL, -1 };
|
|
#else
|
|
static struct cdevsw altq_cdevsw =
|
|
{ altqopen, altqclose, noread, nowrite,
|
|
altqioctl, seltrue, nommap, nostrategy,
|
|
"altq", CDEV_MAJOR, nodump, nopsize, 0, -1 };
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(__NetBSD__)
|
|
const struct cdevsw altq_cdevsw = {
|
|
altqopen, altqclose, noread, nowrite, altqioctl,
|
|
nostop, notty, nopoll, nommap, nokqfilter
|
|
};
|
|
#endif
|
|
|
|
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
|
|
static
|
|
#endif
|
|
int
|
|
altqopen(dev, flag, fmt, p)
|
|
dev_t dev;
|
|
int flag, fmt;
|
|
struct proc *p;
|
|
{
|
|
int unit = minor(dev);
|
|
|
|
if (unit == 0)
|
|
return (0);
|
|
if (unit < naltqsw)
|
|
return (*altqsw[unit].d_open)(dev, flag, fmt, p);
|
|
|
|
return ENXIO;
|
|
}
|
|
|
|
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
|
|
static
|
|
#endif
|
|
int
|
|
altqclose(dev, flag, fmt, p)
|
|
dev_t dev;
|
|
int flag, fmt;
|
|
struct proc *p;
|
|
{
|
|
int unit = minor(dev);
|
|
|
|
if (unit == 0)
|
|
return (0);
|
|
if (unit < naltqsw)
|
|
return (*altqsw[unit].d_close)(dev, flag, fmt, p);
|
|
|
|
return ENXIO;
|
|
}
|
|
|
|
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
|
|
static
|
|
#endif
|
|
int
|
|
altqioctl(dev, cmd, addr, flag, p)
|
|
dev_t dev;
|
|
ioctlcmd_t cmd;
|
|
caddr_t addr;
|
|
int flag;
|
|
struct proc *p;
|
|
{
|
|
int unit = minor(dev);
|
|
|
|
if (unit == 0) {
|
|
struct ifnet *ifp;
|
|
struct altqreq *typereq;
|
|
struct tbrreq *tbrreq;
|
|
int error;
|
|
|
|
switch (cmd) {
|
|
case ALTQGTYPE:
|
|
case ALTQTBRGET:
|
|
break;
|
|
default:
|
|
#if (__FreeBSD_version > 400000)
|
|
if ((error = suser(p)) != 0)
|
|
return (error);
|
|
#else
|
|
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
|
|
return (error);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
switch (cmd) {
|
|
case ALTQGTYPE:
|
|
typereq = (struct altqreq *)addr;
|
|
if ((ifp = ifunit(typereq->ifname)) == NULL)
|
|
return (EINVAL);
|
|
typereq->arg = (u_long)ifp->if_snd.altq_type;
|
|
return (0);
|
|
case ALTQTBRSET:
|
|
tbrreq = (struct tbrreq *)addr;
|
|
if ((ifp = ifunit(tbrreq->ifname)) == NULL)
|
|
return (EINVAL);
|
|
return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
|
|
case ALTQTBRGET:
|
|
tbrreq = (struct tbrreq *)addr;
|
|
if ((ifp = ifunit(tbrreq->ifname)) == NULL)
|
|
return (EINVAL);
|
|
return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
|
|
default:
|
|
return (EINVAL);
|
|
}
|
|
}
|
|
if (unit < naltqsw)
|
|
return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, p);
|
|
|
|
return ENXIO;
|
|
}
|
|
|
|
#if !defined(__NetBSD__)
|
|
static int altq_devsw_installed = 0;
|
|
#endif
|
|
|
|
#ifdef __FreeBSD__
|
|
#if (__FreeBSD_version < 400000)
|
|
#ifdef DEVFS
|
|
static void *altq_devfs_token[sizeof (altqsw) / sizeof (altqsw[0])];
|
|
#endif
|
|
|
|
static void
|
|
altq_drvinit(unused)
|
|
void *unused;
|
|
{
|
|
dev_t dev;
|
|
#ifdef DEVFS
|
|
int i;
|
|
#endif
|
|
|
|
if (!altq_devsw_installed) {
|
|
dev = makedev(CDEV_MAJOR,0);
|
|
cdevsw_add(&dev,&altq_cdevsw,NULL);
|
|
altq_devsw_installed = 1;
|
|
#ifdef DEVFS
|
|
for (i=0; i<naltqsw; i++)
|
|
altq_devfs_token[i] =
|
|
devfs_add_devswf(&altq_cdevsw, i, DV_CHR,
|
|
0, 0, 0644, altqsw[i].d_name);
|
|
#endif
|
|
printf("altq: major number is %d\n", CDEV_MAJOR);
|
|
}
|
|
}
|
|
|
|
#else /* FreeBSD 4.x */
|
|
|
|
static void
|
|
altq_drvinit(unused)
|
|
void *unused;
|
|
{
|
|
int unit;
|
|
|
|
cdevsw_add(&altq_cdevsw);
|
|
altq_devsw_installed = 1;
|
|
printf("altq: major number is %d\n", CDEV_MAJOR);
|
|
|
|
/* create minor devices */
|
|
for (unit = 0; unit < naltqsw; unit++)
|
|
make_dev(&altq_cdevsw, unit, 0, 0, 0644,
|
|
altqsw[unit].d_name);
|
|
}
|
|
|
|
#endif /* FreeBSD 4.x */
|
|
|
|
SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
|
|
|
|
#endif
|
|
|
|
#ifdef ALTQ_KLD
|
|
/*
|
|
* KLD support
|
|
*/
|
|
static int altq_module_register __P((struct altq_module_data *));
|
|
static int altq_module_deregister __P((struct altq_module_data *));
|
|
|
|
static struct altq_module_data *altq_modules[ALTQT_MAX];
|
|
static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
|
|
|
|
void altq_module_incref(type)
|
|
int type;
|
|
{
|
|
if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
|
|
return;
|
|
|
|
altq_modules[type]->ref++;
|
|
}
|
|
|
|
void altq_module_declref(type)
|
|
int type;
|
|
{
|
|
if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
|
|
return;
|
|
|
|
altq_modules[type]->ref--;
|
|
}
|
|
|
|
static int
|
|
altq_module_register(mdata)
|
|
struct altq_module_data *mdata;
|
|
{
|
|
int type = mdata->type;
|
|
|
|
if (type < 0 || type >= ALTQT_MAX)
|
|
return (EINVAL);
|
|
if (altqsw[type].d_open != noopen)
|
|
return (EBUSY);
|
|
altqsw[type] = *mdata->altqsw; /* set discipline functions */
|
|
altq_modules[type] = mdata; /* save module data pointer */
|
|
return (0);
|
|
}
|
|
|
|
static int
|
|
altq_module_deregister(mdata)
|
|
struct altq_module_data *mdata;
|
|
{
|
|
int type = mdata->type;
|
|
|
|
if (type < 0 || type >= ALTQT_MAX)
|
|
return (EINVAL);
|
|
if (mdata != altq_modules[type])
|
|
return (EINVAL);
|
|
if (altq_modules[type]->ref > 0)
|
|
return (EBUSY);
|
|
altqsw[type] = noqdisc;
|
|
altq_modules[type] = NULL;
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
altq_module_handler(mod, cmd, arg)
|
|
module_t mod;
|
|
int cmd;
|
|
void * arg;
|
|
{
|
|
struct altq_module_data *data = (struct altq_module_data *)arg;
|
|
int error = 0;
|
|
|
|
switch (cmd) {
|
|
case MOD_LOAD:
|
|
error = altq_module_register(data);
|
|
break;
|
|
|
|
case MOD_UNLOAD:
|
|
error = altq_module_deregister(data);
|
|
break;
|
|
|
|
default:
|
|
error = EINVAL;
|
|
break;
|
|
}
|
|
|
|
return(error);
|
|
}
|
|
|
|
#endif /* ALTQ_KLD */
|