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