16,20 → 16,16 |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|
|
$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 |
ARP_REQUEST_TTL equ 31 ; 20 s |
ARP_ENTRY_TTL equ 937 ; 600 s |
|
ETHER_ARP equ 0x0608 |
|
ARP_REQ_OPCODE equ 0x0100 ; request |
ARP_REP_OPCODE equ 0x0200 ; reply |
|
39,7 → 35,7 |
.IP dd ? |
.MAC dp ? |
.Status dw ? |
.TTL dw ? ; in seconds |
.TTL dw ? |
.size: |
ends |
|
53,26 → 49,16 |
.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,15 → 74,10 |
; |
; 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 |
103,152 → 84,217 |
mov ecx, 2*MAX_NET_DEVICES |
rep stosd |
|
ret |
} |
|
;--------------------------------------------------------------------------- |
; |
; 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 esi, ARP_table |
.loop: |
cmp [esi + ARP_ENTRY.TTL], 0xffff ; 0xffff = static entry |
je .next |
|
dec [esi + ARP_ENTRY.TTL] |
jz .time_out |
|
.next: |
add esi, ARP_ENTRY.size |
loop .loop |
jmp .exit |
|
.time_out: |
cmp [esi + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
jz .response_timeout |
|
push esi ecx |
call ARP_del_entry |
pop ecx esi |
|
jmp .next |
|
.response_timeout: |
mov [esi + ARP_ENTRY.Status], ARP_RESPONSE_TIMEOUT |
mov [esi + ARP_ENTRY.TTL], 10 |
|
jmp .next |
|
.exit: |
|
} |
|
|
;----------------------------------------------------------------- |
; |
; ARP_IP_to_MAC |
; ARP_input |
; |
; This function resets all ARP variables |
; IN: Pointer to buffer in [esp] |
; size of buffer in [esp+4] |
; packet size (without ethernet header) in ecx |
; OUT: / |
; |
; 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: |
ARP_input: |
|
DEBUGF 1,"ARP_IP_to_MAC\n" |
DEBUGF 1,"ARP_Handler - start\n" |
cmp ecx, 28 |
jl .exit |
|
; 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 |
;--------------------- |
; Handle Reply packets |
|
xor edx, edx ;;; TODO: find device num in edx |
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE |
jne .maybe_request |
|
mov ebx, [IP_LIST + edx] |
and ebx, [SUBNET_LIST + edx] |
DEBUGF 1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\ |
[edx + ARP_Packet.SenderIP]:1,[edx + ARP_Packet.SenderIP+1]:1,[edx + ARP_Packet.SenderIP+2]:1,[edx + ARP_Packet.SenderIP+3]:1, |
|
mov ecx, eax |
and ecx, [SUBNET_LIST + edx] |
mov ecx, [NumARP] |
test ecx, ecx |
jz .exit |
|
cmp ecx, ebx |
je .local |
mov eax, [edx + ARP_Packet.SenderIP] |
mov esi, ARP_table |
|
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 |
.loop: |
cmp [esi + ARP_ENTRY.IP], eax |
je .gotit |
add esi, ARP_ENTRY.size |
loop .scan_loop |
.not_in_list: |
loop .loop |
|
DEBUGF 1,"IP not found on list, preparing for ARP request\n" |
jmp .exit |
|
; if not, reserve an entry in list and send an ARP request packet |
.gotit: |
DEBUGF 1,"ARP_Handler - found matching entry\n" |
|
cmp [esi+ARP_ENTRY.TTL], 0xffff ; if it is a static entry, dont touch it |
je .exit |
|
DEBUGF 1,"ARP_Handler - updating entry\n" |
|
mov [esi+ARP_ENTRY.Status], ARP_VALID_MAPPING |
mov [esi+ARP_ENTRY.TTL], ARP_ENTRY_TTL |
|
mov eax, dword [edx + ARP_Packet.SenderMAC] |
mov dword [esi+ARP_ENTRY.MAC], eax |
mov ax , word [edx + ARP_Packet.SenderMAC + 4] |
mov word [esi+ARP_ENTRY.MAC+4], ax |
|
jmp .exit |
|
|
;----------------------- |
; Handle Request packets |
|
.maybe_request: |
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE |
jne .exit |
|
call NET_ptr_to_num |
cmp edi, -1 |
jz .exit |
DEBUGF 1,"ARP Request packet through device: %u\n", edi |
inc [ARP_PACKETS_RX+4*edi] |
|
mov eax, [IP_LIST+4*edi] |
cmp eax, [edx + ARP_Packet.TargetIP] ; Is it looking for my IP address? |
jne .exit ; TODO: instead of quitting, update local entrys with matching IP's ? |
|
push eax |
push edi |
|
pushw ARP_REQUEST_TTL |
pushw ARP_AWAITING_RESPONSE |
pushd 0 |
pushw 0 |
pushd eax |
call ARP_add_entry |
cmp eax, -1 |
je .full |
; 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) |
|
; <Some dirty test code> |
lea esi, [edx + ARP_Packet.SenderMAC] |
lea edi, [edx + ARP_Packet.TargetMAC] |
movsd ; Move Sender Mac to Dest MAC |
movsw ; |
movsd ; Move sender IP to Dest IP |
|
; This piece of code waits for an ARP reply |
|
mov ebx, eax |
pop esi |
mov esi, [NET_DRV_LIST + 4*esi] |
lea esi, [esi + ETH_DEVICE.mac] |
lea edi, [edx + ARP_Packet.SenderMAC] |
movsd ; Copy MAC address from in MAC_LIST |
movsw ; |
pop eax |
push ebx |
call ARP_create_request |
stosd ; Write our IP |
|
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: |
mov word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE |
|
call change_task ; The ARP reply hasnt been received yet, tell the processor to do some other stuff first |
; Now, Fill in ETHERNET header |
|
mov eax, [esp + 4] |
imul eax, ARP_ENTRY.size |
add eax, ARPTable |
cmp [eax + ARP_ENTRY.Status], ARP_VALID_MAPPING |
je .gogogo |
mov edi, [esp] |
lea esi, [edx + ARP_Packet.TargetMAC] |
movsd |
movsw |
lea esi, [edx + ARP_Packet.SenderMAC] |
movsd |
movsw |
; mov ax , ETHER_ARP |
; stosw |
|
mov eax, [esp] ; Check if the reply hasnt timed-out yet |
cmp [timer_ticks], eax |
jl .dirty_loop |
DEBUGF 1,"ARP_Handler - Sending reply \n" |
|
; </Some dirty test code> |
or eax, -1 |
add esp, 8 |
call [ebx + NET_DEVICE.transmit] |
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 |
.exit: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
|
.full: |
add esp, 4 |
mov eax, -1 |
DEBUGF 1,"ARP_Handler - exiting\n" |
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 |
; ARP_output_request |
; |
; IN: ip in eax |
; |
; OUT: / |
; |
;--------------------------------------------------------------------------- |
align 4 |
ARP_create_request: |
ARP_output_request: |
|
DEBUGF 1,"Create ARP Packet\n" |
|
call IPv4_dest_to_dev |
|
push eax ; DestIP |
mov eax, [IP_LIST+4*edi] ; senderIP |
push eax |
pushd [IP_LIST+edi] ; SenderIP |
|
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 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_create_packet |
call ETH_output |
jz .exit |
|
mov ecx, eax |
259,16 → 305,18 |
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] ; |
add edi, ARP_Packet.SenderMAC |
|
lea esi, [ebx + ETH_DEVICE.mac] ; SenderMac |
movsw ; |
movsd ; |
pop eax ; |
pop eax ; SenderIP |
stosd ; |
mov eax, -1 ; destmac |
|
mov eax, -1 ; DestMac |
stosd ; |
stosw ; |
pop eax |
pop eax ; DestIP |
stosd ; |
|
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx |
278,84 → 326,17 |
ret |
|
.exit: |
add esp, 8 |
add esp, 4+4 |
DEBUGF 1,"Create ARP Packet - failed\n" |
mov eax, -1 |
sub eax, eax |
ret |
|
|
|
;--------------------------------------------------------------------------- |
; |
; ARP_decrease_entry_ttls |
; |
; IN: / |
; OUT: / |
; |
;--------------------------------------------------------------------------- |
align 4 |
ARP_decrease_entry_ttls: |
|
mov ecx, [NumARP] |
test ecx, ecx |
jz .exit |
|
mov ebx, ARPTable |
|
.timer_loop: |
|
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 |
; |
; IN: esi = ptr to entry (can easily be made on the stack) |
; OUT: eax = entry #, -1 on error |
; |
;----------------------------------------------------------------- ; TODO: use a mutex |
365,28 → 346,29 |
DEBUGF 1,"ARP add entry: " |
|
mov ecx, [NumARP] |
test ecx, ecx |
test ecx, ecx ; first entry? |
jz .add |
cmp ecx, ARP_TABLE_SIZE ; list full ? |
jge .error |
|
mov eax, dword[esp + 4 + ARP_ENTRY.MAC] |
mov bx , word[esp + 4 + ARP_ENTRY.MAC + 4] |
mov esi, ARPTable |
mov eax, dword[esi + ARP_ENTRY.MAC] |
mov bx , word[esi + ARP_ENTRY.MAC + 4] |
mov edi, ARP_table |
|
.loop: |
cmp dword [esi + ARP_ENTRY.MAC], eax |
jne .maybe_next |
cmp word [esi + ARP_ENTRY.MAC + 4], bx |
jne .maybe_next |
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[esi + ARP_ENTRY.TTL], 0xFFFF ; static entry |
cmp dword[edi + ARP_ENTRY.TTL], 0xFFFF ; static entry |
jne .notstatic |
cmp dword[esp + 4 + ARP_ENTRY.TTL], 0xFFFF |
cmp dword[esi + ARP_ENTRY.TTL], 0xFFFF |
jne .error |
.notstatic: |
|
mov ebx, [NumARP] |
xchg ebx, ecx |
sub ecx, ebx |
neg ecx |
add ecx, [NumARP] |
jmp .add |
|
.maybe_next: |
394,30 → 376,26 |
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] |
lea edi, [ecx + ARP_table] |
mov ecx, ARP_ENTRY.size/2 |
repz movsw |
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 ARP_ENTRY.size |
ret |
|
.error: |
|
DEBUGF 1,"error! \n" |
|
mov eax, -1 |
jmp .exit |
ret |
|
|
;----------------------------------------------------------------- |
424,7 → 402,7 |
; |
; ARP_del_entry |
; |
; IN: entry # in esi |
; IN: esi = ptr to arp entry |
; OUT: / |
; |
;----------------------------------------------------------------- |
431,161 → 409,129 |
align 4 |
ARP_del_entry: |
|
DEBUGF 1,"ARP del entry %u, total entrys: %u\n", esi, [NumARP] |
DEBUGF 1,"ARP del entry %x, total entrys: %u\n", esi, [NumARP] |
|
cmp esi, [NumARP] |
jge .error |
|
imul esi, ARP_ENTRY.size |
|
mov ecx, (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size |
mov ecx, ARP_table + (ARP_TABLE_SIZE - 1) * ARP_ENTRY.size |
sub ecx, esi |
shr ecx, 1 |
|
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! |
mov edi, esi |
lea esi, [edi + ARP_ENTRY.size] |
rep movsw |
|
dec [NumARP] ;decrease arp-entries counter |
dec [NumARP] |
DEBUGF 1,"ARP entry deleted\n" |
.error: |
|
ret |
|
|
|
|
|
;----------------------------------------------------------------- |
; |
; ARP_Handler: |
; ARP_IP_to_MAC |
; |
; This function handles ARP protocol over ethernet |
; (other protocols may follow in the future) |
; This function translates an IP address to a MAC address |
; |
; IN: Pointer to buffer in [esp] |
; size of buffer in [esp+4] |
; packet size (without ethernet header) in ecx |
; OUT: / |
; 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_handler: |
ARP_IP_to_MAC: |
|
DEBUGF 1,"ARP_Handler - start\n" |
cmp ecx, 28 |
jl .exit |
DEBUGF 1,"ARP_IP_to_MAC\n" |
|
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE ; Is this a reply packet? |
jne .maybe_request |
cmp eax, 0xffffffff |
je .broadcast |
|
DEBUGF 1,"ARP_Handler - it's a reply packet from %u.%u.%u.%u\n",\ |
[edx + ARP_Packet.SenderIP]:1,[edx + ARP_Packet.SenderIP+1]:1,[edx + ARP_Packet.SenderIP+2]:1,[edx + ARP_Packet.SenderIP+3]:1, |
; if ((Remote IP & subnet_mask) == (local IP & subnet_mask )) |
; destination is on same subnet |
; else, destination is remote and must use a gateway |
|
mov ecx, [NumARP] |
test ecx, ecx |
jz .exit |
call IPv4_dest_to_dev |
mov ebx, [IP_LIST + edi] |
and ebx, [SUBNET_LIST + edi] |
|
mov eax, [edx + ARP_Packet.SenderIP] |
mov esi, ARPTable+ARP_ENTRY.IP |
mov ecx, eax |
and ecx, [SUBNET_LIST + edi] |
|
.loop: |
cmp [esi], eax |
je .gotit |
add esi, ARP_ENTRY.size |
loop .loop |
cmp ecx, ebx |
je .local |
|
jmp .exit |
mov eax, [GATEWAY_LIST + edi] |
DEBUGF 1,"requested IP is not on subnet, using default gateway\n" |
|
.gotit: |
;-------------------------------- |
; Try to find the IP in ARP_table |
|
DEBUGF 1,"ARP_Handler - found matching entry\n" |
.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 |
|
cmp [esi+ARP_ENTRY.Status], 0x0300 ;if it is a static entry, dont touch it |
je .exit |
.not_in_list: |
DEBUGF 1,"IP not found on list, preparing for ARP request\n" |
|
DEBUGF 1,"ARP_Handler - updating entry\n" |
;-------------------- |
; Send an ARP request |
|
mov [esi+ARP_ENTRY.Status], ARP_VALID_MAPPING |
mov [esi+ARP_ENTRY.TTL], ARP_ENTRY_TTL |
|
mov eax, dword [edx + ARP_Packet.SenderMAC] |
mov dword [esi+ARP_ENTRY.MAC], eax |
mov ax , word [edx + ARP_Packet.SenderMAC + 4] |
mov word [esi+ARP_ENTRY.MAC+4], ax |
|
jmp .exit |
|
|
;------ |
|
|
.maybe_request: |
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE ; Is this a request packet? |
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 |
|
mov eax, edi |
shl eax, 2 |
add eax, IP_LIST |
mov eax, [eax] |
cmp eax, [edx + ARP_Packet.TargetIP] ; Is it looking for my IP address? |
jnz .exit |
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) |
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 |
|
cld |
lea esi, [edx + ARP_Packet.SenderMAC] |
lea edi, [edx + ARP_Packet.TargetMAC] |
movsd ; Move Sender Mac to Dest MAC |
movsw ; |
movsd ; Move sender IP to Dest IP |
cmp eax, -1 |
je .full |
|
pop esi |
mov esi, [NET_DRV_LIST + 4*esi] |
lea esi, [esi + ETH_DEVICE.mac] |
lea edi, [edx + ARP_Packet.SenderMAC] |
movsd ; Copy MAC address from in MAC_LIST |
movsw ; |
pop eax |
stosd ; Write our IP |
|
mov word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE |
call ARP_output_request |
|
; Now, Fill in ETHERNET header |
mov eax, -2 ; request send |
ret |
|
mov edi, [esp] |
lea esi, [edx + ARP_Packet.TargetMAC] |
movsd |
movsw |
lea esi, [edx + ARP_Packet.SenderMAC] |
movsd |
movsw |
; mov ax , ETHER_ARP |
; stosw |
.found_it: |
DEBUGF 1,"found IP in ARPTable\n" |
cmp [esi + ARP_ENTRY.Status], 1 |
jne .invalid |
|
DEBUGF 1,"ARP_Handler - Sending reply \n" |
movzx eax, word [esi+ARP_ENTRY.MAC] |
mov ebx, dword[esi+ARP_ENTRY.MAC+2] |
ret |
|
call [ebx + NET_DEVICE.transmit] |
.invalid: |
mov eax, -1 |
ret |
|
.exit: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
.full: |
DEBUGF 1,"ARP table is full!\n" |
pop eax |
mov eax, -1 |
ret |
|
DEBUGF 1,"ARP_Handler - exiting\n" |
.broadcast: |
mov eax, 0x0000ffff |
mov ebx, 0xffffffff |
ret |
|
|
|
|
;----------------------------------------------------------------- |
; |
; ARP_API |
643,7 → 589,7 |
; 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 |
|
.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 |
|