Subversion Repositories Kolibri OS

Rev

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

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