Subversion Repositories Kolibri OS

Rev

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

Rev 3735 Rev 3842
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
        mcall   76, API_IPv4 + 3, edx
175
        mcall   76, API_IPv4 + 3, edx
176
 
176
 
177
        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
178
        mov     edx, inibuf
178
        mov     edx, inibuf
179
        call    Ip2dword
179
        call    Ip2dword
180
        mcall   76, API_IPv4 + 9, edx
180
        mcall   76, API_IPv4 + 9, edx
181
 
181
 
182
        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
183
        mov     edx, inibuf
183
        mov     edx, inibuf
184
        call    Ip2dword
184
        call    Ip2dword
185
        mcall   76, API_IPv4 + 5, edx
185
        mcall   76, API_IPv4 + 5, edx
186
 
186
 
187
        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
188
        mov     edx, inibuf
188
        mov     edx, inibuf
189
        call    Ip2dword
189
        call    Ip2dword
190
        mcall   76, API_IPv4 + 7, edx
190
        mcall   76, API_IPv4 + 7, edx
191
 
191
 
192
 
192
 
193
        mcall   -1
193
        mcall   -1
194
 
194
 
195
 
195
 
196
try_dhcp:
196
try_dhcp:
197
 
197
 
198
        DEBUGF  1,"->Trying DHCP\n"
198
        DEBUGF  1,"->Trying DHCP\n"
199
 
199
 
200
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0          ; open socket (parameters: domain, type, reserved)
200
        mcall   75, 0, AF_INET4, SOCK_DGRAM, 0          ; open socket (parameters: domain, type, reserved)
201
        cmp     eax, -1
201
        cmp     eax, -1
202
        je      error
202
        je      error
203
        mov     [socketNum], eax
203
        mov     [socketNum], eax
204
 
204
 
205
        DEBUGF  1,"->Socket %x opened\n", eax
205
        DEBUGF  1,"->Socket %x opened\n", eax
206
 
206
 
207
        mcall   75, 2, [socketNum], sockaddr1, 18       ; bind socket to local port 68
207
        mcall   75, 2, [socketNum], sockaddr1, 18       ; bind socket to local port 68
208
        cmp     eax, -1
208
        cmp     eax, -1
209
        je      error
209
        je      error
210
 
210
 
211
        DEBUGF  1,"->Socket Bound to local port 68\n"
211
        DEBUGF  1,"->Socket Bound to local port 68\n"
212
 
212
 
213
        mcall   75, 4, [socketNum], sockaddr2, 18       ; connect to 255.255.255.255 on port 67
213
        mcall   75, 4, [socketNum], sockaddr2, 18       ; connect to 255.255.255.255 on port 67
214
        cmp     eax, -1
214
        cmp     eax, -1
215
        je      error
215
        je      error
216
 
216
 
217
        DEBUGF  1,"->Connected to 255.255.255.255 on port 67\n"
217
        DEBUGF  1,"->Connected to 255.255.255.255 on port 67\n"
218
 
218
 
219
        mov     [dhcpMsgType], 0x01                     ; DHCP discover
219
        mov     [dhcpMsgType], 0x01                     ; DHCP discover
220
        mov     [dhcpLease], esi                        ; esi is still -1 (-1 = forever)
220
        mov     [dhcpLease], esi                        ; esi is still -1 (-1 = forever)
221
 
221
 
222
        mcall   26, 9                                   ; Get system time
222
        mcall   26, 9                                   ; Get system time
223
        imul    eax, 100
223
        imul    eax, 100
224
        mov     [currTime], eax
224
        mov     [currTime], eax
225
 
225
 
226
build_request:                                          ; Creates a DHCP request packet.
226
build_request:                                          ; Creates a DHCP request packet.
227
 
227
 
228
        mov     [tries], DHCP_TRIES
228
        mov     [tries], DHCP_TRIES
229
 
229
 
230
        DEBUGF  1,"->Building request\n"
230
        DEBUGF  1,"->Building request\n"
231
 
231
 
232
        stdcall mem.Alloc, BUFFER
232
        stdcall mem.Alloc, BUFFER
233
        mov     [dhcpMsg], eax
233
        mov     [dhcpMsg], eax
234
        test    eax, eax
234
        test    eax, eax
235
        jz      dhcp_error
235
        jz      dhcp_error
236
 
236
 
237
            ;;; todo: skip this bullcrap
237
            ;;; todo: skip this bullcrap
238
 
238
 
239
        mov     edi, eax
239
        mov     edi, eax
240
        mov     ecx, BUFFER
240
        mov     ecx, BUFFER
241
        xor     eax, eax
241
        xor     eax, eax
242
        rep     stosb
242
        rep     stosb
243
 
243
 
244
            ;; 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!
245
 
245
 
246
        mov     edx, [dhcpMsg]
246
        mov     edx, [dhcpMsg]
247
 
247
 
248
        ; Boot protocol legacy
248
        ; Boot protocol legacy
249
        mov     [edx], byte 0x01                ; Boot request
249
        mov     [edx], byte 0x01                ; Boot request
250
        mov     [edx+1], byte 0x01              ; Ethernet
250
        mov     [edx+1], byte 0x01              ; Ethernet
251
        mov     [edx+2], byte 0x06              ; Ethernet h/w len
251
        mov     [edx+2], byte 0x06              ; Ethernet h/w len
252
        mov     [edx+4], dword 0x11223344       ; xid                 ;;;;;;;
252
        mov     [edx+4], dword 0x11223344       ; xid                 ;;;;;;;
253
        mov     eax, [currTime]
253
        mov     eax, [currTime]
254
        mov     [edx+8], eax                    ; secs, our uptime
254
        mov     [edx+8], eax                    ; secs, our uptime
255
        mov     [edx+10], byte 0x80             ; broadcast flag set
255
        mov     [edx+10], byte 0x80             ; broadcast flag set
256
        mov     eax, dword [MAC]                ; first 4 bytes of MAC
256
        mov     eax, dword [MAC]                ; first 4 bytes of MAC
257
        mov     [edx+28],dword eax
257
        mov     [edx+28],dword eax
258
        mov     ax, word [MAC+4]                ; last 2 bytes of MAC
258
        mov     ax, word [MAC+4]                ; last 2 bytes of MAC
259
        mov     [edx+32],word ax
259
        mov     [edx+32],word ax
260
 
260
 
261
        ; DHCP extension
261
        ; DHCP extension
262
        mov     [edx+236], dword 0x63538263     ; magic cookie
262
        mov     [edx+236], dword 0x63538263     ; magic cookie
263
        mov     [edx+240], word 0x0135          ; option DHCP msg type
263
        mov     [edx+240], word 0x0135          ; option DHCP msg type
264
        mov     al, [dhcpMsgType]
264
        mov     al, [dhcpMsgType]
265
        mov     [edx+240+2], al
265
        mov     [edx+240+2], al
266
        mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
266
        mov     [edx+240+3], word 0x0433        ; option Lease time = infinity
267
        mov     eax, [dhcpLease]
267
        mov     eax, [dhcpLease]
268
        mov     [edx+240+5], eax
268
        mov     [edx+240+5], eax
269
        mov     [edx+240+9], word 0x0432        ; option requested IP address
269
        mov     [edx+240+9], word 0x0432        ; option requested IP address
270
        mov     eax, [dhcp.ip]
270
        mov     eax, [dhcp.ip]
271
        mov     [edx+240+11], eax
271
        mov     [edx+240+11], eax
272
        mov     [edx+240+15], word 0x0437       ; option request list
272
        mov     [edx+240+15], word 0x0437       ; option request list
273
        mov     [edx+240+17], dword 0x0f060301
273
        mov     [edx+240+17], dword 0x0f060301
274
 
274
 
275
        cmp     [dhcpMsgType], 0x01             ; Check which msg we are sending
275
        cmp     [dhcpMsgType], 0x01             ; Check which msg we are sending
276
        jne     request_options
276
        jne     request_options
277
 
277
 
278
        mov     [edx+240+21], byte 0xff         ; end of options marker
278
        mov     [edx+240+21], byte 0xff         ; end of options marker
279
 
279
 
280
        mov     [dhcpMsgLen], 262               ; length
280
        mov     [dhcpMsgLen], 262               ; length
281
        jmp     send_dhcpmsg
281
        jmp     send_dhcpmsg
282
 
282
 
283
request_options:
283
request_options:
284
        mov     [edx+240+21], word 0x0436       ; server IP
284
        mov     [edx+240+21], word 0x0436       ; server IP
285
        mov     eax, [dhcpServerIP]
285
        mov     eax, [dhcpServerIP]
286
        mov     [edx+240+23], eax
286
        mov     [edx+240+23], eax
287
 
287
 
288
        mov     [edx+240+27], byte 0xff         ; end of options marker
288
        mov     [edx+240+27], byte 0xff         ; end of options marker
289
 
289
 
290
        mov     [dhcpMsgLen], 268               ; length
290
        mov     [dhcpMsgLen], 268               ; length
291
 
291
 
292
send_dhcpmsg:
292
send_dhcpmsg:
293
        DEBUGF  1,"Sending DHCP discover/request\n"
293
        DEBUGF  1,"Sending DHCP discover/request\n"
294
        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 )
295
  .wait:
295
  .wait:
296
        mcall   23, TIMEOUT*100                                 ; wait for data
296
        mcall   23, TIMEOUT*100                                 ; wait for data
297
 
297
 
298
read_data:                                                      ; we have data - this will be the response
298
read_data:                                                      ; we have data - this will be the response
299
        mcall   75, 7, [socketNum], [dhcpMsg], BUFFER, MSG_DONTWAIT     ; read data from socket
299
        mcall   75, 7, [socketNum], [dhcpMsg], BUFFER, MSG_DONTWAIT     ; read data from socket
300
        cmp     eax, -1
300
        cmp     eax, -1
301
        jne     @f
301
        jne     @f
302
        cmp     ebx, 6  ; EWOULDBLOCK
302
        cmp     ebx, 6  ; EWOULDBLOCK
303
        je      send_dhcpmsg.wait
303
        je      send_dhcpmsg.wait
304
        DEBUGF  1,"No answer from DHCP server\n"
304
        DEBUGF  1,"No answer from DHCP server\n"
305
        dec     [tries]
305
        dec     [tries]
306
        jnz     send_dhcpmsg                    ; try again
306
        jnz     send_dhcpmsg                    ; try again
307
        jmp     dhcp_error                      ; fail
307
        jmp     dhcp_error                      ; fail
308
 
308
 
309
  @@:
309
  @@:
310
        DEBUGF  1,"->%d bytes received\n", eax
310
        DEBUGF  1,"->%d bytes received\n", eax
311
        mov     [dhcpMsgLen], eax
311
        mov     [dhcpMsgLen], eax
312
 
312
 
313
; depending on which msg we sent, handle the response
313
; depending on which msg we sent, handle the response
314
; accordingly.
314
; accordingly.
315
; If the response is to a dhcp discover, then:
315
; If the response is to a dhcp discover, then:
316
;  1) If response is DHCP OFFER then
316
;  1) If response is DHCP OFFER then
317
;  1.1) record server IP, lease time & IP address.
317
;  1.1) record server IP, lease time & IP address.
318
;  1.2) send a request packet
318
;  1.2) send a request packet
319
; If the response is to a dhcp request, then:
319
; If the response is to a dhcp request, then:
320
;  1) If the response is DHCP ACK then
320
;  1) If the response is DHCP ACK then
321
;  1.1) extract the DNS & subnet fields. Set them in the stack
321
;  1.1) extract the DNS & subnet fields. Set them in the stack
322
 
322
 
323
        cmp     [dhcpMsgType], 0x01             ; did we send a discover?
323
        cmp     [dhcpMsgType], 0x01             ; did we send a discover?
324
        je      discover
324
        je      discover
325
 
325
 
326
        cmp     [dhcpMsgType], 0x03             ; did we send a request?
326
        cmp     [dhcpMsgType], 0x03             ; did we send a request?
327
        je      request
327
        je      request
328
 
328
 
329
        call    dhcp_end                        ; we should never reach here ;)
329
        call    dhcp_end                        ; we should never reach here ;)
330
        jmp     exit
330
        jmp     exit
331
 
331
 
332
discover:
332
discover:
333
        call    parse_response
333
        call    parse_response
334
 
334
 
335
        cmp     [dhcpMsgType2], 0x02            ; Was the response an offer?
335
        cmp     [dhcpMsgType2], 0x02            ; Was the response an offer?
336
        je      send_request
336
        je      send_request
337
 
337
 
338
        call    dhcp_end
338
        call    dhcp_end
339
        jmp     link_local
339
        jmp     link_local
340
 
340
 
341
send_request:
341
send_request:
342
        DEBUGF  1, "Got offer, making request\n"
342
        DEBUGF  1, "Got offer, making request\n"
343
        mov     [dhcpMsgType], 0x03             ; make it a request
343
        mov     [dhcpMsgType], 0x03             ; make it a request
344
        jmp     build_request
344
        jmp     build_request
345
 
345
 
346
request:
346
request:
347
        call    parse_response
347
        call    parse_response
348
 
348
 
349
        cmp     [dhcpMsgType2], 0x05            ; Was the response an ACK? It should be
349
        cmp     [dhcpMsgType2], 0x05            ; Was the response an ACK? It should be
350
        jne     read_data                       ; NO - read next packets
350
        jne     read_data                       ; NO - read next packets
351
 
351
 
352
        DEBUGF  2, "Setting IP using DHCP\n"
352
        DEBUGF  2, "Setting IP using DHCP\n"
353
 
353
 
354
        call    dhcp_end
354
        call    dhcp_end
355
 
355
 
356
        mov     ebx, API_IPv4 + 3
356
        mov     ebx, API_IPv4 + 3
357
        mov     bh, [device]
357
        mov     bh, [device]
358
        mcall   76, , [dhcp.ip]                 ; ip
358
        mcall   76, , [dhcp.ip]                 ; ip
359
        mov     bl, 5
359
        mov     bl, 5
360
        mcall   76, , [dhcp.dns]                ; dns
360
        mcall   76, , [dhcp.dns]                ; dns
361
        mov     bl, 7
361
        mov     bl, 7
362
        mcall   76, , [dhcp.subnet]             ; subnet
362
        mcall   76, , [dhcp.subnet]             ; subnet
363
        mov     bl, 9
363
        mov     bl, 9
364
        mcall   76, , [dhcp.gateway]            ; gateway
364
        mcall   76, , [dhcp.gateway]            ; gateway
365
 
365
 
366
        jmp     exit
366
        jmp     exit
367
 
367
 
368
dhcp_end:
368
dhcp_end:
369
        mcall   close, [socketNum]
369
        mcall   close, [socketNum]
370
        stdcall mem.Free, [dhcpMsg]
370
        stdcall mem.Free, [dhcpMsg]
371
 
371
 
372
        ret
372
        ret
373
 
373
 
374
;***************************************************************************
374
;***************************************************************************
375
;   Function
375
;   Function
376
;      parseResponse
376
;      parseResponse
377
;
377
;
378
;   Description
378
;   Description
379
;      extracts the fields ( client IP address and options ) from
379
;      extracts the fields ( client IP address and options ) from
380
;      a DHCP response
380
;      a DHCP response
381
;      The values go into
381
;      The values go into
382
;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
382
;       dhcpMsgType,dhcpLease,dhcpClientIP,dhcpServerIP,
383
;       dhcpDNSIP, dhcpSubnet
383
;       dhcpDNSIP, dhcpSubnet
384
;      The message is stored in dhcpMsg
384
;      The message is stored in dhcpMsg
385
;
385
;
386
;***************************************************************************
386
;***************************************************************************
387
parse_response:
387
parse_response:
388
 
388
 
389
        DEBUGF  1,"Data received, parsing response\n"
389
        DEBUGF  1,"Data received, parsing response\n"
390
        mov     edx, [dhcpMsg]
390
        mov     edx, [dhcpMsg]
391
        mov     [dhcpMsgType2], 0
391
        mov     [dhcpMsgType2], 0
392
 
392
 
393
        push    dword [edx+16]
393
        push    dword [edx+16]
394
        pop     [dhcp.ip]
394
        pop     [dhcp.ip]
395
        DEBUGF  1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
395
        DEBUGF  1,"Client: %u.%u.%u.%u\n", [edx+16]:1, [edx+17]:1, [edx+18]:1, [edx+19]:1
396
 
396
 
397
; TODO: check if there really are options
397
; TODO: check if there really are options
398
 
398
 
399
        mov     al, 240                         ; Point to first option
399
        mov     al, 240                         ; Point to first option
400
        movzx   ecx, al
400
        movzx   ecx, al
401
 
401
 
402
  .next_option:
402
  .next_option:
403
        add     edx, ecx
403
        add     edx, ecx
404
 
404
 
405
        mov     al, [edx]                       ; get message identifier
405
        mov     al, [edx]                       ; get message identifier
406
 
406
 
407
        cmp     al, 0xff                        ; End of options?
407
        cmp     al, 0xff                        ; End of options?
408
        je      .done
408
        je      .done
409
 
409
 
410
        cmp     al, 0
410
        cmp     al, 0
411
        je      .pad
411
        je      .pad
412
 
412
 
413
; TODO: check if we still are inside the buffer
413
; TODO: check if we still are inside the buffer
414
 
414
 
415
        inc     edx
415
        inc     edx
416
        movzx   ecx, byte [edx]                 ; get data length
416
        movzx   ecx, byte [edx]                 ; get data length
417
        inc     edx                             ; point to data
417
        inc     edx                             ; point to data
418
 
418
 
419
        cmp     al, dhcp_msg_type               ; Msg type is a single byte option
419
        cmp     al, dhcp_msg_type               ; Msg type is a single byte option
420
        je      .msgtype
420
        je      .msgtype
421
 
421
 
422
        cmp     al, dhcp_dhcp_server_id
422
        cmp     al, dhcp_dhcp_server_id
423
        je      .server
423
        je      .server
424
 
424
 
425
        cmp     al, dhcp_address_time
425
        cmp     al, dhcp_address_time
426
        je      .lease
426
        je      .lease
427
 
427
 
428
        cmp     al, dhcp_subnet_mask
428
        cmp     al, dhcp_subnet_mask
429
        je      .subnet
429
        je      .subnet
430
 
430
 
431
        cmp     al, dhcp_router
431
        cmp     al, dhcp_router
432
        je      .router
432
        je      .router
433
 
433
 
434
        cmp     al, dhcp_domain_server
434
        cmp     al, dhcp_domain_server
435
        je      .dns
435
        je      .dns
436
 
436
 
437
        DEBUGF  1,"Unsupported DHCP option: %u\n", al
437
        DEBUGF  1,"Unsupported DHCP option: %u\n", al
438
 
438
 
439
        jmp     .next_option
439
        jmp     .next_option
440
 
440
 
441
  .pad:
441
  .pad:
442
        xor     ecx, ecx
442
        xor     ecx, ecx
443
        inc     ecx
443
        inc     ecx
444
        jmp     .next_option
444
        jmp     .next_option
445
 
445
 
446
  .msgtype:
446
  .msgtype:
447
        mov     al, [edx]
447
        mov     al, [edx]
448
        mov     [dhcpMsgType2], al
448
        mov     [dhcpMsgType2], al
449
 
449
 
450
        DEBUGF  1,"DHCP Msg type: %u\n", al
450
        DEBUGF  1,"DHCP Msg type: %u\n", al
451
        jmp     .next_option                    ; Get next option
451
        jmp     .next_option                    ; Get next option
452
 
452
 
453
  .server:
453
  .server:
454
        mov     eax, [edx]
454
        mov     eax, [edx]
455
        mov     [dhcpServerIP], eax
455
        mov     [dhcpServerIP], eax
456
        DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
456
        DEBUGF  1,"Server: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
457
        jmp     .next_option
457
        jmp     .next_option
458
 
458
 
459
  .lease:
459
  .lease:
460
        pusha
460
        pusha
461
        mov     eax,[edx]
461
        mov     eax,[edx]
462
        bswap   eax
462
        bswap   eax
463
        mov     [dhcpLease],eax
463
        mov     [dhcpLease],eax
464
        DEBUGF  1,"lease: %d\n",eax
464
        DEBUGF  1,"lease: %d\n",eax
465
        popa
465
        popa
466
        jmp     .next_option
466
        jmp     .next_option
467
 
467
 
468
  .subnet:
468
  .subnet:
469
        push    dword [edx]
469
        push    dword [edx]
470
        pop     [dhcp.subnet]
470
        pop     [dhcp.subnet]
471
        DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
471
        DEBUGF  1,"Subnet: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
472
        jmp     .next_option
472
        jmp     .next_option
473
 
473
 
474
  .router:
474
  .router:
475
        push    dword [edx]
475
        push    dword [edx]
476
        pop     [dhcp.gateway]
476
        pop     [dhcp.gateway]
477
        DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
477
        DEBUGF  1,"Gateway: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
478
        jmp     .next_option
478
        jmp     .next_option
479
 
479
 
480
  .dns:
480
  .dns:
481
        push    dword [edx]
481
        push    dword [edx]
482
        pop     [dhcp.dns]
482
        pop     [dhcp.dns]
483
        DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
483
        DEBUGF  1,"DNS: %u.%u.%u.%u\n",[edx]:1,[edx+1]:1,[edx+2]:1,[edx+3]:1
484
        jmp     .next_option
484
        jmp     .next_option
485
 
485
 
486
  .done:
486
  .done:
487
        ret
487
        ret
488
 
488
 
489
 
489
 
490
 
490
 
491
dhcp_error:
491
dhcp_error:
492
        call    dhcp_end
492
        call    dhcp_end
493
 
493
 
494
link_local:
494
link_local:
495
        call    random
495
        call    random
496
        mov     cx, ax
496
        mov     cx, ax
497
        shl     ecx, 16
497
        shl     ecx, 16
498
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
498
        mov     cx, 0xfea9                              ; IP 169.254.0.0 link local net, see RFC3927
499
        mov     ebx, API_IPv4 + 3
499
        mov     ebx, API_IPv4 + 3
500
        mov     bh, [device]
500
        mov     bh, [device]
501
        mcall   76, , ecx                   ; mask is 255.255.0.0
501
        mcall   76, , ecx                   ; mask is 255.255.0.0
502
        DEBUGF  2,"Link Local IP assigned: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
502
        DEBUGF  2,"Link Local IP assigned: 169.254.%u.%u\n", [generator+0]:1, [generator+1]:1
503
        mov     bl, 7
503
        mov     bl, 7
504
        mcall   76, , 0xffff
504
        mcall   76, , 0xffff
505
        mov     bl, 9
505
        mov     bl, 9
506
        mcall   76, , 0x0
506
        mcall   76, , 0x0
507
        mov     bl, 5
507
        mov     bl, 5
508
        mcall   76, , 0x0
508
        mcall   76, , 0x0
509
 
509
 
510
        mcall   5, PROBE_WAIT*100
510
        mcall   5, PROBE_WAIT*100
511
 
511
 
512
        xor     esi, esi
512
        xor     esi, esi
513
   probe_loop:
513
   probe_loop:
514
        call    random                                  ; create a pseudo random number in eax (seeded by MAC)
514
        call    random                                  ; create a pseudo random number in eax (seeded by MAC)
515
 
515
 
516
        cmp     al, PROBE_MIN*100                       ; check if al is bigger then PROBE_MIN
516
        cmp     al, PROBE_MIN*100                       ; check if al is bigger then PROBE_MIN
517
        jae     @f                                      ; all ok
517
        jae     @f                                      ; all ok
518
        add     al, (PROBE_MAX-PROBE_MIN)*100           ; al is too small
518
        add     al, (PROBE_MAX-PROBE_MIN)*100           ; al is too small
519
   @@:
519
   @@:
520
 
520
 
521
        cmp     al, PROBE_MAX*100
521
        cmp     al, PROBE_MAX*100
522
        jbe     @f
522
        jbe     @f
523
        sub     al, (PROBE_MAX-PROBE_MIN)*100
523
        sub     al, (PROBE_MAX-PROBE_MIN)*100
524
   @@:
524
   @@:
525
 
525
 
526
        movzx   ebx,al
526
        movzx   ebx,al
527
        DEBUGF  1,"Waiting %u0ms\n",ebx
527
        DEBUGF  1,"Waiting %u0ms\n",ebx
528
        mcall   5
528
        mcall   5
529
 
529
 
530
        DEBUGF  1,"Sending Probe\n"
530
        DEBUGF  1,"Sending Probe\n"
531
        mov     ebx, API_ARP + 6
531
        mov     ebx, API_ARP + 6
532
        mov     bh, [device]
532
        mov     bh, [device]
533
        mcall   76
533
        mcall   76
534
        inc     esi
534
        inc     esi
535
 
535
 
536
        cmp     esi, PROBE_NUM
536
        cmp     esi, PROBE_NUM
537
        jb      probe_loop
537
        jb      probe_loop
538
 
538
 
539
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
539
; now we wait further ANNOUNCE_WAIT seconds and send ANNOUNCE_NUM ARP announces. If any other host has assingned
540
; IP within this time, we should create another adress, that have to be done later
540
; IP within this time, we should create another adress, that have to be done later
541
 
541
 
542
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_WAIT
542
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_WAIT
543
        mcall   5, ANNOUNCE_WAIT*100
543
        mcall   5, ANNOUNCE_WAIT*100
544
        xor   esi, esi
544
        xor   esi, esi
545
   announce_loop:
545
   announce_loop:
546
 
546
 
547
        DEBUGF  1,"Sending Announce\n"
547
        DEBUGF  1,"Sending Announce\n"
548
        mov     ebx, API_ARP + 6
548
        mov     ebx, API_ARP + 6
549
        mov     bh, [device]
549
        mov     bh, [device]
550
        mcall   76
550
        mcall   76
551
 
551
 
552
        inc     esi
552
        inc     esi
553
        cmp     esi,ANNOUNCE_NUM
553
        cmp     esi,ANNOUNCE_NUM
554
        je      @f
554
        je      @f
555
 
555
 
556
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_INTERVAL
556
        DEBUGF  1,"Waiting %us\n", ANNOUNCE_INTERVAL
557
        mcall   5, ANNOUNCE_INTERVAL*100
557
        mcall   5, ANNOUNCE_INTERVAL*100
558
        jmp     announce_loop
558
        jmp     announce_loop
559
   @@:
559
   @@:
560
 
560
 
561
 
561
 
562
error:
562
error:
563
        DEBUGF  2,"Socket error\n"
563
        DEBUGF  2,"Socket error\n"
564
exit:   ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
564
exit:   ; we should, instead of closing, detect ARP conflicts and detect if cable keeps connected ;)
565
        DEBUGF  2,"Exiting\n"
565
        DEBUGF  2,"Exiting\n"
566
        mcall   -1
566
        mcall   -1
567
 
567
 
568
 
568
 
569
random:  ; Pseudo random actually
569
random:  ; Pseudo random actually
570
 
570
 
571
        mov     eax, [generator]
571
        mov     eax, [generator]
572
        add     eax, -43ab45b5h
572
        add     eax, -43ab45b5h
573
        ror     eax, 1
573
        ror     eax, 1
574
        bswap   eax
574
        bswap   eax
575
        xor     eax, dword[MAC]
575
        xor     eax, dword[MAC]
576
        ror     eax, 1
576
        ror     eax, 1
577
        xor     eax, dword[MAC+2]
577
        xor     eax, dword[MAC+2]
578
        mov     [generator], eax
578
        mov     [generator], eax
579
 
579
 
580
        ret
580
        ret
581
 
581
 
582
; DATA AREA
582
; DATA AREA
583
 
583
 
584
align 16
584
align 16
585
@IMPORT:
585
@IMPORT:
586
 
586
 
587
library \
587
library \
588
        libini,'libini.obj'
588
        libini,'libini.obj'
589
 
589
 
590
import  libini, \
590
import  libini, \
591
        ini.get_str,'ini_get_str'
591
        ini.get_str,'ini_get_str'
592
 
592
 
593
include_debug_strings
593
include_debug_strings
594
 
594
 
595
str_ip          db 'ip', 0
595
str_ip          db 'ip', 0
596
str_subnet      db 'subnet', 0
596
str_subnet      db 'subnet', 0
597
str_gateway     db 'gateway', 0
597
str_gateway     db 'gateway', 0
598
str_dns         db 'dns', 0
598
str_dns         db 'dns', 0
599
str_ipconfig    db 'ipconfig', 0
599
str_ipconfig    db 'ipconfig', 0
600
str_type        db 'type', 0
600
str_type        db 'type', 0
601
 
601
 
602
 
602
 
603
sockaddr1:
603
sockaddr1:
604
 
604
 
605
        dw AF_INET4
605
        dw AF_INET4
606
        dw 68 shl 8     ; local port
606
        dw 68 shl 8     ; local port
607
        dd 0            ; local IP
607
        dd 0            ; local IP
608
 
608
 
609
        rb 10
609
        rb 10
610
 
610
 
611
 
611
 
612
sockaddr2:
612
sockaddr2:
613
 
613
 
614
        dw AF_INET4
614
        dw AF_INET4
615
        dw 67 shl 8     ; destination port
615
        dw 67 shl 8     ; destination port
616
        dd -1           ; destination IP
616
        dd -1           ; destination IP
617
 
617
 
618
        rb 10
618
        rb 10
619
 
619
 
620
path            db  '/sys/network.ini'
620
path            db  '/sys/network.ini',0
621
 
621
 
622
IM_END:
622
IM_END:
623
 
623
 
624
device          db 1
624
device          db 1
625
inibuf          rb 16
625
inibuf          rb 16
626
tries           db ?
626
tries           db ?
627
 
627
 
628
dhcpMsgType     db ?    ; sent
628
dhcpMsgType     db ?    ; sent
629
dhcpMsgType2    db ?    ; received
629
dhcpMsgType2    db ?    ; received
630
dhcpLease       dd ?
630
dhcpLease       dd ?
631
dhcpServerIP    dd ?
631
dhcpServerIP    dd ?
632
 
632
 
633
dhcp:
633
dhcp:
634
.ip             dd ?
634
.ip             dd ?
635
.subnet         dd ?
635
.subnet         dd ?
636
.dns            dd ?
636
.dns            dd ?
637
.gateway        dd ?
637
.gateway        dd ?
638
 
638
 
639
 
639
 
640
dhcpMsgLen      dd ?
640
dhcpMsgLen      dd ?
641
socketNum       dd ?
641
socketNum       dd ?
642
 
642
 
643
MAC             dp ?
643
MAC             dp ?
644
 
644
 
645
currTime        dd ?
645
currTime        dd ?
646
generator       dd ?
646
generator       dd ?
647
 
647
 
648
dhcpMsg         dd ?
648
dhcpMsg         dd ?
649
 
649
 
650
I_END:
650
I_END: