1 1.1 joe /* 2 1.1 joe * NPF layer 2 ruleset tests. 3 1.1 joe * 4 1.1 joe * Public Domain. 5 1.1 joe */ 6 1.1 joe 7 1.1 joe #ifdef _KERNEL 8 1.1 joe #include <sys/types.h> 9 1.1 joe #endif 10 1.1 joe 11 1.1 joe #include "npf_impl.h" 12 1.1 joe #include "npf_test.h" 13 1.1 joe 14 1.1 joe #define RESULT_PASS 0 15 1.1 joe #define RESULT_BLOCK ENETUNREACH 16 1.1 joe 17 1.1 joe static const struct test_case { 18 1.2 christos const char *src; 19 1.2 christos const char *dst; 20 1.2 christos uint16_t etype; 21 1.2 christos const char *ifname; 22 1.2 christos int di; 23 1.2 christos int ret; 24 1.1 joe } test_cases[] = { 25 1.1 joe { 26 1.1 joe /* pass ether in final from $mac1 to $mac2 type $E_IPv6 */ 27 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:01", 28 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IPV6, 29 1.1 joe .di = PFIL_IN, .ret = RESULT_PASS 30 1.1 joe }, 31 1.1 joe { 32 1.1 joe /* block ether in final from $mac2 */ 33 1.1 joe .src = "00:00:5E:00:53:01", .dst = "00:00:5E:00:53:02", 34 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IP, 35 1.1 joe .di = PFIL_IN, .ret = RESULT_BLOCK 36 1.1 joe }, 37 1.1 joe 38 1.1 joe /* pass ether out final to $mac3 $Apple talk */ 39 1.1 joe { 40 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:02", 41 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_ATALK, 42 1.1 joe .di = PFIL_OUT, .ret = RESULT_PASS 43 1.1 joe }, 44 1.1 joe { 45 1.1 joe /* goto default: block all (since direction is not matching ) */ 46 1.1 joe .src = "00:00:5E:00:53:00", .dst = "00:00:5E:00:53:02", 47 1.2 christos .ifname = IFNAME_INT, .etype = ETHERTYPE_IP, 48 1.1 joe .di = PFIL_IN, .ret = RESULT_BLOCK 49 1.1 joe }, 50 1.3 joe { 51 1.3 joe /* pass from nested options : 03 */ 52 1.3 joe .src = "00:00:5E:00:53:03", .dst = "00:00:5E:00:53:5A", 53 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP, 54 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS 55 1.3 joe }, 56 1.3 joe { 57 1.3 joe /* pass from nested options : 04 */ 58 1.3 joe .src = "00:00:5E:00:53:04", .dst = "00:00:5E:00:53:5A", 59 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP, 60 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS 61 1.3 joe }, 62 1.3 joe { 63 1.3 joe /* pass from nested options : 04 */ 64 1.3 joe .src = "00:00:5E:00:53:05", .dst = "00:00:5E:00:53:5A", 65 1.3 joe .ifname = IFNAME_INT, .etype = ETHERTYPE_IP, 66 1.3 joe .di = PFIL_IN, .ret = RESULT_PASS 67 1.3 joe }, 68 1.1 joe }; 69 1.1 joe 70 1.1 joe static int 71 1.1 joe run_raw_testcase(unsigned i) 72 1.1 joe { 73 1.1 joe const struct test_case *t = &test_cases[i]; 74 1.1 joe npf_t *npf = npf_getkernctx(); 75 1.1 joe npf_cache_t *npc; 76 1.1 joe struct mbuf *m; 77 1.1 joe npf_rule_t *rl; 78 1.1 joe int slock, error; 79 1.1 joe 80 1.2 christos m = mbuf_get_frame(t->src, t->dst, htons(t->etype)); 81 1.1 joe npc = get_cached_pkt(m, t->ifname, NPF_RULE_LAYER_2); 82 1.1 joe 83 1.1 joe slock = npf_config_read_enter(npf); 84 1.1 joe rl = npf_ruleset_inspect(npc, npf_config_ruleset(npf), t->di, NPF_RULE_LAYER_2); 85 1.1 joe if (rl) { 86 1.1 joe npf_match_info_t mi; 87 1.1 joe error = npf_rule_conclude(rl, &mi); 88 1.1 joe } else { 89 1.1 joe error = ENOENT; 90 1.1 joe } 91 1.1 joe npf_config_read_exit(npf, slock); 92 1.1 joe 93 1.1 joe put_cached_pkt(npc); 94 1.1 joe return error; 95 1.1 joe } 96 1.1 joe 97 1.1 joe /* for dynamic testing */ 98 1.1 joe static int 99 1.1 joe run_handler_testcase(unsigned i) 100 1.1 joe { 101 1.1 joe const struct test_case *t = &test_cases[i]; 102 1.1 joe ifnet_t *ifp = npf_test_getif(t->ifname); 103 1.1 joe npf_t *npf = npf_getkernctx(); 104 1.1 joe struct mbuf *m; 105 1.1 joe int error; 106 1.1 joe 107 1.2 christos m = mbuf_get_frame(t->src, t->dst, htons(t->etype)); 108 1.1 joe error = npfk_layer2_handler(npf, &m, ifp, t->di); 109 1.1 joe if (m) { 110 1.1 joe m_freem(m); 111 1.1 joe } 112 1.1 joe return error; 113 1.1 joe } 114 1.1 joe 115 1.1 joe static npf_rule_t * 116 1.1 joe npf_blockall_rule(void) 117 1.1 joe { 118 1.1 joe npf_t *npf = npf_getkernctx(); 119 1.1 joe nvlist_t *rule = nvlist_create(0); 120 1.1 joe npf_rule_t *rl; 121 1.1 joe 122 1.1 joe nvlist_add_number(rule, "attr", 123 1.1 joe NPF_RULE_IN | NPF_RULE_OUT | NPF_RULE_DYNAMIC | NPF_RULE_LAYER_2); 124 1.1 joe rl = npf_rule_alloc(npf, rule); 125 1.1 joe nvlist_destroy(rule); 126 1.1 joe return rl; 127 1.1 joe } 128 1.1 joe 129 1.1 joe static bool 130 1.1 joe test_static(bool verbose) 131 1.1 joe { 132 1.1 joe for (unsigned i = 0; i < __arraycount(test_cases); i++) { 133 1.1 joe const struct test_case *t = &test_cases[i]; 134 1.1 joe int error; 135 1.1 joe 136 1.1 joe if (npf_test_getif(t->ifname) == NULL) { 137 1.1 joe printf("Interface %s is not configured.\n", t->ifname); 138 1.1 joe return false; 139 1.1 joe } 140 1.1 joe 141 1.1 joe error = run_handler_testcase(i); 142 1.1 joe 143 1.1 joe if (verbose) { 144 1.1 joe printf("rule test %d:\texpected %d\n" 145 1.1 joe "\t\t-> returned %d\n", 146 1.1 joe i + 1, t->ret, error); 147 1.1 joe } 148 1.1 joe CHECK_TRUE(error == t->ret); 149 1.1 joe } 150 1.1 joe return true; 151 1.1 joe } 152 1.1 joe 153 1.1 joe static bool 154 1.1 joe test_dynamic(void) 155 1.1 joe { 156 1.1 joe npf_t *npf = npf_getkernctx(); 157 1.1 joe npf_ruleset_t *rlset; 158 1.1 joe npf_rule_t *rl; 159 1.1 joe uint64_t id; 160 1.1 joe int error; 161 1.1 joe 162 1.1 joe /* 163 1.1 joe * Test dynamic NPF rules. 164 1.1 joe */ 165 1.1 joe 166 1.1 joe error = run_raw_testcase(0); 167 1.1 joe CHECK_TRUE(error == RESULT_PASS); 168 1.1 joe 169 1.1 joe npf_config_enter(npf); 170 1.1 joe rlset = npf_config_ruleset(npf); 171 1.1 joe 172 1.1 joe rl = npf_blockall_rule(); 173 1.1 joe error = npf_ruleset_add(rlset, "l2-ruleset", rl); 174 1.1 joe CHECK_TRUE(error == 0); 175 1.1 joe 176 1.1 joe error = run_raw_testcase(0); 177 1.1 joe CHECK_TRUE(error == RESULT_BLOCK); 178 1.1 joe 179 1.1 joe id = npf_rule_getid(rl); 180 1.1 joe error = npf_ruleset_remove(rlset, "l2-ruleset", id); 181 1.1 joe CHECK_TRUE(error == 0); 182 1.1 joe 183 1.1 joe npf_config_exit(npf); 184 1.1 joe 185 1.1 joe error = run_raw_testcase(0); 186 1.1 joe CHECK_TRUE(error == RESULT_PASS); 187 1.1 joe 188 1.1 joe return true; 189 1.1 joe } 190 1.1 joe 191 1.1 joe bool 192 1.1 joe npf_layer2_rule_test(bool verbose) 193 1.1 joe { 194 1.1 joe bool ok; 195 1.1 joe 196 1.1 joe ok = test_static(verbose); 197 1.1 joe CHECK_TRUE(ok); 198 1.1 joe 199 1.1 joe ok = test_dynamic(); 200 1.1 joe CHECK_TRUE(ok); 201 1.1 joe 202 1.1 joe return true; 203 1.1 joe } 204