Subversion Repositories Kolibri OS

Rev

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