Home | History | Annotate | Line # | Download | only in libnpftest
npf_rule_test.c revision 1.2
      1 /*	$NetBSD: npf_rule_test.c,v 1.2 2012/08/21 20:52:11 rmind Exp $	*/
      2 
      3 /*
      4  * NPF ruleset test.
      5  *
      6  * Public Domain.
      7  */
      8 
      9 #include <sys/types.h>
     10 
     11 #include "npf_impl.h"
     12 #include "npf_test.h"
     13 
     14 #define	IFNAME_EXT	"npftest0"
     15 #define	IFNAME_INT	"npftest1"
     16 
     17 #define	RESULT_PASS	0
     18 #define	RESULT_BLOCK	ENETUNREACH
     19 
     20 static const struct test_case {
     21 	const char *	src;
     22 	const char *	dst;
     23 	const char *	ifname;
     24 	int		di;
     25 	int		stateful_ret;
     26 	int		ret;
     27 } test_cases[] = {
     28 
     29 	/* Stateful pass. */
     30 	{
     31 		.src = "10.1.1.1",		.dst = "10.1.1.2",
     32 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     33 		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
     34 	},
     35 	{
     36 		.src = "10.1.1.2",		.dst = "10.1.1.1",
     37 		.ifname = IFNAME_INT,		.di = PFIL_IN,
     38 		.stateful_ret = RESULT_PASS,	.ret = RESULT_BLOCK
     39 	},
     40 
     41 	/* Pass forwards stream only. */
     42 	{
     43 		.src = "10.1.1.1",		.dst = "10.1.1.3",
     44 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     45 		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
     46 	},
     47 	{
     48 		.src = "10.1.1.3",		.dst = "10.1.1.1",
     49 		.ifname = IFNAME_INT,		.di = PFIL_IN,
     50 		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
     51 	},
     52 
     53 	/* Block. */
     54 	{	.src = "10.1.1.1",		.dst = "10.1.1.4",
     55 		.ifname = IFNAME_INT,		.di = PFIL_OUT,
     56 		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
     57 	},
     58 
     59 };
     60 
     61 static struct mbuf *
     62 fill_packet(const struct test_case *t)
     63 {
     64 	struct mbuf *m;
     65 	struct ip *ip;
     66 	struct udphdr *uh;
     67 
     68 	m = mbuf_construct(IPPROTO_UDP);
     69 	uh = mbuf_return_hdrs(m, false, &ip);
     70 	ip->ip_src.s_addr = inet_addr(t->src);
     71 	ip->ip_dst.s_addr = inet_addr(t->dst);
     72 	uh->uh_sport = htons(9000);
     73 	uh->uh_dport = htons(9000);
     74 	return m;
     75 }
     76 
     77 static int
     78 npf_rule_raw_test(bool verbose, struct mbuf *m, ifnet_t *ifp, int di)
     79 {
     80 	npf_cache_t npc = { .npc_info = 0 };
     81 	npf_rule_t *rl;
     82 	int retfl, error;
     83 
     84 	npf_core_enter();
     85 	rl = npf_ruleset_inspect(&npc, m, npf_core_ruleset(),
     86 	    ifp, di, NPF_LAYER_3);
     87 	if (rl) {
     88 		if (verbose) {
     89 			npf_rulenc_dump(rl);
     90 		}
     91 		error = npf_rule_apply(&npc, m, rl, &retfl);
     92 	} else {
     93 		npf_core_exit();
     94 		error = ENOENT;
     95 	}
     96 	return error;
     97 }
     98 
     99 bool
    100 npf_rule_test(bool verbose)
    101 {
    102 	bool fail = false;
    103 
    104 	for (unsigned i = 0; i < __arraycount(test_cases); i++) {
    105 		const struct test_case *t = &test_cases[i];
    106 		ifnet_t *ifp = ifunit(t->ifname);
    107 		int serror, error;
    108 
    109 		if (ifp == NULL) {
    110 			printf("Interface %s is not configured.\n", t->ifname);
    111 			return false;
    112 		}
    113 
    114 		struct mbuf *m = fill_packet(t);
    115 		error = npf_rule_raw_test(verbose, m, ifp, t->di);
    116 		serror = npf_packet_handler(NULL, &m, ifp, t->di);
    117 
    118 		if (m) {
    119 			m_freem(m);
    120 		}
    121 
    122 		if (verbose) {
    123 			printf("Rule test %d, expected %d (stateful) and %d \n"
    124 			    "-> returned %d and %d.\n",
    125 			    i + 1, t->stateful_ret, t->ret, serror, error);
    126 		}
    127 		fail |= (serror != t->stateful_ret || error != t->ret);
    128 	}
    129 	return !fail;
    130 }
    131