X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpppoe.c;h=0d101a18026a31b250a010bba4be28be45cab441;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=6f4f64da70232cbc4232dd2f674c1581bad83762;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 6f4f64da7..0d101a180 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -79,13 +79,16 @@ #define PPPOE_HASH_BITS 4 #define PPPOE_HASH_SIZE (1<pppoe_pa.sid, po->pppoe_pa.remote); - struct pppox_opt *ret; + struct pppox_sock *ret; ret = item_hash_table[hash]; while (ret) { @@ -158,10 +161,10 @@ static int __set_item(struct pppox_opt *po) return 0; } -static struct pppox_opt *__delete_item(unsigned long sid, char *addr) +static struct pppox_sock *__delete_item(unsigned long sid, char *addr) { int hash = hash_item(sid, addr); - struct pppox_opt *ret, **src; + struct pppox_sock *ret, **src; ret = item_hash_table[hash]; src = &item_hash_table[hash]; @@ -184,26 +187,26 @@ static struct pppox_opt *__delete_item(unsigned long sid, char *addr) * Set/get/delete/rehash items * **********************************************************************/ -static inline struct pppox_opt *get_item(unsigned long sid, +static inline struct pppox_sock *get_item(unsigned long sid, unsigned char *addr) { - struct pppox_opt *po; + struct pppox_sock *po; read_lock_bh(&pppoe_hash_lock); po = __get_item(sid, addr); if (po) - sock_hold(po->sk); + sock_hold(sk_pppox(po)); read_unlock_bh(&pppoe_hash_lock); return po; } -static inline struct pppox_opt *get_item_by_addr(struct sockaddr_pppox *sp) +static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp) { return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote); } -static inline int set_item(struct pppox_opt *po) +static inline int set_item(struct pppox_sock *po) { int i; @@ -217,9 +220,9 @@ static inline int set_item(struct pppox_opt *po) return i; } -static inline struct pppox_opt *delete_item(unsigned long sid, char *addr) +static inline struct pppox_sock *delete_item(unsigned long sid, char *addr) { - struct pppox_opt *ret; + struct pppox_sock *ret; write_lock_bh(&pppoe_hash_lock); ret = __delete_item(sid, addr); @@ -245,11 +248,11 @@ static void pppoe_flush_dev(struct net_device *dev) read_lock_bh(&pppoe_hash_lock); for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) { - struct pppox_opt *po = item_hash_table[hash]; + struct pppox_sock *po = item_hash_table[hash]; while (po != NULL) { if (po->pppoe_dev == dev) { - struct sock *sk = po->sk; + struct sock *sk = sk_pppox(po); sock_hold(sk); po->pppoe_dev = NULL; @@ -328,14 +331,15 @@ static struct notifier_block pppoe_notifier = { ***********************************************************************/ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) { - struct pppox_opt *po = pppox_sk(sk); - struct pppox_opt *relay_po = NULL; + struct pppox_sock *po = pppox_sk(sk); + struct pppox_sock *relay_po = NULL; if (sk->sk_state & PPPOX_BOUND) { struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; int len = ntohs(ph->length); - skb_pull(skb, sizeof(struct pppoe_hdr)); - skb_trim(skb, len); + skb_pull_rcsum(skb, sizeof(struct pppoe_hdr)); + if (pskb_trim_rcsum(skb, len)) + goto abort_kfree; ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { @@ -344,11 +348,11 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) if (relay_po == NULL) goto abort_kfree; - if ((relay_po->sk->sk_state & PPPOX_CONNECTED) == 0) + if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) goto abort_put; skb_pull(skb, sizeof(struct pppoe_hdr)); - if (!__pppoe_xmit( relay_po->sk, skb)) + if (!__pppoe_xmit(sk_pppox(relay_po), skb)) goto abort_put; } else { if (sock_queue_rcv_skb(sk, skb)) @@ -358,7 +362,7 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb) return NET_RX_SUCCESS; abort_put: - sock_put(relay_po->sk); + sock_put(sk_pppox(relay_po)); abort_kfree: kfree_skb(skb); @@ -372,13 +376,12 @@ abort_kfree: ***********************************************************************/ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt) + struct packet_type *pt, + struct net_device *orig_dev) { struct pppoe_hdr *ph; - struct pppox_opt *po; - struct sock *sk; - int ret; + struct pppox_sock *po; if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) goto drop; @@ -388,25 +391,9 @@ static int pppoe_rcv(struct sk_buff *skb, ph = (struct pppoe_hdr *) skb->nh.raw; - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); - if (!po) - goto drop; - - sk = po->sk; - bh_lock_sock(sk); - - /* Socket state is unknown, must put skb into backlog. */ - if (sock_owned_by_user(sk) != 0) { - sk_add_backlog(sk, skb); - ret = NET_RX_SUCCESS; - } else { - ret = pppoe_rcv_core(sk, skb); - } - - bh_unlock_sock(sk); - sock_put(sk); - - return ret; + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); + if (po != NULL) + return sk_receive_skb(sk_pppox(po), skb); drop: kfree_skb(skb); out: @@ -421,11 +408,12 @@ out: ***********************************************************************/ static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt) + struct packet_type *pt, + struct net_device *orig_dev) { struct pppoe_hdr *ph; - struct pppox_opt *po; + struct pppox_sock *po; if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) goto abort; @@ -437,9 +425,9 @@ static int pppoe_disc_rcv(struct sk_buff *skb, if (ph->code != PADT_CODE) goto abort; - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); if (po) { - struct sock *sk = po->sk; + struct sock *sk = sk_pppox(po); bh_lock_sock(sk); @@ -475,19 +463,11 @@ static struct packet_type pppoed_ptype = { .func = pppoe_disc_rcv, }; -/*********************************************************************** - * - * Really kill the socket. (Called from pppox_sk_free if refcnt == 0.) - * - **********************************************************************/ -static void pppoe_sk_free(struct sock *sk) -{ - struct pppox_opt *po = pppox_sk(sk); - - if (po) - kfree(po); -} - +static struct proto pppoe_sk_proto = { + .name = "PPPOE", + .owner = THIS_MODULE, + .obj_size = sizeof(struct pppox_sock), +}; /*********************************************************************** * @@ -498,14 +478,13 @@ static int pppoe_create(struct socket *sock) { int error = -ENOMEM; struct sock *sk; - struct pppox_opt *po; - sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL); + sk = sk_alloc(PF_PPPOX, GFP_KERNEL, &pppoe_sk_proto, 1); if (!sk) goto out; sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); + sock->state = SS_UNCONNECTED; sock->ops = &pppoe_ops; @@ -514,23 +493,15 @@ static int pppoe_create(struct socket *sock) sk->sk_type = SOCK_STREAM; sk->sk_family = PF_PPPOX; sk->sk_protocol = PX_PROTO_OE; - sk->sk_destruct = pppoe_sk_free; - po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL); - if (!po) - goto frees; - memset(po, 0, sizeof(*po)); - po->sk = sk; error = 0; out: return error; -frees: sk_free(sk); - goto out; } static int pppoe_release(struct socket *sock) { struct sock *sk = sock->sk; - struct pppox_opt *po; + struct pppox_sock *po; int error = 0; if (!sk) @@ -570,7 +541,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, struct sock *sk = sock->sk; struct net_device *dev = NULL; struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr; - struct pppox_opt *po = pppox_sk(sk); + struct pppox_sock *po = pppox_sk(sk); int error; lock_sock(sk); @@ -599,8 +570,8 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, if(po->pppoe_dev) dev_put(po->pppoe_dev); - memset(po, 0, sizeof(struct pppox_opt)); - po->sk = sk; + memset(sk_pppox(po) + 1, 0, + sizeof(struct pppox_sock) - sizeof(struct sock)); sk->sk_state = PPPOX_NONE; } @@ -676,7 +647,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; - struct pppox_opt *po = pppox_sk(sk); + struct pppox_sock *po = pppox_sk(sk); int val = 0; int err = 0; @@ -691,7 +662,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, if (put_user(po->pppoe_dev->mtu - sizeof(struct pppoe_hdr) - PPP_HDRLEN, - (int *) arg)) + (int __user *) arg)) break; err = 0; break; @@ -702,7 +673,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, break; err = -EFAULT; - if (get_user(val,(int *) arg)) + if (get_user(val,(int __user *) arg)) break; if (val < (po->pppoe_dev->mtu @@ -715,14 +686,14 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, case PPPIOCSFLAGS: err = -EFAULT; - if (get_user(val, (int *) arg)) + if (get_user(val, (int __user *) arg)) break; err = 0; break; case PPPOEIOCSFWD: { - struct pppox_opt *relay_po; + struct pppox_sock *relay_po; err = -EBUSY; if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD)) @@ -736,7 +707,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, PPPoE address to which frames are forwarded to */ err = -EFAULT; if (copy_from_user(&po->pppoe_relay, - (void*)arg, + (void __user *)arg, sizeof(struct sockaddr_pppox))) break; @@ -752,7 +723,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, if (!relay_po) break; - sock_put(relay_po->sk); + sock_put(sk_pppox(relay_po)); sk->sk_state |= PPPOX_RELAY; err = 0; break; @@ -779,7 +750,7 @@ static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, { struct sk_buff *skb = NULL; struct sock *sk = sock->sk; - struct pppox_opt *po = pppox_sk(sk); + struct pppox_sock *po = pppox_sk(sk); int error = 0; struct pppoe_hdr hdr; struct pppoe_hdr *ph; @@ -854,7 +825,7 @@ end: ***********************************************************************/ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) { - struct pppox_opt *po = pppox_sk(sk); + struct pppox_sock *po = pppox_sk(sk); struct net_device *dev = po->pppoe_dev; struct pppoe_hdr hdr; struct pppoe_hdr *ph; @@ -890,6 +861,9 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) * give dev_queue_xmit something it can free. */ skb2 = skb_clone(skb, GFP_ATOMIC); + + if (skb2 == NULL) + goto abort; } ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr)); @@ -981,7 +955,7 @@ end: #ifdef CONFIG_PROC_FS static int pppoe_seq_show(struct seq_file *seq, void *v) { - struct pppox_opt *po; + struct pppox_sock *po; char *dev_name; if (v == SEQ_START_TOKEN) { @@ -1001,9 +975,9 @@ out: return 0; } -static __inline__ struct pppox_opt *pppoe_get_idx(loff_t pos) +static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos) { - struct pppox_opt *po = NULL; + struct pppox_sock *po = NULL; int i = 0; for (; i < PPPOE_HASH_SIZE; i++) { @@ -1028,7 +1002,7 @@ static void *pppoe_seq_start(struct seq_file *seq, loff_t *pos) static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct pppox_opt *po; + struct pppox_sock *po; ++*pos; if (v == SEQ_START_TOKEN) { @@ -1056,7 +1030,7 @@ static void pppoe_seq_stop(struct seq_file *seq, void *v) read_unlock_bh(&pppoe_hash_lock); } -struct seq_operations pppoe_seq_ops = { +static struct seq_operations pppoe_seq_ops = { .start = pppoe_seq_start, .next = pppoe_seq_next, .stop = pppoe_seq_stop, @@ -1080,7 +1054,7 @@ static int __init pppoe_proc_init(void) { struct proc_dir_entry *p; - p = create_proc_entry("pppoe", S_IRUGO, proc_net); + p = create_proc_entry("net/pppoe", S_IRUGO, NULL); if (!p) return -ENOMEM; @@ -1091,9 +1065,7 @@ static int __init pppoe_proc_init(void) static inline int pppoe_proc_init(void) { return 0; } #endif /* CONFIG_PROC_FS */ -/* ->ioctl are set at pppox_create */ - -static struct proto_ops pppoe_ops = { +static const struct proto_ops pppoe_ops = { .family = AF_PPPOX, .owner = THIS_MODULE, .release = pppoe_release, @@ -1109,7 +1081,8 @@ static struct proto_ops pppoe_ops = { .getsockopt = sock_no_getsockopt, .sendmsg = pppoe_sendmsg, .recvmsg = pppoe_recvmsg, - .mmap = sock_no_mmap + .mmap = sock_no_mmap, + .ioctl = pppox_ioctl, }; static struct pppox_proto pppoe_proto = { @@ -1121,22 +1094,29 @@ static struct pppox_proto pppoe_proto = { static int __init pppoe_init(void) { - int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); + int err = proto_register(&pppoe_sk_proto, 0); if (err) goto out; + err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); + if (err) + goto out_unregister_pppoe_proto; + err = pppoe_proc_init(); - if (err) { - unregister_pppox_proto(PX_PROTO_OE); - goto out; - } + if (err) + goto out_unregister_pppox_proto; dev_add_pack(&pppoes_ptype); dev_add_pack(&pppoed_ptype); register_netdevice_notifier(&pppoe_notifier); out: return err; +out_unregister_pppox_proto: + unregister_pppox_proto(PX_PROTO_OE); +out_unregister_pppoe_proto: + proto_unregister(&pppoe_sk_proto); + goto out; } static void __exit pppoe_exit(void) @@ -1145,7 +1125,8 @@ static void __exit pppoe_exit(void) dev_remove_pack(&pppoes_ptype); dev_remove_pack(&pppoed_ptype); unregister_netdevice_notifier(&pppoe_notifier); - remove_proc_entry("pppoe", proc_net); + remove_proc_entry("net/pppoe", NULL); + proto_unregister(&pppoe_sk_proto); } module_init(pppoe_init);