changes in net branch:

-Further development of TCP
-Fixed a design issue in Ethernet drivers wich would cause a lot of overhead for TCP (I probably completely broke RTL8029 driver now, let's finish TCP first..)

git-svn-id: svn://kolibrios.org@1254 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
hidnplayr 2009-11-08 18:00:01 +00:00
parent 1a07e149d0
commit 2fcdc75ae8
11 changed files with 853 additions and 831 deletions

View File

@ -758,21 +758,21 @@ nsr_002:
;*************************************************************************** ;***************************************************************************
; Function ; Function
; transmit ; transmit
; buffer in [esp], size in [esp+4], pointer to device struct in ebx ; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx
;*************************************************************************** ;***************************************************************************
align 4 align 4
transmit: transmit:
mov ebp, ebx mov ebp, ebx
mov esi, [esp] mov esi, [esp + 4]
mov ecx, [esp + 4] mov ecx, [esp + 8]
DEBUGF 2,"Transmitting packet, buffer:%x, size:%u\n",esi, ecx DEBUGF 2,"Transmitting packet, buffer:%x, size:%u\n",esi, ecx
DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2 DEBUGF 2,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2,[esi+6]:2,[esi+7]:2,[esi+8]:2,[esi+9]:2,[esi+10]:2,[esi+11]:2,[esi+13]:2,[esi+12]:2
cmp dword [esp+4], ETH_FRAME_LEN cmp dword [esp + 8], ETH_FRAME_LEN
jg .finish ; packet is too long jg .finish ; packet is too long
cmp dword [esp+4], 60 cmp dword [esp + 8], 60
jl .finish ; packet is too short jl .finish ; packet is too short
xor bl, bl xor bl, bl
@ -804,15 +804,12 @@ transmit:
DEBUGF 2," - Packet Sent!\n" DEBUGF 2," - Packet Sent!\n"
inc [ebp+device.packets_tx] ; inc [ebp+device.packets_tx] ;
mov eax, [esp+4] ; Get packet size in eax mov eax, [esp + 8] ; Get packet size in eax
add dword [ebp + device.bytes_tx], eax add dword [ebp + device.bytes_tx], eax
adc dword [ebp + device.bytes_tx + 4], 0 adc dword [ebp + device.bytes_tx + 4], 0
.finish: .finish:
mov ebx, ebp mov ebx, ebp
call KernelFree
add esp, 4 ; pop (balance stack)
xor eax, eax xor eax, eax
ret ret

View File

@ -7,15 +7,14 @@
;; ;; ;; ;;
;; Written by hidnplayr@kolibrios.org ;; ;; Written by hidnplayr@kolibrios.org ;;
;; ;; ;; ;;
;; v0.1 - march 2009 ;; ;; 0.1 - x march 2009 ;;
;; 0.2 - 8 november 2009 ;;
;; ;; ;; ;;
;; GNU GENERAL PUBLIC LICENSE ;; ;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;; ;; Version 2, June 1991 ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision$
format MS COFF format MS COFF
API_VERSION equ 0x01000100 API_VERSION equ 0x01000100
@ -766,24 +765,24 @@ reset:
;; ;; ;; ;;
;; Transmit ;; ;; Transmit ;;
;; ;; ;; ;;
;; In: buffer pointer in [esp] ;; ;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+4] ;; ;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;; ;; pointer to device structure in ebx ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
align 4 align 4
transmit: transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4] DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8]
mov eax, [esp] mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2 [eax+13]:2,[eax+12]:2
cmp dword [esp+4], MAX_ETH_FRAME_SIZE cmp dword [esp+8], MAX_ETH_FRAME_SIZE
jg .finish ; packet is too long jg .finish ; packet is too long
cmp dword [esp+4], 60 cmp dword [esp+8], 60
jl .finish ; packet is too short jl .finish ; packet is too short
; check descriptor ; check descriptor
@ -822,16 +821,16 @@ transmit:
add edi, eax ; Store it in edi add edi, eax ; Store it in edi
pop edx pop edx
mov esi, [esp] ; Copy data to that address mov esi, [esp+4] ; Copy data to that address
mov ecx, [esp+4] ; mov ecx, [esp+8] ;
shr ecx, 2 ; shr ecx, 2 ;
rep movsd ; rep movsd ;
mov ecx, [esp+4] ; mov ecx, [esp+8] ;
and ecx, 3 ; and ecx, 3 ;
rep movsb ; rep movsb ;
inc [ebx+device.packets_tx] ; inc [ebx+device.packets_tx] ;
mov eax, [esp+4] ; Get packet size in eax mov eax, [esp+8] ; Get packet size in eax
add dword [ebx + device.bytes_tx], eax add dword [ebx + device.bytes_tx], eax
adc dword [ebx + device.bytes_tx + 4], 0 adc dword [ebx + device.bytes_tx + 4], 0
@ -846,9 +845,6 @@ transmit:
DEBUGF 2," - Packet Sent! " DEBUGF 2," - Packet Sent! "
.finish: .finish:
DEBUGF 2," - Done!\n" DEBUGF 2," - Done!\n"
call KernelFree
add esp, 4 ; pop (balance stack)
ret ret

View File

@ -1138,8 +1138,8 @@ reset:
;; ;; ;; ;;
;; Transmit ;; ;; Transmit ;;
;; ;; ;; ;;
;; In: buffer pointer in [esp] ;; ;; In: buffer pointer in [esp+4] ;;
;; size of buffer in [esp+4] ;; ;; size of buffer in [esp+8] ;;
;; pointer to device structure in ebx ;; ;; pointer to device structure in ebx ;;
;; ;; ;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -1147,15 +1147,15 @@ reset:
align 4 align 4
transmit: transmit:
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4] DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4]
mov eax, [esp] mov eax, [esp+4]
DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\ DEBUGF 1,"To: %x-%x-%x-%x-%x-%x From: %x-%x-%x-%x-%x-%x Type:%x%x\n",\
[eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\ [eax+00]:2,[eax+01]:2,[eax+02]:2,[eax+03]:2,[eax+04]:2,[eax+05]:2,\
[eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ [eax+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\
[eax+13]:2,[eax+12]:2 [eax+13]:2,[eax+12]:2
cmp dword [esp+4], 1514 cmp dword [esp+8], 1514
jg .finish ; packet is too long jg .finish ; packet is too long
cmp dword [esp+4], 60 cmp dword [esp+8], 60
jl .finish ; packet is too short jl .finish ; packet is too short
; check descriptor ; check descriptor
@ -1167,8 +1167,8 @@ transmit:
test byte [eax + buf_head.status + 1], 80h test byte [eax + buf_head.status + 1], 80h
jnz .nospace jnz .nospace
; descriptor is free, copy data ; descriptor is free, copy data
mov esi, [esp] mov esi, [esp+4]
mov ecx, [esp+4] mov ecx, [esp+8]
mov edx, ecx mov edx, ecx
shr ecx, 2 shr ecx, 2
and edx, 3 and edx, 3
@ -1176,7 +1176,7 @@ transmit:
mov ecx, edx mov ecx, edx
rep movsb rep movsb
; set length ; set length
mov ecx, [esp+4] mov ecx, [esp+8]
neg ecx neg ecx
mov [eax + buf_head.length], cx mov [eax + buf_head.length], cx
; put to transfer queue ; put to transfer queue
@ -1195,15 +1195,11 @@ transmit:
.finish: .finish:
DEBUGF 2," - Done!\n" DEBUGF 2," - Done!\n"
;;; call KernelFree
add esp, 4+4 ; pop (balance stack)
ret ret
.nospace: .nospace:
DEBUGF 1, 'ERROR: no free transmit descriptors\n' DEBUGF 1, 'ERROR: no free transmit descriptors\n'
; todo: maybe somehow notify the kernel about the error? ; todo: maybe somehow notify the kernel about the error?
add esp, 4+4
ret ret

File diff suppressed because it is too large Load Diff

View File

@ -123,7 +123,6 @@ IPv4_handler:
; save checksum, and clear it in original packet ; save checksum, and clear it in original packet
mov di , [edx + IPv4_Packet.HeaderChecksum] mov di , [edx + IPv4_Packet.HeaderChecksum]
DEBUGF 1,"checksum: %x\n",di
mov word [edx + IPv4_Packet.HeaderChecksum], 0 mov word [edx + IPv4_Packet.HeaderChecksum], 0
; Re-calculate checksum ; Re-calculate checksum
@ -140,6 +139,8 @@ IPv4_handler:
pop ebx edx pop ebx edx
jne .dump ; if checksum isn't valid then dump packet jne .dump ; if checksum isn't valid then dump packet
DEBUGF 1,"IPv4 Checksum is correct\n",di
mov eax, [edx + IPv4_Packet.DestinationAddress] mov eax, [edx + IPv4_Packet.DestinationAddress]
mov edi, BROADCAST mov edi, BROADCAST
mov ecx, MAX_IP+1 mov ecx, MAX_IP+1
@ -157,7 +158,7 @@ IPv4_handler:
.ip_ok: .ip_ok:
call ETH_struc2dev ; TODO: make this work on other protocols too! call ETH_struc2dev ; TODO: make this work on other protocols too!
inc [IP_PACKETS_RX+4*edi] inc [IP_PACKETS_RX+4*edi]
DEBUGF 1,"IP_Handler - packet from %u.%u.%u.%u\n",\ DEBUGF 1,"packet comes from %u.%u.%u.%u\n",\
[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1 [edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
mov al , [edx + IPv4_Packet.VersionAndIHL] mov al , [edx + IPv4_Packet.VersionAndIHL]
@ -189,10 +190,8 @@ IPv4_handler:
add eax, edx add eax, edx
push eax push eax
mov al , [edx + IPv4_Packet.Protocol] mov al , [edx + IPv4_Packet.Protocol]
;----------------------- experimental
mov esi, [edx + IPv4_Packet.SourceAddress] mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress] mov edi, [edx + IPv4_Packet.DestinationAddress]
;-----------------------
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
cmp al , IP_PROTO_TCP cmp al , IP_PROTO_TCP
@ -204,7 +203,7 @@ IPv4_handler:
cmp al , IP_PROTO_ICMP cmp al , IP_PROTO_ICMP
je ICMP_handler je ICMP_handler
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al DEBUGF 1,"unknown protocol: %u\n",al
.dump: .dump:
DEBUGF 1,"IP_Handler - done\n" DEBUGF 1,"IP_Handler - done\n"
@ -402,10 +401,8 @@ IPv4_handler:
add eax, edx add eax, edx
push eax push eax
mov al , [edx + IPv4_Packet.Protocol] mov al , [edx + IPv4_Packet.Protocol]
;----------------------- experimental
mov esi, [edx + IPv4_Packet.SourceAddress] mov esi, [edx + IPv4_Packet.SourceAddress]
mov edi, [edx + IPv4_Packet.DestinationAddress] mov edi, [edx + IPv4_Packet.DestinationAddress]
;-----------------------
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
cmp al , IP_PROTO_TCP cmp al , IP_PROTO_TCP

View File

@ -327,28 +327,18 @@ ETH_send_queued:
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
push ETH_send_queued push ETH_send_queued ; this will cause the procedure to check for more packets
; when a single packet is handled
lodsd mov ebx, [esi]
mov ebx, eax pushd [esi + 8]
pushd [esi + 4]
sub esp, 8
mov edi, esp
movsd
movsd
DEBUGF 1,"dequeued packet for device %x\n", ebx DEBUGF 1,"dequeued packet for device %x\n", ebx
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted) call [ebx+ETH_DEVICE.transmit] ; we will return to get_from_queue macro after transmitting packet
cmp edi, -1
je .fail
jmp [ebx+ETH_DEVICE.transmit] ; we will return to get_from_queue macro after transmitting packet
.fail:
call kernel_free call kernel_free
add esp, 4 ; pop (balance stack) add esp, 4 ; pop (balance stack)
DEBUGF 1,"ETH_Sender - fail\n"
.gohome: .gohome:
ret ret

View File

@ -42,7 +42,7 @@ struct tcp_out_queue_entry
.retries dd ? .retries dd ?
.owner dd ? .owner dd ?
.sendproc dd ? .sendproc dd ?
.ack_num dd ? .seq_num dd ?
.size: .size:
ends ends

View File

@ -43,12 +43,15 @@ struct TCP_SOCKET
.RemotePort dw ? ; In INET byte order .RemotePort dw ? ; In INET byte order
.backlog dw ? ; Backlog .backlog dw ? ; Backlog
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) ; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) ; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
.TCBState dd ? ; TCB state .wndsizeTimer dd ? ; window size timer
.TCBTimer dd ? ; TCB timer (seconds)
.ISS dd ? ; initial send sequence ; Transmission control block
.IRS dd ? ; initial receive sequence .state dd ? ; TCB state
.timer dd ? ; TCB timer (seconds)
.ISS dd ? ; initial send sequence number
.IRS dd ? ; initial receive sequence number
.SND_UNA dd ? ; sequence number of unack'ed sent Packets .SND_UNA dd ? ; sequence number of unack'ed sent Packets
.SND_NXT dd ? ; next send sequence number to use .SND_NXT dd ? ; next send sequence number to use
.SND_WND dd ? ; send window .SND_WND dd ? ; send window
@ -56,7 +59,6 @@ struct TCP_SOCKET
.RCV_WND dd ? ; receive window .RCV_WND dd ? ; receive window
.SEG_LEN dd ? ; segment length .SEG_LEN dd ? ; segment length
.SEG_WND dd ? ; segment window .SEG_WND dd ? ; segment window
.wndsizeTimer dd ? ; window size timer
.flags db ? ; packet flags .flags db ? ; packet flags
@ -121,35 +123,32 @@ socket_init:
ret ret
;----------------------------------------------------------------------------- ;-----------------------------------------------
; ;
; Socket API (function 74) ; Socket API (function 74)
; ;
;----------------------------------------------------------------------------- ;-----------------------------------------------
align 4 align 4
sys_socket: sys_socket:
and ebx, 0x000000FF ; should i remove this line ?
cmp bl , 7 ; highest possible number
jg s_error
lea ebx, [.table + 4*ebx]
jmp dword [ebx]
.table:
dd socket_open ; 0
dd socket_close ; 1
dd socket_bind ; 2
dd socket_listen ; 3
dd socket_connect ; 4
dd socket_accept ; 5
dd socket_send ; 6
dd socket_recv ; 7
; dd socket_get_opt ; 8
; dd socket_set_opt ; 9
test bl, bl
jz socket_open ; 0
dec bl
jz socket_close ; 1
dec bl
jz socket_bind ; 2
dec bl
jz socket_listen ; 3
dec bl
jz socket_connect ; 4
dec bl
jz socket_accept ; 5
dec bl
jz socket_send ; 6
dec bl
jz socket_recv ; 7
dec bl
; jz socket_get_opt ; 8
dec bl
; jz socket_set_opt ; 9
s_error: s_error:
mov dword [esp+32],-1 mov dword [esp+32],-1
@ -157,8 +156,6 @@ s_error:
ret ret
;----------------------------------------------- ;-----------------------------------------------
; ;
; SOCKET_open ; SOCKET_open
@ -186,6 +183,8 @@ socket_open:
stdcall net_socket_addr_to_num, eax stdcall net_socket_addr_to_num, eax
DEBUGF 1,", socketnumber: %u\n", eax DEBUGF 1,", socketnumber: %u\n", eax
; TODO: if it is txcp socket, set state to TCB_CLOSED
mov [esp+32], eax mov [esp+32], eax
ret ret
@ -231,7 +230,6 @@ socket_bind:
; TODO: write code here ; TODO: write code here
mov dword [esp+32],0 mov dword [esp+32],0
ret ret
@ -295,7 +293,7 @@ socket_connect:
cmp eax, -1 cmp eax, -1
jz s_error jz s_error
cmp esi, 2 cmp esi, 8
jl s_error jl s_error
cmp word [edx], AF_INET4 cmp word [edx], AF_INET4
@ -305,21 +303,15 @@ socket_connect:
.af_inet4: .af_inet4:
cmp esi, 8
jl s_error
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
je .udp je .udp
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
je .icmp
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
je .tcp je .tcp
jmp s_error jmp s_error
.udp: .udp:
mov bx , word [edx + 2] mov bx , word [edx + 2]
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
@ -332,92 +324,49 @@ socket_connect:
mov dword [esp+32],0 mov dword [esp+32],0
ret ret
.icmp:
; TODO: write code here
ret
.tcp: .tcp:
; TODO: set sequence number to random value
;local sockAddr dd ?
; cmp esi, SOCKET_PASSIVE ; fill in remote port and IP
; jne .skip_port_check
;
; push ebx
; mov eax, ebx
; xchg al, ah
; mov ebx, net_sockets
;
; .next_socket:
; mov ebx, [ebx + SOCKET.NextPtr]
; or ebx, ebx
; jz .last_socket
; cmp [ebx + SOCKET.TCBState], TCB_LISTEN
; jne .next_socket
; cmp [ebx + SOCKET.LocalPort], ax
; jne .next_socket
;
; xchg al, ah
; DEBUGF 1, "K : error: port %u is listened by 0x%x\n", ax, ebx
; pop ebx
; jmp .error
;
; .last_socket:
; pop ebx
;
; .skip_port_check:
; mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0 ; Reset the window timer.
; ; TODO: figure out WTF this is
; xchg bh, bl mov bx , word [edx + 2]
; mov [eax + SOCKET.LocalPort], bx mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], bx
; xchg ch, cl DEBUGF 1,"remote port: %x ",bx
; mov [eax + SOCKET.RemotePort], cx
; mov [eax + SOCKET.OrigRemotePort], cx
; mov ebx, [IP_LIST]
; mov [eax + SOCKET.LocalIP], ebx
; mov [eax + SOCKET.RemoteIP], edx
; mov [eax + SOCKET.OrigRemoteIP], edx
; mov ebx, TCB_LISTEN mov ebx, dword [edx + 4]
; cmp esi, SOCKET_PASSIVE mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
; je @f
; mov ebx, TCB_SYN_SENT
; @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB
; cmp ebx, TCB_LISTEN ; check if local port and IP is ok
; je .exit
; Now, if we are in active mode, then we have to send a SYN to the specified remote port cmp [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], 0
; mov eax, EMPTY_QUEUE jne @f
; call dequeue push [IP_LIST] ; device zero = default
; cmp ax, NO_BUFFER pop [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
; je .exit @@:
; push eax cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], 0
jne @f
; mov bl, TH_SYN mov ecx, [eax + SOCKET_head.Type]
; xor ecx, ecx call socket_find_port
; stdcall build_tcp_Packet, [sockAddr] test bx, bx
jz s_error
; mov eax, NET1OUT_QUEUE mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
; mov edx, [IP_LIST] @@:
; mov ecx, [sockAddr]
; cmp edx, [ecx + SOCKET.RemoteIP]
; jne .not_local
; mov eax, IPIN_QUEUE
; .not_local:
; Send it.
; pop ebx
; call queue
.exit: mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
xor eax, eax ; now say hello to the remote tcp socket
mov bl, TH_SYN
call TCP_send_ack
mov dword [esp+32],0
ret ret
@ -442,14 +391,19 @@ socket_listen:
cmp eax, -1 cmp eax, -1
jz s_error jz s_error
cmp word [eax + SOCKET_head.Domain], AF_INET4
jne s_error
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
jne s_error
cmp edx, MAX_backlog cmp edx, MAX_backlog
jl .ok jl .ok
mov dx , 20 mov dx , 20
.ok: .ok:
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
; TODO: insert code for active connections like TCP
mov dword [esp+32], 0 mov dword [esp+32], 0
ret ret
@ -569,98 +523,44 @@ socket_close:
ret ret
.tcp: .tcp:
; first, remove all resend entries for this socket
if 1 = 0 cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
;local sockAddr dd ?
; DEBUGF 1, "K : socket_close_tcp (0x%x)\n", ebx
; first, remove any resend entries
pusha
mov esi, resendQ
mov ecx, 0
.next_resendq:
cmp ecx, NUMRESENDENTRIES
je .last_resendq ; None left
cmp [esi + 4], ebx
je @f ; found one
inc ecx
add esi, 8
jmp .next_resendq
@@: mov dword[esi + 4], 0
inc ecx
add esi, 8
jmp .next_resendq
.last_resendq:
popa
mov ebx, eax
; mov [sockAddr], eax
cmp [eax + SOCKET.TCBState], TCB_LISTEN
je .destroy_tcb je .destroy_tcb
cmp [eax + SOCKET.TCBState], TCB_SYN_SENT cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT
je .destroy_tcb je .destroy_tcb
; Now construct the response, and queue for sending by IP ; Now construct the response, and queue for sending by IP
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je .error
push eax
mov bl, TH_FIN mov bl, TH_FIN
xor ecx, ecx call TCP_send_ack
xor esi, esi
stdcall build_tcp_Packet, [sockAddr]
mov ebx, [sockAddr]
; increament SND.NXT in socket ; increament SND.NXT in socket
lea esi, [ebx + SOCKET.SND_NXT] lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
call inc_inet_esi inc_INET esi
; Get the socket state ; Get the socket state
mov eax, [ebx + SOCKET.TCBState] cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
cmp eax, TCB_SYN_RECEIVED
je .fin_wait_1 je .fin_wait_1
cmp eax, TCB_ESTABLISHED cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
je .fin_wait_1 je .fin_wait_1
; assume CLOSE WAIT ; assume CLOSE WAIT
; Send a fin, then enter last-ack state ; Send a fin, then enter last-ack state
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK
jmp .send jmp .send
.fin_wait_1: .fin_wait_1:
; Send a fin, then enter finwait2 state ; Send a fin, then enter finwait2 state
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1
.send: .send:
mov eax, NET1OUT_QUEUE
mov edx, [IP_LIST]
; mov ecx, [sockAddr]
cmp edx, [ecx + SOCKET.RemoteIP]
jne .not_local
mov eax, IPIN_QUEUE
.not_local:
; Send it.
pop ebx
call queue
jmp .exit
;;;;;
.destroy_tcb: .destroy_tcb:
stdcall net_socket_free, eax stdcall net_socket_free, eax
end if
.exit:
mov dword [esp+32],0 mov dword [esp+32],0
ret ret
@ -735,6 +635,7 @@ socket_recv:
; OUT: -1 on error ; OUT: -1 on error
; ;
;----------------------------------------------- ;-----------------------------------------------
align 4 align 4
socket_send: socket_send:
@ -749,7 +650,6 @@ socket_send:
jmp s_error jmp s_error
;---------
.af_inet4: .af_inet4:
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4 DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
@ -763,7 +663,6 @@ socket_send:
je .raw je .raw
jmp s_error jmp s_error
;--------
.udp: .udp:
@ -792,10 +691,27 @@ socket_send:
.tcp: .tcp:
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort],0
jne @f
push esi
mov ecx, [eax + SOCKET_head.Type]
call socket_find_port
test bx, bx
pop esi
je s_error
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx
@@:
mov ecx, esi
mov esi, edx
call TCP_socket_send
mov [esp+32], eax mov [esp+32], eax
ret ret
;--------
.raw: .raw:
cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP
je .raw_ip je .raw_ip
@ -804,11 +720,12 @@ socket_send:
je .raw_icmp je .raw_icmp
jmp s_error jmp s_error
;--------
.raw_ip: .raw_ip:
;;;;;;
mov [esp+32], eax mov [esp+32], eax
ret ret

View File

@ -32,7 +32,7 @@ MAX_EPHEMERAL_PORT equ 61000
ETHER equ 1337 ETHER equ 1337
ETHER_ARP equ 0x0608 ETHER_ARP equ 0x0608
;AF_UNSPEC equ 0 AF_UNSPEC equ 0
AF_UNIX equ 1 AF_UNIX equ 1
AF_INET4 equ 2 AF_INET4 equ 2
;AF_AX25 equ 3 ;AF_AX25 equ 3
@ -55,9 +55,46 @@ SOCK_STREAM = 1
SOCK_DGRAM = 2 SOCK_DGRAM = 2
SOCK_RAW = 3 SOCK_RAW = 3
; TCP opening modes TCB_LISTEN equ 1
SOCKET_PASSIVE equ 0 TCB_SYN_SENT equ 2
SOCKET_ACTIVE equ 1 TCB_SYN_RECEIVED equ 3
TCB_ESTABLISHED equ 4
TCB_FIN_WAIT_1 equ 5
TCB_FIN_WAIT_2 equ 6
TCB_CLOSE_WAIT equ 7
TCB_CLOSING equ 8
TCB_LAST_ACK equ 9
TCB_TIMED_WAIT equ 10
TCB_CLOSED equ 11
TH_FIN equ 1 shl 0
TH_SYN equ 1 shl 1
TH_RST equ 1 shl 2
TH_PUSH equ 1 shl 3
TH_ACK equ 1 shl 4
TH_URG equ 1 shl 5
macro inc_INET reg {
inc byte [reg + 3]
adc byte [reg + 2], 0
adc byte [reg + 1], 0
adc byte [reg + 0], 0
}
macro add_INET reg {
rol ecx, 16
adc byte [reg + 3], ch
adc byte [reg + 2], cl
rol ecx, 16
adc byte [reg + 1], ch
adc byte [reg + 0], cl
}
include "queue.inc" include "queue.inc"
include "ARP.inc" include "ARP.inc"
@ -90,7 +127,7 @@ stack_init:
call ICMP_init call ICMP_init
call socket_init call socket_init
mov al, 0x0 ; set up 1s timer mov al, 0 ; set up 1s timer
out 0x70, al out 0x70, al
in al, 0x71 in al, 0x71
mov [last_1sTick], al mov [last_1sTick], al
@ -116,7 +153,7 @@ stack_handler:
cmp [ETH_RUNNING], 0 cmp [ETH_RUNNING], 0
je .exit je .exit
; Test for 10ms tick ; Test for 1/100 s (10ms) tick
mov eax, [timer_ticks] mov eax, [timer_ticks]
cmp eax, [last_1hsTick] cmp eax, [last_1hsTick]
je .exit je .exit
@ -129,8 +166,8 @@ stack_handler:
.sec_tick: .sec_tick:
; Test for 1 second event ; Test for 1 second tick
mov al, 0x0 ;second mov al, 0
out 0x70, al out 0x70, al
in al, 0x71 in al, 0x71
cmp al, [last_1sTick] cmp al, [last_1sTick]
@ -336,7 +373,7 @@ sys_protocols:
je UDP_API je UDP_API
cmp ax , IP_PROTO_TCP cmp ax , IP_PROTO_TCP
; je TCP_API je TCP_API
cmp ax , ETHER_ARP cmp ax , ETHER_ARP
je ARP_API je ARP_API

View File

@ -17,30 +17,9 @@
$Revision$ $Revision$
TCB_LISTEN equ 1
TCB_SYN_SENT equ 2
TCB_SYN_RECEIVED equ 3
TCB_ESTABLISHED equ 4
TCB_FIN_WAIT_1 equ 5
TCB_FIN_WAIT_2 equ 6
TCB_CLOSE_WAIT equ 7
TCB_CLOSING equ 8
TCB_LAST_ACK equ 9
TCB_TIMED_WAIT equ 10
TCB_CLOSED equ 11
TH_FIN equ 1 shl 0
TH_SYN equ 1 shl 1
TH_RST equ 1 shl 2
TH_PUSH equ 1 shl 3
TH_ACK equ 1 shl 4
TH_URG equ 1 shl 5
TWOMSL equ 10 ; # of secs to wait before closing socket
TCP_RETRIES equ 5 ; Number of times to resend a Packet TCP_RETRIES equ 5 ; Number of times to resend a Packet
TCP_TIMEOUT equ 10 ; resend if not replied to in 1/100 s TCP_PACKET_TTL equ 50 ; resend if not replied to in 1/100 s
TCP_SOCKET_TTL equ 10 ; # of secs to wait before closing socket
TCP_QUEUE_SIZE equ 16 TCP_QUEUE_SIZE equ 16
@ -66,14 +45,14 @@ uglobal
TCP_PACKETS_RX rd MAX_IP TCP_PACKETS_RX rd MAX_IP
TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4 TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4
TCP_OUT_QUEUE dd ? TCP_OUT_QUEUE dd ?
rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4 rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4
endg endg
align 4 align 4
iglobal iglobal
TCBStateHandler: stateHandler:
dd stateTCB_LISTEN dd stateTCB_LISTEN
dd stateTCB_SYN_SENT dd stateTCB_SYN_SENT
@ -90,30 +69,6 @@ TCBStateHandler:
endg endg
macro inc_INET reg {
inc byte [reg + 0]
adc byte [reg + 1], 0
adc byte [reg + 2], 0
adc byte [reg + 3], 0
}
macro add_INET reg {
rol ecx, 16
adc byte [reg + 0], ch
adc byte [reg + 1], cl
rol ecx, 16
adc byte [reg + 2], ch
adc byte [reg + 3], cl
}
;----------------------------------------------------------------- ;-----------------------------------------------------------------
; ;
; TCP_init ; TCP_init
@ -134,7 +89,12 @@ TCP_init:
rep stosd rep stosd
init_queue TCP_IN_QUEUE init_queue TCP_IN_QUEUE
init_queue TCP_OUT_QUEUE
; tcp_out_queue is a special type of queue
xor eax, eax
mov esi, TCP_OUT_QUEUE
mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1
rep stosd
ret ret
@ -165,9 +125,9 @@ TCP_decrease_socket_ttls:
cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP
jne .next_socket jne .next_socket
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] ; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.state]
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], 0 cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0
jne .decrement_tcb jne .decrement_tcb
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0 cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0
jne .decrement_wnd jne .decrement_wnd
@ -175,10 +135,10 @@ TCP_decrease_socket_ttls:
.decrement_tcb: .decrement_tcb:
; decrement it, delete socket if TCB timer = 0 & socket in timewait state ; decrement it, delete socket if TCB timer = 0 & socket in timewait state
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer] dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer]
jnz .next_socket jnz .next_socket
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
jne .next_socket jne .next_socket
push [ebx + SOCKET_head.PrevPtr] push [ebx + SOCKET_head.PrevPtr]
@ -231,30 +191,33 @@ TCP_send_queued:
dec [esi + tcp_out_queue_entry.ttl] dec [esi + tcp_out_queue_entry.ttl]
jz .send_it jz .send_it
.find_next: .find_next:
add esi, tcp_out_queue_entry.size
dec eax dec eax
jz .exit jz .exit
jmp .loop test ecx, ecx
jnz .loop
ret
.send_it: .send_it:
push eax ecx esi push eax ecx esi
mov ebx, [esi + tcp_out_queue_entry.owner]
push [esi + tcp_out_queue_entry.data_size] push [esi + tcp_out_queue_entry.data_size]
push [esi + tcp_out_queue_entry.data_ptr] push [esi + tcp_out_queue_entry.data_ptr]
mov ebx, [esi + tcp_out_queue_entry.owner] DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc]
call [esi + tcp_out_queue_entry.sendproc] call [esi + tcp_out_queue_entry.sendproc]
add esp, 8
pop esi ecx eax pop esi ecx eax
dec [esi + tcp_out_queue_entry.retries] dec [esi + tcp_out_queue_entry.retries]
jz .remove_it jz .remove_it
mov [esi + tcp_out_queue_entry.ttl], TCP_TIMEOUT
mov [esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL
jmp .find_next jmp .find_next
.remove_it: .remove_it:
push [esi + tcp_out_queue_entry.data_ptr] push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0 mov [esi + tcp_out_queue_entry.data_ptr], 0
dec [TCP_OUT_QUEUE]
call kernel_free call kernel_free
jmp .find_next jmp .find_next
@ -278,6 +241,8 @@ TCP_send_queued:
align 4 align 4
TCP_add_to_queue: TCP_add_to_queue:
DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %x\n", [esp], [esp+4], ebx, edx
cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE
jge .full jge .full
@ -291,6 +256,9 @@ TCP_add_to_queue:
loop .loop loop .loop
.full: ; silently discard the packet .full: ; silently discard the packet
DEBUGF 1,"TCP queue is full!\n"
call kernel_free call kernel_free
add esp, 4 add esp, 4
@ -304,8 +272,12 @@ TCP_add_to_queue:
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES
mov [eax + tcp_out_queue_entry.owner], ebx mov [eax + tcp_out_queue_entry.owner], ebx
mov [eax + tcp_out_queue_entry.sendproc], esi mov [eax + tcp_out_queue_entry.sendproc], esi
mov [eax + tcp_out_queue_entry.ack_num], edx mov [eax + tcp_out_queue_entry.seq_num], edx
inc [TCP_OUT_QUEUE]
sub eax, TCP_OUT_QUEUE+4
DEBUGF 1,"Added to queue in pos %u\n", eax
ret ret
@ -332,6 +304,8 @@ TCP_handler :
DEBUGF 1,"TCP_Handler\n" DEBUGF 1,"TCP_Handler\n"
; TODO: validate checksum
; IP Packet TCP Destination Port = local Port ; IP Packet TCP Destination Port = local Port
; IP Packet SA = Remote IP OR = 0 ; IP Packet SA = Remote IP OR = 0
; IP Packet TCP Source Port = remote Port OR = 0 ; IP Packet TCP Source Port = remote Port OR = 0
@ -358,10 +332,12 @@ TCP_handler :
cmp [edx + TCP_Packet.SourcePort] , ax cmp [edx + TCP_Packet.SourcePort] , ax
je .change_state je .change_state
test ax, ax test ax, ax
jne .socket_loop jnz .socket_loop
.change_state: .change_state:
DEBUGF 1,"Found valid socket for packet\n"
push ebx push ebx
lea ebx, [ebx + SOCKET_head.lock] lea ebx, [ebx + SOCKET_head.lock]
call wait_mutex call wait_mutex
@ -373,28 +349,36 @@ TCP_handler :
; edx is pointer to tcp packet ; edx is pointer to tcp packet
; as a Packet has been received, update the TCB timer ; as a Packet has been received, update the TCB timer
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], TWOMSL mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL
; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges ; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges
test [edx + TCP_Packet.Flags], TH_ACK test [edx + TCP_Packet.Flags], TH_ACK
jz .call_handler ; No ACK, so no data yet jz .call_handler ; No ACK, so no data yet
mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax ; mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax
bswap eax ; ; bswap eax ;
add eax, ecx ; ; add eax, ecx ;
mov eax, [edx + TCP_Packet.AckNumber]
;---------
cmp [TCP_OUT_QUEUE], 0 cmp [TCP_OUT_QUEUE], 0
je .call_handler je .call_handler
push ecx push ecx
DEBUGF 1,"Removing all queued packets with smaller ACK\n"
mov ecx, TCP_QUEUE_SIZE mov ecx, TCP_QUEUE_SIZE
mov esi, TCP_OUT_QUEUE+4 mov esi, TCP_OUT_QUEUE+4
.loop: .loop:
cmp [esi + tcp_out_queue_entry.data_ptr], 0 cmp [esi + tcp_out_queue_entry.data_ptr], 0
jne .maybe_next je .maybe_next
cmp [esi + tcp_out_queue_entry.ack_num], eax cmp [esi + tcp_out_queue_entry.seq_num], eax
jg .maybe_next jg .maybe_next
; TODO: check if the packets belong to the same tcp connection !
DEBUGF 1,"Removing a queued packet\n"
push [esi + tcp_out_queue_entry.data_ptr] push [esi + tcp_out_queue_entry.data_ptr]
mov [esi + tcp_out_queue_entry.data_ptr], 0 mov [esi + tcp_out_queue_entry.data_ptr], 0
@ -404,24 +388,23 @@ TCP_handler :
.maybe_next: .maybe_next:
add esi, tcp_out_queue_entry.size add esi, tcp_out_queue_entry.size
loop .loop loop .loop
pop ecx
pop ecx
.call_handler: .call_handler:
; Call handler for given TCB state ; Call handler for given TCB state
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState] mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state]
DEBUGF 1,"Socket state: %u\n", eax
cmp eax, TCB_LISTEN cmp eax, TCB_LISTEN
jb .exit jb .dump
cmp eax, TCB_CLOSED cmp eax, TCB_CLOSED
ja .exit ja .dump
dec eax
shl eax, 2 shl eax, 2
add eax, TCBStateHandler - 4 add eax, stateHandler
push .exit call dword[eax]
jmp eax
.exit:
mov [ebx + SOCKET_head.lock], 0
.dump: .dump:
DEBUGF 1,"Dumping TCP packet\n" DEBUGF 1,"Dumping TCP packet\n"
@ -463,7 +446,7 @@ TCP_socket_send:
push ecx esi eax ; save some variables for later push ecx esi eax ; save some variables for later
add ecx, TCP_Packet.Data add ecx, TCP_Packet.Options
call IPv4_create_packet call IPv4_create_packet
cmp edi, -1 cmp edi, -1
je .fail je .fail
@ -485,7 +468,7 @@ TCP_socket_send:
mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags] mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags]
mov [edi + TCP_Packet.Flags], al mov [edi + TCP_Packet.Flags], al
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes ;;; TODO: read RFC ! mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes
mov [edi + TCP_Packet.UrgentPointer], 0 mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50 mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0 mov [edi + TCP_Packet.Checksum], 0
@ -493,7 +476,7 @@ TCP_socket_send:
; Copy the data ; Copy the data
mov esi, [esp] mov esi, [esp]
mov ecx, [esp+4] mov ecx, [esp+4]
add edi, TCP_Packet.Data add edi, TCP_Packet.Options
shr ecx, 1 shr ecx, 1
jnc .nb jnc .nb
@ -519,12 +502,12 @@ TCP_socket_send:
; And now, send it! ; And now, send it!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender lea esi, [ebx+ETH_DEVICE.transmit]
mov edx, [edi + TCP_Packet.AckNumber] mov edx, [edi + TCP_Packet.AckNumber]
jmp TCP_add_to_queue jmp TCP_add_to_queue
.fail: .fail:
add esp, 12+4 add esp, 12+12+4
ret ret
@ -543,14 +526,15 @@ TCP_socket_send:
align 4 align 4
TCP_send_ack: TCP_send_ack:
DEBUGF 1,"Creating TCP ACK\n" DEBUGF 1,"Creating TCP ACK, socket: %x, flags: %x\n",eax, bl
mov di , IP_PROTO_TCP mov di , IP_PROTO_TCP
mov cx , TCP_Packet.Data mov ecx, TCP_Packet.Options
push bx eax push bx eax
; Create an IPv4 Packet of the correct size ; Create an IPv4 Packet of the correct size
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
@ -564,10 +548,10 @@ TCP_send_ack:
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
pop [edi + TCP_Packet.SequenceNumber] pop [edi + TCP_Packet.SequenceNumber]
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] ; both ports at once
pop dword [edi + TCP_Packet.SourcePort] pop dword [edi + TCP_Packet.SourcePort]
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
pop [edi + TCP_Packet.AckNumber] pop [edi + TCP_Packet.AckNumber]
pop cx pop cx
@ -575,32 +559,39 @@ TCP_send_ack:
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes
mov [edi + TCP_Packet.UrgentPointer], 0 mov [edi + TCP_Packet.UrgentPointer], 0
mov [edi + TCP_Packet.DataOffset], 0x50 mov [edi + TCP_Packet.DataOffset], 0x50
mov [edi + TCP_Packet.Checksum], 0
push eax edx push edx eax
push word TCP_Packet.Data shl 8 lea esi, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
push IP_PROTO_TCP inc_INET esi
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
push [esi + SOCKET_head.end + SOCKET_head.end + IPv4_SOCKET.LocalIP] ; Now, calculate the checksum
pushw TCP_Packet.Options shl 8
pushw IP_PROTO_TCP shl 8
pushd [edi-4] ; destination address
pushd [edi-8] ; source address
; Now, calculate the checksum for pseudoheader
xor edx, edx xor edx, edx
mov ecx, TCP_Packet.Options
mov esi, edi
call checksum_1
mov ecx, 12 mov ecx, 12
mov esi, esp mov esi, esp
call checksum_1 call checksum_1
add esp, 12 ; remove the pseudoheader from stack add esp, 12 ; remove the pseudoheader from stack
; Now create the final checksum and store it in TCP header ; and store it in TCP header
call checksum_2 call checksum_2
mov [edi + TCP_Packet.Checksum], dx mov [edi + TCP_Packet.Checksum], dx
; And now, send it! ; And now, send the packet!
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx DEBUGF 1,"Sending TCP Packet to device %x\n", ebx
mov esi, ETH_sender mov esi, [ebx + ETH_DEVICE.transmit]
mov edx, [edi + TCP_Packet.AckNumber] mov edx, [edi + TCP_Packet.SequenceNumber]
jmp TCP_add_to_queue jmp TCP_add_to_queue
.fail: .fail:
add esp, 12+4 add esp, 2+4
ret ret
@ -609,6 +600,9 @@ TCP_send_ack:
align 4 align 4
stateTCB_LISTEN: stateTCB_LISTEN:
DEBUGF 1,"TCBStateHandler: Listen\n"
; In this case, we are expecting a SYN Packet ; In this case, we are expecting a SYN Packet
; For now, if the Packet is a SYN, process it, and send a response ; For now, if the Packet is a SYN, process it, and send a response
; If not, ignore it ; If not, ignore it
@ -631,22 +625,28 @@ stateTCB_LISTEN:
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS] mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], eax
mov [ebx + SOCKET_head.lock], 0
; Now construct the response ; Now construct the response
mov bl, TH_SYN + TH_ACK mov bl, TH_SYN + TH_ACK
call TCP_send_ack call TCP_send_ack
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
; increment SND.NXT in socket ; increment SND.NXT in socket
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT]
inc_INET esi inc_INET esi
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_SYN_SENT: stateTCB_SYN_SENT:
DEBUGF 1,"TCBStateHandler: Syn_Sent\n"
; We are awaiting an ACK to our SYN, with a SYM ; We are awaiting an ACK to our SYN, with a SYM
; Look at control flags - expecting an ACK ; Look at control flags - expecting an ACK
@ -658,34 +658,40 @@ stateTCB_SYN_SENT:
test al, TH_SYN test al, TH_SYN
jz .exit jz .exit
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED
push TH_SYN + TH_ACK pushd TH_SYN + TH_ACK
jmp .send jmp .send
.syn_ack: .syn_ack:
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
push TH_ACK pushd TH_ACK
.send: .send:
; Store the recv.nxt field ; Store the recv.nxt field
mov eax, [edx + TCP_Packet.SequenceNumber] mov eax, [edx + TCP_Packet.SequenceNumber]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax
; Update our recv.nxt field bswap eax
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax inc eax
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] bswap eax
inc_INET esi mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax ; Update our recv.nxt field
mov [ebx + SOCKET_head.lock], 0
; Send an ACK ; Send an ACK
mov eax, ebx
pop ebx pop ebx
call TCP_send_ack call TCP_send_ack
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_SYN_RECEIVED: stateTCB_SYN_RECEIVED:
DEBUGF 1,"TCBStateHandler: Syn_received\n"
; In this case, we are expecting an ACK Packet ; In this case, we are expecting an ACK Packet
; For now, if the Packet is an ACK, process it, ; For now, if the Packet is an ACK, process it,
; If not, ignore it ; If not, ignore it
@ -693,12 +699,12 @@ stateTCB_SYN_RECEIVED:
test [edx + TCP_Packet.Flags], TH_RST test [edx + TCP_Packet.Flags], TH_RST
jz .check_ack jz .check_ack
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort] ; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort] ; pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort]
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP] ; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP]
pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP] ; pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_LISTEN mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN
jmp .exit jmp .exit
.check_ack: .check_ack:
@ -706,15 +712,20 @@ stateTCB_SYN_RECEIVED:
test [edx + TCP_Packet.Flags], TH_ACK test [edx + TCP_Packet.Flags], TH_ACK
jz .exit jz .exit
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_ESTABLISHED: stateTCB_ESTABLISHED:
DEBUGF 1,"TCBStateHandler: Established\n"
; Here we are expecting data, or a request to close ; Here we are expecting data, or a request to close
; OR both... ; OR both...
@ -724,6 +735,7 @@ stateTCB_ESTABLISHED:
; It was a fin or reset. ; It was a fin or reset.
;;; TODO: write following code:
; Remove resend entries from the queue - I dont want to send any more data ; Remove resend entries from the queue - I dont want to send any more data
; Send an ACK to that fin, and enter closewait state ; Send an ACK to that fin, and enter closewait state
@ -732,6 +744,8 @@ stateTCB_ESTABLISHED:
test [edx + TCP_Packet.Flags], TH_ACK test [edx + TCP_Packet.Flags], TH_ACK
jz .exit jz .exit
DEBUGF 1,"Received ACK\n"
; First, look at the incoming window. If this is less than or equal to 1024, ; First, look at the incoming window. If this is less than or equal to 1024,
; Set the socket window timer to 1. This will stop an additional Packets being queued. ; Set the socket window timer to 1. This will stop an additional Packets being queued.
; ** I may need to tweak this value, since I do not know how many Packets are already queued ; ** I may need to tweak this value, since I do not know how many Packets are already queued
@ -752,7 +766,7 @@ stateTCB_ESTABLISHED:
; recv seq is in [sktAddr]+56, in inet format ; recv seq is in [sktAddr]+56, in inet format
; just do a comparision ; just do a comparision
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
jne @f jne @f
mov ecx, eax mov ecx, eax
@ -763,27 +777,35 @@ stateTCB_ESTABLISHED:
jnz .data jnz .data
; If we had received a fin, we need to ACK it. ; If we had received a fin, we need to ACK it.
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT
je .ack je .ack
jmp .exit jmp .exit
.data: .data:
DEBUGF 1,"Got data!\n"
mov esi, [esp + 4] mov esi, [esp + 4]
sub edx, esi sub edx, esi
mov edi, edx mov edi, edx
call socket_internal_receiver call socket_internal_receiver
.ack: .ack:
mov [ebx + SOCKET_head.lock], 0
; Send an ACK ; Send an ACK
mov eax, ebx
mov bl, TH_ACK mov bl, TH_ACK
call TCP_send_ack call TCP_send_ack
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_FIN_WAIT_1: stateTCB_FIN_WAIT_1:
DEBUGF 1,"TCBStateHandler: Fin_wait_1\n"
; We can either receive an ACK of a fin, or a fin ; We can either receive an ACK of a fin, or a fin
mov al, [edx + TCP_Packet.Flags] mov al, [edx + TCP_Packet.Flags]
and al, TH_FIN + TH_ACK and al, TH_FIN + TH_ACK
@ -792,71 +814,96 @@ stateTCB_FIN_WAIT_1:
jne @f jne @f
; It was an ACK ; It was an ACK
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_FIN_WAIT_2 mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2
jmp .exit jmp .exit
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSING @@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING
cmp al, TH_FIN cmp al, TH_FIN
je @f je @f
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
@@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] @@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi inc_INET esi
mov [ebx + SOCKET_head.lock], 0
; Send an ACK ; Send an ACK
mov eax, ebx
mov bl, TH_ACK mov bl, TH_ACK
call TCP_send_ack call TCP_send_ack
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_FIN_WAIT_2: stateTCB_FIN_WAIT_2:
DEBUGF 1,"TCBStateHandler: Fin_wait_2\n"
test [edx + TCP_Packet.Flags], TH_FIN test [edx + TCP_Packet.Flags], TH_FIN
jz .exit jz .exit
; Change state, as we have a fin ; Change state, as we have a fin
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT]
inc_INET esi inc_INET esi
mov [ebx + SOCKET_head.lock], 0
; Send an ACK ; Send an ACK
mov eax, ebx
mov bl, TH_ACK mov bl, TH_ACK
call TCP_send_ack call TCP_send_ack
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_CLOSE_WAIT: stateTCB_CLOSE_WAIT:
DEBUGF 1,"TCBStateHandler: close_wait\n"
; Intentionally left empty ; Intentionally left empty
; socket_close_tcp handles this ; socket_close_tcp handles this
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_CLOSING: stateTCB_CLOSING:
DEBUGF 1,"TCBStateHandler: closingn\n"
; We can either receive an ACK of a fin, or a fin ; We can either receive an ACK of a fin, or a fin
test [edx + TCP_Packet.Flags], TH_ACK test [edx + TCP_Packet.Flags], TH_ACK
jz .exit jz .exit
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT
.exit: .exit:
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_LAST_ACK: stateTCB_LAST_ACK:
DEBUGF 1,"TCBStateHandler: last_ackn\n"
; Look at control flags - expecting an ACK ; Look at control flags - expecting an ACK
test [edx + TCP_Packet.Flags], TH_ACK test [edx + TCP_Packet.Flags], TH_ACK
jz .exit jz .exit
mov [ebx + SOCKET_head.lock], 0
; delete the socket ; delete the socket
stdcall net_socket_free, ebx stdcall net_socket_free, ebx
@ -866,13 +913,60 @@ stateTCB_LAST_ACK:
align 4 align 4
stateTCB_TIME_WAIT: stateTCB_TIME_WAIT:
DEBUGF 1,"TCBStateHandler: time_wait\n"
mov [ebx + SOCKET_head.lock], 0
ret ret
align 4 align 4
stateTCB_CLOSED: stateTCB_CLOSED:
DEBUGF 1,"TCBStateHandler: closed\n"
mov [ebx + SOCKET_head.lock], 0
ret ret
;---------------------------------------------------------------------------
;
; TCP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
TCP_API:
movzx eax, bh
shl eax, 2
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
.error:
mov eax, -1
ret
.packets_tx:
add eax, TCP_PACKETS_TX
mov eax, [eax]
ret
.packets_rx:
add eax, TCP_PACKETS_RX
mov eax, [eax]
ret

View File

@ -77,9 +77,6 @@ UDP_handler:
DEBUGF 1,"UDP_Handler\n" DEBUGF 1,"UDP_Handler\n"
; First validate, checksum: ; First validate, checksum:
DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4
mov [edx + UDP_Packet.Checksum], 0
pusha pusha
rol cx, 8 rol cx, 8
@ -89,19 +86,23 @@ UDP_handler:
push edi push edi
push esi push esi
mov di, [edx + UDP_Packet.Checksum]
mov [edx + UDP_Packet.Checksum], 0
mov esi, edx mov esi, edx
xor edx, edx xor edx, edx
call checksum_1 call checksum_1
; Checksum for pseudoheader
mov ecx, 12 mov ecx, 12
mov esi, esp mov esi, esp
call checksum_1 call checksum_1
add esp, 12 add esp, 12
call checksum_2 call checksum_2
cmp di, dx
popa popa
jne .dump
DEBUGF 1,"UDP Checksum is correct\n"
; Look for a socket where ; Look for a socket where
; IP Packet UDP Destination Port = local Port ; IP Packet UDP Destination Port = local Port
@ -207,8 +208,7 @@ UDP_socket_send:
sub esp, 8 ; reserve some place in stack for later sub esp, 8 ; reserve some place in stack for later
; Create the pseudoheader in stack, ; Create a part pseudoheader in stack,
; (now that we still have all the variables that are needed.)
push dword IP_PROTO_UDP shl 8 push dword IP_PROTO_UDP shl 8
add ecx, UDP_Packet.Data add ecx, UDP_Packet.Data
@ -221,7 +221,7 @@ UDP_socket_send:
je .fail je .fail
mov [esp + 8 + 4], eax ; pointer to buffer start mov [esp + 8 + 4], eax ; pointer to buffer start
mov [esp + 8 + 4 + 4], edx ; buffer size mov [esp + 8 + 4 + 4], edx ; buffer size
rol cx, 8 rol cx, 8
mov [edi + UDP_Packet.Length], cx mov [edi + UDP_Packet.Length], cx
@ -239,7 +239,7 @@ UDP_socket_send:
rep movsb rep movsb
pop ecx edi pop ecx edi
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
; Checksum for UDP header + data ; Checksum for UDP header + data
@ -247,8 +247,8 @@ UDP_socket_send:
mov esi, edi mov esi, edi
call checksum_1 call checksum_1
; Checksum for pseudoheader ; Checksum for pseudoheader
pushd [edi-4] ; destination address pushd [edi-4] ; destination address
pushd [edi-8] ; source address pushd [edi-8] ; source address
mov ecx, 12 mov ecx, 12
mov esi, esp mov esi, esp
call checksum_1 call checksum_1