Subversion Repositories Kolibri OS

Rev

Rev 4469 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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