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