Subversion Repositories Kolibri OS

Rev

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

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