Skip to content

Commit

Permalink
l2tp: Remove UDP checksum verification
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Tom Herbert authored and David S. Miller committed May 9, 2014
1 parent 0a80966 commit 58d6085
Showing 1 changed file with 1 addition and 56 deletions.
57 changes: 1 addition & 56 deletions net/l2tp/l2tp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,52 +495,6 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)
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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit 58d6085

Please sign in to comment.