X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fpppoe.c;h=315d5c3fc66a0d9480bbc871f14b1b442cc78870;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=64b35cc250c982f314bffa4a70c12efa8515a7df;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 64b35cc25..315d5c3fc 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -85,8 +85,8 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb); static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb); -static struct proto_ops pppoe_ops; -static rwlock_t pppoe_hash_lock = RW_LOCK_UNLOCKED; +static const struct proto_ops pppoe_ops; +static DEFINE_RWLOCK(pppoe_hash_lock); static struct ppp_channel_ops pppoe_chan_ops; @@ -120,17 +120,17 @@ static int hash_item(unsigned long sid, unsigned char *addr) } /* zeroed because its in .bss */ -static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE]; +static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE]; /********************************************************************** * * Set/get/delete/rehash items (internal versions) * **********************************************************************/ -static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr) +static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr) { int hash = hash_item(sid, addr); - struct pppox_opt *ret; + struct pppox_sock *ret; ret = item_hash_table[hash]; @@ -140,10 +140,10 @@ static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr) return ret; } -static int __set_item(struct pppox_opt *po) +static int __set_item(struct pppox_sock *po) { int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); - struct pppox_opt *ret; + struct pppox_sock *ret; ret = item_hash_table[hash]; while (ret) { @@ -161,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]; @@ -187,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; @@ -220,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); @@ -248,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; @@ -331,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) { @@ -347,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)) @@ -361,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); @@ -375,41 +376,24 @@ 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; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; 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, 0); drop: kfree_skb(skb); out: @@ -424,25 +408,26 @@ 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; - if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + if (!(skb = skb_share_check(skb, GFP_ATOMIC))) goto out; ph = (struct pppoe_hdr *) skb->nh.raw; 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); @@ -478,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), +}; /*********************************************************************** * @@ -501,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; @@ -517,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) @@ -573,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); @@ -602,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; } @@ -632,6 +600,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.hdrlen = (sizeof(struct pppoe_hdr) + dev->hard_header_len); + po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr); po->chan.private = sk; po->chan.ops = &pppoe_chan_ops; @@ -679,7 +648,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; @@ -725,7 +694,7 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, case PPPOEIOCSFWD: { - struct pppox_opt *relay_po; + struct pppox_sock *relay_po; err = -EBUSY; if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD)) @@ -755,7 +724,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; @@ -777,12 +746,12 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd, } -static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, +static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len) { 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; @@ -857,7 +826,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; @@ -893,6 +862,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)); @@ -936,8 +908,8 @@ static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) } -static struct ppp_channel_ops pppoe_chan_ops = { - .start_xmit = pppoe_xmit, +static struct ppp_channel_ops pppoe_chan_ops = { + .start_xmit = pppoe_xmit, }; static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, @@ -984,7 +956,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) { @@ -1004,9 +976,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++) { @@ -1031,7 +1003,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) { @@ -1039,7 +1011,7 @@ static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) goto out; } po = v; - if (po->next) + if (po->next) po = po->next; else { int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); @@ -1059,7 +1031,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, @@ -1083,7 +1055,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; @@ -1094,9 +1066,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, @@ -1112,7 +1082,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 = { @@ -1124,22 +1095,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) @@ -1148,7 +1126,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);