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 |