Rev 4388 | Rev 4850 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4388 | Rev 4510 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2013. 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: 3407 $ |
17 | $Revision: 3407 $ |
18 | 18 | ||
19 | ;----------------------------------------------------------------- |
19 | ;----------------------------------------------------------------- |
20 | ; |
20 | ; |
21 | ; TCP_input: |
21 | ; TCP_input: |
22 | ; |
22 | ; |
23 | ; Add a segment to the incoming TCP queue |
23 | ; Add a segment to the incoming TCP queue |
24 | ; |
24 | ; |
25 | ; IN: [esp] = ptr to buffer |
25 | ; IN: [esp] = ptr to buffer |
26 | ; [esp+4] = buffer size (dont care) |
26 | ; [esp+4] = buffer size (dont care) |
27 | ; ebx = ptr to device struct |
27 | ; ebx = ptr to device struct |
28 | ; ecx = segment size |
28 | ; ecx = segment size |
29 | ; esi = ptr to TCP segment |
29 | ; esi = ptr to TCP segment |
30 | ; edi = ptr to ipv4 source address, followed by ipv4 dest address |
30 | ; edi = ptr to ipv4 source address, followed by ipv4 dest address |
31 | ; |
31 | ; |
32 | ; OUT: / |
32 | ; OUT: / |
33 | ; |
33 | ; |
34 | ;----------------------------------------------------------------- |
34 | ;----------------------------------------------------------------- |
35 | 35 | ||
36 | align 4 |
36 | align 4 |
37 | TCP_input: |
37 | TCP_input: |
38 | 38 | ||
39 | ; record the current time |
39 | ; record the current time |
40 | mov eax, [timer_ticks] ; in 1/100 seconds |
40 | mov eax, [timer_ticks] ; in 1/100 seconds |
41 | mov [esp + 4], eax |
41 | mov [esp + 4], eax |
42 | 42 | ||
43 | push ebx ecx esi edi ; mind the order |
43 | push ebx ecx esi edi ; mind the order |
44 | mov esi, esp |
44 | mov esi, esp |
45 | - | ||
46 | pushf |
- | |
47 | cli |
45 | |
48 | add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail |
- | |
49 | popf |
- | |
50 | 46 | add_to_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .fail |
|
51 | add esp, sizeof.TCP_queue_entry |
47 | add esp, sizeof.TCP_queue_entry |
52 | 48 | ||
53 | call NET_ptr_to_num4 |
49 | call NET_ptr_to_num4 |
54 | inc [TCP_segments_rx + edi] |
50 | inc [TCP_segments_rx + edi] |
55 | 51 | ||
56 | xor edx, edx |
52 | xor edx, edx |
57 | mov eax, [TCP_input_event] |
53 | mov eax, [TCP_input_event] |
58 | mov ebx, [eax + EVENT.id] |
54 | mov ebx, [eax + EVENT.id] |
59 | xor esi, esi |
55 | xor esi, esi |
60 | call raise_event |
56 | call raise_event |
61 | 57 | ||
62 | ret |
58 | ret |
63 | 59 | ||
64 | .fail: |
60 | .fail: |
65 | popf |
61 | popf |
66 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" |
62 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP incoming queue is full, discarding packet!\n" |
67 | 63 | ||
68 | call NET_ptr_to_num4 |
64 | call NET_ptr_to_num4 |
69 | inc [TCP_segments_missed + edi] |
65 | inc [TCP_segments_missed + edi] |
70 | 66 | ||
71 | add esp, sizeof.TCP_queue_entry - 8 |
67 | add esp, sizeof.TCP_queue_entry - 8 |
72 | call NET_packet_free |
68 | call NET_packet_free |
73 | add esp, 4 |
69 | add esp, 4 |
74 | 70 | ||
75 | ret |
71 | ret |
76 | 72 | ||
77 | 73 | ||
78 | 74 | ||
79 | 75 | ||
80 | align 4 |
76 | align 4 |
81 | proc TCP_process_input |
77 | proc TCP_process_input |
82 | 78 | ||
83 | locals |
79 | locals |
84 | dataoffset dd ? |
80 | dataoffset dd ? |
85 | timestamp dd ? |
81 | timestamp dd ? |
86 | temp_bits db ? |
82 | temp_bits db ? |
87 | endl |
83 | endl |
88 | 84 | ||
89 | xor esi, esi |
85 | xor esi, esi |
90 | mov ecx, MANUAL_DESTROY |
86 | mov ecx, MANUAL_DESTROY |
91 | call create_event |
87 | call create_event |
92 | mov [TCP_input_event], eax |
88 | mov [TCP_input_event], eax |
93 | 89 | ||
94 | .wait: |
90 | .wait: |
95 | mov eax, [TCP_input_event] |
91 | mov eax, [TCP_input_event] |
96 | mov ebx, [eax + EVENT.id] |
92 | mov ebx, [eax + EVENT.id] |
97 | call wait_event |
93 | call wait_event |
98 | 94 | ||
99 | .loop: |
95 | .loop: |
100 | get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait |
96 | get_from_queue TCP_queue, TCP_QUEUE_SIZE, sizeof.TCP_queue_entry, .wait |
101 | 97 | ||
102 | push [esi + TCP_queue_entry.timestamp] |
98 | push [esi + TCP_queue_entry.timestamp] |
103 | pop [timestamp] |
99 | pop [timestamp] |
104 | push [esi + TCP_queue_entry.buffer_ptr] |
100 | push [esi + TCP_queue_entry.buffer_ptr] |
105 | 101 | ||
106 | mov ebx, [esi + TCP_queue_entry.device_ptr] |
102 | mov ebx, [esi + TCP_queue_entry.device_ptr] |
107 | mov ecx, [esi + TCP_queue_entry.segment_size] |
103 | mov ecx, [esi + TCP_queue_entry.segment_size] |
108 | mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address |
104 | mov edi, [esi + TCP_queue_entry.ip_ptr] ; ptr to ipv4 source address, followed by ipv4 destination address |
109 | mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last |
105 | mov esi, [esi + TCP_queue_entry.segment_ptr] ; change esi last |
110 | 106 | ||
111 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks] |
107 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: size=%u time=%d\n", ecx, [timer_ticks] |
112 | 108 | ||
113 | mov edx, esi |
109 | mov edx, esi |
114 | 110 | ||
115 | cmp ebx, LOOPBACK_DEVICE |
111 | cmp ebx, LOOPBACK_DEVICE |
116 | je .checksum_ok |
112 | je .checksum_ok |
117 | 113 | ||
118 | ; re-calculate the checksum (if not already done by hw) |
114 | ; re-calculate the checksum (if not already done by hw) |
119 | test [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN |
115 | test [ebx + NET_DEVICE.hwacc], NET_HWACC_TCP_IPv4_IN |
120 | jnz .checksum_ok |
116 | jnz .checksum_ok |
121 | 117 | ||
122 | push ecx esi |
118 | push ecx esi |
123 | pushw [esi + TCP_header.Checksum] |
119 | pushw [esi + TCP_header.Checksum] |
124 | mov [esi + TCP_header.Checksum], 0 |
120 | mov [esi + TCP_header.Checksum], 0 |
125 | TCP_checksum (edi), (edi+4) |
121 | TCP_checksum (edi), (edi+4) |
126 | pop cx ; previous checksum |
122 | pop cx ; previous checksum |
127 | cmp cx, dx |
123 | cmp cx, dx |
128 | pop edx ecx |
124 | pop edx ecx |
129 | jne .drop_no_socket |
125 | jne .drop_no_socket |
130 | .checksum_ok: |
126 | .checksum_ok: |
131 | 127 | ||
132 | ; Verify the data offset |
128 | ; Verify the data offset |
133 | movzx eax, [edx + TCP_header.DataOffset] |
129 | movzx eax, [edx + TCP_header.DataOffset] |
134 | and al, 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header) |
130 | and al, 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header) |
135 | shr al, 2 |
131 | shr al, 2 |
136 | cmp al, sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header |
132 | cmp al, sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header |
137 | jb .drop_no_socket ; If not, drop the packet |
133 | jb .drop_no_socket ; If not, drop the packet |
138 | mov [dataoffset], eax |
134 | mov [dataoffset], eax |
139 | 135 | ||
140 | sub ecx, eax ; substract TCP header size from total segment size |
136 | sub ecx, eax ; substract TCP header size from total segment size |
141 | jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet |
137 | jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet |
142 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx |
138 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes of data\n", ecx |
143 | 139 | ||
144 | ;------------------------------------------- |
140 | ;------------------------------------------- |
145 | ; Convert Big-endian values to little endian |
141 | ; Convert Big-endian values to little endian |
146 | 142 | ||
147 | ntohd [edx + TCP_header.SequenceNumber] |
143 | ntohd [edx + TCP_header.SequenceNumber] |
148 | ntohd [edx + TCP_header.AckNumber] |
144 | ntohd [edx + TCP_header.AckNumber] |
149 | 145 | ||
150 | ntohw [edx + TCP_header.Window] |
146 | ntohw [edx + TCP_header.Window] |
151 | ntohw [edx + TCP_header.UrgentPointer] |
147 | ntohw [edx + TCP_header.UrgentPointer] |
152 | 148 | ||
153 | ;------------------------ |
149 | ;------------------------ |
154 | ; Find the socket pointer |
150 | ; Find the socket pointer |
155 | 151 | ||
156 | ; IP Packet TCP Destination Port = local Port |
152 | ; IP Packet TCP Destination Port = local Port |
157 | ; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0) |
153 | ; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0) |
158 | ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
154 | ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
159 | 155 | ||
160 | .findpcb: |
156 | .findpcb: |
161 | pusha |
157 | pusha |
162 | mov ecx, socket_mutex |
158 | mov ecx, socket_mutex |
163 | call mutex_lock |
159 | call mutex_lock |
164 | popa |
160 | popa |
165 | 161 | ||
166 | mov ebx, net_sockets |
162 | mov ebx, net_sockets |
167 | mov si, [edx + TCP_header.DestinationPort] |
163 | mov si, [edx + TCP_header.DestinationPort] |
168 | 164 | ||
169 | .socket_loop: |
165 | .socket_loop: |
170 | mov ebx, [ebx + SOCKET.NextPtr] |
166 | mov ebx, [ebx + SOCKET.NextPtr] |
171 | or ebx, ebx |
167 | or ebx, ebx |
172 | jz .no_socket ;respond_seg_reset |
168 | jz .no_socket ;respond_seg_reset |
173 | 169 | ||
174 | cmp [ebx + SOCKET.Domain], AF_INET4 |
170 | cmp [ebx + SOCKET.Domain], AF_INET4 |
175 | jne .socket_loop |
171 | jne .socket_loop |
176 | 172 | ||
177 | cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP |
173 | cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP |
178 | jne .socket_loop |
174 | jne .socket_loop |
179 | 175 | ||
180 | cmp [ebx + TCP_SOCKET.LocalPort], si |
176 | cmp [ebx + TCP_SOCKET.LocalPort], si |
181 | jne .socket_loop |
177 | jne .socket_loop |
182 | 178 | ||
183 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
179 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
184 | cmp eax, [edi] ; Ipv4 source address |
180 | cmp eax, [edi] ; Ipv4 source address |
185 | je @f |
181 | je @f |
186 | test eax, eax |
182 | test eax, eax |
187 | jnz .socket_loop |
183 | jnz .socket_loop |
188 | @@: |
184 | @@: |
189 | 185 | ||
190 | mov ax, [ebx + TCP_SOCKET.RemotePort] |
186 | mov ax, [ebx + TCP_SOCKET.RemotePort] |
191 | cmp [edx + TCP_header.SourcePort], ax |
187 | cmp [edx + TCP_header.SourcePort], ax |
192 | je .found_socket |
188 | je .found_socket |
193 | test ax, ax |
189 | test ax, ax |
194 | jnz .socket_loop |
190 | jnz .socket_loop |
195 | .found_socket: ; ebx now contains the socketpointer |
191 | .found_socket: ; ebx now contains the socketpointer |
196 | pusha |
192 | pusha |
197 | mov ecx, socket_mutex |
193 | mov ecx, socket_mutex |
198 | call mutex_unlock |
194 | call mutex_unlock |
199 | popa |
195 | popa |
200 | 196 | ||
201 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2 |
197 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2 |
202 | 198 | ||
203 | ;---------------------------- |
199 | ;---------------------------- |
204 | ; Check if socket isnt closed |
200 | ; Check if socket isnt closed |
205 | 201 | ||
206 | cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSED |
202 | cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSED |
207 | je .drop_no_socket |
203 | je .drop_no_socket |
208 | 204 | ||
209 | ;---------------- |
205 | ;---------------- |
210 | ; Lock the socket |
206 | ; Lock the socket |
211 | 207 | ||
212 | pusha |
208 | pusha |
213 | lea ecx, [ebx + SOCKET.mutex] |
209 | lea ecx, [ebx + SOCKET.mutex] |
214 | call mutex_lock |
210 | call mutex_lock |
215 | popa |
211 | popa |
216 | 212 | ||
217 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n" |
213 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: socket locked\n" |
218 | 214 | ||
219 | ;--------------------------- |
215 | ;--------------------------- |
220 | ; disable all temporary bits |
216 | ; disable all temporary bits |
221 | 217 | ||
222 | mov [temp_bits], 0 |
218 | mov [temp_bits], 0 |
223 | 219 | ||
224 | ;--------------------------------------- |
220 | ;--------------------------------------- |
225 | ; unscale the window into a 32 bit value |
221 | ; unscale the window into a 32 bit value |
226 | 222 | ||
227 | movzx eax, [edx + TCP_header.Window] |
223 | movzx eax, [edx + TCP_header.Window] |
228 | push ecx |
224 | push ecx |
229 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
225 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
230 | shl eax, cl |
226 | shl eax, cl |
231 | mov dword [edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore |
227 | mov dword [edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore |
232 | pop ecx |
228 | pop ecx |
233 | 229 | ||
234 | ;--------------------------------------- |
230 | ;--------------------------------------- |
235 | ; Are we accepting incoming connections? |
231 | ; Are we accepting incoming connections? |
236 | 232 | ||
237 | test [ebx + SOCKET.options], SO_ACCEPTCON |
233 | test [ebx + SOCKET.options], SO_ACCEPTCON |
238 | jz .no_accept |
234 | jz .no_accept |
239 | 235 | ||
240 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n" |
236 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Accepting new connection\n" |
241 | 237 | ||
242 | pusha |
238 | pusha |
243 | lea ecx, [ebx + SOCKET.mutex] |
239 | lea ecx, [ebx + SOCKET.mutex] |
244 | call mutex_unlock |
240 | call mutex_unlock |
245 | popa |
241 | popa |
246 | 242 | ||
247 | push ecx edx esi edi ;;; |
243 | push ecx edx esi edi ;;; |
248 | call SOCKET_fork |
244 | call SOCKET_fork |
249 | pop edi esi edx ecx |
245 | pop edi esi edx ecx |
250 | 246 | ||
251 | test eax, eax |
247 | test eax, eax |
252 | jz .drop_no_socket |
248 | jz .drop_no_socket |
253 | 249 | ||
254 | mov ebx, eax |
250 | mov ebx, eax |
255 | 251 | ||
256 | mov [temp_bits], TCP_BIT_DROPSOCKET |
252 | mov [temp_bits], TCP_BIT_DROPSOCKET |
257 | 253 | ||
258 | push dword [edi + 4] ; Ipv4 destination addres |
254 | push dword [edi + 4] ; Ipv4 destination addres |
259 | pop [ebx + IP_SOCKET.LocalIP] |
255 | pop [ebx + IP_SOCKET.LocalIP] |
260 | 256 | ||
261 | push [edx + TCP_header.DestinationPort] |
257 | push [edx + TCP_header.DestinationPort] |
262 | pop [ebx + TCP_SOCKET.LocalPort] |
258 | pop [ebx + TCP_SOCKET.LocalPort] |
263 | 259 | ||
264 | mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN |
260 | mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN |
265 | .no_accept: |
261 | .no_accept: |
266 | 262 | ||
267 | 263 | ||
268 | ;------------------------------------- |
264 | ;------------------------------------- |
269 | ; Reset idle timer and keepalive timer |
265 | ; Reset idle timer and keepalive timer |
270 | 266 | ||
271 | mov [ebx + TCP_SOCKET.t_idle], 0 |
267 | mov [ebx + TCP_SOCKET.t_idle], 0 |
272 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle |
268 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_idle |
273 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive |
269 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive |
274 | 270 | ||
275 | ;-------------------- |
271 | ;-------------------- |
276 | ; Process TCP options |
272 | ; Process TCP options |
277 | 273 | ||
278 | ;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS |
274 | ;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS |
279 | ;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state |
275 | ;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state |
280 | ;;; jz .not_uni_xfer ; also no header prediction |
276 | ;;; jz .not_uni_xfer ; also no header prediction |
281 | 277 | ||
282 | push ecx |
278 | push ecx |
283 | 279 | ||
284 | mov ecx, [dataoffset] |
280 | mov ecx, [dataoffset] |
285 | cmp ecx, sizeof.TCP_header ; Does header contain any options? |
281 | cmp ecx, sizeof.TCP_header ; Does header contain any options? |
286 | je .no_options |
282 | je .no_options |
287 | 283 | ||
288 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n" |
284 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Segment has options\n" |
289 | 285 | ||
290 | add ecx, edx |
286 | add ecx, edx |
291 | lea esi, [edx + sizeof.TCP_header] |
287 | lea esi, [edx + sizeof.TCP_header] |
292 | 288 | ||
293 | .opt_loop: |
289 | .opt_loop: |
294 | cmp esi, ecx ; are we scanning outside of header? |
290 | cmp esi, ecx ; are we scanning outside of header? |
295 | jae .no_options |
291 | jae .no_options |
296 | lodsb |
292 | lodsb |
297 | cmp al, TCP_OPT_EOL ; end of option list? |
293 | cmp al, TCP_OPT_EOL ; end of option list? |
298 | je .no_options |
294 | je .no_options |
299 | cmp al, TCP_OPT_NOP |
295 | cmp al, TCP_OPT_NOP |
300 | je .opt_loop |
296 | je .opt_loop |
301 | cmp al, TCP_OPT_MAXSEG |
297 | cmp al, TCP_OPT_MAXSEG |
302 | je .opt_maxseg |
298 | je .opt_maxseg |
303 | cmp al, TCP_OPT_WINDOW |
299 | cmp al, TCP_OPT_WINDOW |
304 | je .opt_window |
300 | je .opt_window |
305 | cmp al, TCP_OPT_SACK_PERMIT |
301 | cmp al, TCP_OPT_SACK_PERMIT |
306 | je .opt_sack_permit |
302 | je .opt_sack_permit |
307 | ; cmp al, TCP_OPT_SACK |
303 | ; cmp al, TCP_OPT_SACK |
308 | ; je .opt_sack |
304 | ; je .opt_sack |
309 | cmp al, TCP_OPT_TIMESTAMP |
305 | cmp al, TCP_OPT_TIMESTAMP |
310 | je .opt_timestamp |
306 | je .opt_timestamp |
311 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al |
307 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: unknown option:%u\n", al |
312 | jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
308 | jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
313 | 309 | ||
314 | .opt_maxseg: |
310 | .opt_maxseg: |
315 | lodsb |
311 | lodsb |
316 | cmp al, 4 |
312 | cmp al, 4 |
317 | jne .no_options ; error occured, ignore all options! |
313 | jne .no_options ; error occured, ignore all options! |
318 | 314 | ||
319 | test [edx + TCP_header.Flags], TH_SYN |
315 | test [edx + TCP_header.Flags], TH_SYN |
320 | jz @f |
316 | jz @f |
321 | 317 | ||
322 | xor eax, eax |
318 | xor eax, eax |
323 | lodsw |
319 | lodsw |
324 | rol ax, 8 |
320 | rol ax, 8 |
325 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax |
321 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Maxseg=%u\n", eax |
326 | call TCP_mss |
322 | call TCP_mss |
327 | @@: |
323 | @@: |
328 | jmp .opt_loop |
324 | jmp .opt_loop |
329 | 325 | ||
330 | 326 | ||
331 | .opt_window: |
327 | .opt_window: |
332 | lodsb |
328 | lodsb |
333 | cmp al, 3 |
329 | cmp al, 3 |
334 | jne .no_options |
330 | jne .no_options |
335 | 331 | ||
336 | test [edx + TCP_header.Flags], TH_SYN |
332 | test [edx + TCP_header.Flags], TH_SYN |
337 | jz @f |
333 | jz @f |
338 | 334 | ||
339 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n" |
335 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got window scale option\n" |
340 | or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
336 | or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
341 | 337 | ||
342 | lodsb |
338 | lodsb |
343 | mov [ebx + TCP_SOCKET.SND_SCALE], al |
339 | mov [ebx + TCP_SOCKET.SND_SCALE], al |
344 | ;;;;; TODO |
340 | ;;;;; TODO |
345 | 341 | ||
346 | @@: |
342 | @@: |
347 | jmp .opt_loop |
343 | jmp .opt_loop |
348 | 344 | ||
349 | 345 | ||
350 | .opt_sack_permit: |
346 | .opt_sack_permit: |
351 | lodsb |
347 | lodsb |
352 | cmp al, 2 |
348 | cmp al, 2 |
353 | jne .no_options |
349 | jne .no_options |
354 | 350 | ||
355 | test [edx + TCP_header.Flags], TH_SYN |
351 | test [edx + TCP_header.Flags], TH_SYN |
356 | jz @f |
352 | jz @f |
357 | 353 | ||
358 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n" |
354 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Selective Acknowledgement permitted\n" |
359 | or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT |
355 | or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT |
360 | 356 | ||
361 | @@: |
357 | @@: |
362 | jmp .opt_loop |
358 | jmp .opt_loop |
363 | 359 | ||
364 | 360 | ||
365 | .opt_timestamp: |
361 | .opt_timestamp: |
366 | lodsb |
362 | lodsb |
367 | cmp al, 10 ; length must be 10 |
363 | cmp al, 10 ; length must be 10 |
368 | jne .no_options |
364 | jne .no_options |
369 | 365 | ||
370 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n" |
366 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got timestamp option\n" |
371 | 367 | ||
372 | test [edx + TCP_header.Flags], TH_SYN |
368 | test [edx + TCP_header.Flags], TH_SYN |
373 | jz @f |
369 | jz @f |
374 | or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP |
370 | or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP |
375 | @@: |
371 | @@: |
376 | 372 | ||
377 | lodsd |
373 | lodsd |
378 | bswap eax |
374 | bswap eax |
379 | mov [ebx + TCP_SOCKET.ts_val], eax |
375 | mov [ebx + TCP_SOCKET.ts_val], eax |
380 | lodsd ; timestamp echo reply |
376 | lodsd ; timestamp echo reply |
381 | mov [ebx + TCP_SOCKET.ts_ecr], eax |
377 | mov [ebx + TCP_SOCKET.ts_ecr], eax |
382 | or [temp_bits], TCP_BIT_TIMESTAMP |
378 | or [temp_bits], TCP_BIT_TIMESTAMP |
383 | 379 | ||
384 | ; Since we have a timestamp, lets do the paws test right away! |
380 | ; Since we have a timestamp, lets do the paws test right away! |
385 | 381 | ||
386 | test [edx + TCP_header.Flags], TH_RST |
382 | test [edx + TCP_header.Flags], TH_RST |
387 | jnz .no_paws |
383 | jnz .no_paws |
388 | 384 | ||
389 | mov eax, [ebx + TCP_SOCKET.ts_recent] |
385 | mov eax, [ebx + TCP_SOCKET.ts_recent] |
390 | test eax, eax |
386 | test eax, eax |
391 | jz .no_paws |
387 | jz .no_paws |
392 | cmp eax, [ebx + TCP_SOCKET.ts_val] |
388 | cmp eax, [ebx + TCP_SOCKET.ts_val] |
393 | jbe .no_paws |
389 | jbe .no_paws |
394 | 390 | ||
395 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n" |
391 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: PAWS: detected an old segment\n" |
396 | 392 | ||
397 | mov eax, [timestamp] |
393 | mov eax, [timestamp] |
398 | sub eax, [ebx + TCP_SOCKET.ts_recent_age] |
394 | sub eax, [ebx + TCP_SOCKET.ts_recent_age] |
399 | 395 | ||
400 | pop ecx |
396 | pop ecx |
401 | cmp eax, TCP_PAWS_IDLE |
397 | cmp eax, TCP_PAWS_IDLE |
402 | jle .drop_after_ack ; TODO: update stats |
398 | jle .drop_after_ack ; TODO: update stats |
403 | push ecx |
399 | push ecx |
404 | 400 | ||
405 | mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it. |
401 | mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it. |
406 | .no_paws: |
402 | .no_paws: |
407 | jmp .opt_loop |
403 | jmp .opt_loop |
408 | 404 | ||
409 | .no_options: |
405 | .no_options: |
410 | 406 | ||
411 | pop ecx |
407 | pop ecx |
412 | 408 | ||
413 | ;----------------------------------------------------------------------- |
409 | ;----------------------------------------------------------------------- |
414 | ; Time to do some header prediction (Original Principle by Van Jacobson) |
410 | ; Time to do some header prediction (Original Principle by Van Jacobson) |
415 | 411 | ||
416 | ; There are two common cases for an uni-directional data transfer. |
412 | ; There are two common cases for an uni-directional data transfer. |
417 | ; |
413 | ; |
418 | ; General rule: the packets has no control flags, is in-sequence, |
414 | ; General rule: the packets has no control flags, is in-sequence, |
419 | ; window width didnt change and we're not retransmitting. |
415 | ; window width didnt change and we're not retransmitting. |
420 | ; |
416 | ; |
421 | ; Second rules: |
417 | ; Second rules: |
422 | ; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer. |
418 | ; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer. |
423 | ; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer |
419 | ; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer |
424 | ; |
420 | ; |
425 | ; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer. |
421 | ; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer. |
426 | ; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK |
422 | ; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK |
427 | 423 | ||
428 | cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
424 | cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
429 | jnz .not_uni_xfer |
425 | jnz .not_uni_xfer |
430 | 426 | ||
431 | test [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG |
427 | test [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG |
432 | jnz .not_uni_xfer |
428 | jnz .not_uni_xfer |
433 | 429 | ||
434 | test [edx + TCP_header.Flags], TH_ACK |
430 | test [edx + TCP_header.Flags], TH_ACK |
435 | jz .not_uni_xfer |
431 | jz .not_uni_xfer |
436 | 432 | ||
437 | mov eax, [edx + TCP_header.SequenceNumber] |
433 | mov eax, [edx + TCP_header.SequenceNumber] |
438 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
434 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
439 | jne .not_uni_xfer |
435 | jne .not_uni_xfer |
440 | 436 | ||
441 | mov eax, dword [edx + TCP_header.Window] |
437 | mov eax, dword [edx + TCP_header.Window] |
442 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
438 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
443 | jne .not_uni_xfer |
439 | jne .not_uni_xfer |
444 | 440 | ||
445 | mov eax, [ebx + TCP_SOCKET.SND_NXT] |
441 | mov eax, [ebx + TCP_SOCKET.SND_NXT] |
446 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
442 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
447 | jne .not_uni_xfer |
443 | jne .not_uni_xfer |
448 | 444 | ||
449 | ;--------------------------------------- |
445 | ;--------------------------------------- |
450 | ; check if we are sender in the uni-xfer |
446 | ; check if we are sender in the uni-xfer |
451 | 447 | ||
452 | ; If the following 4 conditions are all true, this segment is a pure ACK. |
448 | ; If the following 4 conditions are all true, this segment is a pure ACK. |
453 | ; |
449 | ; |
454 | ; - The segment contains no data. |
450 | ; - The segment contains no data. |
455 | test ecx, ecx |
451 | test ecx, ecx |
456 | jnz .not_sender |
452 | jnz .not_sender |
457 | 453 | ||
458 | ; - The congestion window is greater than or equal to the current send window. |
454 | ; - The congestion window is greater than or equal to the current send window. |
459 | ; 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. |
455 | ; 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. |
460 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
456 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
461 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
457 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
462 | jb .not_uni_xfer |
458 | jb .not_uni_xfer |
463 | 459 | ||
464 | ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent. |
460 | ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent. |
465 | mov eax, [edx + TCP_header.AckNumber] |
461 | mov eax, [edx + TCP_header.AckNumber] |
466 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
462 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
467 | ja .not_uni_xfer |
463 | ja .not_uni_xfer |
468 | 464 | ||
469 | ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number. |
465 | ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number. |
470 | sub eax, [ebx + TCP_SOCKET.SND_UNA] |
466 | sub eax, [ebx + TCP_SOCKET.SND_UNA] |
471 | jbe .not_uni_xfer |
467 | jbe .not_uni_xfer |
472 | 468 | ||
473 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n" |
469 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are sender\n" |
474 | 470 | ||
475 | ;--------------------------------- |
471 | ;--------------------------------- |
476 | ; Packet is a pure ACK, process it |
472 | ; Packet is a pure ACK, process it |
477 | 473 | ||
478 | ; Delete acknowledged bytes from send buffer |
474 | ; Delete acknowledged bytes from send buffer |
479 | pusha |
475 | pusha |
480 | mov ecx, eax |
476 | mov ecx, eax |
481 | lea eax, [ebx + STREAM_SOCKET.snd] |
477 | lea eax, [ebx + STREAM_SOCKET.snd] |
482 | call SOCKET_ring_free |
478 | call SOCKET_ring_free |
483 | popa |
479 | popa |
484 | 480 | ||
485 | ; Update RTT estimators |
481 | ; Update RTT estimators |
486 | 482 | ||
487 | test [temp_bits], TCP_BIT_TIMESTAMP |
483 | test [temp_bits], TCP_BIT_TIMESTAMP |
488 | jz .no_timestamp_rtt |
484 | jz .no_timestamp_rtt |
489 | mov eax, [timestamp] |
485 | mov eax, [timestamp] |
490 | sub eax, [ebx + TCP_SOCKET.ts_ecr] |
486 | sub eax, [ebx + TCP_SOCKET.ts_ecr] |
491 | inc eax |
487 | inc eax |
492 | call TCP_xmit_timer |
488 | call TCP_xmit_timer |
493 | jmp .rtt_done |
489 | jmp .rtt_done |
494 | 490 | ||
495 | .no_timestamp_rtt: |
491 | .no_timestamp_rtt: |
496 | cmp [ebx + TCP_SOCKET.t_rtt], 0 |
492 | cmp [ebx + TCP_SOCKET.t_rtt], 0 |
497 | je .rtt_done |
493 | je .rtt_done |
498 | mov eax, [edx + TCP_header.AckNumber] |
494 | mov eax, [edx + TCP_header.AckNumber] |
499 | cmp eax, [ebx + TCP_SOCKET.t_rtseq] |
495 | cmp eax, [ebx + TCP_SOCKET.t_rtseq] |
500 | jbe .rtt_done |
496 | jbe .rtt_done |
501 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
497 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
502 | call TCP_xmit_timer |
498 | call TCP_xmit_timer |
503 | 499 | ||
504 | .rtt_done: |
500 | .rtt_done: |
505 | 501 | ||
506 | ; update window pointers |
502 | ; update window pointers |
507 | mov eax, [edx + TCP_header.AckNumber] |
503 | mov eax, [edx + TCP_header.AckNumber] |
508 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
504 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
509 | 505 | ||
510 | ; Stop retransmit timer |
506 | ; Stop retransmit timer |
511 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission |
507 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission |
512 | 508 | ||
513 | ; Unlock the socket |
509 | ; Unlock the socket |
514 | pusha |
510 | pusha |
515 | lea ecx, [ebx + SOCKET.mutex] |
511 | lea ecx, [ebx + SOCKET.mutex] |
516 | call mutex_unlock |
512 | call mutex_unlock |
517 | popa |
513 | popa |
518 | 514 | ||
519 | ; Awaken waiting processes |
515 | ; Awaken waiting processes |
520 | mov eax, ebx |
516 | mov eax, ebx |
521 | call SOCKET_notify |
517 | call SOCKET_notify |
522 | 518 | ||
523 | ; Generate more output |
519 | ; Generate more output |
524 | call TCP_output |
520 | call TCP_output |
525 | 521 | ||
526 | jmp .drop_no_socket |
522 | jmp .drop_no_socket |
527 | 523 | ||
528 | ;------------------------------------------------- |
524 | ;------------------------------------------------- |
529 | ; maybe we are the receiver in the uni-xfer then.. |
525 | ; maybe we are the receiver in the uni-xfer then.. |
530 | 526 | ||
531 | .not_sender: |
527 | .not_sender: |
532 | ; - The amount of data in the segment is greater than 0 (data count is in ecx) |
528 | ; - The amount of data in the segment is greater than 0 (data count is in ecx) |
533 | 529 | ||
534 | ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment. |
530 | ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment. |
535 | mov eax, [edx + TCP_header.AckNumber] |
531 | mov eax, [edx + TCP_header.AckNumber] |
536 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
532 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
537 | jne .not_uni_xfer |
533 | jne .not_uni_xfer |
538 | 534 | ||
539 | ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). |
535 | ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). |
540 | 536 | ||
541 | ;;; TODO |
537 | ;;; TODO |
542 | 538 | ||
543 | ; jnz .not_uni_xfer |
539 | ; jnz .not_uni_xfer |
544 | 540 | ||
545 | ; Complete processing of received data |
541 | ; Complete processing of received data |
546 | 542 | ||
547 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx |
543 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction: we are receiving %u bytes\n", ecx |
548 | 544 | ||
549 | mov esi, [dataoffset] |
545 | mov esi, [dataoffset] |
550 | add esi, edx |
546 | add esi, edx |
551 | lea eax, [ebx + STREAM_SOCKET.rcv] |
547 | lea eax, [ebx + STREAM_SOCKET.rcv] |
552 | call SOCKET_ring_write ; Add the data to the socket buffer |
548 | call SOCKET_ring_write ; Add the data to the socket buffer |
553 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
549 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
554 | 550 | ||
555 | mov eax, ebx |
551 | mov eax, ebx |
556 | call SOCKET_notify |
552 | call SOCKET_notify |
557 | 553 | ||
558 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag |
554 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag |
559 | 555 | ||
560 | jmp .drop |
556 | jmp .drop |
561 | 557 | ||
562 | ;-------------------------------------------------- |
558 | ;-------------------------------------------------- |
563 | ; Header prediction failed, do it the slow way |
559 | ; Header prediction failed, do it the slow way |
564 | 560 | ||
565 | .not_uni_xfer: |
561 | .not_uni_xfer: |
566 | 562 | ||
567 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n" |
563 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Header prediction failed\n" |
568 | 564 | ||
569 | ; Calculate receive window size |
565 | ; Calculate receive window size |
570 | push edx |
566 | push edx |
571 | mov eax, SOCKET_MAXDATA |
567 | mov eax, SOCKET_MAXDATA |
572 | sub eax, [ebx + STREAM_SOCKET.rcv.size] |
568 | sub eax, [ebx + STREAM_SOCKET.rcv.size] |
573 | DEBUGF DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax |
569 | DEBUGF DEBUG_NETWORK_VERBOSE, "Space in receive buffer=%d\n", eax |
574 | mov edx, [ebx + TCP_SOCKET.RCV_ADV] |
570 | mov edx, [ebx + TCP_SOCKET.RCV_ADV] |
575 | sub edx, [ebx + TCP_SOCKET.RCV_NXT] |
571 | sub edx, [ebx + TCP_SOCKET.RCV_NXT] |
576 | DEBUGF DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx |
572 | DEBUGF DEBUG_NETWORK_VERBOSE, "Current advertised window=%d\n", edx |
577 | cmp eax, edx |
573 | cmp eax, edx |
578 | jg @f |
574 | jg @f |
579 | mov eax, edx |
575 | mov eax, edx |
580 | @@: |
576 | @@: |
581 | DEBUGF DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax |
577 | DEBUGF DEBUG_NETWORK_VERBOSE, "Receive window size=%d\n", eax |
582 | mov [ebx + TCP_SOCKET.RCV_WND], eax |
578 | mov [ebx + TCP_SOCKET.RCV_WND], eax |
583 | pop edx |
579 | pop edx |
584 | 580 | ||
585 | ; If we are in listen or syn_sent state, go to that specific code right away |
581 | ; If we are in listen or syn_sent state, go to that specific code right away |
586 | 582 | ||
587 | cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN |
583 | cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN |
588 | je .LISTEN |
584 | je .LISTEN |
589 | 585 | ||
590 | cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT |
586 | cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT |
591 | je .SYN_SENT |
587 | je .SYN_SENT |
592 | 588 | ||
593 | ;---------------------------- |
589 | ;---------------------------- |
594 | ; trim any data not in window |
590 | ; trim any data not in window |
595 | 591 | ||
596 | ; 1. Check for duplicate data at beginning of segment |
592 | ; 1. Check for duplicate data at beginning of segment |
597 | 593 | ||
598 | ; Calculate number of bytes we need to drop |
594 | ; Calculate number of bytes we need to drop |
599 | mov eax, [ebx + TCP_SOCKET.RCV_NXT] |
595 | mov eax, [ebx + TCP_SOCKET.RCV_NXT] |
600 | sub eax, [edx + TCP_header.SequenceNumber] |
596 | sub eax, [edx + TCP_header.SequenceNumber] |
601 | jle .no_duplicate |
597 | jle .no_duplicate |
602 | 598 | ||
603 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax |
599 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: %u bytes duplicate data!\n", eax |
604 | 600 | ||
605 | test [edx + TCP_header.Flags], TH_SYN |
601 | test [edx + TCP_header.Flags], TH_SYN |
606 | jz .no_dup_syn |
602 | jz .no_dup_syn |
607 | 603 | ||
608 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n" |
604 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: got duplicate syn\n" |
609 | 605 | ||
610 | and [edx + TCP_header.Flags], not (TH_SYN) |
606 | and [edx + TCP_header.Flags], not (TH_SYN) |
611 | inc [edx + TCP_header.SequenceNumber] |
607 | inc [edx + TCP_header.SequenceNumber] |
612 | 608 | ||
613 | cmp [edx + TCP_header.UrgentPointer], 1 |
609 | cmp [edx + TCP_header.UrgentPointer], 1 |
614 | jbe @f |
610 | jbe @f |
615 | dec [edx + TCP_header.UrgentPointer] |
611 | dec [edx + TCP_header.UrgentPointer] |
616 | jmp .dup_syn |
612 | jmp .dup_syn |
617 | @@: |
613 | @@: |
618 | and [edx + TCP_header.Flags], not (TH_URG) |
614 | and [edx + TCP_header.Flags], not (TH_URG) |
619 | .dup_syn: |
615 | .dup_syn: |
620 | dec eax |
616 | dec eax |
621 | .no_dup_syn: |
617 | .no_dup_syn: |
622 | 618 | ||
623 | ; 2. Check for entire duplicate segment |
619 | ; 2. Check for entire duplicate segment |
624 | cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size |
620 | cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size |
625 | jb .duplicate |
621 | jb .duplicate |
626 | jnz @f |
622 | jnz @f |
627 | test [edx + TCP_header.Flags], TH_FIN |
623 | test [edx + TCP_header.Flags], TH_FIN |
628 | jnz .duplicate |
624 | jnz .duplicate |
629 | @@: |
625 | @@: |
630 | 626 | ||
631 | ; Any valid FIN must be to the left of the window. |
627 | ; Any valid FIN must be to the left of the window. |
632 | ; At this point the FIN must be out of sequence or a duplicate, drop it |
628 | ; At this point the FIN must be out of sequence or a duplicate, drop it |
633 | and [edx + TCP_header.Flags], not TH_FIN |
629 | and [edx + TCP_header.Flags], not TH_FIN |
634 | 630 | ||
635 | ; send an ACK and resynchronize and drop any data. |
631 | ; send an ACK and resynchronize and drop any data. |
636 | ; But keep on processing for RST or ACK |
632 | ; But keep on processing for RST or ACK |
637 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
633 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
638 | mov eax, ecx |
634 | mov eax, ecx |
639 | 635 | ||
640 | ;;; TODO: update stats |
636 | ;;; TODO: update stats |
641 | 637 | ||
642 | ;----------------------------------------------- |
638 | ;----------------------------------------------- |
643 | ; Remove duplicate data and update urgent offset |
639 | ; Remove duplicate data and update urgent offset |
644 | 640 | ||
645 | .duplicate: |
641 | .duplicate: |
646 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n" |
642 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: trimming duplicate data\n" |
647 | 643 | ||
648 | ; Trim data from left side of window |
644 | ; Trim data from left side of window |
649 | add [dataoffset], eax |
645 | add [dataoffset], eax |
650 | add [edx + TCP_header.SequenceNumber], eax |
646 | add [edx + TCP_header.SequenceNumber], eax |
651 | sub ecx, eax |
647 | sub ecx, eax |
652 | 648 | ||
653 | sub [edx + TCP_header.UrgentPointer], ax |
649 | sub [edx + TCP_header.UrgentPointer], ax |
654 | jg @f |
650 | jg @f |
655 | and [edx + TCP_header.Flags], not (TH_URG) |
651 | and [edx + TCP_header.Flags], not (TH_URG) |
656 | mov [edx + TCP_header.UrgentPointer], 0 |
652 | mov [edx + TCP_header.UrgentPointer], 0 |
657 | @@: |
653 | @@: |
658 | 654 | ||
659 | ;-------------------------------------------------- |
655 | ;-------------------------------------------------- |
660 | ; Handle data that arrives after process terminates |
656 | ; Handle data that arrives after process terminates |
661 | 657 | ||
662 | .no_duplicate: |
658 | .no_duplicate: |
663 | cmp [ebx + SOCKET.PID], 0 ;;; TODO: use socket flags instead?? |
659 | cmp [ebx + SOCKET.PID], 0 ;;; TODO: use socket flags instead?? |
664 | jne .not_terminated |
660 | jne .not_terminated |
665 | cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT |
661 | cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT |
666 | jbe .not_terminated |
662 | jbe .not_terminated |
667 | test ecx, ecx |
663 | test ecx, ecx |
668 | jz .not_terminated |
664 | jz .not_terminated |
669 | 665 | ||
670 | mov eax, ebx |
666 | mov eax, ebx |
671 | call TCP_close |
667 | call TCP_close |
672 | ;;; TODO: update stats |
668 | ;;; TODO: update stats |
673 | jmp .respond_seg_reset |
669 | jmp .respond_seg_reset |
674 | 670 | ||
675 | ;---------------------------------------- |
671 | ;---------------------------------------- |
676 | ; Remove data beyond right edge of window |
672 | ; Remove data beyond right edge of window |
677 | 673 | ||
678 | .not_terminated: |
674 | .not_terminated: |
679 | mov eax, [edx + TCP_header.SequenceNumber] |
675 | mov eax, [edx + TCP_header.SequenceNumber] |
680 | add eax, ecx |
676 | add eax, ecx |
681 | sub eax, [ebx + TCP_SOCKET.RCV_NXT] |
677 | sub eax, [ebx + TCP_SOCKET.RCV_NXT] |
682 | sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop |
678 | sub eax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop |
683 | jle .no_excess_data |
679 | jle .no_excess_data |
684 | 680 | ||
685 | DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax |
681 | DEBUGF DEBUG_NETWORK_VERBOSE, "%d bytes beyond right edge of window\n", eax |
686 | 682 | ||
687 | ;;; TODO: update stats |
683 | ;;; TODO: update stats |
688 | cmp eax, ecx |
684 | cmp eax, ecx |
689 | jl .dont_drop_all |
685 | jl .dont_drop_all |
690 | ; If a new connection request is received while in TIME_WAIT, drop the old connection and start over, |
686 | ; If a new connection request is received while in TIME_WAIT, drop the old connection and start over, |
691 | ; if the sequence numbers are above the previous ones |
687 | ; if the sequence numbers are above the previous ones |
692 | 688 | ||
693 | test [edx + TCP_header.Flags], TH_SYN |
689 | test [edx + TCP_header.Flags], TH_SYN |
694 | jz .no_new_request |
690 | jz .no_new_request |
695 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
691 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
696 | jne .no_new_request |
692 | jne .no_new_request |
697 | ; mov edx, [ebx + TCP_SOCKET.RCV_NXT] |
693 | ; mov edx, [ebx + TCP_SOCKET.RCV_NXT] |
698 | ; cmp edx, [edx + TCP_header.SequenceNumber] |
694 | ; cmp edx, [edx + TCP_header.SequenceNumber] |
699 | ; add edx, 64000 ; TCP_ISSINCR FIXME |
695 | ; add edx, 64000 ; TCP_ISSINCR FIXME |
700 | mov eax, ebx |
696 | mov eax, ebx |
701 | call TCP_close |
697 | call TCP_close |
702 | jmp .findpcb ; FIXME: skip code for unscaling window, ... |
698 | jmp .findpcb ; FIXME: skip code for unscaling window, ... |
703 | .no_new_request: |
699 | .no_new_request: |
704 | 700 | ||
705 | ; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from |
701 | ; If window is closed, we can only take segments at window edge, and have to drop data and PUSH from |
706 | ; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK |
702 | ; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK |
707 | 703 | ||
708 | cmp [ebx + TCP_SOCKET.RCV_WND], 0 |
704 | cmp [ebx + TCP_SOCKET.RCV_WND], 0 |
709 | jne .drop_after_ack |
705 | jne .drop_after_ack |
710 | mov esi, [edx + TCP_header.SequenceNumber] |
706 | mov esi, [edx + TCP_header.SequenceNumber] |
711 | cmp esi, [ebx + TCP_SOCKET.RCV_NXT] |
707 | cmp esi, [ebx + TCP_SOCKET.RCV_NXT] |
712 | jne .drop_after_ack |
708 | jne .drop_after_ack |
713 | 709 | ||
714 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
710 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
715 | ;;; TODO: update stats |
711 | ;;; TODO: update stats |
716 | .dont_drop_all: |
712 | .dont_drop_all: |
717 | ;;; TODO: update stats |
713 | ;;; TODO: update stats |
718 | DEBUGF DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n" |
714 | DEBUGF DEBUG_NETWORK_VERBOSE, "Trimming %u bytes from the right of the window\n" |
719 | sub ecx, eax ; remove data from the right side of window (decrease data length) |
715 | sub ecx, eax ; remove data from the right side of window (decrease data length) |
720 | and [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN) |
716 | and [edx + TCP_header.Flags], not (TH_PUSH or TH_FIN) |
721 | .no_excess_data: |
717 | .no_excess_data: |
722 | 718 | ||
723 | ;----------------- |
719 | ;----------------- |
724 | ; Record timestamp |
720 | ; Record timestamp |
725 | 721 | ||
726 | ; If last ACK falls within this segments sequence numbers, record its timestamp |
722 | ; If last ACK falls within this segments sequence numbers, record its timestamp |
727 | test [temp_bits], TCP_BIT_TIMESTAMP |
723 | test [temp_bits], TCP_BIT_TIMESTAMP |
728 | jz .no_timestamp |
724 | jz .no_timestamp |
729 | mov eax, [ebx + TCP_SOCKET.last_ack_sent] |
725 | mov eax, [ebx + TCP_SOCKET.last_ack_sent] |
730 | sub eax, [edx + TCP_header.SequenceNumber] |
726 | sub eax, [edx + TCP_header.SequenceNumber] |
731 | jb .no_timestamp |
727 | jb .no_timestamp |
732 | test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte |
728 | test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte |
733 | jz @f |
729 | jz @f |
734 | dec eax |
730 | dec eax |
735 | @@: |
731 | @@: |
736 | sub eax, ecx |
732 | sub eax, ecx |
737 | jae .no_timestamp |
733 | jae .no_timestamp |
738 | 734 | ||
739 | DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n" |
735 | DEBUGF DEBUG_NETWORK_VERBOSE, "Recording timestamp\n" |
740 | 736 | ||
741 | mov eax, [timestamp] |
737 | mov eax, [timestamp] |
742 | mov [ebx + TCP_SOCKET.ts_recent_age], eax |
738 | mov [ebx + TCP_SOCKET.ts_recent_age], eax |
743 | mov eax, [ebx + TCP_SOCKET.ts_val] |
739 | mov eax, [ebx + TCP_SOCKET.ts_val] |
744 | mov [ebx + TCP_SOCKET.ts_recent], eax |
740 | mov [ebx + TCP_SOCKET.ts_recent], eax |
745 | .no_timestamp: |
741 | .no_timestamp: |
746 | 742 | ||
747 | ;------------------ |
743 | ;------------------ |
748 | ; Process RST flags |
744 | ; Process RST flags |
749 | 745 | ||
750 | test [edx + TCP_header.Flags], TH_RST |
746 | test [edx + TCP_header.Flags], TH_RST |
751 | jz .no_rst |
747 | jz .no_rst |
752 | 748 | ||
753 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n" |
749 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Got an RST flag\n" |
754 | 750 | ||
755 | mov eax, [ebx + TCP_SOCKET.t_state] |
751 | mov eax, [ebx + TCP_SOCKET.t_state] |
756 | shl eax, 2 |
752 | shl eax, 2 |
757 | jmp dword [eax + .rst_sw_list] |
753 | jmp dword [eax + .rst_sw_list] |
758 | 754 | ||
759 | .rst_sw_list: |
755 | .rst_sw_list: |
760 | dd .no_rst ; TCPS_CLOSED |
756 | dd .no_rst ; TCPS_CLOSED |
761 | dd .no_rst ; TCPS_LISTEN |
757 | dd .no_rst ; TCPS_LISTEN |
762 | dd .no_rst ; TCPS_SYN_SENT |
758 | dd .no_rst ; TCPS_SYN_SENT |
763 | dd .econnrefused ; TCPS_SYN_RECEIVED |
759 | dd .econnrefused ; TCPS_SYN_RECEIVED |
764 | dd .econnreset ; TCPS_ESTABLISHED |
760 | dd .econnreset ; TCPS_ESTABLISHED |
765 | dd .econnreset ; TCPS_CLOSE_WAIT |
761 | dd .econnreset ; TCPS_CLOSE_WAIT |
766 | dd .econnreset ; TCPS_FIN_WAIT_1 |
762 | dd .econnreset ; TCPS_FIN_WAIT_1 |
767 | dd .rst_close ; TCPS_CLOSING |
763 | dd .rst_close ; TCPS_CLOSING |
768 | dd .rst_close ; TCPS_LAST_ACK |
764 | dd .rst_close ; TCPS_LAST_ACK |
769 | dd .econnreset ; TCPS_FIN_WAIT_2 |
765 | dd .econnreset ; TCPS_FIN_WAIT_2 |
770 | dd .rst_close ; TCPS_TIMED_WAIT |
766 | dd .rst_close ; TCPS_TIMED_WAIT |
771 | 767 | ||
772 | .econnrefused: |
768 | .econnrefused: |
773 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n" |
769 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection refused\n" |
774 | 770 | ||
775 | mov [ebx + SOCKET.errorcode], ECONNREFUSED |
771 | mov [ebx + SOCKET.errorcode], ECONNREFUSED |
776 | jmp .close |
772 | jmp .close |
777 | 773 | ||
778 | .econnreset: |
774 | .econnreset: |
779 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n" |
775 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Connection reset\n" |
780 | 776 | ||
781 | mov [ebx + SOCKET.errorcode], ECONNRESET |
777 | mov [ebx + SOCKET.errorcode], ECONNRESET |
782 | 778 | ||
783 | .close: |
779 | .close: |
784 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n" |
780 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing connection\n" |
785 | 781 | ||
786 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED |
782 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED |
787 | ;;; TODO: update stats (tcp drops) |
783 | ;;; TODO: update stats (tcp drops) |
788 | mov eax, ebx |
784 | mov eax, ebx |
789 | call TCP_close |
785 | call TCP_close |
790 | jmp .drop_no_socket |
786 | jmp .drop_no_socket |
791 | 787 | ||
792 | .rst_close: |
788 | .rst_close: |
793 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n" |
789 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Closing with reset\n" |
794 | 790 | ||
795 | mov eax, ebx |
791 | mov eax, ebx |
796 | call TCP_close |
792 | call TCP_close |
797 | jmp .drop_no_socket |
793 | jmp .drop_no_socket |
798 | 794 | ||
799 | .no_rst: |
795 | .no_rst: |
800 | 796 | ||
801 | ;-------------------------------------- |
797 | ;-------------------------------------- |
802 | ; handle SYN-full and ACK-less segments |
798 | ; handle SYN-full and ACK-less segments |
803 | 799 | ||
804 | test [edx + TCP_header.Flags], TH_SYN |
800 | test [edx + TCP_header.Flags], TH_SYN |
805 | jz .not_syn_full |
801 | jz .not_syn_full |
806 | 802 | ||
807 | mov eax, ebx |
803 | mov eax, ebx |
808 | mov ebx, ECONNRESET |
804 | mov ebx, ECONNRESET |
809 | call TCP_drop |
805 | call TCP_drop |
810 | jmp .drop_with_reset |
806 | jmp .drop_with_reset |
811 | .not_syn_full: |
807 | .not_syn_full: |
812 | 808 | ||
813 | ;--------------- |
809 | ;--------------- |
814 | ; ACK processing |
810 | ; ACK processing |
815 | 811 | ||
816 | test [edx + TCP_header.Flags], TH_ACK |
812 | test [edx + TCP_header.Flags], TH_ACK |
817 | jz .drop |
813 | jz .drop |
818 | 814 | ||
819 | cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
815 | cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
820 | jb .ack_processed ; states: closed, listen, syn_sent |
816 | jb .ack_processed ; states: closed, listen, syn_sent |
821 | ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait |
817 | ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait |
822 | 818 | ||
823 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n" |
819 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_received\n" |
824 | 820 | ||
825 | mov eax, [edx + TCP_header.AckNumber] |
821 | mov eax, [edx + TCP_header.AckNumber] |
826 | cmp [ebx + TCP_SOCKET.SND_UNA], eax |
822 | cmp [ebx + TCP_SOCKET.SND_UNA], eax |
827 | ja .drop_with_reset |
823 | ja .drop_with_reset |
828 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
824 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
829 | ja .drop_with_reset |
825 | ja .drop_with_reset |
830 | 826 | ||
831 | ;;; TODO: update stats |
827 | ;;; TODO: update stats |
832 | 828 | ||
833 | mov eax, ebx |
829 | mov eax, ebx |
834 | call SOCKET_is_connected |
830 | call SOCKET_is_connected |
835 | mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
831 | mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
836 | 832 | ||
837 | ; Do window scaling? |
833 | ; Do window scaling? |
838 | 834 | ||
839 | test [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
835 | test [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
840 | jz @f |
836 | jz @f |
841 | test [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE |
837 | test [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE |
842 | jz @f |
838 | jz @f |
843 | 839 | ||
844 | push word [ebx + TCP_SOCKET.requested_s_scale] ; Set send and receive scale factors to the received values |
840 | push word [ebx + TCP_SOCKET.requested_s_scale] ; Set send and receive scale factors to the received values |
845 | pop word [ebx + TCP_SOCKET.SND_SCALE] |
841 | pop word [ebx + TCP_SOCKET.SND_SCALE] |
846 | @@: |
842 | @@: |
847 | 843 | ||
848 | ;;; TODO: call TCP_reassemble |
844 | ;;; TODO: call TCP_reassemble |
849 | 845 | ||
850 | mov eax, [edx + TCP_header.SequenceNumber] |
846 | mov eax, [edx + TCP_header.SequenceNumber] |
851 | dec eax |
847 | dec eax |
852 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
848 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
853 | 849 | ||
854 | .no_syn_rcv: |
850 | .no_syn_rcv: |
855 | 851 | ||
856 | ;------------------------- |
852 | ;------------------------- |
857 | ; check for duplicate ACKs |
853 | ; check for duplicate ACKs |
858 | 854 | ||
859 | mov eax, [edx + TCP_header.AckNumber] |
855 | mov eax, [edx + TCP_header.AckNumber] |
860 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
856 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
861 | ja .not_dup_ack |
857 | ja .not_dup_ack |
862 | 858 | ||
863 | test ecx, ecx |
859 | test ecx, ecx |
864 | jnz .reset_dupacks |
860 | jnz .reset_dupacks |
865 | 861 | ||
866 | mov eax, dword [edx + TCP_header.Window] |
862 | mov eax, dword [edx + TCP_header.Window] |
867 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
863 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
868 | jne .reset_dupacks |
864 | jne .reset_dupacks |
869 | 865 | ||
870 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n" |
866 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing duplicate ACK\n" |
871 | 867 | ||
872 | ; If we have outstanding data, other than a window probe, this is a completely duplicate ACK |
868 | ; If we have outstanding data, other than a window probe, this is a completely duplicate ACK |
873 | ; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them, |
869 | ; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them, |
874 | ; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet. |
870 | ; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet. |
875 | 871 | ||
876 | test [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission |
872 | test [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission |
877 | jz @f |
873 | jz @f |
878 | 874 | ||
879 | mov eax, [edx + TCP_header.AckNumber] |
875 | mov eax, [edx + TCP_header.AckNumber] |
880 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
876 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
881 | je .dup_ack |
877 | je .dup_ack |
882 | 878 | ||
883 | @@: |
879 | @@: |
884 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
880 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
885 | jmp .not_dup_ack |
881 | jmp .not_dup_ack |
886 | 882 | ||
887 | .dup_ack: |
883 | .dup_ack: |
888 | inc [ebx + TCP_SOCKET.t_dupacks] |
884 | inc [ebx + TCP_SOCKET.t_dupacks] |
889 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
885 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
890 | jne .no_re_xmit |
886 | jne .no_re_xmit |
891 | 887 | ||
892 | push [ebx + TCP_SOCKET.SND_NXT] ; >>>> |
888 | push [ebx + TCP_SOCKET.SND_NXT] ; >>>> |
893 | 889 | ||
894 | mov eax, [ebx + TCP_SOCKET.SND_WND] |
890 | mov eax, [ebx + TCP_SOCKET.SND_WND] |
895 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
891 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
896 | jbe @f |
892 | jbe @f |
897 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
893 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
898 | @@: |
894 | @@: |
899 | shr eax, 1 |
895 | shr eax, 1 |
900 | push edx |
896 | push edx |
901 | xor edx, edx |
897 | xor edx, edx |
902 | div [ebx + TCP_SOCKET.t_maxseg] |
898 | div [ebx + TCP_SOCKET.t_maxseg] |
903 | cmp eax, 2 |
899 | cmp eax, 2 |
904 | ja @f |
900 | ja @f |
905 | xor eax, eax |
901 | xor eax, eax |
906 | mov al, 2 |
902 | mov al, 2 |
907 | @@: |
903 | @@: |
908 | mul [ebx + TCP_SOCKET.t_maxseg] |
904 | mul [ebx + TCP_SOCKET.t_maxseg] |
909 | pop edx |
905 | pop edx |
910 | mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax |
906 | mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax |
911 | 907 | ||
912 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission ; turn off retransmission timer |
908 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission ; turn off retransmission timer |
913 | mov [ebx + TCP_SOCKET.t_rtt], 0 |
909 | mov [ebx + TCP_SOCKET.t_rtt], 0 |
914 | mov eax, [edx + TCP_header.AckNumber] |
910 | mov eax, [edx + TCP_header.AckNumber] |
915 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
911 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
916 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
912 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
917 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
913 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
918 | 914 | ||
919 | ; Unlock the socket |
915 | ; Unlock the socket |
920 | push ebx |
916 | push ebx |
921 | lea ecx, [ebx + SOCKET.mutex] |
917 | lea ecx, [ebx + SOCKET.mutex] |
922 | call mutex_unlock |
918 | call mutex_unlock |
923 | 919 | ||
924 | ; retransmit missing segment |
920 | ; retransmit missing segment |
925 | mov eax, [esp] |
921 | mov eax, [esp] |
926 | call TCP_output |
922 | call TCP_output |
927 | 923 | ||
928 | ; Lock the socket again |
924 | ; Lock the socket again |
929 | mov ecx, [esp] |
925 | mov ecx, [esp] |
930 | add ecx, SOCKET.mutex |
926 | add ecx, SOCKET.mutex |
931 | call mutex_lock |
927 | call mutex_lock |
932 | pop ebx |
928 | pop ebx |
933 | 929 | ||
934 | ; Continue processing |
930 | ; Continue processing |
935 | xor edx, edx |
931 | xor edx, edx |
936 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
932 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
937 | mul [ebx + TCP_SOCKET.t_dupacks] |
933 | mul [ebx + TCP_SOCKET.t_dupacks] |
938 | add eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
934 | add eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
939 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
935 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
940 | 936 | ||
941 | pop eax ; <<<< |
937 | pop eax ; <<<< |
942 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
938 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
943 | jb @f |
939 | jb @f |
944 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
940 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
945 | @@: |
941 | @@: |
946 | 942 | ||
947 | jmp .drop |
943 | jmp .drop |
948 | 944 | ||
949 | 945 | ||
950 | .no_re_xmit: |
946 | .no_re_xmit: |
951 | jbe .not_dup_ack |
947 | jbe .not_dup_ack |
952 | 948 | ||
953 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n" |
949 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Increasing congestion window\n" |
954 | 950 | ||
955 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
951 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
956 | add [ebx + TCP_SOCKET.SND_CWND], eax |
952 | add [ebx + TCP_SOCKET.SND_CWND], eax |
957 | 953 | ||
958 | ; Unlock the socket |
954 | ; Unlock the socket |
959 | push ebx |
955 | push ebx |
960 | lea ecx, [ebx + SOCKET.mutex] |
956 | lea ecx, [ebx + SOCKET.mutex] |
961 | call mutex_unlock |
957 | call mutex_unlock |
962 | 958 | ||
963 | ; retransmit missing segment |
959 | ; retransmit missing segment |
964 | mov eax, [esp] |
960 | mov eax, [esp] |
965 | call TCP_output |
961 | call TCP_output |
966 | 962 | ||
967 | ; Lock the socket again |
963 | ; Lock the socket again |
968 | mov ecx, [esp] |
964 | mov ecx, [esp] |
969 | add ecx, SOCKET.mutex |
965 | add ecx, SOCKET.mutex |
970 | call mutex_lock |
966 | call mutex_lock |
971 | pop ebx |
967 | pop ebx |
972 | 968 | ||
973 | jmp .drop |
969 | jmp .drop |
974 | 970 | ||
975 | 971 | ||
976 | .not_dup_ack: |
972 | .not_dup_ack: |
977 | 973 | ||
978 | ;------------------------------------------------- |
974 | ;------------------------------------------------- |
979 | ; If the congestion window was inflated to account |
975 | ; If the congestion window was inflated to account |
980 | ; for the other side's cached packets, retract it |
976 | ; for the other side's cached packets, retract it |
981 | 977 | ||
982 | mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
978 | mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH] |
983 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
979 | cmp eax, [ebx + TCP_SOCKET.SND_CWND] |
984 | ja @f |
980 | ja @f |
985 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
981 | cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh |
986 | jbe @f |
982 | jbe @f |
987 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
983 | mov [ebx + TCP_SOCKET.SND_CWND], eax |
988 | @@: |
984 | @@: |
989 | 985 | ||
990 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
986 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
991 | 987 | ||
992 | mov eax, [edx + TCP_header.AckNumber] |
988 | mov eax, [edx + TCP_header.AckNumber] |
993 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
989 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
994 | jbe @f |
990 | jbe @f |
995 | 991 | ||
996 | ;;; TODO: update stats |
992 | ;;; TODO: update stats |
997 | jmp .drop_after_ack |
993 | jmp .drop_after_ack |
998 | 994 | ||
999 | @@: |
995 | @@: |
1000 | 996 | ||
1001 | mov edi, [edx + TCP_header.AckNumber] |
997 | mov edi, [edx + TCP_header.AckNumber] |
1002 | sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in edi |
998 | sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in edi |
1003 | 999 | ||
1004 | ;;; TODO: update stats |
1000 | ;;; TODO: update stats |
1005 | 1001 | ||
1006 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi |
1002 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: acceptable ACK for %u bytes\n", edi |
1007 | 1003 | ||
1008 | ;------------------------------------------ |
1004 | ;------------------------------------------ |
1009 | ; RTT measurements and retransmission timer |
1005 | ; RTT measurements and retransmission timer |
1010 | 1006 | ||
1011 | ; If we have a timestamp, update smoothed RTT |
1007 | ; If we have a timestamp, update smoothed RTT |
1012 | 1008 | ||
1013 | test [temp_bits], TCP_BIT_TIMESTAMP |
1009 | test [temp_bits], TCP_BIT_TIMESTAMP |
1014 | jz .timestamp_not_present |
1010 | jz .timestamp_not_present |
1015 | mov eax, [timestamp] |
1011 | mov eax, [timestamp] |
1016 | sub eax, [ebx + TCP_SOCKET.ts_ecr] |
1012 | sub eax, [ebx + TCP_SOCKET.ts_ecr] |
1017 | inc eax |
1013 | inc eax |
1018 | call TCP_xmit_timer |
1014 | call TCP_xmit_timer |
1019 | jmp .rtt_done_ |
1015 | jmp .rtt_done_ |
1020 | 1016 | ||
1021 | ; If no timestamp but transmit timer is running and timed sequence number was acked, |
1017 | ; If no timestamp but transmit timer is running and timed sequence number was acked, |
1022 | ; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff |
1018 | ; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff |
1023 | ; (Phil Karn's retransmit algo) |
1019 | ; (Phil Karn's retransmit algo) |
1024 | ; Recompute the initial retransmit timer |
1020 | ; Recompute the initial retransmit timer |
1025 | 1021 | ||
1026 | .timestamp_not_present: |
1022 | .timestamp_not_present: |
1027 | mov eax, [edx + TCP_header.AckNumber] |
1023 | mov eax, [edx + TCP_header.AckNumber] |
1028 | cmp eax, [ebx + TCP_SOCKET.t_rtseq] |
1024 | cmp eax, [ebx + TCP_SOCKET.t_rtseq] |
1029 | jbe .rtt_done_ |
1025 | jbe .rtt_done_ |
1030 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
1026 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
1031 | test eax, eax |
1027 | test eax, eax |
1032 | jz .rtt_done_ |
1028 | jz .rtt_done_ |
1033 | call TCP_xmit_timer |
1029 | call TCP_xmit_timer |
1034 | 1030 | ||
1035 | .rtt_done_: |
1031 | .rtt_done_: |
1036 | 1032 | ||
1037 | ; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist) |
1033 | ; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist) |
1038 | ; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value. |
1034 | ; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value. |
1039 | 1035 | ||
1040 | mov eax, [ebx + TCP_SOCKET.SND_MAX] |
1036 | mov eax, [ebx + TCP_SOCKET.SND_MAX] |
1041 | cmp eax, [edx + TCP_header.AckNumber] |
1037 | cmp eax, [edx + TCP_header.AckNumber] |
1042 | jne .more_data |
1038 | jne .more_data |
1043 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission |
1039 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission |
1044 | or [temp_bits], TCP_BIT_NEEDOUTPUT |
1040 | or [temp_bits], TCP_BIT_NEEDOUTPUT |
1045 | jmp .no_restart |
1041 | jmp .no_restart |
1046 | .more_data: |
1042 | .more_data: |
1047 | test [ebx + TCP_SOCKET.timer_flags], timer_flag_persist |
1043 | test [ebx + TCP_SOCKET.timer_flags], timer_flag_persist |
1048 | jnz .no_restart |
1044 | jnz .no_restart |
1049 | 1045 | ||
1050 | mov eax, [ebx + TCP_SOCKET.t_rxtcur] |
1046 | mov eax, [ebx + TCP_SOCKET.t_rxtcur] |
1051 | mov [ebx + TCP_SOCKET.timer_retransmission], eax |
1047 | mov [ebx + TCP_SOCKET.timer_retransmission], eax |
1052 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission |
1048 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_retransmission |
1053 | .no_restart: |
1049 | .no_restart: |
1054 | 1050 | ||
1055 | 1051 | ||
1056 | ;------------------------------------------- |
1052 | ;------------------------------------------- |
1057 | ; Open congestion window in response to ACKs |
1053 | ; Open congestion window in response to ACKs |
1058 | 1054 | ||
1059 | mov esi, [ebx + TCP_SOCKET.SND_CWND] |
1055 | mov esi, [ebx + TCP_SOCKET.SND_CWND] |
1060 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
1056 | mov eax, [ebx + TCP_SOCKET.t_maxseg] |
1061 | 1057 | ||
1062 | cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH] |
1058 | cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH] |
1063 | jbe @f |
1059 | jbe @f |
1064 | push edx |
1060 | push edx |
1065 | push eax |
1061 | push eax |
1066 | mul eax |
1062 | mul eax |
1067 | div esi |
1063 | div esi |
1068 | pop edx |
1064 | pop edx |
1069 | shr edx, 3 |
1065 | shr edx, 3 |
1070 | add eax, edx |
1066 | add eax, edx |
1071 | pop edx |
1067 | pop edx |
1072 | @@: |
1068 | @@: |
1073 | 1069 | ||
1074 | add esi, eax |
1070 | add esi, eax |
1075 | 1071 | ||
1076 | push ecx |
1072 | push ecx |
1077 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
1073 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
1078 | mov eax, TCP_max_win |
1074 | mov eax, TCP_max_win |
1079 | shl eax, cl |
1075 | shl eax, cl |
1080 | pop ecx |
1076 | pop ecx |
1081 | 1077 | ||
1082 | cmp esi, eax |
1078 | cmp esi, eax |
1083 | jbe @f |
1079 | jbe @f |
1084 | mov esi, eax |
1080 | mov esi, eax |
1085 | @@: |
1081 | @@: |
1086 | mov [ebx + TCP_SOCKET.SND_CWND], esi |
1082 | mov [ebx + TCP_SOCKET.SND_CWND], esi |
1087 | 1083 | ||
1088 | ;------------------------------------------ |
1084 | ;------------------------------------------ |
1089 | ; Remove acknowledged data from send buffer |
1085 | ; Remove acknowledged data from send buffer |
1090 | 1086 | ||
1091 | cmp edi, [ebx + STREAM_SOCKET.snd.size] |
1087 | cmp edi, [ebx + STREAM_SOCKET.snd.size] |
1092 | jbe .finiacked |
1088 | jbe .finiacked |
1093 | 1089 | ||
1094 | push ecx edx ebx |
1090 | push ecx edx ebx |
1095 | mov ecx, [ebx + STREAM_SOCKET.snd.size] |
1091 | mov ecx, [ebx + STREAM_SOCKET.snd.size] |
1096 | lea eax, [ebx + STREAM_SOCKET.snd] |
1092 | lea eax, [ebx + STREAM_SOCKET.snd] |
1097 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1093 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1098 | call SOCKET_ring_free |
1094 | call SOCKET_ring_free |
1099 | pop ebx edx ecx |
1095 | pop ebx edx ecx |
1100 | 1096 | ||
1101 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n" |
1097 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is acked\n" |
1102 | stc |
1098 | stc |
1103 | 1099 | ||
1104 | jmp .wakeup |
1100 | jmp .wakeup |
1105 | 1101 | ||
1106 | .finiacked: |
1102 | .finiacked: |
1107 | 1103 | ||
1108 | push ecx edx ebx |
1104 | push ecx edx ebx |
1109 | mov ecx, edi |
1105 | mov ecx, edi |
1110 | lea eax, [ebx + STREAM_SOCKET.snd] |
1106 | lea eax, [ebx + STREAM_SOCKET.snd] |
1111 | call SOCKET_ring_free |
1107 | call SOCKET_ring_free |
1112 | pop ebx |
1108 | pop ebx |
1113 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1109 | sub [ebx + TCP_SOCKET.SND_WND], ecx |
1114 | pop edx ecx |
1110 | pop edx ecx |
1115 | 1111 | ||
1116 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n" |
1112 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: our FIN is not acked\n" |
1117 | clc |
1113 | clc |
1118 | 1114 | ||
1119 | ;---------------------------------------- |
1115 | ;---------------------------------------- |
1120 | ; Wake up process waiting on send buffer |
1116 | ; Wake up process waiting on send buffer |
1121 | 1117 | ||
1122 | .wakeup: |
1118 | .wakeup: |
1123 | 1119 | ||
1124 | pushf ; Keep the flags (Carry flag) |
1120 | pushf ; Keep the flags (Carry flag) |
1125 | mov eax, ebx |
1121 | mov eax, ebx |
1126 | call SOCKET_notify |
1122 | call SOCKET_notify |
1127 | 1123 | ||
1128 | ; Update TCPS |
1124 | ; Update TCPS |
1129 | 1125 | ||
1130 | mov eax, [edx + TCP_header.AckNumber] |
1126 | mov eax, [edx + TCP_header.AckNumber] |
1131 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1127 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1132 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1128 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1133 | jb @f |
1129 | jb @f |
1134 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1130 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1135 | @@: |
1131 | @@: |
1136 | 1132 | ||
1137 | popf |
1133 | popf |
1138 | 1134 | ||
1139 | ; General ACK handling complete |
1135 | ; General ACK handling complete |
1140 | ; Now do the state-specific ones |
1136 | ; Now do the state-specific ones |
1141 | ; Carry flag is set when our FIN is acked |
1137 | ; Carry flag is set when our FIN is acked |
1142 | 1138 | ||
1143 | mov eax, [ebx + TCP_SOCKET.t_state] |
1139 | mov eax, [ebx + TCP_SOCKET.t_state] |
1144 | jmp dword [eax*4 + .ACK_sw_list] |
1140 | jmp dword [eax*4 + .ACK_sw_list] |
1145 | 1141 | ||
1146 | .ACK_sw_list: |
1142 | .ACK_sw_list: |
1147 | dd .ack_processed ; TCPS_CLOSED |
1143 | dd .ack_processed ; TCPS_CLOSED |
1148 | dd .ack_processed ; TCPS_LISTEN |
1144 | dd .ack_processed ; TCPS_LISTEN |
1149 | dd .ack_processed ; TCPS_SYN_SENT |
1145 | dd .ack_processed ; TCPS_SYN_SENT |
1150 | dd .ack_processed ; TCPS_SYN_RECEIVED |
1146 | dd .ack_processed ; TCPS_SYN_RECEIVED |
1151 | dd .ack_processed ; TCPS_ESTABLISHED |
1147 | dd .ack_processed ; TCPS_ESTABLISHED |
1152 | dd .ack_processed ; TCPS_CLOSE_WAIT |
1148 | dd .ack_processed ; TCPS_CLOSE_WAIT |
1153 | dd .ack_fw1 ; TCPS_FIN_WAIT_1 |
1149 | dd .ack_fw1 ; TCPS_FIN_WAIT_1 |
1154 | dd .ack_c ; TCPS_CLOSING |
1150 | dd .ack_c ; TCPS_CLOSING |
1155 | dd .ack_la ; TCPS_LAST_ACK |
1151 | dd .ack_la ; TCPS_LAST_ACK |
1156 | dd .ack_processed ; TCPS_FIN_WAIT_2 |
1152 | dd .ack_processed ; TCPS_FIN_WAIT_2 |
1157 | dd .ack_tw ; TCPS_TIMED_WAIT |
1153 | dd .ack_tw ; TCPS_TIMED_WAIT |
1158 | 1154 | ||
1159 | 1155 | ||
1160 | .ack_fw1: |
1156 | .ack_fw1: |
1161 | jnc .ack_processed |
1157 | jnc .ack_processed |
1162 | 1158 | ||
1163 | test [ebx + SOCKET.state], SS_CANTRCVMORE |
1159 | test [ebx + SOCKET.state], SS_CANTRCVMORE |
1164 | jnz @f |
1160 | jnz @f |
1165 | mov eax, ebx |
1161 | mov eax, ebx |
1166 | call SOCKET_is_disconnected |
1162 | call SOCKET_is_disconnected |
1167 | mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle |
1163 | mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle |
1168 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1164 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1169 | @@: |
1165 | @@: |
1170 | mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2 |
1166 | mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2 |
1171 | jmp .ack_processed |
1167 | jmp .ack_processed |
1172 | 1168 | ||
1173 | .ack_c: |
1169 | .ack_c: |
1174 | jnc .ack_processed |
1170 | jnc .ack_processed |
1175 | 1171 | ||
1176 | mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1172 | mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1177 | mov eax, ebx |
1173 | mov eax, ebx |
1178 | call TCP_cancel_timers |
1174 | call TCP_cancel_timers |
1179 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1175 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1180 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1176 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1181 | mov eax, ebx |
1177 | mov eax, ebx |
1182 | call SOCKET_is_disconnected |
1178 | call SOCKET_is_disconnected |
1183 | jmp .ack_processed |
1179 | jmp .ack_processed |
1184 | 1180 | ||
1185 | .ack_la: |
1181 | .ack_la: |
1186 | jnc .ack_processed |
1182 | jnc .ack_processed |
1187 | 1183 | ||
1188 | push ebx |
1184 | push ebx |
1189 | lea ecx, [ebx + SOCKET.mutex] |
1185 | lea ecx, [ebx + SOCKET.mutex] |
1190 | call mutex_unlock |
1186 | call mutex_unlock |
1191 | pop ebx |
1187 | pop ebx |
1192 | 1188 | ||
1193 | mov eax, ebx |
1189 | mov eax, ebx |
1194 | call TCP_close |
1190 | call TCP_close |
1195 | jmp .drop_no_socket |
1191 | jmp .drop_no_socket |
1196 | 1192 | ||
1197 | .ack_tw: |
1193 | .ack_tw: |
1198 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1194 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1199 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1195 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1200 | jmp .drop_after_ack |
1196 | jmp .drop_after_ack |
1201 | 1197 | ||
1202 | .reset_dupacks: ; We got a new ACK, reset duplicate ACK counter |
1198 | .reset_dupacks: ; We got a new ACK, reset duplicate ACK counter |
1203 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
1199 | mov [ebx + TCP_SOCKET.t_dupacks], 0 |
1204 | jmp .ack_processed |
1200 | jmp .ack_processed |
1205 | 1201 | ||
1206 | ;------- |
1202 | ;------- |
1207 | ; LISTEN |
1203 | ; LISTEN |
1208 | 1204 | ||
1209 | align 4 |
1205 | align 4 |
1210 | .LISTEN: |
1206 | .LISTEN: |
1211 | 1207 | ||
1212 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n" |
1208 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=listen\n" |
1213 | 1209 | ||
1214 | test [edx + TCP_header.Flags], TH_RST |
1210 | test [edx + TCP_header.Flags], TH_RST |
1215 | jnz .drop |
1211 | jnz .drop |
1216 | 1212 | ||
1217 | test [edx + TCP_header.Flags], TH_ACK |
1213 | test [edx + TCP_header.Flags], TH_ACK |
1218 | jnz .drop_with_reset |
1214 | jnz .drop_with_reset |
1219 | 1215 | ||
1220 | test [edx + TCP_header.Flags], TH_SYN |
1216 | test [edx + TCP_header.Flags], TH_SYN |
1221 | jz .drop |
1217 | jz .drop |
1222 | 1218 | ||
1223 | ;;; TODO: check if it's a broadcast or multicast, and drop if so |
1219 | ;;; TODO: check if it's a broadcast or multicast, and drop if so |
1224 | 1220 | ||
1225 | push dword [edi] ; Ipv4 source addres |
1221 | push dword [edi] ; Ipv4 source addres |
1226 | pop [ebx + IP_SOCKET.RemoteIP] |
1222 | pop [ebx + IP_SOCKET.RemoteIP] |
1227 | 1223 | ||
1228 | push [edx + TCP_header.SourcePort] |
1224 | push [edx + TCP_header.SourcePort] |
1229 | pop [ebx + TCP_SOCKET.RemotePort] |
1225 | pop [ebx + TCP_SOCKET.RemotePort] |
1230 | 1226 | ||
1231 | push [edx + TCP_header.SequenceNumber] |
1227 | push [edx + TCP_header.SequenceNumber] |
1232 | pop [ebx + TCP_SOCKET.IRS] |
1228 | pop [ebx + TCP_SOCKET.IRS] |
1233 | 1229 | ||
1234 | mov eax, [TCP_sequence_num] |
1230 | mov eax, [TCP_sequence_num] |
1235 | add [TCP_sequence_num], 64000 / 2 |
1231 | add [TCP_sequence_num], 64000 / 2 |
1236 | mov [ebx + TCP_SOCKET.ISS], eax |
1232 | mov [ebx + TCP_SOCKET.ISS], eax |
1237 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1233 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1238 | 1234 | ||
1239 | TCP_sendseqinit ebx |
1235 | TCP_sendseqinit ebx |
1240 | TCP_rcvseqinit ebx |
1236 | TCP_rcvseqinit ebx |
1241 | 1237 | ||
1242 | mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
1238 | mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
1243 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1239 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1244 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro |
1240 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro |
1245 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive |
1241 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_keepalive |
1246 | 1242 | ||
1247 | lea eax, [ebx + STREAM_SOCKET.snd] |
1243 | lea eax, [ebx + STREAM_SOCKET.snd] |
1248 | call SOCKET_ring_create |
1244 | call SOCKET_ring_create |
1249 | 1245 | ||
1250 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1246 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1251 | call SOCKET_ring_create |
1247 | call SOCKET_ring_create |
1252 | 1248 | ||
1253 | and [temp_bits], not TCP_BIT_DROPSOCKET |
1249 | and [temp_bits], not TCP_BIT_DROPSOCKET |
1254 | 1250 | ||
1255 | pusha |
1251 | pusha |
1256 | mov eax, ebx |
1252 | mov eax, ebx |
1257 | call SOCKET_notify |
1253 | call SOCKET_notify |
1258 | popa |
1254 | popa |
1259 | 1255 | ||
1260 | jmp .trim_then_step6 |
1256 | jmp .trim_then_step6 |
1261 | 1257 | ||
1262 | ;------------ |
1258 | ;------------ |
1263 | ; Active Open |
1259 | ; Active Open |
1264 | 1260 | ||
1265 | align 4 |
1261 | align 4 |
1266 | .SYN_SENT: |
1262 | .SYN_SENT: |
1267 | 1263 | ||
1268 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n" |
1264 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: state=syn_sent\n" |
1269 | 1265 | ||
1270 | test [edx + TCP_header.Flags], TH_ACK |
1266 | test [edx + TCP_header.Flags], TH_ACK |
1271 | jz @f |
1267 | jz @f |
1272 | 1268 | ||
1273 | mov eax, [edx + TCP_header.AckNumber] |
1269 | mov eax, [edx + TCP_header.AckNumber] |
1274 | cmp eax, [ebx + TCP_SOCKET.ISS] |
1270 | cmp eax, [ebx + TCP_SOCKET.ISS] |
1275 | jbe .drop_with_reset |
1271 | jbe .drop_with_reset |
1276 | 1272 | ||
1277 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
1273 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
1278 | ja .drop_with_reset |
1274 | ja .drop_with_reset |
1279 | @@: |
1275 | @@: |
1280 | 1276 | ||
1281 | test [edx + TCP_header.Flags], TH_RST |
1277 | test [edx + TCP_header.Flags], TH_RST |
1282 | jz @f |
1278 | jz @f |
1283 | 1279 | ||
1284 | test [edx + TCP_header.Flags], TH_ACK |
1280 | test [edx + TCP_header.Flags], TH_ACK |
1285 | jz .drop |
1281 | jz .drop |
1286 | 1282 | ||
1287 | mov eax, ebx |
1283 | mov eax, ebx |
1288 | mov ebx, ECONNREFUSED |
1284 | mov ebx, ECONNREFUSED |
1289 | call TCP_drop |
1285 | call TCP_drop |
1290 | 1286 | ||
1291 | jmp .drop |
1287 | jmp .drop |
1292 | @@: |
1288 | @@: |
1293 | 1289 | ||
1294 | test [edx + TCP_header.Flags], TH_SYN |
1290 | test [edx + TCP_header.Flags], TH_SYN |
1295 | jz .drop |
1291 | jz .drop |
1296 | 1292 | ||
1297 | ; at this point, segment seems to be valid |
1293 | ; at this point, segment seems to be valid |
1298 | 1294 | ||
1299 | test [edx + TCP_header.Flags], TH_ACK |
1295 | test [edx + TCP_header.Flags], TH_ACK |
1300 | jz .no_syn_ack |
1296 | jz .no_syn_ack |
1301 | 1297 | ||
1302 | ; now, process received SYN in response to an active open |
1298 | ; now, process received SYN in response to an active open |
1303 | 1299 | ||
1304 | mov eax, [edx + TCP_header.AckNumber] |
1300 | mov eax, [edx + TCP_header.AckNumber] |
1305 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1301 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
1306 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1302 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
1307 | jbe @f |
1303 | jbe @f |
1308 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1304 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
1309 | @@: |
1305 | @@: |
1310 | 1306 | ||
1311 | .no_syn_ack: |
1307 | .no_syn_ack: |
1312 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission ; disable retransmission timer |
1308 | and [ebx + TCP_SOCKET.timer_flags], not timer_flag_retransmission ; disable retransmission timer |
1313 | 1309 | ||
1314 | push [edx + TCP_header.SequenceNumber] |
1310 | push [edx + TCP_header.SequenceNumber] |
1315 | pop [ebx + TCP_SOCKET.IRS] |
1311 | pop [ebx + TCP_SOCKET.IRS] |
1316 | 1312 | ||
1317 | TCP_rcvseqinit ebx |
1313 | TCP_rcvseqinit ebx |
1318 | 1314 | ||
1319 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1315 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1320 | 1316 | ||
1321 | mov eax, [ebx + TCP_SOCKET.SND_UNA] |
1317 | mov eax, [ebx + TCP_SOCKET.SND_UNA] |
1322 | cmp eax, [ebx + TCP_SOCKET.ISS] |
1318 | cmp eax, [ebx + TCP_SOCKET.ISS] |
1323 | jbe .simultaneous_open |
1319 | jbe .simultaneous_open |
1324 | 1320 | ||
1325 | test [edx + TCP_header.Flags], TH_ACK |
1321 | test [edx + TCP_header.Flags], TH_ACK |
1326 | jz .simultaneous_open |
1322 | jz .simultaneous_open |
1327 | 1323 | ||
1328 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n" |
1324 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: active open\n" |
1329 | 1325 | ||
1330 | ;;; TODO: update stats |
1326 | ;;; TODO: update stats |
1331 | 1327 | ||
1332 | ; set socket state to connected |
1328 | ; set socket state to connected |
1333 | push eax |
1329 | push eax |
1334 | mov eax, ebx |
1330 | mov eax, ebx |
1335 | call SOCKET_is_connected |
1331 | call SOCKET_is_connected |
1336 | pop eax |
1332 | pop eax |
1337 | mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
1333 | mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
1338 | 1334 | ||
1339 | ; Do window scaling on this connection ? |
1335 | ; Do window scaling on this connection ? |
1340 | mov eax, [ebx + TCP_SOCKET.t_flags] |
1336 | mov eax, [ebx + TCP_SOCKET.t_flags] |
1341 | and eax, TF_REQ_SCALE or TF_RCVD_SCALE |
1337 | and eax, TF_REQ_SCALE or TF_RCVD_SCALE |
1342 | cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE |
1338 | cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE |
1343 | jne .no_scaling |
1339 | jne .no_scaling |
1344 | 1340 | ||
1345 | mov ax, word [ebx + TCP_SOCKET.requested_s_scale] |
1341 | mov ax, word [ebx + TCP_SOCKET.requested_s_scale] |
1346 | mov word [ebx + TCP_SOCKET.SND_SCALE], ax |
1342 | mov word [ebx + TCP_SOCKET.SND_SCALE], ax |
1347 | .no_scaling: |
1343 | .no_scaling: |
1348 | 1344 | ||
1349 | ;;; TODO: reassemble packets queue |
1345 | ;;; TODO: reassemble packets queue |
1350 | 1346 | ||
1351 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
1347 | mov eax, [ebx + TCP_SOCKET.t_rtt] |
1352 | test eax, eax |
1348 | test eax, eax |
1353 | je .trim_then_step6 |
1349 | je .trim_then_step6 |
1354 | call TCP_xmit_timer |
1350 | call TCP_xmit_timer |
1355 | jmp .trim_then_step6 |
1351 | jmp .trim_then_step6 |
1356 | 1352 | ||
1357 | .simultaneous_open: |
1353 | .simultaneous_open: |
1358 | 1354 | ||
1359 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n" |
1355 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: simultaneous open\n" |
1360 | ; We have received a syn but no ACK, so we are having a simultaneous open.. |
1356 | ; We have received a syn but no ACK, so we are having a simultaneous open.. |
1361 | mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
1357 | mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED |
1362 | 1358 | ||
1363 | ;------------------------------------- |
1359 | ;------------------------------------- |
1364 | ; Common processing for receipt of SYN |
1360 | ; Common processing for receipt of SYN |
1365 | 1361 | ||
1366 | .trim_then_step6: |
1362 | .trim_then_step6: |
1367 | 1363 | ||
1368 | inc [edx + TCP_header.SequenceNumber] |
1364 | inc [edx + TCP_header.SequenceNumber] |
1369 | 1365 | ||
1370 | ; Drop any received data that doesnt fit in the receive window. |
1366 | ; Drop any received data that doesnt fit in the receive window. |
1371 | cmp ecx, [ebx + TCP_SOCKET.RCV_WND] |
1367 | cmp ecx, [ebx + TCP_SOCKET.RCV_WND] |
1372 | jbe .dont_trim |
1368 | jbe .dont_trim |
1373 | 1369 | ||
1374 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax |
1370 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: received data does not fit in window, trimming %u bytes\n", eax |
1375 | mov ecx, [ebx + TCP_SOCKET.RCV_WND] |
1371 | mov ecx, [ebx + TCP_SOCKET.RCV_WND] |
1376 | and [edx + TCP_header.Flags], not (TH_FIN) |
1372 | and [edx + TCP_header.Flags], not (TH_FIN) |
1377 | ;;; TODO: update stats |
1373 | ;;; TODO: update stats |
1378 | 1374 | ||
1379 | .dont_trim: |
1375 | .dont_trim: |
1380 | 1376 | ||
1381 | mov eax, [edx + TCP_header.SequenceNumber] |
1377 | mov eax, [edx + TCP_header.SequenceNumber] |
1382 | mov [ebx + TCP_SOCKET.RCV_UP], eax |
1378 | mov [ebx + TCP_SOCKET.RCV_UP], eax |
1383 | dec eax |
1379 | dec eax |
1384 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
1380 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
1385 | 1381 | ||
1386 | ;------- |
1382 | ;------- |
1387 | ; step 6 |
1383 | ; step 6 |
1388 | 1384 | ||
1389 | .ack_processed: |
1385 | .ack_processed: |
1390 | 1386 | ||
1391 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n" |
1387 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK processed\n" |
1392 | 1388 | ||
1393 | ;---------------------------------------------- |
1389 | ;---------------------------------------------- |
1394 | ; check if we need to update window information |
1390 | ; check if we need to update window information |
1395 | 1391 | ||
1396 | test [edx + TCP_header.Flags], TH_ACK |
1392 | test [edx + TCP_header.Flags], TH_ACK |
1397 | jz .no_window_update |
1393 | jz .no_window_update |
1398 | 1394 | ||
1399 | mov eax, [ebx + TCP_SOCKET.SND_WL1] |
1395 | mov eax, [ebx + TCP_SOCKET.SND_WL1] |
1400 | cmp eax, [edx + TCP_header.SequenceNumber] |
1396 | cmp eax, [edx + TCP_header.SequenceNumber] |
1401 | jb .update_window |
1397 | jb .update_window |
1402 | ja @f |
1398 | ja @f |
1403 | 1399 | ||
1404 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1400 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
1405 | cmp eax, [edx + TCP_header.AckNumber] |
1401 | cmp eax, [edx + TCP_header.AckNumber] |
1406 | jb .update_window |
1402 | jb .update_window |
1407 | ja .no_window_update |
1403 | ja .no_window_update |
1408 | @@: |
1404 | @@: |
1409 | 1405 | ||
1410 | mov eax, dword [edx + TCP_header.Window] |
1406 | mov eax, dword [edx + TCP_header.Window] |
1411 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1407 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
1412 | jbe .no_window_update |
1408 | jbe .no_window_update |
1413 | 1409 | ||
1414 | .update_window: |
1410 | .update_window: |
1415 | 1411 | ||
1416 | ;;; TODO: update stats (Keep track of pure window updates) |
1412 | ;;; TODO: update stats (Keep track of pure window updates) |
1417 | 1413 | ||
1418 | mov eax, dword [edx + TCP_header.Window] |
1414 | mov eax, dword [edx + TCP_header.Window] |
1419 | cmp eax, [ebx + TCP_SOCKET.max_sndwnd] |
1415 | cmp eax, [ebx + TCP_SOCKET.max_sndwnd] |
1420 | jbe @f |
1416 | jbe @f |
1421 | mov [ebx + TCP_SOCKET.max_sndwnd], eax |
1417 | mov [ebx + TCP_SOCKET.max_sndwnd], eax |
1422 | @@: |
1418 | @@: |
1423 | mov [ebx + TCP_SOCKET.SND_WND], eax |
1419 | mov [ebx + TCP_SOCKET.SND_WND], eax |
1424 | 1420 | ||
1425 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax |
1421 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Updating window to %u\n", eax |
1426 | 1422 | ||
1427 | push [edx + TCP_header.SequenceNumber] |
1423 | push [edx + TCP_header.SequenceNumber] |
1428 | pop [ebx + TCP_SOCKET.SND_WL1] |
1424 | pop [ebx + TCP_SOCKET.SND_WL1] |
1429 | 1425 | ||
1430 | push [edx + TCP_header.AckNumber] |
1426 | push [edx + TCP_header.AckNumber] |
1431 | pop [ebx + TCP_SOCKET.SND_WL2] |
1427 | pop [ebx + TCP_SOCKET.SND_WL2] |
1432 | 1428 | ||
1433 | or [temp_bits], TCP_BIT_NEEDOUTPUT |
1429 | or [temp_bits], TCP_BIT_NEEDOUTPUT |
1434 | 1430 | ||
1435 | .no_window_update: |
1431 | .no_window_update: |
1436 | 1432 | ||
1437 | ;----------------- |
1433 | ;----------------- |
1438 | ; process URG flag |
1434 | ; process URG flag |
1439 | 1435 | ||
1440 | test [edx + TCP_header.Flags], TH_URG |
1436 | test [edx + TCP_header.Flags], TH_URG |
1441 | jz .not_urgent |
1437 | jz .not_urgent |
1442 | 1438 | ||
1443 | cmp [edx + TCP_header.UrgentPointer], 0 |
1439 | cmp [edx + TCP_header.UrgentPointer], 0 |
1444 | jz .not_urgent |
1440 | jz .not_urgent |
1445 | 1441 | ||
1446 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1442 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1447 | je .not_urgent |
1443 | je .not_urgent |
1448 | 1444 | ||
1449 | ; Ignore bogus urgent offsets |
1445 | ; Ignore bogus urgent offsets |
1450 | 1446 | ||
1451 | movzx eax, [edx + TCP_header.UrgentPointer] |
1447 | movzx eax, [edx + TCP_header.UrgentPointer] |
1452 | add eax, [ebx + STREAM_SOCKET.rcv.size] |
1448 | add eax, [ebx + STREAM_SOCKET.rcv.size] |
1453 | cmp eax, SOCKET_MAXDATA |
1449 | cmp eax, SOCKET_MAXDATA |
1454 | jbe .not_urgent |
1450 | jbe .not_urgent |
1455 | 1451 | ||
1456 | mov [edx + TCP_header.UrgentPointer], 0 |
1452 | mov [edx + TCP_header.UrgentPointer], 0 |
1457 | and [edx + TCP_header.Flags], not (TH_URG) |
1453 | and [edx + TCP_header.Flags], not (TH_URG) |
1458 | jmp .do_data |
1454 | jmp .do_data |
1459 | 1455 | ||
1460 | .not_urgent: |
1456 | .not_urgent: |
1461 | 1457 | ||
1462 | ; processing of received urgent pointer |
1458 | ; processing of received urgent pointer |
1463 | 1459 | ||
1464 | ;;; TODO (1051-1093) |
1460 | ;;; TODO (1051-1093) |
1465 | 1461 | ||
1466 | 1462 | ||
1467 | ;--------------------------------------- |
1463 | ;--------------------------------------- |
1468 | ; process the data in the segment (1094) |
1464 | ; process the data in the segment (1094) |
1469 | 1465 | ||
1470 | .do_data: |
1466 | .do_data: |
1471 | 1467 | ||
1472 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1468 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1473 | jae .final_processing |
1469 | jae .final_processing |
1474 | 1470 | ||
1475 | test [edx + TCP_header.Flags], TH_FIN |
1471 | test [edx + TCP_header.Flags], TH_FIN |
1476 | jnz @f |
1472 | jnz @f |
1477 | 1473 | ||
1478 | test ecx, ecx |
1474 | test ecx, ecx |
1479 | jz .final_processing |
1475 | jz .final_processing |
1480 | @@: |
1476 | @@: |
1481 | 1477 | ||
1482 | ; The segment is in order? |
1478 | ; The segment is in order? |
1483 | mov eax, [edx + TCP_header.SequenceNumber] |
1479 | mov eax, [edx + TCP_header.SequenceNumber] |
1484 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
1480 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
1485 | jne .out_of_order |
1481 | jne .out_of_order |
1486 | 1482 | ||
1487 | ; The reassembly queue is empty? |
1483 | ; The reassembly queue is empty? |
1488 | cmp [ebx + TCP_SOCKET.seg_next], 0 |
1484 | cmp [ebx + TCP_SOCKET.seg_next], 0 |
1489 | jne .out_of_order |
1485 | jne .out_of_order |
1490 | 1486 | ||
1491 | ; The connection is established? |
1487 | ; The connection is established? |
1492 | cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
1488 | cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED |
1493 | jne .out_of_order |
1489 | jne .out_of_order |
1494 | 1490 | ||
1495 | ; Ok, lets do this.. Set delayed ACK flag and copy data into socket buffer |
1491 | ; Ok, lets do this.. Set delayed ACK flag and copy data into socket buffer |
1496 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK |
1492 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK |
1497 | 1493 | ||
1498 | pusha |
1494 | pusha |
1499 | mov esi, [dataoffset] |
1495 | mov esi, [dataoffset] |
1500 | add esi, edx |
1496 | add esi, edx |
1501 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1497 | lea eax, [ebx + STREAM_SOCKET.rcv] |
1502 | call SOCKET_ring_write ; Add the data to the socket buffer |
1498 | call SOCKET_ring_write ; Add the data to the socket buffer |
1503 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
1499 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
1504 | popa |
1500 | popa |
1505 | 1501 | ||
1506 | ; Wake up the sleeping process |
1502 | ; Wake up the sleeping process |
1507 | mov eax, ebx |
1503 | mov eax, ebx |
1508 | call SOCKET_notify |
1504 | call SOCKET_notify |
1509 | 1505 | ||
1510 | jmp .data_done |
1506 | jmp .data_done |
1511 | 1507 | ||
1512 | .out_of_order: |
1508 | .out_of_order: |
1513 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \ |
1509 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP data is out of order!\nSequencenumber is %u, we expected %u.\n", \ |
1514 | [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT] |
1510 | [edx + TCP_header.SequenceNumber], [ebx + TCP_SOCKET.RCV_NXT] |
1515 | 1511 | ||
1516 | ; Uh-oh, some data is out of order, lets call TCP reassemble for help |
1512 | ; Uh-oh, some data is out of order, lets call TCP reassemble for help |
1517 | 1513 | ||
1518 | call TCP_reassemble |
1514 | call TCP_reassemble |
1519 | 1515 | ||
1520 | ; Generate ACK immediately, to let the other end know that a segment was received out of order, |
1516 | ; Generate ACK immediately, to let the other end know that a segment was received out of order, |
1521 | ; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm. |
1517 | ; and to tell it what sequence number is expected. This aids the fast-retransmit algorithm. |
1522 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1518 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1523 | .data_done: |
1519 | .data_done: |
1524 | 1520 | ||
1525 | ;--------------- |
1521 | ;--------------- |
1526 | ; FIN processing |
1522 | ; FIN processing |
1527 | 1523 | ||
1528 | test [edx + TCP_header.Flags], TH_FIN |
1524 | test [edx + TCP_header.Flags], TH_FIN |
1529 | jz .final_processing |
1525 | jz .final_processing |
1530 | 1526 | ||
1531 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n" |
1527 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Processing FIN\n" |
1532 | 1528 | ||
1533 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1529 | cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1534 | jae .not_first_fin |
1530 | jae .not_first_fin |
1535 | 1531 | ||
1536 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n" |
1532 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: First FIN for this connection\n" |
1537 | 1533 | ||
1538 | mov eax, ebx |
1534 | mov eax, ebx |
1539 | call SOCKET_cant_recv_more |
1535 | call SOCKET_cant_recv_more |
1540 | 1536 | ||
1541 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1537 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
1542 | inc [ebx + TCP_SOCKET.RCV_NXT] |
1538 | inc [ebx + TCP_SOCKET.RCV_NXT] |
1543 | 1539 | ||
1544 | .not_first_fin: |
1540 | .not_first_fin: |
1545 | mov eax, [ebx + TCP_SOCKET.t_state] |
1541 | mov eax, [ebx + TCP_SOCKET.t_state] |
1546 | shl eax, 2 |
1542 | shl eax, 2 |
1547 | jmp dword [eax + .FIN_sw_list] |
1543 | jmp dword [eax + .FIN_sw_list] |
1548 | 1544 | ||
1549 | .FIN_sw_list: |
1545 | .FIN_sw_list: |
1550 | dd .final_processing ; TCPS_CLOSED |
1546 | dd .final_processing ; TCPS_CLOSED |
1551 | dd .final_processing ; TCPS_LISTEN |
1547 | dd .final_processing ; TCPS_LISTEN |
1552 | dd .final_processing ; TCPS_SYN_SENT |
1548 | dd .final_processing ; TCPS_SYN_SENT |
1553 | dd .fin_syn_est ; TCPS_SYN_RECEIVED |
1549 | dd .fin_syn_est ; TCPS_SYN_RECEIVED |
1554 | dd .fin_syn_est ; TCPS_ESTABLISHED |
1550 | dd .fin_syn_est ; TCPS_ESTABLISHED |
1555 | dd .final_processing ; TCPS_CLOSE_WAIT |
1551 | dd .final_processing ; TCPS_CLOSE_WAIT |
1556 | dd .fin_wait1 ; TCPS_FIN_WAIT_1 |
1552 | dd .fin_wait1 ; TCPS_FIN_WAIT_1 |
1557 | dd .final_processing ; TCPS_CLOSING |
1553 | dd .final_processing ; TCPS_CLOSING |
1558 | dd .final_processing ; TCPS_LAST_ACK |
1554 | dd .final_processing ; TCPS_LAST_ACK |
1559 | dd .fin_wait2 ; TCPS_FIN_WAIT_2 |
1555 | dd .fin_wait2 ; TCPS_FIN_WAIT_2 |
1560 | dd .fin_timed ; TCPS_TIMED_WAIT |
1556 | dd .fin_timed ; TCPS_TIMED_WAIT |
1561 | 1557 | ||
1562 | .fin_syn_est: |
1558 | .fin_syn_est: |
1563 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT |
1559 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT |
1564 | jmp .final_processing |
1560 | jmp .final_processing |
1565 | 1561 | ||
1566 | .fin_wait1: |
1562 | .fin_wait1: |
1567 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING |
1563 | mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING |
1568 | jmp .final_processing |
1564 | jmp .final_processing |
1569 | 1565 | ||
1570 | .fin_wait2: |
1566 | .fin_wait2: |
1571 | mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1567 | mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT |
1572 | mov eax, ebx |
1568 | mov eax, ebx |
1573 | call TCP_cancel_timers |
1569 | call TCP_cancel_timers |
1574 | call SOCKET_is_disconnected |
1570 | call SOCKET_is_disconnected |
1575 | 1571 | ||
1576 | .fin_timed: |
1572 | .fin_timed: |
1577 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1573 | mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL |
1578 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1574 | or [ebx + TCP_SOCKET.timer_flags], timer_flag_wait |
1579 | 1575 | ||
1580 | ;----------------- |
1576 | ;----------------- |
1581 | ; Final processing |
1577 | ; Final processing |
1582 | 1578 | ||
1583 | .final_processing: |
1579 | .final_processing: |
1584 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n" |
1580 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Final processing\n" |
1585 | 1581 | ||
1586 | push ebx |
1582 | push ebx |
1587 | lea ecx, [ebx + SOCKET.mutex] |
1583 | lea ecx, [ebx + SOCKET.mutex] |
1588 | call mutex_unlock |
1584 | call mutex_unlock |
1589 | pop eax |
1585 | pop eax |
1590 | 1586 | ||
1591 | test [temp_bits], TCP_BIT_NEEDOUTPUT |
1587 | test [temp_bits], TCP_BIT_NEEDOUTPUT |
1592 | jnz .need_output |
1588 | jnz .need_output |
1593 | 1589 | ||
1594 | test [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
1590 | test [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
1595 | jz .dumpit |
1591 | jz .dumpit |
1596 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n" |
1592 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: ACK now!\n" |
1597 | 1593 | ||
1598 | .need_output: |
1594 | .need_output: |
1599 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n" |
1595 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: need output\n" |
1600 | call TCP_output |
1596 | call TCP_output |
1601 | 1597 | ||
1602 | .dumpit: |
1598 | .dumpit: |
1603 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n" |
1599 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: dumping\n" |
1604 | 1600 | ||
1605 | call NET_packet_free |
1601 | call NET_packet_free |
1606 | jmp .loop |
1602 | jmp .loop |
1607 | 1603 | ||
1608 | 1604 | ||
1609 | ;----------------- |
1605 | ;----------------- |
1610 | ; Drop the segment |
1606 | ; Drop the segment |
1611 | 1607 | ||
1612 | 1608 | ||
1613 | .drop_after_ack: |
1609 | .drop_after_ack: |
1614 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n" |
1610 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop after ACK\n" |
1615 | 1611 | ||
1616 | push edx ebx |
1612 | push edx ebx |
1617 | lea ecx, [ebx + SOCKET.mutex] |
1613 | lea ecx, [ebx + SOCKET.mutex] |
1618 | call mutex_unlock |
1614 | call mutex_unlock |
1619 | pop eax edx |
1615 | pop eax edx |
1620 | 1616 | ||
1621 | test [edx + TCP_header.Flags], TH_RST |
1617 | test [edx + TCP_header.Flags], TH_RST |
1622 | jnz .dumpit |
1618 | jnz .dumpit |
1623 | 1619 | ||
1624 | or [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
1620 | or [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
1625 | jmp .need_output |
1621 | jmp .need_output |
1626 | 1622 | ||
1627 | .drop_with_reset: |
1623 | .drop_with_reset: |
1628 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n" |
1624 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop with reset\n" |
1629 | 1625 | ||
1630 | push ebx edx |
1626 | push ebx edx |
1631 | lea ecx, [ebx + SOCKET.mutex] |
1627 | lea ecx, [ebx + SOCKET.mutex] |
1632 | call mutex_unlock |
1628 | call mutex_unlock |
1633 | pop edx ebx |
1629 | pop edx ebx |
1634 | 1630 | ||
1635 | test [edx + TCP_header.Flags], TH_RST |
1631 | test [edx + TCP_header.Flags], TH_RST |
1636 | jnz .dumpit |
1632 | jnz .dumpit |
1637 | 1633 | ||
1638 | ;;; if its a multicast/broadcast, also drop |
1634 | ;;; if its a multicast/broadcast, also drop |
1639 | 1635 | ||
1640 | test [edx + TCP_header.Flags], TH_ACK |
1636 | test [edx + TCP_header.Flags], TH_ACK |
1641 | jnz .respond_ack |
1637 | jnz .respond_ack |
1642 | 1638 | ||
1643 | test [edx + TCP_header.Flags], TH_SYN |
1639 | test [edx + TCP_header.Flags], TH_SYN |
1644 | jnz .respond_syn |
1640 | jnz .respond_syn |
1645 | jmp .dumpit |
1641 | jmp .dumpit |
1646 | 1642 | ||
1647 | ;--------- |
1643 | ;--------- |
1648 | ; Respond |
1644 | ; Respond |
1649 | 1645 | ||
1650 | .respond_ack: |
1646 | .respond_ack: |
1651 | push ebx |
1647 | push ebx |
1652 | mov cl, TH_RST |
1648 | mov cl, TH_RST |
1653 | call TCP_respond |
1649 | call TCP_respond |
1654 | pop ebx |
1650 | pop ebx |
1655 | jmp .destroy_new_socket |
1651 | jmp .destroy_new_socket |
1656 | 1652 | ||
1657 | .respond_syn: |
1653 | .respond_syn: |
1658 | push ebx |
1654 | push ebx |
1659 | mov cl, TH_RST + TH_ACK |
1655 | mov cl, TH_RST + TH_ACK |
1660 | call TCP_respond |
1656 | call TCP_respond |
1661 | pop ebx |
1657 | pop ebx |
1662 | jmp .destroy_new_socket |
1658 | jmp .destroy_new_socket |
1663 | 1659 | ||
1664 | .no_socket: |
1660 | .no_socket: |
1665 | 1661 | ||
1666 | pusha |
1662 | pusha |
1667 | mov ecx, socket_mutex |
1663 | mov ecx, socket_mutex |
1668 | call mutex_unlock |
1664 | call mutex_unlock |
1669 | popa |
1665 | popa |
1670 | 1666 | ||
1671 | .respond_seg_reset: |
1667 | .respond_seg_reset: |
1672 | test [edx + TCP_header.Flags], TH_RST |
1668 | test [edx + TCP_header.Flags], TH_RST |
1673 | jnz .drop_no_socket |
1669 | jnz .drop_no_socket |
1674 | 1670 | ||
1675 | ;;; TODO: if its a multicast/broadcast, also drop |
1671 | ;;; TODO: if its a multicast/broadcast, also drop |
1676 | 1672 | ||
1677 | test [edx + TCP_header.Flags], TH_ACK |
1673 | test [edx + TCP_header.Flags], TH_ACK |
1678 | jnz .respond_seg_ack |
1674 | jnz .respond_seg_ack |
1679 | 1675 | ||
1680 | test [edx + TCP_header.Flags], TH_SYN |
1676 | test [edx + TCP_header.Flags], TH_SYN |
1681 | jnz .respond_seg_syn |
1677 | jnz .respond_seg_syn |
1682 | 1678 | ||
1683 | jmp .drop_no_socket |
1679 | jmp .drop_no_socket |
1684 | 1680 | ||
1685 | .respond_seg_ack: |
1681 | .respond_seg_ack: |
1686 | mov cl, TH_RST |
1682 | mov cl, TH_RST |
1687 | call TCP_respond_segment |
1683 | call TCP_respond_segment |
1688 | jmp .drop_no_socket |
1684 | jmp .drop_no_socket |
1689 | 1685 | ||
1690 | .respond_seg_syn: |
1686 | .respond_seg_syn: |
1691 | mov cl, TH_RST + TH_ACK |
1687 | mov cl, TH_RST + TH_ACK |
1692 | call TCP_respond_segment |
1688 | call TCP_respond_segment |
1693 | jmp .drop_no_socket |
1689 | jmp .drop_no_socket |
1694 | 1690 | ||
1695 | ;----- |
1691 | ;----- |
1696 | ; Drop |
1692 | ; Drop |
1697 | 1693 | ||
1698 | .drop: |
1694 | .drop: |
1699 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n" |
1695 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Dropping segment\n" |
1700 | 1696 | ||
1701 | pusha |
1697 | pusha |
1702 | lea ecx, [ebx + SOCKET.mutex] |
1698 | lea ecx, [ebx + SOCKET.mutex] |
1703 | call mutex_unlock |
1699 | call mutex_unlock |
1704 | popa |
1700 | popa |
1705 | 1701 | ||
1706 | .destroy_new_socket: |
1702 | .destroy_new_socket: |
1707 | test [temp_bits], TCP_BIT_DROPSOCKET |
1703 | test [temp_bits], TCP_BIT_DROPSOCKET |
1708 | jz .drop_no_socket |
1704 | jz .drop_no_socket |
1709 | 1705 | ||
1710 | mov eax, ebx |
1706 | mov eax, ebx |
1711 | call SOCKET_free |
1707 | call SOCKET_free |
1712 | 1708 | ||
1713 | .drop_no_socket: |
1709 | .drop_no_socket: |
1714 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n" |
1710 | DEBUGF DEBUG_NETWORK_VERBOSE, "TCP_input: Drop (no socket)\n" |
1715 | 1711 | ||
1716 | call NET_packet_free |
1712 | call NET_packet_free |
1717 | jmp .loop |
1713 | jmp .loop |
1718 | 1714 | ||
1719 | endp |
1715 | endp |
1720 | >< |
1716 | >< |
1721 | ><< |
1717 | ><< |
1722 | ><<< |
1718 | ><<< |
1723 | > |
1719 | > |