Subversion Repositories Kolibri OS

Rev

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