Rev 1773 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1773 | Rev 1774 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; Part of the tcp/ip network stack for KolibriOS ;; |
6 | ;; Part of the tcp/ip network stack for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; Based on the code of 4.4BSD ;; |
10 | ;; Based on the code of 4.4BSD ;; |
11 | ;; ;; |
11 | ;; ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
12 | ;; GNU GENERAL PUBLIC LICENSE ;; |
13 | ;; Version 2, June 1991 ;; |
13 | ;; Version 2, June 1991 ;; |
14 | ;; ;; |
14 | ;; ;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
15 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
16 | 16 | ||
17 | $Revision: 1773 $ |
17 | $Revision: 1774 $ |
18 | 18 | ||
19 | ;----------------------------------------------------------------- |
19 | ;----------------------------------------------------------------- |
20 | ; |
20 | ; |
21 | ; TCP_input: |
21 | ; TCP_input: |
22 | ; |
22 | ; |
23 | ; IN: [esp] = ptr to buffer |
23 | ; IN: [esp] = ptr to buffer |
24 | ; [esp+4] = buffer size |
24 | ; [esp+4] = buffer size |
25 | ; ebx = ptr to device struct |
25 | ; ebx = ptr to device struct |
26 | ; ecx = segment size |
26 | ; ecx = segment size |
27 | ; edx = ptr to TCP segment |
27 | ; edx = ptr to TCP segment |
28 | ; |
28 | ; |
29 | ; esi = ipv4 source address |
29 | ; esi = ipv4 source address |
30 | ; edi = ipv4 dest address |
30 | ; edi = ipv4 dest address |
31 | ; |
31 | ; |
32 | ; OUT: / |
32 | ; OUT: / |
33 | ; |
33 | ; |
34 | ;----------------------------------------------------------------- |
34 | ;----------------------------------------------------------------- |
35 | align 4 |
35 | align 4 |
36 | TCP_input: |
36 | TCP_input: |
37 | 37 | ||
38 | DEBUGF 1,"TCP_input size=%u ", ecx |
38 | DEBUGF 1,"TCP_input size=%u ", ecx |
39 | ; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length. |
39 | ; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length. |
40 | 40 | ||
41 | movzx eax, [edx + TCP_segment.DataOffset] |
41 | movzx eax, [edx + TCP_segment.DataOffset] |
42 | and eax, 0xf0 |
42 | and eax, 0xf0 |
43 | shr al, 2 |
43 | shr al, 2 |
44 | 44 | ||
45 | DEBUGF 1,"headersize=%u\n", eax |
45 | DEBUGF 1,"headersize=%u\n", eax |
46 | 46 | ||
47 | cmp eax, 20 |
47 | cmp eax, 20 |
48 | jl .drop_not_locked |
48 | jl .drop_not_locked |
49 | 49 | ||
50 | ;------------------------------- |
50 | ;------------------------------- |
51 | ; Now, re-calculate the checksum |
51 | ; Now, re-calculate the checksum |
52 | 52 | ||
53 | push eax ecx edx |
53 | push eax ecx edx |
54 | pushw [edx + TCP_segment.Checksum] |
54 | pushw [edx + TCP_segment.Checksum] |
55 | mov [edx + TCP_segment.Checksum], 0 |
55 | mov [edx + TCP_segment.Checksum], 0 |
56 | push esi edi |
56 | push esi edi |
57 | mov esi, edx |
57 | mov esi, edx |
58 | TCP_checksum (esp), (esp+4) |
58 | TCP_checksum (esp), (esp+4) |
59 | pop esi edi ; yes, swap them (we dont need dest addr) |
59 | pop esi edi ; yes, swap them (we dont need dest addr) |
60 | pop cx ; previous checksum |
60 | pop cx ; previous checksum |
61 | cmp cx, dx |
61 | cmp cx, dx |
62 | pop edx ecx esi |
62 | pop edx ecx esi |
63 | jnz .drop_not_locked |
63 | jnz .drop_not_locked |
64 | 64 | ||
65 | DEBUGF 1,"Checksum is correct\n" |
65 | DEBUGF 1,"Checksum is correct\n" |
66 | 66 | ||
67 | sub ecx, esi ; update packet size |
67 | sub ecx, esi ; update packet size |
68 | jl .drop_not_locked |
68 | jl .drop_not_locked |
69 | DEBUGF 1,"we got %u bytes of data\n", ecx |
69 | DEBUGF 1,"we got %u bytes of data\n", ecx |
70 | 70 | ||
71 | ;----------------------------------------------------------------------------------------- |
71 | ;----------------------------------------------------------------------------------------- |
72 | ; Check if this packet has a timestamp option (We do it here so we can process it quickly) |
72 | ; Check if this packet has a timestamp option (We do it here so we can process it quickly) |
73 | 73 | ||
74 | cmp esi, 20 + 12 ; Timestamp option is 12 bytes |
74 | cmp esi, 20 + 12 ; Timestamp option is 12 bytes |
75 | jl .no_timestamp |
75 | jl .no_timestamp |
76 | je .is_ok |
76 | je .is_ok |
77 | 77 | ||
78 | cmp byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list |
78 | cmp byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list |
79 | jne .no_timestamp |
79 | jne .no_timestamp |
80 | 80 | ||
81 | .is_ok: |
81 | .is_ok: |
82 | test [edx + TCP_segment.Flags], TH_SYN ; SYN flag must not be set |
82 | test [edx + TCP_segment.Flags], TH_SYN ; SYN flag must not be set |
83 | jnz .no_timestamp |
83 | jnz .no_timestamp |
84 | 84 | ||
85 | cmp dword [edx + TCP_segment.Data], 0x0101080a ; Timestamp header |
85 | cmp dword [edx + TCP_segment.Data], 0x0101080a ; Timestamp header |
86 | jne .no_timestamp |
86 | jne .no_timestamp |
87 | 87 | ||
88 | DEBUGF 1,"timestamp ok\n" |
88 | DEBUGF 1,"timestamp ok\n" |
89 | 89 | ||
90 | ; TODO: Parse the option |
90 | ; TODO: Parse the option |
91 | ; TODO: Set a Bit in the TCP to tell all options are parsed |
91 | ; TODO: Set a Bit in the TCP to tell all options are parsed |
92 | 92 | ||
93 | .no_timestamp: |
93 | .no_timestamp: |
94 | 94 | ||
95 | ;------------------------------------------- |
95 | ;------------------------------------------- |
96 | ; Convert Big-endian values to little endian |
96 | ; Convert Big-endian values to little endian |
97 | 97 | ||
98 | ntohd [edx + TCP_segment.SequenceNumber] |
98 | ntohd [edx + TCP_segment.SequenceNumber] |
99 | ntohd [edx + TCP_segment.AckNumber] |
99 | ntohd [edx + TCP_segment.AckNumber] |
100 | 100 | ||
101 | ntohw [edx + TCP_segment.Window] |
101 | ntohw [edx + TCP_segment.Window] |
102 | ntohw [edx + TCP_segment.UrgentPointer] |
102 | ntohw [edx + TCP_segment.UrgentPointer] |
103 | ntohw [edx + TCP_segment.SourcePort] |
103 | ntohw [edx + TCP_segment.SourcePort] |
104 | ntohw [edx + TCP_segment.DestinationPort] |
104 | ntohw [edx + TCP_segment.DestinationPort] |
105 | 105 | ||
106 | ;------------------------------------------------------------ |
106 | ;------------------------------------------------------------ |
107 | ; Next thing to do is find the TCB (thus, the socket pointer) |
107 | ; Next thing to do is find the TCB (thus, the socket pointer) |
108 | 108 | ||
109 | ; IP Packet TCP Destination Port = local Port |
109 | ; IP Packet TCP Destination Port = local Port |
110 | ; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0) |
110 | ; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0) |
111 | ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
111 | ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
112 | 112 | ||
113 | mov ebx, net_sockets |
113 | mov ebx, net_sockets |
114 | 114 | ||
115 | .socket_loop: |
115 | .socket_loop: |
116 | mov ebx, [ebx + SOCKET.NextPtr] |
116 | mov ebx, [ebx + SOCKET.NextPtr] |
117 | or ebx, ebx |
117 | or ebx, ebx |
118 | jz .drop_with_reset_not_locked |
118 | jz .drop_with_reset_not_locked |
119 | 119 | ||
120 | cmp [ebx + SOCKET.Domain], AF_INET4 |
120 | cmp [ebx + SOCKET.Domain], AF_INET4 |
121 | jne .socket_loop |
121 | jne .socket_loop |
122 | 122 | ||
123 | cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP |
123 | cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP |
124 | jne .socket_loop |
124 | jne .socket_loop |
125 | 125 | ||
126 | mov ax, [edx + TCP_segment.DestinationPort] |
126 | mov ax, [edx + TCP_segment.DestinationPort] |
127 | cmp [ebx + TCP_SOCKET.LocalPort], ax |
127 | cmp [ebx + TCP_SOCKET.LocalPort], ax |
128 | jne .socket_loop |
128 | jne .socket_loop |
129 | 129 | ||
130 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
130 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
131 | cmp eax, edi ; edi is source ip from packet |
131 | cmp eax, edi ; edi is source ip from packet |
132 | je @f |
132 | je @f |
133 | test eax, eax |
133 | test eax, eax |
134 | jnz .socket_loop |
134 | jnz .socket_loop |
135 | @@: |
135 | @@: |
136 | 136 | ||
137 | mov ax, [ebx + TCP_SOCKET.RemotePort] |
137 | mov ax, [ebx + TCP_SOCKET.RemotePort] |
138 | cmp [edx + TCP_segment.SourcePort] , ax |
138 | cmp [edx + TCP_segment.SourcePort] , ax |
139 | je .found_socket |
139 | je .found_socket |
140 | test ax, ax |
140 | test ax, ax |
141 | jnz .socket_loop |
141 | jnz .socket_loop |
142 | .found_socket: |
142 | .found_socket: |
143 | DEBUGF 1,"Socket ptr: %x\n", ebx |
143 | DEBUGF 1,"Socket ptr: %x\n", ebx |
144 | 144 | ||
145 | ; ebx now contains the pointer to the socket |
145 | ; ebx now contains the pointer to the socket |
146 | 146 | ||
147 | ;---------------------------- |
147 | ;---------------------------- |
148 | ; Check if socket isnt closed |
148 | ; Check if socket isnt closed |
149 | 149 | ||
150 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSED |
150 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSED |
151 | je .drop_not_locked |
151 | je .drop_not_locked |
152 | 152 | ||
153 | ;---------------- |
153 | ;---------------- |
154 | ; Lock the socket |
154 | ; Lock the socket |
155 | 155 | ||
156 | add ebx, SOCKET.lock |
156 | add ebx, SOCKET.lock |
157 | DEBUGF 1,"lock: %x\n", [ebx] |
157 | DEBUGF 1,"lock: %x\n", [ebx] |
158 | call wait_mutex |
158 | call wait_mutex |
159 | sub ebx, SOCKET.lock |
159 | sub ebx, SOCKET.lock |
160 | 160 | ||
161 | DEBUGF 1,"Socket locked\n" |
161 | DEBUGF 1,"Socket locked\n" |
162 | 162 | ||
163 | ;--------------------------------------- |
163 | ;--------------------------------------- |
164 | ; unscale the window into a 32 bit value |
164 | ; unscale the window into a 32 bit value |
165 | 165 | ||
166 | movzx eax, [edx + TCP_segment.Window] |
166 | movzx eax, [edx + TCP_segment.Window] |
167 | push ecx |
167 | push ecx |
168 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
168 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
169 | shl eax, cl |
169 | shl eax, cl |
170 | mov dword [edx + TCP_segment.Window], eax ; word after window is checksum, we dont need checksum anymore |
170 | mov dword [edx + TCP_segment.Window], eax ; word after window is checksum, we dont need checksum anymore |
171 | pop ecx |
171 | pop ecx |
172 | 172 | ||
173 | ;----------------------------------- |
173 | ;----------------------------------- |
174 | ; Is this socket a listening socket? |
174 | ; Is this socket a listening socket? |
175 | 175 | ||
176 | test [ebx + SOCKET.options], SO_ACCEPTCON |
176 | test [ebx + SOCKET.options], SO_ACCEPTCON |
177 | jz .no_listening_socket |
177 | jz .no_listening_socket |
178 | 178 | ||
179 | call SOCKET_fork |
179 | call SOCKET_fork |
180 | jz .drop |
180 | jz .drop |
181 | 181 | ||
182 | push [edx + TCP_segment.DestinationPort] |
182 | push [edx + TCP_segment.DestinationPort] |
183 | pop [eax + TCP_SOCKET.LocalPort] |
183 | pop [eax + TCP_SOCKET.LocalPort] |
184 | 184 | ||
185 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress] ;;; FIXME |
185 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress] ;;; FIXME |
186 | pop [eax + IP_SOCKET.LocalIP] |
186 | pop [eax + IP_SOCKET.LocalIP] |
187 | 187 | ||
188 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress] ;;; FIXME |
188 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress] ;;; FIXME |
189 | pop [eax + IP_SOCKET.RemoteIP] |
189 | pop [eax + IP_SOCKET.RemoteIP] |
190 | 190 | ||
191 | mov [eax + TCP_SOCKET.t_state], TCB_LISTEN |
191 | mov [eax + TCP_SOCKET.t_state], TCB_LISTEN |
192 | 192 | ||
193 | jmp .not_uni_xfer |
193 | jmp .not_uni_xfer |
194 | 194 | ||
195 | .no_listening_socket: |
195 | .no_listening_socket: |
196 | 196 | ||
197 | ;------------------------------------- |
197 | ;------------------------------------- |
198 | ; Reset idle timer and keepalive timer |
198 | ; Reset idle timer and keepalive timer |
199 | 199 | ||
200 | mov [ebx + TCP_SOCKET.t_idle], 0 |
200 | mov [ebx + TCP_SOCKET.t_idle], 0 |
201 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval |
201 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval |
202 | 202 | ||
203 | ;-------------------- |
203 | ;-------------------- |
204 | ; Process TCP options |
204 | ; Process TCP options |
205 | 205 | ||
206 | cmp esi, 20 ; esi is headersize |
206 | cmp esi, 20 ; esi is headersize |
207 | je .no_options |
207 | je .no_options |
208 | 208 | ||
209 | DEBUGF 1,"Segment has options\n" |
209 | DEBUGF 1,"Segment has options\n" |
210 | 210 | ||
211 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN ; no options when in listen state |
211 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN ; no options when in listen state |
212 | jz .not_uni_xfer ; also no header prediction |
212 | jz .not_uni_xfer ; also no header prediction |
213 | 213 | ||
214 | lea edi, [edx + TCP_segment.Data] |
214 | lea edi, [edx + TCP_segment.Data] |
215 | lea eax, [edx + esi] |
215 | lea eax, [edx + esi] |
216 | 216 | ||
217 | .opt_loop: |
217 | .opt_loop: |
218 | cmp edi, eax |
218 | cmp edi, eax |
219 | jge .no_options |
219 | jge .no_options |
220 | 220 | ||
221 | cmp byte [edi], TCP_OPT_EOL ; end of option list? |
221 | cmp byte [edi], TCP_OPT_EOL ; end of option list? |
222 | jz .no_options |
222 | jz .no_options |
223 | 223 | ||
224 | cmp byte [edi], TCP_OPT_NOP ; nop ? |
224 | cmp byte [edi], TCP_OPT_NOP ; nop ? |
225 | jz .opt_nop |
225 | jz .opt_nop |
226 | 226 | ||
227 | cmp byte [edi], TCP_OPT_MAXSEG |
227 | cmp byte [edi], TCP_OPT_MAXSEG |
228 | je .opt_maxseg |
228 | je .opt_maxseg |
229 | 229 | ||
230 | cmp byte [edi], TCP_OPT_WINDOW |
230 | cmp byte [edi], TCP_OPT_WINDOW |
231 | je .opt_window |
231 | je .opt_window |
232 | 232 | ||
233 | cmp byte [edi], TCP_OPT_TIMESTAMP |
233 | cmp byte [edi], TCP_OPT_TIMESTAMP |
234 | je .opt_timestamp |
234 | je .opt_timestamp |
235 | 235 | ||
236 | jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
236 | jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
237 | 237 | ||
238 | .opt_nop: |
238 | .opt_nop: |
239 | inc edi |
239 | inc edi |
240 | jmp .opt_loop |
240 | jmp .opt_loop |
241 | 241 | ||
242 | .opt_maxseg: |
242 | .opt_maxseg: |
243 | cmp byte [edi+1], 4 |
243 | cmp byte [edi+1], 4 |
244 | jne .no_options ; error occured, ignore all options! |
244 | jne .no_options ; error occured, ignore all options! |
245 | 245 | ||
246 | test [edx + TCP_segment.Flags], TH_SYN |
246 | test [edx + TCP_segment.Flags], TH_SYN |
247 | jz @f |
247 | jz @f |
248 | 248 | ||
249 | movzx eax, word[edi+2] |
249 | movzx eax, word[edi+2] |
250 | rol ax, 8 |
250 | rol ax, 8 |
251 | DEBUGF 1,"Maxseg: %u\n", ax |
251 | DEBUGF 1,"Maxseg: %u\n", ax |
252 | 252 | ||
253 | mov [ebx + TCP_SOCKET.t_maxseg], eax |
253 | mov [ebx + TCP_SOCKET.t_maxseg], eax |
254 | 254 | ||
255 | @@: |
255 | @@: |
256 | add edi, 4 |
256 | add edi, 4 |
257 | jmp .opt_loop |
257 | jmp .opt_loop |
258 | 258 | ||
259 | 259 | ||
260 | .opt_window: |
260 | .opt_window: |
261 | cmp byte [edi+1], 3 |
261 | cmp byte [edi+1], 3 |
262 | jne .no_options |
262 | jne .no_options |
263 | 263 | ||
264 | test [edx + TCP_segment.Flags], TH_SYN |
264 | test [edx + TCP_segment.Flags], TH_SYN |
265 | jz @f |
265 | jz @f |
266 | 266 | ||
267 | DEBUGF 1,"Got window option\n" |
267 | DEBUGF 1,"Got window option\n" |
268 | 268 | ||
269 | ;;;;; |
269 | ;;;;; |
270 | @@: |
270 | @@: |
271 | add edi, 3 |
271 | add edi, 3 |
272 | jmp .opt_loop |
272 | jmp .opt_loop |
273 | 273 | ||
274 | 274 | ||
275 | .opt_timestamp: |
275 | .opt_timestamp: |
276 | cmp byte [edi+1], 10 |
276 | cmp byte [edi+1], 10 |
277 | jne .no_options |
277 | jne .no_options |
278 | 278 | ||
279 | DEBUGF 1,"Got timestamp option\n" |
279 | DEBUGF 1,"Got timestamp option\n" |
280 | 280 | ||
281 | ;;;;; |
281 | ;;;;; |
282 | 282 | ||
283 | add edi, 10 |
283 | add edi, 10 |
284 | jmp .opt_loop |
284 | jmp .opt_loop |
285 | 285 | ||
286 | .no_options: |
286 | .no_options: |
287 | 287 | ||
288 | 288 | ||
289 | 289 | ||
290 | 290 | ||
291 | 291 | ||
292 | 292 | ||
293 | ;----------------------------------------------------------------------- |
293 | ;----------------------------------------------------------------------- |
294 | ; Time to do some header prediction (Original Principle by Van Jacobson) |
294 | ; Time to do some header prediction (Original Principle by Van Jacobson) |
295 | 295 | ||
296 | ; There are two common cases for an uni-directional data transfer. |
296 | ; There are two common cases for an uni-directional data transfer. |
297 | ; |
297 | ; |
298 | ; General rule: the packets has no control flags, is in-sequence, |
298 | ; General rule: the packets has no control flags, is in-sequence, |
299 | ; window width didnt change and we're not retransmitting. |
299 | ; window width didnt change and we're not retransmitting. |
300 | ; |
300 | ; |
301 | ; Second rules: |
301 | ; Second rules: |
302 | ; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer. |
302 | ; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer. |
303 | ; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer |
303 | ; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer |
304 | ; |
304 | ; |
305 | ; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer. |
305 | ; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer. |
306 | ; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK |
306 | ; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK |
307 | 307 | ||
308 | cmp [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
308 | cmp [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
309 | jnz .not_uni_xfer |
309 | jnz .not_uni_xfer |
310 | 310 | ||
311 | test [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG |
311 | test [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG |
312 | jnz .not_uni_xfer |
312 | jnz .not_uni_xfer |
313 | 313 | ||
314 | test [edx + TCP_segment.Flags], TH_ACK |
314 | test [edx + TCP_segment.Flags], TH_ACK |
315 | jz .not_uni_xfer |
315 | jz .not_uni_xfer |
316 | 316 | ||
317 | mov eax, [edx + TCP_segment.SequenceNumber] |
317 | mov eax, [edx + TCP_segment.SequenceNumber] |
318 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
318 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
319 | jne .not_uni_xfer |
319 | jne .not_uni_xfer |
320 | 320 | ||
321 | mov eax, dword [edx + TCP_segment.Window] |
321 | mov eax, dword [edx + TCP_segment.Window] |
322 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
322 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
323 | jne .not_uni_xfer |
323 | jne .not_uni_xfer |
324 | 324 | ||
325 | mov eax, [ebx + TCP_SOCKET.SND_NXT] |
325 | mov eax, [ebx + TCP_SOCKET.SND_NXT] |
326 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
326 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
327 | jne .not_uni_xfer |
327 | jne .not_uni_xfer |
328 | 328 | ||
329 | ;--------------------------------------- |
329 | ;--------------------------------------- |
330 | ; check if we are sender in the uni-xfer |
330 | ; check if we are sender in the uni-xfer |
331 | 331 | ||
332 | ; If the following 4 conditions are all true, this segment is a pure ACK. |
332 | ; If the following 4 conditions are all true, this segment is a pure ACK. |
333 | ; |
333 | ; |
334 | ; - The segment contains no data. |
334 | ; - The segment contains no data. |
335 | test ecx, ecx |
335 | test ecx, ecx |
336 | jnz .not_sender |
336 | jnz .not_sender |
337 | 337 | ||
338 | ; - The congestion window is greater than or equal to the current send window. |
338 | ; - The congestion window is greater than or equal to the current send window. |
339 | ; This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance. |
339 | ; This test is true only if the window is fully open, that is, the connection is not in the middle of slow start or congestion avoidance. |
340 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
340 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
341 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
341 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
342 | jl .not_uni_xfer |
342 | jl .not_uni_xfer |
343 | 343 | ||
344 | ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent. |
344 | ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent. |
345 | mov eax, [edx + TCP_segment.AckNumber] |
345 | mov eax, [edx + TCP_segment.AckNumber] |
346 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
346 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
347 | jg .not_uni_xfer |
347 | jg .not_uni_xfer |
348 | 348 | ||
349 | ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number. |
349 | ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number. |
350 | sub eax, [ebx + TCP_SOCKET.SND_UNA] |
350 | sub eax, [ebx + TCP_SOCKET.SND_UNA] |
351 | jle .not_uni_xfer |
351 | jle .not_uni_xfer |
352 | 352 | ||
353 | DEBUGF 1,"Header prediction: we are sender\n" |
353 | DEBUGF 1,"Header prediction: we are sender\n" |
354 | 354 | ||
355 | ;--------------------------------- |
355 | ;--------------------------------- |
356 | ; Packet is a pure ACK, process it |
356 | ; Packet is a pure ACK, process it |
357 | 357 | ||
358 | ; Update RTT estimators |
358 | ; Update RTT estimators |
359 | 359 | ||
360 | ;;; TODO |
360 | ;;; TODO |
361 | 361 | ||
362 | ; Delete acknowledged bytes from send buffer |
362 | ; Delete acknowledged bytes from send buffer |
363 | pusha |
363 | pusha |
364 | mov ecx, eax |
364 | mov ecx, eax |
365 | lea eax, [ebx + STREAM_SOCKET.snd] |
365 | lea eax, [ebx + STREAM_SOCKET.snd] |
366 | call SOCKET_ring_free |
366 | call SOCKET_ring_free |
367 | popa |
367 | popa |
368 | 368 | ||
369 | ; update window pointers |
369 | ; update window pointers |
370 | mov eax, [edx + TCP_segment.AckNumber] |
370 | mov eax, [edx + TCP_segment.AckNumber] |
371 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
371 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
372 | 372 | ||
373 | ; Stop retransmit timer |
373 | ; Stop retransmit timer |
374 | mov [ebx + TCP_SOCKET.timer_ack], 0 |
374 | mov [ebx + TCP_SOCKET.timer_ack], 0 |
375 | 375 | ||
376 | ; Awaken waiting processes |
376 | ; Awaken waiting processes |
377 | mov [ebx + SOCKET.lock], 0 |
377 | mov [ebx + SOCKET.lock], 0 |
378 | mov eax, ebx |
378 | mov eax, ebx |
379 | call SOCKET_notify_owner |
379 | call SOCKET_notify_owner |
380 | 380 | ||
381 | ; Generate more output |
381 | ; Generate more output |
382 | call TCP_output |
382 | call TCP_output |
383 | 383 | ||
384 | jmp .drop_not_locked |
384 | jmp .drop_not_locked |
385 | 385 | ||
386 | ;------------------------------------------------- |
386 | ;------------------------------------------------- |
387 | ; maybe we are the receiver in the uni-xfer then.. |
387 | ; maybe we are the receiver in the uni-xfer then.. |
388 | 388 | ||
389 | .not_sender: |
389 | .not_sender: |
390 | ; - The amount of data in the segment is greater than 0 (data count is in ecx) |
390 | ; - The amount of data in the segment is greater than 0 (data count is in ecx) |
391 | 391 | ||
392 | ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment. |
392 | ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment. |
393 | mov eax, [edx + TCP_segment.AckNumber] |
393 | mov eax, [edx + TCP_segment.AckNumber] |
394 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
394 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
395 | jne .not_uni_xfer |
395 | jne .not_uni_xfer |
396 | 396 | ||
397 | ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). |
397 | ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). |
398 | 398 | ||
399 | ;;; TODO |
399 | ;;; TODO |
400 | 400 | ||
401 | jnz .not_uni_xfer |
401 | jnz .not_uni_xfer |
402 | 402 | ||
403 | ; Complete processing of received data |
403 | ; Complete processing of received data |
404 | 404 | ||
405 | DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx |
405 | DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx |
406 | 406 | ||
407 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
407 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
408 | 408 | ||
409 | add esi, edx |
409 | add esi, edx |
410 | lea eax, [ebx + STREAM_SOCKET.rcv] |
410 | lea eax, [ebx + STREAM_SOCKET.rcv] |
411 | call SOCKET_ring_write ; Add the data to the socket buffer |
411 | call SOCKET_ring_write ; Add the data to the socket buffer |
412 | 412 | ||
413 | mov eax, ebx |
413 | mov eax, ebx |
414 | call SOCKET_notify_owner |
414 | call SOCKET_notify_owner |
415 | 415 | ||
416 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag |
416 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag |
417 | 417 | ||
418 | jmp .drop |
418 | jmp .drop |
419 | 419 | ||
420 | 420 | ||
421 | 421 | ||
422 | 422 | ||
423 | 423 | ||
424 | 424 | ||
425 | ;-------------------------------------------------- |
425 | ;-------------------------------------------------- |
426 | ; Header prediction failed, do it the slow way |
426 | ; Header prediction failed, do it the slow way |
427 | 427 | ||
428 | .not_uni_xfer: |
428 | .not_uni_xfer: |
429 | 429 | ||
430 | DEBUGF 1,"Header prediction failed\n" |
430 | DEBUGF 1,"Header prediction failed\n" |
431 | 431 | ||
432 | ; Calculate receive window size |
432 | ; Calculate receive window size |
433 | 433 | ||
434 | ;;;; TODO: 444 |
434 | ;;;; TODO: 444 |
435 | 435 | ||
436 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN |
436 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN |
437 | je .LISTEN |
437 | je .LISTEN |
438 | 438 | ||
439 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT |
439 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT |
440 | je .SYN_SENT |
440 | je .SYN_SENT |
441 | 441 | ||
442 | jmp .NOT_LISTEN_OR_SYN_SENT |
442 | jmp .NOT_LISTEN_OR_SYN_SENT |
443 | 443 | ||
444 | 444 | ||
445 | 445 | ||
446 | ;------------- |
446 | ;------------- |
447 | ; Passive Open |
447 | ; Passive Open |
448 | 448 | ||
449 | align 4 |
449 | align 4 |
450 | .LISTEN: |
450 | .LISTEN: |
451 | 451 | ||
452 | DEBUGF 1,"TCP state: listen\n" |
452 | DEBUGF 1,"TCP state: listen\n" |
453 | 453 | ||
454 | test [edx + TCP_segment.Flags], TH_RST ;;; TODO: kill new socket on error |
454 | test [edx + TCP_segment.Flags], TH_RST ;;; TODO: kill new socket on error |
455 | jnz .drop |
455 | jnz .drop |
456 | 456 | ||
457 | test [edx + TCP_segment.Flags], TH_ACK |
457 | test [edx + TCP_segment.Flags], TH_ACK |
458 | jnz .drop_with_reset |
458 | jnz .drop_with_reset |
459 | 459 | ||
460 | test [edx + TCP_segment.Flags], TH_SYN |
460 | test [edx + TCP_segment.Flags], TH_SYN |
461 | jz .drop |
461 | jz .drop |
462 | 462 | ||
463 | ;;; TODO: check if it's a broadcast or multicast, and drop if so |
463 | ;;; TODO: check if it's a broadcast or multicast, and drop if so |
464 | 464 | ||
465 | add [TCP_sequence_num], 64000 |
465 | add [TCP_sequence_num], 64000 |
466 | 466 | ||
467 | push [edx + TCP_segment.SourcePort] |
467 | push [edx + TCP_segment.SourcePort] |
468 | pop [eax + TCP_SOCKET.RemotePort] |
468 | pop [eax + TCP_SOCKET.RemotePort] |
469 | 469 | ||
470 | push [edx + TCP_segment.SequenceNumber] |
470 | push [edx + TCP_segment.SequenceNumber] |
471 | pop [eax + TCP_SOCKET.IRS] |
471 | pop [eax + TCP_SOCKET.IRS] |
472 | 472 | ||
473 | push [eax + TCP_SOCKET.ISS] |
473 | push [eax + TCP_SOCKET.ISS] |
474 | pop [eax + TCP_SOCKET.SND_NXT] |
474 | pop [eax + TCP_SOCKET.SND_NXT] |
475 | 475 | ||
476 | TCP_sendseqinit eax |
476 | TCP_sendseqinit eax |
477 | TCP_rcvseqinit eax |
477 | TCP_rcvseqinit eax |
478 | 478 | ||
479 | mov [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
479 | mov [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
480 | mov [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
480 | mov [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
481 | mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro |
481 | mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro |
482 | 482 | ||
483 | add eax, STREAM_SOCKET.snd |
483 | add eax, STREAM_SOCKET.snd |
484 | call SOCKET_ring_create |
484 | call SOCKET_ring_create |
485 | 485 | ||
486 | add eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd |
486 | add eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd |
487 | call SOCKET_ring_create |
487 | call SOCKET_ring_create |
488 | 488 | ||
489 | lea ebx, [eax - STREAM_SOCKET.rcv] |
489 | lea ebx, [eax - STREAM_SOCKET.rcv] |
490 | mov [ebx + SOCKET.lock], 0 |
490 | mov [ebx + SOCKET.lock], 0 |
491 | 491 | ||
492 | jmp .trim_then_step6 |
492 | jmp .trim_then_step6 |
493 | 493 | ||
494 | 494 | ||
495 | 495 | ||
496 | 496 | ||
497 | 497 | ||
498 | 498 | ||
499 | 499 | ||
500 | 500 | ||
501 | ;------------ |
501 | ;------------ |
502 | ; Active Open |
502 | ; Active Open |
503 | 503 | ||
504 | align 4 |
504 | align 4 |
505 | .SYN_SENT: |
505 | .SYN_SENT: |
506 | 506 | ||
507 | DEBUGF 1,"TCP state: syn_sent\n" |
507 | DEBUGF 1,"TCP state: syn_sent\n" |
508 | 508 | ||
509 | test [edx + TCP_segment.Flags], TH_ACK |
509 | test [edx + TCP_segment.Flags], TH_ACK |
510 | jz @f |
510 | jz @f |
511 | 511 | ||
512 | mov eax, [edx + TCP_segment.AckNumber] |
512 | mov eax, [edx + TCP_segment.AckNumber] |
513 | cmp eax, [ebx + TCP_SOCKET.ISS] |
513 | cmp eax, [ebx + TCP_SOCKET.ISS] |
514 | jle .drop_with_reset |
514 | jle .drop_with_reset |
515 | 515 | ||
516 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
516 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
517 | jg .drop_with_reset |
517 | jg .drop_with_reset |
518 | @@: |
518 | @@: |
519 | 519 | ||
520 | test [edx + TCP_segment.Flags], TH_RST |
520 | test [edx + TCP_segment.Flags], TH_RST |
521 | jz @f |
521 | jz @f |
522 | 522 | ||
523 | test [edx + TCP_segment.Flags], TH_ACK |
523 | test [edx + TCP_segment.Flags], TH_ACK |
524 | jz .drop |
524 | jz .drop |
525 | 525 | ||
526 | mov eax, ebx |
526 | mov eax, ebx |
527 | mov ebx, ECONNREFUSED |
527 | mov ebx, ECONNREFUSED |
528 | call TCP_drop |
528 | call TCP_drop |
529 | 529 | ||
530 | jmp .drop |
530 | jmp .drop |
531 | @@: |
531 | @@: |
532 | 532 | ||
533 | test [edx + TCP_segment.Flags], TH_SYN |
533 | test [edx + TCP_segment.Flags], TH_SYN |
534 | jz .drop |
534 | jz .drop |
535 | 535 | ||
536 | ; at this point, segment seems to be valid |
536 | ; at this point, segment seems to be valid |
537 | 537 | ||
538 | test [edx + TCP_segment.Flags], TH_ACK |
538 | test [edx + TCP_segment.Flags], TH_ACK |
539 | jz .no_syn_ack |
539 | jz .no_syn_ack |
540 | 540 | ||
541 | ; now, process received SYN in response to an active open |
541 | ; now, process received SYN in response to an active open |
542 | 542 | ||
543 | mov eax, [edx + TCP_segment.AckNumber] |
543 | mov eax, [edx + TCP_segment.AckNumber] |
544 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
544 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
545 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
545 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
546 | jle @f |
546 | jle @f |
547 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
547 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
548 | @@: |
548 | @@: |
549 | 549 | ||
550 | .no_syn_ack: |
550 | .no_syn_ack: |
551 | 551 | ||
552 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission |
552 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission |
553 | 553 | ||
554 | push [edx + TCP_segment.SequenceNumber] |
554 | push [edx + TCP_segment.SequenceNumber] |
555 | pop [ebx + TCP_SOCKET.IRS] |
555 | pop [ebx + TCP_SOCKET.IRS] |
556 | 556 | ||
557 | TCP_rcvseqinit ebx |
557 | TCP_rcvseqinit ebx |
558 | 558 | ||
559 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
559 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
560 | 560 | ||
561 | mov eax, [ebx + TCP_SOCKET.SND_UNA] |
561 | mov eax, [ebx + TCP_SOCKET.SND_UNA] |
562 | cmp eax, [ebx + TCP_SOCKET.ISS] |
562 | cmp eax, [ebx + TCP_SOCKET.ISS] |
563 | jle .simultaneous_open |
563 | jle .simultaneous_open |
564 | 564 | ||
565 | test [edx + TCP_segment.Flags], TH_ACK |
565 | test [edx + TCP_segment.Flags], TH_ACK |
566 | jz .simultaneous_open |
566 | jz .simultaneous_open |
567 | 567 | ||
568 | DEBUGF 1,"TCP: active open\n" |
568 | DEBUGF 1,"TCP: active open\n" |
569 | 569 | ||
570 | ;;; TODO: update stats |
570 | ;;; TODO: update stats |
571 | 571 | ||
572 | ; set socket state to connected |
572 | ; set socket state to connected |
573 | 573 | ||
574 | mov [ebx + SOCKET.state],1 ;;;; FIXME |
574 | mov [ebx + SOCKET.state],1 ;;;; FIXME |
575 | 575 | ||
576 | mov [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
576 | mov [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
577 | 577 | ||
578 | ;;; TODO: check if we should scale the connection (567-572) |
578 | ;;; TODO: check if we should scale the connection (567-572) |
579 | ;;; TODO: update RTT estimators |
579 | ;;; TODO: update RTT estimators |
580 | 580 | ||
581 | jmp .trim_then_step6 |
581 | jmp .trim_then_step6 |
582 | 582 | ||
583 | .simultaneous_open: |
583 | .simultaneous_open: |
584 | 584 | ||
585 | DEBUGF 1,"TCP: simultaneous open\n" |
585 | DEBUGF 1,"TCP: simultaneous open\n" |
586 | ; We have received a syn but no ACK, so we are having a simultaneous open.. |
586 | ; We have received a syn but no ACK, so we are having a simultaneous open.. |
587 | mov [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
587 | mov [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
588 | 588 | ||
589 | 589 | ||
590 | 590 | ||
591 | 591 | ||
592 | 592 | ||
593 | 593 | ||
594 | 594 | ||
595 | ;------------------------------------- |
595 | ;------------------------------------- |
596 | ; Common processing for receipt of SYN |
596 | ; Common processing for receipt of SYN |
597 | 597 | ||
598 | .trim_then_step6: |
598 | .trim_then_step6: |
599 | 599 | ||
600 | inc [edx + TCP_segment.SequenceNumber] |
600 | inc [edx + TCP_segment.SequenceNumber] |
601 | 601 | ||
602 | ;;; TODO: Drop any received data that follows receive window (590) |
602 | ;;; TODO: Drop any received data that follows receive window (590) |
603 | 603 | ||
604 | mov eax, [edx + TCP_segment.SequenceNumber] |
604 | mov eax, [edx + TCP_segment.SequenceNumber] |
605 | mov [ebx + TCP_SOCKET.RCV_UP], eax |
605 | mov [ebx + TCP_SOCKET.RCV_UP], eax |
606 | dec eax |
606 | dec eax |
607 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
607 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
608 | 608 | ||
609 | jmp .ack_processed |
609 | jmp .ack_processed |
610 | 610 | ||
611 | 611 | ||
612 | 612 | ||
613 | 613 | ||
614 | 614 | ||
615 | 615 | ||
616 | 616 | ||
617 | 617 | ||
618 | .NOT_LISTEN_OR_SYN_SENT: |
618 | .NOT_LISTEN_OR_SYN_SENT: |
619 | 619 | ||
620 | DEBUGF 1,"Slow TCP input: not listen or syn_sent state\n" |
620 | DEBUGF 1,"Slow TCP input: not listen or syn_sent state\n" |
621 | 621 | ||
622 | ;-------------------------------------------- |
622 | ;-------------------------------------------- |
623 | ; Protection Against Wrapped Sequence Numbers |
623 | ; Protection Against Wrapped Sequence Numbers |
624 | 624 | ||
625 | ; First, check if timestamp is present |
625 | ; First, check if timestamp is present |
626 | 626 | ||
627 | ;;;; TODO 602 |
627 | ;;;; TODO 602 |
628 | 628 | ||
629 | ; Then, check if at least some bytes of data are within window |
629 | ; Then, check if at least some bytes of data are within window |
630 | 630 | ||
631 | ;;;; TODO |
631 | ;;;; TODO |
632 | 632 | ||
633 | 633 | ||
634 | 634 | ||
635 | 635 | ||
636 | 636 | ||
637 | 637 | ||
638 | 638 | ||
639 | 639 | ||
640 | ;---------------------------- |
640 | ;---------------------------- |
641 | ; trim any data not in window |
641 | ; trim any data not in window |
642 | 642 | ||
643 | ; check for duplicate data at beginning of segment |
643 | ; check for duplicate data at beginning of segment |
644 | 644 | ||
645 | mov eax, [ebx + TCP_SOCKET.RCV_NXT] |
645 | mov eax, [ebx + TCP_SOCKET.RCV_NXT] |
646 | sub eax, [edx + TCP_segment.SequenceNumber] |
646 | sub eax, [edx + TCP_segment.SequenceNumber] |
647 | jle .no_duplicate |
647 | jle .no_duplicate |
648 | 648 | ||
649 | DEBUGF 1,"Uh oh.. %x bytes of duplicate data!\n", eax |
649 | DEBUGF 1,"Uh oh.. %x bytes of duplicate data!\n", eax |
650 | 650 | ||
651 | test [edx + TCP_segment.Flags], TH_SYN |
651 | test [edx + TCP_segment.Flags], TH_SYN |
652 | jz .no_dup_syn |
652 | jz .no_dup_syn |
653 | 653 | ||
654 | ; remove duplicate syn |
654 | ; remove duplicate syn |
655 | 655 | ||
656 | and [edx + TCP_segment.Flags], not (TH_SYN) |
656 | and [edx + TCP_segment.Flags], not (TH_SYN) |
657 | inc [edx + TCP_segment.SequenceNumber] |
657 | inc [edx + TCP_segment.SequenceNumber] |
658 | 658 | ||
659 | cmp [edx + TCP_segment.UrgentPointer], 1 |
659 | cmp [edx + TCP_segment.UrgentPointer], 1 |
660 | jl @f |
660 | jl @f |
661 | 661 | ||
662 | dec [edx + TCP_segment.UrgentPointer] |
662 | dec [edx + TCP_segment.UrgentPointer] |
663 | 663 | ||
664 | jmp .no_dup_syn |
664 | jmp .no_dup_syn |
665 | @@: |
665 | @@: |
666 | 666 | ||
667 | and [edx + TCP_segment.Flags], not (TH_URG) |
667 | and [edx + TCP_segment.Flags], not (TH_URG) |
668 | dec eax |
668 | dec eax |
669 | jz .no_duplicate |
669 | jz .no_duplicate |
670 | .no_dup_syn: |
670 | .no_dup_syn: |
671 | 671 | ||
672 | DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx |
672 | DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx |
673 | 673 | ||
674 | ; eax holds number of bytes to drop |
674 | ; eax holds number of bytes to drop |
675 | 675 | ||
676 | ; Check for entire duplicate packet |
676 | ; Check for entire duplicate packet |
677 | 677 | ||
678 | cmp eax, ecx |
678 | cmp eax, ecx |
679 | jge .duplicate |
679 | jge .duplicate |
680 | 680 | ||
681 | ;;; TODO: apply figure 28.30 |
681 | ;;; TODO: apply figure 28.30 |
682 | 682 | ||
683 | ; Check for duplicate FIN |
683 | ; Check for duplicate FIN |
684 | 684 | ||
685 | test [edx + TCP_segment.Flags], TH_FIN |
685 | test [edx + TCP_segment.Flags], TH_FIN |
686 | jz @f |
686 | jz @f |
687 | inc ecx |
687 | inc ecx |
688 | cmp eax, ecx |
688 | cmp eax, ecx |
689 | dec ecx |
689 | dec ecx |
690 | jne @f |
690 | jne @f |
691 | 691 | ||
692 | mov eax, ecx |
692 | mov eax, ecx |
693 | and [edx + TCP_segment.Flags], not TH_FIN |
693 | and [edx + TCP_segment.Flags], not TH_FIN |
694 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
694 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
695 | jmp .no_duplicate |
695 | jmp .no_duplicate |
696 | @@: |
696 | @@: |
697 | 697 | ||
698 | ; Handle the case when a bound socket connects to itself |
698 | ; Handle the case when a bound socket connects to itself |
699 | ; Allow packets with a SYN and an ACKto continue with the processing |
699 | ; Allow packets with a SYN and an ACKto continue with the processing |
700 | 700 | ||
701 | ;------------------------------------- |
701 | ;------------------------------------- |
702 | ; Generate duplicate ACK if nescessary |
702 | ; Generate duplicate ACK if nescessary |
703 | 703 | ||
704 | ; This code also handles simultaneous half-open or self-connects |
704 | ; This code also handles simultaneous half-open or self-connects |
705 | 705 | ||
706 | test eax, eax |
706 | test eax, eax |
707 | jnz .drop_after_ack |
707 | jnz .drop_after_ack |
708 | 708 | ||
709 | cmp [edx + TCP_segment.Flags], TH_ACK |
709 | cmp [edx + TCP_segment.Flags], TH_ACK |
710 | jz .drop_after_ack |
710 | jz .drop_after_ack |
711 | 711 | ||
712 | .duplicate: |
712 | .duplicate: |
713 | 713 | ||
714 | DEBUGF 1,"Duplicate received\n" |
714 | DEBUGF 1,"Duplicate received\n" |
715 | 715 | ||
716 | ;---------------------------------------- |
716 | ;---------------------------------------- |
717 | ; Update statistics for duplicate packets |
717 | ; Update statistics for duplicate packets |
718 | 718 | ||
719 | ;;; TODO |
719 | ;;; TODO |
720 | 720 | ||
721 | jmp .drop ;;; DROP the packet ?? |
721 | jmp .drop ;;; DROP the packet ?? |
722 | 722 | ||
723 | .no_duplicate: |
723 | .no_duplicate: |
724 | 724 | ||
725 | ;----------------------------------------------- |
725 | ;----------------------------------------------- |
726 | ; Remove duplicate data and update urgent offset |
726 | ; Remove duplicate data and update urgent offset |
727 | 727 | ||
728 | add [edx + TCP_segment.SequenceNumber], eax |
728 | add [edx + TCP_segment.SequenceNumber], eax |
729 | 729 | ||
730 | ;;; TODO |
730 | ;;; TODO |
731 | 731 | ||
732 | sub [edx + TCP_segment.UrgentPointer], ax |
732 | sub [edx + TCP_segment.UrgentPointer], ax |
733 | jg @f |
733 | jg @f |
734 | 734 | ||
735 | and [edx + TCP_segment.Flags], not (TH_URG) |
735 | and [edx + TCP_segment.Flags], not (TH_URG) |
736 | mov [edx + TCP_segment.UrgentPointer], 0 |
736 | mov [edx + TCP_segment.UrgentPointer], 0 |
737 | @@: |
737 | @@: |
738 | 738 | ||
739 | ;-------------------------------------------------- |
739 | ;-------------------------------------------------- |
740 | ; Handle data that arrives after process terminates |
740 | ; Handle data that arrives after process terminates |
741 | 741 | ||
742 | cmp [ebx + SOCKET.PID], 0 |
742 | cmp [ebx + SOCKET.PID], 0 |
743 | jg @f |
743 | jg @f |
744 | 744 | ||
745 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT |
745 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT |
746 | jle @f |
746 | jle @f |
747 | 747 | ||
748 | test ecx, ecx |
748 | test ecx, ecx |
749 | jz @f |
749 | jz @f |
750 | 750 | ||
751 | ;;; Close the socket |
751 | ;;; Close the socket |
752 | ;;; update stats |
752 | ;;; update stats |
753 | 753 | ||
754 | jmp .drop_with_reset |
754 | jmp .drop_with_reset |
755 | @@: |
755 | @@: |
756 | 756 | ||
757 | ;---------------------------------------- |
757 | ;---------------------------------------- |
758 | ; Remove data beyond right edge of window |
758 | ; Remove data beyond right edge of window |
759 | 759 | ||
760 | mov eax, [edx + TCP_segment.SequenceNumber] |
760 | mov eax, [edx + TCP_segment.SequenceNumber] |
761 | add eax, ecx |
761 | add eax, ecx |
762 | sub eax, [ebx + TCP_SOCKET.RCV_NXT] |
762 | sub eax, [ebx + TCP_SOCKET.RCV_NXT] |
763 | sub ax, [ebx + TCP_SOCKET.RCV_WND] |
763 | sub ax, [ebx + TCP_SOCKET.RCV_WND] |
764 | 764 | ||
765 | ; eax now holds the number of bytes to drop |
765 | ; eax now holds the number of bytes to drop |
766 | 766 | ||
767 | jle .no_excess_data |
767 | jle .no_excess_data |
768 | 768 | ||
769 | ;;; TODO: update stats |
769 | ;;; TODO: update stats |
770 | 770 | ||
771 | cmp eax, ecx |
771 | cmp eax, ecx |
772 | jl .dont_drop_all |
772 | jl .dont_drop_all |
773 | 773 | ||
774 | ;;; TODO 700-736 |
774 | ;;; TODO 700-736 |
775 | 775 | ||
776 | .dont_drop_all: |
776 | .dont_drop_all: |
777 | 777 | ||
778 | .no_excess_data: |
778 | .no_excess_data: |
779 | 779 | ||
780 | 780 | ||
781 | 781 | ||
782 | 782 | ||
783 | 783 | ||
784 | 784 | ||
785 | 785 | ||
786 | 786 | ||
787 | ;----------------- |
787 | ;----------------- |
788 | ; Record timestamp |
788 | ; Record timestamp |
789 | 789 | ||
790 | ;;; TODO 737-746 |
790 | ;;; TODO 737-746 |
791 | 791 | ||
792 | 792 | ||
793 | 793 | ||
794 | 794 | ||
795 | 795 | ||
796 | ;------------------ |
796 | ;------------------ |
797 | ; Process RST flags |
797 | ; Process RST flags |
798 | 798 | ||
799 | test [edx + TCP_segment.Flags], TH_RST |
799 | test [edx + TCP_segment.Flags], TH_RST |
800 | jz .rst_skip |
800 | jz .rst_skip |
801 | 801 | ||
802 | DEBUGF 1,"Got an RST flag" |
802 | DEBUGF 1,"Got an RST flag" |
803 | 803 | ||
804 | mov eax, [ebx + TCP_SOCKET.t_state] |
804 | mov eax, [ebx + TCP_SOCKET.t_state] |
805 | shl eax, 2 |
805 | shl eax, 2 |
806 | jmp dword [eax + .rst_sw_list] |
806 | jmp dword [eax + .rst_sw_list] |
807 | 807 | ||
808 | .rst_sw_list: |
808 | .rst_sw_list: |
809 | dd .rst_skip ;TCB_CLOSED |
809 | dd .rst_skip ;TCB_CLOSED |
810 | dd .rst_skip ;TCB_LISTEN |
810 | dd .rst_skip ;TCB_LISTEN |
811 | dd .rst_skip ;TCB_SYN_SENT |
811 | dd .rst_skip ;TCB_SYN_SENT |
812 | dd .econnrefused ;TCB_SYN_RECEIVED |
812 | dd .econnrefused ;TCB_SYN_RECEIVED |
813 | dd .econnreset ;TCB_ESTABLISHED |
813 | dd .econnreset ;TCB_ESTABLISHED |
814 | dd .econnreset ;TCB_CLOSE_WAIT |
814 | dd .econnreset ;TCB_CLOSE_WAIT |
815 | dd .econnreset ;TCB_FIN_WAIT_1 |
815 | dd .econnreset ;TCB_FIN_WAIT_1 |
816 | dd .rst_close ;TCB_CLOSING |
816 | dd .rst_close ;TCB_CLOSING |
817 | dd .rst_close ;TCB_LAST_ACK |
817 | dd .rst_close ;TCB_LAST_ACK |
818 | dd .econnreset ;TCB_FIN_WAIT_2 |
818 | dd .econnreset ;TCB_FIN_WAIT_2 |
819 | dd .rst_close ;TCB_TIMED_WAIT |
819 | dd .rst_close ;TCB_TIMED_WAIT |
820 | 820 | ||
821 | .econnrefused: |
821 | .econnrefused: |
822 | 822 | ||
823 | DEBUGF 1,"Connection refused" |
823 | DEBUGF 1,"Connection refused" |
824 | 824 | ||
825 | ;;; TODO: debug info |
825 | ;;; TODO: debug info |
826 | 826 | ||
827 | jmp .close |
827 | jmp .close |
828 | 828 | ||
829 | .econnreset: |
829 | .econnreset: |
830 | 830 | ||
831 | DEBUGF 1,"Connection reset" |
831 | DEBUGF 1,"Connection reset" |
832 | 832 | ||
833 | ;;; TODO: debug info |
833 | ;;; TODO: debug info |
834 | 834 | ||
835 | .close: |
835 | .close: |
836 | 836 | ||
837 | DEBUGF 1,"Closing connection" |
837 | DEBUGF 1,"Closing connection" |
838 | 838 | ||
839 | ;;; update stats |
839 | ;;; update stats |
840 | 840 | ||
841 | .rst_close: |
841 | .rst_close: |
842 | 842 | ||
843 | DEBUGF 1,"Closing with reset\n" |
843 | DEBUGF 1,"Closing with reset\n" |
844 | 844 | ||
845 | ;;; Close the socket |
845 | ;;; Close the socket |
846 | 846 | ||
847 | jmp .drop |
847 | jmp .drop |
848 | 848 | ||
849 | 849 | ||
850 | 850 | ||
851 | 851 | ||
852 | 852 | ||
853 | 853 | ||
854 | 854 | ||
855 | .rst_skip: |
855 | .rst_skip: |
856 | 856 | ||
857 | 857 | ||
858 | ;-------------------------------------- |
858 | ;-------------------------------------- |
859 | ; handle SYN-full and ACK-less segments |
859 | ; handle SYN-full and ACK-less segments |
860 | 860 | ||
861 | test [edx + TCP_segment.Flags], TH_SYN |
861 | test [edx + TCP_segment.Flags], TH_SYN |
862 | jz @f |
862 | jz @f |
863 | 863 | ||
864 | mov ebx, ECONNRESET |
864 | mov ebx, ECONNRESET |
865 | call TCP_drop |
865 | call TCP_drop |
866 | 866 | ||
867 | jmp .drop_with_reset |
867 | jmp .drop_with_reset |
868 | 868 | ||
869 | test [edx + TCP_segment.Flags], TH_ACK |
869 | test [edx + TCP_segment.Flags], TH_ACK |
870 | jz .drop |
870 | jz .drop |
871 | @@: |
871 | @@: |
872 | 872 | ||
873 | 873 | ||
874 | 874 | ||
875 | 875 | ||
876 | 876 | ||
877 | 877 | ||
878 | 878 | ||
879 | ;--------------- |
879 | ;--------------- |
880 | ; ACK processing |
880 | ; ACK processing |
881 | 881 | ||
882 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
882 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
883 | jnz .no_syn_rcv |
883 | jnz .no_syn_rcv |
884 | 884 | ||
885 | DEBUGF 1,"TCP state = syn received\n" |
885 | DEBUGF 1,"TCP state = syn received\n" |
886 | 886 | ||
887 | ;;;;; 801-815 |
887 | ;;;;; 801-815 |
888 | 888 | ||
889 | .no_syn_rcv: |
889 | .no_syn_rcv: |
890 | 890 | ||
891 | ; check for duplicate ACK |
891 | ; check for duplicate ACK |
892 | 892 | ||
893 | mov eax, [edx + TCP_segment.AckNumber] |
893 | mov eax, [edx + TCP_segment.AckNumber] |
894 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
894 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
895 | jg .not_dup_ack |
895 | jg .not_dup_ack |
896 | 896 | ||
897 | test ecx, ecx |
897 | test ecx, ecx |
898 | jnz .reset_dupacks |
898 | jnz .reset_dupacks |
899 | 899 | ||
900 | mov eax, dword [edx + TCP_segment.Window] |
900 | mov eax, dword [edx + TCP_segment.Window] |
901 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
901 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
902 | jne .reset_dupacks |
902 | jne .reset_dupacks |
903 | 903 | ||
904 | DEBUGF 1,"Processing a duplicate ACK..\n" |
904 | DEBUGF 1,"Processing a duplicate ACK..\n" |
905 | 905 | ||
906 | cmp [ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;; |
906 | cmp [ebx + TCP_SOCKET.timer_retransmission], 10000 ;;;; |
907 | jg @f |
907 | jg @f |
908 | 908 | ||
909 | mov eax, [edx + TCP_segment.AckNumber] |
909 | mov eax, [edx + TCP_segment.AckNumber] |
910 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
910 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
911 | je .dup_ack |
911 | je .dup_ack |
912 | 912 | ||
913 | @@: |
913 | @@: |
914 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
914 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
915 | jmp .not_dup_ack |
915 | jmp .not_dup_ack |
916 | 916 | ||
917 | .dup_ack: |
917 | .dup_ack: |
918 | inc [ebx + TCP_SOCKET.t_dupacks] |
918 | inc [ebx + TCP_SOCKET.t_dupacks] |
919 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
919 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
920 | jne .no_re_xmit |
920 | jne .no_re_xmit |
921 | 921 | ||
922 | push [ebx + TCP_SOCKET.SND_NXT] ; >>>> |
922 | push [ebx + TCP_SOCKET.SND_NXT] ; >>>> |
923 | 923 | ||
924 | mov eax, [ebx + TCP_SOCKET.SND_WND] |
924 | mov eax, [ebx + TCP_SOCKET.SND_WND] |
925 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
925 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
926 | cmovg eax, [ebx + TCP_SOCKET.SND_CWND] |
926 | cmovg eax, [ebx + TCP_SOCKET.SND_CWND] |
927 | shr eax, 1 |
927 | shr eax, 1 |
928 | push edx |
928 | push edx |
929 | xor edx, edx |
929 | xor edx, edx |
930 | div [ebx + TCP_SOCKET.t_maxseg] |
930 | div [ebx + TCP_SOCKET.t_maxseg] |
931 | cmp eax, 2 |
931 | cmp eax, 2 |
932 | jge @f |
932 | jge @f |
933 | mov ax, 2 |
933 | mov ax, 2 |
934 | @@: |
934 | @@: |
935 | mul [ebx + TCP_SOCKET.t_maxseg] |
935 | mul [ebx + TCP_SOCKET.t_maxseg] |
936 | pop edx |
936 | pop edx |
937 | mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax |
937 | mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax |
938 | 938 | ||
939 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer |
939 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer |
940 | mov [ebx + TCP_SOCKET.t_rtt], 0 |
940 | mov [ebx + TCP_SOCKET.t_rtt], 0 |
941 | mov eax, [edx + TCP_segment.AckNumber] |
941 | mov eax, [edx + TCP_segment.AckNumber] |
942 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
942 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
943 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
943 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
944 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
944 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
945 | 945 | ||
946 | mov eax, ebx |
946 | mov eax, ebx |
947 | call TCP_output ; retransmit missing segment |
947 | call TCP_output ; retransmit missing segment |
948 | 948 | ||
949 | push edx |
949 | push edx |
950 | xor edx, edx |
950 | xor edx, edx |
951 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
951 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
952 | mul [ebx + TCP_SOCKET.t_dupacks] |
952 | mul [ebx + TCP_SOCKET.t_dupacks] |
953 | pop edx |
953 | pop edx |
954 | add eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
954 | add eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
955 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
955 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
956 | 956 | ||
957 | pop eax ; <<<< |
957 | pop eax ; <<<< |
958 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
958 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
959 | jl @f |
959 | jl @f |
960 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
960 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
961 | @@: |
961 | @@: |
962 | 962 | ||
963 | jmp .drop |
963 | jmp .drop |
964 | 964 | ||
965 | 965 | ||
966 | .no_re_xmit: |
966 | .no_re_xmit: |
967 | jle .not_dup_ack |
967 | jle .not_dup_ack |
968 | 968 | ||
969 | DEBUGF 1,"Increasing congestion window\n" |
969 | DEBUGF 1,"Increasing congestion window\n" |
970 | 970 | ||
971 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
971 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
972 | add [ebx + TCP_SOCKET.SND_CWND], eax |
972 | add [ebx + TCP_SOCKET.SND_CWND], eax |
973 | 973 | ||
974 | mov eax, ebx |
974 | mov eax, ebx |
975 | call TCP_output |
975 | call TCP_output |
976 | 976 | ||
977 | jmp .drop |
977 | jmp .drop |
978 | 978 | ||
979 | 979 | ||
980 | 980 | ||
981 | 981 | ||
982 | 982 | ||
983 | 983 | ||
984 | .not_dup_ack: |
984 | .not_dup_ack: |
985 | 985 | ||
986 | ;------------------------------------------------- |
986 | ;------------------------------------------------- |
987 | ; If the congestion window was inflated to account |
987 | ; If the congestion window was inflated to account |
988 | ; for the other side's cached packets, retract it |
988 | ; for the other side's cached packets, retract it |
989 | 989 | ||
990 | mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
990 | mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
991 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
991 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
992 | jg @f |
992 | jg @f |
993 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
993 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
994 | jle @f |
994 | jle @f |
995 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
995 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
996 | @@: |
996 | @@: |
997 | 997 | ||
998 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
998 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
999 | 999 | ||
1000 | mov eax, [edx + TCP_segment.AckNumber] |
1000 | mov eax, [edx + TCP_segment.AckNumber] |
1001 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
1001 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
1002 | jle @f |
1002 | jle @f |
1003 | 1003 | ||
1004 | ;;; TODO: update stats |
1004 | ;;; TODO: update stats |
1005 | jmp .drop_after_ack |
1005 | jmp .drop_after_ack |
1006 | 1006 | ||
1007 | @@: |
1007 | @@: |
1008 | 1008 | ||
1009 | mov edi, [edx + TCP_segment.AckNumber] |
1009 | mov edi, [edx + TCP_segment.AckNumber] |
1010 | sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in esi |
1010 | sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in esi |
1011 | 1011 | ||
1012 | ;;; TODO: update stats |
1012 | ;;; TODO: update stats |
1013 | 1013 | ||
1014 | 1014 | ||
1015 | DEBUGF 1,"We have an acceptable ACK of %x bytes\n", esi |
1015 | DEBUGF 1,"We have an acceptable ACK of %x bytes\n", esi |
1016 | 1016 | ||
1017 | 1017 | ||
1018 | 1018 | ||
1019 | 1019 | ||
1020 | 1020 | ||
1021 | 1021 | ||
1022 | ;------------------------------------------ |
1022 | ;------------------------------------------ |
1023 | ; RTT measurements and retransmission timer |
1023 | ; RTT measurements and retransmission timer |
1024 | 1024 | ||
1025 | ;;;;; 912 - 926 |
1025 | ;;;;; 912 - 926 |
1026 | 1026 | ||
1027 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 |
1027 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 |
1028 | 1028 | ||
1029 | mov eax, [ebx + TCP_SOCKET.SND_MAX] |
1029 | mov eax, [ebx + TCP_SOCKET.SND_MAX] |
1030 | cmp eax, [edx + TCP_segment.AckNumber] |
1030 | cmp eax, [edx + TCP_segment.AckNumber] |
1031 | je .all_outstanding |
1031 | je .all_outstanding |
1032 | mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it) |
1032 | mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it) |
1033 | .all_outstanding: |
1033 | .all_outstanding: |
1034 | 1034 | ||
1035 | 1035 | ||
1036 | 1036 | ||
1037 | 1037 | ||
1038 | 1038 | ||
1039 | 1039 | ||
1040 | 1040 | ||
1041 | ;------------------------------------------- |
1041 | ;------------------------------------------- |
1042 | ; Open congestion window in response to ACKs |
1042 | ; Open congestion window in response to ACKs |
1043 | 1043 | ||
1044 | mov esi, [ebx + TCP_SOCKET.SND_CWND] |
1044 | mov esi, [ebx + TCP_SOCKET.SND_CWND] |
1045 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
1045 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
1046 | 1046 | ||
1047 | cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH] |
1047 | cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH] |
1048 | jle @f |
1048 | jle @f |
1049 | push edx |
1049 | push edx |
1050 | push eax |
1050 | push eax |
1051 | mul eax |
1051 | mul eax |
1052 | div esi |
1052 | div esi |
1053 | pop edx |
1053 | pop edx |
1054 | shr edx, 3 |
1054 | shr edx, 3 |
1055 | add eax, edx |
1055 | add eax, edx |
1056 | pop edx |
1056 | pop edx |
1057 | @@: |
1057 | @@: |
1058 | 1058 | ||
1059 | add esi, eax |
1059 | add esi, eax |
1060 | 1060 | ||
1061 | push ecx |
1061 | push ecx |
1062 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
1062 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
1063 | mov eax, TCP_max_win |
1063 | mov eax, TCP_max_win |
1064 | shl eax, cl |
1064 | shl eax, cl |
1065 | pop ecx |
1065 | pop ecx |
1066 | 1066 | ||
1067 | cmp esi, eax |
1067 | cmp esi, eax |
1068 | cmovg esi, eax |
1068 | cmovg esi, eax |
1069 | mov [ebx + TCP_SOCKET.SND_CWND], esi |
1069 | mov [ebx + TCP_SOCKET.SND_CWND], esi |
1070 | 1070 | ||
1071 | 1071 | ||
1072 | 1072 | ||
1073 | 1073 | ||
1074 | 1074 | ||
1075 | 1075 | ||
1076 | 1076 | ||
1077 | ;------------------------------------------ |
1077 | ;------------------------------------------ |
1078 | ; Remove acknowledged data from send buffer |
1078 | ; Remove acknowledged data from send buffer |
1079 | 1079 | ||
1080 | push ecx edx ebx |
1080 | push ecx edx ebx |
1081 | mov ecx, edi |
1081 | mov ecx, edi |
1082 | lea eax, [ebx + STREAM_SOCKET.snd] |
1082 | lea eax, [ebx + STREAM_SOCKET.snd] |
1083 | call SOCKET_ring_free |
1083 | call SOCKET_ring_free |
1084 | pop ebx |
1084 | pop ebx |
1085 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1085 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1086 | pop edx ecx |
1086 | pop edx ecx |
1087 | 1087 | ||
1088 | ; Wake up process waiting on send buffer |
1088 | ; Wake up process waiting on send buffer |
1089 | 1089 | ||
1090 | mov eax, ebx |
1090 | mov eax, ebx |
1091 | call SOCKET_notify_owner |
1091 | call SOCKET_notify_owner |
1092 | 1092 | ||
1093 | ; Update TCB |
1093 | ; Update TCB |
1094 | 1094 | ||
1095 | mov eax, [edx + TCP_segment.AckNumber] |
1095 | mov eax, [edx + TCP_segment.AckNumber] |
1096 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1096 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1097 | 1097 | ||
1098 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1098 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1099 | jl @f |
1099 | jl @f |
1100 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1100 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1101 | @@: |
1101 | @@: |
1102 | 1102 | ||
1103 | 1103 | ||
1104 | ;; TODO: use zero flag as 'ourfinisacked' |
1104 | ;; TODO: use zero flag as 'ourfinisacked' |
1105 | 1105 | ||
1106 | 1106 | ||
1107 | 1107 | ||
1108 | 1108 | ||
1109 | ; General ACK handling complete |
1109 | ; General ACK handling complete |
1110 | ; Now do the state-specific ones |
1110 | ; Now do the state-specific ones |
1111 | 1111 | ||
1112 | mov eax, [ebx + TCP_SOCKET.t_state] |
1112 | mov eax, [ebx + TCP_SOCKET.t_state] |
1113 | jmp dword [eax*4 + .ACK_sw_list] |
1113 | jmp dword [eax*4 + .ACK_sw_list] |
1114 | 1114 | ||
1115 | .ACK_sw_list: |
1115 | .ACK_sw_list: |
1116 | dd .ack_processed ;TCB_CLOSED |
1116 | dd .ack_processed ;TCB_CLOSED |
1117 | dd .ack_processed ;TCB_LISTEN |
1117 | dd .ack_processed ;TCB_LISTEN |
1118 | dd .ack_processed ;TCB_SYN_SENT |
1118 | dd .ack_processed ;TCB_SYN_SENT |
1119 | dd .ack_processed ;TCB_SYN_RECEIVED |
1119 | dd .ack_processed ;TCB_SYN_RECEIVED |
1120 | dd .ack_processed ;TCB_ESTABLISHED |
1120 | dd .ack_processed ;TCB_ESTABLISHED |
1121 | dd .ack_processed ;TCB_CLOSE_WAIT |
1121 | dd .ack_processed ;TCB_CLOSE_WAIT |
1122 | dd .ack_fw1 ;TCB_FIN_WAIT_1 |
1122 | dd .ack_fw1 ;TCB_FIN_WAIT_1 |
1123 | dd .ack_c ;TCB_CLOSING |
1123 | dd .ack_c ;TCB_CLOSING |
1124 | dd .ack_la ;TCB_LAST_ACK |
1124 | dd .ack_la ;TCB_LAST_ACK |
1125 | dd .ack_processed ;TCB_FIN_WAIT_2 |
1125 | dd .ack_processed ;TCB_FIN_WAIT_2 |
1126 | dd .ack_tw ;TCB_TIMED_WAIT |
1126 | dd .ack_tw ;TCB_TIMED_WAIT |
1127 | 1127 | ||
1128 | 1128 | ||
1129 | .ack_fw1: |
1129 | .ack_fw1: |
1130 | jz .ack_processed |
1130 | jz .ack_processed |
1131 | 1131 | ||
1132 | test [ebx + SOCKET.state], SS_CANTRCVMORE |
1132 | test [ebx + SOCKET.state], SS_CANTRCVMORE |
1133 | jnz @f |
1133 | jnz @f |
1134 | mov eax, ebx |
1134 | mov eax, ebx |
1135 | call SOCKET_is_disconnected |
1135 | call SOCKET_is_disconnected |
1136 | ;;; mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle |
1136 | ;;; mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle |
1137 | @@: |
1137 | @@: |
1138 | 1138 | ||
1139 | mov [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_2 |
1139 | mov [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_2 |
1140 | jmp .ack_processed |
1140 | jmp .ack_processed |
1141 | 1141 | ||
1142 | 1142 | ||
1143 | .ack_c: |
1143 | .ack_c: |
1144 | jz .ack_processed |
1144 | jz .ack_processed |
1145 | 1145 | ||
1146 | mov [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
1146 | mov [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
1147 | mov eax, ebx |
1147 | mov eax, ebx |
1148 | call TCP_cancel_timers |
1148 | call TCP_cancel_timers |
1149 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1149 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1150 | mov eax, ebx |
1150 | mov eax, ebx |
1151 | call SOCKET_is_disconnected |
1151 | call SOCKET_is_disconnected |
1152 | jmp .ack_processed |
1152 | jmp .ack_processed |
1153 | 1153 | ||
1154 | 1154 | ||
1155 | .ack_la: |
1155 | .ack_la: |
1156 | jz .ack_processed |
1156 | jz .ack_processed |
1157 | 1157 | ||
1158 | 1158 | ||
1159 | mov eax, ebx |
1159 | mov eax, ebx |
1160 | call TCP_close |
1160 | call TCP_close |
1161 | jmp .drop |
1161 | jmp .drop |
1162 | 1162 | ||
1163 | 1163 | ||
1164 | .ack_tw: |
1164 | .ack_tw: |
1165 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1165 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1166 | jmp .drop_after_ack |
1166 | jmp .drop_after_ack |
1167 | 1167 | ||
1168 | 1168 | ||
1169 | 1169 | ||
1170 | 1170 | ||
1171 | 1171 | ||
1172 | 1172 | ||
1173 | 1173 | ||
1174 | .reset_dupacks: ; We got a new ACK, reset duplicate ACK counter |
1174 | .reset_dupacks: ; We got a new ACK, reset duplicate ACK counter |
1175 | 1175 | ||
1176 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
1176 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
1177 | 1177 | ||
1178 | .ack_processed: ; (step 6) |
1178 | .ack_processed: ; (step 6) |
1179 | 1179 | ||
1180 | DEBUGF 1,"ACK processed\n" |
1180 | DEBUGF 1,"ACK processed\n" |
1181 | 1181 | ||
1182 | ;---------------------------------------------- |
1182 | ;---------------------------------------------- |
1183 | ; check if we need to update window information |
1183 | ; check if we need to update window information |
1184 | 1184 | ||
1185 | test [edx + TCP_segment.Flags], TH_ACK |
1185 | test [edx + TCP_segment.Flags], TH_ACK |
1186 | jz .no_window_update |
1186 | jz .no_window_update |
1187 | 1187 | ||
1188 | mov eax, [ebx + TCP_SOCKET.SND_WL1] |
1188 | mov eax, [ebx + TCP_SOCKET.SND_WL1] |
1189 | cmp eax, [edx + TCP_segment.SequenceNumber] |
1189 | cmp eax, [edx + TCP_segment.SequenceNumber] |
1190 | jl .update_window |
1190 | jl .update_window |
1191 | jg @f |
1191 | jg @f |
1192 | 1192 | ||
1193 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1193 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1194 | cmp eax, [edx + TCP_segment.AckNumber] |
1194 | cmp eax, [edx + TCP_segment.AckNumber] |
1195 | jl .update_window |
1195 | jl .update_window |
1196 | jg .no_window_update |
1196 | jg .no_window_update |
1197 | @@: |
1197 | @@: |
1198 | 1198 | ||
1199 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1199 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1200 | cmp eax, [edx + TCP_segment.AckNumber] |
1200 | cmp eax, [edx + TCP_segment.AckNumber] |
1201 | jne .no_window_update |
1201 | jne .no_window_update |
1202 | 1202 | ||
1203 | movzx eax, [edx + TCP_segment.Window] |
1203 | movzx eax, [edx + TCP_segment.Window] |
1204 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1204 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1205 | jle .no_window_update |
1205 | jle .no_window_update |
1206 | 1206 | ||
1207 | .update_window: |
1207 | .update_window: |
1208 | 1208 | ||
1209 | DEBUGF 1,"Updating window\n" |
1209 | DEBUGF 1,"Updating window\n" |
1210 | 1210 | ||
1211 | ; Keep track of pure window updates |
1211 | ; Keep track of pure window updates |
1212 | 1212 | ||
1213 | ; test ecx, ecx |
1213 | ; test ecx, ecx |
1214 | ; jz @f |
1214 | ; jz @f |
1215 | ; |
1215 | ; |
1216 | ; mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1216 | ; mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1217 | ; cmp eax, [edx + TCP_segment.AckNumber] |
1217 | ; cmp eax, [edx + TCP_segment.AckNumber] |
1218 | ; jne @f |
1218 | ; jne @f |
1219 | ; |
1219 | ; |
1220 | ; ;; mov eax, tiwin |
1220 | ; ;; mov eax, tiwin |
1221 | ; cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1221 | ; cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1222 | ; jle @f |
1222 | ; jle @f |
1223 | ; |
1223 | ; |
1224 | ; ;;; update stats |
1224 | ; ;;; update stats |
1225 | ; |
1225 | ; |
1226 | ; @@: |
1226 | ; @@: |
1227 | 1227 | ||
1228 | mov eax, dword [edx + TCP_segment.Window] |
1228 | mov eax, dword [edx + TCP_segment.Window] |
1229 | cmp eax, [ebx + TCP_SOCKET.max_sndwnd] |
1229 | cmp eax, [ebx + TCP_SOCKET.max_sndwnd] |
1230 | jle @f |
1230 | jle @f |
1231 | mov [ebx + TCP_SOCKET.max_sndwnd], eax |
1231 | mov [ebx + TCP_SOCKET.max_sndwnd], eax |
1232 | @@: |
1232 | @@: |
1233 | mov [ebx + TCP_SOCKET.SND_WND], eax |
1233 | mov [ebx + TCP_SOCKET.SND_WND], eax |
1234 | 1234 | ||
1235 | push [edx + TCP_segment.SequenceNumber] |
1235 | push [edx + TCP_segment.SequenceNumber] |
1236 | pop [ebx + TCP_SOCKET.SND_WL1] |
1236 | pop [ebx + TCP_SOCKET.SND_WL1] |
1237 | 1237 | ||
1238 | push [edx + TCP_segment.AckNumber] |
1238 | push [edx + TCP_segment.AckNumber] |
1239 | pop [ebx + TCP_SOCKET.SND_WL2] |
1239 | pop [ebx + TCP_SOCKET.SND_WL2] |
1240 | 1240 | ||
1241 | ;;; needoutput = 1 |
1241 | ;;; needoutput = 1 |
1242 | 1242 | ||
1243 | .no_window_update: |
1243 | .no_window_update: |
1244 | 1244 | ||
1245 | 1245 | ||
1246 | 1246 | ||
1247 | 1247 | ||
1248 | 1248 | ||
1249 | 1249 | ||
1250 | 1250 | ||
1251 | ;----------------- |
1251 | ;----------------- |
1252 | ; process URG flag |
1252 | ; process URG flag |
1253 | 1253 | ||
1254 | test [edx + TCP_segment.Flags], TH_URG |
1254 | test [edx + TCP_segment.Flags], TH_URG |
1255 | jz .not_urgent |
1255 | jz .not_urgent |
1256 | 1256 | ||
1257 | cmp [edx + TCP_segment.UrgentPointer], 0 |
1257 | cmp [edx + TCP_segment.UrgentPointer], 0 |
1258 | jz .not_urgent |
1258 | jz .not_urgent |
1259 | 1259 | ||
1260 | cmp [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
1260 | cmp [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
1261 | je .not_urgent |
1261 | je .not_urgent |
1262 | 1262 | ||
1263 | ; Ignore bogus urgent offsets |
1263 | ; Ignore bogus urgent offsets |
1264 | 1264 | ||
1265 | ;;; 1040-1050 |
1265 | ;;; 1040-1050 |
1266 | 1266 | ||
1267 | movzx eax, [edx + TCP_segment.UrgentPointer] |
1267 | movzx eax, [edx + TCP_segment.UrgentPointer] |
1268 | add eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size] |
1268 | add eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size] |
1269 | cmp eax, SOCKET_MAXDATA |
1269 | cmp eax, SOCKET_MAXDATA |
1270 | jle .not_urgent |
1270 | jle .not_urgent |
1271 | 1271 | ||
1272 | mov [edx + TCP_segment.UrgentPointer], 0 |
1272 | mov [edx + TCP_segment.UrgentPointer], 0 |
1273 | and [edx + TCP_segment.Flags], not (TH_URG) |
1273 | and [edx + TCP_segment.Flags], not (TH_URG) |
1274 | jmp .do_data |
1274 | jmp .do_data |
1275 | 1275 | ||
1276 | .not_urgent: |
1276 | .not_urgent: |
1277 | 1277 | ||
1278 | ; processing of received urgent pointer |
1278 | ; processing of received urgent pointer |
1279 | 1279 | ||
1280 | ;;; TODO (1051-1093) |
1280 | ;;; TODO (1051-1093) |
1281 | 1281 | ||
1282 | 1282 | ||
1283 | 1283 | ||
1284 | 1284 | ||
1285 | 1285 | ||
1286 | 1286 | ||
1287 | 1287 | ||
1288 | 1288 | ||
1289 | ;-------------------------------- |
1289 | ;-------------------------------- |
1290 | ; process the data in the segment |
1290 | ; process the data in the segment |
1291 | 1291 | ||
1292 | .do_data: |
1292 | .do_data: |
1293 | 1293 | ||
1294 | DEBUGF 1,"TCP: do data (%u)\n", ecx |
1294 | DEBUGF 1,"TCP: do data (%u)\n", ecx |
1295 | 1295 | ||
1296 | test [edx + TCP_segment.Flags], TH_FIN |
1296 | test [edx + TCP_segment.Flags], TH_FIN |
1297 | jnz .process_fin |
1297 | jnz .process_fin |
1298 | 1298 | ||
1299 | cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 |
1299 | cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 |
1300 | jge .dont_do_data |
1300 | jge .dont_do_data |
1301 | 1301 | ||
1302 | test ecx, ecx |
1302 | test ecx, ecx |
1303 | jz .final_processing |
1303 | jz .final_processing |
1304 | 1304 | ||
1305 | DEBUGF 1,"Processing data in segment\n" |
1305 | DEBUGF 1,"Processing data in segment\n" |
1306 | 1306 | ||
1307 | ;; TODO: check if data is in sequence ! |
1307 | ;; TODO: check if data is in sequence ! |
1308 | 1308 | ||
1309 | movzx eax, [edx + TCP_segment.DataOffset] ;;; todo: remember this in.. edi ? |
1309 | movzx eax, [edx + TCP_segment.DataOffset] ;;; todo: remember this in.. edi ? |
1310 | and eax, 0xf0 |
1310 | and eax, 0xf0 |
1311 | shr al, 2 |
1311 | shr al, 2 |
1312 | 1312 | ||
1313 | lea esi, [edx + eax] |
1313 | lea esi, [edx + eax] |
1314 | 1314 | ||
1315 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK |
1315 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK |
1316 | add [ebx + TCP_SOCKET.RCV_NXT], ecx |
1316 | add [ebx + TCP_SOCKET.RCV_NXT], ecx |
1317 | 1317 | ||
1318 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1318 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1319 | call SOCKET_ring_write |
1319 | call SOCKET_ring_write |
1320 | 1320 | ||
1321 | mov eax, ebx |
1321 | mov eax, ebx |
1322 | call SOCKET_notify_owner |
1322 | call SOCKET_notify_owner |
1323 | 1323 | ||
1324 | jmp .final_processing |
1324 | jmp .final_processing |
1325 | 1325 | ||
1326 | 1326 | ||
1327 | .dont_do_data: |
1327 | .dont_do_data: |
1328 | 1328 | ||
1329 | 1329 | ||
1330 | 1330 | ||
1331 | 1331 | ||
1332 | 1332 | ||
1333 | 1333 | ||
1334 | 1334 | ||
1335 | ;--------------- |
1335 | ;--------------- |
1336 | ; FIN processing |
1336 | ; FIN processing |
1337 | 1337 | ||
1338 | .process_fin: |
1338 | .process_fin: |
1339 | 1339 | ||
1340 | DEBUGF 1,"Processing FIN\n" |
1340 | DEBUGF 1,"Processing FIN\n" |
- | 1341 | ||
- | 1342 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT |
|
- | 1343 | je .not_first_fin |
|
- | 1344 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSING |
|
- | 1345 | je .not_first_fin |
|
- | 1346 | cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_2 |
|
- | 1347 | je .not_first_fin |
|
- | 1348 | ||
- | 1349 | DEBUGF 1,"First FIN for this connection\n" |
|
- | 1350 | ||
- | 1351 | mov eax, ebx |
|
- | 1352 | call SOCKET_cant_recv_more |
|
- | 1353 | ||
- | 1354 | mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
|
- | 1355 | inc [ebx + TCP_SOCKET.RCV_NXT] |
|
- | 1356 | ||
1341 | 1357 | .not_first_fin: |
|
1342 | mov eax, [ebx + TCP_SOCKET.t_state] |
1358 | mov eax, [ebx + TCP_SOCKET.t_state] |
1343 | shl eax, 2 |
1359 | shl eax, 2 |
1344 | jmp dword [eax + .FIN_sw_list] |
1360 | jmp dword [eax + .FIN_sw_list] |
1345 | 1361 | ||
1346 | .FIN_sw_list: |
1362 | .FIN_sw_list: |
1347 | dd .no_fin ;TCB_CLOSED |
1363 | dd .no_fin ;TCB_CLOSED |
1348 | dd .no_fin ;TCB_LISTEN |
1364 | dd .no_fin ;TCB_LISTEN |
1349 | dd .no_fin ;TCB_SYN_SENT |
1365 | dd .no_fin ;TCB_SYN_SENT |
1350 | dd .fin_syn_est ;TCB_SYN_RECEIVED |
1366 | dd .fin_syn_est ;TCB_SYN_RECEIVED |
1351 | dd .fin_syn_est ;TCB_ESTABLISHED |
1367 | dd .fin_syn_est ;TCB_ESTABLISHED |
1352 | dd .no_fin ;TCB_CLOSE_WAIT |
1368 | dd .no_fin ;TCB_CLOSE_WAIT |
1353 | dd .fin_wait1 ;TCB_FIN_WAIT_1 |
1369 | dd .fin_wait1 ;TCB_FIN_WAIT_1 |
1354 | dd .no_fin ;TCB_CLOSING |
1370 | dd .no_fin ;TCB_CLOSING |
1355 | dd .no_fin ;TCB_LAST_ACK |
1371 | dd .no_fin ;TCB_LAST_ACK |
1356 | dd .fin_wait2 ;TCB_FIN_WAIT_2 |
1372 | dd .fin_wait2 ;TCB_FIN_WAIT_2 |
1357 | dd .fin_timed ;TCB_TIMED_WAIT |
1373 | dd .fin_timed ;TCB_TIMED_WAIT |
1358 | - | ||
1359 | - | ||
1360 | 1374 | ||
- | 1375 | .fin_syn_est: |
|
1361 | .fin_syn_est: |
1376 | |
1362 | 1377 | mov [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT |
|
1363 | jmp .final_processing |
1378 | jmp .no_fin |
1364 | 1379 | ||
1365 | .fin_wait1: |
1380 | .fin_wait1: |
- | 1381 | ||
1366 | 1382 | mov [ebx + TCP_SOCKET.t_state], TCB_CLOSING |
|
1367 | jmp .final_processing |
1383 | jmp .no_fin |
1368 | 1384 | ||
1369 | .fin_wait2: |
1385 | .fin_wait2: |
- | 1386 | ||
- | 1387 | mov [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
|
- | 1388 | mov eax, ebx |
|
- | 1389 | call TCP_cancel_timers |
|
- | 1390 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
|
1370 | 1391 | call SOCKET_is_disconnected |
|
1371 | jmp .final_processing |
1392 | jmp .no_fin |
1372 | - | ||
- | 1393 | ||
1373 | .fin_timed: |
1394 | .fin_timed: |
1374 | 1395 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
|
1375 | jmp .final_processing |
1396 | jmp .no_fin |
1376 | 1397 | ||
1377 | .no_fin: |
1398 | .no_fin: |
1378 | 1399 | ||
1379 | 1400 | ||
1380 | 1401 | ||
1381 | 1402 | ||
1382 | 1403 | ||
1383 | 1404 | ||
1384 | 1405 | ||
1385 | 1406 | ||
1386 | ;----------------- |
1407 | ;----------------- |
1387 | ; Final processing |
1408 | ; Final processing |
1388 | 1409 | ||
1389 | .final_processing: |
1410 | .final_processing: |
1390 | 1411 | ||
1391 | DEBUGF 1,"Final processing\n" |
1412 | DEBUGF 1,"Final processing\n" |
1392 | 1413 | ||
1393 | ;;; if debug enabled, output packet |
1414 | ;;; if debug enabled, output packet |
1394 | 1415 | ||
1395 | ;test needoutput, needoutput |
1416 | ;test needoutput, needoutput |
1396 | ;jz .dumpit |
1417 | ;jz .dumpit |
1397 | 1418 | ||
1398 | test [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1419 | test [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1399 | jz .dumpit |
1420 | jz .dumpit |
1400 | 1421 | ||
1401 | DEBUGF 1,"ACK now!\n" |
1422 | DEBUGF 1,"ACK now!\n" |
1402 | 1423 | ||
1403 | push ebx |
1424 | push ebx |
1404 | mov eax, ebx |
1425 | mov eax, ebx |
1405 | call TCP_output |
1426 | call TCP_output |
1406 | pop ebx |
1427 | pop ebx |
1407 | 1428 | ||
1408 | .dumpit: |
1429 | .dumpit: |
1409 | 1430 | ||
1410 | mov [ebx + SOCKET.lock], 0 |
1431 | mov [ebx + SOCKET.lock], 0 |
1411 | 1432 | ||
1412 | call kernel_free |
1433 | call kernel_free |
1413 | add esp, 4 |
1434 | add esp, 4 |
1414 | ret |
1435 | ret |
1415 | 1436 | ||
1416 | 1437 | ||
1417 | 1438 | ||
1418 | 1439 | ||
1419 | 1440 | ||
1420 | 1441 | ||
1421 | 1442 | ||
1422 | ;------------------------------------------ |
1443 | ;------------------------------------------ |
1423 | ; Generate an ACK, droping incoming segment |
1444 | ; Generate an ACK, droping incoming segment |
1424 | 1445 | ||
1425 | align 4 |
1446 | align 4 |
1426 | .drop_after_ack: |
1447 | .drop_after_ack: |
1427 | 1448 | ||
1428 | DEBUGF 1,"Drop after ACK\n" |
1449 | DEBUGF 1,"Drop after ACK\n" |
1429 | 1450 | ||
1430 | test [edx + TCP_segment.Flags], TH_RST |
1451 | test [edx + TCP_segment.Flags], TH_RST |
1431 | jnz .drop |
1452 | jnz .drop |
1432 | 1453 | ||
1433 | and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1454 | and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1434 | 1455 | ||
1435 | mov [ebx + SOCKET.lock], 0 |
1456 | mov [ebx + SOCKET.lock], 0 |
1436 | 1457 | ||
1437 | push ebx |
1458 | push ebx |
1438 | mov eax, ebx |
1459 | mov eax, ebx |
1439 | call TCP_output |
1460 | call TCP_output |
1440 | pop ebx |
1461 | pop ebx |
1441 | 1462 | ||
1442 | call kernel_free |
1463 | call kernel_free |
1443 | add esp, 4 |
1464 | add esp, 4 |
1444 | ret |
1465 | ret |
1445 | 1466 | ||
1446 | 1467 | ||
1447 | 1468 | ||
1448 | 1469 | ||
1449 | 1470 | ||
1450 | 1471 | ||
1451 | 1472 | ||
1452 | 1473 | ||
1453 | ;------------------------------------------- |
1474 | ;------------------------------------------- |
1454 | ; Generate an RST, dropping incoming segment |
1475 | ; Generate an RST, dropping incoming segment |
1455 | 1476 | ||
1456 | align 4 |
1477 | align 4 |
1457 | .drop_with_reset: |
1478 | .drop_with_reset: |
1458 | 1479 | ||
1459 | mov [ebx + SOCKET.lock], 0 |
1480 | mov [ebx + SOCKET.lock], 0 |
1460 | 1481 | ||
1461 | .drop_with_reset_not_locked: |
1482 | .drop_with_reset_not_locked: |
1462 | 1483 | ||
1463 | DEBUGF 1,"Drop with reset\n" |
1484 | DEBUGF 1,"Drop with reset\n" |
1464 | 1485 | ||
1465 | test [edx + TCP_segment.Flags], TH_RST |
1486 | test [edx + TCP_segment.Flags], TH_RST |
1466 | jnz .drop |
1487 | jnz .drop |
1467 | 1488 | ||
1468 | ;;; if its a multicast/broadcast, also drop |
1489 | ;;; if its a multicast/broadcast, also drop |
1469 | 1490 | ||
1470 | test [edx + TCP_segment.Flags], TH_ACK |
1491 | test [edx + TCP_segment.Flags], TH_ACK |
1471 | jnz .respond_ack |
1492 | jnz .respond_ack |
1472 | 1493 | ||
1473 | test [edx + TCP_segment.Flags], TH_SYN |
1494 | test [edx + TCP_segment.Flags], TH_SYN |
1474 | jnz .respond_syn |
1495 | jnz .respond_syn |
1475 | 1496 | ||
1476 | call kernel_free |
1497 | call kernel_free |
1477 | add esp, 4 |
1498 | add esp, 4 |
1478 | ret |
1499 | ret |
1479 | 1500 | ||
1480 | .respond_ack: |
1501 | .respond_ack: |
1481 | 1502 | ||
1482 | mov dl, TH_RST |
1503 | mov dl, TH_RST |
1483 | 1504 | ||
1484 | push ebx |
1505 | push ebx |
1485 | call TCP_respond_segment |
1506 | call TCP_respond_segment |
1486 | pop ebx |
1507 | pop ebx |
1487 | 1508 | ||
1488 | jmp .destroy_new_socket |
1509 | jmp .destroy_new_socket |
1489 | 1510 | ||
1490 | 1511 | ||
1491 | .respond_syn: |
1512 | .respond_syn: |
1492 | 1513 | ||
1493 | mov dl, TH_RST + TH_ACK |
1514 | mov dl, TH_RST + TH_ACK |
1494 | 1515 | ||
1495 | push ebx |
1516 | push ebx |
1496 | call TCP_respond_socket |
1517 | call TCP_respond_socket |
1497 | pop ebx |
1518 | pop ebx |
1498 | 1519 | ||
1499 | jmp .destroy_new_socket |
1520 | jmp .destroy_new_socket |
1500 | 1521 | ||
1501 | 1522 | ||
1502 | 1523 | ||
1503 | 1524 | ||
1504 | 1525 | ||
1505 | 1526 | ||
1506 | 1527 | ||
1507 | ;----- |
1528 | ;----- |
1508 | ; Drop |
1529 | ; Drop |
1509 | 1530 | ||
1510 | align 4 |
1531 | align 4 |
1511 | .drop: |
1532 | .drop: |
1512 | 1533 | ||
1513 | mov [ebx + SOCKET.lock], 0 |
1534 | mov [ebx + SOCKET.lock], 0 |
1514 | 1535 | ||
1515 | .drop_not_locked: |
1536 | .drop_not_locked: |
1516 | 1537 | ||
1517 | DEBUGF 1,"Dropping packet\n" |
1538 | DEBUGF 1,"Dropping packet\n" |
1518 | 1539 | ||
1519 | ;;;; If debugging options are enabled, output the packet somwhere |
1540 | ;;;; If debugging options are enabled, output the packet somwhere |
1520 | 1541 | ||
1521 | .destroy_new_socket: |
1542 | .destroy_new_socket: |
1522 | 1543 | ||
1523 | ;;;; kill the newly created socket |
1544 | ;;;; kill the newly created socket |
1524 | 1545 | ||
1525 | call kernel_free |
1546 | call kernel_free |
1526 | add esp, 4 |
1547 | add esp, 4 |
1527 | ret |
1548 | ret |
1528 | >< |
1549 | >< |
1529 | ><< |
1550 | ><< |
1530 | ><<< |
1551 | ><<< |
1531 | > |
1552 | > |