Subversion Repositories Kolibri OS

Rev

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

Rev 260 Rev 485
1
;
1
;
2
; ETH.INC
2
; ETH.INC
3
;
3
;
4
; made by hidnplayr (hidnplayr@gmail.com) for KolibriOS
4
; made by hidnplayr (hidnplayr@gmail.com) for KolibriOS
5
;
5
;
6
; The given code before every macro is only a simple example
6
; The given code before every macro is only a simple example
7
;
7
;
8
;
8
;
9
; HISTORY
9
; HISTORY
10
;
10
;
11
; v1.0: 18 august 2006  original release
11
; v1.0: 18 august 2006  original release
12
; v1.1: december 2006   bugfixes and improvements
12
; v1.1: december 2006   bugfixes and improvements
13
;
13
;
14
 
-
 
15
 
14
 
16
macro mov arg1,arg2 {
15
macro mov arg1,arg2 {
17
    if arg1 eq arg2
16
    if arg1 eq arg2
18
    else
17
    else
19
    mov arg1,arg2
18
    mov arg1,arg2
20
    end if
19
    end if
21
}
20
}
22
 
21
 
23
TCB_LISTEN = 1
22
TCB_LISTEN = 1
24
TCB_SYN_SENT = 2
23
TCB_SYN_SENT = 2
25
TCB_SYN_RECEIVED = 3
24
TCB_SYN_RECEIVED = 3
26
TCB_ESTABLISHED = 4
25
TCB_ESTABLISHED = 4
27
TCB_FIN_WAIT_1 = 5
26
TCB_FIN_WAIT_1 = 5
28
TCB_FIN_WAIT_2 = 6
27
TCB_FIN_WAIT_2 = 6
29
TCB_CLOSE_WAIT = 7
28
TCB_CLOSE_WAIT = 7
30
TCB_CLOSING = 8
29
TCB_CLOSING = 8
31
TCB_LAST_ASK = 9
30
TCB_LAST_ASK = 9
32
TCB_TIME_WAIT = 10
31
TCB_TIME_WAIT = 10
33
TCB_CLOSED = 11
32
TCB_CLOSED = 11
34
 
33
 
35
PASSIVE = 0
34
PASSIVE = 0
36
ACTIVE = 1
35
ACTIVE = 1
37
 
36
 
38
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
37
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39
 
38
 
40
;   eth.get_IP eax
39
;   eth.get_IP eax
41
;
40
;
42
;   gets the current IP that is defined in Stack (return in eax in this example)
41
;   gets the current IP that is defined in Stack (return in eax in this example)
43
macro eth.get_IP IP {
42
macro eth.get_IP IP {
44
    mov  ebx,1
43
    mov  ebx,1
45
    mov  eax,52
44
    mov  eax,52
46
    int  0x40
45
    mcall
47
 
46
 
48
    mov  IP ,eax
47
    mov  IP ,eax
49
}
48
}
50
 
49
 
51
;   eth.get_GATEWAY eax
50
;   eth.get_GATEWAY eax
52
;
51
;
53
;   gets the current GATEWAY that is defined in Stack (return in eax in this example)
52
;   gets the current GATEWAY that is defined in Stack (return in eax in this example)
54
macro eth.get_GATEWAY GATEWAY {
53
macro eth.get_GATEWAY GATEWAY {
55
    mov  ebx,9
54
    mov  ebx,9
56
    mov  eax,52
55
    mov  eax,52
57
    int  0x40
56
    mcall
58
    move GATEWAY ,eax
57
    move GATEWAY ,eax
59
}
58
}
60
 
59
 
61
;   eth.get_SUBNET eax
60
;   eth.get_SUBNET eax
62
;
61
;
63
;   gets the current SUBNET that is defined in Stack (return in eax in this example)
62
;   gets the current SUBNET that is defined in Stack (return in eax in this example)
64
macro eth.get_SUBNET SUBNET {
63
macro eth.get_SUBNET SUBNET {
65
    mov  ebx,10
64
    mov  ebx,10
66
    mov  eax,52
65
    mov  eax,52
67
    int  0x40
66
    mcall
68
    mov SUBNET ,eax
67
    mov SUBNET ,eax
69
}
68
}
70
 
69
 
71
;   eth.get_DNS eax
70
;   eth.get_DNS eax
72
;
71
;
73
;   gets the current DNS that is defined in Stack (return in eax in this example)
72
;   gets the current DNS that is defined in Stack (return in eax in this example)
74
macro eth.get_DNS DNS {
73
macro eth.get_DNS DNS {
75
    mov  ebx,13
74
    mov  ebx,13
76
    mov  eax,52
75
    mov  eax,52
77
    int  0x40
76
    mcall
78
    mov  DNS ,eax
77
    mov  DNS ,eax
79
}
78
}
80
 
79
 
81
;   eth.set_IP eax
80
;   eth.set_IP eax
82
;
81
;
83
;   set a new IP in stack (input in eax in this example)
82
;   set a new IP in stack (input in eax in this example)
84
macro eth.set_IP IP {
83
macro eth.set_IP IP {
85
    mov  ecx,IP
84
    mov  ecx,IP
86
    mov  ebx,3
85
    mov  ebx,3
87
    mov  eax,52
86
    mov  eax,52
88
    int  0x40
87
    mcall
89
}
88
}
90
 
89
 
91
;   eth.set_GATEWAY eax
90
;   eth.set_GATEWAY eax
92
;
91
;
93
;   set a new GATEWAY in stack (input in eax in this example)
92
;   set a new GATEWAY in stack (input in eax in this example)
94
macro eth.set_GATEWAY GATEWAY {
93
macro eth.set_GATEWAY GATEWAY {
95
    mov  ecx,GATEWAY
94
    mov  ecx,GATEWAY
96
    mov  ebx,11
95
    mov  ebx,11
97
    mov  eax,52
96
    mov  eax,52
98
    int  0x40
97
    mcall
99
}
98
}
100
 
99
 
101
;   eth.set_SUBNET eax
100
;   eth.set_SUBNET eax
102
;
101
;
103
;   set a new SUBNET in stack (input in eax in this example)
102
;   set a new SUBNET in stack (input in eax in this example)
104
macro eth.set_SUBNET SUBNET {
103
macro eth.set_SUBNET SUBNET {
105
    mov  ecx,SUBNET
104
    mov  ecx,SUBNET
106
    mov  ebx,12
105
    mov  ebx,12
107
    mov  eax,52
106
    mov  eax,52
108
    int  0x40
107
    mcall
109
}
108
}
110
 
109
 
111
;   eth.set_DNS eax
110
;   eth.set_DNS eax
112
;
111
;
113
;   set a new DNS in stack (input in eax in this example)
112
;   set a new DNS in stack (input in eax in this example)
114
macro eth.set_DNS DNS {
113
macro eth.set_DNS DNS {
115
    mov  ecx,DNS
114
    mov  ecx,DNS
116
    mov  ebx,14
115
    mov  ebx,14
117
    mov  eax,52
116
    mov  eax,52
118
    int  0x40
117
    mcall
119
}
118
}
120
 
119
 
121
;   eth.open eax,80,ebx,[socket]
120
;   eth.open eax,80,ebx,[socket]
122
;
121
;
123
;   open a socket on local port in eax to port 80 on server on ebx
122
;   open a socket on local port in eax to port 80 on server on ebx
124
;   the socketnumber will be returned in [socket] (dword)
123
;   the socketnumber will be returned in [socket] (dword)
125
macro eth.open_udp local,remote,ip,socket {
124
macro eth.open_udp local,remote,ip,socket {
126
    mov  ecx, local
125
    mov  ecx, local
127
    mov  edx, remote
126
    mov  edx, remote
128
    mov  esi, ip
127
    mov  esi, ip
129
    mov  ebx, 0
128
    mov  ebx, 0
130
    mov  eax, 53
129
    mov  eax, 53
131
    int  0x40
130
    mcall
132
 
131
 
133
    mov  socket,eax
132
    mov  socket,eax
134
}
133
}
135
 
134
 
136
;   eth.close [socket]
135
;   eth.close [socket]
137
;
136
;
138
;   closes socket on socketnumber [socket]
137
;   closes socket on socketnumber [socket]
139
macro eth.close_udp socket {
138
macro eth.close_udp socket {
140
    mov  ecx, socket
139
    mov  ecx, socket
141
    mov  ebx, 1
140
    mov  ebx, 1
142
    mov  eax, 53
141
    mov  eax, 53
143
    int  0x40
142
    mcall
144
}
143
}
145
 
144
 
146
;   eth.poll [socket],eax
145
;   eth.poll [socket],eax
147
;
146
;
148
;   polls [socket] for data
147
;   polls [socket] for data
149
;   eax = 0 when there is data
148
;   eax = 0 when there is data
150
macro eth.poll socket {
149
macro eth.poll socket {
151
    mov  ecx, socket
150
    mov  ecx, socket
152
    mov  ebx, 2
151
    mov  ebx, 2
153
    mov  eax, 53
152
    mov  eax, 53
154
    int  0x40
153
    mcall
155
}
154
}
156
 
155
 
157
;   eth.read_byte [socket], bl
156
;   eth.read_byte [socket], bl
158
;
157
;
159
;   reads a byte from the socket and returns in bl
158
;   reads a byte from the socket and returns in bl
160
macro eth.read_byte socket, result {
159
macro eth.read_byte socket, result {
161
    mov  ecx, socket
160
    mov  ecx, socket
162
    mov  ebx, 3
161
    mov  ebx, 3
163
    mov  eax, 53
162
    mov  eax, 53
164
    int  0x40
163
    mcall
165
 
164
 
166
    mov  result,bl
165
    mov  result,bl
167
}
166
}
168
 
167
 
169
;   eth.read_byte [socket], bl
168
;   eth.read_byte [socket], bl
170
;
169
;
171
;   reads a byte from the socket and returns in bl
170
;   reads a byte from the socket and returns in bl
172
macro eth.read_packet socket, result {
171
macro eth.read_packet socket, result {
173
    mov  edx, result
172
    mov  edx, result
174
    mov  ecx, socket
173
    mov  ecx, socket
175
    mov  ebx, 10
174
    mov  ebx, 10
176
    mov  eax, 53
175
    mov  eax, 53
177
    int  0x40
176
    mcall
178
}
177
}
179
 
178
 
180
;   eth.write [socket],12,msg
179
;   eth.write [socket],12,msg
181
;   msg db 'hello world!'
180
;   msg db 'hello world!'
182
;
181
;
183
;   send message msg to socket
182
;   send message msg to socket
184
macro eth.write_udp socket,length,msg,verify {
183
macro eth.write_udp socket,length,msg,verify {
185
    mov  ecx, socket
184
    mov  ecx, socket
186
    mov  edx, length
185
    mov  edx, length
187
    mov  esi, msg
186
    mov  esi, msg
188
    mov  ebx, 4
187
    mov  ebx, 4
189
    mov  eax, 53
188
    mov  eax, 53
190
    int  0x40
189
    mcall
191
 
190
 
192
    if verify eq 1
191
    if verify eq 1
193
    call verifysend
192
    call verifysend
194
    end if
193
    end if
195
 
194
 
196
}
195
}
197
 
196
 
198
verifysend:
197
verifysend:
199
    test eax,eax
198
    test eax,eax
200
    jnz  @f
199
    jnz  @f
201
    ret
200
    ret
202
@@:
201
@@:
203
    pusha
202
    pusha
204
    mov  eax,5
203
    mov  eax,5
205
    mov  ebx,100
204
    mov  ebx,100
206
    int  0x40
205
    mcall
-
 
206
 
207
    popa
207
    popa
208
    int  0x40
208
    mcall
209
ret
209
ret
210
 
210
 
211
;   eth.open_tcp 80,80,eax,0,[socket]
211
;   eth.open_tcp 80,80,eax,0,[socket]
212
;
212
;
213
;   opens a tcp socket on port 80 to port 80 on IP eax with passive open
213
;   opens a tcp socket on port 80 to port 80 on IP eax with passive open
214
;   returns socket number in eax
214
;   returns socket number in eax
215
macro eth.open_tcp local,remote,ip,passive,socket {
215
macro eth.open_tcp local,remote,ip,passive,socket {
216
 
216
 
217
    mov  ecx, local
217
    mov  ecx, local
218
    mov  edx, remote
218
    mov  edx, remote
219
    mov  esi, ip
219
    mov  esi, ip
220
    mov  edi, passive	   ; 0 = PASSIVE open
220
    mov  edi, passive	   ; 0 = PASSIVE open
221
    mov  ebx, 5
221
    mov  ebx, 5
222
    mov  eax, 53
222
    mov  eax, 53
223
    int  0x40
223
    mcall
224
 
224
 
225
    mov  socket,eax
225
    mov  socket,eax
226
}
226
}
227
 
227
 
228
;   eth.socket_status [socket],eax
228
;   eth.socket_status [socket],eax
229
;
229
;
230
;   returns socket status in eax
230
;   returns socket status in eax
231
macro eth.socket_status socket,result {
231
macro eth.socket_status socket,result {
232
    mov  ecx, socket
232
    mov  ecx, socket
233
    mov  ebx, 6
233
    mov  ebx, 6
234
    mov  eax, 53
234
    mov  eax, 53
235
    int  0x40
235
    mcall
236
 
236
 
237
    mov  result,eax
237
    mov  result,eax
238
}
238
}
239
 
239
 
240
;   eth.write_tcp [socket],12,msg
240
;   eth.write_tcp [socket],12,msg
241
;
241
;
242
;   msg db 'hello world!'
242
;   msg db 'hello world!'
243
;
243
;
244
;   send message to TCP socket
244
;   send message to TCP socket
245
macro eth.write_tcp socket,length,msg,verify {
245
macro eth.write_tcp socket,length,msg,verify {
246
    mov  ecx, socket
246
    mov  ecx, socket
247
    mov  edx, length
247
    mov  edx, length
248
    mov  esi, msg
248
    mov  esi, msg
249
    mov  ebx, 7
249
    mov  ebx, 7
250
    mov  eax, 53
250
    mov  eax, 53
251
    int  0x40
251
    mcall
252
 
252
 
253
    if verify eq 1
253
    if verify eq 1
254
    call verifysend
254
    call verifysend
255
    end if
255
    end if
256
}
256
}
257
 
257
 
258
;   eth.close_tcp [socket]
258
;   eth.close_tcp [socket]
259
;
259
;
260
;   closes tcp socket [socket]
260
;   closes tcp socket [socket]
261
macro eth.close_tcp socket {
261
macro eth.close_tcp socket {
262
    mov  ecx, socket
262
    mov  ecx, socket
263
    mov  ebx, 8
263
    mov  ebx, 8
264
    mov  eax, 53
264
    mov  eax, 53
265
    int  0x40
265
    mcall
266
}
266
}
267
 
267
 
268
;   eth.check_port 165,eax
268
;   eth.check_port 165,eax
269
;
269
;
270
;   checks if port 165 is used
270
;   checks if port 165 is used
271
;   return is 0 when port is free
271
;   return is 0 when port is free
272
macro eth.check_port port,result {
272
macro eth.check_port port,result {
273
    mov  ecx, port
273
    mov  ecx, port
274
    mov  ebx, 9
274
    mov  ebx, 9
275
    mov  eax, 53
275
    mov  eax, 53
276
    int  0x40
276
    mcall
277
 
277
 
278
    mov  result,eax
278
    mov  result,eax
279
}
279
}
280
 
280
 
281
;   eth.status eax
281
;   eth.status eax
282
;
282
;
283
;   returns socket status in eax
283
;   returns socket status in eax
284
macro eth.status status {
284
macro eth.status status {
285
    mov  ebx, 255
285
    mov  ebx, 255
286
    mov  ecx, 6
286
    mov  ecx, 6
287
    mov  eax, 53
287
    mov  eax, 53
288
    int  0x40
288
    mcall
289
 
289
 
290
    mov  status,eax
290
    mov  status,eax
291
}
291
}
292
 
292
 
293
;   eth.search 165,edx
293
;   eth.search 165,edx
294
;
294
;
295
;   searches a free local port starting from 166 (165 + 1 !)
295
;   searches a free local port starting from 166 (165 + 1 !)
296
;   returns in edx
296
;   returns in edx
297
macro eth.search_port port,result {
297
macro eth.search_port port,result {
298
    mov  edx,port
298
    mov  edx,port
299
   @@:
299
   @@:
300
    inc  edx
300
    inc  edx
301
    eth.check_port edx,eax
301
    eth.check_port edx,eax
302
    cmp  eax,0
302
    cmp  eax,0
303
    je	 @r
303
    je	 @r
304
    mov  result,edx
304
    mov  result,edx
305
}
305
}
306
 
306
 
307
 
307
 
308
 
308
 
309
;   eth.read_data [socket],buffer,512
309
;   eth.read_data [socket],buffer,512
310
;   buffer  rb 512
310
;   buffer  rb 512
311
;   socket  dd ?
311
;   socket  dd ?
312
;
312
;
313
;   reads data from socket into a buffer, stops when there is no more data or buffer is full.
313
;   reads data from socket into a buffer, stops when there is no more data or buffer is full.
314
macro eth.read_data socket,dest,endptr,bufferl {
314
macro eth.read_data socket,dest,endptr,bufferl {
315
local .getdata,.loop,.end
315
local .getdata,.loop,.end
316
    mov     eax, dest
316
    mov     eax, dest
317
    mov     endptr, eax
317
    mov     endptr, eax
318
 
318
 
319
    ; we have data - this will be the response
319
    ; we have data - this will be the response
320
.getdata:
320
.getdata:
321
    mov     eax,endptr
321
    mov     eax,endptr
322
    cmp     eax,bufferl
322
    cmp     eax,bufferl
323
    jg	    .end
323
    jg	    .end
324
 
324
 
325
    eth.read_byte socket,bl
325
    eth.read_byte socket,bl
326
 
326
 
327
    ; Store the data in the response buffer
327
    ; Store the data in the response buffer
328
    mov     eax, endptr
328
    mov     eax, endptr
329
    mov     [eax], bl
329
    mov     [eax], bl
330
    inc     dword endptr
330
    inc     dword endptr
331
 
331
 
332
    eth.poll socket
332
    eth.poll socket
333
 
333
 
334
    cmp     eax,0
334
    cmp     eax,0
335
    jne     .getdata		      ; yes, so get it
335
    jne     .getdata		      ; yes, so get it
336
 
336
 
337
    ; now we are going to wait 30 times 10 ms (300ms)
337
    ; now we are going to wait 30 times 10 ms (300ms)
338
 
338
 
339
    mov     edx,0
339
    mov     edx,0
340
.loop:
340
.loop:
341
    mov     eax,5
341
    mov     eax,5
342
    mov     ebx,1
342
    mov     ebx,1
343
    int     0x40
343
    mcall
344
 
344
 
345
    eth.poll socket
345
    eth.poll socket
346
 
346
 
347
    cmp     eax, 0
347
    cmp     eax, 0
348
    jne     .getdata		      ; yes, so get it
348
    jne     .getdata		      ; yes, so get it
349
 
349
 
350
    inc     edx
350
    inc     edx
351
    cmp     edx,100
351
    cmp     edx,100
352
    jl	    .loop
352
    jl	    .loop
353
 
353
 
354
.end:
354
.end:
355
 
355
 
356
}
356
}
357
 
357
 
358
;  eth.wait_for_data [socket],60,abort
358
;  eth.wait_for_data [socket],60,abort
359
;  eth.read_data ....
359
;  eth.read_data ....
360
;  abort:
360
;  abort:
361
;
361
;
362
;  Waits for data with timeout
362
;  Waits for data with timeout
363
 
363
 
364
macro eth.wait_for_data socket,TIMEOUT,abort {
364
macro eth.wait_for_data socket,TIMEOUT,abort {
365
 
365
 
366
    mov   edx,TIMEOUT
366
    mov   edx,TIMEOUT
367
 
367
 
368
   @@:
368
   @@:
369
    eth.poll socket
369
    eth.poll socket
370
 
370
 
371
    cmp   eax,0
371
    cmp   eax,0
372
    jne   @f
372
    jne   @f
373
 
373
 
374
    dec   edx
374
    dec   edx
375
    jz	  abort
375
    jz	  abort
376
 
376
 
377
    mov   eax,5 			      ; wait here for event
377
    mov   eax,5 			      ; wait here for event
378
    mov   ebx,10
378
    mov   ebx,10
379
    int   0x40
379
    mcall
380
 
380
 
381
    jmp   @r
381
    jmp   @r
382
   @@:
382
   @@:
383
 
383
 
384
}
384
}
385
 
385
 
386
 
386
 
387
; The function 'resolve' resolves the address in edx and puts the resulting IP in eax.
387
; The function 'resolve' resolves the address in edx and puts the resulting IP in eax.
388
; When the input is an IP-adress, the function will output this IP in eax.
388
; When the input is an IP-adress, the function will output this IP in eax.
389
; If something goes wrong, the result in eax should be 0
389
; If something goes wrong, the result in eax should be 0
390
;
390
;
391
; example:
391
; example:
392
;
392
;
393
; resolve query1,IP,PORT
393
; resolve query1,IP,PORT
394
; resolve '192.168.0.1',IP,PORT
394
; resolve '192.168.0.1',IP,PORT
395
; resolve query2,IP,PORT
395
; resolve query2,IP,PORT
396
;
396
;
397
; query1 db 'www.google.com',0
397
; query1 db 'www.google.com',0
398
; query2 db '49.78.84.45',0
398
; query2 db '49.78.84.45',0
399
; IP     dd ?
399
; IP     dd ?
400
; PORT   dd ?
400
; PORT   dd ?
401
 
401
 
402
macro resolve query,result {
402
macro resolve query,result {
403
 
403
 
404
if    query eqtype 0
404
if    query eqtype 0
405
 mov   edx,query
405
 mov   edx,query
406
else
406
else
407
 local ..string, ..label
407
 local ..string, ..label
408
 jmp   ..label
408
 jmp   ..label
409
 ..string db query,0
409
 ..string db query,0
410
 ..label:
410
 ..label:
411
 mov   edx,..string
411
 mov   edx,..string
412
end   if
412
end   if
413
 
413
 
414
call  __resolve
414
call  __resolve
415
 
415
 
416
mov   result,eax
416
mov   result,eax
417
 
417
 
418
}
418
}
419
 
419
 
420
if used __resolve
420
if used __resolve
421
 
421
 
422
__resolve:
422
__resolve:
423
 
423
 
424
if __DEBUG__ eq 1
424
if __DEBUG__ eq 1
425
DEBUGF 1,'Resolving started\n'
425
DEBUGF 1,'Resolving started\n'
426
end if
426
end if
427
 
427
 
428
    ; This code validates if the query is an IP containing 4 numbers and 3 dots
428
    ; This code validates if the query is an IP containing 4 numbers and 3 dots
429
 
429
 
430
 
430
 
431
    push    edx 	      ; push edx (query address) onto stack
431
    push    edx 	      ; push edx (query address) onto stack
432
    xor     al, al	      ; make al (dot count) zero
432
    xor     al, al	      ; make al (dot count) zero
433
 
433
 
434
   @@:
434
   @@:
435
    cmp     byte[edx],'0'     ; check if this byte is a number, if not jump to no_IP
435
    cmp     byte[edx],'0'     ; check if this byte is a number, if not jump to no_IP
436
    jl	    no_IP	      ;
436
    jl	    no_IP	      ;
437
    cmp     byte[edx],'9'     ;
437
    cmp     byte[edx],'9'     ;
438
    jg	    no_IP	      ;
438
    jg	    no_IP	      ;
439
 
439
 
440
    inc     edx 	      ; the byte was a number, so lets check the next byte
440
    inc     edx 	      ; the byte was a number, so lets check the next byte
441
 
441
 
442
    cmp     byte[edx],0       ; is this byte zero? (have we reached end of query?)
442
    cmp     byte[edx],0       ; is this byte zero? (have we reached end of query?)
443
    jz	    @f		      ; jump to next @@ then
443
    jz	    @f		      ; jump to next @@ then
444
    cmp     byte[edx],':'
444
    cmp     byte[edx],':'
445
    jz	    @f
445
    jz	    @f
446
 
446
 
447
    cmp     byte[edx],'.'     ; is this byte a dot?
447
    cmp     byte[edx],'.'     ; is this byte a dot?
448
    jne     @r		      ; if not, jump to previous @@
448
    jne     @r		      ; if not, jump to previous @@
449
 
449
 
450
    inc     al		      ; the byte was a dot so increment al(dot count)
450
    inc     al		      ; the byte was a dot so increment al(dot count)
451
    inc     edx 	      ; next byte
451
    inc     edx 	      ; next byte
452
    jmp     @r		      ; lets check for numbers again (jump to previous @@)
452
    jmp     @r		      ; lets check for numbers again (jump to previous @@)
453
 
453
 
454
   @@:			      ; we reach this when end of query reached
454
   @@:			      ; we reach this when end of query reached
455
    cmp     al,3	      ; check if there where 3 dots
455
    cmp     al,3	      ; check if there where 3 dots
456
    jnz     no_IP	      ; if not, jump to no_IP (this is where the DNS will take over)
456
    jnz     no_IP	      ; if not, jump to no_IP (this is where the DNS will take over)
457
 
457
 
458
    ; The following code will convert this IP into a dword and output it in eax
458
    ; The following code will convert this IP into a dword and output it in eax
459
    ; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
459
    ; If there is also a port number specified, this will be returned in ebx, otherwise ebx is -1
460
 
460
 
461
    pop     esi 	      ; edx (query address) was pushed onto stack and is now popped in esi
461
    pop     esi 	      ; edx (query address) was pushed onto stack and is now popped in esi
462
 
462
 
463
    xor     edx, edx	      ; result
463
    xor     edx, edx	      ; result
464
    xor     eax, eax	      ; current character
464
    xor     eax, eax	      ; current character
465
    xor     ebx, ebx	      ; current byte
465
    xor     ebx, ebx	      ; current byte
466
 
466
 
467
.outer_loop:
467
.outer_loop:
468
    shl     edx, 8
468
    shl     edx, 8
469
    add     edx, ebx
469
    add     edx, ebx
470
    xor     ebx, ebx
470
    xor     ebx, ebx
471
.inner_loop:
471
.inner_loop:
472
    lodsb
472
    lodsb
473
    test    eax, eax
473
    test    eax, eax
474
    jz	    .finish
474
    jz	    .finish
475
    cmp     al, '.'
475
    cmp     al, '.'
476
    jz	    .outer_loop
476
    jz	    .outer_loop
477
    sub     eax, '0'
477
    sub     eax, '0'
478
    imul    ebx, 10
478
    imul    ebx, 10
479
    add     ebx, eax
479
    add     ebx, eax
480
    jmp     .inner_loop
480
    jmp     .inner_loop
481
.finish:
481
.finish:
482
    shl     edx, 8
482
    shl     edx, 8
483
    add     edx, ebx
483
    add     edx, ebx
484
 
484
 
485
    bswap   edx 	      ; we want little endian order
485
    bswap   edx 	      ; we want little endian order
486
    mov     eax, edx
486
    mov     eax, edx
487
 
487
 
488
    ret
488
    ret
489
 
489
 
490
 
490
 
491
no_IP:
491
no_IP:
492
 
492
 
493
    pop     edx
493
    pop     edx
494
 
494
 
495
    ; The query is not an IP address, we will send the query to a DNS server and hope for answer ;)
495
    ; The query is not an IP address, we will send the query to a DNS server and hope for answer ;)
496
if __DEBUG__ eq 1
496
if __DEBUG__ eq 1
497
    DEBUGF 1,'The query is no ip, Building request string from:%u\n',edx
497
    DEBUGF 1,'The query is no ip, Building request string from:%u\n',edx
498
end if
498
end if
499
 
499
 
500
    ; Build the request string
500
    ; Build the request string
501
    mov     eax, 0x00010100
501
    mov     eax, 0x00010100
502
    mov     [dnsMsg], eax
502
    mov     [dnsMsg], eax
503
    mov     eax, 0x00000100
503
    mov     eax, 0x00000100
504
    mov     [dnsMsg+4], eax
504
    mov     [dnsMsg+4], eax
505
    mov     eax, 0x00000000
505
    mov     eax, 0x00000000
506
    mov     [dnsMsg+8], eax
506
    mov     [dnsMsg+8], eax
507
 
507
 
508
    ; domain name goes in at dnsMsg+12
508
    ; domain name goes in at dnsMsg+12
509
    mov     esi, dnsMsg + 12			 ; location of label length
509
    mov     esi, dnsMsg + 12			 ; location of label length
510
    mov     edi, dnsMsg + 13			 ; label start
510
    mov     edi, dnsMsg + 13			 ; label start
511
    mov     ecx, 12				 ; total string length so far
511
    mov     ecx, 12				 ; total string length so far
512
 
512
 
513
td002:
513
td002:
514
    mov     [esi], byte 0
514
    mov     [esi], byte 0
515
    inc     ecx
515
    inc     ecx
516
 
516
 
517
td0021:
517
td0021:
518
    mov     al, [edx]
518
    mov     al, [edx]
519
 
519
 
520
    cmp     al, 0
520
    cmp     al, 0
521
    je	    td001				 ; we have finished the string translation
521
    je	    td001				 ; we have finished the string translation
522
 
522
 
523
    cmp     al, '.'
523
    cmp     al, '.'
524
    je	    td004				 ; we have finished the label
524
    je	    td004				 ; we have finished the label
525
 
525
 
526
    inc     byte [esi]
526
    inc     byte [esi]
527
    inc     ecx
527
    inc     ecx
528
    mov     [edi], al
528
    mov     [edi], al
529
    inc     edi
529
    inc     edi
530
    inc     edx
530
    inc     edx
531
    jmp     td0021
531
    jmp     td0021
532
 
532
 
533
td004:
533
td004:
534
    mov     esi, edi
534
    mov     esi, edi
535
    inc     edi
535
    inc     edi
536
    inc     edx
536
    inc     edx
537
    jmp     td002
537
    jmp     td002
538
 
538
 
539
    ; write label len + label text
539
    ; write label len + label text
540
td001:
540
td001:
541
    mov     [edi], byte 0
541
    mov     [edi], byte 0
542
    inc     ecx
542
    inc     ecx
543
    inc     edi
543
    inc     edi
544
    mov     [edi], dword 0x01000100
544
    mov     [edi], dword 0x01000100
545
    add     ecx, 4
545
    add     ecx, 4
546
 
546
 
547
    mov     [dnsMsgLen], ecx			 ; We'll need the length of the message when we send it
547
    mov     [dnsMsgLen], ecx			 ; We'll need the length of the message when we send it
548
    ; Now, lets send this and wait for an answer
548
    ; Now, lets send this and wait for an answer
549
 
549
 
550
    eth.search_port 1024,edx			 ; Find a free port starting from 1025 and store in edx
550
    eth.search_port 1024,edx			 ; Find a free port starting from 1025 and store in edx
551
    eth.get_DNS esi				 ; Read DNS IP from stack into esi
551
    eth.get_DNS esi				 ; Read DNS IP from stack into esi
552
    eth.open_udp edx,53,esi,[socketNum] 	     ; First, open socket
552
    eth.open_udp edx,53,esi,[socketNum] 	     ; First, open socket
553
if __DEBUG__ eq 1
553
if __DEBUG__ eq 1
554
    DEBUGF 1,'Socket opened: %u (port %u)\n',[socketNum],ecx
554
    DEBUGF 1,'Socket opened: %u (port %u)\n',[socketNum],ecx
555
end if
555
end if
556
    eth.write_udp [socketNum],[dnsMsgLen],dnsMsg     ; Write to socket ( request DNS lookup )
556
    eth.write_udp [socketNum],[dnsMsgLen],dnsMsg     ; Write to socket ( request DNS lookup )
557
if __DEBUG__ eq 1
557
if __DEBUG__ eq 1
558
    DEBUGF 1,'Data written, length:%u offset:%u\n',[dnsMsgLen],dnsMsg
558
    DEBUGF 1,'Data written, length:%u offset:%u\n',[dnsMsgLen],dnsMsg
559
    DEBUGF 1,'Waiting for data: (timeout is %us)\n',TIMEOUT
559
    DEBUGF 1,'Waiting for data: (timeout is %us)\n',TIMEOUT
560
end if
560
end if
561
    eth.wait_for_data [socketNum],TIMEOUT,abort  ; Now, we wait for data from remote
561
    eth.wait_for_data [socketNum],TIMEOUT,abort  ; Now, we wait for data from remote
562
    eth.read_data [socketNum],dnsMsg,[dnsMsgLen],dnsMsg+BUFFER	    ; Read the data into the buffer
562
    eth.read_data [socketNum],dnsMsg,[dnsMsgLen],dnsMsg+BUFFER	    ; Read the data into the buffer
563
if __DEBUG__ eq 1
563
if __DEBUG__ eq 1
564
    DEBUGF 1,'Data received, offset:%u buffer size:%u length:%u\n',dnsMsg,BUFFER,esi-dnsMsg
564
    DEBUGF 1,'Data received, offset:%u buffer size:%u length:%u\n',dnsMsg,BUFFER,esi-dnsMsg
565
end if
565
end if
566
    eth.close_udp [socketNum]			     ; We're done, close the socket
566
    eth.close_udp [socketNum]			     ; We're done, close the socket
567
if __DEBUG__ eq 1
567
if __DEBUG__ eq 1
568
    DEBUGF 1,'Closed Socket\n'
568
    DEBUGF 1,'Closed Socket\n'
569
end if
569
end if
570
 
570
 
571
    ; Now parse the message to get the host IP. Man, this is complicated. It's described in RFC 1035
571
    ; Now parse the message to get the host IP. Man, this is complicated. It's described in RFC 1035
572
    ; 1) Validate that we have an answer with > 0 responses
572
    ; 1) Validate that we have an answer with > 0 responses
573
    ; 2) Find the answer record with TYPE 0001 ( host IP )
573
    ; 2) Find the answer record with TYPE 0001 ( host IP )
574
    ; 3) Finally, copy the IP address to the display
574
    ; 3) Finally, copy the IP address to the display
575
    ; Note: The response is in dnsMsg, the end of the buffer is pointed to by [dnsMsgLen]
575
    ; Note: The response is in dnsMsg, the end of the buffer is pointed to by [dnsMsgLen]
576
 
576
 
577
    mov     esi, dnsMsg
577
    mov     esi, dnsMsg
578
 
578
 
579
    mov     al, [esi+2] 			 ; Is this a response to my question?
579
    mov     al, [esi+2] 			 ; Is this a response to my question?
580
    and     al, 0x80
580
    and     al, 0x80
581
    cmp     al, 0x80
581
    cmp     al, 0x80
582
    jne     abort
582
    jne     abort
583
if __DEBUG__ eq 1
583
if __DEBUG__ eq 1
584
    DEBUGF 1,'It was a response to my question\n'
584
    DEBUGF 1,'It was a response to my question\n'
585
end if
585
end if
586
 
586
 
587
    mov     al, [esi+3] 			 ; Were there any errors?
587
    mov     al, [esi+3] 			 ; Were there any errors?
588
    and     al, 0x0F
588
    and     al, 0x0F
589
    cmp     al, 0x00
589
    cmp     al, 0x00
590
    jne     abort
590
    jne     abort
591
 
591
 
592
if __DEBUG__ eq 1
592
if __DEBUG__ eq 1
593
    DEBUGF 1,'There were no errors\n'
593
    DEBUGF 1,'There were no errors\n'
594
end if
594
end if
595
 
595
 
596
    mov     ax, [esi+6] 			 ; Is there ( at least 1 ) answer?
596
    mov     ax, [esi+6] 			 ; Is there ( at least 1 ) answer?
597
    cmp     ax, 0x00
597
    cmp     ax, 0x00
598
    je	    abort
598
    je	    abort
599
 
599
 
600
    ; Header validated. Scan through and get my answer
600
    ; Header validated. Scan through and get my answer
601
    add     esi, 12				 ; Skip to the question field
601
    add     esi, 12				 ; Skip to the question field
602
    call    skipName				 ; Skip through the question field
602
    call    skipName				 ; Skip through the question field
603
    add     esi, 4				 ; skip past the questions qtype, qclass
603
    add     esi, 4				 ; skip past the questions qtype, qclass
604
 
604
 
605
ctr002z:
605
ctr002z:
606
    ; Now at the answer. There may be several answers, find the right one ( TYPE = 0x0001 )
606
    ; Now at the answer. There may be several answers, find the right one ( TYPE = 0x0001 )
607
    call    skipName
607
    call    skipName
608
    mov     ax, [esi]
608
    mov     ax, [esi]
609
    cmp     ax, 0x0100				 ; Is this the IP address answer?
609
    cmp     ax, 0x0100				 ; Is this the IP address answer?
610
    jne     ctr002c
610
    jne     ctr002c
611
    add     esi, 10				 ; Yes! Point eax to the first byte of the IP address
611
    add     esi, 10				 ; Yes! Point eax to the first byte of the IP address
612
    mov     eax,[esi]
612
    mov     eax,[esi]
613
 
613
 
614
    ret
614
    ret
615
 
615
 
616
 
616
 
617
ctr002c:					 ; Skip through the answer, move to the next
617
ctr002c:					 ; Skip through the answer, move to the next
618
    add     esi, 8
618
    add     esi, 8
619
    movzx   eax, byte [esi+1]
619
    movzx   eax, byte [esi+1]
620
    mov     ah, [esi]
620
    mov     ah, [esi]
621
    add     esi, eax
621
    add     esi, eax
622
    add     esi, 2
622
    add     esi, 2
623
 
623
 
624
    cmp     esi, [dnsMsgLen]			 ; Have we reached the end of the msg? This is an error condition, should not happen
624
    cmp     esi, [dnsMsgLen]			 ; Have we reached the end of the msg? This is an error condition, should not happen
625
    jl	    ctr002z				 ; Check next answer
625
    jl	    ctr002z				 ; Check next answer
626
 
626
 
627
abort:
627
abort:
628
if __DEBUG__ eq 1
628
if __DEBUG__ eq 1
629
    DEBUGF 1,'Something went wrong, aborting\n'
629
    DEBUGF 1,'Something went wrong, aborting\n'
630
end if
630
end if
631
    xor     eax,eax
631
    xor     eax,eax
632
 
632
 
633
    ret
633
    ret
634
 
634
 
635
 
635
 
636
skipName:
636
skipName:
637
    ; Increment esi to the first byte past the name field
637
    ; Increment esi to the first byte past the name field
638
    ; Names may use compressed labels. Normally do.
638
    ; Names may use compressed labels. Normally do.
639
    ; RFC 1035 page 30 gives details
639
    ; RFC 1035 page 30 gives details
640
    mov     al, [esi]
640
    mov     al, [esi]
641
    cmp     al, 0
641
    cmp     al, 0
642
    je	    sn_exit
642
    je	    sn_exit
643
    and     al, 0xc0
643
    and     al, 0xc0
644
    cmp     al, 0xc0
644
    cmp     al, 0xc0
645
    je	    sn001
645
    je	    sn001
646
 
646
 
647
    movzx   eax, byte [esi]
647
    movzx   eax, byte [esi]
648
    inc     eax
648
    inc     eax
649
    add     esi, eax
649
    add     esi, eax
650
    jmp     skipName
650
    jmp     skipName
651
 
651
 
652
sn001:
652
sn001:
653
    add     esi, 2				 ; A pointer is always at the end
653
    add     esi, 2				 ; A pointer is always at the end
654
    ret
654
    ret
655
 
655
 
656
sn_exit:
656
sn_exit:
657
    inc     esi
657
    inc     esi
658
    ret
658
    ret
659
 
659
 
660
dnsMsgLen:	dd 0
660
dnsMsgLen:	dd 0
661
socketNum:	dd 0xFFFF
661
socketNum:	dd 0xFFFF
662
 
662
 
663
if ~defined dnsMsg
663
if ~defined dnsMsg
664
dnsMsg: 	rb BUFFER
664
dnsMsg: 	rb BUFFER
665
end if
665
end if
666
 
666
 
667
end if
667
end if