npf_state_test.c revision 1.3.4.2 1 1.3.4.2 yamt /* $NetBSD: npf_state_test.c,v 1.3.4.2 2012/10/30 19:00:48 yamt Exp $ */
2 1.3.4.2 yamt
3 1.3.4.2 yamt /*
4 1.3.4.2 yamt * NPF state tracking test.
5 1.3.4.2 yamt *
6 1.3.4.2 yamt * Public Domain.
7 1.3.4.2 yamt */
8 1.3.4.2 yamt
9 1.3.4.2 yamt #include <sys/types.h>
10 1.3.4.2 yamt #include <sys/kmem.h>
11 1.3.4.2 yamt
12 1.3.4.2 yamt #include "npf_impl.h"
13 1.3.4.2 yamt #include "npf_test.h"
14 1.3.4.2 yamt
15 1.3.4.2 yamt typedef struct {
16 1.3.4.2 yamt int tcpfl; /* TCP flags. */
17 1.3.4.2 yamt int tlen; /* TCP data length. */
18 1.3.4.2 yamt uint32_t seq; /* SEQ number. */
19 1.3.4.2 yamt uint32_t ack; /* ACK number. */
20 1.3.4.2 yamt uint32_t win; /* TCP Window. */
21 1.3.4.2 yamt int flags; /* Direction et al. */
22 1.3.4.2 yamt } tcp_meta_t;
23 1.3.4.2 yamt
24 1.3.4.2 yamt #define S TH_SYN
25 1.3.4.2 yamt #define A TH_ACK
26 1.3.4.2 yamt #define F TH_FIN
27 1.3.4.2 yamt #define OUT 0x1
28 1.3.4.2 yamt #define IN 0x2
29 1.3.4.2 yamt #define ERR 0x4
30 1.3.4.2 yamt #define CLEAR .flags = 0
31 1.3.4.2 yamt
32 1.3.4.2 yamt static const tcp_meta_t packet_sequence[] = {
33 1.3.4.2 yamt /*
34 1.3.4.2 yamt * TCP data SEQ ACK WIN
35 1.3.4.2 yamt */
36 1.3.4.2 yamt
37 1.3.4.2 yamt /* Out of order ACK. */
38 1.3.4.2 yamt { S, 0, 9999, 0, 4096, OUT },
39 1.3.4.2 yamt { S|A, 0, 9, 10000, 2048, IN },
40 1.3.4.2 yamt { A, 0, 10000, 10, 4096, OUT },
41 1.3.4.2 yamt /* --- */
42 1.3.4.2 yamt { A, 0, 10, 10000, 2048, IN },
43 1.3.4.2 yamt { A, 1000, 10000, 10, 4096, OUT },
44 1.3.4.2 yamt { A, 1000, 11000, 10, 4096, OUT },
45 1.3.4.2 yamt { A, 0, 10, 12000, 2048, IN },
46 1.3.4.2 yamt { A, 0, 10, 13000, 2048, IN },
47 1.3.4.2 yamt { A, 1000, 12000, 10, 4096, OUT },
48 1.3.4.2 yamt { A, 0, 10, 11000, 1048, IN },
49 1.3.4.2 yamt /* --- */
50 1.3.4.2 yamt { A, 1000, 14000, 10, 4096, OUT },
51 1.3.4.2 yamt { A, 0, 10, 13000, 2048, IN },
52 1.3.4.2 yamt { CLEAR },
53 1.3.4.2 yamt
54 1.3.4.2 yamt /* Retransmission after out of order ACK and missing ACK. */
55 1.3.4.2 yamt { S, 0, 9999, 0, 1000, OUT },
56 1.3.4.2 yamt { S|A, 0, 9, 10000, 4000, IN },
57 1.3.4.2 yamt { A, 0, 10000, 10, 1000, OUT },
58 1.3.4.2 yamt /* --- */
59 1.3.4.2 yamt { A, 1000, 10000, 10, 1000, OUT },
60 1.3.4.2 yamt { A, 0, 10, 11000, 4000, IN },
61 1.3.4.2 yamt { A, 1000, 11000, 10, 1000, OUT },
62 1.3.4.2 yamt { A, 1000, 12000, 10, 1000, OUT },
63 1.3.4.2 yamt { A, 1000, 13000, 10, 1000, OUT },
64 1.3.4.2 yamt { A, 1000, 14000, 10, 1000, OUT },
65 1.3.4.2 yamt /* --- Assume the first was delayed; second was lost after us. */
66 1.3.4.2 yamt { A, 0, 10, 15000, 4000, IN },
67 1.3.4.2 yamt { A, 0, 10, 15000, 2000, IN },
68 1.3.4.2 yamt /* --- */
69 1.3.4.2 yamt { A, 1000, 12000, 10, 1000, OUT },
70 1.3.4.2 yamt { CLEAR },
71 1.3.4.2 yamt
72 1.3.4.2 yamt /* FIN exchange with retransmit. */
73 1.3.4.2 yamt { S, 0, 999, 0, 1000, OUT },
74 1.3.4.2 yamt { S|A, 0, 9, 1000, 2000, IN },
75 1.3.4.2 yamt { A, 0, 1000, 10, 1000, OUT },
76 1.3.4.2 yamt /* --- */
77 1.3.4.2 yamt { F, 0, 10, 1000, 2000, IN },
78 1.3.4.2 yamt { F, 0, 1000, 10, 1000, OUT },
79 1.3.4.2 yamt { A, 0, 1000, 11, 1000, OUT },
80 1.3.4.2 yamt /* --- */
81 1.3.4.2 yamt { F, 0, 1000, 11, 1000, OUT },
82 1.3.4.2 yamt { F, 0, 1000, 11, 1000, OUT },
83 1.3.4.2 yamt { A, 0, 11, 1001, 2000, OUT },
84 1.3.4.2 yamt { CLEAR },
85 1.3.4.2 yamt
86 1.3.4.2 yamt /* Out of window. */
87 1.3.4.2 yamt { S, 0, 9, 0, 8760, OUT },
88 1.3.4.2 yamt { S|A, 0, 9999, 10, 1000, IN },
89 1.3.4.2 yamt { A, 0, 10, 10000, 8760, OUT },
90 1.3.4.2 yamt /* --- */
91 1.3.4.2 yamt { A, 1460, 10000, 10, 1000, IN },
92 1.3.4.2 yamt { A, 1460, 11460, 10, 1000, IN },
93 1.3.4.2 yamt { A, 0, 10, 12920, 8760, OUT },
94 1.3.4.2 yamt { A, 1460, 12920, 10, 1000, IN },
95 1.3.4.2 yamt { A, 0, 10, 14380, 8760, OUT },
96 1.3.4.2 yamt { A, 1460, 17300, 10, 1000, IN },
97 1.3.4.2 yamt { A, 0, 10, 14380, 8760, OUT },
98 1.3.4.2 yamt { A, 1460, 18760, 10, 1000, IN },
99 1.3.4.2 yamt { A, 0, 10, 14380, 8760, OUT },
100 1.3.4.2 yamt { A, 1460, 20220, 10, 1000, IN },
101 1.3.4.2 yamt { A, 0, 10, 14380, 8760, OUT },
102 1.3.4.2 yamt { A, 1460, 21680, 10, 1000, IN },
103 1.3.4.2 yamt { A, 0, 10, 14380, 8760, OUT },
104 1.3.4.2 yamt /* --- */
105 1.3.4.2 yamt { A, 1460, 14380, 10, 1000, IN },
106 1.3.4.2 yamt { A, 1460, 23140, 10, 1000, IN|ERR },
107 1.3.4.2 yamt { CLEAR },
108 1.3.4.2 yamt
109 1.3.4.2 yamt };
110 1.3.4.2 yamt
111 1.3.4.2 yamt #undef S
112 1.3.4.2 yamt #undef A
113 1.3.4.2 yamt #undef F
114 1.3.4.2 yamt
115 1.3.4.2 yamt static struct mbuf *
116 1.3.4.2 yamt construct_packet(const tcp_meta_t *p)
117 1.3.4.2 yamt {
118 1.3.4.2 yamt struct mbuf *m = mbuf_construct(IPPROTO_TCP);
119 1.3.4.2 yamt struct ip *ip;
120 1.3.4.2 yamt struct tcphdr *th;
121 1.3.4.2 yamt
122 1.3.4.2 yamt th = mbuf_return_hdrs(m, false, &ip);
123 1.3.4.2 yamt
124 1.3.4.2 yamt /* Imitate TCP payload, set TCP sequence numbers, flags and window. */
125 1.3.4.2 yamt ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + p->tlen);
126 1.3.4.2 yamt th->th_seq = htonl(p->seq);
127 1.3.4.2 yamt th->th_ack = htonl(p->ack);
128 1.3.4.2 yamt th->th_flags = p->tcpfl;
129 1.3.4.2 yamt th->th_win = htons(p->win);
130 1.3.4.2 yamt return m;
131 1.3.4.2 yamt }
132 1.3.4.2 yamt
133 1.3.4.2 yamt static bool
134 1.3.4.2 yamt process_packet(const int i, npf_state_t *nst, bool *snew)
135 1.3.4.2 yamt {
136 1.3.4.2 yamt const tcp_meta_t *p = &packet_sequence[i];
137 1.3.4.2 yamt npf_cache_t npc = { .npc_info = 0 };
138 1.3.4.2 yamt nbuf_t *nbuf;
139 1.3.4.2 yamt int ret;
140 1.3.4.2 yamt
141 1.3.4.2 yamt if (p->flags == 0) {
142 1.3.4.2 yamt npf_state_destroy(nst);
143 1.3.4.2 yamt *snew = true;
144 1.3.4.2 yamt return true;
145 1.3.4.2 yamt }
146 1.3.4.2 yamt
147 1.3.4.2 yamt nbuf = (nbuf_t *)construct_packet(p);
148 1.3.4.2 yamt ret = npf_cache_all(&npc, nbuf);
149 1.3.4.2 yamt KASSERT((ret & NPC_IPFRAG) == 0);
150 1.3.4.2 yamt
151 1.3.4.2 yamt if (*snew) {
152 1.3.4.2 yamt ret = npf_state_init(&npc, nbuf, nst);
153 1.3.4.2 yamt KASSERT(ret == true);
154 1.3.4.2 yamt *snew = false;
155 1.3.4.2 yamt }
156 1.3.4.2 yamt ret = npf_state_inspect(&npc, nbuf, nst, p->flags == OUT);
157 1.3.4.2 yamt m_freem(nbuf);
158 1.3.4.2 yamt
159 1.3.4.2 yamt return ret ? true : (p->flags & ERR) != 0;
160 1.3.4.2 yamt }
161 1.3.4.2 yamt
162 1.3.4.2 yamt bool
163 1.3.4.2 yamt npf_state_test(bool verbose)
164 1.3.4.2 yamt {
165 1.3.4.2 yamt npf_state_t nst;
166 1.3.4.2 yamt bool snew = true;
167 1.3.4.2 yamt bool ok = true;
168 1.3.4.2 yamt
169 1.3.4.2 yamt for (u_int i = 0; i < __arraycount(packet_sequence); i++) {
170 1.3.4.2 yamt if (process_packet(i, &nst, &snew)) {
171 1.3.4.2 yamt continue;
172 1.3.4.2 yamt }
173 1.3.4.2 yamt if (verbose) {
174 1.3.4.2 yamt printf("Failed on packet %d, state dump:\n", i);
175 1.3.4.2 yamt npf_state_dump(&nst);
176 1.3.4.2 yamt }
177 1.3.4.2 yamt ok = false;
178 1.3.4.2 yamt }
179 1.3.4.2 yamt return ok;
180 1.3.4.2 yamt }
181