Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 383 → Rev 384

/kernel/branches/gfx_kernel/network/ip.inc
12,7 → 12,30
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
; IP underlying protocols numbers
PROTOCOL_ICMP equ 1
PROTOCOL_TCP equ 6
PROTOCOL_UDP equ 17
 
struc IP_PACKET
{ .VersionAndIHL db ? ;+00 - Version[0-3 bits] and IHL(header length)[4-7 bits]
.TypeOfService db ? ;+01
.TotalLength dw ? ;+02
.Identification dw ? ;+04
.FlagsAndFragmentOffset dw ? ;+06 - Flags[0-2] and FragmentOffset[3-15]
.TimeToLive db ? ;+08
.Protocol db ? ;+09
.HeaderChecksum dw ? ;+10
.SourceAddress dd ? ;+12
.DestinationAddress dd ? ;+16
.DataOrOptional dd ? ;+20
}
 
virtual at 0
IP_PACKET IP_PACKET
end virtual
 
 
;*******************************************************************
; Interface
;
24,179 → 47,151
;*******************************************************************
 
 
;
; IP Packet after reception - Normal IP packet format
;
; 0 1 2 3
; 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
;
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;0 |Version| IHL |Type of Service| Total Length |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;4 | Identification |Flags| Fragment Offset |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;8 | Time to Live | Protocol | Header Checksum |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;12 | Source Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;16 | Destination Address |
; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
;20 | Data |
; +-+-+-.......... -+
;
;
; [smb] attention! according to RFC 791 IP packet may have 'options' sections,
; so we can't simply think, that data have offset 20. We must calculate offset from
; IHL field
;
macro GET_IHL reg, header_addr
{
movzx reg, byte [header_addr]
; we need 4-7 bits, so....
and reg, 0x0000000F
; IHL keeps number of octets, so we need to << 2 'reg'
shl reg, 2
}
 
 
;***************************************************************************
; Function
; ip_rx
;
; Description
; Handles received IP packets
; This is a kernel function, called by stack_handler
; Processes all IP-packets received by the network layer
; It calls the appropriate protocol handler
;
;***************************************************************************
ip_rx:
proc ip_rx stdcall
local buffer_number dd ?
 
; Look for a buffer to tx
mov eax, IPIN_QUEUE
call dequeue
cmp ax, NO_BUFFER
je ipr_exit ; Exit if no buffer available
je .exit ; Exit if no buffer available
 
push eax
mov [buffer_number], eax ;save buffer number
 
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
imul eax, IPBUFFSIZE
add eax, IPbuffs
 
mov edx, eax ; Save the address in edx for use by future processes
mov ebx, eax ; ebx=pointer to IP_PACKET
 
; Validate the IP checksum
mov ebx, edx
mov ah, [ebx + 10]
mov al, [ebx + 11] ; Get the checksum in intel format
mov [ebx + 10], word 0 ; clear checksum field - need to when
mov dx, word[ebx + IP_PACKET.HeaderChecksum]
xchg dh,dl ; Get the checksum in intel format
mov [ebx + IP_PACKET.HeaderChecksum], word 0 ; clear checksum field - need to when
; recalculating checksum
 
; this needs two data pointers and two size #.
; 2nd pointer can be of length 0
mov ebx, edx
mov [checkAdd1], ebx
mov [checkSize1], word 20
mov [checkAdd2], dword 0
mov [checkSize2], word 0
 
call checksum ; Recalculate IP checksum
cmp ax, [checkResult]
jnz ipr_dump
GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
stdcall checksum_jb, ebx, ecx ;buf_ptr, buf_size
cmp dx, ax
 
mov edx, ebx ; EDX (IP-BUFFER POINTER) WILL BE USED FOR *_rx HANDLERS BELOW!!!
jnz .dump ;if CHECKSUM isn't valid then dump packet
 
; Validate the IP address, if it isn't broadcast
mov eax, [stack_ip]
cmp dword[ebx + IP_PACKET.DestinationAddress], eax
je @f
 
; If the IP address is 255.255.255.255, accept it
; - it is a broadcast packet, which we need for dhcp
mov eax, [edx + 16]
cmp eax, 0xffffffff
je ipr_p0
cmp dword[ebx + IP_PACKET.DestinationAddress], 0xffffffff
jne .dump
 
; Validate the IP address, if it isn't broadcast
cmp eax, [stack_ip]
jnz ipr_dump
@@:
mov al, [ebx + IP_PACKET.VersionAndIHL]
and al, 0x0f ;get IHL(header length)
cmp al, 0x05 ;if IHL!= 5*4(20 bytes)
jnz .dump ;then dump it
 
ipr_p0:
mov al, [edx]
and al, 0x0f
cmp al, 0x05
jnz ipr_dump
cmp byte[ebx + IP_PACKET.TimeToLive], byte 0
je .dump ;if TTL==0 then dump it
 
cmp [edx+8], byte 0
jz ipr_dump
mov ax, word[ebx + IP_PACKET.FlagsAndFragmentOffset]
and ax, 0xFFBF ;get flags
cmp ax, 0 ;if some flags was set then we dump this packet
jnz .dump ;the flags should be used for fragmented packets
 
mov ax, [edx + 6]
and ax, 0xFFBF
cmp ax, 0
jnz ipr_dump
 
; Check the protocol, and call the appropriate handler
; Each handler will re-use or free the queue buffer as appropriate
mov al, [edx + 9]
cmp al , PROTOCOL_ICMP
jnz ipr_p1
pop eax
call icmp_rx
jmp ipr_exit
 
ipr_p1:
mov al, [ebx + IP_PACKET.Protocol]
 
cmp al , PROTOCOL_TCP
jnz ipr_p2
pop eax
jne .not_tcp
DEBUGF 1,"K : ip_rx - TCP packet\n"
mov eax, dword[buffer_number]
call tcp_rx
jmp ipr_exit
jmp .exit
 
ipr_p2:
.not_tcp:
cmp al , PROTOCOL_UDP
jnz ipr_dump
pop eax
jne .not_udp
DEBUGF 1,"K : ip_rx - UDP packet\n"
mov eax, dword[buffer_number]
call udp_rx
jmp ipr_exit
jmp .exit
 
ipr_dump:
.not_udp:
cmp al , PROTOCOL_ICMP
jne .dump ;protocol ain't supported
 
DEBUGF 1,"K : ip_rx - ICMP packet\n"
;GET_IHL ecx, ebx + IP_PACKET.VersionAndIHL ;get packet length in ecx
mov eax, dword[buffer_number]
stdcall icmp_rx,eax,ebx,ecx ;buffer_number,IPPacketBase,IPHeaderLength
jmp .exit
 
 
.dump:
; No protocol handler available, so
; silently dump the packet, freeing up the queue buffer
 
; inc dword [dumped_rx_count]
inc dword [dumped_rx_count]
 
pop eax
mov eax, dword[buffer_number]
call freeBuff
 
ipr_exit:
.exit:
ret
endp
 
 
 
;***************************************************************************
; Function
; icmp_rx
;
; Description
; ICMP protocol handler
; This is a kernel function, called by ip_rx
; edx contains the address of the buffer in use.
; This buffer must be reused or marked as empty afterwards
;
;***************************************************************************
icmp_rx:
cmp [edx + 20], byte 8 ; Is this an echo request? discard if not
jz icmp_echo
 
call freeBuff
jmp icmp_exit
 
icmp_echo:
push eax
mov [edx + 10], word 0 ; I think this was already done by IP rx
 
; swap the source and destination addresses
mov ecx, [edx + 16]
mov eax, [edx + 12]
mov [edx + 16], eax
mov [edx + 12], ecx
 
; recaluculate the IP header checksum
 
mov ebx, edx
mov [checkAdd1], ebx
mov [checkSize1], word 20
mov [checkAdd2], dword 0
mov [checkSize2], word 0
 
call checksum
mov ax, [checkResult]
mov [edx + 10], ah
mov [edx + 11], al ; ?? correct byte order?
 
mov [edx + 20], byte 0 ; change the request to a response
mov [edx + 22], word 0 ; clear ICMP checksum prior to re-calc
 
; Calculate the length of the ICMP data ( IP payload)
mov ah, [edx + 2]
mov al, [edx + 3]
sub ax, 20
 
mov [checkSize1], ax
mov ebx, edx
add ebx, 20
 
mov [checkAdd1], ebx
mov [checkAdd2], dword 0
mov [checkSize2], word 0
 
call checksum
 
mov ax, [checkResult]
mov [edx + 22], ah
mov [edx + 23], al
 
; Queue packet for transmission
 
pop ebx
mov eax, NET1OUT_QUEUE
call queue
 
icmp_exit:
ret