Subversion Repositories Kolibri OS

Rev

Rev 6923 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6923 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
7892 hidnplayr 3
;; Copyright (C) KolibriOS team 2010-2020. All rights reserved.    ;;
6923 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  tracert.asm - Trace network route for KolibriOS                ;;
7
;;                                                                 ;;
8
;;  Written by hidnplayr@kolibrios.org                             ;;
9
;;                                                                 ;;
10
;;          GNU GENERAL PUBLIC LICENSE                             ;;
11
;;             Version 2, June 1991                                ;;
12
;;                                                                 ;;
13
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
14
 
15
format binary as ""
16
 
17
BUFFERSIZE      = 1500
18
IDENTIFIER      = 0x1337
19
 
20
__DEBUG__               = 1             ; enable/disable
21
__DEBUG_LEVEL__         = 2             ; 1 = all, 2 = errors
22
 
23
use32
24
        org     0x0
25
 
26
        db      'MENUET01'      ; signature
27
        dd      1               ; header version
28
        dd      START           ; entry point
29
        dd      I_END           ; initialized size
30
        dd      IM_END+0x1000   ; required memory
31
        dd      IM_END+0x1000   ; stack pointer
32
        dd      params          ; parameters
33
        dd      0               ; path
34
 
35
include '../../proc32.inc'
36
include '../../macros.inc'
37
purge mov,add,sub
38
include '../../dll.inc'
39
include '../../struct.inc'
40
include '../../debug-fdo.inc'
41
include '../../network.inc'
42
 
43
include '../icmp.inc'
44
include '../ip.inc'
45
 
46
 
47
START:
48
; init heap
49
        mcall   68, 11
50
        test    eax, eax
51
        jz      exit
52
; load libraries
53
        stdcall dll.Load, @IMPORT
54
        test    eax, eax
55
        jnz     exit
56
; initialize console
57
        push    1
58
        call    [con_start]
59
        push    title
60
        push    250
61
        push    80
62
        push    25
63
        push    80
64
        call    [con_init]
65
; main loop
66
        cmp     byte[params], 0
67
        jne     parse_param
68
 
69
        push    str_welcome
70
        call    [con_write_asciiz]
71
main:
72
; write prompt
73
        push    str_prompt
74
        call    [con_write_asciiz]
75
; read string
76
        mov     esi, params
77
        push    1024
78
        push    esi
79
        call    [con_gets]
80
; check for exit
81
        test    eax, eax
82
        jz      exit
83
        cmp     byte [esi], 10
84
        jz      exit
85
; delete terminating '\n'
86
        push    esi
87
@@:
88
        lodsb
89
        test    al, al
90
        jnz     @b
91
        mov     [esi-2], al
92
        pop     esi
93
 
94
parse_param:
95
; Check if any additional parameters were given
96
 
97
        DEBUGF  2, "parse parameters\n"
98
        mov     esi, params
99
        mov     ecx, 1024
100
  .addrloop:
101
        lodsb
102
        test    al, al
103
        jz      .resolve
104
        cmp     al, ' '
105
        jne     .addrloop
106
        mov     byte[esi-1], 0
107
        jmp     .param
108
 
109
  .param_loop:
110
        lodsb
111
        test    al, al
112
        jz      .resolve
113
        cmp     al, ' '
114
        jne     .invalid
115
  .param:
116
        lodsb
117
        cmp     al, '-'
118
        jne     .invalid
119
        lodsb
120
        ; implement more parameters here
121
  .invalid:
122
        push    str13
123
        call    [con_write_asciiz]
124
        jmp     main
125
 
126
  .resolve:
127
        DEBUGF  2, "resolve\n"
128
; resolve name
129
        push    esp     ; reserve stack place
130
        push    esp     ; fourth parameter
131
        push    0       ; third parameter
132
        push    0       ; second parameter
133
        push    params  ; first parameter
134
        call    [getaddrinfo]
135
        pop     esi
136
; test for error
137
        test    eax, eax
138
        jnz     fail
139
 
140
; convert IP address to decimal notation
141
        mov     eax, [esi+addrinfo.ai_addr]
142
        mov     eax, [eax+sockaddr_in.sin_addr]
143
        mov     [sockaddr1.ip], eax
144
        push    eax
145
        call    [inet_ntoa]
146
; write result
147
        mov     [ip_ptr], eax
148
 
149
        push    eax
150
 
151
; free allocated memory
152
        push    esi
153
        call    [freeaddrinfo]
154
 
155
        push    str4
156
        call    [con_write_asciiz]
157
 
158
        mcall   socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
159
        cmp     eax, -1
160
        jz      fail2
161
        mov     [icmp_socket], eax
162
 
163
        mcall   socket, AF_INET4, SOCK_DGRAM, 0
164
        cmp     eax, -1
165
        jz      fail2
166
        mov     [udp_socket], eax
167
 
168
        mcall   connect, [udp_socket], sockaddr1, 18
169
        cmp     eax, -1
170
        je      fail2
171
 
172
        mcall   40, EVM_STACK
173
 
174
        push    str3
175
        call    [con_write_asciiz]
176
 
177
        push    [ip_ptr]
178
        call    [con_write_asciiz]
179
 
180
        push    str4
181
        call    [con_write_asciiz]
182
 
183
        mov     [ttl], 1
184
 
185
 ;;       mcall   send, [udp_socket], udp_packet, 5, 0    ; dummy send
186
 
187
        mcall   recv, [icmp_socket], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT ;; dummy read
188
 
189
mainloop:
190
        call    [con_get_flags]
191
        test    eax, 0x200                      ; con window closed?
192
        jnz     exit_now
193
 
194
        pushd   [ttl]
195
        pushd   str9
196
        call    [con_printf]
197
        add     esp, 2*4
198
 
199
        DEBUGF  2, "Setsockopt\n"
200
 
201
        pushd   [ttl]
202
        pushd   4                               ; length of option
203
        pushd   IP_TTL
204
        pushd   IPPROTO_IP
205
        mcall   setsockopt, [udp_socket], esp
206
        add     esp, 16
207
        cmp     eax, -1
208
        je      fail2
209
 
210
        DEBUGF  2, "Sending\n"
211
 
212
        mcall   26, 10                          ; Get high precision timer count
213
        mov     [time_reference], eax
214
        mcall   send, [udp_socket], udp_packet, 5, 0
215
        cmp     eax, -1
216
        je      fail2
217
 
218
        DEBUGF  2, "Packet sent\n", str_ini_int
219
 
220
   .receive:
221
        mcall   23, [timeout]
222
 
223
        mcall   26, 10                          ; Get high precision timer count
224
        sub     eax, [time_reference]
225
        jz      @f
226
        xor     edx, edx
227
        mov     ebx, 100000
228
        div     ebx
229
        cmp     edx, 50000
230
        jb      @f
231
        inc     eax
232
  @@:
233
        mov     [time_reference], eax
234
 
235
; Receive reply
236
        mcall   recv, [icmp_socket], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
237
        cmp     eax, -1
238
        je      .timeout
239
        test    eax, eax
240
        jz      fail2
241
 
7892 hidnplayr 242
        DEBUGF  2, "Answer of %u bytes\n", eax
6923 hidnplayr 243
 
244
; IP header length
245
        movzx   esi, byte[buffer_ptr]
246
        and     esi, 0xf
247
        shl     esi, 2
248
 
249
; Check packet length
250
        sub     eax, esi
251
        sub     eax, sizeof.ICMP_header
252
        jb      .invalid
253
        mov     [recvd], eax
254
 
255
        DEBUGF  2, "Packet length OK\n", eax
256
 
257
; make esi point to ICMP packet header
258
        add     esi, buffer_ptr
259
 
260
; Verify packet
261
;;        movzx   eax, [esi + sizeof.ICMP_header + IPv4_header.TimeToLive]
262
;;        cmp     eax, [ttl]
263
;;        jne     .receive
264
 
265
; What kind of response is it?
7892 hidnplayr 266
        DEBUGF  2, "Response Type: %u Code: %u\n", [esi + ICMP_header.Type], [esi + ICMP_header.Code]
6923 hidnplayr 267
        cmp     [esi + ICMP_header.Type], ICMP_UNREACH_PORT
268
        je      .last
269
        cmp     [esi + ICMP_header.Type], ICMP_TIMXCEED
270
        jne     .invalid
271
        call    .print
272
        jmp     .continue
273
 
274
  .last:
275
        call    .print
276
        jmp     main
277
 
278
  .print:
279
        DEBUGF  2, "Valid response\n"
280
; we have a response, print a line
281
        mov     eax, [time_reference]
282
        xor     edx, edx
283
        mov     ebx, 10
284
        div     ebx
285
        push    edx
286
        push    eax
287
 
288
        push    str1
289
        call    [con_printf]
290
        add     esp, 3*4
291
 
292
        mov     ebx, [buffer_ptr + IPv4_header.SourceAddress]
293
        push    ebx
294
        call    reverse_dns_lookup
295
 
296
        pop     eax
297
        rol     eax, 16
298
        movzx   ebx, ah
299
        push    ebx
300
        movzx   ebx, al
301
        push    ebx
302
        shr     eax, 16
303
        movzx   ebx, ah
304
        push    ebx
305
        movzx   ebx, al
306
        push    ebx
307
 
308
        push    str2
309
        call    [con_printf]
310
        add     esp, 5*4
311
 
312
        ret
313
 
314
 
315
; Invalid reply
316
  .invalid:
317
        DEBUGF  2, "Invalid response\n"
318
        push    str10
319
        call    [con_write_asciiz]
320
        jmp     main    ;.continue
321
 
322
; Timeout!
323
  .timeout:
324
        DEBUGF  2, "Timeout\n", eax
325
        push    str8
326
        call    [con_write_asciiz]
327
 
328
; Send more ICMP packets ?
329
  .continue:
330
        inc     [ttl]
331
 
332
; wait a second before sending next request
333
        mcall   5, 100
334
        jmp     mainloop
335
 
336
; DNS error
337
fail:
338
        push    str5
339
        call    [con_write_asciiz]
340
        jmp     main
341
 
342
; Socket error
343
fail2:
344
        push    str6
345
        call    [con_write_asciiz]
346
        jmp     main
347
 
348
; Finally.. exit!
349
exit:
350
        push    1
351
        call    [con_exit]
352
exit_now:
353
        mcall   -1
354
 
355
 
356
ascii_to_dec:
357
 
358
        lodsb
359
        cmp     al, ' '
360
        jne     .fail
361
 
362
        xor     eax, eax
363
        xor     ebx, ebx
364
  .loop:
365
        lodsb
366
        test    al, al
367
        jz      .done
368
        cmp     al, ' '
369
        je      .done
370
        sub     al, '0'
371
        jb      .fail
372
        cmp     al, 9
373
        ja      .fail
374
        lea     ebx, [ebx*4+ebx]
375
        lea     ebx, [ebx*2+eax]
376
        jmp     .loop
377
  .fail:
378
        xor     ebx, ebx
379
  .done:
380
        dec     esi
381
        ret
382
 
383
 
384
; ebx = ip
385
reverse_dns_lookup:
386
 
387
        push    ebx
388
        mcall   socket, AF_INET4, SOCK_DGRAM, 0
389
        pop     ebx
390
        cmp     eax, -1
391
        je      .fail
392
        mov     [dns_socket], eax
393
 
394
        push    ebx
395
        mcall   connect, [dns_socket], sockaddr2, 18
396
        pop     ebx
397
        cmp     eax, -1
398
        je      .fail
399
 
400
        mov     edi, dns_pkt.name
401
        rol     ebx, 8
402
        movzx   eax, bl
403
        call    byte_to_ascii
404
        rol     ebx, 8
405
        movzx   eax, bl
406
        call    byte_to_ascii
407
        rol     ebx, 8
408
        movzx   eax, bl
409
        call    byte_to_ascii
410
        rol     ebx, 8
411
        movzx   eax, bl
412
        call    byte_to_ascii
413
 
414
        mov     esi, dns_tr
415
        mov     ecx, dns_tr.length
416
        rep movsb
417
 
418
        sub     edi, dns_pkt
419
        mov     esi, edi
420
 
421
        mcall   send, [dns_socket], dns_pkt, , 0
422
        cmp     eax, -1
423
        je      .fail
424
 
425
        push    esi
426
        mcall   recv, [dns_socket], buffer_ptr, BUFFERSIZE, 0
427
        pop     esi
428
 
429
        mcall   close, [dns_socket]
430
 
431
        cmp     word[buffer_ptr+6], 0   ; answers
432
        je      .fail
433
 
434
        add     esi, buffer_ptr+12
435
        mov     edi, buffer_ptr
436
        xor     ecx, ecx
437
        lodsb
438
        test    al, al
439
        jz      @f
440
        movzx   ecx, al
441
  @@:
442
        rep movsb
443
        lodsb
444
        test    al, al
445
        jz      @f
446
        movzx   ecx, al
447
        mov     al, '.'
448
        stosb
449
        jmp     @r
450
  @@:
451
        stosb
452
 
453
        push    buffer_ptr
454
        call    [con_write_asciiz]
455
 
456
        push    str7
457
        call    [con_write_asciiz]
458
 
459
        ret
460
 
461
  .fail:
462
        ret
463
 
464
 
465
 
466
; input: eax - number
467
;        edi - ptr
468
byte_to_ascii:
469
 
470
        push    ebx ecx edx
471
 
472
        xor     edx, edx        ; result
473
        xor     ecx, ecx        ; byte count
474
        inc     ecx
475
        mov     bl, 10          ; divisor
476
 
477
        div     bl
478
        mov     dl, ah
479
        add     dl, '0'
480
        and     ax, 0x00ff
481
        jz      .ok
482
 
483
        inc     ecx
484
        shl     edx, 8
485
 
486
        div     bl
487
        mov     dl, ah
488
        add     dl, '0'
489
        and     ax, 0x00ff
490
        jz      .ok
491
 
492
        inc     ecx
493
        shl     edx, 8
494
 
495
        mov     dl, al
496
        add     dl, '0'
497
 
498
  .ok:
499
        shl     edx, 8
500
        mov     dl, cl
501
        mov     [edi], edx
502
        add     edi, ecx
503
        inc     edi
504
 
505
        pop     edx ecx ebx
506
        ret
507
 
508
 
509
; data
510
title   db      'Trace route',0
511
str_welcome db  'Please enter the hostname or IP-address of the host you want to trace,',10
512
            db  'or just press enter to exit.',10,10,0
513
str_prompt  db  10,'> ',0
514
str3    db      'Tracing route to ',0
515
 
516
str4    db      10,0
517
str7    db      ' ', 0
518
str5    db      'Name resolution failed.',10,0
519
str6    db      'Socket error.',10,0
520
str13   db      'Invalid parameter(s)',10,0
521
 
522
str9    db      '%u ',0
523
str1    db      '%u.%u ms ',0
524
str2    db      '[%u.%u.%u.%u]',10,0
525
str10   db      'Invalid reply',10,0
526
str8    db      'Timeout!',10,0
527
 
528
 
529
sockaddr1:
530
        dw AF_INET4
531
.port   dw 666
532
.ip     dd 0
533
        rb 10
534
 
535
sockaddr2:
536
        dw AF_INET4
537
.port   dw 53 shl 8     ; DNS port
538
.ip     dd 0x08080808   ; Google DNS
539
        rb 10
540
 
541
time_reference  dd ?
542
ip_ptr          dd ?
543
ttl             dd ?
544
timeout         dd 500
545
recvd           dd ?    ; received number of bytes in last packet
546
 
547
; import
548
align 4
549
@IMPORT:
550
 
551
library console, 'console.obj', \
552
        network, 'network.obj'
553
 
554
import  console,        \
555
        con_start,      'START',        \
556
        con_init,       'con_init',     \
557
        con_write_asciiz,       'con_write_asciiz',     \
558
        con_printf,       'con_printf',     \
559
        con_exit,       'con_exit',     \
560
        con_gets,       'con_gets',\
561
        con_cls,        'con_cls',\
562
        con_getch2,     'con_getch2',\
563
        con_set_cursor_pos, 'con_set_cursor_pos',\
564
        con_get_flags,  'con_get_flags'
565
 
566
import  network,        \
567
        getaddrinfo,    'getaddrinfo',  \
568
        freeaddrinfo,   'freeaddrinfo', \
569
        inet_ntoa,      'inet_ntoa'
570
 
571
include_debug_strings
572
 
573
icmp_socket     dd ?
574
udp_socket      dd ?
575
dns_socket      dd ?
576
 
577
udp_packet      db 'hello!'
578
 
579
dns_tr:
580
        db  7,'in-addr',4,'arpa',0
581
        dw  0x0C00      ; Qtype: PTR
582
        dw  0x0100      ; Class: IN
583
 
584
  .length = $ - dns_tr
585
 
586
dns_pkt:
587
        dw  0x9A02      ; Transaction ID
588
        dw  0x0001      ; Flags: Recursive desired
589
        dw  0x0100      ; Questions
590
        dw  0x0000      ; Answers
591
        dw  0x0000      ; Authority RR
592
        dw  0x0000      ; Additional RR
593
  .name rb  512
594
 
595
I_END:
596
 
597
params          rb 1024
598
buffer_ptr:     rb BUFFERSIZE
599
 
600
IM_END: