Subversion Repositories Kolibri OS

Rev

Rev 7892 | Details | Compare with Previous | Last modification | View Log | RSS feed

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