2011-01-24 23:01:54 +01:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; ;;
|
2012-02-21 09:44:51 +01:00
|
|
|
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
|
2011-01-24 23:01:54 +01:00
|
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
|
|
;; ;;
|
|
|
|
;; Part of the tcp/ip network stack for KolibriOS ;;
|
|
|
|
;; ;;
|
|
|
|
;; Written by hidnplayr@kolibrios.org ;;
|
|
|
|
;; ;;
|
|
|
|
;; Based on the code of 4.4BSD ;;
|
|
|
|
;; ;;
|
|
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
|
|
;; Version 2, June 1991 ;;
|
|
|
|
;; ;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
|
|
|
$Revision$
|
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
;-----------------------------------------------------------------
|
|
|
|
;
|
|
|
|
; TCP_input:
|
|
|
|
;
|
|
|
|
; IN: [esp] = ptr to buffer
|
|
|
|
; [esp+4] = buffer size
|
|
|
|
; ebx = ptr to device struct
|
|
|
|
; ecx = segment size
|
2011-11-12 21:05:07 +01:00
|
|
|
; esi = ptr to TCP segment
|
2011-11-12 16:39:15 +01:00
|
|
|
; edi = ptr to ipv4 source address, followed by ipv4 dest address
|
2011-01-08 15:59:21 +01:00
|
|
|
;
|
|
|
|
; OUT: /
|
|
|
|
;
|
|
|
|
;-----------------------------------------------------------------
|
2011-02-01 17:14:18 +01:00
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
align 4
|
|
|
|
TCP_input:
|
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
pushfd
|
|
|
|
cli
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: size=%u\n", ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
; First, record the current time
|
2012-08-27 15:55:15 +02:00
|
|
|
mov eax, [timer_ticks] ; in 1/100 seconds
|
2012-08-28 00:47:10 +02:00
|
|
|
mov [esp+8], eax
|
2012-08-19 13:21:20 +02:00
|
|
|
|
|
|
|
; then, re-calculate the checksum (if not already done by hw)
|
|
|
|
; test [ebx + NET_DEVICE.hwacc], HWACC_TCP_IPv4_IN
|
|
|
|
; jnz .checksum_ok
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push ecx esi
|
|
|
|
pushw [esi + TCP_header.Checksum]
|
|
|
|
mov [esi + TCP_header.Checksum], 0
|
|
|
|
TCP_checksum (edi), (edi+4)
|
2012-08-27 15:55:15 +02:00
|
|
|
pop cx ; previous checksum
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp cx, dx
|
|
|
|
pop edx ecx
|
2012-04-11 15:07:45 +02:00
|
|
|
jne .drop_no_socket
|
2012-08-19 13:21:20 +02:00
|
|
|
.checksum_ok:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
; Verify the data offset
|
2012-02-23 23:21:40 +01:00
|
|
|
and [edx + TCP_header.DataOffset], 0xf0 ; Calculate TCP segment header size (throwing away unused reserved bits in TCP header)
|
|
|
|
shr [edx + TCP_header.DataOffset], 2
|
|
|
|
cmp [edx + TCP_header.DataOffset], sizeof.TCP_header ; Now see if it's at least the size of a standard TCP header
|
2012-04-11 15:07:45 +02:00
|
|
|
jb .drop_no_socket ; If not, drop the packet
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx eax, [edx + TCP_header.DataOffset]
|
|
|
|
sub ecx, eax ; substract TCP header size from total segment size
|
2012-04-11 15:07:45 +02:00
|
|
|
jb .drop_no_socket ; If total segment size is less then the advertised header size, drop packet
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: %u bytes of data\n", ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;-------------------------------------------
|
|
|
|
; Convert Big-endian values to little endian
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
ntohd [edx + TCP_header.SequenceNumber]
|
|
|
|
ntohd [edx + TCP_header.AckNumber]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
ntohw [edx + TCP_header.Window]
|
|
|
|
ntohw [edx + TCP_header.UrgentPointer]
|
|
|
|
ntohw [edx + TCP_header.SourcePort]
|
|
|
|
ntohw [edx + TCP_header.DestinationPort]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;------------------------
|
|
|
|
; Find the socket pointer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; IP Packet TCP Destination Port = local Port
|
|
|
|
; (IP Packet SenderAddress = Remote IP) OR (Remote IP = 0)
|
2011-11-12 20:20:33 +01:00
|
|
|
; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0)
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
.findpcb:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov ebx, net_sockets
|
|
|
|
mov si, [edx + TCP_header.DestinationPort]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.socket_loop:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov ebx, [ebx + SOCKET.NextPtr]
|
|
|
|
or ebx, ebx
|
2012-04-11 15:07:45 +02:00
|
|
|
jz .drop_with_reset_no_socket
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + SOCKET.Domain], AF_INET4
|
|
|
|
jne .socket_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + SOCKET.Protocol], IP_PROTO_TCP
|
|
|
|
jne .socket_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.LocalPort], si
|
|
|
|
jne .socket_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + IP_SOCKET.RemoteIP]
|
|
|
|
cmp eax, [edi] ; Ipv4 source addres
|
|
|
|
je @f
|
|
|
|
test eax, eax
|
|
|
|
jnz .socket_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov ax, [ebx + TCP_SOCKET.RemotePort]
|
|
|
|
cmp [edx + TCP_header.SourcePort], ax
|
|
|
|
je .found_socket
|
|
|
|
test ax, ax
|
|
|
|
jnz .socket_loop
|
|
|
|
.found_socket: ; ebx now contains the socketpointer
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: socket ptr=%x state=%u flags=%x\n", ebx, [ebx + TCP_SOCKET.t_state], [edx + TCP_header.Flags]:2
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;-------------
|
2012-07-26 16:54:57 +02:00
|
|
|
; update stats
|
2012-08-19 13:21:20 +02:00
|
|
|
|
2012-07-26 16:54:57 +02:00
|
|
|
inc [TCP_segments_rx] ; FIXME: correct interface?
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;----------------------------
|
|
|
|
; Check if socket isnt closed
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
|
2012-08-27 15:55:15 +02:00
|
|
|
je .drop_no_socket
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;----------------
|
|
|
|
; Lock the socket
|
|
|
|
|
2012-02-25 13:03:22 +01:00
|
|
|
pusha
|
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_lock
|
|
|
|
popa
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: socket locked\n"
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
;---------------------------
|
|
|
|
; disable all temporary bits
|
2012-07-27 01:21:35 +02:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
mov [ebx + TCP_SOCKET.temp_bits], 0
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;---------------------------------------
|
|
|
|
; unscale the window into a 32 bit value
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx eax, [edx + TCP_header.Window]
|
|
|
|
push ecx
|
|
|
|
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
|
|
|
|
shl eax, cl
|
|
|
|
mov dword [edx + TCP_header.Window], eax ; word after window is checksum, we dont need checksum anymore
|
|
|
|
pop ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;---------------------------------------
|
|
|
|
; Are we accepting incoming connections?
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [ebx + SOCKET.options], SO_ACCEPTCON
|
2012-08-19 13:21:20 +02:00
|
|
|
jnz .accept_connection
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;-------------------------------------
|
|
|
|
; Reset idle timer and keepalive timer
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_idle], 0
|
|
|
|
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;--------------------
|
|
|
|
; Process TCP options
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx eax, [edx + TCP_header.DataOffset]
|
|
|
|
cmp eax, sizeof.TCP_header ; Does header contain any options?
|
|
|
|
je .no_options
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Segment has options\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
|
|
|
|
jz .not_uni_xfer ; also no header prediction
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
add eax, edx
|
|
|
|
lea esi, [edx + sizeof.TCP_header]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.opt_loop:
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp esi, eax ; are we scanning outside of header?
|
|
|
|
jae .no_options
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi], TCP_OPT_EOL ; end of option list?
|
|
|
|
jz .no_options
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi], TCP_OPT_NOP ; nop ?
|
|
|
|
jz .opt_nop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi], TCP_OPT_MAXSEG
|
|
|
|
je .opt_maxseg
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi], TCP_OPT_WINDOW
|
|
|
|
je .opt_window
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi], TCP_OPT_TIMESTAMP
|
|
|
|
je .opt_timestamp
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
jmp .no_options ; If we reach here, some unknown options were received, skip them all!
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.opt_nop:
|
2012-08-19 13:21:20 +02:00
|
|
|
inc esi
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .opt_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.opt_maxseg:
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi+1], 4
|
2012-08-27 15:55:15 +02:00
|
|
|
jne .no_options ; error occured, ignore all options!
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz @f
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx eax, word[esi+2]
|
|
|
|
rol ax, 8
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_maxseg], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
@@:
|
2012-08-19 13:21:20 +02:00
|
|
|
add esi, 4
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .opt_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
.opt_window:
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp byte [esi+1], 3
|
|
|
|
jne .no_options
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz @f
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Got window option\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
;;;;;
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
2012-08-19 13:21:20 +02:00
|
|
|
add esi, 3
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .opt_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
.opt_timestamp:
|
2012-08-27 15:55:15 +02:00
|
|
|
cmp byte [esi+1], 10 ; length must be 10
|
2012-02-23 23:21:40 +01:00
|
|
|
jne .no_options
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Got timestamp option\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
push dword [esi + 2] ; timestamp
|
|
|
|
pop [ebx + TCP_SOCKET.ts_val]
|
|
|
|
push dword [esi + 6] ; timestamp echo reply
|
2012-08-19 13:21:20 +02:00
|
|
|
pop [ebx + TCP_SOCKET.ts_ecr]
|
2012-08-27 15:55:15 +02:00
|
|
|
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
add esi, 10
|
|
|
|
jmp .opt_loop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.no_options:
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------------
|
|
|
|
; Time to do some header prediction (Original Principle by Van Jacobson)
|
|
|
|
|
|
|
|
; There are two common cases for an uni-directional data transfer.
|
|
|
|
;
|
|
|
|
; General rule: the packets has no control flags, is in-sequence,
|
|
|
|
; window width didnt change and we're not retransmitting.
|
|
|
|
;
|
|
|
|
; Second rules:
|
|
|
|
; - If the length is 0 and the ACK moved forward, we're the sender side of the transfer.
|
|
|
|
; In this case we'll free the ACK'ed data and notify higher levels that we have free space in buffer
|
|
|
|
;
|
|
|
|
; - If the length is not 0 and the ACK didn't move, we're the receiver side of the transfer.
|
|
|
|
; If the packets are in order (data queue is empty), add the data to the socket buffer and request a delayed ACK
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
|
|
|
jnz .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN + TH_FIN + TH_RST + TH_URG
|
|
|
|
jnz .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
|
|
|
|
jne .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, dword [edx + TCP_header.Window]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_WND]
|
|
|
|
jne .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_NXT]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
jne .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;---------------------------------------
|
|
|
|
; check if we are sender in the uni-xfer
|
|
|
|
|
|
|
|
; If the following 4 conditions are all true, this segment is a pure ACK.
|
|
|
|
;
|
|
|
|
; - The segment contains no data.
|
2012-02-23 23:21:40 +01:00
|
|
|
test ecx, ecx
|
|
|
|
jnz .not_sender
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; - The congestion window is greater than or equal to the current send window.
|
|
|
|
; 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.
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_CWND]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_WND]
|
|
|
|
jb .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; - The acknowledgment field in the segment is less than or equal to the maximum sequence number sent.
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
ja .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; - The acknowledgment field in the segment is greater than the largest unacknowledged sequence number.
|
2012-02-23 23:21:40 +01:00
|
|
|
sub eax, [ebx + TCP_SOCKET.SND_UNA]
|
|
|
|
jbe .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Header prediction: we are sender\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;---------------------------------
|
|
|
|
; Packet is a pure ACK, process it
|
|
|
|
|
2011-01-24 23:01:54 +01:00
|
|
|
; Delete acknowledged bytes from send buffer
|
2012-02-23 23:21:40 +01:00
|
|
|
pusha
|
|
|
|
mov ecx, eax
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.snd]
|
|
|
|
call SOCKET_ring_free
|
|
|
|
popa
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
; Update RTT estimators
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
|
|
|
jz .no_timestamp_rtt
|
2012-08-28 00:47:10 +02:00
|
|
|
mov eax, [esp + 4+4] ; timestamp when this segment was received
|
2012-08-27 15:55:15 +02:00
|
|
|
sub eax, [ebx + TCP_SOCKET.ts_ecr]
|
|
|
|
inc eax
|
|
|
|
call TCP_xmit_timer
|
|
|
|
jmp .rtt_done
|
|
|
|
|
|
|
|
.no_timestamp_rtt:
|
|
|
|
cmp [ebx + TCP_SOCKET.t_rtt], 0
|
|
|
|
je .rtt_done
|
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
|
|
|
|
jbe .rtt_done
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_rtt]
|
|
|
|
call TCP_xmit_timer
|
2012-08-19 13:21:20 +02:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
.rtt_done:
|
2012-08-19 13:21:20 +02:00
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
; update window pointers
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_UNA], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Stop retransmit timer
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.timer_retransmission], 0
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Awaken waiting processes
|
2012-02-25 13:03:22 +01:00
|
|
|
pusha
|
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
|
|
|
popa
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_notify_owner
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2011-01-24 23:01:54 +01:00
|
|
|
; Generate more output
|
2012-02-23 23:21:40 +01:00
|
|
|
call TCP_output
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
jmp .drop_no_socket
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;-------------------------------------------------
|
|
|
|
; maybe we are the receiver in the uni-xfer then..
|
|
|
|
|
|
|
|
.not_sender:
|
|
|
|
; - The amount of data in the segment is greater than 0 (data count is in ecx)
|
|
|
|
|
|
|
|
; - The acknowledgment field equals the largest unacknowledged sequence number. This means no data is acknowledged by this segment.
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
|
|
|
|
jne .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; - The reassembly list of out-of-order segments for the connection is empty (seg_next equals tp).
|
|
|
|
|
|
|
|
;;; TODO
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
; jnz .not_uni_xfer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Complete processing of received data
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Header prediction: we are receiving %u bytes\n", ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
add [ebx + TCP_SOCKET.RCV_NXT], ecx ; Update sequence number with number of bytes we have copied
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx esi, [edx + TCP_header.DataOffset]
|
|
|
|
add esi, edx
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.rcv]
|
|
|
|
call SOCKET_ring_write ; Add the data to the socket buffer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_notify_owner
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
or [ebx + TCP_SOCKET.t_flags], TF_DELACK ; Set delayed ack flag
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;--------------------------------------------------
|
|
|
|
; Header prediction failed, do it the slow way
|
|
|
|
|
|
|
|
.not_uni_xfer:
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Header prediction failed\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Calculate receive window size
|
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
push edx
|
2012-08-27 15:55:15 +02:00
|
|
|
mov eax, SOCKETBUFFSIZE
|
|
|
|
sub eax, [ebx + STREAM_SOCKET.rcv.size]
|
|
|
|
mov edx, [ebx + TCP_SOCKET.RCV_ADV]
|
|
|
|
sub edx, [ebx + TCP_SOCKET.RCV_NXT]
|
|
|
|
cmp eax, edx
|
2012-08-28 00:47:10 +02:00
|
|
|
jg @f
|
2012-08-27 15:55:15 +02:00
|
|
|
mov eax, edx
|
|
|
|
@@:
|
2012-08-28 00:47:10 +02:00
|
|
|
DEBUGF 1,"Receive window size=%d\n", ax
|
2012-08-27 15:55:15 +02:00
|
|
|
mov [ebx + TCP_SOCKET.RCV_WND], ax
|
2012-08-28 00:47:10 +02:00
|
|
|
pop edx
|
2012-08-27 15:55:15 +02:00
|
|
|
|
|
|
|
; If listen or Syn sent, go to that specific code right away
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
|
|
|
|
je .LISTEN
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_SENT
|
|
|
|
je .SYN_SENT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: state is not listen or syn_sent\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;--------------------------------------------
|
|
|
|
; Protection Against Wrapped Sequence Numbers
|
|
|
|
|
|
|
|
; First, check if timestamp is present
|
|
|
|
|
2011-01-24 23:01:54 +01:00
|
|
|
;;;; TODO 602
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Then, check if at least some bytes of data are within window
|
|
|
|
|
|
|
|
;;;; TODO
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;----------------------------
|
|
|
|
; trim any data not in window
|
|
|
|
|
|
|
|
; check for duplicate data at beginning of segment
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.RCV_NXT]
|
|
|
|
sub eax, [edx + TCP_header.SequenceNumber]
|
2012-08-28 00:47:10 +02:00
|
|
|
jle .no_duplicate
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: %u bytes duplicate data!\n", eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz .no_dup_syn
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
DEBUGF 1,"TCP_input: got duplicate syn\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
and [edx + TCP_header.Flags], not (TH_SYN)
|
|
|
|
inc [edx + TCP_header.SequenceNumber]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [edx + TCP_header.UrgentPointer], 1
|
|
|
|
jbe @f
|
|
|
|
dec [edx + TCP_header.UrgentPointer]
|
|
|
|
jmp .dup_syn
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
and [edx + TCP_header.Flags], not (TH_URG)
|
2011-02-03 22:35:16 +01:00
|
|
|
.dup_syn:
|
2012-02-23 23:21:40 +01:00
|
|
|
dec eax
|
2011-01-24 23:01:54 +01:00
|
|
|
.no_dup_syn:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; Check for entire duplicate segment
|
|
|
|
cmp eax, ecx ; eax holds number of bytes to drop, ecx is data size
|
|
|
|
jb .duplicate
|
|
|
|
jnz @f
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_FIN
|
2012-08-27 15:55:15 +02:00
|
|
|
jnz .duplicate
|
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; Any valid FIN must be to the left of the window.
|
|
|
|
; At this point the FIN must be out of sequence or a duplicate, drop it
|
2012-02-23 23:21:40 +01:00
|
|
|
and [edx + TCP_header.Flags], not TH_FIN
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; send an ACK and resynchronize and drop any data.
|
|
|
|
; But keep on processing for RST or ACK
|
|
|
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
mov eax, ecx
|
|
|
|
;TODO: update stats
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;-----------------------------------------------
|
|
|
|
; Remove duplicate data and update urgent offset
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
.duplicate:
|
|
|
|
;;; TODO: 677
|
2012-02-23 23:21:40 +01:00
|
|
|
add [edx + TCP_header.SequenceNumber], eax
|
2012-08-27 15:55:15 +02:00
|
|
|
sub ecx, eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
sub [edx + TCP_header.UrgentPointer], ax
|
2012-08-28 00:47:10 +02:00
|
|
|
jg @f
|
2012-02-23 23:21:40 +01:00
|
|
|
and [edx + TCP_header.Flags], not (TH_URG)
|
|
|
|
mov [edx + TCP_header.UrgentPointer], 0
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
|
|
|
|
|
|
|
;--------------------------------------------------
|
|
|
|
; Handle data that arrives after process terminates
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
.no_duplicate:
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + SOCKET.PID], 0
|
2012-08-27 15:55:15 +02:00
|
|
|
jne .not_terminated
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
|
2012-08-27 15:55:15 +02:00
|
|
|
jbe .not_terminated
|
2012-02-23 23:21:40 +01:00
|
|
|
test ecx, ecx
|
2012-08-27 15:55:15 +02:00
|
|
|
jz .not_terminated
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
mov eax, ebx
|
|
|
|
call TCP_close
|
|
|
|
;;;TODO: update stats
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .drop_with_reset
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;----------------------------------------
|
2012-08-27 15:55:15 +02:00
|
|
|
; Remove data beyond right edge of window (700-736)
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
.not_terminated:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
add eax, ecx
|
|
|
|
sub eax, [ebx + TCP_SOCKET.RCV_NXT]
|
2012-08-27 15:55:15 +02:00
|
|
|
sub ax, [ebx + TCP_SOCKET.RCV_WND] ; eax now holds the number of bytes to drop
|
2012-08-28 00:47:10 +02:00
|
|
|
jle .no_excess_data
|
|
|
|
|
|
|
|
DEBUGF 1,"%d bytes beyond right edge of window\n", eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;;; TODO: update stats
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp eax, ecx
|
2012-08-28 00:47:10 +02:00
|
|
|
jl .dont_drop_all
|
2012-08-27 15:55:15 +02:00
|
|
|
; If a new connection request is received while in TIME_WAIT, drop the old connection and start over,
|
|
|
|
; if the sequence numbers are above the previous ones
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz .no_new_request
|
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
jne .no_new_request
|
2012-08-28 00:47:10 +02:00
|
|
|
; mov edx, [ebx + TCP_SOCKET.RCV_NXT]
|
|
|
|
; cmp edx, [edx + TCP_header.SequenceNumber]
|
|
|
|
; add edx, 64000 ; TCP_ISSINCR FIXME
|
2012-08-27 15:55:15 +02:00
|
|
|
mov eax, ebx
|
|
|
|
call TCP_close
|
|
|
|
jmp .findpcb ; FIXME: skip code for unscaling window, ...
|
|
|
|
.no_new_request:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; If window is closed can only take segments at window edge, and have to drop data and PUSH from
|
|
|
|
; incoming segments. Continue processing, but remember to ACK. Otherwise drop segment and ACK
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
cmp [ebx + TCP_SOCKET.RCV_WND], 0
|
|
|
|
jne .drop_after_ack
|
|
|
|
mov eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.RCV_NXT]
|
|
|
|
jne .drop_after_ack
|
|
|
|
|
|
|
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
;;; TODO: update stats
|
|
|
|
jmp .no_excess_data
|
|
|
|
.dont_drop_all:
|
|
|
|
;;; TODO: update stats
|
|
|
|
;;; TODO: 733
|
|
|
|
sub ecx, eax
|
|
|
|
and [ebx + TCP_SOCKET.t_flags], not (TH_PUSH or TH_FIN)
|
2011-01-08 15:59:21 +01:00
|
|
|
.no_excess_data:
|
|
|
|
|
|
|
|
;-----------------
|
2012-08-27 15:55:15 +02:00
|
|
|
; Record timestamp (737-746) TODO
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; If last ACK falls within this segments sequence numbers, record its timestamp
|
|
|
|
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
|
|
|
jz .no_timestamp
|
|
|
|
mov eax, [ebx + TCP_SOCKET.last_ack_sent]
|
|
|
|
sub eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
jb .no_timestamp
|
|
|
|
test [ebx + TCP_header.Flags], TH_SYN or TH_FIN ; syn and fin occupy one byte
|
|
|
|
jz @f
|
|
|
|
dec eax
|
|
|
|
@@:
|
|
|
|
sub eax, ecx
|
|
|
|
jae .no_timestamp
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
mov eax, [esp + 4+4] ; tcp_now
|
2012-08-27 15:55:15 +02:00
|
|
|
mov [ebx + TCP_SOCKET.ts_recent_age], eax
|
|
|
|
mov eax, [ebx + TCP_SOCKET.ts_val]
|
|
|
|
mov [ebx + TCP_SOCKET.ts_recent], eax
|
|
|
|
.no_timestamp:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;------------------
|
|
|
|
; Process RST flags
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
2012-07-27 01:21:35 +02:00
|
|
|
jz .no_rst
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Got an RST flag\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.t_state]
|
|
|
|
shl eax, 2
|
|
|
|
jmp dword [eax + .rst_sw_list]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.rst_sw_list:
|
2012-07-27 01:21:35 +02:00
|
|
|
dd .no_rst ; TCPS_CLOSED
|
|
|
|
dd .no_rst ; TCPS_LISTEN
|
|
|
|
dd .no_rst ; TCPS_SYN_SENT
|
|
|
|
dd .econnrefused ; TCPS_SYN_RECEIVED
|
|
|
|
dd .econnreset ; TCPS_ESTABLISHED
|
|
|
|
dd .econnreset ; TCPS_CLOSE_WAIT
|
|
|
|
dd .econnreset ; TCPS_FIN_WAIT_1
|
|
|
|
dd .rst_close ; TCPS_CLOSING
|
|
|
|
dd .rst_close ; TCPS_LAST_ACK
|
|
|
|
dd .econnreset ; TCPS_FIN_WAIT_2
|
|
|
|
dd .rst_close ; TCPS_TIMED_WAIT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.econnrefused:
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Connection refused\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + SOCKET.errorcode], ECONNREFUSED
|
|
|
|
jmp .close
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.econnreset:
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Connection reset\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + SOCKET.errorcode], ECONNRESET
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-19 15:17:11 +02:00
|
|
|
.close:
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Closing connection\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSED
|
2012-08-27 15:55:15 +02:00
|
|
|
;;; TODO: update stats (tcp drops)
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call TCP_close
|
|
|
|
jmp .drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.rst_close:
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Closing with reset\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call TCP_close
|
|
|
|
jmp .drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
.no_rst:
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
;--------------------------------------
|
|
|
|
; handle SYN-full and ACK-less segments
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
2012-08-27 15:55:15 +02:00
|
|
|
jz .not_syn_full
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
mov ebx, ECONNRESET
|
|
|
|
call TCP_drop
|
|
|
|
jmp .drop_with_reset
|
2012-08-27 15:55:15 +02:00
|
|
|
.not_syn_full:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;---------------
|
|
|
|
; ACK processing
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .drop
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
|
2012-08-27 15:55:15 +02:00
|
|
|
jb .ack_processed ; states: closed, listen, syn_sent
|
|
|
|
ja .no_syn_rcv ; established, fin_wait_1, fin_wait_2, close_wait, closing, last_ack, time_wait
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: state=syn_received\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp [ebx + TCP_SOCKET.SND_UNA], eax
|
|
|
|
ja .drop_with_reset
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
ja .drop_with_reset
|
2011-02-03 22:35:16 +01:00
|
|
|
|
2011-11-12 20:20:33 +01:00
|
|
|
;;; TODO: update stats
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_is_connected
|
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
2011-02-01 18:00:04 +01:00
|
|
|
|
|
|
|
; Do window scaling?
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
|
|
|
|
jz @f
|
|
|
|
test [ebx + TCP_SOCKET.t_flags], TF_REQ_SCALE
|
|
|
|
jz @f
|
2011-02-01 18:00:04 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push word [ebx + TCP_SOCKET.requested_s_scale] ; Set send and receive scale factors to the received values
|
|
|
|
pop word [ebx + TCP_SOCKET.SND_SCALE]
|
2011-02-01 18:00:04 +01:00
|
|
|
@@:
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
;;; TODO: call TCP_reassemble
|
2011-02-01 18:00:04 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
dec eax
|
|
|
|
mov [ebx + TCP_SOCKET.SND_WL1], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.no_syn_rcv:
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
;-------------------------
|
|
|
|
; check for duplicate ACKs
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
|
|
|
|
ja .not_dup_ack
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test ecx, ecx
|
|
|
|
jnz .reset_dupacks
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, dword [edx + TCP_header.Window]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_WND]
|
|
|
|
jne .reset_dupacks
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Processing duplicate ACK\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; If we have outstanidn data, other than a window probe, this is a completely duplicate ACK
|
|
|
|
; (window info didnt change) The ACK is the biggest we've seen and we've seen exactly our rexmt threshold of them,
|
|
|
|
; assume a packet has been dropped and retransmit it. Kludge snd_nxt & the congestion window so we send only this one packet.
|
|
|
|
|
|
|
|
cmp [ebx + TCP_SOCKET.timer_retransmission], 0 ;;;; FIXME
|
|
|
|
jg @f
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_UNA]
|
|
|
|
je .dup_ack
|
2011-01-24 23:01:54 +01:00
|
|
|
|
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_dupacks], 0
|
|
|
|
jmp .not_dup_ack
|
2011-01-24 23:01:54 +01:00
|
|
|
|
|
|
|
.dup_ack:
|
2012-02-23 23:21:40 +01:00
|
|
|
inc [ebx + TCP_SOCKET.t_dupacks]
|
|
|
|
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
|
|
|
|
jne .no_re_xmit
|
|
|
|
|
|
|
|
push [ebx + TCP_SOCKET.SND_NXT] ; >>>>
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_WND]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
|
2012-07-13 15:29:28 +02:00
|
|
|
cmova eax, [ebx + TCP_SOCKET.SND_CWND]
|
2012-02-23 23:21:40 +01:00
|
|
|
shr eax, 1
|
|
|
|
push edx
|
|
|
|
xor edx, edx
|
|
|
|
div [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
cmp eax, 2
|
2012-08-27 15:55:15 +02:00
|
|
|
ja @f
|
|
|
|
xor eax, eax
|
|
|
|
mov al, 2
|
2011-01-24 23:01:54 +01:00
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
mul [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
pop edx
|
|
|
|
mov [ebx + TCP_SOCKET.SND_SSTHRESH], eax
|
|
|
|
|
|
|
|
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; turn off retransmission timer
|
|
|
|
mov [ebx + TCP_SOCKET.t_rtt], 0
|
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_NXT], eax
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_CWND], eax
|
|
|
|
|
|
|
|
mov eax, ebx
|
|
|
|
call TCP_output ; retransmit missing segment
|
|
|
|
|
|
|
|
push edx
|
|
|
|
xor edx, edx
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
mul [ebx + TCP_SOCKET.t_dupacks]
|
|
|
|
pop edx
|
|
|
|
add eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_CWND], eax
|
|
|
|
|
|
|
|
pop eax ; <<<<
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
|
|
|
|
jb @f
|
|
|
|
mov [ebx + TCP_SOCKET.SND_NXT], eax
|
2011-01-24 23:01:54 +01:00
|
|
|
@@:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
2011-01-24 23:01:54 +01:00
|
|
|
.no_re_xmit:
|
2012-02-23 23:21:40 +01:00
|
|
|
jbe .not_dup_ack
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Increasing congestion window\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
add [ebx + TCP_SOCKET.SND_CWND], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call TCP_output
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
2011-01-24 23:01:54 +01:00
|
|
|
.not_dup_ack:
|
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
;-------------------------------------------------
|
|
|
|
; If the congestion window was inflated to account
|
|
|
|
; for the other side's cached packets, retract it
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_SSTHRESH]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_CWND]
|
|
|
|
ja @f
|
|
|
|
cmp [ebx + TCP_SOCKET.t_dupacks], TCP_re_xmit_thresh
|
|
|
|
jbe @f
|
|
|
|
mov [ebx + TCP_SOCKET.SND_CWND], eax
|
2011-01-24 23:01:54 +01:00
|
|
|
@@:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_dupacks], 0
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
jbe @f
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
;;; TODO: update stats
|
|
|
|
jmp .drop_after_ack
|
2011-01-24 23:01:54 +01:00
|
|
|
|
|
|
|
@@:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov edi, [edx + TCP_header.AckNumber]
|
|
|
|
sub edi, [ebx + TCP_SOCKET.SND_UNA] ; now we got the number of acked bytes in edi
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
;;; TODO: update stats
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: acceptable ACK for %u bytes\n", edi
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;------------------------------------------
|
2012-08-27 15:55:15 +02:00
|
|
|
; RTT measurements and retransmission timer (912-926)
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; If we have a timestamp, update smoothed RTT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
|
|
|
|
jne .timestamp_not_present
|
2012-08-28 00:47:10 +02:00
|
|
|
mov eax, [esp+4+4]
|
2012-08-27 15:55:15 +02:00
|
|
|
sub eax, [ebx + TCP_SOCKET.ts_ecr]
|
|
|
|
inc eax
|
|
|
|
call TCP_xmit_timer
|
|
|
|
jmp .rtt_done_
|
|
|
|
|
|
|
|
; If no timestamp but transmit timer is running and timed sequence number was acked,
|
|
|
|
; update smoothed RTT. Since we now have an RTT measurement, cancel the timer backoff
|
|
|
|
; (Phil Karn's retransmit algo)
|
|
|
|
; Recompute the initial retransmit timer
|
|
|
|
|
|
|
|
.timestamp_not_present:
|
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.t_rtseq]
|
|
|
|
jbe .rtt_done_
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_rtt]
|
|
|
|
test eax, eax
|
|
|
|
jz .rtt_done_
|
|
|
|
call TCP_xmit_timer
|
|
|
|
|
|
|
|
.rtt_done_:
|
|
|
|
|
|
|
|
; If all outstanding data is acked, stop retransmit timer and remember to restart (more output or persist)
|
|
|
|
; If there is more data to be acked, restart retransmit timer, using current (possible backed-off) value.
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
cmp eax, [edx + TCP_header.AckNumber]
|
2012-08-27 15:55:15 +02:00
|
|
|
jne .more_data
|
|
|
|
mov [ebx + TCP_SOCKET.timer_retransmission], 0
|
|
|
|
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
|
|
|
|
jmp .no_restart
|
|
|
|
.more_data:
|
|
|
|
cmp [ebx + TCP_SOCKET.timer_persist], 0
|
|
|
|
jne .no_restart
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_rxtcur]
|
|
|
|
mov [ebx + TCP_SOCKET.timer_retransmission], ax
|
|
|
|
|
|
|
|
.no_restart:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
;-------------------------------------------
|
|
|
|
; Open congestion window in response to ACKs
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov esi, [ebx + TCP_SOCKET.SND_CWND]
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_maxseg]
|
|
|
|
|
|
|
|
cmp esi, [ebx + TCP_SOCKET.SND_SSTHRESH]
|
|
|
|
jbe @f
|
|
|
|
push edx
|
|
|
|
push eax
|
|
|
|
mul eax
|
|
|
|
div esi
|
|
|
|
pop edx
|
|
|
|
shr edx, 3
|
|
|
|
add eax, edx
|
|
|
|
pop edx
|
2011-01-24 23:01:54 +01:00
|
|
|
@@:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
add esi, eax
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push ecx
|
|
|
|
mov cl, [ebx + TCP_SOCKET.SND_SCALE]
|
|
|
|
mov eax, TCP_max_win
|
|
|
|
shl eax, cl
|
|
|
|
pop ecx
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp esi, eax
|
2012-07-13 15:29:28 +02:00
|
|
|
cmova esi, eax
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.SND_CWND], esi
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
;------------------------------------------
|
|
|
|
; Remove acknowledged data from send buffer
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
cmp edi, [ebx + STREAM_SOCKET.snd.size]
|
|
|
|
jbe .finiacked
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
push ecx edx ebx
|
|
|
|
mov ecx, [ebx + STREAM_SOCKET.snd.size]
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.snd]
|
|
|
|
sub [ebx + TCP_SOCKET.SND_WND], ecx
|
|
|
|
call SOCKET_ring_free
|
|
|
|
pop ebx edx ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: our FIN is acked\n"
|
|
|
|
stc
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
jmp .wakeup
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
.finiacked:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push ecx edx ebx
|
|
|
|
mov ecx, edi
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.snd]
|
|
|
|
call SOCKET_ring_free
|
|
|
|
pop ebx
|
|
|
|
sub [ebx + TCP_SOCKET.SND_WND], ecx
|
|
|
|
pop edx ecx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: our FIN is not acked\n"
|
|
|
|
clc
|
|
|
|
|
|
|
|
;----------------------------------------
|
2011-01-08 15:59:21 +01:00
|
|
|
; Wake up process waiting on send buffer
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
.wakeup:
|
|
|
|
|
|
|
|
pushf
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_notify_owner
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2011-02-01 18:00:04 +01:00
|
|
|
; Update TCPS
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_UNA], eax
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
|
|
|
|
jb @f
|
|
|
|
mov [ebx + TCP_SOCKET.SND_NXT], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
popf
|
2011-01-24 23:01:54 +01:00
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
; General ACK handling complete
|
|
|
|
; Now do the state-specific ones
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.t_state]
|
|
|
|
jmp dword [eax*4 + .ACK_sw_list]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.ACK_sw_list:
|
2012-07-27 01:21:35 +02:00
|
|
|
dd .ack_processed ; TCPS_CLOSED
|
|
|
|
dd .ack_processed ; TCPS_LISTEN
|
|
|
|
dd .ack_processed ; TCPS_SYN_SENT
|
|
|
|
dd .ack_processed ; TCPS_SYN_RECEIVED
|
|
|
|
dd .ack_processed ; TCPS_ESTABLISHED
|
|
|
|
dd .ack_processed ; TCPS_CLOSE_WAIT
|
|
|
|
dd .ack_fw1 ; TCPS_FIN_WAIT_1
|
|
|
|
dd .ack_c ; TCPS_CLOSING
|
|
|
|
dd .ack_la ; TCPS_LAST_ACK
|
|
|
|
dd .ack_processed ; TCPS_FIN_WAIT_2
|
|
|
|
dd .ack_tw ; TCPS_TIMED_WAIT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
2011-01-28 17:16:31 +01:00
|
|
|
.ack_fw1:
|
2012-07-27 01:21:35 +02:00
|
|
|
jnc .ack_processed
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [ebx + SOCKET.state], SS_CANTRCVMORE
|
|
|
|
jnz @f
|
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_is_disconnected
|
2012-08-27 15:55:15 +02:00
|
|
|
mov [ebx + TCP_SOCKET.timer_timed_wait], TCP_time_max_idle
|
2011-01-28 17:16:31 +01:00
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_FIN_WAIT_2
|
|
|
|
jmp .ack_processed
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2011-01-28 17:16:31 +01:00
|
|
|
.ack_c:
|
2012-07-27 01:21:35 +02:00
|
|
|
jnc .ack_processed
|
2011-01-28 17:16:31 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
mov eax, ebx
|
|
|
|
call TCP_cancel_timers
|
|
|
|
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
|
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_is_disconnected
|
|
|
|
jmp .ack_processed
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2011-01-28 17:16:31 +01:00
|
|
|
.ack_la:
|
2012-07-27 01:21:35 +02:00
|
|
|
jnc .ack_processed
|
2011-01-28 17:16:31 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
2012-07-19 15:17:11 +02:00
|
|
|
call TCP_disconnect
|
2012-02-23 23:21:40 +01:00
|
|
|
jmp .drop
|
2011-01-28 17:16:31 +01:00
|
|
|
|
|
|
|
.ack_tw:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
|
|
|
|
jmp .drop_after_ack
|
2011-01-28 17:16:31 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
.reset_dupacks: ; We got a new ACK, reset duplicate ACK counter
|
|
|
|
mov [ebx + TCP_SOCKET.t_dupacks], 0
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .ack_processed
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;-------------
|
|
|
|
; Passive Open
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
align 4
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.accept_connection:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
DEBUGF 1,"TCP_input: Accepting new connection\n"
|
|
|
|
|
|
|
|
pusha
|
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
|
|
|
popa
|
|
|
|
|
|
|
|
push ecx edx esi edi ;;;
|
|
|
|
call SOCKET_fork
|
|
|
|
pop edi esi edx ecx
|
|
|
|
|
|
|
|
test eax, eax
|
|
|
|
jz .drop
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
mov [eax + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
push dword [edi + 4] ; Ipv4 destination addres
|
|
|
|
pop [eax + IP_SOCKET.LocalIP]
|
|
|
|
|
|
|
|
push [edx + TCP_header.DestinationPort]
|
|
|
|
pop [eax + TCP_SOCKET.LocalPort]
|
|
|
|
|
|
|
|
mov [eax + TCP_SOCKET.t_state], TCPS_LISTEN
|
|
|
|
mov ebx, eax
|
|
|
|
|
|
|
|
.LISTEN:
|
|
|
|
|
|
|
|
DEBUGF 1,"TCP_input: state=listen\n"
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
2012-08-19 13:21:20 +02:00
|
|
|
jnz .drop
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jnz .drop_with_reset
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz .drop
|
|
|
|
|
|
|
|
;;; TODO: check if it's a broadcast or multicast, and drop if so
|
|
|
|
|
|
|
|
push dword [edi] ; Ipv4 source addres
|
|
|
|
pop [ebx + IP_SOCKET.RemoteIP]
|
|
|
|
|
|
|
|
push [edx + TCP_header.SourcePort]
|
|
|
|
pop [ebx + TCP_SOCKET.RemotePort]
|
|
|
|
|
|
|
|
push [edx + TCP_header.SequenceNumber]
|
|
|
|
pop [ebx + TCP_SOCKET.IRS]
|
|
|
|
|
|
|
|
mov eax, [TCP_sequence_num]
|
|
|
|
add [TCP_sequence_num], 64000 / 2
|
|
|
|
mov [ebx + TCP_SOCKET.ISS], eax
|
|
|
|
mov [ebx + TCP_SOCKET.SND_NXT], eax
|
|
|
|
|
|
|
|
TCP_sendseqinit ebx
|
|
|
|
TCP_rcvseqinit ebx
|
|
|
|
|
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
|
|
|
|
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
mov [ebx + TCP_SOCKET.timer_keepalive], TCP_time_keep_interval ;;;; macro
|
|
|
|
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.snd]
|
|
|
|
call SOCKET_ring_create
|
|
|
|
|
|
|
|
lea eax, [ebx + STREAM_SOCKET.rcv]
|
|
|
|
call SOCKET_ring_create
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
and [ebx + TCP_SOCKET.temp_bits], not TCP_BIT_DROPSOCKET
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;;; call SOCKET_notify_owner
|
|
|
|
|
|
|
|
jmp .trim_then_step6
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;------------
|
|
|
|
; Active Open
|
|
|
|
|
|
|
|
align 4
|
2012-08-27 15:55:15 +02:00
|
|
|
.SYN_SENT:
|
2012-08-19 13:21:20 +02:00
|
|
|
|
|
|
|
DEBUGF 1,"TCP_input: state=syn_sent\n"
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz @f
|
|
|
|
|
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.ISS]
|
|
|
|
jbe .drop_with_reset
|
|
|
|
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_MAX]
|
|
|
|
ja .drop_with_reset
|
|
|
|
@@:
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
|
|
|
jz @f
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .drop
|
|
|
|
|
|
|
|
mov eax, ebx
|
|
|
|
mov ebx, ECONNREFUSED
|
|
|
|
call TCP_drop
|
|
|
|
|
|
|
|
jmp .drop
|
|
|
|
@@:
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jz .drop
|
|
|
|
|
|
|
|
; at this point, segment seems to be valid
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .no_syn_ack
|
|
|
|
|
|
|
|
; now, process received SYN in response to an active open
|
|
|
|
|
|
|
|
mov eax, [edx + TCP_header.AckNumber]
|
|
|
|
mov [ebx + TCP_SOCKET.SND_UNA], eax
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_NXT]
|
|
|
|
jbe @f
|
|
|
|
mov [ebx + TCP_SOCKET.SND_NXT], eax
|
|
|
|
@@:
|
|
|
|
|
|
|
|
.no_syn_ack:
|
|
|
|
mov [ebx + TCP_SOCKET.timer_retransmission], 0 ; disable retransmission
|
|
|
|
|
|
|
|
push [edx + TCP_header.SequenceNumber]
|
|
|
|
pop [ebx + TCP_SOCKET.IRS]
|
|
|
|
|
|
|
|
TCP_rcvseqinit ebx
|
|
|
|
|
|
|
|
or [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_UNA]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.ISS]
|
|
|
|
jbe .simultaneous_open
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .simultaneous_open
|
|
|
|
|
|
|
|
DEBUGF 1,"TCP_input: active open\n"
|
|
|
|
|
|
|
|
;;; TODO: update stats
|
|
|
|
|
|
|
|
; set socket state to connected
|
|
|
|
mov [ebx + SOCKET.state], SS_ISCONNECTED
|
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_ESTABLISHED
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
; Do window scaling on this connection ?
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_flags]
|
|
|
|
and eax, TF_REQ_SCALE or TF_RCVD_SCALE
|
|
|
|
cmp eax, TF_REQ_SCALE or TF_RCVD_SCALE
|
|
|
|
jne .no_scaling
|
2012-08-19 13:21:20 +02:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
mov ax, word [ebx + TCP_SOCKET.requested_s_scale]
|
|
|
|
mov word [ebx + TCP_SOCKET.SND_SCALE], ax
|
|
|
|
.no_scaling:
|
2012-08-19 13:21:20 +02:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
;;; TODO: reassemble packets queue
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.t_rtt]
|
|
|
|
test eax, eax
|
|
|
|
je .trim_then_step6
|
|
|
|
call TCP_xmit_timer
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .trim_then_step6
|
|
|
|
|
|
|
|
.simultaneous_open:
|
|
|
|
|
|
|
|
DEBUGF 1,"TCP_input: simultaneous open\n"
|
|
|
|
; We have received a syn but no ACK, so we are having a simultaneous open..
|
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
|
|
|
|
|
|
|
|
;-------------------------------------
|
|
|
|
; Common processing for receipt of SYN
|
|
|
|
|
|
|
|
.trim_then_step6:
|
|
|
|
|
|
|
|
inc [edx + TCP_header.SequenceNumber]
|
|
|
|
|
|
|
|
;;; TODO: Drop any received data that follows receive window (590)
|
|
|
|
|
|
|
|
mov eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
mov [ebx + TCP_SOCKET.RCV_UP], eax
|
|
|
|
dec eax
|
|
|
|
mov [ebx + TCP_SOCKET.SND_WL1], eax
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.ack_processed: ; (step 6)
|
|
|
|
|
|
|
|
DEBUGF 1,"TCP_input: ACK processed\n"
|
|
|
|
|
|
|
|
;----------------------------------------------
|
|
|
|
; check if we need to update window information
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jz .no_window_update
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_WL1]
|
|
|
|
cmp eax, [edx + TCP_header.SequenceNumber]
|
|
|
|
jb .update_window
|
|
|
|
ja @f
|
|
|
|
|
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_WL2]
|
|
|
|
cmp eax, [edx + TCP_header.AckNumber]
|
|
|
|
jb .update_window
|
2012-02-23 23:21:40 +01:00
|
|
|
ja .no_window_update
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.SND_WL2]
|
|
|
|
cmp eax, [edx + TCP_header.AckNumber]
|
|
|
|
jne .no_window_update
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, dword [edx + TCP_header.Window]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.SND_WND]
|
|
|
|
jbe .no_window_update
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.update_window:
|
|
|
|
|
2012-04-14 20:20:01 +02:00
|
|
|
;;; TODO: Keep track of pure window updates
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, dword [edx + TCP_header.Window]
|
|
|
|
cmp eax, [ebx + TCP_SOCKET.max_sndwnd]
|
|
|
|
jbe @f
|
|
|
|
mov [ebx + TCP_SOCKET.max_sndwnd], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
@@:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.SND_WND], eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Updating window to %u\n", eax
|
2012-04-14 20:20:01 +02:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push [edx + TCP_header.SequenceNumber]
|
|
|
|
pop [ebx + TCP_SOCKET.SND_WL1]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
push [edx + TCP_header.AckNumber]
|
|
|
|
pop [ebx + TCP_SOCKET.SND_WL2]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.no_window_update:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;-----------------
|
|
|
|
; process URG flag
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_URG
|
|
|
|
jz .not_urgent
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [edx + TCP_header.UrgentPointer], 0
|
|
|
|
jz .not_urgent
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
je .not_urgent
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
; Ignore bogus urgent offsets
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
;;; 1040-1050
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
movzx eax, [edx + TCP_header.UrgentPointer]
|
|
|
|
add eax, [ebx + STREAM_SOCKET.rcv.size]
|
|
|
|
cmp eax, SOCKET_MAXDATA
|
|
|
|
jbe .not_urgent
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [edx + TCP_header.UrgentPointer], 0
|
|
|
|
and [edx + TCP_header.Flags], not (TH_URG)
|
|
|
|
jmp .do_data
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.not_urgent:
|
|
|
|
|
|
|
|
; processing of received urgent pointer
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
;;; TODO (1051-1093)
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
;---------------------------------------
|
|
|
|
; process the data in the segment (1094)
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.do_data:
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
jae .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test [edx + TCP_header.Flags], TH_FIN
|
2012-07-27 01:21:35 +02:00
|
|
|
jnz @f
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
test ecx, ecx
|
2012-07-27 01:21:35 +02:00
|
|
|
jnz .final_processing
|
|
|
|
@@:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
; call TCP_reassemble ;;; TODO
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
;---------------
|
|
|
|
; FIN processing
|
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_FIN
|
2012-08-19 13:21:20 +02:00
|
|
|
jz .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Processing FIN\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
cmp [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
jae .not_first_fin
|
2011-01-29 00:07:25 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: First FIN for this connection\n"
|
2011-01-29 00:07:25 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_cant_recv_more
|
2011-01-29 00:07:25 +01:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
inc [ebx + TCP_SOCKET.RCV_NXT]
|
2011-01-29 00:07:25 +01:00
|
|
|
|
|
|
|
.not_first_fin:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov eax, [ebx + TCP_SOCKET.t_state]
|
|
|
|
shl eax, 2
|
|
|
|
jmp dword [eax + .FIN_sw_list]
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.FIN_sw_list:
|
2012-08-27 15:55:15 +02:00
|
|
|
dd .final_processing ; TCPS_CLOSED
|
|
|
|
dd .final_processing ; TCPS_LISTEN
|
|
|
|
dd .final_processing ; TCPS_SYN_SENT
|
|
|
|
dd .fin_syn_est ; TCPS_SYN_RECEIVED
|
|
|
|
dd .fin_syn_est ; TCPS_ESTABLISHED
|
|
|
|
dd .final_processing ; TCPS_CLOSE_WAIT
|
|
|
|
dd .fin_wait1 ; TCPS_FIN_WAIT_1
|
|
|
|
dd .final_processing ; TCPS_CLOSING
|
|
|
|
dd .final_processing ; TCPS_LAST_ACK
|
|
|
|
dd .fin_wait2 ; TCPS_FIN_WAIT_2
|
|
|
|
dd .fin_timed ; TCPS_TIMED_WAIT
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.fin_syn_est:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSE_WAIT
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.fin_wait1:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_CLOSING
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.fin_wait2:
|
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.t_state], TCPS_TIMED_WAIT
|
|
|
|
mov eax, ebx
|
|
|
|
call TCP_cancel_timers
|
|
|
|
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
|
|
|
|
call SOCKET_is_disconnected
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.fin_timed:
|
2012-02-23 23:21:40 +01:00
|
|
|
mov [ebx + TCP_SOCKET.timer_timed_wait], 2 * TCP_time_MSL
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .final_processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.drop_after_ack:
|
|
|
|
DEBUGF 1,"TCP_input: Drop after ACK\n"
|
2012-07-27 01:21:35 +02:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
push edx ebx
|
2012-07-27 01:21:35 +02:00
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
2012-08-19 13:21:20 +02:00
|
|
|
pop eax edx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
|
|
|
jnz .dumpit
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
or [eax + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
jmp .need_output
|
2012-07-27 01:21:35 +02:00
|
|
|
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.drop_with_reset:
|
|
|
|
DEBUGF 1,"TCP_input: Drop with reset\n"
|
|
|
|
|
|
|
|
push ebx edx
|
2012-02-25 13:03:22 +01:00
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
2012-08-19 13:21:20 +02:00
|
|
|
pop edx ebx
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
|
|
|
jnz .dumpit
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;;; if its a multicast/broadcast, also drop
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jnz .respond_ack
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jnz .respond_syn
|
|
|
|
jmp .dumpit
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
;-----------------
|
|
|
|
; Final processing
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.final_processing:
|
|
|
|
DEBUGF 1,"TCP_input: Final processing\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
push ebx
|
2012-02-25 13:03:22 +01:00
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
2012-08-19 13:21:20 +02:00
|
|
|
pop eax
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [eax + TCP_SOCKET.temp_bits], TCP_BIT_NEEDOUTPUT
|
|
|
|
jnz .need_output
|
2012-08-19 13:21:20 +02:00
|
|
|
|
|
|
|
test [eax + TCP_SOCKET.t_flags], TF_ACKNOW
|
|
|
|
jz .dumpit
|
|
|
|
DEBUGF 1,"TCP_input: ACK now!\n"
|
|
|
|
|
|
|
|
.need_output:
|
2012-02-23 23:21:40 +01:00
|
|
|
call TCP_output
|
2012-08-19 13:21:20 +02:00
|
|
|
|
|
|
|
.dumpit:
|
|
|
|
DEBUGF 1,"TCP_input: dumping\n"
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
popf
|
2012-02-23 23:21:40 +01:00
|
|
|
call kernel_free
|
|
|
|
add esp, 4
|
2012-08-28 00:47:10 +02:00
|
|
|
|
2012-02-23 23:21:40 +01:00
|
|
|
ret
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
.respond_ack:
|
2012-02-23 23:21:40 +01:00
|
|
|
push ebx
|
|
|
|
mov cl, TH_RST
|
|
|
|
call TCP_respond_socket
|
|
|
|
pop ebx
|
|
|
|
jmp .destroy_new_socket
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
.respond_syn:
|
2012-02-23 23:21:40 +01:00
|
|
|
push ebx
|
|
|
|
mov cl, TH_RST + TH_ACK
|
|
|
|
call TCP_respond_socket
|
|
|
|
pop ebx
|
|
|
|
jmp .destroy_new_socket
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;-----
|
|
|
|
; Drop
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.drop:
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
DEBUGF 1,"TCP_input: Dropping packet\n"
|
|
|
|
|
2012-02-25 13:03:22 +01:00
|
|
|
pusha
|
|
|
|
lea ecx, [ebx + SOCKET.mutex]
|
|
|
|
call mutex_unlock
|
|
|
|
popa
|
2011-01-08 15:59:21 +01:00
|
|
|
|
|
|
|
.destroy_new_socket:
|
|
|
|
|
2012-08-27 15:55:15 +02:00
|
|
|
test [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET
|
|
|
|
jz .drop_no_socket
|
|
|
|
|
|
|
|
mov eax, ebx
|
|
|
|
call SOCKET_free
|
2011-01-08 15:59:21 +01:00
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.drop_no_socket:
|
|
|
|
DEBUGF 1,"TCP_input: Drop (no socket)\n"
|
|
|
|
|
2012-08-28 00:47:10 +02:00
|
|
|
popf
|
2012-02-23 23:21:40 +01:00
|
|
|
call kernel_free
|
|
|
|
add esp, 4
|
2012-08-28 00:47:10 +02:00
|
|
|
|
2012-04-11 15:07:45 +02:00
|
|
|
ret
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
.drop_with_reset_no_socket:
|
2012-04-11 15:07:45 +02:00
|
|
|
|
2012-07-27 01:21:35 +02:00
|
|
|
DEBUGF 1,"TCP_input: Drop with reset (no socket)\n"
|
2012-04-11 15:07:45 +02:00
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_RST
|
|
|
|
jnz .drop_no_socket
|
|
|
|
|
|
|
|
;;; if its a multicast/broadcast, also drop
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_ACK
|
|
|
|
jnz .respond_seg_ack
|
|
|
|
|
|
|
|
test [edx + TCP_header.Flags], TH_SYN
|
|
|
|
jnz .respond_seg_syn
|
|
|
|
|
2012-08-19 13:21:20 +02:00
|
|
|
jmp .drop_no_socket
|
2012-04-11 15:07:45 +02:00
|
|
|
|
|
|
|
.respond_seg_ack:
|
|
|
|
|
|
|
|
mov cl, TH_RST
|
|
|
|
call TCP_respond_segment
|
|
|
|
jmp .drop_no_socket
|
|
|
|
|
|
|
|
.respond_seg_syn:
|
|
|
|
|
|
|
|
mov cl, TH_RST + TH_ACK
|
|
|
|
call TCP_respond_segment
|
|
|
|
jmp .drop_no_socket
|