]> git.hungrycats.org Git - linux/commitdiff
[NET]: ethertap fixes.
authorStephen Hemminger <shemminger@osdl.org>
Tue, 2 Sep 2003 05:19:49 +0000 (22:19 -0700)
committerStephen Hemminger <shemminger@osdl.org>
Tue, 2 Sep 2003 05:19:49 +0000 (22:19 -0700)
includes these changes from viro
* switched ethertap to dynamic allocation
* ethertap: embedded ->priv
* ethertap: fixed resource leaks on failure exits
and from me
* get it out of the static device list completely.
* add dependency on NETLINK_DEV
* not really obsolete yet
* configurable number of interfaces

drivers/net/Kconfig
drivers/net/Space.c
drivers/net/ethertap.c

index 30939c0fec8e56358dd5fbb16d49fcca698dae24..0b4e722c6bf29c6fe116a64adc65ae09fa835a7f 100644 (file)
@@ -132,8 +132,8 @@ config TUN
          If you don't know what to use this for, you don't need it.
 
 config ETHERTAP
-       tristate "Ethertap network tap (OBSOLETE)"
-       depends on NETDEVICES && EXPERIMENTAL
+       tristate "Ethertap network tap"
+       depends on NETDEVICES && EXPERIMENTAL && NETLINK_DEV
        ---help---
          If you say Y here (and have said Y to "Kernel/User network link
          driver", above) and create a character special file /dev/tap0 with
index 838c59729c711eade4223b2fba7959eb8f2db1c1..46fe5a996a8e1d3dc51a6f0d160d412208c50503 100644 (file)
@@ -89,7 +89,6 @@ extern int apne_probe(struct net_device *);
 extern int bionet_probe(struct net_device *);
 extern int pamsnet_probe(struct net_device *);
 extern int cs89x0_probe(struct net_device *dev);
-extern int ethertap_probe(struct net_device *dev);
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
@@ -387,17 +386,6 @@ static int __init ethif_probe(struct net_device *dev)
        return -ENODEV;
 }
 
-#ifdef CONFIG_ETHERTAP
-static struct net_device tap0_dev = {
-       .name           = "tap0",
-       .base_addr      = NETLINK_TAPBASE,
-       .next           = NEXT_DEV,
-       .init           = ethertap_probe,
-};
-#undef NEXT_DEV
-#define NEXT_DEV       (&tap0_dev)
-#endif
-
 #ifdef CONFIG_SDLA
 extern int sdla_init(struct net_device *);
 static struct net_device sdla0_dev = {
index 5f8162612c25789778e1c43ec08ff2593c569eff..b5c4fd8a38ffc95d2c42abf193e8b055f18b1b6c 100644 (file)
@@ -33,7 +33,6 @@
  *     Index to functions.
  */
 
-int        ethertap_probe(struct net_device *dev);
 static int  ethertap_open(struct net_device *dev);
 static int  ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static int  ethertap_close(struct net_device *dev);
@@ -45,7 +44,11 @@ static void set_multicast_list(struct net_device *dev);
 
 static int ethertap_debug;
 
-static struct net_device *tap_map[32]; /* Returns the tap device for a given netlink */
+static int max_taps = 1;
+MODULE_PARM(max_taps, "i");
+MODULE_PARM_DESC(max_taps,"Max number of ethernet tap devices");
+
+static struct net_device **tap_map;    /* Returns the tap device for a given netlink */
 
 /*
  *     Board-specific info in dev->priv.
@@ -64,24 +67,28 @@ struct net_local
  *     To call this a probe is a bit misleading, however for real
  *     hardware it would have to check what was present.
  */
- 
-int __init ethertap_probe(struct net_device *dev)
+static int  __init ethertap_probe(int unit)
 {
+       struct net_device *dev;
+       int err = -ENOMEM;
+
+       dev = alloc_netdev(sizeof(struct net_local), "tap%d",
+                          ether_setup);
+
+       if (!dev)
+               goto out;
+
        SET_MODULE_OWNER(dev);
 
+       sprintf(dev->name, "tap%d", unit);
+       dev->base_addr = unit + NETLINK_TAPBASE;
+
+       netdev_boot_setup_check(dev);
+
        memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6);
        if (dev->mem_start & 0xf)
                ethertap_debug = dev->mem_start & 0x7;
 
-       /*
-        *      Initialize the device structure.
-        */
-
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-       if (dev->priv == NULL)
-               return -ENOMEM;
-       memset(dev->priv, 0, sizeof(struct net_local));
-
        /*
         *      The tap specific entries in the device structure.
         */
@@ -94,17 +101,19 @@ int __init ethertap_probe(struct net_device *dev)
        dev->set_multicast_list = set_multicast_list;
 #endif
 
-       /*
-        *      Setup the generic properties
-        */
-
-       ether_setup(dev);
-
        dev->tx_queue_len = 0;
        dev->flags|=IFF_NOARP;
-       tap_map[dev->base_addr]=dev;
 
+       err = register_netdev(dev);
+       if (err)
+               goto out1;
+
+       tap_map[unit]=dev;
        return 0;
+out1:
+       kfree(dev);
+out:
+       return err;
 }
 
 /*
@@ -116,11 +125,12 @@ static int ethertap_open(struct net_device *dev)
        struct net_local *lp = (struct net_local*)dev->priv;
 
        if (ethertap_debug > 2)
-               printk("%s: Doing ethertap_open()...", dev->name);
+               printk(KERN_DEBUG "%s: Doing ethertap_open()...", dev->name);
 
        lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx);
        if (lp->nl == NULL)
                return -ENOBUFS;
+
        netif_start_queue(dev);
        return 0;
 }
@@ -302,7 +312,7 @@ static void ethertap_rx(struct sock *sk, int len)
        }
 
        if (ethertap_debug > 3)
-               printk("%s: ethertap_rx()\n", dev->name);
+               printk(KERN_DEBUG "%s: ethertap_rx()\n", dev->name);
 
        while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
                ethertap_rx_skb(skb, dev);
@@ -314,7 +324,7 @@ static int ethertap_close(struct net_device *dev)
        struct sock *sk = lp->nl;
 
        if (ethertap_debug > 2)
-               printk("%s: Shutting down.\n", dev->name);
+               printk(KERN_DEBUG "%s: Shutting down.\n", dev->name);
 
        netif_stop_queue(dev);
 
@@ -332,45 +342,49 @@ static struct net_device_stats *ethertap_get_stats(struct net_device *dev)
        return &lp->stats;
 }
 
-#ifdef MODULE
-
-static int unit;
-MODULE_PARM(unit,"i");
-MODULE_PARM_DESC(unit,"Ethertap device number");
 
-static struct net_device dev_ethertap =
+int __init ethertap_init(void)
 {
-       .name           =       " ",
-       .init           =        ethertap_probe
-};
+       int i, err = 0;
 
-int init_module(void)
-{
-       dev_ethertap.base_addr=unit+NETLINK_TAPBASE;
-       sprintf(dev_ethertap.name,"tap%d",unit);
-       if (dev_get(dev_ethertap.name))
-       {
-               printk(KERN_INFO "%s already loaded.\n", dev_ethertap.name);
-               return -EBUSY;
+       /* netlink can only hande 16 entries unless modified */
+       if (max_taps > MAX_LINKS - NETLINK_TAPBASE)
+               return -E2BIG;
+
+       tap_map = kmalloc(sizeof(struct net_device *)*max_taps, GFP_KERNEL);
+       if (!tap_map)
+               return -ENOMEM;
+
+       for (i = 0; i < max_taps; i++) {
+               err = ethertap_probe(i);
+               if (err) {
+                       while (--i > 0) {
+                               unregister_netdev(tap_map[i]);
+                               free_netdev(tap_map[i]);
+                       }
+                       break;
+               }
        }
-       if (register_netdev(&dev_ethertap) != 0)
-               return -EIO;
-       return 0;
+       if (err)
+               kfree(tap_map);
+       return err;
 }
+module_init(ethertap_init);
 
-void cleanup_module(void)
+void __exit ethertap_cleanup(void)
 {
-       tap_map[dev_ethertap.base_addr]=NULL;
-       unregister_netdev(&dev_ethertap);
-
-       /*
-        *      Free up the private structure.
-        */
-
-       kfree(dev_ethertap.priv);
-       dev_ethertap.priv = NULL;       /* gets re-allocated by ethertap_probe */
+       int i;
+
+       for (i = 0; i < max_taps; i++) {
+               struct net_device *dev = tap_map[i];
+               if (dev) {
+                       tap_map[i] = NULL;
+                       unregister_netdev(dev);
+                       free_netdev(dev);
+               }
+       }
+       kfree(tap_map);
 }
+module_exit(ethertap_cleanup);
 
-#endif /* MODULE */
 MODULE_LICENSE("GPL");
-