summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2020-07-22 22:12:46 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2020-07-22 22:12:46 +0000
commit4e0a5f13fc1018d0d5f60616c32b863277937134 (patch)
tree00bf302e6b69c9c3b22f2e444bf0c510688dd38d
parent72c4ca6fac6546abfe7386b5c7a7f853ffda4317 (diff)
parent8345935471cf3f67be19de3eac51f9ab7d6a8ac5 (diff)
downloadnetd-4e0a5f13fc1018d0d5f60616c32b863277937134.tar.gz
Change-Id: I844f2e7744fc71755d0d995236270b57cec58c81
-rw-r--r--bpf_progs/clatd.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/bpf_progs/clatd.c b/bpf_progs/clatd.c
index 102ecd96..e7586928 100644
--- a/bpf_progs/clatd.c
+++ b/bpf_progs/clatd.c
@@ -26,6 +26,10 @@
#include <stdbool.h>
#include <stdint.h>
+// bionic kernel uapi linux/udp.h header is munged...
+#define __kernel_udphdr udphdr
+#include <linux/udp.h>
+
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
#include "netdbpf/bpf_shared.h"
@@ -226,9 +230,18 @@ int sched_cls_egress_clat_rawip(struct __sk_buff* skb) {
switch (ip4->protocol) {
case IPPROTO_TCP: // For TCP & UDP the checksum neutrality of the chosen IPv6
- case IPPROTO_UDP: // address means there is no need to update their checksums.
- case IPPROTO_GRE: // We do not need to bother looking at GRE/ESP headers,
- case IPPROTO_ESP: // since there is never a checksum to update.
+ case IPPROTO_GRE: // address means there is no need to update their checksums.
+ case IPPROTO_ESP: // We do not need to bother looking at GRE/ESP headers,
+ break; // since there is never a checksum to update.
+
+ case IPPROTO_UDP: // See above comment, but must also have UDP header...
+ if (data + sizeof(*ip4) + sizeof(struct udphdr) > data_end) return TC_ACT_OK;
+ const struct udphdr* uh = (const struct udphdr*)(ip4 + 1);
+ // If IPv4/UDP checksum is 0 then fallback to clatd so it can calculate the
+ // checksum. Otherwise the network or more likely the NAT64 gateway might
+ // drop the packet because in most cases IPv6/UDP packets with a zero checksum
+ // are invalid. See RFC 6935. TODO: calculate checksum via bpf_csum_diff()
+ if (!uh->check) return TC_ACT_OK;
break;
default: // do not know how to handle anything else