forked from KolibriOS/kolibrios
Changes in net branch:
Things changed: sockets data organisation, queue macro's are more universal, new checksum routines, changed socket structures, ... What's new: UDP checksum generation & validation Rough TCP code has been written, but not debugged yet. git-svn-id: svn://kolibrios.org@1249 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
parent
725fe0911e
commit
7f9d0c6697
@ -56,13 +56,13 @@
|
||||
|
||||
include 'macros.inc'
|
||||
|
||||
$Revision: 1025 $
|
||||
$Revision$
|
||||
|
||||
|
||||
USE_COM_IRQ equ 1 ; make irq 3 and irq 4 available for PCI devices
|
||||
|
||||
; Enabling the next line will enable serial output console
|
||||
;debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
|
||||
debug_com_base equ 0x3f8 ; 0x3f8 is com1, 0x2f8 is com2, 0x3e8 is com3, 0x2e8 is com4, no irq's are used
|
||||
|
||||
include "proc32.inc"
|
||||
include "kglobals.inc"
|
||||
|
@ -221,7 +221,7 @@ ARP_create_request:
|
||||
mov ecx, 60 ; minimum packet size
|
||||
mov edx, edi ;;;
|
||||
mov di , ETHER_ARP
|
||||
call ETH_create_Packet
|
||||
call ETH_create_packet
|
||||
cmp edi, -1
|
||||
je .exit
|
||||
|
||||
@ -248,7 +248,7 @@ ARP_create_request:
|
||||
DEBUGF 1,"ARP Packet for device %x created successfully\n", ebx
|
||||
|
||||
push edx ecx
|
||||
jmp ETH_Sender
|
||||
jmp ETH_sender
|
||||
|
||||
.exit:
|
||||
add esp, 8
|
||||
@ -555,7 +555,7 @@ ARP_handler:
|
||||
|
||||
DEBUGF 1,"ARP_Handler - Sending reply \n"
|
||||
|
||||
jmp ETH_Sender ; And send it!
|
||||
jmp ETH_sender ; And send it!
|
||||
|
||||
.exit:
|
||||
call kernel_free
|
||||
|
@ -3,7 +3,7 @@
|
||||
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
|
||||
;; Distributed under terms of the GNU General Public License ;;
|
||||
;; ;;
|
||||
;; IP.INC ;;
|
||||
;; IPv4.INC ;;
|
||||
;; ;;
|
||||
;; Part of the tcp/ip network stack for KolibriOS ;;
|
||||
;; ;;
|
||||
@ -52,7 +52,7 @@ struct FRAGMENT_entry ; This structure will replace the ethernet header
|
||||
.PrevPtr dd ? ; Pointer to previous fragment entry (-1 for first packet)
|
||||
.NextPtr dd ? ; Pointer to next fragment entry (-1 for last packet)
|
||||
.Owner dd ? ; Pointer to structure of driver
|
||||
rb 2 ; to match ethernet header size
|
||||
rb 2 ; to match ethernet header size ; TODO: fix this hack
|
||||
.Data: ; Ip header begins here (we will need the IP header to re-construct the complete packet)
|
||||
ends
|
||||
|
||||
@ -99,10 +99,9 @@ IPv4_init:
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; IP_Handler:
|
||||
; IPv4_Handler:
|
||||
;
|
||||
; Called by eth_handler,
|
||||
; will check if IP Packet isnt damaged
|
||||
; Will check if IP Packet isnt damaged
|
||||
; and call appropriate handler. (TCP/UDP/ICMP/..)
|
||||
;
|
||||
; It will also re-construct fragmented packets
|
||||
@ -119,20 +118,27 @@ align 4
|
||||
IPv4_handler:
|
||||
|
||||
DEBUGF 1,"IP_Handler - start\n"
|
||||
mov cx , [edx + IPv4_Packet.HeaderChecksum]
|
||||
xchg ch , cl ; Get the checksum in intel format
|
||||
|
||||
mov word [edx + IPv4_Packet.HeaderChecksum], 0 ; Clear checksum field to recalculating checksum
|
||||
push edx ebx
|
||||
|
||||
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
|
||||
and eax, 0x0000000F ;
|
||||
shl eax, 2 ;
|
||||
; save checksum, and clear it in original packet
|
||||
mov di , [edx + IPv4_Packet.HeaderChecksum]
|
||||
DEBUGF 1,"checksum: %x\n",di
|
||||
mov word [edx + IPv4_Packet.HeaderChecksum], 0
|
||||
|
||||
push edx
|
||||
stdcall checksum_jb, edx, eax ; buf_ptr, buf_size
|
||||
pop edx
|
||||
cmp cx , ax
|
||||
jnz .dump ; if CHECKSUM isn't valid then dump Packet
|
||||
; Re-calculate checksum
|
||||
movzx ecx, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
|
||||
and ecx, 0x0000000F ;
|
||||
shl cx , 2 ;
|
||||
mov esi, edx
|
||||
xor edx, edx
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
|
||||
; now compare the two..
|
||||
cmp dx, di
|
||||
pop ebx edx
|
||||
jne .dump ; if checksum isn't valid then dump packet
|
||||
|
||||
mov eax, [edx + IPv4_Packet.DestinationAddress]
|
||||
mov edi, BROADCAST
|
||||
@ -183,10 +189,14 @@ IPv4_handler:
|
||||
add eax, edx
|
||||
push eax
|
||||
mov al , [edx + IPv4_Packet.Protocol]
|
||||
;----------------------- experimental
|
||||
mov esi, [edx + IPv4_Packet.SourceAddress]
|
||||
mov edi, [edx + IPv4_Packet.DestinationAddress]
|
||||
;-----------------------
|
||||
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
|
||||
|
||||
cmp al , IP_PROTO_TCP
|
||||
; je TCP_handler
|
||||
je TCP_handler
|
||||
|
||||
cmp al , IP_PROTO_UDP
|
||||
je UDP_handler
|
||||
@ -385,14 +395,21 @@ IPv4_handler:
|
||||
movzx eax, byte [edx + IPv4_Packet.VersionAndIHL] ; Calculate Header length by using IHL field
|
||||
and ax, 0x000F ;
|
||||
shl ax, 2 ;
|
||||
sub ecx, eax ;
|
||||
|
||||
sub ecx, eax
|
||||
|
||||
|
||||
add eax, edx
|
||||
push eax
|
||||
mov al , [edx + IPv4_Packet.Protocol]
|
||||
;----------------------- experimental
|
||||
mov esi, [edx + IPv4_Packet.SourceAddress]
|
||||
mov edi, [edx + IPv4_Packet.DestinationAddress]
|
||||
;-----------------------
|
||||
pop edx ; Offset to data (tcp/udp/icmp/.. Packet)
|
||||
|
||||
cmp al , IP_PROTO_TCP
|
||||
; je TCP_handler
|
||||
je TCP_handler
|
||||
|
||||
cmp al , IP_PROTO_UDP
|
||||
je UDP_handler
|
||||
@ -493,12 +510,12 @@ IPv4_decrease_fragment_ttls:
|
||||
; dx = fragment id
|
||||
; di = protocol
|
||||
;
|
||||
; OUT: eax points to buffer start
|
||||
; ebx is size of complete buffer
|
||||
; edi = pointer to start of data (-1 on error)
|
||||
; OUT: eax = pointer to buffer start
|
||||
; ebx = pointer to device struct (needed for sending procedure)
|
||||
; ecx = unchanged (packet size of embedded data)
|
||||
; edx = pointer to device struct (needed for sending procedure)
|
||||
; edx = size of complete buffer
|
||||
; esi = pointer to sending procedure
|
||||
; edi = pointer to start of data (-1 on error)
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
@ -550,7 +567,7 @@ IPv4_create_packet:
|
||||
mov ecx, [esp+18] ;; 18 or 22 ??
|
||||
add ecx, IPv4_Packet.DataOrOptional
|
||||
mov di , ETHER_IPv4
|
||||
call ETH_create_Packet ; TODO: figure out a way to make this work with other protocols too
|
||||
call ETH_create_packet ; TODO: figure out a way to make this work with other protocols too
|
||||
add esp, 6
|
||||
cmp edi, -1
|
||||
je .exit
|
||||
@ -571,21 +588,25 @@ IPv4_create_packet:
|
||||
pop ecx
|
||||
mov [edi + IPv4_Packet.DestinationAddress], ecx
|
||||
|
||||
push eax
|
||||
stdcall checksum_jb, edi, IPv4_Packet.DataOrOptional ; buf_ptr, buf_size
|
||||
xchg al, ah
|
||||
mov [edi + IPv4_Packet.HeaderChecksum], ax
|
||||
pop eax ecx
|
||||
push eax ebx edx
|
||||
; calculate checksum
|
||||
xor edx, edx
|
||||
mov esi, edi
|
||||
mov ecx, IPv4_Packet.DataOrOptional
|
||||
call checksum_1
|
||||
call checksum_2
|
||||
mov [edi + IPv4_Packet.HeaderChecksum], dx
|
||||
pop edx ebx eax ecx
|
||||
add edi, IPv4_Packet.DataOrOptional
|
||||
|
||||
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", edx
|
||||
DEBUGF 1,"IPv4 Packet for device %x created successfully\n", ebx
|
||||
|
||||
ret
|
||||
|
||||
|
||||
.not_found:
|
||||
DEBUGF 1,"Create IPv4 Packet - ARP entry not found!\n"
|
||||
; TODO: QUEUE!
|
||||
; TODO: QUEUE the packet to resend later!
|
||||
.exit:
|
||||
add esp, 16
|
||||
.exit_:
|
||||
|
@ -80,13 +80,8 @@ ETH_init:
|
||||
mov ecx, (1+MAX_ETH_DEVICES)
|
||||
rep stosd
|
||||
|
||||
mov dword [ETH_IN_QUEUE], ETH_QUEUE_SIZE
|
||||
mov dword [ETH_IN_QUEUE+4], ETH_IN_QUEUE + queue.data
|
||||
mov dword [ETH_IN_QUEUE+8], ETH_IN_QUEUE + queue.data
|
||||
|
||||
mov dword [ETH_OUT_QUEUE], ETH_QUEUE_SIZE
|
||||
mov dword [ETH_OUT_QUEUE+4], ETH_OUT_QUEUE + queue.data
|
||||
mov dword [ETH_OUT_QUEUE+8], ETH_OUT_QUEUE + queue.data
|
||||
init_queue ETH_IN_QUEUE
|
||||
init_queue ETH_OUT_QUEUE
|
||||
|
||||
ret
|
||||
|
||||
@ -104,7 +99,7 @@ ETH_init:
|
||||
;---------------------------------------------------------
|
||||
|
||||
align 4
|
||||
ETH_Add_Device:
|
||||
ETH_add_device:
|
||||
|
||||
DEBUGF 1,"ETH_Add_Device: %x ", ebx
|
||||
|
||||
@ -122,7 +117,6 @@ ETH_Add_Device:
|
||||
mov ecx, MAX_ETH_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
|
||||
mov edi, ETH_DRV_LIST
|
||||
|
||||
cld
|
||||
repne scasd ; See if device is already in the list
|
||||
jz .error
|
||||
|
||||
@ -167,7 +161,7 @@ ETH_Add_Device:
|
||||
;--------------------------------
|
||||
|
||||
align 4
|
||||
ETH_Remove_Device:
|
||||
ETH_remove_device:
|
||||
|
||||
cmp [ETH_RUNNING], 0
|
||||
je .error
|
||||
@ -212,12 +206,21 @@ ETH_Remove_Device:
|
||||
;-------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
ETH_Receiver:
|
||||
DEBUGF 1,"ETH_Receiver \n"
|
||||
ETH_receiver:
|
||||
DEBUGF 1,"ETH_Receiver: "
|
||||
|
||||
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
|
||||
push ebx
|
||||
mov esi, esp
|
||||
add_to_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
|
||||
DEBUGF 1,"Queued packet successfully\n"
|
||||
add esp, 4*3
|
||||
ret
|
||||
|
||||
.gohome:
|
||||
.fail:
|
||||
DEBUGF 1,"ETH_IN_QUEUE is full!\n"
|
||||
add esp, 4
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
|
||||
@ -238,7 +241,18 @@ ETH_Receiver:
|
||||
align 4
|
||||
ETH_handler:
|
||||
|
||||
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, .gohome
|
||||
get_from_queue ETH_IN_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
|
||||
|
||||
push ETH_handler
|
||||
|
||||
lodsd
|
||||
mov ebx, eax
|
||||
lodsd
|
||||
mov ecx, eax
|
||||
lodsd
|
||||
xchg eax, ecx
|
||||
push ecx
|
||||
push eax
|
||||
|
||||
DEBUGF 1,"ETH_Handler - size: %u\n", ecx
|
||||
cmp ecx, 60 ; check packet length
|
||||
@ -262,13 +276,13 @@ ETH_handler:
|
||||
add esp, 4
|
||||
|
||||
.gohome:
|
||||
ret ; return 1. to get more from queue / 2. to caller
|
||||
ret ; return to get more from queue / to caller
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_Sender:
|
||||
; ETH_sender:
|
||||
;
|
||||
; This function sends an ethernet packet to the correct driver.
|
||||
;
|
||||
@ -280,35 +294,66 @@ ETH_handler:
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
ETH_Sender:
|
||||
DEBUGF 1,"ETH_Sender \n"
|
||||
ETH_sender:
|
||||
DEBUGF 1,"ETH_Sender: queuing for device: %x, %u bytes\n", [esp], [esp + 4]
|
||||
|
||||
add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
|
||||
|
||||
.gohome:
|
||||
push ebx
|
||||
mov esi, esp
|
||||
add_to_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .fail
|
||||
DEBUGF 1,"Queued packet successfully\n"
|
||||
add esp, 3*4
|
||||
ret
|
||||
|
||||
.fail:
|
||||
DEBUGF 1,"ETH_OUT_QUEUE is full!\n"
|
||||
add esp, 4
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; ETH_send_queued:
|
||||
;
|
||||
; IN: /
|
||||
; OUT: /
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
ETH_send_queued:
|
||||
|
||||
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, .gohome
|
||||
get_from_queue ETH_OUT_QUEUE, ETH_QUEUE_SIZE, eth_queue_entry.size, .gohome
|
||||
|
||||
push ETH_send_queued
|
||||
|
||||
lodsd
|
||||
mov ebx, eax
|
||||
|
||||
sub esp, 8
|
||||
mov edi, esp
|
||||
movsd
|
||||
movsd
|
||||
|
||||
DEBUGF 1,"dequeued packet for device %x\n", ebx
|
||||
|
||||
call ETH_struc2dev ; convert struct ptr to device num (this way we know if driver is still mounted)
|
||||
cmp edi, -1
|
||||
je .fail
|
||||
|
||||
DEBUGF 1,"ETH_Sender - device: %u\n", edi
|
||||
|
||||
jmp [ebx+ETH_DEVICE.transmit]
|
||||
jmp [ebx+ETH_DEVICE.transmit] ; we will return to get_from_queue macro after transmitting packet
|
||||
|
||||
.fail:
|
||||
call kernel_free
|
||||
add esp, 4 ; pop (balance stack)
|
||||
DEBUGF 1,"ETH_Sender - fail\n"
|
||||
|
||||
.gohome:
|
||||
ret
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; ETH_struc2dev
|
||||
@ -362,7 +407,7 @@ ETH_struc2dev:
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
ETH_create_Packet:
|
||||
ETH_create_packet:
|
||||
|
||||
DEBUGF 1,"Creating Ethernet Packet (size=%u): \n", ecx
|
||||
|
||||
@ -394,7 +439,7 @@ ETH_create_Packet:
|
||||
lea eax, [edi - ETH_FRAME.Data] ; Set eax to buffer start
|
||||
mov edx, ecx ; Set ebx to complete buffer size
|
||||
pop ecx
|
||||
mov esi, ETH_Sender
|
||||
mov esi, ETH_sender
|
||||
|
||||
xor ebx, ebx ;;;; TODO: Fixme
|
||||
mov ebx, [ETH_DRV_LIST + ebx]
|
||||
|
@ -133,8 +133,8 @@ ICMP_init:
|
||||
;
|
||||
; 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!
|
||||
; this procedure will send reply's to ICMP echo's
|
||||
; and insert packets into sockets when needed ;;; TODO: update this to work with fragmented packets too!
|
||||
;
|
||||
; IN: Pointer to buffer in [esp]
|
||||
; size of buffer in [esp+4]
|
||||
@ -181,33 +181,31 @@ ICMP_handler: ;TODO: works only on pure ethernet right now !
|
||||
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
|
||||
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
|
||||
; mov esi, [esp] ; Find length of IP Packet
|
||||
movzx eax, word[esi + IPv4_Packet.TotalLength] ;
|
||||
movzx eax, word[esi + IPv4_Packet.TotalLength] ; Find length of IP Packet
|
||||
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
|
||||
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
|
||||
|
||||
jmp ETH_Sender ; Send the reply
|
||||
jmp ETH_sender ; Send the reply
|
||||
|
||||
|
||||
|
||||
@ -222,20 +220,14 @@ ICMP_handler: ;TODO: works only on pure ethernet right now !
|
||||
.try_more:
|
||||
mov ax , [edx + ICMP_Packet.Identifier]
|
||||
.next_socket:
|
||||
mov esi, [esi + SOCKET.NextPtr]
|
||||
mov esi, [esi + SOCKET_head.NextPtr]
|
||||
or esi, esi
|
||||
jz .dump
|
||||
cmp [esi + SOCKET.Type], IP_PROTO_ICMP
|
||||
cmp [esi + SOCKET_head.Type], IP_PROTO_ICMP
|
||||
jne .next_socket
|
||||
cmp [esi + SOCKET.LocalPort], ax
|
||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + ICMP_SOCKET.Identifier], 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
|
||||
@ -243,60 +235,25 @@ ICMP_handler: ;TODO: works only on pure ethernet right now !
|
||||
|
||||
DEBUGF 1,"Found valid ICMP packet for socket %x\n", esi
|
||||
|
||||
lea ebx, [esi + SOCKET.lock]
|
||||
lea ebx, [esi + SOCKET_head.lock]
|
||||
call wait_mutex
|
||||
|
||||
; Now, copy data to socket. We have socket address in esi.
|
||||
; Now, assign 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
|
||||
mov eax, esi
|
||||
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
|
||||
add esp, 4
|
||||
sub edx, esi
|
||||
mov edi, edx
|
||||
jmp socket_internal_receiver
|
||||
|
||||
.dump:
|
||||
DEBUGF 1,"ICMP_Handler - dumping\n"
|
||||
|
||||
call kernel_free
|
||||
add esp, 8 ; pop (balance stack)
|
||||
add esp, 4 ; pop (balance stack)
|
||||
|
||||
ret
|
||||
|
||||
@ -351,7 +308,7 @@ ICMP_handler_fragments: ; works only on pure ethernet right now !
|
||||
DEBUGF 1,"ICMP_Handler_fragments - end\n"
|
||||
|
||||
call kernel_free
|
||||
add esp, 8 ; pop (balance stack)
|
||||
add esp, 4 ; pop (balance stack)
|
||||
ret
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
@ -397,11 +354,14 @@ ICMP_create_packet:
|
||||
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
|
||||
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
|
||||
|
||||
pop esi
|
||||
sub ecx, ICMP_Packet.Data
|
||||
add edi, ICMP_Packet.Data
|
||||
push cx
|
||||
|
@ -15,88 +15,97 @@
|
||||
$Revision$
|
||||
|
||||
struct queue
|
||||
.size dd ?
|
||||
.w_ptr dd ?
|
||||
.r_ptr dd ?
|
||||
.size dd ? ; number of queued packets in thsi queue
|
||||
.w_ptr dd ? ; current writing pointer in queue
|
||||
.r_ptr dd ? ; current reading pointer
|
||||
.data:
|
||||
ends
|
||||
|
||||
struct queue_entry
|
||||
struct eth_queue_entry
|
||||
.owner dd ?
|
||||
.data_ptr dd ?
|
||||
.data_size dd ?
|
||||
.size:
|
||||
ends
|
||||
|
||||
struct tcp_in_queue_entry
|
||||
.data_ptr dd ?
|
||||
.data_size dd ?
|
||||
.offset dd ?
|
||||
.size:
|
||||
ends
|
||||
|
||||
macro add_to_queue ptr, size, returnaddr {
|
||||
struct tcp_out_queue_entry
|
||||
.data_ptr dd ?
|
||||
.data_size dd ?
|
||||
.ttl dd ?
|
||||
.retries dd ?
|
||||
.owner dd ?
|
||||
.sendproc dd ?
|
||||
.ack_num dd ?
|
||||
.size:
|
||||
ends
|
||||
|
||||
cmp dword [ptr + queue.size], size ; Check if queue isnt full
|
||||
jge .fail
|
||||
struct socket_queue_entry
|
||||
.data_ptr dd ?
|
||||
.data_size dd ?
|
||||
.offset dd ?
|
||||
.size:
|
||||
ends
|
||||
|
||||
DEBUGF 1,"Queuing packet for device %x\n",ebx
|
||||
macro add_to_queue ptr, size, entry_size, failaddr {
|
||||
|
||||
inc dword [ptr + queue.size]
|
||||
cmp [ptr + queue.size], size ; Check if queue isnt full
|
||||
jge failaddr
|
||||
|
||||
mov edi, dword [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
|
||||
inc [ptr + queue.size]
|
||||
|
||||
mov eax, ebx
|
||||
stosd
|
||||
pop eax
|
||||
stosd
|
||||
pop eax
|
||||
stosd
|
||||
mov edi, [ptr + queue.w_ptr] ; Current write pointer (FIFO!)
|
||||
mov ecx, entry_size/4 ; Write the queue entry
|
||||
rep movsd ;
|
||||
|
||||
cmp edi, size*queue_entry.size+ptr+queue.data ; entry size
|
||||
lea ecx, [size*entry_size+ptr+queue.data]
|
||||
cmp edi, ecx ; entry size
|
||||
jl .no_wrap
|
||||
|
||||
sub edi, size*queue_entry.size
|
||||
sub edi, size*entry_size
|
||||
|
||||
.no_wrap:
|
||||
mov dword [ptr + queue.w_ptr], edi
|
||||
jmp returnaddr
|
||||
|
||||
.fail:
|
||||
DEBUGF 1,"queuing failed\n"
|
||||
|
||||
call kernel_free
|
||||
add esp, 4
|
||||
ret
|
||||
mov [ptr + queue.w_ptr], edi
|
||||
|
||||
}
|
||||
|
||||
|
||||
macro get_from_queue ptr, size, returnaddr {
|
||||
|
||||
.start_of_code:
|
||||
cmp dword [ptr + queue.size], 0 ; any packets queued?
|
||||
je returnaddr
|
||||
macro get_from_queue ptr, size, entry_size, failaddr {
|
||||
|
||||
DEBUGF 1,"Dequeuing packet"
|
||||
cmp [ptr + queue.size], 0 ; any packets queued?
|
||||
je failaddr
|
||||
|
||||
dec dword [ptr + queue.size]
|
||||
|
||||
push dword .start_of_code ; return address for call's
|
||||
dec [ptr + queue.size]
|
||||
|
||||
mov esi, [ptr + queue.r_ptr]
|
||||
lodsd
|
||||
mov ebx, eax
|
||||
lodsd
|
||||
mov ecx, eax
|
||||
lodsd
|
||||
push eax
|
||||
push ecx
|
||||
xchg eax, ecx
|
||||
push esi
|
||||
|
||||
DEBUGF 1," for device %x\n", ebx
|
||||
add esi, entry_size
|
||||
|
||||
cmp esi, size*queue_entry.size+ptr+queue.data ; entry size
|
||||
lea ecx, [size*entry_size+ptr+queue.data]
|
||||
cmp esi, ecx ; entry size
|
||||
jl .no_wrap
|
||||
|
||||
sub esi, size*queue_entry.size
|
||||
sub esi, size*entry_size
|
||||
|
||||
.no_wrap:
|
||||
mov dword [ptr + queue.r_ptr], esi
|
||||
|
||||
pop esi
|
||||
|
||||
}
|
||||
|
||||
macro init_queue queue_ptr {
|
||||
|
||||
mov [queue_ptr + queue.size] , 0
|
||||
lea esi, [queue_ptr + queue.data]
|
||||
mov [queue_ptr + queue.w_ptr], esi
|
||||
mov [queue_ptr + queue.r_ptr], esi
|
||||
}
|
@ -5,7 +5,6 @@
|
||||
;; ;;
|
||||
;; SOCKET.INC ;;
|
||||
;; ;;
|
||||
;; ;;
|
||||
;; Written by hidnplayr@kolibrios.org ;;
|
||||
;; based on code by mike.dld ;;
|
||||
;; ;;
|
||||
@ -16,8 +15,7 @@
|
||||
|
||||
$Revision$
|
||||
|
||||
align 4
|
||||
struct SOCKET
|
||||
struct SOCKET_head
|
||||
.PrevPtr dd ? ; pointer to previous socket in list
|
||||
.NextPtr dd ? ; pointer to next socket in list
|
||||
.Number dd ? ; socket number (unique within single process)
|
||||
@ -25,35 +23,73 @@ struct SOCKET
|
||||
.Domain dd ? ; INET/UNIX/..
|
||||
.Type dd ? ; RAW/UDP/TCP/...
|
||||
.Protocol dd ? ; ICMP/IPv4/ARP/
|
||||
.LocalIP dd ? ; local IP address
|
||||
.RemoteIP dd ? ; remote IP address
|
||||
.LocalPort dw ? ; local port (In INET byte order)
|
||||
.RemotePort dw ? ; remote port (IN INET byte order
|
||||
.lock dd ? ; lock mutex
|
||||
.end:
|
||||
ends
|
||||
|
||||
struct IPv4_SOCKET
|
||||
.LocalIP dd ?
|
||||
.RemoteIP dd ?
|
||||
.SequenceNumber dd ?
|
||||
|
||||
; todo: add options (for func 8 and 9)
|
||||
|
||||
.end:
|
||||
ends
|
||||
|
||||
struct TCP_SOCKET
|
||||
|
||||
.LocalPort dw ? ; In INET byte order
|
||||
.RemotePort dw ? ; In INET byte order
|
||||
|
||||
.backlog dw ? ; Backlog
|
||||
.OrigRemoteIP dd ? ; original remote IP address (used to reset to LISTEN state)
|
||||
.OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
|
||||
.rxDataCount dd ? ; rx data count
|
||||
.TCBState dd ? ; TCB state
|
||||
.TCBTimer dd ? ; TCB timer (seconds)
|
||||
.ISS dd ? ; initial send sequence
|
||||
.IRS dd ? ; initial receive sequence
|
||||
.SND_UNA dd ? ; sequence number of unack'ed sent Packets
|
||||
.SND_NXT dd ? ; bext send sequence number to use
|
||||
.SND_NXT dd ? ; next send sequence number to use
|
||||
.SND_WND dd ? ; send window
|
||||
.RCV_NXT dd ? ; next receive sequence number to use
|
||||
.RCV_WND dd ? ; receive window
|
||||
.SEG_LEN dd ? ; segment length
|
||||
.SEG_WND dd ? ; segment window
|
||||
.wndsizeTimer dd ? ; window size timer
|
||||
.lock dd ? ; lock mutex
|
||||
.backlog dw ? ; Backlog
|
||||
.rxData: ; receive data buffer here
|
||||
|
||||
.flags db ? ; packet flags
|
||||
|
||||
.end:
|
||||
ends
|
||||
|
||||
MAX_backlog equ 20
|
||||
struct UDP_SOCKET
|
||||
|
||||
; socket buffers
|
||||
SOCKETBUFFSIZE equ 4096 ; state + config + buffer.
|
||||
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data
|
||||
.LocalPort dw ? ; In INET byte order
|
||||
.RemotePort dw ? ; In INET byte order
|
||||
|
||||
.end:
|
||||
ends
|
||||
|
||||
struct ICMP_SOCKET
|
||||
|
||||
.Identifier dw ? ;
|
||||
|
||||
.end:
|
||||
|
||||
ends
|
||||
|
||||
struct IPC_SOCKET
|
||||
|
||||
.ConnectedTo dd ? ; Socket number of other socket this one is connected to
|
||||
|
||||
.end:
|
||||
|
||||
ends
|
||||
|
||||
MAX_backlog equ 20 ; backlog for stream sockets
|
||||
SOCKETBUFFSIZE equ 4096 ; in bytes
|
||||
SOCKET_QUEUE_SIZE equ 10 ; maximum number ofincoming packets queued for 1 socket
|
||||
|
||||
uglobal
|
||||
net_sockets rd 2
|
||||
@ -110,6 +146,10 @@ sys_socket:
|
||||
jz socket_send ; 6
|
||||
dec bl
|
||||
jz socket_recv ; 7
|
||||
dec bl
|
||||
; jz socket_get_opt ; 8
|
||||
dec bl
|
||||
; jz socket_set_opt ; 9
|
||||
|
||||
s_error:
|
||||
mov dword [esp+32],-1
|
||||
@ -139,9 +179,9 @@ socket_open:
|
||||
or eax, eax
|
||||
jz s_error
|
||||
|
||||
mov [eax + SOCKET.Domain], ecx
|
||||
mov [eax + SOCKET.Type], edx
|
||||
mov [eax + SOCKET.Protocol], esi
|
||||
mov [eax + SOCKET_head.Domain], ecx
|
||||
mov [eax + SOCKET_head.Type], edx
|
||||
mov [eax + SOCKET_head.Protocol], esi
|
||||
|
||||
stdcall net_socket_addr_to_num, eax
|
||||
DEBUGF 1,", socketnumber: %u\n", eax
|
||||
@ -153,6 +193,10 @@ socket_open:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
;
|
||||
; SOCKET_bind
|
||||
@ -176,14 +220,28 @@ socket_bind:
|
||||
jl s_error
|
||||
|
||||
cmp word [edx], AF_INET4
|
||||
jne s_error
|
||||
je .af_inet4
|
||||
|
||||
cmp word [edx], AF_UNIX
|
||||
je .af_unix
|
||||
|
||||
jmp s_error
|
||||
|
||||
.af_unix:
|
||||
|
||||
; TODO: write code here
|
||||
|
||||
|
||||
mov dword [esp+32],0
|
||||
ret
|
||||
|
||||
.af_inet4:
|
||||
|
||||
cmp esi, 6
|
||||
jl s_error
|
||||
|
||||
mov ecx, [eax + SOCKET.Type]
|
||||
mov ecx, [eax + SOCKET_head.Type]
|
||||
|
||||
mov bx, word [edx + 2]
|
||||
DEBUGF 1,"local port: %x ",bx
|
||||
test bx, bx
|
||||
@ -202,13 +260,14 @@ socket_bind:
|
||||
|
||||
.got_port:
|
||||
DEBUGF 1,"using port: %x ",bx
|
||||
mov word [eax + SOCKET.LocalPort], bx
|
||||
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
|
||||
|
||||
mov ebx, dword [edx + 4]
|
||||
mov dword [eax + SOCKET.LocalIP], ebx
|
||||
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP], ebx
|
||||
|
||||
DEBUGF 1,"local ip: %u.%u.%u.%u\n",\
|
||||
[eax + SOCKET.LocalIP]:1,[eax + SOCKET.LocalIP + 1]:1,[eax + SOCKET.LocalIP + 2]:1,[eax + SOCKET.LocalIP + 3]:1
|
||||
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 0]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 1]:1,\
|
||||
[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 2]:1,[eax + SOCKET_head.end + IPv4_SOCKET.LocalIP + 3]:1
|
||||
|
||||
mov dword [esp+32],0
|
||||
ret
|
||||
@ -249,13 +308,13 @@ socket_connect:
|
||||
cmp esi, 8
|
||||
jl s_error
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_UDP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
|
||||
je .udp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
|
||||
je .icmp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
|
||||
je .tcp
|
||||
|
||||
jmp s_error
|
||||
@ -263,11 +322,11 @@ socket_connect:
|
||||
.udp:
|
||||
|
||||
mov bx , word [edx + 2]
|
||||
mov word [eax + SOCKET.RemotePort], bx
|
||||
mov word [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
|
||||
DEBUGF 1,"remote port: %x ",bx
|
||||
|
||||
mov ebx, dword [edx + 4]
|
||||
mov dword [eax + SOCKET.RemoteIP], ebx
|
||||
mov dword [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
|
||||
DEBUGF 1,"remote ip: %u.%u.%u.%u\n",[edx+4]:1,[edx+5]:1,[edx+6]:1,[edx+7]:1
|
||||
|
||||
mov dword [esp+32],0
|
||||
@ -275,6 +334,7 @@ socket_connect:
|
||||
|
||||
.icmp:
|
||||
|
||||
; TODO: write code here
|
||||
|
||||
ret
|
||||
|
||||
@ -387,7 +447,7 @@ socket_listen:
|
||||
mov dx , 20
|
||||
.ok:
|
||||
|
||||
mov [eax + SOCKET.backlog], dx
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], dx
|
||||
|
||||
; TODO: insert code for active connections like TCP
|
||||
|
||||
@ -420,7 +480,21 @@ socket_accept:
|
||||
jz s_error
|
||||
mov esi, eax
|
||||
|
||||
cmp [esi + SOCKET.backlog], 0
|
||||
cmp word [esi + SOCKET_head.Domain], AF_INET4
|
||||
je .af_inet4
|
||||
|
||||
jmp s_error
|
||||
|
||||
.af_inet4:
|
||||
|
||||
cmp [esi + SOCKET_head.Type], IP_PROTO_TCP
|
||||
je .tcp
|
||||
|
||||
jmp s_error
|
||||
|
||||
.tcp:
|
||||
|
||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
|
||||
jz s_error
|
||||
|
||||
call net_socket_alloc
|
||||
@ -428,19 +502,21 @@ socket_accept:
|
||||
jz s_error
|
||||
mov edi, eax
|
||||
|
||||
dec [esi + SOCKET.backlog]
|
||||
dec [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog]
|
||||
|
||||
mov ecx, (SOCKET.rxData+3)/4
|
||||
mov ecx, (SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.end+3)/4
|
||||
push esi edi
|
||||
rep movsd
|
||||
pop edi esi
|
||||
|
||||
mov [edi + SOCKET.backlog], 0
|
||||
mov [edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.backlog], 0
|
||||
|
||||
; TODO: fill in structure in ecx
|
||||
|
||||
mov [esi + SOCKET.RemoteIP], 0
|
||||
mov [esi + SOCKET.RemotePort], 0
|
||||
mov [esi + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0
|
||||
mov [esi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RemotePort], 0
|
||||
|
||||
stdcall net_socket_addr_to_num, eax
|
||||
stdcall net_socket_addr_to_num, edi
|
||||
mov [esp+32], eax
|
||||
|
||||
ret
|
||||
@ -465,26 +541,23 @@ socket_close:
|
||||
or eax, eax
|
||||
jz s_error
|
||||
|
||||
cmp [eax + SOCKET_head.Domain], AF_INET4
|
||||
jne s_error
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_UDP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
|
||||
je .udp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_ICMP
|
||||
je .icmp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
|
||||
je .tcp
|
||||
|
||||
jmp s_error
|
||||
|
||||
.udp:
|
||||
|
||||
lea ebx, [eax + SOCKET.lock]
|
||||
call wait_mutex
|
||||
; TODO: mark the socket for deletion, using the mutex
|
||||
|
||||
stdcall net_socket_free, eax
|
||||
|
||||
mov dword [esp+32],0
|
||||
ret
|
||||
|
||||
@ -600,8 +673,8 @@ end if
|
||||
;
|
||||
;
|
||||
; IN: socket number in ecx
|
||||
; addr in edx
|
||||
; addrlen in esi
|
||||
; addr to buffer in edx
|
||||
; length of buffer in esi
|
||||
; flags in edi
|
||||
; OUT: eax is number of bytes copied, -1 on error
|
||||
;
|
||||
@ -609,70 +682,46 @@ end if
|
||||
align 4
|
||||
socket_recv:
|
||||
|
||||
DEBUGF 1,"Socket_receive: socknum: %u sockaddr: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
|
||||
DEBUGF 1,"Socket_receive: socknum: %u bufferaddress: %x, length: %u, flags: %x\n",ecx,edx,esi,edi
|
||||
|
||||
stdcall net_socket_num_to_addr, ecx ; get real socket address
|
||||
or eax, eax
|
||||
jz s_error
|
||||
|
||||
DEBUGF 1,"real socket address:%x\n", eax
|
||||
DEBUGF 1,"Socket pointer: %x\n", eax
|
||||
|
||||
mov dword[esp+32], -1
|
||||
get_from_queue (eax + 2048), SOCKET_QUEUE_SIZE, 4*3, s_error
|
||||
|
||||
mov edi, edx
|
||||
mov ecx, [esi + socket_queue_entry.data_size]
|
||||
|
||||
lea ebx, [eax + SOCKET.lock]
|
||||
call wait_mutex
|
||||
DEBUGF 1,"Got %u bytes of data\n", ecx
|
||||
|
||||
mov ecx, [eax + SOCKET.rxDataCount] ; get count of bytes
|
||||
DEBUGF 1,"bytes in socket:%u\n", ecx
|
||||
test ecx, ecx ; if count of bytes is zero..
|
||||
jz .exit ; exit function (eax will be zero)
|
||||
cmp ecx, edx
|
||||
jle .large_enough
|
||||
DEBUGF 1,"Buffer too small...\n"
|
||||
jmp s_error
|
||||
.large_enough:
|
||||
|
||||
cmp ecx, esi ; if buffer size is larger then the bytes of data, copy all data
|
||||
jle .copy_all_bytes
|
||||
push [esi + socket_queue_entry.data_ptr]
|
||||
mov esi, [esi + socket_queue_entry.offset]
|
||||
add esi, [esp]
|
||||
DEBUGF 1,"Source buffer: %x, real addr: %x\n", [esp], esi
|
||||
|
||||
sub ecx, esi ; store new count (data bytes in buffer - bytes we're about to copy)
|
||||
mov [eax + SOCKET.rxDataCount], ecx ;
|
||||
push ecx
|
||||
mov edx, esi
|
||||
mov dword[esp+32+4], ecx ; return number of bytes copied
|
||||
|
||||
call .start_copy ; copy to the application
|
||||
shr ecx, 1
|
||||
jnc .nb
|
||||
movsb
|
||||
.nb: shr ecx, 1
|
||||
jnc .nw
|
||||
movsw
|
||||
.nw: rep movsd
|
||||
|
||||
mov dword[esp+32], edx
|
||||
call kernel_free
|
||||
|
||||
lea edi, [eax + SOCKET.rxData] ; Now shift the remaining bytes to start of buffer
|
||||
lea esi, [edi + edx]
|
||||
mov ecx, [esp]
|
||||
shr ecx, 2 ; divide eax by 4
|
||||
rep movsd ; copy all full dwords
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb ; copy remaining bytes
|
||||
|
||||
.exit:
|
||||
mov [eax + SOCKET.lock], 0
|
||||
ret
|
||||
|
||||
.copy_all_bytes:
|
||||
mov dword[esp+32], ecx
|
||||
mov [eax + SOCKET.rxDataCount], 0 ; store new count (zero)
|
||||
push dword .exit ; this code results in same as commented out code
|
||||
|
||||
.start_copy:
|
||||
DEBUGF 1,"copying %u bytes\n",ecx
|
||||
|
||||
lea esi, [eax + SOCKET.rxData]
|
||||
push ecx
|
||||
shr ecx, 2 ; divide eax by 4
|
||||
rep movsd
|
||||
pop ecx
|
||||
and ecx, 3
|
||||
rep movsb ; copy the rest bytes
|
||||
|
||||
ret ; exit, or go back to shift remaining bytes if any
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
;
|
||||
@ -695,84 +744,97 @@ socket_send:
|
||||
or eax, eax
|
||||
jz s_error
|
||||
|
||||
cmp word [eax + SOCKET.Domain], AF_INET4
|
||||
cmp word [eax + SOCKET_head.Domain], AF_INET4
|
||||
je .af_inet4
|
||||
|
||||
jmp s_error
|
||||
|
||||
;---------
|
||||
.af_inet4:
|
||||
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET_head.Type]:4
|
||||
|
||||
DEBUGF 1,"Socket type:%u\n", [eax + SOCKET.Type]:4
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_UDP
|
||||
je .udp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_ICMP
|
||||
je .icmp
|
||||
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_TCP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_TCP
|
||||
je .tcp
|
||||
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
|
||||
je .udp
|
||||
|
||||
cmp [eax + SOCKET_head.Type], SOCK_RAW
|
||||
je .raw
|
||||
|
||||
jmp s_error
|
||||
;--------
|
||||
|
||||
.udp:
|
||||
|
||||
DEBUGF 1,"type: UDP, "
|
||||
|
||||
cmp [eax + SOCKET.LocalPort],0
|
||||
jne .port_ok
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort],0
|
||||
jne @f
|
||||
|
||||
push esi
|
||||
mov ecx, [eax + SOCKET.Type]
|
||||
mov ecx, [eax + SOCKET_head.Type]
|
||||
call socket_find_port
|
||||
test bx, bx
|
||||
pop esi
|
||||
je s_error
|
||||
mov [eax + SOCKET.LocalPort], bx
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
|
||||
|
||||
.port_ok:
|
||||
@@:
|
||||
|
||||
mov ecx, esi
|
||||
mov esi, edx
|
||||
mov edx, dword [eax + SOCKET.LocalPort] ; load local port and remote port at once
|
||||
DEBUGF 1,"local port: %x, remote port: %x\n",[eax + SOCKET.LocalPort]:4, [eax + SOCKET.RemotePort]:4
|
||||
mov ebx, [eax + SOCKET.LocalIP]
|
||||
mov eax, [eax + SOCKET.RemoteIP]
|
||||
|
||||
call UDP_create_packet
|
||||
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
|
||||
.icmp:
|
||||
; note: for ICMP sockets the SOCKET.LocalPort is used as the 'Identifier' value for ICMP packets
|
||||
; the application must add the header to the data, the kernel will fill in 'identifier' and 'checksum'
|
||||
|
||||
sub ecx, ICMP_Packet.Data
|
||||
mov esi, edx
|
||||
push ax
|
||||
call IPv4_get_frgmnt_num
|
||||
mov dx, ax
|
||||
pop ax
|
||||
shl edx, 16
|
||||
mov dh , [esi + ICMP_Packet.Type]
|
||||
mov dl , [esi + ICMP_Packet.Code]
|
||||
mov di , [esi + ICMP_Packet.Identifier]
|
||||
; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's
|
||||
shl edi, 16
|
||||
mov di , [esi + ICMP_Packet.SequenceNumber]
|
||||
add esi, ICMP_Packet.Data
|
||||
mov ebx, [eax + SOCKET.LocalIP]
|
||||
mov eax, [eax + SOCKET.RemoteIP]
|
||||
call ICMP_create_packet
|
||||
call UDP_socket_send
|
||||
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
|
||||
.tcp:
|
||||
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
|
||||
;--------
|
||||
.raw:
|
||||
cmp [eax + SOCKET_head.Protocol], IP_PROTO_IP
|
||||
je .raw_ip
|
||||
|
||||
cmp [eax + SOCKET_head.Protocol], IP_PROTO_ICMP
|
||||
je .raw_icmp
|
||||
|
||||
jmp s_error
|
||||
;--------
|
||||
|
||||
|
||||
.raw_ip:
|
||||
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
|
||||
|
||||
.raw_icmp:
|
||||
|
||||
; sub ecx, ICMP_Packet.Data
|
||||
; mov esi, edx
|
||||
; push ax
|
||||
; call IPv4_get_frgmnt_num
|
||||
; mov dx, ax
|
||||
; pop ax
|
||||
; shl edx, 16
|
||||
; mov dh , [esi + ICMP_Packet.Type]
|
||||
; mov dl , [esi + ICMP_Packet.Code]
|
||||
; mov di , [esi + ICMP_Packet.Identifier]
|
||||
; mov [eax + SOCKET.LocalPort], di ; Set localport to the identifier number, so we can receive reply's
|
||||
; shl edi, 16
|
||||
; mov di , [esi + ICMP_Packet.SequenceNumber]
|
||||
; add esi, ICMP_Packet.Data
|
||||
; mov ebx, [eax + SOCKET.LocalIP]
|
||||
; mov eax, [eax + SOCKET.RemoteIP]
|
||||
; call ICMP_create_packet
|
||||
|
||||
mov [esp+32], eax
|
||||
ret
|
||||
|
||||
|
||||
|
||||
@ -812,15 +874,15 @@ socket_find_port:
|
||||
mov esi, net_sockets
|
||||
|
||||
.next_socket:
|
||||
mov esi, [esi + SOCKET.NextPtr]
|
||||
mov esi, [esi + SOCKET_head.NextPtr]
|
||||
or esi, esi
|
||||
jz .port_ok
|
||||
|
||||
cmp [esi + SOCKET.Type], ecx
|
||||
cmp [esi + SOCKET_head.Type], ecx
|
||||
jne .next_socket
|
||||
|
||||
rol bx, 8
|
||||
cmp [esi + SOCKET.LocalPort], bx
|
||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
|
||||
rol bx, 8 ; this doesnt change the zero flag, does it ?
|
||||
jne .next_socket
|
||||
|
||||
@ -852,14 +914,14 @@ socket_check_port:
|
||||
mov esi, net_sockets
|
||||
|
||||
.next_socket:
|
||||
mov esi, [esi + SOCKET.NextPtr]
|
||||
mov esi, [esi + SOCKET_head.NextPtr]
|
||||
or esi, esi
|
||||
jz .port_ok
|
||||
|
||||
cmp [esi + SOCKET.Type], ecx
|
||||
cmp [esi + SOCKET_head.Type], ecx
|
||||
jne .next_socket
|
||||
|
||||
cmp [esi + SOCKET.LocalPort], bx
|
||||
cmp [esi + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
|
||||
jne .next_socket
|
||||
|
||||
xor ebx, ebx
|
||||
@ -868,19 +930,18 @@ socket_check_port:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------
|
||||
;
|
||||
; SOCKET_internal_receiver
|
||||
;
|
||||
; Checks if any socket wants the received data
|
||||
; If so, update the socket
|
||||
; Updates a socket with received data
|
||||
;
|
||||
; IN: eax = socket number
|
||||
; ecx = number of bytes
|
||||
; esi = pointer to beginning of data
|
||||
; dx = Remote port (in INET byte order)
|
||||
; edi = IP address of sender
|
||||
; Note: the mutex must already be set !
|
||||
;
|
||||
; IN: eax = socket ptr
|
||||
; ecx = size
|
||||
; esi = pointer to buffer
|
||||
; edi = offset
|
||||
;
|
||||
; OUT: xxx
|
||||
;
|
||||
@ -888,39 +949,20 @@ socket_check_port:
|
||||
align 4
|
||||
socket_internal_receiver:
|
||||
|
||||
DEBUGF 1,"internal socket receiver\n"
|
||||
DEBUGF 1,"Internal socket receiver: buffer %x, offset: %x\n", esi, edi
|
||||
|
||||
lea ebx, [eax + SOCKET.lock]
|
||||
call wait_mutex
|
||||
push edi ; offset
|
||||
push ecx ; size
|
||||
push esi ; data_ptr
|
||||
mov esi, esp
|
||||
add_to_queue (eax + 2048), SOCKET_QUEUE_SIZE, 3*4, .full
|
||||
DEBUGF 1,"Queued packet successfully\n"
|
||||
add esp, 4*3
|
||||
|
||||
mov [eax + SOCKET.RemotePort], dx ; update remote port number
|
||||
mov [eax + SOCKET.RemoteIP], edi
|
||||
|
||||
mov edx, [eax + SOCKET.rxDataCount] ; get # of bytes already in buffer
|
||||
DEBUGF 1,"bytes already in socket: %u ", edx
|
||||
|
||||
lea edi, [ecx + edx] ; check for buffer overflow
|
||||
cmp edi, SOCKETBUFFSIZE - SOCKETHEADERSIZE ;
|
||||
jg .dump ;
|
||||
|
||||
lea edi, [eax + SOCKET.rxData + edx]
|
||||
add [eax + SOCKET.rxDataCount], ecx ; increment the count of bytes in buffer
|
||||
DEBUGF 1,"adding %u bytes\n", ecx
|
||||
|
||||
; copy the data across
|
||||
push cx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
pop cx
|
||||
and cx, 3
|
||||
rep movsb
|
||||
|
||||
DEBUGF 1,"socket updated\n"
|
||||
|
||||
mov [eax + SOCKET.lock], 0
|
||||
mov [eax + SOCKET_head.lock], 0
|
||||
|
||||
; flag an event to the application
|
||||
mov edx, [eax + SOCKET.PID] ; get socket owner PID
|
||||
mov edx, [eax + SOCKET_head.PID] ; get socket owner PID
|
||||
mov ecx, 1
|
||||
mov esi, TASK_DATA + TASKDATA.pid
|
||||
|
||||
@ -939,14 +981,16 @@ socket_internal_receiver:
|
||||
mov [check_idle_semaphore], 200
|
||||
ret
|
||||
|
||||
.dump:
|
||||
mov [eax + SOCKET.lock], 0
|
||||
.full:
|
||||
DEBUGF 1,"Socket %x is full!\n",eax
|
||||
mov [eax + SOCKET_head.lock], 0
|
||||
call kernel_free
|
||||
add esp, 8
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; Allocate memory for socket data and put new socket into the list
|
||||
; Newly created socket is initialized with calling PID and number and
|
||||
; put into beginning of list (which is a fastest way).
|
||||
@ -963,27 +1007,30 @@ proc net_socket_alloc stdcall uses ebx ecx edx edi
|
||||
; zero-initialize allocated memory
|
||||
push eax
|
||||
mov edi, eax
|
||||
|
||||
mov ecx, SOCKETBUFFSIZE / 4
|
||||
; cld
|
||||
xor eax, eax
|
||||
rep stosd
|
||||
pop eax
|
||||
|
||||
init_queue (eax + 2048)
|
||||
|
||||
; add socket to the list by changing pointers
|
||||
mov ebx, net_sockets
|
||||
push [ebx + SOCKET.NextPtr]
|
||||
mov [ebx + SOCKET.NextPtr], eax
|
||||
mov [eax + SOCKET.PrevPtr], ebx
|
||||
push [ebx + SOCKET_head.NextPtr]
|
||||
mov [ebx + SOCKET_head.NextPtr], eax
|
||||
mov [eax + SOCKET_head.PrevPtr], ebx
|
||||
pop ebx
|
||||
mov [eax + SOCKET.NextPtr], ebx
|
||||
mov [eax + SOCKET_head.NextPtr], ebx
|
||||
or ebx, ebx
|
||||
jz @f
|
||||
mov [ebx + SOCKET.PrevPtr], eax
|
||||
mov [ebx + SOCKET_head.PrevPtr], eax
|
||||
|
||||
@@: ; set socket owner PID to the one of calling process
|
||||
mov ebx, [TASK_BASE]
|
||||
mov ebx, [ebx + TASKDATA.pid]
|
||||
mov [eax + SOCKET.PID], ebx
|
||||
mov [eax + SOCKET_head.PID], ebx
|
||||
|
||||
; find first free socket number and use it
|
||||
;mov edx, ebx
|
||||
@ -992,10 +1039,10 @@ proc net_socket_alloc stdcall uses ebx ecx edx edi
|
||||
.next_socket_number:
|
||||
inc ecx
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
mov ebx, [ebx + SOCKET_head.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .last_socket_number
|
||||
cmp [ebx + SOCKET.Number], ecx
|
||||
cmp [ebx + SOCKET_head.Number], ecx
|
||||
jne .next_socket
|
||||
;cmp [ebx + SOCKET.PID], edx
|
||||
;jne .next_socket
|
||||
@ -1003,7 +1050,7 @@ proc net_socket_alloc stdcall uses ebx ecx edx edi
|
||||
jmp .next_socket_number
|
||||
|
||||
.last_socket_number:
|
||||
mov [eax + SOCKET.Number], ecx
|
||||
mov [eax + SOCKET_head.Number], ecx
|
||||
|
||||
.exit:
|
||||
ret
|
||||
@ -1025,7 +1072,7 @@ proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
|
||||
;mov ecx, [TASK_BASE]
|
||||
;mov ecx, [ecx + TASKDATA.pid]
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
mov ebx, [ebx + SOCKET_head.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .error
|
||||
cmp ebx, eax
|
||||
@ -1035,12 +1082,15 @@ proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
|
||||
|
||||
; okay, we found the correct one
|
||||
; remove it from the list first, changing pointers
|
||||
mov ebx, [eax + SOCKET.NextPtr]
|
||||
mov eax, [eax + SOCKET.PrevPtr]
|
||||
mov [eax + SOCKET.NextPtr], ebx
|
||||
mov ebx, [eax + SOCKET_head.NextPtr]
|
||||
mov eax, [eax + SOCKET_head.PrevPtr]
|
||||
mov [eax + SOCKET_head.NextPtr], ebx
|
||||
or ebx, ebx
|
||||
jz @f
|
||||
mov [ebx + SOCKET.PrevPtr], eax
|
||||
mov [ebx + SOCKET_head.PrevPtr], eax
|
||||
|
||||
lea ebx, [eax + SOCKET_head.lock]
|
||||
call wait_mutex
|
||||
|
||||
@@: ; and finally free the memory structure used
|
||||
stdcall kernel_free, [sockAddr]
|
||||
@ -1070,10 +1120,10 @@ proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
|
||||
;mov ecx, [TASK_BASE]
|
||||
;mov ecx, [ecx + TASKDATA.pid]
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
mov ebx, [ebx + SOCKET_head.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .error
|
||||
cmp [ebx + SOCKET.Number], eax
|
||||
cmp [ebx + SOCKET_head.Number], eax
|
||||
jne .next_socket
|
||||
;cmp [ebx + SOCKET.PID], ecx
|
||||
;jne .next_socket
|
||||
@ -1106,7 +1156,7 @@ proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
|
||||
;mov ecx, [TASK_BASE]
|
||||
;mov ecx, [ecx + TASKDATA.pid]
|
||||
.next_socket:
|
||||
mov ebx, [ebx + SOCKET.NextPtr]
|
||||
mov ebx, [ebx + SOCKET_head.NextPtr]
|
||||
or ebx, ebx
|
||||
jz .error
|
||||
cmp ebx, eax
|
||||
@ -1115,7 +1165,7 @@ proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
|
||||
;jne .next_socket
|
||||
|
||||
; okay, we found the correct one
|
||||
mov eax, [ebx + SOCKET.Number]
|
||||
mov eax, [ebx + SOCKET_head.Number]
|
||||
ret
|
||||
|
||||
.error:
|
||||
|
@ -33,7 +33,7 @@ ETHER equ 1337
|
||||
ETHER_ARP equ 0x0608
|
||||
|
||||
;AF_UNSPEC equ 0
|
||||
;AF_UNIX equ 1
|
||||
AF_UNIX equ 1
|
||||
AF_INET4 equ 2
|
||||
;AF_AX25 equ 3
|
||||
;AF_IPX equ 4
|
||||
@ -64,7 +64,7 @@ include "ARP.inc"
|
||||
include "IPv4.inc"
|
||||
include "ethernet.inc"
|
||||
include "socket.inc"
|
||||
;include "tcp.inc"
|
||||
include "tcp.inc"
|
||||
include "udp.inc"
|
||||
include "icmp.inc"
|
||||
|
||||
@ -86,6 +86,7 @@ stack_init:
|
||||
call IPv4_init
|
||||
call ARP_init
|
||||
call UDP_init
|
||||
call TCP_init
|
||||
call ICMP_init
|
||||
call socket_init
|
||||
|
||||
@ -115,20 +116,20 @@ stack_handler:
|
||||
cmp [ETH_RUNNING], 0
|
||||
je .exit
|
||||
|
||||
call ETH_handler ; handle all queued ethernet packets
|
||||
call ETH_send_queued
|
||||
|
||||
; Test for 10ms tick, call tcp timer
|
||||
; Test for 10ms tick
|
||||
mov eax, [timer_ticks]
|
||||
cmp eax, [last_1hsTick]
|
||||
je .exit
|
||||
|
||||
mov [last_1hsTick], eax
|
||||
; call tcp_tx_handler
|
||||
|
||||
call ETH_handler ; handle all queued ethernet packets
|
||||
call ETH_send_queued
|
||||
call TCP_send_queued
|
||||
|
||||
.sec_tick:
|
||||
|
||||
; Test for 1 second event, call 1s timer functions
|
||||
; Test for 1 second event
|
||||
mov al, 0x0 ;second
|
||||
out 0x70, al
|
||||
in al, 0x71
|
||||
@ -139,48 +140,84 @@ stack_handler:
|
||||
|
||||
call ARP_decrease_entry_ttls
|
||||
call IPv4_decrease_fragment_ttls
|
||||
; call tcp_tcb_handler
|
||||
call TCP_decrease_socket_ttls
|
||||
|
||||
.exit:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Checksum [by Johnny_B]
|
||||
;; IN:
|
||||
;; buf_ptr=POINTER to buffer
|
||||
;; buf_size=SIZE of buffer
|
||||
;; OUT:
|
||||
;; AX=16-bit checksum
|
||||
;; Saves all used registers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
proc checksum_jb stdcall uses ebx esi ecx,\
|
||||
buf_ptr:DWORD, buf_size:DWORD
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; checksum_1
|
||||
;
|
||||
; This is the first of two functions needed to calculate the TCP checksum.
|
||||
;
|
||||
; IN: edx = start offeset for semi-checksum
|
||||
; esi = pointer to data
|
||||
; ecx = data size
|
||||
; OUT: edx = semi-checksum
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
checksum_1:
|
||||
|
||||
xor eax, eax
|
||||
xor ebx, ebx ;accumulator
|
||||
mov esi, dword[buf_ptr]
|
||||
mov ecx, dword[buf_size]
|
||||
shr ecx, 1 ; ecx=ecx/2
|
||||
jnc @f ; if CF==0 then size is even number
|
||||
mov bh, byte[esi + ecx*2]
|
||||
@@:
|
||||
cld
|
||||
|
||||
.loop:
|
||||
lodsw ;eax=word[esi],esi=esi+2
|
||||
xchg ah,al ;cause must be a net byte-order
|
||||
add ebx, eax
|
||||
shr ecx, 1
|
||||
pushf
|
||||
.loop:
|
||||
lodsw
|
||||
xchg al, ah
|
||||
add edx, eax
|
||||
loop .loop
|
||||
|
||||
mov eax, ebx
|
||||
shr eax, 16
|
||||
add ax, bx
|
||||
not ax
|
||||
popf
|
||||
jnc .end
|
||||
|
||||
lodsb
|
||||
shl ax, 8
|
||||
add edx, eax
|
||||
|
||||
.end:
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; checksum_2
|
||||
;
|
||||
; This function calculates the final ip/tcp/udp checksum for you
|
||||
;
|
||||
; IN: edx = semi-checksum
|
||||
; OUT: dx = checksum (in INET byte order)
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
align 4
|
||||
checksum_2:
|
||||
|
||||
mov ecx, edx
|
||||
shr ecx, 16
|
||||
and edx, 0xffff
|
||||
add edx, ecx
|
||||
mov eax, edx
|
||||
shr eax, 16
|
||||
add edx, eax
|
||||
|
||||
not dx
|
||||
jnz .not_zero
|
||||
dec dx
|
||||
.not_zero:
|
||||
xchg dl, dh
|
||||
|
||||
DEBUGF 1,"Checksum: %x\n",dx
|
||||
|
||||
ret
|
||||
endp
|
||||
|
||||
|
||||
|
||||
@ -250,6 +287,14 @@ sys_network:
|
||||
jmp .return
|
||||
|
||||
@@:
|
||||
dec bl ; 4 = Get driver pointer
|
||||
jnz @f
|
||||
|
||||
; ..;
|
||||
|
||||
|
||||
@@:
|
||||
; ... ; 5 Get driver name
|
||||
|
||||
.doesnt_exist:
|
||||
DEBUGF 1,"sys_network: invalid device/function specified!\n"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -75,7 +75,33 @@ align 4
|
||||
UDP_handler:
|
||||
|
||||
DEBUGF 1,"UDP_Handler\n"
|
||||
; TODO: First validate the header & checksum!
|
||||
; First validate, checksum:
|
||||
|
||||
DEBUGF 1,"Real UDP checksum: %x\n", [edx + UDP_Packet.Checksum]:4
|
||||
mov [edx + UDP_Packet.Checksum], 0
|
||||
|
||||
pusha
|
||||
|
||||
rol cx, 8
|
||||
push cx
|
||||
rol cx, 8
|
||||
push word IP_PROTO_UDP shl 8
|
||||
push edi
|
||||
push esi
|
||||
|
||||
mov esi, edx
|
||||
xor edx, edx
|
||||
call checksum_1
|
||||
; Checksum for pseudoheader
|
||||
mov ecx, 12
|
||||
mov esi, esp
|
||||
call checksum_1
|
||||
add esp, 12
|
||||
call checksum_2
|
||||
|
||||
popa
|
||||
|
||||
|
||||
|
||||
; Look for a socket where
|
||||
; IP Packet UDP Destination Port = local Port
|
||||
@ -85,14 +111,14 @@ UDP_handler:
|
||||
.try_more:
|
||||
mov bx , [edx + UDP_Packet.DestinationPort] ; get the local port from the IP Packet's UDP header
|
||||
.next_socket:
|
||||
mov eax, [eax + SOCKET.NextPtr]
|
||||
mov eax, [eax + SOCKET_head.NextPtr]
|
||||
or eax, eax
|
||||
jz .dump
|
||||
cmp [eax + SOCKET.Domain], AF_INET4
|
||||
cmp [eax + SOCKET_head.Domain], AF_INET4
|
||||
jne .next_socket
|
||||
cmp [eax + SOCKET.Type], IP_PROTO_UDP
|
||||
cmp [eax + SOCKET_head.Type], IP_PROTO_UDP
|
||||
jne .next_socket
|
||||
cmp [eax + SOCKET.LocalPort], bx
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort], bx
|
||||
jne .next_socket
|
||||
|
||||
DEBUGF 1,"found socket with matching domain, type and localport\n"
|
||||
@ -101,12 +127,12 @@ UDP_handler:
|
||||
; 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 [eax + SOCKET.RemoteIP], 0xffffffff
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], 0xffffffff
|
||||
je .ok1
|
||||
|
||||
mov ebx, [esp]
|
||||
mov ebx, [ebx + ETH_FRAME.Data + IPv4_Packet.SourceAddress] ; get the Source address from the IP Packet FIXME
|
||||
cmp [eax + SOCKET.RemoteIP], ebx
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], ebx
|
||||
jne .try_more ; Quit if the source IP is not valid, check for more sockets with this IP/PORT combination
|
||||
|
||||
|
||||
@ -115,10 +141,10 @@ UDP_handler:
|
||||
|
||||
mov bx, [edx + UDP_Packet.SourcePort] ; Remote port must be 0, or equal to sourceport of packet
|
||||
|
||||
cmp [eax + SOCKET.RemotePort], 0
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], 0
|
||||
je .ok2
|
||||
|
||||
cmp [eax + SOCKET.RemotePort], bx
|
||||
cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], bx
|
||||
jne .dump
|
||||
|
||||
.ok2:
|
||||
@ -130,10 +156,21 @@ UDP_handler:
|
||||
sub cx , UDP_Packet.Data
|
||||
mov dx , bx
|
||||
|
||||
call socket_internal_receiver
|
||||
|
||||
lea ebx, [eax + SOCKET_head.lock]
|
||||
call wait_mutex
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort], dx ; update remote port number
|
||||
mov [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP], edi
|
||||
inc [UDP_PACKETS_RX]
|
||||
|
||||
pop edi
|
||||
add esp, 4
|
||||
|
||||
sub esi, edi
|
||||
xchg esi, edi
|
||||
jmp socket_internal_receiver
|
||||
|
||||
|
||||
.dump:
|
||||
DEBUGF 1,"Dumping UDP packet\n"
|
||||
call kernel_free
|
||||
@ -146,69 +183,93 @@ UDP_handler:
|
||||
|
||||
;-----------------------------------------------------------------
|
||||
;
|
||||
; Note: UDP works only on top of IP protocol :)
|
||||
; UDP_socket_send
|
||||
;
|
||||
; IN: eax = dest ip
|
||||
; ebx = source ip
|
||||
; ecx = data length
|
||||
; edx = remote port shl 16 + local port (both in INET order)
|
||||
; esi = data offset
|
||||
; IN: eax = socket pointer
|
||||
; ecx = number of bytes to send
|
||||
; esi = pointer to data
|
||||
;
|
||||
;-----------------------------------------------------------------
|
||||
|
||||
UDP_create_packet:
|
||||
align 4
|
||||
UDP_socket_send:
|
||||
|
||||
mov edx, dword [eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort] ; load local port and remote port at once
|
||||
DEBUGF 1,"local port: %x, remote port: %x\n",\
|
||||
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.LocalPort]:4,\
|
||||
[eax + SOCKET_head.end + IPv4_SOCKET.end + UDP_SOCKET.RemotePort]:4
|
||||
mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP]
|
||||
mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP]
|
||||
|
||||
DEBUGF 1,"Create UDP Packet (size=%u)\n",ecx
|
||||
|
||||
push edx esi
|
||||
|
||||
add ecx, UDP_Packet.Data
|
||||
mov di , IP_PROTO_UDP
|
||||
|
||||
; dx = fragment id
|
||||
sub esp, 8 ; reserve some place in stack for later
|
||||
|
||||
; Create the pseudoheader in stack,
|
||||
; (now that we still have all the variables that are needed.)
|
||||
push dword IP_PROTO_UDP shl 8
|
||||
push eax
|
||||
push ebx
|
||||
|
||||
add ecx, UDP_Packet.Data
|
||||
|
||||
; TODO: fill in: dx = fragment id
|
||||
|
||||
push edx esi
|
||||
call IPv4_create_packet ; TODO: figure out a way to choose between IPv4 and IPv6
|
||||
cmp edi, -1
|
||||
je .fail
|
||||
|
||||
mov byte[edi + UDP_Packet.Length], ch
|
||||
mov byte[edi + UDP_Packet.Length+1], cl
|
||||
sub ecx , UDP_Packet.Data
|
||||
mov [esp + 8 + 12], eax ; pointer to buffer start
|
||||
mov [esp + 8 + 12 + 4], edx ; buffer size
|
||||
|
||||
rol cx, 8
|
||||
mov [edi + UDP_Packet.Length], cx
|
||||
mov [esp + 8 + 10], cx
|
||||
ror cx, 8
|
||||
|
||||
pop esi
|
||||
push edi
|
||||
push edi ecx
|
||||
sub ecx, UDP_Packet.Data
|
||||
add edi, UDP_Packet.Data
|
||||
push cx
|
||||
shr ecx, 2
|
||||
rep movsd
|
||||
pop cx
|
||||
mov ecx, [esp]
|
||||
and cx , 3
|
||||
rep movsb
|
||||
pop edi
|
||||
pop ecx edi
|
||||
|
||||
pop ecx
|
||||
mov dword [edi + UDP_Packet.SourcePort], ecx ; notice: we write both port's at once
|
||||
pop dword [edi + UDP_Packet.SourcePort] ; fill in both portnumbers
|
||||
mov [edi + UDP_Packet.Checksum], 0 ; set it to zero, to calculate checksum
|
||||
|
||||
mov [edi + UDP_Packet.Checksum], 0
|
||||
|
||||
; TODO: calculate checksum using Pseudo-header (However, using a 0 as checksum shouldnt generate any errors :)
|
||||
; Checksum for UDP header + data
|
||||
xor edx, edx
|
||||
mov esi, edi
|
||||
call checksum_1
|
||||
; Checksum for pseudoheader
|
||||
mov ecx, 12
|
||||
mov esi, esp
|
||||
call checksum_1
|
||||
add esp, 12 ; remove the pseudoheader from stack
|
||||
; Now create the final checksum and store it in UDP header
|
||||
call checksum_2
|
||||
mov [edi + UDP_Packet.Checksum], dx
|
||||
|
||||
inc [UDP_PACKETS_TX]
|
||||
|
||||
push edx eax ; TODO: make this work on other protocols besides ethernet
|
||||
DEBUGF 1,"Sending UDP Packet to device %x\n", ebx ;
|
||||
jmp ETH_Sender ;
|
||||
|
||||
.exit:
|
||||
ret
|
||||
jmp ETH_sender ;
|
||||
|
||||
.fail:
|
||||
; todo: queue the packet
|
||||
add esp, 8
|
||||
add esp, 8+12+8
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
;
|
||||
; UDP_API
|
||||
|
Loading…
Reference in New Issue
Block a user