forked from KolibriOS/kolibrios
602924a5b5
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
467 lines
12 KiB
PHP
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
|