aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/pppol2tp.c
diff options
context:
space:
mode:
authorJames Chapman <jchapman@katalix.com>2008-12-16 04:23:49 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-16 04:23:49 -0500
commitffcebb163c6ddba11abd2e8aabc7a8a88982e4f4 (patch)
treeb531cdc5afb34dae85d67aef5607d344996e1f44 /drivers/net/pppol2tp.c
parent09a2c3c0d3d3550675b766aa5edc28ffee79d7ab (diff)
l2tp: fix UDP checksum support
The pppol2tp driver has had broken UDP checksum code for a long time. This patch fixes it. If UDP checksums are enabled in the tunnel's UDP socket, the L2TP driver now properly validates the checksum on receive and fills in the checksum on transmit. If the network device has hardware checksum support and is enabled, it is used instead of generating/checking the checksum in software. Signed-off-by: James Chapman <jchapman@katalix.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/pppol2tp.c')
-rw-r--r--drivers/net/pppol2tp.c94
1 files changed, 82 insertions, 12 deletions
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index e98d9773158d..f1a946785c6a 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -489,6 +489,30 @@ out:
489 spin_unlock_bh(&session->reorder_q.lock); 489 spin_unlock_bh(&session->reorder_q.lock);
490} 490}
491 491
492static inline int pppol2tp_verify_udp_checksum(struct sock *sk,
493 struct sk_buff *skb)
494{
495 struct udphdr *uh = udp_hdr(skb);
496 u16 ulen = ntohs(uh->len);
497 struct inet_sock *inet;
498 __wsum psum;
499
500 if (sk->sk_no_check || skb_csum_unnecessary(skb) || !uh->check)
501 return 0;
502
503 inet = inet_sk(sk);
504 psum = csum_tcpudp_nofold(inet->saddr, inet->daddr, ulen,
505 IPPROTO_UDP, 0);
506
507 if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
508 !csum_fold(csum_add(psum, skb->csum)))
509 return 0;
510
511 skb->csum = psum;
512
513 return __skb_checksum_complete(skb);
514}
515
492/* Internal receive frame. Do the real work of receiving an L2TP data frame 516/* Internal receive frame. Do the real work of receiving an L2TP data frame
493 * here. The skb is not on a list when we get here. 517 * here. The skb is not on a list when we get here.
494 * Returns 0 if the packet was a data packet and was successfully passed on. 518 * Returns 0 if the packet was a data packet and was successfully passed on.
@@ -509,6 +533,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
509 if (tunnel == NULL) 533 if (tunnel == NULL)
510 goto no_tunnel; 534 goto no_tunnel;
511 535
536 if (tunnel->sock && pppol2tp_verify_udp_checksum(tunnel->sock, skb))
537 goto discard_bad_csum;
538
512 /* UDP always verifies the packet length. */ 539 /* UDP always verifies the packet length. */
513 __skb_pull(skb, sizeof(struct udphdr)); 540 __skb_pull(skb, sizeof(struct udphdr));
514 541
@@ -725,6 +752,14 @@ discard:
725 752
726 return 0; 753 return 0;
727 754
755discard_bad_csum:
756 LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
757 UDP_INC_STATS_USER(&init_net, UDP_MIB_INERRORS, 0);
758 tunnel->stats.rx_errors++;
759 kfree_skb(skb);
760
761 return 0;
762
728error: 763error:
729 /* Put UDP header back */ 764 /* Put UDP header back */
730 __skb_push(skb, sizeof(struct udphdr)); 765 __skb_push(skb, sizeof(struct udphdr));
@@ -851,7 +886,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
851 static const unsigned char ppph[2] = { 0xff, 0x03 }; 886 static const unsigned char ppph[2] = { 0xff, 0x03 };
852 struct sock *sk = sock->sk; 887 struct sock *sk = sock->sk;
853 struct inet_sock *inet; 888 struct inet_sock *inet;
854 __wsum csum = 0; 889 __wsum csum;
855 struct sk_buff *skb; 890 struct sk_buff *skb;
856 int error; 891 int error;
857 int hdr_len; 892 int hdr_len;
@@ -859,6 +894,8 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
859 struct pppol2tp_tunnel *tunnel; 894 struct pppol2tp_tunnel *tunnel;
860 struct udphdr *uh; 895 struct udphdr *uh;
861 unsigned int len; 896 unsigned int len;
897 struct sock *sk_tun;
898 u16 udp_len;
862 899
863 error = -ENOTCONN; 900 error = -ENOTCONN;
864 if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED)) 901 if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
@@ -870,7 +907,8 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
870 if (session == NULL) 907 if (session == NULL)
871 goto error; 908 goto error;
872 909
873 tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock); 910 sk_tun = session->tunnel_sock;
911 tunnel = pppol2tp_sock_to_tunnel(sk_tun);
874 if (tunnel == NULL) 912 if (tunnel == NULL)
875 goto error_put_sess; 913 goto error_put_sess;
876 914
@@ -893,11 +931,12 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
893 skb_reset_transport_header(skb); 931 skb_reset_transport_header(skb);
894 932
895 /* Build UDP header */ 933 /* Build UDP header */
896 inet = inet_sk(session->tunnel_sock); 934 inet = inet_sk(sk_tun);
935 udp_len = hdr_len + sizeof(ppph) + total_len;
897 uh = (struct udphdr *) skb->data; 936 uh = (struct udphdr *) skb->data;
898 uh->source = inet->sport; 937 uh->source = inet->sport;
899 uh->dest = inet->dport; 938 uh->dest = inet->dport;
900 uh->len = htons(hdr_len + sizeof(ppph) + total_len); 939 uh->len = htons(udp_len);
901 uh->check = 0; 940 uh->check = 0;
902 skb_put(skb, sizeof(struct udphdr)); 941 skb_put(skb, sizeof(struct udphdr));
903 942
@@ -919,8 +958,22 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
919 skb_put(skb, total_len); 958 skb_put(skb, total_len);
920 959
921 /* Calculate UDP checksum if configured to do so */ 960 /* Calculate UDP checksum if configured to do so */
922 if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT) 961 if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
923 csum = udp_csum_outgoing(sk, skb); 962 skb->ip_summed = CHECKSUM_NONE;
963 else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
964 skb->ip_summed = CHECKSUM_COMPLETE;
965 csum = skb_checksum(skb, 0, udp_len, 0);
966 uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
967 udp_len, IPPROTO_UDP, csum);
968 if (uh->check == 0)
969 uh->check = CSUM_MANGLED_0;
970 } else {
971 skb->ip_summed = CHECKSUM_PARTIAL;
972 skb->csum_start = skb_transport_header(skb) - skb->head;
973 skb->csum_offset = offsetof(struct udphdr, check);
974 uh->check = ~csum_tcpudp_magic(inet->saddr, inet->daddr,
975 udp_len, IPPROTO_UDP, 0);
976 }
924 977
925 /* Debug */ 978 /* Debug */
926 if (session->send_seq) 979 if (session->send_seq)
@@ -1008,13 +1061,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
1008 struct sock *sk = (struct sock *) chan->private; 1061 struct sock *sk = (struct sock *) chan->private;
1009 struct sock *sk_tun; 1062 struct sock *sk_tun;
1010 int hdr_len; 1063 int hdr_len;
1064 u16 udp_len;
1011 struct pppol2tp_session *session; 1065 struct pppol2tp_session *session;
1012 struct pppol2tp_tunnel *tunnel; 1066 struct pppol2tp_tunnel *tunnel;
1013 int rc; 1067 int rc;
1014 int headroom; 1068 int headroom;
1015 int data_len = skb->len; 1069 int data_len = skb->len;
1016 struct inet_sock *inet; 1070 struct inet_sock *inet;
1017 __wsum csum = 0; 1071 __wsum csum;
1018 struct udphdr *uh; 1072 struct udphdr *uh;
1019 unsigned int len; 1073 unsigned int len;
1020 int old_headroom; 1074 int old_headroom;
@@ -1060,6 +1114,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
1060 /* Setup L2TP header */ 1114 /* Setup L2TP header */
1061 pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len)); 1115 pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len));
1062 1116
1117 udp_len = sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len;
1118
1063 /* Setup UDP header */ 1119 /* Setup UDP header */
1064 inet = inet_sk(sk_tun); 1120 inet = inet_sk(sk_tun);
1065 __skb_push(skb, sizeof(*uh)); 1121 __skb_push(skb, sizeof(*uh));
@@ -1067,13 +1123,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
1067 uh = udp_hdr(skb); 1123 uh = udp_hdr(skb);
1068 uh->source = inet->sport; 1124 uh->source = inet->sport;
1069 uh->dest = inet->dport; 1125 uh->dest = inet->dport;
1070 uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len); 1126 uh->len = htons(udp_len);
1071 uh->check = 0; 1127 uh->check = 0;
1072 1128
1073 /* *BROKEN* Calculate UDP checksum if configured to do so */
1074 if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
1075 csum = udp_csum_outgoing(sk_tun, skb);
1076
1077 /* Debug */ 1129 /* Debug */
1078 if (session->send_seq) 1130 if (session->send_seq)
1079 PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG, 1131 PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
@@ -1108,6 +1160,24 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
1108 skb->dst = dst_clone(__sk_dst_get(sk_tun)); 1160 skb->dst = dst_clone(__sk_dst_get(sk_tun));
1109 pppol2tp_skb_set_owner_w(skb, sk_tun); 1161 pppol2tp_skb_set_owner_w(skb, sk_tun);
1110 1162
1163 /* Calculate UDP checksum if configured to do so */
1164 if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
1165 skb->ip_summed = CHECKSUM_NONE;
1166 else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
1167 skb->ip_summed = CHECKSUM_COMPLETE;
1168 csum = skb_checksum(skb, 0, udp_len, 0);
1169 uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
1170 udp_len, IPPROTO_UDP, csum);
1171 if (uh->check == 0)
1172 uh->check = CSUM_MANGLED_0;
1173 } else {
1174 skb->ip_summed = CHECKSUM_PARTIAL;
1175 skb->csum_start = skb_transport_header(skb) - skb->head;
1176 skb->csum_offset = offsetof(struct udphdr, check);
1177 uh->check = ~csum_tcpudp_magic(inet->saddr, inet->daddr,
1178 udp_len, IPPROTO_UDP, 0);
1179 }
1180
1111 /* Queue the packet to IP for output */ 1181 /* Queue the packet to IP for output */
1112 len = skb->len; 1182 len = skb->len;
1113 rc = ip_queue_xmit(skb, 1); 1183 rc = ip_queue_xmit(skb, 1);