1,6 → 1,6 |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
;; ;; |
;; Copyright (C) KolibriOS team 2010-2014. All rights reserved. ;; |
;; Copyright (C) KolibriOS team 2010-2015. All rights reserved. ;; |
;; Distributed under terms of the GNU General Public License ;; |
;; ;; |
;; zeroconfig.asm - Zeroconfig service for KolibriOS ;; |
62,116 → 62,84 |
include 'dhcp.inc' |
include '../../dll.inc' |
|
START: |
mcall 68, 11 |
|
Ip2dword: |
push edx |
stdcall dll.Load,@IMPORT |
or eax, eax |
jnz fail |
|
; This code validates if the query is an IP containing 4 numbers and 3 dots |
DEBUGF 2,"Zero-config service loaded\n" |
|
xor al, al ; make al (dot count) zero |
mcall 40, EVM_STACK2 |
|
@@: |
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP |
jl no_IP ; |
cmp byte[edx],'9' ; |
jg no_IP ; |
wait_for_link_up: |
mov bh, [device] |
mov bl, 0 ; Get device type |
mcall 74 |
cmp eax, 1 ; Ethernet |
jne .wait |
|
inc edx ; the byte was a number, so lets check the next byte |
|
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?) |
jz @f ; jump to next @@ then |
cmp byte[edx],':' |
jz @f |
|
cmp byte[edx],'.' ; is this byte a dot? |
jne @r ; if not, jump to previous @@ |
|
inc al ; the byte was a dot so increment al(dot count) |
inc edx ; next byte |
jmp @r ; lets check for numbers again (jump to previous @@) |
|
@@: ; we reach this when end of query reached |
cmp al,3 ; check if there where 3 dots |
jnz no_IP ; if not, jump to no_IP |
|
; The following code will convert this IP into a dword and output it in eax |
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1 |
|
pop esi ; edx (query address) was pushed onto stack and is now popped in esi |
|
xor edx, edx ; result |
xor eax, eax ; current character |
xor ebx, ebx ; current byte |
|
.outer_loop: |
shl edx, 8 |
add edx, ebx |
xor ebx, ebx |
.inner_loop: |
lodsb |
mov bl, 10 ; Get Link status |
mcall 74 |
test eax, eax |
jz .finish |
cmp al, '.' |
jz .outer_loop |
sub eax, '0' |
imul ebx, 10 |
add ebx, eax |
jmp .inner_loop |
.finish: |
shl edx, 8 |
add edx, ebx |
jnz .go |
|
bswap edx ; we want little endian order |
.wait: |
mcall 10 |
jmp wait_for_link_up |
|
ret |
.go: |
mov ebx, API_ETH + 0 |
mov bh, [device] |
mcall 76 ; get MAC of the ethernet interface |
mov word[MAC], bx |
mov dword[MAC+2], eax |
DEBUGF 1,"MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2 |
|
no_IP: |
pop edx |
xor edx, edx |
invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0 |
|
ret |
cmp dword[inibuf], 'stat' |
je static |
jmp try_dhcp |
|
wait_for_link_down: |
; TODO: detect ARP conflicts |
|
|
|
|
|
START: |
mcall 40, EVM_STACK2 |
.loop: |
mcall 10 |
mov bh, [device] |
mov bl, 0 ; Get device type |
mcall 74 |
cmp eax, 0 ; No device |
je .down |
|
DEBUGF 2,"Zero-config service loaded\n" |
mov bl, 10 ; Get Link status |
mcall 74 |
test eax, eax |
jnz .loop |
|
.wait: |
mov ebx, API_ETH + 0 |
.down: |
xor ecx, ecx |
mov ebx, API_IPv4 + 3 |
mov bh, [device] |
mcall 76 ; get MAC of ethernet interface 1 |
cmp eax, -1 |
jne .start |
mcall 76 ; ip |
mov bl, 5 |
mcall 76 ; dns |
mov bl, 7 |
mcall 76 ; subnet |
mov bl, 9 |
mcall 76 ; gateway |
|
mcall 10 |
jmp .wait |
jmp wait_for_link_up |
|
.start: |
mov word[MAC], bx |
mov dword[MAC+2], eax |
DEBUGF 1,"MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2 |
static: |
DEBUGF 1,"Applying Static IP settings\n" |
|
mcall 40, EVM_STACK |
|
mcall 68, 11 |
|
stdcall dll.Load,@IMPORT |
or eax, eax |
jnz try_dhcp |
|
invoke ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0 |
|
cmp dword[inibuf], 'stat' |
jne try_dhcp |
|
invoke ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
call ip_str_to_dword |
mov ecx, edx |
mov ebx, API_IPv4 + 3 ; set IP |
mov bh, [device] |
179,7 → 147,7 |
|
invoke ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
call ip_str_to_dword |
mov ecx, edx |
mov ebx, API_IPv4 + 9 ; set gateway |
mov bh, [device] |
187,7 → 155,7 |
|
invoke ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
call ip_str_to_dword |
mov ecx, edx |
mov ebx, API_IPv4 + 5 ; set DNS |
mov bh, [device] |
195,23 → 163,26 |
|
invoke ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0 |
mov edx, inibuf |
call Ip2dword |
call ip_str_to_dword |
mov ecx, edx |
mov ebx, API_IPv4 + 7 ; set subnet |
mov bh, [device] |
mcall 76 |
|
mov [notify_struct.msg], str_connected |
mcall 70, notify_struct |
jmp wait_for_link_down |
|
mcall -1 |
|
|
try_dhcp: |
|
DEBUGF 2,"Trying to contact DHCP server\n" |
|
mcall 40, EVM_STACK |
|
mcall 75, 0, AF_INET4, SOCK_DGRAM, 0 ; open socket (parameters: domain, type, reserved) |
cmp eax, -1 |
je error |
je socket_error |
mov [socketNum], eax |
|
DEBUGF 1,"Socket %x opened\n", eax |
218,13 → 189,13 |
|
mcall 75, 2, [socketNum], sockaddr1, 18 ; bind socket to local port 68 |
cmp eax, -1 |
je error |
je socket_error |
|
DEBUGF 1,"Socket Bound to local port 68\n" |
|
mcall 75, 4, [socketNum], sockaddr2, 18 ; connect to 255.255.255.255 on port 67 |
cmp eax, -1 |
je error |
je socket_error |
|
DEBUGF 1,"Connected to 255.255.255.255 on port 67\n" |
|
242,18 → 213,16 |
DEBUGF 1,"Building request\n" |
|
stdcall mem.Alloc, BUFFER |
test eax, eax |
jz dhcp_fail2 |
mov [dhcpMsg], eax |
test eax, eax |
jz dhcp_error |
|
;;; todo: skip this bullcrap |
|
mov edi, eax |
mov ecx, BUFFER |
xor eax, eax |
rep stosb |
|
;; todo: put this in a buffer instead of writing bytes and words! |
;; todo: put this in one buffer we can copy, instead of writing bytes and words! |
|
mov edx, [dhcpMsg] |
|
261,7 → 230,7 |
mov [edx], byte 0x01 ; Boot request |
mov [edx+1], byte 0x01 ; Ethernet |
mov [edx+2], byte 0x06 ; Ethernet h/w len |
mov [edx+4], dword 0x11223344 ; xid ;;;;;;; |
mov [edx+4], dword 0x11223344 ; xid ;;;;;;; FIXME |
mov eax, [currTime] |
mov [edx+8], eax ; secs, our uptime |
mov [edx+10], byte 0x80 ; broadcast flag set |
308,7 → 277,7 |
add eax, TIMEOUT*100 |
mov [timeout], eax |
.wait: |
mcall 23, TIMEOUT ; wait for data |
mcall 23, TIMEOUT ; wait for data (with timeout) |
|
read_data: ; we have data - this will be the response |
mcall 75, 7, [socketNum], [dhcpMsg], BUFFER, MSG_DONTWAIT ; read data from socket |
322,7 → 291,7 |
DEBUGF 2,"No answer from DHCP server\n" |
dec [tries] |
jnz send_dhcpmsg ; try again |
jmp dhcp_error ; fail |
jmp dhcp_fail |
|
@@: |
DEBUGF 1,"%d bytes received\n", eax |
344,19 → 313,15 |
cmp [dhcpMsgType], 0x03 ; did we send a request? |
je request |
|
call dhcp_end ; we should never reach here ;) |
jmp exit |
; we should never reach here ;) |
jmp fail |
|
discover: |
call parse_response |
|
cmp [dhcpMsgType2], 0x02 ; Was the response an offer? |
je send_request |
jne dhcp_fail |
|
call dhcp_end |
jmp link_local |
|
send_request: |
DEBUGF 1, "Got offer, making request\n" |
mov [dhcpMsgType], 0x03 ; make it a request |
jmp build_request |
367,11 → 332,11 |
cmp [dhcpMsgType2], 0x05 ; Was the response an ACK? It should be |
jne read_data ; NO - read next packets |
|
DEBUGF 2, "Setting IP using DHCP\n" |
DEBUGF 2, "IP assigned by DHCP server successfully\n" |
|
mov [notify_struct.msg], str_connected |
mcall 70, notify_struct |
call dhcp_end |
call dhcp_fail |
|
mov ebx, API_IPv4 + 3 |
mov bh, [device] |
383,14 → 348,9 |
mov bl, 9 |
mcall 76, , [dhcp.gateway] ; gateway |
|
jmp exit |
jmp wait_for_link_down |
|
dhcp_end: |
mcall close, [socketNum] |
stdcall mem.Free, [dhcpMsg] |
|
ret |
|
;*************************************************************************** |
; Function |
; parseResponse |
481,7 → 441,7 |
mov eax,[edx] |
bswap eax |
mov [dhcpLease],eax |
DEBUGF 1,"lease: %d\n",eax |
DEBUGF 1,"Lease: %d\n",eax |
popa |
jmp .next_option |
|
506,10 → 466,13 |
.done: |
ret |
|
dhcp_fail: |
|
mcall close, [socketNum] |
stdcall mem.Free, [dhcpMsg] |
|
dhcp_error: |
call dhcp_end |
dhcp_fail2: |
DEBUGF 1,"DHCP failed\n" |
|
link_local: |
call random |
577,13 → 540,13 |
mcall 5, ANNOUNCE_INTERVAL*100 |
jmp announce_loop |
@@: |
jmp exit |
jmp wait_for_link_down |
|
|
error: |
socket_error: |
DEBUGF 2,"Socket error\n" |
exit: ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;) |
DEBUGF 2,"Exiting\n" |
fail: |
DEBUGF 2,"Zeroconf failed!\n" |
mcall -1 |
|
|
600,6 → 563,76 |
|
ret |
|
|
|
ip_str_to_dword: |
push edx |
|
; This code validates if the query is an IP containing 4 numbers and 3 dots |
|
xor al, al ; make al (dot count) zero |
|
@@: |
cmp byte[edx],'0' ; check if this byte is a number, if not jump to no_IP |
jl no_IP ; |
cmp byte[edx],'9' ; |
jg no_IP ; |
|
inc edx ; the byte was a number, so lets check the next byte |
|
cmp byte[edx],0 ; is this byte zero? (have we reached end of query?) |
jz @f ; jump to next @@ then |
cmp byte[edx],':' |
jz @f |
|
cmp byte[edx],'.' ; is this byte a dot? |
jne @r ; if not, jump to previous @@ |
|
inc al ; the byte was a dot so increment al(dot count) |
inc edx ; next byte |
jmp @r ; lets check for numbers again (jump to previous @@) |
|
@@: ; we reach this when end of query reached |
cmp al,3 ; check if there where 3 dots |
jnz no_IP ; if not, jump to no_IP |
|
; The following code will convert this IP into a dword and output it in eax |
; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1 |
|
pop esi ; edx (query address) was pushed onto stack and is now popped in esi |
|
xor edx, edx ; result |
xor eax, eax ; current character |
xor ebx, ebx ; current byte |
|
.outer_loop: |
shl edx, 8 |
add edx, ebx |
xor ebx, ebx |
.inner_loop: |
lodsb |
test eax, eax |
jz .finish |
cmp al, '.' |
jz .outer_loop |
sub eax, '0' |
imul ebx, 10 |
add ebx, eax |
jmp .inner_loop |
.finish: |
shl edx, 8 |
add edx, ebx |
|
bswap edx ; we want little endian order |
|
ret |
|
no_IP: |
pop edx |
xor edx, edx |
|
ret |
|
; DATA AREA |
|
align 16 |