Make v6 frag parsing optional
authorMatt Corallo <git@bluematt.me>
Sun, 4 Apr 2021 00:00:51 +0000 (20:00 -0400)
committerMatt Corallo <git@bluematt.me>
Sun, 4 Apr 2021 01:08:20 +0000 (21:08 -0400)
genrules.py
test.sh
xdp.c

index 82b8d8225cc0ab34161397e1cf17691df44f4e0b..6c8411b03ec3962a8100e3aa585e34fb3197ba04 100755 (executable)
@@ -238,6 +238,7 @@ if (!( {ast.write("((((uint32_t)(ip6->flow_lbl[0] & 0xf)) << 2*8) | (((uint32_t)
 with open("rules.h", "w") as out:
     parse = argparse.ArgumentParser()
     parse.add_argument("--ihl", dest="ihl", required=True, choices=["drop-options","accept-options","parse-options"])
+    parse.add_argument("--v6frag", dest="v6frag", required=True, choices=["drop-frags","ignore","parse-frags","ignore-parse-if-rule"])
     parse.add_argument("--8021q", dest="vlan", required=True, choices=["drop-vlan","accept-vlan","parse-vlan"])
     parse.add_argument("--require-8021q", dest="vlan_tag")
     args = parse.parse_args(sys.argv[1:])
@@ -249,6 +250,13 @@ with open("rules.h", "w") as out:
     elif args.ihl == "parse-options":
         out.write("#define PARSE_IHL PARSE\n")
 
+    if args.v6frag == "drop-frags":
+        out.write("#define PARSE_V6_FRAG XDP_DROP\n")
+    elif args.v6frag == "ignore":
+        pass
+    elif args.v6frag == "parse-frags":
+        out.write("#define PARSE_V6_FRAG PARSE\n")
+
     if args.vlan == "drop-vlan":
         out.write("#define PARSE_8021Q XDP_DROP\n")
     elif args.vlan == "accept-vlan":
@@ -263,6 +271,7 @@ with open("rules.h", "w") as out:
 
     use_v4 = False
     use_v6 = False
+    use_v6_frags = False
 
     out.write("#define RULES \\\n")
 
@@ -318,6 +327,8 @@ with open("rules.h", "w") as out:
             elif step.strip().startswith("label"):
                 write_rule(flow_label_to_rule(step.strip()[6:]))
             elif step.strip().startswith("fragment"):
+                if proto == 6:
+                    use_v6_frags = True
                 write_rule(fragment_to_rule(proto, step.strip()[9:]))
             elif step.strip() == "":
                 pass
@@ -331,3 +342,6 @@ with open("rules.h", "w") as out:
         out.write("#define NEED_V4_PARSE\n")
     if use_v6:
         out.write("#define NEED_V6_PARSE\n")
+    if args.v6frag == "ignore-parse-if-rule":
+        if use_v6_frags:
+            out.write("#define PARSE_V6_FRAG PARSE\n")
diff --git a/test.sh b/test.sh
index f25fffa482fb6a9c0ba6c341461c0ccaf8e42da8..a64c82911cbc336657f2e5e08d653f8d0debc0e1 100755 (executable)
--- a/test.sh
+++ b/test.sh
@@ -15,33 +15,33 @@ TEST_PKT='#define TEST \
 "\xb5\xc3\xa9\xa6\x21\x14\xc7\xd9\x71\x07"'
 
 # Test all the things...
-echo "flow4 { src 72.229.104.206/32; dst 103.99.170.10/32; proto = 17; sport = 56733; dport = 4242; length = 140; dscp 0/0xff; fragment !dont_fragment && !is_fragment && !first_fragment && !last_fragment };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow4 { src 72.229.104.206/32; dst 103.99.170.10/32; proto = 17; sport = 56733; dport = 4242; length = 140; dscp 0/0xff; fragment !dont_fragment && !is_fragment && !first_fragment && !last_fragment };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { port = 4242; icmp code = 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow4 { port = 4242; icmp code = 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
 # Some port tests...
-echo "flow4 { port = 4242 && = 56733; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow4 { port = 4242 && = 56733; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { port = 4242 || 1; sport = 56733 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow4 { port = 4242 || 1; sport = 56733 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { port = 4242 && 1 };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow4 { port = 4242 && 1 };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow4 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
@@ -55,17 +55,17 @@ TEST_PKT='#define TEST \
 "\x75\xde\xeb\x22\xd6\x80"'
 
 # Some v6 TCP tests...
-echo "flow6 { src 2a01:4f8:130:71d2::2/128; dst 2620:6e:a000:2001::6/128; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { src 2a01:4f8:130:71d2::2/128; dst 2620:6e:a000:2001::6/128; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 0:4f8:130:71d2::2/128 offset 16; dst 0:0:a000:2001::/64 offset 32; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { src 0:4f8:130:71d2::2/128 offset 16; dst 0:0:a000:2001::/64 offset 32; next header 6; port 8333 && 49778; tcp flags 0x010/0xfff;};" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
@@ -80,37 +80,37 @@ TEST_PKT='#define TEST \
 "\x32\x33\x34\x35\x36\x37"'
 
 # ICMP and VLAN tests
-echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan
+echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { icmp type 8; icmp code > 0; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan
+echo "flow4 { icmp type 8; icmp code > 0; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { icmp type 9; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan
+echo "flow4 { icmp type 9; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=3
+echo "flow4 { src 10.0.0.0/8; dst 209.250.0.0/16; proto = 1; icmp type 8; icmp code >= 0; length < 100; fragment dont_fragment; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=3 --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=4
+echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=accept-options --8021q=parse-vlan --require-8021q=4 --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --require-8021q=3
+echo "flow4 { src 0.0.0.0/32; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --require-8021q=3 --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow4 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan
+echo "flow4 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=parse-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
@@ -138,27 +138,27 @@ TEST_PKT='#define TEST \
 "\x00\x00\x00\x00\x00\x00"'
 
 # ICMPv6 tests
-echo "flow6 { icmp type 129; icmp code 0; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { icmp type 129; icmp code 0; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { icmp code != 0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { tcp flags 0x0/0x0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { tcp flags 0x0/0x0; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { port 42; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { fragment is_fragment || first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { fragment is_fragment || first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=drop-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
@@ -176,27 +176,43 @@ TEST_PKT='#define TEST \
 
 # Last frag ICMPv6 tests
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && !first_fragment && last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && !first_fragment && last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || first_fragment || !last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
 #TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
+# Test the --v6frag options (ignore-parse-if-rule is tested below)
+echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_PASS" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
+echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=drop-frags
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_DROP" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
+echo "flow6 { tcp flags 42/42; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_PASS" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
 TEST_PKT='#define TEST \
 "\x00\x17\x10\x95\xe8\x96\x00\x0d\xb9\x50\x11\x4c\x86\xdd\x60\x0a" \
 "\x18\xa7\x04\xd8\x2c\x3e\x26\x20\x00\x6e\xa0\x07\x02\x33\x00\x00" \
@@ -282,34 +298,50 @@ TEST_PKT='#define TEST \
 
 # First frag ICMPv6 tests
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || !first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment !is_fragment || !first_fragment || last_fragment; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
-echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; icmp code 0; icmp type 128 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { src 2620:6e:a007:233::1/128; dst 2001:470:0:503::2/128; fragment is_fragment && first_fragment && !last_fragment; icmp code 0; icmp type 128 };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
 #TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan
+echo "flow6 { next header 44; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=parse-frags
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_DROP" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
 
 #TODO Is nextheader frag correct to match on here? Should we support matching on any nexthdr?
-echo "flow6 { next header 58; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan
+echo "flow6 { next header 58; };" | ./genrules.py --ihl=drop-options --8021q=drop-vlan --v6frag=parse-frags
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_PASS" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
+# Test accept-parse-if-rule
+echo "flow6 { icmp code 0; icmp type 128; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_PASS" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
+echo "flow6 { icmp code 0; icmp type 128; fragment is_fragment; };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
+echo "$TEST_PKT" >> rules.h
+echo "#define TEST_EXP XDP_DROP" >> rules.h
+clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
+
+echo "flow6 { icmp code 0; icmp type 128; fragment !is_fragment };" | ./genrules.py --ihl=accept-options --8021q=accept-vlan --v6frag=ignore-parse-if-rule
 echo "$TEST_PKT" >> rules.h
 echo "#define TEST_EXP XDP_PASS" >> rules.h
 clang -std=c99 -fsanitize=address -pedantic -Wall -Wextra -Wno-pointer-arith -Wno-unused-variable -O0 -g xdp.c -o xdp && ./xdp
diff --git a/xdp.c b/xdp.c
index b93b16936bdfdde7f72d6e84277a95cda8e501cf..10ed78b2a22411988661a367de4a87fc73817bef 100644 (file)
--- a/xdp.c
+++ b/xdp.c
@@ -221,16 +221,21 @@ int xdp_drop_prog(struct xdp_md *ctx)
 
                l4hdr = pktdata + 40;
 
-               uint8_t v6nexthdr;
+               uint8_t v6nexthdr = ip6->nexthdr;
+#ifdef PARSE_V6_FRAG
+#if PARSE_V6_FRAG == PARSE
                if (ip6->nexthdr == IP6_PROTO_FRAG) {
                        if (unlikely(l4hdr + sizeof(struct ip6_fraghdr) > data_end))
                                return XDP_DROP;
                        frag6 = (struct ip6_fraghdr*) l4hdr;
                        l4hdr = l4hdr + sizeof(struct ip6_fraghdr);
                        v6nexthdr = frag6->nexthdr;
-               } else {
-                       v6nexthdr = ip6->nexthdr;
+#else
+               if (unlikely(ip6->nexthdr == IP6_PROTO_FRAG)) {
+                       return PARSE_V6_FRAG;
+#endif
                }
+#endif
 
                if (v6nexthdr == IP_PROTO_TCP) {
                        if (unlikely(l4hdr + sizeof(struct tcphdr) > data_end))