Subversion Repositories Kolibri OS

Rev

Rev 4435 | 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
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
4469 hidnplayr 165
        jb      .invalid
4012 hidnplayr 166
        mov     [recvd], eax
167
 
168
        cmp     word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER
4469 hidnplayr 169
        jne     .invalid
4012 hidnplayr 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
 
4469 hidnplayr 195
        jmp     .continue
3545 hidnplayr 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]
4469 hidnplayr 203
        jmp     .continue
3545 hidnplayr 204
 
4469 hidnplayr 205
; Invalid reply
206
  .invalid:
207
        push    str10
208
        call    [con_write_asciiz]
209
        jmp     .continue
210
 
4012 hidnplayr 211
; Timeout!
3545 hidnplayr 212
  .no_response:
213
        push    str8
214
        call    [con_write_asciiz]
215
 
4012 hidnplayr 216
; Send more ICMP packets ?
4469 hidnplayr 217
  .continue:
4435 hidnplayr 218
        inc     [icmp_packet.seq]
219
 
3545 hidnplayr 220
        dec     [count]
221
        jz      done
4012 hidnplayr 222
 
3545 hidnplayr 223
        mcall   5, 100  ; wait a second
4012 hidnplayr 224
 
3545 hidnplayr 225
        jmp     mainloop
226
 
4012 hidnplayr 227
; Done..
228
done:
4019 hidnplayr 229
        cmp     [stats.rx], 0
230
        jne     @f
231
        xor     eax, eax
232
        jmp     .zero
233
  @@:
4012 hidnplayr 234
        xor     edx, edx
235
        mov     eax, [stats.time]
236
        div     [stats.rx]
4019 hidnplayr 237
  .zero:
4012 hidnplayr 238
        push    eax
239
        push    [stats.rx]
240
        push    [stats.tx]
241
        push    str12
242
        call    [con_printf]
4019 hidnplayr 243
        jmp     main
3545 hidnplayr 244
 
4012 hidnplayr 245
; DNS error
3545 hidnplayr 246
fail:
247
        push    str5
248
        call    [con_write_asciiz]
4019 hidnplayr 249
        jmp     main
4012 hidnplayr 250
 
251
; Socket error
3545 hidnplayr 252
fail2:
253
        push    str6
254
        call    [con_write_asciiz]
4019 hidnplayr 255
        jmp     main
3545 hidnplayr 256
 
4019 hidnplayr 257
; Finally.. exit!
258
exit:
259
        push    1
260
        call    [con_exit]
3545 hidnplayr 261
 
4019 hidnplayr 262
        mcall   -1
263
 
264
 
3545 hidnplayr 265
; data
4019 hidnplayr 266
title   db      'ICMP echo (ping) client',0
267
str_welcome db  'Please enter the hostname or IP-address of the host you want to ping,',10
268
            db  'or just press enter to exit.',10,0
269
str_prompt  db  10,'> ',0
4012 hidnplayr 270
str3    db      'Pinging to ',0
271
str3b   db      ' with %u data bytes',10,0
272
 
3545 hidnplayr 273
str4    db      10,0
274
str5    db      'Name resolution failed.',10,0
275
str6    db      'Could not open socket',10,0
4012 hidnplayr 276
 
277
str11   db      'Answer: ',0
4014 hidnplayr 278
str7    db      'bytes=%u seq=%u time=%u ms',10,0
4012 hidnplayr 279
str8    db      'timeout!',10,0
280
str9    db      'miscompare at offset %u',10,0
4469 hidnplayr 281
str10   db      'reply invalid',10,0
3545 hidnplayr 282
 
4014 hidnplayr 283
str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
4012 hidnplayr 284
 
3545 hidnplayr 285
sockaddr1:
286
        dw AF_INET4
287
.port   dw 0
288
.ip     dd 0
289
        rb 10
290
 
291
time_reference  dd ?
292
ip_ptr          dd ?
293
count           dd ?
4012 hidnplayr 294
recvd           dd ?    ; received number of bytes in last packet
3545 hidnplayr 295
 
4012 hidnplayr 296
stats:
4019 hidnplayr 297
        .tx     dd ?
298
        .rx     dd ?
299
        .time   dd ?
3545 hidnplayr 300
 
301
; import
302
align 4
303
@IMPORT:
304
 
305
library network, 'network.obj', console, 'console.obj'
306
import  network,        \
307
        getaddrinfo,    'getaddrinfo',  \
308
        freeaddrinfo,   'freeaddrinfo', \
309
        inet_ntoa,      'inet_ntoa'
310
 
311
import  console,        \
312
        con_start,      'START',        \
313
        con_init,       'con_init',     \
314
        con_write_asciiz,       'con_write_asciiz',     \
315
        con_printf,       'con_printf',     \
316
        con_exit,       'con_exit',     \
317
        con_gets,       'con_gets',\
318
        con_cls,        'con_cls',\
319
        con_getch2,     'con_getch2',\
320
        con_set_cursor_pos, 'con_set_cursor_pos'
321
 
322
socketnum       dd ?
323
 
324
icmp_packet:    db 8            ; type
325
                db 0            ; code
326
                dw 0            ;
4012 hidnplayr 327
 .id            dw IDENTIFIER   ; identifier
328
 .seq           dw 0x0000       ; sequence number
329
 .data          db 'abcdefghijklmnopqrstuvwxyz012345'
3545 hidnplayr 330
 .length = $ - icmp_packet
331
 
332
I_END:
333
 
334
buffer_ptr      rb BUFFERSIZE
335
 
336
s               rb 1024
337
                rb 4096    ; stack
338
mem: