diff -urN linux-2.4.18.imq/drivers/net/imq.c linux-2.4.18/drivers/net/imq.c --- linux-2.4.18.imq/drivers/net/imq.c Wed Jul 3 23:50:39 2002 +++ linux-2.4.18/drivers/net/imq.c Thu Jul 4 22:30:39 2002 @@ -3,6 +3,8 @@ * * Authors: Patrick McHardy, * + * 05.07.2002 Dynamic device allocation by Cougar + * * The first version was written by Martin Devera, * * This program is free software; you can redistribute it and/or @@ -11,6 +13,8 @@ * 2 of the License, or (at your option) any later version. */ +#define __NO_VERSION__ +#include /* for copy_from_user */ #include #include #include @@ -29,7 +33,14 @@ #define IMQ_HH_LEN(info) (((info)->hook == NF_IP_PRE_ROUTING) ? \ (info)->indev->hard_header_len : \ (info)->outdev->hard_header_len) - + +static int unregister_imq_device(const char* imq_if_name); +static int register_imq_device(const char* imq_if_name); +static int __init imq_dev_init(struct net_device *dev); +static void imq_dev_uninit(struct net_device *dev); +static int imq_dev_xmit(struct sk_buff *skb, struct net_device *dev); +static struct net_device_stats *imq_get_stats(struct net_device *dev); + static nf_hookfn imq_nf_hook; static struct nf_hook_ops imq_ingress_ipv4 = { @@ -66,14 +77,6 @@ }; #endif -static unsigned int numdevs = 2; - -MODULE_PARM(numdevs, "i"); -MODULE_PARM_DESC(numdevs, "number of imq devices"); - -static struct net_device *imq_devs; - - static struct net_device_stats *imq_get_stats(struct net_device *dev) { return (struct net_device_stats *)dev->priv; @@ -118,13 +121,9 @@ struct net_device_stats *stats; struct sk_buff *skb2 = NULL; struct Qdisc *q; - unsigned int index = skb->imq_flags&IMQ_F_IFMASK; int ret = -1; - if (index > numdevs) - return -1; - - dev = imq_devs + index; + dev = skb->dev; if (!(dev->flags & IFF_UP)) { skb->imq_flags = 0; nf_reinject(skb, info, NF_ACCEPT); @@ -178,6 +177,78 @@ return NF_ACCEPT; } +int imq_ioctl_handler(unsigned long arg) +{ + struct imq_ioctl_args args; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (copy_from_user(&args, (void*)arg, sizeof(struct imq_ioctl_args))) + return -EFAULT; + + args.device[IFNAMSIZ - 1] = 0; + + switch (args.cmd) { + case ADD_IMQ_CMD: + return (register_imq_device(args.device)); + break; + + case DEL_IMQ_CMD: + return (unregister_imq_device(args.device)); + break; + + default: + printk(KERN_ERR __FUNCTION__ ": Unknown IMQ CMD: %x \n", args.cmd); + }; + return -EINVAL; +} + +static int register_imq_device(const char *imq_if_name) +{ + struct net_device *dev; + + if (dev_get_by_name(imq_if_name)) { + printk(KERN_DEBUG __FUNCTION__ ": device %s already exist\n", imq_if_name); + return -EEXIST; + } + + if ((dev = kmalloc(sizeof(struct net_device), GFP_KERNEL)) == NULL) + return -ENOBUFS; + + memset(dev, 0, sizeof(struct net_device)); + + SET_MODULE_OWNER(dev); + memcpy(dev->name, imq_if_name, IFNAMSIZ); + dev->init = imq_dev_init; + dev->uninit = imq_dev_uninit; + dev->features |= NETIF_F_DYNALLOC; + + if (register_netdev(dev) < 0) { + kfree(dev); + return -EIO; + } + + MOD_INC_USE_COUNT; + return 0; +} + +static int unregister_imq_device(const char *imq_if_name) +{ + struct net_device *dev; + + dev = dev_get_by_name(imq_if_name); + + if (dev == NULL) { + printk(KERN_DEBUG __FUNCTION__ ": no such device %s\n", imq_if_name); + return -EINVAL; + } + + unregister_netdev(dev); + + MOD_DEC_USE_COUNT; + return 0; +} static int __init imq_init_hooks(void) { @@ -249,64 +320,14 @@ kfree(dev->priv); } -static int __init imq_init_devs(void) -{ - struct net_device *dev; - int i; - - if (!numdevs || numdevs > IMQ_MAX_DEVS) { - printk(KERN_ERR "numdevs has to be betweed 1 and %u\n", - IMQ_MAX_DEVS); - return -EINVAL; - } - - imq_devs = kmalloc(sizeof(struct net_device) * numdevs, GFP_KERNEL); - if (!imq_devs) - return -ENOMEM; - memset(imq_devs, 0, sizeof(struct net_device) * numdevs); - - /* we start counting at zero */ - numdevs--; - - for (i = 0, dev = imq_devs; i <= numdevs; i++, dev++) { - SET_MODULE_OWNER(dev); - strcpy(dev->name, "imq%d"); - dev->init = imq_dev_init; - dev->uninit = imq_dev_uninit; - - if (register_netdev(dev) < 0) - goto err_register; - } - return 0; - -err_register: - for (; i; i--) - unregister_netdev(--dev); - kfree(imq_devs); - return -EIO; -} - -static void imq_cleanup_devs(void) -{ - int i; - struct net_device *dev = imq_devs; - - for (i = 0; i <= numdevs; i++) - unregister_netdev(dev++); - - kfree(imq_devs); -} - static int __init imq_init_module(void) { int err; - if ((err = imq_init_devs())) + if ((err = imq_init_hooks())) return err; - if ((err = imq_init_hooks())) { - imq_cleanup_devs(); - return err; - } + + imq_ioctl_hook = imq_ioctl_handler; printk(KERN_INFO "imq driver loaded.\n"); @@ -316,7 +337,7 @@ static void __exit imq_cleanup_module(void) { imq_unhook(); - imq_cleanup_devs(); + imq_ioctl_hook = NULL; } module_init(imq_init_module); diff -urN linux-2.4.18.imq/include/linux/imq.h linux-2.4.18/include/linux/imq.h --- linux-2.4.18.imq/include/linux/imq.h Wed Jul 3 23:50:39 2002 +++ linux-2.4.18/include/linux/imq.h Thu Jul 4 22:04:40 2002 @@ -1,9 +1,24 @@ #ifndef _IMQ_H #define _IMQ_H -#define IMQ_MAX_DEVS 16 - -#define IMQ_F_IFMASK 0x7f #define IMQ_F_ENQUEUE 0x80 + +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif + +/* found in af_inet.c */ +extern int (*imq_ioctl_hook)(unsigned long arg); + +/* Passed in imq_ioctl_args structure to determine behaviour. */ +enum imq_ioctl_cmds { + ADD_IMQ_CMD, + DEL_IMQ_CMD +}; + +struct imq_ioctl_args { + int cmd; /* Should be one of the imq_ioctl_cmds enum above. */ + char device[IFNAMSIZ]; +}; #endif /* _IMQ_H */ diff -urN linux-2.4.18.imq/include/linux/sockios.h linux-2.4.18/include/linux/sockios.h --- linux-2.4.18.imq/include/linux/sockios.h Thu Nov 8 00:39:36 2001 +++ linux-2.4.18/include/linux/sockios.h Thu Jul 4 17:51:13 2002 @@ -105,6 +105,8 @@ #define SIOCGIFVLAN 0x8982 /* 802.1Q VLAN support */ #define SIOCSIFVLAN 0x8983 /* Set 802.1Q VLAN options */ +#define SIOCSIFIMQ 0x8984 /* Set IMQ device options */ + /* bonding calls */ #define SIOCBONDENSLAVE 0x8990 /* enslave a device to the bond */ diff -urN linux-2.4.18.imq/net/ipv4/af_inet.c linux-2.4.18/net/ipv4/af_inet.c --- linux-2.4.18.imq/net/ipv4/af_inet.c Fri Dec 21 19:42:05 2001 +++ linux-2.4.18/net/ipv4/af_inet.c Thu Jul 4 18:37:04 2002 @@ -147,6 +147,10 @@ int (*vlan_ioctl_hook)(unsigned long arg); #endif +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +int (*imq_ioctl_hook)(unsigned long arg); +#endif + /* The inetsw table contains everything that inet_create needs to * build a new socket. */ @@ -895,6 +899,17 @@ #endif if (vlan_ioctl_hook != NULL) return vlan_ioctl_hook(arg); +#endif + return -ENOPKG; + + case SIOCSIFIMQ: +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +#ifdef CONFIG_KMOD + if (imq_ioctl_hook == NULL) + request_module("imq"); +#endif + if (imq_ioctl_hook != NULL) + return imq_ioctl_hook(arg); #endif return -ENOPKG; diff -urN linux-2.4.18.imq/net/netsyms.c linux-2.4.18/net/netsyms.c --- linux-2.4.18.imq/net/netsyms.c Mon Feb 25 21:38:14 2002 +++ linux-2.4.18/net/netsyms.c Thu Jul 4 21:59:12 2002 @@ -31,6 +31,7 @@ #include #include #include +#include #include #ifdef CONFIG_NET_DIVERT #include @@ -219,6 +220,10 @@ #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) EXPORT_SYMBOL(dev_change_flags); EXPORT_SYMBOL(vlan_ioctl_hook); +#endif + +#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE) +EXPORT_SYMBOL(imq_ioctl_hook); #endif EXPORT_SYMBOL(sklist_destroy_socket);