Subversion Repositories Kolibri OS

Rev

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

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