Subversion Repositories Kolibri OS

Rev

Rev 4019 | Blame | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;; Copyright (C) KolibriOS team 2010-2013. 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     resolve
  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. resolve:
  94. ; resolve name
  95.         push    esp     ; reserve stack place
  96.         push    esp     ; fourth parameter
  97.         push    0       ; third parameter
  98.         push    0       ; second parameter
  99.         push    s       ; first parameter
  100.         call    [getaddrinfo]
  101.         pop     esi
  102. ; test for error
  103.         test    eax, eax
  104.         jnz     fail
  105.  
  106. ; convert IP address to decimal notation
  107.         mov     eax, [esi+addrinfo.ai_addr]
  108.         mov     eax, [eax+sockaddr_in.sin_addr]
  109.         mov     [sockaddr1.ip], eax
  110.         push    eax
  111.         call    [inet_ntoa]
  112. ; write result
  113.         mov     [ip_ptr], eax
  114.  
  115.         push    eax
  116.  
  117. ; free allocated memory
  118.         push    esi
  119.         call    [freeaddrinfo]
  120.  
  121.         push    str4
  122.         call    [con_write_asciiz]
  123.  
  124.         mcall   socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
  125.         cmp     eax, -1
  126.         jz      fail2
  127.         mov     [socketnum], eax
  128.  
  129.         mcall   connect, [socketnum], sockaddr1, 18
  130.  
  131.         mcall   40, 1 shl 7 ; + 7
  132. ;        call    [con_cls]
  133.  
  134.         mov     [count], 4
  135.  
  136.         push    str3
  137.         call    [con_write_asciiz]
  138.  
  139.         push    [ip_ptr]
  140.         call    [con_write_asciiz]
  141.  
  142.         push    (icmp_packet.length - ICMP_Packet.Data)
  143.         push    str3b
  144.         call    [con_printf]
  145.  
  146. mainloop:
  147.         inc     [stats.tx]
  148.         mcall   26,9
  149.         mov     [time_reference], eax
  150.         mcall   send, [socketnum], icmp_packet, icmp_packet.length, 0
  151.  
  152.         mcall   23, 300 ; 3 seconds time-out
  153.         mcall   26,9
  154.         sub     eax, [time_reference]
  155.         xor     edx, edx
  156.         mov     cx, 10
  157.         mul     cx
  158.         mov     [time_reference], eax
  159.  
  160.         mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
  161.         cmp     eax, -1
  162.         je      .no_response
  163.  
  164.         sub     eax, ICMP_Packet.Data
  165.         jb      .no_response            ; FIXME: use other error message?
  166.         mov     [recvd], eax
  167.  
  168.         cmp     word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER
  169.         jne     .no_response            ; FIXME: use other error message?
  170.  
  171. ; OK, we have a response, update stats and let the user know
  172.         inc     [stats.rx]
  173.         mov     eax, [time_reference]
  174.         add     [stats.time], eax
  175.  
  176.         push    str11                   ; TODO: print IP address of packet sender
  177.         call    [con_write_asciiz]
  178.  
  179. ; validate the packet
  180.         lea     esi, [buffer_ptr + ICMP_Packet.Data]
  181.         mov     ecx, [recvd]
  182.         mov     edi, icmp_packet.data
  183.         repe    cmpsb
  184.         jne     .miscomp
  185.  
  186. ; All OK, print to the user!
  187.         push    [time_reference]
  188.         movzx   eax, word[buffer_ptr + ICMP_Packet.SequenceNumber]
  189.         push    eax
  190.         push    [recvd]
  191.  
  192.         push    str7
  193.         call    [con_printf]
  194.  
  195.         jmp     continue
  196.  
  197. ; Error in packet, print it to user
  198.   .miscomp:
  199.         sub     edi, icmp_packet.data
  200.         push    edi
  201.         push    str9
  202.         call    [con_printf]
  203.         jmp     continue
  204.  
  205. ; Timeout!
  206.   .no_response:
  207.         push    str8
  208.         call    [con_write_asciiz]
  209.  
  210. ; Send more ICMP packets ?
  211.    continue:
  212.         dec     [count]
  213.         jz      done
  214.  
  215.         mcall   5, 100  ; wait a second
  216.  
  217.         inc     [icmp_packet.seq]
  218.         jmp     mainloop
  219.  
  220. ; Done..
  221. done:
  222.         cmp     [stats.rx], 0
  223.         jne     @f
  224.         xor     eax, eax
  225.         jmp     .zero
  226.   @@:
  227.         xor     edx, edx
  228.         mov     eax, [stats.time]
  229.         div     [stats.rx]
  230.   .zero:
  231.         push    eax
  232.         push    [stats.rx]
  233.         push    [stats.tx]
  234.         push    str12
  235.         call    [con_printf]
  236.         jmp     main
  237.  
  238. ; DNS error
  239. fail:
  240.         push    str5
  241.         call    [con_write_asciiz]
  242.         jmp     main
  243.  
  244. ; Socket error
  245. fail2:
  246.         push    str6
  247.         call    [con_write_asciiz]
  248.         jmp     main
  249.  
  250. ; Finally.. exit!
  251. exit:
  252.         push    1
  253.         call    [con_exit]
  254.  
  255.         mcall   -1
  256.  
  257.  
  258. ; data
  259. title   db      'ICMP echo (ping) client',0
  260. str_welcome db  'Please enter the hostname or IP-address of the host you want to ping,',10
  261.             db  'or just press enter to exit.',10,0
  262. str_prompt  db  10,'> ',0
  263. str3    db      'Pinging to ',0
  264. str3b   db      ' with %u data bytes',10,0
  265.  
  266. str4    db      10,0
  267. str5    db      'Name resolution failed.',10,0
  268. str6    db      'Could not open socket',10,0
  269.  
  270. str11   db      'Answer: ',0
  271. str7    db      'bytes=%u seq=%u time=%u ms',10,0
  272. str8    db      'timeout!',10,0
  273. str9    db      'miscompare at offset %u',10,0
  274.  
  275. str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
  276.  
  277. sockaddr1:
  278.         dw AF_INET4
  279. .port   dw 0
  280. .ip     dd 0
  281.         rb 10
  282.  
  283. time_reference  dd ?
  284. ip_ptr          dd ?
  285. count           dd ?
  286. recvd           dd ?    ; received number of bytes in last packet
  287.  
  288. stats:
  289.         .tx     dd ?
  290.         .rx     dd ?
  291.         .time   dd ?
  292.  
  293. ; import
  294. align 4
  295. @IMPORT:
  296.  
  297. library network, 'network.obj', console, 'console.obj'
  298. import  network,        \
  299.         getaddrinfo,    'getaddrinfo',  \
  300.         freeaddrinfo,   'freeaddrinfo', \
  301.         inet_ntoa,      'inet_ntoa'
  302.  
  303. import  console,        \
  304.         con_start,      'START',        \
  305.         con_init,       'con_init',     \
  306.         con_write_asciiz,       'con_write_asciiz',     \
  307.         con_printf,       'con_printf',     \
  308.         con_exit,       'con_exit',     \
  309.         con_gets,       'con_gets',\
  310.         con_cls,        'con_cls',\
  311.         con_getch2,     'con_getch2',\
  312.         con_set_cursor_pos, 'con_set_cursor_pos'
  313.  
  314. socketnum       dd ?
  315.  
  316. icmp_packet:    db 8            ; type
  317.                 db 0            ; code
  318.                 dw 0            ;
  319.  .id            dw IDENTIFIER   ; identifier
  320.  .seq           dw 0x0000       ; sequence number
  321.  .data          db 'abcdefghijklmnopqrstuvwxyz012345'
  322.  .length = $ - icmp_packet
  323.  
  324. I_END:
  325.  
  326. buffer_ptr      rb BUFFERSIZE
  327.  
  328. s               rb 1024
  329.                 rb 4096    ; stack
  330. mem:
  331.