Rev 1719 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1719 | Rev 1733 | ||
---|---|---|---|
Line 14... | Line 14... | ||
14 | ;; GNU GENERAL PUBLIC LICENSE ;; |
14 | ;; GNU GENERAL PUBLIC LICENSE ;; |
15 | ;; Version 2, June 1991 ;; |
15 | ;; Version 2, June 1991 ;; |
16 | ;; ;; |
16 | ;; ;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
17 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
Line 18... | Line 18... | ||
18 | 18 | ||
Line 19... | Line 19... | ||
19 | $Revision: 1719 $ |
19 | $Revision: 1733 $ |
20 | 20 | ||
21 | ; Socket states |
21 | ; Socket states |
22 | TCB_CLOSED equ 0 |
22 | TCB_CLOSED equ 0 |
Line 118... | Line 118... | ||
118 | mov [TCP_sequence_num], eax |
118 | mov [TCP_sequence_num], eax |
Line 119... | Line 119... | ||
119 | 119 | ||
Line 120... | Line -... | ||
120 | } |
- | |
121 | - | ||
122 | - | ||
123 | ;---------------------- |
- | |
124 | ; |
- | |
125 | ; |
- | |
126 | ;---------------------- |
- | |
127 | macro TCP_timer_160ms { |
- | |
128 | - | ||
129 | local .loop |
- | |
130 | local .exit |
- | |
131 | - | ||
132 | mov eax, net_sockets |
- | |
133 | .loop: |
- | |
134 | mov eax, [eax + SOCKET.NextPtr] |
- | |
135 | or eax, eax |
- | |
136 | jz .exit |
- | |
137 | - | ||
138 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP ;;; We should also check if family is AF_INET |
- | |
139 | jne .loop |
- | |
140 | - | ||
141 | dec [eax + TCP_SOCKET.timer_ack] |
- | |
142 | jnz .loop |
- | |
143 | - | ||
144 | DEBUGF 1,"TCP ack for socket %x expired, time to piggyback!\n", eax |
- | |
145 | - | ||
146 | push eax |
- | |
147 | call TCP_respond_socket |
- | |
148 | pop eax |
- | |
149 | - | ||
150 | jmp .loop |
- | |
151 | - | ||
152 | .exit: |
- | |
153 | - | ||
154 | } |
- | |
155 | - | ||
156 | - | ||
157 | ;----------------------------------------------------------------- |
- | |
158 | ; |
- | |
159 | ; |
- | |
160 | ;----------------------------------------------------------------- |
- | |
161 | macro TCP_timer_640ms { |
- | |
162 | - | ||
163 | local .loop |
- | |
164 | local .exit |
- | |
165 | - | ||
166 | ; Update TCP sequence number |
- | |
167 | - | ||
168 | add [TCP_sequence_num], 64000 |
- | |
169 | - | ||
170 | ; scan through all the active TCP sockets, decrementing ALL timers |
- | |
171 | ; timers do not have the chance to wrap because of the keepalive timer will kill the socket when it expires |
- | |
172 | - | ||
173 | mov eax, net_sockets |
- | |
174 | .loop: |
- | |
175 | mov eax, [eax + SOCKET.NextPtr] |
- | |
176 | .check_only: |
- | |
177 | or eax, eax |
- | |
178 | jz .exit |
- | |
179 | - | ||
180 | cmp [eax + SOCKET.Protocol], IP_PROTO_TCP ;;; We should also check if family is AF_INET |
- | |
181 | jne .loop |
- | |
182 | - | ||
183 | inc [eax + TCP_SOCKET.t_idle] |
- | |
184 | dec [eax + TCP_SOCKET.timer_retransmission] |
- | |
185 | jnz .check_more2 |
- | |
186 | - | ||
187 | DEBUGF 1,"socket %x: Retransmission timer expired\n", eax |
- | |
188 | - | ||
189 | push eax |
- | |
190 | call TCP_output |
- | |
191 | pop eax |
- | |
192 | - | ||
193 | .check_more2: |
- | |
194 | dec [eax + TCP_SOCKET.timer_keepalive] |
- | |
195 | jnz .check_more3 |
- | |
196 | - | ||
197 | DEBUGF 1,"socket %x: Keepalive expired\n", eax |
- | |
198 | - | ||
199 | ;;; TODO: check socket state and handle accordingly |
- | |
200 | - | ||
201 | .check_more3: |
- | |
202 | dec [eax + TCP_SOCKET.timer_timed_wait] |
- | |
203 | jnz .check_more5 |
- | |
204 | - | ||
205 | DEBUGF 1,"socket %x: 2MSL timer expired\n", eax |
- | |
206 | - | ||
207 | .check_more5: |
- | |
208 | dec [eax + TCP_SOCKET.timer_persist] |
- | |
209 | jnz .loop |
- | |
210 | - | ||
211 | DEBUGF 1,"socket %x: persist timer expired\n", eax |
- | |
212 | - | ||
213 | jmp .loop |
- | |
214 | .exit: |
- | |
215 | } |
- | |
216 | - | ||
217 | - | ||
218 | - | ||
219 | - | ||
220 | macro TCP_checksum IP1, IP2 { |
- | |
221 | - | ||
222 | ;------------- |
- | |
223 | ; Pseudoheader |
- | |
224 | - | ||
225 | ; protocol type |
- | |
226 | mov edx, IP_PROTO_TCP |
- | |
227 | - | ||
228 | ; source address |
- | |
229 | add dl, byte [IP1+1] |
- | |
230 | adc dh, byte [IP1+0] |
- | |
231 | adc dl, byte [IP1+3] |
- | |
232 | adc dh, byte [IP1+2] |
- | |
233 | - | ||
234 | ; destination address |
- | |
235 | adc dl, byte [IP2+1] |
- | |
236 | adc dh, byte [IP2+0] |
- | |
237 | adc dl, byte [IP2+3] |
- | |
238 | adc dh, byte [IP2+2] |
- | |
239 | - | ||
240 | ; size |
- | |
241 | adc dl, cl |
- | |
242 | adc dh, ch |
- | |
243 | - | ||
244 | ;--------------------- |
- | |
245 | ; Real header and data |
- | |
246 | - | ||
247 | push esi |
- | |
248 | call checksum_1 |
- | |
249 | call checksum_2 |
- | |
250 | pop esi |
- | |
251 | - | ||
252 | } ; returns in dx only |
- | |
253 | - | ||
254 | - | ||
255 | macro TCP_sendseqinit ptr { |
- | |
256 | - | ||
257 | push edi ;;;; i dont like this static use of edi |
- | |
258 | mov edi, [ptr + TCP_SOCKET.ISS] |
- | |
259 | mov [ptr + TCP_SOCKET.SND_UP], edi |
- | |
260 | mov [ptr + TCP_SOCKET.SND_MAX], edi |
- | |
261 | mov [ptr + TCP_SOCKET.SND_NXT], edi |
- | |
262 | mov [ptr + TCP_SOCKET.SND_UNA], edi |
- | |
263 | pop edi |
- | |
264 | - | ||
265 | } |
- | |
266 | - | ||
267 | macro TCP_rcvseqinit ptr { |
- | |
268 | - | ||
269 | push edi |
- | |
270 | mov edi, [ptr + TCP_SOCKET.IRS] |
- | |
271 | inc edi |
- | |
272 | mov [ptr + TCP_SOCKET.RCV_NXT], edi |
- | |
273 | mov [ptr + TCP_SOCKET.RCV_ADV], edi |
- | |
274 | pop edi |
- | |
275 | - | ||
276 | } |
- | |
277 | - | ||
278 | - | ||
279 | - | ||
280 | ;----------------------------------------------------------------- |
- | |
281 | ; |
- | |
282 | ; TCP_input: |
- | |
283 | ; |
- | |
284 | ; IN: [esp] = ptr to buffer |
- | |
285 | ; [esp+4] = buffer size |
- | |
286 | ; ebx = ptr to device struct |
- | |
287 | ; ecx = segment size |
- | |
288 | ; edx = ptr to TCP segment |
- | |
289 | ; |
- | |
290 | ; esi = ipv4 source address |
- | |
291 | ; edi = ipv4 dest address |
- | |
292 | ; |
- | |
293 | ; OUT: / |
- | |
294 | ; |
- | |
295 | ;----------------------------------------------------------------- |
- | |
296 | align 4 |
- | |
297 | TCP_input: |
- | |
298 | - | ||
299 | DEBUGF 1,"TCP_input size=%u\n", ecx |
- | |
300 | ; Offset must be greater than or equal to the size of the standard TCP header (20) and less than or equal to the TCP length. |
- | |
301 | - | ||
302 | movzx eax, [edx + TCP_segment.DataOffset] |
- | |
303 | and eax, 0xf0 |
- | |
304 | shr al, 2 |
- | |
305 | - | ||
306 | DEBUGF 1,"headersize=%u\n", eax |
- | |
307 | - | ||
308 | cmp eax, 20 |
- | |
309 | jl .drop |
- | |
310 | - | ||
311 | ;------------------------------- |
- | |
312 | ; Now, re-calculate the checksum |
- | |
313 | - | ||
314 | push eax ecx edx |
- | |
315 | pushw [edx + TCP_segment.Checksum] |
- | |
316 | mov [edx + TCP_segment.Checksum], 0 |
- | |
317 | push esi edi |
- | |
318 | mov esi, edx |
- | |
319 | TCP_checksum (esp), (esp+4) |
- | |
320 | pop esi edi ; yes, swap them (we dont need dest addr) |
- | |
321 | pop cx ; previous checksum |
- | |
322 | cmp cx, dx |
- | |
323 | pop edx ecx esi |
- | |
324 | jnz .drop |
- | |
325 | - | ||
326 | DEBUGF 1,"Checksum is correct\n" |
- | |
327 | - | ||
328 | sub ecx, esi ; update packet size |
- | |
329 | jl .drop |
- | |
330 | DEBUGF 1,"we got %u bytes of data\n", ecx |
- | |
331 | - | ||
332 | ;----------------------------------------------------------------------------------------- |
- | |
333 | ; Check if this packet has a timestamp option (We do it here so we can process it quickly) |
- | |
334 | - | ||
335 | cmp esi, 20 + 12 ; Timestamp option is 12 bytes |
- | |
336 | jl .no_timestamp |
- | |
337 | je .is_ok |
- | |
338 | - | ||
339 | cmp byte [edx + TCP_segment.Data + 12], TCP_OPT_EOL ; end of option list |
- | |
340 | jne .no_timestamp |
- | |
341 | - | ||
342 | .is_ok: |
- | |
343 | test [edx + TCP_segment.Flags], TH_SYN ; SYN flag must not be set |
- | |
344 | jnz .no_timestamp |
- | |
345 | - | ||
346 | cmp dword [edx + TCP_segment.Data], 0x0101080a ; Timestamp header |
- | |
347 | jne .no_timestamp |
- | |
348 | - | ||
349 | DEBUGF 1,"timestamp ok\n" |
- | |
350 | - | ||
351 | ; TODO: Parse the option |
- | |
352 | ; TODO: Set a Bit in the TCP to tell all options are parsed |
- | |
353 | - | ||
354 | .no_timestamp: |
- | |
355 | - | ||
356 | ;------------------------------------------- |
- | |
357 | ; Convert Big-endian values to little endian |
- | |
358 | - | ||
359 | ntohd [edx + TCP_segment.SequenceNumber] |
- | |
360 | ntohd [edx + TCP_segment.AckNumber] |
- | |
361 | - | ||
362 | ntohw [edx + TCP_segment.Window] |
- | |
363 | ntohw [edx + TCP_segment.UrgentPointer] |
- | |
364 | ntohw [edx + TCP_segment.SourcePort] |
- | |
365 | ntohw [edx + TCP_segment.DestinationPort] |
- | |
366 | - | ||
367 | ;------------------------------------------------------------ |
- | |
368 | ; Next thing to do is find the TCB (thus, the socket pointer) |
- | |
369 | - | ||
370 | ; IP Packet TCP Destination Port = local Port |
- | |
371 | ; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0) |
- | |
372 | ; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) |
- | |
373 | - | ||
374 | mov ebx, net_sockets |
- | |
375 | - | ||
376 | .socket_loop: |
- | |
377 | mov ebx, [ebx + SOCKET.NextPtr] |
- | |
378 | or ebx, ebx |
- | |
379 | jz .drop_with_reset |
- | |
380 | - | ||
381 | cmp [ebx + SOCKET.Domain], AF_INET4 |
- | |
382 | jne .socket_loop |
- | |
383 | - | ||
384 | cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP |
- | |
385 | jne .socket_loop |
- | |
386 | - | ||
387 | mov ax, [edx + TCP_segment.DestinationPort] |
- | |
388 | cmp [ebx + TCP_SOCKET.LocalPort], ax |
- | |
389 | jne .socket_loop |
- | |
390 | - | ||
391 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
- | |
392 | cmp eax, edi ; edi is source ip from packet |
- | |
393 | je @f |
- | |
394 | test eax, eax |
- | |
395 | jnz .socket_loop |
- | |
396 | @@: |
- | |
397 | - | ||
398 | mov ax, [ebx + TCP_SOCKET.RemotePort] |
- | |
399 | cmp [edx + TCP_segment.SourcePort] , ax |
- | |
400 | je .found_socket |
- | |
401 | test ax, ax |
- | |
402 | jnz .socket_loop |
- | |
403 | .found_socket: |
- | |
404 | DEBUGF 1,"Socket ptr: %x\n", ebx |
- | |
405 | - | ||
406 | ; ebx now contains the pointer to the socket |
- | |
407 | - | ||
408 | ;---------------------------- |
- | |
409 | ; Check if socket isnt closed |
- | |
410 | - | ||
411 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSED |
- | |
412 | je .drop |
- | |
413 | - | ||
414 | ;---------------- |
- | |
415 | ; Lock the socket |
- | |
416 | - | ||
417 | ;; add ebx, SOCKET.lock ; TODO: figure out if we should lock now already |
- | |
418 | ;; call wait_mutex |
- | |
419 | ;; sub ebx, SOCKET.lock |
- | |
420 | - | ||
421 | DEBUGF 1,"Socket locked\n" |
- | |
422 | - | ||
423 | ;--------------------------------------- |
- | |
424 | ; unscale the window into a 32 bit value |
- | |
425 | - | ||
426 | movzx eax, [edx + TCP_segment.Window] |
- | |
427 | push ecx |
- | |
428 | mov cl, [ebx + TCP_SOCKET.SND_SCALE] |
- | |
429 | shl eax, cl |
- | |
430 | mov dword [edx + TCP_segment.Window], eax ; word after window is checksum, we dont need checksum anymore |
- | |
431 | pop ecx |
- | |
432 | - | ||
433 | ;----------------------------------- |
- | |
434 | ; Is this socket a listening socket? |
- | |
435 | - | ||
436 | test [ebx + SOCKET.options], SO_ACCEPTCON |
- | |
437 | jz .no_listening_socket |
- | |
438 | - | ||
439 | call SOCKET_fork |
- | |
440 | jz .drop |
- | |
441 | - | ||
442 | push [edx + TCP_segment.DestinationPort] |
- | |
443 | pop [eax + TCP_SOCKET.LocalPort] |
- | |
444 | - | ||
445 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.DestinationAddress] ;;; FIXME |
- | |
446 | pop [eax + IP_SOCKET.LocalIP] |
- | |
447 | - | ||
448 | push [edx - IPv4_Packet.DataOrOptional + IPv4_Packet.SourceAddress] ;;; FIXME |
- | |
449 | pop [eax + IP_SOCKET.RemoteIP] |
- | |
450 | - | ||
451 | mov [eax + TCP_SOCKET.t_state], TCB_LISTEN |
- | |
452 | - | ||
453 | jmp .not_uni_xfer |
- | |
454 | - | ||
455 | .no_listening_socket: |
- | |
456 | - | ||
457 | ;------------------------------------- |
- | |
458 | ; Reset idle timer and keepalive timer |
- | |
459 | - | ||
460 | mov [ebx + TCP_SOCKET.t_idle], 0 |
- | |
461 | mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval |
- | |
462 | - | ||
463 | ;-------------------- |
- | |
464 | ; Process TCP options |
- | |
465 | - | ||
466 | cmp esi, 20 ; esi is headersize |
- | |
467 | je .no_options |
- | |
468 | - | ||
469 | DEBUGF 1,"Segment has options\n" |
- | |
470 | - | ||
471 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN ; no options when in listen state |
- | |
472 | jz .not_uni_xfer ; also no header prediction |
- | |
473 | - | ||
474 | lea edi, [edx + TCP_segment.Data] |
- | |
475 | lea eax, [edx + esi] |
- | |
476 | - | ||
477 | .opt_loop: |
- | |
478 | cmp edi, eax |
- | |
479 | jge .no_options |
- | |
480 | - | ||
481 | cmp byte [edi], TCP_OPT_EOL ; end of option list? |
- | |
482 | jz .no_options |
- | |
483 | - | ||
484 | cmp byte [edi], TCP_OPT_NOP ; nop ? |
- | |
485 | jz .opt_nop |
- | |
486 | - | ||
487 | cmp byte [edi], TCP_OPT_MAXSEG |
- | |
488 | je .opt_maxseg |
- | |
489 | - | ||
490 | cmp byte [edi], TCP_OPT_WINDOW |
- | |
491 | je .opt_window |
- | |
492 | - | ||
493 | cmp byte [edi], TCP_OPT_TIMESTAMP |
- | |
494 | je .opt_timestamp |
- | |
495 | - | ||
496 | jmp .no_options ; If we reach here, some unknown options were received, skip them all! |
- | |
497 | - | ||
498 | .opt_nop: |
- | |
499 | inc edi |
- | |
500 | jmp .opt_loop |
- | |
501 | - | ||
502 | .opt_maxseg: |
- | |
503 | cmp byte [edi+1], 4 |
- | |
504 | jne .no_options ; error occured, ignore all options! |
- | |
505 | - | ||
506 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
507 | jz @f |
- | |
508 | - | ||
509 | movzx eax, word[edi+2] |
- | |
510 | rol ax, 8 |
- | |
511 | DEBUGF 1,"Maxseg: %u\n", ax |
- | |
512 | - | ||
513 | mov [ebx + TCP_SOCKET.t_maxseg], eax |
- | |
514 | - | ||
515 | @@: |
- | |
516 | add edi, 4 |
- | |
517 | jmp .opt_loop |
- | |
518 | - | ||
519 | - | ||
520 | .opt_window: |
- | |
521 | cmp byte [edi+1], 3 |
- | |
522 | jne .no_options |
- | |
523 | - | ||
524 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
525 | jz @f |
- | |
526 | - | ||
527 | DEBUGF 1,"Got window option\n" |
- | |
528 | - | ||
529 | ;;;;; |
- | |
530 | @@: |
- | |
531 | add edi, 3 |
- | |
532 | jmp .opt_loop |
- | |
533 | - | ||
534 | - | ||
535 | .opt_timestamp: |
- | |
536 | cmp byte [edi+1], 10 |
- | |
537 | jne .no_options |
- | |
538 | - | ||
539 | DEBUGF 1,"Got timestamp option\n" |
- | |
540 | - | ||
541 | ;;;;; |
- | |
542 | - | ||
543 | add edi, 10 |
- | |
544 | jmp .opt_loop |
- | |
545 | - | ||
546 | .no_options: |
- | |
547 | - | ||
548 | ;----------------------------------------------------------------------- |
- | |
549 | ; Time to do some header prediction (Original Principle by Van Jacobson) |
- | |
550 | - | ||
551 | ; There are two common cases for an uni-directional data transfer. |
- | |
552 | ; |
- | |
553 | ; General rule: the packets has no control flags, is in-sequence, |
- | |
554 | ; window width didnt change and we're not retransmitting. |
- | |
555 | ; |
- | |
556 | ; Second rules: |
- | |
557 | ; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer. |
- | |
558 | ; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer |
- | |
559 | ; |
- | |
560 | ; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer. |
- | |
561 | ; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK |
- | |
562 | - | ||
563 | cmp [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
- | |
564 | jnz .not_uni_xfer |
- | |
565 | - | ||
566 | test [edx + TCP_segment.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG |
- | |
567 | jnz .not_uni_xfer |
- | |
568 | - | ||
569 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
570 | jz .not_uni_xfer |
- | |
571 | - | ||
572 | mov eax, [edx + TCP_segment.SequenceNumber] |
- | |
573 | cmp eax, [ebx + TCP_SOCKET.RCV_NXT] |
- | |
574 | jne .not_uni_xfer |
- | |
575 | DEBUGF 1,"TCP_segment.window=%u\n", [edx + TCP_segment.Window]:4 |
- | |
576 | DEBUGF 1,"TCP_SOCKET.SND_WND=%u\n", [ebx + TCP_SOCKET.SND_WND]:4 |
- | |
577 | mov eax, dword [edx + TCP_segment.Window] |
- | |
578 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
- | |
579 | jne .not_uni_xfer |
- | |
580 | - | ||
581 | mov eax, [ebx + TCP_SOCKET.SND_NXT] |
- | |
582 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
- | |
583 | jne .not_uni_xfer |
- | |
584 | - | ||
585 | ;--------------------------------------- |
- | |
586 | ; check if we are sender in the uni-xfer |
- | |
587 | - | ||
588 | ; If the following 4 conditions are all true, this segment is a pure ACK. |
- | |
589 | ; |
- | |
590 | ; - The segment contains no data. |
- | |
591 | test ecx, ecx |
- | |
592 | jnz .not_sender |
- | |
593 | - | ||
594 | ; - The congestion window is greater than or equal to the current send window. |
- | |
595 | ; 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. |
- | |
596 | mov eax, [ebx + TCP_SOCKET.SND_CWND] |
- | |
597 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
- | |
598 | jl .not_uni_xfer |
- | |
599 | - | ||
600 | ; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent. |
- | |
601 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
602 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
- | |
603 | jg .not_uni_xfer |
- | |
604 | - | ||
605 | ; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number. |
- | |
606 | sub eax, [ebx + TCP_SOCKET.SND_UNA] |
- | |
607 | jle .not_uni_xfer |
- | |
608 | - | ||
609 | DEBUGF 1,"Header prediction: we are sender\n" |
- | |
610 | - | ||
611 | ;--------------------------------- |
- | |
612 | ; Packet is a pure ACK, process it |
- | |
613 | - | ||
614 | ; Update RTT estimators |
- | |
615 | - | ||
616 | ; Delete acknowledged bytes from send buffer |
- | |
617 | pusha |
- | |
618 | mov ecx, eax |
- | |
619 | lea eax, [ebx + STREAM_SOCKET.snd] |
- | |
620 | call SOCKET_ring_free |
- | |
621 | popa |
- | |
622 | - | ||
623 | ; update window pointers |
- | |
624 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
625 | dec eax |
- | |
626 | mov [ebx + TCP_SOCKET.SND_WL1], eax |
- | |
627 | - | ||
628 | ; Stop retransmit timer |
- | |
629 | mov [ebx + TCP_SOCKET.timer_ack], 0 |
- | |
630 | - | ||
631 | ; Awaken waiting processes |
- | |
632 | mov eax, ebx |
- | |
633 | call SOCKET_notify_owner |
- | |
634 | - | ||
635 | ;; Generate more output FIXME |
- | |
636 | ;; mov eax, ebx |
- | |
637 | ;; call TCP_output |
- | |
638 | ;; |
- | |
639 | ;; jmp .drop |
- | |
640 | jmp .ack_processed |
- | |
641 | - | ||
642 | ;------------------------------------------------- |
- | |
643 | ; maybe we are the receiver in the uni-xfer then.. |
- | |
644 | - | ||
645 | .not_sender: |
- | |
646 | ; - The amount of data in the segment is greater than 0 (data count is in ecx) |
- | |
647 | - | ||
648 | ; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment. |
- | |
649 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
650 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
- | |
651 | jne .not_uni_xfer |
- | |
652 | - | ||
653 | ; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp). |
- | |
654 | - | ||
655 | ;;;;;;; TODO |
- | |
656 | - | ||
657 | jnz .not_uni_xfer |
- | |
658 | - | ||
659 | ;------------------------------------- |
- | |
660 | ; Complete processing of received data |
- | |
661 | - | ||
662 | DEBUGF 1,"header prediction: we are receiver\nreceiving %u bytes of data\n", ecx |
- | |
663 | - | ||
664 | pusha |
- | |
665 | add esi, edx |
- | |
666 | lea eax, [ebx + STREAM_SOCKET.rcv] |
- | |
667 | call SOCKET_ring_write ; Add the data to the socket buffer |
- | |
668 | - | ||
669 | mov eax, ebx |
- | |
670 | call SOCKET_notify_owner |
- | |
671 | popa |
- | |
672 | - | ||
673 | add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied |
- | |
674 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag |
- | |
675 | - | ||
676 | jmp .drop |
- | |
677 | - | ||
678 | ;---------------------------------------------------- |
- | |
679 | ; Header prediction failed, doing it the slow way.. ;;;;; current implementation of header prediction destroys some regs (ecx) !! |
- | |
680 | - | ||
681 | .not_uni_xfer: |
- | |
682 | - | ||
683 | DEBUGF 1,"Header prediction failed\n" ; time to do it the "slow" way :) |
- | |
684 | - | ||
685 | ;------------------------------ |
- | |
686 | ; Calculate receive window size |
- | |
687 | - | ||
688 | ;;;; |
- | |
689 | - | ||
690 | cmp [ebx + TCP_SOCKET.t_state], TCB_LISTEN |
- | |
691 | je .LISTEN |
- | |
692 | - | ||
693 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_SENT |
- | |
694 | je .SYN_SENT |
- | |
695 | - | ||
696 | ;-------------------------------------------- |
- | |
697 | ; Protection Against Wrapped Sequence Numbers |
- | |
698 | - | ||
699 | ; First, check if timestamp is present |
- | |
700 | - | ||
701 | ;;;; TODO |
- | |
702 | - | ||
703 | ; Then, check if at least some bytes of data are within window |
- | |
704 | - | ||
705 | ;;;; TODO |
- | |
706 | - | ||
707 | jmp .trim_then_step6 |
- | |
708 | - | ||
709 | ;------------- |
- | |
710 | ; Passive Open |
- | |
711 | - | ||
712 | align 4 |
- | |
713 | .LISTEN: |
- | |
714 | - | ||
715 | DEBUGF 1,"TCP state: listen\n" |
- | |
716 | - | ||
717 | test [edx + TCP_segment.Flags], TH_RST ;;; TODO: kill new socket on error |
- | |
718 | jnz .drop |
- | |
719 | - | ||
720 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
721 | jnz .drop_with_reset |
- | |
722 | - | ||
723 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
724 | jz .drop |
- | |
725 | - | ||
726 | - | ||
727 | ; TODO: check if it's a broadcast or multicast, and drop if so |
- | |
728 | - | ||
729 | ;----------------------- |
- | |
730 | ; Fill in some variables |
- | |
731 | - | ||
732 | add [TCP_sequence_num], 64000 |
- | |
733 | - | ||
734 | push [edx + TCP_segment.SourcePort] |
- | |
735 | pop [eax + TCP_SOCKET.RemotePort] |
- | |
736 | - | ||
737 | push [edx + TCP_segment.SequenceNumber] |
- | |
738 | pop [eax + TCP_SOCKET.IRS] |
- | |
739 | - | ||
740 | push [eax + TCP_SOCKET.ISS] |
- | |
741 | pop [eax + TCP_SOCKET.SND_NXT] |
- | |
742 | - | ||
743 | TCP_sendseqinit eax |
- | |
744 | TCP_rcvseqinit eax |
- | |
745 | - | ||
746 | mov [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
- | |
747 | mov [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
748 | mov [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro |
- | |
749 | - | ||
750 | add eax, STREAM_SOCKET.snd |
- | |
751 | call SOCKET_ring_create |
- | |
752 | - | ||
753 | add eax, STREAM_SOCKET.rcv - STREAM_SOCKET.snd |
- | |
754 | call SOCKET_ring_create |
- | |
755 | - | ||
756 | sub eax, STREAM_SOCKET.rcv |
- | |
757 | - | ||
758 | mov [eax + SOCKET.lock], 0 |
- | |
759 | mov ebx, eax ; if there is data, it must arrive in this new socket! |
- | |
760 | jmp .trim_then_step6 |
- | |
761 | - | ||
762 | - | ||
763 | ;------------ |
- | |
764 | ; Active Open |
- | |
765 | - | ||
766 | align 4 |
- | |
767 | .SYN_SENT: |
- | |
768 | - | ||
769 | DEBUGF 1,"TCP state: syn_sent\n" |
- | |
770 | - | ||
771 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
772 | jz @f |
- | |
773 | - | ||
774 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
775 | cmp eax, [ebx + TCP_SOCKET.ISS] |
- | |
776 | jle .drop_with_reset |
- | |
777 | cmp eax, [ebx + TCP_SOCKET.SND_MAX] |
- | |
778 | jg .drop_with_reset |
- | |
779 | @@: |
- | |
780 | - | ||
781 | test [edx + TCP_segment.Flags], TH_RST |
- | |
782 | jz @f |
- | |
783 | - | ||
784 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
785 | jz .drop |
- | |
786 | - | ||
787 | mov eax, ebx |
- | |
788 | mov ebx, ECONNREFUSED |
- | |
789 | call TCP_drop |
- | |
790 | - | ||
791 | jmp .drop |
- | |
792 | @@: |
- | |
793 | - | ||
794 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
795 | jz .drop |
- | |
796 | - | ||
797 | ; at this point, segment seems to be valid |
- | |
798 | - | ||
799 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
800 | jz .no_syn_ack |
- | |
801 | - | ||
802 | ; now, process received SYN in response to an active open |
- | |
803 | - | ||
804 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
805 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
- | |
806 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
- | |
807 | jle @f |
- | |
808 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
- | |
809 | @@: |
- | |
810 | - | ||
811 | .no_syn_ack: |
- | |
812 | - | ||
813 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission |
- | |
814 | - | ||
815 | push [edx + TCP_segment.SequenceNumber] |
- | |
816 | pop [ebx + TCP_SOCKET.IRS] |
- | |
817 | - | ||
818 | TCP_rcvseqinit ebx |
- | |
819 | - | ||
820 | mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
821 | - | ||
822 | mov eax, [ebx + TCP_SOCKET.SND_UNA] |
- | |
823 | cmp eax, [ebx + TCP_SOCKET.ISS] |
- | |
824 | jle .simultaneous_open |
- | |
825 | - | ||
826 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
827 | jz .simultaneous_open |
- | |
828 | - | ||
829 | DEBUGF 1,"TCP: active open\n" |
- | |
830 | - | ||
831 | ; TODO: update stats |
- | |
832 | ; TODO: set general socket state to connected |
- | |
833 | - | ||
834 | mov [ebx + TCP_SOCKET.t_state], TCB_ESTABLISHED |
- | |
835 | - | ||
836 | ; TODO: check if we should scale the connection (567-572) |
- | |
837 | ; TODO: update RTT estimators |
- | |
838 | - | ||
839 | jmp .trimthenstep6 |
- | |
840 | - | ||
841 | .simultaneous_open: |
- | |
842 | - | ||
843 | DEBUGF 1,"TCP: simultaneous open\n" |
- | |
844 | ; We have received a syn but no ACK, so we are having a simultaneous open.. |
- | |
845 | mov [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
- | |
846 | - | ||
847 | ;------------------------------------- |
- | |
848 | ; Common processing for receipt of SYN |
- | |
849 | - | ||
850 | .trimthenstep6: |
- | |
851 | - | ||
852 | inc [edx + TCP_segment.SequenceNumber] |
- | |
853 | - | ||
854 | cmp cx, [ebx + TCP_SOCKET.RCV_WND] |
- | |
855 | jle @f |
- | |
856 | - | ||
857 | movzx eax, cx |
- | |
858 | sub ax, [ebx + TCP_SOCKET.RCV_WND] |
- | |
859 | ; TODO: 592 |
- | |
860 | mov cx, [ebx + TCP_SOCKET.RCV_WND] |
- | |
861 | ; TODO... |
- | |
862 | @@: |
- | |
863 | ;;;;; |
- | |
864 | jmp .ack_processed |
- | |
865 | - | ||
866 | - | ||
867 | .trim_then_step6: |
- | |
868 | - | ||
869 | ;---------------------------- |
- | |
870 | ; trim any data not in window |
- | |
871 | - | ||
872 | DEBUGF 1,"Trimming window\n" |
- | |
873 | - | ||
874 | mov eax, [ebx + TCP_SOCKET.RCV_NXT] |
- | |
875 | sub eax, [edx + TCP_segment.SequenceNumber] |
- | |
876 | jz .no_duplicate |
- | |
877 | - | ||
878 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
879 | jz .no_drop |
- | |
880 | - | ||
881 | and [edx + TCP_segment.Flags], not (TH_SYN) |
- | |
882 | inc [edx + TCP_segment.SequenceNumber] |
- | |
883 | - | ||
884 | cmp [edx + TCP_segment.UrgentPointer], 1 |
- | |
885 | jl @f |
- | |
886 | - | ||
887 | dec [edx + TCP_segment.UrgentPointer] |
- | |
888 | - | ||
889 | jmp .no_drop |
- | |
890 | @@: |
- | |
891 | - | ||
892 | and [edx + TCP_segment.Flags], not (TH_URG) |
- | |
893 | dec eax |
- | |
894 | jz .no_duplicate |
- | |
895 | .no_drop: |
- | |
896 | - | ||
897 | DEBUGF 1,"Going to drop %u out of %u bytes\n", eax, ecx |
- | |
898 | - | ||
899 | ; eax holds number of bytes to drop |
- | |
900 | - | ||
901 | ;---------------------------------- |
- | |
902 | ; Check for entire duplicate packet |
- | |
903 | - | ||
904 | cmp eax, ecx |
- | |
905 | jge .duplicate |
- | |
906 | - | ||
907 | ;;; TODO: figure 28.30 |
- | |
908 | - | ||
909 | ;------------------------ |
- | |
910 | ; Check for duplicate FIN |
- | |
911 | - | ||
912 | test [edx + TCP_segment.Flags], TH_FIN |
- | |
913 | jz @f |
- | |
914 | inc ecx |
- | |
915 | cmp eax, ecx |
- | |
916 | dec ecx |
- | |
917 | jne @f |
- | |
918 | - | ||
919 | mov eax, ecx |
- | |
920 | and [edx + TCP_segment.Flags], not TH_FIN |
- | |
921 | or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
922 | jmp .no_duplicate |
- | |
923 | @@: |
- | |
924 | - | ||
925 | ; Handle the case when a bound socket connects to itself |
- | |
926 | ; Allow packets with a SYN and an ACKto continue with the processing |
- | |
927 | - | ||
928 | ;------------------------------------- |
- | |
929 | ; Generate duplicate ACK if nescessary |
- | |
930 | - | ||
931 | ; This code also handles simultaneous half-open or self-connects |
120 | } |
932 | - | ||
933 | test eax, eax |
- | |
934 | jnz .drop_after_ack |
- | |
935 | - | ||
936 | cmp [edx + TCP_segment.Flags], TH_ACK |
- | |
937 | jz .drop_after_ack |
- | |
938 | - | ||
939 | .duplicate: |
- | |
940 | - | ||
941 | DEBUGF 1,"Duplicate received\n" |
- | |
942 | - | ||
943 | ;---------------------------------------- |
- | |
944 | ; Update statistics for duplicate packets |
- | |
945 | - | ||
946 | ;;; TODO |
- | |
947 | - | ||
948 | jmp .drop ;;; DROP the packet ?? |
- | |
949 | - | ||
950 | .no_duplicate: |
- | |
951 | - | ||
952 | ;----------------------------------------------- |
- | |
953 | ; Remove duplicate data and update urgent offset |
- | |
954 | - | ||
955 | add [edx + TCP_segment.SequenceNumber], eax |
- | |
956 | - | ||
957 | ;;; TODO |
- | |
958 | - | ||
959 | sub [edx + TCP_segment.UrgentPointer], ax |
- | |
960 | jg @f |
- | |
961 | - | ||
962 | and [edx + TCP_segment.Flags], not (TH_URG) |
- | |
963 | mov [edx + TCP_segment.UrgentPointer], 0 |
- | |
964 | @@: |
- | |
965 | - | ||
966 | ;-------------------------------------------------- |
- | |
967 | ; Handle data that arrives after process terminates |
- | |
968 | - | ||
969 | cmp [ebx + SOCKET.PID], 0 |
- | |
970 | jg @f |
- | |
971 | - | ||
972 | cmp [ebx + TCP_SOCKET.t_state], TCB_CLOSE_WAIT |
- | |
973 | jle @f |
- | |
974 | - | ||
975 | test ecx, ecx |
- | |
976 | jz @f |
- | |
977 | - | ||
978 | ;;; Close the socket |
- | |
979 | ;;; update stats |
- | |
980 | - | ||
981 | jmp .drop_with_reset |
- | |
982 | @@: |
- | |
983 | - | ||
984 | ;---------------------------------------- |
- | |
985 | ; Remove data beyond right edge of window |
- | |
986 | - | ||
987 | mov eax, [edx + TCP_segment.SequenceNumber] |
- | |
988 | add eax, ecx |
- | |
989 | sub eax, [ebx + TCP_SOCKET.RCV_NXT] |
- | |
990 | sub ax, [ebx + TCP_SOCKET.RCV_WND] |
- | |
991 | - | ||
992 | ; eax now holds the number of bytes to drop |
- | |
993 | - | ||
994 | jle .no_excess_data |
- | |
995 | - | ||
996 | ;;; TODO: update stats |
- | |
997 | - | ||
998 | cmp eax, ecx |
- | |
999 | jl .dont_drop_all |
- | |
1000 | - | ||
1001 | ;;; TODO 700-736 |
- | |
1002 | - | ||
1003 | .dont_drop_all: |
- | |
1004 | - | ||
1005 | .no_excess_data: |
- | |
1006 | - | ||
1007 | ;----------------- |
- | |
1008 | ; Record timestamp |
- | |
1009 | - | ||
1010 | ;;; TODO 737-746 |
- | |
1011 | - | ||
1012 | ;------------------ |
- | |
1013 | ; Process RST flags |
- | |
1014 | - | ||
1015 | test [edx + TCP_segment.Flags], TH_RST |
- | |
1016 | jz .rst_skip |
- | |
1017 | - | ||
1018 | DEBUGF 1,"Got an RST flag" |
- | |
1019 | - | ||
1020 | mov eax, [ebx + TCP_SOCKET.t_state] |
- | |
1021 | shl eax, 2 |
- | |
1022 | jmp dword [eax + .rst_sw_list] |
- | |
1023 | - | ||
1024 | .rst_sw_list: |
- | |
1025 | dd .rst_skip ;TCB_CLOSED |
- | |
1026 | dd .rst_skip ;TCB_LISTEN |
- | |
1027 | dd .rst_skip ;TCB_SYN_SENT |
- | |
1028 | dd .econnrefused ;TCB_SYN_RECEIVED |
- | |
1029 | dd .econnreset ;TCB_ESTABLISHED |
- | |
1030 | dd .econnreset ;TCB_CLOSE_WAIT |
- | |
1031 | dd .econnreset ;TCB_FIN_WAIT_1 |
- | |
1032 | dd .rst_close ;TCB_CLOSING |
- | |
1033 | dd .rst_close ;TCB_LAST_ACK |
- | |
1034 | dd .econnreset ;TCB_FIN_WAIT_2 |
- | |
1035 | dd .rst_close ;TCB_TIMED_WAIT |
- | |
1036 | - | ||
1037 | .econnrefused: |
- | |
1038 | - | ||
1039 | DEBUGF 1,"Connection refused" |
- | |
1040 | - | ||
1041 | ;;; TODO: debug info |
- | |
1042 | - | ||
1043 | jmp .close |
- | |
1044 | - | ||
1045 | .econnreset: |
- | |
1046 | - | ||
1047 | DEBUGF 1,"Connection reset" |
- | |
1048 | - | ||
1049 | ;;; TODO: debug info |
- | |
1050 | .close: |
- | |
1051 | - | ||
1052 | DEBUGF 1,"Closing connection" |
- | |
1053 | - | ||
1054 | ;;; update stats |
- | |
1055 | - | ||
1056 | .rst_close: |
- | |
1057 | - | ||
1058 | DEBUGF 1,"Closing with reset\n" |
- | |
1059 | - | ||
1060 | ;;; Close the socket |
- | |
1061 | jmp .drop |
- | |
1062 | - | ||
1063 | .rst_skip: |
- | |
1064 | - | ||
1065 | ;-------------------------------------- |
- | |
1066 | ; handle SYN-full and ACK-less segments |
- | |
1067 | - | ||
1068 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
1069 | jz @f |
- | |
1070 | - | ||
1071 | mov eax, ebx |
- | |
1072 | mov ebx, ECONNRESET |
- | |
1073 | call TCP_drop |
- | |
1074 | - | ||
1075 | jmp .drop_with_reset |
- | |
1076 | - | ||
1077 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
1078 | jz .drop |
- | |
1079 | @@: |
- | |
1080 | - | ||
1081 | ;--------------- |
- | |
1082 | ; ACK processing |
- | |
1083 | - | ||
1084 | cmp [ebx + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
- | |
1085 | jnz .no_syn_rcv |
- | |
1086 | - | ||
1087 | DEBUGF 1,"TCP state = syn received\n" |
- | |
1088 | - | ||
1089 | ;;;;; 801-815 |
- | |
1090 | - | ||
1091 | .no_syn_rcv: |
- | |
1092 | - | ||
1093 | ; check for duplicate ACK |
- | |
1094 | - | ||
1095 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
1096 | cmp eax, [ebx + TCP_SOCKET.SND_UNA] |
- | |
1097 | jg .not_dup_ack |
- | |
1098 | - | ||
1099 | DEBUGF 1,"Duplicate ACK\n" |
- | |
1100 | - | ||
1101 | test ecx, ecx |
- | |
1102 | jnz .ack_processed |
- | |
1103 | - | ||
1104 | mov eax, dword [edx + TCP_segment.Window] |
- | |
1105 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
- | |
1106 | jne .ack_processed |
- | |
1107 | - | ||
1108 | ; Process the duplicate ACK |
- | |
1109 | - | ||
1110 | ;;;;; 833 - 878 |
- | |
1111 | - | ||
1112 | ;;; call TCP_output |
- | |
1113 | jmp .drop |
- | |
1114 | - | ||
1115 | .not_dup_ack: |
- | |
1116 | - | ||
1117 | DEBUGF 1,"new ACK\n" |
- | |
1118 | - | ||
1119 | - | ||
1120 | ;------------------------------------------------- |
- | |
1121 | ; If the congestion window was inflated to account |
- | |
1122 | ; for the other side's cached packets, retract it |
- | |
1123 | - | ||
1124 | ;;;; 888 - 902 |
- | |
1125 | - | ||
1126 | - | ||
1127 | ;------------------------------------------ |
- | |
1128 | ; RTT measurements and retransmission timer |
- | |
1129 | - | ||
1130 | ;;;;; 903 - 926 |
- | |
1131 | - | ||
1132 | mov [ebx + TCP_SOCKET.timer_retransmission], 0 |
- | |
1133 | - | ||
1134 | mov eax, [ebx + TCP_SOCKET.SND_MAX] |
- | |
1135 | cmp eax, [edx + TCP_segment.AckNumber] |
- | |
1136 | je .all_outstanding |
- | |
1137 | mov [ebx + TCP_SOCKET.timer_retransmission], 120 ;;;; TODO: correct this value (use a macro for it) |
- | |
1138 | .all_outstanding: |
- | |
1139 | - | ||
1140 | ;------------------------------------------- |
- | |
1141 | ; Open congestion window in response to ACKs |
- | |
1142 | - | ||
1143 | ;;;; |
- | |
1144 | - | ||
1145 | - | ||
1146 | ;------------------------------------------ |
- | |
1147 | ; Remove acknowledged data from send buffer |
- | |
1148 | - | ||
1149 | pusha |
- | |
1150 | mov ecx, [edx + TCP_segment.AckNumber] |
- | |
1151 | sub ecx, [ebx + TCP_SOCKET.SND_UNA] ; ecx now holds number of bytes acked |
- | |
1152 | - | ||
1153 | lea eax, [ebx + STREAM_SOCKET.snd] |
- | |
1154 | call SOCKET_ring_free |
- | |
1155 | popa |
- | |
1156 | - | ||
1157 | ;--------------------------------------- |
- | |
1158 | ; Wake up process waiting on send buffer |
- | |
1159 | - | ||
1160 | mov eax, ebx |
- | |
1161 | call SOCKET_notify_owner |
- | |
1162 | - | ||
1163 | ; Update TCB |
- | |
1164 | - | ||
1165 | mov eax, [edx + TCP_segment.AckNumber] |
- | |
1166 | mov [ebx + TCP_SOCKET.SND_UNA], eax |
- | |
1167 | - | ||
1168 | cmp eax, [ebx + TCP_SOCKET.SND_NXT] |
- | |
1169 | jl @f |
- | |
1170 | mov [ebx + TCP_SOCKET.SND_NXT], eax |
- | |
1171 | @@: |
- | |
1172 | - | ||
1173 | ; General ACK handling complete |
- | |
1174 | ; Now do the state-specific ones |
- | |
1175 | - | ||
1176 | mov eax, [ebx + TCP_SOCKET.t_state] |
- | |
1177 | jmp dword [eax*4 + .ACK_sw_list] |
- | |
1178 | - | ||
1179 | .ACK_sw_list: |
- | |
1180 | dd .ack_processed ;TCB_CLOSED |
- | |
1181 | dd .ack_processed ;TCB_LISTEN |
- | |
1182 | dd .ack_processed ;TCB_SYN_SENT |
- | |
1183 | dd .ack_processed ;TCB_SYN_RECEIVED |
- | |
1184 | dd .ack_processed ;TCB_ESTABLISHED |
- | |
1185 | dd .ack_processed ;TCB_CLOSE_WAIT |
- | |
1186 | dd .ack_fw1 ;TCB_FIN_WAIT_1 |
- | |
1187 | dd .ack_c ;TCB_CLOSING |
- | |
1188 | dd .ack_la ;TCB_LAST_ACK |
- | |
1189 | dd .ack_processed ;TCB_FIN_WAIT_2 |
- | |
1190 | dd .ack_tw ;TCB_TIMED_WAIT |
- | |
1191 | - | ||
1192 | - | ||
1193 | .ack_fw1: |
- | |
1194 | - | ||
1195 | ;;; TODO: 963 |
- | |
1196 | - | ||
1197 | jmp .ack_processed |
- | |
1198 | - | ||
1199 | .ack_c: |
- | |
1200 | - | ||
1201 | ;;; TODO: 958 |
- | |
1202 | - | ||
1203 | jmp .ack_processed |
- | |
1204 | - | ||
1205 | .ack_la: |
- | |
1206 | - | ||
1207 | ;;; TODO: 999 |
- | |
1208 | - | ||
1209 | jmp .ack_processed |
- | |
1210 | - | ||
1211 | - | ||
1212 | .ack_tw: |
- | |
1213 | - | ||
1214 | ;;; TODO: 1010 |
- | |
1215 | - | ||
1216 | jmp .ack_processed |
- | |
1217 | - | ||
1218 | - | ||
1219 | .ack_processed: |
- | |
1220 | - | ||
1221 | DEBUGF 1,"ack processed\n" |
- | |
1222 | - | ||
1223 | ;---------------------------------------------- |
- | |
1224 | ; check if we need to update window information |
- | |
1225 | - | ||
1226 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
1227 | jz .no_window_update |
- | |
1228 | - | ||
1229 | mov eax, [ebx + TCP_SOCKET.SND_WL1] |
- | |
1230 | cmp eax, [edx + TCP_segment.SequenceNumber] |
- | |
1231 | jl .update_window |
- | |
1232 | jg @f |
- | |
1233 | - | ||
1234 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
- | |
1235 | cmp eax, [edx + TCP_segment.AckNumber] |
- | |
1236 | jl .update_window |
- | |
1237 | jg .no_window_update |
- | |
1238 | @@: |
- | |
1239 | - | ||
1240 | mov eax, [ebx + TCP_SOCKET.SND_WL2] |
- | |
1241 | cmp eax, [edx + TCP_segment.AckNumber] |
- | |
1242 | jne .no_window_update |
- | |
1243 | - | ||
1244 | movzx eax, [edx + TCP_segment.Window] |
- | |
1245 | cmp eax, [ebx + TCP_SOCKET.SND_WND] |
- | |
1246 | jle .no_window_update |
- | |
1247 | - | ||
1248 | .update_window: |
- | |
1249 | - | ||
1250 | DEBUGF 1,"Updating window\n" |
- | |
1251 | - | ||
1252 | ;---------------------------------- |
- | |
1253 | ; Keep track of pure window updates |
- | |
1254 | - | ||
1255 | ; test ecx, ecx |
- | |
1256 | ; jz @f |
- | |
1257 | ; |
- | |
1258 | ; mov eax, [ebx + TCP_SOCKET.SND_WL2] |
- | |
1259 | ; cmp eax, [edx + TCP_segment.AckNumber] |
- | |
1260 | ; jne @f |
- | |
1261 | ; |
- | |
1262 | ; ;; mov eax, tiwin |
- | |
1263 | ; cmp eax, [ebx + TCP_SOCKET.SND_WND] |
- | |
1264 | ; jle @f |
- | |
1265 | ; |
- | |
1266 | ; ;;; update stats |
- | |
1267 | ; |
- | |
1268 | ; @@: |
- | |
1269 | - | ||
1270 | mov eax, dword [edx + TCP_segment.Window] |
- | |
1271 | cmp eax, [ebx + TCP_SOCKET.max_sndwnd] |
- | |
1272 | jle @f |
- | |
1273 | mov [ebx + TCP_SOCKET.max_sndwnd], eax |
- | |
1274 | @@: |
- | |
1275 | mov [ebx + TCP_SOCKET.SND_WND], eax |
- | |
1276 | - | ||
1277 | push [edx + TCP_segment.SequenceNumber] |
- | |
1278 | pop [ebx + TCP_SOCKET.SND_WL1] |
- | |
1279 | - | ||
1280 | push [edx + TCP_segment.AckNumber] |
- | |
1281 | pop [ebx + TCP_SOCKET.SND_WL2] |
- | |
1282 | - | ||
1283 | ;;; needoutput = 1 |
- | |
1284 | - | ||
1285 | .no_window_update: |
- | |
1286 | - | ||
1287 | ;----------------- |
- | |
1288 | ; process URG flag |
- | |
1289 | - | ||
1290 | test [edx + TCP_segment.Flags], TH_URG |
- | |
1291 | jz .not_urgent |
- | |
1292 | - | ||
1293 | cmp [edx + TCP_segment.UrgentPointer], 0 |
- | |
1294 | jz .not_urgent |
- | |
1295 | - | ||
1296 | cmp [ebx + TCP_SOCKET.t_state], TCB_TIMED_WAIT |
- | |
1297 | je .not_urgent |
- | |
1298 | - | ||
1299 | ; Ignore bogus urgent offsets |
- | |
1300 | - | ||
1301 | ;;; 1040-1050 |
- | |
1302 | - | ||
1303 | movzx eax, [edx + TCP_segment.UrgentPointer] |
121 | |
1304 | add eax, [ebx + STREAM_SOCKET.rcv + RING_BUFFER.size] |
- | |
1305 | cmp eax, SOCKET_MAXDATA |
- | |
1306 | jle .not_urgent |
- | |
1307 | - | ||
1308 | mov [edx + TCP_segment.UrgentPointer], 0 |
- | |
1309 | and [edx + TCP_segment.Flags], not (TH_URG) |
- | |
1310 | jmp .do_data |
- | |
1311 | - | ||
1312 | .not_urgent: |
- | |
1313 | - | ||
1314 | ;-------------------------------------- |
- | |
1315 | ; processing of received urgent pointer |
- | |
1316 | - | ||
1317 | ;;; TODO (1051-1093) |
- | |
1318 | - | ||
1319 | ;-------------------------------- |
- | |
1320 | ; process the data in the segment |
- | |
1321 | - | ||
1322 | .do_data: |
- | |
1323 | - | ||
1324 | DEBUGF 1,"TCP: do data (%u)\n", ecx |
- | |
1325 | - | ||
1326 | test [edx + TCP_segment.Flags], TH_FIN |
- | |
1327 | jnz .process_fin |
- | |
1328 | - | ||
1329 | cmp [ebx + TCP_SOCKET.t_state], TCB_FIN_WAIT_1 |
- | |
1330 | jge .dont_do_data |
- | |
1331 | - | ||
1332 | test ecx, ecx |
- | |
1333 | jz .final_processing |
- | |
1334 | - | ||
1335 | DEBUGF 1,"Processing data in segment\n" |
- | |
1336 | - | ||
1337 | ;; TODO: check if data is in sequence ! |
- | |
1338 | - | ||
1339 | movzx eax, [edx + TCP_segment.DataOffset] ;;; todo: remember this in.. edi ? |
- | |
1340 | and eax, 0xf0 |
- | |
1341 | shr al, 2 |
- | |
1342 | - | ||
1343 | lea esi, [edx + eax] |
- | |
1344 | - | ||
1345 | or [ebx + TCP_SOCKET.t_flags], TF_DELACK |
- | |
1346 | add [ebx + TCP_SOCKET.RCV_NXT], ecx |
122 | |
1347 | - | ||
1348 | lea eax, [ebx + STREAM_SOCKET.rcv] |
- | |
1349 | call SOCKET_ring_write |
- | |
1350 | - | ||
1351 | mov eax, ebx |
- | |
1352 | call SOCKET_notify_owner |
- | |
1353 | - | ||
1354 | jmp .final_processing |
- | |
1355 | - | ||
1356 | - | ||
1357 | .dont_do_data: |
- | |
1358 | - | ||
1359 | ;--------------- |
- | |
1360 | ; FIN processing |
- | |
1361 | - | ||
1362 | .process_fin: |
- | |
1363 | - | ||
1364 | DEBUGF 1,"Processing FIN\n" |
- | |
1365 | - | ||
1366 | mov eax, [ebx + TCP_SOCKET.t_state] |
- | |
1367 | shl eax, 2 |
- | |
1368 | jmp dword [eax + .FIN_sw_list] |
- | |
1369 | - | ||
1370 | .FIN_sw_list: |
- | |
1371 | dd .no_fin ;TCB_CLOSED |
- | |
1372 | dd .no_fin ;TCB_LISTEN |
- | |
1373 | dd .no_fin ;TCB_SYN_SENT |
- | |
1374 | dd .fin_syn_est ;TCB_SYN_RECEIVED |
- | |
1375 | dd .fin_syn_est ;TCB_ESTABLISHED |
- | |
1376 | dd .no_fin ;TCB_CLOSE_WAIT |
- | |
1377 | dd .fin_wait1 ;TCB_FIN_WAIT_1 |
- | |
1378 | dd .no_fin ;TCB_CLOSING |
- | |
1379 | dd .no_fin ;TCB_LAST_ACK |
- | |
1380 | dd .fin_wait2 ;TCB_FIN_WAIT_2 |
- | |
1381 | dd .fin_timed ;TCB_TIMED_WAIT |
- | |
1382 | - | ||
1383 | - | ||
1384 | - | ||
1385 | .fin_syn_est: |
- | |
1386 | - | ||
1387 | jmp .final_processing |
- | |
1388 | - | ||
1389 | .fin_wait1: |
- | |
1390 | - | ||
1391 | jmp .final_processing |
- | |
1392 | - | ||
1393 | .fin_wait2: |
- | |
1394 | - | ||
1395 | jmp .final_processing |
- | |
1396 | - | ||
1397 | .fin_timed: |
- | |
1398 | - | ||
1399 | jmp .final_processing |
- | |
1400 | - | ||
1401 | .no_fin: |
- | |
1402 | - | ||
1403 | ;----------------- |
- | |
1404 | ; Final processing |
- | |
1405 | - | ||
1406 | .final_processing: |
- | |
1407 | - | ||
1408 | DEBUGF 1,"Final processing\n" |
- | |
1409 | - | ||
1410 | mov [ebx + SOCKET.lock], 0 |
- | |
1411 | - | ||
1412 | ;;; if debug enabled, output packet |
- | |
1413 | - | ||
1414 | ;test needoutput, needoutput |
- | |
1415 | ;jz .dumpit |
- | |
1416 | - | ||
1417 | test [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
1418 | jz .dumpit |
- | |
1419 | - | ||
1420 | DEBUGF 1,"ACK now!\n" |
- | |
1421 | - | ||
1422 | push ebx |
- | |
1423 | mov eax, ebx |
- | |
1424 | call TCP_output |
- | |
1425 | pop ebx |
- | |
1426 | - | ||
1427 | .dumpit: |
- | |
1428 | - | ||
1429 | call kernel_free |
- | |
1430 | add esp, 4 |
- | |
1431 | ret |
- | |
1432 | - | ||
1433 | ;------------------------------------------ |
- | |
1434 | ; Generate an ACK, droping incoming segment |
- | |
1435 | - | ||
1436 | align 4 |
- | |
1437 | .drop_after_ack: |
- | |
1438 | - | ||
1439 | DEBUGF 1,"Drop after ACK\n" |
- | |
1440 | - | ||
1441 | test [edx + TCP_segment.Flags], TH_RST |
- | |
1442 | jnz .drop |
- | |
1443 | - | ||
1444 | and [ebx + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
1445 | - | ||
1446 | push ebx |
- | |
1447 | mov eax, ebx |
- | |
1448 | call TCP_output |
- | |
1449 | pop ebx |
- | |
1450 | - | ||
1451 | call kernel_free |
- | |
1452 | add esp, 4 |
- | |
1453 | ret |
- | |
1454 | - | ||
1455 | - | ||
1456 | ;------------------------------------------- |
- | |
1457 | ; Generate an RST, dropping incoming segment |
- | |
1458 | - | ||
1459 | align 4 |
- | |
1460 | .drop_with_reset: |
- | |
1461 | - | ||
1462 | DEBUGF 1,"Drop with reset\n" |
- | |
1463 | - | ||
1464 | test [edx + TCP_segment.Flags], TH_RST |
- | |
1465 | jnz .drop |
- | |
1466 | - | ||
1467 | ;;; if its a multicast/broadcast, also drop |
- | |
1468 | - | ||
1469 | test [edx + TCP_segment.Flags], TH_ACK |
- | |
1470 | jnz .respond_ack |
- | |
1471 | - | ||
1472 | test [edx + TCP_segment.Flags], TH_SYN |
- | |
1473 | jnz .respond_syn |
- | |
1474 | - | ||
1475 | call kernel_free |
- | |
1476 | add esp, 4 |
- | |
1477 | ret |
- | |
1478 | - | ||
1479 | .respond_ack: |
- | |
1480 | - | ||
1481 | mov dl, TH_RST |
- | |
1482 | - | ||
1483 | push ebx |
- | |
1484 | call TCP_respond_segment |
- | |
1485 | pop ebx |
- | |
1486 | - | ||
1487 | jmp .destroy_new_socket |
- | |
1488 | - | ||
1489 | - | ||
1490 | .respond_syn: |
- | |
1491 | - | ||
1492 | mov dl, TH_RST + TH_ACK |
- | |
1493 | - | ||
1494 | push ebx |
- | |
1495 | call TCP_respond_socket |
- | |
1496 | pop ebx |
- | |
1497 | - | ||
1498 | jmp .destroy_new_socket |
- | |
1499 | - | ||
1500 | ;----- |
- | |
1501 | ; Drop |
- | |
1502 | - | ||
1503 | align 4 |
- | |
1504 | .drop: |
- | |
1505 | - | ||
1506 | DEBUGF 1,"Dropping packet\n" |
- | |
1507 | - | ||
1508 | ;;;; If debugging options are enabled, output the packet somwhere |
- | |
1509 | - | ||
1510 | .destroy_new_socket: |
- | |
1511 | - | ||
1512 | ;;;; kill the newly created socket |
- | |
1513 | - | ||
1514 | call kernel_free |
- | |
1515 | add esp, 4 |
- | |
1516 | ret |
- | |
1517 | - | ||
1518 | - | ||
1519 | - | ||
1520 | - | ||
1521 | - | ||
1522 | - | ||
1523 | ;--------------------------- |
- | |
1524 | ; |
- | |
1525 | ; TCP_pull_out_of_band |
- | |
1526 | ; |
- | |
1527 | ; IN: eax = |
- | |
1528 | ; ebx = socket ptr |
- | |
1529 | ; edx = tcp packet ptr |
- | |
1530 | ; |
- | |
1531 | ; OUT: / |
- | |
1532 | ; |
- | |
1533 | ;--------------------------- |
- | |
1534 | - | ||
1535 | align 4 |
- | |
1536 | TCP_pull_out_of_band: |
- | |
1537 | - | ||
1538 | DEBUGF 1,"TCP_pull_out_of_band\n" |
- | |
1539 | - | ||
1540 | ;;;; 1282-1305 |
- | |
1541 | - | ||
1542 | ret |
- | |
1543 | - | ||
1544 | - | ||
1545 | - | ||
1546 | ;----------------------------------------------------------------- |
- | |
1547 | ; |
- | |
1548 | ; TCP_output |
- | |
1549 | ; |
- | |
1550 | ; IN: eax = socket pointer |
- | |
1551 | ; |
- | |
1552 | ; OUT: / |
- | |
1553 | ; |
- | |
1554 | ;----------------------------------------------------------------- |
- | |
1555 | align 4 |
- | |
1556 | TCP_output: |
- | |
1557 | - | ||
1558 | DEBUGF 1,"TCP_output, socket: %x\n", eax |
- | |
1559 | - | ||
1560 | ; We'll detect the length of the data to be transmitted, and flags to be used |
- | |
1561 | ; If there is some data, or any critical controls to send (SYN / RST), then transmit |
- | |
1562 | ; Otherwise, investigate further |
- | |
1563 | - | ||
1564 | mov ebx, [eax + TCP_SOCKET.SND_MAX] |
- | |
1565 | cmp ebx, [eax + TCP_SOCKET.SND_UNA] |
- | |
1566 | jne .not_idle |
- | |
1567 | - | ||
1568 | mov ebx, [eax + TCP_SOCKET.t_idle] |
- | |
1569 | cmp ebx, [eax + TCP_SOCKET.t_rxtcur] |
- | |
1570 | jle .not_idle |
- | |
1571 | - | ||
1572 | ; We have been idle for a while and no ACKS are expected to clock out any data we send.. |
- | |
1573 | ; Slow start to get ack "clock" running again. |
- | |
1574 | - | ||
1575 | mov ebx, [eax + TCP_SOCKET.t_maxseg] |
- | |
1576 | mov [eax + TCP_SOCKET.SND_CWND], ebx |
- | |
1577 | - | ||
1578 | .not_idle: |
- | |
1579 | .again: |
- | |
1580 | mov ebx, [eax + TCP_SOCKET.SND_NXT] ; calculate offset |
- | |
1581 | sub ebx, [eax + TCP_SOCKET.SND_UNA] ; |
- | |
1582 | - | ||
1583 | mov ecx, [eax + TCP_SOCKET.SND_WND] ; determine window |
- | |
1584 | cmp ecx, [eax + TCP_SOCKET.SND_CWND] ; |
- | |
1585 | jl @f ; |
- | |
1586 | mov ecx, [eax + TCP_SOCKET.SND_CWND] ; |
- | |
1587 | @@: ; |
- | |
1588 | - | ||
1589 | call TCP_outflags ; in dl |
- | |
1590 | - | ||
1591 | ; If in persist timeout with window of 0, send 1 byte. |
- | |
1592 | ; Otherwise, if window is small but nonzero, and timer expired, |
- | |
1593 | ; we will send what we can and go to transmit state |
- | |
1594 | - | ||
1595 | test [eax + TCP_SOCKET.t_force], -1 |
- | |
1596 | jz .no_persist_timeout |
- | |
1597 | - | ||
1598 | test ecx, ecx |
- | |
1599 | jnz .no_zero_window |
- | |
1600 | - | ||
1601 | cmp ebx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] |
- | |
1602 | jge @f |
- | |
1603 | - | ||
1604 | and dl, not (TH_FIN) ; clear the FIN flag ??? how can it be set before? |
- | |
1605 | - | ||
1606 | @@: |
- | |
1607 | inc ecx |
- | |
1608 | jmp .no_persist_timeout |
- | |
1609 | - | ||
1610 | .no_zero_window: |
- | |
1611 | - | ||
1612 | mov [eax + TCP_SOCKET.timer_persist], 0 |
- | |
1613 | mov [eax + TCP_SOCKET.t_rxtshift], 0 |
- | |
1614 | - | ||
1615 | .no_persist_timeout: |
- | |
1616 | - | ||
1617 | ;;;106 |
- | |
1618 | - | ||
1619 | mov esi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] |
- | |
1620 | cmp esi, ecx |
- | |
1621 | jl @f |
- | |
1622 | mov esi, ecx |
- | |
1623 | @@: |
- | |
1624 | sub esi, ebx |
- | |
1625 | - | ||
1626 | cmp esi, -1 |
- | |
1627 | jne .not_minus_one |
- | |
1628 | - | ||
1629 | ; If FIN has been set, but not ACKed, and we havent been called to retransmit, |
- | |
1630 | ; len (esi) will be -1 |
- | |
1631 | ; Otherwise, window shrank after we sent into it. |
- | |
1632 | ; If window shrank to 0, cancel pending retransmit and pull SND_NXT back to (closed) window |
- | |
1633 | ; We will enter persist state below. |
- | |
1634 | ; If window didn't close completely, just wait for an ACK |
- | |
1635 | - | ||
1636 | xor esi, esi |
- | |
1637 | - | ||
1638 | test ecx, ecx |
- | |
1639 | jnz @f |
- | |
1640 | - | ||
1641 | mov [eax + TCP_SOCKET.timer_retransmission], 0 ; cancel retransmit |
- | |
1642 | - | ||
1643 | push [eax + TCP_SOCKET.SND_UNA] |
- | |
1644 | pop [eax + TCP_SOCKET.SND_NXT] |
- | |
1645 | @@: |
- | |
1646 | - | ||
1647 | .not_minus_one: |
- | |
1648 | - | ||
1649 | ;;; 124 |
- | |
1650 | - | ||
1651 | cmp esi, [eax + TCP_SOCKET.t_maxseg] |
- | |
1652 | jle @f |
- | |
1653 | - | ||
1654 | mov esi, [eax + TCP_SOCKET.t_maxseg] |
- | |
1655 | ;sendalot = 1 |
- | |
1656 | - | ||
1657 | @@: |
- | |
1658 | - | ||
1659 | ;;; 128 |
- | |
1660 | - | ||
1661 | mov edi, [eax + TCP_SOCKET.SND_NXT] |
- | |
1662 | add edi, esi ; len |
- | |
1663 | sub edi, [eax + TCP_SOCKET.SND_UNA] |
- | |
1664 | add edi, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] |
- | |
1665 | cmp edi, 0 |
- | |
1666 | jle @f |
- | |
1667 | - | ||
1668 | and dl, not (TH_FIN) ; clear the FIN flag |
- | |
1669 | - | ||
1670 | @@: |
- | |
1671 | - | ||
1672 | - | ||
1673 | ; set ecx to space available in receive buffer |
- | |
1674 | ; From now on, ecx will be the window we advertise to the other end |
- | |
1675 | - | ||
1676 | mov ecx, SOCKET_MAXDATA |
- | |
1677 | sub ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size] |
- | |
1678 | - | ||
1679 | ;------------------------------ |
- | |
1680 | ; Sender silly window avoidance |
- | |
1681 | - | ||
1682 | cmp ecx, [eax + TCP_SOCKET.t_maxseg] |
- | |
1683 | je .send |
- | |
1684 | - | ||
1685 | ;;; TODO: 144-145 |
- | |
1686 | - | ||
1687 | test [eax + TCP_SOCKET.t_force], -1 |
- | |
1688 | jnz .send |
- | |
1689 | - | ||
1690 | mov ebx, [eax + TCP_SOCKET.max_sndwnd] |
- | |
1691 | shr ebx, 1 |
- | |
1692 | cmp ecx, ebx |
- | |
1693 | jge .send |
- | |
1694 | - | ||
1695 | mov ebx, [eax + TCP_SOCKET.SND_NXT] |
- | |
1696 | cmp ebx, [eax + TCP_SOCKET.SND_MAX] |
- | |
1697 | jl .send |
- | |
1698 | - | ||
1699 | ;---------------------------------------- |
- | |
1700 | ; Check if a window update should be sent |
- | |
1701 | - | ||
1702 | test ecx, ecx ; window |
- | |
1703 | jz .no_window |
- | |
1704 | - | ||
1705 | ;;; TODO 154-172 |
- | |
1706 | - | ||
1707 | .no_window: |
- | |
1708 | - | ||
1709 | ;-------------------------- |
- | |
1710 | ; Should a segment be sent? |
- | |
1711 | - | ||
1712 | test [eax + TCP_SOCKET.t_flags], TF_ACKNOW |
- | |
1713 | jnz .send |
- | |
1714 | - | ||
1715 | test dl, TH_SYN + TH_RST |
- | |
1716 | jnz .send |
- | |
1717 | - | ||
1718 | mov ebx, [eax + TCP_SOCKET.SND_UP] |
- | |
1719 | cmp ebx, [eax + TCP_SOCKET.SND_UNA] |
- | |
1720 | jg .send |
- | |
1721 | - | ||
1722 | test dl, TH_FIN |
- | |
1723 | jz .enter_persist |
- | |
1724 | - | ||
1725 | test [eax + TCP_SOCKET.t_flags], TF_SENTFIN |
- | |
1726 | jnz .send |
- | |
1727 | - | ||
1728 | mov ebx, [eax + TCP_SOCKET.SND_NXT] |
- | |
1729 | cmp ebx, [eax + TCP_SOCKET.SND_UNA] |
- | |
1730 | je .send |
- | |
1731 | - | ||
1732 | ;-------------------- |
- | |
1733 | ; Enter persist state |
- | |
1734 | - | ||
1735 | .enter_persist: |
- | |
1736 | - | ||
1737 | DEBUGF 1,"Entering persist state\n" |
- | |
1738 | - | ||
1739 | ;-------------------------------------- |
- | |
1740 | ; No reason to send a segment, just ret |
- | |
1741 | - | ||
1742 | DEBUGF 1,"No reason to send a segment\n" |
- | |
1743 | - | ||
1744 | ret |
- | |
1745 | - | ||
1746 | - | ||
1747 | ;----------------------------------------------- |
- | |
1748 | ; |
- | |
1749 | ; Send a segment |
- | |
1750 | ; |
- | |
1751 | ; eax = socket pointer |
- | |
1752 | ; dl = flags |
- | |
1753 | ; |
- | |
1754 | ;----------------------------------------------- |
- | |
1755 | - | ||
1756 | .send: |
- | |
1757 | - | ||
1758 | DEBUGF 1,"Preparing to send a segment\n" |
- | |
1759 | - | ||
1760 | mov edi, TCP_segment.Data ; edi will contain headersize |
- | |
1761 | - | ||
1762 | sub esp, 8 ; create some space on stack |
- | |
1763 | push eax ; save this too.. |
- | |
1764 | - | ||
1765 | ;------------------------------------ |
- | |
1766 | ; Send options with first SYN segment |
- | |
1767 | - | ||
1768 | test dl, TH_SYN |
- | |
1769 | jz .no_options |
- | |
1770 | - | ||
1771 | push [eax + TCP_SOCKET.ISS] |
- | |
1772 | pop [eax + TCP_SOCKET.SND_NXT] |
- | |
1773 | - | ||
1774 | test [eax + TCP_SOCKET.t_flags], TF_NOOPT |
- | |
1775 | jnz .no_options |
- | |
1776 | - | ||
1777 | mov ecx, 1460 |
- | |
1778 | or ecx, TCP_OPT_MAXSEG shl 24 + 4 shl 16 |
- | |
1779 | bswap ecx |
- | |
1780 | push ecx |
- | |
1781 | add di, 4 |
- | |
1782 | - | ||
1783 | test [eax + TCP_SOCKET.t_flags], TF_REQ_SCALE |
- | |
1784 | jz .no_syn |
- | |
1785 | - | ||
1786 | test dl, TH_ACK |
- | |
1787 | jnz .scale_opt |
- | |
1788 | - | ||
1789 | test [eax + TCP_SOCKET.t_flags], TF_RCVD_SCALE |
- | |
1790 | jz .no_syn |
- | |
1791 | - | ||
1792 | .scale_opt: |
- | |
1793 | movzx ecx, byte [eax + TCP_SOCKET.request_r_scale] |
- | |
1794 | or ecx, TCP_OPT_WINDOW shl 24 + 4 shl 16 + TCP_OPT_NOP shl 8 |
- | |
1795 | bswap ecx |
- | |
1796 | pushd ecx |
- | |
1797 | add di, 4 |
- | |
1798 | - | ||
1799 | .no_syn: |
- | |
1800 | - | ||
1801 | ;------------------------------------ |
- | |
1802 | ; Make the timestamp option if needed |
- | |
1803 | - | ||
1804 | test [eax + TCP_SOCKET.t_flags], TF_REQ_TSTMP |
- | |
1805 | jz .no_timestamp |
- | |
1806 | - | ||
1807 | test dl, TH_RST |
- | |
1808 | jnz .no_timestamp |
- | |
1809 | - | ||
1810 | test dl, TH_ACK |
- | |
1811 | jz .timestamp |
- | |
1812 | - | ||
1813 | test [eax + TCP_SOCKET.t_flags], TF_RCVD_TSTMP |
- | |
1814 | jz .no_timestamp |
- | |
1815 | - | ||
1816 | .timestamp: |
- | |
1817 | mov esi, [timer_ticks] |
- | |
1818 | bswap esi |
- | |
1819 | push esi |
- | |
1820 | pushw 0 |
- | |
1821 | pushd TCP_OPT_TIMESTAMP + 10 shl 8 + TCP_OPT_NOP shl 16 + TCP_OPT_NOP shl 24 |
- | |
1822 | add di, 10 |
- | |
1823 | - | ||
1824 | .no_timestamp: |
- | |
1825 | ;; TODO: check if we dont exceed the max segment size |
- | |
1826 | - | ||
1827 | .no_options: |
- | |
1828 | ; eax = socket ptr |
- | |
1829 | ; edx = flags |
- | |
1830 | ; ecx = data size |
- | |
1831 | ; edi = header size |
- | |
1832 | ; esi = snd ring buff ptr |
- | |
1833 | - | ||
1834 | mov ecx, [eax + STREAM_SOCKET.snd + RING_BUFFER.size] |
- | |
1835 | cmp ecx, [eax + TCP_SOCKET.t_maxseg] ;;; right? |
- | |
1836 | jle @f |
- | |
1837 | mov ecx, [eax + TCP_SOCKET.t_maxseg] |
- | |
1838 | @@: |
- | |
1839 | add ecx, edi ; total TCP segment size |
- | |
1840 | - | ||
1841 | ; Start by pushing all TCP header values in reverse order on stack |
- | |
1842 | ; (essentially, creating the tcp header!) |
- | |
1843 | - | ||
1844 | pushw 0 ; .UrgentPointer dw ? |
- | |
1845 | pushw 0 ; .Checksum dw ? |
- | |
1846 | pushw 0x00a0 ; .Window dw ? ;;;;;;; |
- | |
1847 | shl edi, 2 ; .DataOffset db ? only 4 left-most bits |
- | |
1848 | shl dx, 8 |
- | |
1849 | or dx, di ; .Flags db ? |
- | |
1850 | pushw dx |
- | |
1851 | shr edi, 2 ; .DataOffset db ? ;;;; |
- | |
1852 | - | ||
1853 | push [eax + TCP_SOCKET.RCV_NXT] ; .AckNumber dd ? |
- | |
1854 | ntohd [esp] |
- | |
1855 | - | ||
1856 | push [eax + TCP_SOCKET.SND_NXT] ; .SequenceNumber dd ? |
- | |
1857 | ntohd [esp] |
- | |
1858 | - | ||
1859 | push [eax + TCP_SOCKET.RemotePort] ; .DestinationPort dw ? |
- | |
1860 | ntohw [esp] |
- | |
1861 | - | ||
1862 | push [eax + TCP_SOCKET.LocalPort] ; .SourcePort dw ? |
- | |
1863 | ntohw [esp] |
- | |
1864 | - | ||
1865 | push edi ; header size |
- | |
1866 | - | ||
1867 | ; Create the IP packet |
- | |
1868 | mov ebx, [eax + IP_SOCKET.LocalIP] ; source ip |
- | |
1869 | mov eax, [eax + IP_SOCKET.RemoteIP] ; dest ip |
- | |
1870 | mov di, IP_PROTO_TCP shl 8 + 128 |
- | |
1871 | call IPv4_output |
- | |
1872 | jz .fail |
- | |
1873 | - | ||
1874 | ;----------------------------------------- |
- | |
1875 | ; Move TCP header from stack to TCP packet |
- | |
1876 | - | ||
1877 | push ecx |
- | |
1878 | mov ecx, [esp+4] |
- | |
1879 | lea esi, [esp+4+4] |
- | |
1880 | shr ecx, 2 |
- | |
1881 | rep movsd |
- | |
1882 | pop ecx ; full TCP packet size |
- | |
1883 | - | ||
1884 | pop esi ; headersize |
- | |
1885 | add esp, esi |
- | |
1886 | - | ||
1887 | mov [esp + 4], eax ; packet ptr |
- | |
1888 | mov [esp + 4+4], edx ; packet size |
- | |
1889 | - | ||
1890 | mov edx, edi ; begin of data |
- | |
1891 | sub edx, esi ; begin of packet (edi = begin of data) |
- | |
1892 | push ecx |
- | |
1893 | sub ecx, esi ; data size |
- | |
1894 | - | ||
1895 | ;-------------- |
- | |
1896 | ; Copy the data |
- | |
1897 | - | ||
1898 | ; eax = ptr to ring struct |
- | |
1899 | ; ecx = buffer size |
- | |
1900 | ; edi = ptr to buffer |
- | |
1901 | - | ||
1902 | ; test ecx, ecx |
- | |
1903 | mov eax, [esp+4] ; socket ptr |
- | |
1904 | add [eax + TCP_SOCKET.SND_NXT], ecx |
- | |
1905 | add eax, STREAM_SOCKET.snd |
- | |
1906 | push edx |
- | |
1907 | call SOCKET_ring_read |
- | |
1908 | pop esi |
- | |
1909 | pop ecx |
- | |
1910 | pop eax |
- | |
1911 | - | ||
1912 | test [esi + TCP_segment.Flags], TH_SYN + TH_FIN |
- | |
1913 | jz @f |
- | |
1914 | inc [eax + TCP_SOCKET.SND_NXT] |
- | |
1915 | ;;; TODO: update sentfin flag |
- | |
1916 | @@: |
- | |
1917 | - | ||
1918 | mov edx, [eax + TCP_SOCKET.SND_NXT] |
- | |
1919 | cmp edx, [eax + TCP_SOCKET.SND_MAX] |
- | |
1920 | jle @f |
- | |
1921 | mov [eax + TCP_SOCKET.SND_MAX], edx |
- | |
1922 | - | ||
1923 | ;;;; TODO: time transmission (420) |
- | |
1924 | @@: |
- | |
1925 | - | ||
1926 | ;;; TODO: set retransmission timer |
- | |
1927 | - | ||
1928 | ;-------------------- |
- | |
1929 | ; Create the checksum |
- | |
1930 | - | ||
1931 | DEBUGF 1,"checksum: ptr=%x size=%u\n", esi, ecx |
- | |
1932 | - | ||
1933 | TCP_checksum (eax + IP_SOCKET.LocalIP), (eax + IP_SOCKET.RemoteIP) |
- | |
1934 | mov [esi+TCP_segment.Checksum], dx |
- | |
1935 | - | ||
1936 | ;---------------- |
- | |
1937 | ; Send the packet |
- | |
1938 | - | ||
1939 | DEBUGF 1,"Sending TCP Packet to device %x\n", ebx |
- | |
1940 | call [ebx + NET_DEVICE.transmit] |
- | |
1941 | ret |
- | |
1942 | - | ||
1943 | - | ||
1944 | .fail: |
- | |
1945 | pop ecx |
- | |
1946 | add esp, ecx |
- | |
1947 | add esp, 4+8 |
- | |
1948 | DEBUGF 1,"TCP_output: failed\n" |
- | |
1949 | ret |
- | |
1950 | - | ||
1951 | - | ||
1952 | - | ||
1953 | ;------------------------- |
- | |
1954 | ; |
- | |
1955 | ; TCP_outflags |
- | |
1956 | ; |
- | |
1957 | ; IN: eax = socket ptr |
- | |
1958 | ; |
- | |
1959 | ; OUT: edx = flags |
- | |
1960 | ; |
- | |
1961 | ;------------------------- |
- | |
1962 | align 4 |
- | |
1963 | TCP_outflags: |
- | |
1964 | - | ||
1965 | mov edx, [eax + TCP_SOCKET.t_state] |
- | |
1966 | movzx edx, byte [edx + .flaglist] |
- | |
1967 | - | ||
1968 | DEBUGF 1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl |
- | |
1969 | - | ||
1970 | ret |
- | |
1971 | - | ||
1972 | .flaglist: |
- | |
1973 | - | ||
1974 | db TH_RST + TH_ACK ; TCB_CLOSED |
- | |
1975 | db 0 ; TCB_LISTEN |
- | |
1976 | db TH_SYN ; TCB_SYN_SENT |
- | |
1977 | db TH_SYN + TH_ACK ; TCB_SYN_RECEIVED |
- | |
1978 | db TH_ACK ; TCB_ESTABLISHED |
- | |
1979 | db TH_ACK ; TCB_CLOSE_WAIT |
- | |
1980 | db TH_SYN + TH_ACK ; TCB_FIN_WAIT_1 |
- | |
1981 | db TH_SYN + TH_ACK ; TCB_CLOSING |
- | |
1982 | db TH_SYN + TH_ACK ; TCB_LAST_ACK |
- | |
1983 | db TH_ACK ; TCB_FIN_WAIT_2 |
- | |
1984 | db TH_ACK ; TCB_TIMED_WAIT |
- | |
1985 | - | ||
1986 | - | ||
1987 | - | ||
1988 | - | ||
1989 | ;------------------------- |
- | |
1990 | ; |
- | |
1991 | ; TCP_drop |
- | |
1992 | ; |
- | |
1993 | ; IN: eax = socket ptr |
- | |
1994 | ; ebx = error number |
- | |
1995 | ; |
- | |
1996 | ; OUT: eax = socket ptr |
- | |
1997 | ; |
- | |
1998 | ;------------------------- |
- | |
1999 | align 4 |
- | |
2000 | TCP_drop: |
- | |
2001 | - | ||
2002 | DEBUGF 1,"TCP_drop\n" |
- | |
2003 | - | ||
2004 | cmp [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED |
- | |
2005 | jl .no_syn_received |
- | |
2006 | - | ||
2007 | mov [eax + TCP_SOCKET.t_state], TCB_CLOSED |
- | |
2008 | - | ||
2009 | call TCP_output |
- | |
2010 | - | ||
2011 | ;;; TODO: update stats |
- | |
2012 | - | ||
2013 | jmp TCP_close |
- | |
2014 | - | ||
2015 | .no_syn_received: |
- | |
2016 | - | ||
2017 | ;;; TODO: update stats |
- | |
2018 | - | ||
2019 | ;;; TODO: check if error code is "Connection timed out' and handle accordingly |
- | |
2020 | - | ||
2021 | mov [eax + SOCKET.errorcode], ebx |
- | |
2022 | - | ||
2023 | jmp TCP_close |
- | |
2024 | - | ||
2025 | - | ||
2026 | ;------------------------- |
- | |
2027 | ; |
- | |
2028 | ; TCP_close |
- | |
2029 | ; |
- | |
2030 | ; IN: eax = socket ptr |
- | |
2031 | ; OUT: eax = socket ptr |
- | |
2032 | ; |
- | |
2033 | ;------------------------- |
- | |
2034 | align 4 |
- | |
2035 | TCP_close: |
- | |
2036 | - | ||
2037 | DEBUGF 1,"TCP_close\n" |
- | |
2038 | - | ||
2039 | ;;; TODO: update RTT and mean deviation |
- | |
2040 | ;;; TODO: update slow start threshold |
- | |
2041 | ;;; TODO: release connection resources |
- | |
2042 | - | ||
2043 | ; Now, mark the socket as being disconnected |
- | |
2044 | - | ||
2045 | mov [eax + SOCKET.state], 0 ;;; FIXME |
- | |
2046 | - | ||
2047 | ret |
- | |
2048 | - | ||
2049 | - | ||
2050 | - | ||
2051 | - | ||
2052 | ;--------------------------------------- |
- | |
2053 | ; |
- | |
2054 | ; The easy way to send an ACK/RST/keepalive segment |
- | |
2055 | ; |
- | |
2056 | ; TCP_respond_socket: |
- | |
2057 | ; |
- | |
2058 | ; IN: ebx = socket ptr |
- | |
2059 | ; cl = flags |
- | |
2060 | ; |
- | |
2061 | ;-------------------------------------- |
- | |
2062 | align 4 |
- | |
2063 | TCP_respond_socket: |
- | |
2064 | - | ||
2065 | DEBUGF 1,"TCP_respond_socket\n" |
- | |
2066 | - | ||
2067 | ;--------------------- |
- | |
2068 | ; Create the IP packet |
- | |
2069 | - | ||
2070 | push cx ebx |
- | |
2071 | mov eax, [ebx + IP_SOCKET.RemoteIP] |
- | |
2072 | mov ebx, [ebx + IP_SOCKET.LocalIP] |
- | |
2073 | mov ecx, TCP_segment.Data |
- | |
2074 | mov di , IP_PROTO_TCP shl 8 + 128 |
- | |
2075 | call IPv4_output |
- | |
2076 | test edi, edi |
- | |
2077 | jz .error |
- | |
2078 | pop esi cx |
- | |
2079 | push edx eax |
- | |
2080 | - | ||
2081 | ;----------------------------------------------- |
- | |
2082 | ; Fill in the TCP header by using the socket ptr |
- | |
2083 | - | ||
2084 | mov ax, [esi + TCP_SOCKET.LocalPort] |
- | |
2085 | rol ax, 8 |
- | |
2086 | stosw |
- | |
2087 | mov ax, [esi + TCP_SOCKET.RemotePort] |
- | |
2088 | rol ax, 8 |
- | |
2089 | stosw |
- | |
2090 | mov eax, [esi + TCP_SOCKET.SND_NXT] |
- | |
2091 | bswap eax |
- | |
2092 | stosd |
- | |
2093 | mov eax, [esi + TCP_SOCKET.RCV_NXT] |
- | |
2094 | bswap eax |
- | |
2095 | stosd |
- | |
2096 | mov al, 0x50 ; Dataoffset: 20 bytes |
- | |
2097 | stosb |
- | |
2098 | mov al, cl |
- | |
2099 | stosb |
- | |
2100 | mov ax, [esi + TCP_SOCKET.RCV_WND] |
- | |
2101 | rol ax, 8 |
- | |
2102 | stosw ; window |
- | |
2103 | xor eax, eax |
- | |
2104 | stosd ; checksum + urgentpointer |
- | |
2105 | - | ||
2106 | ;--------------------- |
- | |
2107 | ; Fill in the checksum |
- | |
2108 | - | ||
2109 | .checksum: |
- | |
2110 | sub edi, TCP_segment.Data |
- | |
2111 | mov ecx, TCP_segment.Data |
- | |
2112 | xchg esi, edi |
- | |
2113 | TCP_checksum (edi + IP_SOCKET.LocalIP), (esi + IP_SOCKET.RemoteIP) |
- | |
2114 | mov [esi+TCP_segment.Checksum], dx |
- | |
2115 | - | ||
2116 | ;-------------------- |
- | |
2117 | ; And send the segment |
- | |
2118 | - | ||
2119 | call [ebx + NET_DEVICE.transmit] |
- | |
2120 | ret |
- | |
2121 | - | ||
2122 | .error: |
- | |
2123 | DEBUGF 1,"TCP_respond failed\n" |
- | |
2124 | add esp, 2+4 |
- | |
2125 | - | ||
2126 | ret |
- | |
2127 | - | ||
2128 | - | ||
2129 | - | ||
2130 | ;------------------------- |
- | |
2131 | ; TCP_respond.segment: |
- | |
2132 | ; |
- | |
2133 | ; IN: edx = segment ptr (a previously received segment) |
- | |
2134 | ; cl = flags |
- | |
2135 | - | ||
2136 | align 4 |
- | |
2137 | TCP_respond_segment: |
- | |
2138 | - | ||
2139 | DEBUGF 1,"TCP_respond_segment\n" |
- | |
2140 | - | ||
2141 | ;--------------------- |
- | |
2142 | ; Create the IP packet |
- | |
2143 | - | ||
2144 | push cx edx |
- | |
2145 | mov ebx, [edx - 20 + IPv4_Packet.SourceAddress] ;;;; and what if ip packet had options?! |
- | |
2146 | mov eax, [edx - 20 + IPv4_Packet.DestinationAddress] ;;; |
123 | include 'tcp_timer.inc' |
2147 | mov ecx, TCP_segment.Data |
- | |
2148 | mov di , IP_PROTO_TCP shl 8 + 128 |
- | |
2149 | call IPv4_output |
- | |
2150 | jz .error |
- | |
2151 | pop esi cx |
- | |
2152 | - | ||
2153 | push edx eax |
- | |
2154 | - | ||
2155 | ;--------------------------------------------------- |
- | |
2156 | ; Fill in the TCP header by using a received segment |
- | |
2157 | - | ||
2158 | mov ax, [esi + TCP_segment.DestinationPort] |
- | |
2159 | rol ax, 8 |
- | |
2160 | stosw |
- | |
2161 | mov ax, [esi + TCP_segment.SourcePort] |
- | |
2162 | rol ax, 8 |
- | |
2163 | stosw |
- | |
2164 | mov eax, [esi + TCP_segment.AckNumber] |
- | |
2165 | bswap eax |
- | |
2166 | stosd |
- | |
2167 | xor eax, eax |
- | |
2168 | stosd |
- | |
2169 | mov al, 0x50 ; Dataoffset: 20 bytes |
- | |
2170 | stosb |
- | |
2171 | mov al, cl |
- | |
2172 | stosb |
- | |
2173 | mov ax, 1280 |
- | |
2174 | rol ax, 8 |
- | |
2175 | stosw ; window |
- | |
2176 | xor eax, eax |
- | |
2177 | stosd ; checksum + urgentpointer |
- | |
2178 | - | ||
2179 | ;--------------------- |
- | |
2180 | ; Fill in the checksum |
- | |
2181 | - | ||
2182 | .checksum: |
- | |
2183 | lea esi, [edi - TCP_segment.Data] |
- | |
2184 | mov ecx, TCP_segment.Data |
- | |
2185 | TCP_checksum (esi - 20 + IPv4_Packet.DestinationAddress), (esi - 20 + IPv4_Packet.DestinationAddress) |
- | |
2186 | mov [esi+TCP_segment.Checksum], dx |
- | |
2187 | - | ||
2188 | ;-------------------- |
- | |
2189 | ; And send the segment |
- | |
2190 | - | ||
2191 | call [ebx + NET_DEVICE.transmit] |
- | |
2192 | ret |
- | |
2193 | - | ||
2194 | .error: |
- | |
2195 | DEBUGF 1,"TCP_respond failed\n" |
- | |
2196 | add esp, 2+4 |
- | |
2197 | - | ||
Line 2198... | Line 124... | ||
2198 | ret |
124 | include 'tcp_subr.inc' |
2199 | 125 | include 'tcp_input.inc' |
|
2200 | 126 | include 'tcp_output.inc' |