Subversion Repositories Kolibri OS

Rev

Rev 3618 | Rev 3636 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3618 Rev 3632
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  zeroconfig.asm - Zeroconfig service for KolibriOS              ;;
6
;;  zeroconfig.asm - Zeroconfig service for KolibriOS              ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
9
;;    Some code contributed by Derpenguin                          ;;
9
;;    Some code contributed by Derpenguin                          ;;
10
;;                                                                 ;;
10
;;                                                                 ;;
11
;;  DHCP code is based on that by Mike Hibbet                      ;;
11
;;  DHCP code is based on that by Mike Hibbet                      ;;
12
;;      (DHCP client for menuetos)                                 ;;
12
;;      (DHCP client for menuetos)                                 ;;
13
;;                                                                 ;;
13
;;                                                                 ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18
 
18
 
19
format binary as ""
19
format binary as ""
20
 
20
 
21
; CONFIGURATION
21
; CONFIGURATION
22
 
22
 
23
TIMEOUT                 = 60            ; in seconds
23
TIMEOUT                 = 3             ; in seconds
-
 
24
BUFFER                  = 1024          ; in bytes
24
BUFFER                  = 1024          ; in bytes
25
DHCP_TRIES              = 3             ; number of times to try contacting DHCP server
25
__DEBUG__               = 1             ; enable/disable
26
__DEBUG__               = 1             ; enable/disable
26
__DEBUG_LEVEL__         = 1             ; 1 = all, 2 = errors
27
__DEBUG_LEVEL__         = 1             ; 1 = all, 2 = errors
27
 
28
 
28
; CONFIGURATION FOR LINK-LOCAL
29
; CONFIGURATION FOR LINK-LOCAL
29
 
30
 
30
PROBE_WAIT              = 1             ; second  (initial random delay)
31
PROBE_WAIT              = 1             ; second  (initial random delay)
31
PROBE_MIN               = 1             ; second  (minimum delay till repeated probe)
32
PROBE_MIN               = 1             ; second  (minimum delay till repeated probe)
32
PROBE_MAX               = 2             ; seconds (maximum delay till repeated probe)
33
PROBE_MAX               = 2             ; seconds (maximum delay till repeated probe)
33
PROBE_NUM               = 3             ;         (number of probe packets)
34
PROBE_NUM               = 3             ;         (number of probe packets)
34
 
35
 
35
ANNOUNCE_NUM            = 2             ;         (number of announcement packets)
36
ANNOUNCE_NUM            = 2             ;         (number of announcement packets)
36
ANNOUNCE_INTERVAL       = 2             ; seconds (time between announcement packets)
37
ANNOUNCE_INTERVAL       = 2             ; seconds (time between announcement packets)
37
ANNOUNCE_WAIT           = 2             ; seconds (delay before announcing)
38
ANNOUNCE_WAIT           = 2             ; seconds (delay before announcing)
38
 
39
 
39
MAX_CONFLICTS           = 10            ;         (max conflicts before rate limiting)
40
MAX_CONFLICTS           = 10            ;         (max conflicts before rate limiting)
40
 
41
 
41
RATE_LIMIT_INTERVAL     = 60            ; seconds (delay between successive attempts)
42
RATE_LIMIT_INTERVAL     = 60            ; seconds (delay between successive attempts)
42
 
43
 
43
DEFEND_INTERVAL         = 10            ; seconds (min. wait between defensive ARPs)
44
DEFEND_INTERVAL         = 10            ; seconds (min. wait between defensive ARPs)
44
 
45
 
45
use32
46
use32
46
        org     0x0
47
        org     0x0
47
 
48
 
48
        db      'MENUET01'              ; 8 byte id
49
        db      'MENUET01'              ; 8 byte id
49
        dd      0x01                    ; header version
50
        dd      0x01                    ; header version
50
        dd      START                   ; start of code
51
        dd      START                   ; start of code
51
        dd      IM_END                  ; size of image
52
        dd      IM_END                  ; size of image
52
        dd      (I_END+0x100)           ; memory for app
53
        dd      (I_END+0x100)           ; memory for app
53
        dd      (I_END+0x100)           ; esp
54
        dd      (I_END+0x100)           ; esp
54
        dd      0, 0                    ; I_Param, I_Path
55
        dd      0, 0                    ; I_Param, I_Path
55
 
56
 
56
 
57
 
57
include '../../proc32.inc'
58
include '../../proc32.inc'
58
include '../../macros.inc'
59
include '../../macros.inc'
59
include '../../debug-fdo.inc'
60
include '../../debug-fdo.inc'
60
include '../../network.inc'
61
include '../../network.inc'
61
include 'dhcp.inc'
62
include 'dhcp.inc'
62
include '../../dll.inc'
63
include '../../dll.inc'
63
 
64
 
64
 
65
 
65
Ip2dword:
66
Ip2dword:
66
    push    edx
67
    push    edx
67
 
68
 
68
    ; This code validates if the query is an IP containing 4 numbers and 3 dots
69
    ; This code validates if the query is an IP containing 4 numbers and 3 dots
69
 
70
 
70
    xor     al, al            ; make al (dot count) zero
71
    xor     al, al            ; make al (dot count) zero
71
 
72
 
72
   @@:
73
   @@:
73
    cmp     byte[edx],'0'     ; check if this byte is a number, if not jump to no_IP
74
    cmp     byte[edx],'0'     ; check if this byte is a number, if not jump to no_IP
74
    jl      no_IP             ;
75
    jl      no_IP             ;
75
    cmp     byte[edx],'9'     ;
76
    cmp     byte[edx],'9'     ;
76
    jg      no_IP             ;
77
    jg      no_IP             ;
77
 
78
 
78
    inc     edx               ; the byte was a number, so lets check the next byte
79
    inc     edx               ; the byte was a number, so lets check the next byte
79
 
80
 
80
    cmp     byte[edx],0       ; is this byte zero? (have we reached end of query?)
81
    cmp     byte[edx],0       ; is this byte zero? (have we reached end of query?)
81
    jz      @f                ; jump to next @@ then
82
    jz      @f                ; jump to next @@ then
82
    cmp     byte[edx],':'
83
    cmp     byte[edx],':'
83
    jz      @f
84
    jz      @f
84
 
85
 
85
    cmp     byte[edx],'.'     ; is this byte a dot?
86
    cmp     byte[edx],'.'     ; is this byte a dot?
86
    jne     @r                ; if not, jump to previous @@
87
    jne     @r                ; if not, jump to previous @@
87
 
88
 
88
    inc     al                ; the byte was a dot so increment al(dot count)
89
    inc     al                ; the byte was a dot so increment al(dot count)
89
    inc     edx               ; next byte
90
    inc     edx               ; next byte
90
    jmp     @r                ; lets check for numbers again (jump to previous @@)
91
    jmp     @r                ; lets check for numbers again (jump to previous @@)
91
 
92
 
92
   @@:                        ; we reach this when end of query reached
93
   @@:                        ; we reach this when end of query reached
93
    cmp     al,3              ; check if there where 3 dots
94
    cmp     al,3              ; check if there where 3 dots
94
    jnz     no_IP             ; if not, jump to no_IP
95
    jnz     no_IP             ; if not, jump to no_IP
95
 
96
 
96
    ; The following code will convert this IP into a dword and output it in eax
97
    ; The following code will convert this IP into a dword and output it in eax
97
    ; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
98
    ; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
98
 
99
 
99
    pop     esi               ; edx (query address) was pushed onto stack and is now popped in esi
100
    pop     esi               ; edx (query address) was pushed onto stack and is now popped in esi
100
 
101
 
101
    xor     edx, edx          ; result
102
    xor     edx, edx          ; result
102
    xor     eax, eax          ; current character
103
    xor     eax, eax          ; current character
103
    xor     ebx, ebx          ; current byte
104
    xor     ebx, ebx          ; current byte
104
 
105
 
105
  .outer_loop:
106
  .outer_loop:
106
    shl     edx, 8
107
    shl     edx, 8
107
    add     edx, ebx
108
    add     edx, ebx
108
    xor     ebx, ebx
109
    xor     ebx, ebx
109
  .inner_loop:
110
  .inner_loop:
110
    lodsb
111
    lodsb
111
    test    eax, eax
112
    test    eax, eax
112
    jz      .finish
113
    jz      .finish
113
    cmp     al, '.'
114
    cmp     al, '.'
114
    jz      .outer_loop
115
    jz      .outer_loop
115
    sub     eax, '0'
116
    sub     eax, '0'
116
    imul    ebx, 10
117
    imul    ebx, 10
117
    add     ebx, eax
118
    add     ebx, eax
118
    jmp     .inner_loop
119
    jmp     .inner_loop
119
  .finish:
120
  .finish:
120
    shl     edx, 8
121
    shl     edx, 8
121
    add     edx, ebx
122
    add     edx, ebx
122
 
123
 
123
    bswap   edx               ; we want little endian order
124
    bswap   edx               ; we want little endian order
124
 
125
 
125
    ret
126
    ret
126
 
127
 
127
no_IP:
128
no_IP:
128
    pop     edx
129
    pop     edx
129
    xor     edx, edx
130
    xor     edx, edx
130
 
131
 
131
    ret
132
    ret
132
 
133
 
133
 
134
 
134
 
135
 
135
 
136
 
136
 
137
 
137
 
138
 
138
START:
139
START:
139
        mcall   40, EVM_STACK2
140
        mcall   40, EVM_STACK2
140
 
141
 
141
        DEBUGF  1,">Zero-config service loaded\n"
142
        DEBUGF  1,">Zero-config service loaded\n"
142
 
143
 
143
  .wait:
144
  .wait:
144
        mov     ebx, API_ETH + 0
145
        mov     ebx, API_ETH + 0
145
        mov     bh, [device]
146
        mov     bh, [device]
146
        mcall   76                              ; get MAC of ethernet interface 1
147
        mcall   76                              ; get MAC of ethernet interface 1
147
        cmp     eax, -1
148
        cmp     eax, -1
148
        jne     .start
149
        jne     .start
149
 
150
 
150
        mcall   10
151
        mcall   10
151
        jmp     .wait
152
        jmp     .wait
152
 
153
 
153
  .start:
154
  .start:
154
        mov     word[MAC], bx
155
        mov     word[MAC], bx
155
        mov     dword[MAC+2], eax
156
        mov     dword[MAC+2], eax
156
        DEBUGF  1,"->MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2
157
        DEBUGF  1,"->MAC: %x-%x-%x-%x-%x-%x\n", [MAC+0]:2, [MAC+1]:2, [MAC+2]:2, [MAC+3]:2, [MAC+4]:2, [MAC+5]:2
157
 
158
 
158
        mcall   40, EVM_STACK
159
        mcall   40, EVM_STACK
159
 
160
 
160
        mcall   68, 11
161
        mcall   68, 11
161
 
162
 
162
        stdcall dll.Load,@IMPORT
163
        stdcall dll.Load,@IMPORT
163
        or      eax, eax
164
        or      eax, eax
164
        jnz     try_dhcp
165
        jnz     try_dhcp
165
 
166
 
166
        invoke  ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
167
        invoke  ini.get_str, path, str_ipconfig, str_type, inibuf, 16, 0
167
 
168
 
168
        cmp     dword[inibuf], 'stat'
169
        cmp     dword[inibuf], 'stat'
169
        jne     try_dhcp
170
        jne     try_dhcp
170
 
171
 
171
        invoke  ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
172
        invoke  ini.get_str, path, str_ipconfig, str_ip, inibuf, 16, 0
172
        mov     edx, inibuf
173
        mov     edx, inibuf
173
        call    Ip2dword
174
        call    Ip2dword
174
        mcall   76, API_IPv4 + 3, edx
175
        mcall   76, API_IPv4 + 3, edx
175
 
176
 
176
        invoke  ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
177
        invoke  ini.get_str, path, str_ipconfig, str_gateway, inibuf, 16, 0
177
        mov     edx, inibuf
178
        mov     edx, inibuf
178
        call    Ip2dword
179
        call    Ip2dword
179
        mcall   76, API_IPv4 + 9, edx
180
        mcall   76, API_IPv4 + 9, edx
180
 
181
 
181
        invoke  ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
182
        invoke  ini.get_str, path, str_ipconfig, str_dns, inibuf, 16, 0
182
        mov     edx, inibuf
183
        mov     edx, inibuf
183
        call    Ip2dword
184
        call    Ip2dword
184
        mcall   76, API_IPv4 + 5, edx
185
        mcall   76, API_IPv4 + 5, edx
185
 
186
 
186
        invoke  ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
187
        invoke  ini.get_str, path, str_ipconfig, str_subnet, inibuf, 16, 0
187
        mov     edx, inibuf
188
        mov     edx, inibuf
188
        call    Ip2dword
189
        call    Ip2dword
189
        mcall   76, API_IPv4 + 7, edx
190
        mcall   76, API_IPv4 + 7, edx
190
 
191
 
191
 
192
 
192
        mcall   -1
193
        mcall   -1
193
 
194
 
194
 
195
 
195
try_dhcp:
196
try_dhcp:
-
 
197
 
-
 
198
        mov     [tries], DHCP_TRIES
196
 
199
 
197
        DEBUGF  1,"->Trying DHCP\n"
200
        DEBUGF  1,"->Trying DHCP\n"
198
 
201
 
199
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0          ; open socket (parameters: domain, type, reserved)
202
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0          ; open socket (parameters: domain, type, reserved)
200
        cmp     eax, -1
203
        cmp     eax, -1
201
        je      error
204
        je      error
202
        mov     [socketNum], eax
205
        mov     [socketNum], eax
203
 
206
 
204
        DEBUGF  1,"->Socket %x opened\n", eax
207
        DEBUGF  1,"->Socket %x opened\n", eax
205
 
208
 
206
        mcall   75, 2, [socketNum], sockaddr1, 18       ; bind socket to local port 68
209
        mcall   75, 2, [socketNum], sockaddr1, 18       ; bind socket to local port 68
207
        cmp     eax, -1
210
        cmp     eax, -1
208
        je      error
211
        je      error
209
 
212
 
210
        DEBUGF  1,"->Socket Bound to local port 68\n"
213
        DEBUGF  1,"->Socket Bound to local port 68\n"
211
 
214
 
212
        mcall   75, 4, [socketNum], sockaddr2, 18       ; connect to 255.255.255.255 on port 67
215
        mcall   75, 4, [socketNum], sockaddr2, 18       ; connect to 255.255.255.255 on port 67
213
        cmp     eax, -1
216
        cmp     eax, -1
214
        je      error
217
        je      error
215
 
218
 
216
        DEBUGF  1,"->Connected to 255.255.255.255 on port 67\n"
219
        DEBUGF  1,"->Connected to 255.255.255.255 on port 67\n"
217
 
220
 
218
        mov     [dhcpMsgType], 0x01                     ; DHCP discover
221
        mov     [dhcpMsgType], 0x01                     ; DHCP discover
219
        mov     [dhcpLease], esi                        ; esi is still -1 (-1 = forever)
222
        mov     [dhcpLease], esi                        ; esi is still -1 (-1 = forever)
220
 
223
 
221
        mcall   26, 9                                   ; Get system time
224
        mcall   26, 9                                   ; Get system time
222
        imul    eax, 100
225
        imul    eax, 100
223
        mov     [currTime], eax
226
        mov     [currTime], eax
224
 
227
 
225
build_request:                                          ; Creates a DHCP request packet.
228
build_request:                                          ; Creates a DHCP request packet.
226
 
229
 
227
        DEBUGF  1,"->Building request\n"
230
        DEBUGF  1,"->Building request\n"
228
 
231
 
229
        stdcall mem.Alloc, BUFFER
232
        stdcall mem.Alloc, BUFFER
230
        mov     [dhcpMsg], eax
233
        mov     [dhcpMsg], eax
231
        test    eax, eax
234
        test    eax, eax
232
        jz      dhcp_error
235
        jz      dhcp_error
233
 
236
 
234
            ;;; todo: skip this bullcrap
237
            ;;; todo: skip this bullcrap
235
 
238
 
236
        mov     edi, eax
239
        mov     edi, eax
237
        mov     ecx, BUFFER
240
        mov     ecx, BUFFER
238
        xor     eax, eax
241
        xor     eax, eax
239
        rep     stosb
242
        rep     stosb
240
 
243
 
241
            ;; todo: put this in a buffer instead of writing bytes and words!
244
            ;; todo: put this in a buffer instead of writing bytes and words!
242
 
245
 
243
        mov     edx, [dhcpMsg]
246
        mov     edx, [dhcpMsg]
244
 
247
 
245
        ; Boot protocol legacy
248
        ; Boot protocol legacy
246
        mov     [edx], byte 0x01                ; Boot request
249
        mov     [edx], byte 0x01                ; Boot request
247
        mov     [edx+1], byte 0x01              ; Ethernet
250
        mov     [edx+1], byte 0x01              ; Ethernet
248
        mov     [edx+2], byte 0x06              ; Ethernet h/w len
251
        mov     [edx+2], byte 0x06              ; Ethernet h/w len
249
        mov     [edx+4], dword 0x11223344       ; xid                 ;;;;;;;
252
        mov     [edx+4], dword 0x11223344       ; xid                 ;;;;;;;
250
        mov     eax, [currTime]
253
        mov     eax, [currTime]
251
        mov     [edx+8], eax                    ; secs, our uptime
254
        mov     [edx+8], eax                    ; secs, our uptime
252
        mov     [edx+10], byte 0x80             ; broadcast flag set
255
        mov     [edx+10], byte 0x80             ; broadcast flag set
253
        mov     eax, dword [MAC]                ; first 4 bytes of MAC
256
        mov     eax, dword [MAC]                ; first 4 bytes of MAC
254
        mov     [edx+28],dword eax
257
        mov     [edx+28],dword eax
255
        mov     ax, word [MAC+4]                ; last 2 bytes of MAC
258
        mov     ax, word [MAC+4]                ; last 2 bytes of MAC
256
        mov     [edx+32],word ax
259
        mov     [edx+32],word ax
257
 
260
 
258
        ; DHCP extension
261
        ; DHCP extension
259
        mov     [edx+236], dword 0x63538263     ; magic cookie
262
        mov     [edx+236], dword 0x63538263     ; magic cookie
260
        mov     [edx+240], word 0x0135          ; option DHCP msg type
263
        mov     [edx+240], word 0x0135          ; option DHCP msg type
261
        mov     al, [dhcpMsgType]
264
        mov     al, [dhcpMsgType]
262
        mov     [edx+240+2], al
265
        mov     [edx+240+2], al
263
        mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
266
        mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
264
        mov     eax, [dhcpLease]
267
        mov     eax, [dhcpLease]
265
        mov     [edx+240+5], eax
268
        mov     [edx+240+5], eax
266
        mov     [edx+240+9], word 0x0432        ; option requested IP address
269
        mov     [edx+240+9], word 0x0432        ; option requested IP address
267
        mov     eax, [dhcp.ip]
270
        mov     eax, [dhcp.ip]
268
        mov     [edx+240+11], eax
271
        mov     [edx+240+11], eax
269
        mov     [edx+240+15], word 0x0437       ; option request list
272
        mov     [edx+240+15], word 0x0437       ; option request list
270
        mov     [edx+240+17], dword 0x0f060301
273
        mov     [edx+240+17], dword 0x0f060301
271
 
274
 
272
        cmp     [dhcpMsgType], byte 0x01        ; Check which msg we are sending
275
        cmp     [dhcpMsgType], byte 0x01        ; Check which msg we are sending
273
        jne     request_options
276
        jne     request_options
274
 
277
 
275
        mov     [edx+240+21], byte 0xff         ; "Discover" options
278
        mov     [edx+240+21], byte 0xff         ; "Discover" options
276
 
279
 
277
        mov     [dhcpMsgLen], dword 262         ; end of options marker
280
        mov     [dhcpMsgLen], dword 262         ; end of options marker
278
        jmp     send_dhcpmsg
281
        jmp     send_dhcpmsg
279
 
282
 
280
request_options:
283
request_options:
281
        mov     [edx+240+21], word 0x0436       ; server IP
284
        mov     [edx+240+21], word 0x0436       ; server IP
282
        mov     eax, [dhcpServerIP]
285
        mov     eax, [dhcpServerIP]
283
        mov     [edx+240+23], eax
286
        mov     [edx+240+23], eax
284
 
287
 
285
        mov     [edx+240+27], byte 0xff         ; end of options marker
288
        mov     [edx+240+27], byte 0xff         ; end of options marker
286
 
289
 
287
        mov     [dhcpMsgLen], dword 268
290
        mov     [dhcpMsgLen], dword 268
288
 
291
 
289
send_dhcpmsg:
292
send_dhcpmsg:
-
 
293
        DEBUGF  1,"Sending DHCP request\n"
290
        mcall   75, 6, [socketNum], [dhcpMsg], [dhcpMsgLen]     ; write to socket ( send broadcast request )
294
        mcall   75, 6, [socketNum], [dhcpMsg], [dhcpMsgLen]     ; write to socket ( send broadcast request )
291
 
-
 
292
        mov     eax, [dhcpMsg]                          ; Setup the DHCP buffer to receive response
-
 
293
        mov     [dhcpMsgLen], eax                       ; Used as a pointer to the data
-
 
294
 
-
 
295
        mcall   23, TIMEOUT*10                          ; wait for data
295
        mcall   23, TIMEOUT*100                                 ; wait for data
296
 
296
 
297
read_data:                                              ; we have data - this will be the response
297
read_data:                                                      ; we have data - this will be the response
298
        mcall   75, 7, [socketNum], [dhcpMsg], BUFFER, 0   ; read data from socket
298
        mcall   75, 7, [socketNum], [dhcpMsg], BUFFER, 0        ; read data from socket
299
 
-
 
300
        DEBUGF  1,"->%d bytes received\n", eax
-
 
301
 
-
 
302
        cmp     eax, -1
299
        cmp     eax, -1
-
 
300
        jne     @f
-
 
301
        DEBUGF  1,"No answer from DHCP server\n"
303
        je      dhcp_error
302
        dec     [tries]
-
 
303
        jnz     send_dhcpmsg                    ; try again
-
 
304
        jmp     dhcp_error                      ; fail
-
 
305
 
-
 
306
  @@:
304
 
307
        DEBUGF  1,"->%d bytes received\n", eax
305
        mov     [dhcpMsgLen], eax
308
        mov     [dhcpMsgLen], eax
306
 
309
 
307
; depending on which msg we sent, handle the response
310
; depending on which msg we sent, handle the response
308
; accordingly.
311
; accordingly.
309
; If the response is to a dhcp discover, then:
312
; If the response is to a dhcp discover, then:
310
;  1) If response is DHCP OFFER then
313
;  1) If response is DHCP OFFER then
311
;  1.1) record server IP, lease time & IP address.
314
;  1.1) record server IP, lease time & IP address.
312
;  1.2) send a request packet
315
;  1.2) send a request packet
313
; If the response is to a dhcp request, then:
316
; If the response is to a dhcp request, then:
314
;  1) If the response is DHCP ACK then
317
;  1) If the response is DHCP ACK then
315
;  1.1) extract the DNS & subnet fields. Set them in the stack
318
;  1.1) extract the DNS & subnet fields. Set them in the stack
316
 
319
 
317
        cmp     [dhcpMsgType], 0x01             ; did we send a discover?
320
        cmp     [dhcpMsgType], 0x01             ; did we send a discover?
318
        je      discover
321
        je      discover
319
 
322
 
320
        cmp     [dhcpMsgType], 0x03             ; did we send a request?
323
        cmp     [dhcpMsgType], 0x03             ; did we send a request?
321
        je      request
324
        je      request
322
 
325
 
323
        call    dhcp_end                        ; we should never reach here ;)
326
        call    dhcp_end                        ; we should never reach here ;)
324
        jmp     exit
327
        jmp     exit
325
 
328
 
326
discover:
329
discover:
327
        call    parse_response
330
        call    parse_response
328
 
331
 
329
        cmp     [dhcpMsgType], 0x02             ; Was the response an offer?
332
        cmp     [dhcpMsgType], 0x02             ; Was the response an offer?
330
        je      send_request
333
        je      send_request
331
 
334
 
332
        call    dhcp_end
335
        call    dhcp_end
333
        jmp     link_local
336
        jmp     link_local
334
 
337
 
335
send_request:
338
send_request:
336
        mov     [dhcpMsgType], 0x03             ; make it a request
339
        mov     [dhcpMsgType], 0x03             ; make it a request
337
        jmp     build_request
340
        jmp     build_request
338
 
341
 
339
request:
342
request:
340
        call    parse_response
343
        call    parse_response
341
 
344
 
342
        cmp     [dhcpMsgType], 0x05             ; Was the response an ACK? It should be
345
        cmp     [dhcpMsgType], 0x05             ; Was the response an ACK? It should be
343
        jne     read_data                       ; NO - read next packets
346
        jne     read_data                       ; NO - read next packets
344
 
347
 
345
        call    dhcp_end
348
        call    dhcp_end
346
 
349
 
347
        mov     ebx, API_IPv4 + 3
350
        mov     ebx, API_IPv4 + 3
348
        mov     bh, [device]
351
        mov     bh, [device]
349
        mcall   76, , [dhcp.ip]                 ; ip
352
        mcall   76, , [dhcp.ip]                 ; ip
350
        mov     bl, 5
353
        mov     bl, 5
351
        mcall   76, , [dhcp.dns]                ; dns
354
        mcall   76, , [dhcp.dns]                ; dns
352
        mov     bl, 7
355
        mov     bl, 7
353
        mcall   76, , [dhcp.subnet]             ; subnet
356
        mcall   76, , [dhcp.subnet]             ; subnet
354
        mov     bl, 9
357
        mov     bl, 9
355
        mcall   76, , [dhcp.gateway]            ; gateway
358
        mcall   76, , [dhcp.gateway]            ; gateway
356
 
359
 
357
        jmp     exit
360
        jmp     exit
358
 
361
 
359
dhcp_end:
362
dhcp_end:
360
        mcall   close, [socketNum]
363
        mcall   close, [socketNum]
361
        stdcall mem.Free, [dhcpMsg]
364
        stdcall mem.Free, [dhcpMsg]
362
 
365
 
363
        ret
366
        ret
364
 
367
 
365
;***************************************************************************
368
;***************************************************************************
366
;   Function
369
;   Function
367
;      parseResponse
370
;      parseResponse
368
;
371
;
369
;   Description
372
;   Description
370
;      extracts the fields ( client IP address and options ) from
373
;      extracts the fields ( client IP address and options ) from
371
;      a DHCP response
374
;      a DHCP response
372
;      The values go into
375
;      The values go into
373
;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
376
;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
374
;       dhcpDNSIP, dhcpSubnet
377
;       dhcpDNSIP, dhcpSubnet
375
;      The message is stored in dhcpMsg
378
;      The message is stored in dhcpMsg
376
;
379
;
377
;***************************************************************************
380
;***************************************************************************
378
parse_response:
381
parse_response:
379
 
382
 
380
        DEBUGF  1,"Data received, parsing response\n"
383
        DEBUGF  1,"Data received, parsing response\n"
381
        mov     edx, [dhcpMsg]
384
        mov     edx, [dhcpMsg]
382
 
385
 
383
        push    dword [edx+16]
386
        push    dword [edx+16]
384
        pop     [dhcp.ip]
387
        pop     [dhcp.ip]
385
        DEBUGF  1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
388
        DEBUGF  1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
386
 
389
 
387
; TODO: check if there really are options
390
; TODO: check if there really are options
388
 
391
 
389
        mov     al, 240                         ; Point to first option
392
        mov     al, 240                         ; Point to first option
390
        movzx   ecx, al
393
        movzx   ecx, al
391
 
394
 
392
  .next_option:
395
  .next_option:
393
        add     edx, ecx
396
        add     edx, ecx
394
 
397
 
395
        mov     al, [edx]                       ; get message identifier
398
        mov     al, [edx]                       ; get message identifier
396
 
399
 
397
        cmp     al, 0xff                        ; End of options?
400
        cmp     al, 0xff                        ; End of options?
398
        je      .done
401
        je      .done
399
 
402
 
400
        cmp     al, 0
403
        cmp     al, 0
401
        je      .pad
404
        je      .pad
402
 
405
 
403
; TODO: check if we still are inside the buffer
406
; TODO: check if we still are inside the buffer
404
 
407
 
405
        inc     edx
408
        inc     edx
406
        movzx   ecx, byte [edx]                 ; get data length
409
        movzx   ecx, byte [edx]                 ; get data length
407
        inc     edx                             ; point to data
410
        inc     edx                             ; point to data
408
 
411
 
409
        cmp     al, dhcp_msg_type               ; Msg type is a single byte option
412
        cmp     al, dhcp_msg_type               ; Msg type is a single byte option
410
        je      .msgtype
413
        je      .msgtype
411
 
414
 
412
        cmp     al, dhcp_dhcp_server_id
415
        cmp     al, dhcp_dhcp_server_id
413
        je      .server
416
        je      .server
414
 
417
 
415
        cmp     al, dhcp_address_time
418
        cmp     al, dhcp_address_time
416
        je      .lease
419
        je      .lease
417
 
420
 
418
        cmp     al, dhcp_subnet_mask
421
        cmp     al, dhcp_subnet_mask
419
        je      .subnet
422
        je      .subnet
420
 
423
 
421
        cmp     al, dhcp_router
424
        cmp     al, dhcp_router
422
        je      .router
425
        je      .router
423
 
426
 
424
        cmp     al, dhcp_domain_server
427
        cmp     al, dhcp_domain_server
425
        je      .dns
428
        je      .dns
426
 
429
 
427
        DEBUGF  1,"Unsupported DHCP option: %u\n", al
430
        DEBUGF  1,"Unsupported DHCP option: %u\n", al
428
 
431
 
429
        jmp     .next_option
432
        jmp     .next_option
430
 
433
 
431
  .pad:
434
  .pad:
432
        xor     ecx, ecx
435
        xor     ecx, ecx
433
        inc     ecx
436
        inc     ecx
434
        jmp     .next_option
437
        jmp     .next_option
435
 
438
 
436
  .msgtype:
439
  .msgtype:
437
        mov     al, [edx]
440
        mov     al, [edx]
438
        mov     [dhcpMsgType], al
441
        mov     [dhcpMsgType], al
439
 
442
 
440
        DEBUGF  1,"DHCP Msg type: %u\n", al
443
        DEBUGF  1,"DHCP Msg type: %u\n", al
441
        jmp     .next_option                    ; Get next option
444
        jmp     .next_option                    ; Get next option
442
 
445
 
443
  .server:
446
  .server:
444
        mov     eax, [edx]
447
        mov     eax, [edx]
445
        mov     [dhcpServerIP], eax
448
        mov     [dhcpServerIP], eax
446
        DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
449
        DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
447
        jmp     .next_option
450
        jmp     .next_option
448
 
451
 
449
  .lease:
452
  .lease:
450
        pusha
453
        pusha
451
        mov     eax,[edx]
454
        mov     eax,[edx]
452
        bswap   eax
455
        bswap   eax
453
        mov     [dhcpLease],eax
456
        mov     [dhcpLease],eax
454
        DEBUGF  1,"lease: %d\n",eax
457
        DEBUGF  1,"lease: %d\n",eax
455
        popa
458
        popa
456
        jmp     .next_option
459
        jmp     .next_option
457
 
460
 
458
  .subnet:
461
  .subnet:
459
        push    dword [edx]
462
        push    dword [edx]
460
        pop     [dhcp.subnet]
463
        pop     [dhcp.subnet]
461
        DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
464
        DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
462
        jmp     .next_option
465
        jmp     .next_option
463
 
466
 
464
  .router:
467
  .router:
465
        push    dword [edx]
468
        push    dword [edx]
466
        pop     [dhcp.gateway]
469
        pop     [dhcp.gateway]
467
        DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
470
        DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
468
        jmp     .next_option
471
        jmp     .next_option
469
 
472
 
470
  .dns:
473
  .dns:
471
        push    dword [edx]
474
        push    dword [edx]
472
        pop     [dhcp.dns]
475
        pop     [dhcp.dns]
473
        DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
476
        DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
474
        jmp     .next_option
477
        jmp     .next_option
475
 
478
 
476
  .done:
479
  .done:
477
        ret
480
        ret
478
 
481
 
479
 
482
 
480
 
483
 
481
dhcp_error:
484
dhcp_error:
482
        call    dhcp_end
485
        call    dhcp_end
483
 
486
 
484
link_local:
487
link_local:
485
        call    random
488
        call    random
486
        mov     cx, ax
489
        mov     cx, ax
487
        shl     ecx, 16
490
        shl     ecx, 16
488
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
491
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
489
        mov     ebx, API_IPv4 + 3
492
        mov     ebx, API_IPv4 + 3
490
        mov     bh, [device]
493
        mov     bh, [device]
491
        mcall   76, , ecx                   ; mask is 255.255.0.0
494
        mcall   76, , ecx                   ; mask is 255.255.0.0
492
        DEBUGF  1,"Link Local IP assinged: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
495
        DEBUGF  1,"Link Local IP assinged: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
493
        mov     bl, 7
496
        mov     bl, 7
494
        mcall   76, , 0xffff
497
        mcall   76, , 0xffff
495
        mov     bl, 9
498
        mov     bl, 9
496
        mcall   76, , 0x0
499
        mcall   76, , 0x0
497
        mov     bl, 5
500
        mov     bl, 5
498
        mcall   76, , 0x0
501
        mcall   76, , 0x0
499
 
502
 
500
        mcall   5, PROBE_WAIT*100
503
        mcall   5, PROBE_WAIT*100
501
 
504
 
502
        xor     esi, esi
505
        xor     esi, esi
503
   probe_loop:
506
   probe_loop:
504
        call    random                                  ; create a pseudo random number in eax (seeded by MAC)
507
        call    random                                  ; create a pseudo random number in eax (seeded by MAC)
505
 
508
 
506
        cmp     al, PROBE_MIN*100                       ; check if al is bigger then PROBE_MIN
509
        cmp     al, PROBE_MIN*100                       ; check if al is bigger then PROBE_MIN
507
        jae     @f                                      ; all ok
510
        jae     @f                                      ; all ok
508
        add     al, (PROBE_MAX-PROBE_MIN)*100           ; al is too small
511
        add     al, (PROBE_MAX-PROBE_MIN)*100           ; al is too small
509
   @@:
512
   @@:
510
 
513
 
511
        cmp     al, PROBE_MAX*100
514
        cmp     al, PROBE_MAX*100
512
        jbe     @f
515
        jbe     @f
513
        sub     al, (PROBE_MAX-PROBE_MIN)*100
516
        sub     al, (PROBE_MAX-PROBE_MIN)*100
514
   @@:
517
   @@:
515
 
518
 
516
        movzx   ebx,al
519
        movzx   ebx,al
517
        DEBUGF  1,"Waiting %u0ms\n",ebx
520
        DEBUGF  1,"Waiting %u0ms\n",ebx
518
        mcall   5
521
        mcall   5
519
 
522
 
520
        DEBUGF  1,"Sending Probe\n"
523
        DEBUGF  1,"Sending Probe\n"
521
        mov     ebx, API_ARP + 6
524
        mov     ebx, API_ARP + 6
522
        mov     bh, [device]
525
        mov     bh, [device]
523
        mcall   76
526
        mcall   76
524
        inc     esi
527
        inc     esi
525
 
528
 
526
        cmp     esi, PROBE_NUM
529
        cmp     esi, PROBE_NUM
527
        jb      probe_loop
530
        jb      probe_loop
528
 
531
 
529
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
532
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
530
; IP within this time, we should create another adress, that have to be done later
533
; IP within this time, we should create another adress, that have to be done later
531
 
534
 
532
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_WAIT
535
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_WAIT
533
        mcall   5, ANNOUNCE_WAIT*100
536
        mcall   5, ANNOUNCE_WAIT*100
534
        xor   esi, esi
537
        xor   esi, esi
535
   announce_loop:
538
   announce_loop:
536
 
539
 
537
        DEBUGF  1,"Sending Announce\n"
540
        DEBUGF  1,"Sending Announce\n"
538
        mov     ebx, API_ARP + 6
541
        mov     ebx, API_ARP + 6
539
        mov     bh, [device]
542
        mov     bh, [device]
540
        mcall   76
543
        mcall   76
541
 
544
 
542
        inc     esi
545
        inc     esi
543
        cmp     esi,ANNOUNCE_NUM
546
        cmp     esi,ANNOUNCE_NUM
544
        je      @f
547
        je      @f
545
 
548
 
546
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_INTERVAL
549
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_INTERVAL
547
        mcall   5, ANNOUNCE_INTERVAL*100
550
        mcall   5, ANNOUNCE_INTERVAL*100
548
        jmp     announce_loop
551
        jmp     announce_loop
549
   @@:
552
   @@:
550
 
553
 
551
 
554
 
552
error:
555
error:
553
        DEBUGF  1,"Socket error\n"
556
        DEBUGF  1,"Socket error\n"
554
exit:   ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
557
exit:   ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
555
        mcall   -1
558
        mcall   -1
556
 
559
 
557
 
560
 
558
random:  ; Pseudo random actually
561
random:  ; Pseudo random actually
559
 
562
 
560
        mov     eax, [generator]
563
        mov     eax, [generator]
561
        add     eax, -43ab45b5h
564
        add     eax, -43ab45b5h
562
        ror     eax, 1
565
        ror     eax, 1
563
        bswap   eax
566
        bswap   eax
564
        xor     eax, dword[MAC]
567
        xor     eax, dword[MAC]
565
        ror     eax, 1
568
        ror     eax, 1
566
        xor     eax, dword[MAC+2]
569
        xor     eax, dword[MAC+2]
567
        mov     [generator], eax
570
        mov     [generator], eax
568
 
571
 
569
        ret
572
        ret
570
 
573
 
571
; DATA AREA
574
; DATA AREA
572
 
575
 
573
align 16
576
align 16
574
@IMPORT:
577
@IMPORT:
575
 
578
 
576
library \
579
library \
577
        libini,'libini.obj'
580
        libini,'libini.obj'
578
 
581
 
579
import  libini, \
582
import  libini, \
580
        ini.get_str,'ini_get_str'
583
        ini.get_str,'ini_get_str'
581
 
584
 
582
include_debug_strings
585
include_debug_strings
583
 
586
 
584
str_ip          db 'ip', 0
587
str_ip          db 'ip', 0
585
str_subnet      db 'subnet', 0
588
str_subnet      db 'subnet', 0
586
str_gateway     db 'gateway', 0
589
str_gateway     db 'gateway', 0
587
str_dns         db 'dns', 0
590
str_dns         db 'dns', 0
588
str_ipconfig    db 'ipconfig', 0
591
str_ipconfig    db 'ipconfig', 0
589
str_type        db 'type', 0
592
str_type        db 'type', 0
590
 
593
 
591
 
594
 
592
sockaddr1:
595
sockaddr1:
593
 
596
 
594
        dw AF_INET4
597
        dw AF_INET4
595
        dw 68 shl 8     ; local port
598
        dw 68 shl 8     ; local port
596
        dd 0            ; local IP
599
        dd 0            ; local IP
597
 
600
 
598
        rb 10
601
        rb 10
599
 
602
 
600
 
603
 
601
sockaddr2:
604
sockaddr2:
602
 
605
 
603
        dw AF_INET4
606
        dw AF_INET4
604
        dw 67 shl 8     ; destination port
607
        dw 67 shl 8     ; destination port
605
        dd -1           ; destination IP
608
        dd -1           ; destination IP
606
 
609
 
607
        rb 10
610
        rb 10
608
 
611
 
609
path            db  '/sys/network.ini'
612
path            db  '/sys/network.ini'
610
 
613
 
611
IM_END:
614
IM_END:
612
 
615
 
613
device          db 1
616
device          db 1
614
inibuf          rb 16
617
inibuf          rb 16
-
 
618
tries           db ?
615
 
619
 
616
dhcpMsgType     db  ?
620
dhcpMsgType     db ?
617
dhcpLease       dd  ?
621
dhcpLease       dd ?
618
dhcpServerIP    dd  ?
622
dhcpServerIP    dd ?
619
 
623
 
620
dhcp:
624
dhcp:
621
.ip             dd  ?
625
.ip             dd ?
622
.subnet         dd  ?
626
.subnet         dd ?
623
.dns            dd  ?
627
.dns            dd ?
624
.gateway        dd  ?
628
.gateway        dd ?
625
 
629
 
626
 
630
 
627
dhcpMsgLen      dd  ?
631
dhcpMsgLen      dd ?
628
socketNum       dd  ?
632
socketNum       dd ?
629
 
633
 
630
MAC             dp  ?
634
MAC             dp ?
631
 
635
 
632
currTime        dd  ?
636
currTime        dd ?
633
generator       dd  ?
637
generator       dd ?
634
 
638
 
635
dhcpMsg         dd  ?
639
dhcpMsg         dd ?
636
 
640
 
637
I_END:
641
I_END: