Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1513 → Rev 1514

/kernel/branches/net/network/IPv4.inc
1,6 → 1,6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; IPv4.INC ;;
18,16 → 18,13
 
$Revision$
 
; IP underlying protocols numbers
 
ETHER_IPv4 equ 0x0008 ; Reversed from 0800 for intel
 
MAX_FRAGMENTS equ 16
MAX_FRAGMENTS equ 64
MAX_IP equ MAX_NET_DEVICES
IP_MAX_INTERFACES equ MAX_IP
 
struct IPv4_Packet
.VersionAndIHL db ? ; Version[0-3 bits] and IHL(header length)[4-7 bits]
.TypeOfService db ?
.TypeOfService db ? ; precedence [7-5] minimize delay [4], maximize throughput [3], maximize riliability [2] minimize momentary cost [1] and zero [0]
.TotalLength dw ?
.Identification dw ?
.FlagsAndFragmentOffset dw ? ; Flags[0-2] and FragmentOffset[3-15]
58,13 → 55,15
 
align 4
uglobal
BROADCAST dd ?
 
IP_LIST rd MAX_IP
SUBNET_LIST rd MAX_IP
DNS_LIST rd MAX_IP
GATEWAY_LIST rd MAX_IP
 
IP_PACKETS_TX rd MAX_IP
IP_PACKETS_RX rd MAX_IP
 
FRAGMENT_LIST rb MAX_FRAGMENTS*FRAGMENT_slot.size
endg
 
83,11 → 82,11
IPv4_init:
 
or eax, -1
mov edi, BROADCAST
mov ecx, 4*MAX_IP+1
mov edi, IP_LIST
mov ecx, 4*MAX_IP
rep stosd
 
xor eax, eax
inc eax
mov edi, FRAGMENT_LIST
mov ecx, FRAGMENT_slot.size*MAX_FRAGMENTS/4 + 2*MAX_IP
rep stosd
114,11 → 113,13
;-----------------------------------------------------------------
align 4
IPv4_handler: ; TODO: implement handler for IP options
; TODO2: add code for IPv4 sockets (raw sockets)
; TODO2: add code for raw sockets
 
DEBUGF 1,"IP_Handler - start\n"
DEBUGF 1,"IPv4_Handler, packet from: %u.%u.%u.%u ",\
[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
DEBUGF 1,"to: %u.%u.%u.%u\n",\
[edx + IPv4_Packet.DestinationAddress]:1,[edx + IPv4_Packet.DestinationAddress + 1]:1,[edx + IPv4_Packet.DestinationAddress + 2]:1,[edx + IPv4_Packet.DestinationAddress + 3]:1
 
 
;-------------------------------------------
; Check if the packet still has time to live
 
133,61 → 134,66
cmp al , 0x05 ; IHL!= 5*4(20 bytes)
jnz .has_options
 
 
;-------------------------------
; Now, re-calcualte the checksum
; Now, re-calculate the checksum
 
; Re-calculate checksum
push edx ebx
mov esi, edx
call IPv4_checksum
pop ebx edx
 
; now see if it was correct
cmp [edx + IPv4_Packet.HeaderChecksum], 0
jne .dump ; if checksum isn't valid then dump packet
 
DEBUGF 1,"IPv4 Checksum is correct\n"
 
;-------------------------------------------------------
; Time to find out what interface this packet belongs to
;-----------------------------------
; Check if destination IP is correct
 
; Therefore we will scan the current list of IP's
call NET_ptr_to_num
shl edi, 2
 
mov eax, [edx + IPv4_Packet.DestinationAddress]
mov edi, BROADCAST
mov ecx, MAX_IP+1
; check if it matches local ip
 
.find_ip_loop:
cmp eax, dword [edi]
jz .ip_ok
add edi, 4
dec ecx
jnz .find_ip_loop
mov eax, dword[IP_LIST+edi]
cmp [edx + IPv4_Packet.DestinationAddress], eax
je .ip_ok
 
; it was not on the list, perhaps it's a loopback ?
; check for broadcast
 
mov eax, dword[SUBNET_LIST+edi]
not eax
test eax, 127 shl 24 ; 127.x.x.x
jz .ip_ok
or eax, dword[IP_LIST+edi]
cmp [edx + IPv4_Packet.DestinationAddress], eax
je .ip_ok
 
; TODO: we need to check for broadcasts (other then 255.255.255.255)
; or a special broadcast
 
DEBUGF 2,"Destination address does not match!\n"
cmp [edx + IPv4_Packet.DestinationAddress], -1
je .ip_ok
 
jmp .dump
; ; maybe it's a multicast then
;
; mov eax, [edx + IPv4_Packet.DestinationAddress]
; and eax, 0xff000000
; cmp eax, 224 shl 24
; je .ip_ok
 
; or a loopback address
 
;---------------------------------------------------
; Now we can update stats and find the device number
cmp eax, 127 shl 24
je .ip_ok
 
.ip_ok:
call ETH_struc2dev ; TODO: make this work on other protocols too!
inc [IP_PACKETS_RX+4*edi]
DEBUGF 1,"Packet comes from %u.%u.%u.%u\n",\
[edx + IPv4_Packet.SourceAddress]:1,[edx + IPv4_Packet.SourceAddress + 1]:1,[edx + IPv4_Packet.SourceAddress + 2]:1,[edx + IPv4_Packet.SourceAddress + 3]:1
; or it's not meant for us..
 
DEBUGF 2,"Destination address does not match!\n"
jmp .dump
 
;------------------------
; Now we can update stats
 
.ip_ok:
inc [IP_PACKETS_RX+edi]
 
;----------------------------------
; Check if the packet is fragmented
198,14 → 204,12
test [edx + IPv4_Packet.FlagsAndFragmentOffset], 0xff1f ; If flag is not set, but there is a fragment offset, the packet is last in series of fragmented packets
jnz .is_last_fragment
 
 
 
;-------------------------------------------------------------------
; No, it's just a regular IP packet, pass it to the higher protocols
 
.handle_it: ; We reach here if packet hasnt been fragmented, or when it already has been re-constructed
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
and eax, 0x0000000F ;
and eax, 0x0000000f ;
shl eax, 2 ;
movzx ecx, word [edx + IPv4_Packet.TotalLength] ; Calculate length of encapsulated Packet
xchg cl , ch ;
220,13 → 224,13
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
 
cmp al , IP_PROTO_TCP
je TCP_handler
je TCP_input
 
cmp al , IP_PROTO_UDP
je UDP_handler
je UDP_input
 
cmp al , IP_PROTO_ICMP
je ICMP_handler
je ICMP_input
 
DEBUGF 2,"unknown Internet protocol: %u\n", al
 
351,7 → 355,7
cmp esi, -1
jne .count_bytes
 
mov esi, [esp+4] ;;;
mov esi, [esp+4]
mov [edi + FRAGMENT_entry.NextPtr], esi ; Add this packet to the chain, this simplifies the following code
mov [esi + FRAGMENT_entry.NextPtr], -1
mov [esi + FRAGMENT_entry.PrevPtr], edi
463,7 → 467,7
;
; find fragment slot
;
; IN: pointer to fragmented packet in edx ; TODO: the RFC says we should check protocol too
; IN: pointer to fragmented packet in edx
; OUT: pointer to slot in edi, -1 on error
;
;-----------------------------------------------------------------
470,6 → 474,8
align 4
IPv4_find_fragment_slot:
 
;;; TODO: the RFC says we should check protocol number too
 
push eax ebx ecx edx
mov ax , word [edx + IPv4_Packet.Identification]
mov ecx, MAX_FRAGMENTS
514,7 → 520,7
dec [esi + FRAGMENT_slot.ttl]
jnz .try_next
DEBUGF 1,"Fragment slot timed-out!\n"
; TODO: clear all entry's of timed-out slot
;;; TODO: clear all entry's of timed-out slot
.try_next:
add esi, 4
loop .loop
524,14 → 530,40
 
 
 
;-----------------------------------------------------------------
;------------------------------------------------------------------
;
;
; IN: dword [esp] = pointer to packet to be fragmented
; dword [esp+4] = buffer size
; edx = pointer to IPv4 header in that packet
; ecx = data length
; ebx = device structure
;
; OUT: /
;
;------------------------------------------------------------------
align 4
IPv4_fragment:
 
;;; TODO: write code here
 
 
call kernel_free
add esp, 4
 
ret
 
 
 
 
;------------------------------------------------------------------
;
; Create_IPv4_Packet
;
; IN: eax = dest ip
; ebx = source ip
; ecx = data length
; dx = fragment id
; dx = fragment id ;;;;
; di = protocol
;
; OUT: eax = pointer to buffer start
538,19 → 570,18
; ebx = pointer to device struct (needed for sending procedure)
; ecx = unchanged (packet size of embedded data)
; edx = size of complete buffer
; esi = pointer to sending procedure
; edi = pointer to start of data (-1 on error)
; edi = pointer to start of data (0 on error)
;
;----------------------------------------------------------------- ;;; TODO: create fragmented packets
;------------------------------------------------------------------
align 4
IPv4_create_packet:
 
DEBUGF 1,"Create IPv4 Packet (size=%u)\n", ecx
 
cmp ecx, 1480
cmp ecx, 65500 ; Max IPv4 packet size
jg .exit_
 
test ebx, ebx ; if dest ip = 0
test ebx, ebx ; if source ip = 0
jnz .ip_ok ; and local ip is valid
; use local ip instead
cmp [IP_LIST],0xffffffff ;
582,16 → 613,17
.send:
call IPv4_dest_to_dev
inc [IP_PACKETS_TX+4*edi]
mov edx, [ETH_DRV_LIST + 4*edi]
mov edx, [NET_DRV_LIST + 4*edi]
lea eax, [edx + ETH_DEVICE.mac]
mov ebx, esp
mov ecx, [esp+18] ;; 18 or 22 ??
add ecx, IPv4_Packet.DataOrOptional
mov di , ETHER_IPv4
call ETH_create_packet ; TODO: figure out a way to make this work with other protocols too
;;; TODO: detect if packet is too large for ethernet, if so, call IPv4_fragment
call ETH_create_packet ;;; TODO: figure out a way to make this work with other protocols too
add esp, 6
cmp edi, -1
je .exit
test edi, edi
jz .exit
 
mov [edi + IPv4_Packet.VersionAndIHL], 0x45 ; IPv4, normal length (no Optional header)
mov [edi + IPv4_Packet.TypeOfService], 0
622,12 → 654,12
 
.not_found:
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
; TODO: QUEUE the packet to resend later!
;;;;;;
.exit:
add esp, 16
.exit_:
DEBUGF 1,"Create IPv4 Packet - failed\n"
or edi, -1
and edi, 0
ret