Subversion Repositories Kolibri OS

Rev

Rev 4469 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2014. All rights reserved.    ;;
  4. ;; Distributed under terms of the GNU General Public License       ;;
  5. ;;                                                                 ;;
  6. ;;  ping.asm - ICMP echo client for KolibriOS                      ;;
  7. ;;                                                                 ;;
  8. ;;  Written by hidnplayr@kolibrios.org                             ;;
  9. ;;                                                                 ;;
  10. ;;          GNU GENERAL PUBLIC LICENSE                             ;;
  11. ;;             Version 2, June 1991                                ;;
  12. ;;                                                                 ;;
  13. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  14.  
  15. ; TODO: more precise timer, ttl, user selectable size/number of packets
  16.  
  17. format binary as ""
  18.  
  19. BUFFERSIZE      = 1500
  20. IDENTIFIER      = 0x1337
  21.  
  22. use32
  23.         org     0x0
  24.  
  25.         db      'MENUET01'      ; signature
  26.         dd      1               ; header version
  27.         dd      start           ; entry point
  28.         dd      I_END           ; initialized size
  29.         dd      mem             ; required memory
  30.         dd      mem             ; stack pointer
  31.         dd      s               ; parameters
  32.         dd      0               ; path
  33.  
  34.  
  35. ; useful includes
  36. include '../../macros.inc'
  37. purge mov,add,sub
  38. include '../../proc32.inc'
  39. include '../../dll.inc'
  40. include '../../network.inc'
  41.  
  42. include 'icmp.inc'
  43.  
  44.  
  45. start:
  46. ; load libraries
  47.         stdcall dll.Load, @IMPORT
  48.         test    eax, eax
  49.         jnz     exit
  50. ; initialize console
  51.         push    1
  52.         call    [con_start]
  53.         push    title
  54.         push    25
  55.         push    80
  56.         push    25
  57.         push    80
  58.         call    [con_init]
  59. ; main loop
  60.         cmp     byte[s], 0
  61.         jne     parse_param
  62.  
  63.         push    str_welcome
  64.         call    [con_write_asciiz]
  65. main:
  66. ; write prompt
  67.         push    str_prompt
  68.         call    [con_write_asciiz]
  69. ; read string
  70.         mov     esi, s
  71.         push    256
  72.         push    esi
  73.         call    [con_gets]
  74. ; check for exit
  75.         test    eax, eax
  76.         jz      exit
  77.         cmp     byte [esi], 10
  78.         jz      exit
  79. ; delete terminating '\n'
  80.         push    esi
  81. @@:
  82.         lodsb
  83.         test    al, al
  84.         jnz     @b
  85.         mov     byte [esi-2], al
  86.         pop     esi
  87.  
  88. ; reset stats
  89.         mov     [stats.tx], 0
  90.         mov     [stats.rx], 0
  91.         mov     [stats.time], 0
  92.  
  93. parse_param:
  94.         mov     [count], 4      ; default number of pings to send
  95.  
  96. ; Check if any additional parameters were given
  97.         mov     esi, s
  98.         mov     ecx, 1024
  99.   .addrloop:
  100.         lodsb
  101.         test    al, al
  102.         jz      .resolve
  103.         cmp     al, ' '
  104.         jne     .addrloop
  105.         mov     byte[esi-1], 0
  106.         jmp     .param
  107.  
  108.   .param_loop:
  109.         lodsb
  110.         test    al, al
  111.         jz      .resolve
  112.         cmp     al, ' '
  113.         jne     .invalid
  114.   .param:
  115.         lodsb
  116.         cmp     al, '-'
  117.         jne     .invalid
  118.         lodsb
  119.         cmp     al, 't'
  120.         jne     @f
  121.         mov     [count], -1     ; infinite
  122.         jmp     .param_loop
  123.   @@:
  124.         ; implement more parameters here
  125.   .invalid:
  126.         push    str13
  127.         call    [con_write_asciiz]
  128.         jmp     main
  129.  
  130.   .resolve:
  131. ; resolve name
  132.         push    esp     ; reserve stack place
  133.         push    esp     ; fourth parameter
  134.         push    0       ; third parameter
  135.         push    0       ; second parameter
  136.         push    s       ; first parameter
  137.         call    [getaddrinfo]
  138.         pop     esi
  139. ; test for error
  140.         test    eax, eax
  141.         jnz     fail
  142.  
  143. ; convert IP address to decimal notation
  144.         mov     eax, [esi+addrinfo.ai_addr]
  145.         mov     eax, [eax+sockaddr_in.sin_addr]
  146.         mov     [sockaddr1.ip], eax
  147.         push    eax
  148.         call    [inet_ntoa]
  149. ; write result
  150.         mov     [ip_ptr], eax
  151.  
  152.         push    eax
  153.  
  154. ; free allocated memory
  155.         push    esi
  156.         call    [freeaddrinfo]
  157.  
  158.         push    str4
  159.         call    [con_write_asciiz]
  160.  
  161.         mcall   socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
  162.         cmp     eax, -1
  163.         jz      fail2
  164.         mov     [socketnum], eax
  165.  
  166.         mcall   connect, [socketnum], sockaddr1, 18
  167.  
  168.         mcall   40, 1 shl 7 ; + 7
  169. ;        call    [con_cls]
  170.  
  171.         push    str3
  172.         call    [con_write_asciiz]
  173.  
  174.         push    [ip_ptr]
  175.         call    [con_write_asciiz]
  176.  
  177.         push    (icmp_packet.length - ICMP_Packet.Data)
  178.         push    str3b
  179.         call    [con_printf]
  180.  
  181. mainloop:
  182.         call    [con_get_flags]
  183.         test    eax, 0x200                      ; con window closed?
  184.         jnz     exit_now
  185.  
  186.         inc     [stats.tx]
  187.         mcall   26, 9
  188.         mov     [time_reference], eax
  189.         mcall   send, [socketnum], icmp_packet, icmp_packet.length, 0
  190.  
  191.         mcall   23, 300 ; 3 seconds time-out
  192.         mcall   26, 9
  193.         sub     eax, [time_reference]
  194.         xor     edx, edx
  195.         mov     cx, 10
  196.         mul     cx
  197.         mov     [time_reference], eax
  198.  
  199.         mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
  200.         cmp     eax, -1
  201.         je      .no_response
  202.  
  203.         sub     eax, ICMP_Packet.Data
  204.         jb      .invalid
  205.         mov     [recvd], eax
  206.  
  207.         cmp     word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER
  208.         jne     .invalid
  209.  
  210. ; OK, we have a response, update stats and let the user know
  211.         inc     [stats.rx]
  212.         mov     eax, [time_reference]
  213.         add     [stats.time], eax
  214.  
  215.         push    str11                   ; TODO: print IP address of packet sender
  216.         call    [con_write_asciiz]
  217.  
  218. ; validate the packet
  219.         lea     esi, [buffer_ptr + ICMP_Packet.Data]
  220.         mov     ecx, [recvd]
  221.         mov     edi, icmp_packet.data
  222.         repe    cmpsb
  223.         jne     .miscomp
  224.  
  225. ; All OK, print to the user!
  226.         push    [time_reference]
  227.         movzx   eax, word[buffer_ptr + ICMP_Packet.SequenceNumber]
  228.         push    eax
  229.         push    [recvd]
  230.  
  231.         push    str7
  232.         call    [con_printf]
  233.  
  234.         jmp     .continue
  235.  
  236. ; Error in packet, print it to user
  237.   .miscomp:
  238.         sub     edi, icmp_packet.data
  239.         push    edi
  240.         push    str9
  241.         call    [con_printf]
  242.         jmp     .continue
  243.  
  244. ; Invalid reply
  245.   .invalid:
  246.         push    str10
  247.         call    [con_write_asciiz]
  248.         jmp     .continue
  249.  
  250. ; Timeout!
  251.   .no_response:
  252.         push    str8
  253.         call    [con_write_asciiz]
  254.  
  255. ; Send more ICMP packets ?
  256.   .continue:
  257.         inc     [icmp_packet.seq]
  258.  
  259.         cmp     [count], -1
  260.         je      .forever
  261.         dec     [count]
  262.         jz      done
  263.   .forever:
  264.         mcall   5, 100  ; wait a second
  265.  
  266.         jmp     mainloop
  267.  
  268. ; Done..
  269. done:
  270.         cmp     [stats.rx], 0
  271.         jne     @f
  272.         xor     eax, eax
  273.         jmp     .zero
  274.   @@:
  275.         xor     edx, edx
  276.         mov     eax, [stats.time]
  277.         div     [stats.rx]
  278.   .zero:
  279.         push    eax
  280.         push    [stats.rx]
  281.         push    [stats.tx]
  282.         push    str12
  283.         call    [con_printf]
  284.         jmp     main
  285.  
  286. ; DNS error
  287. fail:
  288.         push    str5
  289.         call    [con_write_asciiz]
  290.         jmp     main
  291.  
  292. ; Socket error
  293. fail2:
  294.         push    str6
  295.         call    [con_write_asciiz]
  296.         jmp     main
  297.  
  298. ; Finally.. exit!
  299. exit:
  300.         push    1
  301.         call    [con_exit]
  302. exit_now:
  303.         mcall   -1
  304.  
  305.  
  306. ; data
  307. title   db      'ICMP echo (ping) client',0
  308. str_welcome db  'Please enter the hostname or IP-address of the host you want to ping,',10
  309.             db  'or just press enter to exit.',10,0
  310. str_prompt  db  10,'> ',0
  311. str3    db      'Pinging to ',0
  312. str3b   db      ' with %u data bytes',10,0
  313.  
  314. str4    db      10,0
  315. str5    db      'Name resolution failed.',10,0
  316. str6    db      'Could not open socket',10,0
  317. str13   db      'Invalid parameter(s)',10,0
  318.  
  319. str11   db      'Answer: ',0
  320. str7    db      'bytes=%u seq=%u time=%u ms',10,0
  321. str8    db      'timeout!',10,0
  322. str9    db      'miscompare at offset %u',10,0
  323. str10   db      'reply invalid',10,0
  324.  
  325. str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
  326.  
  327. sockaddr1:
  328.         dw AF_INET4
  329. .port   dw 0
  330. .ip     dd 0
  331.         rb 10
  332.  
  333. time_reference  dd ?
  334. ip_ptr          dd ?
  335. count           dd ?
  336. recvd           dd ?    ; received number of bytes in last packet
  337.  
  338. stats:
  339.         .tx     dd ?
  340.         .rx     dd ?
  341.         .time   dd ?
  342.  
  343. ; import
  344. align 4
  345. @IMPORT:
  346.  
  347. library network, 'network.obj', console, 'console.obj'
  348. import  network,        \
  349.         getaddrinfo,    'getaddrinfo',  \
  350.         freeaddrinfo,   'freeaddrinfo', \
  351.         inet_ntoa,      'inet_ntoa'
  352.  
  353. import  console,        \
  354.         con_start,      'START',        \
  355.         con_init,       'con_init',     \
  356.         con_write_asciiz,       'con_write_asciiz',     \
  357.         con_printf,       'con_printf',     \
  358.         con_exit,       'con_exit',     \
  359.         con_gets,       'con_gets',\
  360.         con_cls,        'con_cls',\
  361.         con_getch2,     'con_getch2',\
  362.         con_set_cursor_pos, 'con_set_cursor_pos',\
  363.         con_get_flags,  'con_get_flags'
  364.  
  365. socketnum       dd ?
  366.  
  367. icmp_packet:    db 8            ; type
  368.                 db 0            ; code
  369.                 dw 0            ;
  370.  .id            dw IDENTIFIER   ; identifier
  371.  .seq           dw 0x0000       ; sequence number
  372.  .data          db 'abcdefghijklmnopqrstuvwxyz012345'
  373.  .length = $ - icmp_packet
  374.  
  375. I_END:
  376.  
  377. buffer_ptr      rb BUFFERSIZE
  378.  
  379. s               rb 1024
  380.                 rb 4096    ; stack
  381. mem:
  382.