Subversion Repositories Kolibri OS

Rev

Rev 1514 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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