rewrote TCP option parser, added SACK, moved connection accepter to run before option parser.

git-svn-id: svn://kolibrios.org@2954 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2012-08-28 19:56:28 +00:00
parent eaebc59a11
commit c10e7c783c

View File

@ -159,7 +159,35 @@ TCP_input:
; Are we accepting incoming connections? ; Are we accepting incoming connections?
test [ebx + SOCKET.options], SO_ACCEPTCON test [ebx + SOCKET.options], SO_ACCEPTCON
jnz .accept_connection jz .no_accept
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_no_socket
mov ebx, eax
mov [ebx + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
push dword [edi + 4] ; Ipv4 destination addres
pop [ebx + IP_SOCKET.LocalIP]
push [edx + TCP_header.DestinationPort]
pop [ebx + TCP_SOCKET.LocalPort]
mov [ebx + TCP_SOCKET.t_state], TCPS_LISTEN
.no_accept:
;------------------------------------- ;-------------------------------------
; Reset idle timer and keepalive timer ; Reset idle timer and keepalive timer
@ -170,85 +198,108 @@ TCP_input:
;-------------------- ;--------------------
; Process TCP options ; Process TCP options
movzx eax, [edx + TCP_header.DataOffset] push ecx
cmp eax, sizeof.TCP_header ; Does header contain any options?
movzx ecx, [edx + TCP_header.DataOffset]
cmp ecx, sizeof.TCP_header ; Does header contain any options?
je .no_options je .no_options
DEBUGF 1,"TCP_input: Segment has options\n" DEBUGF 1,"TCP_input: Segment has options\n"
cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state ;;; FIXME: for LISTEN, options should be called after we determined route, we need it for MSS
jz .not_uni_xfer ; also no header prediction ;;; cmp [ebx + TCP_SOCKET.t_state], TCPS_LISTEN ; no options when in listen state
;;; jz .not_uni_xfer ; also no header prediction
add eax, edx add ecx, edx
lea esi, [edx + sizeof.TCP_header] lea esi, [edx + sizeof.TCP_header]
.opt_loop: .opt_loop:
cmp esi, eax ; are we scanning outside of header? cmp esi, ecx ; are we scanning outside of header?
jae .no_options jae .no_options
lodsb
cmp byte [esi], TCP_OPT_EOL ; end of option list? cmp al, TCP_OPT_EOL ; end of option list?
jz .no_options je .no_options
cmp al, TCP_OPT_NOP
cmp byte [esi], TCP_OPT_NOP ; nop ? je .opt_loop
jz .opt_nop cmp al, TCP_OPT_MAXSEG
cmp byte [esi], TCP_OPT_MAXSEG
je .opt_maxseg je .opt_maxseg
cmp al, TCP_OPT_WINDOW
cmp byte [esi], TCP_OPT_WINDOW
je .opt_window je .opt_window
cmp al, TCP_OPT_SACK_PERMIT
cmp byte [esi], TCP_OPT_TIMESTAMP je .opt_sack_permit
; cmp al, TCP_OPT_SACK
; je .opt_sack
cmp al, TCP_OPT_TIMESTAMP
je .opt_timestamp je .opt_timestamp
DEBUGF 1,"TCP_input: unknown option:%u\n", al
jmp .no_options ; If we reach here, some unknown options were received, skip them all! jmp .no_options ; If we reach here, some unknown options were received, skip them all!
.opt_nop:
inc esi
jmp .opt_loop
.opt_maxseg: .opt_maxseg:
cmp byte [esi+1], 4 lodsb
cmp al, 4
jne .no_options ; error occured, ignore all options! jne .no_options ; error occured, ignore all options!
test [edx + TCP_header.Flags], TH_SYN test [edx + TCP_header.Flags], TH_SYN
jz @f jz @f
movzx eax, word[esi+2] lodsw
rol ax, 8 rol ax, 8
DEBUGF 1,"TCP_input: Maxseg=%u\n", ax DEBUGF 1,"TCP_input: Maxseg=%u\n", ax
mov [ebx + TCP_SOCKET.t_maxseg], eax mov [ebx + TCP_SOCKET.t_maxseg], eax
@@: @@:
add esi, 4
jmp .opt_loop jmp .opt_loop
.opt_window: .opt_window:
cmp byte [esi+1], 3 lodsb
cmp al, 3
jne .no_options jne .no_options
test [edx + TCP_header.Flags], TH_SYN test [edx + TCP_header.Flags], TH_SYN
jz @f jz @f
DEBUGF 1,"TCP_input: Got window option\n" DEBUGF 1,"TCP_input: Got window scale option\n"
or [ebx + TCP_SOCKET.t_flags], TF_RCVD_SCALE
lodsb
mov [ebx + TCP_SOCKET.SND_SCALE], al
;;;;; TODO
@@:
jmp .opt_loop
.opt_sack_permit:
lodsb
cmp al, 2
jne .no_options
test [edx + TCP_header.Flags], TH_SYN
jz @f
DEBUGF 1,"TCP_input: Selective Acknowledgement permitted\n"
or [ebx + TCP_SOCKET.t_flags], TF_SACK_PERMIT
;;;;;
@@: @@:
add esi, 3
jmp .opt_loop jmp .opt_loop
.opt_timestamp: .opt_timestamp:
cmp byte [esi+1], 10 ; length must be 10 lodsb
cmp al, 10 ; length must be 10
jne .no_options jne .no_options
DEBUGF 1,"TCP_input: Got timestamp option\n" DEBUGF 1,"TCP_input: Got timestamp option\n"
push dword [esi + 2] ; timestamp test [edx + TCP_header.Flags], TH_SYN
pop [ebx + TCP_SOCKET.ts_val] jz @f
push dword [esi + 6] ; timestamp echo reply or [ebx + TCP_SOCKET.t_flags], TF_RCVD_TSTMP
pop [ebx + TCP_SOCKET.ts_ecr] @@:
lodsd
mov [ebx + TCP_SOCKET.ts_val], eax
lodsd ; timestamp echo reply
mov [ebx + TCP_SOCKET.ts_ecr], eax
or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP or [ebx + TCP_SOCKET.temp_bits], TCP_BIT_TIMESTAMP
; Since we have a timestamp, lets do the paws test right away! ; Since we have a timestamp, lets do the paws test right away!
@ -264,19 +315,19 @@ TCP_input:
DEBUGF 1,"TCP_input: PAWS: detected an old segment\n" DEBUGF 1,"TCP_input: PAWS: detected an old segment\n"
mov eax, [esp+4+4] ; tcp_now mov eax, [esp+4+4+4] ; tcp_now
sub eax, [ebx + TCP_SOCKET.ts_recent_age] sub eax, [ebx + TCP_SOCKET.ts_recent_age]
cmp eax, TCP_PAWS_IDLE cmp eax, TCP_PAWS_IDLE
jle .drop_after_ack ; TODO: update stats jle .drop_after_ack ; TODO: update stats
mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it. mov [ebx + TCP_SOCKET.ts_recent], 0 ; timestamp was invalid, fix it.
.no_paws: .no_paws:
add esi, 10
jmp .opt_loop jmp .opt_loop
.no_options: .no_options:
pop ecx
;----------------------------------------------------------------------- ;-----------------------------------------------------------------------
; Time to do some header prediction (Original Principle by Van Jacobson) ; Time to do some header prediction (Original Principle by Van Jacobson)
@ -1038,37 +1089,8 @@ TCP_input:
;-------------
; Passive Open
align 4
.accept_connection:
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
mov [eax + TCP_SOCKET.temp_bits], TCP_BIT_DROPSOCKET ;;; FIXME: should we take over bits from previous socket?
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: .LISTEN:
@ -1262,17 +1284,13 @@ align 4
ja .no_window_update ja .no_window_update
@@: @@:
mov eax, [ebx + TCP_SOCKET.SND_WL2]
cmp eax, [edx + TCP_header.AckNumber]
jne .no_window_update
mov eax, dword [edx + TCP_header.Window] mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.SND_WND] cmp eax, [ebx + TCP_SOCKET.SND_WND]
jbe .no_window_update jbe .no_window_update
.update_window: .update_window:
;;; TODO: Keep track of pure window updates ;;; TODO: update stats (Keep track of pure window updates)
mov eax, dword [edx + TCP_header.Window] mov eax, dword [edx + TCP_header.Window]
cmp eax, [ebx + TCP_SOCKET.max_sndwnd] cmp eax, [ebx + TCP_SOCKET.max_sndwnd]
@ -1293,12 +1311,6 @@ align 4
.no_window_update: .no_window_update:
;----------------- ;-----------------
; process URG flag ; process URG flag
@ -1464,6 +1476,7 @@ align 4
DEBUGF 1,"TCP_input: ACK now!\n" DEBUGF 1,"TCP_input: ACK now!\n"
.need_output: .need_output:
DEBUGF 1,"TCP_input: need output\n"
call TCP_output call TCP_output
.dumpit: .dumpit: