Subversion Repositories Kolibri OS

Rev

Rev 4435 | 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     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      .invalid
  166.         mov     [recvd], eax
  167.  
  168.         cmp     word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER
  169.         jne     .invalid
  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. ; Invalid reply
  206.   .invalid:
  207.         push    str10
  208.         call    [con_write_asciiz]
  209.         jmp     .continue
  210.  
  211. ; Timeout!
  212.   .no_response:
  213.         push    str8
  214.         call    [con_write_asciiz]
  215.  
  216. ; Send more ICMP packets ?
  217.   .continue:
  218.         inc     [icmp_packet.seq]
  219.  
  220.         dec     [count]
  221.         jz      done
  222.  
  223.         mcall   5, 100  ; wait a second
  224.  
  225.         jmp     mainloop
  226.  
  227. ; Done..
  228. done:
  229.         cmp     [stats.rx], 0
  230.         jne     @f
  231.         xor     eax, eax
  232.         jmp     .zero
  233.   @@:
  234.         xor     edx, edx
  235.         mov     eax, [stats.time]
  236.         div     [stats.rx]
  237.   .zero:
  238.         push    eax
  239.         push    [stats.rx]
  240.         push    [stats.tx]
  241.         push    str12
  242.         call    [con_printf]
  243.         jmp     main
  244.  
  245. ; DNS error
  246. fail:
  247.         push    str5
  248.         call    [con_write_asciiz]
  249.         jmp     main
  250.  
  251. ; Socket error
  252. fail2:
  253.         push    str6
  254.         call    [con_write_asciiz]
  255.         jmp     main
  256.  
  257. ; Finally.. exit!
  258. exit:
  259.         push    1
  260.         call    [con_exit]
  261.  
  262.         mcall   -1
  263.  
  264.  
  265. ; data
  266. title   db      'ICMP echo (ping) client',0
  267. str_welcome db  'Please enter the hostname or IP-address of the host you want to ping,',10
  268.             db  'or just press enter to exit.',10,0
  269. str_prompt  db  10,'> ',0
  270. str3    db      'Pinging to ',0
  271. str3b   db      ' with %u data bytes',10,0
  272.  
  273. str4    db      10,0
  274. str5    db      'Name resolution failed.',10,0
  275. str6    db      'Could not open socket',10,0
  276.  
  277. str11   db      'Answer: ',0
  278. str7    db      'bytes=%u seq=%u time=%u ms',10,0
  279. str8    db      'timeout!',10,0
  280. str9    db      'miscompare at offset %u',10,0
  281. str10   db      'reply invalid',10,0
  282.  
  283. str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
  284.  
  285. sockaddr1:
  286.         dw AF_INET4
  287. .port   dw 0
  288. .ip     dd 0
  289.         rb 10
  290.  
  291. time_reference  dd ?
  292. ip_ptr          dd ?
  293. count           dd ?
  294. recvd           dd ?    ; received number of bytes in last packet
  295.  
  296. stats:
  297.         .tx     dd ?
  298.         .rx     dd ?
  299.         .time   dd ?
  300.  
  301. ; import
  302. align 4
  303. @IMPORT:
  304.  
  305. library network, 'network.obj', console, 'console.obj'
  306. import  network,        \
  307.         getaddrinfo,    'getaddrinfo',  \
  308.         freeaddrinfo,   'freeaddrinfo', \
  309.         inet_ntoa,      'inet_ntoa'
  310.  
  311. import  console,        \
  312.         con_start,      'START',        \
  313.         con_init,       'con_init',     \
  314.         con_write_asciiz,       'con_write_asciiz',     \
  315.         con_printf,       'con_printf',     \
  316.         con_exit,       'con_exit',     \
  317.         con_gets,       'con_gets',\
  318.         con_cls,        'con_cls',\
  319.         con_getch2,     'con_getch2',\
  320.         con_set_cursor_pos, 'con_set_cursor_pos'
  321.  
  322. socketnum       dd ?
  323.  
  324. icmp_packet:    db 8            ; type
  325.                 db 0            ; code
  326.                 dw 0            ;
  327.  .id            dw IDENTIFIER   ; identifier
  328.  .seq           dw 0x0000       ; sequence number
  329.  .data          db 'abcdefghijklmnopqrstuvwxyz012345'
  330.  .length = $ - icmp_packet
  331.  
  332. I_END:
  333.  
  334. buffer_ptr      rb BUFFERSIZE
  335.  
  336. s               rb 1024
  337.                 rb 4096    ; stack
  338. mem:
  339.