diff options
author | Tom Herbert <therbert@google.com> | 2014-05-23 11:47:32 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-23 16:28:53 -0400 |
commit | 1c19448c9ba6545b80ded18488a64a7f3d8e6998 (patch) | |
tree | 7323d68eaf334d9040a9d5a709c56caf2a7aaeeb /net/ipv6/udp.c | |
parent | 28448b80456feafe07e2d05b6363b00f61f6171e (diff) |
net: Make enabling of zero UDP6 csums more restrictive
RFC 6935 permits zero checksums to be used in IPv6 however this is
recommended only for certain tunnel protocols, it does not make
checksums completely optional like they are in IPv4.
This patch restricts the use of IPv6 zero checksums that was previously
intoduced. no_check6_tx and no_check6_rx have been added to control
the use of checksums in UDP6 RX and TX path. The normal
sk_no_check_{rx,tx} settings are not used (this avoids ambiguity when
dealing with a dual stack socket).
A helper function has been added (udp_set_no_check6) which can be
called by tunnel impelmentations to all zero checksums (send on the
socket, and accept them as valid).
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r-- | net/ipv6/udp.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b8db453133aa..60325236446a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -794,10 +794,10 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
794 | dif = inet6_iif(skb); | 794 | dif = inet6_iif(skb); |
795 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 795 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
796 | while (sk) { | 796 | while (sk) { |
797 | /* If zero checksum and sk_no_check is not on for | 797 | /* If zero checksum and no_check is not on for |
798 | * the socket then skip it. | 798 | * the socket then skip it. |
799 | */ | 799 | */ |
800 | if (uh->check || sk->sk_no_check_rx) | 800 | if (uh->check || udp_sk(sk)->no_check6_rx) |
801 | stack[count++] = sk; | 801 | stack[count++] = sk; |
802 | 802 | ||
803 | sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, | 803 | sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, |
@@ -887,7 +887,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
887 | if (sk != NULL) { | 887 | if (sk != NULL) { |
888 | int ret; | 888 | int ret; |
889 | 889 | ||
890 | if (!uh->check && !sk->sk_no_check_rx) { | 890 | if (!uh->check && !udp_sk(sk)->no_check6_rx) { |
891 | sock_put(sk); | 891 | sock_put(sk); |
892 | udp6_csum_zero_error(skb); | 892 | udp6_csum_zero_error(skb); |
893 | goto csum_error; | 893 | goto csum_error; |
@@ -1037,7 +1037,7 @@ static int udp_v6_push_pending_frames(struct sock *sk) | |||
1037 | 1037 | ||
1038 | if (is_udplite) | 1038 | if (is_udplite) |
1039 | csum = udplite_csum_outgoing(sk, skb); | 1039 | csum = udplite_csum_outgoing(sk, skb); |
1040 | else if (sk->sk_no_check_tx) { /* UDP csum disabled */ | 1040 | else if (up->no_check6_tx) { /* UDP csum disabled */ |
1041 | skb->ip_summed = CHECKSUM_NONE; | 1041 | skb->ip_summed = CHECKSUM_NONE; |
1042 | goto send; | 1042 | goto send; |
1043 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ | 1043 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |