2009-09-17 13:55:38 +02:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; ;;
|
2010-07-12 01:13:12 +02:00
|
|
|
;; Copyright (C) KolibriOS team 2004-2010. All rights reserved. ;;
|
2009-09-17 13:55:38 +02:00
|
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
|
|
;; ;;
|
|
|
|
;; UDP.INC ;;
|
|
|
|
;; ;;
|
|
|
|
;; Part of the tcp/ip network stack for KolibriOS ;;
|
|
|
|
;; ;;
|
|
|
|
;; Written by hidnplayr@kolibrios.org ;;
|
|
|
|
;; ;;
|
|
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
|
|
;; Version 2, June 1991 ;;
|
|
|
|
;; ;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2009-10-12 16:39:59 +02:00
|
|
|
$Revision$
|
2009-09-17 13:55:38 +02:00
|
|
|
|
|
|
|
|
|
|
|
struct UDP_Packet
|
|
|
|
.SourcePort dw ?
|
|
|
|
.DestinationPort dw ?
|
|
|
|
.Length dw ? ; Length of (UDP Header + Data)
|
|
|
|
.Checksum dw ?
|
|
|
|
.Data:
|
|
|
|
|
|
|
|
ends
|
|
|
|
|
|
|
|
|
|
|
|
align 4
|
|
|
|
uglobal
|
|
|
|
UDP_PACKETS_TX rd MAX_IP
|
|
|
|
UDP_PACKETS_RX rd MAX_IP
|
|
|
|
endg
|
|
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
;
|
|
|
|
; UDP_init
|
|
|
|
;
|
|
|
|
; This function resets all UDP variables
|
|
|
|
;
|
|
|
|
; IN: /
|
|
|
|
; OUT: /
|
|
|
|
;
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
align 4
|
|
|
|
UDP_init:
|
|
|
|
|
|
|
|
xor eax, eax
|
|
|
|
mov edi, UDP_PACKETS_TX
|
|
|
|
mov ecx, 2*MAX_IP
|
|
|
|
rep stosd
|
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
;
|
2010-07-12 01:13:12 +02:00
|
|
|
; UDP_input:
|
2009-09-17 13:55:38 +02:00
|
|
|
;
|
2010-07-12 01:13:12 +02:00
|
|
|
; Called by IPv4_input,
|
2009-09-17 13:55:38 +02:00
|
|
|
; this procedure will inject the udp data diagrams in the application sockets.
|
|
|
|
;
|
|
|
|
; IN: Pointer to buffer in [esp]
|
|
|
|
; size of buffer in [esp+4]
|
|
|
|
; pointer to device struct in ebx
|
|
|
|
; UDP Packet size in ecx
|
2010-06-07 11:37:13 +02:00
|
|
|
; pointer to UDP Packet in edx
|
2010-06-07 16:17:36 +02:00
|
|
|
;
|
|
|
|
; esi = ipv4 source address
|
|
|
|
; edi = ipv4 dest address
|
|
|
|
;
|
2009-09-17 13:55:38 +02:00
|
|
|
; OUT: /
|
|
|
|
;
|
|
|
|
;-----------------------------------------------------------------
|
2009-10-12 16:39:59 +02:00
|
|
|
align 4
|
2010-07-12 01:13:12 +02:00
|
|
|
UDP_input:
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
DEBUGF 1,"UDP_input, size:%u\n", ecx
|
2010-05-28 22:47:32 +02:00
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
; First validate, checksum:
|
2010-06-07 16:17:36 +02:00
|
|
|
cmp [edx + UDP_Packet.Checksum], 0
|
|
|
|
jz .no_checksum
|
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
xchg edi, esi ; save ipv4 source address to edi so we can use it later
|
2009-11-06 21:45:08 +01:00
|
|
|
|
2010-06-07 14:57:52 +02:00
|
|
|
push edx
|
2010-07-12 01:13:12 +02:00
|
|
|
push esi edi
|
2009-11-06 21:45:08 +01:00
|
|
|
mov esi, edx
|
2010-07-12 01:13:12 +02:00
|
|
|
call UDP_checksum ; this destroys edx, ecx and esi (but not edi...)
|
2010-06-07 14:57:52 +02:00
|
|
|
pop edx
|
2010-05-28 22:47:32 +02:00
|
|
|
|
2010-06-07 16:17:36 +02:00
|
|
|
cmp [edx + UDP_Packet.Checksum], 0
|
|
|
|
jnz .checksum_mismatch
|
2010-05-28 22:47:32 +02:00
|
|
|
|
|
|
|
.no_checksum:
|
|
|
|
DEBUGF 1,"UDP Checksum is correct\n"
|
2009-09-17 13:55:38 +02:00
|
|
|
|
|
|
|
; Look for a socket where
|
|
|
|
; IP Packet UDP Destination Port = local Port
|
|
|
|
; IP Packet SA = Remote IP
|
|
|
|
|
2009-10-12 16:39:59 +02:00
|
|
|
mov eax, net_sockets
|
2009-09-17 13:55:38 +02:00
|
|
|
.try_more:
|
2010-05-28 22:47:32 +02:00
|
|
|
mov si , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
|
2010-07-12 01:13:12 +02:00
|
|
|
rol si , 8
|
2009-09-17 13:55:38 +02:00
|
|
|
.next_socket:
|
2010-07-12 01:13:12 +02:00
|
|
|
mov eax, [eax + SOCKET.NextPtr]
|
2009-10-12 16:39:59 +02:00
|
|
|
or eax, eax
|
2009-09-17 13:55:38 +02:00
|
|
|
jz .dump
|
2010-07-12 01:13:12 +02:00
|
|
|
cmp [eax + SOCKET.Domain], AF_INET4
|
2009-09-17 13:55:38 +02:00
|
|
|
jne .next_socket
|
2010-07-12 01:13:12 +02:00
|
|
|
cmp [eax + SOCKET.Type], IP_PROTO_UDP
|
2009-10-12 16:39:59 +02:00
|
|
|
jne .next_socket
|
2010-07-12 01:13:12 +02:00
|
|
|
cmp [eax + UDP_SOCKET.LocalPort], si
|
2009-09-17 13:55:38 +02:00
|
|
|
jne .next_socket
|
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
DEBUGF 1,"using socket: %x\n", eax
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
;;; TODO: when packet is processed, check more sockets!
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
cmp [eax + IP_SOCKET.RemoteIP], 0xffffffff
|
|
|
|
je @f
|
|
|
|
cmp [eax + IP_SOCKET.RemoteIP], edi ; edi is the packets source address
|
|
|
|
jne .try_more
|
|
|
|
@@:
|
2009-10-12 20:14:14 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
cmp [eax + UDP_SOCKET.firstpacket], 0
|
2009-12-27 22:05:25 +01:00
|
|
|
jz .updateport
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-05-28 22:47:32 +02:00
|
|
|
mov si, [edx + UDP_Packet.SourcePort]
|
2010-07-12 01:13:12 +02:00
|
|
|
rol si, 8
|
|
|
|
cmp [eax + UDP_SOCKET.RemotePort], si
|
2009-10-12 16:39:59 +02:00
|
|
|
jne .dump
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-05-28 22:47:32 +02:00
|
|
|
push ebx
|
2010-07-12 01:13:12 +02:00
|
|
|
lea ebx, [eax + SOCKET.lock]
|
2009-12-28 22:02:54 +01:00
|
|
|
call wait_mutex
|
2010-05-28 22:47:32 +02:00
|
|
|
pop ebx
|
2009-12-28 22:02:54 +01:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
.updatesock:
|
|
|
|
inc [UDP_PACKETS_RX]
|
2010-05-28 22:47:32 +02:00
|
|
|
DEBUGF 1,"Found valid UDP packet for socket %x\n", eax
|
2009-10-12 16:39:59 +02:00
|
|
|
lea esi, [edx + UDP_Packet.Data]
|
|
|
|
movzx ecx, [edx + UDP_Packet.Length]
|
|
|
|
rol cx , 8
|
|
|
|
sub cx , UDP_Packet.Data
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
jmp SOCKET_input
|
2009-11-06 21:45:08 +01:00
|
|
|
|
2009-12-27 22:05:25 +01:00
|
|
|
.updateport:
|
2010-05-28 22:47:32 +02:00
|
|
|
push ebx
|
2010-07-12 01:13:12 +02:00
|
|
|
lea ebx, [eax + SOCKET.lock]
|
2009-12-28 22:02:54 +01:00
|
|
|
call wait_mutex
|
2010-05-28 22:47:32 +02:00
|
|
|
pop ebx
|
2009-12-28 22:02:54 +01:00
|
|
|
|
2010-05-28 22:47:32 +02:00
|
|
|
mov si, [edx + UDP_Packet.SourcePort]
|
2010-07-12 01:13:12 +02:00
|
|
|
rol si, 8
|
|
|
|
DEBUGF 1,"Changing remote port to: %u\n", si
|
|
|
|
mov [eax + UDP_SOCKET.RemotePort], si
|
|
|
|
inc [eax + UDP_SOCKET.firstpacket]
|
2009-12-27 22:05:25 +01:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
jmp .updatesock
|
2009-12-27 22:05:25 +01:00
|
|
|
|
2010-06-07 14:57:52 +02:00
|
|
|
|
2010-05-28 22:47:32 +02:00
|
|
|
.checksum_mismatch:
|
|
|
|
|
|
|
|
DEBUGF 2,"UDP_Handler - checksum mismatch\n"
|
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
; mov esi, edx
|
|
|
|
; @@: ;
|
|
|
|
; lodsb ;
|
|
|
|
; DEBUGF 2,"%x ", eax:2 ;
|
|
|
|
; loop @r ;
|
2010-05-28 22:47:32 +02:00
|
|
|
|
2009-10-12 16:39:59 +02:00
|
|
|
.dump:
|
2009-09-17 13:55:38 +02:00
|
|
|
call kernel_free
|
|
|
|
add esp, 4 ; pop (balance stack)
|
2010-05-28 22:47:32 +02:00
|
|
|
DEBUGF 2,"UDP_Handler - dumping\n"
|
2009-09-17 13:55:38 +02:00
|
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
;
|
2010-07-12 01:13:12 +02:00
|
|
|
; UDP_output
|
2009-09-17 13:55:38 +02:00
|
|
|
;
|
2009-11-06 21:45:08 +01:00
|
|
|
; IN: eax = socket pointer
|
|
|
|
; ecx = number of bytes to send
|
|
|
|
; esi = pointer to data
|
2009-09-17 13:55:38 +02:00
|
|
|
;
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
|
2009-11-06 21:45:08 +01:00
|
|
|
align 4
|
2010-07-12 01:13:12 +02:00
|
|
|
UDP_output:
|
2009-11-06 21:45:08 +01:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
DEBUGF 1,"UDP_output: socket:%x, bytes: %u, data ptr: %x\n", eax, ecx, esi
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
mov dx, [eax + UDP_SOCKET.RemotePort]
|
|
|
|
DEBUGF 1,"remote port: %u\n", dx
|
|
|
|
rol dx, 8
|
|
|
|
rol edx, 16
|
|
|
|
mov dx, [eax + UDP_SOCKET.LocalPort]
|
|
|
|
DEBUGF 1,"local port: %u\n", dx
|
|
|
|
rol dx, 8
|
|
|
|
|
|
|
|
|
|
|
|
mov ebx, [eax + IP_SOCKET.LocalIP]
|
|
|
|
mov eax, [eax + IP_SOCKET.RemoteIP]
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2009-11-06 21:45:08 +01:00
|
|
|
mov di , IP_PROTO_UDP
|
2010-06-07 11:37:13 +02:00
|
|
|
sub esp, 8 ; Data ptr and data size will be placed here
|
2009-09-17 13:55:38 +02:00
|
|
|
add ecx, UDP_Packet.Data
|
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
;;; TODO: fragment id
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2009-11-06 21:45:08 +01:00
|
|
|
push edx esi
|
2010-07-12 01:13:12 +02:00
|
|
|
call IPv4_create_packet
|
|
|
|
jz .fail
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
mov [esp + 8], eax ; pointer to buffer start
|
|
|
|
mov [esp + 8 + 4], edx ; buffer size
|
2009-11-06 21:45:08 +01:00
|
|
|
|
|
|
|
rol cx, 8
|
|
|
|
mov [edi + UDP_Packet.Length], cx
|
|
|
|
ror cx, 8
|
2009-09-17 13:55:38 +02:00
|
|
|
|
|
|
|
pop esi
|
2009-11-06 21:45:08 +01:00
|
|
|
push edi ecx
|
|
|
|
sub ecx, UDP_Packet.Data
|
2009-09-17 13:55:38 +02:00
|
|
|
add edi, UDP_Packet.Data
|
|
|
|
shr ecx, 2
|
|
|
|
rep movsd
|
2009-11-06 21:45:08 +01:00
|
|
|
mov ecx, [esp]
|
2009-11-07 17:13:47 +01:00
|
|
|
and ecx, 3
|
2009-09-17 13:55:38 +02:00
|
|
|
rep movsb
|
2009-11-06 21:45:08 +01:00
|
|
|
pop ecx edi
|
|
|
|
|
2010-07-12 01:13:12 +02:00
|
|
|
pop dword [edi + UDP_Packet.SourcePort]
|
2009-11-06 21:45:08 +01:00
|
|
|
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
; Checksum
|
2009-11-06 21:45:08 +01:00
|
|
|
mov esi, edi
|
2010-07-12 01:13:12 +02:00
|
|
|
pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options..
|
2009-11-08 19:00:01 +01:00
|
|
|
pushd [edi-8] ; source address
|
2010-06-07 11:37:13 +02:00
|
|
|
call UDP_checksum
|
2009-09-17 13:55:38 +02:00
|
|
|
|
2009-10-12 16:39:59 +02:00
|
|
|
inc [UDP_PACKETS_TX]
|
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx
|
2010-07-12 01:13:12 +02:00
|
|
|
|
2010-07-15 20:54:19 +02:00
|
|
|
call [ebx + NET_DEVICE.transmit]
|
|
|
|
ret
|
2009-10-12 16:39:59 +02:00
|
|
|
.fail:
|
2010-06-07 18:10:07 +02:00
|
|
|
add esp, 8+8
|
2009-10-12 16:39:59 +02:00
|
|
|
ret
|
|
|
|
|
2009-09-17 13:55:38 +02:00
|
|
|
|
|
|
|
|
2009-11-06 21:45:08 +01:00
|
|
|
|
2010-06-07 11:37:13 +02:00
|
|
|
;-----------------------------------------------------------------
|
|
|
|
;
|
2010-07-12 01:13:12 +02:00
|
|
|
; UDP_checksum
|
2010-06-07 11:37:13 +02:00
|
|
|
;
|
|
|
|
; This is the fast procedure to create or check a UDP header
|
|
|
|
; - To create a new checksum, the checksum field must be set to 0 before computation
|
|
|
|
; - To check an existing checksum, leave the checksum as is,
|
|
|
|
; and it will be 0 after this procedure, if it was correct
|
|
|
|
;
|
|
|
|
; IN: push source ip
|
|
|
|
; push dest ip
|
|
|
|
; esi = packet ptr
|
|
|
|
;
|
|
|
|
; OUT: checksum is filled in in packet! (but also in dx)
|
|
|
|
;
|
|
|
|
;-----------------------------------------------------------------
|
|
|
|
|
|
|
|
align 4
|
|
|
|
UDP_checksum:
|
|
|
|
|
|
|
|
; Pseudoheader
|
|
|
|
mov edx, IP_PROTO_UDP ; NO shl 8 here ! (it took me ages to figure this one out)
|
|
|
|
|
|
|
|
add dl, [esp+1+4]
|
|
|
|
adc dh, [esp+0+4]
|
|
|
|
adc dl, [esp+3+4]
|
|
|
|
adc dh, [esp+2+4]
|
|
|
|
|
|
|
|
adc dl, [esp+1+8]
|
|
|
|
adc dh, [esp+0+8]
|
|
|
|
adc dl, [esp+3+8]
|
|
|
|
adc dh, [esp+2+8]
|
|
|
|
|
2010-06-07 14:57:52 +02:00
|
|
|
|
|
|
|
adc dl, cl ; byte[esi+UDP_Packet.Length+1]
|
|
|
|
adc dh, ch ; byte[esi+UDP_Packet.Length+0]
|
2010-06-07 11:37:13 +02:00
|
|
|
|
|
|
|
; Done with pseudoheader, now do real header
|
|
|
|
adc dl, byte[esi+UDP_Packet.SourcePort+1]
|
|
|
|
adc dh, byte[esi+UDP_Packet.SourcePort+0]
|
|
|
|
|
|
|
|
adc dl, byte[esi+UDP_Packet.DestinationPort+1]
|
|
|
|
adc dh, byte[esi+UDP_Packet.DestinationPort+0]
|
|
|
|
|
|
|
|
adc dl, byte[esi+UDP_Packet.Length+1]
|
|
|
|
adc dh, byte[esi+UDP_Packet.Length+0]
|
|
|
|
|
|
|
|
adc edx, 0
|
|
|
|
|
|
|
|
; Done with header, now do data
|
|
|
|
push esi
|
|
|
|
movzx ecx, [esi+UDP_Packet.Length]
|
|
|
|
rol cx , 8
|
|
|
|
sub cx , UDP_Packet.Data
|
|
|
|
add esi, UDP_Packet.Data
|
|
|
|
|
|
|
|
call checksum_1
|
|
|
|
call checksum_2
|
|
|
|
pop esi
|
|
|
|
|
|
|
|
neg [esi+UDP_Packet.Checksum] ; zero will stay zero so we just get the checksum
|
|
|
|
add [esi+UDP_Packet.Checksum], dx ; , else we will get (new checksum - old checksum) in the end, wich should be 0 :)
|
|
|
|
|
|
|
|
ret 8
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-09-17 13:55:38 +02:00
|
|
|
;---------------------------------------------------------------------------
|
|
|
|
;
|
|
|
|
; UDP_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
|
|
|
|
UDP_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, UDP_PACKETS_TX
|
|
|
|
mov eax, [eax]
|
|
|
|
ret
|
|
|
|
|
|
|
|
.packets_rx:
|
|
|
|
add eax, UDP_PACKETS_RX
|
|
|
|
mov eax, [eax]
|
|
|
|
ret
|