Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2017. 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 after %u\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.         cmp     [esi + ICMP_header.Type], ICMP_UNREACH_PORT
  267.         je      .last
  268.         cmp     [esi + ICMP_header.Type], ICMP_TIMXCEED
  269.         jne     .invalid
  270.         call    .print
  271.         jmp     .continue
  272.  
  273.   .last:
  274.         call    .print
  275.         jmp     main
  276.  
  277.   .print:
  278.         DEBUGF  2, "Valid response\n"
  279. ; we have a response, print a line
  280.         mov     eax, [time_reference]
  281.         xor     edx, edx
  282.         mov     ebx, 10
  283.         div     ebx
  284.         push    edx
  285.         push    eax
  286.  
  287.         push    str1
  288.         call    [con_printf]
  289.         add     esp, 3*4
  290.  
  291.         mov     ebx, [buffer_ptr + IPv4_header.SourceAddress]
  292.         push    ebx
  293.         call    reverse_dns_lookup
  294.  
  295.         pop     eax
  296.         rol     eax, 16
  297.         movzx   ebx, ah
  298.         push    ebx
  299.         movzx   ebx, al
  300.         push    ebx
  301.         shr     eax, 16
  302.         movzx   ebx, ah
  303.         push    ebx
  304.         movzx   ebx, al
  305.         push    ebx
  306.  
  307.         push    str2
  308.         call    [con_printf]
  309.         add     esp, 5*4
  310.  
  311.         ret
  312.  
  313.  
  314. ; Invalid reply
  315.   .invalid:
  316.         DEBUGF  2, "Invalid response\n"
  317.         push    str10
  318.         call    [con_write_asciiz]
  319.         jmp     main    ;.continue
  320.  
  321. ; Timeout!
  322.   .timeout:
  323.         DEBUGF  2, "Timeout\n", eax
  324.         push    str8
  325.         call    [con_write_asciiz]
  326.  
  327. ; Send more ICMP packets ?
  328.   .continue:
  329.         inc     [ttl]
  330.  
  331. ; wait a second before sending next request
  332.         mcall   5, 100
  333.         jmp     mainloop
  334.  
  335. ; DNS error
  336. fail:
  337.         push    str5
  338.         call    [con_write_asciiz]
  339.         jmp     main
  340.  
  341. ; Socket error
  342. fail2:
  343.         push    str6
  344.         call    [con_write_asciiz]
  345.         jmp     main
  346.  
  347. ; Finally.. exit!
  348. exit:
  349.         push    1
  350.         call    [con_exit]
  351. exit_now:
  352.         mcall   -1
  353.  
  354.  
  355. ascii_to_dec:
  356.  
  357.         lodsb
  358.         cmp     al, ' '
  359.         jne     .fail
  360.  
  361.         xor     eax, eax
  362.         xor     ebx, ebx
  363.   .loop:
  364.         lodsb
  365.         test    al, al
  366.         jz      .done
  367.         cmp     al, ' '
  368.         je      .done
  369.         sub     al, '0'
  370.         jb      .fail
  371.         cmp     al, 9
  372.         ja      .fail
  373.         lea     ebx, [ebx*4+ebx]
  374.         lea     ebx, [ebx*2+eax]
  375.         jmp     .loop
  376.   .fail:
  377.         xor     ebx, ebx
  378.   .done:
  379.         dec     esi
  380.         ret
  381.  
  382.  
  383. ; ebx = ip
  384. reverse_dns_lookup:
  385.  
  386.         push    ebx
  387.         mcall   socket, AF_INET4, SOCK_DGRAM, 0
  388.         pop     ebx
  389.         cmp     eax, -1
  390.         je      .fail
  391.         mov     [dns_socket], eax
  392.  
  393.         push    ebx
  394.         mcall   connect, [dns_socket], sockaddr2, 18
  395.         pop     ebx
  396.         cmp     eax, -1
  397.         je      .fail
  398.  
  399.         mov     edi, dns_pkt.name
  400.         rol     ebx, 8
  401.         movzx   eax, bl
  402.         call    byte_to_ascii
  403.         rol     ebx, 8
  404.         movzx   eax, bl
  405.         call    byte_to_ascii
  406.         rol     ebx, 8
  407.         movzx   eax, bl
  408.         call    byte_to_ascii
  409.         rol     ebx, 8
  410.         movzx   eax, bl
  411.         call    byte_to_ascii
  412.  
  413.         mov     esi, dns_tr
  414.         mov     ecx, dns_tr.length
  415.         rep movsb
  416.  
  417.         sub     edi, dns_pkt
  418.         mov     esi, edi
  419.  
  420.         mcall   send, [dns_socket], dns_pkt, , 0
  421.         cmp     eax, -1
  422.         je      .fail
  423.  
  424.         push    esi
  425.         mcall   recv, [dns_socket], buffer_ptr, BUFFERSIZE, 0
  426.         pop     esi
  427.  
  428.         mcall   close, [dns_socket]
  429.  
  430.         cmp     word[buffer_ptr+6], 0   ; answers
  431.         je      .fail
  432.  
  433.         add     esi, buffer_ptr+12
  434.         mov     edi, buffer_ptr
  435.         xor     ecx, ecx
  436.         lodsb
  437.         test    al, al
  438.         jz      @f
  439.         movzx   ecx, al
  440.   @@:
  441.         rep movsb
  442.         lodsb
  443.         test    al, al
  444.         jz      @f
  445.         movzx   ecx, al
  446.         mov     al, '.'
  447.         stosb
  448.         jmp     @r
  449.   @@:
  450.         stosb
  451.  
  452.         push    buffer_ptr
  453.         call    [con_write_asciiz]
  454.  
  455.         push    str7
  456.         call    [con_write_asciiz]
  457.  
  458.         ret
  459.  
  460.   .fail:
  461.         ret
  462.  
  463.  
  464.  
  465. ; input: eax - number
  466. ;        edi - ptr
  467. byte_to_ascii:
  468.  
  469.         push    ebx ecx edx
  470.  
  471.         xor     edx, edx        ; result
  472.         xor     ecx, ecx        ; byte count
  473.         inc     ecx
  474.         mov     bl, 10          ; divisor
  475.  
  476.         div     bl
  477.         mov     dl, ah
  478.         add     dl, '0'
  479.         and     ax, 0x00ff
  480.         jz      .ok
  481.  
  482.         inc     ecx
  483.         shl     edx, 8
  484.  
  485.         div     bl
  486.         mov     dl, ah
  487.         add     dl, '0'
  488.         and     ax, 0x00ff
  489.         jz      .ok
  490.  
  491.         inc     ecx
  492.         shl     edx, 8
  493.  
  494.         mov     dl, al
  495.         add     dl, '0'
  496.  
  497.   .ok:
  498.         shl     edx, 8
  499.         mov     dl, cl
  500.         mov     [edi], edx
  501.         add     edi, ecx
  502.         inc     edi
  503.  
  504.         pop     edx ecx ebx
  505.         ret
  506.  
  507.  
  508. ; data
  509. title   db      'Trace route',0
  510. str_welcome db  'Please enter the hostname or IP-address of the host you want to trace,',10
  511.             db  'or just press enter to exit.',10,10,0
  512. str_prompt  db  10,'> ',0
  513. str3    db      'Tracing route to ',0
  514.  
  515. str4    db      10,0
  516. str7    db      ' ', 0
  517. str5    db      'Name resolution failed.',10,0
  518. str6    db      'Socket error.',10,0
  519. str13   db      'Invalid parameter(s)',10,0
  520.  
  521. str9    db      '%u ',0
  522. str1    db      '%u.%u ms ',0
  523. str2    db      '[%u.%u.%u.%u]',10,0
  524. str10   db      'Invalid reply',10,0
  525. str8    db      'Timeout!',10,0
  526.  
  527.  
  528. sockaddr1:
  529.         dw AF_INET4
  530. .port   dw 666
  531. .ip     dd 0
  532.         rb 10
  533.  
  534. sockaddr2:
  535.         dw AF_INET4
  536. .port   dw 53 shl 8     ; DNS port
  537. .ip     dd 0x08080808   ; Google DNS
  538.         rb 10
  539.  
  540. time_reference  dd ?
  541. ip_ptr          dd ?
  542. ttl             dd ?
  543. timeout         dd 500
  544. recvd           dd ?    ; received number of bytes in last packet
  545.  
  546. ; import
  547. align 4
  548. @IMPORT:
  549.  
  550. library console, 'console.obj', \
  551.         network, 'network.obj'
  552.  
  553. import  console,        \
  554.         con_start,      'START',        \
  555.         con_init,       'con_init',     \
  556.         con_write_asciiz,       'con_write_asciiz',     \
  557.         con_printf,       'con_printf',     \
  558.         con_exit,       'con_exit',     \
  559.         con_gets,       'con_gets',\
  560.         con_cls,        'con_cls',\
  561.         con_getch2,     'con_getch2',\
  562.         con_set_cursor_pos, 'con_set_cursor_pos',\
  563.         con_get_flags,  'con_get_flags'
  564.  
  565. import  network,        \
  566.         getaddrinfo,    'getaddrinfo',  \
  567.         freeaddrinfo,   'freeaddrinfo', \
  568.         inet_ntoa,      'inet_ntoa'
  569.  
  570. include_debug_strings
  571.  
  572. icmp_socket     dd ?
  573. udp_socket      dd ?
  574. dns_socket      dd ?
  575.  
  576. udp_packet      db 'hello!'
  577.  
  578. dns_tr:
  579.         db  7,'in-addr',4,'arpa',0
  580.         dw  0x0C00      ; Qtype: PTR
  581.         dw  0x0100      ; Class: IN
  582.  
  583.   .length = $ - dns_tr
  584.  
  585. dns_pkt:
  586.         dw  0x9A02      ; Transaction ID
  587.         dw  0x0001      ; Flags: Recursive desired
  588.         dw  0x0100      ; Questions
  589.         dw  0x0000      ; Answers
  590.         dw  0x0000      ; Authority RR
  591.         dw  0x0000      ; Additional RR
  592.   .name rb  512
  593.  
  594. I_END:
  595.  
  596. params          rb 1024
  597. buffer_ptr:     rb BUFFERSIZE
  598.  
  599. IM_END:
  600.