aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2009-01-24 20:14:24 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2009-01-24 20:14:24 +0000
commit766c10c386f5f4c6e01fa2d2797f52809db25ef4 (patch)
tree75319f2d0d5a7744e2b2eace30fda23ca5a72e7e
parentfa65a3d78f32a305239494b8dc0f8ef14f83465d (diff)
downloadbusybox-w32-766c10c386f5f4c6e01fa2d2797f52809db25ef4.tar.gz
busybox-w32-766c10c386f5f4c6e01fa2d2797f52809db25ef4.tar.bz2
busybox-w32-766c10c386f5f4c6e01fa2d2797f52809db25ef4.zip
traceroute: rewrite. Do not emit raw IP packets, instead send UDP or ICMP
packets and rely on the kernel to form IP headers, select source IP and interface. Doing it in traceroute wasn't working too good, and was bloating it. function old new delta freehostinfo 29 - -29 setsin 30 - -30 in_cksum 57 - -57 gethostinfo 165 - -165 ifaddrlist 364 - -364 traceroute_main 3713 2951 -762 ------------------------------------------------------------------------------ (add/remove: 0/5 grow/shrink: 0/1 up/down: 0/-1407) Total: -1407 bytes
-rw-r--r--networking/traceroute.c725
1 files changed, 166 insertions, 559 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 958299aaa..244a74d6d 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -215,13 +215,6 @@
215#include "libbb.h" 215#include "libbb.h"
216#include "inet_common.h" 216#include "inet_common.h"
217 217
218
219/*
220 * Definitions for internet protocol version 4.
221 * Per RFC 791, September 1981.
222 */
223#define IPVERSION 4
224
225#ifndef IPPROTO_ICMP 218#ifndef IPPROTO_ICMP
226# define IPPROTO_ICMP 1 219# define IPPROTO_ICMP 1
227#endif 220#endif
@@ -229,122 +222,57 @@
229# define IPPROTO_IP 0 222# define IPPROTO_IP 0
230#endif 223#endif
231 224
232/* 225/* Keep in sync with getopt32 call! */
233 * Overlay for ip header used by other protocols (tcp, udp). 226enum {
234 */ 227 OPT_DONT_FRAGMNT = (1 << 0), /* F */
235struct ipovly { 228 OPT_USE_ICMP = (1 << 1) * ENABLE_FEATURE_TRACEROUTE_USE_ICMP, /* I */
236 unsigned char ih_x1[9]; /* (unused) */ 229 OPT_TTL_FLAG = (1 << 2), /* l */
237 unsigned char ih_pr; /* protocol */ 230 OPT_ADDR_NUM = (1 << 3), /* n */
238 short ih_len; /* protocol length */ 231 OPT_BYPASS_ROUTE = (1 << 4), /* r */
239 struct in_addr ih_src; /* source internet address */ 232 OPT_DEBUG = (1 << 5), /* d */
240 struct in_addr ih_dst; /* destination internet address */ 233 OPT_VERBOSE = (1 << 6) * ENABLE_FEATURE_TRACEROUTE_VERBOSE, /* v */
234 OPT_IP_CHKSUM = (1 << 7), /* x */
235 OPT_TOS = (1 << 8), /* t */
236 OPT_DEVICE = (1 << 9), /* i */
237 OPT_MAX_TTL = (1 << 10), /* m */
238 OPT_PORT = (1 << 11), /* p */
239 OPT_NPROBES = (1 << 12), /* q */
240 OPT_SOURCE = (1 << 13), /* s */
241 OPT_WAITTIME = (1 << 14), /* w */
242 OPT_PAUSE_MS = (1 << 15), /* z */
243 OPT_FIRST_TTL = (1 << 16), /* f */
241}; 244};
245#define verbose (option_mask32 & OPT_VERBOSE)
242 246
243/* 247enum {
244 * UDP kernel structures and variables. 248 SIZEOF_ICMP_HDR = 8,
245 */ 249 rcvsock = 3, /* receive (icmp) socket file descriptor */
246struct udpiphdr { 250 sndsock = 4, /* send (udp/icmp) socket file descriptor */
247 struct ipovly ui_i; /* overlaid ip structure */
248 struct udphdr ui_u; /* udp header */
249};
250#define ui_next ui_i.ih_next
251#define ui_prev ui_i.ih_prev
252#define ui_x1 ui_i.ih_x1
253#define ui_pr ui_i.ih_pr
254#define ui_len ui_i.ih_len
255#define ui_src ui_i.ih_src
256#define ui_dst ui_i.ih_dst
257#define ui_sport ui_u.uh_sport
258#define ui_dport ui_u.uh_dport
259#define ui_ulen ui_u.uh_ulen
260#define ui_sum ui_u.uh_sum
261
262
263/* Host name and address list */
264struct hostinfo {
265 char *name;
266 int n;
267 uint32_t *addrs;
268}; 251};
269 252
270/* Data section of the probe packet */ 253/* Data section of the probe packet */
271typedef struct outdata { 254struct outdata_t {
272 unsigned char seq; /* sequence number of this packet */ 255 unsigned char seq; /* sequence number of this packet */
273 unsigned char ttl; /* ttl packet left with */ 256 unsigned char ttl; /* ttl packet left with */
274// UNUSED. Retaining to have the same packet size. 257// UNUSED. Retaining to have the same packet size.
275 struct timeval tv_UNUSED PACKED; /* time packet left */ 258 struct timeval tv_UNUSED PACKED; /* time packet left */
276} outdata_t;
277
278struct IFADDRLIST {
279 uint32_t addr;
280 char device[sizeof(struct ifreq)];
281}; 259};
282 260
283
284/* Keep in sync with getopt32 call! */
285#define OPT_DONT_FRAGMNT (1<<0) /* F */
286#define OPT_USE_ICMP (1<<1) /* I */
287#define OPT_TTL_FLAG (1<<2) /* l */
288#define OPT_ADDR_NUM (1<<3) /* n */
289#define OPT_BYPASS_ROUTE (1<<4) /* r */
290#define OPT_DEBUG (1<<5) /* d */
291#define OPT_VERBOSE (1<<6) /* v */
292#define OPT_IP_CHKSUM (1<<7) /* x */
293#define OPT_TOS (1<<8) /* t */
294#define OPT_DEVICE (1<<9) /* i */
295#define OPT_MAX_TTL (1<<10) /* m */
296#define OPT_PORT (1<<11) /* p */
297#define OPT_NPROBES (1<<12) /* q */
298#define OPT_SOURCE (1<<13) /* s */
299#define OPT_WAITTIME (1<<14) /* w */
300#define OPT_PAUSE_MS (1<<15) /* z */
301#define OPT_FIRST_TTL (1<<16) /* f */
302
303#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
304/* use icmp echo instead of udp packets */
305#define useicmp (option_mask32 & OPT_USE_ICMP)
306#endif
307#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
308#define verbose (option_mask32 & OPT_VERBOSE)
309#endif
310#define nflag (option_mask32 & OPT_ADDR_NUM)
311
312
313struct globals { 261struct globals {
314 struct ip *outip; /* last output (udp) packet */ 262 struct ip *outip;
315 struct udphdr *outudp; /* last output (udp) packet */ 263 struct outdata_t *outdata;
316 struct outdata *outdata; /* last output (udp) packet */ 264 len_and_sockaddr *dest_lsa;
317
318#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
319 struct icmp *outicmp; /* last output (icmp) packet */
320#endif
321
322 int rcvsock; /* receive (icmp) socket file descriptor */
323 int sndsock; /* send (udp/icmp) socket file descriptor */
324
325 int packlen; /* total length of packet */ 265 int packlen; /* total length of packet */
326 int minpacket; /* min ip packet size */
327 int maxpacket; // 32 * 1024; /* max ip packet size */
328 int pmtu; /* Path MTU Discovery (RFC1191) */ 266 int pmtu; /* Path MTU Discovery (RFC1191) */
329
330 char *hostname;
331
332 uint16_t ident; 267 uint16_t ident;
333 uint16_t port; // 32768 + 666; /* start udp dest port # for probe packets */ 268 uint16_t port; // 32768 + 666; /* start udp dest port # for probe packets */
334
335 int waittime; // 5; /* time to wait for response (in seconds) */ 269 int waittime; // 5; /* time to wait for response (in seconds) */
336 int doipcksum; // 1; /* calculate ip checksums by default */
337
338#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 270#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
339 int optlen; /* length of ip options */ 271 int optlen; /* length of ip options */
340#else 272#else
341#define optlen 0 273#define optlen 0
342#endif 274#endif
343 275 unsigned char recv_pkt[512]; /* last inbound (icmp) packet */
344 struct sockaddr_storage whereto; /* Who to try to reach */
345 struct sockaddr_storage wherefrom; /* Who we are */
346 /* last inbound (icmp) packet */
347 unsigned char packet[512];
348#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 276#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
349 /* Maximum number of gateways (include room for one noop) */ 277 /* Maximum number of gateways (include room for one noop) */
350#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t))) 278#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
@@ -355,206 +283,39 @@ struct globals {
355 283
356#define G (*ptr_to_globals) 284#define G (*ptr_to_globals)
357#define outip (G.outip ) 285#define outip (G.outip )
358#define outudp (G.outudp )
359#define outdata (G.outdata ) 286#define outdata (G.outdata )
360#define outicmp (G.outicmp ) 287#define dest_lsa (G.dest_lsa )
361#define rcvsock (G.rcvsock )
362#define sndsock (G.sndsock )
363#define packlen (G.packlen ) 288#define packlen (G.packlen )
364#define minpacket (G.minpacket)
365#define maxpacket (G.maxpacket)
366#define pmtu (G.pmtu ) 289#define pmtu (G.pmtu )
367#define hostname (G.hostname )
368#define ident (G.ident ) 290#define ident (G.ident )
369#define port (G.port ) 291#define port (G.port )
370#define waittime (G.waittime ) 292#define waittime (G.waittime )
371#define doipcksum (G.doipcksum)
372#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 293#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
373#define optlen (G.optlen ) 294# define optlen (G.optlen )
374#endif 295#endif
375#define packet (G.packet ) 296#define recv_pkt (G.recv_pkt )
376#define whereto (G.whereto )
377#define wherefrom (G.wherefrom)
378#define gwlist (G.gwlist ) 297#define gwlist (G.gwlist )
379#define INIT_G() do { \ 298#define INIT_G() do { \
380 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 299 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
381 maxpacket = 32 * 1024; \
382 port = 32768 + 666; \ 300 port = 32768 + 666; \
383 waittime = 5; \ 301 waittime = 5; \
384 doipcksum = 1; \
385} while (0) 302} while (0)
386 303
304#define outicmp ((struct icmp *)(outip + 1))
305#define outudp ((struct udphdr *)(outip + 1))
387 306
388/*
389 * Return the interface list
390 */
391static int
392ifaddrlist(struct IFADDRLIST **ipaddrp)
393{
394 enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) };
395
396 int fd, nipaddr;
397#ifdef HAVE_SOCKADDR_SA_LEN
398 int n;
399#endif
400 struct ifreq *ifrp, *ifend, *ifnext;
401 struct sockaddr_in *addr_sin;
402 struct IFADDRLIST *al;
403 struct ifconf ifc;
404 struct ifreq ifr;
405 /* Was on stack, but 32k is a bit too much: */
406 struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0]));
407 struct IFADDRLIST *st_ifaddrlist;
408
409 fd = xsocket(AF_INET, SOCK_DGRAM, 0);
410
411 ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]);
412 ifc.ifc_buf = (caddr_t)ibuf;
413
414 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
415 || ifc.ifc_len < (int)sizeof(struct ifreq)
416 ) {
417 if (errno == EINVAL)
418 bb_error_msg_and_die(
419 "SIOCGIFCONF: ifreq struct too small (%u bytes)",
420 (unsigned)(IFREQ_BUFSIZE * sizeof(ibuf[0])));
421 bb_perror_msg_and_die("SIOCGIFCONF");
422 }
423 ifrp = ibuf;
424 ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
425
426 nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
427 st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST));
428 al = st_ifaddrlist;
429 nipaddr = 0;
430
431 for (; ifrp < ifend; ifrp = ifnext) {
432#ifdef HAVE_SOCKADDR_SA_LEN
433 n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
434 if (n < sizeof(*ifrp))
435 ifnext = ifrp + 1;
436 else
437 ifnext = (struct ifreq *)((char *)ifrp + n);
438 if (ifrp->ifr_addr.sa_family != AF_INET)
439 continue;
440#else
441 ifnext = ifrp + 1;
442#endif
443 /*
444 * Need a template to preserve address info that is
445 * used below to locate the next entry. (Otherwise,
446 * SIOCGIFFLAGS stomps over it because the requests
447 * are returned in a union.)
448 */
449 strncpy_IFNAMSIZ(ifr.ifr_name, ifrp->ifr_name);
450 if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
451 if (errno == ENXIO)
452 continue;
453 bb_perror_msg_and_die("SIOCGIFFLAGS: %.*s",
454 (int)sizeof(ifr.ifr_name), ifr.ifr_name);
455 }
456
457 /* Must be up */
458 if ((ifr.ifr_flags & IFF_UP) == 0)
459 continue;
460
461 safe_strncpy(al->device, ifr.ifr_name, sizeof(ifr.ifr_name) + 1);
462#ifdef sun
463 /* Ignore sun virtual interfaces */
464 if (strchr(al->device, ':') != NULL)
465 continue;
466#endif
467 ioctl_or_perror_and_die(fd, SIOCGIFADDR, (char *)&ifr,
468 "SIOCGIFADDR: %s", al->device);
469
470 addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
471 al->addr = addr_sin->sin_addr.s_addr;
472 ++al;
473 ++nipaddr;
474 }
475 if (nipaddr == 0)
476 bb_error_msg_and_die("can't find any network interfaces");
477
478 free(ibuf);
479 close(fd);
480 *ipaddrp = st_ifaddrlist;
481 return nipaddr;
482}
483
484static void
485setsin(struct sockaddr_in *addr_sin, uint32_t addr)
486{
487 memset(addr_sin, 0, sizeof(*addr_sin));
488#ifdef HAVE_SOCKADDR_SA_LEN
489 addr_sin->sin_len = sizeof(*addr_sin);
490#endif
491 addr_sin->sin_family = AF_INET;
492 addr_sin->sin_addr.s_addr = addr;
493}
494
495/*
496 * Return the source address for the given destination address
497 */
498static void
499findsaddr(const struct sockaddr_in *to, struct sockaddr_in *from)
500{
501 int i, n;
502 FILE *f;
503 uint32_t mask;
504 uint32_t dest, tmask;
505 struct IFADDRLIST *al;
506 char buf[256], tdevice[256], device[256];
507
508 f = xfopen_for_read("/proc/net/route");
509
510 /* Find the appropriate interface */
511 n = 0;
512 mask = 0;
513 device[0] = '\0';
514 while (fgets(buf, sizeof(buf), f) != NULL) {
515 ++n;
516 if (n == 1 && strncmp(buf, "Iface", 5) == 0)
517 continue;
518 i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
519 tdevice, &dest, &tmask);
520 if (i != 3)
521 bb_error_msg_and_die("junk in buffer");
522 if ((to->sin_addr.s_addr & tmask) == dest
523 && (tmask > mask || mask == 0)
524 ) {
525 mask = tmask;
526 strcpy(device, tdevice);
527 }
528 }
529 fclose(f);
530
531 if (device[0] == '\0')
532 bb_error_msg_and_die("can't find interface");
533
534 /* Get the interface address list */
535 n = ifaddrlist(&al);
536
537 /* Find our appropriate source address */
538 for (i = n; i > 0; --i, ++al)
539 if (strcmp(device, al->device) == 0)
540 break;
541 if (i <= 0)
542 bb_error_msg_and_die("can't find interface %s", device);
543
544 setsin(from, al->addr);
545}
546 307
547static int 308static int
548wait_for_reply(int sock, struct sockaddr_in *fromp) 309wait_for_reply(struct sockaddr_in *fromp)
549{ 310{
550 struct pollfd pfd[1]; 311 struct pollfd pfd[1];
551 int cc = 0; 312 int cc = 0;
552 socklen_t fromlen = sizeof(*fromp); 313 socklen_t fromlen = sizeof(*fromp);
553 314
554 pfd[0].fd = sock; 315 pfd[0].fd = rcvsock;
555 pfd[0].events = POLLIN; 316 pfd[0].events = POLLIN;
556 if (safe_poll(pfd, 1, waittime * 1000) > 0) 317 if (safe_poll(pfd, 1, waittime * 1000) > 0)
557 cc = recvfrom(sock, packet, sizeof(packet), 0, 318 cc = recvfrom(rcvsock, recv_pkt, sizeof(recv_pkt), 0,
558 (struct sockaddr *)fromp, &fromlen); 319 (struct sockaddr *)fromp, &fromlen);
559 return cc; 320 return cc;
560} 321}
@@ -595,22 +356,8 @@ in_cksum(uint16_t *addr, int len)
595static void 356static void
596send_probe(int seq, int ttl) 357send_probe(int seq, int ttl)
597{ 358{
598 int cc; 359 int len, res;
599 struct udpiphdr *ui, *oui; 360 void *out;
600 struct ip tip;
601
602 outip->ip_ttl = ttl;
603 outip->ip_id = htons(ident + seq);
604
605 /*
606 * In most cases, the kernel will recalculate the ip checksum.
607 * But we must do it anyway so that the udp checksum comes out right.
608 */
609 if (doipcksum) {
610 outip->ip_sum = in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
611 if (outip->ip_sum == 0)
612 outip->ip_sum = 0xffff;
613 }
614 361
615 /* Payload */ 362 /* Payload */
616 outdata->seq = seq; 363 outdata->seq = seq;
@@ -618,39 +365,15 @@ send_probe(int seq, int ttl)
618// UNUSED: was storing gettimeofday's result there, but never ever checked it 365// UNUSED: was storing gettimeofday's result there, but never ever checked it
619 /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/ 366 /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
620 367
621#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 368 if (option_mask32 & OPT_USE_ICMP) {
622 if (useicmp)
623 outicmp->icmp_seq = htons(seq); 369 outicmp->icmp_seq = htons(seq);
624 else
625#endif
626 outudp->dest = htons(port + seq);
627 370
628#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
629 if (useicmp) {
630 /* Always calculate checksum for icmp packets */ 371 /* Always calculate checksum for icmp packets */
631 outicmp->icmp_cksum = 0; 372 outicmp->icmp_cksum = 0;
632 outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp, 373 outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp,
633 packlen - (sizeof(*outip) + optlen)); 374 packlen - (sizeof(*outip) + optlen));
634 if (outicmp->icmp_cksum == 0) 375 if (outicmp->icmp_cksum == 0)
635 outicmp->icmp_cksum = 0xffff; 376 outicmp->icmp_cksum = 0xffff;
636 } else
637#endif
638 if (doipcksum) {
639 /* Checksum (we must save and restore ip header) */
640 tip = *outip;
641 ui = (struct udpiphdr *)outip;
642 oui = (struct udpiphdr *)&tip;
643 /* Easier to zero and put back things that are ok */
644 memset(ui, 0, sizeof(ui->ui_i));
645 ui->ui_src = oui->ui_src;
646 ui->ui_dst = oui->ui_dst;
647 ui->ui_pr = oui->ui_pr;
648 ui->ui_len = outudp->len;
649 outudp->check = 0;
650 outudp->check = in_cksum((uint16_t *)ui, packlen);
651 if (outudp->check == 0)
652 outudp->check = 0xffff;
653 *outip = tip;
654 } 377 }
655 378
656//BUG! verbose is (x & OPT_VERBOSE), not a counter! 379//BUG! verbose is (x & OPT_VERBOSE), not a counter!
@@ -679,17 +402,25 @@ send_probe(int seq, int ttl)
679 } 402 }
680#endif 403#endif
681 404
682#if !defined(IP_HDRINCL) && defined(IP_TTL) 405#if defined(IP_TTL)
683 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL, 406 if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
684 (char *)&ttl, sizeof(ttl)) < 0) { 407 (char *)&ttl, sizeof(ttl)) < 0) {
685 bb_perror_msg_and_die("setsockopt ttl %d", ttl); 408 bb_perror_msg_and_die("setsockopt ttl %d", ttl);
686 } 409 }
687#endif 410#endif
688 411
689 cc = xsendto(sndsock, outip, packlen, 412 len = packlen - sizeof(*outip);
690 (struct sockaddr *)&whereto, sizeof(whereto)); 413 if (option_mask32 & OPT_USE_ICMP)
691 if (cc != packlen) { 414 out = outicmp;
692 bb_info_msg("sent %s %d octets, ret=%d", hostname, packlen, cc); 415 else {
416 out = outdata;
417 len -= sizeof(*outudp);
418 set_nport(dest_lsa, htons(port + seq));
419 }
420 res = xsendto(sndsock, out, len,
421 (struct sockaddr *)&dest_lsa->u.sa, dest_lsa->len);
422 if (res != len) {
423 bb_info_msg("sent %d octets, ret=%d", len, res);
693 } 424 }
694} 425}
695 426
@@ -716,18 +447,18 @@ pr_type(unsigned char t)
716#endif 447#endif
717 448
718#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE 449#if !ENABLE_FEATURE_TRACEROUTE_VERBOSE
719#define packet_ok(buf, cc, from, seq) \ 450#define packet_ok(cc, from, seq) \
720 packet_ok(buf, cc, seq) 451 packet_ok(cc, seq)
721#endif 452#endif
722static int 453static int
723packet_ok(const unsigned char *buf, int cc, const struct sockaddr_in *from, int seq) 454packet_ok(int cc, const struct sockaddr_in *from, int seq)
724{ 455{
725 const struct icmp *icp; 456 const struct icmp *icp;
726 unsigned char type, code; 457 unsigned char type, code;
727 int hlen; 458 int hlen;
728 const struct ip *ip; 459 const struct ip *ip;
729 460
730 ip = (struct ip *) buf; 461 ip = (struct ip *) recv_pkt;
731 hlen = ip->ip_hl << 2; 462 hlen = ip->ip_hl << 2;
732 if (cc < hlen + ICMP_MINLEN) { 463 if (cc < hlen + ICMP_MINLEN) {
733#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 464#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
@@ -738,7 +469,7 @@ packet_ok(const unsigned char *buf, int cc, const struct sockaddr_in *from, int
738 return 0; 469 return 0;
739 } 470 }
740 cc -= hlen; 471 cc -= hlen;
741 icp = (struct icmp *)(buf + hlen); 472 icp = (struct icmp *)(recv_pkt + hlen);
742 type = icp->icmp_type; 473 type = icp->icmp_type;
743 code = icp->icmp_code; 474 code = icp->icmp_code;
744 /* Path MTU Discovery (RFC1191) */ 475 /* Path MTU Discovery (RFC1191) */
@@ -755,33 +486,37 @@ packet_ok(const unsigned char *buf, int cc, const struct sockaddr_in *from, int
755 486
756 hip = &icp->icmp_ip; 487 hip = &icp->icmp_ip;
757 hlen = hip->ip_hl << 2; 488 hlen = hip->ip_hl << 2;
758#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 489 if (option_mask32 & OPT_USE_ICMP) {
759 if (useicmp) {
760 struct icmp *hicmp; 490 struct icmp *hicmp;
761 491
762 /* XXX */ 492 /* XXX */
763 if (type == ICMP_ECHOREPLY && 493 if (type == ICMP_ECHOREPLY
764 icp->icmp_id == htons(ident) && 494 && icp->icmp_id == htons(ident)
765 icp->icmp_seq == htons(seq)) 495 && icp->icmp_seq == htons(seq)
496 ) {
766 return -2; 497 return -2;
498 }
767 499
768 hicmp = (struct icmp *)((unsigned char *)hip + hlen); 500 hicmp = (struct icmp *)((unsigned char *)hip + hlen);
769 /* XXX 8 is a magic number */ 501 if (hlen + SIZEOF_ICMP_HDR <= cc
770 if (hlen + 8 <= cc && 502 && hip->ip_p == IPPROTO_ICMP
771 hip->ip_p == IPPROTO_ICMP && 503 && hicmp->icmp_id == htons(ident)
772 hicmp->icmp_id == htons(ident) && 504 && hicmp->icmp_seq == htons(seq)
773 hicmp->icmp_seq == htons(seq)) 505 ) {
774 return (type == ICMP_TIMXCEED ? -1 : code + 1); 506 return (type == ICMP_TIMXCEED ? -1 : code + 1);
775 } else 507 }
776#endif 508 } else {
777 { 509 up = (struct udphdr *)((char *)hip + hlen);
778 up = (struct udphdr *)((unsigned char *)hip + hlen); 510 if (hlen + 12 <= cc
779 /* XXX 8 is a magic number */ 511 && hip->ip_p == IPPROTO_UDP
780 if (hlen + 12 <= cc && 512// Off: since we do not form the entire IP packet,
781 hip->ip_p == IPPROTO_UDP && 513// but defer it to kernel, we can't set source port,
782 up->source == htons(ident) && 514// and thus can't check it here in the reply
783 up->dest == htons(port + seq)) 515 /* && up->source == htons(ident) */
516 && up->dest == htons(port + seq)
517 ) {
784 return (type == ICMP_TIMXCEED ? -1 : code + 1); 518 return (type == ICMP_TIMXCEED ? -1 : code + 1);
519 }
785 } 520 }
786 } 521 }
787#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 522#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
@@ -812,85 +547,31 @@ print_inetname(const struct sockaddr_in *from)
812 const char *ina; 547 const char *ina;
813 548
814 ina = inet_ntoa(from->sin_addr); 549 ina = inet_ntoa(from->sin_addr);
815 if (nflag) 550 if (option_mask32 & OPT_ADDR_NUM)
816 printf(" %s", ina); 551 printf(" %s", ina);
817 else { 552 else {
818 char *n = NULL; 553 char *n = NULL;
819 if (from->sin_addr.s_addr != INADDR_ANY) 554 if (from->sin_addr.s_addr != INADDR_ANY)
820 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from); 555 n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
821 printf(" %s (%s)", (n ? n : ina), ina); 556 printf(" %s (%s)", (n ? n : ina), ina);
822 free(n); 557 free(n);
823 } 558 }
824} 559}
825 560
826static void 561static void
827print(const unsigned char *buf, int cc, const struct sockaddr_in *from) 562print(int cc, const struct sockaddr_in *from)
828{ 563{
829 const struct ip *ip;
830 int hlen;
831
832 ip = (struct ip *) buf;
833 hlen = ip->ip_hl << 2;
834 cc -= hlen;
835
836 print_inetname(from); 564 print_inetname(from);
837#if ENABLE_FEATURE_TRACEROUTE_VERBOSE 565 if (verbose) {
838 if (verbose) 566 const struct ip *ip;
839 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst)); 567 int hlen;
840#endif
841}
842 568
843static struct hostinfo * 569 ip = (struct ip *) recv_pkt;
844gethostinfo(const char *host) 570 hlen = ip->ip_hl << 2;
845{ 571 cc -= hlen;
846 int n; 572 printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
847 struct hostent *hp;
848 struct hostinfo *hi;
849 char **p;
850 uint32_t addr, *ap;
851
852 hi = xzalloc(sizeof(*hi));
853 addr = inet_addr(host);
854 if (addr != 0xffffffff) {
855 hi->name = xstrdup(host);
856 hi->n = 1;
857 hi->addrs = xzalloc(sizeof(hi->addrs[0]));
858 hi->addrs[0] = addr;
859 return hi;
860 } 573 }
861
862 hp = xgethostbyname(host);
863 if (hp->h_addrtype != AF_INET || hp->h_length != 4)
864 bb_perror_msg_and_die("bad host %s", host);
865 hi->name = xstrdup(hp->h_name);
866 for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
867 continue;
868 hi->n = n;
869 hi->addrs = xzalloc(n * sizeof(hi->addrs[0]));
870 for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
871 memcpy(ap, *p, sizeof(*ap));
872 return hi;
873}
874
875static void
876freehostinfo(struct hostinfo *hi)
877{
878 free(hi->name);
879 free(hi->addrs);
880 free(hi);
881}
882
883#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
884static void
885getaddr(uint32_t *ap, const char *host)
886{
887 struct hostinfo *hi;
888
889 hi = gethostinfo(host);
890 *ap = hi->addrs[0];
891 freehostinfo(hi);
892} 574}
893#endif
894 575
895static void 576static void
896print_delta_ms(unsigned t1p, unsigned t2p) 577print_delta_ms(unsigned t1p, unsigned t2p)
@@ -900,46 +581,38 @@ print_delta_ms(unsigned t1p, unsigned t2p)
900} 581}
901 582
902/* 583/*
903"Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n" 584Usage: [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]
904"\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n" 585[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]
905"\t[-w waittime] [-z pausemsecs] host [packetlen]" 586[-w waittime] [-z pausemsecs] host [packetlen]"
906*/ 587*/
907 588
908int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 589int traceroute_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
909int traceroute_main(int argc, char **argv) 590int traceroute_main(int argc, char **argv)
910{ 591{
911 unsigned char *outp; 592 int minpacket;
912 struct sockaddr_in *from; 593 int ttl, i;
913 struct sockaddr_in *to;
914 struct hostinfo *hi;
915 int ttl, probe, i;
916 int seq = 0; 594 int seq = 0;
917 int tos = 0; 595 int tos = 0;
918 char *tos_str; 596 int max_ttl = 30;
919 char *source; 597 int nprobes = 3;
598 int first_ttl = 1;
599 unsigned pausemsecs = 0;
920 unsigned op; 600 unsigned op;
921#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 601 char *source;
922 int lsrr = 0;
923#endif
924 struct IFADDRLIST *al;
925 char *device; 602 char *device;
926 int max_ttl = 30; 603 char *tos_str;
927 char *max_ttl_str; 604 char *max_ttl_str;
928 char *port_str; 605 char *port_str;
929 int nprobes = 3;
930 char *nprobes_str; 606 char *nprobes_str;
931 char *waittime_str; 607 char *waittime_str;
932 unsigned pausemsecs = 0;
933 char *pausemsecs_str; 608 char *pausemsecs_str;
934 int first_ttl = 1;
935 char *first_ttl_str; 609 char *first_ttl_str;
936#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 610#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
937 llist_t *source_route_list = NULL; 611 llist_t *source_route_list = NULL;
612 int lsrr = 0;
938#endif 613#endif
939 614
940 INIT_G(); 615 INIT_G();
941 from = (struct sockaddr_in *)&wherefrom;
942 to = (struct sockaddr_in *)&whereto;
943 616
944#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 617#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
945 opt_complementary = "x-x:g::"; 618 opt_complementary = "x-x:g::";
@@ -958,10 +631,10 @@ int traceroute_main(int argc, char **argv)
958#endif 631#endif
959 ); 632 );
960 633
961 if (op & OPT_IP_CHKSUM) { 634#if 0 /* IGNORED */
962 doipcksum = 0; 635 if (op & OPT_IP_CHKSUM)
963 bb_error_msg("warning: ip checksums disabled"); 636 bb_error_msg("warning: ip checksums disabled");
964 } 637#endif
965 if (op & OPT_TOS) 638 if (op & OPT_TOS)
966 tos = xatou_range(tos_str, 0, 255); 639 tos = xatou_range(tos_str, 0, 255);
967 if (op & OPT_MAX_TTL) 640 if (op & OPT_MAX_TTL)
@@ -988,42 +661,33 @@ int traceroute_main(int argc, char **argv)
988#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 661#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
989 if (source_route_list) { 662 if (source_route_list) {
990 while (source_route_list) { 663 while (source_route_list) {
664 len_and_sockaddr *lsa;
665
991 if (lsrr >= NGATEWAYS) 666 if (lsrr >= NGATEWAYS)
992 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS); 667 bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
993 getaddr(gwlist + lsrr, llist_pop(&source_route_list)); 668 lsa = xhost_and_af2sockaddr(llist_pop(&source_route_list), 0, AF_INET);
669 gwlist[lsrr] = lsa->u.sin.sin_addr.s_addr;
670 free(lsa);
994 ++lsrr; 671 ++lsrr;
995 } 672 }
996 optlen = (lsrr + 1) * sizeof(gwlist[0]); 673 optlen = (lsrr + 1) * sizeof(gwlist[0]);
997 } 674 }
998#endif 675#endif
999 676
1000 minpacket = sizeof(*outip) + sizeof(*outdata) + optlen; 677 minpacket = sizeof(*outip) + SIZEOF_ICMP_HDR + sizeof(*outdata) + optlen;
1001 678 if (!(op & OPT_USE_ICMP))
1002#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP 679 minpacket += sizeof(*outudp) - SIZEOF_ICMP_HDR;
1003 if (useicmp) 680 packlen = minpacket;
1004 minpacket += 8; /* XXX magic number */
1005 else
1006#endif
1007 minpacket += sizeof(*outudp);
1008 packlen = minpacket; /* minimum sized packet */
1009 681
1010 /* Process destination and optional packet size */ 682 /* Process destination and optional packet size */
1011 argv += optind; 683 argv += optind;
1012 argc -= optind; 684 argc -= optind;
1013 switch (argc) { 685 switch (argc) {
1014 case 2: 686 case 2:
1015 packlen = xatoul_range(argv[1], minpacket, maxpacket); 687 packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
1016 /* Fall through */ 688 /* Fall through */
1017 case 1: 689 case 1:
1018 hostname = argv[0]; 690 dest_lsa = xhost2sockaddr(argv[0], port);
1019 hi = gethostinfo(hostname);
1020 setsin(to, hi->addrs[0]);
1021 if (hi->n > 1)
1022 bb_error_msg("warning: %s has multiple addresses; using %s",
1023 hostname, inet_ntoa(to->sin_addr));
1024 hostname = hi->name;
1025 hi->name = NULL;
1026 freehostinfo(hi);
1027 break; 691 break;
1028 default: 692 default:
1029 bb_show_usage(); 693 bb_show_usage();
@@ -1032,8 +696,7 @@ int traceroute_main(int argc, char **argv)
1032 /* Ensure the socket fds won't be 0, 1 or 2 */ 696 /* Ensure the socket fds won't be 0, 1 or 2 */
1033 bb_sanitize_stdio(); 697 bb_sanitize_stdio();
1034 698
1035 rcvsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); 699 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), rcvsock);
1036
1037#if TRACEROUTE_SO_DEBUG 700#if TRACEROUTE_SO_DEBUG
1038 if (op & OPT_DEBUG) 701 if (op & OPT_DEBUG)
1039 setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, 702 setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
@@ -1043,15 +706,17 @@ int traceroute_main(int argc, char **argv)
1043 setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, 706 setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
1044 &const_int_1, sizeof(const_int_1)); 707 &const_int_1, sizeof(const_int_1));
1045 708
1046 sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW); 709 if (op & OPT_USE_ICMP)
1047 710 xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock);
711 else
712 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
1048#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE 713#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
1049#if defined(IP_OPTIONS) 714#if defined(IP_OPTIONS)
1050 if (lsrr > 0) { 715 if (lsrr > 0) {
1051 unsigned char optlist[MAX_IPOPTLEN]; 716 unsigned char optlist[MAX_IPOPTLEN];
1052 717
1053 /* final hop */ 718 /* final hop */
1054 gwlist[lsrr] = to->sin_addr.s_addr; 719 gwlist[lsrr] = dest_lsa->u.sin.sin_addr.s_addr;
1055 ++lsrr; 720 ++lsrr;
1056 721
1057 /* force 4 byte alignment */ 722 /* force 4 byte alignment */
@@ -1071,24 +736,20 @@ int traceroute_main(int argc, char **argv)
1071 } 736 }
1072#endif /* IP_OPTIONS */ 737#endif /* IP_OPTIONS */
1073#endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */ 738#endif /* CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE */
1074
1075#ifdef SO_SNDBUF 739#ifdef SO_SNDBUF
1076 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { 740 if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
1077 bb_perror_msg_and_die("SO_SNDBUF"); 741 bb_perror_msg_and_die("SO_SNDBUF");
1078 } 742 }
1079#endif 743#endif
1080#ifdef IP_HDRINCL
1081 if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0
1082 && errno != ENOPROTOOPT
1083 ) {
1084 bb_perror_msg_and_die("IP_HDRINCL");
1085 }
1086#else
1087#ifdef IP_TOS 744#ifdef IP_TOS
1088 if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { 745 if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
1089 bb_perror_msg_and_die("setsockopt tos %d", tos); 746 bb_perror_msg_and_die("setsockopt tos %d", tos);
1090 } 747 }
1091#endif 748#endif
749#ifdef IP_DONTFRAG
750 if (op & OPT_DONT_FRAGMNT)
751 setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG,
752 &const_int_1, sizeof(const_int_1));
1092#endif 753#endif
1093#if TRACEROUTE_SO_DEBUG 754#if TRACEROUTE_SO_DEBUG
1094 if (op & OPT_DEBUG) 755 if (op & OPT_DEBUG)
@@ -1099,136 +760,82 @@ int traceroute_main(int argc, char **argv)
1099 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, 760 setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
1100 &const_int_1, sizeof(const_int_1)); 761 &const_int_1, sizeof(const_int_1));
1101 762
1102 /* Revert to non-privileged user after opening sockets */
1103 xsetgid(getgid());
1104 xsetuid(getuid());
1105
1106 outip = xzalloc(packlen); 763 outip = xzalloc(packlen);
1107 764
1108 outip->ip_v = IPVERSION; 765 if (op & OPT_USE_ICMP) {
1109 if (op & OPT_TOS) 766 ident = getpid() | 0x8000;
1110 outip->ip_tos = tos;
1111 outip->ip_len = htons(packlen);
1112 if (op & OPT_DONT_FRAGMNT)
1113 outip->ip_off = htons(IP_DF);
1114 outp = (unsigned char *)(outip + 1);
1115 outip->ip_dst = to->sin_addr;
1116
1117 outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
1118 ident = (getpid() & 0xffff) | 0x8000;
1119#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
1120 if (useicmp) {
1121 outip->ip_p = IPPROTO_ICMP;
1122 outicmp = (struct icmp *)outp;
1123 outicmp->icmp_type = ICMP_ECHO; 767 outicmp->icmp_type = ICMP_ECHO;
1124 outicmp->icmp_id = htons(ident); 768 outicmp->icmp_id = htons(ident);
1125 outdata = (outdata_t *)(outp + 8); /* XXX magic number */ 769 outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR);
1126 } else 770 } else {
1127#endif 771 outdata = (struct outdata_t *)(outudp + 1);
1128 {
1129 outip->ip_p = IPPROTO_UDP;
1130 outudp = (struct udphdr *)outp;
1131 outudp->source = htons(ident);
1132 outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen)));
1133 outdata = (outdata_t *)(outudp + 1);
1134 } 772 }
1135 773
1136 /* Look for a specific device */ 774 if (op & OPT_DEVICE) /* hmm, do we need error check? */
1137 if (op & OPT_DEVICE) { 775 setsockopt_bindtodevice(sndsock, device);
1138 /* Get the interface address list */
1139 int n = ifaddrlist(&al);
1140 for (; n > 0; --n, ++al)
1141 if (strcmp(device, al->device) == 0)
1142 goto found_dev;
1143 bb_error_msg_and_die("can't find interface %s", device);
1144 }
1145 found_dev:
1146 776
1147 /* Determine our source address */ 777 if (op & OPT_SOURCE) {
1148 if (!(op & OPT_SOURCE)) { 778 len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0);
1149 /* 779 /* Ping does this (why?) */
1150 * If a device was specified, use the interface address. 780 if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF,
1151 * Otherwise, try to determine our source address. 781 &source_lsa->u.sa, source_lsa->len))
1152 */ 782 bb_error_msg_and_die("can't set multicast source interface");
1153 if (op & OPT_DEVICE) 783//TODO: we can query source port we bound to,
1154 setsin(from, al->addr); 784// and check it in replies... if we care enough
1155 findsaddr(to, from); 785 xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
1156 } else { 786 free(source_lsa);
1157 hi = gethostinfo(source);
1158 source = hi->name;
1159 hi->name = NULL;
1160 /*
1161 * If the device was specified make sure it
1162 * corresponds to the source address specified.
1163 * Otherwise, use the first address (and warn if
1164 * there are more than one).
1165 */
1166 if (op & OPT_DEVICE) {
1167 uint32_t *ap;
1168 for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
1169 if (*ap == al->addr)
1170 goto found_dev2;
1171 bb_error_msg_and_die("%s is not on interface %s",
1172 source, device);
1173 found_dev2:
1174 setsin(from, *ap);
1175 } else {
1176 setsin(from, hi->addrs[0]);
1177 if (hi->n > 1)
1178 bb_error_msg(
1179 "warning: %s has multiple addresses; using %s",
1180 source, inet_ntoa(from->sin_addr));
1181 }
1182 freehostinfo(hi);
1183 } 787 }
1184 788
1185 outip->ip_src = from->sin_addr; 789 /* Revert to non-privileged user after opening sockets */
1186#ifndef IP_HDRINCL 790 xsetgid(getgid());
1187 xbind(sndsock, (struct sockaddr *)from, sizeof(*from)); 791 xsetuid(getuid());
1188#endif
1189 792
1190 printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr)); 793 printf("traceroute to %s (%s)", argv[0],
794 xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa));
1191 if (op & OPT_SOURCE) 795 if (op & OPT_SOURCE)
1192 printf(" from %s", source); 796 printf(" from %s", source);
1193 printf(", %d hops max, %d byte packets\n", max_ttl, packlen); 797 printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
1194 798
1195 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) { 799 for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
800//TODO: make it protocol agnostic (get rid of sockaddr_in)
801 struct sockaddr_in from;
1196 uint32_t lastaddr = 0; 802 uint32_t lastaddr = 0;
1197 int gotlastaddr = 0; 803 int probe;
804 int unreachable = 0; /* counter */
805 int gotlastaddr = 0; /* flags */
1198 int got_there = 0; 806 int got_there = 0;
1199 int unreachable = 0; 807 int first = 1;
1200 int sentfirst = 0;
1201 808
1202 printf("%2d ", ttl); 809 printf("%2d", ttl);
1203 for (probe = 0; probe < nprobes; ++probe) { 810 for (probe = 0; probe < nprobes; ++probe) {
1204 int cc; 811 int cc;
1205 unsigned t1; 812 unsigned t1;
1206 unsigned t2; 813 unsigned t2;
1207 struct ip *ip; 814 struct ip *ip;
1208 815
1209 if (sentfirst && pausemsecs > 0) 816 if (!first && pausemsecs > 0)
1210 usleep(pausemsecs * 1000); 817 usleep(pausemsecs * 1000);
1211 fflush(stdout); 818 fflush(stdout);
1212 819
1213 t1 = monotonic_us(); 820 t1 = monotonic_us();
1214 send_probe(++seq, ttl); 821 send_probe(++seq, ttl);
1215 ++sentfirst; 822 first = 0;
1216 823
1217 while ((cc = wait_for_reply(rcvsock, from)) != 0) { 824 while ((cc = wait_for_reply(&from)) != 0) {
1218 t2 = monotonic_us(); 825 t2 = monotonic_us();
1219 i = packet_ok(packet, cc, from, seq); 826 i = packet_ok(cc, &from, seq);
1220 /* Skip short packet */ 827 /* Skip short packet */
1221 if (i == 0) 828 if (i == 0)
1222 continue; 829 continue;
1223 if (!gotlastaddr 830 if (!gotlastaddr
1224 || from->sin_addr.s_addr != lastaddr 831 || from.sin_addr.s_addr != lastaddr
1225 ) { 832 ) {
1226 print(packet, cc, from); 833 print(cc, &from);
1227 lastaddr = from->sin_addr.s_addr; 834 lastaddr = from.sin_addr.s_addr;
1228 ++gotlastaddr; 835 gotlastaddr = 1;
1229 } 836 }
1230 print_delta_ms(t1, t2); 837 print_delta_ms(t1, t2);
1231 ip = (struct ip *)packet; 838 ip = (struct ip *)recv_pkt;
1232 if (op & OPT_TTL_FLAG) 839 if (op & OPT_TTL_FLAG)
1233 printf(" (%d)", ip->ip_ttl); 840 printf(" (%d)", ip->ip_ttl);
1234 if (i == -2) { 841 if (i == -2) {