Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1195 → Rev 1196

/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