Mon Dec 5 00:34:25 2011 UTC ()
- Add npf_tcpfl2case() and make TCP state table more compact.
- Adjust the state for FIN case on sim-SYN and SYN-RECEIVED.


(rmind)
diff -r1.1 -r1.2 src/sys/net/npf/npf_state_tcp.c

cvs diff -r1.1 -r1.2 src/sys/net/npf/npf_state_tcp.c (expand / switch to unified diff)

--- src/sys/net/npf/npf_state_tcp.c 2011/11/29 20:05:30 1.1
+++ src/sys/net/npf/npf_state_tcp.c 2011/12/05 00:34:25 1.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $ */ 1/* $NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010-2011 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010-2011 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This material is based upon work partially supported by The 7 * This material is based upon work partially supported by The
8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * NPF TCP state engine for connection tracking. 33 * NPF TCP state engine for connection tracking.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.1 2011/11/29 20:05:30 rmind Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: npf_state_tcp.c,v 1.2 2011/12/05 00:34:25 rmind Exp $");
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/types.h> 40#include <sys/types.h>
41 41
42#ifndef _KERNEL 42#ifndef _KERNEL
43#include <stdio.h> 43#include <stdio.h>
44#include <stdbool.h> 44#include <stdbool.h>
45#include <inttypes.h> 45#include <inttypes.h>
46#endif 46#endif
47#include <netinet/in.h> 47#include <netinet/in.h>
48#include <netinet/tcp.h> 48#include <netinet/tcp.h>
49#include <netinet/tcp_seq.h> 49#include <netinet/tcp_seq.h>
50 50
@@ -69,197 +69,210 @@ void npf_state_sample(npf_state_t *); @@ -69,197 +69,210 @@ void npf_state_sample(npf_state_t *);
69#define NPF_TCPS_ESTABLISHED 4 69#define NPF_TCPS_ESTABLISHED 4
70#define NPF_TCPS_FIN_SEEN 5 70#define NPF_TCPS_FIN_SEEN 5
71#define NPF_TCPS_CLOSE_WAIT 6 71#define NPF_TCPS_CLOSE_WAIT 6
72#define NPF_TCPS_FIN_WAIT 7 72#define NPF_TCPS_FIN_WAIT 7
73#define NPF_TCPS_CLOSING 8 73#define NPF_TCPS_CLOSING 8
74#define NPF_TCPS_LAST_ACK 9 74#define NPF_TCPS_LAST_ACK 9
75#define NPF_TCPS_TIME_WAIT 10 75#define NPF_TCPS_TIME_WAIT 10
76 76
77#define NPF_TCP_NSTATES 11 77#define NPF_TCP_NSTATES 11
78 78
79/* 79/*
80 * TCP connection timeout table (in seconds). 80 * TCP connection timeout table (in seconds).
81 */ 81 */
82static const u_int npf_tcp_timeouts[] __read_mostly = { 82static u_int npf_tcp_timeouts[] __read_mostly = {
83 /* Closed, timeout nearly immediately. */ 83 /* Closed, timeout nearly immediately. */
84 [NPF_TCPS_CLOSED] = 10, 84 [NPF_TCPS_CLOSED] = 10,
85 /* Unsynchronised states. */ 85 /* Unsynchronised states. */
86 [NPF_TCPS_SYN_SENT] = 30, 86 [NPF_TCPS_SYN_SENT] = 30,
87 [NPF_TCPS_SIMSYN_SENT] = 30, 87 [NPF_TCPS_SIMSYN_SENT] = 30,
88 [NPF_TCPS_SYN_RECEIVED] = 60, 88 [NPF_TCPS_SYN_RECEIVED] = 60,
89 /* Established, timeout: 24 hours. */ 89 /* Established, timeout: 24 hours. */
90 [NPF_TCPS_ESTABLISHED] = 60 * 60 * 24, 90 [NPF_TCPS_ESTABLISHED] = 60 * 60 * 24,
91 /* Closure cases, timeout: 4 minutes (2 * MSL). */ 91 /* Closure cases, timeout: 4 minutes (2 * MSL). */
92 [NPF_TCPS_FIN_SEEN] = 60 * 2 * 2, 92 [NPF_TCPS_FIN_SEEN] = 60 * 2 * 2,
93 [NPF_TCPS_CLOSE_WAIT] = 60 * 2 * 2, 93 [NPF_TCPS_CLOSE_WAIT] = 60 * 2 * 2,
94 [NPF_TCPS_FIN_WAIT] = 60 * 2 * 2, 94 [NPF_TCPS_FIN_WAIT] = 60 * 2 * 2,
95 [NPF_TCPS_CLOSING] = 30, 95 [NPF_TCPS_CLOSING] = 30,
96 [NPF_TCPS_LAST_ACK] = 30, 96 [NPF_TCPS_LAST_ACK] = 30,
97 [NPF_TCPS_TIME_WAIT] = 60 * 2 * 2, 97 [NPF_TCPS_TIME_WAIT] = 60 * 2 * 2,
98}; 98};
99 99
100#define NPF_TCP_MAXACKWIN 66000 100#define NPF_TCP_MAXACKWIN 66000
101 101
102#define TH_STATE_MASK (TH_SYN | TH_ACK | TH_FIN) 102/*
103#define TH_SYNACK (TH_SYN | TH_ACK) 103 * List of TCP flag cases and conversion of flags to a case (index).
104#define TH_FINACK (TH_FIN | TH_ACK) 104 */
 105
 106#define TCPFC_INVALID 0
 107#define TCPFC_SYN 1
 108#define TCPFC_SYNACK 2
 109#define TCPFC_ACK 3
 110#define TCPFC_FIN 4
 111#define TCPFC_COUNT 5
 112
 113static inline u_int
 114npf_tcpfl2case(const int tcpfl)
 115{
 116 u_int i, c;
 117
 118 /*
 119 * Magic value maps flag combinations to TCPFC case numbers.
 120 * Other cases are zero. Note: FIN-ACK is mapped to FIN.
 121 */
 122 i = (tcpfl & (TH_SYN | TH_FIN)) | ((tcpfl & TH_ACK) >> 2);
 123 c = (0x2430140 >> (i << 2)) & 7;
 124
 125 KASSERT(c < TCPFC_COUNT);
 126 return c;
 127}
105 128
106/* 129/*
107 * NPF transition table of a tracked TCP connection. 130 * NPF transition table of a tracked TCP connection.
108 * 131 *
109 * There is a single state, which is changed in the following way: 132 * There is a single state, which is changed in the following way:
110 * 133 *
111 * new_state = npf_tcp_fsm[old_state][direction][tcp_flags & TH_STATE_MASK]; 134 * new_state = npf_tcp_fsm[old_state][direction][npf_tcpfl2case(tcp_flags)];
112 * 135 *
113 * Note that this state is different from the state in each end (host). 136 * Note that this state is different from the state in each end (host).
114 */ 137 */
115 138
116static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1] 139static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TCPFC_COUNT] = {
117 __read_mostly = { 
118 [NPF_TCPS_CLOSED] = { 140 [NPF_TCPS_CLOSED] = {
119 [NPF_FLOW_FORW] = { 141 [NPF_FLOW_FORW] = {
120 /* Handshake (1): initial SYN. */ 142 /* Handshake (1): initial SYN. */
121 [TH_SYN] = NPF_TCPS_SYN_SENT, 143 [TCPFC_SYN] = NPF_TCPS_SYN_SENT,
122 }, 144 },
123 }, 145 },
124 [NPF_TCPS_SYN_SENT] = { 146 [NPF_TCPS_SYN_SENT] = {
125 [NPF_FLOW_FORW] = { 147 [NPF_FLOW_FORW] = {
126 /* SYN may be retransmitted. */ 148 /* SYN may be retransmitted. */
127 [TH_SYN] = NPF_TCPS_OK, 149 [TCPFC_SYN] = NPF_TCPS_OK,
128 }, 150 },
129 [NPF_FLOW_BACK] = { 151 [NPF_FLOW_BACK] = {
130 /* Handshake (2): SYN-ACK is expected. */ 152 /* Handshake (2): SYN-ACK is expected. */
131 [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, 153 [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED,
132 /* Simultaneous initiation - SYN. */ 154 /* Simultaneous initiation - SYN. */
133 [TH_SYN] = NPF_TCPS_SIMSYN_SENT, 155 [TCPFC_SYN] = NPF_TCPS_SIMSYN_SENT,
134 }, 156 },
135 }, 157 },
136 [NPF_TCPS_SIMSYN_SENT] = { 158 [NPF_TCPS_SIMSYN_SENT] = {
137 [NPF_FLOW_FORW] = { 159 [NPF_FLOW_FORW] = {
138 /* Original SYN re-transmission. */ 160 /* Original SYN re-transmission. */
139 [TH_SYN] = NPF_TCPS_OK, 161 [TCPFC_SYN] = NPF_TCPS_OK,
140 /* SYN-ACK response to simultaneous SYN. */ 162 /* SYN-ACK response to simultaneous SYN. */
141 [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, 163 [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED,
142 }, 164 },
143 [NPF_FLOW_BACK] = { 165 [NPF_FLOW_BACK] = {
144 /* Simultaneous SYN re-transmission.*/ 166 /* Simultaneous SYN re-transmission.*/
145 [TH_SYN] = NPF_TCPS_OK, 167 [TCPFC_SYN] = NPF_TCPS_OK,
146 /* SYN-ACK response to original SYN. */ 168 /* SYN-ACK response to original SYN. */
147 [TH_SYNACK] = NPF_TCPS_SYN_RECEIVED, 169 [TCPFC_SYNACK] = NPF_TCPS_SYN_RECEIVED,
148 /* FIN may be sent at this point. */ 170 /* FIN may be sent early. */
149 [TH_FIN] = NPF_TCPS_FIN_SEEN, 171 [TCPFC_FIN] = NPF_TCPS_FIN_SEEN,
150 [TH_FINACK] = NPF_TCPS_FIN_SEEN, 
151 }, 172 },
152 }, 173 },
153 [NPF_TCPS_SYN_RECEIVED] = { 174 [NPF_TCPS_SYN_RECEIVED] = {
154 [NPF_FLOW_FORW] = { 175 [NPF_FLOW_FORW] = {
155 /* Handshake (3): ACK is expected. */ 176 /* Handshake (3): ACK is expected. */
156 [TH_ACK] = NPF_TCPS_ESTABLISHED, 177 [TCPFC_ACK] = NPF_TCPS_ESTABLISHED,
157 [TH_FIN] = NPF_TCPS_CLOSING, 178 /* FIN may be sent early. */
158 [TH_FINACK] = NPF_TCPS_CLOSING, 179 [TCPFC_FIN] = NPF_TCPS_FIN_SEEN,
159 }, 180 },
160 [NPF_FLOW_BACK] = { 181 [NPF_FLOW_BACK] = {
161 /* SYN-ACK may be retransmitted. */ 182 /* SYN-ACK may be retransmitted. */
162 [TH_SYNACK] = NPF_TCPS_OK, 183 [TCPFC_SYNACK] = NPF_TCPS_OK,
163 /* XXX: ACK of late SYN in simultaneous case? */ 184 /* XXX: ACK of late SYN in simultaneous case? */
164 [TH_ACK] = NPF_TCPS_OK, 185 [TCPFC_ACK] = NPF_TCPS_OK,
165 /* XXX: Can this happen? 186 /* FIN may be sent early. */
166 [TH_FIN] = NPF_TCPS_CLOSING, */ 187 [TCPFC_FIN] = NPF_TCPS_FIN_SEEN,
167 }, 188 },
168 }, 189 },
169 [NPF_TCPS_ESTABLISHED] = { 190 [NPF_TCPS_ESTABLISHED] = {
170 /* 191 /*
171 * Regular ACKs (data exchange) or FIN. 192 * Regular ACKs (data exchange) or FIN.
172 * FIN packets may have ACK set. 193 * FIN packets may have ACK set.
173 */ 194 */
174 [NPF_FLOW_FORW] = { 195 [NPF_FLOW_FORW] = {
175 [TH_ACK] = NPF_TCPS_OK, 196 [TCPFC_ACK] = NPF_TCPS_OK,
176 /* FIN by the sender. */ 197 /* FIN by the sender. */
177 [TH_FIN] = NPF_TCPS_FIN_SEEN, 198 [TCPFC_FIN] = NPF_TCPS_FIN_SEEN,
178 [TH_FINACK] = NPF_TCPS_FIN_SEEN, 
179 }, 199 },
180 [NPF_FLOW_BACK] = { 200 [NPF_FLOW_BACK] = {
181 [TH_ACK] = NPF_TCPS_OK, 201 [TCPFC_ACK] = NPF_TCPS_OK,
182 /* FIN by the receiver. */ 202 /* FIN by the receiver. */
183 [TH_FIN] = NPF_TCPS_FIN_SEEN, 203 [TCPFC_FIN] = NPF_TCPS_FIN_SEEN,
184 [TH_FINACK] = NPF_TCPS_FIN_SEEN, 
185 }, 204 },
186 }, 205 },
187 [NPF_TCPS_FIN_SEEN] = { 206 [NPF_TCPS_FIN_SEEN] = {
188 /* 207 /*
189 * FIN was seen. If ACK only, connection is half-closed now, 208 * FIN was seen. If ACK only, connection is half-closed now,
190 * need to determine which end is closed (sender or receiver). 209 * need to determine which end is closed (sender or receiver).
191 * However, both FIN and FIN-ACK may race here - in which 210 * However, both FIN and FIN-ACK may race here - in which
192 * case we are closing immediately. 211 * case we are closing immediately.
193 */ 212 */
194 [NPF_FLOW_FORW] = { 213 [NPF_FLOW_FORW] = {
195 [TH_ACK] = NPF_TCPS_CLOSE_WAIT, 214 [TCPFC_ACK] = NPF_TCPS_CLOSE_WAIT,
196 [TH_FIN] = NPF_TCPS_CLOSING, 215 [TCPFC_FIN] = NPF_TCPS_CLOSING,
197 [TH_FINACK] = NPF_TCPS_CLOSING, 
198 }, 216 },
199 [NPF_FLOW_BACK] = { 217 [NPF_FLOW_BACK] = {
200 [TH_ACK] = NPF_TCPS_FIN_WAIT, 218 [TCPFC_ACK] = NPF_TCPS_FIN_WAIT,
201 [TH_FIN] = NPF_TCPS_CLOSING, 219 [TCPFC_FIN] = NPF_TCPS_CLOSING,
202 [TH_FINACK] = NPF_TCPS_CLOSING, 
203 }, 220 },
204 }, 221 },
205 [NPF_TCPS_CLOSE_WAIT] = { 222 [NPF_TCPS_CLOSE_WAIT] = {
206 /* Sender has sent the FIN and closed its end. */ 223 /* Sender has sent the FIN and closed its end. */
207 [NPF_FLOW_FORW] = { 224 [NPF_FLOW_FORW] = {
208 [TH_ACK] = NPF_TCPS_OK, 225 [TCPFC_ACK] = NPF_TCPS_OK,
209 [TH_FIN] = NPF_TCPS_LAST_ACK, 226 [TCPFC_FIN] = NPF_TCPS_LAST_ACK,
210 [TH_FINACK] = NPF_TCPS_LAST_ACK, 
211 }, 227 },
212 [NPF_FLOW_BACK] = { 228 [NPF_FLOW_BACK] = {
213 [TH_ACK] = NPF_TCPS_OK, 229 [TCPFC_ACK] = NPF_TCPS_OK,
214 [TH_FIN] = NPF_TCPS_LAST_ACK, 230 [TCPFC_FIN] = NPF_TCPS_LAST_ACK,
215 [TH_FINACK] = NPF_TCPS_LAST_ACK, 
216 }, 231 },
217 }, 232 },
218 [NPF_TCPS_FIN_WAIT] = { 233 [NPF_TCPS_FIN_WAIT] = {
219 /* Receiver has closed its end. */ 234 /* Receiver has closed its end. */
220 [NPF_FLOW_FORW] = { 235 [NPF_FLOW_FORW] = {
221 [TH_ACK] = NPF_TCPS_OK, 236 [TCPFC_ACK] = NPF_TCPS_OK,
222 [TH_FIN] = NPF_TCPS_LAST_ACK, 237 [TCPFC_FIN] = NPF_TCPS_LAST_ACK,
223 [TH_FINACK] = NPF_TCPS_LAST_ACK, 
224 }, 238 },
225 [NPF_FLOW_BACK] = { 239 [NPF_FLOW_BACK] = {
226 [TH_ACK] = NPF_TCPS_OK, 240 [TCPFC_ACK] = NPF_TCPS_OK,
227 [TH_FIN] = NPF_TCPS_LAST_ACK, 241 [TCPFC_FIN] = NPF_TCPS_LAST_ACK,
228 [TH_FINACK] = NPF_TCPS_LAST_ACK, 
229 }, 242 },
230 }, 243 },
231 [NPF_TCPS_CLOSING] = { 244 [NPF_TCPS_CLOSING] = {
232 /* Race of FINs - expecting ACK. */ 245 /* Race of FINs - expecting ACK. */
233 [NPF_FLOW_FORW] = { 246 [NPF_FLOW_FORW] = {
234 [TH_ACK] = NPF_TCPS_LAST_ACK, 247 [TCPFC_ACK] = NPF_TCPS_LAST_ACK,
235 }, 248 },
236 [NPF_FLOW_BACK] = { 249 [NPF_FLOW_BACK] = {
237 [TH_ACK] = NPF_TCPS_LAST_ACK, 250 [TCPFC_ACK] = NPF_TCPS_LAST_ACK,
238 }, 251 },
239 }, 252 },
240 [NPF_TCPS_LAST_ACK] = { 253 [NPF_TCPS_LAST_ACK] = {
241 /* FINs exchanged - expecting last ACK. */ 254 /* FINs exchanged - expecting last ACK. */
242 [NPF_FLOW_FORW] = { 255 [NPF_FLOW_FORW] = {
243 [TH_ACK] = NPF_TCPS_TIME_WAIT, 256 [TCPFC_ACK] = NPF_TCPS_TIME_WAIT,
244 }, 257 },
245 [NPF_FLOW_BACK] = { 258 [NPF_FLOW_BACK] = {
246 [TH_ACK] = NPF_TCPS_TIME_WAIT, 259 [TCPFC_ACK] = NPF_TCPS_TIME_WAIT,
247 }, 260 },
248 }, 261 },
249 [NPF_TCPS_TIME_WAIT] = { 262 [NPF_TCPS_TIME_WAIT] = {
250 /* May re-open the connection as per RFC 1122. */ 263 /* May re-open the connection as per RFC 1122. */
251 [NPF_FLOW_FORW] = { 264 [NPF_FLOW_FORW] = {
252 [TH_SYN] = NPF_TCPS_SYN_SENT, 265 [TCPFC_SYN] = NPF_TCPS_SYN_SENT,
253 }, 266 },
254 }, 267 },
255}; 268};
256 269
257/* 270/*
258 * npf_tcp_inwindow: determine whether the packet is in the TCP window 271 * npf_tcp_inwindow: determine whether the packet is in the TCP window
259 * and thus part of the connection we are tracking. 272 * and thus part of the connection we are tracking.
260 */ 273 */
261static bool 274static bool
262npf_tcp_inwindow(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, 275npf_tcp_inwindow(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst,
263 const int di) 276 const int di)
264{ 277{
265 const struct tcphdr * const th = &npc->npc_l4.tcp; 278 const struct tcphdr * const th = &npc->npc_l4.tcp;
@@ -270,27 +283,27 @@ npf_tcp_inwindow(const npf_cache_t *npc, @@ -270,27 +283,27 @@ npf_tcp_inwindow(const npf_cache_t *npc,
270 uint32_t win; 283 uint32_t win;
271 284
272 KASSERT(npf_iscached(npc, NPC_TCP)); 285 KASSERT(npf_iscached(npc, NPC_TCP));
273 KASSERT(di == NPF_FLOW_FORW || di == NPF_FLOW_BACK); 286 KASSERT(di == NPF_FLOW_FORW || di == NPF_FLOW_BACK);
274 287
275 /* 288 /*
276 * Perform SEQ/ACK numbers check against boundaries. Reference: 289 * Perform SEQ/ACK numbers check against boundaries. Reference:
277 * 290 *
278 * Rooij G., "Real stateful TCP packet filtering in IP Filter", 291 * Rooij G., "Real stateful TCP packet filtering in IP Filter",
279 * 10th USENIX Security Symposium invited talk, Aug. 2001. 292 * 10th USENIX Security Symposium invited talk, Aug. 2001.
280 * 293 *
281 * There four boundaries are defined as following: 294 * There four boundaries are defined as following:
282 * I) SEQ + LEN <= MAX { SND.ACK + MAX(SND.WIN, 1) } 295 * I) SEQ + LEN <= MAX { SND.ACK + MAX(SND.WIN, 1) }
283 * II) SEQ >= MAX { SND.SEQ + SND.LEN } 296 * II) SEQ >= MAX { SND.SEQ + SND.LEN - MAX(RCV.WIN, 1) }
284 * III) ACK <= MAX { RCV.SEQ + RCV.LEN } 297 * III) ACK <= MAX { RCV.SEQ + RCV.LEN }
285 * IV) ACK >= MAX { RCV.SEQ + RCV.LEN } - MAXACKWIN 298 * IV) ACK >= MAX { RCV.SEQ + RCV.LEN } - MAXACKWIN
286 * 299 *
287 * Let these members of npf_tcpstate_t be the maximum seen values of: 300 * Let these members of npf_tcpstate_t be the maximum seen values of:
288 * nst_end - SEQ + LEN 301 * nst_end - SEQ + LEN
289 * nst_maxend - ACK + MAX(WIN, 1) 302 * nst_maxend - ACK + MAX(WIN, 1)
290 * nst_maxwin - MAX(WIN, 1) 303 * nst_maxwin - MAX(WIN, 1)
291 */ 304 */
292 305
293 tcpdlen = npf_tcpsaw(__UNCONST(npc), &seq, &ack, &win); 306 tcpdlen = npf_tcpsaw(__UNCONST(npc), &seq, &ack, &win);
294 end = seq + tcpdlen; 307 end = seq + tcpdlen;
295 if (tcpfl & TH_SYN) { 308 if (tcpfl & TH_SYN) {
296 end++; 309 end++;
@@ -417,27 +430,28 @@ npf_tcp_inwindow(const npf_cache_t *npc, @@ -417,27 +430,28 @@ npf_tcp_inwindow(const npf_cache_t *npc,
417 } 430 }
418 return true; 431 return true;
419} 432}
420 433
421bool 434bool
422npf_state_tcp(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, int di) 435npf_state_tcp(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, int di)
423{ 436{
424 const struct tcphdr * const th = &npc->npc_l4.tcp; 437 const struct tcphdr * const th = &npc->npc_l4.tcp;
425 const int tcpfl = th->th_flags, state = nst->nst_state; 438 const int tcpfl = th->th_flags, state = nst->nst_state;
426 int nstate; 439 int nstate;
427 440
428 /* Look for a transition to a new state. */ 441 /* Look for a transition to a new state. */
429 if (__predict_true((tcpfl & TH_RST) == 0)) { 442 if (__predict_true((tcpfl & TH_RST) == 0)) {
430 nstate = npf_tcp_fsm[state][di][tcpfl & TH_STATE_MASK]; 443 const int flagcase = npf_tcpfl2case(tcpfl);
 444 nstate = npf_tcp_fsm[state][di][flagcase];
431 } else if (state == NPF_TCPS_TIME_WAIT) { 445 } else if (state == NPF_TCPS_TIME_WAIT) {
432 /* Prevent TIME-WAIT assassination (RFC 1337). */ 446 /* Prevent TIME-WAIT assassination (RFC 1337). */
433 nstate = NPF_TCPS_OK; 447 nstate = NPF_TCPS_OK;
434 } else { 448 } else {
435 nstate = NPF_TCPS_CLOSED; 449 nstate = NPF_TCPS_CLOSED;
436 } 450 }
437 /* Determine whether TCP packet really belongs to this connection. */ 451 /* Determine whether TCP packet really belongs to this connection. */
438 if (!npf_tcp_inwindow(npc, nbuf, nst, di)) { 452 if (!npf_tcp_inwindow(npc, nbuf, nst, di)) {
439 return false; 453 return false;
440 } 454 }
441 if (__predict_true(nstate == NPF_TCPS_OK)) { 455 if (__predict_true(nstate == NPF_TCPS_OK)) {
442 return true; 456 return true;
443 } 457 }