npf_state_test.c revision 1.1 1 1.1 rmind /* $NetBSD: npf_state_test.c,v 1.1 2012/06/04 00:28:34 rmind Exp $ */
2 1.1 rmind
3 1.1 rmind /*
4 1.1 rmind * NPF state tracking test.
5 1.1 rmind *
6 1.1 rmind * Public Domain.
7 1.1 rmind */
8 1.1 rmind
9 1.1 rmind #include <sys/types.h>
10 1.1 rmind #include <sys/kmem.h>
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.1 rmind /* Out of window. */
73 1.1 rmind { S, 0, 9, 0, 8760, OUT },
74 1.1 rmind { S|A, 0, 9999, 10, 1000, IN },
75 1.1 rmind { A, 0, 10, 10000, 8760, OUT },
76 1.1 rmind /* --- */
77 1.1 rmind { A, 1460, 10000, 10, 1000, IN },
78 1.1 rmind { A, 1460, 11460, 10, 1000, IN },
79 1.1 rmind { A, 0, 10, 12920, 8760, OUT },
80 1.1 rmind { A, 1460, 12920, 10, 1000, IN },
81 1.1 rmind { A, 0, 10, 14380, 8760, OUT },
82 1.1 rmind { A, 1460, 17300, 10, 1000, IN },
83 1.1 rmind { A, 0, 10, 14380, 8760, OUT },
84 1.1 rmind { A, 1460, 18760, 10, 1000, IN },
85 1.1 rmind { A, 0, 10, 14380, 8760, OUT },
86 1.1 rmind { A, 1460, 20220, 10, 1000, IN },
87 1.1 rmind { A, 0, 10, 14380, 8760, OUT },
88 1.1 rmind { A, 1460, 21680, 10, 1000, IN },
89 1.1 rmind { A, 0, 10, 14380, 8760, OUT },
90 1.1 rmind /* --- */
91 1.1 rmind { A, 1460, 14380, 10, 1000, IN },
92 1.1 rmind { A, 1460, 23140, 10, 1000, IN|ERR },
93 1.1 rmind { CLEAR },
94 1.1 rmind
95 1.1 rmind };
96 1.1 rmind
97 1.1 rmind #undef S
98 1.1 rmind #undef A
99 1.1 rmind #undef F
100 1.1 rmind
101 1.1 rmind static struct mbuf *
102 1.1 rmind construct_packet(const tcp_meta_t *p)
103 1.1 rmind {
104 1.1 rmind struct mbuf *m = mbuf_construct(IPPROTO_TCP);
105 1.1 rmind struct ip *ip;
106 1.1 rmind struct tcphdr *th;
107 1.1 rmind
108 1.1 rmind th = mbuf_return_hdrs(m, false, &ip);
109 1.1 rmind
110 1.1 rmind /* Imitate TCP payload, set TCP sequence numbers, flags and window. */
111 1.1 rmind ip->ip_len = htons(sizeof(struct ip) + sizeof(struct tcphdr) + p->tlen);
112 1.1 rmind th->th_seq = htonl(p->seq);
113 1.1 rmind th->th_ack = htonl(p->ack);
114 1.1 rmind th->th_flags = p->tcpfl;
115 1.1 rmind th->th_win = htons(p->win);
116 1.1 rmind return m;
117 1.1 rmind }
118 1.1 rmind
119 1.1 rmind static bool
120 1.1 rmind process_packet(const int i, npf_state_t *nst, bool *snew)
121 1.1 rmind {
122 1.1 rmind const tcp_meta_t *p = &packet_sequence[i];
123 1.1 rmind npf_cache_t npc = { .npc_info = 0 };
124 1.1 rmind nbuf_t *nbuf;
125 1.1 rmind int ret;
126 1.1 rmind
127 1.1 rmind if (p->flags == 0) {
128 1.1 rmind npf_state_destroy(nst);
129 1.1 rmind *snew = true;
130 1.1 rmind return true;
131 1.1 rmind }
132 1.1 rmind
133 1.1 rmind nbuf = (nbuf_t *)construct_packet(p);
134 1.1 rmind ret = npf_cache_all(&npc, nbuf);
135 1.1 rmind KASSERT((ret & NPC_IPFRAG) == 0);
136 1.1 rmind
137 1.1 rmind if (*snew) {
138 1.1 rmind ret = npf_state_init(&npc, nbuf, nst);
139 1.1 rmind KASSERT(ret == true);
140 1.1 rmind *snew = false;
141 1.1 rmind }
142 1.1 rmind ret = npf_state_inspect(&npc, nbuf, nst, p->flags == OUT);
143 1.1 rmind m_freem(nbuf);
144 1.1 rmind
145 1.1 rmind return ret ? true : (p->flags & ERR) != 0;
146 1.1 rmind }
147 1.1 rmind
148 1.1 rmind bool
149 1.1 rmind npf_state_test(bool verbose)
150 1.1 rmind {
151 1.1 rmind npf_state_t nst;
152 1.1 rmind bool snew = true;
153 1.1 rmind
154 1.1 rmind for (u_int i = 0; i < __arraycount(packet_sequence); i++) {
155 1.1 rmind if (process_packet(i, &nst, &snew)) {
156 1.1 rmind continue;
157 1.1 rmind }
158 1.1 rmind if (verbose) {
159 1.1 rmind printf("Failed on packet %d, state dump:\n", i);
160 1.1 rmind npf_state_dump(&nst);
161 1.1 rmind }
162 1.1 rmind return false;
163 1.1 rmind }
164 1.1 rmind return true;
165 1.1 rmind }
166