aboutsummaryrefslogtreecommitdiffstats
path: root/net/l2tp/l2tp_core.c
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-05-07 19:52:48 -0400
committerDavid S. Miller <davem@davemloft.net>2014-05-08 23:47:50 -0400
commit58d6085c14f5db61c092c90b59813397bc771417 (patch)
tree3e3a8bf63676f025cca73ac50fd7e3645d7b138e /net/l2tp/l2tp_core.c
parent0a80966b1043c3e2dc684140f155a3fded308660 (diff)
l2tp: Remove UDP checksum verification
Validating the UDP checksum is now done in UDP before handing packets to the encapsulation layer. Note that this also eliminates the "feature" where L2TP can ignore a non-zero UDP checksum (doing this was contrary to RFC 1122). Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp/l2tp_core.c')
-rw-r--r--net/l2tp/l2tp_core.c57
1 files changed, 1 insertions, 56 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index a4e37d7158dc..aa1a9d44c107 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -495,52 +495,6 @@ out:
495 spin_unlock_bh(&session->reorder_q.lock); 495 spin_unlock_bh(&session->reorder_q.lock);
496} 496}
497 497
498static inline int l2tp_verify_udp_checksum(struct sock *sk,
499 struct sk_buff *skb)
500{
501 struct udphdr *uh = udp_hdr(skb);
502 u16 ulen = ntohs(uh->len);
503 __wsum psum;
504
505 if (sk->sk_no_check || skb_csum_unnecessary(skb))
506 return 0;
507
508#if IS_ENABLED(CONFIG_IPV6)
509 if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) {
510 if (!uh->check) {
511 LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
512 return 1;
513 }
514 if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
515 !csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
516 &ipv6_hdr(skb)->daddr, ulen,
517 IPPROTO_UDP, skb->csum)) {
518 skb->ip_summed = CHECKSUM_UNNECESSARY;
519 return 0;
520 }
521 skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
522 &ipv6_hdr(skb)->daddr,
523 skb->len, IPPROTO_UDP,
524 0));
525 } else
526#endif
527 {
528 struct inet_sock *inet;
529 if (!uh->check)
530 return 0;
531 inet = inet_sk(sk);
532 psum = csum_tcpudp_nofold(inet->inet_saddr, inet->inet_daddr,
533 ulen, IPPROTO_UDP, 0);
534
535 if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
536 !csum_fold(csum_add(psum, skb->csum)))
537 return 0;
538 skb->csum = psum;
539 }
540
541 return __skb_checksum_complete(skb);
542}
543
544static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr) 498static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
545{ 499{
546 u32 nws; 500 u32 nws;
@@ -895,8 +849,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
895 u16 version; 849 u16 version;
896 int length; 850 int length;
897 851
898 if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb)) 852 /* UDP has verifed checksum */
899 goto discard_bad_csum;
900 853
901 /* UDP always verifies the packet length. */ 854 /* UDP always verifies the packet length. */
902 __skb_pull(skb, sizeof(struct udphdr)); 855 __skb_pull(skb, sizeof(struct udphdr));
@@ -979,14 +932,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
979 932
980 return 0; 933 return 0;
981 934
982discard_bad_csum:
983 LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
984 UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0);
985 atomic_long_inc(&tunnel->stats.rx_errors);
986 kfree_skb(skb);
987
988 return 0;
989
990error: 935error:
991 /* Put UDP header back */ 936 /* Put UDP header back */
992 __skb_push(skb, sizeof(struct udphdr)); 937 __skb_push(skb, sizeof(struct udphdr));