Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5391 hidnplayr 3
;; Copyright (C) KolibriOS team 2010-2015. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  zeroconfig.asm - Zeroconfig service for KolibriOS              ;;
7
;;                                                                 ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
9
;;    Some code contributed by Derpenguin                          ;;
10
;;                                                                 ;;
11
;;  DHCP code is based on that by Mike Hibbet                      ;;
3618 hidnplayr 12
;;      (DHCP client for menuetos)                                 ;;
3545 hidnplayr 13
;;                                                                 ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
 
19
format binary as ""
20
 
21
; CONFIGURATION
22
 
3632 hidnplayr 23
TIMEOUT                 = 3             ; in seconds
3545 hidnplayr 24
BUFFER                  = 1024          ; in bytes
3632 hidnplayr 25
DHCP_TRIES              = 3             ; number of times to try contacting DHCP server
3545 hidnplayr 26
__DEBUG__               = 1             ; enable/disable
3682 hidnplayr 27
__DEBUG_LEVEL__         = 2             ; 1 = all, 2 = errors
3545 hidnplayr 28
 
29
; CONFIGURATION FOR LINK-LOCAL
30
 
31
PROBE_WAIT              = 1             ; second  (initial random delay)
32
PROBE_MIN               = 1             ; second  (minimum delay till repeated probe)
33
PROBE_MAX               = 2             ; seconds (maximum delay till repeated probe)
34
PROBE_NUM               = 3             ;         (number of probe packets)
35
 
36
ANNOUNCE_NUM            = 2             ;         (number of announcement packets)
37
ANNOUNCE_INTERVAL       = 2             ; seconds (time between announcement packets)
38
ANNOUNCE_WAIT           = 2             ; seconds (delay before announcing)
39
 
40
MAX_CONFLICTS           = 10            ;         (max conflicts before rate limiting)
41
 
42
RATE_LIMIT_INTERVAL     = 60            ; seconds (delay between successive attempts)
43
 
44
DEFEND_INTERVAL         = 10            ; seconds (min. wait between defensive ARPs)
45
 
5586 hidnplayr 46
MAX_INTERFACES          = 8
47
 
3618 hidnplayr 48
use32
49
        org     0x0
3545 hidnplayr 50
 
3618 hidnplayr 51
        db      'MENUET01'              ; 8 byte id
52
        dd      0x01                    ; header version
53
        dd      START                   ; start of code
54
        dd      IM_END                  ; size of image
55
        dd      (I_END+0x100)           ; memory for app
56
        dd      (I_END+0x100)           ; esp
57
        dd      0, 0                    ; I_Param, I_Path
58
 
59
 
60
include '../../proc32.inc'
61
include '../../macros.inc'
62
include '../../debug-fdo.inc'
63
include '../../network.inc'
3545 hidnplayr 64
include 'dhcp.inc'
3618 hidnplayr 65
include '../../dll.inc'
3545 hidnplayr 66
 
5586 hidnplayr 67
struct  dhcp_msg
68
        op              db ?    ; Operation Code
69
        htype           db ?    ; Hardware type
70
        hlen            db ?    ; Hardware address length
71
        hops            db ?
72
        xid             dd ?    ; Transaction Identifier
73
        secs            dw ?    ; Seconds since boot
74
        flags           dw ?
75
        ciaddr          dd ?    ; Client IP address
76
        yiaddr          dd ?    ; "Your" IP address
77
        siaddr          dd ?    ; Server IP address
78
        giaddr          dd ?    ; Gateway IP address
79
        chaddr          rb 16   ; Client hardware address
80
        sname           rb 64   ; Server name
81
        file            rb 128  ; boot filename
82
        cookie          dd ?    ; Magic cookie (0x63538263)
83
        options         rb 512
84
ends
85
 
86
struct  interface
87
        number          dd ?
88
        state           dd ?    ; 0 - disconnected, 1 - connected
89
        mode            dd ?    ; 0 - static, 1 - dhcp, 2 - auto (zero config)
90
        tries           dd ?
91
        lease           dd ?
92
        ServerIP        dd ?
93
        ip              dd ?
94
        subnet          dd ?
95
        dns             dd ?
96
        gateway         dd ?
97
        socketNum       dd ?
98
        timeout         dd ?
99
        ip_conflicts    dd ?
100
ends
101
 
5391 hidnplayr 102
START:
5586 hidnplayr 103
        mcall   68, 11                  ; init heap
3545 hidnplayr 104
 
5586 hidnplayr 105
        stdcall dll.Load, @IMPORT       ; load libraries
5391 hidnplayr 106
        or      eax, eax
5586 hidnplayr 107
        jnz     exit_immediately
3545 hidnplayr 108
 
5586 hidnplayr 109
        DEBUGF  2, "Zero-config service loaded\n"
3545 hidnplayr 110
 
5586 hidnplayr 111
        mcall   40, EVM_STACK2          ; We only want low-level network events
3545 hidnplayr 112
 
5586 hidnplayr 113
; Set up interface list
114
        mov     edi, device_list
115
        xor     ebx, ebx
116
  @@:
117
        inc     ebx
118
        mov     eax, ebx
119
        stosd
120
        mov     ecx, sizeof.interface/4-1
121
        xor     eax,eax
122
        rep stosd
123
        cmp     ebx, MAX_INTERFACES
124
        jb      @b
125
 
126
        mov     ebp, device_list
127
mainloop:
128
        cmp     [ebp + interface.state], 0
129
        je      .link_up?
130
        jmp     .maintain_link
131
 
132
  .next:
133
        cmp     [ebp + interface.number], MAX_INTERFACES
134
        je      .wait
135
        add     ebp, sizeof.interface
136
        jmp     mainloop
137
 
138
  .wait:
139
        mcall   10                      ; Wait for event
140
        mov     ebp, device_list
141
        jmp     mainloop
142
 
143
  .link_up?:
144
        mov     bh, byte[ebp + interface.number]
145
        mov     bl, 0                   ; Get device type
5391 hidnplayr 146
        mcall   74
5586 hidnplayr 147
        cmp     eax, 1                  ; Ethernet
148
        jne     mainloop.next
3545 hidnplayr 149
 
5586 hidnplayr 150
        mov     bl, 10                  ; Get Link status
5391 hidnplayr 151
        mcall   74
152
        test    eax, eax
5586 hidnplayr 153
        jz      mainloop.next
3545 hidnplayr 154
 
5586 hidnplayr 155
        mov     [ebp + interface.state], 1
3545 hidnplayr 156
 
5586 hidnplayr 157
        call    create_str_ini_int
158
 
159
; Try to read settings from .ini file
160
        invoke  ini.get_str, ini_path, str_ini_int, str_ip_type, inibuf, 16, str_null
161
        test    eax, eax
162
        jz      @f
163
; If settings not found, use default settings from 'ip?' section
164
        mov     dword[str_ini_int], 'ip?'
165
  @@:
166
 
5391 hidnplayr 167
        mov     ebx, API_ETH + 0
5586 hidnplayr 168
        mov     bh, byte[ebp + interface.number]
169
        mcall   76                      ; get MAC of the ethernet interface
170
        mov     word[tx_msg.chaddr], bx
171
        mov     dword[tx_msg.chaddr+2], eax
172
        DEBUGF  1, "MAC: %x-%x-%x-%x-%x-%x\n", \
173
        [tx_msg.chaddr+0]:2, [tx_msg.chaddr+1]:2, [tx_msg.chaddr+2]:2, \
174
        [tx_msg.chaddr+3]:2, [tx_msg.chaddr+4]:2, [tx_msg.chaddr+5]:2
3545 hidnplayr 175
 
5586 hidnplayr 176
        invoke  ini.get_str, ini_path, str_ini_int, str_ip_type, inibuf, 16, str_null
177
        test    eax, eax
178
        jnz     .fail
179
        mov     eax, dword[inibuf]
180
        or      eax, 0x20202020
181
        mov     [ebp + interface.mode], 0
182
        cmp     eax, 'stat'
5391 hidnplayr 183
        je      static
5586 hidnplayr 184
        mov     [ebp + interface.mode], 1
185
        cmp     eax, 'dhcp'
186
        je      dhcp
187
        mov     [ebp + interface.mode], 2
188
        cmp     eax, 'auto'
189
        je      dhcp
3545 hidnplayr 190
 
5586 hidnplayr 191
  .fail:
192
        DEBUGF  2, "Invalid network.ini settings\n"
193
        mcall   -1                      ; Give up
3545 hidnplayr 194
 
5586 hidnplayr 195
  .maintain_link:
196
 
197
; Check for IP conflicts
198
        mov     ebx, API_ARP
199
        mov     bh, byte[ebp + interface.number]
200
        mov     bl, 7
201
        mcall   76                      ; Number of IP conflicts
202
        cmp     eax, [ebp + interface.ip_conflicts]
203
        je      @f
204
        mov     [ebp + interface.ip_conflicts], eax
205
        DEBUGF  2, "IP address conflict on interface %u\n", [ebp + interface.number]
206
        ; Notify user of the IP address conflict
207
        mov     [notify_struct.msg], str_conflict
208
        mcall   70, notify_struct
209
  @@:
210
 
211
; Check if device is still there
212
        mov     bh, byte[ebp + interface.number]
213
        mov     bl, 0                   ; Get device type
5391 hidnplayr 214
        mcall   74
5586 hidnplayr 215
        test    eax, eax                ; No device
216
        jz      .link_down
3545 hidnplayr 217
 
5586 hidnplayr 218
; Check if link is still there
219
        mov     bl, 10                  ; Get Link status
5391 hidnplayr 220
        mcall   74
221
        test    eax, eax
5586 hidnplayr 222
        jnz     .next
3545 hidnplayr 223
 
5586 hidnplayr 224
  .link_down:
225
        mov     [ebp + interface.state], 0
226
 
227
; Notify user that the link is down
228
        mov     [notify_struct.msg], str_disconnected
229
        mcall   70, notify_struct
230
 
231
; CHECKME: should we do this in kernel instead? Should we even do this at all?
5391 hidnplayr 232
        xor     ecx, ecx
233
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 234
        mov     bh, byte[ebp + interface.number]
235
        mcall   76                      ; ip
5391 hidnplayr 236
        mov     bl, 5
5586 hidnplayr 237
        mcall   76                      ; dns
5391 hidnplayr 238
        mov     bl, 7
5586 hidnplayr 239
        mcall   76                      ; subnet
5391 hidnplayr 240
        mov     bl, 9
5586 hidnplayr 241
        mcall   76                      ; gateway
3545 hidnplayr 242
 
5586 hidnplayr 243
        jmp     .next
3545 hidnplayr 244
 
5586 hidnplayr 245
link_up:
246
 
247
; Read number of previous IP conflicts
248
        mov     ebx, API_ARP
249
        mov     bh, byte[ebp + interface.number]
250
        mov     bl, 7
251
        mcall   76
252
        mov     [ebp + interface.ip_conflicts], eax
253
 
254
; Notify user that the link is up and running
255
        mov     [notify_struct.msg], str_connected
256
        mcall   70, notify_struct
257
 
258
  .fail:
259
        mcall   40, EVM_STACK2
260
        jmp     mainloop.next
261
 
5391 hidnplayr 262
static:
5586 hidnplayr 263
        DEBUGF  1, "Applying Static IP settings\n"
3545 hidnplayr 264
 
5586 hidnplayr 265
        invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
266
        mov     esi, inibuf
5391 hidnplayr 267
        call    ip_str_to_dword
3844 hidnplayr 268
        mov     ebx, API_IPv4 + 3       ; set IP
5586 hidnplayr 269
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 270
        mcall   76
3545 hidnplayr 271
 
5586 hidnplayr 272
        invoke  ini.get_str, ini_path, str_ini_int, str_subnet, inibuf, 16, str_null
273
        mov     esi, inibuf
5391 hidnplayr 274
        call    ip_str_to_dword
5586 hidnplayr 275
        mov     ebx, API_IPv4 + 7       ; set subnet
276
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 277
        mcall   76
3545 hidnplayr 278
 
5586 hidnplayr 279
        invoke  ini.get_str, ini_path, str_ini_int, str_gateway, inibuf, 16, str_null
280
        mov     esi, inibuf
5391 hidnplayr 281
        call    ip_str_to_dword
5586 hidnplayr 282
        mov     ebx, API_IPv4 + 9       ; set gateway
283
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 284
        mcall   76
3545 hidnplayr 285
 
5586 hidnplayr 286
  .dns:
287
        invoke  ini.get_str, ini_path, str_ini_int, str_dns, inibuf, 16, str_null
288
        mov     esi, inibuf
5391 hidnplayr 289
        call    ip_str_to_dword
5586 hidnplayr 290
        mov     ebx, API_IPv4 + 5       ; set DNS
291
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 292
        mcall   76
3545 hidnplayr 293
 
5586 hidnplayr 294
        jmp     link_up
3545 hidnplayr 295
 
296
 
5586 hidnplayr 297
dhcp:
3545 hidnplayr 298
 
5586 hidnplayr 299
        DEBUGF  2, "Trying to contact DHCP server\n"
3545 hidnplayr 300
 
5391 hidnplayr 301
        mcall   40, EVM_STACK
302
 
5586 hidnplayr 303
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0                          ; open socket (parameters: domain, type, reserved)
3545 hidnplayr 304
        cmp     eax, -1
5586 hidnplayr 305
        je      dhcp_error
306
        mov     [ebp + interface.socketNum], eax
307
 
308
        DEBUGF  1, "Socket %x opened\n", eax
309
 
310
        mcall   75, 2, [ebp + interface.socketNum], sock_local, 18      ; bind socket to local port 68
311
        cmp     eax, -1
5391 hidnplayr 312
        je      socket_error
3545 hidnplayr 313
 
5586 hidnplayr 314
        DEBUGF  1, "Socket Bound to local port 68\n"
3545 hidnplayr 315
 
5586 hidnplayr 316
        pushd   [ebp + interface.number]
317
        pushd   4                       ; length of option
318
        pushd   1 shl 9                 ; SO_BINDTODEVICE
319
        pushd   0                       ; SOL_SOCKET
320
        mcall   75, 8, [ebp + interface.socketNum], esp
321
        add     esp, 16
3545 hidnplayr 322
        cmp     eax, -1
5391 hidnplayr 323
        je      socket_error
3545 hidnplayr 324
 
5586 hidnplayr 325
        DEBUGF  1, "Socket Bound to local interface %u\n", [ebp + interface.number]
3545 hidnplayr 326
 
5586 hidnplayr 327
        mcall   75, 4, [ebp + interface.socketNum], sock_remote, 18     ; connect to 255.255.255.255 on port 67
3545 hidnplayr 328
        cmp     eax, -1
5391 hidnplayr 329
        je      socket_error
3545 hidnplayr 330
 
5586 hidnplayr 331
        DEBUGF  1, "Connected to 255.255.255.255 on port 67\n"
3545 hidnplayr 332
 
5586 hidnplayr 333
        ; Read preferred IP address from settings file
334
        invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
335
        mov     esi, inibuf
336
        call    ip_str_to_dword
337
        mov     [ebp + interface.ip], ecx
3545 hidnplayr 338
 
5419 hidnplayr 339
        call    random
5586 hidnplayr 340
        mov     [tx_msg.xid], eax                                       ; randomize session ID
341
        mov     [tx_msg_type], 1                                        ; DHCP discover
5419 hidnplayr 342
 
5586 hidnplayr 343
build_dhcp_packet:
5419 hidnplayr 344
 
5586 hidnplayr 345
        DEBUGF  1, "Building DHCP packet\n"
5419 hidnplayr 346
 
5586 hidnplayr 347
        mov     [ebp + interface.tries], DHCP_TRIES
3545 hidnplayr 348
 
5586 hidnplayr 349
        ; Boot protocol legacy
350
        mov     [tx_msg.op], 1                                          ; Boot request
351
        mov     [tx_msg.htype], 1                                       ; Ethernet
352
        mov     [tx_msg.hlen], 6                                        ; Ethernet address h/w len
353
        mov     [tx_msg.hops], 0
354
        mcall   26, 9                                                   ; Time since boot
355
        xor     edx, edx
356
        mov     ebx, 100
357
        div     ebx                                                     ; Divide by 100 to get number of seconds
358
        mov     [tx_msg.secs], ax
359
        mov     [tx_msg.flags], 0
3636 hidnplayr 360
 
5586 hidnplayr 361
        ; DHCP extension
362
        mov     [tx_msg.cookie], 0x63538263                             ; magic cookie
3545 hidnplayr 363
 
5586 hidnplayr 364
        mov     word[tx_msg+240], 0x0135                                ; option DHCP msg type
365
        mov     al,[tx_msg_type]
366
        mov     [tx_msg+240+2], al
3545 hidnplayr 367
 
5586 hidnplayr 368
        mov     word[tx_msg+240+3], 0x0433                              ; option Lease time
369
        mov     dword[tx_msg+240+5], -1                                 ; infinite
3545 hidnplayr 370
 
5586 hidnplayr 371
        mov     word[tx_msg+240+9], 0x0432                              ; option requested IP address
372
        mov     eax,[ebp + interface.ip]
373
        mov     [tx_msg+240+11], eax
3545 hidnplayr 374
 
5586 hidnplayr 375
        mov     word[tx_msg+240+15], 0x0437                             ; option request list
376
        mov     dword[tx_msg+240+17], 0x0f060301
3545 hidnplayr 377
 
5586 hidnplayr 378
        cmp     [tx_msg_type], 1                                        ; Check which msg we are sending
379
        jne     .request
3545 hidnplayr 380
 
5586 hidnplayr 381
        mov     byte[tx_msg+240+21], 0xff                               ; end of options marker
3545 hidnplayr 382
 
5586 hidnplayr 383
        mov     [tx_msg_len], 262                                       ; length
384
        jmp     send_dhcp_packet
3545 hidnplayr 385
 
5586 hidnplayr 386
  .request:
387
        mov     word[tx_msg+240+21], 0x0436                             ; server IP
388
        mov     eax,[ebp + interface.ServerIP]
389
        mov     [tx_msg+240+23], eax
3545 hidnplayr 390
 
5586 hidnplayr 391
        mov     byte[tx_msg+240+27], 0xff                               ; end of options marker
3545 hidnplayr 392
 
5586 hidnplayr 393
        mov     [tx_msg_len], 268                                       ; length
3545 hidnplayr 394
 
5419 hidnplayr 395
 
5586 hidnplayr 396
send_dhcp_packet:
397
        DEBUGF  1, "Sending DHCP packet\n"
398
        lea     edx, [tx_msg]
399
        mcall   75, 6, [ebp + interface.socketNum], , [tx_msg_len]
400
 
401
; Wait for reply
4805 hidnplayr 402
        mcall   26, 9
403
        add     eax, TIMEOUT*100
5586 hidnplayr 404
        mov     [ebp + interface.timeout], eax
405
        mov     ebx, TIMEOUT*100
3735 hidnplayr 406
  .wait:
5586 hidnplayr 407
        mcall   23                                                      ; Wait for event with timeout
408
read_packet:                                                            ; we have data - this will be the response
409
        lea     edx, [rx_msg]
410
        mcall   75, 7, [ebp + interface.socketNum], , BUFFER, MSG_DONTWAIT    ; read data from socket
3632 hidnplayr 411
        cmp     eax, -1
5419 hidnplayr 412
        jne     .got_data
4805 hidnplayr 413
 
414
        mcall   26, 9
5586 hidnplayr 415
        mov     ebx, eax
416
        sub     ebx, [ebp + interface.timeout]
417
        ja      send_dhcp_packet.wait
4805 hidnplayr 418
 
5586 hidnplayr 419
        DEBUGF  2, "No answer from DHCP server\n"
420
        dec     [ebp + interface.tries]
421
        jnz     send_dhcp_packet
5391 hidnplayr 422
        jmp     dhcp_fail
3545 hidnplayr 423
 
5419 hidnplayr 424
  .got_data:
5586 hidnplayr 425
        DEBUGF  1, "%d bytes received\n", eax
426
        mov     [rx_msg_len], eax
3545 hidnplayr 427
 
428
; depending on which msg we sent, handle the response
429
; accordingly.
430
; If the response is to a dhcp discover, then:
431
;  1) If response is DHCP OFFER then
432
;  1.1) record server IP, lease time & IP address.
433
;  1.2) send a request packet
434
; If the response is to a dhcp request, then:
435
;  1) If the response is DHCP ACK then
436
;  1.1) extract the DNS & subnet fields. Set them in the stack
437
 
5586 hidnplayr 438
        cmp     [tx_msg_type], 1                ; did we send a discover?
5419 hidnplayr 439
        je      discover_sent
5586 hidnplayr 440
        cmp     [tx_msg_type], 3                ; did we send a request?
5419 hidnplayr 441
        je      request_sent
5586 hidnplayr 442
        jmp     exit_immediately
3545 hidnplayr 443
 
5419 hidnplayr 444
discover_sent:
5586 hidnplayr 445
        call    parse_dhcp_reply
446
        cmp     [rx_msg_type], 2                ; Was the response an offer?
447
        jne     read_packet
3545 hidnplayr 448
 
3636 hidnplayr 449
        DEBUGF  1, "Got offer, making request\n"
5586 hidnplayr 450
        mov     [tx_msg_type], 3                ; make it a request
451
        jmp     build_dhcp_packet
3545 hidnplayr 452
 
5419 hidnplayr 453
request_sent:
5586 hidnplayr 454
        call    parse_dhcp_reply
455
        cmp     [rx_msg_type], 5                ; Was the response an ACK? It should be
456
        jne     read_packet                     ; NO - read next packets
3545 hidnplayr 457
 
5391 hidnplayr 458
        DEBUGF  2, "IP assigned by DHCP server successfully\n"
3636 hidnplayr 459
 
5586 hidnplayr 460
        mcall   close, [ebp + interface.socketNum]
3545 hidnplayr 461
 
3601 hidnplayr 462
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 463
        mov     bh, byte[ebp + interface.number]
464
        mcall   76, , [ebp + interface.ip]            ; ip
3601 hidnplayr 465
        mov     bl, 5
5586 hidnplayr 466
        mcall   76, , [ebp + interface.subnet]        ; subnet
3601 hidnplayr 467
        mov     bl, 9
5586 hidnplayr 468
        mcall   76, , [ebp + interface.gateway]       ; gateway
3545 hidnplayr 469
 
5586 hidnplayr 470
        invoke  ini.get_str, ini_path, str_ini_int, str_dns_type, inibuf, 16, str_null
471
        test    eax, eax
472
        jnz     @f
473
        mov     eax, dword[inibuf]
474
        or      eax, 0x202020
475
        cmp     eax, 'stat'
476
        je      static.dns
477
  @@:
478
        mcall   76, , [ebp + interface.dns]           ; dns
479
        mov     bl, 7
3545 hidnplayr 480
 
5586 hidnplayr 481
        jmp     link_up
3545 hidnplayr 482
 
483
 
5586 hidnplayr 484
parse_dhcp_reply:
3545 hidnplayr 485
 
5586 hidnplayr 486
        DEBUGF  1, "Parsing response\n"
487
        mov     [rx_msg_type], 0
488
 
5419 hidnplayr 489
; Verify if session ID matches
5586 hidnplayr 490
        mov     eax, [tx_msg.xid]
491
        cmp     [rx_msg.xid], eax
5419 hidnplayr 492
        jne     .done
493
 
5586 hidnplayr 494
        pushd   [rx_msg.yiaddr]
495
        pop     [ebp + interface.ip]
496
        DEBUGF  1, "Client: %u.%u.%u.%u\n", \
497
        [rx_msg.yiaddr]:1, [rx_msg.yiaddr+1]:1, [rx_msg.yiaddr+2]:1, [rx_msg.yiaddr+3]:1
3545 hidnplayr 498
 
5586 hidnplayr 499
; Verify magic cookie
500
        cmp     [rx_msg.cookie], 0x63538263
501
        jne     .done
3545 hidnplayr 502
 
5586 hidnplayr 503
; Parse the DHCP options
504
        lea     esi, [rx_msg]
505
        mov     ecx, 240                        ; point to the first option
3545 hidnplayr 506
  .next_option:
5586 hidnplayr 507
; TODO: check if we still are inside the buffer!
508
        add     esi, ecx
3545 hidnplayr 509
 
5586 hidnplayr 510
        lodsb                                   ; get message identifier
511
        mov     bl, al
512
        cmp     bl, 0xff                        ; End of options?
3545 hidnplayr 513
        je      .done
5586 hidnplayr 514
        test    bl, bl
515
        jz      .pad
3545 hidnplayr 516
 
5586 hidnplayr 517
        lodsb                                   ; load data length
518
        movzx   ecx, al
519
        cmp     bl, dhcp_msg_type               ; Msg type is a single byte option
3545 hidnplayr 520
        je      .msgtype
5586 hidnplayr 521
        cmp     bl, dhcp_dhcp_server_id
3545 hidnplayr 522
        je      .server
5586 hidnplayr 523
        cmp     bl, dhcp_address_time
3545 hidnplayr 524
        je      .lease
5586 hidnplayr 525
        cmp     bl, dhcp_subnet_mask
3545 hidnplayr 526
        je      .subnet
5586 hidnplayr 527
        cmp     bl, dhcp_router
3545 hidnplayr 528
        je      .router
5586 hidnplayr 529
        cmp     bl, dhcp_domain_server
3545 hidnplayr 530
        je      .dns
531
 
5586 hidnplayr 532
        DEBUGF  1, "Unsupported DHCP option: %u\n", bl
3545 hidnplayr 533
        jmp     .next_option
534
 
535
  .pad:
536
        xor     ecx, ecx
537
        inc     ecx
538
        jmp     .next_option
539
 
540
  .msgtype:
5586 hidnplayr 541
        mov     al, [esi]
542
        mov     [rx_msg_type], al
3545 hidnplayr 543
 
5586 hidnplayr 544
        DEBUGF  1, "DHCP Msg type: %u\n", al
3545 hidnplayr 545
        jmp     .next_option                    ; Get next option
546
 
547
  .server:
5586 hidnplayr 548
        pushd   [esi]
549
        pop     [ebp + interface.ServerIP]
550
        DEBUGF  1, "Server: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 551
        jmp     .next_option
552
 
553
  .lease:
554
        pusha
5586 hidnplayr 555
        mov     eax,[esi]
3545 hidnplayr 556
        bswap   eax
5586 hidnplayr 557
        mov     [ebp + interface.lease], eax
558
        DEBUGF  1, "Lease: %d\n", eax
3545 hidnplayr 559
        popa
560
        jmp     .next_option
561
 
562
  .subnet:
5586 hidnplayr 563
        pushd   [esi]
564
        pop     [ebp + interface.subnet]
565
        DEBUGF  1, "Subnet: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 566
        jmp     .next_option
567
 
568
  .router:
5586 hidnplayr 569
        pushd   [esi]
570
        pop     [ebp + interface.gateway]
571
        DEBUGF  1, "Gateway: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 572
        jmp     .next_option
573
 
574
  .dns:
5586 hidnplayr 575
        pushd   [esi]
576
        pop     [ebp + interface.dns]
577
        DEBUGF  1, "DNS: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 578
        jmp     .next_option
579
 
580
  .done:
581
        ret
582
 
5586 hidnplayr 583
exit_immediately:
584
        DEBUGF  2, "Zeroconf failed!\n"
585
        mcall   -1
5419 hidnplayr 586
 
5586 hidnplayr 587
socket_error:
588
        DEBUGF  2, "Socket error!\n"
589
 
5391 hidnplayr 590
dhcp_fail:
5586 hidnplayr 591
        mcall   close, [ebp + interface.socketNum]
3545 hidnplayr 592
 
5586 hidnplayr 593
dhcp_error:
594
        DEBUGF  1, "DHCP failed\n"
595
        cmp     [ebp + interface.mode], 2               ; zero config mode?
596
        jne     link_up
3545 hidnplayr 597
 
5586 hidnplayr 598
link_local:
3545 hidnplayr 599
 
5586 hidnplayr 600
; TODO: send ARP probes before setting the IP address in stack!
5419 hidnplayr 601
 
3545 hidnplayr 602
        call    random
603
        mov     cx, ax
604
        shl     ecx, 16
605
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
3601 hidnplayr 606
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 607
        mov     bh, byte[ebp + interface.number]
5419 hidnplayr 608
        mcall   76, , ecx                               ; mask is 255.255.0.0
5586 hidnplayr 609
        DEBUGF  2, "Link Local IP assigned: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
3601 hidnplayr 610
        mov     bl, 7
611
        mcall   76, , 0xffff
612
        mov     bl, 9
613
        mcall   76, , 0x0
614
        mov     bl, 5
615
        mcall   76, , 0x0
3545 hidnplayr 616
 
5586 hidnplayr 617
        jmp     link_up
3545 hidnplayr 618
 
619
 
620
random:  ; Pseudo random actually
621
 
5586 hidnplayr 622
        mov     eax,[generator]
3545 hidnplayr 623
        add     eax, -43ab45b5h
624
        ror     eax, 1
625
        bswap   eax
5586 hidnplayr 626
        xor     eax, dword[tx_msg.chaddr]
3545 hidnplayr 627
        ror     eax, 1
5586 hidnplayr 628
        xor     eax, dword[tx_msg.chaddr+2]
3545 hidnplayr 629
        mov     [generator], eax
630
 
631
        ret
632
 
5391 hidnplayr 633
 
634
 
5586 hidnplayr 635
create_str_ini_int:
636
        mov     eax, [ebp + interface.number]
637
        mov     ebx, 10
638
        xor     edx, edx
639
        push    0
640
  @@:
641
        div     ebx
642
        add     dl, '0'
643
        push    edx
644
        test    eax, eax
645
        jnz     @r
646
  @@:
647
        mov     edi, str_ini_int+2
648
  @@:
649
        pop     eax
650
        stosb
651
        test    eax, eax
652
        jnz     @r
5391 hidnplayr 653
 
5586 hidnplayr 654
        ret
5391 hidnplayr 655
 
656
 
657
 
5586 hidnplayr 658
; In: esi = ptr to ASCIIZ IP address
659
; Out: ecx = IP (0 on error)
5391 hidnplayr 660
 
5586 hidnplayr 661
ip_str_to_dword:
5391 hidnplayr 662
 
5586 hidnplayr 663
        xor     ecx, ecx        ; end result
664
  .charloop:
665
        lodsb
666
        test    al, al
667
        jz      .finish
668
        cmp     al, '.'
669
        je      .dot
670
        sub     al, '0'
671
        jb      .fail
672
        cmp     al, 9
673
        ja      .fail
674
        mov     dl, cl
675
        shl     cl, 2
676
        jc      .fail
677
        add     cl, dl
678
        jc      .fail
679
        add     cl, cl
680
        jc      .fail
681
        add     cl, al
682
        jc      .fail
683
        jmp     .charloop
684
  .dot:
685
        shl     ecx, 8
686
        jc      .fail
687
        xor     cl, cl
688
        jmp     .charloop
5391 hidnplayr 689
  .finish:
5586 hidnplayr 690
        bswap   ecx             ; we want little endian order
691
        ret
5391 hidnplayr 692
 
5586 hidnplayr 693
  .fail:
694
        xor     ecx, ecx
695
        ret
5391 hidnplayr 696
 
3545 hidnplayr 697
; DATA AREA
698
 
699
align 16
700
@IMPORT:
701
 
702
library \
5586 hidnplayr 703
        libini,         'libini.obj'
3545 hidnplayr 704
 
705
import  libini, \
5586 hidnplayr 706
        ini.get_str,    'ini_get_str',\
707
        ini.set_str,    'ini_set_str'
3545 hidnplayr 708
 
709
include_debug_strings
710
 
711
str_ip          db 'ip', 0
712
str_subnet      db 'subnet', 0
713
str_gateway     db 'gateway', 0
714
str_dns         db 'dns', 0
715
 
5586 hidnplayr 716
str_ip_type     db 'ip_type', 0
717
str_dns_type    db 'dns_type', 0
3545 hidnplayr 718
 
5586 hidnplayr 719
str_ini_int     db 'ip1', 0
720
                rb 10
3545 hidnplayr 721
 
5586 hidnplayr 722
str_null        db 0
723
 
724
sock_local:
3545 hidnplayr 725
        dw AF_INET4
726
        dw 68 shl 8     ; local port
727
        dd 0            ; local IP
728
        rb 10
729
 
730
 
5586 hidnplayr 731
sock_remote:
3545 hidnplayr 732
        dw AF_INET4
733
        dw 67 shl 8     ; destination port
734
        dd -1           ; destination IP
735
        rb 10
736
 
4013 hidnplayr 737
notify_struct:
738
        dd 7            ; run application
739
        dd 0
740
 .msg   dd 0
741
        dd 0
742
        dd 0
743
        db '/sys/@notify', 0
3545 hidnplayr 744
 
5586 hidnplayr 745
str_connected           db '"You are now connected to the network." -N', 0
746
str_disconnected        db '"You are now disconnected from the network." -N', 0
747
str_conflict            db '"An IP address conflict has been detected on the network." -W', 0
5419 hidnplayr 748
 
5586 hidnplayr 749
ini_path                db '/sys/settings/network.ini',0
4013 hidnplayr 750
 
3545 hidnplayr 751
IM_END:
752
 
5586 hidnplayr 753
generator       dd ?
754
 
3545 hidnplayr 755
inibuf          rb 16
756
 
5586 hidnplayr 757
tx_msg_len      dd ?
758
rx_msg_len      dd ?
759
tx_msg_type     db ?
760
rx_msg_type     db ?
761
tx_msg          dhcp_msg
762
rx_msg          dhcp_msg
3545 hidnplayr 763
 
5586 hidnplayr 764
device_list     rd MAX_INTERFACES*sizeof.interface
3545 hidnplayr 765
 
766
I_END: