- Get afd to build.
[reactos.git] / reactos / drivers / net / npf / tcp_session.c
1 /*
2 * Copyright (c) 2001
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifdef WIN32
23 #include "tme.h"
24 #include "tcp_session.h"
25 #endif
26
27 #ifdef __FreeBSD
28
29 #ifdef _KERNEL
30 #include <net/tme/tme.h>
31 #include <net/tme/tcp_session.h>
32 #else
33 #include <tme/tme.h>
34 #include <tme/tcp_session.h>
35 #endif
36
37 #endif
38
39 uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
40
41 {
42
43 uint32 next_status;
44 uint32 direction=ULONG_AT(mem_data,12);
45 uint8 flags=mem_ex->buffer[25];
46 tcp_data *session=(tcp_data*)(block+data->key_len*4);
47
48 session->last_timestamp=session->timestamp_block;
49 session->timestamp_block.tv_sec=0x7fffffff;
50
51 if (direction==session->direction)
52 {
53 session->pkts_cln_to_srv++;
54 session->bytes_cln_to_srv+=pkt_size;
55 }
56 else
57 {
58 session->pkts_srv_to_cln++;
59 session->bytes_srv_to_cln+=pkt_size;
60 }
61 /* we use only thes four flags, we don't need PSH or URG */
62 flags&=(ACK|FIN|SYN|RST);
63
64 switch (session->status)
65 {
66 case ERROR_TCP:
67 next_status=ERROR_TCP;
68 break;
69
70 case UNKNOWN:
71 if (flags==SYN)
72 {
73 if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
74 {
75
76 next_status=ERROR_TCP;
77 break;
78 }
79 next_status=SYN_RCV;
80 session->syn_timestamp=session->last_timestamp;
81
82 session->direction=direction;
83 session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
84 }
85 else
86 next_status=UNKNOWN;
87 break;
88
89 case SYN_RCV:
90 if ((flags&RST)&&(direction!=session->direction))
91 {
92 next_status=CLOSED_RST;
93 break;
94 }
95 if ((flags==SYN)&&(direction==session->direction))
96 { /* two syns... */
97 next_status=SYN_RCV;
98 session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
99 break;
100 }
101
102 if ((flags==(SYN|ACK))&&(direction!=session->direction))
103 {
104 if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
105 {
106 next_status=ERROR_TCP;
107 break;
108 }
109 next_status=SYN_ACK_RCV;
110
111 session->syn_ack_timestamp=session->last_timestamp;
112
113 session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
114 session->ack_cln=session->seq_n_0_cln+1;
115 }
116 else
117 {
118 next_status=ERROR_TCP;
119 }
120 break;
121
122 case SYN_ACK_RCV:
123 if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
124 {
125 next_status=CLOSED_RST;
126 session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
127 break;
128 }
129
130 if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
131 {
132 if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
133 {
134 next_status=ERROR_TCP;
135 break;
136 }
137 next_status=ESTABLISHED;
138 session->ack_srv=session->seq_n_0_srv+1;
139 break;
140 }
141 if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
142 {
143 next_status=SYN_ACK_RCV;
144 break;
145 }
146
147 next_status=ERROR_TCP;
148 break;
149
150 case ESTABLISHED:
151 if (flags&SYN)
152 {
153 if ((flags&ACK)&&
154 (direction!=session->direction)&&
155 ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
156 )
157 { /* SYN_ACK duplicato */
158 next_status=ESTABLISHED;
159 break;
160 }
161
162 if ((!(flags&ACK))&&
163 (direction==session->direction)&&
164 (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
165 (ULONG_AT(mem_ex->buffer,20)==0)
166 )
167 { /* syn duplicato */
168 next_status=ESTABLISHED;
169 break;
170 }
171
172 next_status=ERROR_TCP;
173 break;
174 }
175 if (flags&ACK)
176 {
177 if (direction==session->direction)
178 {
179 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
180 if (new_ack-session->ack_srv<MAX_WINDOW)
181 session->ack_srv=new_ack;
182 }
183 else
184 {
185 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
186 if (new_ack-session->ack_cln<MAX_WINDOW)
187 session->ack_cln=new_ack;
188 }
189 }
190 if (flags&RST)
191 {
192 next_status=CLOSED_RST;
193 break;
194 }
195 if (flags&FIN)
196 {
197 if (direction==session->direction)
198 { /* an hack to make all things work */
199 session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
200 next_status=FIN_CLN_RCV;
201 break;
202 }
203 else
204 {
205 session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
206 next_status=FIN_SRV_RCV;
207 break;
208 }
209 }
210 next_status=ESTABLISHED;
211 break;
212
213 case CLOSED_RST:
214 next_status=CLOSED_RST;
215 break;
216
217 case FIN_SRV_RCV:
218 if (flags&SYN)
219 {
220 next_status=ERROR_TCP;
221 break;
222 }
223
224 next_status=FIN_SRV_RCV;
225
226 if (flags&ACK)
227 {
228 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
229 if (direction!=session->direction)
230 if ((new_ack-session->ack_cln)<MAX_WINDOW)
231 session->ack_cln=new_ack;
232 }
233
234 if (flags&RST)
235 next_status=CLOSED_RST;
236 else
237 if ((flags&FIN)&&(direction==session->direction))
238 {
239 session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
240 next_status=CLOSED_FIN;
241 }
242
243 break;
244
245 case FIN_CLN_RCV:
246 if (flags&SYN)
247 {
248 next_status=ERROR_TCP;
249 break;
250 }
251
252 next_status=FIN_CLN_RCV;
253
254 if (flags&ACK)
255 {
256 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
257 if (direction==session->direction)
258 if (new_ack-session->ack_srv<MAX_WINDOW)
259 session->ack_srv=new_ack;
260 }
261
262 if (flags&RST)
263 next_status=CLOSED_RST;
264 else
265 if ((flags&FIN)&&(direction!=session->direction))
266 {
267 session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
268 next_status=CLOSED_FIN;
269 }
270
271 break;
272
273 case CLOSED_FIN:
274 next_status=CLOSED_FIN;
275 break;
276 default:
277 next_status=ERROR_TCP;
278
279 }
280
281 session->status=next_status;
282
283 if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
284 session->timestamp_block=session->last_timestamp;
285
286 return TME_SUCCESS;
287 }
288