diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/pppoe.c | 50 |
1 files changed, 13 insertions, 37 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 5ac3eff6a2a..8818253102f 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
@@ -850,9 +850,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) | |||
850 | struct net_device *dev = po->pppoe_dev; | 850 | struct net_device *dev = po->pppoe_dev; |
851 | struct pppoe_hdr hdr; | 851 | struct pppoe_hdr hdr; |
852 | struct pppoe_hdr *ph; | 852 | struct pppoe_hdr *ph; |
853 | int headroom = skb_headroom(skb); | ||
854 | int data_len = skb->len; | 853 | int data_len = skb->len; |
855 | struct sk_buff *skb2; | ||
856 | 854 | ||
857 | if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) | 855 | if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) |
858 | goto abort; | 856 | goto abort; |
@@ -866,53 +864,31 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) | |||
866 | if (!dev) | 864 | if (!dev) |
867 | goto abort; | 865 | goto abort; |
868 | 866 | ||
869 | /* Copy the skb if there is no space for the header. */ | 867 | /* Copy the data if there is no space for the header or if it's |
870 | if (headroom < (sizeof(struct pppoe_hdr) + dev->hard_header_len)) { | 868 | * read-only. |
871 | skb2 = dev_alloc_skb(32+skb->len + | 869 | */ |
872 | sizeof(struct pppoe_hdr) + | 870 | if (skb_cow(skb, sizeof(*ph) + dev->hard_header_len)) |
873 | dev->hard_header_len); | 871 | goto abort; |
874 | |||
875 | if (skb2 == NULL) | ||
876 | goto abort; | ||
877 | |||
878 | skb_reserve(skb2, dev->hard_header_len + sizeof(struct pppoe_hdr)); | ||
879 | skb_copy_from_linear_data(skb, skb_put(skb2, skb->len), | ||
880 | skb->len); | ||
881 | } else { | ||
882 | /* Make a clone so as to not disturb the original skb, | ||
883 | * give dev_queue_xmit something it can free. | ||
884 | */ | ||
885 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
886 | |||
887 | if (skb2 == NULL) | ||
888 | goto abort; | ||
889 | } | ||
890 | 872 | ||
891 | ph = (struct pppoe_hdr *) skb_push(skb2, sizeof(struct pppoe_hdr)); | 873 | ph = (struct pppoe_hdr *) skb_push(skb, sizeof(struct pppoe_hdr)); |
892 | memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); | 874 | memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); |
893 | skb2->protocol = __constant_htons(ETH_P_PPP_SES); | 875 | skb->protocol = __constant_htons(ETH_P_PPP_SES); |
894 | 876 | ||
895 | skb_reset_network_header(skb2); | 877 | skb_reset_network_header(skb); |
896 | 878 | ||
897 | skb2->dev = dev; | 879 | skb->dev = dev; |
898 | 880 | ||
899 | dev->hard_header(skb2, dev, ETH_P_PPP_SES, | 881 | dev->hard_header(skb, dev, ETH_P_PPP_SES, |
900 | po->pppoe_pa.remote, NULL, data_len); | 882 | po->pppoe_pa.remote, NULL, data_len); |
901 | 883 | ||
902 | /* We're transmitting skb2, and assuming that dev_queue_xmit | 884 | if (dev_queue_xmit(skb) < 0) |
903 | * will free it. The generic ppp layer however, is expecting | ||
904 | * that we give back 'skb' (not 'skb2') in case of failure, | ||
905 | * but free it in case of success. | ||
906 | */ | ||
907 | |||
908 | if (dev_queue_xmit(skb2) < 0) | ||
909 | goto abort; | 885 | goto abort; |
910 | 886 | ||
911 | kfree_skb(skb); | ||
912 | return 1; | 887 | return 1; |
913 | 888 | ||
914 | abort: | 889 | abort: |
915 | return 0; | 890 | kfree_skb(skb); |
891 | return 1; | ||
916 | } | 892 | } |
917 | 893 | ||
918 | 894 | ||