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