linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / net / ppp_generic.c
index c872f7c..0245e40 100644 (file)
  * ==FILEVERSION 20041108==
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/list.h>
+#include <linux/devfs_fs_kernel.h>
 #include <linux/netdevice.h>
 #include <linux/poll.h>
 #include <linux/ppp_defs.h>
@@ -44,7 +46,6 @@
 #include <linux/rwsem.h>
 #include <linux/stddef.h>
 #include <linux/device.h>
-#include <linux/mutex.h>
 #include <net/slhc_vj.h>
 #include <asm/atomic.h>
 
@@ -192,16 +193,16 @@ struct cardmap {
        void *ptr[CARDMAP_WIDTH];
 };
 static void *cardmap_get(struct cardmap *map, unsigned int nr);
-static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
+static void cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
 static unsigned int cardmap_find_first_free(struct cardmap *map);
 static void cardmap_destroy(struct cardmap **map);
 
 /*
- * all_ppp_mutex protects the all_ppp_units mapping.
+ * all_ppp_sem protects the all_ppp_units mapping.
  * It also ensures that finding a ppp unit in the all_ppp_units map
  * and updating its file.refcnt field is atomic.
  */
-static DEFINE_MUTEX(all_ppp_mutex);
+static DECLARE_MUTEX(all_ppp_sem);
 static struct cardmap *all_ppp_units;
 static atomic_t ppp_unit_count = ATOMIC_INIT(0);
 
@@ -803,7 +804,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
                /* Attach to an existing ppp unit */
                if (get_user(unit, p))
                        break;
-               mutex_lock(&all_ppp_mutex);
+               down(&all_ppp_sem);
                err = -ENXIO;
                ppp = ppp_find_unit(unit);
                if (ppp != 0) {
@@ -811,7 +812,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
                        file->private_data = &ppp->file;
                        err = 0;
                }
-               mutex_unlock(&all_ppp_mutex);
+               up(&all_ppp_sem);
                break;
 
        case PPPIOCATTCHAN:
@@ -861,6 +862,10 @@ static int __init ppp_init(void)
                        goto out_chrdev;
                }
                class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+               err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
+                               S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
+               if (err)
+                       goto out_class;
        }
 
 out:
@@ -868,6 +873,9 @@ out:
                printk(KERN_ERR "failed to register PPP device (%d)\n", err);
        return err;
 
+out_class:
+       class_device_destroy(ppp_class, MKDEV(PPP_MAJOR,0));
+       class_destroy(ppp_class);
 out_chrdev:
        unregister_chrdev(PPP_MAJOR, "ppp");
        goto out;
@@ -1600,6 +1608,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                        kfree_skb(skb);
                        skb = ns;
                }
+               else if (!pskb_may_pull(skb, skb->len))
+                       goto err;
                else
                        skb->ip_summed = CHECKSUM_NONE;
 
@@ -1681,8 +1691,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
                    || ppp->npmode[npi] != NPMODE_PASS) {
                        kfree_skb(skb);
                } else {
-                       /* chop off protocol */
-                       skb_pull_rcsum(skb, 2);
+                       skb_pull(skb, 2);       /* chop off protocol */
+                       skb_postpull_rcsum(skb, skb->data - 2, 2);
                        skb->dev = ppp->dev;
                        skb->protocol = htons(npindex_to_ethertype[npi]);
                        skb->mac.raw = skb->data;
@@ -1995,9 +2005,10 @@ ppp_register_channel(struct ppp_channel *chan)
 {
        struct channel *pch;
 
-       pch = kzalloc(sizeof(struct channel), GFP_KERNEL);
+       pch = kmalloc(sizeof(struct channel), GFP_KERNEL);
        if (pch == 0)
                return -ENOMEM;
+       memset(pch, 0, sizeof(struct channel));
        pch->ppp = NULL;
        pch->chan = chan;
        chan->ppp = pch;
@@ -2407,12 +2418,13 @@ ppp_create_interface(int unit, int *retp)
        int ret = -ENOMEM;
        int i;
 
-       ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL);
+       ppp = kmalloc(sizeof(struct ppp), GFP_KERNEL);
        if (!ppp)
                goto out;
        dev = alloc_netdev(0, "", ppp_setup);
        if (!dev)
                goto out1;
+       memset(ppp, 0, sizeof(struct ppp));
 
        ppp->mru = PPP_MRU;
        init_ppp_file(&ppp->file, INTERFACE);
@@ -2434,7 +2446,7 @@ ppp_create_interface(int unit, int *retp)
        dev->do_ioctl = ppp_net_ioctl;
 
        ret = -EEXIST;
-       mutex_lock(&all_ppp_mutex);
+       down(&all_ppp_sem);
        if (unit < 0)
                unit = cardmap_find_first_free(all_ppp_units);
        else if (cardmap_get(all_ppp_units, unit) != NULL)
@@ -2452,18 +2464,13 @@ ppp_create_interface(int unit, int *retp)
        }
 
        atomic_inc(&ppp_unit_count);
-       ret = cardmap_set(&all_ppp_units, unit, ppp);
-       if (ret != 0)
-               goto out3;
-
-       mutex_unlock(&all_ppp_mutex);
+       cardmap_set(&all_ppp_units, unit, ppp);
+       up(&all_ppp_sem);
        *retp = 0;
        return ppp;
 
-out3:
-       atomic_dec(&ppp_unit_count);
 out2:
-       mutex_unlock(&all_ppp_mutex);
+       up(&all_ppp_sem);
        free_netdev(dev);
 out1:
        kfree(ppp);
@@ -2493,7 +2500,7 @@ static void ppp_shutdown_interface(struct ppp *ppp)
 {
        struct net_device *dev;
 
-       mutex_lock(&all_ppp_mutex);
+       down(&all_ppp_sem);
        ppp_lock(ppp);
        dev = ppp->dev;
        ppp->dev = NULL;
@@ -2507,7 +2514,7 @@ static void ppp_shutdown_interface(struct ppp *ppp)
        ppp->file.dead = 1;
        ppp->owner = NULL;
        wake_up_interruptible(&ppp->file.rwait);
-       mutex_unlock(&all_ppp_mutex);
+       up(&all_ppp_sem);
 }
 
 /*
@@ -2549,7 +2556,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
 
 /*
  * Locate an existing ppp unit.
- * The caller should have locked the all_ppp_mutex.
+ * The caller should have locked the all_ppp_sem.
  */
 static struct ppp *
 ppp_find_unit(int unit)
@@ -2572,7 +2579,8 @@ ppp_find_channel(int unit)
 
        list_for_each_entry(pch, &new_channels, list) {
                if (pch->file.index == unit) {
-                       list_move(&pch->list, &all_channels);
+                       list_del(&pch->list);
+                       list_add(&pch->list, &all_channels);
                        return pch;
                }
        }
@@ -2593,7 +2601,7 @@ ppp_connect_channel(struct channel *pch, int unit)
        int ret = -ENXIO;
        int hdrlen;
 
-       mutex_lock(&all_ppp_mutex);
+       down(&all_ppp_sem);
        ppp = ppp_find_unit(unit);
        if (ppp == 0)
                goto out;
@@ -2618,7 +2626,7 @@ ppp_connect_channel(struct channel *pch, int unit)
  outl:
        write_unlock_bh(&pch->upl);
  out:
-       mutex_unlock(&all_ppp_mutex);
+       up(&all_ppp_sem);
        return ret;
 }
 
@@ -2675,6 +2683,7 @@ static void __exit ppp_cleanup(void)
        cardmap_destroy(&all_ppp_units);
        if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
                printk(KERN_ERR "PPP: failed to unregister PPP device\n");
+       devfs_remove("ppp");
        class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
        class_destroy(ppp_class);
 }
@@ -2698,7 +2707,7 @@ static void *cardmap_get(struct cardmap *map, unsigned int nr)
        return NULL;
 }
 
-static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
+static void cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
 {
        struct cardmap *p;
        int i;
@@ -2707,9 +2716,8 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
        if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
                do {
                        /* need a new top level */
-                       struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
-                       if (!np)
-                               goto enomem;
+                       struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
+                       memset(np, 0, sizeof(*np));
                        np->ptr[0] = p;
                        if (p != NULL) {
                                np->shift = p->shift + CARDMAP_ORDER;
@@ -2723,9 +2731,8 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
        while (p->shift > 0) {
                i = (nr >> p->shift) & CARDMAP_MASK;
                if (p->ptr[i] == NULL) {
-                       struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
-                       if (!np)
-                               goto enomem;
+                       struct cardmap *np = kmalloc(sizeof(*np), GFP_KERNEL);
+                       memset(np, 0, sizeof(*np));
                        np->shift = p->shift - CARDMAP_ORDER;
                        np->parent = p;
                        p->ptr[i] = np;
@@ -2740,9 +2747,6 @@ static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
                set_bit(i, &p->inuse);
        else
                clear_bit(i, &p->inuse);
-       return 0;
- enomem:
-       return -ENOMEM;
 }
 
 static unsigned int cardmap_find_first_free(struct cardmap *map)