Subversion Repositories Kolibri OS

Rev

Rev 7891 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
9128 hidnplayr 3
;; Copyright (C) KolibriOS team 2010-2021. 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
 
15
format binary as ""
16
 
7891 hidnplayr 17
BUFFERSIZE      = 65536
3618 hidnplayr 18
 
3545 hidnplayr 19
use32
20
        org     0x0
21
 
22
        db      'MENUET01'      ; signature
23
        dd      1               ; header version
5805 hidnplayr 24
        dd      START           ; entry point
3545 hidnplayr 25
        dd      I_END           ; initialized size
5805 hidnplayr 26
        dd      IM_END+0x1000   ; required memory
27
        dd      IM_END+0x1000   ; stack pointer
5842 hidnplayr 28
        dd      params          ; parameters
3545 hidnplayr 29
        dd      0               ; path
30
 
5805 hidnplayr 31
include '../../proc32.inc'
3618 hidnplayr 32
include '../../macros.inc'
3545 hidnplayr 33
purge mov,add,sub
3618 hidnplayr 34
include '../../dll.inc'
5842 hidnplayr 35
include '../../struct.inc'
3618 hidnplayr 36
include '../../network.inc'
3545 hidnplayr 37
 
6477 hidnplayr 38
include '../icmp.inc'
39
include '../ip.inc'
3545 hidnplayr 40
 
41
 
5805 hidnplayr 42
START:
43
; init heap
44
        mcall   68, 11
45
        test    eax, eax
46
        jz      exit
3545 hidnplayr 47
; load libraries
48
        stdcall dll.Load, @IMPORT
49
        test    eax, eax
50
        jnz     exit
51
; initialize console
9128 hidnplayr 52
        invoke  con_start, 1
53
        invoke  con_init, 80, 25, 80, 250, title
7891 hidnplayr 54
; Init identifier with our PID number
55
        mcall   9, thread_info, -1
56
        mov     eax, [thread_info.PID]
57
        mov     [icmp_packet.id], ax
5842 hidnplayr 58
; expand payload to 65504 bytes
59
        mov     edi, icmp_packet.data+32
60
        mov     ecx, 65504/32-1
61
  .expand_payload:
62
        mov     esi, icmp_packet.data
63
        movsd
64
        movsd
65
        movsd
66
        movsd
67
        movsd
68
        movsd
69
        movsd
70
        movsd
71
        dec     ecx
72
        jnz     .expand_payload
3545 hidnplayr 73
; main loop
5842 hidnplayr 74
        cmp     byte[params], 0
5249 hidnplayr 75
        jne     parse_param
4019 hidnplayr 76
 
9128 hidnplayr 77
        invoke  con_write_asciiz, str_welcome
3545 hidnplayr 78
main:
79
; write prompt
9128 hidnplayr 80
        invoke  con_write_asciiz, str_prompt
3545 hidnplayr 81
; read string
5842 hidnplayr 82
        mov     esi, params
9128 hidnplayr 83
        invoke  con_gets, esi, 1024
3545 hidnplayr 84
; check for exit
85
        test    eax, eax
4024 hidnplayr 86
        jz      exit
3545 hidnplayr 87
        cmp     byte [esi], 10
4024 hidnplayr 88
        jz      exit
3545 hidnplayr 89
; delete terminating '\n'
90
        push    esi
91
@@:
92
        lodsb
93
        test    al, al
94
        jnz     @b
5805 hidnplayr 95
        mov     [esi-2], al
3545 hidnplayr 96
        pop     esi
97
 
4019 hidnplayr 98
; reset stats
99
        mov     [stats.tx], 0
100
        mov     [stats.rx], 0
101
        mov     [stats.time], 0
102
 
5249 hidnplayr 103
parse_param:
5842 hidnplayr 104
; parameters defaults
105
        mov     [count], 4
106
        mov     [size], 32
107
        mov     [ttl], 128
108
        mov     [timeout], 300
5249 hidnplayr 109
 
110
; Check if any additional parameters were given
5842 hidnplayr 111
        mov     esi, params
5249 hidnplayr 112
        mov     ecx, 1024
113
  .addrloop:
114
        lodsb
115
        test    al, al
116
        jz      .resolve
117
        cmp     al, ' '
118
        jne     .addrloop
119
        mov     byte[esi-1], 0
120
        jmp     .param
121
 
122
  .param_loop:
123
        lodsb
124
        test    al, al
125
        jz      .resolve
126
        cmp     al, ' '
127
        jne     .invalid
128
  .param:
129
        lodsb
130
        cmp     al, '-'
131
        jne     .invalid
132
        lodsb
133
        cmp     al, 't'
134
        jne     @f
135
        mov     [count], -1     ; infinite
136
        jmp     .param_loop
137
  @@:
5842 hidnplayr 138
        cmp     al, 'n'
139
        jne     @f
140
        call    ascii_to_dec
141
        test    ebx, ebx
142
        jz      .invalid
143
        mov     [count], ebx
144
        jmp     .param_loop
145
  @@:
146
        cmp     al, 'l'
147
        jne     @f
148
        call    ascii_to_dec
149
        test    ebx, ebx
150
        jz      .invalid
151
        cmp     ebx, 65500
152
        ja      .invalid
153
        mov     [size], ebx
154
        jmp     .param_loop
155
  @@:
156
        cmp     al, 'i'
157
        jne     @f
158
        call    ascii_to_dec
159
        test    ebx, ebx
160
        jz      .invalid
161
        cmp     ebx, 255
162
        ja      .invalid
163
        mov     [ttl], ebx
164
        jmp     .param_loop
165
  @@:
166
        cmp     al, 'w'
167
        jne     @f
168
        call    ascii_to_dec
169
        test    ebx, ebx
170
        jz      .invalid
171
        mov     [timeout], ebx
172
        jmp     .param_loop
173
  @@:
5249 hidnplayr 174
        ; implement more parameters here
175
  .invalid:
9128 hidnplayr 176
        invoke  con_write_asciiz, str13
5249 hidnplayr 177
        jmp     main
178
 
179
  .resolve:
3545 hidnplayr 180
; resolve name
181
        push    esp     ; reserve stack place
9128 hidnplayr 182
        invoke  getaddrinfo, params, 0, 0, esp
3545 hidnplayr 183
        pop     esi
184
; test for error
185
        test    eax, eax
186
        jnz     fail
187
 
188
; convert IP address to decimal notation
189
        mov     eax, [esi+addrinfo.ai_addr]
190
        mov     eax, [eax+sockaddr_in.sin_addr]
191
        mov     [sockaddr1.ip], eax
9128 hidnplayr 192
        invoke  inet_ntoa, eax
3545 hidnplayr 193
; write result
194
        mov     [ip_ptr], eax
195
 
196
        push    eax
197
 
198
; free allocated memory
9128 hidnplayr 199
        invoke  freeaddrinfo, esi
3545 hidnplayr 200
 
9128 hidnplayr 201
        invoke  con_write_asciiz, str4
3545 hidnplayr 202
 
203
        mcall   socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
204
        cmp     eax, -1
205
        jz      fail2
206
        mov     [socketnum], eax
207
 
208
        mcall   connect, [socketnum], sockaddr1, 18
5842 hidnplayr 209
        cmp     eax, -1
210
        je      fail2
3545 hidnplayr 211
 
5842 hidnplayr 212
        pushd   [ttl]
213
        pushd   4                               ; length of option
214
        pushd   IP_TTL
215
        pushd   IPPROTO_IP
216
        mcall   setsockopt, [socketnum], esp
217
        add     esp, 16
218
        cmp     eax, -1
219
        je      fail2
220
 
5805 hidnplayr 221
        mcall   40, EVM_STACK
3545 hidnplayr 222
 
9128 hidnplayr 223
        invoke  con_write_asciiz, str3
224
        invoke  con_write_asciiz, [ip_ptr]
225
        invoke  con_printf, str3b, [size]
5842 hidnplayr 226
        add     esp, 2*4
4012 hidnplayr 227
 
228
mainloop:
9128 hidnplayr 229
        invoke  con_get_flags
5249 hidnplayr 230
        test    eax, 0x200                      ; con window closed?
231
        jnz     exit_now
232
 
4012 hidnplayr 233
        inc     [stats.tx]
5805 hidnplayr 234
        mcall   26, 10                          ; Get high precision timer count
3545 hidnplayr 235
        mov     [time_reference], eax
5842 hidnplayr 236
        mov     esi, [size]
237
        add     esi, sizeof.ICMP_header
238
        xor     edi, edi
239
        mcall   send, [socketnum], icmp_packet
240
        cmp     eax, -1
241
        je      fail2
3545 hidnplayr 242
 
7891 hidnplayr 243
        mov     [time_exceeded], 0
244
  .receiveloop:
245
        mov     ebx, [timeout]
246
        sub     ebx, [time_exceeded]
247
        jb      .no_response
248
        mcall   23                              ; Wait for network event with timeout
249
 
5805 hidnplayr 250
        mcall   26, 10                          ; Get high precision timer count
4014 hidnplayr 251
        sub     eax, [time_reference]
5805 hidnplayr 252
        jz      @f
4014 hidnplayr 253
        xor     edx, edx
5805 hidnplayr 254
        mov     ebx, 100000
255
        div     ebx
256
        cmp     edx, 50000
257
        jb      @f
258
        inc     eax
259
  @@:
7891 hidnplayr 260
        mov     [time_exceeded], eax           ; Exceeded time in 1/100 s
3545 hidnplayr 261
 
5842 hidnplayr 262
; Receive reply
4012 hidnplayr 263
        mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
3545 hidnplayr 264
        cmp     eax, -1
265
        je      .no_response
5842 hidnplayr 266
        test    eax, eax
267
        jz      fail2
3545 hidnplayr 268
 
5842 hidnplayr 269
; IP header length
270
        movzx   esi, byte[buffer_ptr]
271
        and     esi, 0xf
272
        shl     esi, 2
273
 
274
; Check packet length
275
        sub     eax, esi
276
        sub     eax, sizeof.ICMP_header
4469 hidnplayr 277
        jb      .invalid
4012 hidnplayr 278
        mov     [recvd], eax
279
 
5842 hidnplayr 280
; make esi point to ICMP packet header
281
        add     esi, buffer_ptr
4012 hidnplayr 282
 
7891 hidnplayr 283
; Check identifier
284
        mov     ax, [icmp_packet.id]
285
        cmp     [esi + ICMP_header.Identifier], ax
286
        jne     .receiveloop
287
 
5842 hidnplayr 288
; we have a response, print the sender IP
289
        push    esi
290
        mov     eax, [buffer_ptr + IPv4_header.SourceAddress]
291
        rol     eax, 16
292
        movzx   ebx, ah
293
        push    ebx
294
        movzx   ebx, al
295
        push    ebx
296
        shr     eax, 16
297
        movzx   ebx, ah
298
        push    ebx
299
        movzx   ebx, al
300
        push    ebx
301
        push    str11
302
        call    [con_printf]
303
        add     esp, 5*4
304
        pop     esi
4012 hidnplayr 305
 
5842 hidnplayr 306
; What kind of response is it?
307
        cmp     [esi + ICMP_header.Type], ICMP_ECHOREPLY
308
        je      .echo_reply
309
        cmp     [esi + ICMP_header.Type], ICMP_TIMXCEED
310
        je      .ttl_exceeded
4012 hidnplayr 311
 
5842 hidnplayr 312
        jmp     .invalid
313
 
314
 
315
  .echo_reply:
316
 
7891 hidnplayr 317
; Validate the payload
5842 hidnplayr 318
        add     esi, sizeof.ICMP_header
319
        mov     ecx, [size]
3545 hidnplayr 320
        mov     edi, icmp_packet.data
4012 hidnplayr 321
        repe    cmpsb
3545 hidnplayr 322
        jne     .miscomp
323
 
5842 hidnplayr 324
; update stats
325
        inc     [stats.rx]
7891 hidnplayr 326
        mov     eax, [time_exceeded]
5842 hidnplayr 327
        add     [stats.time], eax
328
 
7891 hidnplayr 329
; Print time exceeded
5842 hidnplayr 330
        movzx   eax, [buffer_ptr + IPv4_header.TimeToLive]
331
        push    eax
7891 hidnplayr 332
        mov     eax, [time_exceeded]
5805 hidnplayr 333
        xor     edx, edx
334
        mov     ebx, 10
335
        div     ebx
336
        push    edx
4012 hidnplayr 337
        push    eax
338
        push    [recvd]
339
 
9128 hidnplayr 340
        invoke  con_printf, str7
5842 hidnplayr 341
        add     esp, 5*4
3545 hidnplayr 342
 
4469 hidnplayr 343
        jmp     .continue
3545 hidnplayr 344
 
5842 hidnplayr 345
 
346
  .ttl_exceeded:
9128 hidnplayr 347
        invoke  con_write_asciiz, str14
5842 hidnplayr 348
        jmp     .continue
349
 
350
 
4012 hidnplayr 351
; Error in packet, print it to user
3545 hidnplayr 352
  .miscomp:
5842 hidnplayr 353
        sub     edi, icmp_packet.data+1
3545 hidnplayr 354
        push    edi
9128 hidnplayr 355
        invoke  con_printf, str9
5842 hidnplayr 356
        add     esp, 2*4
4469 hidnplayr 357
        jmp     .continue
3545 hidnplayr 358
 
4469 hidnplayr 359
; Invalid reply
360
  .invalid:
9128 hidnplayr 361
        invoke  con_write_asciiz, str13
4469 hidnplayr 362
        jmp     .continue
363
 
4012 hidnplayr 364
; Timeout!
3545 hidnplayr 365
  .no_response:
9128 hidnplayr 366
        invoke  con_write_asciiz, str8
3545 hidnplayr 367
 
4012 hidnplayr 368
; Send more ICMP packets ?
4469 hidnplayr 369
  .continue:
4435 hidnplayr 370
        inc     [icmp_packet.seq]
371
 
9128 hidnplayr 372
        invoke  con_kbhit
373
        test    eax, eax
374
        jz      .nokey
375
        invoke  con_getch2
376
        cmp     ax, 0x1E03      ; Ctrl+C
377
        je      .stats
378
  .nokey:
379
 
5249 hidnplayr 380
        cmp     [count], -1
381
        je      .forever
3545 hidnplayr 382
        dec     [count]
5842 hidnplayr 383
        jz      .stats
5249 hidnplayr 384
  .forever:
5842 hidnplayr 385
; wait a second before sending next request
386
        mcall   5, 100
3545 hidnplayr 387
        jmp     mainloop
388
 
5842 hidnplayr 389
; Print statistics
390
  .stats:
4019 hidnplayr 391
        cmp     [stats.rx], 0
392
        jne     @f
393
        xor     eax, eax
5805 hidnplayr 394
        xor     edx, edx
4019 hidnplayr 395
        jmp     .zero
396
  @@:
4012 hidnplayr 397
        xor     edx, edx
398
        mov     eax, [stats.time]
399
        div     [stats.rx]
5805 hidnplayr 400
        xor     edx, edx
401
        mov     ebx, 10
402
        div     ebx
4019 hidnplayr 403
  .zero:
5805 hidnplayr 404
        push    edx
4012 hidnplayr 405
        push    eax
406
        push    [stats.rx]
407
        push    [stats.tx]
9128 hidnplayr 408
        invoke  con_printf, str12
5842 hidnplayr 409
        add     esp, 5*4
4019 hidnplayr 410
        jmp     main
3545 hidnplayr 411
 
4012 hidnplayr 412
; DNS error
3545 hidnplayr 413
fail:
9128 hidnplayr 414
        invoke  con_write_asciiz, str5
4019 hidnplayr 415
        jmp     main
4012 hidnplayr 416
 
417
; Socket error
3545 hidnplayr 418
fail2:
9128 hidnplayr 419
        invoke  con_write_asciiz, str6
4019 hidnplayr 420
        jmp     main
3545 hidnplayr 421
 
4019 hidnplayr 422
; Finally.. exit!
423
exit:
9128 hidnplayr 424
        invoke  con_exit, 1
5249 hidnplayr 425
exit_now:
4019 hidnplayr 426
        mcall   -1
427
 
428
 
5842 hidnplayr 429
ascii_to_dec:
430
 
431
        lodsb
432
        cmp     al, ' '
433
        jne     .fail
434
 
435
        xor     eax, eax
436
        xor     ebx, ebx
437
  .loop:
438
        lodsb
439
        test    al, al
440
        jz      .done
441
        cmp     al, ' '
442
        je      .done
443
        sub     al, '0'
444
        jb      .fail
445
        cmp     al, 9
446
        ja      .fail
447
        lea     ebx, [ebx*4+ebx]
448
        lea     ebx, [ebx*2+eax]
449
        jmp     .loop
450
  .fail:
451
        xor     ebx, ebx
452
  .done:
453
        dec     esi
454
        ret
455
 
456
 
457
 
458
 
3545 hidnplayr 459
; data
4019 hidnplayr 460
title   db      'ICMP echo (ping) client',0
461
str_welcome db  'Please enter the hostname or IP-address of the host you want to ping,',10
5842 hidnplayr 462
            db  'or just press enter to exit.',10,10
463
            db  'Options:',10
9128 hidnplayr 464
            db  ' -t            Send packets till users abort. (Ctrl+C))',10
5842 hidnplayr 465
            db  ' -n number     Number of requests to send.',10
466
            db  ' -i TTL        Time to live.',10
467
            db  ' -l size       Size of echo request.',10
468
            db  ' -w time-out   Time-out in hundredths of a second.',10,0
4019 hidnplayr 469
str_prompt  db  10,'> ',0
4012 hidnplayr 470
str3    db      'Pinging to ',0
471
str3b   db      ' with %u data bytes',10,0
472
 
3545 hidnplayr 473
str4    db      10,0
474
str5    db      'Name resolution failed.',10,0
5842 hidnplayr 475
str6    db      'Socket error.',10,0
5249 hidnplayr 476
str13   db      'Invalid parameter(s)',10,0
4012 hidnplayr 477
 
5842 hidnplayr 478
str11   db      'Answer from %u.%u.%u.%u: ',0
479
str7    db      'bytes=%u time=%u.%u ms TTL=%u',10,0
5805 hidnplayr 480
str8    db      'Timeout',10,0
5842 hidnplayr 481
str9    db      'miscompare at offset %u.',10,0
482
str10   db      'invalid reply.',10,0
483
str14   db      'TTL expired.',10,0
3545 hidnplayr 484
 
5805 hidnplayr 485
str12   db      10,'Statistics:',10,'%u packets sent, %u packets received',10,'average response time=%u.%u ms',10,0
4012 hidnplayr 486
 
3545 hidnplayr 487
sockaddr1:
488
        dw AF_INET4
489
.port   dw 0
490
.ip     dd 0
491
        rb 10
492
 
7891 hidnplayr 493
time_reference  dd ?    ; start time of sent packet
494
time_exceeded   dd ?    ; time exceeded between send and receive
3545 hidnplayr 495
ip_ptr          dd ?
496
count           dd ?
5842 hidnplayr 497
size            dd ?
498
ttl             dd ?
499
timeout         dd ?
4012 hidnplayr 500
recvd           dd ?    ; received number of bytes in last packet
3545 hidnplayr 501
 
4012 hidnplayr 502
stats:
4019 hidnplayr 503
        .tx     dd ?
504
        .rx     dd ?
505
        .time   dd ?
3545 hidnplayr 506
 
507
; import
508
align 4
509
@IMPORT:
510
 
511
library network, 'network.obj', console, 'console.obj'
512
import  network,        \
513
        getaddrinfo,    'getaddrinfo',  \
514
        freeaddrinfo,   'freeaddrinfo', \
515
        inet_ntoa,      'inet_ntoa'
516
 
517
import  console,        \
518
        con_start,      'START',        \
519
        con_init,       'con_init',     \
520
        con_write_asciiz,       'con_write_asciiz',     \
521
        con_printf,       'con_printf',     \
522
        con_exit,       'con_exit',     \
523
        con_gets,       'con_gets',\
524
        con_cls,        'con_cls',\
525
        con_getch2,     'con_getch2',\
5249 hidnplayr 526
        con_set_cursor_pos, 'con_set_cursor_pos',\
9128 hidnplayr 527
        con_get_flags,  'con_get_flags',\
528
        con_kbhit,      'con_kbhit'
3545 hidnplayr 529
 
530
socketnum       dd ?
531
 
5842 hidnplayr 532
icmp_packet     db ICMP_ECHO    ; type
3545 hidnplayr 533
                db 0            ; code
5842 hidnplayr 534
                dw 0            ; checksum
7891 hidnplayr 535
 .id            dw 0            ; identifier
4012 hidnplayr 536
 .seq           dw 0x0000       ; sequence number
537
 .data          db 'abcdefghijklmnopqrstuvwxyz012345'
3545 hidnplayr 538
 
539
I_END:
5842 hidnplayr 540
                rb 65504-32
3545 hidnplayr 541
 
7891 hidnplayr 542
thread_info process_information
543
 
5842 hidnplayr 544
params          rb 1024
545
buffer_ptr:     rb BUFFERSIZE
3545 hidnplayr 546
 
5805 hidnplayr 547
IM_END: