forked from KolibriOS/kolibrios
Deleted double macro in netdrv.inc
Refactoring of ARP code. Used universal names for protocol handlers. Moved some pieces of code from procs to macros. Added IPv4_fragment (currently disabled) Added ring-buffer functions for sockets Updates in TCP code git-svn-id: svn://kolibrios.org@1529 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
f01c3da0f2
commit
fab920c5c8
@ -82,7 +82,7 @@ iglobal
|
|||||||
szNetUnRegDev db 'NetUnRegDev',0
|
szNetUnRegDev db 'NetUnRegDev',0
|
||||||
szNetPtrToNum db 'NetPtrToNum',0
|
szNetPtrToNum db 'NetPtrToNum',0
|
||||||
szEthReceiver db 'EthReceiver',0
|
szEthReceiver db 'EthReceiver',0
|
||||||
szIPv4Handler db 'IPv4Handler',0
|
szIPv4_input db 'IPv4_input',0
|
||||||
|
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
@ -155,8 +155,8 @@ kernel_export:
|
|||||||
dd szNetRegDev , NET_add_device
|
dd szNetRegDev , NET_add_device
|
||||||
dd szNetUnRegDev , NET_remove_device
|
dd szNetUnRegDev , NET_remove_device
|
||||||
dd szNetPtrToNum , NET_ptr_to_num
|
dd szNetPtrToNum , NET_ptr_to_num
|
||||||
dd szEthReceiver , ETH_receiver
|
dd szEthReceiver , ETH_input
|
||||||
dd szIPv4Handler , IPv4_handler
|
dd szIPv4_input , IPv4_input
|
||||||
|
|
||||||
exp_lfb:
|
exp_lfb:
|
||||||
dd szLFBAddress , 0
|
dd szLFBAddress , 0
|
||||||
|
@ -35,22 +35,15 @@
|
|||||||
macro set_io addr {
|
macro set_io addr {
|
||||||
|
|
||||||
if addr = 0
|
if addr = 0
|
||||||
|
|
||||||
mov edx, [device.io_addr]
|
mov edx, [device.io_addr]
|
||||||
|
|
||||||
else if addr = LAST_IO
|
else if addr = LAST_IO
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
add edx, addr - LAST_IO
|
add edx, addr - LAST_IO
|
||||||
|
|
||||||
end if
|
end if
|
||||||
|
|
||||||
LAST_IO = addr
|
LAST_IO = addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
macro allocate_and_clear dest, size, err {
|
macro allocate_and_clear dest, size, err {
|
||||||
|
|
||||||
; We need to allocate at least 8 pages, if we want a continuous memory in ram
|
; We need to allocate at least 8 pages, if we want a continuous memory in ram
|
||||||
@ -83,8 +76,6 @@ macro allocate_and_clear dest, size, err {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
macro find_io bus, dev, io {
|
macro find_io bus, dev, io {
|
||||||
|
|
||||||
local .check, .inc, .got
|
local .check, .inc, .got
|
||||||
@ -126,7 +117,6 @@ macro find_irq bus, dev, irq {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro find_rev bus, dev, rev {
|
macro find_rev bus, dev, rev {
|
||||||
|
|
||||||
push eax edx ecx
|
push eax edx ecx
|
||||||
@ -138,8 +128,6 @@ macro find_rev bus, dev, rev {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
macro make_bus_master bus, dev {
|
macro make_bus_master bus, dev {
|
||||||
|
|
||||||
movzx ecx, bus
|
movzx ecx, bus
|
||||||
@ -168,10 +156,7 @@ virtual at edx
|
|||||||
end virtual
|
end virtual
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if used null_op
|
if used null_op
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
null_op:
|
null_op:
|
||||||
or eax, -1
|
or eax, -1
|
||||||
@ -180,11 +165,11 @@ null_op:
|
|||||||
end if
|
end if
|
||||||
|
|
||||||
|
|
||||||
macro virt_to_dma { ; input is eax
|
macro GetRealAddr { ; input is eax
|
||||||
|
|
||||||
push ax
|
push ax
|
||||||
and word[esp], PAGESIZE - 1
|
|
||||||
call GetPgAddr
|
call GetPgAddr
|
||||||
|
and word[esp], PAGESIZE - 1
|
||||||
or ax, word[esp]
|
or ax, word[esp]
|
||||||
inc esp
|
inc esp
|
||||||
inc esp
|
inc esp
|
||||||
@ -209,7 +194,7 @@ macro NET_DEVICE {
|
|||||||
.end:
|
.end:
|
||||||
}
|
}
|
||||||
|
|
||||||
;struc ETH_DEVICE {
|
|
||||||
macro ETH_DEVICE {
|
macro ETH_DEVICE {
|
||||||
NET_DEVICE
|
NET_DEVICE
|
||||||
|
|
||||||
@ -236,15 +221,3 @@ macro SLIP_DEVICE {
|
|||||||
.mode dd ?
|
.mode dd ?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro GetRealAddr {
|
|
||||||
|
|
||||||
push eax
|
|
||||||
call GetPgAddr
|
|
||||||
and dword [esp], (PAGESIZE - 1)
|
|
||||||
or eax, dword [esp]
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,19 +16,15 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
||||||
$Revision$
|
$Revision$
|
||||||
|
|
||||||
|
|
||||||
ARP_NO_ENTRY equ 0
|
ARP_NO_ENTRY equ 0
|
||||||
ARP_VALID_MAPPING equ 1
|
ARP_VALID_MAPPING equ 1
|
||||||
ARP_AWAITING_RESPONSE equ 2
|
ARP_AWAITING_RESPONSE equ 2
|
||||||
ARP_RESPONSE_TIMEOUT equ 3
|
ARP_RESPONSE_TIMEOUT equ 3
|
||||||
|
|
||||||
ARP_REQUEST_TTL = 20 ; in seconds
|
ARP_REQUEST_TTL equ 31 ; 20 s
|
||||||
ARP_ENTRY_TTL = 600 ; in seconds
|
ARP_ENTRY_TTL equ 937 ; 600 s
|
||||||
|
|
||||||
ETHER_ARP equ 0x0608
|
|
||||||
|
|
||||||
ARP_REQ_OPCODE equ 0x0100 ; request
|
ARP_REQ_OPCODE equ 0x0100 ; request
|
||||||
ARP_REP_OPCODE equ 0x0200 ; reply
|
ARP_REP_OPCODE equ 0x0200 ; reply
|
||||||
@ -39,7 +35,7 @@ struct ARP_ENTRY
|
|||||||
.IP dd ?
|
.IP dd ?
|
||||||
.MAC dp ?
|
.MAC dp ?
|
||||||
.Status dw ?
|
.Status dw ?
|
||||||
.TTL dw ? ; in seconds
|
.TTL dw ?
|
||||||
.size:
|
.size:
|
||||||
ends
|
ends
|
||||||
|
|
||||||
@ -53,26 +49,16 @@ struct ARP_Packet
|
|||||||
.SenderIP dd ?
|
.SenderIP dd ?
|
||||||
.TargetMAC dp ?
|
.TargetMAC dp ?
|
||||||
.TargetIP dd ?
|
.TargetIP dd ?
|
||||||
|
.size:
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
|
||||||
; The TTL field is decremented every second, and is deleted when it
|
|
||||||
; reaches 0. It is refreshed every time a packet is received
|
|
||||||
; If the TTL field is 0xFFFF it is a static entry and is never deleted
|
|
||||||
; The status field can be the following values:
|
|
||||||
; 0x0000 entry not used
|
|
||||||
; 0x0001 entry holds a valid mapping
|
|
||||||
; 0x0002 entry contains an IP address, awaiting ARP response
|
|
||||||
; 0x0003 No response received to ARP request.
|
|
||||||
; The last status value is provided to allow the network layer to delete
|
|
||||||
; a packet that is queued awaiting an ARP response
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
uglobal
|
uglobal
|
||||||
|
|
||||||
NumARP dd ?
|
NumARP dd ?
|
||||||
|
|
||||||
ARPTable rb ARP_ENTRY.size * ARP_TABLE_SIZE
|
ARP_table rb ARP_ENTRY.size * ARP_TABLE_SIZE
|
||||||
|
|
||||||
ARP_PACKETS_TX rd MAX_NET_DEVICES
|
ARP_PACKETS_TX rd MAX_NET_DEVICES
|
||||||
ARP_PACKETS_RX rd MAX_NET_DEVICES
|
ARP_PACKETS_RX rd MAX_NET_DEVICES
|
||||||
@ -88,379 +74,81 @@ endg
|
|||||||
;
|
;
|
||||||
; This function resets all ARP variables
|
; This function resets all ARP variables
|
||||||
;
|
;
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
macro ARP_init {
|
||||||
ARP_init:
|
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
|
|
||||||
mov [NumARP], eax
|
mov [NumARP], eax
|
||||||
|
|
||||||
mov edi, ARP_PACKETS_TX
|
mov edi, ARP_PACKETS_TX
|
||||||
mov ecx, 2*MAX_NET_DEVICES
|
mov ecx, 2*MAX_NET_DEVICES
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
ret
|
}
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; ARP_IP_to_MAC
|
|
||||||
;
|
|
||||||
; This function resets all ARP variables
|
|
||||||
;
|
|
||||||
; IN: eax = IPv4 address
|
|
||||||
; OUT: eax = -1 on error, else eax = first two bytes of mac
|
|
||||||
; ( high 16 bits are zero)
|
|
||||||
; ebx = last four bytes of mac ; TODO: special eax value for 'request send'
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
align 4
|
|
||||||
ARP_IP_to_MAC:
|
|
||||||
|
|
||||||
DEBUGF 1,"ARP_IP_to_MAC\n"
|
|
||||||
|
|
||||||
; first, check destination IP to see if it is on 'this' network.
|
|
||||||
; The test is:
|
|
||||||
; if ( destIP & subnet_mask == stack_ip & subnet_mask )
|
|
||||||
; destination is local
|
|
||||||
; else
|
|
||||||
; destination is remote, so pass to gateway
|
|
||||||
|
|
||||||
xor edx, edx ;;; TODO: find device num in edx
|
|
||||||
|
|
||||||
mov ebx, [IP_LIST + edx]
|
|
||||||
and ebx, [SUBNET_LIST + edx]
|
|
||||||
|
|
||||||
mov ecx, eax
|
|
||||||
and ecx, [SUBNET_LIST + edx]
|
|
||||||
|
|
||||||
cmp ecx, ebx
|
|
||||||
je .local
|
|
||||||
|
|
||||||
mov eax, [GATEWAY_LIST + edx]
|
|
||||||
DEBUGF 1,"requested IP is not on subnet, using gateway\n"
|
|
||||||
|
|
||||||
.local:
|
|
||||||
; try to find it on the list
|
|
||||||
mov ecx, [NumARP]
|
|
||||||
test ecx, ecx
|
|
||||||
jz .not_in_list
|
|
||||||
mov esi, ARPTable + ARP_ENTRY.IP
|
|
||||||
.scan_loop:
|
|
||||||
cmp [esi], eax
|
|
||||||
je .found_it
|
|
||||||
add esi, ARP_ENTRY.size
|
|
||||||
loop .scan_loop
|
|
||||||
.not_in_list:
|
|
||||||
|
|
||||||
DEBUGF 1,"IP not found on list, preparing for ARP request\n"
|
|
||||||
|
|
||||||
; if not, reserve an entry in list and send an ARP request packet
|
|
||||||
|
|
||||||
push eax
|
|
||||||
|
|
||||||
pushw ARP_REQUEST_TTL
|
|
||||||
pushw ARP_AWAITING_RESPONSE
|
|
||||||
pushd 0
|
|
||||||
pushw 0
|
|
||||||
pushd eax
|
|
||||||
call ARP_add_entry
|
|
||||||
cmp eax, -1
|
|
||||||
je .full
|
|
||||||
|
|
||||||
; <Some dirty test code>
|
|
||||||
|
|
||||||
; This piece of code waits for an ARP reply
|
|
||||||
|
|
||||||
mov ebx, eax
|
|
||||||
pop eax
|
|
||||||
push ebx
|
|
||||||
call ARP_create_request
|
|
||||||
|
|
||||||
push [timer_ticks]
|
|
||||||
add dword[esp], 100*ARP_REQUEST_TTL
|
|
||||||
DEBUGF 1,"Waiting for ARP reply, time: %x, entry:%u\n",[timer_ticks], [esp + 4]
|
|
||||||
.dirty_loop:
|
|
||||||
|
|
||||||
call change_task ; The ARP reply hasnt been received yet, tell the processor to do some other stuff first
|
|
||||||
|
|
||||||
mov eax, [esp + 4]
|
|
||||||
imul eax, ARP_ENTRY.size
|
|
||||||
add eax, ARPTable
|
|
||||||
cmp [eax + ARP_ENTRY.Status], ARP_VALID_MAPPING
|
|
||||||
je .gogogo
|
|
||||||
|
|
||||||
mov eax, [esp] ; Check if the reply hasnt timed-out yet
|
|
||||||
cmp [timer_ticks], eax
|
|
||||||
jl .dirty_loop
|
|
||||||
|
|
||||||
; </Some dirty test code>
|
|
||||||
or eax, -1
|
|
||||||
add esp, 8
|
|
||||||
ret
|
|
||||||
|
|
||||||
.found_it:
|
|
||||||
DEBUGF 1,"found MAC in ARPTable\n"
|
|
||||||
movzx eax, word [esi+ARP_ENTRY.MAC]
|
|
||||||
mov ebx, dword[esi+ARP_ENTRY.MAC+2]
|
|
||||||
ret
|
|
||||||
|
|
||||||
.full:
|
|
||||||
add esp, 4
|
|
||||||
mov eax, -1
|
|
||||||
ret
|
|
||||||
|
|
||||||
.gogogo:
|
|
||||||
DEBUGF 1,"got ARP reply, time: %x\n",[timer_ticks]
|
|
||||||
mov ebx, dword[eax+ARP_ENTRY.MAC+2]
|
|
||||||
movzx eax, word [eax+ARP_ENTRY.MAC]
|
|
||||||
add esp, 8
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; ARP_create_request
|
|
||||||
;
|
|
||||||
; IN: ip in eax
|
|
||||||
;
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;---------------------------------------------------------------------------
|
|
||||||
align 4
|
|
||||||
ARP_create_request:
|
|
||||||
|
|
||||||
DEBUGF 1,"Create ARP Packet\n"
|
|
||||||
|
|
||||||
call IPv4_dest_to_dev
|
|
||||||
|
|
||||||
push eax ; DestIP
|
|
||||||
mov eax, [IP_LIST+4*edi] ; senderIP
|
|
||||||
push eax
|
|
||||||
|
|
||||||
mov edi, [NET_DRV_LIST + 4*edi]
|
|
||||||
lea eax, [edi + ETH_DEVICE.mac]
|
|
||||||
mov ebx, ETH_BROADCAST
|
|
||||||
mov ecx, 60 ; minimum packet size
|
|
||||||
mov edx, edi ;;;
|
|
||||||
mov di , ETHER_ARP
|
|
||||||
call ETH_create_packet
|
|
||||||
jz .exit
|
|
||||||
|
|
||||||
mov ecx, eax
|
|
||||||
|
|
||||||
mov [edi + ARP_Packet.HardwareType], 0x0100 ;Ethernet
|
|
||||||
mov [edi + ARP_Packet.ProtocolType], 0x0008 ;IP
|
|
||||||
mov [edi + ARP_Packet.HardwareSize], 6 ;MAC-addr length
|
|
||||||
mov [edi + ARP_Packet.ProtocolSize], 4 ;IP-addr length
|
|
||||||
mov [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE ;Request
|
|
||||||
|
|
||||||
add edi, ARP_Packet.SenderMAC ; sendermac
|
|
||||||
lea esi, [ebx + ETH_DEVICE.mac] ;
|
|
||||||
movsw ;
|
|
||||||
movsd ;
|
|
||||||
pop eax ;
|
|
||||||
stosd ;
|
|
||||||
mov eax, -1 ; destmac
|
|
||||||
stosd ;
|
|
||||||
stosw ;
|
|
||||||
pop eax
|
|
||||||
stosd ;
|
|
||||||
|
|
||||||
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
|
|
||||||
|
|
||||||
push edx ecx
|
|
||||||
call [ebx + NET_DEVICE.transmit]
|
|
||||||
ret
|
|
||||||
|
|
||||||
.exit:
|
|
||||||
add esp, 8
|
|
||||||
DEBUGF 1,"Create ARP Packet - failed\n"
|
|
||||||
mov eax, -1
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; ARP_decrease_entry_ttls
|
; ARP_decrease_entry_ttls
|
||||||
;
|
;
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
align 4
|
|
||||||
ARP_decrease_entry_ttls:
|
macro ARP_decrease_entry_ttls {
|
||||||
|
|
||||||
|
local .loop
|
||||||
|
local .exit
|
||||||
|
|
||||||
|
; The TTL field is decremented every second, and is deleted when it reaches 0.
|
||||||
|
; It is refreshed every time a packet is received.
|
||||||
|
; If the TTL field is 0xFFFF it is a static entry and is never deleted.
|
||||||
|
; The status field can be the following values:
|
||||||
|
; 0x0000 entry not used
|
||||||
|
; 0x0001 entry holds a valid mapping
|
||||||
|
; 0x0002 entry contains an IP address, awaiting ARP response
|
||||||
|
; 0x0003 No response received to ARP request.
|
||||||
|
; The last status value is provided to allow the network layer to delete
|
||||||
|
; a packet that is queued awaiting an ARP response
|
||||||
|
|
||||||
mov ecx, [NumARP]
|
mov ecx, [NumARP]
|
||||||
test ecx, ecx
|
test ecx, ecx
|
||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
mov ebx, ARPTable
|
mov esi, ARP_table
|
||||||
|
.loop:
|
||||||
|
cmp [esi + ARP_ENTRY.TTL], 0xffff ; 0xffff = static entry
|
||||||
|
je .next
|
||||||
|
|
||||||
.timer_loop:
|
dec [esi + ARP_ENTRY.TTL]
|
||||||
|
jz .time_out
|
||||||
|
|
||||||
cmp [ebx + ARP_ENTRY.TTL], 0xFFFF
|
.next:
|
||||||
je .timer_loop_end ;if TTL==0xFFFF then it's static entry
|
|
||||||
|
|
||||||
cmp [ebx + ARP_ENTRY.TTL], 0
|
|
||||||
jnz .timer_loop_end_with_dec ;if TTL!=0
|
|
||||||
|
|
||||||
; Ok, TTL is 0
|
|
||||||
;if Status==AWAITING_RESPONSE and TTL==0
|
|
||||||
;then we have to change it to ARP_RESPONSE_TIMEOUT
|
|
||||||
cmp [ebx + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
|
|
||||||
jne @f
|
|
||||||
|
|
||||||
mov [ebx + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
|
|
||||||
mov [ebx + ARP_ENTRY.TTL], word 0x000A ;10 sec
|
|
||||||
jmp .timer_loop_end
|
|
||||||
|
|
||||||
@@:
|
|
||||||
;if TTL==0 and Status==VALID_MAPPING, we have to delete it
|
|
||||||
;if TTL==0 and Status==RESPONSE_TIMEOUT, delete too
|
|
||||||
mov esi, [NumARP]
|
|
||||||
sub esi, ecx ;esi=index of entry, will be deleted
|
|
||||||
|
|
||||||
push ebx ecx
|
|
||||||
call ARP_del_entry
|
|
||||||
pop ecx ebx
|
|
||||||
|
|
||||||
jmp .timer_loop_end
|
|
||||||
|
|
||||||
|
|
||||||
.timer_loop_end_with_dec:
|
|
||||||
|
|
||||||
dec [ebx + ARP_ENTRY.TTL] ;decrease TTL
|
|
||||||
|
|
||||||
.timer_loop_end:
|
|
||||||
|
|
||||||
add ebx, ARP_ENTRY.size
|
|
||||||
loop .timer_loop
|
|
||||||
|
|
||||||
.exit:
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; ARP_add_entry (or update)
|
|
||||||
;
|
|
||||||
; IN: arp entry in stack: esp .IP
|
|
||||||
; esp+4 .MAC
|
|
||||||
; esp+10 .Status
|
|
||||||
; esp+12 .TTL
|
|
||||||
; esp+14
|
|
||||||
;
|
|
||||||
; OUT: eax = entry #, -1 on error
|
|
||||||
;
|
|
||||||
;----------------------------------------------------------------- ; TODO: use a mutex
|
|
||||||
align 4
|
|
||||||
ARP_add_entry:
|
|
||||||
|
|
||||||
DEBUGF 1,"ARP add entry: "
|
|
||||||
|
|
||||||
mov ecx, [NumARP]
|
|
||||||
test ecx, ecx
|
|
||||||
jz .add
|
|
||||||
|
|
||||||
mov eax, dword[esp + 4 + ARP_ENTRY.MAC]
|
|
||||||
mov bx , word[esp + 4 + ARP_ENTRY.MAC + 4]
|
|
||||||
mov esi, ARPTable
|
|
||||||
|
|
||||||
.loop:
|
|
||||||
cmp dword [esi + ARP_ENTRY.MAC], eax
|
|
||||||
jne .maybe_next
|
|
||||||
cmp word [esi + ARP_ENTRY.MAC + 4], bx
|
|
||||||
jne .maybe_next
|
|
||||||
|
|
||||||
cmp dword[esi + ARP_ENTRY.TTL], 0xFFFF ; static entry
|
|
||||||
jne .notstatic
|
|
||||||
cmp dword[esp + 4 + ARP_ENTRY.TTL], 0xFFFF
|
|
||||||
jne .error
|
|
||||||
.notstatic:
|
|
||||||
|
|
||||||
mov ebx, [NumARP]
|
|
||||||
xchg ebx, ecx
|
|
||||||
sub ecx, ebx
|
|
||||||
jmp .add
|
|
||||||
|
|
||||||
.maybe_next:
|
|
||||||
add esi, ARP_ENTRY.size
|
add esi, ARP_ENTRY.size
|
||||||
loop .loop
|
loop .loop
|
||||||
|
|
||||||
mov ecx, [NumARP]
|
|
||||||
cmp ecx, ARP_TABLE_SIZE
|
|
||||||
jge .error
|
|
||||||
|
|
||||||
.add:
|
|
||||||
push ecx
|
|
||||||
imul ecx, ARP_ENTRY.size
|
|
||||||
lea edi, [ecx + ARPTable]
|
|
||||||
lea esi, [esp + 8]
|
|
||||||
mov ecx, ARP_ENTRY.size/2
|
|
||||||
repz movsw
|
|
||||||
|
|
||||||
inc [NumARP]
|
|
||||||
pop eax
|
|
||||||
DEBUGF 1,"New entry created: %u\n", eax
|
|
||||||
.exit:
|
|
||||||
DEBUGF 1,"Exiting\n"
|
|
||||||
ret ARP_ENTRY.size
|
|
||||||
|
|
||||||
.error:
|
|
||||||
|
|
||||||
DEBUGF 1,"error! \n"
|
|
||||||
|
|
||||||
mov eax, -1
|
|
||||||
jmp .exit
|
jmp .exit
|
||||||
|
|
||||||
|
.time_out:
|
||||||
|
cmp [esi + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
|
||||||
|
jz .response_timeout
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
push esi ecx
|
||||||
;
|
call ARP_del_entry
|
||||||
; ARP_del_entry
|
pop ecx esi
|
||||||
;
|
|
||||||
; IN: entry # in esi
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
align 4
|
|
||||||
ARP_del_entry:
|
|
||||||
|
|
||||||
DEBUGF 1,"ARP del entry %u, total entrys: %u\n", esi, [NumARP]
|
jmp .next
|
||||||
|
|
||||||
cmp esi, [NumARP]
|
.response_timeout:
|
||||||
jge .error
|
mov [esi + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
|
||||||
|
mov [esi + ARP_ENTRY.TTL], 10
|
||||||
|
|
||||||
imul esi, ARP_ENTRY.size
|
jmp .next
|
||||||
|
|
||||||
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size
|
|
||||||
sub ecx, esi
|
|
||||||
|
|
||||||
lea edi, [ARPTable + esi] ;edi=ptr to entry that should be deleted
|
|
||||||
lea esi, [edi + ARP_ENTRY.size] ;esi=ptr to next entry
|
|
||||||
|
|
||||||
shr ecx,1 ;ecx/2 => ARP_ENTRY_SIZE MUST BE EVEN NUMBER!
|
|
||||||
rep movsw
|
|
||||||
|
|
||||||
dec [NumARP] ;decrease arp-entries counter
|
|
||||||
DEBUGF 1,"ARP entry deleted\n"
|
|
||||||
.error:
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; ARP_Handler:
|
; ARP_input
|
||||||
;
|
|
||||||
; This function handles ARP protocol over ethernet
|
|
||||||
; (other protocols may follow in the future)
|
|
||||||
;
|
;
|
||||||
; IN: Pointer to buffer in [esp]
|
; IN: Pointer to buffer in [esp]
|
||||||
; size of buffer in [esp+4]
|
; size of buffer in [esp+4]
|
||||||
@ -469,13 +157,16 @@ ARP_del_entry:
|
|||||||
;
|
;
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
ARP_handler:
|
ARP_input:
|
||||||
|
|
||||||
DEBUGF 1,"ARP_Handler - start\n"
|
DEBUGF 1,"ARP_Handler - start\n"
|
||||||
cmp ecx, 28
|
cmp ecx, 28
|
||||||
jl .exit
|
jl .exit
|
||||||
|
|
||||||
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE ; Is this a reply packet?
|
;---------------------
|
||||||
|
; Handle Reply packets
|
||||||
|
|
||||||
|
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE
|
||||||
jne .maybe_request
|
jne .maybe_request
|
||||||
|
|
||||||
DEBUGF 1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
|
DEBUGF 1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
|
||||||
@ -486,10 +177,10 @@ ARP_handler:
|
|||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
mov eax, [edx + ARP_Packet.SenderIP]
|
mov eax, [edx + ARP_Packet.SenderIP]
|
||||||
mov esi, ARPTable+ARP_ENTRY.IP
|
mov esi, ARP_table
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
cmp [esi], eax
|
cmp [esi + ARP_ENTRY.IP], eax
|
||||||
je .gotit
|
je .gotit
|
||||||
add esi, ARP_ENTRY.size
|
add esi, ARP_ENTRY.size
|
||||||
loop .loop
|
loop .loop
|
||||||
@ -497,10 +188,9 @@ ARP_handler:
|
|||||||
jmp .exit
|
jmp .exit
|
||||||
|
|
||||||
.gotit:
|
.gotit:
|
||||||
|
|
||||||
DEBUGF 1,"ARP_Handler - found matching entry\n"
|
DEBUGF 1,"ARP_Handler - found matching entry\n"
|
||||||
|
|
||||||
cmp [esi+ARP_ENTRY.Status], 0x0300 ;if it is a static entry, dont touch it
|
cmp [esi+ARP_ENTRY.TTL], 0xffff ; if it is a static entry, dont touch it
|
||||||
je .exit
|
je .exit
|
||||||
|
|
||||||
DEBUGF 1,"ARP_Handler - updating entry\n"
|
DEBUGF 1,"ARP_Handler - updating entry\n"
|
||||||
@ -516,32 +206,29 @@ ARP_handler:
|
|||||||
jmp .exit
|
jmp .exit
|
||||||
|
|
||||||
|
|
||||||
;------
|
;-----------------------
|
||||||
|
; Handle Request packets
|
||||||
|
|
||||||
.maybe_request:
|
.maybe_request:
|
||||||
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE ; Is this a request packet?
|
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE
|
||||||
jne .exit
|
jne .exit
|
||||||
|
|
||||||
call NET_ptr_to_num
|
call NET_ptr_to_num
|
||||||
DEBUGF 1,"ARP Request packet through device: %u\n", edi
|
|
||||||
inc [ARP_PACKETS_RX+4*edi]
|
|
||||||
cmp edi, -1
|
cmp edi, -1
|
||||||
jz .exit
|
jz .exit
|
||||||
|
DEBUGF 1,"ARP Request packet through device: %u\n", edi
|
||||||
|
inc [ARP_PACKETS_RX+4*edi]
|
||||||
|
|
||||||
mov eax, edi
|
mov eax, [IP_LIST+4*edi]
|
||||||
shl eax, 2
|
|
||||||
add eax, IP_LIST
|
|
||||||
mov eax, [eax]
|
|
||||||
cmp eax, [edx + ARP_Packet.TargetIP] ; Is it looking for my IP address?
|
cmp eax, [edx + ARP_Packet.TargetIP] ; Is it looking for my IP address?
|
||||||
jnz .exit
|
jne .exit ; TODO: instead of quitting, update local entrys with matching IP's ?
|
||||||
|
|
||||||
push eax
|
push eax
|
||||||
push edi
|
push edi
|
||||||
|
|
||||||
; OK, it is a request for one of our MAC addresses. Build the frame and send it
|
; OK, it is a request for one of our MAC addresses.
|
||||||
; We can reuse the buffer. (faster then using ARP_create_packet)
|
; Build the frame and send it. We can reuse the buffer. (faster then using ARP_create_packet)
|
||||||
|
|
||||||
cld
|
|
||||||
lea esi, [edx + ARP_Packet.SenderMAC]
|
lea esi, [edx + ARP_Packet.SenderMAC]
|
||||||
lea edi, [edx + ARP_Packet.TargetMAC]
|
lea edi, [edx + ARP_Packet.TargetMAC]
|
||||||
movsd ; Move Sender Mac to Dest MAC
|
movsd ; Move Sender Mac to Dest MAC
|
||||||
@ -584,6 +271,265 @@ ARP_handler:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;---------------------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; ARP_output_request
|
||||||
|
;
|
||||||
|
; IN: ip in eax
|
||||||
|
; OUT: /
|
||||||
|
;
|
||||||
|
;---------------------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
ARP_output_request:
|
||||||
|
|
||||||
|
DEBUGF 1,"Create ARP Packet\n"
|
||||||
|
|
||||||
|
call IPv4_dest_to_dev
|
||||||
|
push eax ; DestIP
|
||||||
|
pushd [IP_LIST+edi] ; SenderIP
|
||||||
|
|
||||||
|
mov ebx, [NET_DRV_LIST+edi] ; device ptr
|
||||||
|
|
||||||
|
lea eax, [ebx + ETH_DEVICE.mac] ; local device mac
|
||||||
|
mov edx, ETH_BROADCAST ; broadcast mac
|
||||||
|
mov ecx, ARP_Packet.size
|
||||||
|
mov di, ETHER_ARP
|
||||||
|
call ETH_output
|
||||||
|
jz .exit
|
||||||
|
|
||||||
|
mov ecx, eax
|
||||||
|
|
||||||
|
mov [edi + ARP_Packet.HardwareType], 0x0100 ; Ethernet
|
||||||
|
mov [edi + ARP_Packet.ProtocolType], 0x0008 ; IP
|
||||||
|
mov [edi + ARP_Packet.HardwareSize], 6 ; MAC-addr length
|
||||||
|
mov [edi + ARP_Packet.ProtocolSize], 4 ; IP-addr length
|
||||||
|
mov [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE ; Request
|
||||||
|
|
||||||
|
add edi, ARP_Packet.SenderMAC
|
||||||
|
|
||||||
|
lea esi, [ebx + ETH_DEVICE.mac] ; SenderMac
|
||||||
|
movsw ;
|
||||||
|
movsd ;
|
||||||
|
pop eax ; SenderIP
|
||||||
|
stosd ;
|
||||||
|
|
||||||
|
mov eax, -1 ; DestMac
|
||||||
|
stosd ;
|
||||||
|
stosw ;
|
||||||
|
pop eax ; DestIP
|
||||||
|
stosd ;
|
||||||
|
|
||||||
|
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
|
||||||
|
|
||||||
|
push edx ecx
|
||||||
|
call [ebx + NET_DEVICE.transmit]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
add esp, 4+4
|
||||||
|
DEBUGF 1,"Create ARP Packet - failed\n"
|
||||||
|
sub eax, eax
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; ARP_add_entry (or update)
|
||||||
|
;
|
||||||
|
; IN: esi = ptr to entry (can easily be made on the stack)
|
||||||
|
; OUT: eax = entry #, -1 on error
|
||||||
|
;
|
||||||
|
;----------------------------------------------------------------- ; TODO: use a mutex
|
||||||
|
align 4
|
||||||
|
ARP_add_entry:
|
||||||
|
|
||||||
|
DEBUGF 1,"ARP add entry: "
|
||||||
|
|
||||||
|
mov ecx, [NumARP]
|
||||||
|
test ecx, ecx ; first entry?
|
||||||
|
jz .add
|
||||||
|
cmp ecx, ARP_TABLE_SIZE ; list full ?
|
||||||
|
jge .error
|
||||||
|
|
||||||
|
mov eax, dword[esi + ARP_ENTRY.MAC]
|
||||||
|
mov bx , word[esi + ARP_ENTRY.MAC + 4]
|
||||||
|
mov edi, ARP_table
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
cmp dword [edi + ARP_ENTRY.MAC], eax ; Check for duplicate MAC's
|
||||||
|
jne .maybe_next ;
|
||||||
|
cmp word [edi + ARP_ENTRY.MAC + 4], bx ;
|
||||||
|
jne .maybe_next ;
|
||||||
|
|
||||||
|
cmp dword[edi + ARP_ENTRY.TTL], 0xFFFF ; static entry
|
||||||
|
jne .notstatic
|
||||||
|
cmp dword[esi + ARP_ENTRY.TTL], 0xFFFF
|
||||||
|
jne .error
|
||||||
|
.notstatic:
|
||||||
|
|
||||||
|
neg ecx
|
||||||
|
add ecx, [NumARP]
|
||||||
|
jmp .add
|
||||||
|
|
||||||
|
.maybe_next:
|
||||||
|
add esi, ARP_ENTRY.size
|
||||||
|
loop .loop
|
||||||
|
|
||||||
|
mov ecx, [NumARP]
|
||||||
|
.add:
|
||||||
|
push ecx
|
||||||
|
imul ecx, ARP_ENTRY.size
|
||||||
|
lea edi, [ecx + ARP_table]
|
||||||
|
mov ecx, ARP_ENTRY.size/2
|
||||||
|
rep movsw
|
||||||
|
|
||||||
|
lea esi, [edi - ARP_ENTRY.size]
|
||||||
|
inc [NumARP]
|
||||||
|
pop eax
|
||||||
|
DEBUGF 1,"New entry created: %u\n", eax
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
DEBUGF 1,"Exiting\n"
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
DEBUGF 1,"error! \n"
|
||||||
|
mov eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; ARP_del_entry
|
||||||
|
;
|
||||||
|
; IN: esi = ptr to arp entry
|
||||||
|
; OUT: /
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
ARP_del_entry:
|
||||||
|
|
||||||
|
DEBUGF 1,"ARP del entry %x, total entrys: %u\n", esi, [NumARP]
|
||||||
|
|
||||||
|
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size
|
||||||
|
sub ecx, esi
|
||||||
|
shr ecx, 1
|
||||||
|
|
||||||
|
mov edi, esi
|
||||||
|
lea esi, [edi + ARP_ENTRY.size]
|
||||||
|
rep movsw
|
||||||
|
|
||||||
|
dec [NumARP]
|
||||||
|
DEBUGF 1,"ARP entry deleted\n"
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; ARP_IP_to_MAC
|
||||||
|
;
|
||||||
|
; This function translates an IP address to a MAC address
|
||||||
|
;
|
||||||
|
; IN: eax = IPv4 address
|
||||||
|
; OUT: eax = -1 on error, -2 means request send
|
||||||
|
; else, ax = first two bytes of mac (high 16 bits of eax will be 0)
|
||||||
|
; ebx = last four bytes of mac
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
ARP_IP_to_MAC:
|
||||||
|
|
||||||
|
DEBUGF 1,"ARP_IP_to_MAC\n"
|
||||||
|
|
||||||
|
cmp eax, 0xffffffff
|
||||||
|
je .broadcast
|
||||||
|
|
||||||
|
; if ((Remote IP & subnet_mask) == (local IP & subnet_mask ))
|
||||||
|
; destination is on same subnet
|
||||||
|
; else, destination is remote and must use a gateway
|
||||||
|
|
||||||
|
call IPv4_dest_to_dev
|
||||||
|
mov ebx, [IP_LIST + edi]
|
||||||
|
and ebx, [SUBNET_LIST + edi]
|
||||||
|
|
||||||
|
mov ecx, eax
|
||||||
|
and ecx, [SUBNET_LIST + edi]
|
||||||
|
|
||||||
|
cmp ecx, ebx
|
||||||
|
je .local
|
||||||
|
|
||||||
|
mov eax, [GATEWAY_LIST + edi]
|
||||||
|
DEBUGF 1,"requested IP is not on subnet, using default gateway\n"
|
||||||
|
|
||||||
|
;--------------------------------
|
||||||
|
; Try to find the IP in ARP_table
|
||||||
|
|
||||||
|
.local:
|
||||||
|
mov ecx, [NumARP]
|
||||||
|
test ecx, ecx
|
||||||
|
jz .not_in_list
|
||||||
|
mov esi, ARP_table + ARP_ENTRY.IP
|
||||||
|
.scan_loop:
|
||||||
|
cmp [esi], eax
|
||||||
|
je .found_it
|
||||||
|
add esi, ARP_ENTRY.size
|
||||||
|
loop .scan_loop
|
||||||
|
|
||||||
|
.not_in_list:
|
||||||
|
DEBUGF 1,"IP not found on list, preparing for ARP request\n"
|
||||||
|
|
||||||
|
;--------------------
|
||||||
|
; Send an ARP request
|
||||||
|
|
||||||
|
push eax
|
||||||
|
|
||||||
|
pushw ARP_REQUEST_TTL
|
||||||
|
pushw ARP_AWAITING_RESPONSE
|
||||||
|
pushd 0
|
||||||
|
pushw 0
|
||||||
|
pushd eax
|
||||||
|
mov esi, esp
|
||||||
|
call ARP_add_entry
|
||||||
|
add esp, ARP_ENTRY.size
|
||||||
|
|
||||||
|
cmp eax, -1
|
||||||
|
je .full
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
call ARP_output_request
|
||||||
|
|
||||||
|
mov eax, -2 ; request send
|
||||||
|
ret
|
||||||
|
|
||||||
|
.found_it:
|
||||||
|
DEBUGF 1,"found IP in ARPTable\n"
|
||||||
|
cmp [esi + ARP_ENTRY.Status], 1
|
||||||
|
jne .invalid
|
||||||
|
|
||||||
|
movzx eax, word [esi+ARP_ENTRY.MAC]
|
||||||
|
mov ebx, dword[esi+ARP_ENTRY.MAC+2]
|
||||||
|
ret
|
||||||
|
|
||||||
|
.invalid:
|
||||||
|
mov eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.full:
|
||||||
|
DEBUGF 1,"ARP table is full!\n"
|
||||||
|
pop eax
|
||||||
|
mov eax, -1
|
||||||
|
ret
|
||||||
|
|
||||||
|
.broadcast:
|
||||||
|
mov eax, 0x0000ffff
|
||||||
|
mov ebx, 0xffffffff
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
@ -643,7 +589,7 @@ ARP_API:
|
|||||||
; edi = pointer to buffer
|
; edi = pointer to buffer
|
||||||
; ecx = # entry
|
; ecx = # entry
|
||||||
imul ecx, ARP_ENTRY.size
|
imul ecx, ARP_ENTRY.size
|
||||||
add ecx, ARPTable
|
add ecx, ARP_table
|
||||||
mov esi, ecx
|
mov esi, ecx
|
||||||
mov ecx, ARP_ENTRY.size/2
|
mov ecx, ARP_ENTRY.size/2
|
||||||
rep movsw
|
rep movsw
|
||||||
@ -653,16 +599,15 @@ ARP_API:
|
|||||||
|
|
||||||
.write:
|
.write:
|
||||||
; esi = pointer to buffer
|
; esi = pointer to buffer
|
||||||
sub esp, ARP_ENTRY.size
|
|
||||||
mov edi, esp
|
|
||||||
mov ecx, ARP_ENTRY.size/2
|
|
||||||
rep movsw
|
|
||||||
call ARP_add_entry ;out: eax = entry number, -1 on error
|
call ARP_add_entry ;out: eax = entry number, -1 on error
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.remove:
|
.remove:
|
||||||
; ecx = # entry
|
; ecx = # entry
|
||||||
mov esi, ecx
|
cmp ecx, [NumARP]
|
||||||
|
jge .error
|
||||||
|
imul ecx, ARP_ENTRY.size
|
||||||
|
lea esi, [ARP_table + ecx]
|
||||||
call ARP_del_entry
|
call ARP_del_entry
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
@ -53,6 +53,73 @@ struct FRAGMENT_entry ; This structure will replace the ethernet header
|
|||||||
.Data: ; Ip header begins here (we will need the IP header to re-construct the complete packet)
|
.Data: ; Ip header begins here (we will need the IP header to re-construct the complete packet)
|
||||||
ends
|
ends
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
macro IPv4_checksum ptr {
|
||||||
|
|
||||||
|
; This is the fast procedure to create or check a IP header without options
|
||||||
|
; To create a new checksum, the checksum field must be set to 0 before computation
|
||||||
|
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
|
||||||
|
|
||||||
|
push ebx
|
||||||
|
xor ebx, ebx
|
||||||
|
add bl, [ptr+1]
|
||||||
|
adc bh, [ptr+0]
|
||||||
|
|
||||||
|
adc bl, [ptr+3]
|
||||||
|
adc bh, [ptr+2]
|
||||||
|
|
||||||
|
adc bl, [ptr+5]
|
||||||
|
adc bh, [ptr+4]
|
||||||
|
|
||||||
|
adc bl, [ptr+7]
|
||||||
|
adc bh, [ptr+6]
|
||||||
|
|
||||||
|
adc bl, [ptr+9]
|
||||||
|
adc bh, [ptr+8]
|
||||||
|
|
||||||
|
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
|
||||||
|
|
||||||
|
adc bl, [ptr+13]
|
||||||
|
adc bh, [ptr+12]
|
||||||
|
|
||||||
|
adc bl, [ptr+15]
|
||||||
|
adc bh, [ptr+14]
|
||||||
|
|
||||||
|
adc bl, [ptr+17]
|
||||||
|
adc bh, [ptr+16]
|
||||||
|
|
||||||
|
adc bl, [ptr+19]
|
||||||
|
adc bh, [ptr+18]
|
||||||
|
|
||||||
|
adc ebx, 0
|
||||||
|
|
||||||
|
push ecx
|
||||||
|
mov ecx, ebx
|
||||||
|
shr ecx, 16
|
||||||
|
and ebx, 0xffff
|
||||||
|
add ebx, ecx
|
||||||
|
|
||||||
|
mov ecx, ebx
|
||||||
|
shr ecx, 16
|
||||||
|
add ebx, ecx
|
||||||
|
|
||||||
|
not bx
|
||||||
|
jnz .not_zero
|
||||||
|
dec bx
|
||||||
|
.not_zero:
|
||||||
|
xchg bl, bh
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
neg word [ptr+10] ; zero will stay zero so we just get the checksum
|
||||||
|
add word [ptr+10], bx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
||||||
|
pop ebx
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
align 4
|
align 4
|
||||||
uglobal
|
uglobal
|
||||||
|
|
||||||
@ -74,30 +141,49 @@ endg
|
|||||||
;
|
;
|
||||||
; This function resets all IP variables
|
; This function resets all IP variables
|
||||||
;
|
;
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
macro IPv4_init {
|
||||||
IPv4_init:
|
|
||||||
|
|
||||||
or eax, -1
|
xor eax, eax
|
||||||
mov edi, IP_LIST
|
mov edi, IP_LIST
|
||||||
mov ecx, 4*MAX_IP
|
mov ecx, 4*MAX_IP
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
inc eax
|
|
||||||
mov edi, FRAGMENT_LIST
|
mov edi, FRAGMENT_LIST
|
||||||
mov ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
|
mov ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
ret
|
}
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; Decrease TimeToLive of all fragment slots
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
macro IPv4_decrease_fragment_ttls {
|
||||||
|
|
||||||
|
local .loop
|
||||||
|
|
||||||
|
mov esi, FRAGMENT_LIST
|
||||||
|
mov ecx, MAX_FRAGMENTS
|
||||||
|
.loop:
|
||||||
|
cmp [esi + FRAGMENT_slot.ttl], 0
|
||||||
|
je .try_next
|
||||||
|
dec [esi + FRAGMENT_slot.ttl]
|
||||||
|
jnz .try_next
|
||||||
|
DEBUGF 1,"Fragment slot timed-out!\n"
|
||||||
|
;;; TODO: clear all entry's of timed-out slot
|
||||||
|
.try_next:
|
||||||
|
add esi, 4
|
||||||
|
loop .loop
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; IPv4_Handler:
|
; IPv4_input:
|
||||||
;
|
;
|
||||||
; Will check if IP Packet isnt damaged
|
; Will check if IP Packet isnt damaged
|
||||||
; and call appropriate handler. (TCP/UDP/ICMP/..)
|
; and call appropriate handler. (TCP/UDP/ICMP/..)
|
||||||
@ -112,7 +198,7 @@ IPv4_init:
|
|||||||
;
|
;
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
IPv4_handler: ; TODO: implement handler for IP options
|
IPv4_input: ; TODO: implement handler for IP options
|
||||||
; TODO2: add code for raw sockets
|
; TODO2: add code for raw sockets
|
||||||
|
|
||||||
DEBUGF 1,"IPv4_Handler, packet from: %u.%u.%u.%u ",\
|
DEBUGF 1,"IPv4_Handler, packet from: %u.%u.%u.%u ",\
|
||||||
@ -137,13 +223,8 @@ IPv4_handler: ; TODO: implement handler for IP options
|
|||||||
;-------------------------------
|
;-------------------------------
|
||||||
; Now, re-calculate the checksum
|
; Now, re-calculate the checksum
|
||||||
|
|
||||||
push edx ebx
|
IPv4_checksum edx
|
||||||
mov esi, edx
|
jnz .dump ; if checksum isn't valid then dump packet
|
||||||
call IPv4_checksum
|
|
||||||
pop ebx edx
|
|
||||||
|
|
||||||
cmp [edx + IPv4_Packet.HeaderChecksum], 0
|
|
||||||
jne .dump ; if checksum isn't valid then dump packet
|
|
||||||
|
|
||||||
DEBUGF 1,"IPv4 Checksum is correct\n"
|
DEBUGF 1,"IPv4 Checksum is correct\n"
|
||||||
|
|
||||||
@ -435,10 +516,7 @@ IPv4_handler: ; TODO: implement handler for IP options
|
|||||||
|
|
||||||
; mov esi, edx ; This prints the IP packet to the debug board (usefull when using serial output debug..)
|
; mov esi, edx ; This prints the IP packet to the debug board (usefull when using serial output debug..)
|
||||||
; ;
|
; ;
|
||||||
; @@: ;
|
; packet_to_debug
|
||||||
; lodsb ;
|
|
||||||
; DEBUGF 1,"%x ", eax:2 ;
|
|
||||||
; loop @r ;
|
|
||||||
|
|
||||||
jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
|
jmp .handle_it ; edx = buf ptr, ecx = size, [esp] buf ptr, [esp+4], total size, ebx=device ptr
|
||||||
|
|
||||||
@ -460,9 +538,6 @@ IPv4_handler: ; TODO: implement handler for IP options
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; find fragment slot
|
; find fragment slot
|
||||||
@ -501,70 +576,15 @@ IPv4_find_fragment_slot:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; Decrease TimeToLive of all fragment slots
|
|
||||||
;
|
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
align 4
|
|
||||||
IPv4_decrease_fragment_ttls:
|
|
||||||
|
|
||||||
mov esi, FRAGMENT_LIST
|
|
||||||
mov ecx, MAX_FRAGMENTS
|
|
||||||
.loop:
|
|
||||||
cmp [esi + FRAGMENT_slot.ttl], 0
|
|
||||||
je .try_next
|
|
||||||
dec [esi + FRAGMENT_slot.ttl]
|
|
||||||
jnz .try_next
|
|
||||||
DEBUGF 1,"Fragment slot timed-out!\n"
|
|
||||||
;;; TODO: clear all entry's of timed-out slot
|
|
||||||
.try_next:
|
|
||||||
add esi, 4
|
|
||||||
loop .loop
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;------------------------------------------------------------------
|
;------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
;
|
; IPv4_output
|
||||||
; IN: dword [esp] = pointer to packet to be fragmented
|
|
||||||
; dword [esp+4] = buffer size
|
|
||||||
; edx = pointer to IPv4 header in that packet
|
|
||||||
; ecx = data length
|
|
||||||
; ebx = device structure
|
|
||||||
;
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;------------------------------------------------------------------
|
|
||||||
align 4
|
|
||||||
IPv4_fragment:
|
|
||||||
|
|
||||||
;;; TODO: write code here
|
|
||||||
|
|
||||||
|
|
||||||
call kernel_free
|
|
||||||
add esp, 4
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;------------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; Create_IPv4_Packet
|
|
||||||
;
|
;
|
||||||
; IN: eax = dest ip
|
; IN: eax = dest ip
|
||||||
; ebx = source ip
|
; ebx = source ip
|
||||||
; ecx = data length
|
; ecx = data length
|
||||||
; dx = fragment id ;;;;
|
; dx = fragment id
|
||||||
; di = protocol
|
; di = TTL shl 8 + protocol
|
||||||
;
|
;
|
||||||
; OUT: eax = pointer to buffer start
|
; OUT: eax = pointer to buffer start
|
||||||
; ebx = pointer to device struct (needed for sending procedure)
|
; ebx = pointer to device struct (needed for sending procedure)
|
||||||
@ -574,184 +594,224 @@ IPv4_fragment:
|
|||||||
;
|
;
|
||||||
;------------------------------------------------------------------
|
;------------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
IPv4_create_packet:
|
IPv4_output:
|
||||||
|
|
||||||
DEBUGF 1,"Create IPv4 Packet (size=%u)\n", ecx
|
DEBUGF 1,"IPv4_create_packet: size=%u\n", ecx
|
||||||
|
|
||||||
cmp ecx, 65500 ; Max IPv4 packet size
|
cmp ecx, 65500 ; Max IPv4 packet size
|
||||||
jg .exit_
|
jg .too_large
|
||||||
|
|
||||||
test ebx, ebx ; if source ip = 0
|
|
||||||
jnz .ip_ok ; and local ip is valid
|
|
||||||
; use local ip instead
|
|
||||||
cmp [IP_LIST],0xffffffff ;
|
|
||||||
je .ip_ok ; TODO: find solution to send broadcast
|
|
||||||
; on device other then device 0
|
|
||||||
mov ebx, [IP_LIST] ;
|
|
||||||
;
|
|
||||||
.ip_ok: ;
|
|
||||||
|
|
||||||
push ecx eax ebx dx di
|
push ecx eax ebx dx di
|
||||||
|
|
||||||
cmp eax, -1
|
|
||||||
je .broadcast ; If it is broadcast, just send
|
|
||||||
|
|
||||||
call ARP_IP_to_MAC
|
call ARP_IP_to_MAC
|
||||||
|
|
||||||
|
test eax, 0xffff0000 ; error bits
|
||||||
|
jnz .arp_error
|
||||||
|
|
||||||
|
push ebx ; push the mac
|
||||||
|
push ax
|
||||||
|
|
||||||
|
call IPv4_dest_to_dev
|
||||||
|
inc [IP_PACKETS_TX+edi]
|
||||||
|
mov ebx, [NET_DRV_LIST+edi]
|
||||||
|
lea eax, [ebx + ETH_DEVICE.mac]
|
||||||
|
mov edx, esp
|
||||||
|
mov ecx, [esp + 18]
|
||||||
|
add ecx, IPv4_Packet.DataOrOptional
|
||||||
|
mov di , ETHER_IPv4
|
||||||
|
call ETH_output
|
||||||
|
jz .error
|
||||||
|
|
||||||
|
add esp, 6 ; pop the mac
|
||||||
|
|
||||||
|
mov [edi + IPv4_Packet.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
|
||||||
|
mov [edi + IPv4_Packet.TypeOfService], 0 ; nothing special, just plain ip packet
|
||||||
|
mov [edi + IPv4_Packet.TotalLength], cx
|
||||||
|
rol [edi + IPv4_Packet.TotalLength], 8 ; internet byte order
|
||||||
|
mov [edi + IPv4_Packet.FlagsAndFragmentOffset], 0x0000
|
||||||
|
mov [edi + IPv4_Packet.HeaderChecksum], 0
|
||||||
|
popw word [edi + IPv4_Packet.TimeToLive] ; ttl shl 8 + protocol
|
||||||
|
; [edi + IPv4_Packet.Protocol]
|
||||||
|
popw [edi + IPv4_Packet.Identification] ; fragment id
|
||||||
|
popd [edi + IPv4_Packet.SourceAddress]
|
||||||
|
popd [edi + IPv4_Packet.DestinationAddress]
|
||||||
|
|
||||||
|
pop ecx
|
||||||
|
|
||||||
|
IPv4_checksum edi
|
||||||
|
add edi, IPv4_Packet.DataOrOptional
|
||||||
|
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.error:
|
||||||
|
add esp, 6
|
||||||
|
.arp_error:
|
||||||
|
add esp, 4+4+4+2+2
|
||||||
|
.too_large:
|
||||||
|
DEBUGF 1,"IPv4_create_packet: Failed\n"
|
||||||
|
sub edi, edi
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;--------------------------------------------------------
|
||||||
|
;
|
||||||
|
;
|
||||||
|
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
|
||||||
|
; dword [esp+4] = buffer size
|
||||||
|
; esi = pointer to ip header in that buffer
|
||||||
|
; ecx = max size of fragments
|
||||||
|
;
|
||||||
|
; OUT: /
|
||||||
|
;
|
||||||
|
;--------------------------------------------------------
|
||||||
|
|
||||||
|
align 4
|
||||||
|
IPv4_fragment:
|
||||||
|
|
||||||
|
DEBUGF 1,"IPv4_fragment\n"
|
||||||
|
|
||||||
|
and ecx, not 111b ; align 4
|
||||||
|
|
||||||
|
cmp ecx, IPv4_Packet.DataOrOptional + 8 ; must be able to put at least 8 bytes
|
||||||
|
jl .err2
|
||||||
|
|
||||||
|
push esi ecx
|
||||||
|
mov eax, [esi + IPv4_Packet.DestinationAddress]
|
||||||
|
call ARP_IP_to_MAC
|
||||||
|
pop ecx esi
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je .not_found
|
jz .err2
|
||||||
|
|
||||||
push ebx
|
push ebx
|
||||||
push ax
|
push ax
|
||||||
|
|
||||||
jmp .send
|
mov ebx, [NET_DRV_LIST]
|
||||||
|
lea eax, [ebx + ETH_DEVICE.mac]
|
||||||
|
push eax
|
||||||
|
|
||||||
.broadcast:
|
|
||||||
push word -1
|
|
||||||
push dword -1
|
|
||||||
|
|
||||||
.send:
|
push esi ; ptr to ip header
|
||||||
call IPv4_dest_to_dev
|
sub ecx, 20 ; substract header size
|
||||||
inc [IP_PACKETS_TX+4*edi]
|
push ecx ; max data size
|
||||||
mov edx, [NET_DRV_LIST + 4*edi]
|
push dword 0 ; offset
|
||||||
lea eax, [edx + ETH_DEVICE.mac]
|
|
||||||
mov ebx, esp
|
.new_fragment:
|
||||||
mov ecx, [esp+18] ;; 18 or 22 ??
|
DEBUGF 1,"Ipv4_fragment - new_fragmentn"
|
||||||
add ecx, IPv4_Packet.DataOrOptional
|
|
||||||
|
|
||||||
|
mov eax, [esp + 3*4]
|
||||||
|
lea ebx, [esp + 4*4]
|
||||||
mov di , ETHER_IPv4
|
mov di , ETHER_IPv4
|
||||||
;;; TODO: detect if packet is too large for ethernet, if so, call IPv4_fragment
|
call ETH_output
|
||||||
call ETH_create_packet ;;; TODO: figure out a way to make this work with other protocols too
|
|
||||||
add esp, 6
|
|
||||||
test edi, edi
|
|
||||||
jz .exit
|
|
||||||
|
|
||||||
mov [edi + IPv4_Packet.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
|
cmp edi, -1
|
||||||
mov [edi + IPv4_Packet.TypeOfService], 0
|
jz .err
|
||||||
xchg ch, cl
|
|
||||||
|
; copy header
|
||||||
|
mov esi, [esp + 2*4]
|
||||||
|
mov ecx, 5 ; 5 dwords: TODO: use IHL field of the header!
|
||||||
|
rep movsd
|
||||||
|
|
||||||
|
; copy data
|
||||||
|
mov esi, [esp + 2*4]
|
||||||
|
add esi, 20
|
||||||
|
add esi, [esp] ; offset
|
||||||
|
|
||||||
|
mov ecx, [esp + 1*4]
|
||||||
|
DEBUGF 1,"IPv4_fragment - copying data (%u bytes)\n", ecx
|
||||||
|
rep movsb
|
||||||
|
|
||||||
|
; now, correct header
|
||||||
|
mov ecx, [esp + 1*4]
|
||||||
|
add ecx, 20
|
||||||
|
xchg cl, ch
|
||||||
mov [edi + IPv4_Packet.TotalLength], cx
|
mov [edi + IPv4_Packet.TotalLength], cx
|
||||||
mov [edi + IPv4_Packet.FlagsAndFragmentOffset], 0x0000
|
|
||||||
mov [edi + IPv4_Packet.TimeToLive], 128
|
mov ecx, [esp] ; offset
|
||||||
|
xchg cl, ch
|
||||||
|
|
||||||
|
; cmp dword[esp + 4*4], 0 ; last fragment?;<<<<<<
|
||||||
|
; je .last_fragment
|
||||||
|
or cx, 1 shl 2 ; more fragments
|
||||||
|
; .last_fragment:
|
||||||
|
mov [edi + IPv4_Packet.FlagsAndFragmentOffset], cx
|
||||||
|
|
||||||
mov [edi + IPv4_Packet.HeaderChecksum], 0
|
mov [edi + IPv4_Packet.HeaderChecksum], 0
|
||||||
pop cx
|
|
||||||
mov [edi + IPv4_Packet.Protocol], cl
|
|
||||||
pop cx
|
|
||||||
mov [edi + IPv4_Packet.Identification], cx
|
|
||||||
pop ecx
|
|
||||||
mov [edi + IPv4_Packet.SourceAddress], ecx
|
|
||||||
pop ecx
|
|
||||||
mov [edi + IPv4_Packet.DestinationAddress], ecx
|
|
||||||
|
|
||||||
push eax edx esi
|
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
|
||||||
mov esi, edi
|
mov ecx, [esp + 1*4]
|
||||||
call IPv4_checksum
|
|
||||||
pop esi edx eax ecx
|
|
||||||
add edi, IPv4_Packet.DataOrOptional
|
|
||||||
|
|
||||||
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
|
push edx eax
|
||||||
|
IPv4_checksum edi
|
||||||
|
|
||||||
|
call [ebx + NET_DEVICE.transmit]
|
||||||
|
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
mov ecx, [esp+4]
|
||||||
|
add [esp], ecx
|
||||||
|
|
||||||
|
mov ecx, [esp+3*4+6+4] ; ptr to begin of buff
|
||||||
|
add ecx, [esp+3*4+6+4+4] ; buff size
|
||||||
|
sub ecx, [esp+2*4] ; ptr to ip header
|
||||||
|
add ecx, [esp] ; offset
|
||||||
|
|
||||||
|
DEBUGF 1,"Ipv4_fragment - bytes remaining: %u\n", ecx
|
||||||
|
|
||||||
|
cmp ecx, [esp+1*4]
|
||||||
|
jge .new_fragment
|
||||||
|
|
||||||
|
mov [esp+4], ecx ; set fragment size to remaining packet size
|
||||||
|
jmp .new_fragment
|
||||||
|
|
||||||
|
.err:
|
||||||
|
DEBUGF 1,"Ipv4_fragment - failed\n"
|
||||||
|
.done:
|
||||||
|
add esp, 12 + 4 + 6
|
||||||
|
.err2:
|
||||||
|
DEBUGF 1,"Ipv4_fragment - dumping\n"
|
||||||
|
call kernel_free
|
||||||
|
add esp, 4
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
.not_found:
|
|
||||||
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
|
|
||||||
;;;;;;
|
|
||||||
.exit:
|
|
||||||
add esp, 16
|
|
||||||
.exit_:
|
|
||||||
DEBUGF 1,"Create IPv4 Packet - failed\n"
|
|
||||||
and edi, 0
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
align 4
|
|
||||||
IPv4_checksum:
|
|
||||||
|
|
||||||
; This is the fast procedure to create or check a IP header without options
|
|
||||||
;
|
|
||||||
; To create a new checksum, the checksum field must be set to 0 before computation
|
|
||||||
;
|
|
||||||
; To check an existing checksum, leave the checksum as is, and it will be 0 after this procedure, if it was correct
|
|
||||||
|
|
||||||
xor edx, edx
|
|
||||||
|
|
||||||
add dl, [esi+1]
|
|
||||||
adc dh, [esi+0]
|
|
||||||
|
|
||||||
adc dl, [esi+3]
|
|
||||||
adc dh, [esi+2]
|
|
||||||
|
|
||||||
adc dl, [esi+5]
|
|
||||||
adc dh, [esi+4]
|
|
||||||
|
|
||||||
adc dl, [esi+7]
|
|
||||||
adc dh, [esi+6]
|
|
||||||
|
|
||||||
adc dl, [esi+9]
|
|
||||||
adc dh, [esi+8]
|
|
||||||
|
|
||||||
; we skip 11th and 12th byte, they are the checksum bytes and should be 0 for re-calculation
|
|
||||||
|
|
||||||
adc dl, [esi+13]
|
|
||||||
adc dh, [esi+12]
|
|
||||||
|
|
||||||
adc dl, [esi+15]
|
|
||||||
adc dh, [esi+14]
|
|
||||||
|
|
||||||
adc dl, [esi+17]
|
|
||||||
adc dh, [esi+16]
|
|
||||||
|
|
||||||
adc dl, [esi+19]
|
|
||||||
adc dh, [esi+18]
|
|
||||||
|
|
||||||
adc edx, 0
|
|
||||||
|
|
||||||
call checksum_2
|
|
||||||
|
|
||||||
neg word [esi+10] ; zero will stay zero so we just get the checksum
|
|
||||||
add word [esi+10], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; IPv4_dest_to_dev
|
; IPv4_dest_to_dev
|
||||||
;
|
;
|
||||||
; IN: Destination IP in eax
|
; IN: eax = Destination IP
|
||||||
; OUT: device id in edi
|
; OUT: edi = device id * 4
|
||||||
;
|
;
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
IPv4_dest_to_dev:
|
IPv4_dest_to_dev:
|
||||||
|
|
||||||
DEBUGF 1,"IPv4 destination to device: "
|
cmp eax, 0xffffffff
|
||||||
|
je .invalid
|
||||||
|
|
||||||
xor edi, edi
|
xor edi, edi
|
||||||
mov ecx, MAX_IP
|
mov ecx, MAX_IP
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
mov ebx, [IP_LIST+edi] ; we dont need to worry about non exisiting ip interfaces
|
mov ebx, [IP_LIST+edi]
|
||||||
and ebx, [SUBNET_LIST+edi] ; they have IP and SUBNET set to all one's, so they will have no match except 255.255.255.255
|
and ebx, [SUBNET_LIST+edi]
|
||||||
; (only a moron would insert that ip into this function..)
|
jz .next
|
||||||
|
|
||||||
mov edx, eax
|
mov edx, eax
|
||||||
and edx, [SUBNET_LIST+edi]
|
and edx, [SUBNET_LIST+edi]
|
||||||
|
|
||||||
cmp ebx, edx
|
cmp ebx, edx
|
||||||
je .found_it
|
je .found_it
|
||||||
|
.next:
|
||||||
add edi, 4
|
add edi, 4
|
||||||
loop .loop
|
loop .loop
|
||||||
|
|
||||||
|
.invalid:
|
||||||
xor edi, edi ; if none found, use device 0 as default device
|
xor edi, edi ; if none found, use device 0 as default device
|
||||||
|
|
||||||
.found_it:
|
.found_it:
|
||||||
shr edi, 2
|
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
|
||||||
|
|
||||||
DEBUGF 1,"%u\n",edi
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
@ -869,7 +929,3 @@ IPv4_API:
|
|||||||
mov [eax], ecx
|
mov [eax], ecx
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,37 +56,33 @@ endg
|
|||||||
;
|
;
|
||||||
; This function resets all ethernet variables
|
; This function resets all ethernet variables
|
||||||
;
|
;
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
macro ETH_init {
|
||||||
ETH_init:
|
|
||||||
|
|
||||||
mov [ETH_RUNNING], 0
|
mov [ETH_RUNNING], 0
|
||||||
|
|
||||||
ret
|
}
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; ETH_Receiver:
|
; ETH_input
|
||||||
;
|
;
|
||||||
; This function is called by ethernet drivers,
|
; This function is called by ethernet drivers,
|
||||||
; It pushes the received ethernet packets onto the eth_in_queue
|
; It pushes the received ethernet packets onto the eth_in_queue
|
||||||
;
|
;
|
||||||
; IN: [esp] = Pointer to buffer
|
; IN: [esp] = Pointer to buffer
|
||||||
; [esp-4] = size of buffer
|
; [esp+4] = size of buffer
|
||||||
; ebx = pointer to eth_device
|
; ebx = pointer to eth_device
|
||||||
; OUT: /
|
; OUT: /
|
||||||
;
|
;
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
ETH_receiver:
|
ETH_input:
|
||||||
mov eax, [esp]
|
mov eax, [esp]
|
||||||
mov ecx, [esp+4]
|
mov ecx, [esp+4]
|
||||||
|
|
||||||
DEBUGF 1,"ETH_Handler - size: %u\n", ecx
|
DEBUGF 1,"ETH_input - size: %u\n", ecx
|
||||||
cmp ecx, 60 ; check packet length
|
cmp ecx, 60 ; check packet length
|
||||||
jl .dump
|
jl .dump
|
||||||
sub ecx, ETH_FRAME.Data
|
sub ecx, ETH_FRAME.Data
|
||||||
@ -95,10 +91,10 @@ ETH_receiver:
|
|||||||
mov ax , [eax + ETH_FRAME.Type]
|
mov ax , [eax + ETH_FRAME.Type]
|
||||||
|
|
||||||
cmp ax, ETHER_IPv4
|
cmp ax, ETHER_IPv4
|
||||||
je IPv4_handler
|
je IPv4_input
|
||||||
|
|
||||||
cmp ax, ETHER_ARP
|
cmp ax, ETHER_ARP
|
||||||
je ARP_handler
|
je ARP_input
|
||||||
|
|
||||||
; cmp ax, ETHER_PPP_DISCOVERY
|
; cmp ax, ETHER_PPP_DISCOVERY
|
||||||
; je PPPOE_discovery
|
; je PPPOE_discovery
|
||||||
@ -106,19 +102,19 @@ ETH_receiver:
|
|||||||
DEBUGF 2,"Unknown ethernet packet type %x\n", ax
|
DEBUGF 2,"Unknown ethernet packet type %x\n", ax
|
||||||
|
|
||||||
.dump:
|
.dump:
|
||||||
DEBUGF 2,"ETH_Handler - dumping\n"
|
DEBUGF 2,"ETH_input - dumping\n"
|
||||||
call kernel_free
|
call kernel_free
|
||||||
add esp, 4
|
add esp, 4
|
||||||
ret
|
ret
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; ETH_create_packet
|
; ETH_output
|
||||||
;
|
;
|
||||||
; IN: eax = pointer to source mac
|
; IN: eax = pointer to source mac
|
||||||
; ebx = pointer to destination mac
|
; ebx = device ptr
|
||||||
; ecx = packet size
|
; ecx = packet size
|
||||||
; edx = device number
|
; edx = pointer to destination mac
|
||||||
; di = protocol
|
; di = protocol
|
||||||
;
|
;
|
||||||
; OUT: edi = 0 on error, pointer to buffer otherwise
|
; OUT: edi = 0 on error, pointer to buffer otherwise
|
||||||
@ -129,62 +125,60 @@ ETH_receiver:
|
|||||||
;
|
;
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
align 4
|
||||||
ETH_create_packet:
|
ETH_output:
|
||||||
|
|
||||||
DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
|
DEBUGF 1,"ETH_output: size=%u device:%x\n", ecx, ebx
|
||||||
|
|
||||||
push esi
|
cmp ecx, [ebx + NET_DEVICE.mtu]
|
||||||
mov esi, [NET_DRV_LIST] ;;; TODO: FIXME
|
|
||||||
cmp ecx, [esi + NET_DEVICE.mtu]
|
|
||||||
pop esi
|
|
||||||
jg .exit
|
jg .exit
|
||||||
|
|
||||||
push ecx di eax ebx edx
|
push ecx ; << 1
|
||||||
|
push di eax edx ; << 2
|
||||||
add ecx, ETH_FRAME.Data
|
add ecx, ETH_FRAME.Data
|
||||||
push ecx
|
|
||||||
push ecx
|
push ecx ; << 3
|
||||||
call kernel_alloc
|
|
||||||
|
push ecx ; << 4
|
||||||
|
call kernel_alloc ; >> 4
|
||||||
|
test eax, eax
|
||||||
|
jz .out_of_ram
|
||||||
mov edi, eax
|
mov edi, eax
|
||||||
test edi, edi
|
|
||||||
jz .pop_exit
|
|
||||||
|
|
||||||
pop ecx
|
pop ecx ; >> 3
|
||||||
pop edx
|
|
||||||
|
|
||||||
pop esi
|
pop esi ; >> 2
|
||||||
movsd
|
movsd
|
||||||
movsw
|
movsw
|
||||||
pop esi
|
pop esi ; >> 2
|
||||||
movsd
|
movsd
|
||||||
movsw
|
movsw
|
||||||
pop ax
|
pop ax ; >> 2
|
||||||
stosw
|
stosw
|
||||||
|
|
||||||
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
|
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
|
||||||
mov edx, ecx ; Set ebx to complete buffer size
|
mov edx, ecx ; Set edx to complete buffer size
|
||||||
pop ecx
|
|
||||||
|
|
||||||
xor ebx, ebx ;;;; TODO: Fixme
|
pop ecx ; >> 1
|
||||||
mov ebx, [NET_DRV_LIST + ebx]
|
|
||||||
|
|
||||||
cmp edx, 46 + ETH_FRAME.Data ; If data size is less then 46, add padding bytes
|
cmp edx, 60-1 ; minimum ethernet packet size
|
||||||
jge .continue
|
jle .adjust_size
|
||||||
mov edx, 46 + ETH_FRAME.Data
|
DEBUGF 1,"ETH_output: done: %x total size: %u\n", eax, edx
|
||||||
.continue:
|
|
||||||
|
|
||||||
DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.pop_exit:
|
.adjust_size:
|
||||||
DEBUGF 2,"Out of ram space!!\n"
|
mov edx, 60
|
||||||
add esp, 18
|
ret
|
||||||
and edi, 0
|
|
||||||
|
.out_of_ram:
|
||||||
|
DEBUGF 2,"ETH_output: Out of ram space!!\n"
|
||||||
|
add esp, 3*4+2+4
|
||||||
|
sub edi, edi
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.exit:
|
.exit:
|
||||||
DEBUGF 2,"Packet too large!\n"
|
DEBUGF 2,"ETH_output: Packet too large!\n"
|
||||||
and edi, 0
|
sub edi, edi
|
||||||
|
;;; dec edi
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,21 +109,16 @@ endg
|
|||||||
;
|
;
|
||||||
; ICMP_init
|
; ICMP_init
|
||||||
;
|
;
|
||||||
; This function resets all ICMP variables
|
|
||||||
;
|
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
|
||||||
ICMP_init:
|
macro ICMP_init {
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov edi, ICMP_PACKETS_TX
|
mov edi, ICMP_PACKETS_TX
|
||||||
mov ecx, 2*MAX_IP
|
mov ecx, 2*MAX_IP
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
ret
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -235,7 +230,7 @@ ICMP_input:
|
|||||||
call IPv4_dest_to_dev
|
call IPv4_dest_to_dev
|
||||||
cmp edi,-1
|
cmp edi,-1
|
||||||
je .dump
|
je .dump
|
||||||
inc [ICMP_PACKETS_RX+4*edi]
|
inc [ICMP_PACKETS_RX+edi]
|
||||||
|
|
||||||
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
|
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
|
||||||
|
|
||||||
@ -284,10 +279,10 @@ ICMP_output:
|
|||||||
push esi edi edx
|
push esi edi edx
|
||||||
|
|
||||||
add ecx, ICMP_Packet.Data
|
add ecx, ICMP_Packet.Data
|
||||||
mov di , IP_PROTO_ICMP
|
mov di , IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
||||||
shr edx, 16
|
shr edx, 16
|
||||||
|
|
||||||
call IPv4_create_packet
|
call IPv4_output
|
||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
DEBUGF 1,"full icmp packet size: %u\n", edx
|
DEBUGF 1,"full icmp packet size: %u\n", edx
|
||||||
|
@ -5,8 +5,10 @@
|
|||||||
;; ;;
|
;; ;;
|
||||||
;; SOCKET.INC ;;
|
;; SOCKET.INC ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; Written by hidnplayr@kolibrios.org ;;
|
;; Written by hidnplayr@kolibrios.org, ;;
|
||||||
;; based on code by mike.dld ;;
|
;; and Clevermouse. ;;
|
||||||
|
;; ;;
|
||||||
|
;; Based on code by mike.dld ;;
|
||||||
;; ;;
|
;; ;;
|
||||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||||
;; Version 2, June 1991 ;;
|
;; Version 2, June 1991 ;;
|
||||||
@ -31,9 +33,7 @@ virtual at 0
|
|||||||
.errorcode dd ?
|
.errorcode dd ?
|
||||||
|
|
||||||
.options dd ?
|
.options dd ?
|
||||||
.SO_SND.SB_CC dd ? ;;;;; socket options: number of bytes in socket
|
.state dd ?
|
||||||
.SO_RCV.SB_CC dd ?
|
|
||||||
.state dd ? ;;;;;;;;;
|
|
||||||
|
|
||||||
.end:
|
.end:
|
||||||
end virtual
|
end virtual
|
||||||
@ -51,15 +51,6 @@ virtual at SOCKET.end
|
|||||||
.end:
|
.end:
|
||||||
end virtual
|
end virtual
|
||||||
|
|
||||||
virtual at SOCKET.end
|
|
||||||
|
|
||||||
SOCKET_virtual:
|
|
||||||
|
|
||||||
.ConnectedTo dd ? ; Socket number of other socket this one is connected to
|
|
||||||
|
|
||||||
.end:
|
|
||||||
end virtual
|
|
||||||
|
|
||||||
virtual at IP_SOCKET.end
|
virtual at IP_SOCKET.end
|
||||||
|
|
||||||
TCP_SOCKET:
|
TCP_SOCKET:
|
||||||
@ -114,7 +105,6 @@ virtual at IP_SOCKET.end
|
|||||||
|
|
||||||
;----------------------
|
;----------------------
|
||||||
; Transmit timing stuff
|
; Transmit timing stuff
|
||||||
|
|
||||||
.t_idle dd ?
|
.t_idle dd ?
|
||||||
.t_rtt dd ?
|
.t_rtt dd ?
|
||||||
.t_rtseq dd ?
|
.t_rtseq dd ?
|
||||||
@ -125,7 +115,6 @@ virtual at IP_SOCKET.end
|
|||||||
|
|
||||||
;-----------------
|
;-----------------
|
||||||
; Out-of-band data
|
; Out-of-band data
|
||||||
|
|
||||||
.t_oobflags dd ?
|
.t_oobflags dd ?
|
||||||
.t_iobc dd ?
|
.t_iobc dd ?
|
||||||
.t_softerror dd ?
|
.t_softerror dd ?
|
||||||
@ -133,7 +122,6 @@ virtual at IP_SOCKET.end
|
|||||||
|
|
||||||
;---------
|
;---------
|
||||||
; RFC 1323
|
; RFC 1323
|
||||||
|
|
||||||
.SND_SCALE db ? ; Scale factor
|
.SND_SCALE db ? ; Scale factor
|
||||||
.RCV_SCALE db ?
|
.RCV_SCALE db ?
|
||||||
.request_r_scale db ?
|
.request_r_scale db ?
|
||||||
@ -146,7 +134,6 @@ virtual at IP_SOCKET.end
|
|||||||
|
|
||||||
;-------
|
;-------
|
||||||
; Timers
|
; Timers
|
||||||
|
|
||||||
.timer_retransmission dw ? ; rexmt
|
.timer_retransmission dw ? ; rexmt
|
||||||
.timer_ack dw ?
|
.timer_ack dw ?
|
||||||
.timer_persist dw ?
|
.timer_persist dw ?
|
||||||
@ -176,9 +163,32 @@ virtual at IP_SOCKET.end
|
|||||||
.end:
|
.end:
|
||||||
end virtual
|
end virtual
|
||||||
|
|
||||||
|
struc RING_BUFFER {
|
||||||
|
.start_ptr dd ? ; Pointer to start of buffer
|
||||||
|
.end_ptr dd ? ; pointer to end of buffer
|
||||||
|
.read_ptr dd ? ; Read pointer
|
||||||
|
.write_ptr dd ? ; Write pointer
|
||||||
|
.size dd ? ; Number of bytes buffered
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual at 0
|
||||||
|
|
||||||
|
RING_BUFFER RING_BUFFER
|
||||||
|
|
||||||
|
end virtual
|
||||||
|
|
||||||
|
virtual at TCP_SOCKET.end
|
||||||
|
|
||||||
|
rcv RING_BUFFER
|
||||||
|
snd RING_BUFFER
|
||||||
|
|
||||||
|
STREAM_SOCKET:
|
||||||
|
.end:
|
||||||
|
|
||||||
|
end virtual
|
||||||
|
|
||||||
|
|
||||||
struct socket_queue_entry
|
struct socket_queue_entry
|
||||||
; .owner dd ?
|
|
||||||
.data_ptr dd ?
|
.data_ptr dd ?
|
||||||
.buf_ptr dd ?
|
.buf_ptr dd ?
|
||||||
.data_size dd ?
|
.data_size dd ?
|
||||||
@ -186,7 +196,6 @@ struct socket_queue_entry
|
|||||||
ends
|
ends
|
||||||
|
|
||||||
|
|
||||||
MAX_backlog equ 20 ; backlog for stream sockets
|
|
||||||
SOCKETBUFFSIZE equ 4096 ; in bytes
|
SOCKETBUFFSIZE equ 4096 ; in bytes
|
||||||
|
|
||||||
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
|
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
|
||||||
@ -204,24 +213,41 @@ endg
|
|||||||
;
|
;
|
||||||
; SOCKET_init
|
; SOCKET_init
|
||||||
;
|
;
|
||||||
; -
|
|
||||||
;
|
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
macro SOCKET_init {
|
||||||
socket_init:
|
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov edi, net_sockets
|
mov edi, net_sockets
|
||||||
mov ecx, 4
|
mov ecx, 4
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
mov [last_UDP_port], MIN_EPHEMERAL_PORT
|
;--- for random port --
|
||||||
mov [last_TCP_port], MIN_EPHEMERAL_PORT
|
|
||||||
|
|
||||||
ret
|
mov al, 0x0 ; set up 1s timer
|
||||||
|
out 0x70, al
|
||||||
|
in al, 0x71
|
||||||
|
|
||||||
|
;----------------------
|
||||||
|
|
||||||
|
@@:
|
||||||
|
pseudo_random eax
|
||||||
|
cmp ax, MIN_EPHEMERAL_PORT
|
||||||
|
jl @r
|
||||||
|
cmp ax, MAX_EPHEMERAL_PORT
|
||||||
|
jg @r
|
||||||
|
|
||||||
|
mov [last_UDP_port], ax
|
||||||
|
|
||||||
|
@@:
|
||||||
|
pseudo_random eax
|
||||||
|
cmp ax, MIN_EPHEMERAL_PORT
|
||||||
|
jl @r
|
||||||
|
cmp ax, MAX_EPHEMERAL_PORT
|
||||||
|
jg @r
|
||||||
|
|
||||||
|
mov [last_TCP_port], ax
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
@ -232,11 +258,20 @@ socket_init:
|
|||||||
align 4
|
align 4
|
||||||
sys_socket:
|
sys_socket:
|
||||||
cmp ebx, 8 ; highest possible number
|
cmp ebx, 8 ; highest possible number
|
||||||
jg s_error
|
jg @f
|
||||||
lea ebx, [.table + 4*ebx]
|
lea ebx, [sock_sysfn_table + 4*ebx]
|
||||||
jmp dword [ebx]
|
jmp dword [ebx]
|
||||||
|
@@:
|
||||||
|
cmp ebx, 255
|
||||||
|
jz SOCKET_debug
|
||||||
|
|
||||||
.table:
|
s_error:
|
||||||
|
DEBUGF 1,"socket error\n"
|
||||||
|
mov dword [esp+32], -1
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
sock_sysfn_table:
|
||||||
dd SOCKET_open ; 0
|
dd SOCKET_open ; 0
|
||||||
dd SOCKET_close ; 1
|
dd SOCKET_close ; 1
|
||||||
dd SOCKET_bind ; 2
|
dd SOCKET_bind ; 2
|
||||||
@ -249,12 +284,6 @@ sys_socket:
|
|||||||
; dd SOCKET_set_opt ; 9
|
; dd SOCKET_set_opt ; 9
|
||||||
|
|
||||||
|
|
||||||
s_error:
|
|
||||||
DEBUGF 1,"socket error\n"
|
|
||||||
mov dword [esp+32], -1
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
@ -280,6 +309,40 @@ SOCKET_open:
|
|||||||
|
|
||||||
mov [esp+32], edi
|
mov [esp+32], edi
|
||||||
|
|
||||||
|
cmp ecx, AF_INET4
|
||||||
|
jnz .no_stream
|
||||||
|
|
||||||
|
push [IP_LIST] ;;;;
|
||||||
|
pop [eax + IP_SOCKET.LocalIP] ;;;;
|
||||||
|
|
||||||
|
cmp edx, IP_PROTO_TCP
|
||||||
|
jnz .no_stream
|
||||||
|
|
||||||
|
mov esi, eax
|
||||||
|
stdcall kernel_alloc, SOCKET_MAXDATA
|
||||||
|
mov [esi + rcv.start_ptr], eax
|
||||||
|
mov [esi + rcv.write_ptr], eax
|
||||||
|
mov [esi + rcv.read_ptr], eax
|
||||||
|
mov [esi + rcv.size], 0
|
||||||
|
add eax, SOCKET_MAXDATA
|
||||||
|
mov [esi + rcv.end_ptr], eax
|
||||||
|
|
||||||
|
stdcall kernel_alloc, SOCKET_MAXDATA
|
||||||
|
mov [esi + snd.start_ptr], eax
|
||||||
|
mov [esi + snd.write_ptr], eax
|
||||||
|
mov [esi + snd.read_ptr], eax
|
||||||
|
mov [esi + snd.size], 0
|
||||||
|
add eax, SOCKET_MAXDATA
|
||||||
|
mov [esi + snd.end_ptr], eax
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.no_stream:
|
||||||
|
|
||||||
|
push edi
|
||||||
|
init_queue (eax + SOCKET_QUEUE_LOCATION)
|
||||||
|
pop edi
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
@ -347,9 +410,6 @@ SOCKET_bind:
|
|||||||
DEBUGF 1,"using local port: %u\n", bx
|
DEBUGF 1,"using local port: %u\n", bx
|
||||||
mov word [eax + UDP_SOCKET.LocalPort], bx
|
mov word [eax + UDP_SOCKET.LocalPort], bx
|
||||||
|
|
||||||
mov ebx, dword [edx + 4]
|
|
||||||
mov dword [eax + IP_SOCKET.LocalIP], ebx
|
|
||||||
|
|
||||||
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
|
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
|
||||||
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
|
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
|
||||||
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
|
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
|
||||||
@ -411,21 +471,11 @@ SOCKET_connect:
|
|||||||
|
|
||||||
|
|
||||||
.tcp:
|
.tcp:
|
||||||
; set sequence number
|
|
||||||
|
|
||||||
mov ebx, [TCP_sequence_num]
|
|
||||||
add [TCP_sequence_num], 6400
|
|
||||||
mov [eax + TCP_SOCKET.ISS], ebx
|
|
||||||
|
|
||||||
mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*630ms => 75,6 seconds
|
|
||||||
|
|
||||||
lea ebx, [eax + SOCKET.lock]
|
lea ebx, [eax + SOCKET.lock]
|
||||||
call wait_mutex
|
call wait_mutex
|
||||||
|
|
||||||
; fill in remote port and IP
|
; fill in remote port and IP
|
||||||
|
|
||||||
;;;;;; mov [eax + TCP_SOCKET.wndsizeTimer], 0 ; Reset the window timer.
|
|
||||||
|
|
||||||
mov bx , word [edx + 2]
|
mov bx , word [edx + 2]
|
||||||
mov [eax + TCP_SOCKET.RemotePort], bx
|
mov [eax + TCP_SOCKET.RemotePort], bx
|
||||||
DEBUGF 1,"remote port: %u\n", bx
|
DEBUGF 1,"remote port: %u\n", bx
|
||||||
@ -435,21 +485,25 @@ SOCKET_connect:
|
|||||||
|
|
||||||
; check if local port and IP is ok
|
; check if local port and IP is ok
|
||||||
|
|
||||||
cmp [eax + IP_SOCKET.LocalIP], 0
|
|
||||||
jne @f
|
|
||||||
push [IP_LIST] ;;;;; device zero = default
|
|
||||||
pop [eax + IP_SOCKET.LocalIP]
|
|
||||||
@@:
|
|
||||||
|
|
||||||
cmp [eax + TCP_SOCKET.LocalPort], 0
|
cmp [eax + TCP_SOCKET.LocalPort], 0
|
||||||
jne @f
|
jne @f
|
||||||
call SOCKET_find_port
|
call SOCKET_find_port
|
||||||
@@:
|
@@:
|
||||||
|
DEBUGF 1,"local port: %u\n", [eax + TCP_SOCKET.LocalPort]:2
|
||||||
|
|
||||||
DEBUGF 1,"remote port: %u\n", [eax + TCP_SOCKET.LocalPort]:2
|
;;;;;
|
||||||
|
mov [eax + TCP_SOCKET.timer_persist], 0
|
||||||
|
mov [eax + TCP_SOCKET.t_state], TCB_SYN_SENT
|
||||||
|
mov ebx, [TCP_sequence_num]
|
||||||
|
add [TCP_sequence_num], 6400
|
||||||
|
mov [eax + TCP_SOCKET.ISS], ebx
|
||||||
|
mov [eax + TCP_SOCKET.timer_keepalive], 120 ; 120*640ms => 75,6 seconds
|
||||||
|
|
||||||
; mov [eax + TCP_SOCKET.t_state], TCB_SYN_SENT
|
;;;; mov [ebx + TCP_SOCKET.timer_retransmission],
|
||||||
|
|
||||||
|
push eax
|
||||||
call TCP_output
|
call TCP_output
|
||||||
|
pop eax
|
||||||
|
|
||||||
mov [eax + SOCKET.lock], 0
|
mov [eax + SOCKET.lock], 0
|
||||||
|
|
||||||
@ -583,11 +637,11 @@ SOCKET_close:
|
|||||||
test [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED ;;;;;;
|
test [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED ;;;;;;
|
||||||
jz .free
|
jz .free
|
||||||
|
|
||||||
call TCP_output
|
;;; call TCP_output
|
||||||
|
|
||||||
mov dword [esp+32], 0
|
;;; mov dword [esp+32], 0
|
||||||
|
|
||||||
ret
|
;;; ret
|
||||||
|
|
||||||
; state must be LISTEN, SYN_SENT, CLOSED or maybe even invalid
|
; state must be LISTEN, SYN_SENT, CLOSED or maybe even invalid
|
||||||
; so, we may destroy the socket
|
; so, we may destroy the socket
|
||||||
@ -688,6 +742,12 @@ SOCKET_send:
|
|||||||
.af_inet4:
|
.af_inet4:
|
||||||
DEBUGF 1,"af_inet4\n"
|
DEBUGF 1,"af_inet4\n"
|
||||||
|
|
||||||
|
cmp [eax + IP_SOCKET.LocalIP], 0
|
||||||
|
jne @f
|
||||||
|
mov ebx, [IP_LIST] ;;;;
|
||||||
|
mov dword [eax + IP_SOCKET.LocalIP], ebx
|
||||||
|
@@:
|
||||||
|
|
||||||
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
||||||
je .tcp
|
je .tcp
|
||||||
|
|
||||||
@ -790,6 +850,35 @@ SOCKET_get_opt:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; SOCKET_debug
|
||||||
|
;
|
||||||
|
; Copies socket variables to application buffer
|
||||||
|
;
|
||||||
|
; IN: ecx = socket number
|
||||||
|
; edx = pointer to buffer
|
||||||
|
;
|
||||||
|
; OUT: -1 on error
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
SOCKET_debug:
|
||||||
|
|
||||||
|
DEBUGF 1,"socket_debug\n"
|
||||||
|
|
||||||
|
call SOCKET_num_to_ptr
|
||||||
|
jz s_error
|
||||||
|
|
||||||
|
mov esi, eax
|
||||||
|
mov edi, edx
|
||||||
|
mov ecx, SOCKETBUFFSIZE/4
|
||||||
|
rep movsd
|
||||||
|
|
||||||
|
mov dword [esp+32], 0
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; SOCKET_find_port
|
; SOCKET_find_port
|
||||||
@ -939,6 +1028,188 @@ SOCKET_input:
|
|||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; SOCKET_ring_add
|
||||||
|
;
|
||||||
|
; Adds data to a stream socket
|
||||||
|
;
|
||||||
|
; IN: eax = ptr to ring struct
|
||||||
|
; ecx = data size
|
||||||
|
; esi = ptr to data
|
||||||
|
;
|
||||||
|
; OUT: eax = number of bytes stored
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
SOCKET_ring_add:
|
||||||
|
|
||||||
|
DEBUGF 1,"SOCKET_ring_add: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
|
||||||
|
|
||||||
|
mov edi, [eax + RING_BUFFER.size]
|
||||||
|
add edi, ecx
|
||||||
|
cmp edi, SOCKET_MAXDATA
|
||||||
|
jg .too_large
|
||||||
|
|
||||||
|
mov [eax + RING_BUFFER.size], edi ; update size
|
||||||
|
.copy:
|
||||||
|
push ecx ;<<<< 1
|
||||||
|
mov edi, [eax + RING_BUFFER.write_ptr] ; set write ptr in edi
|
||||||
|
add [eax + RING_BUFFER.write_ptr], ecx ; update write pointer
|
||||||
|
mov edx, [eax + RING_BUFFER.end_ptr]
|
||||||
|
cmp edx, [eax + RING_BUFFER.write_ptr]
|
||||||
|
jg .copy_in_2
|
||||||
|
je .wrap_write_ptr
|
||||||
|
|
||||||
|
.copy_more:
|
||||||
|
push ecx
|
||||||
|
and ecx, 3
|
||||||
|
rep movsb
|
||||||
|
pop ecx
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
pop ecx ; >>>> 1/2
|
||||||
|
DEBUGF 2,"Copied %u bytes\n", ecx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.too_large:
|
||||||
|
mov ecx, SOCKET_MAXDATA ; calculate number of bytes available in buffer
|
||||||
|
sub ecx, [eax + RING_BUFFER.size]
|
||||||
|
jz .full
|
||||||
|
|
||||||
|
mov [eax + RING_BUFFER.size], SOCKET_MAXDATA ; update size, we will fill buffer completely
|
||||||
|
|
||||||
|
jmp .copy
|
||||||
|
|
||||||
|
.full:
|
||||||
|
DEBUGF 2,"Ring buffer is full!\n"
|
||||||
|
xor ecx, ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.copy_in_2:
|
||||||
|
DEBUGF 1,"Copying in 2 passes\n"
|
||||||
|
|
||||||
|
mov edx, ecx
|
||||||
|
mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer
|
||||||
|
sub ecx, edi
|
||||||
|
sub edx, ecx
|
||||||
|
push edx ; <<<< 2
|
||||||
|
|
||||||
|
mov edi, [eax + RING_BUFFER.start_ptr]
|
||||||
|
call .copy_more
|
||||||
|
|
||||||
|
.wrap_write_ptr:
|
||||||
|
sub [eax + RING_BUFFER.write_ptr], SOCKET_MAXDATA ; update write pointer
|
||||||
|
jmp .copy_more
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; SOCKET_ring_read
|
||||||
|
;
|
||||||
|
; reads the data, but let the data remain in the buffer
|
||||||
|
;
|
||||||
|
; IN: eax = ptr to ring struct
|
||||||
|
; ecx = buffer size
|
||||||
|
; edi = ptr to buffer
|
||||||
|
;
|
||||||
|
; OUT: eax = number of bytes read
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
SOCKET_ring_read:
|
||||||
|
|
||||||
|
DEBUGF 1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
|
||||||
|
|
||||||
|
cmp [eax + RING_BUFFER.size], ecx ; update size
|
||||||
|
jl .too_large
|
||||||
|
|
||||||
|
mov esi, [eax + RING_BUFFER.read_ptr] ; update read ptr
|
||||||
|
.copy:
|
||||||
|
push ecx ;<<<< 1
|
||||||
|
mov edx, [eax + RING_BUFFER.read_ptr]
|
||||||
|
add edx, ecx
|
||||||
|
cmp edx, [eax + RING_BUFFER.end_ptr]
|
||||||
|
jg .copy_in_2
|
||||||
|
|
||||||
|
.copy_more:
|
||||||
|
push ecx
|
||||||
|
and ecx, 3
|
||||||
|
rep movsb
|
||||||
|
pop ecx
|
||||||
|
shr ecx, 2
|
||||||
|
rep movsd
|
||||||
|
pop ecx ; >>>> 1/2
|
||||||
|
DEBUGF 2,"Copied %u bytes\n", ecx
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.too_large:
|
||||||
|
mov ecx, [eax + RING_BUFFER.size]
|
||||||
|
jmp .copy
|
||||||
|
|
||||||
|
.full:
|
||||||
|
DEBUGF 2,"Ring buffer is full!\n"
|
||||||
|
xor ecx, ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.copy_in_2:
|
||||||
|
DEBUGF 1,"Copying in 2 passes\n"
|
||||||
|
|
||||||
|
mov edx, ecx
|
||||||
|
mov ecx, [eax + RING_BUFFER.end_ptr] ; find number of bytes till end of buffer
|
||||||
|
sub ecx, edi
|
||||||
|
sub edx, ecx
|
||||||
|
push edx ; <<<< 2
|
||||||
|
|
||||||
|
mov esi, [eax + RING_BUFFER.start_ptr]
|
||||||
|
call .copy_more
|
||||||
|
|
||||||
|
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
;
|
||||||
|
; SOCKET_ring_free
|
||||||
|
;
|
||||||
|
; Free's some bytes from the ringbuffer
|
||||||
|
;
|
||||||
|
; IN: eax = ptr to ring struct
|
||||||
|
; ecx = data size
|
||||||
|
;
|
||||||
|
; OUT: ecx = number of bytes free-ed
|
||||||
|
;
|
||||||
|
;-----------------------------------------------------------------
|
||||||
|
align 4
|
||||||
|
SOCKET_ring_free:
|
||||||
|
|
||||||
|
DEBUGF 1,"Trying to free %u bytes of data from ring %x\n", ecx, eax
|
||||||
|
|
||||||
|
cmp ecx, [eax + RING_BUFFER.size]
|
||||||
|
jle .go_for_it
|
||||||
|
|
||||||
|
cmp ecx, SOCKET_MAXDATA ;;;;
|
||||||
|
jg .moron_input
|
||||||
|
|
||||||
|
mov ecx, [eax + RING_BUFFER.size]
|
||||||
|
|
||||||
|
.go_for_it:
|
||||||
|
sub [eax + RING_BUFFER.size], ecx
|
||||||
|
add [eax + RING_BUFFER.read_ptr], ecx
|
||||||
|
|
||||||
|
mov edx, [eax + RING_BUFFER.end_ptr]
|
||||||
|
cmp [eax + RING_BUFFER.read_ptr], edx
|
||||||
|
jl @f
|
||||||
|
sub [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA ;;;;;
|
||||||
|
@@:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.moron_input:
|
||||||
|
xor ecx, ecx
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; SOCKET_notify_owner
|
; SOCKET_notify_owner
|
||||||
@ -1011,7 +1282,7 @@ SOCKET_alloc:
|
|||||||
push ecx ebx
|
push ecx ebx
|
||||||
|
|
||||||
stdcall kernel_alloc, SOCKETBUFFSIZE
|
stdcall kernel_alloc, SOCKETBUFFSIZE
|
||||||
DEBUGF 1, "socket_alloc: %x ", eax
|
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
|
||||||
or eax, eax
|
or eax, eax
|
||||||
jz .exit
|
jz .exit
|
||||||
|
|
||||||
@ -1023,17 +1294,14 @@ SOCKET_alloc:
|
|||||||
rep stosd
|
rep stosd
|
||||||
pop edi eax
|
pop edi eax
|
||||||
|
|
||||||
init_queue (eax + SOCKET_QUEUE_LOCATION)
|
|
||||||
|
|
||||||
; find first free socket number and use it
|
; find first free socket number and use it
|
||||||
|
|
||||||
mov ebx, net_sockets
|
mov ebx, net_sockets
|
||||||
xor ecx, ecx
|
xor ecx, ecx
|
||||||
.next_socket_number:
|
.next_socket_number:
|
||||||
inc ecx
|
inc ecx
|
||||||
.next_socket:
|
.next_socket:
|
||||||
mov ebx, [ebx + SOCKET.NextPtr]
|
mov ebx, [ebx + SOCKET.NextPtr]
|
||||||
or ebx, ebx
|
test ebx, ebx
|
||||||
jz .last_socket
|
jz .last_socket
|
||||||
cmp [ebx + SOCKET.Number], ecx
|
cmp [ebx + SOCKET.Number], ecx
|
||||||
jne .next_socket
|
jne .next_socket
|
||||||
@ -1042,23 +1310,21 @@ SOCKET_alloc:
|
|||||||
|
|
||||||
.last_socket:
|
.last_socket:
|
||||||
mov [eax + SOCKET.Number], ecx
|
mov [eax + SOCKET.Number], ecx
|
||||||
|
DEBUGF 1, "SOCKET_alloc: number=%u\n", ecx
|
||||||
DEBUGF 1, "(number: %u)\n", ecx
|
mov edi, ecx
|
||||||
|
|
||||||
; Fill in PID
|
; Fill in PID
|
||||||
mov ebx, [TASK_BASE]
|
mov ebx, [TASK_BASE]
|
||||||
mov ebx, [ebx + TASKDATA.pid]
|
mov ebx, [ebx + TASKDATA.pid]
|
||||||
|
|
||||||
mov [eax + SOCKET.PID], ebx
|
mov [eax + SOCKET.PID], ebx
|
||||||
|
|
||||||
; add socket to the list by changing pointers
|
; add socket to the list by re-arranging some pointers
|
||||||
|
|
||||||
mov ebx, [net_sockets + SOCKET.NextPtr]
|
mov ebx, [net_sockets + SOCKET.NextPtr]
|
||||||
|
|
||||||
mov [eax + SOCKET.PrevPtr], net_sockets
|
mov [eax + SOCKET.PrevPtr], net_sockets
|
||||||
mov [eax + SOCKET.NextPtr], ebx
|
mov [eax + SOCKET.NextPtr], ebx
|
||||||
|
|
||||||
or ebx, ebx
|
test ebx, ebx
|
||||||
jz @f
|
jz @f
|
||||||
add ebx, SOCKET.lock ; lock the next socket
|
add ebx, SOCKET.lock ; lock the next socket
|
||||||
call wait_mutex
|
call wait_mutex
|
||||||
@ -1068,8 +1334,6 @@ SOCKET_alloc:
|
|||||||
@@:
|
@@:
|
||||||
|
|
||||||
mov [net_sockets + SOCKET.NextPtr], eax
|
mov [net_sockets + SOCKET.NextPtr], eax
|
||||||
|
|
||||||
mov edi, ecx
|
|
||||||
or eax, eax ; used to clear zero flag
|
or eax, eax ; used to clear zero flag
|
||||||
.exit:
|
.exit:
|
||||||
pop ebx ecx
|
pop ebx ecx
|
||||||
@ -1101,6 +1365,16 @@ SOCKET_free:
|
|||||||
|
|
||||||
DEBUGF 1, "freeing socket..\n"
|
DEBUGF 1, "freeing socket..\n"
|
||||||
|
|
||||||
|
cmp [eax + SOCKET.Domain], AF_INET4
|
||||||
|
jnz .no_stream
|
||||||
|
|
||||||
|
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
||||||
|
jnz .no_stream
|
||||||
|
|
||||||
|
stdcall kernel_free, [eax + rcv.start_ptr]
|
||||||
|
stdcall kernel_free, [eax + snd.start_ptr]
|
||||||
|
.no_stream:
|
||||||
|
|
||||||
push eax ; this will be passed to kernel_free
|
push eax ; this will be passed to kernel_free
|
||||||
mov ebx, [eax + SOCKET.NextPtr]
|
mov ebx, [eax + SOCKET.NextPtr]
|
||||||
mov eax, [eax + SOCKET.PrevPtr]
|
mov eax, [eax + SOCKET.PrevPtr]
|
||||||
@ -1126,6 +1400,39 @@ SOCKET_free:
|
|||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
; socket nr in ebx
|
||||||
|
; new socket nr in eax
|
||||||
|
; preserver edx
|
||||||
|
|
||||||
|
align 4
|
||||||
|
SOCKET_fork:
|
||||||
|
|
||||||
|
;; Exit if backlog queue is full
|
||||||
|
; mov ax, [ebx + TCP_SOCKET.backlog_cur]
|
||||||
|
; cmp ax, [ebx + TCP_SOCKET.backlog]
|
||||||
|
; jae .exit
|
||||||
|
|
||||||
|
; Allocate new socket
|
||||||
|
call SOCKET_alloc
|
||||||
|
;;; jz .fail
|
||||||
|
|
||||||
|
; Copy structure from current socket to new, (including lock!)
|
||||||
|
; We start at PID to reserve the socket num, and the 2 pointers at beginning of socket
|
||||||
|
lea esi, [edx + SOCKET.PID]
|
||||||
|
lea edi, [eax + SOCKET.PID]
|
||||||
|
mov ecx, (TCP_SOCKET.end - SOCKET.PID + 3)/4
|
||||||
|
rep movsd
|
||||||
|
|
||||||
|
;; Push pointer to new socket to queue
|
||||||
|
; movzx ecx, [ebx + TCP_SOCKET.backlog_cur]
|
||||||
|
; inc [ebx + TCP_SOCKET.backlog_cur]
|
||||||
|
; mov [ebx + TCP_SOCKET.end + ecx*4], eax
|
||||||
|
|
||||||
|
;;;; mov [eax + IP_SOCKET.RemoteIP], esi ; IP source address
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------
|
;---------------------------------------------------
|
||||||
;
|
;
|
||||||
; SOCKET_num_to_ptr
|
; SOCKET_num_to_ptr
|
||||||
|
@ -68,12 +68,14 @@ SOCK_RAW equ 3
|
|||||||
; Socket options
|
; Socket options
|
||||||
SO_ACCEPTCON equ 1
|
SO_ACCEPTCON equ 1
|
||||||
|
|
||||||
SOCKET_MAXDATA equ 4096
|
SOCKET_MAXDATA equ 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
|
||||||
|
|
||||||
; Network driver types
|
; Network driver types
|
||||||
NET_TYPE_ETH equ 1
|
NET_TYPE_ETH equ 1
|
||||||
NET_TYPE_SLIP equ 2
|
NET_TYPE_SLIP equ 2
|
||||||
|
|
||||||
|
MAX_backlog equ 20 ; backlog for stream sockets
|
||||||
|
|
||||||
|
|
||||||
virtual at 0
|
virtual at 0
|
||||||
|
|
||||||
@ -92,6 +94,8 @@ virtual at 0
|
|||||||
.packets_tx dd ? ;
|
.packets_tx dd ? ;
|
||||||
.packets_rx dd ? ;
|
.packets_rx dd ? ;
|
||||||
|
|
||||||
|
; .chksum dd ? ; bitmask stating available checksum routines on hardware
|
||||||
|
|
||||||
.end:
|
.end:
|
||||||
|
|
||||||
end virtual
|
end virtual
|
||||||
@ -102,6 +106,7 @@ macro pseudo_random reg {
|
|||||||
add reg, [esp]
|
add reg, [esp]
|
||||||
rol reg, 5
|
rol reg, 5
|
||||||
xor reg, [timer_ticks]
|
xor reg, [timer_ticks]
|
||||||
|
add reg, [CPU_FREQ]
|
||||||
imul reg, 214013
|
imul reg, 214013
|
||||||
xor reg, 0xdeadbeef
|
xor reg, 0xdeadbeef
|
||||||
rol reg, 9
|
rol reg, 9
|
||||||
@ -111,7 +116,7 @@ macro ntohld reg {
|
|||||||
|
|
||||||
rol word reg, 8
|
rol word reg, 8
|
||||||
rol dword reg, 16
|
rol dword reg, 16
|
||||||
rol word reg, 8
|
rol word reg , 8
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,6 +127,18 @@ macro ntohlw reg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macro packet_to_debug { ; set esi to packet you want to print, ecx to number of bytes
|
||||||
|
|
||||||
|
local .loop
|
||||||
|
|
||||||
|
.loop:
|
||||||
|
lodsb
|
||||||
|
DEBUGF 1,"%x ", eax:2
|
||||||
|
loop @r
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
include "queue.inc"
|
include "queue.inc"
|
||||||
|
|
||||||
include "ethernet.inc"
|
include "ethernet.inc"
|
||||||
@ -161,25 +178,23 @@ align 4
|
|||||||
stack_init:
|
stack_init:
|
||||||
|
|
||||||
; Init the network drivers list
|
; Init the network drivers list
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov edi, NET_RUNNING
|
mov edi, NET_RUNNING
|
||||||
mov ecx, MAX_NET_DEVICES + 1
|
mov ecx, MAX_NET_DEVICES + 1
|
||||||
rep stosd
|
rep stosd
|
||||||
|
|
||||||
; Call other init procedures
|
ETH_init
|
||||||
|
; SLIP_init
|
||||||
|
; PPPOE_init
|
||||||
|
|
||||||
call ETH_init
|
IPv4_init
|
||||||
; call SLIP_init
|
ICMP_init
|
||||||
|
|
||||||
call IPv4_init
|
ARP_init
|
||||||
call ICMP_init
|
UDP_init
|
||||||
|
TCP_init
|
||||||
|
|
||||||
call ARP_init
|
SOCKET_init
|
||||||
call UDP_init
|
|
||||||
call TCP_init
|
|
||||||
|
|
||||||
call socket_init
|
|
||||||
|
|
||||||
mov [net_tmr_count], 0
|
mov [net_tmr_count], 0
|
||||||
|
|
||||||
@ -211,14 +226,14 @@ stack_handler:
|
|||||||
test [net_10ms], 0x0f ; 160ms
|
test [net_10ms], 0x0f ; 160ms
|
||||||
jnz .exit
|
jnz .exit
|
||||||
|
|
||||||
; call TCP_timer_160ms
|
TCP_timer_160ms
|
||||||
|
|
||||||
test [net_10ms], 0x3f ; 640ms
|
test [net_10ms], 0x3f ; 640ms
|
||||||
jnz .exit
|
jnz .exit
|
||||||
|
|
||||||
; call TCP_timer_640ms
|
TCP_timer_640ms
|
||||||
call ARP_decrease_entry_ttls
|
ARP_decrease_entry_ttls
|
||||||
call IPv4_decrease_fragment_ttls
|
IPv4_decrease_fragment_ttls
|
||||||
|
|
||||||
.exit:
|
.exit:
|
||||||
ret
|
ret
|
||||||
@ -275,13 +290,13 @@ NET_add_device:
|
|||||||
jmp .error
|
jmp .error
|
||||||
|
|
||||||
.ethernet:
|
.ethernet:
|
||||||
DEBUGF 1,"Trying to add an ethernet driver\n"
|
DEBUGF 1,"Trying to add an ethernet device\n"
|
||||||
|
|
||||||
inc [ETH_RUNNING] ; Indicate that one more ethernet device is up and running
|
inc [ETH_RUNNING] ; Indicate that one more ethernet device is up and running
|
||||||
jmp .add_it
|
jmp .add_it
|
||||||
|
|
||||||
.slip:
|
.slip:
|
||||||
DEBUGF 1,"Trying to add a slip driver\n"
|
DEBUGF 1,"Trying to add a slip device\n"
|
||||||
;;;;
|
;;;;
|
||||||
jmp .error
|
jmp .error
|
||||||
|
|
||||||
@ -490,15 +505,15 @@ checksum_2:
|
|||||||
|
|
||||||
mov ecx, edx
|
mov ecx, edx
|
||||||
shr ecx, 16
|
shr ecx, 16
|
||||||
add edx, ecx
|
add dx, cx
|
||||||
|
test dx, dx ; it seems that ZF is not set when CF is set :(
|
||||||
not dx
|
not dx
|
||||||
jnz .not_zero
|
jnz .not_zero
|
||||||
dec dx
|
dec dx
|
||||||
.not_zero:
|
.not_zero:
|
||||||
xchg dl, dh
|
xchg dl, dh
|
||||||
|
|
||||||
DEBUGF 1,"Checksum: %x\n",dx
|
DEBUGF 1,"Checksum: %x\n", dx
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -40,19 +40,62 @@ endg
|
|||||||
;
|
;
|
||||||
; This function resets all UDP variables
|
; This function resets all UDP variables
|
||||||
;
|
;
|
||||||
; IN: /
|
|
||||||
; OUT: /
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
align 4
|
macro UDP_init {
|
||||||
UDP_init:
|
|
||||||
|
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
mov edi, UDP_PACKETS_TX
|
mov edi, UDP_PACKETS_TX
|
||||||
mov ecx, 2*MAX_IP
|
mov ecx, 2*MAX_IP
|
||||||
rep stosd
|
rep stosd
|
||||||
|
}
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
macro UDP_checksum IP1, IP2 { ; esi = ptr to udp packet, ecx = packet size, destroys: ecx, edx
|
||||||
|
|
||||||
|
; Pseudoheader
|
||||||
|
mov edx, IP_PROTO_UDP
|
||||||
|
|
||||||
|
add dl, [IP1+1+4]
|
||||||
|
adc dh, [IP1+0+4]
|
||||||
|
adc dl, [IP1+3+4]
|
||||||
|
adc dh, [IP1+2+4]
|
||||||
|
|
||||||
|
adc dl, [IP2+1+8]
|
||||||
|
adc dh, [IP2+0+8]
|
||||||
|
adc dl, [IP2+3+8]
|
||||||
|
adc dh, [IP2+2+8]
|
||||||
|
|
||||||
|
adc dl, cl ; byte[esi+UDP_Packet.Length+1]
|
||||||
|
adc dh, ch ; byte[esi+UDP_Packet.Length+0]
|
||||||
|
|
||||||
|
; Done with pseudoheader, now do real header
|
||||||
|
adc dl, byte[esi+UDP_Packet.SourcePort+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.SourcePort+0]
|
||||||
|
|
||||||
|
adc dl, byte[esi+UDP_Packet.DestinationPort+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.DestinationPort+0]
|
||||||
|
|
||||||
|
adc dl, byte[esi+UDP_Packet.Length+1]
|
||||||
|
adc dh, byte[esi+UDP_Packet.Length+0]
|
||||||
|
|
||||||
|
adc edx, 0
|
||||||
|
|
||||||
|
; Done with header, now do data
|
||||||
|
push esi
|
||||||
|
movzx ecx, [esi+UDP_Packet.Length]
|
||||||
|
rol cx , 8
|
||||||
|
sub cx , UDP_Packet.Data
|
||||||
|
add esi, UDP_Packet.Data
|
||||||
|
|
||||||
|
call checksum_1
|
||||||
|
call checksum_2
|
||||||
|
pop esi
|
||||||
|
|
||||||
|
add [esi+UDP_Packet.Checksum], dx ; this final instruction will set or clear ZF :)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
;-----------------------------------------------------------------
|
||||||
@ -62,11 +105,11 @@ UDP_init:
|
|||||||
; Called by IPv4_input,
|
; Called by IPv4_input,
|
||||||
; this procedure will inject the udp data diagrams in the application sockets.
|
; this procedure will inject the udp data diagrams in the application sockets.
|
||||||
;
|
;
|
||||||
; IN: Pointer to buffer in [esp]
|
; IN: [esp] = Pointer to buffer
|
||||||
; size of buffer in [esp+4]
|
; [esp+4] = size of buffer
|
||||||
; pointer to device struct in ebx
|
; ebx = ptr to device struct
|
||||||
; UDP Packet size in ecx
|
; ecx = UDP Packet size
|
||||||
; pointer to UDP Packet in edx
|
; edx = ptr to UDP header
|
||||||
;
|
;
|
||||||
; esi = ipv4 source address
|
; esi = ipv4 source address
|
||||||
; edi = ipv4 dest address
|
; edi = ipv4 dest address
|
||||||
@ -80,18 +123,18 @@ UDP_input:
|
|||||||
DEBUGF 1,"UDP_input, size:%u\n", ecx
|
DEBUGF 1,"UDP_input, size:%u\n", ecx
|
||||||
|
|
||||||
; First validate, checksum:
|
; First validate, checksum:
|
||||||
cmp [edx + UDP_Packet.Checksum], 0
|
neg [esi+UDP_Packet.Checksum] ; substract chechksum from 0
|
||||||
jz .no_checksum
|
jz .no_checksum ; if checksum is zero, it is considered valid and we continue processing
|
||||||
|
; otherwise, we will re-calculate the checksum and add it to this value, thus creating 0 when it is correct
|
||||||
xchg edi, esi ; save ipv4 source address to edi so we can use it later
|
|
||||||
|
|
||||||
push edx
|
push edx
|
||||||
push esi edi
|
push edi
|
||||||
|
push esi
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
call UDP_checksum ; this destroys edx, ecx and esi (but not edi...)
|
UDP_checksum (esp), (esp+4)
|
||||||
|
pop edi
|
||||||
|
pop esi ; we dont need it, but it is smaller then add esp, 4
|
||||||
pop edx
|
pop edx
|
||||||
|
|
||||||
cmp [edx + UDP_Packet.Checksum], 0
|
|
||||||
jnz .checksum_mismatch
|
jnz .checksum_mismatch
|
||||||
|
|
||||||
.no_checksum:
|
.no_checksum:
|
||||||
@ -168,12 +211,6 @@ UDP_input:
|
|||||||
|
|
||||||
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
||||||
|
|
||||||
; mov esi, edx
|
|
||||||
; @@: ;
|
|
||||||
; lodsb ;
|
|
||||||
; DEBUGF 2,"%x ", eax:2 ;
|
|
||||||
; loop @r ;
|
|
||||||
|
|
||||||
.dump:
|
.dump:
|
||||||
call kernel_free
|
call kernel_free
|
||||||
add esp, 4 ; pop (balance stack)
|
add esp, 4 ; pop (balance stack)
|
||||||
@ -207,26 +244,23 @@ UDP_output:
|
|||||||
DEBUGF 1,"local port: %u\n", dx
|
DEBUGF 1,"local port: %u\n", dx
|
||||||
rol dx, 8
|
rol dx, 8
|
||||||
|
|
||||||
|
|
||||||
mov ebx, [eax + IP_SOCKET.LocalIP]
|
mov ebx, [eax + IP_SOCKET.LocalIP]
|
||||||
mov eax, [eax + IP_SOCKET.RemoteIP]
|
mov eax, [eax + IP_SOCKET.RemoteIP]
|
||||||
|
|
||||||
mov di , IP_PROTO_UDP
|
mov di, IP_PROTO_UDP shl 8 + 128
|
||||||
sub esp, 8 ; Data ptr and data size will be placed here
|
sub esp, 8 ; Data ptr and data size will be placed here
|
||||||
add ecx, UDP_Packet.Data
|
add ecx, UDP_Packet.Data
|
||||||
|
|
||||||
;;; TODO: fragment id
|
;;; TODO: fragment id
|
||||||
|
|
||||||
push edx esi
|
push edx esi
|
||||||
call IPv4_create_packet
|
call IPv4_output
|
||||||
jz .fail
|
jz .fail
|
||||||
|
|
||||||
mov [esp + 8], eax ; pointer to buffer start
|
mov [esp + 8], eax ; pointer to buffer start
|
||||||
mov [esp + 8 + 4], edx ; buffer size
|
mov [esp + 8 + 4], edx ; buffer size
|
||||||
|
|
||||||
rol cx, 8
|
|
||||||
mov [edi + UDP_Packet.Length], cx
|
mov [edi + UDP_Packet.Length], cx
|
||||||
ror cx, 8
|
rol [edi + UDP_Packet.Length], 8
|
||||||
|
|
||||||
pop esi
|
pop esi
|
||||||
push edi ecx
|
push edi ecx
|
||||||
@ -240,13 +274,11 @@ UDP_output:
|
|||||||
pop ecx edi
|
pop ecx edi
|
||||||
|
|
||||||
pop dword [edi + UDP_Packet.SourcePort]
|
pop dword [edi + UDP_Packet.SourcePort]
|
||||||
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
|
||||||
|
|
||||||
; Checksum
|
; Checksum
|
||||||
mov esi, edi
|
mov esi, edi
|
||||||
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
|
mov [edi + UDP_Packet.Checksum], 0
|
||||||
pushd [edi-8] ; source address
|
UDP_checksum (edi-4), (edi-8) ; TODO: fix this, IPv4 packet could have options..
|
||||||
call UDP_checksum
|
|
||||||
|
|
||||||
inc [UDP_PACKETS_TX]
|
inc [UDP_PACKETS_TX]
|
||||||
|
|
||||||
@ -254,81 +286,15 @@ UDP_output:
|
|||||||
|
|
||||||
call [ebx + NET_DEVICE.transmit]
|
call [ebx + NET_DEVICE.transmit]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
.fail:
|
.fail:
|
||||||
add esp, 8+8
|
DEBUGF 1,"UDP_output: failed\n"
|
||||||
|
add esp, 4+4+8
|
||||||
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
;
|
|
||||||
; UDP_checksum
|
|
||||||
;
|
|
||||||
; This is the fast procedure to create or check a UDP header
|
|
||||||
; - To create a new checksum, the checksum field must be set to 0 before computation
|
|
||||||
; - To check an existing checksum, leave the checksum as is,
|
|
||||||
; and it will be 0 after this procedure, if it was correct
|
|
||||||
;
|
|
||||||
; IN: push source ip
|
|
||||||
; push dest ip
|
|
||||||
; esi = packet ptr
|
|
||||||
;
|
|
||||||
; OUT: checksum is filled in in packet! (but also in dx)
|
|
||||||
;
|
|
||||||
;-----------------------------------------------------------------
|
|
||||||
|
|
||||||
align 4
|
|
||||||
UDP_checksum:
|
|
||||||
|
|
||||||
; Pseudoheader
|
|
||||||
mov edx, IP_PROTO_UDP ; NO shl 8 here ! (it took me ages to figure this one out)
|
|
||||||
|
|
||||||
add dl, [esp+1+4]
|
|
||||||
adc dh, [esp+0+4]
|
|
||||||
adc dl, [esp+3+4]
|
|
||||||
adc dh, [esp+2+4]
|
|
||||||
|
|
||||||
adc dl, [esp+1+8]
|
|
||||||
adc dh, [esp+0+8]
|
|
||||||
adc dl, [esp+3+8]
|
|
||||||
adc dh, [esp+2+8]
|
|
||||||
|
|
||||||
|
|
||||||
adc dl, cl ; byte[esi+UDP_Packet.Length+1]
|
|
||||||
adc dh, ch ; byte[esi+UDP_Packet.Length+0]
|
|
||||||
|
|
||||||
; Done with pseudoheader, now do real header
|
|
||||||
adc dl, byte[esi+UDP_Packet.SourcePort+1]
|
|
||||||
adc dh, byte[esi+UDP_Packet.SourcePort+0]
|
|
||||||
|
|
||||||
adc dl, byte[esi+UDP_Packet.DestinationPort+1]
|
|
||||||
adc dh, byte[esi+UDP_Packet.DestinationPort+0]
|
|
||||||
|
|
||||||
adc dl, byte[esi+UDP_Packet.Length+1]
|
|
||||||
adc dh, byte[esi+UDP_Packet.Length+0]
|
|
||||||
|
|
||||||
adc edx, 0
|
|
||||||
|
|
||||||
; Done with header, now do data
|
|
||||||
push esi
|
|
||||||
movzx ecx, [esi+UDP_Packet.Length]
|
|
||||||
rol cx , 8
|
|
||||||
sub cx , UDP_Packet.Data
|
|
||||||
add esi, UDP_Packet.Data
|
|
||||||
|
|
||||||
call checksum_1
|
|
||||||
call checksum_2
|
|
||||||
pop esi
|
|
||||||
|
|
||||||
neg [esi+UDP_Packet.Checksum] ; zero will stay zero so we just get the checksum
|
|
||||||
add [esi+UDP_Packet.Checksum], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
|
||||||
|
|
||||||
ret 8
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;---------------------------------------------------------------------------
|
;---------------------------------------------------------------------------
|
||||||
;
|
;
|
||||||
; UDP_API
|
; UDP_API
|
||||||
|
Loading…
Reference in New Issue
Block a user