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
294 lines
7.3 KiB
PHP
294 lines
7.3 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
|
|
;; 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 ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision: 983 $
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; UDP_Handler:
|
|
;
|
|
; Called by IPv4_handler,
|
|
; 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
|
|
; pointer to UDP Packet data in edx
|
|
; OUT: /
|
|
;
|
|
;-----------------------------------------------------------------
|
|
|
|
UDP_handler:
|
|
|
|
DEBUGF 1,"UDP_Handler\n"
|
|
; TODO: First validate the header & checksum. Discard buffer if error
|
|
|
|
; Look for a socket where
|
|
; IP Packet UDP Destination Port = local Port
|
|
; IP Packet SA = Remote IP
|
|
|
|
mov esi, net_sockets
|
|
.try_more:
|
|
mov ax , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
|
|
rol ax , 8
|
|
.next_socket:
|
|
mov esi, [esi + SOCKET.NextPtr]
|
|
or esi, esi
|
|
jz .dump
|
|
cmp [esi + SOCKET.Type], IP_PROTO_UDP
|
|
jne .next_socket
|
|
cmp [esi + SOCKET.LocalPort], ax
|
|
jne .next_socket
|
|
|
|
; For dhcp, we must allow any remote server to respond.
|
|
; I will accept the first incoming response to be the one
|
|
; I bind to, if the socket is opened with a destination IP address of
|
|
; 255.255.255.255
|
|
cmp [esi + SOCKET.RemoteIP], 0xffffffff
|
|
je @f
|
|
|
|
mov eax, [esp]
|
|
mov eax, [eax + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet
|
|
cmp [esi + SOCKET.RemoteIP], eax
|
|
jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
|
|
|
|
@@:
|
|
DEBUGF 1,"Found valid UDP packet for socket %x\n", esi
|
|
|
|
; sub ecx, UDP_Packet.Data ; get # of bytes in ecx
|
|
; mov eax, ecx
|
|
|
|
movzx ecx, [edx + UDP_Packet.Length]
|
|
xchg cl , ch
|
|
|
|
; cmp ecx, eax ; If UDP packet size is bigger then IP packet told us,
|
|
; jg .error ; Something must went wrong!
|
|
|
|
lea ebx, [esi + SOCKET.lock]
|
|
call wait_mutex
|
|
|
|
; OK - we have a valid UDP Packet for this socket.
|
|
; First, update the sockets remote port number with the incoming msg
|
|
; - it will have changed
|
|
; from the original ( 69 normally ) to allow further connects
|
|
mov ax, [edx + UDP_Packet.SourcePort] ; get the UDP source port
|
|
xchg al, ah
|
|
mov [esi + SOCKET.RemotePort], ax
|
|
|
|
; Now, copy data to socket. We have socket address as [eax + sockets].
|
|
; We have IP Packet in edx
|
|
|
|
add edx, UDP_Packet.Data
|
|
mov eax, [esi + SOCKET.rxDataCount] ; get # of bytes already in buffer
|
|
DEBUGF 1,"bytes in socket: %u ", eax
|
|
lea edi, [ecx + eax] ; check for buffer overflow
|
|
cmp edi, SOCKETBUFFSIZE - SOCKETHEADERSIZE ;
|
|
jg .dump ;
|
|
add [esi + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer
|
|
DEBUGF 1,"adding %u bytes\n", ecx
|
|
|
|
; ecx has count, edx points to data
|
|
|
|
lea edi, [esi + eax + 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,"UDP 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,"UDP_handler - dumping\n"
|
|
|
|
call kernel_free
|
|
add esp, 4 ; pop (balance stack)
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; Note: UDP works only on top of IP protocol :)
|
|
;
|
|
; IN: eax = dest ip
|
|
; ebx = source ip
|
|
; ecx = data length
|
|
; edx = remote port shl 16 + local port (both in INET order)
|
|
; esi = data offset
|
|
;
|
|
;-----------------------------------------------------------------
|
|
|
|
UDP_create_packet:
|
|
|
|
DEBUGF 1,"Create UDP Packet\n"
|
|
|
|
push edx esi
|
|
|
|
add ecx, UDP_Packet.Data
|
|
mov di , IP_PROTO_UDP
|
|
|
|
; dx = fragment id
|
|
|
|
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6
|
|
cmp edi, -1
|
|
je .exit
|
|
|
|
sub ecx , UDP_Packet.Data
|
|
mov byte[edi + UDP_Packet.Length], ch
|
|
mov byte[edi + UDP_Packet.Length+1], cl
|
|
|
|
pop esi
|
|
push edi
|
|
add edi, UDP_Packet.Data
|
|
push cx
|
|
shr ecx, 2
|
|
rep movsd
|
|
pop cx
|
|
and cx , 3
|
|
rep movsb
|
|
pop edi
|
|
|
|
pop ecx
|
|
; bswap ecx ; convert little endian - big endian
|
|
; rol ecx, 16 ;
|
|
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once
|
|
|
|
|
|
mov [edi + UDP_Packet.Checksum], 0
|
|
|
|
; TODO: calculate checksum using Pseudo-header (However, using a 0 as checksum shouldnt generate any errors :)
|
|
|
|
push ebx eax ; TODO: make this work on other protocols besides ethernet
|
|
mov ebx,edx ;
|
|
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
|
|
jmp ETH_Sender ;
|
|
|
|
.exit:
|
|
ret
|
|
|
|
|
|
|
|
;---------------------------------------------------------------------------
|
|
;
|
|
; 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
|