forked from KolibriOS/kolibrios
f8ca762192
git-svn-id: svn://kolibrios.org@551 a494cfbc-eb01-0410-851d-a64ba20cac60
583 lines
13 KiB
NASM
583 lines
13 KiB
NASM
;
|
|
; DHCP Client
|
|
;
|
|
; Compile with FASM for Menuet
|
|
;
|
|
|
|
include 'lang.inc'
|
|
include '..\..\..\macros.inc'
|
|
|
|
use32
|
|
|
|
org 0x0
|
|
|
|
db 'MENUET01' ; 8 byte id
|
|
dd 0x01 ; header version
|
|
dd START ; start of code
|
|
dd I_END ; size of image
|
|
dd I_END+0x8000 ; memory for app
|
|
dd I_END+0x8000 ; esp
|
|
dd 0x0 , 0x0 ; I_Param , I_Icon
|
|
|
|
|
|
START: ; start of execution
|
|
mov eax,40 ; Report events
|
|
mov ebx,10000111b ; Stack 8 + defaults
|
|
int 0x40
|
|
|
|
red: ; redraw
|
|
call draw_window ; at first, draw the window
|
|
|
|
still:
|
|
mov eax,10 ; wait here for event
|
|
mcall
|
|
|
|
cmp eax,1 ; redraw request ?
|
|
jz red
|
|
cmp eax,2 ; key in buffer ?
|
|
jz key
|
|
cmp eax,3 ; button in buffer ?
|
|
jz button
|
|
|
|
jmp still
|
|
key: ; Keys are not valid at this part of the
|
|
mov eax,2 ; loop. Just read it and ignore
|
|
mcall
|
|
jmp still
|
|
|
|
button: ; button
|
|
mov eax,17 ; get id
|
|
mcall
|
|
|
|
cmp ah,1 ; button id=1 ?
|
|
jnz noclose
|
|
|
|
; close socket before exiting
|
|
mov eax, 53
|
|
mov ebx, 1
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
mov eax,0xffffffff ; close this program
|
|
mcall
|
|
|
|
noclose:
|
|
cmp ah,3 ; Resolve address?
|
|
jnz still
|
|
|
|
call draw_window
|
|
|
|
call contactDHCPServer
|
|
|
|
jmp still
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; parseResponse
|
|
;
|
|
; Description
|
|
; extracts the fields ( client IP address and options ) from
|
|
; a DHCP response
|
|
; The values go into
|
|
; dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
|
|
; dhcpDNSIP, dhcpSubnet
|
|
; The message is stored in dhcpMsg
|
|
;
|
|
;***************************************************************************
|
|
parseResponse:
|
|
mov edx, dhcpMsg
|
|
|
|
mov eax, [edx+16]
|
|
mov [dhcpClientIP], eax
|
|
|
|
; Scan options
|
|
|
|
add edx, 240 ; Point to first option
|
|
|
|
pr001:
|
|
; Get option id
|
|
mov al, [edx]
|
|
cmp al, 0xff ; End of options?
|
|
je pr_exit
|
|
|
|
cmp al, 53 ; Msg type is a single byte option
|
|
jne pr002
|
|
|
|
mov al, [edx+2]
|
|
mov [dhcpMsgType], al
|
|
add edx, 3
|
|
jmp pr001 ; Get next option
|
|
|
|
pr002:
|
|
; All other (accepted) options are 4 bytes in length
|
|
inc edx
|
|
movzx ecx, byte [edx]
|
|
inc edx ; point to data
|
|
|
|
cmp al, 54 ; server id
|
|
jne pr0021
|
|
mov eax, [edx] ; All options are 4 bytes, so get it
|
|
mov [dhcpServerIP], eax
|
|
jmp pr003
|
|
|
|
pr0021:
|
|
cmp al, 51 ; lease
|
|
jne pr0022
|
|
mov eax, [edx] ; All options are 4 bytes, so get it
|
|
mov [dhcpLease], eax
|
|
jmp pr003
|
|
|
|
pr0022:
|
|
cmp al, 1 ; subnet mask
|
|
jne pr0023
|
|
mov eax, [edx] ; All options are 4 bytes, so get it
|
|
mov [dhcpSubnet], eax
|
|
jmp pr003
|
|
|
|
pr0023:
|
|
cmp al, 6 ; dns ip
|
|
jne pr0024
|
|
mov eax, [edx] ; All options are 4 bytes, so get it
|
|
mov [dhcpDNSIP], eax
|
|
|
|
pr0024:
|
|
cmp al, 3 ; gateway ip
|
|
jne pr003
|
|
mov eax, [edx] ; All options are 4 bytes, so get it
|
|
mov [dhcpGateway], eax
|
|
|
|
pr003:
|
|
add edx, ecx
|
|
jmp pr001
|
|
|
|
pr_exit:
|
|
ret
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; buildRequest
|
|
;
|
|
; Description
|
|
; Creates a DHCP request packet.
|
|
;
|
|
;***************************************************************************
|
|
buildRequest:
|
|
; Clear dhcpMsg to all zeros
|
|
xor eax,eax
|
|
mov edi,dhcpMsg
|
|
mov ecx,512
|
|
cld
|
|
rep stosb
|
|
|
|
mov edx, dhcpMsg
|
|
|
|
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+10], byte 0x80 ; broadcast flag set
|
|
mov [edx+236], dword 0x63538263 ; magic number
|
|
|
|
; option DHCP msg type
|
|
mov [edx+240], word 0x0135
|
|
mov al, [dhcpMsgType]
|
|
mov [edx+240+2], al
|
|
|
|
; option Lease time = infinity
|
|
mov [edx+240+3], word 0x0433
|
|
mov eax, [dhcpLease]
|
|
mov [edx+240+5], eax
|
|
|
|
; option requested IP address
|
|
mov [edx+240+9], word 0x0432
|
|
mov eax, [dhcpClientIP]
|
|
mov [edx+240+11], eax
|
|
|
|
; option request list
|
|
mov [edx+240+15], word 0x0437
|
|
mov [edx+240+17], dword 0x0f060301
|
|
|
|
; Check which msg we are sending
|
|
cmp [dhcpMsgType], byte 0x01
|
|
jne br001
|
|
|
|
; "Discover" options
|
|
; end of options marker
|
|
mov [edx+240+21], byte 0xff
|
|
|
|
mov [dhcpMsgLen], dword 262
|
|
jmp br_exit
|
|
|
|
br001:
|
|
; "Request" options
|
|
|
|
; server IP
|
|
mov [edx+240+21], word 0x0436
|
|
mov eax, [dhcpServerIP]
|
|
mov [edx+240+23], eax
|
|
|
|
; end of options marker
|
|
mov [edx+240+27], byte 0xff
|
|
|
|
mov [dhcpMsgLen], dword 268
|
|
|
|
br_exit:
|
|
ret
|
|
|
|
|
|
|
|
;***************************************************************************
|
|
; Function
|
|
; contactDHCPServer
|
|
;
|
|
; Description
|
|
; negotiates settings with a DHCP server
|
|
;
|
|
;***************************************************************************
|
|
contactDHCPServer:
|
|
; First, open socket
|
|
mov eax, 53
|
|
mov ebx, 0
|
|
mov ecx, 68 ; local port dhcp client
|
|
mov edx, 67 ; remote port - dhcp server
|
|
mov esi, 0xffffffff ; broadcast
|
|
mcall
|
|
|
|
mov [socketNum], eax
|
|
|
|
; Setup the first msg we will send
|
|
mov [dhcpMsgType], byte 0x01 ; DHCP discover
|
|
mov [dhcpLease], dword 0xffffffff
|
|
mov [dhcpClientIP], dword 0
|
|
mov [dhcpServerIP], dword 0
|
|
|
|
call buildRequest
|
|
|
|
ctr000:
|
|
; write to socket ( send broadcast request )
|
|
mov eax, 53
|
|
mov ebx, 4
|
|
mov ecx, [socketNum]
|
|
mov edx, [dhcpMsgLen]
|
|
mov esi, dhcpMsg
|
|
mcall
|
|
|
|
; Setup the DHCP buffer to receive response
|
|
|
|
mov eax, dhcpMsg
|
|
mov [dhcpMsgLen], eax ; Used as a pointer to the data
|
|
|
|
; now, we wait for
|
|
; UI redraw
|
|
; UI close
|
|
; or data from remote
|
|
|
|
ctr001:
|
|
mov eax,10 ; wait here for event
|
|
mcall
|
|
|
|
cmp eax,1 ; redraw request ?
|
|
je ctr003
|
|
cmp eax,2 ; key in buffer ?
|
|
je ctr004
|
|
cmp eax,3 ; button in buffer ?
|
|
je ctr005
|
|
|
|
|
|
; Any data in the UDP receive buffer?
|
|
mov eax, 53
|
|
mov ebx, 2
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
cmp eax, 0
|
|
je ctr001
|
|
|
|
; we have data - this will be the response
|
|
ctr002:
|
|
mov eax, 53
|
|
mov ebx, 3
|
|
mov ecx, [socketNum]
|
|
mcall ; read byte - block (high byte)
|
|
|
|
; Store the data in the response buffer
|
|
mov eax, [dhcpMsgLen]
|
|
mov [eax], bl
|
|
inc dword [dhcpMsgLen]
|
|
|
|
mov eax, 53
|
|
mov ebx, 2
|
|
mov ecx, [socketNum]
|
|
mcall ; any more data?
|
|
|
|
cmp eax, 0
|
|
jne ctr002 ; yes, so get it
|
|
|
|
; depending on which msg we sent, handle the response
|
|
; accordingly.
|
|
; If the response is to a dhcp discover, then:
|
|
; 1) If response is DHCP OFFER then
|
|
; 1.1) record server IP, lease time & IP address.
|
|
; 1.2) send a request packet
|
|
; 2) else exit ( display error )
|
|
; If the response is to a dhcp request, then:
|
|
; 1) If the response is DHCP ACK then
|
|
; 1.1) extract the DNS & subnet fields. Set them in the stack
|
|
; 2) else exit ( display error )
|
|
|
|
|
|
cmp [dhcpMsgType], byte 0x01 ; did we send a discover?
|
|
je ctr007
|
|
cmp [dhcpMsgType], byte 0x03 ; did we send a request?
|
|
je ctr008
|
|
|
|
; should never get here - we only send discover or request
|
|
jmp ctr006
|
|
|
|
ctr007:
|
|
call parseResponse
|
|
|
|
; Was the response an offer? It should be
|
|
cmp [dhcpMsgType], byte 0x02
|
|
jne ctr006 ; NO - so quit
|
|
|
|
; send request
|
|
mov [dhcpMsgType], byte 0x03 ; DHCP request
|
|
call buildRequest
|
|
jmp ctr000
|
|
|
|
ctr008:
|
|
call parseResponse
|
|
|
|
; Was the response an ACK? It should be
|
|
cmp [dhcpMsgType], byte 0x05
|
|
jne ctr006 ; NO - so quit
|
|
|
|
; Set or display addresses here...
|
|
|
|
ctr006:
|
|
; close socket
|
|
mov eax, 53
|
|
mov ebx, 1
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
mov [socketNum], dword 0xFFFF
|
|
|
|
call draw_window
|
|
|
|
jmp ctr001
|
|
|
|
ctr003: ; redraw
|
|
call draw_window
|
|
jmp ctr001
|
|
|
|
ctr004: ; key
|
|
mov eax,2 ; just read it and ignore
|
|
mcall
|
|
jmp ctr001
|
|
|
|
ctr005: ; button
|
|
mov eax,17 ; get id
|
|
mcall
|
|
|
|
; close socket
|
|
mov eax, 53
|
|
mov ebx, 1
|
|
mov ecx, [socketNum]
|
|
mcall
|
|
|
|
mov [socketNum], dword 0xFFFF
|
|
|
|
call draw_window ; at first, draw the window
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
; *********************************************
|
|
; ******* WINDOW DEFINITIONS AND DRAW ********
|
|
; *********************************************
|
|
|
|
|
|
; Pass in the IP address in edi
|
|
; row to display in [ya]
|
|
drawIP:
|
|
; mov edi,hostIP
|
|
mov ecx, edi
|
|
add ecx, 4
|
|
mov edx,[ya]
|
|
add edx, 97*65536
|
|
mov esi,0x00ffffff
|
|
mov ebx,3*65536
|
|
|
|
ipdisplay:
|
|
mov eax,47
|
|
push ecx
|
|
movzx ecx,byte [edi]
|
|
mcall
|
|
pop ecx
|
|
add edx,6*4*65536
|
|
inc edi
|
|
cmp edi,ecx
|
|
jb ipdisplay
|
|
ret
|
|
|
|
|
|
drawDHMS:
|
|
|
|
mov eax,[edi]
|
|
bswap eax
|
|
|
|
mov esi,dhms
|
|
mov ecx,16
|
|
mov edi,text+40*4+12
|
|
cmp eax,0xffffffff
|
|
jne nforever
|
|
mov esi,forever
|
|
cld
|
|
rep movsb
|
|
ret
|
|
nforever:
|
|
cld
|
|
rep movsb
|
|
|
|
mov ecx,28
|
|
xor edx,edx
|
|
mov ebx,60
|
|
div ebx
|
|
call displayDHMS
|
|
xor edx,edx
|
|
div ebx
|
|
call displayDHMS
|
|
xor edx,edx
|
|
mov ebx,24
|
|
div ebx
|
|
call displayDHMS
|
|
mov edx,eax
|
|
call displayDHMS
|
|
|
|
ret
|
|
|
|
|
|
displayDHMS:
|
|
|
|
pusha
|
|
mov eax,47
|
|
mov ebx,3*65536
|
|
mov edx,ecx
|
|
imul edx,6
|
|
shl edx,16
|
|
add edx,1*65536+99
|
|
mov ecx,[esp+20]
|
|
mov esi,0xffffff
|
|
mcall
|
|
popa
|
|
sub ecx,4
|
|
ret
|
|
|
|
|
|
draw_window:
|
|
|
|
mov eax,12 ; function 12:tell os about windowdraw
|
|
mov ebx,1 ; 1, start of draw
|
|
mcall
|
|
; DRAW WINDOW
|
|
mov eax,0 ; function 0 : define and draw window
|
|
mov ebx,100*65536+300 ; [x start] *65536 + [x size]
|
|
mov ecx,100*65536+156 ; [y start] *65536 + [y size]
|
|
mov edx,0x14224466 ; color of work area RRGGBB
|
|
mov edi,title ; WINDOW LABEL
|
|
mcall
|
|
|
|
mov eax,8 ; Resolve
|
|
mov ebx,20*65536+90
|
|
mov ecx,127*65536+15
|
|
mov edx,3
|
|
mov esi,0x557799
|
|
mcall
|
|
|
|
; Pass in the IP address in edi
|
|
; row to display in [ya]
|
|
mov edi, dhcpClientIP
|
|
mov eax, 35
|
|
mov [ya], eax
|
|
call drawIP
|
|
mov edi, dhcpGateway
|
|
mov eax, 35 + 16
|
|
mov [ya], eax
|
|
call drawIP
|
|
mov edi, dhcpSubnet
|
|
mov eax, 35 + 32
|
|
mov [ya], eax
|
|
call drawIP
|
|
mov edi, dhcpDNSIP
|
|
mov eax, 35 + 48
|
|
mov [ya], eax
|
|
call drawIP
|
|
mov edi, dhcpLease
|
|
call drawDHMS
|
|
|
|
; Re-draw the screen text
|
|
cld
|
|
mov eax,4
|
|
mov ebx,25*65536+35 ; draw info text with function 4
|
|
mov ecx,0xffffff
|
|
mov edx,text
|
|
mov esi,40
|
|
newline:
|
|
mcall
|
|
add ebx,16
|
|
add edx,40
|
|
cmp [edx],byte 'x'
|
|
jnz newline
|
|
|
|
|
|
mov eax,12 ; function 12:tell os about windowdraw
|
|
mov ebx,2 ; 2, end of draw
|
|
mcall
|
|
|
|
ret
|
|
|
|
|
|
|
|
; DATA AREA
|
|
|
|
ya dd 0x0
|
|
|
|
text:
|
|
db 'Client IP : . . . '
|
|
db 'Gateway IP: . . . '
|
|
db 'Subnet : . . . '
|
|
db 'DNS IP : . . . '
|
|
db 'Lease Time: d h m s '
|
|
db ' '
|
|
db ' SEND REQUEST '
|
|
db 'x <- END MARKER, DONT DELETE '
|
|
|
|
|
|
dhms db ' d h m s'
|
|
forever db 'Forever '
|
|
|
|
title db 'DHCP Client Test',0
|
|
|
|
dhcpMsgType: db 0
|
|
dhcpLease: dd 0
|
|
dhcpClientIP: dd 0
|
|
dhcpServerIP: dd 0
|
|
dhcpDNSIP: dd 0
|
|
dhcpSubnet: dd 0
|
|
dhcpGateway: dd 0
|
|
|
|
dhcpMsgLen: dd 0
|
|
socketNum: dd 0xFFFF
|
|
dhcpMsg:
|
|
I_END:
|
|
|
|
|
|
|
|
|