kolibrios/kernel/branches/net/network/icmp.inc
hidnplayr 602924a5b5 compile netcfg on unix
fixed bug in netcfg created in last revision
netcfg gives error msg when driver is not loaded
zeroconfig now works with latest version of libini
also fixed use of static and link-local ip in zeroconfig
initial IPv4 variables are now 0.0.0.0 instead of 255.255.255.255
created kernel function that shows number of active network devices 
fixed the use of temp mac variable in IPV4.inc (variable is now in stack)
rewrite of ARP code, needs full testing/debugging (new application needed: ARP manager)
port numbers are now in INET byte order, as is in posix standards

git-svn-id: svn://kolibrios.org@1196 a494cfbc-eb01-0410-851d-a64ba20cac60
2009-10-05 20:47:27 +00:00

467 lines
12 KiB
PHP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; ICMP.INC ;;
;; ;;
;; Part of the tcp/ip network stack for KolibriOS ;;
;; ;;
;; Based on the work of [Johnny_B] and [smb] ;;
;; ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
$Revision: 593 $
; ICMP types & codes
ICMP_ECHOREPLY equ 0 ; echo reply message
ICMP_UNREACH equ 3
ICMP_UNREACH_NET equ 0 ; bad net
ICMP_UNREACH_HOST equ 1 ; bad host
ICMP_UNREACH_PROTOCOL equ 2 ; bad protocol
ICMP_UNREACH_PORT equ 3 ; bad port
ICMP_UNREACH_NEEDFRAG equ 4 ; IP_DF caused drop
ICMP_UNREACH_SRCFAIL equ 5 ; src route failed
ICMP_UNREACH_NET_UNKNOWN equ 6 ; unknown net
ICMP_UNREACH_HOST_UNKNOWN equ 7 ; unknown host
ICMP_UNREACH_ISOLATED equ 8 ; src host isolated
ICMP_UNREACH_NET_PROHIB equ 9 ; prohibited access
ICMP_UNREACH_HOST_PROHIB equ 10 ; ditto
ICMP_UNREACH_TOSNET equ 11 ; bad tos for net
ICMP_UNREACH_TOSHOST equ 12 ; bad tos for host
ICMP_UNREACH_FILTER_PROHIB equ 13 ; admin prohib
ICMP_UNREACH_HOST_PRECEDENCE equ 14 ; host prec vio.
ICMP_UNREACH_PRECEDENCE_CUTOFF equ 15 ; prec cutoff
ICMP_SOURCEQUENCH equ 4 ; Packet lost, slow down
ICMP_REDIRECT equ 5 ; shorter route, codes:
ICMP_REDIRECT_NET equ 0 ; for network
ICMP_REDIRECT_HOST equ 1 ; for host
ICMP_REDIRECT_TOSNET equ 2 ; for tos and net
ICMP_REDIRECT_TOSHOST equ 3 ; for tos and host
ICMP_ALTHOSTADDR equ 6 ; alternate host address
ICMP_ECHO equ 8 ; echo service
ICMP_ROUTERADVERT equ 9 ; router advertisement
ICMP_ROUTERADVERT_NORMAL equ 0 ; normal advertisement
ICMP_ROUTERADVERT_NOROUTE_COMMON equ 16 ; selective routing
ICMP_ROUTERSOLICIT equ 10 ; router solicitation
ICMP_TIMXCEED equ 11 ; time exceeded, code:
ICMP_TIMXCEED_INTRANS equ 0 ; ttl==0 in transit
ICMP_TIMXCEED_REASS equ 1 ; ttl==0 in reass
ICMP_PARAMPROB equ 12 ; ip header bad
ICMP_PARAMPROB_ERRATPTR equ 0 ; error at param ptr
ICMP_PARAMPROB_OPTABSENT equ 1 ; req. opt. absent
ICMP_PARAMPROB_LENGTH equ 2 ; bad length
ICMP_TSTAMP equ 13 ; timestamp request
ICMP_TSTAMPREPLY equ 14 ; timestamp reply
ICMP_IREQ equ 15 ; information request
ICMP_IREQREPLY equ 16 ; information reply
ICMP_MASKREQ equ 17 ; address mask request
ICMP_MASKREPLY equ 18 ; address mask reply
ICMP_TRACEROUTE equ 30 ; traceroute
ICMP_DATACONVERR equ 31 ; data conversion error
ICMP_MOBILE_REDIRECT equ 32 ; mobile host redirect
ICMP_IPV6_WHEREAREYOU equ 33 ; IPv6 where-are-you
ICMP_IPV6_IAMHERE equ 34 ; IPv6 i-am-here
ICMP_MOBILE_REGREQUEST equ 35 ; mobile registration req
ICMP_MOBILE_REGREPLY equ 36 ; mobile registreation reply
ICMP_SKIP equ 39 ; SKIP
ICMP_PHOTURIS equ 40 ; Photuris
ICMP_PHOTURIS_UNKNOWN_INDEX equ 1 ; unknown sec index
ICMP_PHOTURIS_AUTH_FAILED equ 2 ; auth failed
ICMP_PHOTURIS_DECRYPT_FAILED equ 3 ; decrypt failed
struct ICMP_Packet
.Type db ?
.Code db ?
.Checksum dw ?
.Identifier dw ?
.SequenceNumber dw ?
.Data:
ends
align 4
uglobal
ICMP_PACKETS_TX rd MAX_IP
ICMP_PACKETS_RX rd MAX_IP
endg
;-----------------------------------------------------------------
;
; ICMP_init
;
; This function resets all ICMP variables
;
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
ICMP_init:
xor eax, eax
mov edi, ICMP_PACKETS_TX
mov ecx, 2*MAX_IP
rep stosd
ret
;--------------------------------
;
; ICMP_Handler:
;
; Called by IP_handler,
; this procedure will send reply's to ICMP echo's etc ;;; TODO: update this to work with fragmented packets too!
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; ICMP Packet size in ecx
; pointer to ICMP Packet data in edx
; OUT: /
;
;--------------------------------
align 4
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?
jne .check_sockets
mov byte [edx + ICMP_Packet.Type], ICMP_ECHOREPLY ; Change Packet type to reply
mov word [edx + ICMP_Packet.Checksum], 0 ; Set checksum to 0, needed to calculate new checksum
call ETH_struc2dev
cmp edi,-1
je .dump
inc [ICMP_PACKETS_RX+4*edi]
inc [ICMP_PACKETS_TX+4*edi]
; exchange dest and source address in IP header
; exchange dest and source MAC in ETH header
mov esi, [esp]
mov eax, dword [esi + ETH_FRAME.DstMAC]
mov ecx, dword [esi + ETH_FRAME.SrcMAC]
mov dword [esi + ETH_FRAME.SrcMAC], eax
mov dword [esi + ETH_FRAME.DstMAC], ecx
mov ax, word [esi + ETH_FRAME.DstMAC + 4]
mov cx, word [esi + ETH_FRAME.SrcMAC + 4]
mov word [esi + ETH_FRAME.SrcMAC + 4], ax
mov word [esi + ETH_FRAME.DstMAC + 4], cx
mov eax, dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress]
mov ecx, dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress]
mov dword [esi + ETH_FRAME.Data + IPv4_Packet.DestinationAddress], eax
mov dword [esi + ETH_FRAME.Data + IPv4_Packet.SourceAddress], ecx
; Recalculate ip header checksum
; mov esi, [esp]
add esi, ETH_FRAME.Data ; Point esi to start of IP Packet
movzx eax, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
and eax, 0x0000000F ;
shl eax, 2 ;
push ebx edx esi
stdcall checksum_jb, esi, eax ; calculate the checksum
pop esi edx ebx
xchg al, ah ; convert to intel byte order
; mov esi, [esp]
mov word [esi + IPv4_Packet.HeaderChecksum], ax ; Store it in the IP Packet header
; Recalculate ICMP CheckSum
; mov esi, [esp] ; Find length of IP Packet
movzx eax, word[esi + IPv4_Packet.TotalLength] ;
xchg ah , al ;
movzx edi, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
and edi, 0x0000000F ;
shl edi, 2 ;
sub ax , di ; Now we know the length of ICMP data in eax
push ebx edx
stdcall checksum_jb,edx,eax ; Calculate the checksum of icmp data
pop edx ebx
xchg al, ah ; Convert to intel byte order
mov word [edx + ICMP_Packet.Checksum], ax
jmp ETH_Sender ; Send the reply
.check_sockets:
; TODO: validate the header & checksum. Discard buffer if error
; Look for an open ICMP socket
mov esi, net_sockets
.try_more:
mov ax , [edx + ICMP_Packet.Identifier]
.next_socket:
mov esi, [esi + SOCKET.NextPtr]
or esi, esi
jz .dump
cmp [esi + SOCKET.Type], IP_PROTO_ICMP
jne .next_socket
cmp [esi + SOCKET.LocalPort], ax
jne .next_socket
cmp [esi + SOCKET.rxDataCount],0 ; get # of bytes already in buffer
jnz .dump ; only one packet at a time may be in the buffer!
cmp ecx, SOCKETBUFFSIZE - SOCKETHEADERSIZE; TODO: fix this problem !
jg .dump
call IPv4_dest_to_dev
cmp edi,-1
je .dump
inc [ICMP_PACKETS_RX+4*edi]
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
lea ebx, [esi + SOCKET.lock]
call wait_mutex
; Now, copy data to socket. We have socket address in esi.
; We have ICMP Packet in edx
; number of bytes in ecx
; note: we do not strip the header!
DEBUGF 1,"bytes: %u\n", ecx
mov [esi + SOCKET.rxDataCount], ecx
lea edi, [esi + SOCKETHEADERSIZE]
push esi
push ecx
mov esi, edx
shr ecx, 2
rep movsd ; copy the data across
pop ecx
and ecx, 3
rep movsb
pop esi
DEBUGF 1,"ICMP socket updated\n"
mov [esi + SOCKET.lock], 0
; flag an event to the application
mov eax, [esi + SOCKET.PID] ; get socket owner PID
mov ecx, 1
mov esi, TASK_DATA + TASKDATA.pid
.next_pid:
cmp [esi], eax
je .found_pid
inc ecx
add esi, 0x20
cmp ecx, [TASK_COUNT]
jbe .next_pid
jmp .dump
.found_pid:
shl ecx, 8
or [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK ; stack event
mov [check_idle_semaphore], 200
.dump:
DEBUGF 1,"ICMP_Handler - dumping\n"
call kernel_free
add esp, 8 ; pop (balance stack)
ret
;--------------------------------
;
; ICMP_Handler_fragments:
;
; Called by IP_handler,
; this procedure will send reply's to ICMP echo's etc
;
; IN: Pointer to buffer in [esp]
; size of buffer in [esp+4]
; pointer to device struct in ebx
; ICMP Packet size in ecx
; pointer to ICMP Packet data in edx
; OUT: /
;
;--------------------------------
align 4
ICMP_handler_fragments: ; works only on pure ethernet right now !
DEBUGF 1,"ICMP_Handler_fragments - start\n"
cmp ecx, 65500
jg .dump
cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request? discard if not
jne .dump
mov esi, [esp]
sub ecx, ICMP_Packet.Data
mov eax, [esi + IPv4_Packet.SourceAddress]
mov ebx, [esi + IPv4_Packet.DestinationAddress]
push word [esi + IPv4_Packet.Identification]
mov di , [edx + ICMP_Packet.Identifier]
shl edi, 16
mov di , [edx + ICMP_Packet.SequenceNumber]
mov esi, edx
add esi, ICMP_Packet.Data
pop dx
shl edx, 16
mov dx , ICMP_ECHOREPLY shl 8 + 0 ; Type + Code
call ICMP_create_packet
.dump:
DEBUGF 1,"ICMP_Handler_fragments - end\n"
call kernel_free
add esp, 8 ; pop (balance stack)
ret
;-----------------------------------------------------------------
;
; Note: ICMP only works on top of IP protocol :)
;
; inputs:
;
; eax = dest ip
; ebx = source ip
; ecx = data length
; dh = type
; dl = code
; high 16 bits of edx = fragment id (for IP header)
; esi = data offset
; edi = identifier shl 16 + sequence number
;
;-----------------------------------------------------------------
align 4
ICMP_create_packet:
DEBUGF 1,"Create ICMP Packet\n"
push esi edi edx
add ecx, ICMP_Packet.Data
mov di , IP_PROTO_ICMP
shr edx, 16
call IPv4_create_packet
cmp edi, -1
je .exit
DEBUGF 1,"full icmp packet size: %u\n", ebx
pop eax
mov word [edi + ICMP_Packet.Type], ax ; Write both type and code bytes at once
pop eax
mov [edi + ICMP_Packet.SequenceNumber], ax
shr eax, 16
mov [edi + ICMP_Packet.Identifier], ax
mov [edi + ICMP_Packet.Checksum], 0
stdcall checksum_jb, edi , ecx
xchg al, ah
mov [edi + ICMP_Packet.Checksum], ax
pop esi
sub ecx, ICMP_Packet.Data
add edi, ICMP_Packet.Data
push cx
shr cx , 2
rep movsd
pop cx
and cx , 3
rep movsb
sub edi, ebx ;; TODO: find a better way to remember start of packet
xchg ebx, edx
mov ecx, [ebx + ETH_DEVICE.transmit]
push edx edi ecx
DEBUGF 1,"Sending ICMP Packet\n"
ret ; Send the packet (create_packet routine outputs pointer to routine to send packet in eax)
.exit:
DEBUGF 1,"Creating ICMP Packet failed\n"
add esp, 3*4
ret
;---------------------------------------------------------------------------
;
; ICMP_API
;
; This function is called by system function 75
;
; IN: subfunction number in bl
; device number in bh
; ecx, edx, .. depends on subfunction
;
; OUT:
;
;---------------------------------------------------------------------------
align 4
ICMP_API:
movzx eax, bh
shl eax, 2
test bl, bl
jz .packets_tx ; 0
dec bl
jz .packets_rx ; 1
.error:
mov eax, -1
ret
.packets_tx:
add eax, ICMP_PACKETS_TX
mov eax, [eax]
ret
.packets_rx:
add eax, ICMP_PACKETS_RX
mov eax, [eax]
ret