l2tp: Remove UDP checksum verification
authorTom Herbert <therbert@google.com>
Wed, 7 May 2014 23:52:48 +0000 (16:52 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 9 May 2014 03:47:50 +0000 (23:47 -0400)
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>
net/l2tp/l2tp_core.c

index a4e37d7158dcca42455a04eaf0460a48e39242fd..aa1a9d44c107fd0bd446de521adbc2f2d16328a9 100644 (file)
@@ -495,52 +495,6 @@ out:
        spin_unlock_bh(&session->reorder_q.lock);
 }
 
-static inline int l2tp_verify_udp_checksum(struct sock *sk,
-                                          struct sk_buff *skb)
-{
-       struct udphdr *uh = udp_hdr(skb);
-       u16 ulen = ntohs(uh->len);
-       __wsum psum;
-
-       if (sk->sk_no_check || skb_csum_unnecessary(skb))
-               return 0;
-
-#if IS_ENABLED(CONFIG_IPV6)
-       if (sk->sk_family == PF_INET6 && !l2tp_tunnel(sk)->v4mapped) {
-               if (!uh->check) {
-                       LIMIT_NETDEBUG(KERN_INFO "L2TP: IPv6: checksum is 0\n");
-                       return 1;
-               }
-               if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
-                   !csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-                                    &ipv6_hdr(skb)->daddr, ulen,
-                                    IPPROTO_UDP, skb->csum)) {
-                       skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       return 0;
-               }
-               skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
-                                                        &ipv6_hdr(skb)->daddr,
-                                                        skb->len, IPPROTO_UDP,
-                                                        0));
-       } else
-#endif
-       {
-               struct inet_sock *inet;
-               if (!uh->check)
-                       return 0;
-               inet = inet_sk(sk);
-               psum = csum_tcpudp_nofold(inet->inet_saddr, inet->inet_daddr,
-                                         ulen, IPPROTO_UDP, 0);
-
-               if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
-                   !csum_fold(csum_add(psum, skb->csum)))
-                       return 0;
-               skb->csum = psum;
-       }
-
-       return __skb_checksum_complete(skb);
-}
-
 static int l2tp_seq_check_rx_window(struct l2tp_session *session, u32 nr)
 {
        u32 nws;
@@ -895,8 +849,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
        u16 version;
        int length;
 
-       if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb))
-               goto discard_bad_csum;
+       /* UDP has verifed checksum */
 
        /* UDP always verifies the packet length. */
        __skb_pull(skb, sizeof(struct udphdr));
@@ -979,14 +932,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 
        return 0;
 
-discard_bad_csum:
-       LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
-       UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0);
-       atomic_long_inc(&tunnel->stats.rx_errors);
-       kfree_skb(skb);
-
-       return 0;
-
 error:
        /* Put UDP header back */
        __skb_push(skb, sizeof(struct udphdr));