Subversion Repositories Kolibri OS

Rev

Rev 337 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 hidnplayr 1
; Automated dhcp client
336 hidnplayr 2
; v 1.3
104 hidnplayr 3
;
336 hidnplayr 4
; with thanks to authors of DHCP client for menuetos: Mike Hibbet
104 hidnplayr 5
;
336 hidnplayr 6
; by HidnPlayr & Derpenguin
104 hidnplayr 7
 
8
use32
9
	       org    0x0
10
 
339 hidnplayr 11
	       db     'MENUET01'	    ; 8 byte id
12
	       dd     0x01		    ; header version
13
	       dd     START		    ; start of code
14
	       dd     IM_END		    ; size of image
15
	       dd     I_END		    ; memory for app
16
	       dd     I_END		    ; esp
17
	       dd     0x0 , 0x0 	    ; I_Param , I_Icon
104 hidnplayr 18
 
339 hidnplayr 19
; CONFIGURATION
104 hidnplayr 20
 
21
 
339 hidnplayr 22
TIMEOUT 	    equ 60		    ; in seconds
23
BUFFER		    equ 1024		    ; in bytes
24
__DEBUG__	    equ 1		    ; enable/disable
25
__DEBUG_LEVEL__     equ 1		    ; 1 = all, 2 = errors
104 hidnplayr 26
 
339 hidnplayr 27
; CONFIGURATION FOR LINK-LOCAL
104 hidnplayr 28
 
339 hidnplayr 29
PROBE_WAIT	    equ 1		    ; second  (initial random delay)
30
PROBE_MIN	    equ 1		    ; second  (minimum delay till repeated probe)
31
PROBE_MAX	    equ 2		    ; seconds (maximum delay till repeated probe)
32
PROBE_NUM	    equ 3		    ;         (number of probe packets)
336 hidnplayr 33
 
339 hidnplayr 34
ANNOUNCE_NUM	    equ 2		    ;         (number of announcement packets)
35
ANNOUNCE_INTERVAL   equ 2		    ; seconds (time between announcement packets)
36
ANNOUNCE_WAIT	    equ 2		    ; seconds (delay before announcing)
104 hidnplayr 37
 
339 hidnplayr 38
MAX_CONFLICTS	    equ 10		    ;         (max conflicts before rate limiting)
104 hidnplayr 39
 
339 hidnplayr 40
RATE_LIMIT_INTERVAL equ 60		    ; seconds (delay between successive attempts)
104 hidnplayr 41
 
339 hidnplayr 42
DEFEND_INTERVAL     equ 10		    ; seconds (min. wait between defensive ARPs)
43
 
44
include 'macros.inc'
45
include 'eth.inc'
46
include 'debug-fdo.inc'
47
include 'dhcp.inc'
48
include 'events.inc'
49
include 'common.inc'
50
 
51
 
52
START:					    ; start of execution
53
 
54
    set_event_mask	event_network
55
    eth.set_network_drv 0x00000383
56
 
57
    DEBUGF  1,"Stack Initialized.\n"
58
 
59
    eth.status eax			    ; Read the Stack status
60
    test    eax,eax			    ; if eax is zero, no driver was found
336 hidnplayr 61
    jnz     @f
339 hidnplayr 62
    DEBUGF  1,"No Card detected\n"
336 hidnplayr 63
    jmp     close
104 hidnplayr 64
 
336 hidnplayr 65
   @@:
339 hidnplayr 66
    DEBUGF  1,"Detected card: %x\n",eax
336 hidnplayr 67
   @@:
68
    eth.check_cable eax
69
    test    al,al
70
    jnz     @f
339 hidnplayr 71
    DEBUGF  1,"Ethernet Cable not connected\n"
72
    wait 500				    ; loop until cable is connected (check every 5 sec)
336 hidnplayr 73
    jmp     @r
104 hidnplayr 74
 
75
   @@:
339 hidnplayr 76
    DEBUGF  1,"Ethernet Cable status: %d\n",al
104 hidnplayr 77
 
336 hidnplayr 78
    eth.read_mac MAC
339 hidnplayr 79
    DEBUGF  1,"MAC address: %x-%x-%x-%x-%x-%x\n",[MAC]:2,[MAC+1]:2,[MAC+2]:2,[MAC+3]:2,[MAC+4]:2,[MAC+5]:2
104 hidnplayr 80
 
339 hidnplayr 81
    eth.check_port 68,eax		    ; Check if port 68 is available
336 hidnplayr 82
    cmp     eax,1
83
    je	    @f
84
 
339 hidnplayr 85
    DEBUGF  1,"Port 68 is already in use!\n"
336 hidnplayr 86
    jmp     close
87
 
88
   @@:
339 hidnplayr 89
    eth.open_udp 68,67,-1,[socketNum]	    ; open socket (local,remote,ip,socket)
90
    DEBUGF  1,"Socket opened: %d\n",eax
91
					    ; Setup the first msg we will send
92
    mov     byte [dhcpMsgType], 0x01	    ; DHCP discover
93
    mov     dword [dhcpLease], esi	    ; esi is still -1 (-1 = forever)
336 hidnplayr 94
 
339 hidnplayr 95
    get_time_counter eax
336 hidnplayr 96
    imul    eax,100
97
    mov     [currTime],eax
98
 
339 hidnplayr 99
buildRequest:				    ; Creates a DHCP request packet.
336 hidnplayr 100
    xor     eax,eax			    ; Clear dhcpMsg to all zeros
104 hidnplayr 101
    mov     edi,dhcpMsg
336 hidnplayr 102
    mov     ecx,BUFFER
104 hidnplayr 103
    cld
104
    rep     stosb
105
 
106
    mov     edx, dhcpMsg
107
 
108
    mov     [edx], byte 0x01		    ; Boot request
109
    mov     [edx+1], byte 0x01		    ; Ethernet
110
    mov     [edx+2], byte 0x06		    ; Ethernet h/w len
111
    mov     [edx+4], dword 0x11223344	    ; xid
336 hidnplayr 112
    mov     eax,[currTime]
113
    mov     [edx+8], eax		    ; secs, our uptime
104 hidnplayr 114
    mov     [edx+10], byte 0x80 	    ; broadcast flag set
336 hidnplayr 115
    mov     eax, dword [MAC]		    ; first 4 bytes of MAC
116
    mov     [edx+28],dword eax
117
    mov     ax, word [MAC+4]		    ; last 2 bytes of MAC
118
    mov     [edx+32],word ax
104 hidnplayr 119
    mov     [edx+236], dword 0x63538263     ; magic number
336 hidnplayr 120
    mov     [edx+240], word 0x0135	    ; option DHCP msg type
104 hidnplayr 121
    mov     al, [dhcpMsgType]
122
    mov     [edx+240+2], al
336 hidnplayr 123
    mov     [edx+240+3], word 0x0433	    ; option Lease time = infinity
104 hidnplayr 124
    mov     eax, [dhcpLease]
125
    mov     [edx+240+5], eax
336 hidnplayr 126
    mov     [edx+240+9], word 0x0432	    ; option requested IP address
127
    mov     eax, [dhcpClientIP]
128
    mov     [edx+240+11], eax
129
    mov     [edx+240+15], word 0x0437	    ; option request list
104 hidnplayr 130
    mov     [edx+240+17], dword 0x0f060301
131
 
336 hidnplayr 132
    cmp     [dhcpMsgType], byte 0x01	    ; Check which msg we are sending
339 hidnplayr 133
    jne     request_options
104 hidnplayr 134
 
336 hidnplayr 135
    mov     [edx+240+21], byte 0xff	    ; "Discover" options
104 hidnplayr 136
 
336 hidnplayr 137
    mov     [dhcpMsgLen], dword 262	    ; end of options marker
339 hidnplayr 138
    jmp     send_request
104 hidnplayr 139
 
339 hidnplayr 140
request_options:
336 hidnplayr 141
    mov     [edx+240+21], word 0x0436	    ; server IP
104 hidnplayr 142
    mov     eax, [dhcpServerIP]
143
    mov     [edx+240+23], eax
144
 
336 hidnplayr 145
    mov     [edx+240+27], byte 0xff	    ; end of options marker
104 hidnplayr 146
 
147
    mov     [dhcpMsgLen], dword 268
148
 
339 hidnplayr 149
send_request:
150
    eth.write_udp [socketNum],[dhcpMsgLen],dhcpMsg ; write to socket ( send broadcast request )
104 hidnplayr 151
 
336 hidnplayr 152
    mov     eax, dhcpMsg		    ; Setup the DHCP buffer to receive response
153
    mov     [dhcpMsgLen], eax		    ; Used as a pointer to the data
104 hidnplayr 154
 
336 hidnplayr 155
    mov     eax,23			    ; wait here for event (data from remote)
156
    mov     ebx,TIMEOUT*10
104 hidnplayr 157
    int     0x40
158
 
336 hidnplayr 159
    eth.poll [socketNum]
104 hidnplayr 160
 
336 hidnplayr 161
    test    eax,eax
339 hidnplayr 162
    jnz     read_data
104 hidnplayr 163
 
339 hidnplayr 164
    DEBUGF  2,"Timeout!\n"
336 hidnplayr 165
    eth.close_udp [socketNum]
166
    jmp    apipa			    ; no server found, lets try zeroconf
104 hidnplayr 167
 
168
 
339 hidnplayr 169
read_data:				    ; we have data - this will be the response
336 hidnplayr 170
    eth.read_packet [socketNum], dhcpMsg, BUFFER
171
    mov     [dhcpMsgLen], eax
172
    eth.close_udp [socketNum]
104 hidnplayr 173
 
174
    ; depending on which msg we sent, handle the response
175
    ; accordingly.
176
    ; If the response is to a dhcp discover, then:
177
    ;  1) If response is DHCP OFFER then
178
    ;  1.1) record server IP, lease time & IP address.
179
    ;  1.2) send a request packet
180
    ; If the response is to a dhcp request, then:
181
    ;  1) If the response is DHCP ACK then
182
    ;  1.1) extract the DNS & subnet fields. Set them in the stack
183
 
336 hidnplayr 184
    cmp     [dhcpMsgType], byte 0x01	    ; did we send a discover?
104 hidnplayr 185
    je	    discover
336 hidnplayr 186
    cmp     [dhcpMsgType], byte 0x03	    ; did we send a request?
104 hidnplayr 187
    je	    request
188
 
336 hidnplayr 189
    jmp     close			    ; really unknown, what we did
104 hidnplayr 190
 
191
discover:
192
    call    parseResponse
193
 
336 hidnplayr 194
    cmp     [dhcpMsgType], byte 0x02	    ; Was the response an offer?
195
    jne     apipa			    ; NO - so we do zeroconf
196
    mov     [dhcpMsgType], byte 0x03	    ; DHCP request
104 hidnplayr 197
    jmp     buildRequest
198
 
199
request:
339 hidnplayr 200
    call    parseResponse
104 hidnplayr 201
 
336 hidnplayr 202
    cmp     [dhcpMsgType], byte 0x05	    ; Was the response an ACK? It should be
203
    jne     apipa			    ; NO - so we do zeroconf
104 hidnplayr 204
 
339 hidnplayr 205
    jmp     close
104 hidnplayr 206
 
207
;***************************************************************************
208
;   Function
209
;      parseResponse
210
;
211
;   Description
212
;      extracts the fields ( client IP address and options ) from
213
;      a DHCP response
214
;      The values go into
215
;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
216
;       dhcpDNSIP, dhcpSubnet
217
;      The message is stored in dhcpMsg
218
;
219
;***************************************************************************
220
parseResponse:
339 hidnplayr 221
    DEBUGF  1,"Data received, parsing response\n"
104 hidnplayr 222
    mov     edx, dhcpMsg
223
 
224
    pusha
336 hidnplayr 225
    eth.set_IP [edx+16]
226
    mov     eax,[edx]
227
    mov     [dhcpClientIP],eax
339 hidnplayr 228
    DEBUGF  1,"Client: %u.%u.%u.%u\n",[edx+16]:1,[edx+17]:1,[edx+18]:1,[edx+19]:1
104 hidnplayr 229
    popa
230
 
339 hidnplayr 231
    add     edx, 240			    ; Point to first option
232
    xor     ecx, ecx
104 hidnplayr 233
 
339 hidnplayr 234
next_option:
235
    add     edx, ecx
104 hidnplayr 236
pr001:
237
    mov     al, [edx]
339 hidnplayr 238
    cmp     al, 0xff			    ; End of options?
104 hidnplayr 239
    je	    pr_exit
240
 
339 hidnplayr 241
    cmp     al, dhcp_msg_type		    ; Msg type is a single byte option
242
    jne     @f
104 hidnplayr 243
 
244
    mov     al, [edx+2]
245
    mov     [dhcpMsgType], al
246
    add     edx, 3
339 hidnplayr 247
    jmp     pr001			    ; Get next option
104 hidnplayr 248
 
339 hidnplayr 249
@@:
104 hidnplayr 250
    inc     edx
251
    movzx   ecx, byte [edx]
339 hidnplayr 252
    inc     edx 			    ; point to data
104 hidnplayr 253
 
339 hidnplayr 254
    cmp     al, dhcp_dhcp_server_id	    ; server ip
255
    jne     @f
256
    mov     eax, [edx]
104 hidnplayr 257
    mov     [dhcpServerIP], eax
339 hidnplayr 258
    DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
259
    jmp     next_option
104 hidnplayr 260
 
339 hidnplayr 261
@@:
262
    cmp     al, dhcp_address_time
263
    jne     @f
104 hidnplayr 264
 
265
    pusha
339 hidnplayr 266
    mov     eax,[edx]
267
    bswap   eax
268
    mov     [dhcpLease],eax
269
    DEBUGF  1,"lease: %d\n",eax
104 hidnplayr 270
    popa
271
 
339 hidnplayr 272
    jmp     next_option
104 hidnplayr 273
 
339 hidnplayr 274
@@:
275
    cmp     al, dhcp_subnet_mask
276
    jne     @f
104 hidnplayr 277
 
278
    pusha
336 hidnplayr 279
    eth.set_SUBNET [edx]
339 hidnplayr 280
    DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
336 hidnplayr 281
    popa
104 hidnplayr 282
 
339 hidnplayr 283
    jmp     next_option
104 hidnplayr 284
 
339 hidnplayr 285
@@:
286
    cmp     al, dhcp_router
287
    jne     @f
104 hidnplayr 288
 
289
    pusha
336 hidnplayr 290
    eth.set_GATEWAY [edx]
339 hidnplayr 291
    DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
104 hidnplayr 292
    popa
293
 
339 hidnplayr 294
    jmp     next_option
104 hidnplayr 295
 
296
 
339 hidnplayr 297
@@:
298
    cmp     al, dhcp_domain_server
299
    jne     next_option
300
 
336 hidnplayr 301
    pusha
302
    eth.set_DNS [edx]
339 hidnplayr 303
    DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
104 hidnplayr 304
    popa
305
 
339 hidnplayr 306
    jmp     next_option
104 hidnplayr 307
 
336 hidnplayr 308
pr_exit:
104 hidnplayr 309
 
339 hidnplayr 310
;    DEBUGF  1,"Sending ARP announce\n"
311
;    eth.ARP_ANNOUNCE [dhcpClientIP]         ; send an ARP announce packet
104 hidnplayr 312
 
336 hidnplayr 313
    jmp close
104 hidnplayr 314
 
336 hidnplayr 315
apipa:
316
    call random
339 hidnplayr 317
    mov  ecx,0xfea9			    ; IP 169.254.0.0 link local net, see RFC3927
336 hidnplayr 318
    mov  cx,ax
339 hidnplayr 319
    eth.set_IP ecx			    ; mask is 255.255.0.0
320
    DEBUGF 1,"Link Local IP assinged: 169.254.%u.%u\n",[generator+2]:1,[generator+3]:1
336 hidnplayr 321
    eth.set_SUBNET 0xffff
322
    eth.set_GATEWAY 0x0
323
    eth.set_DNS 0x0
104 hidnplayr 324
 
339 hidnplayr 325
    wait PROBE_WAIT*100
104 hidnplayr 326
 
336 hidnplayr 327
    xor esi,esi
328
   probe_loop:
339 hidnplayr 329
    call  random			    ; create a pseudo random number in eax (seeded by MAC)
104 hidnplayr 330
 
339 hidnplayr 331
    cmp   al,PROBE_MIN*100		    ; check if al is bigger then PROBE_MIN
332
    jge   @f				    ; all ok
333
    add   al,(PROBE_MAX-PROBE_MIN)*100	    ; al is too small
336 hidnplayr 334
   @@:
104 hidnplayr 335
 
336 hidnplayr 336
    cmp   al,PROBE_MAX*100
337
    jle   @f
338
    sub   al,(PROBE_MAX-PROBE_MIN)*100
339
   @@:
104 hidnplayr 340
 
336 hidnplayr 341
    movzx ebx,al
339 hidnplayr 342
    DEBUGF  1,"Waiting %u0ms\n",ebx
343
    wait  ebx
104 hidnplayr 344
 
339 hidnplayr 345
    DEBUGF  1,"Sending Probe\n"
346
;    eth.ARP_PROBE MAC
336 hidnplayr 347
    inc   esi
104 hidnplayr 348
 
336 hidnplayr 349
    cmp   esi,PROBE_NUM
350
    jl	  probe_loop
104 hidnplayr 351
 
339 hidnplayr 352
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
336 hidnplayr 353
; IP within this time, we should create another adress, that have to be done later
104 hidnplayr 354
 
339 hidnplayr 355
    DEBUGF  1,"Waiting %us\n",ANNOUNCE_WAIT
356
    wait ANNOUNCE_WAIT*100
104 hidnplayr 357
    xor   esi,esi
336 hidnplayr 358
   announce_loop:
104 hidnplayr 359
 
339 hidnplayr 360
    DEBUGF  1,"Sending Announce\n"
361
;    eth.ARP_ANNOUNCE MAC
104 hidnplayr 362
 
363
    inc   esi
336 hidnplayr 364
    cmp   esi,ANNOUNCE_NUM
365
    je	  @f
104 hidnplayr 366
 
339 hidnplayr 367
    DEBUGF  1,"Waiting %us\n",ANNOUNCE_INTERVAL
368
    wait  ANNOUNCE_INTERVAL*100
336 hidnplayr 369
    jmp   announce_loop
370
   @@:
339 hidnplayr 371
    ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
104 hidnplayr 372
 
339 hidnplayr 373
close:
374
    DEBUGF  1,"Exiting\n"
375
    exit				    ; at last, exit
376
 
377
 
336 hidnplayr 378
random:
339 hidnplayr 379
 
336 hidnplayr 380
    mov   eax,[generator]
381
    add   eax,-43ab45b5h
382
    ror   eax,1
383
    bswap eax
384
    xor   eax,dword[MAC]
385
    ror   eax,1
386
    xor   eax,dword[MAC+2]
387
    mov   [generator],eax
339 hidnplayr 388
 
336 hidnplayr 389
ret
104 hidnplayr 390
 
336 hidnplayr 391
; DATA AREA
104 hidnplayr 392
 
339 hidnplayr 393
include_debug_strings
104 hidnplayr 394
 
395
IM_END:
396
 
336 hidnplayr 397
dhcpClientIP	dd  0
398
dhcpMsgType	db  0
399
dhcpLease	dd  0
400
dhcpServerIP	dd  0
104 hidnplayr 401
 
336 hidnplayr 402
dhcpMsgLen	dd  0
403
socketNum	dd  0
104 hidnplayr 404
 
336 hidnplayr 405
MAC		rb  6
406
currTime	dd  0
407
renewTime	dd  0
408
generator	dd  0
409
 
410
dhcpMsg 	rb  BUFFER
104 hidnplayr 411
I_END: