Home | History | Annotate | Line # | Download | only in libnpftest
      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