/kernel/branches/net/network/ARP.inc |
---|
1,23 → 1,22 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ARP.INC ;; |
;; ;; |
;; Address Resolution Protocol ;; |
;; Part of the tcp/ip network stack for KolibriOS ;; |
;; ;; |
;; This file contains the following: ;; |
;; arp_table_manager - Manages an ARPTable ;; |
;; arp_request - Sends an ARP request on the ethernet ;; |
;; arp_handler - Called when an ARP packet is received ;; |
;; Based on the work of [Johnny_B] and [smb] ;; |
;; ;; |
;; Changes history: ;; |
;; 22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net ;; |
;; 11.11.2006 - [Johnny_B] and [smb] ;; |
;; Written by hidnplayr@kolibrios.org ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 983 $ |
26,6 → 25,9 |
ARP_AWAITING_RESPONSE equ 2 |
ARP_RESPONSE_TIMEOUT equ 3 |
ARP_REQUEST_TTL = 20 ; in seconds |
ARP_ENTRY_TTL = 30 ; in seconds |
ETHER_ARP equ 0x0608 |
ARP_REQ_OPCODE equ 0x0100 ; request |
79,7 → 81,18 |
;----------------------------------------------------------------- |
; |
; ARP_init |
; |
; This function resets all ARP variables |
; |
; IN: / |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
ARP_init: |
xor eax, eax |
93,176 → 106,24 |
ret |
;*************************************************************************** |
; Function |
; arp_table_manager [by Johnny_B] |
;----------------------------------------------------------------- |
; |
; Description |
; Does a most required operations with ARP-table |
; IN: |
; Operation: see Opcode's constants below |
; Index: Index of entry in the ARP-table |
; Extra: Extra parameter for some Opcodes |
; OUT: |
; EAX = Returned value depends on opcodes, more detailed see below |
; ARP_IP_to_MAC |
; |
;*************************************************************************** |
;Opcode's constants |
ARP_TABLE_ADD equ 1 |
ARP_TABLE_IP_TO_MAC equ 5 |
; 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' |
; |
;----------------------------------------------------------------- |
;Index's constants |
EXTRA_IS_ARP_PACKET_PTR equ 0 ;if Extra contain pointer to ARP_Packet |
EXTRA_IS_ARP_ENTRY_PTR equ -1 ;if Extra contain pointer to ARP_ENTRY |
align 4 |
proc arp_table_manager stdcall uses ebx esi edi ecx edx, Opcode:DWORD,Index:DWORD,Extra:DWORD |
ARP_IP_to_MAC: |
mov ebx, ARPTable ;ARPTable base |
mov ecx, dword[NumARP] ;ARP-entries counter |
DEBUGF 1,"ARP_IP_to_MAC\n" |
mov eax, dword[Opcode] |
DEBUGF 1,"ARP table manager opcode:%u numARP:%u\n",eax,ecx |
cmp eax, ARP_TABLE_ADD |
je .add |
cmp eax, ARP_TABLE_IP_TO_MAC |
je .ip_to_mac |
jmp .exit ;if unknown opcode |
;;BEGIN ADD |
;;Description: it adds an entry in the table. If ARP-table already |
;; contains same IP, it will be updated. |
;;IN: Operation: ARP_TABLE_ADD |
;; Index: specifies what contains Extra-parameter |
;; Extra: if Index==EXTRA_IS_ARP_Packet_PTR, |
;; then Extra contains pointer to ARP_Packet, |
;; otherwise Extra contains pointer to ARP_ENTRY |
;;OUT: |
;; EAX=index of entry, that has been added |
;; |
.add: |
DEBUGF 1,"1" |
sub esp, ARP_ENTRY.size ;Allocate ARP_ENTRY_SIZE byte in stack |
mov esi, [Extra] ;pointer |
mov edi, [Index] ;opcode |
cmp edi, EXTRA_IS_ARP_PACKET_PTR |
je .ARP_Packet_to_entry ;if Extra contain ptr to ARP_Packet and we have to form arp-entry |
;else it contain ptr to arp-entry |
DEBUGF 1,"2" |
cld |
; esi already has been loaded |
mov edi, esp ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY.size/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw ;copy |
jmp .search |
.ARP_Packet_to_entry: |
DEBUGF 1,"3" |
mov edx, dword[esi + ARP_Packet.SenderIP] ;esi=base of ARP_Packet |
mov [esp + ARP_ENTRY.IP], edx |
cld |
lea esi, [esi + ARP_Packet.SenderMAC] |
lea edi, [esp + ARP_ENTRY.MAC] |
movsd |
movsw |
mov word[esp + ARP_ENTRY.Status], ARP_VALID_MAPPING ; specify the type - a valid entry |
mov word[esp + ARP_ENTRY.TTL], 0x0E10 ; = 1 hour |
.search: |
DEBUGF 1,"4" |
mov edx, dword[esp + ARP_ENTRY.IP] ;edx=IP-address, which we'll search |
mov ecx, dword[NumARP] ;ecx=ARP-entries counter |
jecxz .add_to_end ;if ARP-entries number == 0 |
imul eax, ecx, ARP_ENTRY.size ;eax=current table size(in bytes) |
@@: |
sub eax, ARP_ENTRY.size |
cmp dword[ebx + eax + ARP_ENTRY.IP], edx |
loopnz @b |
; jz .replace ; found, replace existing entry, ptr to it is in eax |
.add_to_end: |
; |
; DEBUGF 1,"5\n" |
; ;else add to end |
; or eax,-1 ;set eax=0xFFFFFFFF if adding is impossible |
; mov ecx, dword[NumARP] |
; cmp ecx, ARP_TABLE_SIZE |
; je .add_exit ;if arp-entries number is equal to arp-table maxsize |
; imul eax, dword[NumARP], ARP_ENTRY.size ;eax=ptr to end of ARPTable |
; inc dword [NumARP] ;increase ARP-entries counter |
; .replace: |
DEBUGF 1,"Updating ARP entry: %x-%x-%x-%x-%x-%x = %u.%u.%u.%u to slot:%u\n",\ |
[esp + ARP_ENTRY.MAC]:2,[esp + ARP_ENTRY.MAC+1]:2,[esp + ARP_ENTRY.MAC+2]:2,[esp + ARP_ENTRY.MAC+3]:2,[esp + ARP_ENTRY.MAC+4]:2,[esp + ARP_ENTRY.MAC+5]:2,\ |
[esp + ARP_ENTRY.IP]:1,[esp + ARP_ENTRY.IP+1]:1,[esp + ARP_ENTRY.IP+2]:1,[esp + ARP_ENTRY.IP+3]:1,eax |
cld |
mov esi, esp ;esp=base of ARP-entry, that will be added |
lea edi, [ebx + eax] ;ebx + eax=ARPTable_base + ARP-entry_base(where we will add) |
mov ecx,ARP_ENTRY.size/2 ;ARP_ENTRY_SIZE must be even number!!! |
rep movsw |
mov ecx, ARP_ENTRY.size |
xor edx, edx ;"div" takes operand from EDX:EAX |
div ecx ;eax=index of entry, which has been added |
.add_exit: |
add esp, ARP_ENTRY.size ;free stack |
jmp .exit |
;;END ADD |
;;BEGIN IP_TO_MAC |
;;Description: it gets an IP from Index, scans each entry in the table and writes |
;; MAC, that relates to specified IP, into buffer specified in Extra. |
;; And if it cannot find an IP-address in the table, it does an ARP-request of that. |
;;IN: Operation: ARP_TABLE_IP_TO_MAC |
;; Index: IP that should be transformed into MAC |
;; Extra: pointer to buffer where will be written the MAC-address. |
;;OUT: |
;; EAX=ARP table entry status code. |
;; If EAX==ARP_NO_ENTRY, IP isn't found in the table and we have sent the request. |
;; If EAX==ARP_AWAITING_RESPONSE, we wait the response from remote system. |
;; If EAX==ARP_RESPONSE_TIMEOUT, remote system not responds too long. |
;; If EAX==ARP_VALID_MAPPING, all is ok, we've got a true MAC. |
;; |
;; If MAC will equal to a zero, in the buffer. It means, that IP-address was not yet |
;; resolved, or that doesn't exist. I recommend you, to do at most 3-5 calls of this |
;; function with 1sec delay. sure, only if it not return a valid MAC after a first call. |
;; |
.ip_to_mac: |
DEBUGF 1,"Trying to find MAC for %u.%u.%u.%u\n",[Index]:1,[Index+1]:1,[Index+2]:1,[Index+3]:1 |
xor eax, eax |
mov edi, dword[Extra] |
cld |
stosd |
stosw |
; first, check destination IP to see if it is on 'this' network. |
; The test is: |
; if ( destIP & subnet_mask == stack_ip & subnet_mask ) |
270,187 → 131,133 |
; else |
; destination is remote, so pass to gateway |
xor edx, edx ; TODO: find device num in edx |
;;; TODO: get device number ! (in edx) |
xor edx, 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, [Index] ;eax=required IP |
mov esi, eax |
and esi, [SUBNET_LIST+edx] |
mov ecx, [IP_LIST+edx] |
and ecx, [SUBNET_LIST+edx] |
cmp esi, ecx |
je @f ;if we and target IP are located in the same network |
mov eax, [GATEWAY_LIST+edx] |
mov [Index], eax |
DEBUGF 1,"IP is not on subnet, using %u.%u.%u.%u instead\n",[Index]:1,[Index+1]:1,[Index+2]:1,[Index+3]:1 |
@@: |
DEBUGF 1,"requested IP is not on subnet, using gateway\n" |
cmp dword[NumARP], 0 |
je .ip_to_mac_send_request ;if ARP-table not contain an entries, we have to request IP. |
;EAX will be containing a zero, it's equal to ARP_NO_ENTRY |
.local: |
; try to find it on the list |
mov ecx, [NumARP] |
jz .not_in_list |
mov esi, ARPTable + ARP_ENTRY.IP |
.scan_loop: |
scasd |
jz .found_it |
add esi, ARP_ENTRY.size - 4 |
loop .scan_loop |
.not_in_list: |
mov ecx, dword[NumARP] |
imul esi, ecx, ARP_ENTRY.size ;esi=current ARP-table size |
DEBUGF 1,"IP not found on list, preparing for ARP request\n" |
@@: |
sub esi, ARP_ENTRY.size |
cmp [ebx + esi + ARP_ENTRY.IP], eax ; ebx=ARPTable base |
loopnz @b ; Return back if non match |
jnz .ip_to_mac_send_request ; and request IP->MAC if none found in the table |
; if not, reserve an entry in list and send an ARP request packet |
; Return the entry status in eax |
movzx eax, word[ebx + esi + ARP_ENTRY.Status] |
push eax |
DEBUGF 1,"MAC found: %x-%x-%x-%x-%x-%x status:%x in slot:%u\n",\ |
[ebx + esi + ARP_ENTRY.MAC]:2,[ebx + esi + ARP_ENTRY.MAC+1]:2,[ebx + esi + ARP_ENTRY.MAC+2]:2,[ebx + esi + ARP_ENTRY.MAC+3]:2,[ebx + esi + ARP_ENTRY.MAC+4]:2,[ebx + esi + ARP_ENTRY.MAC+5]:2, ax, esi |
push word ARP_REQUEST_TTL |
push word ARP_AWAITING_RESPONSE |
push dword 0 |
push word 0 |
push eax |
call ARP_add_entry |
; esi holds index |
cld |
lea esi, [ebx + esi + ARP_ENTRY.MAC] |
mov edi, [Extra] ;edi=ptr to buffer for write MAC |
movsd |
movsw |
jmp .exit |
cmp eax, -1 |
je .full |
.ip_to_mac_send_request: |
;;; TODO: get device number ! (in edx) |
xor edx, edx |
mov edx, [ETH_DRV_LIST + 4*edx] |
lea ecx, [edx + ETH_DEVICE.mac] |
pop eax |
call ARP_create_request |
stdcall arp_request,[Index],[IP_LIST+edx],ecx ;TargetIP,SenderIP_ptr,SenderMAC_ptr |
mov eax, ARP_NO_ENTRY |
jmp .exit |
ret |
;;END IP_TO_MAC |
.found_it: |
DEBUGF 1,"Found MAC! (%u-%u-%u-%u-%u-%u)\n",[esi+0]:2,[esi+1]:2,[esi+2]:2,[esi+3]:2,[esi+4]:2,[esi+5]:2 |
movzx eax, word [esi] |
mov ebx, [esi+2] |
.exit: |
ret |
endp |
.full: |
add esp, 4 |
mov eax, -1 |
ret |
;*************************************************************************** |
; Function |
; arp_request [by Johnny_B] |
;--------------------------------------------------------------------------- |
; |
; Description |
; Sends an ARP request on the ethernet |
; IN: |
; TargetIP : requested IP address |
; SenderIP_ptr : POINTER to sender's IP address(our system's address) |
; SenderMAC_ptr : POINTER to sender's MAC address(our system's address) |
; OUT: |
; EAX=0 (if all is ok), otherwise EAX is not defined |
; ARP_create_packet |
; |
; EBX,ESI,EDI will be saved |
; IN: ip in eax |
; |
;*************************************************************************** |
proc arp_request stdcall uses ebx esi edi,\ |
TargetIP:DWORD, SenderIP_ptr:DWORD, SenderMAC_ptr:DWORD |
; OUT: / |
; |
;--------------------------------------------------------------------------- |
DEBUGF 1,"Create ARP request\n" |
align 4 |
ARP_create_request: |
stdcall kernel_alloc, 60 ; minimum eth packet size |
test eax, eax |
jz .exit |
DEBUGF 1,"Create ARP Packet\n" |
mov ebx, eax |
call IPv4_dest_to_dev |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.HardwareType], 0x0100 ;Ethernet |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.ProtocolType], 0x0008 ;IP |
mov byte [ebx + ETH_FRAME.Data + ARP_Packet.HardwareSize], 0x06 ;MAC-addr length |
mov byte [ebx + ETH_FRAME.Data + ARP_Packet.ProtocolSize], 0x04 ;IP-addr length |
mov word [ebx + ETH_FRAME.Data + ARP_Packet.Opcode], 0x0100 ;Request |
push eax ; DestIP |
mov eax, [IP_LIST+4*edi] ; senderIP |
push eax |
DEBUGF 1,"1" |
mov edi, [ETH_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 |
cmp edi, -1 |
je .exit |
cld |
mov esi, [SenderMAC_ptr] |
lea edi, [ebx + ETH_FRAME.Data + ARP_Packet.SenderMAC] ;Our MAC-addr |
movsd |
movsw |
mov word [edi + ARP_Packet.HardwareType], 0x0100 ;Ethernet |
mov word [edi + ARP_Packet.ProtocolType], 0x0008 ;IP |
mov byte [edi + ARP_Packet.HardwareSize], 6 ;MAC-addr length |
mov byte [edi + ARP_Packet.ProtocolSize], 4 ;IP-addr length |
mov word [edi + ARP_Packet.Opcode], ARP_REQ_OPCODE ;Request |
DEBUGF 1,"2" |
add edi, ARP_Packet.SenderMAC ; sendermac |
lea esi, [edx + ETH_DEVICE.mac] ; |
movsw ; |
movsd ; |
mov esi, [SenderIP_ptr] |
mov [ebx + ETH_FRAME.Data + ARP_Packet.SenderIP], esi ;Our IP-addr |
; movsd |
pop eax |
stosd ; |
DEBUGF 1,"3" |
xor eax, eax ; destmac |
movsw ; |
movsw ; |
lea edi, [ebx + ETH_FRAME.Data + ARP_Packet.TargetMAC] ; Required MAC-addr |
xor eax, eax |
stosd |
stosw |
pop eax |
movsd ; |
DEBUGF 1,"4" |
DEBUGF 1,"ARP Packet for device %x created successfully\n", edx |
lea edi, [ebx + ETH_FRAME.DstMAC] |
stosd |
stosw |
call esi |
DEBUGF 1,"5" |
inc [ARP_PACKETS_TX+4*edi] |
mov esi, [TargetIP] |
mov dword [ebx + ETH_FRAME.Data + ARP_Packet.TargetIP], esi ;Required IP-addr(we get it as function parameter) |
ret |
DEBUGF 1,"6" |
mov esi, [SenderMAC_ptr] |
lea edi, [ebx + ETH_FRAME.SrcMAC] |
movsd |
movsw |
DEBUGF 1,"7" |
mov ax , ETHER_ARP |
stosw |
DEBUGF 1,"8" |
;;; TODO: get device number in edx !! |
xor edx, edx |
shl edx, 2 |
inc [ARP_PACKETS_TX+edx] |
push dword .returnaddr |
push dword 60 |
push ebx |
mov ebx, [ETH_DRV_LIST + edx] |
jmp [ebx + ETH_DEVICE.transmit] |
.returnaddr: |
; Add an entry in the ARP table, awaiting response |
sub esp, ARP_ENTRY.size ;allocate memory for ARP-entry |
mov esi, dword[TargetIP] |
mov dword[esp + ARP_ENTRY.IP],esi |
lea edi, [esp + ARP_ENTRY.MAC] |
xor eax, eax |
stosd |
stosw |
mov word[esp + ARP_ENTRY.Status], ARP_AWAITING_RESPONSE |
mov word[esp + ARP_ENTRY.TTL], 10 ; 10 seconds |
stdcall arp_table_manager,ARP_TABLE_ADD,EXTRA_IS_ARP_ENTRY_PTR,esp |
add esp, ARP_ENTRY.size ; free memory |
.exit: |
DEBUGF 1,"ARP request - end\n" |
add esp, 8 |
DEBUGF 1,"Create ARP Packet - failed\n" |
mov eax, -1 |
ret |
endp |
;--------------------------------------------------------------------------- |
; |
; ARP_decrease_entry_ttls |
512,7 → 319,82 |
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: |
mov ecx, [NumARP] |
test ecx, ecx |
jz .add |
mov eax, dword[esp + ARP_ENTRY.MAC] |
mov bx , word[esp + 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 + ARP_ENTRY.TTL], 0xFFFF |
jne .exit |
.notstatic: |
mov ebx, [NumARP] |
xchg ebx, ecx |
sub ecx, ebx |
jmp .add |
.maybe_next: |
add esi, ARP_ENTRY.size |
loop .loop |
mov ecx, [NumARP] |
cmp ecx, ARP_TABLE_SIZE |
jge .full |
.add: |
push ecx |
imul ecx, ARP_ENTRY.size |
lea edi, [ecx + ARPTable] |
lea esi, [esp + 4] |
mov ecx, ARP_ENTRY.size/2 |
repz movsw |
inc [NumARP] |
pop eax |
.exit: |
add esp, 14 |
ret |
.full: |
mov eax, -1 |
jmp .exit |
;--------------------------------------------------------------------------- |
; |
; ARP_del_entry |
537,13 → 419,12 |
cld |
rep movsw |
dec dword[NumARP] ;decrease arp-entries counter |
dec [NumARP] ;decrease arp-entries counter |
ret |
;----------------------------------------------------- |
; |
; ARP_Handler: |
557,22 → 438,53 |
; OUT: / |
; |
;----------------------------------------------------- |
align 4 |
ARP_Handler: |
ARP_handler: |
DEBUGF 1,"ARP_Handler - start\n" |
cmp ecx, 28 |
jl .exit |
; Is this a REQUEST? |
; Is this a request for My Host IP |
; Yes - So construct a response message. |
; Send this message to the ethernet card for transmission |
cmp word [edx + ARP_Packet.Opcode], ARP_REP_OPCODE ; Is this a reply packet? |
jne .maybe_request |
; push ebx edx |
stdcall arp_table_manager, ARP_TABLE_ADD, EXTRA_IS_ARP_PACKET_PTR, edx |
; pop edx ebx |
mov ecx, [NumARP] |
test ecx, ecx |
jz .exit |
mov eax, [esp] |
mov eax, [eax + ARP_Packet.SenderIP] |
mov esi, ARPTable+ARP_ENTRY.IP |
.loop: |
scasd |
jz .gotit |
add esi, ARP_ENTRY.size-4 |
loop .loop |
jmp .exit |
.gotit: |
cmp [esi-4+ARP_ENTRY.Status], 0x0300 ;if it is a static entry, dont touch it |
je .exit |
mov [esi-4+ARP_ENTRY.Status], ARP_VALID_MAPPING |
mov [esi+ARP_ENTRY.TTL-4], ARP_ENTRY_TTL |
mov ebx, [esp] |
mov eax, dword [ebx + ARP_Packet.SenderMAC] |
mov dword [esi+ARP_ENTRY.MAC-4], eax |
mov ax , word [ebx + ARP_Packet.SenderMAC + 4] |
mov word [esi+ARP_ENTRY.MAC-4+4], ax |
jmp .exit |
;------ |
.maybe_request: |
cmp word [edx + ARP_Packet.Opcode], ARP_REQ_OPCODE ; Is this a request packet? |
jne .exit |
591,10 → 503,8 |
push eax |
push edi |
; DEBUGF 1,"ETH_ARP_Handler - request for %u.%u.%u.%u\n",[edi+0]:1,[edi+1]:1,[edi+2]:1,[edi+3]:1 |
; OK, it is a request for one of our MAC addresses. Build the frame and send it |
; We can reuse the buffer. |
; We can reuse the buffer. (faster then using ARP_create_packet) |
cld |
lea esi, [edx + ARP_Packet.SenderMAC] |
623,8 → 533,8 |
lea esi, [edx + ARP_Packet.SenderMAC] |
movsd |
movsw |
mov ax , ETHER_ARP |
stosw |
; mov ax , ETHER_ARP |
; stosw |
jmp ETH_Sender ; And send it! |
672,7 → 582,6 |
jz .remove ; 5 |
dec bl |
.error: |
mov eax, -1 |
ret |
697,9 → 606,11 |
.write: |
; TODO: write code |
; call ARP_write_entry |
ret |
.remove: |
; TODO: write code |
mov esi, eax |
call ARP_del_entry |
ret |
/kernel/branches/net/network/IPv4.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; IP.INC ;; |
85,7 → 85,9 |
or eax, -1 |
mov edi, BROADCAST |
mov ecx, 1+4*MAX_IP |
stosd |
xor eax, eax |
mov ecx, 4*MAX_IP |
rep stosd |
xor eax, eax |
116,7 → 118,7 |
;----------------------------------------------------------------- |
align 4 |
IPv4_Handler: |
IPv4_handler: |
DEBUGF 1,"IP_Handler - start\n" |
mov cx , [edx + IPv4_Packet.HeaderChecksum] |
186,13 → 188,13 |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
cmp al , IP_PROTO_TCP |
; je TCP_Handler |
; je TCP_handler |
cmp al , IP_PROTO_UDP |
je UDP_Handler |
je UDP_handler |
cmp al , IP_PROTO_ICMP |
je ICMP_Handler |
je ICMP_handler |
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
391,14 → 393,14 |
mov al , [edx + IPv4_Packet.Protocol] |
pop edx ; Offset to data (tcp/udp/icmp/.. Packet) |
; cmp al , IP_PROTO_TCP |
; je TCP_Handler |
cmp al , IP_PROTO_TCP |
; je TCP_handler |
cmp al , IP_PROTO_UDP |
je UDP_Handler |
je UDP_handler |
cmp al , IP_PROTO_ICMP |
je ICMP_Handler_fragments |
je ICMP_handler_fragments |
DEBUGF 1,"IP_Handler - unknown protocol:%u\n",al |
505,7 → 507,7 |
;;; TODO: create fragmented packets |
align 4 |
IPv4_create_Packet: |
IPv4_create_packet: |
DEBUGF 1,"Create IPv4 Packet\n" |
515,12 → 517,11 |
cmp eax, -1 |
je .broadcast ; If it is broadcast, just send |
push eax |
stdcall arp_table_manager, ARP_TABLE_IP_TO_MAC, eax, temp_dstmac ;opcode,IP,MAC_ptr - Get the MAC address. |
cmp eax, ARP_NO_ENTRY |
pop eax |
jne .send |
call ARP_IP_to_MAC |
cmp eax, -1 |
jne .found |
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n" |
; TODO: QUEUE! |
528,9 → 529,15 |
ret |
.found: |
push ax |
push ebx |
jmp .send |
.broadcast: |
mov dword [temp_dstmac], -1 |
mov word [temp_dstmac+4], -1 |
push word -1 |
push dword -1 |
.send: |
539,9 → 546,10 |
inc [IP_PACKETS_TX+4*edi] |
mov edi, [ETH_DRV_LIST + 4*edi] |
lea eax, [edi + ETH_DEVICE.mac] |
mov ebx, temp_dstmac |
lea ebx, [esp+16] |
mov ecx, [esp+12] |
add ecx, IPv4_Packet.DataOrOptional |
mov edx, edi ;;; |
mov di , ETHER_IPv4 |
call ETH_create_Packet ; TODO: figure out a way to make this work with other protocols too |
cmp edi, -1 |
572,10 → 580,12 |
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", edx |
add esp, 6 |
ret |
.exit: |
add esp, 16 |
add esp, 16+6 |
.exit_: |
DEBUGF 1,"Create IPv4 Packet - failed\n" |
or edi, -1 |
582,11 → 592,7 |
ret |
uglobal |
temp_dstmac dp ? ; TODO: place this in stack instead! |
endg |
;--------------------------------------------------------------------------- |
; |
; IPv4_dest_to_dev |
/kernel/branches/net/network/ethernet.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ETHERNET.INC ;; |
46,6 → 46,12 |
align 4 |
iglobal |
ETH_BROADCAST dp 0xffffffffffff |
endg |
align 4 |
uglobal |
ETH_RUNNING dd ? |
230,7 → 236,7 |
;------------------------------------------------------------- |
align 4 |
ETH_Handler: |
ETH_handler: |
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome |
243,10 → 249,10 |
mov ax , [eax + ETH_FRAME.Type] |
cmp ax, ETHER_IPv4 |
je IPv4_Handler |
je IPv4_handler |
cmp ax, ETHER_ARP |
je ARP_Handler |
je ARP_handler |
DEBUGF 1,"Unknown ethernet packet type %x\n", ax |
377,19 → 383,15 |
pop ecx |
pop edx |
DEBUGF 1,"1" |
mov edi, eax |
pop esi |
movsd |
movsw |
DEBUGF 1,"2" |
pop esi |
movsd |
movsw |
DEBUGF 1,"3" |
pop ax |
stosw |
DEBUGF 1,"4" |
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start |
mov ebx, ecx ; Set ebx to complete buffer size |
/kernel/branches/net/network/icmp.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; ICMP.INC ;; |
146,7 → 146,7 |
;-------------------------------- |
align 4 |
ICMP_Handler: ;TODO: works only on pure ethernet right now ! |
ICMP_handler: ;TODO: works only on pure ethernet right now ! |
DEBUGF 1,"ICMP_Handler - start\n" |
cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request? |
318,7 → 318,7 |
;-------------------------------- |
align 4 |
ICMP_Handler_fragments: ; works only on pure ethernet right now ! |
ICMP_handler_fragments: ; works only on pure ethernet right now ! |
DEBUGF 1,"ICMP_Handler_fragments - start\n" |
345,7 → 345,7 |
shl edx, 16 |
mov dx , ICMP_ECHOREPLY shl 8 + 0 ; Type + Code |
call ICMP_create_Packet |
call ICMP_create_packet |
.dump: |
DEBUGF 1,"ICMP_Handler_fragments - end\n" |
372,7 → 372,7 |
;----------------------------------------------------------------- |
align 4 |
ICMP_create_Packet: |
ICMP_create_packet: |
DEBUGF 1,"Create ICMP Packet\n" |
382,7 → 382,7 |
mov di , IP_PROTO_ICMP |
shr edx, 16 |
call IPv4_create_Packet |
call IPv4_create_packet |
cmp edi, -1 |
je .exit |
/kernel/branches/net/network/queue.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; queue.inc ;; |
/kernel/branches/net/network/socket.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; SOCKET.INC ;; |
24,24 → 24,25 |
.PID dd ? ; application process id |
.Domain dd ? ; INET/UNIX/.. |
.Type dd ? ; RAW/UDP/TCP/... |
.Protocol dd ? ; ICMP/IPv4/ARP/ |
.LocalIP dd ? ; local IP address |
.RemoteIP dd ? ; remote IP address |
.LocalPort dw ? ; local port |
.RemotePort dw ? ; remote port |
; .OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
; .OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state) |
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state) |
.rxDataCount dd ? ; rx data count |
; .TCBState dd ? ; TCB state |
; .TCBTimer dd ? ; TCB timer (seconds) |
; .ISS dd ? ; initial send sequence |
; .IRS dd ? ; initial receive sequence |
; .SND_UNA dd ? ; sequence number of unack'ed sent Packets |
; .SND_NXT dd ? ; bext send sequence number to use |
; .SND_WND dd ? ; send window |
; .RCV_NXT dd ? ; next receive sequence number to use |
; .RCV_WND dd ? ; receive window |
; .SEG_LEN dd ? ; segment length |
; .SEG_WND dd ? ; segment window |
.TCBState dd ? ; TCB state |
.TCBTimer dd ? ; TCB timer (seconds) |
.ISS dd ? ; initial send sequence |
.IRS dd ? ; initial receive sequence |
.SND_UNA dd ? ; sequence number of unack'ed sent Packets |
.SND_NXT dd ? ; bext send sequence number to use |
.SND_WND dd ? ; send window |
.RCV_NXT dd ? ; next receive sequence number to use |
.RCV_WND dd ? ; receive window |
.SEG_LEN dd ? ; segment length |
.SEG_WND dd ? ; segment window |
.wndsizeTimer dd ? ; window size timer |
.lock dd ? ; lock mutex |
.backlog dw ? ; Backlog |
125,7 → 126,7 |
; |
; IN: domain in ecx |
; type in edx |
; set esi to zero, it is reserved for future use |
; protocol in esi |
; OUT: eax is socket num, -1 on error |
; |
;----------------------------------------------- |
139,6 → 140,7 |
mov [eax + SOCKET.Domain], ecx |
mov [eax + SOCKET.Type], edx |
mov [eax + SOCKET.Protocol], esi |
stdcall net_socket_addr_to_num, eax |
DEBUGF 1,", socketnumber: %u\n", eax |
154,7 → 156,6 |
; |
; SOCKET_bind |
; |
; |
; IN: socket number in ecx |
; pointer to sockaddr struct in edx |
; length of that struct in esi |
184,6 → 185,7 |
jl s_error |
mov bx, word [edx + 2] |
rol bx,8 ;;; |
DEBUGF 1,"local port: %u ",bx |
test bx, bx |
jnz .check_only |
280,6 → 282,7 |
.udp: |
mov bx , word [edx + 2] |
rol bx, 8 |
mov word [eax + SOCKET.RemotePort], bx |
DEBUGF 1,"remote port: %u ",bx |
735,12 → 738,13 |
mov ecx, esi |
mov esi, edx |
mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once |
DEBUGF 1,"local port: %u, remote port:%u\n",[eax + SOCKET.LocalPort]:2, [eax + SOCKET.RemotePort]:2 |
bswap edx ;;; |
rol edx, 16 ;;; |
mov ebx, [eax + SOCKET.LocalIP] |
mov eax, [eax + SOCKET.RemoteIP] |
call UDP_create_Packet |
call UDP_create_packet |
mov [esp+32], eax |
ret |
765,7 → 769,7 |
add esi, ICMP_Packet.Data |
mov ebx, [eax + SOCKET.LocalIP] |
mov eax, [eax + SOCKET.RemoteIP] |
call ICMP_create_Packet |
call ICMP_create_packet |
mov [esp+32], eax |
ret |
/kernel/branches/net/network/stack.inc |
---|
110,7 → 110,7 |
cmp [ETH_RUNNING], 0 |
je .exit |
call ETH_Handler ; handle all queued ethernet packets |
call ETH_handler ; handle all queued ethernet packets |
call ETH_send_queued |
; Test for 10ms tick, call tcp timer |
188,6 → 188,13 |
align 4 |
sys_network: |
cmp ebx, -1 |
jne @f |
mov eax, [ETH_RUNNING] |
jmp .return |
@@: |
cmp bh, MAX_NET_DEVICES ; Check if device number exists |
jge .doesnt_exist |
200,7 → 207,7 |
test bl, bl ; 0 = Get device type (ethernet/token ring/...) |
jnz @f |
; todo |
xor eax, eax |
jmp .return |
/kernel/branches/net/network/tcp.inc |
---|
1,21 → 1,20 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; TCP.INC ;; |
;; ;; |
;; TCP Processes for Menuet OS TCP/IP stack ;; |
;; Part of the tcp/ip network stack for KolibriOS ;; |
;; ;; |
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;; |
;; Written by hidnplayr@kolibrios.org ;; |
;; ;; |
;; See file COPYING for details ;; |
;; v0.6 : Added reset handling in the established state ;; |
;; Added a timer per socket to allow delays when ;; |
;; rx window gets below 1KB ;; |
;; GNU GENERAL PUBLIC LICENSE ;; |
;; Version 2, June 1991 ;; |
;; ;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
$Revision: 1019 $ |
44,6 → 43,8 |
TCP_RETRIES equ 5 ; Number of times to resend a Packet |
TCP_TIMEOUT equ 10 ; resend if not replied to in x hs |
TCP_QUEUE_SIZE equ 16 |
struct TCP_Packet |
.SourcePort dw ? |
.DestinationPort dw ? |
59,17 → 60,59 |
.Data: |
ends |
align 4 |
uglobal |
TCP_PACKETS_TX rd MAX_IP |
TCP_PACKETS_RX rd MAX_IP |
;*************************************************************************** |
; Function |
TCP_IN_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
TCP_OUT_QUEUE rd 3*TCP_QUEUE_SIZE+3 |
endg |
;----------------------------------------------------------------- |
; |
; TCP_init |
; |
; This function resets all TCP variables |
; |
; IN: / |
; OUT: / |
; |
;----------------------------------------------------------------- |
align 4 |
TCP_init: |
xor eax, eax |
mov edi, TCP_PACKETS_TX |
mov ecx, 2*MAX_IP |
rep stosd |
mov dword [TCP_IN_QUEUE], TCP_QUEUE_SIZE |
mov dword [TCP_IN_QUEUE+4], TCP_IN_QUEUE + queue.data |
mov dword [TCP_IN_QUEUE+8], TCP_IN_QUEUE + queue.data |
mov dword [TCP_OUT_QUEUE], TCP_QUEUE_SIZE |
mov dword [TCP_OUT_QUEUE+4], TCP_OUT_QUEUE + queue.data |
mov dword [TCP_OUT_QUEUE+8], TCP_OUT_QUEUE + queue.data |
ret |
;----------------------------------------------------------------- |
; |
; tcp_tcb_handler |
; |
; Description |
; Handles sockets in the timewait state, closing them |
; when the TCB timer expires |
; |
;*************************************************************************** |
;----------------------------------------------------------------- |
align 4 |
tcp_tcb_handler: |
; scan through all the sockets, decrementing active timers |
84,7 → 127,7 |
or ebx, ebx |
jz .exit |
DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
; DEBUGF 1, "K : %x-%x: %x-%x-%x-%u\n", [ebx + SOCKET.PID]:2, [ebx + SOCKET.Number]:2, [ebx + SOCKET.LocalPort]:4, [ebx + SOCKET.RemoteIP], [ebx + SOCKET.RemotePort]:4, [ebx + SOCKET.TCBState] |
cmp [ebx + SOCKET.TCBTimer], 0 |
jne .decrement_tcb |
124,7 → 167,8 |
; |
;*************************************************************************** |
proc tcp_tx_handler stdcall |
align 4 |
tcp_tx_handler: |
; decrement all resend buffers timers. If they |
; expire, queue them for sending, and restart the timer. |
; If the retries counter reach 0, delete the entry |
133,7 → 177,7 |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .exit ; None left |
cmp dword[esi + 4], 0 |
jne @f ; found one |
162,9 → 206,9 |
@@: ; resend Packet |
pushad |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
jne .tth004z |
; TODO - try again in 10ms. |
179,21 → 223,21 |
.tth004z: |
; we have a buffer # in ax |
push eax ecx |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
; push eax ecx |
; mov ecx, IPBUFFSIZE |
; mul ecx |
; add eax, IPbuffs |
; we have the buffer address in eax |
mov edi, eax |
pop ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov esi, resendBuffer |
@@: add esi, IPBUFFSIZE |
; mov esi, resendBuffer |
; @@: add esi, IPBUFFSIZE |
loop @b |
; we have resend buffer location in esi |
mov ecx, IPBUFFSIZE |
; mov ecx, IPBUFFSIZE |
; copy data across |
push edi |
202,15 → 246,15 |
pop edi |
; queue Packet |
mov eax, NET1OUT_QUEUE |
mov edx, [IP_LIST] |
cmp edx, [edi + IP_Packet.DestinationAddress] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, NET1OUT_QUEUE |
; mov edx, [IP_LIST] |
; cmp edx, [edi + IP_Packet.DestinationAddress] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
pop ebx |
call queue |
; call queue |
.tth005: |
popad |
221,36 → 265,33 |
.exit: |
ret |
endp |
;*************************************************************************** |
; Function |
; tcp_rx |
;----------------------------------------------------------------- |
; |
; Description |
; TCP protocol handler |
; This is a kernel function, called by ip_rx |
; IP buffer address given in edx |
; IP buffer number in eax |
; Free up (or re-use) IP buffer when finished |
; TCP_Handler: |
; |
;*************************************************************************** |
; Called by IPv4_handler, |
; this procedure will inject the tcp data diagrams in the application sockets. |
; |
; IN: Pointer to buffer in [esp] |
; size of buffer in [esp+4] |
; pointer to device struct in ebx |
; TCP Packet size in ecx |
; pointer to TCP Packet data in edx |
; SourceAddres in esi |
; OUT: / |
; |
;----------------------------------------------------------------- |
proc tcp_rx stdcall uses ebx |
; The process is as follows. |
; Look for a socket with matching remote IP, remote port, local port |
; if not found, then |
; look for remote IP + local port match ( where sockets remote port = 0) |
; if not found, then |
; look for a socket where local socket port == IP Packets remote port |
; where sockets remote port, remote IP = 0 |
; discard if not found |
; Call sockets tcbStateMachine, with pointer to Packet. |
; the state machine will not delete the Packet, so do that here. |
TCP_Handler : |
push eax |
DEBUGF 1,"TCP_Handler\n" |
jmp .exit ;;;; |
; Look for a socket where |
; IP Packet TCP Destination Port = local Port |
; IP Packet SA = Remote IP |
265,19 → 306,19 |
; DEBUGF 1, "K : tcp_rx - 1.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; get the dest. port from the TCP hdr |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
jne .next_socket.1 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 1.sport: %x - %x\n", [edx + 20 + TCP_Packet.SourcePort]:4, [ebx + SOCKET.RemotePort]:4 |
mov ax, [edx + 20 + TCP_Packet.SourcePort] ; get the source port from the TCP hdr |
mov ax, [edx + TCP_Packet.SourcePort] ; get the source port from the TCP hdr |
cmp [ebx + SOCKET.RemotePort], ax ; compare with socket's remote port |
jne .next_socket.1 ; different - try next socket |
301,14 → 342,14 |
; DEBUGF 1, "K : tcp_rx - 2.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
mov ax, [edx + TCP_Packet.DestinationPort] ; get the dest. port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.addr: %x - %x\n", [edx + IP_Packet.SourceAddress], [ebx + SOCKET.RemoteIP] |
mov eax, [edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], eax ; compare with socket's remote IP |
; mov eax, esi ;[edx + IP_Packet.SourceAddress] ; get the source IP Addr from the IP hdr |
cmp [ebx + SOCKET.RemoteIP], esi ; compare with socket's remote IP |
jne .next_socket.2 ; different - try next socket |
; DEBUGF 1, "K : tcp_rx - 2.sport: 0000 - %x\n", [ebx + SOCKET.RemotePort]:4 |
336,7 → 377,7 |
; DEBUGF 1, "K : tcp_rx - 3.dport: %x - %x\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [ebx + SOCKET.LocalPort]:4 |
mov ax, [edx + 20 + TCP_Packet.DestinationPort] ; get destination port from the TCP hdr |
mov ax, [edx + TCP_Packet.DestinationPort] ; get destination port from the TCP hdr |
cmp [ebx + SOCKET.LocalPort], ax ; compare with socket's local port |
jne .next_socket.3 ; different - try next socket |
358,9 → 399,9 |
; If we got here, we need to reject the Packet |
DEBUGF 1, "K : tcp_rx - dumped\n" |
DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [edx + IP_Packet.SourceAddress], [edx + 20 + TCP_Packet.SourcePort]:4, [edx + 20 + TCP_Packet.Flags]:2 |
; DEBUGF 1, "K : --------: %x-%x-%x (flags: %x)\n", [edx + 20 + TCP_Packet.DestinationPort]:4, [edx + IP_Packet.SourceAddress], [edx + 20 + TCP_Packet.SourcePort]:4, [edx + 20 + TCP_Packet.Flags]:2 |
inc [dumped_rx_count] |
; inc [dumped_rx_count] |
jmp .exit |
.change_state: |
373,12 → 414,27 |
stdcall tcpStateMachine, ebx |
.exit: |
pop eax |
call freeBuff |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
endp |
;----------------------------------------------------------------- |
; |
; IN: eax = dest ip |
; ebx = source ip |
; ecx = data length |
; edx = remote port shl 16 + local port |
; esi = data offset |
; |
;----------------------------------------------------------------- |
TCP_create_Packet: |
DEBUGF 1,"Create TCP Packet\n" |
;*************************************************************************** |
; Function |
; buildTCPPacket |
394,30 → 450,31 |
; |
;*************************************************************************** |
proc build_tcp_Packet stdcall, sockAddr:DWORD |
push ecx ; Save data length |
; convert buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
add ecx, UDP_Packet.Data |
mov di , IP_PROTO_UDP |
mov edx, eax |
; dx = fragment id |
mov [edx + 20 + TCP_Packet.Flags], bl ; TCP flags |
call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
cmp edi, -1 |
je .exit |
mov ebx, [sockAddr] |
mov [edi + TCP_Packet.Flags], bl ; TCP flags |
; mov ebx, [sockAddr];---------------------------------------------------------- eof |
; So, ebx holds the socket ptr, edx holds the IPbuffer ptr |
; Fill in the IP header ( some data is in the socket descriptor) |
mov eax, [ebx + SOCKET.LocalIP] |
mov [edx + IP_Packet.SourceAddress], eax |
; mov [edx + IP_Packet.SourceAddress], eax |
mov eax, [ebx + SOCKET.RemoteIP] |
mov [edx + IP_Packet.DestinationAddress], eax |
; mov [edx + IP_Packet.DestinationAddress], eax |
mov [edx + IP_Packet.VersionAndIHL], 0x45 |
mov [edx + IP_Packet.TypeOfService], 0 |
; mov [edx + IP_Packet.VersionAndIHL], 0x45 |
; mov [edx + IP_Packet.TypeOfService], 0 |
pop eax ; Get the TCP data length |
push eax |
424,14 → 481,14 |
add eax, 20 + 20 ; add IP header and TCP header lengths |
rol ax, 8 |
mov [edx + IP_Packet.TotalLength], ax |
mov [edx + IP_Packet.Identification], 0 |
mov [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040 |
mov [edx + IP_Packet.TimeToLive], 0x20 |
mov [edx + IP_Packet.Protocol], PROTOCOL_TCP |
; mov [edx + IP_Packet.TotalLength], ax |
; mov [edx + IP_Packet.Identification], 0 |
; mov [edx + IP_Packet.FlagsAndFragmentOffset], 0x0040 |
; mov [edx + IP_Packet.TimeToLive], 0x20 |
; mov [edx + IP_Packet.Protocol], PROTOCOL_TCP |
; Checksum left unfilled |
mov [edx + IP_Packet.HeaderChecksum], 0 |
; mov [edx + IP_Packet.HeaderChecksum], 0 |
; Fill in the TCP header (some data is in the socket descriptor) |
mov ax, [ebx + SOCKET.LocalPort] |
475,54 → 532,64 |
@@: ; we have edx as IPbuffer ptr. |
; Fill in the TCP checksum |
; First, fill in pseudoheader |
mov eax, [edx + IP_Packet.SourceAddress] |
mov [pseudoHeader], eax |
mov eax, [edx + IP_Packet.DestinationAddress] |
mov [pseudoHeader + 4], eax |
mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
add ebx, 20 |
mov [pseudoHeader + 10], bh |
mov [pseudoHeader + 11], bl |
; mov eax, [edx + IP_Packet.SourceAddress] |
; mov [pseudoHeader], eax |
; mov eax, [edx + IP_Packet.DestinationAddress] |
; mov [pseudoHeader + 4], eax |
; mov word[pseudoHeader + 8], PROTOCOL_TCP shl 8 + 0 |
; add ebx, 20 |
; mov [pseudoHeader + 10], bh |
; mov [pseudoHeader + 11], bl |
; |
; mov eax, pseudoHeader |
; mov [checkAdd1], eax |
; mov word[checkSize1], 12 |
; mov eax, edx |
; add eax, 20 |
; mov [checkAdd2], eax |
; mov eax, ebx |
; mov [checkSize2], ax |
; |
; call checksum |
mov eax, pseudoHeader |
mov [checkAdd1], eax |
mov word[checkSize1], 12 |
mov eax, edx |
add eax, 20 |
mov [checkAdd2], eax |
mov eax, ebx |
mov [checkSize2], ax |
call checksum |
; store it in the TCP checksum ( in the correct order! ) |
mov ax, [checkResult] |
rol ax, 8 |
mov [edx + 20 + TCP_Packet.Checksum], ax |
; mov ax, [checkResult] |
; rol ax, 8 |
; mov [edx + 20 + TCP_Packet.Checksum], ax |
; Fill in the IP header checksum |
movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
and eax, 0x0000000F ; |
shl eax, 2 ; |
; movzx eax, byte [edx + IP_Packet.VersionAndIHL] ; Calculate Header length by using IHL field |
; and eax, 0x0000000F ; |
; shl eax, 2 ; |
; |
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size |
rol ax, 8 |
mov [edx + IP_Packet.HeaderChecksum], ax |
; mov [edx + IP_Packet.HeaderChecksum], ax |
.exit: |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
endp |
;endp |
; Increments the 32 bit value pointed to by esi in internet order |
proc inc_inet_esi stdcall |
push eax |
mov eax, [esi] |
bswap eax |
inc eax |
bswap eax |
mov [esi], eax |
pop eax |
ret |
; push eax |
; mov eax, [esi] |
; bswap eax |
; inc eax |
; bswap eax |
; mov [esi], eax |
; pop eax |
; ret |
inc byte[esi+0] |
adc byte[esi+1],0 |
adc byte[esi+2],0 |
adc byte[esi+3],0 |
endp |
591,7 → 658,7 |
xor ecx, ecx |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .call_handler ; None left |
cmp [esi + 4], eax |
je @f ; found one |
606,8 → 673,8 |
push ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
imul edi, ecx, IPBUFFSIZE |
add edi, resendBuffer |
; imul edi, ecx, IPBUFFSIZE |
; add edi, resendBuffer |
; we have dest buffer location in edi. incoming Packet in edx. |
; Get this Packets sequence number |
668,41 → 735,41 |
; We have a SYN. update the socket with this IP Packets details, |
; And send a response |
mov eax, [edx + IP_Packet.SourceAddress] |
mov [ebx + SOCKET.RemoteIP], eax |
mov ax, [edx + 20 + TCP_Packet.SourcePort] |
mov [ebx + SOCKET.RemotePort], ax |
mov eax, [edx + 20 + TCP_Packet.SequenceNumber] |
mov [ebx + SOCKET.IRS], eax |
mov [ebx + SOCKET.RCV_NXT], eax |
lea esi, [ebx + SOCKET.RCV_NXT] |
call inc_inet_esi ; RCV.NXT |
mov eax, [ebx + SOCKET.ISS] |
mov [ebx + SOCKET.SND_NXT], eax |
; mov eax, [edx + IP_Packet.SourceAddress] |
; mov [ebx + SOCKET.RemoteIP], eax |
; mov ax, [edx + 20 + TCP_Packet.SourcePort] |
; mov [ebx + SOCKET.RemotePort], ax |
; mov eax, [edx + 20 + TCP_Packet.SequenceNumber] |
; mov [ebx + SOCKET.IRS], eax |
; mov [ebx + SOCKET.RCV_NXT], eax |
; lea esi, [ebx + SOCKET.RCV_NXT] |
; call inc_inet_esi ; RCV.NXT |
; mov eax, [ebx + SOCKET.ISS] |
; mov [ebx + SOCKET.SND_NXT], eax |
; |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
; je .exit |
push eax |
mov bl, TH_SYN + TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
mov esi, [sockAddr] |
mov [esi + SOCKET.TCBState], TCB_SYN_RECEIVED |
747,9 → 814,9 |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
pop ebx |
je .exit |
757,19 → 824,19 |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
822,13 → 889,13 |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
je .last_resendq ; None left |
cmp [esi + 4], eax |
je @f ; found one |
inc ecx |
add esi, 8 |
jmp .next_resendq |
; cmp ecx, NUMRESENDENTRIES |
; je .last_resendq ; None left |
; cmp [esi + 4], eax |
; je @f ; found one |
; inc ecx |
; add esi, 8 |
; jmp .next_resendq |
@@: mov dword[esi + 4], 0 |
inc ecx |
881,7 → 948,7 |
; Read the data bytes, store in socket buffer |
movzx ecx, [edx + IP_Packet.TotalLength] |
; movzx ecx, [edx + IP_Packet.TotalLength] |
xchg cl, ch |
sub ecx, 40 ; Discard 40 bytes of header |
ja .data ; Read data, if any |
943,9 → 1010,9 |
.ack: |
; Send an ACK |
; Now construct the response, and queue for sending by IP |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
je .exit |
push eax |
953,20 → 1020,20 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1000,9 → 1067,9 |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
je .exit |
push eax |
1010,19 → 1077,19 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1040,10 → 1107,10 |
call inc_inet_esi |
; Send an ACK |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .exit |
; mov eax, EMPTY_QUEUE |
; call dequeue |
;; cmp ax, NO_BUFFER |
; je .exit |
push eax |
1050,19 → 1117,19 |
mov bl, TH_ACK |
xor ecx, ecx |
xor esi, esi |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; mov edx, [stack_ip] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov eax, IPIN_QUEUE |
.not_local: |
; Send it. |
pop ebx |
call queue |
;;; call queue |
.exit: |
ret |
1119,8 → 1186,8 |
; @param EDX is pointer to application data buffer |
; @return 0 (sent successfully) or -1 (error) in EAX |
;; |
proc socket_write_tcp stdcall |
local sockAddr dd ? |
;proc socket_write_tcp stdcall |
;local sockAddr dd ? |
; DEBUGF 1, "socket_write_tcp(0x%x)\n", ebx |
stdcall net_socket_num_to_addr, ebx |
1128,16 → 1195,16 |
jz .error |
mov ebx, eax |
mov [sockAddr], ebx |
; mov [sockAddr], ebx |
; If the sockets window timer is nonzero, do not queue Packet |
cmp [ebx + SOCKET.wndsizeTimer], 0 |
jne .error |
mov eax, EMPTY_QUEUE |
call dequeue |
cmp ax, NO_BUFFER |
je .error |
; mov eax, EMPTY_QUEUE |
; call dequeue |
; cmp ax, NO_BUFFER |
; je .error |
push eax |
1152,7 → 1219,7 |
push ecx |
mov bl, TH_ACK |
stdcall build_tcp_Packet, [sockAddr] |
; stdcall build_tcp_Packet, [sockAddr] |
pop ecx |
; Check destination IP address. |
1161,24 → 1228,24 |
pop ebx |
push ecx |
mov eax, NET1OUT_QUEUE |
; mov eax, NET1OUT_QUEUE |
;;; TODO: get device id in edx |
xor edx, edx |
shl edx, 2 |
mov edx, [IP_LIST+edx] |
mov ecx, [sockAddr] |
cmp edx, [ecx + SOCKET.RemoteIP] |
jne .not_local |
mov eax, IPIN_QUEUE |
; mov ecx, [sockAddr] |
; cmp edx, [ecx + SOCKET.RemoteIP] |
; jne .not_local |
; mov eax, IPIN_QUEUE |
.not_local: |
pop ecx |
push ebx ; save ipbuffer number |
call queue |
;;;; call queue |
mov esi, [sockAddr] |
; mov esi, [sockAddr] |
; increament SND.NXT in socket |
; Amount to increment by is in ecx |
1193,7 → 1260,7 |
mov ecx, 0 |
.next_resendq: |
cmp ecx, NUMRESENDENTRIES |
; cmp ecx, NUMRESENDENTRIES |
je .exit ; None found |
cmp dword[esi + 4], 0 |
je @f ; found one |
1211,7 → 1278,7 |
; retry time |
; fill IP buffer associated with this descriptor |
stdcall net_socket_addr_to_num, [sockAddr] |
; stdcall net_socket_addr_to_num, [sockAddr] |
mov [esi + 4], eax |
mov byte[esi + 1], TCP_RETRIES |
mov word[esi + 2], TCP_TIMEOUT |
1218,21 → 1285,21 |
inc ecx |
; Now get buffer location, and copy buffer across. argh! more copying,, |
mov edi, resendBuffer - IPBUFFSIZE |
; mov edi, resendBuffer - IPBUFFSIZE |
@@: add edi, IPBUFFSIZE |
; @@: add edi, IPBUFFSIZE |
loop @b |
; we have dest buffer location in edi |
pop eax |
; convert source buffer pointer eax to the absolute address |
mov ecx, IPBUFFSIZE |
mul ecx |
add eax, IPbuffs |
mov esi, eax |
; mov ecx, IPBUFFSIZE |
; mul ecx |
; add eax, IPbuffs |
; mov esi, eax |
; do copy |
mov ecx, IPBUFFSIZE |
; mov ecx, IPBUFFSIZE |
; cld |
rep movsb |
1243,7 → 1310,7 |
.error: |
or eax, -1 |
ret |
endp |
;endp |
1262,10 → 1329,10 |
checksum: |
pusha |
mov eax, [checkAdd1] |
; mov eax, [checkAdd1] |
xor edx, edx ; edx is the accumulative checksum |
xor ebx, ebx |
mov cx, [checkSize1] |
; mov cx, [checkSize1] |
shr cx, 1 |
jz cs1_1 |
1279,7 → 1346,7 |
loopw cs1 |
cs1_1: |
and word [checkSize1], 0x01 |
; and word [checkSize1], 0x01 |
jz cs_test2 |
mov bh, [eax] |
1288,11 → 1355,11 |
add edx, ebx |
cs_test2: |
mov cx, [checkSize2] |
; mov cx, [checkSize2] |
cmp cx, 0 |
jz cs_exit ; Finished if no 2nd buffer |
mov eax, [checkAdd2] |
; mov eax, [checkAdd2] |
shr cx, 1 |
jz cs2_1 |
1307,7 → 1374,7 |
loopw cs2 |
cs2_1: |
and word [checkSize2], 0x01 |
; and word [checkSize2], 0x01 |
jz cs_exit |
mov bh, [eax] |
1326,21 → 1393,7 |
add edx, eax |
not dx |
mov [checkResult], dx |
; mov [checkResult], dx |
popa |
ret |
TCP_HANDLER: |
;;; TODO: write code here |
call kernel_free |
add esp, 4 ; pop (balance stack) |
ret |
/kernel/branches/net/network/udp.inc |
---|
1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; UDP.INC ;; |
73,7 → 73,7 |
; |
;----------------------------------------------------------------- |
UDP_Handler: |
UDP_handler: |
DEBUGF 1,"UDP_Handler\n" |
; TODO: First validate the header & checksum. Discard buffer if error |
110,7 → 110,6 |
@@: |
DEBUGF 1,"Found valid UDP packet for socket %x\n", esi |
; sub ecx, UDP_Packet.Data ; get # of bytes in ecx |
; mov eax, ecx |
199,12 → 198,12 |
; IN: eax = dest ip |
; ebx = source ip |
; ecx = data length |
; edx = remote port shl 16 + local port |
; edx = remote port shl 16 + local port (both in INET order) |
; esi = data offset |
; |
;----------------------------------------------------------------- |
UDP_create_Packet: |
UDP_create_packet: |
DEBUGF 1,"Create UDP Packet\n" |
215,13 → 214,13 |
; dx = fragment id |
call IPv4_create_Packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6 |
cmp edi, -1 |
je .exit |
sub ecx , UDP_Packet.Data |
mov byte[edi + UDP_Packet.Length], ch |
mov byte[edi + UDP_Packet.Length+1], cl |
sub ecx , UDP_Packet.Data |
pop esi |
push edi |
235,8 → 234,8 |
pop edi |
pop ecx |
bswap ecx ; convert little endian - big endian |
rol ecx, 16 ; |
; bswap ecx ; convert little endian - big endian |
; rol ecx, 16 ; |
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once |