From: Matt Corallo Date: Sun, 4 Apr 2021 15:54:59 +0000 (-0400) Subject: Update (and test) AST grammar based on feedback X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=d1468659faf993c7ccb398e3e35b8132bb208d83;p=flowspec-xdp Update (and test) AST grammar based on feedback --- diff --git a/genrules.py b/genrules.py index 40fc5c1..6de9382 100755 --- a/genrules.py +++ b/genrules.py @@ -12,13 +12,18 @@ IP_PROTO_TCP = 6 IP_PROTO_UDP = 17 class ASTAction(Enum): - OR = 1, - AND = 2, - NOT = 3, - EXPR = 4 + OR = 1 + AND = 2 + NOT = 3 + FALSE = 4 + TRUE = 5 + EXPR = 6 class ASTNode: def __init__(self, action, left, right=None): self.action = action + if action == ASTAction.FALSE or action == ASTAction.TRUE: + assert left is None and right is None + return self.left = left if right is None: assert action == ASTAction.EXPR or action == ASTAction.NOT @@ -32,23 +37,32 @@ class ASTNode: return "(" + self.left.write(expr_param, expr_param2) + ") && (" + self.right.write(expr_param, expr_param2) + ")" if self.action == ASTAction.NOT: return "!(" + self.left.write(expr_param, expr_param2) + ")" + if self.action == ASTAction.FALSE: + return "0" + if self.action == ASTAction.TRUE: + return "1" if self.action == ASTAction.EXPR: return self.left.write(expr_param, expr_param2) def parse_ast(expr, parse_expr): expr = expr.strip() - and_split = expr.split("&&", 1) + comma_split = expr.split(",", 1) or_split = expr.split("||", 1) - if len(and_split) > 1 and not "||" in and_split[0]: - return ASTNode(ASTAction.AND, parse_ast(and_split[0], parse_expr), parse_ast(and_split[1], parse_expr)) + if len(comma_split) > 1 and not "||" in comma_split[0]: + return ASTNode(ASTAction.OR, parse_ast(comma_split[0], parse_expr), parse_ast(comma_split[1], parse_expr)) if len(or_split) > 1: - assert not "&&" in or_split[0] + assert not "," in or_split[0] return ASTNode(ASTAction.OR, parse_ast(or_split[0], parse_expr), parse_ast(or_split[1], parse_expr)) - comma_split = expr.split(",", 1) - if len(comma_split) > 1: - return ASTNode(ASTAction.OR, parse_ast(comma_split[0], parse_expr), parse_ast(comma_split[1], parse_expr)) + and_split = expr.split("&&", 1) + if len(and_split) > 1: + return ASTNode(ASTAction.AND, parse_ast(and_split[0], parse_expr), parse_ast(and_split[1], parse_expr)) + + if expr.strip() == "true": + return ASTNode(ASTAction.TRUE, None) + if expr.strip() == "false": + return ASTNode(ASTAction.FALSE, None) if expr.startswith("!"): return ASTNode(ASTAction.NOT, parse_ast(expr[1:], parse_expr)) diff --git a/test.sh b/test.sh index a64c829..10ae086 100755 --- a/test.sh +++ b/test.sh @@ -41,6 +41,43 @@ 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 match-order tests... +# (43 && 42) || 4242 +echo "flow4 { port = 43 && 42, 4242; };" | ./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 + +# (43 && 42) || 4242 +echo "flow4 { port = 43 && 42 || 4242; };" | ./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 + +# 4242 || (42 && 43) +echo "flow4 { port = 4242, 42 && 43; };" | ./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 + +# (4242 && false) || (42 && 4242) +echo "flow4 { port = 4242 && false, 42 && 4242; };" | ./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 + +# (4242 && true) || (42 && 43) +echo "flow4 { port = 4242 && true, 42 && 43; };" | ./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 + +# 42 || true +echo "flow4 { port = 42, true; };" | ./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 { 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