Subversion Repositories Kolibri OS

Rev

Rev 4012 | Go to most recent revision | Details | Compare with Previous | 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
62
main:
63
; write prompt
64
        push    str2
65
        call    [con_write_asciiz]
66
; read string
67
        mov     esi, s
68
        push    256
69
        push    esi
70
        call    [con_gets]
71
; check for exit
72
        test    eax, eax
73
        jz      done
74
        cmp     byte [esi], 10
75
        jz      done
76
; delete terminating '\n'
77
        push    esi
78
@@:
79
        lodsb
80
        test    al, al
81
        jnz     @b
82
        mov     byte [esi-2], al
83
        pop     esi
84
 
85
resolve:
86
; resolve name
87
        push    esp     ; reserve stack place
88
        push    esp     ; fourth parameter
89
        push    0       ; third parameter
90
        push    0       ; second parameter
91
        push    s       ; first parameter
92
        call    [getaddrinfo]
93
        pop     esi
94
; test for error
95
        test    eax, eax
96
        jnz     fail
97
 
98
; convert IP address to decimal notation
99
        mov     eax, [esi+addrinfo.ai_addr]
100
        mov     eax, [eax+sockaddr_in.sin_addr]
101
        mov     [sockaddr1.ip], eax
102
        push    eax
103
        call    [inet_ntoa]
104
; write result
105
        mov     [ip_ptr], eax
106
 
107
        push    eax
108
 
109
; free allocated memory
110
        push    esi
111
        call    [freeaddrinfo]
112
 
113
        push    str4
114
        call    [con_write_asciiz]
115
 
116
        mcall   socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP
117
        cmp     eax, -1
118
        jz      fail2
119
        mov     [socketnum], eax
120
 
121
        mcall   connect, [socketnum], sockaddr1, 18
122
 
123
        mcall   40, 1 shl 7 ; + 7
124
;        call    [con_cls]
125
 
126
        mov     [count], 4
127
 
128
        push    str3
129
        call    [con_write_asciiz]
4012 hidnplayr 130
 
3545 hidnplayr 131
        push    [ip_ptr]
132
        call    [con_write_asciiz]
133
 
4012 hidnplayr 134
        push    (icmp_packet.length - ICMP_Packet.Data)
135
        push    str3b
136
        call    [con_printf]
137
 
138
mainloop:
139
        inc     [stats.tx]
3545 hidnplayr 140
        mcall   26,9
141
        mov     [time_reference], eax
142
        mcall   send, [socketnum], icmp_packet, icmp_packet.length, 0
143
 
144
        mcall   23, 300 ; 3 seconds time-out
145
        mcall   26,9
4014 hidnplayr 146
        sub     eax, [time_reference]
147
        xor     edx, edx
148
        mov     cx, 10
149
        mul     cx
150
        mov     [time_reference], eax
3545 hidnplayr 151
 
4012 hidnplayr 152
        mcall   recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT
3545 hidnplayr 153
        cmp     eax, -1
154
        je      .no_response
155
 
4012 hidnplayr 156
        sub     eax, ICMP_Packet.Data
157
        jb      .no_response            ; FIXME: use other error message?
158
        mov     [recvd], eax
159
 
160
        cmp     word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER
161
        jne     .no_response            ; FIXME: use other error message?
162
 
163
; OK, we have a response, update stats and let the user know
164
        inc     [stats.rx]
165
        mov     eax, [time_reference]
166
        add     [stats.time], eax
167
 
168
        push    str11                   ; TODO: print IP address of packet sender
169
        call    [con_write_asciiz]
170
 
3545 hidnplayr 171
; validate the packet
172
        lea     esi, [buffer_ptr + ICMP_Packet.Data]
4012 hidnplayr 173
        mov     ecx, [recvd]
3545 hidnplayr 174
        mov     edi, icmp_packet.data
4012 hidnplayr 175
        repe    cmpsb
3545 hidnplayr 176
        jne     .miscomp
177
 
4012 hidnplayr 178
; All OK, print to the user!
3545 hidnplayr 179
        push    [time_reference]
4012 hidnplayr 180
        movzx   eax, word[buffer_ptr + ICMP_Packet.SequenceNumber]
181
        push    eax
182
        push    [recvd]
183
 
3545 hidnplayr 184
        push    str7
185
        call    [con_printf]
186
 
187
        jmp     continue
188
 
4012 hidnplayr 189
; Error in packet, print it to user
3545 hidnplayr 190
  .miscomp:
191
        sub     edi, icmp_packet.data
192
        push    edi
193
        push    str9
194
        call    [con_printf]
195
        jmp     continue
196
 
4012 hidnplayr 197
; Timeout!
3545 hidnplayr 198
  .no_response:
199
        push    str8
200
        call    [con_write_asciiz]
201
 
4012 hidnplayr 202
; Send more ICMP packets ?
3545 hidnplayr 203
   continue:
204
        dec     [count]
205
        jz      done
4012 hidnplayr 206
 
3545 hidnplayr 207
        mcall   5, 100  ; wait a second
4012 hidnplayr 208
 
209
        inc     [icmp_packet.seq]
3545 hidnplayr 210
        jmp     mainloop
211
 
4012 hidnplayr 212
; Done..
213
done:
214
        xor     edx, edx
215
        mov     eax, [stats.time]
216
        div     [stats.rx]
217
        push    eax
218
        push    [stats.rx]
219
        push    [stats.tx]
220
        push    str12
221
        call    [con_printf]
3545 hidnplayr 222
 
223
        push    str10
224
        call    [con_write_asciiz]
225
        call    [con_getch2]
226
        push    1
227
        call    [con_exit]
4012 hidnplayr 228
 
229
; Finally.. exit!
3545 hidnplayr 230
exit:
231
        mcall   -1
232
 
4012 hidnplayr 233
; DNS error
3545 hidnplayr 234
fail:
235
        push    str5
236
        call    [con_write_asciiz]
237
        jmp     done
4012 hidnplayr 238
 
239
; Socket error
3545 hidnplayr 240
fail2:
241
        push    str6
242
        call    [con_write_asciiz]
243
        jmp     done
244
 
245
 
246
; data
247
title   db      'ICMP - echo client',0
248
str2    db      '> ',0
4012 hidnplayr 249
str3    db      'Pinging to ',0
250
str3b   db      ' with %u data bytes',10,0
251
 
3545 hidnplayr 252
str4    db      10,0
253
str5    db      'Name resolution failed.',10,0
254
str6    db      'Could not open socket',10,0
4012 hidnplayr 255
 
256
str11   db      'Answer: ',0
4014 hidnplayr 257
str7    db      'bytes=%u seq=%u time=%u ms',10,0
4012 hidnplayr 258
str8    db      'timeout!',10,0
259
str9    db      'miscompare at offset %u',10,0
3545 hidnplayr 260
str10   db      10,'Press any key to exit',0
261
 
4014 hidnplayr 262
str12   db      10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0
4012 hidnplayr 263
 
3545 hidnplayr 264
sockaddr1:
265
        dw AF_INET4
266
.port   dw 0
267
.ip     dd 0
268
        rb 10
269
 
270
time_reference  dd ?
271
ip_ptr          dd ?
272
count           dd ?
4012 hidnplayr 273
recvd           dd ?    ; received number of bytes in last packet
3545 hidnplayr 274
 
4012 hidnplayr 275
stats:
276
        .tx     dd 0
277
        .rx     dd 0
278
        .time   dd 0
3545 hidnplayr 279
 
280
; import
281
align 4
282
@IMPORT:
283
 
284
library network, 'network.obj', console, 'console.obj'
285
import  network,        \
286
        getaddrinfo,    'getaddrinfo',  \
287
        freeaddrinfo,   'freeaddrinfo', \
288
        inet_ntoa,      'inet_ntoa'
289
 
290
import  console,        \
291
        con_start,      'START',        \
292
        con_init,       'con_init',     \
293
        con_write_asciiz,       'con_write_asciiz',     \
294
        con_printf,       'con_printf',     \
295
        con_exit,       'con_exit',     \
296
        con_gets,       'con_gets',\
297
        con_cls,        'con_cls',\
298
        con_getch2,     'con_getch2',\
299
        con_set_cursor_pos, 'con_set_cursor_pos'
300
 
301
socketnum       dd ?
302
 
303
icmp_packet:    db 8            ; type
304
                db 0            ; code
305
                dw 0            ;
4012 hidnplayr 306
 .id            dw IDENTIFIER   ; identifier
307
 .seq           dw 0x0000       ; sequence number
308
 .data          db 'abcdefghijklmnopqrstuvwxyz012345'
3545 hidnplayr 309
 .length = $ - icmp_packet
310
 
311
I_END:
312
 
313
buffer_ptr      rb BUFFERSIZE
314
 
315
s               rb 1024
316
                rb 4096    ; stack
317
mem: