X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fppp_generic.c;h=6516011055677d7cc39e207446da23f96f5cedeb;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=ffd5ac3a848ee1f617e98eed2743fca8bf3ab656;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index ffd5ac3a8..651601105 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -129,8 +129,9 @@ struct ppp { #endif /* CONFIG_PPP_MULTILINK */ struct net_device_stats stats; /* statistics */ #ifdef CONFIG_PPP_FILTER - struct sock_fprog pass_filter; /* filter for packets to pass */ - struct sock_fprog active_filter;/* filter for pkts to reset idle */ + struct sock_filter *pass_filter; /* filter for packets to pass */ + struct sock_filter *active_filter;/* filter for pkts to reset idle */ + unsigned pass_len, active_len; #endif /* CONFIG_PPP_FILTER */ }; @@ -370,7 +371,7 @@ static int ppp_release(struct inode *inode, struct file *file) struct ppp *ppp; if (pf != 0) { - file->private_data = 0; + file->private_data = NULL; if (pf->kind == INTERFACE) { ppp = PF_TO_PPP(pf); if (file == ppp->owner) @@ -396,7 +397,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, struct ppp_file *pf = file->private_data; DECLARE_WAITQUEUE(wait, current); ssize_t ret; - struct sk_buff *skb = 0; + struct sk_buff *skb = NULL; ret = count; @@ -493,6 +494,45 @@ static unsigned int ppp_poll(struct file *file, poll_table *wait) return mask; } +#ifdef CONFIG_PPP_FILTER +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 > BPF_MAXINSNS) + return -EINVAL; + + if (!uprog.len) { + *p = NULL; + return 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; + } + + *p = code; + return uprog.len; +} +#endif /* CONFIG_PPP_FILTER */ + static int ppp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { @@ -503,6 +543,8 @@ static int ppp_ioctl(struct inode *inode, struct file *file, struct npioctl npi; int unit, cflags; struct slcompress *vj; + void __user *argp = (void __user *)arg; + int __user *p = argp; if (pf == 0) return ppp_unattached_ioctl(pf, file, cmd, arg); @@ -540,7 +582,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, switch (cmd) { case PPPIOCCONNECT: - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; err = ppp_connect_channel(pch, unit); break; @@ -569,14 +611,14 @@ static int ppp_ioctl(struct inode *inode, struct file *file, ppp = PF_TO_PPP(pf); switch (cmd) { case PPPIOCSMRU: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp->mru = val; err = 0; break; case PPPIOCSFLAGS: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp_lock(ppp); cflags = ppp->flags & ~val; @@ -589,7 +631,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGFLAGS: val = ppp->flags | ppp->xstate | ppp->rstate; - if (put_user(val, (int *) arg)) + if (put_user(val, p)) break; err = 0; break; @@ -599,20 +641,20 @@ static int ppp_ioctl(struct inode *inode, struct file *file, break; case PPPIOCGUNIT: - if (put_user(ppp->file.index, (int *) arg)) + if (put_user(ppp->file.index, p)) break; err = 0; break; case PPPIOCSDEBUG: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp->debug = val; err = 0; break; case PPPIOCGDEBUG: - if (put_user(ppp->debug, (int *) arg)) + if (put_user(ppp->debug, p)) break; err = 0; break; @@ -620,13 +662,13 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGIDLE: idle.xmit_idle = (jiffies - ppp->last_xmit) / HZ; idle.recv_idle = (jiffies - ppp->last_recv) / HZ; - if (copy_to_user((void __user *) arg, &idle, sizeof(idle))) + if (copy_to_user(argp, &idle, sizeof(idle))) break; err = 0; break; case PPPIOCSMAXCID: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; val2 = 15; if ((val >> 16) != 0) { @@ -649,7 +691,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, case PPPIOCGNPMODE: case PPPIOCSNPMODE: - if (copy_from_user(&npi, (void __user *) arg, sizeof(npi))) + if (copy_from_user(&npi, argp, sizeof(npi))) break; err = proto_to_npindex(npi.protocol); if (err < 0) @@ -658,7 +700,7 @@ static int ppp_ioctl(struct inode *inode, struct file *file, if (cmd == PPPIOCGNPMODE) { err = -EFAULT; npi.mode = ppp->npmode[i]; - if (copy_to_user((void __user *) arg, &npi, sizeof(npi))) + if (copy_to_user(argp, &npi, sizeof(npi))) break; } else { ppp->npmode[i] = npi.mode; @@ -670,49 +712,38 @@ static int ppp_ioctl(struct inode *inode, struct file *file, #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: + { + struct sock_filter *code; + err = get_filter(argp, &code); + if (err >= 0) { + ppp_lock(ppp); + kfree(ppp->pass_filter); + ppp->pass_filter = code; + ppp->pass_len = err; + ppp_unlock(ppp); + err = 0; + } + break; + } case PPPIOCSACTIVE: { - struct sock_fprog uprog, *filtp; - struct sock_filter *code = NULL; - int len; - - if (copy_from_user(&uprog, (void __user *) arg, sizeof(uprog))) - break; - err = -EINVAL; - if (uprog.len > BPF_MAXINSNS) - break; - err = -ENOMEM; - if (uprog.len > 0) { - len = uprog.len * sizeof(struct sock_filter); - code = kmalloc(len, GFP_KERNEL); - if (code == NULL) - break; - err = -EFAULT; - if (copy_from_user(code, (void __user *) uprog.filter, len)) { - kfree(code); - break; - } - err = sk_chk_filter(code, uprog.len); - if (err) { - kfree(code); - break; - } + struct sock_filter *code; + err = get_filter(argp, &code); + if (err >= 0) { + ppp_lock(ppp); + kfree(ppp->active_filter); + ppp->active_filter = code; + ppp->active_len = err; + ppp_unlock(ppp); + err = 0; } - filtp = (cmd == PPPIOCSPASS)? &ppp->pass_filter: &ppp->active_filter; - ppp_lock(ppp); - if (filtp->filter) - kfree(filtp->filter); - filtp->filter = code; - filtp->len = uprog.len; - ppp_unlock(ppp); - err = 0; break; } #endif /* CONFIG_PPP_FILTER */ #ifdef CONFIG_PPP_MULTILINK case PPPIOCSMRRU: - if (get_user(val, (int *) arg)) + if (get_user(val, p)) break; ppp_recv_lock(ppp); ppp->mrru = val; @@ -734,11 +765,12 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, int unit, err = -EFAULT; struct ppp *ppp; struct channel *chan; + int __user *p = (int __user *)arg; switch (cmd) { case PPPIOCNEWUNIT: /* Create a new ppp unit */ - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; ppp = ppp_create_interface(unit, &err); if (ppp == 0) @@ -746,14 +778,14 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, file->private_data = &ppp->file; ppp->owner = file; err = -EFAULT; - if (put_user(ppp->file.index, (int *) arg)) + if (put_user(ppp->file.index, p)) break; err = 0; break; case PPPIOCATTACH: /* Attach to an existing ppp unit */ - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; down(&all_ppp_sem); err = -ENXIO; @@ -767,7 +799,7 @@ static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file, break; case PPPIOCATTCHAN: - if (get_user(unit, (int *) arg)) + if (get_user(unit, p)) break; spin_lock_bh(&all_channels_lock); err = -ENXIO; @@ -994,23 +1026,19 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* check if we should pass this packet */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ - { - u_int16_t *p = (u_int16_t *) skb_push(skb, 2); - - *p = htons(4); /* indicate outbound in DLT_LINUX_SLL */; - } - if (ppp->pass_filter.filter - && sk_run_filter(skb, ppp->pass_filter.filter, - ppp->pass_filter.len) == 0) { + *skb_push(skb, 2) = 1; + if (ppp->pass_filter + && sk_run_filter(skb, ppp->pass_filter, + ppp->pass_len) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: outbound frame not passed\n"); kfree_skb(skb); return; } /* if this packet passes the active filter, record the time */ - if (!(ppp->active_filter.filter - && sk_run_filter(skb, ppp->active_filter.filter, - ppp->active_filter.len) == 0)) + if (!(ppp->active_filter + && sk_run_filter(skb, ppp->active_filter, + ppp->active_len) == 0)) ppp->last_xmit = jiffies; skb_pull(skb, 2); #else @@ -1129,7 +1157,7 @@ ppp_push(struct ppp *ppp) list = &ppp->channels; if (list_empty(list)) { /* nowhere to send the packet, just drop it */ - ppp->xmit_pending = 0; + ppp->xmit_pending = NULL; kfree_skb(skb); return; } @@ -1142,11 +1170,11 @@ ppp_push(struct ppp *ppp) spin_lock_bh(&pch->downl); if (pch->chan) { if (pch->chan->ops->start_xmit(pch->chan, skb)) - ppp->xmit_pending = 0; + ppp->xmit_pending = NULL; } else { /* channel got unregistered */ kfree_skb(skb); - ppp->xmit_pending = 0; + ppp->xmit_pending = NULL; } spin_unlock_bh(&pch->downl); return; @@ -1159,7 +1187,7 @@ ppp_push(struct ppp *ppp) return; #endif /* CONFIG_PPP_MULTILINK */ - ppp->xmit_pending = 0; + ppp->xmit_pending = NULL; kfree_skb(skb); } @@ -1541,22 +1569,18 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) /* check if the packet passes the pass and active filters */ /* the filter instructions are constructed assuming a four-byte PPP header on each packet */ - { - u_int16_t *p = (u_int16_t *) skb_push(skb, 2); - - *p = 0; /* indicate inbound in DLT_LINUX_SLL */ - } - if (ppp->pass_filter.filter - && sk_run_filter(skb, ppp->pass_filter.filter, - ppp->pass_filter.len) == 0) { + *skb_push(skb, 2) = 0; + if (ppp->pass_filter + && sk_run_filter(skb, ppp->pass_filter, + ppp->pass_len) == 0) { if (ppp->debug & 1) printk(KERN_DEBUG "PPP: inbound frame not passed\n"); kfree_skb(skb); return; } - if (!(ppp->active_filter.filter - && sk_run_filter(skb, ppp->active_filter.filter, - ppp->active_filter.len) == 0)) + if (!(ppp->active_filter + && sk_run_filter(skb, ppp->active_filter, + ppp->active_len) == 0)) ppp->last_recv = jiffies; skb_pull(skb, 2); #else @@ -1944,7 +1968,7 @@ ppp_unregister_channel(struct ppp_channel *chan) if (pch == 0) return; /* should never happen */ - chan->ppp = 0; + chan->ppp = NULL; /* * This ensures that we have returned from any calls into the @@ -1952,7 +1976,7 @@ ppp_unregister_channel(struct ppp_channel *chan) */ down_write(&pch->chan_sem); spin_lock_bh(&pch->downl); - pch->chan = 0; + pch->chan = NULL; spin_unlock_bh(&pch->downl); up_write(&pch->chan_sem); ppp_disconnect_channel(pch); @@ -2155,11 +2179,11 @@ ppp_ccp_closed(struct ppp *ppp) ppp->xstate = 0; xcomp = ppp->xcomp; xstate = ppp->xc_state; - ppp->xc_state = 0; + ppp->xc_state = NULL; ppp->rstate = 0; rcomp = ppp->rcomp; rstate = ppp->rc_state; - ppp->rc_state = 0; + ppp->rc_state = NULL; ppp_unlock(ppp); if (xstate) { @@ -2192,7 +2216,7 @@ find_comp_entry(int proto) if (ce->comp->compress_proto == proto) return ce; } - return 0; + return NULL; } /* Register a compressor */ @@ -2237,7 +2261,7 @@ static struct compressor * find_compressor(int type) { struct compressor_entry *ce; - struct compressor *cp = 0; + struct compressor *cp = NULL; spin_lock(&compressor_list_lock); ce = find_comp_entry(type); @@ -2381,7 +2405,7 @@ static void ppp_shutdown_interface(struct ppp *ppp) down(&all_ppp_sem); ppp_lock(ppp); dev = ppp->dev; - ppp->dev = 0; + ppp->dev = NULL; ppp_unlock(ppp); /* This will call dev_close() for us. */ if (dev) { @@ -2415,7 +2439,7 @@ static void ppp_destroy_interface(struct ppp *ppp) ppp_ccp_closed(ppp); if (ppp->vj) { slhc_free(ppp->vj); - ppp->vj = 0; + ppp->vj = NULL; } skb_queue_purge(&ppp->file.xq); skb_queue_purge(&ppp->file.rq); @@ -2423,13 +2447,13 @@ static void ppp_destroy_interface(struct ppp *ppp) skb_queue_purge(&ppp->mrq); #endif /* CONFIG_PPP_MULTILINK */ #ifdef CONFIG_PPP_FILTER - if (ppp->pass_filter.filter) { - kfree(ppp->pass_filter.filter); - ppp->pass_filter.filter = NULL; + if (ppp->pass_filter) { + kfree(ppp->pass_filter); + ppp->pass_filter = NULL; } - if (ppp->active_filter.filter) { - kfree(ppp->active_filter.filter); - ppp->active_filter.filter = 0; + if (ppp->active_filter) { + kfree(ppp->active_filter); + ppp->active_filter = NULL; } #endif /* CONFIG_PPP_FILTER */ @@ -2475,7 +2499,7 @@ ppp_find_channel(int unit) if (pch->file.index == unit) return pch; } - return 0; + return NULL; } /*