]> git.proxmox.com Git - mirror_ovs.git/commitdiff
datapath: Fix checksum calculation when modifying ICMPv6 packets.
authorJesse Gross <jesse@nicira.com>
Fri, 15 Aug 2014 18:01:54 +0000 (11:01 -0700)
committerJesse Gross <jesse@nicira.com>
Fri, 29 Aug 2014 20:20:27 +0000 (13:20 -0700)
The checksum of ICMPv6 packets uses the IP pseudoheader as part of
the calculation, unlike ICMP in IPv4. This was not implemented,
which means that modifying the IP addresses of an ICMPv6 packet
would cause the checksum to no longer be correct as the psuedoheader
did not match.

Reported-by: Neal Shrader <icosahedral@gmail.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Pravin B Shelar <pshelar@nicira.com>
datapath/actions.c
lib/packets.c

index 7f2555300d04a9dc4947f23fa63f375cff8926aa..8fb4ad73940ada9e4c957c8cb53cc735154e7558 100644 (file)
@@ -383,11 +383,11 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
 {
        int transport_len = skb->len - skb_transport_offset(skb);
 
-       if (l4_proto == IPPROTO_TCP) {
+       if (l4_proto == NEXTHDR_TCP) {
                if (likely(transport_len >= sizeof(struct tcphdr)))
                        inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
                                                  addr, new_addr, 1);
-       } else if (l4_proto == IPPROTO_UDP) {
+       } else if (l4_proto == NEXTHDR_UDP) {
                if (likely(transport_len >= sizeof(struct udphdr))) {
                        struct udphdr *uh = udp_hdr(skb);
 
@@ -398,6 +398,10 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
                                        uh->check = CSUM_MANGLED_0;
                        }
                }
+       } else if (l4_proto == NEXTHDR_ICMP) {
+               if (likely(transport_len >= sizeof(struct icmp6hdr)))
+                       inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum,
+                                                 skb, addr, new_addr, 1);
        }
 }
 
index 6244c3f5fac85049a7788a32fb83639802ebb8ae..ace7d8ed51235608b471d283359da631e466879c 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/ip6.h>
+#include <netinet/icmp6.h>
 #include <stdlib.h>
 #include "byte-order.h"
 #include "csum.h"
@@ -714,6 +715,10 @@ packet_update_csum128(struct ofpbuf *packet, uint8_t proto,
                 uh->udp_csum = htons(0xffff);
             }
         }
+    } else if (proto == IPPROTO_ICMPV6 && l4_size >= sizeof(struct icmp6_hdr)) {
+        struct icmp6_hdr *icmp = ofpbuf_l4(packet);
+
+        icmp->icmp6_cksum = recalc_csum128(icmp->icmp6_cksum, addr, new_addr);
     }
 }