| @@ -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 | */ |
82 | static const u_int npf_tcp_timeouts[] __read_mostly = { | | 82 | static 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 | |
| | | 113 | static inline u_int |
| | | 114 | npf_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 | |
116 | static const int npf_tcp_fsm[NPF_TCP_NSTATES][2][TH_STATE_MASK + 1] | | 139 | static 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 | */ |
261 | static bool | | 274 | static bool |
262 | npf_tcp_inwindow(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, | | 275 | npf_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 | |
421 | bool | | 434 | bool |
422 | npf_state_tcp(const npf_cache_t *npc, nbuf_t *nbuf, npf_state_t *nst, int di) | | 435 | npf_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 | } |