-
-
-static const char route[] = "/proc/net/route";
-
-/* last inbound (icmp) packet */
-static unsigned char packet[512] ATTRIBUTE_ALIGNED(32);
-
-static struct ip *outip; /* last output (udp) packet */
-static struct udphdr *outudp; /* last output (udp) packet */
-static struct outdata *outdata; /* last output (udp) packet */
-
-#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
-static struct icmp *outicmp; /* last output (icmp) packet */
-#endif
-
-#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
-/* Maximum number of gateways (include room for one noop) */
-#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
-/* loose source route gateway list (including room for final destination) */
-static u_int32_t gwlist[NGATEWAYS + 1];
-#endif
-
-static int s; /* receive (icmp) socket file descriptor */
-static int sndsock; /* send (udp/icmp) socket file descriptor */
-
-static struct sockaddr_storage whereto; /* Who to try to reach */
-static struct sockaddr_storage wherefrom; /* Who we are */
-static int packlen; /* total length of packet */
-static int minpacket; /* min ip packet size */
-static int maxpacket = 32 * 1024; /* max ip packet size */
-static int pmtu; /* Path MTU Discovery (RFC1191) */
-
-static char *hostname;
-
-static uint16_t ident;
-static uint16_t port = 32768 + 666; /* start udp dest port # for probe packets */
-
-static int waittime = 5; /* time to wait for response (in seconds) */
-static int nflag; /* print addresses numerically */
-static int doipcksum = 1; /* calculate ip checksums by default */
-
-#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
-static int optlen; /* length of ip options */
-#else
-#define optlen 0
-#endif
-
-#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
-static int useicmp; /* use icmp echo instead of udp packets */
-#endif
-#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
-static int verbose;
-#endif
-
-/*
- * Return the interface list
- */
-static int
-ifaddrlist(struct IFADDRLIST **ipaddrp)
-{
- int fd, nipaddr;
-#ifdef HAVE_SOCKADDR_SA_LEN
- int n;
-#endif
- struct ifreq *ifrp, *ifend, *ifnext;
- struct sockaddr_in *addr_sin;
- struct IFADDRLIST *al;
- struct ifconf ifc;
- struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr;
- struct IFADDRLIST *st_ifaddrlist;
-
- fd = xsocket(AF_INET, SOCK_DGRAM, 0);
-
- ifc.ifc_len = sizeof(ibuf);
- ifc.ifc_buf = (caddr_t)ibuf;
-
- if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
- ifc.ifc_len < sizeof(struct ifreq)) {
- if (errno == EINVAL)
- bb_error_msg_and_die(
- "SIOCGIFCONF: ifreq struct too small (%d bytes)",
- (int)sizeof(ibuf));
- else
- bb_perror_msg_and_die("SIOCGIFCONF");
- }
- ifrp = ibuf;
- ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
-
- nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
- st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST));
- al = st_ifaddrlist;
- nipaddr = 0;
-
- for (; ifrp < ifend; ifrp = ifnext) {
-#ifdef HAVE_SOCKADDR_SA_LEN
- n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
- if (n < sizeof(*ifrp))
- ifnext = ifrp + 1;
- else
- ifnext = (struct ifreq *)((char *)ifrp + n);
- if (ifrp->ifr_addr.sa_family != AF_INET)
- continue;
-#else
- ifnext = ifrp + 1;
-#endif
- /*
- * Need a template to preserve address info that is
- * used below to locate the next entry. (Otherwise,
- * SIOCGIFFLAGS stomps over it because the requests
- * are returned in a union.)
- */
- strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
- if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
- if (errno == ENXIO)
- continue;
- bb_perror_msg_and_die("SIOCGIFFLAGS: %.*s",
- (int)sizeof(ifr.ifr_name), ifr.ifr_name);
- }
-
- /* Must be up */
- if ((ifr.ifr_flags & IFF_UP) == 0)
- continue;
-
- safe_strncpy(al->device, ifr.ifr_name, sizeof(ifr.ifr_name) + 1);
-#ifdef sun
- /* Ignore sun virtual interfaces */
- if (strchr(al->device, ':') != NULL)
- continue;
-#endif
- if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)
- bb_perror_msg_and_die("SIOCGIFADDR: %s", al->device);
-
- addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
- al->addr = addr_sin->sin_addr.s_addr;
- ++al;
- ++nipaddr;
- }
- if (nipaddr == 0)
- bb_error_msg_and_die ("can't find any network interfaces");
- (void)close(fd);
-
- *ipaddrp = st_ifaddrlist;
- return nipaddr;
-}
-
-
-static void
-setsin(struct sockaddr_in *addr_sin, u_int32_t addr)
-{
- memset(addr_sin, 0, sizeof(*addr_sin));
-#ifdef HAVE_SOCKADDR_SA_LEN
- addr_sin->sin_len = sizeof(*addr_sin);