Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2020. 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.         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.  
  242.         DEBUGF  2, "Answer of %u bytes\n", eax
  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?
  266.         DEBUGF  2, "Response Type: %u Code: %u\n", [esi + ICMP_header.Type], [esi + ICMP_header.Code]
  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:
  601.