Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 3544 → Rev 3545

/kernel/trunk/network/stack.inc
1,918 → 1,789
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;; STACK.INC ;;
;; ;;
;; TCP/IP stack for Menuet OS ;;
;; TCP/IP stack for KolibriOS ;;
;; ;;
;; Copyright 2002 Mike Hibbett, mikeh@oceanfree.net ;;
;; Written by hidnplayr@kolibrios.org ;;
;; ;;
;; See file COPYING for details ;;
;; Some parts of code are based on the work of: ;;
;; Mike Hibbett (menuetos network stack) ;;
;; Eugen Brasoveanu (solar os network stack and drivers) ;;
;; mike.dld (kolibrios socket code) ;;
;; ;;
;; Version 0.7 ;;
;; Added a timer per socket to allow delays when rx window ;;
;; gets below 1KB ;;
;; TCP part is based on 4.4BSD ;;
;; ;;
;;10.01.2007 Bugfix for checksum function from Paolo Franchetti ;;
;; GNU GENERAL PUBLIC LICENSE ;;
;; Version 2, June 1991 ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
$Revision$
$Revision: 3523 $
 
 
;*******************************************************************
; Interface
; The interfaces defined in ETHERNET.INC plus:
; stack_init
; stack_handler
; app_stack_handler
; app_socket_handler
; checksum
;
;*******************************************************************
 
uglobal
StackCounters:
dumped_rx_count dd 0
arp_tx_count:
dd 0
arp_rx_count:
dd 0
ip_rx_count:
dd 0
ip_tx_count:
dd 0
net_10ms dd ?
net_tmr_count dw ?
endg
 
; socket buffers
SOCKETBUFFSIZE equ 4096 ; state + config + buffer.
SOCKETHEADERSIZE equ SOCKET.rxData ; thus 4096 - SOCKETHEADERSIZE bytes data
MAX_NET_DEVICES = 16
ARP_BLOCK = 1 ; true or false
 
;NUM_SOCKETS equ 16 ; Number of open sockets supported. Was 20
MIN_EPHEMERAL_PORT = 49152
MIN_EPHEMERAL_PORT_N = 0x00C0 ; same in Network byte order (FIXME)
MAX_EPHEMERAL_PORT = 61000
MAX_EPHEMERAL_PORT_N = 0x48EE ; same in Network byte order (FIXME)
 
; IPBUFF status values
BUFF_EMPTY equ 0
BUFF_RX_FULL equ 1
BUFF_ALLOCATED equ 2
BUFF_TX_FULL equ 3
; Ethernet protocol numbers
ETHER_ARP = 0x0608
ETHER_IPv4 = 0x0008
ETHER_IPv6 = 0xDD86
ETHER_PPP_DISCOVERY = 0x6388
ETHER_PPP_SESSION = 0x6488
 
NUM_IPBUFFERS equ 20 ; buffers allocated for TX/RX
; PPP protocol numbers
PPP_IPv4 = 0x2100
PPP_IPV6 = 0x5780
 
NUMQUEUES equ 4
;Protocol family
AF_UNSPEC = 0
AF_LOCAL = 1
AF_INET4 = 2
AF_INET6 = 10
AF_PPP = 777
 
EMPTY_QUEUE equ 0
IPIN_QUEUE equ 1
IPOUT_QUEUE equ 2
NET1OUT_QUEUE equ 3
; Internet protocol numbers
IP_PROTO_IP = 0
IP_PROTO_ICMP = 1
IP_PROTO_TCP = 6
IP_PROTO_UDP = 17
 
NO_BUFFER equ 0xFFFF
IPBUFFSIZE equ 1500 ; MTU of an ethernet packet
NUMQUEUEENTRIES equ NUM_IPBUFFERS
NUMRESENDENTRIES equ 18 ; Buffers for TCP resend packets
; PPP protocol number
PPP_PROTO_ETHERNET = 666
 
; These are the 0x40 function codes for application access to the stack
STACK_DRIVER_STATUS equ 52
SOCKET_INTERFACE equ 53
; Socket types
SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
 
; Socket options
SO_ACCEPTCON = 1 shl 0
SO_BROADCAST = 1 shl 1
SO_DEBUG = 1 shl 2
SO_DONTROUTE = 1 shl 3
SO_KEEPALIVE = 1 shl 4
SO_OOBINLINE = 1 shl 5
SO_REUSEADDR = 1 shl 6
SO_REUSEPORT = 1 shl 7
SO_USELOOPBACK = 1 shl 8
SO_BINDTODEVICE = 1 shl 9
 
; 128KB allocated for the stack and network driver buffers and other
; data requirements
;stack_data_start equ 0x700000
;eth_data_start equ 0x700000
;stack_data equ 0x704000
;stack_data_end equ 0x71ffff
SO_BLOCK = 1 shl 10 ; TO BE REMOVED
SO_NONBLOCK = 1 shl 31
 
; 32 bit word
stack_config equ stack_data
; Socket flags for user calls
MSG_PEEK = 0x02
MSG_DONTWAIT = 0x40
 
; 32 bit word - IP Address in network format
stack_ip equ stack_data + 4
; Socket level
SOL_SOCKET = 0
 
; 1 byte. 0 == inactive, 1 = active
ethernet_active equ stack_data + 9
 
; Socket States
SS_NOFDREF = 0x0001 ; no file table ref any more
SS_ISCONNECTED = 0x0002 ; socket connected to a peer
SS_ISCONNECTING = 0x0004 ; in process of connecting to peer
SS_ISDISCONNECTING = 0x0008 ; in process of disconnecting
SS_CANTSENDMORE = 0x0010 ; can't send more data to peer
SS_CANTRCVMORE = 0x0020 ; can't receive more data from peer
SS_RCVATMARK = 0x0040 ; at mark on input
SS_ISABORTING = 0x0080 ; aborting fd references - close()
SS_RESTARTSYS = 0x0100 ; restart blocked system calls
SS_ISDISCONNECTED = 0x0800 ; socket disconnected from peer
 
; TODO :: empty memory area
SS_ASYNC = 0x0100 ; async i/o notify
SS_ISCONFIRMING = 0x0200 ; deciding to accept connection req
SS_MORETOCOME = 0x0400
 
; Address of selected socket
;sktAddr equ stack_data + 32
; Parameter to checksum routine - data ptr
checkAdd1 equ stack_data + 36
; Parameter to checksum routine - 2nd data ptr
checkAdd2 equ stack_data + 40
; Parameter to checksum routine - data size
checkSize1 equ stack_data + 44
; Parameter to checksum routine - 2nd data size
checkSize2 equ stack_data + 46
; result of checksum routine
checkResult equ stack_data + 48
SS_BLOCKED = 0x8000
 
; holds the TCP/UDP pseudo header. SA|DA|0|prot|UDP len|
pseudoHeader equ stack_data + 50
 
; receive and transmit IP buffer allocation
;sockets equ stack_data + 62
Next_free2 equ stack_data + 62;Next_free2 equ sockets + (SOCKETBUFFSIZE * NUM_SOCKETS)
; 1560 byte buffer for rx / tx ethernet packets
Ether_buffer equ Next_free2
Next_free3 equ Ether_buffer + 1518
last_1sTick equ Next_free3
IPbuffs equ Next_free3 + 1
queues equ IPbuffs + ( NUM_IPBUFFERS * IPBUFFSIZE )
queueList equ queues + (2 * NUMQUEUES)
last_1hsTick equ queueList + ( 2 * NUMQUEUEENTRIES )
SOCKET_MAXDATA = 4096*32 ; must be 4096*(power of 2) where 'power of 2' is at least 8
 
;resendQ equ queueList + ( 2 * NUMQUEUEENTRIES )
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP
; equ resendBuffer + ( IPBUFFSIZE * NUMRESENDENTRIES )
; Network driver types
NET_TYPE_LOOPBACK = 0
NET_TYPE_ETH = 1
NET_TYPE_SLIP = 2
 
MAX_backlog = 20 ; maximum backlog for stream sockets
 
; Error Codes
ENOBUFS = 55
ECONNREFUSED = 61
ECONNRESET = 52
ETIMEDOUT = 60
ECONNABORTED = 53
 
;resendQ equ 0x770000
;resendBuffer equ resendQ + ( 4 * NUMRESENDENTRIES ) ; for TCP ; XTODO: validate size
resendBuffer equ resendQ + ( 8 * NUMRESENDENTRIES ) ; for TCP
; Api protocol numbers
API_ETH = 0
API_IPv4 = 1
API_ICMP = 2
API_UDP = 3
API_TCP = 4
API_ARP = 5
API_PPPOE = 6
API_IPv6 = 7
 
HWACC_TCP_IPv4 = 1 shl 0
 
uglobal
net_sockets rd 2
endg
struct NET_DEVICE
 
; simple macro for memory set operation
macro _memset_dw adr,value,amount
{
mov edi, adr
mov ecx, amount
if value = 0
xor eax, eax
else
mov eax, value
end if
cld
rep stosd
type dd ? ; Type field
mtu dd ? ; Maximal Transmission Unit
name dd ? ; Ptr to 0 terminated string
 
unload dd ? ; Ptrs to driver functions
reset dd ? ;
transmit dd ? ;
 
bytes_tx dq ? ; Statistics, updated by the driver
bytes_rx dq ? ;
packets_tx dd ? ;
packets_rx dd ? ;
 
state dd ? ; link state (0 = no link)
hwacc dd ? ; bitmask stating enabled HW accelerations (offload engines)
 
ends
 
 
; Exactly as it says..
macro pseudo_random reg {
add reg, [esp]
rol reg, 5
xor reg, [timer_ticks]
; add reg, [CPU_FREQ]
imul reg, 214013
xor reg, 0xdeadbeef
rol reg, 9
}
 
; Network to Hardware byte order (dword)
macro ntohd reg {
 
; Below, the main network layer source code is included
;
rol word reg, 8
rol dword reg, 16
rol word reg , 8
 
}
 
; Network to Hardware byte order (word)
macro ntohw reg {
 
rol word reg, 8
 
}
 
 
include "queue.inc"
include "eth_drv/ethernet.inc"
include "ip.inc"
 
include "loopback.inc"
include "ethernet.inc"
 
include "PPPoE.inc"
 
include "ARP.inc"
include "IPv4.inc"
include "IPv6.inc"
 
include "icmp.inc"
include "udp.inc"
include "tcp.inc"
 
include "socket.inc"
 
;***************************************************************************
; Function
 
 
align 4
uglobal
 
NET_RUNNING dd ?
NET_DEFAULT dd ?
NET_DRV_LIST rd MAX_NET_DEVICES
 
endg
 
 
;-----------------------------------------------------------------
;
; stack_init
;
; Description
; Clear all allocated memory to zero. This ensures that
; on startup, the stack is inactive, and consumes no resources
; This is a kernel function, called prior to the OS main loop
; in set_variables
; This function calls all network init procedures
;
;***************************************************************************
 
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_init:
; Init two address spaces with default values
_memset_dw stack_data_start, 0, 0x20000/4
_memset_dw resendQ, 0, NUMRESENDENTRIES * 2
 
mov [net_sockets], 0
mov [net_sockets + 4], 0
; Init the network drivers list
xor eax, eax
mov edi, NET_RUNNING
mov ecx, (MAX_NET_DEVICES + 2)
rep stosd
 
; Queries initialization
call queueInit
PPPoE_init
 
; The following block sets up the 1s timer
mov al, 0x0
out 0x70, al
in al, 0x71
mov [last_1sTick], al
IPv4_init
; IPv6_init
ICMP_init
 
ARP_init
UDP_init
TCP_init
 
SOCKET_init
 
mov [net_tmr_count], 0
 
ret
 
 
 
; Wakeup every tick.
proc stack_handler_has_work?
 
mov eax, [timer_ticks]
cmp eax, [last_1hsTick]
cmp eax, [net_10ms]
 
ret
endp
 
 
;***************************************************************************
; Function
;-----------------------------------------------------------------
;
; stack_handler
;
; Description
; The kernel loop routine for the stack
; This is a kernel function, called in the main loop
; This function is called in kernel loop
;
;***************************************************************************
; IN: /
; OUT: /
;
;-----------------------------------------------------------------
align 4
stack_handler:
 
call ethernet_driver
call ip_rx
; Test for 10ms tick
mov eax, [timer_ticks]
cmp eax, [net_10ms]
je .exit
mov [net_10ms], eax
 
cmp [NET_RUNNING], 0
je .exit
 
; Test for 10ms tick, call tcp timer
mov eax, [timer_ticks];[0xfdf0]
cmp eax, [last_1hsTick]
je sh_001
test [net_10ms], 0x0f ; 160ms
jnz .exit
 
mov [last_1hsTick], eax
call tcp_tx_handler
TCP_timer_160ms
 
sh_001:
test [net_10ms], 0x3f ; 640ms
jnz .exit
 
; Test for 1 second event, call 1s timer functions
mov al, 0x0;second
out 0x70, al
in al, 0x71
cmp al, [last_1sTick]
je sh_exit
TCP_timer_640ms
ARP_decrease_entry_ttls
IPv4_decrease_fragment_ttls
 
mov [last_1sTick], al
.exit:
ret
 
stdcall arp_table_manager, ARP_TABLE_TIMER, 0, 0
call tcp_tcb_handler
 
sh_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
align 4
NET_link_changed:
 
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
DEBUGF 1,"NET_link_changed device=0x%x status=0x%x\n", ebx, [ebx + NET_DEVICE.state]
 
align 4
NET_send_event:
 
DEBUGF 1,"NET_send_event\n"
 
; Send event to all applications
push edi ecx
mov edi, SLOT_BASE
mov ecx, [TASK_COUNT]
.loop:
lodsw ;eax=word[esi],esi=esi+2
xchg ah, al;cause must be a net byte-order
add ebx, eax
add edi, 256
or [edi + APPDATA.event_mask], EVENT_NETWORK2
loop .loop
pop ecx edi
 
mov eax, ebx
shr eax, 16
add ax, bx
not ax
 
ret
endp
 
;***************************************************************************
; Function
; checksum
 
 
;-----------------------------------------------------------------
;
; Description
; checkAdd1,checkAdd2, checkSize1, checkSize2, checkResult
; Dont break anything; Most registers are used by the caller
; This code is derived from the 'C' source, cksum.c, in the book
; Internetworking with TCP/IP Volume II by D.E. Comer
; NET_add_device:
;
;***************************************************************************
; This function is called by the network drivers,
; to register each running NIC to the kernel
;
; IN: Pointer to device structure in ebx
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
NET_add_device:
 
DEBUGF 1,"NET_Add_Device: %x\n", ebx ;;; TODO: use mutex to lock net device list
 
checksum:
pusha
mov eax, [checkAdd1]
xor edx, edx ; edx is the accumulative checksum
xor ebx, ebx
mov cx, [checkSize1]
shr cx, 1
jz cs1_1
cmp [NET_RUNNING], MAX_NET_DEVICES
jae .error
 
cs1:
mov bh, [eax]
mov bl, [eax + 1]
;----------------------------------
; Check if device is already listed
mov eax, ebx
mov ecx, MAX_NET_DEVICES ; We need to check whole list because a device may be removed without re-organizing list
mov edi, NET_DRV_LIST
 
add eax, 2
add edx, ebx
repne scasd ; See if device is already in the list
jz .error
 
loopw cs1
;----------------------------
; Find empty slot in the list
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
cs1_1:
and word [checkSize1], 0x01
jz cs_test2
repne scasd
jnz .error
 
mov bh, [eax]
xor bl, bl
sub edi, 4
 
add edx, ebx
;-----------------------------
; Add device to the found slot
mov [edi], ebx ; add device to list
 
cs_test2:
mov cx, [checkSize2]
cmp cx, 0
jz cs_exit ; Finished if no 2nd buffer
mov eax, edi ; Calculate device number in eax
sub eax, NET_DRV_LIST
shr eax, 2
 
mov eax, [checkAdd2]
inc [NET_RUNNING] ; Indicate that one more network device is up and running
 
shr cx, 1
jz cs2_1
cmp eax, 1 ; If it's the first network device, try to set it as default
jne @f
push eax
call NET_set_default
pop eax
@@:
 
cs2:
mov bh, [eax]
mov bl, [eax + 1]
call NET_send_event
 
add eax, 2
add edx, ebx
DEBUGF 1,"Device number: %u\n", eax
ret
 
loopw cs2
 
cs2_1:
and word [checkSize2], 0x01
jz cs_exit
 
mov bh, [eax]
xor bl, bl
 
add edx, ebx
 
cs_exit:
mov ebx, edx
 
shr ebx, 16
and edx, 0xffff
add edx, ebx
mov eax, edx
shr eax, 16
add edx, eax
not dx
 
mov [checkResult], dx
popa
.error:
or eax, -1
DEBUGF 2,"Adding network device failed\n"
ret
 
 
 
 
;***************************************************************************
; Function
; app_stack_handler
;-----------------------------------------------------------------
;
; Description
; This is an application service, called by int 0x40, function 52
; It provides application access to the network interface layer
; NET_set_default
;
;***************************************************************************
iglobal
; API to set the default interface
;
; IN: Device num in eax
; OUT: Device num in eax, -1 on error
;
;-----------------------------------------------------------------
align 4
f52call:
dd app_stack_handler.00
dd app_stack_handler.01
dd app_stack_handler.02
dd app_stack_handler.03
dd app_stack_handler.fail ;04
dd app_stack_handler.fail ;05
dd stack_insert_packet ;app_stack_handler.06
dd app_stack_handler.fail ;07
dd stack_get_packet ;app_stack_handler.08
dd app_stack_handler.09
dd app_stack_handler.10
dd app_stack_handler.11
dd app_stack_handler.12
dd app_stack_handler.13
dd app_stack_handler.14
dd app_stack_handler.15
endg
app_stack_handler:
;in ebx,ecx
;out eax
cmp ebx, 15
ja .fail ;if more than 15 then exit
NET_set_default:
 
jmp dword [f52call+ebx*4]
DEBUGF 1,"NET_set_default: device=%x\n", eax
 
cmp eax, MAX_NET_DEVICES
jae .error
 
.00:
; Read the configuration word
mov eax, [stack_config]
cmp [NET_DRV_LIST+eax*4], 0
je .error
 
mov [NET_DEFAULT], eax
 
DEBUGF 1,"NET_set_default: succes\n"
ret
 
.01:
; read the IP address
mov eax, [stack_ip]
.error:
or eax, -1
DEBUGF 1,"NET_set_default: failed\n"
ret
 
.02:
; write the configuration word
mov [stack_config], ecx
 
; <Slip shouldn't be active anyway - thats an operational issue.>
; If ethernet now enabled, probe for the card, reset it and empty
; the packet buffer
; If all successfull, enable the card.
; If ethernet now disabled, set it as disabled. Should really
; empty the tcpip data area too.
;-----------------------------------------------------------------
;
; NET_Remove_Device:
;
; This function is called by etwork drivers,
; to unregister network devices from the kernel
;
; IN: Pointer to device structure in ebx
; OUT: eax: -1 on error
;
;-----------------------------------------------------------------
align 4
NET_remove_device:
 
; ethernet interface is '3' in ls 7 bits
and cl, 0x7f
cmp cl, 3
je ash_eth_enable
; Ethernet isn't enabled, so make sure that the card is disabled
mov [ethernet_active], byte 0
ret
cmp [NET_RUNNING], 0
je .error
 
.03:
; write the IP Address
mov [stack_ip], ecx
ret
;old functions was deleted
;.06:
; Insert an IP packet into the stacks received packet queue
; call stack_insert_packet
; ret
cmp [NET_DRV_LIST], ebx
jne @f
mov [NET_DRV_LIST], 0
cmp [NET_RUNNING], 1
je @f
; there are still active devices, find one and make it default
xor eax, eax
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
repe scasd
je @f
shr edi, 2
dec edi
mov [NET_DEFAULT], edi
@@:
 
; Test for any packets queued for transmission over the network
;----------------------------
; Find the driver in the list
 
;.08:
; call stack_get_packet
; Extract a packet queued for transmission by the network
; ret
mov eax, ebx
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST+4
 
.09:
; read the gateway IP address
mov eax, [gateway_ip]
ret
repne scasd
jnz .error
 
.10:
; read the subnet mask
mov eax, [subnet_mask]
ret
.11:
; write the gateway IP Address
mov [gateway_ip], ecx
ret
;------------------------
; Remove it from the list
 
.12:
; write the subnet mask
mov [subnet_mask], ecx
ret
xor eax, eax
mov dword [edi-4], eax
 
.13:
; read the dns
mov eax, [dns_ip]
ret
call NET_send_event
 
.14:
; write the dns IP Address
mov [dns_ip], ecx
dec [NET_RUNNING]
ret
 
.15:
;<added by Frank Sommer>
; in ecx we need 4 to read the last 2 bytes
; or we need 0 to read the first 4 bytes
cmp ecx, 4
ja .param_error
 
; read MAC, returned (in mirrored byte order) in eax
mov eax, [node_addr + ecx]
.error:
or eax, -1
ret
 
.param_error:
or eax, -1 ; params not accepted
ret
 
.16:
; 0 -> arp_probe
; 1 -> arp_announce
; 2 -> arp_responce (not supported yet)
test ecx, ecx
je a_probe
 
dec ebx
jz a_ann ; arp announce
.fail:
or eax, -1
ret
;-----------------------------------------------------------------
;
; NET_ptr_to_num
;
; IN: ebx = ptr to device struct
; OUT: edi = -1 on error, device number otherwise
;
;-----------------------------------------------------------------
align 4
NET_ptr_to_num:
push ecx
 
; cmp ebx,2
; jne a_resp ; arp response
mov ecx, MAX_NET_DEVICES
mov edi, NET_DRV_LIST
 
; arp probe, sender IP must be set to 0.0.0.0, target IP is set to address being probed
; ecx: pointer to target MAC, MAC should set to 0 by application
; edx: target IP
a_probe:
push dword [stack_ip]
.loop:
cmp ebx, [edi]
jz .found
add edi, 4
dec ecx
jnz .loop
 
mov edx, [stack_ip]
and [stack_ip], dword 0
mov esi, ecx ; pointer to target MAC address
call arp_request
; repnz scasd could work too if eax is used instead of ebx!
 
pop dword [stack_ip]
ret
or edi, -1
 
; arp announce, sender IP must be set to target IP
; ecx: pointer to target MAC
a_ann:
mov edx, [stack_ip]
mov esi, ecx ; pointer to target MAC address
call arp_request
pop ecx
ret
 
.17:
;</added by Frank Sommer>
; modified by [smb]
.found:
sub edi, NET_DRV_LIST
shr edi, 2
 
;<added by Johnny_B>
; ARPTable manager interface
;see "proc arp_table_manager" for more details
stdcall arp_table_manager, ecx, edx, esi;Opcode,Index,Extra
pop ecx
ret
;</added by Johnny_B>
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ash_eth_enable:
; Probe for the card. This will reset it and enable the interface
; if found
call eth_probe
test eax, eax
jz ash_eth_done ; Abort if no hardware found
 
mov [ethernet_active], byte 1
ash_eth_done:
ret
;***************************************************************************
; Function
; app_socket_handler
;-----------------------------------------------------------------
;
; Description
; This is an application service, called by int 0x40, function 53
; It provides application access to stack socket services
; such as opening sockets
; checksum_1
;
;***************************************************************************
iglobal
; This is the first of two functions needed to calculate a checksum.
;
; IN: edx = start offset for semi-checksum
; esi = pointer to data
; ecx = data size
; OUT: edx = semi-checksum
;
;
; Code was optimized by diamond
;
;-----------------------------------------------------------------
align 4
f53call:
dd socket_open ;00
dd socket_close ;01
dd socket_poll ;02
dd socket_read ;03
dd socket_write ;04
dd socket_open_tcp ;05
dd socket_status ;06
dd socket_write_tcp ;07
dd socket_close_tcp ;08
dd is_localport_unused ;09
dd app_socket_handler.10
dd socket_read_packet ;11
endg
checksum_1:
 
app_socket_handler:
;in ebx,ecx,edx,wsi
;out eax
cmp eax, 255
je stack_internal_status
shr ecx, 1
pushf
jz .no_2
 
cmp eax, 11
ja .fail ;if more than 15 then exit
shr ecx, 1
pushf
jz .no_4
 
jmp dword [f53call+eax*4]
shr ecx, 1
pushf
jz .no_8
 
.10:
mov eax, dword[drvr_cable]
test eax, eax
jnz @f ; if function is not implented, return -1
or al, -1
ret
@@:
jmp dword[drvr_cable]
.loop:
add dl, [esi+1]
adc dh, [esi+0]
 
.fail:
or eax, -1
ret
uglobal
ARPTmp:
times 14 db 0
endg
adc dl, [esi+3]
adc dh, [esi+2]
 
;***************************************************************************
; Function
; stack_internal_status
;
; Description
; Returns information about the internal status of the stack
; This is only useful for debugging
; It works with the ethernet driver
; sub function in ebx
; return requested data in eax
;
;***************************************************************************
; This sub function allows access to debugging information on the stack
; ecx holds the request:
; 100 : return length of empty queue
; 101 : return length of IPOUT QUEUE
; 102 : return length of IPIN QUEUE
; 103 : return length of NET1OUT QUEUE
; 200 : return # of ARP entries
; 201 : return size of ARP table ( max # entries )
; 202 : select ARP table entry #
; 203 : return IP of selected table entry
; 204 : return High 4 bytes of MAC address of selected table entry
; 205 : return low 2 bytes of MAC address of selected table entry
; 206 : return status word of selected table entry
; 207 : return Time to live of selected table entry
adc dl, [esi+5]
adc dh, [esi+4]
 
adc dl, [esi+7]
adc dh, [esi+6]
 
; 2 : return number of IP packets received
; 3 : return number of packets transmitted
; 4 : return number of received packets dumped
; 5 : return number of arp packets received
; 6 : return status of packet driver
; ( 0 == not active, FFFFFFFF = successful )
adc edx, 0
add esi, 8
 
dec ecx
jnz .loop
 
stack_internal_status:
cmp ebx, 100
jnz notsis100
adc edx, 0
 
; 100 : return length of EMPTY QUEUE
mov ebx, EMPTY_QUEUE
call queueSize
ret
.no_8:
popf
jnc .no_4
 
notsis100:
cmp ebx, 101
jnz notsis101
add dl, [esi+1]
adc dh, [esi+0]
 
; 101 : return length of IPOUT QUEUE
mov ebx, IPOUT_QUEUE
call queueSize
ret
adc dl, [esi+3]
adc dh, [esi+2]
 
notsis101:
cmp ebx, 102
jnz notsis102
adc edx, 0
add esi, 4
 
; 102 : return length of IPIN QUEUE
mov ebx, IPIN_QUEUE
call queueSize
ret
.no_4:
popf
jnc .no_2
 
notsis102:
cmp ebx, 103
jnz notsis103
add dl, [esi+1]
adc dh, [esi+0]
 
; 103 : return length of NET1OUT QUEUE
mov ebx, NET1OUT_QUEUE
call queueSize
ret
adc edx, 0
inc esi
inc esi
 
notsis103:
cmp ebx, 200
jnz notsis200
.no_2:
popf
jnc .end
 
; 200 : return num entries in arp table
movzx eax, byte [NumARP]
add dh, [esi+0]
adc edx, 0
.end:
ret
 
notsis200:
cmp ebx, 201
jnz notsis201
;-----------------------------------------------------------------
;
; 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:
 
; 201 : return arp table size
mov eax, 20; ARP_TABLE_SIZE
ret
mov ecx, edx
shr ecx, 16
and edx, 0xffff
add edx, ecx
 
notsis201:
cmp ebx, 202
jnz notsis202
mov ecx, edx
shr ecx, 16
add dx, cx
test dx, dx ; it seems that ZF is not set when CF is set :(
not dx
jnz .not_zero
dec dx
.not_zero:
xchg dl, dh
 
; 202 - read the requested table entry
; into a temporary buffer
; ecx holds the entry number
DEBUGF 1,"Checksum: %x\n", dx
 
mov eax, ecx
mov ecx, 14; ARP_ENTRY_SIZE
mul ecx
 
mov ecx, [eax + ARPTable]
mov [ARPTmp], ecx
mov ecx, [eax + ARPTable+4]
mov [ARPTmp+4], ecx
mov ecx, [eax + ARPTable+8]
mov [ARPTmp+8], ecx
mov cx, [eax + ARPTable+12]
mov [ARPTmp+12], cx
ret
 
notsis202:
cmp ebx, 203
jnz notsis203
 
; 203 - return IP address
mov eax, [ARPTmp]
ret
 
notsis203:
cmp ebx, 204
jnz notsis204
;----------------------------------------------------------------
;
; System function to work with network devices (75)
;
;----------------------------------------------------------------
align 4
sys_network: ; FIXME: make default device easily accessible
 
; 204 - return MAC high dword
mov eax, [ARPTmp+4]
ret
cmp ebx, -1
jne @f
 
notsis204:
cmp ebx, 205
jnz notsis205
mov eax, [NET_RUNNING]
jmp .return
 
; 205 - return MAC ls word
movzx eax, word [ARPTmp+8]
ret
@@:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
notsis205:
cmp ebx, 206
jnz notsis206
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6
 
; 206 - return status word
movzx eax, word [ARPTmp+10]
ret
cmp dword [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
notsis206:
cmp ebx, 207
jnz notsis207
mov eax, [esi + NET_DRV_LIST]
 
; 207 - return ttl word
movzx eax, word [ARPTmp+12]
ret
and ebx, 0x000000ff
cmp ebx, .number
ja .doesnt_exist
jmp dword [.table + 4*ebx]
 
notsis207:
cmp ebx, 2
jnz notsis2
.table:
dd .get_type ; 0
dd .get_dev_name ; 1
dd .reset ; 2
dd .stop ; 3
dd .get_ptr ; 4
dd .get_drv_name ; 5
dd .set_default ; 6
.number = ($ - .table) / 4 - 1
 
; 2 : return number of IP packets received
mov eax, [ip_rx_count]
ret
.get_type: ; 0 = Get device type (ethernet/token ring/...)
 
notsis2:
cmp ebx, 3
jnz notsis3
mov eax, [eax + NET_DEVICE.type]
jmp .return
 
; 3 : return number of packets transmitted
mov eax, [ip_tx_count]
ret
 
notsis3:
cmp ebx, 4
jnz notsis4
.get_dev_name: ; 1 = Get device name
 
; 4 : return number of received packets dumped
mov eax, [dumped_rx_count]
ret
mov esi, [eax + NET_DEVICE.name]
mov edi, ecx
 
notsis4:
cmp ebx, 5
jnz notsis5
mov ecx, 64/4 ; max length
rep movsd
 
; 5 : return number of arp packets received
mov eax, [arp_rx_count]
ret
xor eax, eax
jmp .return
 
notsis5:
cmp ebx, 6
jnz notsis6
.reset: ; 2 = Reset the device
 
; 6 : return status of packet driver
; ( 0 == not active, FFFFFFFF = successful )
mov eax, [eth_status]
ret
call [eax + NET_DEVICE.reset]
jmp .return
 
notsis6:
xor eax, eax
ret
.stop: ; 3 = Stop driver for this device
 
call [eax + NET_DEVICE.unload]
jmp .return
 
 
;***************************************************************************
; Function
; stack_get_packet
;
; Description
; extracts an IP packet from the NET1 output queue
; and sends the data to the calling process
; pointer to data in edx
; returns number of bytes read in eax
;
;***************************************************************************
stack_get_packet:
; Look for a buffer to tx
mov eax, NET1OUT_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sgp_non_exit ; Exit if no buffer available
.get_ptr: ; 4 = Get driver pointer
 
push eax ; Save buffer number for freeing at end
jmp .return
 
push edx
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
pop edx
 
push eax ; save address of IP data
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add edx, [edi]
mov edi, edx
pop eax
.get_drv_name: ; 5 = Get driver name
 
mov ecx, 1500 ; should get the actual number of bytes to write
mov esi, eax
cld
rep movsb ; copy the data across
xor eax, eax
jmp .return
 
; And finally, return the buffer to the free queue
pop eax
call freeBuff
 
mov eax, 1500
ret
.set_default: ; 6 = Set default device
 
sgp_non_exit:
xor eax, eax
call NET_set_default
jmp .return
 
.doesnt_exist:
mov eax, -1
 
.return:
mov [esp+32], eax
ret
 
 
 
;***************************************************************************
; Function
; stack_insert_packet
;----------------------------------------------------------------
;
; Description
; writes an IP packet into the stacks receive queue
; # of bytes to write in ecx
; pointer to data in edx
; returns 0 in eax ok, -1 == failed
; System function to work with protocols (76)
;
;***************************************************************************
stack_insert_packet:
;----------------------------------------------------------------
align 4
sys_protocols:
cmp bh, MAX_NET_DEVICES ; Check if device number exists
jae .doesnt_exist
 
mov eax, EMPTY_QUEUE
call dequeue
cmp ax, NO_BUFFER
je sip_err_exit
mov esi, ebx
and esi, 0x0000ff00
shr esi, 6 ; now we have the device num * 4 in esi
cmp [esi + NET_DRV_LIST], 0 ; check if driver is running
je .doesnt_exist
 
push eax
push .return ; return address (we will be using jumps instead of calls)
 
; save the pointers to the data buffer & size
push edx
push ecx
mov eax, ebx ; set ax to protocol number
shr eax, 16 ;
 
; convert buffer pointer eax to the absolute address
mov ecx, IPBUFFSIZE
mul ecx
add eax, IPbuffs
cmp ax, API_ETH
je ETH_api
 
mov edx, eax
cmp ax, API_IPv4
je IPv4_api
 
; So, edx holds the IPbuffer ptr
cmp ax, API_ICMP
je ICMP_api
 
pop ecx ; count of bytes to send
mov ebx, ecx ; need the length later
pop eax ; get callers ptr to data to send
cmp ax, API_UDP
je UDP_api
 
; Get the address of the callers data
mov edi, [TASK_BASE]
add edi, TASKDATA.mem_start
add eax, [edi]
mov esi, eax
cmp ax, API_TCP
je TCP_api
 
mov edi, edx
cld
rep movsb ; copy the data across
cmp ax, API_ARP
je ARP_api
 
pop ebx
cmp ax, API_PPPOE
je PPPoE_api
 
mov eax, IPIN_QUEUE
call queue
cmp ax, API_IPv6
je IPv6_api
 
inc dword [ip_rx_count]
add esp, 4 ; if we reached here, no function was called, so we need to balance stack
 
mov eax, 0
ret
.doesnt_exist:
mov eax, -1
 
sip_err_exit:
mov eax, 0xFFFFFFFF
.return:
mov [esp+28+4], eax ; return eax value to the program
ret
 
Property changes:
Deleted: svn:keywords
-Rev
\ No newline at end of property