diff options
Diffstat (limited to 'drivers/net/pppol2tp.c')
-rw-r--r-- | drivers/net/pppol2tp.c | 63 |
1 files changed, 23 insertions, 40 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 440e190778a1..abe91cb595f4 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c | |||
@@ -962,7 +962,6 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
962 | int data_len = skb->len; | 962 | int data_len = skb->len; |
963 | struct inet_sock *inet; | 963 | struct inet_sock *inet; |
964 | __wsum csum = 0; | 964 | __wsum csum = 0; |
965 | struct sk_buff *skb2 = NULL; | ||
966 | struct udphdr *uh; | 965 | struct udphdr *uh; |
967 | unsigned int len; | 966 | unsigned int len; |
968 | 967 | ||
@@ -993,41 +992,30 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
993 | */ | 992 | */ |
994 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + | 993 | headroom = NET_SKB_PAD + sizeof(struct iphdr) + |
995 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); | 994 | sizeof(struct udphdr) + hdr_len + sizeof(ppph); |
996 | if (skb_headroom(skb) < headroom) { | 995 | if (skb_cow_head(skb, headroom)) |
997 | skb2 = skb_realloc_headroom(skb, headroom); | 996 | goto abort; |
998 | if (skb2 == NULL) | ||
999 | goto abort; | ||
1000 | } else | ||
1001 | skb2 = skb; | ||
1002 | |||
1003 | /* Check that the socket has room */ | ||
1004 | if (atomic_read(&sk_tun->sk_wmem_alloc) < sk_tun->sk_sndbuf) | ||
1005 | skb_set_owner_w(skb2, sk_tun); | ||
1006 | else | ||
1007 | goto discard; | ||
1008 | 997 | ||
1009 | /* Setup PPP header */ | 998 | /* Setup PPP header */ |
1010 | skb_push(skb2, sizeof(ppph)); | 999 | __skb_push(skb, sizeof(ppph)); |
1011 | skb2->data[0] = ppph[0]; | 1000 | skb->data[0] = ppph[0]; |
1012 | skb2->data[1] = ppph[1]; | 1001 | skb->data[1] = ppph[1]; |
1013 | 1002 | ||
1014 | /* Setup L2TP header */ | 1003 | /* Setup L2TP header */ |
1015 | skb_push(skb2, hdr_len); | 1004 | pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len)); |
1016 | pppol2tp_build_l2tp_header(session, skb2->data); | ||
1017 | 1005 | ||
1018 | /* Setup UDP header */ | 1006 | /* Setup UDP header */ |
1019 | inet = inet_sk(sk_tun); | 1007 | inet = inet_sk(sk_tun); |
1020 | skb_push(skb2, sizeof(struct udphdr)); | 1008 | __skb_push(skb, sizeof(*uh)); |
1021 | skb_reset_transport_header(skb2); | 1009 | skb_reset_transport_header(skb); |
1022 | uh = (struct udphdr *) skb2->data; | 1010 | uh = udp_hdr(skb); |
1023 | uh->source = inet->sport; | 1011 | uh->source = inet->sport; |
1024 | uh->dest = inet->dport; | 1012 | uh->dest = inet->dport; |
1025 | uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); | 1013 | uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); |
1026 | uh->check = 0; | 1014 | uh->check = 0; |
1027 | 1015 | ||
1028 | /* Calculate UDP checksum if configured to do so */ | 1016 | /* *BROKEN* Calculate UDP checksum if configured to do so */ |
1029 | if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT) | 1017 | if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT) |
1030 | csum = udp_csum_outgoing(sk_tun, skb2); | 1018 | csum = udp_csum_outgoing(sk_tun, skb); |
1031 | 1019 | ||
1032 | /* Debug */ | 1020 | /* Debug */ |
1033 | if (session->send_seq) | 1021 | if (session->send_seq) |
@@ -1040,7 +1028,7 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1040 | 1028 | ||
1041 | if (session->debug & PPPOL2TP_MSG_DATA) { | 1029 | if (session->debug & PPPOL2TP_MSG_DATA) { |
1042 | int i; | 1030 | int i; |
1043 | unsigned char *datap = skb2->data; | 1031 | unsigned char *datap = skb->data; |
1044 | 1032 | ||
1045 | printk(KERN_DEBUG "%s: xmit:", session->name); | 1033 | printk(KERN_DEBUG "%s: xmit:", session->name); |
1046 | for (i = 0; i < data_len; i++) { | 1034 | for (i = 0; i < data_len; i++) { |
@@ -1053,18 +1041,18 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1053 | printk("\n"); | 1041 | printk("\n"); |
1054 | } | 1042 | } |
1055 | 1043 | ||
1056 | memset(&(IPCB(skb2)->opt), 0, sizeof(IPCB(skb2)->opt)); | 1044 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
1057 | IPCB(skb2)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | 1045 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
1058 | IPSKB_REROUTED); | 1046 | IPSKB_REROUTED); |
1059 | nf_reset(skb2); | 1047 | nf_reset(skb); |
1060 | 1048 | ||
1061 | /* Get routing info from the tunnel socket */ | 1049 | /* Get routing info from the tunnel socket */ |
1062 | dst_release(skb2->dst); | 1050 | dst_release(skb->dst); |
1063 | skb2->dst = sk_dst_get(sk_tun); | 1051 | skb->dst = sk_dst_get(sk_tun); |
1064 | 1052 | ||
1065 | /* Queue the packet to IP for output */ | 1053 | /* Queue the packet to IP for output */ |
1066 | len = skb2->len; | 1054 | len = skb->len; |
1067 | rc = ip_queue_xmit(skb2, 1); | 1055 | rc = ip_queue_xmit(skb, 1); |
1068 | 1056 | ||
1069 | /* Update stats */ | 1057 | /* Update stats */ |
1070 | if (rc >= 0) { | 1058 | if (rc >= 0) { |
@@ -1077,17 +1065,12 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) | |||
1077 | session->stats.tx_errors++; | 1065 | session->stats.tx_errors++; |
1078 | } | 1066 | } |
1079 | 1067 | ||
1080 | /* Free the original skb */ | ||
1081 | kfree_skb(skb); | ||
1082 | |||
1083 | return 1; | 1068 | return 1; |
1084 | 1069 | ||
1085 | discard: | ||
1086 | /* Free the new skb. Caller will free original skb. */ | ||
1087 | if (skb2 != skb) | ||
1088 | kfree_skb(skb2); | ||
1089 | abort: | 1070 | abort: |
1090 | return 0; | 1071 | /* Free the original skb */ |
1072 | kfree_skb(skb); | ||
1073 | return 1; | ||
1091 | } | 1074 | } |
1092 | 1075 | ||
1093 | /***************************************************************************** | 1076 | /***************************************************************************** |