Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
3618 hidnplayr 3
;; Copyright (C) KolibriOS team 2010-2013. All rights reserved.    ;;
3545 hidnplayr 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
 
4012 hidnplayr 15
; TODO: more precise timer, ttl, user selectable size/number of packets
16
 
3545 hidnplayr 17
format binary as ""
18
 
3618 hidnplayr 19
BUFFERSIZE      = 1500
4012 hidnplayr 20
IDENTIFIER      = 0x1337
3618 hidnplayr 21
 
3545 hidnplayr 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
3618 hidnplayr 36
include '../../macros.inc'
3545 hidnplayr 37
purge mov,add,sub
3618 hidnplayr 38
include '../../proc32.inc'
39
include '../../dll.inc'
40
include '../../network.inc'
3545 hidnplayr 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
4019 hidnplayr 62
 
63
        push    str_welcome
64
        call    [con_write_asciiz]
3545 hidnplayr 65
main:
66
; write prompt
4019 hidnplayr 67
        push    str_prompt
3545 hidnplayr 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
4024 hidnplayr 76
        jz      exit
3545 hidnplayr 77
        cmp     byte [esi], 10
4024 hidnplayr 78
        jz      exit
3545 hidnplayr 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
 
4019 hidnplayr 88
; reset stats
89
        mov     [stats.tx], 0
90
        mov     [stats.rx], 0
91
        mov     [stats.time], 0
92
 
3545 hidnplayr 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]
4012 hidnplayr 138
 
3545 hidnplayr 139
        push    [ip_ptr]
140
        call    [con_write_asciiz]
141
 
4012 hidnplayr 142
        push    (icmp_packet.length - ICMP_Packet.Data)
143
        push    str3b
144
        call    [con_printf]
145
 
146
mainloop:
147
        inc     [stats.tx]
3545 hidnplayr 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
4014 hidnplayr 154
        sub     eax, [time_reference]
155
        xor     edx, edx
156
        mov     cx, 10
157
        mul     cx
158
        mov     [time_reference], eax
3545 hidnplayr 159
 
4012 hidnplayr 160
        mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
3545 hidnplayr 161
        cmp     eax, -1
162
        je      .no_response
163
 
4012 hidnplayr 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
 
3545 hidnplayr 179
; validate the packet
180
        lea     esi, [buffer_ptr + ICMP_Packet.Data]
4012 hidnplayr 181
        mov     ecx, [recvd]
3545 hidnplayr 182
        mov     edi, icmp_packet.data
4012 hidnplayr 183
        repe    cmpsb
3545 hidnplayr 184
        jne     .miscomp
185
 
4012 hidnplayr 186
; All OK, print to the user!
3545 hidnplayr 187
        push    [time_reference]
4012 hidnplayr 188
        movzx   eax, word[buffer_ptr + ICMP_Packet.SequenceNumber]
189
        push    eax
190
        push    [recvd]
191
 
3545 hidnplayr 192
        push    str7
193
        call    [con_printf]
194
 
195
        jmp     continue
196
 
4012 hidnplayr 197
; Error in packet, print it to user
3545 hidnplayr 198
  .miscomp:
199
        sub     edi, icmp_packet.data
200
        push    edi
201
        push    str9
202
        call    [con_printf]
203
        jmp     continue
204
 
4012 hidnplayr 205
; Timeout!
3545 hidnplayr 206
  .no_response:
207
        push    str8
208
        call    [con_write_asciiz]
209
 
4012 hidnplayr 210
; Send more ICMP packets ?
3545 hidnplayr 211
   continue:
212
        dec     [count]
213
        jz      done
4012 hidnplayr 214
 
3545 hidnplayr 215
        mcall   5, 100  ; wait a second
4012 hidnplayr 216
 
217
        inc     [icmp_packet.seq]
3545 hidnplayr 218
        jmp     mainloop
219
 
4012 hidnplayr 220
; Done..
221
done:
4019 hidnplayr 222
        cmp     [stats.rx], 0
223
        jne     @f
224
        xor     eax, eax
225
        jmp     .zero
226
  @@:
4012 hidnplayr 227
        xor     edx, edx
228
        mov     eax, [stats.time]
229
        div     [stats.rx]
4019 hidnplayr 230
  .zero:
4012 hidnplayr 231
        push    eax
232
        push    [stats.rx]
233
        push    [stats.tx]
234
        push    str12
235
        call    [con_printf]
4019 hidnplayr 236
        jmp     main
3545 hidnplayr 237
 
4012 hidnplayr 238
; DNS error
3545 hidnplayr 239
fail:
240
        push    str5
241
        call    [con_write_asciiz]
4019 hidnplayr 242
        jmp     main
4012 hidnplayr 243
 
244
; Socket error
3545 hidnplayr 245
fail2:
246
        push    str6
247
        call    [con_write_asciiz]
4019 hidnplayr 248
        jmp     main
3545 hidnplayr 249
 
4019 hidnplayr 250
; Finally.. exit!
251
exit:
252
        push    1
253
        call    [con_exit]
3545 hidnplayr 254
 
4019 hidnplayr 255
        mcall   -1
256
 
257
 
3545 hidnplayr 258
; data
4019 hidnplayr 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
4012 hidnplayr 263
str3    db      'Pinging to ',0
264
str3b   db      ' with %u data bytes',10,0
265
 
3545 hidnplayr 266
str4    db      10,0
267
str5    db      'Name resolution failed.',10,0
268
str6    db      'Could not open socket',10,0
4012 hidnplayr 269
 
270
str11   db      'Answer: ',0
4014 hidnplayr 271
str7    db      'bytes=%u seq=%u time=%u ms',10,0
4012 hidnplayr 272
str8    db      'timeout!',10,0
273
str9    db      'miscompare at offset %u',10,0
3545 hidnplayr 274
 
4014 hidnplayr 275
str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
4012 hidnplayr 276
 
3545 hidnplayr 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 ?
4012 hidnplayr 286
recvd           dd ?    ; received number of bytes in last packet
3545 hidnplayr 287
 
4012 hidnplayr 288
stats:
4019 hidnplayr 289
        .tx     dd ?
290
        .rx     dd ?
291
        .time   dd ?
3545 hidnplayr 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            ;
4012 hidnplayr 319
 .id            dw IDENTIFIER   ; identifier
320
 .seq           dw 0x0000       ; sequence number
321
 .data          db 'abcdefghijklmnopqrstuvwxyz012345'
3545 hidnplayr 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: