Subversion Repositories Kolibri OS

Rev

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

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