kolibrios-fun/programs/dhcp/trunk/dhcp.asm

596 lines
14 KiB
NASM
Raw Normal View History

;
; DHCP Client
;
; Compile with FASM for Menuet
;
include 'lang.inc'
include 'macros.inc'
use32
org 0x0
db 'MENUET00' ; 8 byte id
dd 38 ; required os
dd START ; program start
dd I_END ; program image size
dd 0x100000 ; required amount of memory
dd 0x00000000 ; reserved=no extended header
START: ; start of execution
mov eax,40 ; Report events
mov ebx,10000111b ; Stack 8 + defaults
int 0x40
call draw_window ; at first, draw the window
still:
mov eax,10 ; wait here for event
int 0x40
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
red: ; redraw
call draw_window
jmp still
key: ; Keys are not valid at this part of the
mov eax,2 ; loop. Just read it and ignore
int 0x40
jmp still
button: ; button
mov eax,17 ; get id
int 0x40
cmp ah,1 ; button id=1 ?
jnz noclose
; close socket before exiting
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
mov eax,0xffffffff ; close this program
int 0x40
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
int 0x40
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
int 0x40
; 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
int 0x40
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]
int 0x40
cmp eax, 0
je ctr001
; we have data - this will be the response
ctr002:
mov eax, 53
mov ebx, 3
mov ecx, [socketNum]
int 0x40 ; 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]
int 0x40 ; 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]
int 0x40
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
int 0x40
jmp ctr001
ctr005: ; button
mov eax,17 ; get id
int 0x40
; close socket
mov eax, 53
mov ebx, 1
mov ecx, [socketNum]
int 0x40
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]
int 0x40
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
int 0x40
popa
sub ecx,4
ret
draw_window:
mov eax,12 ; function 12:tell os about windowdraw
mov ebx,1 ; 1, start of draw
int 0x40
; 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,0x03224466 ; color of work area RRGGBB
mov esi,0x00334455 ; color of grab bar RRGGBB,8->color gl
mov edi,0x00ddeeff ; color of frames RRGGBB
int 0x40
; WINDOW LABEL
mov eax,4 ; function 4 : write text to window
mov ebx,8*65536+8 ; [x start] *65536 + [y start]
mov ecx,0x00ffffff ; color of text RRGGBB
mov edx,labelt ; pointer to text beginning
mov esi,labellen-labelt ; text length
int 0x40
mov eax,8 ; Resolve
mov ebx,20*65536+90
mov ecx,127*65536+15
mov edx,3
mov esi,0x557799
int 0x40
; 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 ebx,25*65536+35 ; draw info text with function 4
mov ecx,0xffffff
mov edx,text
mov esi,40
newline:
mov eax,4
int 0x40
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
int 0x40
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 '
labelt: db 'DHCP Client Test'
labellen:
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: