aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) {