/kernel/branches/net/drivers/pcnet32.asm |
---|
1138,8 → 1138,8 |
;; ;; |
;; Transmit ;; |
;; ;; |
;; In: buffer pointer in [esp+4] ;; |
;; size of buffer in [esp+8] ;; |
;; In: buffer pointer in [esp] ;; |
;; size of buffer in [esp+4] ;; |
;; pointer to device structure in ebx ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1147,15 → 1147,15 |
align 4 |
transmit: |
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4] |
mov eax, [esp+4] |
mov eax, [esp] |
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+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
[eax+13]:2,[eax+12]:2 |
cmp dword [esp+8], 1514 |
cmp dword [esp+4], 1514 |
jg .finish ; packet is too long |
cmp dword [esp+8], 60 |
cmp dword [esp+4], 60 |
jl .finish ; packet is too short |
; check descriptor |
1167,8 → 1167,8 |
test byte [eax + buf_head.status + 1], 80h |
jnz .nospace |
; descriptor is free, copy data |
mov esi, [esp+4] |
mov ecx, [esp+8] |
mov esi, [esp] |
mov ecx, [esp+4] |
mov edx, ecx |
shr ecx, 2 |
and edx, 3 |
1176,7 → 1176,7 |
mov ecx, edx |
rep movsb |
; set length |
mov ecx, [esp+8] |
mov ecx, [esp+4] |
neg ecx |
mov [eax + buf_head.length], cx |
; put to transfer queue |
1195,11 → 1195,15 |
.finish: |
DEBUGF 2," - Done!\n" |
;;; call KernelFree |
add esp, 4+4 ; pop (balance stack) |
ret |
.nospace: |
DEBUGF 1, 'ERROR: no free transmit descriptors\n' |
; todo: maybe somehow notify the kernel about the error? |
add esp, 4+4 |
ret |
/kernel/branches/net/drivers/sis900.asm |
---|
1249,8 → 1249,8 |
; transmit |
; Description |
; Transmits a packet of data via the ethernet card |
; buffer pointer in [esp+4] |
; size of buffer in [esp+8] |
; buffer pointer in [esp] |
; size of buffer in [esp+4] |
; pointer to device structure in ebx |
; |
; only one transmit descriptor is used |
1263,9 → 1263,9 |
str1 db 'Transmitting packet:',13,10,0 |
str2 db ' ',0 |
transmit: |
cmp dword [esp+8], MAX_ETH_FRAME_SIZE |
cmp dword [esp+4], MAX_ETH_FRAME_SIZE |
jg transmit_finish |
cmp dword [esp+8], 60 |
cmp dword [esp+4], 60 |
jl transmit_finish |
push ebp |
mov ebp, [ebx+device.io_addr] ; Base Address |
1281,9 → 1281,9 |
add eax, device.txd |
out dx, eax |
;******* copy packet to descriptor******* |
mov esi, [esp+8] |
mov esi, [esp+4] |
lea edi, [ebx+0x1000] |
mov ecx, [esp+12] |
mov ecx, [esp+8] |
mov edx, ecx |
shr ecx, 2 |
and edx, 3 |
1291,7 → 1291,7 |
mov ecx, edx |
rep movsb |
;**************set length tag************** |
mov ecx, [esp+12] ;restore packet size |
mov ecx, [esp+8] ;restore packet size |
and ecx, SIS900_DSIZE ; |
inc [ebx+device.packets_tx] |
add dword [ebx+device.bytes_tx], ecx |
1331,6 → 1331,8 |
SIS900_transmit_OK: |
pop ebp |
transmit_finish: |
call KernelFree |
add esp, 4 |
ret |
;*************************************************************************** |
/kernel/branches/net/drivers/RTL8029.asm |
---|
758,7 → 758,7 |
;*************************************************************************** |
; Function |
; transmit |
; buffer in [esp+4], size in [esp+8], pointer to device struct in ebx |
; buffer in [esp], size in [esp+4], pointer to device struct in ebx |
;*************************************************************************** |
align 4 |
765,14 → 765,14 |
transmit: |
mov ebp, ebx |
mov esi, [esp + 4] |
mov ecx, [esp + 8] |
mov esi, [esp] |
mov ecx, [esp + 4] |
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 |
cmp dword [esp + 8], ETH_FRAME_LEN |
cmp dword [esp+4], ETH_FRAME_LEN |
jg .finish ; packet is too long |
cmp dword [esp + 8], 60 |
cmp dword [esp+4], 60 |
jl .finish ; packet is too short |
xor bl, bl |
804,12 → 804,15 |
DEBUGF 2," - Packet Sent!\n" |
inc [ebp+device.packets_tx] ; |
mov eax, [esp + 8] ; Get packet size in eax |
mov eax, [esp+4] ; Get packet size in eax |
add dword [ebp + device.bytes_tx], eax |
adc dword [ebp + device.bytes_tx + 4], 0 |
.finish: |
mov ebx, ebp |
call KernelFree |
add esp, 4 ; pop (balance stack) |
xor eax, eax |
ret |
/kernel/branches/net/drivers/RTL8139.asm |
---|
7,8 → 7,7 |
;; ;; |
;; Written by hidnplayr@kolibrios.org ;; |
;; ;; |
;; 0.1 - x march 2009 ;; |
;; 0.2 - 8 november 2009 ;; |
;; v0.1 - march 2009 ;; |
;; ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
15,6 → 14,8 |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision$ |
format MS COFF |
API_VERSION equ 0x01000100 |
765,8 → 766,8 |
;; ;; |
;; Transmit ;; |
;; ;; |
;; In: buffer pointer in [esp+4] ;; |
;; size of buffer in [esp+8] ;; |
;; In: buffer pointer in [esp] ;; |
;; size of buffer in [esp+4] ;; |
;; pointer to device structure in ebx ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
773,16 → 774,16 |
align 4 |
transmit: |
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp+4],[esp+8] |
mov eax, [esp+4] |
DEBUGF 1,"Transmitting packet, buffer:%x, size:%u\n",[esp],[esp+4] |
mov eax, [esp] |
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+06]:2,[eax+07]:2,[eax+08]:2,[eax+09]:2,[eax+10]:2,[eax+11]:2,\ |
[eax+13]:2,[eax+12]:2 |
cmp dword [esp+8], MAX_ETH_FRAME_SIZE |
cmp dword [esp+4], MAX_ETH_FRAME_SIZE |
jg .finish ; packet is too long |
cmp dword [esp+8], 60 |
cmp dword [esp+4], 60 |
jl .finish ; packet is too short |
; check descriptor |
821,16 → 822,16 |
add edi, eax ; Store it in edi |
pop edx |
mov esi, [esp+4] ; Copy data to that address |
mov ecx, [esp+8] ; |
mov esi, [esp] ; Copy data to that address |
mov ecx, [esp+4] ; |
shr ecx, 2 ; |
rep movsd ; |
mov ecx, [esp+8] ; |
mov ecx, [esp+4] ; |
and ecx, 3 ; |
rep movsb ; |
inc [ebx+device.packets_tx] ; |
mov eax, [esp+8] ; Get packet size in eax |
mov eax, [esp+4] ; Get packet size in eax |
add dword [ebx + device.bytes_tx], eax |
adc dword [ebx + device.bytes_tx + 4], 0 |
845,6 → 846,9 |
DEBUGF 2," - Packet Sent! " |
.finish: |
DEBUGF 2," - Done!\n" |
call KernelFree |
add esp, 4 ; pop (balance stack) |
ret |
/kernel/branches/net/network/IPv4.inc |
---|
123,6 → 123,7 |
; save checksum, and clear it in original packet |
mov di , [edx + IPv4_Packet.HeaderChecksum] |
DEBUGF 1,"checksum: %x\n",di |
mov word [edx + IPv4_Packet.HeaderChecksum], 0 |
; Re-calculate checksum |
139,8 → 140,6 |
pop ebx edx |
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 edi, BROADCAST |
mov ecx, MAX_IP+1 |
158,7 → 157,7 |
.ip_ok: |
call ETH_struc2dev ; TODO: make this work on other protocols too! |
inc [IP_PACKETS_RX+4*edi] |
DEBUGF 1,"packet comes from %u.%u.%u.%u\n",\ |
DEBUGF 1,"IP_Handler - packet 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 |
mov al , [edx + IPv4_Packet.VersionAndIHL] |
190,8 → 189,10 |
add eax, edx |
push eax |
mov al , [edx + IPv4_Packet.Protocol] |
;----------------------- experimental |
mov esi, [edx + IPv4_Packet.SourceAddress] |
mov edi, [edx + IPv4_Packet.DestinationAddress] |
;----------------------- |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
cmp al , IP_PROTO_TCP |
203,7 → 204,7 |
cmp al , IP_PROTO_ICMP |
je ICMP_handler |
DEBUGF 1,"unknown protocol: %u\n",al |
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
.dump: |
DEBUGF 1,"IP_Handler - done\n" |
401,8 → 402,10 |
add eax, edx |
push eax |
mov al , [edx + IPv4_Packet.Protocol] |
;----------------------- experimental |
mov esi, [edx + IPv4_Packet.SourceAddress] |
mov edi, [edx + IPv4_Packet.DestinationAddress] |
;----------------------- |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
cmp al , IP_PROTO_TCP |
/kernel/branches/net/network/stack.inc |
---|
32,7 → 32,7 |
ETHER equ 1337 |
ETHER_ARP equ 0x0608 |
AF_UNSPEC equ 0 |
;AF_UNSPEC equ 0 |
AF_UNIX equ 1 |
AF_INET4 equ 2 |
;AF_AX25 equ 3 |
55,47 → 55,10 |
SOCK_DGRAM = 2 |
SOCK_RAW = 3 |
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 |
; TCP opening modes |
SOCKET_PASSIVE equ 0 |
SOCKET_ACTIVE equ 1 |
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 "ARP.inc" |
include "IPv4.inc" |
127,7 → 90,7 |
call ICMP_init |
call socket_init |
mov al, 0 ; set up 1s timer |
mov al, 0x0 ; set up 1s timer |
out 0x70, al |
in al, 0x71 |
mov [last_1sTick], al |
153,7 → 116,7 |
cmp [ETH_RUNNING], 0 |
je .exit |
; Test for 1/100 s (10ms) tick |
; Test for 10ms tick |
mov eax, [timer_ticks] |
cmp eax, [last_1hsTick] |
je .exit |
166,8 → 129,8 |
.sec_tick: |
; Test for 1 second tick |
mov al, 0 |
; Test for 1 second event |
mov al, 0x0 ;second |
out 0x70, al |
in al, 0x71 |
cmp al, [last_1sTick] |
373,7 → 336,7 |
je UDP_API |
cmp ax , IP_PROTO_TCP |
je TCP_API |
; je TCP_API |
cmp ax , ETHER_ARP |
je ARP_API |
/kernel/branches/net/network/udp.inc |
---|
77,6 → 77,9 |
DEBUGF 1,"UDP_Handler\n" |
; First validate, checksum: |
DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4 |
mov [edx + UDP_Packet.Checksum], 0 |
pusha |
rol cx, 8 |
86,12 → 89,10 |
push edi |
push esi |
mov di, [edx + UDP_Packet.Checksum] |
mov [edx + UDP_Packet.Checksum], 0 |
mov esi, edx |
xor edx, edx |
call checksum_1 |
; Checksum for pseudoheader |
mov ecx, 12 |
mov esi, esp |
call checksum_1 |
98,12 → 99,10 |
add esp, 12 |
call checksum_2 |
cmp di, dx |
popa |
jne .dump |
DEBUGF 1,"UDP Checksum is correct\n" |
; Look for a socket where |
; IP Packet UDP Destination Port = local Port |
; IP Packet SA = Remote IP |
208,7 → 207,8 |
sub esp, 8 ; reserve some place in stack for later |
; Create a part pseudoheader in stack, |
; Create the pseudoheader in stack, |
; (now that we still have all the variables that are needed.) |
push dword IP_PROTO_UDP shl 8 |
add ecx, UDP_Packet.Data |
/kernel/branches/net/network/ethernet.inc |
---|
327,18 → 327,28 |
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome |
push ETH_send_queued ; this will cause the procedure to check for more packets |
; when a single packet is handled |
push ETH_send_queued |
mov ebx, [esi] |
pushd [esi + 8] |
pushd [esi + 4] |
lodsd |
mov ebx, eax |
sub esp, 8 |
mov edi, esp |
movsd |
movsd |
DEBUGF 1,"dequeued packet for device %x\n", ebx |
call [ebx+ETH_DEVICE.transmit] ; we will return to get_from_queue macro after transmitting packet |
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted) |
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 |
add esp, 4 ; pop (balance stack) |
DEBUGF 1,"ETH_Sender - fail\n" |
.gohome: |
ret |
/kernel/branches/net/network/queue.inc |
---|
42,7 → 42,7 |
.retries dd ? |
.owner dd ? |
.sendproc dd ? |
.seq_num dd ? |
.ack_num dd ? |
.size: |
ends |
/kernel/branches/net/network/socket.inc |
---|
43,15 → 43,12 |
.RemotePort dw ? ; In INET byte order |
.backlog dw ? ; Backlog |
; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.wndsizeTimer dd ? ; window size timer |
; Transmission control block |
.state dd ? ; TCB state |
.timer dd ? ; TCB timer (seconds) |
.ISS dd ? ; initial send sequence number |
.IRS dd ? ; initial receive sequence number |
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.TCBState dd ? ; TCB state |
.TCBTimer dd ? ; TCB timer (seconds) |
.ISS dd ? ; initial send sequence |
.IRS dd ? ; initial receive sequence |
.SND_UNA dd ? ; sequence number of unack'ed sent Packets |
.SND_NXT dd ? ; next send sequence number to use |
.SND_WND dd ? ; send window |
59,6 → 56,7 |
.RCV_WND dd ? ; receive window |
.SEG_LEN dd ? ; segment length |
.SEG_WND dd ? ; segment window |
.wndsizeTimer dd ? ; window size timer |
.flags db ? ; packet flags |
123,33 → 121,36 |
ret |
;----------------------------------------------- |
;----------------------------------------------------------------------------- |
; |
; Socket API (function 74) |
; |
;----------------------------------------------- |
;----------------------------------------------------------------------------- |
align 4 |
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: |
mov dword [esp+32],-1 |
156,6 → 157,8 |
ret |
;----------------------------------------------- |
; |
; SOCKET_open |
183,8 → 186,6 |
stdcall net_socket_addr_to_num, eax |
DEBUGF 1,", socketnumber: %u\n", eax |
; TODO: if it is txcp socket, set state to TCB_CLOSED |
mov [esp+32], eax |
ret |
230,6 → 231,7 |
; TODO: write code here |
mov dword [esp+32],0 |
ret |
293,7 → 295,7 |
cmp eax, -1 |
jz s_error |
cmp esi, 8 |
cmp esi, 2 |
jl s_error |
cmp word [edx], AF_INET4 |
303,9 → 305,15 |
.af_inet4: |
cmp esi, 8 |
jl s_error |
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP |
je .udp |
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP |
je .icmp |
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP |
je .tcp |
324,49 → 332,92 |
mov dword [esp+32],0 |
ret |
.icmp: |
.tcp: |
; TODO: set sequence number to random value |
; TODO: write code here |
ret |
; fill in remote port and IP |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
; TODO: figure out WTF this is |
mov bx , word [edx + 2] |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], bx |
DEBUGF 1,"remote port: %x ",bx |
mov ebx, dword [edx + 4] |
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx |
.tcp: |
; check if local port and IP is ok |
;local sockAddr dd ? |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], 0 |
jne @f |
push [IP_LIST] ; device zero = default |
pop [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
@@: |
; cmp esi, SOCKET_PASSIVE |
; 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: |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], 0 |
jne @f |
; mov [eax + SOCKET.wndsizeTimer], 0 ; Reset the window timer. |
; |
; xchg bh, bl |
; mov [eax + SOCKET.LocalPort], bx |
; xchg ch, cl |
; 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 ecx, [eax + SOCKET_head.Type] |
call socket_find_port |
test bx, bx |
jz s_error |
; mov ebx, TCB_LISTEN |
; cmp esi, SOCKET_PASSIVE |
; je @f |
; mov ebx, TCB_SYN_SENT |
; @@: mov [eax + SOCKET.TCBState], ebx ; Indicate the state of the TCB |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort], bx |
@@: |
; cmp ebx, TCB_LISTEN |
; je .exit |
; Now, if we are in active mode, then we have to send a SYN to the specified remote port |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
; je .exit |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT |
; now say hello to the remote tcp socket |
; push eax |
mov bl, TH_SYN |
call TCP_send_ack |
; mov bl, TH_SYN |
; xor ecx, ecx |
; stdcall build_tcp_Packet, [sockAddr] |
mov dword [esp+32],0 |
; 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 |
.exit: |
xor eax, eax |
ret |
391,12 → 442,6 |
cmp eax, -1 |
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 |
jl .ok |
mov dx , 20 |
403,8 → 448,9 |
.ok: |
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 |
ret |
523,44 → 569,98 |
ret |
.tcp: |
; first, remove all resend entries for this socket |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN |
if 1 = 0 |
;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 |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT |
cmp [eax + SOCKET.TCBState], TCB_SYN_SENT |
je .destroy_tcb |
; 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 |
call TCP_send_ack |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
mov ebx, [sockAddr] |
; increament SND.NXT in socket |
lea esi, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
inc_INET esi |
lea esi, [ebx + SOCKET.SND_NXT] |
call inc_inet_esi |
; Get the socket state |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED |
mov eax, [ebx + SOCKET.TCBState] |
cmp eax, TCB_SYN_RECEIVED |
je .fin_wait_1 |
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED |
cmp eax, TCB_ESTABLISHED |
je .fin_wait_1 |
; assume CLOSE WAIT |
; Send a fin, then enter last-ack state |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK |
mov [ebx + SOCKET.TCBState], TCB_LAST_ACK |
jmp .send |
.fin_wait_1: |
; Send a fin, then enter finwait2 state |
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1 |
mov [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1 |
.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: |
stdcall net_socket_free, eax |
end if |
.exit: |
mov dword [esp+32],0 |
ret |
635,7 → 735,6 |
; OUT: -1 on error |
; |
;----------------------------------------------- |
align 4 |
socket_send: |
650,6 → 749,7 |
jmp s_error |
;--------- |
.af_inet4: |
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4 |
663,6 → 763,7 |
je .raw |
jmp s_error |
;-------- |
.udp: |
691,27 → 792,10 |
.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 |
ret |
;-------- |
.raw: |
cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP |
je .raw_ip |
720,12 → 804,11 |
je .raw_icmp |
jmp s_error |
;-------- |
.raw_ip: |
;;;;;; |
mov [esp+32], eax |
ret |
/kernel/branches/net/network/tcp.inc |
---|
17,9 → 17,30 |
$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_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_TIMEOUT equ 10 ; resend if not replied to in 1/100 s |
TCP_QUEUE_SIZE equ 16 |
52,7 → 73,7 |
align 4 |
iglobal |
stateHandler: |
TCBStateHandler: |
dd stateTCB_LISTEN |
dd stateTCB_SYN_SENT |
69,6 → 90,30 |
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 |
89,13 → 134,8 |
rep stosd |
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 |
125,9 → 165,9 |
cmp [ebx + SOCKET_head.Type], IP_PROTO_TCP |
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.state] |
; 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] |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], 0 |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], 0 |
jne .decrement_tcb |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 0 |
jne .decrement_wnd |
135,10 → 175,10 |
.decrement_tcb: |
; decrement it, delete socket if TCB timer = 0 & socket in timewait state |
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer] |
dec [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer] |
jnz .next_socket |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
jne .next_socket |
push [ebx + SOCKET_head.PrevPtr] |
191,33 → 231,30 |
dec [esi + tcp_out_queue_entry.ttl] |
jz .send_it |
.find_next: |
add esi, tcp_out_queue_entry.size |
dec eax |
jz .exit |
test ecx, ecx |
jnz .loop |
ret |
jmp .loop |
.send_it: |
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_ptr] |
DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc] |
mov ebx, [esi + tcp_out_queue_entry.owner] |
call [esi + tcp_out_queue_entry.sendproc] |
add esp, 8 |
pop esi ecx eax |
dec [esi + tcp_out_queue_entry.retries] |
jz .remove_it |
mov [esi + tcp_out_queue_entry.ttl], TCP_PACKET_TTL |
mov [esi + tcp_out_queue_entry.ttl], TCP_TIMEOUT |
jmp .find_next |
.remove_it: |
push [esi + tcp_out_queue_entry.data_ptr] |
mov [esi + tcp_out_queue_entry.data_ptr], 0 |
dec [TCP_OUT_QUEUE] |
call kernel_free |
jmp .find_next |
241,8 → 278,6 |
align 4 |
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 |
jge .full |
256,9 → 291,6 |
loop .loop |
.full: ; silently discard the packet |
DEBUGF 1,"TCP queue is full!\n" |
call kernel_free |
add esp, 4 |
272,13 → 304,9 |
mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES |
mov [eax + tcp_out_queue_entry.owner], ebx |
mov [eax + tcp_out_queue_entry.sendproc], esi |
mov [eax + tcp_out_queue_entry.seq_num], edx |
mov [eax + tcp_out_queue_entry.ack_num], edx |
inc [TCP_OUT_QUEUE] |
sub eax, TCP_OUT_QUEUE+4 |
DEBUGF 1,"Added to queue in pos %u\n", eax |
ret |
304,8 → 332,6 |
DEBUGF 1,"TCP_Handler\n" |
; TODO: validate checksum |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP OR = 0 |
; IP Packet TCP Source Port = remote Port OR = 0 |
332,12 → 358,10 |
cmp [edx + TCP_Packet.SourcePort] , ax |
je .change_state |
test ax, ax |
jnz .socket_loop |
jne .socket_loop |
.change_state: |
DEBUGF 1,"Found valid socket for packet\n" |
push ebx |
lea ebx, [ebx + SOCKET_head.lock] |
call wait_mutex |
349,37 → 373,29 |
; edx is pointer to tcp packet |
; as a Packet has been received, update the TCB timer |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBTimer], TWOMSL |
; 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 |
jz .call_handler ; No ACK, so no data yet |
; mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax |
; bswap eax ; |
; add eax, ecx ; |
mov eax, [edx + TCP_Packet.SequenceNumber] ; Calculate sequencenumber in eax |
bswap eax ; |
add eax, ecx ; |
mov eax, [edx + TCP_Packet.AckNumber] |
;--------- |
cmp [TCP_OUT_QUEUE], 0 |
je .call_handler |
push ecx |
DEBUGF 1,"Removing all queued packets with smaller ACK\n" |
mov ecx, TCP_QUEUE_SIZE |
mov esi, TCP_OUT_QUEUE+4 |
.loop: |
cmp [esi + tcp_out_queue_entry.data_ptr], 0 |
je .maybe_next |
cmp [esi + tcp_out_queue_entry.seq_num], eax |
jne .maybe_next |
cmp [esi + tcp_out_queue_entry.ack_num], eax |
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] |
mov [esi + tcp_out_queue_entry.data_ptr], 0 |
dec [TCP_OUT_QUEUE] |
388,24 → 404,25 |
.maybe_next: |
add esi, tcp_out_queue_entry.size |
loop .loop |
pop ecx |
pop ecx |
.call_handler: |
; Call handler for given TCB state |
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state] |
DEBUGF 1,"Socket state: %u\n", eax |
mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState] |
cmp eax, TCB_LISTEN |
jb .dump |
jb .exit |
cmp eax, TCB_CLOSED |
ja .dump |
ja .exit |
dec eax |
shl eax, 2 |
add eax, stateHandler |
add eax, TCBStateHandler - 4 |
call dword[eax] |
push .exit |
jmp eax |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
.dump: |
DEBUGF 1,"Dumping TCP packet\n" |
call kernel_free |
446,7 → 463,7 |
push ecx esi eax ; save some variables for later |
add ecx, TCP_Packet.Options |
add ecx, TCP_Packet.Data |
call IPv4_create_packet |
cmp edi, -1 |
je .fail |
468,7 → 485,7 |
mov al, [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.flags] |
mov [edi + TCP_Packet.Flags], al |
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes |
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes ;;; TODO: read RFC ! |
mov [edi + TCP_Packet.UrgentPointer], 0 |
mov [edi + TCP_Packet.DataOffset], 0x50 |
mov [edi + TCP_Packet.Checksum], 0 |
476,7 → 493,7 |
; Copy the data |
mov esi, [esp] |
mov ecx, [esp+4] |
add edi, TCP_Packet.Options |
add edi, TCP_Packet.Data |
shr ecx, 1 |
jnc .nb |
502,12 → 519,12 |
; And now, send it! |
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx |
lea esi, [ebx+ETH_DEVICE.transmit] |
mov esi, ETH_sender |
mov edx, [edi + TCP_Packet.AckNumber] |
jmp TCP_add_to_queue |
.fail: |
add esp, 12+12+4 |
add esp, 12+4 |
ret |
526,15 → 543,14 |
align 4 |
TCP_send_ack: |
DEBUGF 1,"Creating TCP ACK, socket: %x, flags: %x\n",eax, bl |
DEBUGF 1,"Creating TCP ACK\n" |
mov di , IP_PROTO_TCP |
mov ecx, TCP_Packet.Options |
mov cx , TCP_Packet.Data |
push bx eax |
; Create an IPv4 Packet of the correct size |
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] |
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
548,10 → 564,10 |
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
pop [edi + TCP_Packet.SequenceNumber] |
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] ; both ports at once |
push dword [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] |
pop dword [edi + TCP_Packet.SourcePort] |
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
push [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
pop [edi + TCP_Packet.AckNumber] |
pop cx |
559,39 → 575,32 |
mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes |
mov [edi + TCP_Packet.UrgentPointer], 0 |
mov [edi + TCP_Packet.DataOffset], 0x50 |
mov [edi + TCP_Packet.Checksum], 0 |
push edx eax |
push eax edx |
lea esi, [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
inc_INET esi |
push word TCP_Packet.Data shl 8 |
push IP_PROTO_TCP |
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 |
mov ecx, TCP_Packet.Options |
mov esi, edi |
call checksum_1 |
mov ecx, 12 |
mov esi, esp |
call checksum_1 |
add esp, 12 ; remove the pseudoheader from stack |
; and store it in TCP header |
; Now create the final checksum and store it in TCP header |
call checksum_2 |
mov [edi + TCP_Packet.Checksum], dx |
; And now, send the packet! |
; And now, send it! |
DEBUGF 1,"Sending TCP Packet to device %x\n", ebx |
mov esi, [ebx + ETH_DEVICE.transmit] |
mov edx, [edi + TCP_Packet.SequenceNumber] |
mov esi, ETH_sender |
mov edx, [edi + TCP_Packet.AckNumber] |
jmp TCP_add_to_queue |
.fail: |
add esp, 2+4 |
add esp, 12+4 |
ret |
600,9 → 609,6 |
align 4 |
stateTCB_LISTEN: |
DEBUGF 1,"TCBStateHandler: Listen\n" |
; In this case, we are expecting a SYN Packet |
; For now, if the Packet is a SYN, process it, and send a response |
; If not, ignore it |
625,13 → 631,11 |
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.lock], 0 |
; Now construct the response |
mov bl, TH_SYN + TH_ACK |
call TCP_send_ack |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED |
; increment SND.NXT in socket |
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] |
638,15 → 642,11 |
inc_INET esi |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
align 4 |
stateTCB_SYN_SENT: |
DEBUGF 1,"TCBStateHandler: Syn_Sent\n" |
; We are awaiting an ACK to our SYN, with a SYM |
; Look at control flags - expecting an ACK |
658,31 → 658,28 |
test al, TH_SYN |
jz .exit |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED |
pushd TH_SYN + TH_ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_SYN_RECEIVED |
push TH_SYN + TH_ACK |
jmp .send |
.syn_ack: |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED |
pushd TH_ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED |
push TH_ACK |
.send: |
; Store the recv.nxt field |
mov eax, [edx + TCP_Packet.SequenceNumber] |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.IRS], eax |
bswap eax |
inc eax |
bswap eax |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax ; Update our recv.nxt field |
mov [ebx + SOCKET_head.lock], 0 |
; Update our recv.nxt field |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
; Send an ACK |
mov eax, ebx |
pop ebx |
call TCP_send_ack |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
689,9 → 686,6 |
align 4 |
stateTCB_SYN_RECEIVED: |
DEBUGF 1,"TCBStateHandler: Syn_received\n" |
; In this case, we are expecting an ACK Packet |
; For now, if the Packet is an ACK, process it, |
; If not, ignore it |
699,12 → 693,12 |
test [edx + TCP_Packet.Flags], TH_RST |
jz .check_ack |
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort] |
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort] |
; push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP] |
; pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemotePort] |
pop [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort] |
push [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.OrigRemoteIP] |
pop [ebx + SOCKET_head.end + IPv4_SOCKET.RemoteIP] |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_LISTEN |
jmp .exit |
.check_ack: |
712,10 → 706,9 |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_ESTABLISHED |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
722,10 → 715,6 |
align 4 |
stateTCB_ESTABLISHED: |
DEBUGF 1,"TCBStateHandler: Established\n" |
; Here we are expecting data, or a request to close |
; OR both... |
735,7 → 724,6 |
; It was a fin or reset. |
;;; TODO: write following code: |
; Remove resend entries from the queue - I dont want to send any more data |
; Send an ACK to that fin, and enter closewait state |
744,8 → 732,6 |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
DEBUGF 1,"Received ACK\n" |
; 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. |
; ** I may need to tweak this value, since I do not know how many Packets are already queued |
766,7 → 752,7 |
; recv seq is in [sktAddr]+56, in inet format |
; just do a comparision |
mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT |
jne @f |
mov ecx, eax |
777,12 → 763,11 |
jnz .data |
; If we had received a fin, we need to ACK it. |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT |
cmp [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSE_WAIT |
je .ack |
jmp .exit |
.data: |
DEBUGF 1,"Got data!\n" |
mov esi, [esp + 4] |
sub edx, esi |
mov edi, edx |
789,14 → 774,10 |
call socket_internal_receiver |
.ack: |
mov [ebx + SOCKET_head.lock], 0 |
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
803,9 → 784,6 |
align 4 |
stateTCB_FIN_WAIT_1: |
DEBUGF 1,"TCBStateHandler: Fin_wait_1\n" |
; We can either receive an ACK of a fin, or a fin |
mov al, [edx + TCP_Packet.Flags] |
and al, TH_FIN + TH_ACK |
814,25 → 792,21 |
jne @f |
; It was an ACK |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_2 |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_FIN_WAIT_2 |
jmp .exit |
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING |
@@: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_CLOSING |
cmp al, TH_FIN |
je @f |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
@@: lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
mov [ebx + SOCKET_head.lock], 0 |
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
839,27 → 813,20 |
align 4 |
stateTCB_FIN_WAIT_2: |
DEBUGF 1,"TCBStateHandler: Fin_wait_2\n" |
test [edx + TCP_Packet.Flags], TH_FIN |
jz .exit |
; Change state, as we have a fin |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] |
inc_INET esi |
mov [ebx + SOCKET_head.lock], 0 |
; Send an ACK |
mov eax, ebx |
mov bl, TH_ACK |
call TCP_send_ack |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
866,12 → 833,8 |
align 4 |
stateTCB_CLOSE_WAIT: |
DEBUGF 1,"TCBStateHandler: close_wait\n" |
; Intentionally left empty |
; socket_close_tcp handles this |
mov [ebx + SOCKET_head.lock], 0 |
ret |
878,32 → 841,22 |
align 4 |
stateTCB_CLOSING: |
DEBUGF 1,"TCBStateHandler: closingn\n" |
; We can either receive an ACK of a fin, or a fin |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT |
mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.TCBState], TCB_TIMED_WAIT |
.exit: |
mov [ebx + SOCKET_head.lock], 0 |
ret |
align 4 |
stateTCB_LAST_ACK: |
DEBUGF 1,"TCBStateHandler: last_ackn\n" |
; Look at control flags - expecting an ACK |
test [edx + TCP_Packet.Flags], TH_ACK |
jz .exit |
mov [ebx + SOCKET_head.lock], 0 |
; delete the socket |
stdcall net_socket_free, ebx |
913,60 → 866,13 |
align 4 |
stateTCB_TIME_WAIT: |
DEBUGF 1,"TCBStateHandler: time_wait\n" |
mov [ebx + SOCKET_head.lock], 0 |
ret |
align 4 |
stateTCB_CLOSED: |
DEBUGF 1,"TCBStateHandler: closed\n" |
mov [ebx + SOCKET_head.lock], 0 |
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 |