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
|
||||
szNetPtrToNum db 'NetPtrToNum',0
|
||||
szEthReceiver db 'EthReceiver',0
|
||||
szIPv4Handler db 'IPv4Handler',0
|
||||
szIPv4_input db 'IPv4_input',0
|
||||
|
||||
|
||||
align 16
|
||||
@ -155,8 +155,8 @@ kernel_export:
|
||||
dd szNetRegDev , NET_add_device
|
||||
dd szNetUnRegDev , NET_remove_device
|
||||
dd szNetPtrToNum , NET_ptr_to_num
|
||||
dd szEthReceiver , ETH_receiver
|
||||
dd szIPv4Handler , IPv4_handler
|
||||
dd szEthReceiver , ETH_input
|
||||
dd szIPv4_input , IPv4_input
|
||||
|
||||
exp_lfb:
|
||||
dd szLFBAddress , 0
|
||||
|
@ -35,22 +35,15 @@
|
||||
macro set_io addr {
|
||||
|
||||
if addr = 0
|
||||
|
||||
mov edx, [device.io_addr]
|
||||
|
||||
else if addr = LAST_IO
|
||||
|
||||
else
|
||||
|
||||
add edx, addr - LAST_IO
|
||||
|
||||
end if
|
||||
|
||||
LAST_IO = addr
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro allocate_and_clear dest, size, err {
|
||||
|
||||
; 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 {
|
||||
|
||||
local .check, .inc, .got
|
||||
@ -126,7 +117,6 @@ macro find_irq bus, dev, irq {
|
||||
|
||||
}
|
||||
|
||||
|
||||
macro find_rev bus, dev, rev {
|
||||
|
||||
push eax edx ecx
|
||||
@ -138,8 +128,6 @@ macro find_rev bus, dev, rev {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
macro make_bus_master bus, dev {
|
||||
|
||||
movzx ecx, bus
|
||||
@ -168,10 +156,7 @@ virtual at edx
|
||||
end virtual
|
||||
|
||||
|
||||
|
||||
|
||||
if used null_op
|
||||
|
||||
align 4
|
||||
null_op:
|
||||
or eax, -1
|
||||
@ -180,11 +165,11 @@ null_op:
|
||||
end if
|
||||
|
||||
|
||||
macro virt_to_dma { ; input is eax
|
||||
macro GetRealAddr { ; input is eax
|
||||
|
||||
push ax
|
||||
and word[esp], PAGESIZE - 1
|
||||
call GetPgAddr
|
||||
and word[esp], PAGESIZE - 1
|
||||
or ax, word[esp]
|
||||
inc esp
|
||||
inc esp
|
||||
@ -209,7 +194,7 @@ macro NET_DEVICE {
|
||||
.end:
|
||||
}
|
||||
|
||||
;struc ETH_DEVICE {
|
||||
|
||||
macro ETH_DEVICE {
|
||||
NET_DEVICE
|
||||
|
||||
@ -236,15 +221,3 @@ macro SLIP_DEVICE {
|
||||
.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$
|
||||
|
||||
|
||||
ARP_NO_ENTRY equ 0
|
||||
ARP_VALID_MAPPING equ 1
|
||||
ARP_AWAITING_RESPONSE equ 2
|
||||
ARP_RESPONSE_TIMEOUT equ 3
|
||||
|
||||
ARP_REQUEST_TTL = 20 ; in seconds
|
||||
ARP_ENTRY_TTL = 600 ; in seconds
|
||||
|
||||
ETHER_ARP equ 0x0608
|
||||
ARP_REQUEST_TTL equ 31 ; 20 s
|
||||
ARP_ENTRY_TTL equ 937 ; 600 s
|
||||
|
||||
ARP_REQ_OPCODE equ 0x0100 ; request
|
||||
ARP_REP_OPCODE equ 0x0200 ; reply
|
||||
@ -39,7 +35,7 @@ struct ARP_ENTRY
|
||||
.IP dd ?
|
||||
.MAC dp ?
|
||||
.Status dw ?
|
||||
.TTL dw ? ; in seconds
|
||||
.TTL dw ?
|
||||
.size:
|
||||
ends
|
||||
|
||||
@ -53,26 +49,16 @@ struct ARP_Packet
|
||||
.SenderIP dd ?
|
||||
.TargetMAC dp ?
|
||||
.TargetIP dd ?
|
||||
.size:
|
||||
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
|
||||
uglobal
|
||||
|
||||
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_RX rd MAX_NET_DEVICES
|
||||
@ -88,379 +74,81 @@ endg
|
||||
;
|
||||
; This function resets all ARP variables
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_init:
|
||||
macro ARP_init {
|
||||
|
||||
xor eax, eax
|
||||
|
||||
mov [NumARP], eax
|
||||
|
||||
mov edi, ARP_PACKETS_TX
|
||||
mov ecx, 2*MAX_NET_DEVICES
|
||||
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
|
||||
;
|
||||
; 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]
|
||||
test ecx, ecx
|
||||
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
|
||||
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:
|
||||
.next:
|
||||
add esi, ARP_ENTRY.size
|
||||
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
|
||||
|
||||
.time_out:
|
||||
cmp [esi + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE
|
||||
jz .response_timeout
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_del_entry
|
||||
;
|
||||
; IN: entry # in esi
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_del_entry:
|
||||
push esi ecx
|
||||
call ARP_del_entry
|
||||
pop ecx esi
|
||||
|
||||
DEBUGF 1,"ARP del entry %u, total entrys: %u\n", esi, [NumARP]
|
||||
jmp .next
|
||||
|
||||
cmp esi, [NumARP]
|
||||
jge .error
|
||||
.response_timeout:
|
||||
mov [esi + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT
|
||||
mov [esi + ARP_ENTRY.TTL], 10
|
||||
|
||||
imul esi, ARP_ENTRY.size
|
||||
|
||||
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
|
||||
jmp .next
|
||||
|
||||
.exit:
|
||||
|
||||
}
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ARP_Handler:
|
||||
;
|
||||
; This function handles ARP protocol over ethernet
|
||||
; (other protocols may follow in the future)
|
||||
; ARP_input
|
||||
;
|
||||
; IN: Pointer to buffer in [esp]
|
||||
; size of buffer in [esp+4]
|
||||
@ -469,13 +157,16 @@ ARP_del_entry:
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ARP_handler:
|
||||
ARP_input:
|
||||
|
||||
DEBUGF 1,"ARP_Handler - start\n"
|
||||
cmp ecx, 28
|
||||
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
|
||||
|
||||
DEBUGF 1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\
|
||||
@ -486,10 +177,10 @@ ARP_handler:
|
||||
jz .exit
|
||||
|
||||
mov eax, [edx + ARP_Packet.SenderIP]
|
||||
mov esi, ARPTable+ARP_ENTRY.IP
|
||||
mov esi, ARP_table
|
||||
|
||||
.loop:
|
||||
cmp [esi], eax
|
||||
cmp [esi + ARP_ENTRY.IP], eax
|
||||
je .gotit
|
||||
add esi, ARP_ENTRY.size
|
||||
loop .loop
|
||||
@ -497,10 +188,9 @@ ARP_handler:
|
||||
jmp .exit
|
||||
|
||||
.gotit:
|
||||
|
||||
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
|
||||
|
||||
DEBUGF 1,"ARP_Handler - updating entry\n"
|
||||
@ -516,32 +206,29 @@ ARP_handler:
|
||||
jmp .exit
|
||||
|
||||
|
||||
;------
|
||||
|
||||
;-----------------------
|
||||
; Handle Request packets
|
||||
|
||||
.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
|
||||
|
||||
call NET_ptr_to_num
|
||||
DEBUGF 1,"ARP Request packet through device: %u\n", edi
|
||||
inc [ARP_PACKETS_RX+4*edi]
|
||||
cmp edi, -1
|
||||
jz .exit
|
||||
DEBUGF 1,"ARP Request packet through device: %u\n", edi
|
||||
inc [ARP_PACKETS_RX+4*edi]
|
||||
|
||||
mov eax, edi
|
||||
shl eax, 2
|
||||
add eax, IP_LIST
|
||||
mov eax, [eax]
|
||||
mov eax, [IP_LIST+4*edi]
|
||||
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 edi
|
||||
|
||||
; OK, it is a request for one of our MAC addresses. Build the frame and send it
|
||||
; We can reuse the buffer. (faster then using ARP_create_packet)
|
||||
; OK, it is a request for one of our MAC addresses.
|
||||
; 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 edi, [edx + ARP_Packet.TargetMAC]
|
||||
movsd ; Move Sender Mac to Dest MAC
|
||||
@ -584,6 +271,265 @@ ARP_handler:
|
||||
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
|
||||
; ecx = # entry
|
||||
imul ecx, ARP_ENTRY.size
|
||||
add ecx, ARPTable
|
||||
add ecx, ARP_table
|
||||
mov esi, ecx
|
||||
mov ecx, ARP_ENTRY.size/2
|
||||
rep movsw
|
||||
@ -653,16 +599,15 @@ ARP_API:
|
||||
|
||||
.write:
|
||||
; 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
|
||||
ret
|
||||
|
||||
.remove:
|
||||
; ecx = # entry
|
||||
mov esi, ecx
|
||||
cmp ecx, [NumARP]
|
||||
jge .error
|
||||
imul ecx, ARP_ENTRY.size
|
||||
lea esi, [ARP_table + ecx]
|
||||
call ARP_del_entry
|
||||
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)
|
||||
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
|
||||
uglobal
|
||||
|
||||
@ -74,30 +141,49 @@ endg
|
||||
;
|
||||
; This function resets all IP variables
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
IPv4_init:
|
||||
macro IPv4_init {
|
||||
|
||||
or eax, -1
|
||||
xor eax, eax
|
||||
mov edi, IP_LIST
|
||||
mov ecx, 4*MAX_IP
|
||||
rep stosd
|
||||
|
||||
inc eax
|
||||
mov edi, FRAGMENT_LIST
|
||||
mov ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
|
||||
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
|
||||
; and call appropriate handler. (TCP/UDP/ICMP/..)
|
||||
@ -112,7 +198,7 @@ IPv4_init:
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
IPv4_handler: ; TODO: implement handler for IP options
|
||||
IPv4_input: ; TODO: implement handler for IP options
|
||||
; TODO2: add code for raw sockets
|
||||
|
||||
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
|
||||
|
||||
push edx ebx
|
||||
mov esi, edx
|
||||
call IPv4_checksum
|
||||
pop ebx edx
|
||||
|
||||
cmp [edx + IPv4_Packet.HeaderChecksum], 0
|
||||
jne .dump ; if checksum isn't valid then dump packet
|
||||
IPv4_checksum edx
|
||||
jnz .dump ; if checksum isn't valid then dump packet
|
||||
|
||||
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..)
|
||||
; ;
|
||||
; @@: ;
|
||||
; lodsb ;
|
||||
; DEBUGF 1,"%x ", eax:2 ;
|
||||
; loop @r ;
|
||||
; packet_to_debug
|
||||
|
||||
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
|
||||
@ -501,70 +576,15 @@ IPv4_find_fragment_slot:
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------
|
||||
;
|
||||
;
|
||||
; 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
|
||||
; IPv4_output
|
||||
;
|
||||
; IN: eax = dest ip
|
||||
; ebx = source ip
|
||||
; ecx = data length
|
||||
; dx = fragment id ;;;;
|
||||
; di = protocol
|
||||
; dx = fragment id
|
||||
; di = TTL shl 8 + protocol
|
||||
;
|
||||
; OUT: eax = pointer to buffer start
|
||||
; ebx = pointer to device struct (needed for sending procedure)
|
||||
@ -574,184 +594,224 @@ IPv4_fragment:
|
||||
;
|
||||
;------------------------------------------------------------------
|
||||
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
|
||||
jg .exit_
|
||||
|
||||
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: ;
|
||||
jg .too_large
|
||||
|
||||
push ecx eax ebx dx di
|
||||
|
||||
cmp eax, -1
|
||||
je .broadcast ; If it is broadcast, just send
|
||||
|
||||
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
|
||||
je .not_found
|
||||
jz .err2
|
||||
|
||||
push ebx
|
||||
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:
|
||||
call IPv4_dest_to_dev
|
||||
inc [IP_PACKETS_TX+4*edi]
|
||||
mov edx, [NET_DRV_LIST + 4*edi]
|
||||
lea eax, [edx + ETH_DEVICE.mac]
|
||||
mov ebx, esp
|
||||
mov ecx, [esp+18] ;; 18 or 22 ??
|
||||
add ecx, IPv4_Packet.DataOrOptional
|
||||
push esi ; ptr to ip header
|
||||
sub ecx, 20 ; substract header size
|
||||
push ecx ; max data size
|
||||
push dword 0 ; offset
|
||||
|
||||
.new_fragment:
|
||||
DEBUGF 1,"Ipv4_fragment - new_fragmentn"
|
||||
|
||||
|
||||
mov eax, [esp + 3*4]
|
||||
lea ebx, [esp + 4*4]
|
||||
mov di , ETHER_IPv4
|
||||
;;; TODO: detect if packet is too large for ethernet, if so, call IPv4_fragment
|
||||
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
|
||||
call ETH_output
|
||||
|
||||
mov [edi + IPv4_Packet.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
|
||||
mov [edi + IPv4_Packet.TypeOfService], 0
|
||||
xchg ch, cl
|
||||
cmp edi, -1
|
||||
jz .err
|
||||
|
||||
; 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.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
|
||||
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
|
||||
mov esi, edi
|
||||
call IPv4_checksum
|
||||
pop esi edx eax ecx
|
||||
add edi, IPv4_Packet.DataOrOptional
|
||||
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
|
||||
mov ecx, [esp + 1*4]
|
||||
|
||||
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
|
||||
|
||||
|
||||
.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
|
||||
;
|
||||
; IN: Destination IP in eax
|
||||
; OUT: device id in edi
|
||||
; IN: eax = Destination IP
|
||||
; OUT: edi = device id * 4
|
||||
;
|
||||
;---------------------------------------------------------------------------
|
||||
align 4
|
||||
IPv4_dest_to_dev:
|
||||
|
||||
DEBUGF 1,"IPv4 destination to device: "
|
||||
cmp eax, 0xffffffff
|
||||
je .invalid
|
||||
|
||||
xor edi, edi
|
||||
mov ecx, MAX_IP
|
||||
|
||||
.loop:
|
||||
mov ebx, [IP_LIST+edi] ; we dont need to worry about non exisiting ip interfaces
|
||||
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
|
||||
; (only a moron would insert that ip into this function..)
|
||||
mov ebx, [IP_LIST+edi]
|
||||
and ebx, [SUBNET_LIST+edi]
|
||||
jz .next
|
||||
|
||||
mov edx, eax
|
||||
and edx, [SUBNET_LIST+edi]
|
||||
|
||||
cmp ebx, edx
|
||||
je .found_it
|
||||
|
||||
.next:
|
||||
add edi, 4
|
||||
loop .loop
|
||||
|
||||
.invalid:
|
||||
xor edi, edi ; if none found, use device 0 as default device
|
||||
|
||||
.found_it:
|
||||
shr edi, 2
|
||||
|
||||
DEBUGF 1,"%u\n",edi
|
||||
DEBUGF 1,"IPv4_dest_to_dev: %u\n", edi
|
||||
|
||||
ret
|
||||
|
||||
@ -869,7 +929,3 @@ IPv4_API:
|
||||
mov [eax], ecx
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -56,37 +56,33 @@ endg
|
||||
;
|
||||
; This function resets all ethernet variables
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ETH_init:
|
||||
macro ETH_init {
|
||||
|
||||
mov [ETH_RUNNING], 0
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_Receiver:
|
||||
; ETH_input
|
||||
;
|
||||
; This function is called by ethernet drivers,
|
||||
; It pushes the received ethernet packets onto the eth_in_queue
|
||||
;
|
||||
; IN: [esp] = Pointer to buffer
|
||||
; [esp-4] = size of buffer
|
||||
; [esp+4] = size of buffer
|
||||
; ebx = pointer to eth_device
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ETH_receiver:
|
||||
ETH_input:
|
||||
mov eax, [esp]
|
||||
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
|
||||
jl .dump
|
||||
sub ecx, ETH_FRAME.Data
|
||||
@ -95,10 +91,10 @@ ETH_receiver:
|
||||
mov ax , [eax + ETH_FRAME.Type]
|
||||
|
||||
cmp ax, ETHER_IPv4
|
||||
je IPv4_handler
|
||||
je IPv4_input
|
||||
|
||||
cmp ax, ETHER_ARP
|
||||
je ARP_handler
|
||||
je ARP_input
|
||||
|
||||
; cmp ax, ETHER_PPP_DISCOVERY
|
||||
; je PPPOE_discovery
|
||||
@ -106,19 +102,19 @@ ETH_receiver:
|
||||
DEBUGF 2,"Unknown ethernet packet type %x\n", ax
|
||||
|
||||
.dump:
|
||||
DEBUGF 2,"ETH_Handler - dumping\n"
|
||||
DEBUGF 2,"ETH_input - dumping\n"
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_create_packet
|
||||
; ETH_output
|
||||
;
|
||||
; IN: eax = pointer to source mac
|
||||
; ebx = pointer to destination mac
|
||||
; ebx = device ptr
|
||||
; ecx = packet size
|
||||
; edx = device number
|
||||
; edx = pointer to destination mac
|
||||
; di = protocol
|
||||
;
|
||||
; OUT: edi = 0 on error, pointer to buffer otherwise
|
||||
@ -129,62 +125,60 @@ ETH_receiver:
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
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
|
||||
mov esi, [NET_DRV_LIST] ;;; TODO: FIXME
|
||||
cmp ecx, [esi + NET_DEVICE.mtu]
|
||||
pop esi
|
||||
cmp ecx, [ebx + NET_DEVICE.mtu]
|
||||
jg .exit
|
||||
|
||||
push ecx di eax ebx edx
|
||||
|
||||
push ecx ; << 1
|
||||
push di eax edx ; << 2
|
||||
add ecx, ETH_FRAME.Data
|
||||
push ecx
|
||||
push ecx
|
||||
call kernel_alloc
|
||||
|
||||
push ecx ; << 3
|
||||
|
||||
push ecx ; << 4
|
||||
call kernel_alloc ; >> 4
|
||||
test eax, eax
|
||||
jz .out_of_ram
|
||||
mov edi, eax
|
||||
test edi, edi
|
||||
jz .pop_exit
|
||||
|
||||
pop ecx
|
||||
pop edx
|
||||
pop ecx ; >> 3
|
||||
|
||||
pop esi
|
||||
pop esi ; >> 2
|
||||
movsd
|
||||
movsw
|
||||
pop esi
|
||||
pop esi ; >> 2
|
||||
movsd
|
||||
movsw
|
||||
pop ax
|
||||
pop ax ; >> 2
|
||||
stosw
|
||||
|
||||
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
|
||||
mov edx, ecx ; Set ebx to complete buffer size
|
||||
pop ecx
|
||||
mov edx, ecx ; Set edx to complete buffer size
|
||||
|
||||
xor ebx, ebx ;;;; TODO: Fixme
|
||||
mov ebx, [NET_DRV_LIST + ebx]
|
||||
pop ecx ; >> 1
|
||||
|
||||
cmp edx, 46 + ETH_FRAME.Data ; If data size is less then 46, add padding bytes
|
||||
jge .continue
|
||||
mov edx, 46 + ETH_FRAME.Data
|
||||
.continue:
|
||||
|
||||
DEBUGF 1,"done: %x size:%u device:%x\n", eax, edx, ebx
|
||||
cmp edx, 60-1 ; minimum ethernet packet size
|
||||
jle .adjust_size
|
||||
DEBUGF 1,"ETH_output: done: %x total size: %u\n", eax, edx
|
||||
ret
|
||||
|
||||
.pop_exit:
|
||||
DEBUGF 2,"Out of ram space!!\n"
|
||||
add esp, 18
|
||||
and edi, 0
|
||||
.adjust_size:
|
||||
mov edx, 60
|
||||
ret
|
||||
|
||||
.out_of_ram:
|
||||
DEBUGF 2,"ETH_output: Out of ram space!!\n"
|
||||
add esp, 3*4+2+4
|
||||
sub edi, edi
|
||||
ret
|
||||
|
||||
.exit:
|
||||
DEBUGF 2,"Packet too large!\n"
|
||||
and edi, 0
|
||||
DEBUGF 2,"ETH_output: Packet too large!\n"
|
||||
sub edi, edi
|
||||
;;; dec edi
|
||||
ret
|
||||
|
||||
|
||||
|
@ -109,21 +109,16 @@ endg
|
||||
;
|
||||
; ICMP_init
|
||||
;
|
||||
; This function resets all ICMP variables
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
ICMP_init:
|
||||
|
||||
macro ICMP_init {
|
||||
|
||||
xor eax, eax
|
||||
mov edi, ICMP_PACKETS_TX
|
||||
mov ecx, 2*MAX_IP
|
||||
rep stosd
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -235,7 +230,7 @@ ICMP_input:
|
||||
call IPv4_dest_to_dev
|
||||
cmp edi,-1
|
||||
je .dump
|
||||
inc [ICMP_PACKETS_RX+4*edi]
|
||||
inc [ICMP_PACKETS_RX+edi]
|
||||
|
||||
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
|
||||
|
||||
@ -284,10 +279,10 @@ ICMP_output:
|
||||
push esi edi edx
|
||||
|
||||
add ecx, ICMP_Packet.Data
|
||||
mov di , IP_PROTO_ICMP
|
||||
mov di , IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
||||
shr edx, 16
|
||||
|
||||
call IPv4_create_packet
|
||||
call IPv4_output
|
||||
jz .exit
|
||||
|
||||
DEBUGF 1,"full icmp packet size: %u\n", edx
|
||||
|
@ -5,8 +5,10 @@
|
||||
;; ;;
|
||||
;; SOCKET.INC ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; based on code by mike.dld ;;
|
||||
;; Written by hidnplayr@kolibrios.org, ;;
|
||||
;; and Clevermouse. ;;
|
||||
;; ;;
|
||||
;; Based on code by mike.dld ;;
|
||||
;; ;;
|
||||
;; GNU GENERAL PUBLIC LICENSE ;;
|
||||
;; Version 2, June 1991 ;;
|
||||
@ -31,9 +33,7 @@ virtual at 0
|
||||
.errorcode dd ?
|
||||
|
||||
.options dd ?
|
||||
.SO_SND.SB_CC dd ? ;;;;; socket options: number of bytes in socket
|
||||
.SO_RCV.SB_CC dd ?
|
||||
.state dd ? ;;;;;;;;;
|
||||
.state dd ?
|
||||
|
||||
.end:
|
||||
end virtual
|
||||
@ -51,15 +51,6 @@ virtual at SOCKET.end
|
||||
.end:
|
||||
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
|
||||
|
||||
TCP_SOCKET:
|
||||
@ -114,7 +105,6 @@ virtual at IP_SOCKET.end
|
||||
|
||||
;----------------------
|
||||
; Transmit timing stuff
|
||||
|
||||
.t_idle dd ?
|
||||
.t_rtt dd ?
|
||||
.t_rtseq dd ?
|
||||
@ -125,7 +115,6 @@ virtual at IP_SOCKET.end
|
||||
|
||||
;-----------------
|
||||
; Out-of-band data
|
||||
|
||||
.t_oobflags dd ?
|
||||
.t_iobc dd ?
|
||||
.t_softerror dd ?
|
||||
@ -133,7 +122,6 @@ virtual at IP_SOCKET.end
|
||||
|
||||
;---------
|
||||
; RFC 1323
|
||||
|
||||
.SND_SCALE db ? ; Scale factor
|
||||
.RCV_SCALE db ?
|
||||
.request_r_scale db ?
|
||||
@ -146,7 +134,6 @@ virtual at IP_SOCKET.end
|
||||
|
||||
;-------
|
||||
; Timers
|
||||
|
||||
.timer_retransmission dw ? ; rexmt
|
||||
.timer_ack dw ?
|
||||
.timer_persist dw ?
|
||||
@ -176,9 +163,32 @@ virtual at IP_SOCKET.end
|
||||
.end:
|
||||
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
|
||||
; .owner dd ?
|
||||
.data_ptr dd ?
|
||||
.buf_ptr dd ?
|
||||
.data_size dd ?
|
||||
@ -186,7 +196,6 @@ struct socket_queue_entry
|
||||
ends
|
||||
|
||||
|
||||
MAX_backlog equ 20 ; backlog for stream sockets
|
||||
SOCKETBUFFSIZE equ 4096 ; in bytes
|
||||
|
||||
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
|
||||
@ -204,24 +213,41 @@ endg
|
||||
;
|
||||
; SOCKET_init
|
||||
;
|
||||
; -
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
socket_init:
|
||||
macro SOCKET_init {
|
||||
|
||||
xor eax, eax
|
||||
mov edi, net_sockets
|
||||
mov ecx, 4
|
||||
rep stosd
|
||||
|
||||
mov [last_UDP_port], MIN_EPHEMERAL_PORT
|
||||
mov [last_TCP_port], MIN_EPHEMERAL_PORT
|
||||
;--- for random 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
|
||||
sys_socket:
|
||||
cmp ebx, 8 ; highest possible number
|
||||
jg s_error
|
||||
lea ebx, [.table + 4*ebx]
|
||||
jg @f
|
||||
lea ebx, [sock_sysfn_table + 4*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_close ; 1
|
||||
dd SOCKET_bind ; 2
|
||||
@ -249,12 +284,6 @@ sys_socket:
|
||||
; 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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -347,9 +410,6 @@ SOCKET_bind:
|
||||
DEBUGF 1,"using local port: %u\n", 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",\
|
||||
[eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
|
||||
[eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
|
||||
@ -411,21 +471,11 @@ SOCKET_connect:
|
||||
|
||||
|
||||
.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]
|
||||
call wait_mutex
|
||||
|
||||
; fill in remote port and IP
|
||||
|
||||
;;;;;; mov [eax + TCP_SOCKET.wndsizeTimer], 0 ; Reset the window timer.
|
||||
|
||||
mov bx , word [edx + 2]
|
||||
mov [eax + TCP_SOCKET.RemotePort], bx
|
||||
DEBUGF 1,"remote port: %u\n", bx
|
||||
@ -435,21 +485,25 @@ SOCKET_connect:
|
||||
|
||||
; 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
|
||||
jne @f
|
||||
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
|
||||
pop eax
|
||||
|
||||
mov [eax + SOCKET.lock], 0
|
||||
|
||||
@ -583,11 +637,11 @@ SOCKET_close:
|
||||
test [eax + TCP_SOCKET.t_state], TCB_SYN_RECEIVED ;;;;;;
|
||||
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
|
||||
; so, we may destroy the socket
|
||||
@ -688,6 +742,12 @@ SOCKET_send:
|
||||
.af_inet4:
|
||||
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
|
||||
je .tcp
|
||||
|
||||
@ -790,6 +850,35 @@ SOCKET_get_opt:
|
||||
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
|
||||
@ -939,6 +1028,188 @@ SOCKET_input:
|
||||
|
||||
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
|
||||
@ -1011,7 +1282,7 @@ SOCKET_alloc:
|
||||
push ecx ebx
|
||||
|
||||
stdcall kernel_alloc, SOCKETBUFFSIZE
|
||||
DEBUGF 1, "socket_alloc: %x ", eax
|
||||
DEBUGF 1, "SOCKET_alloc: ptr=%x\n", eax
|
||||
or eax, eax
|
||||
jz .exit
|
||||
|
||||
@ -1023,17 +1294,14 @@ SOCKET_alloc:
|
||||
rep stosd
|
||||
pop edi eax
|
||||
|
||||
init_queue (eax + SOCKET_QUEUE_LOCATION)
|
||||
|
||||
; find first free socket number and use it
|
||||
|
||||
mov ebx, net_sockets
|
||||
xor ecx, ecx
|
||||
.next_socket_number:
|
||||
inc ecx
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
or ebx, ebx
|
||||
test ebx, ebx
|
||||
jz .last_socket
|
||||
cmp [ebx + SOCKET.Number], ecx
|
||||
jne .next_socket
|
||||
@ -1042,23 +1310,21 @@ SOCKET_alloc:
|
||||
|
||||
.last_socket:
|
||||
mov [eax + SOCKET.Number], ecx
|
||||
|
||||
DEBUGF 1, "(number: %u)\n", ecx
|
||||
DEBUGF 1, "SOCKET_alloc: number=%u\n", ecx
|
||||
mov edi, ecx
|
||||
|
||||
; Fill in PID
|
||||
mov ebx, [TASK_BASE]
|
||||
mov ebx, [ebx + TASKDATA.pid]
|
||||
|
||||
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 [eax + SOCKET.PrevPtr], net_sockets
|
||||
mov [eax + SOCKET.NextPtr], ebx
|
||||
|
||||
or ebx, ebx
|
||||
test ebx, ebx
|
||||
jz @f
|
||||
add ebx, SOCKET.lock ; lock the next socket
|
||||
call wait_mutex
|
||||
@ -1068,8 +1334,6 @@ SOCKET_alloc:
|
||||
@@:
|
||||
|
||||
mov [net_sockets + SOCKET.NextPtr], eax
|
||||
|
||||
mov edi, ecx
|
||||
or eax, eax ; used to clear zero flag
|
||||
.exit:
|
||||
pop ebx ecx
|
||||
@ -1101,6 +1365,16 @@ SOCKET_free:
|
||||
|
||||
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
|
||||
mov ebx, [eax + SOCKET.NextPtr]
|
||||
mov eax, [eax + SOCKET.PrevPtr]
|
||||
@ -1126,6 +1400,39 @@ SOCKET_free:
|
||||
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
|
||||
|
@ -68,12 +68,14 @@ SOCK_RAW equ 3
|
||||
; Socket options
|
||||
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
|
||||
NET_TYPE_ETH equ 1
|
||||
NET_TYPE_SLIP equ 2
|
||||
|
||||
MAX_backlog equ 20 ; backlog for stream sockets
|
||||
|
||||
|
||||
virtual at 0
|
||||
|
||||
@ -92,6 +94,8 @@ virtual at 0
|
||||
.packets_tx dd ? ;
|
||||
.packets_rx dd ? ;
|
||||
|
||||
; .chksum dd ? ; bitmask stating available checksum routines on hardware
|
||||
|
||||
.end:
|
||||
|
||||
end virtual
|
||||
@ -102,6 +106,7 @@ macro pseudo_random reg {
|
||||
add reg, [esp]
|
||||
rol reg, 5
|
||||
xor reg, [timer_ticks]
|
||||
add reg, [CPU_FREQ]
|
||||
imul reg, 214013
|
||||
xor reg, 0xdeadbeef
|
||||
rol reg, 9
|
||||
@ -111,7 +116,7 @@ macro ntohld reg {
|
||||
|
||||
rol word reg, 8
|
||||
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 "ethernet.inc"
|
||||
@ -161,25 +178,23 @@ align 4
|
||||
stack_init:
|
||||
|
||||
; Init the network drivers list
|
||||
|
||||
xor eax, eax
|
||||
mov edi, NET_RUNNING
|
||||
mov ecx, MAX_NET_DEVICES + 1
|
||||
rep stosd
|
||||
|
||||
; Call other init procedures
|
||||
ETH_init
|
||||
; SLIP_init
|
||||
; PPPOE_init
|
||||
|
||||
call ETH_init
|
||||
; call SLIP_init
|
||||
IPv4_init
|
||||
ICMP_init
|
||||
|
||||
call IPv4_init
|
||||
call ICMP_init
|
||||
ARP_init
|
||||
UDP_init
|
||||
TCP_init
|
||||
|
||||
call ARP_init
|
||||
call UDP_init
|
||||
call TCP_init
|
||||
|
||||
call socket_init
|
||||
SOCKET_init
|
||||
|
||||
mov [net_tmr_count], 0
|
||||
|
||||
@ -211,14 +226,14 @@ stack_handler:
|
||||
test [net_10ms], 0x0f ; 160ms
|
||||
jnz .exit
|
||||
|
||||
; call TCP_timer_160ms
|
||||
TCP_timer_160ms
|
||||
|
||||
test [net_10ms], 0x3f ; 640ms
|
||||
jnz .exit
|
||||
|
||||
; call TCP_timer_640ms
|
||||
call ARP_decrease_entry_ttls
|
||||
call IPv4_decrease_fragment_ttls
|
||||
TCP_timer_640ms
|
||||
ARP_decrease_entry_ttls
|
||||
IPv4_decrease_fragment_ttls
|
||||
|
||||
.exit:
|
||||
ret
|
||||
@ -275,13 +290,13 @@ NET_add_device:
|
||||
jmp .error
|
||||
|
||||
.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
|
||||
jmp .add_it
|
||||
|
||||
.slip:
|
||||
DEBUGF 1,"Trying to add a slip driver\n"
|
||||
DEBUGF 1,"Trying to add a slip device\n"
|
||||
;;;;
|
||||
jmp .error
|
||||
|
||||
@ -490,15 +505,15 @@ checksum_2:
|
||||
|
||||
mov ecx, edx
|
||||
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
|
||||
jnz .not_zero
|
||||
dec dx
|
||||
.not_zero:
|
||||
xchg dl, dh
|
||||
|
||||
DEBUGF 1,"Checksum: %x\n",dx
|
||||
DEBUGF 1,"Checksum: %x\n", dx
|
||||
|
||||
ret
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,19 +40,62 @@ endg
|
||||
;
|
||||
; This function resets all UDP variables
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
align 4
|
||||
UDP_init:
|
||||
macro UDP_init {
|
||||
|
||||
xor eax, eax
|
||||
mov edi, UDP_PACKETS_TX
|
||||
mov ecx, 2*MAX_IP
|
||||
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,
|
||||
; this procedure will inject the udp data diagrams in the application sockets.
|
||||
;
|
||||
; IN: Pointer to buffer in [esp]
|
||||
; size of buffer in [esp+4]
|
||||
; pointer to device struct in ebx
|
||||
; UDP Packet size in ecx
|
||||
; pointer to UDP Packet in edx
|
||||
; IN: [esp] = Pointer to buffer
|
||||
; [esp+4] = size of buffer
|
||||
; ebx = ptr to device struct
|
||||
; ecx = UDP Packet size
|
||||
; edx = ptr to UDP header
|
||||
;
|
||||
; esi = ipv4 source address
|
||||
; edi = ipv4 dest address
|
||||
@ -80,18 +123,18 @@ UDP_input:
|
||||
DEBUGF 1,"UDP_input, size:%u\n", ecx
|
||||
|
||||
; First validate, checksum:
|
||||
cmp [edx + UDP_Packet.Checksum], 0
|
||||
jz .no_checksum
|
||||
|
||||
xchg edi, esi ; save ipv4 source address to edi so we can use it later
|
||||
neg [esi+UDP_Packet.Checksum] ; substract chechksum from 0
|
||||
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
|
||||
|
||||
push edx
|
||||
push esi edi
|
||||
push edi
|
||||
push esi
|
||||
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
|
||||
|
||||
cmp [edx + UDP_Packet.Checksum], 0
|
||||
jnz .checksum_mismatch
|
||||
|
||||
.no_checksum:
|
||||
@ -168,12 +211,6 @@ UDP_input:
|
||||
|
||||
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
||||
|
||||
; mov esi, edx
|
||||
; @@: ;
|
||||
; lodsb ;
|
||||
; DEBUGF 2,"%x ", eax:2 ;
|
||||
; loop @r ;
|
||||
|
||||
.dump:
|
||||
call kernel_free
|
||||
add esp, 4 ; pop (balance stack)
|
||||
@ -207,26 +244,23 @@ UDP_output:
|
||||
DEBUGF 1,"local port: %u\n", dx
|
||||
rol dx, 8
|
||||
|
||||
|
||||
mov ebx, [eax + IP_SOCKET.LocalIP]
|
||||
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
|
||||
add ecx, UDP_Packet.Data
|
||||
|
||||
;;; TODO: fragment id
|
||||
|
||||
push edx esi
|
||||
call IPv4_create_packet
|
||||
call IPv4_output
|
||||
jz .fail
|
||||
|
||||
mov [esp + 8], eax ; pointer to buffer start
|
||||
mov [esp + 8 + 4], edx ; buffer size
|
||||
|
||||
rol cx, 8
|
||||
mov [edi + UDP_Packet.Length], cx
|
||||
ror cx, 8
|
||||
rol [edi + UDP_Packet.Length], 8
|
||||
|
||||
pop esi
|
||||
push edi ecx
|
||||
@ -240,13 +274,11 @@ UDP_output:
|
||||
pop ecx edi
|
||||
|
||||
pop dword [edi + UDP_Packet.SourcePort]
|
||||
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
||||
|
||||
; Checksum
|
||||
mov esi, edi
|
||||
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
|
||||
pushd [edi-8] ; source address
|
||||
call UDP_checksum
|
||||
mov [edi + UDP_Packet.Checksum], 0
|
||||
UDP_checksum (edi-4), (edi-8) ; TODO: fix this, IPv4 packet could have options..
|
||||
|
||||
inc [UDP_PACKETS_TX]
|
||||
|
||||
@ -254,81 +286,15 @@ UDP_output:
|
||||
|
||||
call [ebx + NET_DEVICE.transmit]
|
||||
ret
|
||||
|
||||
.fail:
|
||||
add esp, 8+8
|
||||
DEBUGF 1,"UDP_output: failed\n"
|
||||
add esp, 4+4+8
|
||||
xor eax, eax
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user