Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2021. All rights reserved.    ;;
  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.         invoke  con_start, 1
  58.         invoke  con_init, 80, 25, 80, 250, title
  59. ; main loop
  60.         cmp     byte[params], 0
  61.         jne     parse_param
  62.  
  63.         invoke  con_write_asciiz, str_welcome
  64. main:
  65. ; write prompt
  66.         invoke  con_write_asciiz, str_prompt
  67. ; read string
  68.         mov     esi, params
  69.         invoke  con_gets, esi, 1024
  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:
  112.         invoke  con_write_asciiz, str13
  113.         jmp     main
  114.  
  115.   .resolve:
  116.         DEBUGF  2, "resolve\n"
  117. ; resolve name
  118.         push    esp     ; reserve stack place
  119.         invoke  getaddrinfo, params, 0, 0, esp
  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
  129.         invoke  inet_ntoa
  130. ; write result
  131.         mov     [ip_ptr], eax
  132.  
  133.         push    eax
  134.  
  135. ; free allocated memory
  136.         invoke  freeaddrinfo, esi
  137.  
  138.         invoke  con_write_asciiz, str4
  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.  
  156.         invoke  con_write_asciiz, str3
  157.         invoke  con_write_asciiz, [ip_ptr]
  158.         invoke  con_write_asciiz, str4
  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:
  167.         invoke  con_get_flags
  168.         test    eax, 0x200                      ; con window closed?
  169.         jnz     exit_now
  170.  
  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.  
  179.         pushd   [ttl]
  180.         invoke  con_printf, str9
  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.  
  226.         DEBUGF  2, "Answer of %u bytes\n", eax
  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?
  250.         DEBUGF  2, "Response Type: %u Code: %u\n", [esi + ICMP_header.Type], [esi + ICMP_header.Code]
  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.  
  272.         invoke  con_printf, str1
  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.  
  291.         invoke  con_printf, str2
  292.         add     esp, 5*4
  293.  
  294.         ret
  295.  
  296.  
  297. ; Invalid reply
  298.   .invalid:
  299.         DEBUGF  2, "Invalid response\n"
  300.         invoke  con_write_asciiz, str10
  301.         jmp     main    ;.continue
  302.  
  303. ; Timeout!
  304.   .timeout:
  305.         DEBUGF  2, "Timeout\n", eax
  306.         invoke  con_write_asciiz, str8
  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:
  318.         invoke  con_write_asciiz, str5
  319.         jmp     main
  320.  
  321. ; Socket error
  322. fail2:
  323.         invoke  con_write_asciiz, str6
  324.         jmp     main
  325.  
  326. ; Finally.. exit!
  327. exit:
  328.         invoke  con_exit, 1
  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.  
  430.         invoke  con_write_asciiz, buffer_ptr
  431.         invoke  con_write_asciiz, str7
  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',\
  537.         con_get_flags,  'con_get_flags',\
  538.         con_kbhit,      'con_kbhit'
  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:
  575.