Home | History | Annotate | Line # | Download | only in libnpftest
npf_rule_test.c revision 1.3
      1  1.3  rmind /*	$NetBSD: npf_rule_test.c,v 1.3 2012/12/24 19:05:48 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.1  rmind 	npf_core_enter();
     89  1.3  rmind 	rl = npf_ruleset_inspect(&npc, &nbuf, npf_core_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.3  rmind 		error = npf_rule_apply(&npc, &nbuf, rl, &retfl);
     96  1.1  rmind 	} else {
     97  1.1  rmind 		npf_core_exit();
     98  1.1  rmind 		error = ENOENT;
     99  1.1  rmind 	}
    100  1.1  rmind 	return error;
    101  1.1  rmind }
    102  1.1  rmind 
    103  1.1  rmind bool
    104  1.1  rmind npf_rule_test(bool verbose)
    105  1.1  rmind {
    106  1.2  rmind 	bool fail = false;
    107  1.2  rmind 
    108  1.1  rmind 	for (unsigned i = 0; i < __arraycount(test_cases); i++) {
    109  1.1  rmind 		const struct test_case *t = &test_cases[i];
    110  1.1  rmind 		ifnet_t *ifp = ifunit(t->ifname);
    111  1.1  rmind 		int serror, error;
    112  1.1  rmind 
    113  1.1  rmind 		if (ifp == NULL) {
    114  1.1  rmind 			printf("Interface %s is not configured.\n", t->ifname);
    115  1.1  rmind 			return false;
    116  1.1  rmind 		}
    117  1.1  rmind 
    118  1.2  rmind 		struct mbuf *m = fill_packet(t);
    119  1.1  rmind 		error = npf_rule_raw_test(verbose, m, ifp, t->di);
    120  1.1  rmind 		serror = npf_packet_handler(NULL, &m, ifp, t->di);
    121  1.1  rmind 
    122  1.1  rmind 		if (m) {
    123  1.1  rmind 			m_freem(m);
    124  1.1  rmind 		}
    125  1.1  rmind 
    126  1.1  rmind 		if (verbose) {
    127  1.1  rmind 			printf("Rule test %d, expected %d (stateful) and %d \n"
    128  1.1  rmind 			    "-> returned %d and %d.\n",
    129  1.1  rmind 			    i + 1, t->stateful_ret, t->ret, serror, error);
    130  1.1  rmind 		}
    131  1.2  rmind 		fail |= (serror != t->stateful_ret || error != t->ret);
    132  1.1  rmind 	}
    133  1.2  rmind 	return !fail;
    134  1.1  rmind }
    135