Subversion Repositories Kolibri OS

Rev

Rev 6123 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
6123 hidnplayr 3
;; Copyright (C) KolibriOS team 2010-2016. 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
 
5842 hidnplayr 23
TIMEOUT                 = 5             ; 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
5610 hidnplayr 89
        mode            dd ?    ; 0 - disabled, 1 - static, 2 - dhcp, 3 - auto (zero config)
5586 hidnplayr 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
5610 hidnplayr 178
        jnz     .invalid
5586 hidnplayr 179
        mov     eax, dword[inibuf]
180
        or      eax, 0x20202020
181
        mov     [ebp + interface.mode], 0
5610 hidnplayr 182
        cmp     eax, 'disa'
183
        je      .next
184
        mov     [ebp + interface.mode], 1
5586 hidnplayr 185
        cmp     eax, 'stat'
5391 hidnplayr 186
        je      static
5610 hidnplayr 187
        mov     [ebp + interface.mode], 2
5586 hidnplayr 188
        cmp     eax, 'dhcp'
189
        je      dhcp
5610 hidnplayr 190
        mov     [ebp + interface.mode], 3
5586 hidnplayr 191
        cmp     eax, 'auto'
192
        je      dhcp
3545 hidnplayr 193
 
5610 hidnplayr 194
  .invalid:
195
        DEBUGF  2, "Invalid settings for interface: %s.\n", str_ini_int
196
        jmp     .next
3545 hidnplayr 197
 
5586 hidnplayr 198
  .maintain_link:
199
 
200
; Check for IP conflicts
201
        mov     ebx, API_ARP
202
        mov     bh, byte[ebp + interface.number]
203
        mov     bl, 7
204
        mcall   76                      ; Number of IP conflicts
205
        cmp     eax, [ebp + interface.ip_conflicts]
206
        je      @f
207
        mov     [ebp + interface.ip_conflicts], eax
208
        DEBUGF  2, "IP address conflict on interface %u\n", [ebp + interface.number]
209
        ; Notify user of the IP address conflict
210
        mov     [notify_struct.msg], str_conflict
211
        mcall   70, notify_struct
212
  @@:
213
 
214
; Check if device is still there
215
        mov     bh, byte[ebp + interface.number]
216
        mov     bl, 0                   ; Get device type
5391 hidnplayr 217
        mcall   74
5586 hidnplayr 218
        test    eax, eax                ; No device
219
        jz      .link_down
3545 hidnplayr 220
 
5586 hidnplayr 221
; Check if link is still there
222
        mov     bl, 10                  ; Get Link status
5391 hidnplayr 223
        mcall   74
224
        test    eax, eax
5586 hidnplayr 225
        jnz     .next
3545 hidnplayr 226
 
5586 hidnplayr 227
  .link_down:
228
        mov     [ebp + interface.state], 0
229
 
230
; Notify user that the link is down
231
        mov     [notify_struct.msg], str_disconnected
232
        mcall   70, notify_struct
233
 
234
; CHECKME: should we do this in kernel instead? Should we even do this at all?
5391 hidnplayr 235
        xor     ecx, ecx
236
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 237
        mov     bh, byte[ebp + interface.number]
238
        mcall   76                      ; ip
5391 hidnplayr 239
        mov     bl, 5
5586 hidnplayr 240
        mcall   76                      ; dns
5391 hidnplayr 241
        mov     bl, 7
5586 hidnplayr 242
        mcall   76                      ; subnet
5391 hidnplayr 243
        mov     bl, 9
5586 hidnplayr 244
        mcall   76                      ; gateway
3545 hidnplayr 245
 
5586 hidnplayr 246
        jmp     .next
3545 hidnplayr 247
 
5586 hidnplayr 248
link_up:
249
 
250
; Read number of previous IP conflicts
251
        mov     ebx, API_ARP
252
        mov     bh, byte[ebp + interface.number]
253
        mov     bl, 7
254
        mcall   76
255
        mov     [ebp + interface.ip_conflicts], eax
256
 
257
; Notify user that the link is up and running
258
        mov     [notify_struct.msg], str_connected
259
        mcall   70, notify_struct
260
 
261
  .fail:
262
        mcall   40, EVM_STACK2
263
        jmp     mainloop.next
264
 
5391 hidnplayr 265
static:
5586 hidnplayr 266
        DEBUGF  1, "Applying Static IP settings\n"
3545 hidnplayr 267
 
5586 hidnplayr 268
        invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
269
        mov     esi, inibuf
5391 hidnplayr 270
        call    ip_str_to_dword
3844 hidnplayr 271
        mov     ebx, API_IPv4 + 3       ; set IP
5586 hidnplayr 272
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 273
        mcall   76
3545 hidnplayr 274
 
5586 hidnplayr 275
        invoke  ini.get_str, ini_path, str_ini_int, str_subnet, inibuf, 16, str_null
276
        mov     esi, inibuf
5391 hidnplayr 277
        call    ip_str_to_dword
5586 hidnplayr 278
        mov     ebx, API_IPv4 + 7       ; set subnet
279
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 280
        mcall   76
3545 hidnplayr 281
 
5586 hidnplayr 282
        invoke  ini.get_str, ini_path, str_ini_int, str_gateway, inibuf, 16, str_null
283
        mov     esi, inibuf
5391 hidnplayr 284
        call    ip_str_to_dword
5586 hidnplayr 285
        mov     ebx, API_IPv4 + 9       ; set gateway
286
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 287
        mcall   76
3545 hidnplayr 288
 
5586 hidnplayr 289
  .dns:
290
        invoke  ini.get_str, ini_path, str_ini_int, str_dns, inibuf, 16, str_null
291
        mov     esi, inibuf
5391 hidnplayr 292
        call    ip_str_to_dword
5586 hidnplayr 293
        mov     ebx, API_IPv4 + 5       ; set DNS
294
        mov     bh, byte[ebp + interface.number]
3844 hidnplayr 295
        mcall   76
3545 hidnplayr 296
 
5586 hidnplayr 297
        jmp     link_up
3545 hidnplayr 298
 
299
 
5586 hidnplayr 300
dhcp:
3545 hidnplayr 301
 
5586 hidnplayr 302
        DEBUGF  2, "Trying to contact DHCP server\n"
3545 hidnplayr 303
 
5391 hidnplayr 304
        mcall   40, EVM_STACK
305
 
5586 hidnplayr 306
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0                          ; open socket (parameters: domain, type, reserved)
3545 hidnplayr 307
        cmp     eax, -1
5586 hidnplayr 308
        je      dhcp_error
309
        mov     [ebp + interface.socketNum], eax
310
 
311
        DEBUGF  1, "Socket %x opened\n", eax
312
 
313
        mcall   75, 2, [ebp + interface.socketNum], sock_local, 18      ; bind socket to local port 68
314
        cmp     eax, -1
5391 hidnplayr 315
        je      socket_error
3545 hidnplayr 316
 
5586 hidnplayr 317
        DEBUGF  1, "Socket Bound to local port 68\n"
3545 hidnplayr 318
 
5586 hidnplayr 319
        pushd   [ebp + interface.number]
320
        pushd   4                       ; length of option
5842 hidnplayr 321
        pushd   SO_BINDTODEVICE
322
        pushd   SOL_SOCKET
5586 hidnplayr 323
        mcall   75, 8, [ebp + interface.socketNum], esp
324
        add     esp, 16
3545 hidnplayr 325
        cmp     eax, -1
5391 hidnplayr 326
        je      socket_error
3545 hidnplayr 327
 
5586 hidnplayr 328
        DEBUGF  1, "Socket Bound to local interface %u\n", [ebp + interface.number]
3545 hidnplayr 329
 
5586 hidnplayr 330
        mcall   75, 4, [ebp + interface.socketNum], sock_remote, 18     ; connect to 255.255.255.255 on port 67
3545 hidnplayr 331
        cmp     eax, -1
5391 hidnplayr 332
        je      socket_error
3545 hidnplayr 333
 
5586 hidnplayr 334
        DEBUGF  1, "Connected to 255.255.255.255 on port 67\n"
3545 hidnplayr 335
 
5586 hidnplayr 336
        ; Read preferred IP address from settings file
337
        invoke  ini.get_str, ini_path, str_ini_int, str_ip, inibuf, 16, str_null
338
        mov     esi, inibuf
339
        call    ip_str_to_dword
340
        mov     [ebp + interface.ip], ecx
3545 hidnplayr 341
 
5419 hidnplayr 342
        call    random
5586 hidnplayr 343
        mov     [tx_msg.xid], eax                                       ; randomize session ID
344
        mov     [tx_msg_type], 1                                        ; DHCP discover
5419 hidnplayr 345
 
5586 hidnplayr 346
build_dhcp_packet:
5419 hidnplayr 347
 
5586 hidnplayr 348
        DEBUGF  1, "Building DHCP packet\n"
5419 hidnplayr 349
 
5586 hidnplayr 350
        mov     [ebp + interface.tries], DHCP_TRIES
3545 hidnplayr 351
 
5586 hidnplayr 352
        ; Boot protocol legacy
353
        mov     [tx_msg.op], 1                                          ; Boot request
354
        mov     [tx_msg.htype], 1                                       ; Ethernet
355
        mov     [tx_msg.hlen], 6                                        ; Ethernet address h/w len
356
        mov     [tx_msg.hops], 0
357
        mcall   26, 9                                                   ; Time since boot
358
        xor     edx, edx
359
        mov     ebx, 100
360
        div     ebx                                                     ; Divide by 100 to get number of seconds
6228 hidnplayr 361
        xchg    al, ah                                                  ; Convert to big endian
5586 hidnplayr 362
        mov     [tx_msg.secs], ax
363
        mov     [tx_msg.flags], 0
3636 hidnplayr 364
 
5586 hidnplayr 365
        ; DHCP extension
366
        mov     [tx_msg.cookie], 0x63538263                             ; magic cookie
3545 hidnplayr 367
 
5586 hidnplayr 368
        mov     word[tx_msg+240], 0x0135                                ; option DHCP msg type
369
        mov     al,[tx_msg_type]
370
        mov     [tx_msg+240+2], al
3545 hidnplayr 371
 
5586 hidnplayr 372
        mov     word[tx_msg+240+3], 0x0433                              ; option Lease time
373
        mov     dword[tx_msg+240+5], -1                                 ; infinite
3545 hidnplayr 374
 
5586 hidnplayr 375
        mov     word[tx_msg+240+9], 0x0432                              ; option requested IP address
376
        mov     eax,[ebp + interface.ip]
377
        mov     [tx_msg+240+11], eax
3545 hidnplayr 378
 
5586 hidnplayr 379
        mov     word[tx_msg+240+15], 0x0437                             ; option request list
380
        mov     dword[tx_msg+240+17], 0x0f060301
3545 hidnplayr 381
 
5586 hidnplayr 382
        cmp     [tx_msg_type], 1                                        ; Check which msg we are sending
383
        jne     .request
3545 hidnplayr 384
 
5586 hidnplayr 385
        mov     byte[tx_msg+240+21], 0xff                               ; end of options marker
3545 hidnplayr 386
 
5586 hidnplayr 387
        mov     [tx_msg_len], 262                                       ; length
388
        jmp     send_dhcp_packet
3545 hidnplayr 389
 
5586 hidnplayr 390
  .request:
391
        mov     word[tx_msg+240+21], 0x0436                             ; server IP
392
        mov     eax,[ebp + interface.ServerIP]
393
        mov     [tx_msg+240+23], eax
3545 hidnplayr 394
 
5586 hidnplayr 395
        mov     byte[tx_msg+240+27], 0xff                               ; end of options marker
3545 hidnplayr 396
 
5586 hidnplayr 397
        mov     [tx_msg_len], 268                                       ; length
3545 hidnplayr 398
 
5419 hidnplayr 399
 
5586 hidnplayr 400
send_dhcp_packet:
401
        DEBUGF  1, "Sending DHCP packet\n"
402
        lea     edx, [tx_msg]
403
        mcall   75, 6, [ebp + interface.socketNum], , [tx_msg_len]
404
 
405
; Wait for reply
4805 hidnplayr 406
        mcall   26, 9
407
        add     eax, TIMEOUT*100
5586 hidnplayr 408
        mov     [ebp + interface.timeout], eax
409
        mov     ebx, TIMEOUT*100
3735 hidnplayr 410
  .wait:
5586 hidnplayr 411
        mcall   23                                                      ; Wait for event with timeout
412
read_packet:                                                            ; we have data - this will be the response
413
        lea     edx, [rx_msg]
414
        mcall   75, 7, [ebp + interface.socketNum], , BUFFER, MSG_DONTWAIT    ; read data from socket
3632 hidnplayr 415
        cmp     eax, -1
5419 hidnplayr 416
        jne     .got_data
4805 hidnplayr 417
 
418
        mcall   26, 9
5586 hidnplayr 419
        mov     ebx, eax
420
        sub     ebx, [ebp + interface.timeout]
421
        ja      send_dhcp_packet.wait
4805 hidnplayr 422
 
6123 hidnplayr 423
        DEBUGF  1, "No answer from DHCP server\n"
5586 hidnplayr 424
        dec     [ebp + interface.tries]
425
        jnz     send_dhcp_packet
5391 hidnplayr 426
        jmp     dhcp_fail
3545 hidnplayr 427
 
5419 hidnplayr 428
  .got_data:
5586 hidnplayr 429
        DEBUGF  1, "%d bytes received\n", eax
430
        mov     [rx_msg_len], eax
3545 hidnplayr 431
 
432
; depending on which msg we sent, handle the response
433
; accordingly.
434
; If the response is to a dhcp discover, then:
435
;  1) If response is DHCP OFFER then
436
;  1.1) record server IP, lease time & IP address.
437
;  1.2) send a request packet
438
; If the response is to a dhcp request, then:
439
;  1) If the response is DHCP ACK then
440
;  1.1) extract the DNS & subnet fields. Set them in the stack
441
 
5586 hidnplayr 442
        cmp     [tx_msg_type], 1                ; did we send a discover?
5419 hidnplayr 443
        je      discover_sent
5586 hidnplayr 444
        cmp     [tx_msg_type], 3                ; did we send a request?
5419 hidnplayr 445
        je      request_sent
5586 hidnplayr 446
        jmp     exit_immediately
3545 hidnplayr 447
 
5419 hidnplayr 448
discover_sent:
5586 hidnplayr 449
        call    parse_dhcp_reply
450
        cmp     [rx_msg_type], 2                ; Was the response an offer?
451
        jne     read_packet
3545 hidnplayr 452
 
3636 hidnplayr 453
        DEBUGF  1, "Got offer, making request\n"
5586 hidnplayr 454
        mov     [tx_msg_type], 3                ; make it a request
455
        jmp     build_dhcp_packet
3545 hidnplayr 456
 
5419 hidnplayr 457
request_sent:
5586 hidnplayr 458
        call    parse_dhcp_reply
459
        cmp     [rx_msg_type], 5                ; Was the response an ACK? It should be
460
        jne     read_packet                     ; NO - read next packets
3545 hidnplayr 461
 
6123 hidnplayr 462
        DEBUGF  2, "IP address %u.%u.%u.%u assigned to network interface %u by DHCP\n",\
463
        [ebp+interface.ip+0]:1, [ebp+interface.ip+1]:1, [ebp+interface.ip+2]:1, [ebp+interface.ip+3]:1, [ebp + interface.number]:1
3636 hidnplayr 464
 
5586 hidnplayr 465
        mcall   close, [ebp + interface.socketNum]
3545 hidnplayr 466
 
3601 hidnplayr 467
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 468
        mov     bh, byte[ebp + interface.number]
469
        mcall   76, , [ebp + interface.ip]            ; ip
5587 hidnplayr 470
        mov     bl, 7
5586 hidnplayr 471
        mcall   76, , [ebp + interface.subnet]        ; subnet
3601 hidnplayr 472
        mov     bl, 9
5586 hidnplayr 473
        mcall   76, , [ebp + interface.gateway]       ; gateway
3545 hidnplayr 474
 
5586 hidnplayr 475
        invoke  ini.get_str, ini_path, str_ini_int, str_dns_type, inibuf, 16, str_null
476
        test    eax, eax
477
        jnz     @f
478
        mov     eax, dword[inibuf]
479
        or      eax, 0x202020
480
        cmp     eax, 'stat'
481
        je      static.dns
482
  @@:
5587 hidnplayr 483
        mov     ebx, API_IPv4 + 5
484
        mov     bh, byte[ebp + interface.number]
5586 hidnplayr 485
        mcall   76, , [ebp + interface.dns]           ; dns
3545 hidnplayr 486
 
5586 hidnplayr 487
        jmp     link_up
3545 hidnplayr 488
 
489
 
5586 hidnplayr 490
parse_dhcp_reply:
3545 hidnplayr 491
 
5586 hidnplayr 492
        DEBUGF  1, "Parsing response\n"
493
        mov     [rx_msg_type], 0
494
 
5419 hidnplayr 495
; Verify if session ID matches
5586 hidnplayr 496
        mov     eax, [tx_msg.xid]
497
        cmp     [rx_msg.xid], eax
5419 hidnplayr 498
        jne     .done
499
 
5586 hidnplayr 500
        pushd   [rx_msg.yiaddr]
501
        pop     [ebp + interface.ip]
502
        DEBUGF  1, "Client: %u.%u.%u.%u\n", \
503
        [rx_msg.yiaddr]:1, [rx_msg.yiaddr+1]:1, [rx_msg.yiaddr+2]:1, [rx_msg.yiaddr+3]:1
3545 hidnplayr 504
 
5586 hidnplayr 505
; Verify magic cookie
506
        cmp     [rx_msg.cookie], 0x63538263
507
        jne     .done
3545 hidnplayr 508
 
5586 hidnplayr 509
; Parse the DHCP options
510
        lea     esi, [rx_msg]
511
        mov     ecx, 240                        ; point to the first option
3545 hidnplayr 512
  .next_option:
5586 hidnplayr 513
; TODO: check if we still are inside the buffer!
514
        add     esi, ecx
3545 hidnplayr 515
 
5586 hidnplayr 516
        lodsb                                   ; get message identifier
517
        mov     bl, al
518
        cmp     bl, 0xff                        ; End of options?
3545 hidnplayr 519
        je      .done
5586 hidnplayr 520
        test    bl, bl
521
        jz      .pad
3545 hidnplayr 522
 
5586 hidnplayr 523
        lodsb                                   ; load data length
524
        movzx   ecx, al
525
        cmp     bl, dhcp_msg_type               ; Msg type is a single byte option
3545 hidnplayr 526
        je      .msgtype
5586 hidnplayr 527
        cmp     bl, dhcp_dhcp_server_id
3545 hidnplayr 528
        je      .server
5586 hidnplayr 529
        cmp     bl, dhcp_address_time
3545 hidnplayr 530
        je      .lease
5586 hidnplayr 531
        cmp     bl, dhcp_subnet_mask
3545 hidnplayr 532
        je      .subnet
5586 hidnplayr 533
        cmp     bl, dhcp_router
3545 hidnplayr 534
        je      .router
5586 hidnplayr 535
        cmp     bl, dhcp_domain_server
3545 hidnplayr 536
        je      .dns
537
 
5586 hidnplayr 538
        DEBUGF  1, "Unsupported DHCP option: %u\n", bl
3545 hidnplayr 539
        jmp     .next_option
540
 
541
  .pad:
542
        xor     ecx, ecx
543
        inc     ecx
544
        jmp     .next_option
545
 
546
  .msgtype:
5586 hidnplayr 547
        mov     al, [esi]
548
        mov     [rx_msg_type], al
3545 hidnplayr 549
 
5586 hidnplayr 550
        DEBUGF  1, "DHCP Msg type: %u\n", al
3545 hidnplayr 551
        jmp     .next_option                    ; Get next option
552
 
553
  .server:
5586 hidnplayr 554
        pushd   [esi]
555
        pop     [ebp + interface.ServerIP]
556
        DEBUGF  1, "Server: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 557
        jmp     .next_option
558
 
559
  .lease:
560
        pusha
5586 hidnplayr 561
        mov     eax,[esi]
3545 hidnplayr 562
        bswap   eax
5586 hidnplayr 563
        mov     [ebp + interface.lease], eax
564
        DEBUGF  1, "Lease: %d\n", eax
3545 hidnplayr 565
        popa
566
        jmp     .next_option
567
 
568
  .subnet:
5586 hidnplayr 569
        pushd   [esi]
570
        pop     [ebp + interface.subnet]
571
        DEBUGF  1, "Subnet: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 572
        jmp     .next_option
573
 
574
  .router:
5586 hidnplayr 575
        pushd   [esi]
576
        pop     [ebp + interface.gateway]
577
        DEBUGF  1, "Gateway: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 578
        jmp     .next_option
579
 
580
  .dns:
5586 hidnplayr 581
        pushd   [esi]
582
        pop     [ebp + interface.dns]
583
        DEBUGF  1, "DNS: %u.%u.%u.%u\n", [esi]:1, [esi+1]:1, [esi+2]:1, [esi+3]:1
3545 hidnplayr 584
        jmp     .next_option
585
 
586
  .done:
587
        ret
588
 
5586 hidnplayr 589
exit_immediately:
590
        DEBUGF  2, "Zeroconf failed!\n"
591
        mcall   -1
5419 hidnplayr 592
 
5586 hidnplayr 593
socket_error:
594
        DEBUGF  2, "Socket error!\n"
595
 
5391 hidnplayr 596
dhcp_fail:
5586 hidnplayr 597
        mcall   close, [ebp + interface.socketNum]
3545 hidnplayr 598
 
5586 hidnplayr 599
dhcp_error:
6123 hidnplayr 600
        DEBUGF  2, "DHCP failed\n"
5610 hidnplayr 601
        cmp     [ebp + interface.mode], 3               ; zero config mode?
5586 hidnplayr 602
        jne     link_up
3545 hidnplayr 603
 
5586 hidnplayr 604
link_local:
3545 hidnplayr 605
 
5586 hidnplayr 606
; TODO: send ARP probes before setting the IP address in stack!
5419 hidnplayr 607
 
3545 hidnplayr 608
        call    random
609
        mov     cx, ax
610
        shl     ecx, 16
611
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
3601 hidnplayr 612
        mov     ebx, API_IPv4 + 3
5586 hidnplayr 613
        mov     bh, byte[ebp + interface.number]
5419 hidnplayr 614
        mcall   76, , ecx                               ; mask is 255.255.0.0
6123 hidnplayr 615
        DEBUGF  2, "IP address 169.254.%u.%u assigned to network interface %u through Link-Local\n",\
616
        [generator+0]:1, [generator+1]:1, [ebp + interface.number]:1
3601 hidnplayr 617
        mov     bl, 7
618
        mcall   76, , 0xffff
619
        mov     bl, 9
620
        mcall   76, , 0x0
621
        mov     bl, 5
622
        mcall   76, , 0x0
3545 hidnplayr 623
 
5586 hidnplayr 624
        jmp     link_up
3545 hidnplayr 625
 
626
 
627
random:  ; Pseudo random actually
628
 
5586 hidnplayr 629
        mov     eax,[generator]
3545 hidnplayr 630
        add     eax, -43ab45b5h
631
        ror     eax, 1
632
        bswap   eax
5586 hidnplayr 633
        xor     eax, dword[tx_msg.chaddr]
3545 hidnplayr 634
        ror     eax, 1
5586 hidnplayr 635
        xor     eax, dword[tx_msg.chaddr+2]
3545 hidnplayr 636
        mov     [generator], eax
637
 
638
        ret
639
 
5391 hidnplayr 640
 
641
 
5586 hidnplayr 642
create_str_ini_int:
643
        mov     eax, [ebp + interface.number]
644
        mov     ebx, 10
645
        xor     edx, edx
646
        push    0
647
  @@:
648
        div     ebx
649
        add     dl, '0'
650
        push    edx
651
        test    eax, eax
652
        jnz     @r
653
  @@:
654
        mov     edi, str_ini_int+2
655
  @@:
656
        pop     eax
657
        stosb
658
        test    eax, eax
659
        jnz     @r
5391 hidnplayr 660
 
5586 hidnplayr 661
        ret
5391 hidnplayr 662
 
663
 
664
 
5586 hidnplayr 665
; In: esi = ptr to ASCIIZ IP address
666
; Out: ecx = IP (0 on error)
5391 hidnplayr 667
 
5586 hidnplayr 668
ip_str_to_dword:
5391 hidnplayr 669
 
5586 hidnplayr 670
        xor     ecx, ecx        ; end result
671
  .charloop:
672
        lodsb
673
        test    al, al
674
        jz      .finish
675
        cmp     al, '.'
676
        je      .dot
677
        sub     al, '0'
678
        jb      .fail
679
        cmp     al, 9
680
        ja      .fail
681
        mov     dl, cl
682
        shl     cl, 2
683
        jc      .fail
684
        add     cl, dl
685
        jc      .fail
686
        add     cl, cl
687
        jc      .fail
688
        add     cl, al
689
        jc      .fail
690
        jmp     .charloop
691
  .dot:
692
        shl     ecx, 8
693
        jc      .fail
694
        xor     cl, cl
695
        jmp     .charloop
5391 hidnplayr 696
  .finish:
5586 hidnplayr 697
        bswap   ecx             ; we want little endian order
698
        ret
5391 hidnplayr 699
 
5586 hidnplayr 700
  .fail:
701
        xor     ecx, ecx
702
        ret
5391 hidnplayr 703
 
3545 hidnplayr 704
; DATA AREA
705
 
706
align 16
707
@IMPORT:
708
 
709
library \
5586 hidnplayr 710
        libini,         'libini.obj'
3545 hidnplayr 711
 
712
import  libini, \
5586 hidnplayr 713
        ini.get_str,    'ini_get_str',\
714
        ini.set_str,    'ini_set_str'
3545 hidnplayr 715
 
716
include_debug_strings
717
 
718
str_ip          db 'ip', 0
719
str_subnet      db 'subnet', 0
720
str_gateway     db 'gateway', 0
721
str_dns         db 'dns', 0
722
 
5586 hidnplayr 723
str_ip_type     db 'ip_type', 0
724
str_dns_type    db 'dns_type', 0
3545 hidnplayr 725
 
5586 hidnplayr 726
str_ini_int     db 'ip1', 0
727
                rb 10
3545 hidnplayr 728
 
5586 hidnplayr 729
str_null        db 0
730
 
731
sock_local:
3545 hidnplayr 732
        dw AF_INET4
733
        dw 68 shl 8     ; local port
734
        dd 0            ; local IP
735
        rb 10
736
 
737
 
5586 hidnplayr 738
sock_remote:
3545 hidnplayr 739
        dw AF_INET4
740
        dw 67 shl 8     ; destination port
741
        dd -1           ; destination IP
742
        rb 10
743
 
4013 hidnplayr 744
notify_struct:
745
        dd 7            ; run application
746
        dd 0
747
 .msg   dd 0
748
        dd 0
749
        dd 0
750
        db '/sys/@notify', 0
3545 hidnplayr 751
 
5586 hidnplayr 752
str_connected           db '"You are now connected to the network." -N', 0
753
str_disconnected        db '"You are now disconnected from the network." -N', 0
754
str_conflict            db '"An IP address conflict has been detected on the network." -W', 0
5419 hidnplayr 755
 
5586 hidnplayr 756
ini_path                db '/sys/settings/network.ini',0
4013 hidnplayr 757
 
3545 hidnplayr 758
IM_END:
759
 
5586 hidnplayr 760
generator       dd ?
761
 
3545 hidnplayr 762
inibuf          rb 16
763
 
5586 hidnplayr 764
tx_msg_len      dd ?
765
rx_msg_len      dd ?
766
tx_msg_type     db ?
767
rx_msg_type     db ?
768
tx_msg          dhcp_msg
769
rx_msg          dhcp_msg
3545 hidnplayr 770
 
5586 hidnplayr 771
device_list     rd MAX_INTERFACES*sizeof.interface
3545 hidnplayr 772
 
773
I_END: