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