fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / isdn / i4l / isdn_ppp.c
index 62ffcc6..4e3f127 100644 (file)
@@ -9,7 +9,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/isdn.h>
 #include <linux/poll.h>
 #include <linux/ppp-comp.h>
@@ -109,7 +108,7 @@ isdn_ppp_free(isdn_net_local * lp)
 {
        struct ippp_struct *is;
 
-       if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
                        __FUNCTION__, lp->ppp_slot);
                return 0;
@@ -126,7 +125,7 @@ isdn_ppp_free(isdn_net_local * lp)
        lp->netdev->pb->ref_ct--;
        spin_unlock(&lp->netdev->pb->lock);
 #endif /* CONFIG_ISDN_MPP */
-       if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
                        __FUNCTION__, lp->ppp_slot);
                return 0;
@@ -279,7 +278,7 @@ isdn_ppp_open(int min, struct file *file)
        int slot;
        struct ippp_struct *is;
 
-       if (min < 0 || min > ISDN_MAX_CHANNELS)
+       if (min < 0 || min >= ISDN_MAX_CHANNELS)
                return -ENODEV;
 
        slot = isdn_ppp_get_slot();
@@ -320,8 +319,8 @@ isdn_ppp_open(int min, struct file *file)
        is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
 #endif
 #ifdef CONFIG_IPPP_FILTER
-       is->pass_filter.filter = NULL;
-       is->active_filter.filter = NULL;
+       is->pass_filter = NULL;
+       is->active_filter = NULL;
 #endif
        is->state = IPPP_OPEN;
 
@@ -364,10 +363,8 @@ isdn_ppp_release(int min, struct file *file)
                isdn_net_hangup(&p->dev);
        }
        for (i = 0; i < NUM_RCV_BUFFS; i++) {
-               if (is->rq[i].buf) {
-                       kfree(is->rq[i].buf);
-                       is->rq[i].buf = NULL;
-               }
+               kfree(is->rq[i].buf);
+               is->rq[i].buf = NULL;
        }
        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
        is->last = is->rq;
@@ -378,14 +375,10 @@ isdn_ppp_release(int min, struct file *file)
        is->slcomp = NULL;
 #endif
 #ifdef CONFIG_IPPP_FILTER
-       if (is->pass_filter.filter) {
-               kfree(is->pass_filter.filter);
-               is->pass_filter.filter = NULL;
-       }
-       if (is->active_filter.filter) {
-               kfree(is->active_filter.filter);
-               is->active_filter.filter = NULL;
-       }
+       kfree(is->pass_filter);
+       is->pass_filter = NULL;
+       kfree(is->active_filter);
+       is->active_filter = NULL;
 #endif
 
 /* TODO: if this was the previous master: link the stuff to the new master */
@@ -414,11 +407,11 @@ isdn_ppp_release(int min, struct file *file)
  * get_arg .. ioctl helper
  */
 static int
-get_arg(void *b, void *val, int len)
+get_arg(void __user *b, void *val, int len)
 {
        if (len <= 0)
                len = sizeof(void *);
-       if (copy_from_user((void *) val, b, len))
+       if (copy_from_user(val, b, len))
                return -EFAULT;
        return 0;
 }
@@ -427,15 +420,50 @@ get_arg(void *b, void *val, int len)
  * set arg .. ioctl helper
  */
 static int
-set_arg(void *b, void *val,int len)
+set_arg(void __user *b, void *val,int len)
 {
        if(len <= 0)
                len = sizeof(void *);
-       if (copy_to_user(b, (void *) val, len))
+       if (copy_to_user(b, val, len))
                return -EFAULT;
        return 0;
 }
 
+static int get_filter(void __user *arg, struct sock_filter **p)
+{
+       struct sock_fprog uprog;
+       struct sock_filter *code = NULL;
+       int len, err;
+
+       if (copy_from_user(&uprog, arg, sizeof(uprog)))
+               return -EFAULT;
+
+       if (!uprog.len) {
+               *p = NULL;
+               return 0;
+       }
+
+       /* uprog.len is unsigned short, so no overflow here */
+       len = uprog.len * sizeof(struct sock_filter);
+       code = kmalloc(len, GFP_KERNEL);
+       if (code == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(code, uprog.filter, len)) {
+               kfree(code);
+               return -EFAULT;
+       }
+
+       err = sk_chk_filter(code, uprog.len);
+       if (err) {
+               kfree(code);
+               return err;
+       }
+
+       *p = code;
+       return uprog.len;
+}
+
 /*
  * ippp device ioctl
  */
@@ -447,6 +475,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
        struct ippp_struct *is;
        isdn_net_local *lp;
        struct isdn_ppp_comp_data data;
+       void __user *argp = (void __user *)arg;
 
        is = (struct ippp_struct *) file->private_data;
        lp = is->lp;
@@ -462,7 +491,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 #ifdef CONFIG_ISDN_MPP
                        if (!(is->state & IPPP_CONNECT))
                                return -EINVAL;
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+                       if ((r = get_arg(argp, &val, sizeof(val) )))
                                return r;
                        printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
                               (int) min, (int) is->unit, (int) val);
@@ -472,30 +501,30 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 #endif
                        break;
                case PPPIOCGUNIT:       /* get ppp/isdn unit number */
-                       if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) )))
+                       if ((r = set_arg(argp, &is->unit, sizeof(is->unit) )))
                                return r;
                        break;
                case PPPIOCGIFNAME:
                        if(!lp)
                                return -EINVAL;
-                       if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
+                       if ((r = set_arg(argp, lp->name, strlen(lp->name))))
                                return r;
                        break;
                case PPPIOCGMPFLAGS:    /* get configuration flags */
-                       if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) )))
+                       if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg) )))
                                return r;
                        break;
                case PPPIOCSMPFLAGS:    /* set configuration flags */
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+                       if ((r = get_arg(argp, &val, sizeof(val) )))
                                return r;
                        is->mpppcfg = val;
                        break;
                case PPPIOCGFLAGS:      /* get configuration flags */
-                       if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) )))
+                       if ((r = set_arg(argp, &is->pppcfg,sizeof(is->pppcfg) )))
                                return r;
                        break;
                case PPPIOCSFLAGS:      /* set configuration flags */
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) ))) {
+                       if ((r = get_arg(argp, &val, sizeof(val) ))) {
                                return r;
                        }
                        if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
@@ -512,12 +541,12 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                        if (lp) {
                                struct ppp_idle pidle;
                                pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
-                               if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle))))
+                               if ((r = set_arg(argp, &pidle,sizeof(struct ppp_idle))))
                                         return r;
                        }
                        break;
                case PPPIOCSMRU:        /* set receive unit size for PPP */
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+                       if ((r = get_arg(argp, &val, sizeof(val) )))
                                return r;
                        is->mru = val;
                        break;
@@ -526,7 +555,7 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                case PPPIOCSMPMTU:
                        break;
                case PPPIOCSMAXCID:     /* set the maximum compression slot id */
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+                       if ((r = get_arg(argp, &val, sizeof(val) )))
                                return r;
                        val++;
                        if (is->maxcid != val) {
@@ -549,11 +578,11 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                        }
                        break;
                case PPPIOCGDEBUG:
-                       if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) )))
+                       if ((r = set_arg(argp, &is->debug, sizeof(is->debug) )))
                                return r;
                        break;
                case PPPIOCSDEBUG:
-                       if ((r = get_arg((void *) arg, &val, sizeof(val) )))
+                       if ((r = get_arg(argp, &val, sizeof(val) )))
                                return r;
                        is->debug = val;
                        break;
@@ -568,12 +597,12 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                                                protos[j] |= (0x1<<i);
                                        ipc = ipc->next;
                                }
-                               if ((r = set_arg((void *) arg,protos,8*sizeof(long) )))
+                               if ((r = set_arg(argp,protos,8*sizeof(long) )))
                                        return r;
                        }
                        break;
                case PPPIOCSCOMPRESSOR:
-                       if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data))))
+                       if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data))))
                                return r;
                        return isdn_ppp_set_compressor(is, &data);
                case PPPIOCGCALLINFO:
@@ -594,38 +623,29 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
                                        if(lp->flags & ISDN_NET_CALLBACK)
                                                pci.calltype |= CALLTYPE_CALLBACK;
                                }
-                               return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+                               return set_arg(argp,&pci,sizeof(struct pppcallinfo));
                        }
 #ifdef CONFIG_IPPP_FILTER
                case PPPIOCSPASS:
+                       {
+                               struct sock_filter *code;
+                               int len = get_filter(argp, &code);
+                               if (len < 0)
+                                       return len;
+                               kfree(is->pass_filter);
+                               is->pass_filter = code;
+                               is->pass_len = len;
+                               break;
+                       }
                case PPPIOCSACTIVE:
                        {
-                               struct sock_fprog uprog, *filtp;
-                               struct sock_filter *code = NULL;
-                               int len, err;
-
-                               if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
-                                       return -EFAULT;
-                               if (uprog.len > 0) {
-                                       len = uprog.len * sizeof(struct sock_filter);
-                                       code = kmalloc(len, GFP_KERNEL);
-                                       if (code == NULL)
-                                               return -ENOMEM;
-                                       if (copy_from_user(code, uprog.filter, len)) {
-                                               kfree(code);
-                                               return -EFAULT;
-                                       }
-                                       err = sk_chk_filter(code, uprog.len);
-                                       if (err) {
-                                               kfree(code);
-                                               return err;
-                                       }
-                               }
-                               filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
-                               if (filtp->filter)
-                                       kfree(filtp->filter);
-                               filtp->filter = code;
-                               filtp->len = uprog.len;
+                               struct sock_filter *code;
+                               int len = get_filter(argp, &code);
+                               if (len < 0)
+                                       return len;
+                               kfree(is->active_filter);
+                               is->active_filter = code;
+                               is->active_len = len;
                                break;
                        }
 #endif /* CONFIG_IPPP_FILTER */
@@ -647,7 +667,7 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
 
        if (is->debug & 0x2)
                printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-                               MINOR(file->f_dentry->d_inode->i_rdev));
+                               iminor(file->f_path.dentry->d_inode));
 
        /* just registers wait_queue hook. This doesn't really wait. */
        poll_wait(file, &is->wq, wait);
@@ -697,7 +717,7 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
                printk(KERN_DEBUG "ippp: device not activated.\n");
                return 0;
        }
-       nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
+       nbuf = kmalloc(len + 4, GFP_ATOMIC);
        if (!nbuf) {
                printk(KERN_WARNING "ippp: Can't alloc buf\n");
                return 0;
@@ -733,11 +753,10 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
  */
 
 int
-isdn_ppp_read(int min, struct file *file, char *buf, int count)
+isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
 {
        struct ippp_struct *is;
        struct ippp_buf_queue *b;
-       int r;
        u_long flags;
        u_char *save_buf;
 
@@ -746,8 +765,8 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count)
        if (!(is->state & IPPP_OPEN))
                return 0;
 
-       if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
-               return r;
+       if (!access_ok(VERIFY_WRITE, buf, count))
+               return -EFAULT;
 
        spin_lock_irqsave(&is->buflock, flags);
        b = is->first->next;
@@ -762,7 +781,8 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count)
        is->first = b;
 
        spin_unlock_irqrestore(&is->buflock, flags);
-       copy_to_user(buf, save_buf, count);
+       if (copy_to_user(buf, save_buf, count))
+               count = -EFAULT;
        kfree(save_buf);
 
        return count;
@@ -773,7 +793,7 @@ isdn_ppp_read(int min, struct file *file, char *buf, int count)
  */
 
 int
-isdn_ppp_write(int min, struct file *file, const char *buf, int count)
+isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
 {
        isdn_net_local *lp;
        struct ippp_struct *is;
@@ -856,14 +876,12 @@ isdn_ppp_init(void)
 #endif /* CONFIG_ISDN_MPP */
 
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               if (!(ippp_table[i] = (struct ippp_struct *)
-                     kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
+               if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
                        printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
                        for (j = 0; j < i; j++)
                                kfree(ippp_table[j]);
                        return -1;
                }
-               memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
                spin_lock_init(&ippp_table[i]->buflock);
                ippp_table[i]->state = 0;
                ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
@@ -888,8 +906,7 @@ isdn_ppp_cleanup(void)
                kfree(ippp_table[i]);
 
 #ifdef CONFIG_ISDN_MPP
-       if (isdn_ppp_bundle_arr)
-               kfree(isdn_ppp_bundle_arr);
+       kfree(isdn_ppp_bundle_arr);
 #endif /* CONFIG_ISDN_MPP */
 
 }
@@ -954,11 +971,10 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
        int slot;
        int proto;
 
-       if (net_dev->local->master)
-               BUG(); // we're called with the master device always
+       BUG_ON(net_dev->local->master); // we're called with the master device always
 
        slot = lp->ppp_slot;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
                        lp->ppp_slot);
                kfree_skb(skb);
@@ -1013,7 +1029,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
        int slot;
 
        slot = lp->ppp_slot;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
                        lp->ppp_slot);
                goto drop_packet;
@@ -1023,7 +1039,7 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
        if (lp->master) { // FIXME?
                mlp = (isdn_net_local *) lp->master->priv;
                slot = mlp->ppp_slot;
-               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                        printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
                                lp->ppp_slot);
                        goto drop_packet;
@@ -1125,20 +1141,19 @@ isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff
        {
                u_int16_t *p = (u_int16_t *) skb->data;
 
-               *p = 0; /* indicate inbound in DLT_LINUX_SLL */
+               *p = 0; /* indicate inbound */
        }
 
-       if (is->pass_filter.filter
-           && sk_run_filter(skb, is->pass_filter.filter,
-                           is->pass_filter.len) == 0) {
+       if (is->pass_filter
+           && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) {
                if (is->debug & 0x2)
                        printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
                kfree_skb(skb);
                return;
        }
-       if (!(is->active_filter.filter
-             && sk_run_filter(skb, is->active_filter.filter,
-                              is->active_filter.len) == 0)) {
+       if (!(is->active_filter
+             && sk_run_filter(skb, is->active_filter,
+                              is->active_len) == 0)) {
                if (is->debug & 0x2)
                        printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
                lp->huptimer = 0;
@@ -1208,7 +1223,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
        nd = mlp->netdev;       /* get master lp */
 
        slot = mlp->ppp_slot;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
                        mlp->ppp_slot);
                kfree_skb(skb);
@@ -1246,7 +1261,7 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* we have our lp locked from now on */
 
        slot = lp->ppp_slot;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
                        lp->ppp_slot);
                kfree_skb(skb);
@@ -1267,26 +1282,25 @@ isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
        /* check if we should pass this packet
         * the filter instructions are constructed assuming
         * a four-byte PPP header on each packet */
-       skb_push(skb, 4);
+       *skb_push(skb, 4) = 1; /* indicate outbound */
 
        {
                u_int16_t *p = (u_int16_t *) skb->data;
 
-               *p++ = htons(4); /* indicate outbound in DLT_LINUX_SLL */
+               p++;
                *p   = htons(proto);
        }
 
-       if (ipt->pass_filter.filter 
-           && sk_run_filter(skb, ipt->pass_filter.filter,
-                            ipt->pass_filter.len) == 0) {
+       if (ipt->pass_filter
+           && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) {
                if (ipt->debug & 0x4)
                        printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
                kfree_skb(skb);
                goto unlock;
        }
-       if (!(ipt->active_filter.filter
-             && sk_run_filter(skb, ipt->active_filter.filter,
-                              ipt->active_filter.len) == 0)) {
+       if (!(ipt->active_filter
+             && sk_run_filter(skb, ipt->active_filter,
+                              ipt->active_len) == 0)) {
                if (ipt->debug & 0x4)
                        printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
                lp->huptimer = 0;
@@ -1466,21 +1480,19 @@ int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
         * temporarily remove part of the fake header stuck on
         * earlier.
         */
-       skb_pull(skb, IPPP_MAX_HEADER - 4);
+       *skb_pull(skb, IPPP_MAX_HEADER - 4) = 1; /* indicate outbound */
 
        {
                u_int16_t *p = (u_int16_t *) skb->data;
 
-               *p++ = htons(4);        /* indicate outbound in DLT_LINUX_SLL */
+               p++;
                *p   = htons(proto);
        }
        
-       drop |= is->pass_filter.filter
-               && sk_run_filter(skb, is->pass_filter.filter,
-                                is->pass_filter.len) == 0;
-       drop |= is->active_filter.filter
-               && sk_run_filter(skb, is->active_filter.filter,
-                                is->active_filter.len) == 0;
+       drop |= is->pass_filter
+               && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0;
+       drop |= is->active_filter
+               && sk_run_filter(skb, is->active_filter, is->active_len) == 0;
        
        skb_push(skb, IPPP_MAX_HEADER - 4);
        return drop;
@@ -1515,10 +1527,8 @@ static int isdn_ppp_mp_bundle_array_init(void)
 {
        int i;
        int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
-       if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz, 
-                                                       GFP_KERNEL)) == NULL )
+       if( (isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL )
                return -ENOMEM;
-       memset(isdn_ppp_bundle_arr, 0, sz);
        for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
                spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
        return 0;
@@ -1555,7 +1565,7 @@ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
                lp->next = lp->last = lp;       /* nobody else in a queue */
                lp->netdev->pb->frags = NULL;
                lp->netdev->pb->frames = 0;
-               lp->netdev->pb->seq = LONG_MAX;
+               lp->netdev->pb->seq = UINT_MAX;
        }
        lp->netdev->pb->ref_ct++;
        
@@ -1588,7 +1598,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
        mp = net_dev->pb;
         stats = &mp->stats;
        slot = lp->ppp_slot;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
                        __FUNCTION__, lp->ppp_slot);
                stats->frame_drops++;
@@ -1625,7 +1635,7 @@ static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
        is->last_link_seqno = minseq = newseq;
        for (lpq = net_dev->queue;;) {
                slot = lpq->ppp_slot;
-               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                        printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
                                __FUNCTION__, lpq->ppp_slot);
                } else {
@@ -1859,7 +1869,7 @@ void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
        struct sk_buff * skb;
        unsigned int tot_len;
 
-       if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
                        __FUNCTION__, lp->ppp_slot);
                return;
@@ -1969,16 +1979,12 @@ out:
 static int
 isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
 {
-       struct ppp_stats *res,
-        t;
+       struct ppp_stats __user *res = ifr->ifr_data;
+       struct ppp_stats t;
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
-       int err;
-
-       res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data;
-       err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats));
 
-       if (err)
-               return err;
+       if (!access_ok(VERIFY_WRITE, res, sizeof(struct ppp_stats)))
+               return -EFAULT;
 
        /* build a temporary stat struct and copy it to user space */
 
@@ -2004,7 +2010,8 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
                }
 #endif
        }
-       if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
+       if (copy_to_user(res, &t, sizeof(struct ppp_stats)))
+               return -EFAULT;
        return 0;
 }
 
@@ -2012,7 +2019,6 @@ int
 isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        int error=0;
-       char *r;
        int len;
        isdn_net_local *lp = (isdn_net_local *) dev->priv;
 
@@ -2023,9 +2029,8 @@ isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        switch (cmd) {
 #define PPP_VERSION "2.3.7"
                case SIOCGPPPVER:
-                       r = (char *) ifr->ifr_ifru.ifru_data;
                        len = strlen(PPP_VERSION) + 1;
-                       if (copy_to_user(r, PPP_VERSION, len))
+                       if (copy_to_user(ifr->ifr_data, PPP_VERSION, len))
                                error = -EFAULT;
                        break;
 
@@ -2237,13 +2242,12 @@ static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
 static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
 {
        struct ippp_ccp_reset *r;
-       r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
+       r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
        if(!r) {
                printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
                       " structure - no mem\n");
                return NULL;
        }
-       memset(r, 0, sizeof(struct ippp_ccp_reset));
        printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
        is->reset = r;
        return r;
@@ -2329,13 +2333,13 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
                       id);
                return NULL;
        } else {
-               rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+               rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
                if(!rs)
                        return NULL;
-               memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
                rs->state = CCPResetIdle;
                rs->is = is;
                rs->id = id;
+               init_timer(&rs->timer);
                rs->timer.data = (unsigned long)rs;
                rs->timer.function = isdn_ppp_ccp_timer_callback;
                is->reset->rs[id] = rs;
@@ -2516,8 +2520,7 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
                printk(KERN_DEBUG "ippp: no decompressor defined!\n");
                return skb;
        }
-       if (!stat) // if we have a compressor, stat has been set as well
-               BUG();
+       BUG_ON(!stat); // if we have a compressor, stat has been set as well
 
        if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
                // compressed packets are compressed by their protocol type
@@ -2528,6 +2531,11 @@ static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struc
                rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
   
                skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
+               if (!skb_out) {
+                       kfree_skb(skb);
+                       printk(KERN_ERR "ippp: decomp memory allocation failure\n");
+                       return NULL;
+               }
                len = ipc->decompress(stat, skb, skb_out, &rsparm);
                kfree_skb(skb);
                if (len <= 0) {
@@ -2639,7 +2647,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
 
        printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
                lp->ppp_slot);
-       if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
                        __FUNCTION__, lp->ppp_slot);
                return;
@@ -2649,7 +2657,7 @@ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
 
        if(lp->master) {
                int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
-               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                        printk(KERN_ERR "%s: slot(%d) out of range\n",
                                __FUNCTION__, slot);
                        return;
@@ -2813,7 +2821,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
 
        if(!skb || skb->len < 3)
                return;
-       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
                        __FUNCTION__, slot);
                return;
@@ -2836,7 +2844,7 @@ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct
 
        if (lp->master) {
                slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
-               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
                        printk(KERN_ERR "%s: slot(%d) out of range\n",
                                __FUNCTION__, slot);
                        return;