forked from KolibriOS/kolibrios
8a7ebf6b32
added pci ids of dec21x4x cards to netcfg bugfixes in dex21x4x driver, pcnet32 driver, rtl8139 driver and sis900 driver new network program (ICMP) to ping computers, uses new RAW socket code (experimental) git-svn-id: svn://kolibrios.org@1541 a494cfbc-eb01-0410-851d-a64ba20cac60
422 lines
11 KiB
PHP
422 lines
11 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2010. 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$
|
|
|
|
; 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
|
|
;
|
|
;-----------------------------------------------------------------
|
|
|
|
macro ICMP_init {
|
|
|
|
xor eax, eax
|
|
mov edi, ICMP_PACKETS_TX
|
|
mov ecx, 2*MAX_IP
|
|
rep stosd
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; ICMP_input:
|
|
;
|
|
; This procedure will send reply's to ICMP echo's
|
|
; and insert packets into sockets when needed
|
|
;
|
|
; IN: Pointer to buffer in [esp]
|
|
; size of buffer in [esp+4]
|
|
; ebx = pointer to device struct
|
|
; ecx = ICMP Packet size
|
|
; edx = ptr to ICMP Packet data
|
|
; esi = ipv4 source address
|
|
; edi = ipv4 dest address
|
|
; OUT: /
|
|
;
|
|
;-----------------------------------------------------------------
|
|
align 4
|
|
ICMP_input:
|
|
|
|
;;; TODO: check checksum!
|
|
|
|
DEBUGF 1,"ICMP_input - start\n"
|
|
cmp byte [edx + ICMP_Packet.Type], ICMP_ECHO ; Is this an echo request?
|
|
jne .check_sockets
|
|
|
|
DEBUGF 1,"ICMP_input - echo request\n"
|
|
|
|
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 NET_ptr_to_num
|
|
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
|
|
add esi, ETH_FRAME.Data ; Point esi to start of IP Packet
|
|
movzx ecx, byte [esi + IPv4_Packet.VersionAndIHL] ; Calculate IP Header length by using IHL field
|
|
and ecx, 0x0000000F ;
|
|
shl cx , 2
|
|
push ebx edx ecx esi
|
|
xor edx, edx
|
|
call checksum_1
|
|
call checksum_2
|
|
pop esi
|
|
mov word [esi + IPv4_Packet.HeaderChecksum], dx ; Store it in the IP Packet header
|
|
|
|
; Recalculate ICMP CheckSum
|
|
movzx eax, word[esi + IPv4_Packet.TotalLength] ; Find length of IP Packet
|
|
xchg ah , al ;
|
|
sub eax, [esp] ; Now we know the length of ICMP data in eax
|
|
mov ecx, eax
|
|
mov esi, [esp + 4]
|
|
xor edx, edx
|
|
call checksum_1
|
|
call checksum_2
|
|
mov ax , dx
|
|
pop ecx edx ebx
|
|
mov word [edx + ICMP_Packet.Checksum], ax
|
|
|
|
call [ebx + NET_DEVICE.transmit]
|
|
ret
|
|
|
|
|
|
|
|
|
|
.check_sockets:
|
|
; Look for an open ICMP socket
|
|
; esi = sender ip
|
|
|
|
mov ebx, net_sockets
|
|
.try_more:
|
|
; mov ax , [edx + ICMP_Packet.Identifier]
|
|
.next_socket:
|
|
mov ebx, [ebx + SOCKET.NextPtr]
|
|
or ebx, ebx
|
|
jz .dump
|
|
|
|
cmp [ebx + SOCKET.Domain], AF_INET4
|
|
jne .next_socket
|
|
|
|
cmp [ebx + SOCKET.Type], SOCK_RAW
|
|
jne .next_socket
|
|
|
|
cmp [ebx + SOCKET.Protocol], IP_PROTO_ICMP
|
|
jne .next_socket
|
|
|
|
cmp [ebx + IP_SOCKET.RemoteIP], esi
|
|
jne .next_socket
|
|
|
|
; cmp [esi + ICMP_SOCKET.Identifier], ax
|
|
; jne .next_socket
|
|
|
|
; call IPv4_dest_to_dev
|
|
; cmp edi,-1
|
|
; je .dump
|
|
; inc [ICMP_PACKETS_RX+edi]
|
|
|
|
DEBUGF 1,"Found valid ICMP packet for socket %x\n", ebx
|
|
|
|
mov eax, ebx
|
|
add ebx, SOCKET.lock
|
|
call wait_mutex
|
|
|
|
mov esi, edx
|
|
jmp SOCKET_input
|
|
|
|
|
|
.dump:
|
|
DEBUGF 1,"ICMP_Handler - dumping\n"
|
|
|
|
call kernel_free
|
|
add esp, 4 ; pop (balance stack)
|
|
|
|
ret
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; ICMP_output
|
|
;
|
|
; IN: 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_output:
|
|
|
|
DEBUGF 1,"Creating ICMP Packet\n"
|
|
|
|
push esi edi edx
|
|
|
|
mov ebx, [eax + IP_SOCKET.LocalIP]
|
|
mov eax, [eax + IP_SOCKET.RemoteIP]
|
|
add ecx, ICMP_Packet.Data
|
|
mov di , IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
|
shr edx, 16
|
|
|
|
call IPv4_output
|
|
jz .exit
|
|
|
|
DEBUGF 1,"full icmp packet size: %u\n", edx
|
|
|
|
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
|
|
|
|
push eax ebx ecx edx
|
|
mov esi, edi
|
|
xor edx, edx
|
|
call checksum_1
|
|
call checksum_2
|
|
mov [edi + ICMP_Packet.Checksum], dx
|
|
pop edx ecx ebx eax 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, edx ;;; TODO: find a better way to remember start of packet
|
|
push edx edi
|
|
DEBUGF 1,"Sending ICMP Packet\n"
|
|
call [ebx + NET_DEVICE.transmit]
|
|
ret
|
|
.exit:
|
|
DEBUGF 1,"Creating ICMP Packet failed\n"
|
|
add esp, 3*4
|
|
ret
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; ICMP_output
|
|
;
|
|
; IN: eax = socket ptr
|
|
; ecx = data length
|
|
; esi = data offset
|
|
;
|
|
;-----------------------------------------------------------------
|
|
align 4
|
|
ICMP_output_raw:
|
|
|
|
DEBUGF 1,"Creating ICMP Packet for socket %x, data ptr=%x\n", eax, edx
|
|
|
|
push edx
|
|
|
|
mov di, IP_PROTO_ICMP SHL 8 + 128 ; TTL
|
|
shr edx, 16
|
|
mov ebx, [eax + IP_SOCKET.LocalIP]
|
|
mov eax, [eax + IP_SOCKET.RemoteIP]
|
|
call IPv4_output
|
|
jz .exit
|
|
|
|
pop esi
|
|
push edx
|
|
push eax
|
|
|
|
push edi ecx
|
|
DEBUGF 1,"copying %u bytes from %x to %x\n", ecx, esi, edi
|
|
rep movsb
|
|
pop ecx edi
|
|
|
|
mov [edi + ICMP_Packet.Checksum], 0
|
|
|
|
mov esi, edi
|
|
xor edx, edx
|
|
call checksum_1
|
|
call checksum_2
|
|
mov [edi + ICMP_Packet.Checksum], dx
|
|
|
|
DEBUGF 1,"Sending ICMP Packet\n"
|
|
call [ebx + NET_DEVICE.transmit]
|
|
ret
|
|
.exit:
|
|
DEBUGF 1,"Creating ICMP Packet failed\n"
|
|
add esp, 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
|