dc1c59db4d
git-svn-id: svn://kolibrios.org@1259 a494cfbc-eb01-0410-851d-a64ba20cac60
386 lines
7.6 KiB
PHP
386 lines
7.6 KiB
PHP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
|
|
;; Distributed under terms of the GNU General Public License ;;
|
|
;; ;;
|
|
;; STACK.INC ;;
|
|
;; ;;
|
|
;; BASIC TCP/IP stack for KolibriOS ;;
|
|
;; ;;
|
|
;; Written by hidnplayr@kolibrios.org ;;
|
|
;; ;;
|
|
;; based on the work of Mike Hibbett, mikeh@oceanfree.net ;;
|
|
;; but also Paolo Franchetti ;;
|
|
;; ;;
|
|
;; GNU GENERAL PUBLIC LICENSE ;;
|
|
;; Version 2, June 1991 ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
$Revision$
|
|
|
|
uglobal
|
|
last_1sTick db ?
|
|
last_1hsTick dd ?
|
|
endg
|
|
|
|
MAX_NET_DEVICES equ 16
|
|
QUEUE_BEFORE_SENDING equ 1 ; 1 or 0 (enable or disable) currently only affects ethernet
|
|
|
|
MIN_EPHEMERAL_PORT equ 49152
|
|
MAX_EPHEMERAL_PORT equ 61000
|
|
|
|
ETHER equ 1337 ; TODO: find another value for this (how does it work in posix ?)
|
|
ETHER_ARP equ 0x0608
|
|
|
|
AF_UNSPEC equ 0
|
|
AF_UNIX equ 1
|
|
AF_INET4 equ 2
|
|
;AF_AX25 equ 3
|
|
;AF_IPX equ 4
|
|
;AF_APPLETALK equ 5
|
|
;AF_NETROM equ 6
|
|
;AF_BRIDGE equ 7
|
|
;AF_AAL5 equ 8
|
|
;AF_X25 equ 9
|
|
;AF_INET6 equ 10
|
|
;AF_MAX equ 12
|
|
|
|
IP_PROTO_IP equ 0
|
|
IP_PROTO_ICMP equ 1
|
|
IP_PROTO_TCP equ 6
|
|
IP_PROTO_UDP equ 17
|
|
|
|
; Socket types
|
|
SOCK_STREAM = 1
|
|
SOCK_DGRAM = 2
|
|
SOCK_RAW = 3
|
|
|
|
TCB_LISTEN equ 1
|
|
TCB_SYN_SENT equ 2
|
|
TCB_SYN_RECEIVED equ 3
|
|
TCB_ESTABLISHED equ 4
|
|
TCB_FIN_WAIT_1 equ 5
|
|
TCB_FIN_WAIT_2 equ 6
|
|
TCB_CLOSE_WAIT equ 7
|
|
TCB_CLOSING equ 8
|
|
TCB_LAST_ACK equ 9
|
|
TCB_TIMED_WAIT equ 10
|
|
TCB_CLOSED equ 11
|
|
|
|
TH_FIN equ 1 shl 0
|
|
TH_SYN equ 1 shl 1
|
|
TH_RST equ 1 shl 2
|
|
TH_PUSH equ 1 shl 3
|
|
TH_ACK equ 1 shl 4
|
|
TH_URG equ 1 shl 5
|
|
|
|
|
|
macro inc_INET reg {
|
|
|
|
add byte [reg + 3], 1
|
|
adc byte [reg + 2], 0
|
|
adc byte [reg + 1], 0
|
|
adc byte [reg], 0
|
|
|
|
}
|
|
|
|
|
|
macro add_INET reg {
|
|
add byte [reg + 3], cl
|
|
adc byte [reg + 2], ch
|
|
adc byte [reg + 1], 0
|
|
adc byte [reg], 0
|
|
rol ecx, 16
|
|
add byte [reg + 1], cl
|
|
adc byte [reg], ch
|
|
rol ecx, 16
|
|
}
|
|
|
|
include "queue.inc"
|
|
include "ARP.inc"
|
|
include "IPv4.inc"
|
|
include "ethernet.inc"
|
|
include "socket.inc"
|
|
include "tcp.inc"
|
|
include "udp.inc"
|
|
include "icmp.inc"
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; stack_init
|
|
;
|
|
; This function calls all network init procedures
|
|
;
|
|
; IN: /
|
|
; OUT: /
|
|
;
|
|
;-----------------------------------------------------------------
|
|
align 4
|
|
stack_init:
|
|
|
|
call ETH_init
|
|
call IPv4_init
|
|
call ARP_init
|
|
call UDP_init
|
|
call TCP_init
|
|
call ICMP_init
|
|
call socket_init
|
|
|
|
mov al, 0 ; set up 1s timer
|
|
out 0x70, al
|
|
in al, 0x71
|
|
mov [last_1sTick], al
|
|
|
|
ret
|
|
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; stack_handler
|
|
;
|
|
; This function calls all network init procedures
|
|
;
|
|
; IN: /
|
|
; OUT: /
|
|
;
|
|
;-----------------------------------------------------------------
|
|
align 4
|
|
stack_handler:
|
|
|
|
cmp [ETH_RUNNING], 0
|
|
je .exit
|
|
|
|
; Test for 1/100 s (10ms) tick
|
|
mov eax, [timer_ticks]
|
|
cmp eax, [last_1hsTick]
|
|
je .exit
|
|
|
|
mov [last_1hsTick], eax
|
|
|
|
call ETH_handler ; handle all queued ethernet packets
|
|
if QUEUE_BEFORE_SENDING
|
|
call ETH_send_queued
|
|
end if
|
|
call TCP_send_queued
|
|
|
|
.sec_tick:
|
|
|
|
; Test for 1 second tick
|
|
mov al, 0
|
|
out 0x70, al
|
|
in al, 0x71
|
|
cmp al, [last_1sTick]
|
|
je .exit
|
|
|
|
mov [last_1sTick], al
|
|
|
|
call ARP_decrease_entry_ttls
|
|
call IPv4_decrease_fragment_ttls
|
|
call TCP_decrease_socket_ttls
|
|
|
|
.exit:
|
|
ret
|
|
|
|
|
|
;-----------------------------------------------------------------
|
|
;
|
|
; 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
|
|
shr ecx, 1
|
|
pushf
|
|
.loop:
|
|
lodsw
|
|
xchg al, ah
|
|
add edx, eax
|
|
loop .loop
|
|
|
|
popf
|
|
jnc .end
|
|
|
|
add dh, [esi]
|
|
adc edx, 0
|
|
|
|
.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
|
|
|
|
|
|
|
|
;----------------------------------------------------------------
|
|
;
|
|
; System function to work with network devices (73)
|
|
;
|
|
;----------------------------------------------------------------
|
|
align 4
|
|
sys_network:
|
|
|
|
cmp ebx, -1
|
|
jne @f
|
|
|
|
mov eax, [ETH_RUNNING]
|
|
jmp .return
|
|
|
|
@@:
|
|
cmp bh, MAX_NET_DEVICES ; Check if device number exists
|
|
jge .doesnt_exist
|
|
|
|
mov esi, ebx
|
|
and esi, 0x0000ff00
|
|
shr esi, 6
|
|
|
|
cmp dword [esi + ETH_DRV_LIST], 0 ; check if driver is running
|
|
je .doesnt_exist
|
|
|
|
test bl, bl ; 0 = Get device type (ethernet/token ring/...)
|
|
jnz @f
|
|
; todo
|
|
xor eax, eax
|
|
jmp .return
|
|
|
|
|
|
@@:
|
|
dec bl ; 1 = Get device name
|
|
jnz @f
|
|
|
|
mov esi, [esi + ETH_DRV_LIST]
|
|
mov esi, [esi + ETH_DEVICE.name]
|
|
mov edi, ecx
|
|
|
|
mov ecx, 64 ; max length
|
|
repnz movsb
|
|
|
|
xor eax, eax
|
|
jmp .return
|
|
|
|
@@:
|
|
|
|
dec bl ; 2 = Reset the device
|
|
jnz @f
|
|
|
|
mov esi, [esi + ETH_DRV_LIST]
|
|
call [esi + ETH_DEVICE.reset]
|
|
jmp .return
|
|
|
|
@@:
|
|
|
|
dec bl ; 3 = Stop driver for this device
|
|
jnz @f
|
|
|
|
mov esi, [esi + ETH_DRV_LIST]
|
|
call [esi + ETH_DEVICE.unload]
|
|
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"
|
|
mov eax, -1
|
|
|
|
.return:
|
|
mov [esp+28+4], eax
|
|
ret
|
|
|
|
|
|
;----------------------------------------------------------------
|
|
;
|
|
; System Function To work with Protocols (75)
|
|
;
|
|
;----------------------------------------------------------------
|
|
align 4
|
|
sys_protocols:
|
|
cmp bh, MAX_NET_DEVICES ; Check if device number exists
|
|
jge .doesnt_exist
|
|
|
|
mov esi, ebx
|
|
and esi, 0x0000ff00
|
|
shr esi, 6
|
|
cmp dword [esi + ETH_DRV_LIST], 0 ; check if driver is running TODO: check other lists too
|
|
je .doesnt_exist
|
|
|
|
push .return ; return address (we will be using jumps instead of calls)
|
|
|
|
mov eax, ebx ; set ax to protocol number
|
|
shr eax, 16 ;
|
|
|
|
cmp ax , IP_PROTO_IP
|
|
je IPv4_API
|
|
|
|
cmp ax , IP_PROTO_ICMP
|
|
je ICMP_API
|
|
|
|
cmp ax , IP_PROTO_UDP
|
|
je UDP_API
|
|
|
|
cmp ax , IP_PROTO_TCP
|
|
je TCP_API
|
|
|
|
cmp ax , ETHER_ARP
|
|
je ARP_API
|
|
|
|
cmp ax , ETHER
|
|
je ETH_API
|
|
|
|
add esp, 4 ; if we reached here, no function was called, so we need to balance stack
|
|
|
|
.doesnt_exist:
|
|
DEBUGF 1,"sys_protocols: protocol %u doesnt exist on device %u!\n",ax, bh
|
|
mov eax, -1
|
|
|
|
.return:
|
|
mov [esp+28+4], eax
|
|
ret
|