aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-09-19 13:46:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-09-20 15:14:18 -0400
commitf3d5e3a4155b6f42f6f6f0a2cc95ca0adbabe1af (patch)
tree82cf55e9144b5aba570c6a8e240fd1daf6c4a88d /drivers/net
parent7a70e39b6633ad85936b029463134ee2599600f1 (diff)
[PPP] L2TP: Fix skb handling in pppol2tp_xmit
This patch makes pppol2tp_xmit call skb_cow_head so that we don't modify cloned skb data. It also gets rid of skb2 we only need to preserve the original skb for congestion notification, which is only applicable for ppp_async and ppp_sync. The other semantic change made here is the removal of socket accounting for data tranmitted out of pppol2tp_xmit. The original code leaked any existing socket skb accounting. We could fix this by dropping the original skb owner. However, this is undesirable as the packet has not physically left the host yet. In fact, all other tunnels in the kernel do not account skb's passing through to their own socket. In partciular, ESP over UDP does not do so and it is the closest tunnel type to PPPoL2TP. So this patch simply removes the socket accounting in pppol2tp_xmit. The accounting still applies to control packets of course. I've also added a reminder that the outgoing checksum here doesn't work. I suppose existing deployments don't actually enable checksums. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/pppol2tp.c63
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
1085discard:
1086 /* Free the new skb. Caller will free original skb. */
1087 if (skb2 != skb)
1088 kfree_skb(skb2);
1089abort: 1070abort:
1090 return 0; 1071 /* Free the original skb */
1072 kfree_skb(skb);
1073 return 1;
1091} 1074}
1092 1075
1093/***************************************************************************** 1076/*****************************************************************************