Rev 4435 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4435 | Rev 4469 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2013. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2010-2014. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;; ping.asm - ICMP echo client for KolibriOS ;; |
6 | ;; ping.asm - ICMP echo client for KolibriOS ;; |
7 | ;; ;; |
7 | ;; ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
8 | ;; Written by hidnplayr@kolibrios.org ;; |
9 | ;; ;; |
9 | ;; ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
10 | ;; GNU GENERAL PUBLIC LICENSE ;; |
11 | ;; Version 2, June 1991 ;; |
11 | ;; Version 2, June 1991 ;; |
12 | ;; ;; |
12 | ;; ;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
13 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
14 | 14 | ||
15 | ; TODO: more precise timer, ttl, user selectable size/number of packets |
15 | ; TODO: more precise timer, ttl, user selectable size/number of packets |
16 | 16 | ||
17 | format binary as "" |
17 | format binary as "" |
18 | 18 | ||
19 | BUFFERSIZE = 1500 |
19 | BUFFERSIZE = 1500 |
20 | IDENTIFIER = 0x1337 |
20 | IDENTIFIER = 0x1337 |
21 | 21 | ||
22 | use32 |
22 | use32 |
23 | org 0x0 |
23 | org 0x0 |
24 | 24 | ||
25 | db 'MENUET01' ; signature |
25 | db 'MENUET01' ; signature |
26 | dd 1 ; header version |
26 | dd 1 ; header version |
27 | dd start ; entry point |
27 | dd start ; entry point |
28 | dd I_END ; initialized size |
28 | dd I_END ; initialized size |
29 | dd mem ; required memory |
29 | dd mem ; required memory |
30 | dd mem ; stack pointer |
30 | dd mem ; stack pointer |
31 | dd s ; parameters |
31 | dd s ; parameters |
32 | dd 0 ; path |
32 | dd 0 ; path |
33 | 33 | ||
34 | 34 | ||
35 | ; useful includes |
35 | ; useful includes |
36 | include '../../macros.inc' |
36 | include '../../macros.inc' |
37 | purge mov,add,sub |
37 | purge mov,add,sub |
38 | include '../../proc32.inc' |
38 | include '../../proc32.inc' |
39 | include '../../dll.inc' |
39 | include '../../dll.inc' |
40 | include '../../network.inc' |
40 | include '../../network.inc' |
41 | 41 | ||
42 | include 'icmp.inc' |
42 | include 'icmp.inc' |
43 | 43 | ||
44 | 44 | ||
45 | start: |
45 | start: |
46 | ; load libraries |
46 | ; load libraries |
47 | stdcall dll.Load, @IMPORT |
47 | stdcall dll.Load, @IMPORT |
48 | test eax, eax |
48 | test eax, eax |
49 | jnz exit |
49 | jnz exit |
50 | ; initialize console |
50 | ; initialize console |
51 | push 1 |
51 | push 1 |
52 | call [con_start] |
52 | call [con_start] |
53 | push title |
53 | push title |
54 | push 25 |
54 | push 25 |
55 | push 80 |
55 | push 80 |
56 | push 25 |
56 | push 25 |
57 | push 80 |
57 | push 80 |
58 | call [con_init] |
58 | call [con_init] |
59 | ; main loop |
59 | ; main loop |
60 | cmp byte[s], 0 |
60 | cmp byte[s], 0 |
61 | jne resolve |
61 | jne resolve |
62 | 62 | ||
63 | push str_welcome |
63 | push str_welcome |
64 | call [con_write_asciiz] |
64 | call [con_write_asciiz] |
65 | main: |
65 | main: |
66 | ; write prompt |
66 | ; write prompt |
67 | push str_prompt |
67 | push str_prompt |
68 | call [con_write_asciiz] |
68 | call [con_write_asciiz] |
69 | ; read string |
69 | ; read string |
70 | mov esi, s |
70 | mov esi, s |
71 | push 256 |
71 | push 256 |
72 | push esi |
72 | push esi |
73 | call [con_gets] |
73 | call [con_gets] |
74 | ; check for exit |
74 | ; check for exit |
75 | test eax, eax |
75 | test eax, eax |
76 | jz exit |
76 | jz exit |
77 | cmp byte [esi], 10 |
77 | cmp byte [esi], 10 |
78 | jz exit |
78 | jz exit |
79 | ; delete terminating '\n' |
79 | ; delete terminating '\n' |
80 | push esi |
80 | push esi |
81 | @@: |
81 | @@: |
82 | lodsb |
82 | lodsb |
83 | test al, al |
83 | test al, al |
84 | jnz @b |
84 | jnz @b |
85 | mov byte [esi-2], al |
85 | mov byte [esi-2], al |
86 | pop esi |
86 | pop esi |
87 | 87 | ||
88 | ; reset stats |
88 | ; reset stats |
89 | mov [stats.tx], 0 |
89 | mov [stats.tx], 0 |
90 | mov [stats.rx], 0 |
90 | mov [stats.rx], 0 |
91 | mov [stats.time], 0 |
91 | mov [stats.time], 0 |
92 | 92 | ||
93 | resolve: |
93 | resolve: |
94 | ; resolve name |
94 | ; resolve name |
95 | push esp ; reserve stack place |
95 | push esp ; reserve stack place |
96 | push esp ; fourth parameter |
96 | push esp ; fourth parameter |
97 | push 0 ; third parameter |
97 | push 0 ; third parameter |
98 | push 0 ; second parameter |
98 | push 0 ; second parameter |
99 | push s ; first parameter |
99 | push s ; first parameter |
100 | call [getaddrinfo] |
100 | call [getaddrinfo] |
101 | pop esi |
101 | pop esi |
102 | ; test for error |
102 | ; test for error |
103 | test eax, eax |
103 | test eax, eax |
104 | jnz fail |
104 | jnz fail |
105 | 105 | ||
106 | ; convert IP address to decimal notation |
106 | ; convert IP address to decimal notation |
107 | mov eax, [esi+addrinfo.ai_addr] |
107 | mov eax, [esi+addrinfo.ai_addr] |
108 | mov eax, [eax+sockaddr_in.sin_addr] |
108 | mov eax, [eax+sockaddr_in.sin_addr] |
109 | mov [sockaddr1.ip], eax |
109 | mov [sockaddr1.ip], eax |
110 | push eax |
110 | push eax |
111 | call [inet_ntoa] |
111 | call [inet_ntoa] |
112 | ; write result |
112 | ; write result |
113 | mov [ip_ptr], eax |
113 | mov [ip_ptr], eax |
114 | 114 | ||
115 | push eax |
115 | push eax |
116 | 116 | ||
117 | ; free allocated memory |
117 | ; free allocated memory |
118 | push esi |
118 | push esi |
119 | call [freeaddrinfo] |
119 | call [freeaddrinfo] |
120 | 120 | ||
121 | push str4 |
121 | push str4 |
122 | call [con_write_asciiz] |
122 | call [con_write_asciiz] |
123 | 123 | ||
124 | mcall socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP |
124 | mcall socket, AF_INET4, SOCK_RAW, IPPROTO_ICMP |
125 | cmp eax, -1 |
125 | cmp eax, -1 |
126 | jz fail2 |
126 | jz fail2 |
127 | mov [socketnum], eax |
127 | mov [socketnum], eax |
128 | 128 | ||
129 | mcall connect, [socketnum], sockaddr1, 18 |
129 | mcall connect, [socketnum], sockaddr1, 18 |
130 | 130 | ||
131 | mcall 40, 1 shl 7 ; + 7 |
131 | mcall 40, 1 shl 7 ; + 7 |
132 | ; call [con_cls] |
132 | ; call [con_cls] |
133 | 133 | ||
134 | mov [count], 4 |
134 | mov [count], 4 |
135 | 135 | ||
136 | push str3 |
136 | push str3 |
137 | call [con_write_asciiz] |
137 | call [con_write_asciiz] |
138 | 138 | ||
139 | push [ip_ptr] |
139 | push [ip_ptr] |
140 | call [con_write_asciiz] |
140 | call [con_write_asciiz] |
141 | 141 | ||
142 | push (icmp_packet.length - ICMP_Packet.Data) |
142 | push (icmp_packet.length - ICMP_Packet.Data) |
143 | push str3b |
143 | push str3b |
144 | call [con_printf] |
144 | call [con_printf] |
145 | 145 | ||
146 | mainloop: |
146 | mainloop: |
147 | inc [stats.tx] |
147 | inc [stats.tx] |
148 | mcall 26,9 |
148 | mcall 26,9 |
149 | mov [time_reference], eax |
149 | mov [time_reference], eax |
150 | mcall send, [socketnum], icmp_packet, icmp_packet.length, 0 |
150 | mcall send, [socketnum], icmp_packet, icmp_packet.length, 0 |
151 | 151 | ||
152 | mcall 23, 300 ; 3 seconds time-out |
152 | mcall 23, 300 ; 3 seconds time-out |
153 | mcall 26,9 |
153 | mcall 26,9 |
154 | sub eax, [time_reference] |
154 | sub eax, [time_reference] |
155 | xor edx, edx |
155 | xor edx, edx |
156 | mov cx, 10 |
156 | mov cx, 10 |
157 | mul cx |
157 | mul cx |
158 | mov [time_reference], eax |
158 | mov [time_reference], eax |
159 | 159 | ||
160 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT |
160 | mcall recv, [socketnum], buffer_ptr, BUFFERSIZE, MSG_DONTWAIT |
161 | cmp eax, -1 |
161 | cmp eax, -1 |
162 | je .no_response |
162 | je .no_response |
163 | 163 | ||
164 | sub eax, ICMP_Packet.Data |
164 | sub eax, ICMP_Packet.Data |
165 | jb .no_response ; FIXME: use other error message? |
165 | jb .invalid |
166 | mov [recvd], eax |
166 | mov [recvd], eax |
167 | 167 | ||
168 | cmp word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER |
168 | cmp word[buffer_ptr + ICMP_Packet.Identifier], IDENTIFIER |
169 | jne .no_response ; FIXME: use other error message? |
169 | jne .invalid |
170 | 170 | ||
171 | ; OK, we have a response, update stats and let the user know |
171 | ; OK, we have a response, update stats and let the user know |
172 | inc [stats.rx] |
172 | inc [stats.rx] |
173 | mov eax, [time_reference] |
173 | mov eax, [time_reference] |
174 | add [stats.time], eax |
174 | add [stats.time], eax |
175 | 175 | ||
176 | push str11 ; TODO: print IP address of packet sender |
176 | push str11 ; TODO: print IP address of packet sender |
177 | call [con_write_asciiz] |
177 | call [con_write_asciiz] |
178 | 178 | ||
179 | ; validate the packet |
179 | ; validate the packet |
180 | lea esi, [buffer_ptr + ICMP_Packet.Data] |
180 | lea esi, [buffer_ptr + ICMP_Packet.Data] |
181 | mov ecx, [recvd] |
181 | mov ecx, [recvd] |
182 | mov edi, icmp_packet.data |
182 | mov edi, icmp_packet.data |
183 | repe cmpsb |
183 | repe cmpsb |
184 | jne .miscomp |
184 | jne .miscomp |
185 | 185 | ||
186 | ; All OK, print to the user! |
186 | ; All OK, print to the user! |
187 | push [time_reference] |
187 | push [time_reference] |
188 | movzx eax, word[buffer_ptr + ICMP_Packet.SequenceNumber] |
188 | movzx eax, word[buffer_ptr + ICMP_Packet.SequenceNumber] |
189 | push eax |
189 | push eax |
190 | push [recvd] |
190 | push [recvd] |
191 | 191 | ||
192 | push str7 |
192 | push str7 |
193 | call [con_printf] |
193 | call [con_printf] |
194 | 194 | ||
195 | jmp continue |
195 | jmp .continue |
196 | 196 | ||
197 | ; Error in packet, print it to user |
197 | ; Error in packet, print it to user |
198 | .miscomp: |
198 | .miscomp: |
199 | sub edi, icmp_packet.data |
199 | sub edi, icmp_packet.data |
200 | push edi |
200 | push edi |
201 | push str9 |
201 | push str9 |
202 | call [con_printf] |
202 | call [con_printf] |
203 | jmp continue |
203 | jmp .continue |
- | 204 | ||
- | 205 | ; Invalid reply |
|
- | 206 | .invalid: |
|
- | 207 | push str10 |
|
- | 208 | call [con_write_asciiz] |
|
- | 209 | jmp .continue |
|
204 | 210 | ||
205 | ; Timeout! |
211 | ; Timeout! |
206 | .no_response: |
212 | .no_response: |
207 | push str8 |
213 | push str8 |
208 | call [con_write_asciiz] |
214 | call [con_write_asciiz] |
209 | 215 | ||
210 | ; Send more ICMP packets ? |
216 | ; Send more ICMP packets ? |
211 | continue: |
217 | .continue: |
212 | inc [icmp_packet.seq] |
218 | inc [icmp_packet.seq] |
213 | 219 | ||
214 | dec [count] |
220 | dec [count] |
215 | jz done |
221 | jz done |
216 | 222 | ||
217 | mcall 5, 100 ; wait a second |
223 | mcall 5, 100 ; wait a second |
218 | 224 | ||
219 | jmp mainloop |
225 | jmp mainloop |
220 | 226 | ||
221 | ; Done.. |
227 | ; Done.. |
222 | done: |
228 | done: |
223 | cmp [stats.rx], 0 |
229 | cmp [stats.rx], 0 |
224 | jne @f |
230 | jne @f |
225 | xor eax, eax |
231 | xor eax, eax |
226 | jmp .zero |
232 | jmp .zero |
227 | @@: |
233 | @@: |
228 | xor edx, edx |
234 | xor edx, edx |
229 | mov eax, [stats.time] |
235 | mov eax, [stats.time] |
230 | div [stats.rx] |
236 | div [stats.rx] |
231 | .zero: |
237 | .zero: |
232 | push eax |
238 | push eax |
233 | push [stats.rx] |
239 | push [stats.rx] |
234 | push [stats.tx] |
240 | push [stats.tx] |
235 | push str12 |
241 | push str12 |
236 | call [con_printf] |
242 | call [con_printf] |
237 | jmp main |
243 | jmp main |
238 | 244 | ||
239 | ; DNS error |
245 | ; DNS error |
240 | fail: |
246 | fail: |
241 | push str5 |
247 | push str5 |
242 | call [con_write_asciiz] |
248 | call [con_write_asciiz] |
243 | jmp main |
249 | jmp main |
244 | 250 | ||
245 | ; Socket error |
251 | ; Socket error |
246 | fail2: |
252 | fail2: |
247 | push str6 |
253 | push str6 |
248 | call [con_write_asciiz] |
254 | call [con_write_asciiz] |
249 | jmp main |
255 | jmp main |
250 | 256 | ||
251 | ; Finally.. exit! |
257 | ; Finally.. exit! |
252 | exit: |
258 | exit: |
253 | push 1 |
259 | push 1 |
254 | call [con_exit] |
260 | call [con_exit] |
255 | 261 | ||
256 | mcall -1 |
262 | mcall -1 |
257 | 263 | ||
258 | 264 | ||
259 | ; data |
265 | ; data |
260 | title db 'ICMP echo (ping) client',0 |
266 | title db 'ICMP echo (ping) client',0 |
261 | str_welcome db 'Please enter the hostname or IP-address of the host you want to ping,',10 |
267 | str_welcome db 'Please enter the hostname or IP-address of the host you want to ping,',10 |
262 | db 'or just press enter to exit.',10,0 |
268 | db 'or just press enter to exit.',10,0 |
263 | str_prompt db 10,'> ',0 |
269 | str_prompt db 10,'> ',0 |
264 | str3 db 'Pinging to ',0 |
270 | str3 db 'Pinging to ',0 |
265 | str3b db ' with %u data bytes',10,0 |
271 | str3b db ' with %u data bytes',10,0 |
266 | 272 | ||
267 | str4 db 10,0 |
273 | str4 db 10,0 |
268 | str5 db 'Name resolution failed.',10,0 |
274 | str5 db 'Name resolution failed.',10,0 |
269 | str6 db 'Could not open socket',10,0 |
275 | str6 db 'Could not open socket',10,0 |
270 | 276 | ||
271 | str11 db 'Answer: ',0 |
277 | str11 db 'Answer: ',0 |
272 | str7 db 'bytes=%u seq=%u time=%u ms',10,0 |
278 | str7 db 'bytes=%u seq=%u time=%u ms',10,0 |
273 | str8 db 'timeout!',10,0 |
279 | str8 db 'timeout!',10,0 |
274 | str9 db 'miscompare at offset %u',10,0 |
280 | str9 db 'miscompare at offset %u',10,0 |
- | 281 | str10 db 'reply invalid',10,0 |
|
275 | 282 | ||
276 | str12 db 10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0 |
283 | str12 db 10,'Ping stats:',10,'%u packets sent, %u packets received',10,'average response time=%u ms',10,0 |
277 | 284 | ||
278 | sockaddr1: |
285 | sockaddr1: |
279 | dw AF_INET4 |
286 | dw AF_INET4 |
280 | .port dw 0 |
287 | .port dw 0 |
281 | .ip dd 0 |
288 | .ip dd 0 |
282 | rb 10 |
289 | rb 10 |
283 | 290 | ||
284 | time_reference dd ? |
291 | time_reference dd ? |
285 | ip_ptr dd ? |
292 | ip_ptr dd ? |
286 | count dd ? |
293 | count dd ? |
287 | recvd dd ? ; received number of bytes in last packet |
294 | recvd dd ? ; received number of bytes in last packet |
288 | 295 | ||
289 | stats: |
296 | stats: |
290 | .tx dd ? |
297 | .tx dd ? |
291 | .rx dd ? |
298 | .rx dd ? |
292 | .time dd ? |
299 | .time dd ? |
293 | 300 | ||
294 | ; import |
301 | ; import |
295 | align 4 |
302 | align 4 |
296 | @IMPORT: |
303 | @IMPORT: |
297 | 304 | ||
298 | library network, 'network.obj', console, 'console.obj' |
305 | library network, 'network.obj', console, 'console.obj' |
299 | import network, \ |
306 | import network, \ |
300 | getaddrinfo, 'getaddrinfo', \ |
307 | getaddrinfo, 'getaddrinfo', \ |
301 | freeaddrinfo, 'freeaddrinfo', \ |
308 | freeaddrinfo, 'freeaddrinfo', \ |
302 | inet_ntoa, 'inet_ntoa' |
309 | inet_ntoa, 'inet_ntoa' |
303 | 310 | ||
304 | import console, \ |
311 | import console, \ |
305 | con_start, 'START', \ |
312 | con_start, 'START', \ |
306 | con_init, 'con_init', \ |
313 | con_init, 'con_init', \ |
307 | con_write_asciiz, 'con_write_asciiz', \ |
314 | con_write_asciiz, 'con_write_asciiz', \ |
308 | con_printf, 'con_printf', \ |
315 | con_printf, 'con_printf', \ |
309 | con_exit, 'con_exit', \ |
316 | con_exit, 'con_exit', \ |
310 | con_gets, 'con_gets',\ |
317 | con_gets, 'con_gets',\ |
311 | con_cls, 'con_cls',\ |
318 | con_cls, 'con_cls',\ |
312 | con_getch2, 'con_getch2',\ |
319 | con_getch2, 'con_getch2',\ |
313 | con_set_cursor_pos, 'con_set_cursor_pos' |
320 | con_set_cursor_pos, 'con_set_cursor_pos' |
314 | 321 | ||
315 | socketnum dd ? |
322 | socketnum dd ? |
316 | 323 | ||
317 | icmp_packet: db 8 ; type |
324 | icmp_packet: db 8 ; type |
318 | db 0 ; code |
325 | db 0 ; code |
319 | dw 0 ; |
326 | dw 0 ; |
320 | .id dw IDENTIFIER ; identifier |
327 | .id dw IDENTIFIER ; identifier |
321 | .seq dw 0x0000 ; sequence number |
328 | .seq dw 0x0000 ; sequence number |
322 | .data db 'abcdefghijklmnopqrstuvwxyz012345' |
329 | .data db 'abcdefghijklmnopqrstuvwxyz012345' |
323 | .length = $ - icmp_packet |
330 | .length = $ - icmp_packet |
324 | 331 | ||
325 | I_END: |
332 | I_END: |
326 | 333 | ||
327 | buffer_ptr rb BUFFERSIZE |
334 | buffer_ptr rb BUFFERSIZE |
328 | 335 | ||
329 | s rb 1024 |
336 | s rb 1024 |
330 | rb 4096 ; stack |
337 | rb 4096 ; stack |
331 | mem: |
338 | mem: |