19f44a47fSAlexander V. Chernikovimport errno 29f44a47fSAlexander V. Chernikovimport json 39f44a47fSAlexander V. Chernikovimport os 49f44a47fSAlexander V. Chernikovimport socket 59f44a47fSAlexander V. Chernikovimport struct 69f44a47fSAlexander V. Chernikovimport subprocess 79f44a47fSAlexander V. Chernikovimport sys 89f44a47fSAlexander V. Chernikovfrom ctypes import c_byte 99f44a47fSAlexander V. Chernikovfrom ctypes import c_char 109f44a47fSAlexander V. Chernikovfrom ctypes import c_int 119f44a47fSAlexander V. Chernikovfrom ctypes import c_long 129f44a47fSAlexander V. Chernikovfrom ctypes import c_uint32 139f44a47fSAlexander V. Chernikovfrom ctypes import c_uint8 149f44a47fSAlexander V. Chernikovfrom ctypes import c_ulong 159f44a47fSAlexander V. Chernikovfrom ctypes import c_ushort 169f44a47fSAlexander V. Chernikovfrom ctypes import sizeof 179f44a47fSAlexander V. Chernikovfrom ctypes import Structure 189f44a47fSAlexander V. Chernikovfrom enum import Enum 199f44a47fSAlexander V. Chernikovfrom typing import Any 209f44a47fSAlexander V. Chernikovfrom typing import Dict 219f44a47fSAlexander V. Chernikovfrom typing import List 229f44a47fSAlexander V. Chernikovfrom typing import NamedTuple 239f44a47fSAlexander V. Chernikovfrom typing import Optional 249f44a47fSAlexander V. Chernikovfrom typing import Union 259f44a47fSAlexander V. Chernikov 269f44a47fSAlexander V. Chernikovimport pytest 279f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import Icmp6RejectCode 289f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import IcmpRejectCode 299f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import Insn 309f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnComment 319f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnEmpty 329f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnIp 339f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnIp6 349f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnPorts 359f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnProb 369f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnProto 379f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnReject 389f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import InsnTable 399f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.insns import IpFwOpcode 409f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import CTlv 419f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import CTlvRule 429f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import IpFwTlvType 439f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import IpFwXRule 449f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import NTlv 459f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import Op3CmdType 469f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ioctl import RawRule 479f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.ipfw import DebugIoReader 489f44a47fSAlexander V. Chernikovfrom atf_python.sys.netpfil.ipfw.utils import enum_from_int 499f44a47fSAlexander V. Chernikovfrom atf_python.utils import BaseTest 509f44a47fSAlexander V. Chernikov 519f44a47fSAlexander V. Chernikov 529f44a47fSAlexander V. ChernikovIPFW_PATH = "/sbin/ipfw" 539f44a47fSAlexander V. Chernikov 549f44a47fSAlexander V. Chernikov 559f44a47fSAlexander V. Chernikovdef differ(w_obj, g_obj, w_stack=[], g_stack=[]): 569f44a47fSAlexander V. Chernikov if bytes(w_obj) == bytes(g_obj): 579f44a47fSAlexander V. Chernikov return True 589f44a47fSAlexander V. Chernikov num_objects = 0 599f44a47fSAlexander V. Chernikov for i, w_child in enumerate(w_obj.obj_list): 60*7e1ec25cSAlexander V. Chernikov if i >= len(g_obj.obj_list): 619f44a47fSAlexander V. Chernikov print("MISSING object from chain {}".format(" / ".join(w_stack))) 629f44a47fSAlexander V. Chernikov w_child.print_obj() 639f44a47fSAlexander V. Chernikov print("==========================") 649f44a47fSAlexander V. Chernikov return False 659f44a47fSAlexander V. Chernikov g_child = g_obj.obj_list[i] 669f44a47fSAlexander V. Chernikov if bytes(w_child) == bytes(g_child): 679f44a47fSAlexander V. Chernikov num_objects += 1 689f44a47fSAlexander V. Chernikov continue 699f44a47fSAlexander V. Chernikov w_stack.append(w_obj.obj_name) 709f44a47fSAlexander V. Chernikov g_stack.append(g_obj.obj_name) 719f44a47fSAlexander V. Chernikov if not differ(w_child, g_child, w_stack, g_stack): 729f44a47fSAlexander V. Chernikov return False 739f44a47fSAlexander V. Chernikov break 749f44a47fSAlexander V. Chernikov if num_objects == len(w_obj.obj_list) and num_objects < len(g_obj.obj_list): 759f44a47fSAlexander V. Chernikov g_child = g_obj.obj_list[num_objects] 769f44a47fSAlexander V. Chernikov print("EXTRA object from chain {}".format(" / ".join(g_stack))) 779f44a47fSAlexander V. Chernikov g_child.print_obj() 789f44a47fSAlexander V. Chernikov print("==========================") 799f44a47fSAlexander V. Chernikov return False 809f44a47fSAlexander V. Chernikov print("OBJECTS DIFFER") 819f44a47fSAlexander V. Chernikov print("WANTED CHAIN: {}".format(" / ".join(w_stack))) 829f44a47fSAlexander V. Chernikov w_obj.print_obj() 839f44a47fSAlexander V. Chernikov w_obj.print_obj_hex() 849f44a47fSAlexander V. Chernikov print("==========================") 859f44a47fSAlexander V. Chernikov print("GOT CHAIN: {}".format(" / ".join(g_stack))) 869f44a47fSAlexander V. Chernikov g_obj.print_obj() 879f44a47fSAlexander V. Chernikov g_obj.print_obj_hex() 889f44a47fSAlexander V. Chernikov print("==========================") 899f44a47fSAlexander V. Chernikov return False 909f44a47fSAlexander V. Chernikov 919f44a47fSAlexander V. Chernikov 929f44a47fSAlexander V. Chernikovclass TestAddRule(BaseTest): 939f44a47fSAlexander V. Chernikov def compile_rule(self, out): 949f44a47fSAlexander V. Chernikov tlvs = [] 959f44a47fSAlexander V. Chernikov if "objs" in out: 969f44a47fSAlexander V. Chernikov tlvs.append(CTlv(IpFwTlvType.IPFW_TLV_TBLNAME_LIST, out["objs"])) 979f44a47fSAlexander V. Chernikov rule = RawRule(rulenum=out.get("rulenum", 0), obj_list=out["insns"]) 989f44a47fSAlexander V. Chernikov tlvs.append(CTlvRule(obj_list=[rule])) 999f44a47fSAlexander V. Chernikov return IpFwXRule(Op3CmdType.IP_FW_XADD, tlvs) 1009f44a47fSAlexander V. Chernikov 1019f44a47fSAlexander V. Chernikov def verify_rule(self, in_data: str, out_data): 1029f44a47fSAlexander V. Chernikov # Prepare the desired output 1039f44a47fSAlexander V. Chernikov expected = self.compile_rule(out_data) 1049f44a47fSAlexander V. Chernikov 1059f44a47fSAlexander V. Chernikov reader = DebugIoReader(IPFW_PATH) 1069f44a47fSAlexander V. Chernikov ioctls = reader.get_records(in_data) 1079f44a47fSAlexander V. Chernikov assert len(ioctls) == 1 # Only 1 ioctl request expected 1089f44a47fSAlexander V. Chernikov got = ioctls[0] 1099f44a47fSAlexander V. Chernikov 1109f44a47fSAlexander V. Chernikov if not differ(expected, got): 1119f44a47fSAlexander V. Chernikov print("=> CMD: {}".format(in_data)) 1129f44a47fSAlexander V. Chernikov print("=> WANTED:") 1139f44a47fSAlexander V. Chernikov expected.print_obj() 1149f44a47fSAlexander V. Chernikov print("==========================") 1159f44a47fSAlexander V. Chernikov print("=> GOT:") 1169f44a47fSAlexander V. Chernikov got.print_obj() 1179f44a47fSAlexander V. Chernikov print("==========================") 1189f44a47fSAlexander V. Chernikov assert bytes(got) == bytes(expected) 1199f44a47fSAlexander V. Chernikov 1209f44a47fSAlexander V. Chernikov @pytest.mark.parametrize( 1219f44a47fSAlexander V. Chernikov "rule", 1229f44a47fSAlexander V. Chernikov [ 1239f44a47fSAlexander V. Chernikov pytest.param( 1249f44a47fSAlexander V. Chernikov { 1259f44a47fSAlexander V. Chernikov "in": "add 200 allow ip from any to any", 1269f44a47fSAlexander V. Chernikov "out": { 1279f44a47fSAlexander V. Chernikov "insns": [InsnEmpty(IpFwOpcode.O_ACCEPT)], 1289f44a47fSAlexander V. Chernikov "rulenum": 200, 1299f44a47fSAlexander V. Chernikov }, 1309f44a47fSAlexander V. Chernikov }, 1319f44a47fSAlexander V. Chernikov id="test_rulenum", 1329f44a47fSAlexander V. Chernikov ), 1339f44a47fSAlexander V. Chernikov pytest.param( 1349f44a47fSAlexander V. Chernikov { 1359f44a47fSAlexander V. Chernikov "in": "add allow ip from { 1.2.3.4 or 2.3.4.5 } to any", 1369f44a47fSAlexander V. Chernikov "out": { 1379f44a47fSAlexander V. Chernikov "insns": [ 1389f44a47fSAlexander V. Chernikov InsnIp(IpFwOpcode.O_IP_SRC, ip="1.2.3.4", is_or=True), 1399f44a47fSAlexander V. Chernikov InsnIp(IpFwOpcode.O_IP_SRC, ip="2.3.4.5"), 1409f44a47fSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 1419f44a47fSAlexander V. Chernikov ], 1429f44a47fSAlexander V. Chernikov }, 1439f44a47fSAlexander V. Chernikov }, 1449f44a47fSAlexander V. Chernikov id="test_or", 1459f44a47fSAlexander V. Chernikov ), 1469f44a47fSAlexander V. Chernikov pytest.param( 1479f44a47fSAlexander V. Chernikov { 1489f44a47fSAlexander V. Chernikov "in": "add allow ip from table(AAA) to table(BBB)", 1499f44a47fSAlexander V. Chernikov "out": { 1509f44a47fSAlexander V. Chernikov "objs": [ 1519f44a47fSAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=1, name="AAA"), 1529f44a47fSAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_TBL_NAME, idx=2, name="BBB"), 1539f44a47fSAlexander V. Chernikov ], 1549f44a47fSAlexander V. Chernikov "insns": [ 1559f44a47fSAlexander V. Chernikov InsnTable(IpFwOpcode.O_IP_SRC_LOOKUP, arg1=1), 1569f44a47fSAlexander V. Chernikov InsnTable(IpFwOpcode.O_IP_DST_LOOKUP, arg1=2), 1579f44a47fSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 1589f44a47fSAlexander V. Chernikov ], 1599f44a47fSAlexander V. Chernikov }, 1609f44a47fSAlexander V. Chernikov }, 1619f44a47fSAlexander V. Chernikov id="test_tables", 1629f44a47fSAlexander V. Chernikov ), 1639f44a47fSAlexander V. Chernikov pytest.param( 1649f44a47fSAlexander V. Chernikov { 1659f44a47fSAlexander V. Chernikov "in": "add allow ip from any to 1.2.3.4 // test comment", 1669f44a47fSAlexander V. Chernikov "out": { 1679f44a47fSAlexander V. Chernikov "insns": [ 1689f44a47fSAlexander V. Chernikov InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"), 1699f44a47fSAlexander V. Chernikov InsnComment(comment="test comment"), 1709f44a47fSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 1719f44a47fSAlexander V. Chernikov ], 1729f44a47fSAlexander V. Chernikov }, 1739f44a47fSAlexander V. Chernikov }, 1749f44a47fSAlexander V. Chernikov id="test_comment", 1759f44a47fSAlexander V. Chernikov ), 17684b41342SAlexander V. Chernikov pytest.param( 17784b41342SAlexander V. Chernikov { 17884b41342SAlexander V. Chernikov "in": "add tcp-setmss 123 ip from any to 1.2.3.4", 17984b41342SAlexander V. Chernikov "out": { 18084b41342SAlexander V. Chernikov "objs": [ 18184b41342SAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="tcp-setmss"), 18284b41342SAlexander V. Chernikov ], 18384b41342SAlexander V. Chernikov "insns": [ 18484b41342SAlexander V. Chernikov InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"), 18584b41342SAlexander V. Chernikov Insn(IpFwOpcode.O_EXTERNAL_ACTION, arg1=1), 18684b41342SAlexander V. Chernikov Insn(IpFwOpcode.O_EXTERNAL_DATA, arg1=123), 18784b41342SAlexander V. Chernikov ], 18884b41342SAlexander V. Chernikov }, 18984b41342SAlexander V. Chernikov }, 19084b41342SAlexander V. Chernikov id="test_eaction_tcp-setmss", 19184b41342SAlexander V. Chernikov ), 19284b41342SAlexander V. Chernikov pytest.param( 19384b41342SAlexander V. Chernikov { 19484b41342SAlexander V. Chernikov "in": "add eaction ntpv6 AAA ip from any to 1.2.3.4", 19584b41342SAlexander V. Chernikov "out": { 19684b41342SAlexander V. Chernikov "objs": [ 19784b41342SAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_EACTION, idx=1, name="ntpv6"), 19884b41342SAlexander V. Chernikov NTlv(0, idx=2, name="AAA"), 19984b41342SAlexander V. Chernikov ], 20084b41342SAlexander V. Chernikov "insns": [ 20184b41342SAlexander V. Chernikov InsnIp(IpFwOpcode.O_IP_DST, ip="1.2.3.4"), 20284b41342SAlexander V. Chernikov Insn(IpFwOpcode.O_EXTERNAL_ACTION, arg1=1), 20384b41342SAlexander V. Chernikov Insn(IpFwOpcode.O_EXTERNAL_INSTANCE, arg1=2), 20484b41342SAlexander V. Chernikov ], 20584b41342SAlexander V. Chernikov }, 20684b41342SAlexander V. Chernikov }, 20784b41342SAlexander V. Chernikov id="test_eaction_ntp", 20884b41342SAlexander V. Chernikov ), 209*7e1ec25cSAlexander V. Chernikov pytest.param( 210*7e1ec25cSAlexander V. Chernikov { 211*7e1ec25cSAlexander V. Chernikov "in": "add // test comment", 212*7e1ec25cSAlexander V. Chernikov "out": { 213*7e1ec25cSAlexander V. Chernikov "insns": [ 214*7e1ec25cSAlexander V. Chernikov InsnComment(comment="test comment"), 215*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_COUNT), 216*7e1ec25cSAlexander V. Chernikov ], 217*7e1ec25cSAlexander V. Chernikov }, 218*7e1ec25cSAlexander V. Chernikov }, 219*7e1ec25cSAlexander V. Chernikov id="test_action_comment", 220*7e1ec25cSAlexander V. Chernikov ), 221*7e1ec25cSAlexander V. Chernikov pytest.param( 222*7e1ec25cSAlexander V. Chernikov { 223*7e1ec25cSAlexander V. Chernikov "in": "add check-state :OUT // test comment", 224*7e1ec25cSAlexander V. Chernikov "out": { 225*7e1ec25cSAlexander V. Chernikov "objs": [ 226*7e1ec25cSAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="OUT"), 227*7e1ec25cSAlexander V. Chernikov ], 228*7e1ec25cSAlexander V. Chernikov "insns": [ 229*7e1ec25cSAlexander V. Chernikov InsnComment(comment="test comment"), 230*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_CHECK_STATE, arg1=1), 231*7e1ec25cSAlexander V. Chernikov ], 232*7e1ec25cSAlexander V. Chernikov }, 233*7e1ec25cSAlexander V. Chernikov }, 234*7e1ec25cSAlexander V. Chernikov id="test_check_state", 235*7e1ec25cSAlexander V. Chernikov ), 236*7e1ec25cSAlexander V. Chernikov pytest.param( 237*7e1ec25cSAlexander V. Chernikov { 238*7e1ec25cSAlexander V. Chernikov "in": "add allow tcp from any to any keep-state :OUT", 239*7e1ec25cSAlexander V. Chernikov "out": { 240*7e1ec25cSAlexander V. Chernikov "objs": [ 241*7e1ec25cSAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="OUT"), 242*7e1ec25cSAlexander V. Chernikov ], 243*7e1ec25cSAlexander V. Chernikov "insns": [ 244*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_PROBE_STATE, arg1=1), 245*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_PROTO, arg1=6), 246*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_KEEP_STATE, arg1=1), 247*7e1ec25cSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 248*7e1ec25cSAlexander V. Chernikov ], 249*7e1ec25cSAlexander V. Chernikov }, 250*7e1ec25cSAlexander V. Chernikov }, 251*7e1ec25cSAlexander V. Chernikov id="test_keep_state", 252*7e1ec25cSAlexander V. Chernikov ), 253*7e1ec25cSAlexander V. Chernikov pytest.param( 254*7e1ec25cSAlexander V. Chernikov { 255*7e1ec25cSAlexander V. Chernikov "in": "add allow tcp from any to any record-state", 256*7e1ec25cSAlexander V. Chernikov "out": { 257*7e1ec25cSAlexander V. Chernikov "objs": [ 258*7e1ec25cSAlexander V. Chernikov NTlv(IpFwTlvType.IPFW_TLV_STATE_NAME, idx=1, name="default"), 259*7e1ec25cSAlexander V. Chernikov ], 260*7e1ec25cSAlexander V. Chernikov "insns": [ 261*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_PROTO, arg1=6), 262*7e1ec25cSAlexander V. Chernikov Insn(IpFwOpcode.O_KEEP_STATE, arg1=1), 263*7e1ec25cSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 264*7e1ec25cSAlexander V. Chernikov ], 265*7e1ec25cSAlexander V. Chernikov }, 266*7e1ec25cSAlexander V. Chernikov }, 267*7e1ec25cSAlexander V. Chernikov id="test_record_state", 268*7e1ec25cSAlexander V. Chernikov ), 2699f44a47fSAlexander V. Chernikov ], 2709f44a47fSAlexander V. Chernikov ) 2719f44a47fSAlexander V. Chernikov def test_add_rule(self, rule): 2729f44a47fSAlexander V. Chernikov """Tests if the compiled rule is sane and matches the spec""" 2739f44a47fSAlexander V. Chernikov self.verify_rule(rule["in"], rule["out"]) 2749f44a47fSAlexander V. Chernikov 2759f44a47fSAlexander V. Chernikov @pytest.mark.parametrize( 2769f44a47fSAlexander V. Chernikov "action", 2779f44a47fSAlexander V. Chernikov [ 2789f44a47fSAlexander V. Chernikov pytest.param(("allow", InsnEmpty(IpFwOpcode.O_ACCEPT)), id="test_allow"), 2799f44a47fSAlexander V. Chernikov pytest.param( 2809f44a47fSAlexander V. Chernikov ( 2819f44a47fSAlexander V. Chernikov "abort", 2829f44a47fSAlexander V. Chernikov Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_REJECT_ABORT), 2839f44a47fSAlexander V. Chernikov ), 2849f44a47fSAlexander V. Chernikov id="abort", 2859f44a47fSAlexander V. Chernikov ), 2869f44a47fSAlexander V. Chernikov pytest.param( 2879f44a47fSAlexander V. Chernikov ( 2889f44a47fSAlexander V. Chernikov "abort6", 2899f44a47fSAlexander V. Chernikov Insn( 2909f44a47fSAlexander V. Chernikov IpFwOpcode.O_UNREACH6, arg1=Icmp6RejectCode.ICMP6_UNREACH_ABORT 2919f44a47fSAlexander V. Chernikov ), 2929f44a47fSAlexander V. Chernikov ), 2939f44a47fSAlexander V. Chernikov id="abort6", 2949f44a47fSAlexander V. Chernikov ), 2959f44a47fSAlexander V. Chernikov pytest.param(("accept", InsnEmpty(IpFwOpcode.O_ACCEPT)), id="accept"), 2969f44a47fSAlexander V. Chernikov pytest.param(("deny", InsnEmpty(IpFwOpcode.O_DENY)), id="deny"), 2979f44a47fSAlexander V. Chernikov pytest.param( 2989f44a47fSAlexander V. Chernikov ( 2999f44a47fSAlexander V. Chernikov "reject", 3009f44a47fSAlexander V. Chernikov Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_HOST), 3019f44a47fSAlexander V. Chernikov ), 3029f44a47fSAlexander V. Chernikov id="reject", 3039f44a47fSAlexander V. Chernikov ), 3049f44a47fSAlexander V. Chernikov pytest.param( 3059f44a47fSAlexander V. Chernikov ( 3069f44a47fSAlexander V. Chernikov "reset", 3079f44a47fSAlexander V. Chernikov Insn(IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_REJECT_RST), 3089f44a47fSAlexander V. Chernikov ), 3099f44a47fSAlexander V. Chernikov id="reset", 3109f44a47fSAlexander V. Chernikov ), 3119f44a47fSAlexander V. Chernikov pytest.param( 3129f44a47fSAlexander V. Chernikov ( 3139f44a47fSAlexander V. Chernikov "reset6", 3149f44a47fSAlexander V. Chernikov Insn(IpFwOpcode.O_UNREACH6, arg1=Icmp6RejectCode.ICMP6_UNREACH_RST), 3159f44a47fSAlexander V. Chernikov ), 3169f44a47fSAlexander V. Chernikov id="reset6", 3179f44a47fSAlexander V. Chernikov ), 3189f44a47fSAlexander V. Chernikov pytest.param( 3199f44a47fSAlexander V. Chernikov ( 3209f44a47fSAlexander V. Chernikov "unreach port", 3219f44a47fSAlexander V. Chernikov InsnReject( 3229f44a47fSAlexander V. Chernikov IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_PORT 3239f44a47fSAlexander V. Chernikov ), 3249f44a47fSAlexander V. Chernikov ), 3259f44a47fSAlexander V. Chernikov id="unreach_port", 3269f44a47fSAlexander V. Chernikov ), 3279f44a47fSAlexander V. Chernikov pytest.param( 3289f44a47fSAlexander V. Chernikov ( 3299f44a47fSAlexander V. Chernikov "unreach port", 3309f44a47fSAlexander V. Chernikov InsnReject( 3319f44a47fSAlexander V. Chernikov IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_PORT 3329f44a47fSAlexander V. Chernikov ), 3339f44a47fSAlexander V. Chernikov ), 3349f44a47fSAlexander V. Chernikov id="unreach_port", 3359f44a47fSAlexander V. Chernikov ), 3369f44a47fSAlexander V. Chernikov pytest.param( 3379f44a47fSAlexander V. Chernikov ( 3389f44a47fSAlexander V. Chernikov "unreach needfrag", 3399f44a47fSAlexander V. Chernikov InsnReject( 3409f44a47fSAlexander V. Chernikov IpFwOpcode.O_REJECT, arg1=IcmpRejectCode.ICMP_UNREACH_NEEDFRAG 3419f44a47fSAlexander V. Chernikov ), 3429f44a47fSAlexander V. Chernikov ), 3439f44a47fSAlexander V. Chernikov id="unreach_needfrag", 3449f44a47fSAlexander V. Chernikov ), 3459f44a47fSAlexander V. Chernikov pytest.param( 3469f44a47fSAlexander V. Chernikov ( 3479f44a47fSAlexander V. Chernikov "unreach needfrag 1420", 3489f44a47fSAlexander V. Chernikov InsnReject( 3499f44a47fSAlexander V. Chernikov IpFwOpcode.O_REJECT, 3509f44a47fSAlexander V. Chernikov arg1=IcmpRejectCode.ICMP_UNREACH_NEEDFRAG, 3519f44a47fSAlexander V. Chernikov mtu=1420, 3529f44a47fSAlexander V. Chernikov ), 3539f44a47fSAlexander V. Chernikov ), 3549f44a47fSAlexander V. Chernikov id="unreach_needfrag_mtu", 3559f44a47fSAlexander V. Chernikov ), 3569f44a47fSAlexander V. Chernikov pytest.param( 3579f44a47fSAlexander V. Chernikov ( 3589f44a47fSAlexander V. Chernikov "unreach6 port", 3599f44a47fSAlexander V. Chernikov Insn( 3609f44a47fSAlexander V. Chernikov IpFwOpcode.O_UNREACH6, 3619f44a47fSAlexander V. Chernikov arg1=Icmp6RejectCode.ICMP6_DST_UNREACH_NOPORT, 3629f44a47fSAlexander V. Chernikov ), 3639f44a47fSAlexander V. Chernikov ), 3649f44a47fSAlexander V. Chernikov id="unreach6_port", 3659f44a47fSAlexander V. Chernikov ), 3669f44a47fSAlexander V. Chernikov pytest.param(("count", InsnEmpty(IpFwOpcode.O_COUNT)), id="count"), 3679f44a47fSAlexander V. Chernikov # TOK_NAT 3689f44a47fSAlexander V. Chernikov pytest.param( 3699f44a47fSAlexander V. Chernikov ("queue 42", Insn(IpFwOpcode.O_QUEUE, arg1=42)), id="queue_42" 3709f44a47fSAlexander V. Chernikov ), 3719f44a47fSAlexander V. Chernikov pytest.param(("pipe 42", Insn(IpFwOpcode.O_PIPE, arg1=42)), id="pipe_42"), 3729f44a47fSAlexander V. Chernikov pytest.param( 3739f44a47fSAlexander V. Chernikov ("skipto 42", Insn(IpFwOpcode.O_SKIPTO, arg1=42)), id="skipto_42" 3749f44a47fSAlexander V. Chernikov ), 3759f44a47fSAlexander V. Chernikov pytest.param( 3769f44a47fSAlexander V. Chernikov ("netgraph 42", Insn(IpFwOpcode.O_NETGRAPH, arg1=42)), id="netgraph_42" 3779f44a47fSAlexander V. Chernikov ), 3789f44a47fSAlexander V. Chernikov pytest.param( 3799f44a47fSAlexander V. Chernikov ("ngtee 42", Insn(IpFwOpcode.O_NGTEE, arg1=42)), id="ngtee_42" 3809f44a47fSAlexander V. Chernikov ), 3819f44a47fSAlexander V. Chernikov pytest.param( 3829f44a47fSAlexander V. Chernikov ("divert 42", Insn(IpFwOpcode.O_DIVERT, arg1=42)), id="divert_42" 3839f44a47fSAlexander V. Chernikov ), 3849f44a47fSAlexander V. Chernikov pytest.param( 3859f44a47fSAlexander V. Chernikov ("divert natd", Insn(IpFwOpcode.O_DIVERT, arg1=8668)), id="divert_natd" 3869f44a47fSAlexander V. Chernikov ), 3879f44a47fSAlexander V. Chernikov pytest.param(("tee 42", Insn(IpFwOpcode.O_TEE, arg1=42)), id="tee_42"), 3889f44a47fSAlexander V. Chernikov pytest.param( 3899f44a47fSAlexander V. Chernikov ("call 420", Insn(IpFwOpcode.O_CALLRETURN, arg1=420)), id="call_420" 3909f44a47fSAlexander V. Chernikov ), 3919f44a47fSAlexander V. Chernikov # TOK_FORWARD 3929f44a47fSAlexander V. Chernikov pytest.param( 3939f44a47fSAlexander V. Chernikov ("setfib 1", Insn(IpFwOpcode.O_SETFIB, arg1=1 | 0x8000)), 3949f44a47fSAlexander V. Chernikov id="setfib_1", 3959f44a47fSAlexander V. Chernikov marks=pytest.mark.skip("needs net.fibs>1"), 3969f44a47fSAlexander V. Chernikov ), 3979f44a47fSAlexander V. Chernikov pytest.param( 3989f44a47fSAlexander V. Chernikov ("setdscp 42", Insn(IpFwOpcode.O_SETDSCP, arg1=42 | 0x8000)), 3999f44a47fSAlexander V. Chernikov id="setdscp_42", 4009f44a47fSAlexander V. Chernikov ), 4019f44a47fSAlexander V. Chernikov pytest.param(("reass", InsnEmpty(IpFwOpcode.O_REASS)), id="reass"), 4029f44a47fSAlexander V. Chernikov pytest.param( 4039f44a47fSAlexander V. Chernikov ("return", InsnEmpty(IpFwOpcode.O_CALLRETURN, is_not=True)), id="return" 4049f44a47fSAlexander V. Chernikov ), 4059f44a47fSAlexander V. Chernikov ], 4069f44a47fSAlexander V. Chernikov ) 4079f44a47fSAlexander V. Chernikov def test_add_action(self, action): 4089f44a47fSAlexander V. Chernikov """Tests if the rule action is compiled properly""" 4099f44a47fSAlexander V. Chernikov rule_in = "add {} ip from any to any".format(action[0]) 4109f44a47fSAlexander V. Chernikov rule_out = {"insns": [action[1]]} 4119f44a47fSAlexander V. Chernikov self.verify_rule(rule_in, rule_out) 4129f44a47fSAlexander V. Chernikov 4139f44a47fSAlexander V. Chernikov @pytest.mark.parametrize( 4149f44a47fSAlexander V. Chernikov "insn", 4159f44a47fSAlexander V. Chernikov [ 4169f44a47fSAlexander V. Chernikov pytest.param( 4179f44a47fSAlexander V. Chernikov { 4189f44a47fSAlexander V. Chernikov "in": "add prob 0.7 allow ip from any to any", 4199f44a47fSAlexander V. Chernikov "out": InsnProb(prob=0.7), 4209f44a47fSAlexander V. Chernikov }, 4219f44a47fSAlexander V. Chernikov id="test_prob", 4229f44a47fSAlexander V. Chernikov ), 4239f44a47fSAlexander V. Chernikov pytest.param( 4249f44a47fSAlexander V. Chernikov { 4259f44a47fSAlexander V. Chernikov "in": "add allow tcp from any to any", 4269f44a47fSAlexander V. Chernikov "out": InsnProto(arg1=6), 4279f44a47fSAlexander V. Chernikov }, 4289f44a47fSAlexander V. Chernikov id="test_proto", 4299f44a47fSAlexander V. Chernikov ), 4309f44a47fSAlexander V. Chernikov pytest.param( 4319f44a47fSAlexander V. Chernikov { 4329f44a47fSAlexander V. Chernikov "in": "add allow ip from any to any 57", 4339f44a47fSAlexander V. Chernikov "out": InsnPorts(IpFwOpcode.O_IP_DSTPORT, port_pairs=[57, 57]), 4349f44a47fSAlexander V. Chernikov }, 4359f44a47fSAlexander V. Chernikov id="test_ports", 4369f44a47fSAlexander V. Chernikov ), 4379f44a47fSAlexander V. Chernikov ], 4389f44a47fSAlexander V. Chernikov ) 4399f44a47fSAlexander V. Chernikov def test_add_single_instruction(self, insn): 4409f44a47fSAlexander V. Chernikov """Tests if the compiled rule is sane and matches the spec""" 4419f44a47fSAlexander V. Chernikov 4429f44a47fSAlexander V. Chernikov # Prepare the desired output 4439f44a47fSAlexander V. Chernikov out = { 4449f44a47fSAlexander V. Chernikov "insns": [insn["out"], InsnEmpty(IpFwOpcode.O_ACCEPT)], 4459f44a47fSAlexander V. Chernikov } 4469f44a47fSAlexander V. Chernikov self.verify_rule(insn["in"], out) 4479f44a47fSAlexander V. Chernikov 4489f44a47fSAlexander V. Chernikov @pytest.mark.parametrize( 4499f44a47fSAlexander V. Chernikov "opcode", 4509f44a47fSAlexander V. Chernikov [ 4519f44a47fSAlexander V. Chernikov pytest.param(IpFwOpcode.O_IP_SRCPORT, id="src"), 4529f44a47fSAlexander V. Chernikov pytest.param(IpFwOpcode.O_IP_DSTPORT, id="dst"), 4539f44a47fSAlexander V. Chernikov ], 4549f44a47fSAlexander V. Chernikov ) 4559f44a47fSAlexander V. Chernikov @pytest.mark.parametrize( 4569f44a47fSAlexander V. Chernikov "params", 4579f44a47fSAlexander V. Chernikov [ 4589f44a47fSAlexander V. Chernikov pytest.param( 4599f44a47fSAlexander V. Chernikov { 4609f44a47fSAlexander V. Chernikov "in": "57", 4619f44a47fSAlexander V. Chernikov "out": [(57, 57)], 4629f44a47fSAlexander V. Chernikov }, 4639f44a47fSAlexander V. Chernikov id="test_single", 4649f44a47fSAlexander V. Chernikov ), 4659f44a47fSAlexander V. Chernikov pytest.param( 4669f44a47fSAlexander V. Chernikov { 4679f44a47fSAlexander V. Chernikov "in": "57-59", 4689f44a47fSAlexander V. Chernikov "out": [(57, 59)], 4699f44a47fSAlexander V. Chernikov }, 4709f44a47fSAlexander V. Chernikov id="test_range", 4719f44a47fSAlexander V. Chernikov ), 4729f44a47fSAlexander V. Chernikov pytest.param( 4739f44a47fSAlexander V. Chernikov { 4749f44a47fSAlexander V. Chernikov "in": "57-59,41", 4759f44a47fSAlexander V. Chernikov "out": [(57, 59), (41, 41)], 4769f44a47fSAlexander V. Chernikov }, 4779f44a47fSAlexander V. Chernikov id="test_ranges", 4789f44a47fSAlexander V. Chernikov ), 4799f44a47fSAlexander V. Chernikov ], 4809f44a47fSAlexander V. Chernikov ) 4819f44a47fSAlexander V. Chernikov def test_add_ports(self, params, opcode): 4829f44a47fSAlexander V. Chernikov if opcode == IpFwOpcode.O_IP_DSTPORT: 4839f44a47fSAlexander V. Chernikov txt = "add allow ip from any to any " + params["in"] 4849f44a47fSAlexander V. Chernikov else: 4859f44a47fSAlexander V. Chernikov txt = "add allow ip from any " + params["in"] + " to any" 4869f44a47fSAlexander V. Chernikov out = { 4879f44a47fSAlexander V. Chernikov "insns": [ 4889f44a47fSAlexander V. Chernikov InsnPorts(opcode, port_pairs=params["out"]), 4899f44a47fSAlexander V. Chernikov InsnEmpty(IpFwOpcode.O_ACCEPT), 4909f44a47fSAlexander V. Chernikov ] 4919f44a47fSAlexander V. Chernikov } 4929f44a47fSAlexander V. Chernikov self.verify_rule(txt, out) 493