Home | History | Annotate | Line # | Download | only in libnpftest
npf_rule_test.c revision 1.6
      1  1.6  rmind /*	$NetBSD: npf_rule_test.c,v 1.6 2013/02/16 21:11:16 rmind Exp $	*/
      2  1.1  rmind 
      3  1.1  rmind /*
      4  1.1  rmind  * NPF ruleset test.
      5  1.1  rmind  *
      6  1.1  rmind  * Public Domain.
      7  1.1  rmind  */
      8  1.1  rmind 
      9  1.1  rmind #include <sys/types.h>
     10  1.1  rmind 
     11  1.1  rmind #include "npf_impl.h"
     12  1.1  rmind #include "npf_test.h"
     13  1.1  rmind 
     14  1.1  rmind #define	IFNAME_EXT	"npftest0"
     15  1.1  rmind #define	IFNAME_INT	"npftest1"
     16  1.1  rmind 
     17  1.1  rmind #define	RESULT_PASS	0
     18  1.1  rmind #define	RESULT_BLOCK	ENETUNREACH
     19  1.1  rmind 
     20  1.1  rmind static const struct test_case {
     21  1.1  rmind 	const char *	src;
     22  1.1  rmind 	const char *	dst;
     23  1.1  rmind 	const char *	ifname;
     24  1.1  rmind 	int		di;
     25  1.1  rmind 	int		stateful_ret;
     26  1.1  rmind 	int		ret;
     27  1.1  rmind } test_cases[] = {
     28  1.1  rmind 
     29  1.1  rmind 	/* Stateful pass. */
     30  1.1  rmind 	{
     31  1.1  rmind 		.src = "10.1.1.1",		.dst = "10.1.1.2",
     32  1.1  rmind 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     33  1.1  rmind 		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
     34  1.1  rmind 	},
     35  1.1  rmind 	{
     36  1.1  rmind 		.src = "10.1.1.2",		.dst = "10.1.1.1",
     37  1.1  rmind 		.ifname = IFNAME_INT,		.di = PFIL_IN,
     38  1.1  rmind 		.stateful_ret = RESULT_PASS,	.ret = RESULT_BLOCK
     39  1.1  rmind 	},
     40  1.1  rmind 
     41  1.1  rmind 	/* Pass forwards stream only. */
     42  1.1  rmind 	{
     43  1.1  rmind 		.src = "10.1.1.1",		.dst = "10.1.1.3",
     44  1.1  rmind 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     45  1.1  rmind 		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
     46  1.1  rmind 	},
     47  1.1  rmind 	{
     48  1.1  rmind 		.src = "10.1.1.3",		.dst = "10.1.1.1",
     49  1.1  rmind 		.ifname = IFNAME_INT,		.di = PFIL_IN,
     50  1.1  rmind 		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
     51  1.1  rmind 	},
     52  1.1  rmind 
     53  1.1  rmind 	/* Block. */
     54  1.1  rmind 	{	.src = "10.1.1.1",		.dst = "10.1.1.4",
     55  1.1  rmind 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     56  1.1  rmind 		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
     57  1.1  rmind 	},
     58  1.1  rmind 
     59  1.1  rmind };
     60  1.1  rmind 
     61  1.1  rmind static struct mbuf *
     62  1.1  rmind fill_packet(const struct test_case *t)
     63  1.1  rmind {
     64  1.1  rmind 	struct mbuf *m;
     65  1.1  rmind 	struct ip *ip;
     66  1.1  rmind 	struct udphdr *uh;
     67  1.1  rmind 
     68  1.1  rmind 	m = mbuf_construct(IPPROTO_UDP);
     69  1.1  rmind 	uh = mbuf_return_hdrs(m, false, &ip);
     70  1.1  rmind 	ip->ip_src.s_addr = inet_addr(t->src);
     71  1.1  rmind 	ip->ip_dst.s_addr = inet_addr(t->dst);
     72  1.1  rmind 	uh->uh_sport = htons(9000);
     73  1.1  rmind 	uh->uh_dport = htons(9000);
     74  1.1  rmind 	return m;
     75  1.1  rmind }
     76  1.1  rmind 
     77  1.1  rmind static int
     78  1.1  rmind npf_rule_raw_test(bool verbose, struct mbuf *m, ifnet_t *ifp, int di)
     79  1.1  rmind {
     80  1.1  rmind 	npf_cache_t npc = { .npc_info = 0 };
     81  1.3  rmind 	nbuf_t nbuf;
     82  1.1  rmind 	npf_rule_t *rl;
     83  1.1  rmind 	int retfl, error;
     84  1.1  rmind 
     85  1.3  rmind 	nbuf_init(&nbuf, m, ifp);
     86  1.3  rmind 	npf_cache_all(&npc, &nbuf);
     87  1.3  rmind 
     88  1.4  rmind 	int slock = npf_config_read_enter();
     89  1.4  rmind 	rl = npf_ruleset_inspect(&npc, &nbuf, npf_config_ruleset(),
     90  1.3  rmind 	    di, NPF_LAYER_3);
     91  1.1  rmind 	if (rl) {
     92  1.1  rmind 		if (verbose) {
     93  1.1  rmind 			npf_rulenc_dump(rl);
     94  1.1  rmind 		}
     95  1.4  rmind 		error = npf_rule_conclude(rl, &retfl);
     96  1.1  rmind 	} else {
     97  1.1  rmind 		error = ENOENT;
     98  1.1  rmind 	}
     99  1.4  rmind 	npf_config_read_exit(slock);
    100  1.1  rmind 	return error;
    101  1.1  rmind }
    102  1.1  rmind 
    103  1.4  rmind static int
    104  1.4  rmind npf_test_first(bool verbose)
    105  1.4  rmind {
    106  1.4  rmind 	const struct test_case *t = &test_cases[0];
    107  1.4  rmind 	ifnet_t *ifp = ifunit(t->ifname);
    108  1.4  rmind 	int error;
    109  1.4  rmind 
    110  1.4  rmind 	struct mbuf *m = fill_packet(t);
    111  1.4  rmind 	error = npf_rule_raw_test(verbose, m, ifp, t->di);
    112  1.4  rmind 	m_freem(m);
    113  1.4  rmind 	return error;
    114  1.4  rmind }
    115  1.4  rmind 
    116  1.4  rmind static npf_rule_t *
    117  1.4  rmind npf_blockall_rule(void)
    118  1.4  rmind {
    119  1.4  rmind 	prop_dictionary_t rldict;
    120  1.4  rmind 
    121  1.4  rmind 	rldict = prop_dictionary_create();
    122  1.4  rmind 	prop_dictionary_set_uint32(rldict, "attributes",
    123  1.4  rmind 	    NPF_RULE_IN | NPF_RULE_OUT);
    124  1.4  rmind 	return npf_rule_alloc(rldict);
    125  1.4  rmind }
    126  1.4  rmind 
    127  1.1  rmind bool
    128  1.1  rmind npf_rule_test(bool verbose)
    129  1.1  rmind {
    130  1.4  rmind 	npf_ruleset_t *rlset;
    131  1.4  rmind 	npf_rule_t *rl;
    132  1.2  rmind 	bool fail = false;
    133  1.6  rmind 	uint64_t id;
    134  1.4  rmind 	int error;
    135  1.2  rmind 
    136  1.1  rmind 	for (unsigned i = 0; i < __arraycount(test_cases); i++) {
    137  1.1  rmind 		const struct test_case *t = &test_cases[i];
    138  1.1  rmind 		ifnet_t *ifp = ifunit(t->ifname);
    139  1.4  rmind 		int serror;
    140  1.1  rmind 
    141  1.1  rmind 		if (ifp == NULL) {
    142  1.1  rmind 			printf("Interface %s is not configured.\n", t->ifname);
    143  1.1  rmind 			return false;
    144  1.1  rmind 		}
    145  1.1  rmind 
    146  1.2  rmind 		struct mbuf *m = fill_packet(t);
    147  1.1  rmind 		error = npf_rule_raw_test(verbose, m, ifp, t->di);
    148  1.1  rmind 		serror = npf_packet_handler(NULL, &m, ifp, t->di);
    149  1.1  rmind 
    150  1.1  rmind 		if (m) {
    151  1.1  rmind 			m_freem(m);
    152  1.1  rmind 		}
    153  1.1  rmind 
    154  1.1  rmind 		if (verbose) {
    155  1.1  rmind 			printf("Rule test %d, expected %d (stateful) and %d \n"
    156  1.1  rmind 			    "-> returned %d and %d.\n",
    157  1.1  rmind 			    i + 1, t->stateful_ret, t->ret, serror, error);
    158  1.1  rmind 		}
    159  1.2  rmind 		fail |= (serror != t->stateful_ret || error != t->ret);
    160  1.1  rmind 	}
    161  1.4  rmind 
    162  1.4  rmind 	error = npf_test_first(verbose);
    163  1.4  rmind 	assert(error == RESULT_PASS);
    164  1.4  rmind 
    165  1.4  rmind 	npf_config_enter();
    166  1.4  rmind 	rlset = npf_config_ruleset();
    167  1.4  rmind 
    168  1.4  rmind 	rl = npf_blockall_rule();
    169  1.4  rmind 	error = npf_ruleset_add(rlset, "test-rules", rl);
    170  1.4  rmind 	fail |= error != 0;
    171  1.4  rmind 
    172  1.4  rmind 	error = npf_test_first(verbose);
    173  1.4  rmind 	fail |= (error != RESULT_BLOCK);
    174  1.4  rmind 
    175  1.6  rmind 	id = npf_rule_getid(rl);
    176  1.6  rmind 	error = npf_ruleset_remove(rlset, "test-rules", id);
    177  1.5  rmind 	fail |= error != 0;
    178  1.4  rmind 
    179  1.4  rmind 	npf_config_exit();
    180  1.4  rmind 
    181  1.4  rmind 	error = npf_test_first(verbose);
    182  1.4  rmind 	fail |= (error != RESULT_PASS);
    183  1.4  rmind 
    184  1.2  rmind 	return !fail;
    185  1.1  rmind }
    186