npf_ext_test.c revision 1.1 1 1.1 joe
2 1.1 joe
3 1.1 joe
4 1.1 joe #ifdef _KERNEL
5 1.1 joe #include <sys/types.h>
6 1.1 joe #endif
7 1.1 joe
8 1.1 joe #include "npf_impl.h"
9 1.1 joe #include "npf_test.h"
10 1.1 joe
11 1.1 joe static const struct test_case {
12 1.1 joe const char * src;
13 1.1 joe in_port_t sport;
14 1.1 joe const char * dst;
15 1.1 joe in_port_t dport;
16 1.1 joe const char * ifname;
17 1.1 joe int di;
18 1.1 joe int af;
19 1.1 joe } test_cases[] = {
20 1.1 joe {
21 1.1 joe LOCAL_IP60, 15000, LOCAL_IP70, 7000,
22 1.1 joe IFNAME_EXT, PFIL_OUT,
23 1.1 joe AF_INET
24 1.1 joe },
25 1.1 joe {
26 1.1 joe LOCAL_IP60, 15040, LOCAL_IP70, 6000,
27 1.1 joe IFNAME_EXT, PFIL_OUT,
28 1.1 joe AF_INET
29 1.1 joe },
30 1.1 joe
31 1.1 joe };
32 1.1 joe
33 1.1 joe #define TCP_OPT_LEN 4
34 1.1 joe static struct mbuf *
35 1.1 joe mbuf_get_pkt_with_option(int af, int proto, const char *src, const char *dst,
36 1.1 joe int sport, int dport)
37 1.1 joe {
38 1.1 joe struct mbuf *m;
39 1.1 joe struct ip *ip;
40 1.1 joe struct tcphdr *th;
41 1.1 joe void *ipsrc, *ipdst;
42 1.1 joe int size = 0;
43 1.1 joe uint8_t *opt;
44 1.1 joe uint16_t mss = 1400;
45 1.1 joe
46 1.1 joe m = m_gethdr(M_WAITOK, MT_HEADER);
47 1.1 joe ip = mtod(m, struct ip *);
48 1.1 joe
49 1.1 joe ip->ip_v = IPVERSION;
50 1.1 joe ip->ip_hl = sizeof(struct ip) >> 2;
51 1.1 joe ip->ip_off = 0;
52 1.1 joe ip->ip_ttl = 64;
53 1.1 joe ip->ip_p = proto;
54 1.1 joe
55 1.1 joe ipsrc = &ip->ip_src.s_addr;
56 1.1 joe ipdst = &ip->ip_dst.s_addr;
57 1.1 joe
58 1.1 joe npf_inet_pton(af, src, ipsrc);
59 1.1 joe npf_inet_pton(af, dst, ipdst);
60 1.1 joe
61 1.1 joe th = mbuf_return_hdrs(m, false, &ip);
62 1.1 joe size = sizeof(struct ip) + sizeof(struct tcphdr) + TCP_OPT_LEN;
63 1.1 joe th->th_flags |= TH_SYN;
64 1.1 joe th->th_off = (sizeof(struct tcphdr) + TCP_OPT_LEN) >> 2;
65 1.1 joe th->th_sport = htons(sport);
66 1.1 joe th->th_dport = htons(dport);
67 1.1 joe
68 1.1 joe opt = (uint8_t *)th + sizeof(struct tcphdr);
69 1.1 joe opt[0] = TCPOPT_MAXSEG; /* Kind = 2 */
70 1.1 joe opt[1] = TCPOLEN_MAXSEG; /* Length = 4 */
71 1.1 joe opt[2] = (mss >> 8) & 0xff; /* 0x05 */
72 1.1 joe opt[3] = mss & 0xff; /* 0x29 */
73 1.1 joe
74 1.1 joe ip->ip_len = htons(size);
75 1.1 joe
76 1.1 joe m->m_pkthdr.len = size;
77 1.1 joe m->m_len = size;
78 1.1 joe m->m_next = NULL;
79 1.1 joe return m;
80 1.1 joe }
81 1.1 joe
82 1.1 joe static int
83 1.1 joe run_raw_testcase(npf_cache_t *npc, unsigned i, bool verbose)
84 1.1 joe {
85 1.1 joe const struct test_case *t = &test_cases[i];
86 1.1 joe npf_t *npf = npf_getkernctx();
87 1.1 joe int slock, error;
88 1.1 joe npf_rproc_t *rp;
89 1.1 joe npf_rule_t *rl;
90 1.1 joe npf_match_info_t mi;
91 1.1 joe int decision = 1;
92 1.1 joe
93 1.1 joe slock = npf_config_read_enter(npf);
94 1.1 joe rl = npf_ruleset_inspect(npc, npf_config_ruleset(npf), t->di, NPF_RULE_LAYER_3);
95 1.1 joe if (rl) {
96 1.1 joe error = npf_rule_conclude(rl, &mi);
97 1.1 joe } else {
98 1.1 joe error = ENOENT;
99 1.1 joe return error;
100 1.1 joe }
101 1.1 joe npf_config_read_exit(npf, slock);
102 1.1 joe
103 1.1 joe rp = npf_rule_getrproc(rl);
104 1.1 joe assert(rp != NULL);
105 1.1 joe
106 1.1 joe error = npf_rproc_run(npc, rp, &mi, &decision);
107 1.1 joe
108 1.1 joe if (error == 1) {
109 1.1 joe npf_rproc_release(rp);
110 1.1 joe }
111 1.1 joe
112 1.1 joe return error;
113 1.1 joe }
114 1.1 joe
115 1.1 joe static void
116 1.1 joe npf_get_normalize_params(npf_cache_t *npc, uint16_t *ip_ttl, uint8_t *ip_id, int *df, uint16_t *maxmss)
117 1.1 joe {
118 1.1 joe int wscale;
119 1.1 joe struct ip *ip = npc->npc_ip.v4;
120 1.1 joe *ip_id = ip->ip_id;
121 1.1 joe *ip_ttl = ip->ip_ttl;
122 1.1 joe *df = ip->ip_off & IP_DF;
123 1.1 joe npf_fetch_tcpopts(npc, maxmss, &wscale);
124 1.1 joe }
125 1.1 joe
126 1.1 joe bool
127 1.1 joe npf_procedure_test(bool verbose)
128 1.1 joe {
129 1.1 joe int ret;
130 1.1 joe for (unsigned i = 0; i < __arraycount(test_cases); i++) {
131 1.1 joe const struct test_case *t = &test_cases[i];
132 1.1 joe npf_cache_t *npc;
133 1.1 joe struct mbuf *m;
134 1.1 joe uint16_t ip_ttl;
135 1.1 joe uint8_t ip_id;
136 1.1 joe int df;
137 1.1 joe uint16_t maxmss;
138 1.1 joe
139 1.1 joe if (npf_test_getif(t->ifname) == NULL) {
140 1.1 joe printf("Interface %s is not configured.\n", t->ifname);
141 1.1 joe return false;
142 1.1 joe }
143 1.1 joe
144 1.1 joe m = mbuf_get_pkt_with_option(t->af, IPPROTO_TCP, t->src, t->dst, 9000, 9000);
145 1.1 joe npc = get_cached_pkt(m, t->ifname, NPF_RULE_LAYER_3);
146 1.1 joe
147 1.1 joe ret = run_raw_testcase(npc, i, verbose);
148 1.1 joe if (verbose) {
149 1.1 joe printf("%s: expected return in raw testcase 1, returned %d\n", __func__, ret);
150 1.1 joe }
151 1.1 joe CHECK_TRUE(ret == 1);
152 1.1 joe
153 1.1 joe npf_get_normalize_params(npc, &ip_ttl, &ip_id, &df, &maxmss);
154 1.1 joe maxmss = ntohs(maxmss);
155 1.1 joe
156 1.1 joe if (verbose) {
157 1.1 joe printf("Normalization:\texpected 164 ttl but got %u\n", ip_ttl);
158 1.1 joe printf("Normalization:\texpected 1321 maxmss but got %u\n", maxmss);
159 1.1 joe }
160 1.1 joe CHECK_TRUE((df & IP_DF) == 0);
161 1.1 joe CHECK_TRUE(maxmss == 1321);
162 1.1 joe CHECK_TRUE(ip_ttl == 164);
163 1.1 joe put_cached_pkt(npc);
164 1.1 joe }
165 1.1 joe
166 1.1 joe return true;
167 1.1 joe }
168