Changes in uspace/app/ping/ping.c [3e6a98c5:ccdc63e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/ping/ping.c
r3e6a98c5 rccdc63e 1 1 /* 2 * Copyright (c) 201 2Jiri Svoboda2 * Copyright (c) 2013 Jiri Svoboda 3 3 * All rights reserved. 4 4 * … … 37 37 #include <errno.h> 38 38 #include <fibril_synch.h> 39 #include <net/socket_codes.h> 40 #include <inet/dnsr.h> 41 #include <inet/addr.h> 39 42 #include <inet/inetping.h> 40 43 #include <io/console.h> 44 #include <getopt.h> 41 45 #include <stdio.h> 42 46 #include <stdlib.h> 47 #include <str.h> 48 #include <str_error.h> 43 49 #include <sys/types.h> 44 50 … … 51 57 #define PING_TIMEOUT (1000 * 1000) 52 58 59 typedef enum { 60 RECEIVED_NONE, 61 RECEIVED_SUCCESS, 62 RECEIVED_INTERRUPT 63 } received_t; 64 65 static received_t received; 66 static FIBRIL_CONDVAR_INITIALIZE(received_cv); 67 static FIBRIL_MUTEX_INITIALIZE(received_lock); 68 69 static bool quit = false; 70 static FIBRIL_CONDVAR_INITIALIZE(quit_cv); 71 static FIBRIL_MUTEX_INITIALIZE(quit_lock); 72 53 73 static int ping_ev_recv(inetping_sdu_t *); 54 55 static bool done = false;56 static FIBRIL_CONDVAR_INITIALIZE(done_cv);57 static FIBRIL_MUTEX_INITIALIZE(done_lock);58 74 59 75 static inetping_ev_ops_t ev_ops = { … … 61 77 }; 62 78 63 static inet_addr_t src_addr; 64 static inet_addr_t dest_addr; 65 66 static bool ping_repeat = false; 79 static addr32_t src; 80 static addr32_t dest; 81 82 static bool repeat_forever = false; 83 static size_t repeat_count = 1; 84 85 static const char *short_options = "rn:"; 67 86 68 87 static void print_syntax(void) 69 88 { 70 printf("syntax: " NAME " [-r] <addr>\n"); 71 } 72 73 static int addr_parse(const char *text, inet_addr_t *addr) 74 { 75 unsigned long a[4]; 76 char *cp = (char *)text; 77 int i; 78 79 for (i = 0; i < 3; i++) { 80 a[i] = strtoul(cp, &cp, 10); 81 if (*cp != '.') 82 return EINVAL; 83 ++cp; 84 } 85 86 a[3] = strtoul(cp, &cp, 10); 87 if (*cp != '\0') 88 return EINVAL; 89 90 addr->ipv4 = 0; 91 for (i = 0; i < 4; i++) { 92 if (a[i] > 255) 93 return EINVAL; 94 addr->ipv4 = (addr->ipv4 << 8) | a[i]; 95 } 96 97 return EOK; 98 } 99 100 static int addr_format(inet_addr_t *addr, char **bufp) 101 { 102 int rc; 103 104 rc = asprintf(bufp, "%d.%d.%d.%d", addr->ipv4 >> 24, 105 (addr->ipv4 >> 16) & 0xff, (addr->ipv4 >> 8) & 0xff, 106 addr->ipv4 & 0xff); 107 108 if (rc < 0) 109 return ENOMEM; 110 111 return EOK; 112 } 113 114 static void ping_signal_done(void) 115 { 116 fibril_mutex_lock(&done_lock); 117 done = true; 118 fibril_mutex_unlock(&done_lock); 119 fibril_condvar_broadcast(&done_cv); 89 printf("Syntax: %s [-n <count>|-r] <host>\n", NAME); 90 } 91 92 static void ping_signal_received(received_t value) 93 { 94 fibril_mutex_lock(&received_lock); 95 received = value; 96 fibril_mutex_unlock(&received_lock); 97 fibril_condvar_broadcast(&received_cv); 98 } 99 100 static void ping_signal_quit(void) 101 { 102 fibril_mutex_lock(&quit_lock); 103 quit = true; 104 fibril_mutex_unlock(&quit_lock); 105 fibril_condvar_broadcast(&quit_cv); 120 106 } 121 107 122 108 static int ping_ev_recv(inetping_sdu_t *sdu) 123 109 { 124 char *asrc, *adest; 125 int rc; 126 127 rc = addr_format(&sdu->src, &asrc); 110 inet_addr_t src_addr; 111 inet_addr_set(sdu->src, &src_addr); 112 113 inet_addr_t dest_addr; 114 inet_addr_set(sdu->dest, &dest_addr); 115 116 char *asrc; 117 int rc = inet_addr_format(&src_addr, &asrc); 128 118 if (rc != EOK) 129 119 return ENOMEM; 130 131 rc = addr_format(&sdu->dest, &adest); 120 121 char *adest; 122 rc = inet_addr_format(&dest_addr, &adest); 132 123 if (rc != EOK) { 133 124 free(asrc); 134 125 return ENOMEM; 135 126 } 127 136 128 printf("Received ICMP echo reply: from %s to %s, seq. no %u, " 137 129 "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size); 138 139 if (!ping_repeat) { 140 ping_signal_done(); 141 } 142 130 131 ping_signal_received(RECEIVED_SUCCESS); 132 143 133 free(asrc); 144 134 free(adest); … … 149 139 { 150 140 inetping_sdu_t sdu; 151 int rc; 152 153 sdu.src = src_addr; 154 sdu.dest = dest_addr; 141 142 sdu.src = src; 143 sdu.dest = dest; 155 144 sdu.seq_no = seq_no; 156 145 sdu.data = (void *) "foo"; 157 146 sdu.size = 3; 158 159 rc = inetping_send(&sdu); 160 if (rc != EOK) { 161 printf(NAME ": Failed sending echo request (%d).\n", rc); 162 return rc; 163 } 164 165 return EOK; 147 148 int rc = inetping_send(&sdu); 149 if (rc != EOK) 150 printf("Failed sending echo request: %s (%d).\n", 151 str_error(rc), rc); 152 153 return rc; 166 154 } 167 155 … … 169 157 { 170 158 uint16_t seq_no = 0; 171 159 160 while ((repeat_count--) || (repeat_forever)) { 161 fibril_mutex_lock(&received_lock); 162 received = RECEIVED_NONE; 163 fibril_mutex_unlock(&received_lock); 164 165 (void) ping_send(++seq_no); 166 167 fibril_mutex_lock(&received_lock); 168 int rc = fibril_condvar_wait_timeout(&received_cv, &received_lock, 169 PING_TIMEOUT); 170 received_t recv = received; 171 fibril_mutex_unlock(&received_lock); 172 173 if ((rc == ETIMEOUT) || (recv == RECEIVED_NONE)) 174 printf("Echo request timed out (seq. no %u)\n", seq_no); 175 176 if (recv == RECEIVED_INTERRUPT) 177 break; 178 179 if ((repeat_count > 0) || (repeat_forever)) { 180 fibril_mutex_lock(&received_lock); 181 rc = fibril_condvar_wait_timeout(&received_cv, &received_lock, 182 PING_DELAY); 183 recv = received; 184 fibril_mutex_unlock(&received_lock); 185 186 if (recv == RECEIVED_INTERRUPT) 187 break; 188 } 189 } 190 191 ping_signal_quit(); 192 return 0; 193 } 194 195 static int input_fibril(void *arg) 196 { 197 console_ctrl_t *con = console_init(stdin, stdout); 198 172 199 while (true) { 173 fibril_mutex_lock(&done_lock); 174 if (done) { 175 fibril_mutex_unlock(&done_lock); 176 return 0; 177 } 178 fibril_mutex_unlock(&done_lock); 179 180 (void) ping_send(++seq_no); 181 async_usleep(PING_DELAY); 182 } 183 200 cons_event_t ev; 201 if (!console_get_event(con, &ev)) 202 break; 203 204 if ((ev.type == CEV_KEY) && (ev.ev.key.type == KEY_PRESS) && 205 ((ev.ev.key.mods & (KM_ALT | KM_SHIFT)) == 0) && 206 ((ev.ev.key.mods & KM_CTRL) != 0)) { 207 /* Ctrl+key */ 208 if (ev.ev.key.key == KC_Q) { 209 ping_signal_received(RECEIVED_INTERRUPT); 210 break; 211 } 212 } 213 } 214 184 215 return 0; 185 216 } 186 217 187 static int input_fibril(void *arg) 188 { 189 console_ctrl_t *con; 190 kbd_event_t ev; 191 192 con = console_init(stdin, stdout); 193 printf("[Press Ctrl-Q to quit]\n"); 194 195 while (true) { 196 if (!console_get_kbd_event(con, &ev)) 218 int main(int argc, char *argv[]) 219 { 220 dnsr_hostinfo_t *hinfo = NULL; 221 char *asrc = NULL; 222 char *adest = NULL; 223 char *sdest = NULL; 224 225 int rc = inetping_init(&ev_ops); 226 if (rc != EOK) { 227 printf("Failed connecting to internet ping service: " 228 "%s (%d).\n", str_error(rc), rc); 229 goto error; 230 } 231 232 int c; 233 while ((c = getopt(argc, argv, short_options)) != -1) { 234 switch (c) { 235 case 'r': 236 repeat_forever = true; 197 237 break; 198 199 if (ev.type == KEY_PRESS && (ev.mods & (KM_ALT | KM_SHIFT)) == 200 0 && (ev.mods & KM_CTRL) != 0) { 201 /* Ctrl+key */ 202 if (ev.key == KC_Q) { 203 ping_signal_done(); 204 return 0; 238 case 'n': 239 rc = str_size_t(optarg, NULL, 10, true, &repeat_count); 240 if (rc != EOK) { 241 printf("Invalid repeat count.\n"); 242 print_syntax(); 243 goto error; 205 244 } 206 } 207 } 208 245 break; 246 default: 247 printf("Unknown option passed.\n"); 248 print_syntax(); 249 goto error; 250 } 251 } 252 253 if (optind >= argc) { 254 printf("IP address or host name not supplied.\n"); 255 print_syntax(); 256 goto error; 257 } 258 259 /* Parse destination address */ 260 inet_addr_t dest_addr; 261 rc = inet_addr_parse(argv[optind], &dest_addr); 262 if (rc != EOK) { 263 /* Try interpreting as a host name */ 264 rc = dnsr_name2host(argv[optind], &hinfo, AF_INET); 265 if (rc != EOK) { 266 printf("Error resolving host '%s'.\n", argv[optind]); 267 goto error; 268 } 269 270 dest_addr = hinfo->addr; 271 } 272 273 uint16_t af = inet_addr_get(&dest_addr, &dest, NULL); 274 if (af != AF_INET) { 275 printf("Destination '%s' is not an IPv4 address.\n", 276 argv[optind]); 277 goto error; 278 } 279 280 /* Determine source address */ 281 rc = inetping_get_srcaddr(dest, &src); 282 if (rc != EOK) { 283 printf("Failed determining source address.\n"); 284 goto error; 285 } 286 287 inet_addr_t src_addr; 288 inet_addr_set(src, &src_addr); 289 290 rc = inet_addr_format(&src_addr, &asrc); 291 if (rc != EOK) { 292 printf("Out of memory.\n"); 293 goto error; 294 } 295 296 rc = inet_addr_format(&dest_addr, &adest); 297 if (rc != EOK) { 298 printf("Out of memory.\n"); 299 goto error; 300 } 301 302 if (hinfo != NULL) { 303 rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest); 304 if (rc < 0) { 305 printf("Out of memory.\n"); 306 goto error; 307 } 308 } else { 309 sdest = adest; 310 adest = NULL; 311 } 312 313 printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n", 314 asrc, sdest); 315 316 fid_t fid = fibril_create(transmit_fibril, NULL); 317 if (fid == 0) { 318 printf("Failed creating transmit fibril.\n"); 319 goto error; 320 } 321 322 fibril_add_ready(fid); 323 324 fid = fibril_create(input_fibril, NULL); 325 if (fid == 0) { 326 printf("Failed creating input fibril.\n"); 327 goto error; 328 } 329 330 fibril_add_ready(fid); 331 332 fibril_mutex_lock(&quit_lock); 333 while (!quit) 334 fibril_condvar_wait(&quit_cv, &quit_lock); 335 fibril_mutex_unlock(&quit_lock); 336 337 free(asrc); 338 free(adest); 339 free(sdest); 340 dnsr_hostinfo_destroy(hinfo); 209 341 return 0; 210 } 211 212 int main(int argc, char *argv[]) 213 { 214 int rc; 215 int argi; 216 217 rc = inetping_init(&ev_ops); 218 if (rc != EOK) { 219 printf(NAME ": Failed connecting to internet ping service " 220 "(%d).\n", rc); 221 return 1; 222 } 223 224 argi = 1; 225 if (argi < argc && str_cmp(argv[argi], "-r") == 0) { 226 ping_repeat = true; 227 ++argi; 228 } else { 229 ping_repeat = false; 230 } 231 232 if (argc - argi != 1) { 233 print_syntax(); 234 return 1; 235 } 236 237 /* Parse destination address */ 238 rc = addr_parse(argv[argi], &dest_addr); 239 if (rc != EOK) { 240 printf(NAME ": Invalid address format.\n"); 241 print_syntax(); 242 return 1; 243 } 244 245 /* Determine source address */ 246 rc = inetping_get_srcaddr(&dest_addr, &src_addr); 247 if (rc != EOK) { 248 printf(NAME ": Failed determining source address.\n"); 249 return 1; 250 } 251 252 fid_t fid; 253 254 if (ping_repeat) { 255 fid = fibril_create(transmit_fibril, NULL); 256 if (fid == 0) { 257 printf(NAME ": Failed creating transmit fibril.\n"); 258 return 1; 259 } 260 261 fibril_add_ready(fid); 262 263 fid = fibril_create(input_fibril, NULL); 264 if (fid == 0) { 265 printf(NAME ": Failed creating input fibril.\n"); 266 return 1; 267 } 268 269 fibril_add_ready(fid); 270 } else { 271 ping_send(1); 272 } 273 274 fibril_mutex_lock(&done_lock); 275 rc = EOK; 276 while (!done && rc != ETIMEOUT) { 277 rc = fibril_condvar_wait_timeout(&done_cv, &done_lock, 278 ping_repeat ? 0 : PING_TIMEOUT); 279 } 280 fibril_mutex_unlock(&done_lock); 281 282 if (rc == ETIMEOUT) { 283 printf(NAME ": Echo request timed out.\n"); 284 return 1; 285 } 286 287 return 0; 342 343 error: 344 free(asrc); 345 free(adest); 346 free(sdest); 347 dnsr_hostinfo_destroy(hinfo); 348 return 1; 288 349 } 289 350
Note:
See TracChangeset
for help on using the changeset viewer.