1/*	$NetBSD: npf_processor_test.c,v 1.1.4.4 2012/11/18 21:48:56 riz Exp $	*/
2
3/*
4 * NPF n-code processor test.
5 *
6 * Public Domain.
7 */
8
9#include <sys/types.h>
10#include <sys/endian.h>
11
12#include "npf_impl.h"
13#include "npf_ncode.h"
14#include "npf_test.h"
15
16#if BYTE_ORDER == LITTLE_ENDIAN
17#define	IP4(a, b, c, d)	((a << 0) | (b << 8) | (c << 16) | (d << 24))
18#elif BYTE_ORDER == BIG_ENDIAN
19#define	IP4(a, b, c, d)	((a << 24) | (b << 16) | (c << 8) | (d << 0))
20#endif
21
22#define	PORTS(a, b)	((htons(a) << 16) | htons(b))
23
24static const uint32_t nc_match[] = {
25	NPF_OPCODE_CMP,		NPF_LAYER_3,	0,
26	NPF_OPCODE_BEQ,		0x0c,
27	NPF_OPCODE_ETHER,	0x00,	0x00,	htons(ETHERTYPE_IP),
28	NPF_OPCODE_BEQ,		0x04,
29	NPF_OPCODE_RET,		0xff,
30	NPF_OPCODE_ADVR,	3,
31	NPF_OPCODE_IP4MASK,	0x01,	IP4(192,168,2,0),	24,
32	NPF_OPCODE_BEQ,		0x04,
33	NPF_OPCODE_RET,		0xff,
34	NPF_OPCODE_TCP_PORTS,	0x00,	PORTS(80, 80),
35	NPF_OPCODE_BEQ,		0x04,
36	NPF_OPCODE_RET,		0xff,
37	NPF_OPCODE_RET,		0x00
38};
39
40static const uint32_t nc_nmatch[] = {
41	NPF_OPCODE_CMP,		NPF_LAYER_3,	0,
42	NPF_OPCODE_BEQ,		0x0c,
43	NPF_OPCODE_ETHER,	0x00,	0x00,	htons(ETHERTYPE_IP),
44	NPF_OPCODE_BEQ,		0x04,
45	NPF_OPCODE_RET,		0xff,
46	NPF_OPCODE_ADVR,	3,
47	NPF_OPCODE_IP4MASK,	0x01,	IP4(192,168,2,1),	32,
48	NPF_OPCODE_BEQ,		0x04,
49	NPF_OPCODE_RET,		0xff,
50	NPF_OPCODE_RET,		0x00
51};
52
53static const uint32_t nc_rmatch[] = {
54	NPF_OPCODE_MOVE,	offsetof(struct ip, ip_src),	1,
55	NPF_OPCODE_ADVR,	1,
56	NPF_OPCODE_LW,		sizeof(in_addr_t),		0,
57	NPF_OPCODE_CMP,		IP4(192,168,2,100),		0,
58	NPF_OPCODE_BEQ,		0x04,
59	NPF_OPCODE_RET,		0xff,
60	NPF_OPCODE_MOVE,	sizeof(struct ip) - offsetof(struct ip, ip_src)
61				+ offsetof(struct tcphdr, th_sport),	1,
62	NPF_OPCODE_ADVR,	1,
63	NPF_OPCODE_LW,		2 * sizeof(in_port_t),		0,
64	NPF_OPCODE_CMP,		htonl((15000 << 16) | 80),	0,
65	NPF_OPCODE_BEQ,		0x04,
66	NPF_OPCODE_RET,		0xff,
67	NPF_OPCODE_RET,		0x01
68};
69
70static const uint32_t nc_inval[] = {
71	NPF_OPCODE_BEQ,		0x05,
72	NPF_OPCODE_RET,		0xff,
73	NPF_OPCODE_RET,		0x01
74};
75
76static const uint32_t nc_match6[] = {
77	NPF_OPCODE_IP6MASK,	0x01,	htonl(0xfe80 << 16), 0x0, 0x0, 0x0, 10,
78	NPF_OPCODE_BEQ,		0x04,
79	NPF_OPCODE_RET,		0xff,
80	NPF_OPCODE_TCP_PORTS,	0x00,	PORTS(80, 80),
81	NPF_OPCODE_BEQ,		0x04,
82	NPF_OPCODE_RET,		0xff,
83	NPF_OPCODE_RET,		0x00
84};
85
86static struct mbuf *
87fill_packet(int proto, bool ether)
88{
89	struct mbuf *m;
90	struct ip *ip;
91	struct tcphdr *th;
92
93	if (ether) {
94		m = mbuf_construct_ether(IPPROTO_TCP);
95	} else {
96		m = mbuf_construct(IPPROTO_TCP);
97	}
98	th = mbuf_return_hdrs(m, ether, &ip);
99	ip->ip_src.s_addr = inet_addr("192.168.2.100");
100	ip->ip_dst.s_addr = inet_addr("10.0.0.1");
101	th->th_sport = htons(15000);
102	th->th_dport = htons(80);
103	return m;
104}
105
106static struct mbuf *
107fill_packet6(int proto)
108{
109	uint16_t src[] = {
110	    htons(0xfe80), 0x0, 0x0, 0x0,
111	    htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1234)
112	};
113	uint16_t dst[] = {
114	    htons(0xfe80), 0x0, 0x0, 0x0,
115	    htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1111)
116	};
117	struct mbuf *m;
118	struct ip6_hdr *ip;
119	struct tcphdr *th;
120
121	m = mbuf_construct6(proto);
122	(void)mbuf_return_hdrs(m, false, (struct ip **)&ip);
123	memcpy(&ip->ip6_src, src, sizeof(ip->ip6_src));
124	memcpy(&ip->ip6_dst, dst, sizeof(ip->ip6_src));
125
126	th = (void *)(ip + 1);
127	th->th_sport = htons(15000);
128	th->th_dport = htons(80);
129	return m;
130}
131
132static bool
133retcode_fail_p(const char *msg, bool verbose, int ret, int expected)
134{
135	bool fail = (ret != expected);
136
137	if (verbose) {
138		printf("%-25s\t%-4d == %4d\t-> %s\n",
139		    msg, ret, expected, fail ? "fail" : "ok");
140	}
141	return fail;
142}
143
144static void
145npf_nc_cachetest(struct mbuf *m, npf_cache_t *npc, nbuf_t *nbuf)
146{
147	const void *dummy_ifp = (void *)0xdeadbeef;
148
149	nbuf_init(nbuf, m, dummy_ifp);
150	memset(npc, 0, sizeof(npf_cache_t));
151	npf_cache_all(npc, nbuf);
152}
153
154bool
155npf_processor_test(bool verbose)
156{
157	npf_cache_t npc;
158	struct mbuf *m;
159	nbuf_t nbuf;
160	int errat, ret;
161	bool fail = false;
162
163#if 0
164	/* Layer 2 (Ethernet + IP + TCP). */
165	ret = npf_ncode_validate(nc_match, sizeof(nc_match), &errat);
166	fail |= retcode_fail_p("Ether validation", verbose, ret, 0);
167
168	m = fill_packet(IPPROTO_TCP, true);
169	npf_nc_cachetest(m, &npc, &nbuf);
170	ret = npf_ncode_process(&npc, nc_match, &nbuf, NPF_LAYER_2);
171	fail |= retcode_fail_p("Ether", verbose, ret, 0);
172	m_freem(m);
173#endif
174
175	/* Layer 3 (IP + TCP). */
176	m = fill_packet(IPPROTO_TCP, false);
177	npf_nc_cachetest(m, &npc, &nbuf);
178	ret = npf_ncode_process(&npc, nc_match, &nbuf, NPF_LAYER_3);
179	fail |= retcode_fail_p("IPv4 mask 1", verbose, ret, 0);
180
181	/* Non-matching IPv4 case. */
182	ret = npf_ncode_validate(nc_nmatch, sizeof(nc_nmatch), &errat);
183	fail |= retcode_fail_p("IPv4 mask 2 validation", verbose, ret, 0);
184
185	npf_nc_cachetest(m, &npc, &nbuf);
186	ret = npf_ncode_process(&npc, nc_nmatch, &nbuf, NPF_LAYER_3);
187	fail |= retcode_fail_p("IPv4 mask 2", verbose, ret, 255);
188
189	/* Invalid n-code case. */
190	ret = npf_ncode_validate(nc_inval, sizeof(nc_inval), &errat);
191	fail |= retcode_fail_p("Invalid n-code", verbose, ret, NPF_ERR_JUMP);
192
193	/* RISC-like insns. */
194	ret = npf_ncode_validate(nc_rmatch, sizeof(nc_rmatch), &errat);
195	fail |= retcode_fail_p("RISC-like n-code validation", verbose, ret, 0);
196
197	npf_nc_cachetest(m, &npc, &nbuf);
198	ret = npf_ncode_process(&npc, nc_rmatch, &nbuf, NPF_LAYER_3);
199	fail |= retcode_fail_p("RISC-like n-code", verbose, ret, 1);
200	m_freem(m);
201
202	/* IPv6 matching. */
203	ret = npf_ncode_validate(nc_match6, sizeof(nc_match6), &errat);
204	fail |= retcode_fail_p("IPv6 mask validation", verbose, ret, 0);
205
206	m = fill_packet6(IPPROTO_TCP);
207	npf_nc_cachetest(m, &npc, &nbuf);
208	ret = npf_ncode_process(&npc, nc_match6, &nbuf, NPF_LAYER_3);
209	fail |= retcode_fail_p("IPv6 mask", verbose, ret, 0);
210	m_freem(m);
211
212	return !fail;
213}
214