update for HEAD-2003091401
[reactos.git] / 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                         if (direction==session->direction)
177                         {
178                                 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
179                                 if (new_ack-session->ack_srv<MAX_WINDOW)
180                                         session->ack_srv=new_ack;
181                         }
182                         else
183                         {
184                                 uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
185                                 if (new_ack-session->ack_cln<MAX_WINDOW)
186                                         session->ack_cln=new_ack;
187                         }
188                 if (flags&RST)
189                 {
190                         next_status=CLOSED_RST;
191                         break;
192                 }
193                 if (flags&FIN)
194                         if (direction==session->direction)
195                         {   /* an hack to make all things work */
196                                 session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
197                                 next_status=FIN_CLN_RCV;
198                                 break;
199                         }
200                         else
201                         {
202                                 session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
203                                 next_status=FIN_SRV_RCV;
204                                 break;
205                         }
206                 next_status=ESTABLISHED;
207                 break;
208         
209         case CLOSED_RST:
210                 next_status=CLOSED_RST;
211                 break;
212         
213         case FIN_SRV_RCV:       
214                 if (flags&SYN)
215                 {
216                         next_status=ERROR_TCP;
217                         break;
218                 }
219                         
220                 next_status=FIN_SRV_RCV;
221                 
222                 if (flags&ACK)
223                 {
224                         uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
225                         if (direction!=session->direction)
226                                 if ((new_ack-session->ack_cln)<MAX_WINDOW)
227                                         session->ack_cln=new_ack;
228                 }
229                 
230                 if (flags&RST)
231                         next_status=CLOSED_RST;
232                 else
233                         if ((flags&FIN)&&(direction==session->direction))
234                         {
235                                 session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
236                                 next_status=CLOSED_FIN;
237                         }
238
239                 break;
240
241         case FIN_CLN_RCV:
242                 if (flags&SYN)
243                 {
244                         next_status=ERROR_TCP;
245                         break;
246                 }
247                         
248                 next_status=FIN_CLN_RCV;
249                 
250                 if (flags&ACK)
251                 {
252                         uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
253                         if (direction==session->direction)
254                                 if (new_ack-session->ack_srv<MAX_WINDOW)
255                                         session->ack_srv=new_ack;
256                 }
257                 
258                 if (flags&RST)
259                         next_status=CLOSED_RST;
260                 else
261                         if ((flags&FIN)&&(direction!=session->direction))
262                         {
263                                 session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
264                                 next_status=CLOSED_FIN;
265                         }
266
267                 break;
268
269         case CLOSED_FIN:
270                         next_status=CLOSED_FIN;
271                 break;
272         default:
273                 next_status=ERROR_TCP;
274
275         }
276
277         session->status=next_status;
278         
279         if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
280                 session->timestamp_block=session->last_timestamp;
281         
282         return TME_SUCCESS;
283 }
284