Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/networking/traceroute.c

    r902 r1765  
    197197 */
    198198
    199 #undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     199#define TRACEROUTE_SO_DEBUG 0
     200
     201/* TODO: undefs were uncommented - ??! we have config system for that! */
     202/* probably ok to remove altogether */
     203//#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
    200204//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
    201 #undef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG   /* not in documentation man */
    202 #undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     205//#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    203206//#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    204 #undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     207//#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    205208//#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    206209
    207 #include <errno.h>
    208 #include <stdio.h>
    209 #include <stdlib.h>
    210 #include <string.h>
    211 #include <unistd.h>
    212 #include <fcntl.h>
    213 #include <netdb.h>
    214 #include <endian.h>
    215 #include <getopt.h>
    216 
    217 #include <sys/param.h>
    218 #include <sys/file.h>
    219 #include <sys/ioctl.h>
    220 #include <sys/socket.h>
    221 #include <sys/select.h>
    222 #include "inet_common.h"
    223210
    224211#include <net/if.h>
     212#include <arpa/inet.h>
    225213#include <netinet/in.h>
    226 #include <arpa/inet.h>
    227214#include <netinet/udp.h>
    228215#include <netinet/ip.h>
    229216#include <netinet/ip_icmp.h>
    230217
    231 #include "busybox.h"
     218#include "libbb.h"
     219#include "inet_common.h"
    232220
    233221
     
    236224 * Per RFC 791, September 1981.
    237225 */
    238 #define IPVERSION       4
     226#define IPVERSION 4
     227
     228#ifndef IPPROTO_ICMP
     229/* Grrrr.... */
     230#define IPPROTO_ICMP 1
     231#endif
     232#ifndef IPPROTO_IP
     233#define IPPROTO_IP 0
     234#endif
    239235
    240236/*
     
    252248 * UDP kernel structures and variables.
    253249 */
    254 struct  udpiphdr {
     250struct udpiphdr {
    255251    struct  ipovly ui_i;            /* overlaid ip structure */
    256252    struct  udphdr ui_u;            /* udp header */
     
    273269    char *name;
    274270    int n;
    275     u_int32_t *addrs;
     271    uint32_t *addrs;
    276272};
    277273
     
    280276    unsigned char seq;             /* sequence number of this packet */
    281277    unsigned char ttl;             /* ttl packet left with */
    282     struct timeval tv ATTRIBUTE_PACKED; /* time packet left */
     278// UNUSED. Retaining to have the same packet size.
     279    struct timeval tv_UNUSED ATTRIBUTE_PACKED; /* time packet left */
    283280};
    284281
    285282struct IFADDRLIST {
    286     u_int32_t addr;
     283    uint32_t addr;
    287284    char device[sizeof(struct ifreq)];
    288285};
    289286
    290 
    291 static const char route[] = "/proc/net/route";
    292 
    293 /* last inbound (icmp) packet */
    294 static unsigned char  packet[512] ATTRIBUTE_ALIGNED(32);
    295287
    296288static struct ip *outip;               /* last output (udp) packet */
     
    298290static struct outdata *outdata;        /* last output (udp) packet */
    299291
    300 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     292#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    301293static struct icmp *outicmp;           /* last output (icmp) packet */
    302 #endif
    303 
    304 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    305 /* Maximum number of gateways (include room for one noop) */
    306 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
    307 /* loose source route gateway list (including room for final destination) */
    308 static u_int32_t gwlist[NGATEWAYS + 1];
    309294#endif
    310295
     
    312297static int sndsock;                    /* send (udp/icmp) socket file descriptor */
    313298
    314 static struct sockaddr_storage whereto;        /* Who to try to reach */
    315 static struct sockaddr_storage wherefrom;      /* Who we are */
    316299static int packlen;                    /* total length of packet */
    317300static int minpacket;                  /* min ip packet size */
     
    321304static char *hostname;
    322305
    323 static u_short ident;
    324 static u_short port = 32768 + 666;     /* start udp dest port # for probe packets */
     306static uint16_t ident;
     307static uint16_t port = 32768 + 666;     /* start udp dest port # for probe packets */
    325308
    326309static int waittime = 5;               /* time to wait for response (in seconds) */
    327 static int nflag;                      /* print addresses numerically */
    328310static int doipcksum = 1;              /* calculate ip checksums by default */
    329311
    330 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     312#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    331313static int optlen;                     /* length of ip options */
    332314#else
     
    334316#endif
    335317
    336 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    337 static int useicmp;                    /* use icmp echo instead of udp packets */
    338 #endif
    339 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
    340 static int verbose;
    341 #endif
     318
     319/* Keep in sync with getopt32 call! */
     320#define OPT_DONT_FRAGMNT (1<<0)    /* F */
     321#define OPT_USE_ICMP     (1<<1)    /* I */
     322#define OPT_TTL_FLAG     (1<<2)    /* l */
     323#define OPT_ADDR_NUM     (1<<3)    /* n */
     324#define OPT_BYPASS_ROUTE (1<<4)    /* r */
     325#define OPT_DEBUG        (1<<5)    /* d */
     326#define OPT_VERBOSE      (1<<6)    /* v */
     327#define OPT_IP_CHKSUM    (1<<7)    /* x */
     328#define OPT_TOS          (1<<8)    /* t */
     329#define OPT_DEVICE       (1<<9)    /* i */
     330#define OPT_MAX_TTL      (1<<10)   /* m */
     331#define OPT_PORT         (1<<11)   /* p */
     332#define OPT_NPROBES      (1<<12)   /* q */
     333#define OPT_SOURCE       (1<<13)   /* s */
     334#define OPT_WAITTIME     (1<<14)   /* w */
     335#define OPT_PAUSE_MS     (1<<15)   /* z */
     336#define OPT_FIRST_TTL    (1<<16)   /* f */
     337
     338#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
     339/* use icmp echo instead of udp packets */
     340#define useicmp (option_mask32 & OPT_USE_ICMP)
     341#endif
     342#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
     343#define verbose (option_mask32 & OPT_VERBOSE)
     344#endif
     345#define nflag   (option_mask32 & OPT_ADDR_NUM)
     346
     347
     348struct globals {
     349    /* last inbound (icmp) packet */
     350    unsigned char packet[512];
     351    struct sockaddr_storage whereto;        /* Who to try to reach */
     352    struct sockaddr_storage wherefrom;      /* Who we are */
     353#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
     354    /* Maximum number of gateways (include room for one noop) */
     355#define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(uint32_t)))
     356    /* loose source route gateway list (including room for final destination) */
     357    uint32_t gwlist[NGATEWAYS + 1];
     358#endif
     359};
     360
     361#define G (*ptr_to_globals)
     362
     363#define packet    (G.packet   )
     364#define whereto   (G.whereto  )
     365#define wherefrom (G.wherefrom)
     366#define gwlist    (G.gwlist   )
     367
    342368
    343369/*
     
    347373ifaddrlist(struct IFADDRLIST **ipaddrp)
    348374{
     375    enum { IFREQ_BUFSIZE = (32 * 1024) / sizeof(struct ifreq) };
     376
    349377    int fd, nipaddr;
    350378#ifdef HAVE_SOCKADDR_SA_LEN
     
    355383    struct IFADDRLIST *al;
    356384    struct ifconf ifc;
    357     struct ifreq ibuf[(32 * 1024) / sizeof(struct ifreq)], ifr;
     385    struct ifreq ifr;
     386    /* Was on stack, but 32k is a bit too much: */
     387    struct ifreq *ibuf = xmalloc(IFREQ_BUFSIZE * sizeof(ibuf[0]));
    358388    struct IFADDRLIST *st_ifaddrlist;
    359389
    360     fd = bb_xsocket(AF_INET, SOCK_DGRAM, 0);
    361 
    362     ifc.ifc_len = sizeof(ibuf);
     390    fd = xsocket(AF_INET, SOCK_DGRAM, 0);
     391
     392    ifc.ifc_len = IFREQ_BUFSIZE * sizeof(ibuf[0]);
    363393    ifc.ifc_buf = (caddr_t)ibuf;
    364394
    365     if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
    366         ifc.ifc_len < sizeof(struct ifreq)) {
     395    if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
     396     || ifc.ifc_len < sizeof(struct ifreq)
     397    ) {
    367398        if (errno == EINVAL)
    368399            bb_error_msg_and_die(
    369                 "SIOCGIFCONF: ifreq struct too small (%d bytes)",
    370                 (int)sizeof(ibuf));
    371         else
    372             bb_perror_msg_and_die("SIOCGIFCONF");
     400                "SIOCGIFCONF: ifreq struct too small (%u bytes)",
     401                (unsigned)(IFREQ_BUFSIZE * sizeof(ibuf[0])));
     402        bb_perror_msg_and_die("SIOCGIFCONF");
    373403    }
    374404    ifrp = ibuf;
     
    376406
    377407    nipaddr = 1 + (ifc.ifc_len / sizeof(struct ifreq));
    378     st_ifaddrlist = xcalloc(nipaddr, sizeof(struct IFADDRLIST));
     408    st_ifaddrlist = xzalloc(nipaddr * sizeof(struct IFADDRLIST));
    379409    al = st_ifaddrlist;
    380410    nipaddr = 0;
     
    416446            continue;
    417447#endif
    418         if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0)
    419             bb_perror_msg_and_die("SIOCGIFADDR: %s", al->device);
     448        ioctl_or_perror_and_die(fd, SIOCGIFADDR, (char *)&ifr,
     449                "SIOCGIFADDR: %s", al->device);
    420450
    421451        addr_sin = (struct sockaddr_in *)&ifr.ifr_addr;
     
    424454        ++nipaddr;
    425455    }
    426     if(nipaddr == 0)
    427         bb_error_msg_and_die ("Can't find any network interfaces");
    428     (void)close(fd);
    429 
     456    if (nipaddr == 0)
     457        bb_error_msg_and_die("can't find any network interfaces");
     458
     459    free(ibuf);
     460    close(fd);
    430461    *ipaddrp = st_ifaddrlist;
    431462    return nipaddr;
     
    434465
    435466static void
    436 setsin(struct sockaddr_in *addr_sin, u_int32_t addr)
     467setsin(struct sockaddr_in *addr_sin, uint32_t addr)
    437468{
    438469    memset(addr_sin, 0, sizeof(*addr_sin));
     
    453484    int i, n;
    454485    FILE *f;
    455     u_int32_t mask;
    456     u_int32_t dest, tmask;
     486    uint32_t mask;
     487    uint32_t dest, tmask;
    457488    struct IFADDRLIST *al;
    458489    char buf[256], tdevice[256], device[256];
    459490
    460     f = bb_xfopen(route, "r");
     491    f = xfopen("/proc/net/route", "r");
    461492
    462493    /* Find the appropriate interface */
     
    468499        if (n == 1 && strncmp(buf, "Iface", 5) == 0)
    469500            continue;
    470         if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
    471             tdevice, &dest, &tmask)) != 3)
    472             bb_error_msg_and_die ("junk in buffer");
    473         if ((to->sin_addr.s_addr & tmask) == dest &&
    474             (tmask > mask || mask == 0)) {
     501        i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
     502                    tdevice, &dest, &tmask);
     503        if (i != 3)
     504            bb_error_msg_and_die("junk in buffer");
     505        if ((to->sin_addr.s_addr & tmask) == dest
     506         && (tmask > mask || mask == 0)
     507        ) {
    475508            mask = tmask;
    476509            strcpy(device, tdevice);
     
    480513
    481514    if (device[0] == '\0')
    482         bb_error_msg_and_die ("Can't find interface");
     515        bb_error_msg_and_die("can't find interface");
    483516
    484517    /* Get the interface address list */
     
    490523            break;
    491524    if (i <= 0)
    492         bb_error_msg_and_die("Can't find interface %s", device);
     525        bb_error_msg_and_die("can't find interface %s", device);
    493526
    494527    setsin(from, al->addr);
     
    502535*/
    503536
    504 /* String to value with optional min and max. Handles decimal and hex. */
    505537static int
    506 str2val(const char *str, const char *what, int mi, int ma)
    507 {
    508     const char *cp;
    509     int val;
    510     char *ep;
    511 
    512     if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
    513         cp = str + 2;
    514         val = (int)strtol(cp, &ep, 16);
    515     } else
    516         val = (int)strtol(str, &ep, 10);
    517     if (*ep != '\0') {
    518         bb_error_msg_and_die("\"%s\" bad value for %s \n", str, what);
    519     }
    520     if (val < mi && mi >= 0) {
    521         if (mi == 0)
    522             bb_error_msg_and_die("%s must be >= %d\n", what, mi);
    523         else
    524             bb_error_msg_and_die("%s must be > %d\n", what, mi - 1);
    525     }
    526     if (val > ma && ma >= 0)
    527         bb_error_msg_and_die("%s must be <= %d\n", what, ma);
    528     return val;
    529 }
    530 
    531 
    532 /*
    533  * Subtract 2 timeval structs:  out = out - in.
    534  * Out is assumed to be >= in.
    535  */
    536 static inline void
    537 tvsub(struct timeval *out, struct timeval *in)
    538 {
    539 
    540     if ((out->tv_usec -= in->tv_usec) < 0)   {
    541         --out->tv_sec;
    542         out->tv_usec += 1000000;
    543     }
    544     out->tv_sec -= in->tv_sec;
    545 }
    546 
    547 static int
    548 wait_for_reply(int sock, struct sockaddr_in *fromp, const struct timeval *tp)
     538wait_for_reply(int sock, struct sockaddr_in *fromp)
    549539{
    550540    fd_set fds;
    551     struct timeval now, wait;
    552     struct timezone tz;
     541    struct timeval tvwait;
    553542    int cc = 0;
    554543    socklen_t fromlen = sizeof(*fromp);
     
    557546    FD_SET(sock, &fds);
    558547
    559     wait.tv_sec = tp->tv_sec + waittime;
    560     wait.tv_usec = tp->tv_usec;
    561     (void)gettimeofday(&now, &tz);
    562     tvsub(&wait, &now);
    563 
    564     if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
     548    tvwait.tv_sec = waittime;
     549    tvwait.tv_usec = 0;
     550
     551    if (select(sock + 1, &fds, NULL, NULL, &tvwait) > 0)
    565552        cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
    566553                (struct sockaddr *)fromp, &fromlen);
     
    572559 * Checksum routine for Internet Protocol family headers (C Version)
    573560 */
    574 static u_short
    575 in_cksum(u_short *addr, int len)
     561static uint16_t
     562in_cksum(uint16_t *addr, int len)
    576563{
    577564    int nleft = len;
    578     u_short *w = addr;
    579     u_short answer;
     565    uint16_t *w = addr;
     566    uint16_t answer;
    580567    int sum = 0;
    581568
     
    606593
    607594static void
    608 send_probe(int seq, int ttl, struct timeval *tp)
     595send_probe(int seq, int ttl)
    609596{
    610597    int cc;
     
    622609    if (doipcksum) {
    623610        outip->ip_sum =
    624             in_cksum((u_short *)outip, sizeof(*outip) + optlen);
     611            in_cksum((uint16_t *)outip, sizeof(*outip) + optlen);
    625612        if (outip->ip_sum == 0)
    626613            outip->ip_sum = 0xffff;
     
    630617    outdata->seq = seq;
    631618    outdata->ttl = ttl;
    632     memcpy(&outdata->tv, tp, sizeof(outdata->tv));
    633 
    634 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     619// UNUSED: was storing gettimeofday's result there, but never ever checked it
     620    /*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
     621
     622#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    635623    if (useicmp)
    636624        outicmp->icmp_seq = htons(seq);
     
    639627        outudp->dest = htons(port + seq);
    640628
    641 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     629#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    642630    if (useicmp) {
    643631        /* Always calculate checksum for icmp packets */
    644632        outicmp->icmp_cksum = 0;
    645         outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
     633        outicmp->icmp_cksum = in_cksum((uint16_t *)outicmp,
    646634            packlen - (sizeof(*outip) + optlen));
    647635        if (outicmp->icmp_cksum == 0)
     
    649637    } else
    650638#endif
    651            if (doipcksum) {
     639    if (doipcksum) {
    652640        /* Checksum (we must save and restore ip header) */
    653641        tip = *outip;
     
    661649        ui->ui_len = outudp->len;
    662650        outudp->check = 0;
    663         outudp->check = in_cksum((u_short *)ui, packlen);
     651        outudp->check = in_cksum((uint16_t *)ui, packlen);
    664652        if (outudp->check == 0)
    665653            outudp->check = 0xffff;
     
    667655    }
    668656
    669 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     657#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
    670658    /* XXX undocumented debugging hack */
    671659    if (verbose > 1) {
    672         const u_short *sp;
     660        const uint16_t *sp;
    673661        int nshorts, i;
    674662
    675         sp = (u_short *)outip;
    676         nshorts = (u_int)packlen / sizeof(u_short);
     663        sp = (uint16_t *)outip;
     664        nshorts = (unsigned)packlen / sizeof(uint16_t);
    677665        i = 0;
    678666        printf("[ %d bytes", packlen);
     
    699687#endif
    700688
    701     cc = sendto(sndsock, (char *)outip,
    702         packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto));
    703     if (cc < 0 || cc != packlen)  {
    704         if (cc < 0)
    705             bb_perror_msg_and_die("sendto");
    706         printf("%s: wrote %s %d chars, ret=%d\n",
    707             bb_applet_name, hostname, packlen, cc);
    708         (void)fflush(stdout);
    709     }
    710 }
    711 
    712 static inline double
    713 deltaT(struct timeval *t1p, struct timeval *t2p)
    714 {
    715     double dt;
    716 
    717     dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
    718          (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
    719     return dt;
    720 }
    721 
    722 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     689    cc = xsendto(sndsock, (char *)outip,
     690        packlen, (struct sockaddr *)&whereto, sizeof(whereto));
     691    if (cc != packlen)  {
     692        bb_info_msg("wrote %s %d chars, ret=%d", hostname, packlen, cc);
     693    }
     694}
     695
     696#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
    723697/*
    724698 * Convert an ICMP "type" field to a printable string.
     
    727701pr_type(unsigned char t)
    728702{
    729     static const char * const ttab[] = {
     703    static const char *const ttab[] = {
    730704    "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
    731705    "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
     
    753727    hlen = ip->ip_hl << 2;
    754728    if (cc < hlen + ICMP_MINLEN) {
    755 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     729#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
    756730        if (verbose)
    757731            printf("packet too short (%d bytes) from %s\n", cc,
     
    777751        hip = &icp->icmp_ip;
    778752        hlen = hip->ip_hl << 2;
    779 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     753#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    780754        if (useicmp) {
    781755            struct icmp *hicmp;
     
    796770        } else
    797771#endif
    798               {
     772        {
    799773            up = (struct udphdr *)((unsigned char *)hip + hlen);
    800774            /* XXX 8 is a magic number */
     
    806780        }
    807781    }
    808 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     782#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
    809783    if (verbose) {
    810784        int i;
    811         u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
     785        uint32_t *lp = (uint32_t *)&icp->icmp_ip;
    812786
    813787        printf("\n%d bytes from %s to "
     
    815789            cc, inet_ntoa(from->sin_addr),
    816790            inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
    817         for (i = 4; i < cc ; i += sizeof(*lp))
     791        for (i = 4; i < cc; i += sizeof(*lp))
    818792            printf("%2d: x%8.8x\n", i, *lp++);
    819793    }
     
    829803 */
    830804static inline void
    831 inetname(struct sockaddr_in *from)
    832 {
    833     const char *n = NULL;
     805print_inetname(struct sockaddr_in *from)
     806{
    834807    const char *ina;
    835     char name[257];
    836 
    837     if (!nflag && from->sin_addr.s_addr != INADDR_ANY) {
    838         if(INET_rresolve(name, sizeof(name), from, 0x4000, 0xffffffff) >= 0)
    839             n = name;
    840     }
     808
    841809    ina = inet_ntoa(from->sin_addr);
    842810    if (nflag)
    843811        printf(" %s", ina);
    844     else
     812    else {
     813        char *n = NULL;
     814        if (from->sin_addr.s_addr != INADDR_ANY)
     815            n = xmalloc_sockaddr2host_noport((struct sockaddr*)from);
    845816        printf(" %s (%s)", (n ? n : ina), ina);
     817        free(n);
     818    }
    846819}
    847820
     
    856829    cc -= hlen;
    857830
    858     inetname(from);
    859 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
     831    print_inetname(from);
     832#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
    860833    if (verbose)
    861         printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
     834        printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
    862835#endif
    863836}
     
    871844    struct hostinfo *hi;
    872845    char **p;
    873     u_int32_t addr, *ap;
    874 
    875     hi = xcalloc(1, sizeof(*hi));
     846    uint32_t addr, *ap;
     847
     848    hi = xzalloc(sizeof(*hi));
    876849    addr = inet_addr(host);
    877     if ((int32_t)addr != -1) {
    878         hi->name = bb_xstrdup(host);
     850    if (addr != 0xffffffff) {
     851        hi->name = xstrdup(host);
    879852        hi->n = 1;
    880         hi->addrs = xcalloc(1, sizeof(hi->addrs[0]));
     853        hi->addrs = xzalloc(sizeof(hi->addrs[0]));
    881854        hi->addrs[0] = addr;
    882855        return hi;
     
    886859    if (hp->h_addrtype != AF_INET || hp->h_length != 4)
    887860        bb_perror_msg_and_die("bad host %s", host);
    888     hi->name = bb_xstrdup(hp->h_name);
     861    hi->name = xstrdup(hp->h_name);
    889862    for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
    890863        continue;
    891864    hi->n = n;
    892     hi->addrs = xcalloc(n, sizeof(hi->addrs[0]));
     865    hi->addrs = xzalloc(n * sizeof(hi->addrs[0]));
    893866    for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
    894867        memcpy(ap, *p, sizeof(*ap));
     
    900873{
    901874    free(hi->name);
    902     hi->name = NULL;
    903     free((char *)hi->addrs);
    904     free((char *)hi);
    905 }
    906 
    907 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     875    free(hi->addrs);
     876    free(hi);
     877}
     878
     879#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    908880static void
    909 getaddr(u_int32_t *ap, const char *host)
     881getaddr(uint32_t *ap, const char *host)
    910882{
    911883    struct hostinfo *hi;
     
    917889#endif
    918890
    919 
    920 int
    921 traceroute_main(int argc, char *argv[])
     891static void
     892print_delta_ms(unsigned t1p, unsigned t2p)
     893{
     894    unsigned tt = t2p - t1p;
     895    printf("  %u.%03u ms", tt/1000, tt%1000);
     896}
     897
     898int traceroute_main(int argc, char **argv);
     899int traceroute_main(int argc, char **argv)
    922900{
    923901    int code, n;
    924     char *cp;
    925902    unsigned char *outp;
    926     u_int32_t *ap;
    927     struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
    928     struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
     903    uint32_t *ap;
     904    struct sockaddr_in *from;
     905    struct sockaddr_in *to;
    929906    struct hostinfo *hi;
    930     int on = 1;
    931     struct protoent *pe;
    932907    int ttl, probe, i;
    933908    int seq = 0;
    934909    int tos = 0;
    935     char *tos_str = NULL;
    936     char *source = NULL;
    937     unsigned long op;
    938 
    939 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     910    char *tos_str;
     911    char *source;
     912    unsigned op;
     913#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    940914    int lsrr = 0;
    941915#endif
    942     u_short off = 0;
     916    uint16_t off = 0;
    943917    struct IFADDRLIST *al;
    944     char *device = NULL;
     918    char *device;
    945919    int max_ttl = 30;
    946     char *max_ttl_str = NULL;
    947     char *port_str = NULL;
     920    char *max_ttl_str;
     921    char *port_str;
    948922    int nprobes = 3;
    949     char *nprobes_str = NULL;
    950     char *waittime_str = NULL;
    951     u_int pausemsecs = 0;
    952     char *pausemsecs_str = NULL;
     923    char *nprobes_str;
     924    char *waittime_str;
     925    unsigned pausemsecs = 0;
     926    char *pausemsecs_str;
    953927    int first_ttl = 1;
    954     char *first_ttl_str = NULL;
    955 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    956     llist_t *sourse_route_list = NULL;
    957 #endif
    958 
    959     opterr = 0;
    960 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    961     bb_opt_complementally = "x-x:g::";
     928    char *first_ttl_str;
     929#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
     930    llist_t *source_route_list = NULL;
     931#endif
     932
     933    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     934    from = (struct sockaddr_in *)&wherefrom;
     935    to = (struct sockaddr_in *)&whereto;
     936
     937    //opterr = 0;
     938#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
     939    opt_complementary = "x-x:g::";
    962940#else
    963     bb_opt_complementally = "x-x";
    964 #endif
    965 
    966     op = bb_getopt_ulflags(argc, argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
    967 #define USAGE_OP_DONT_FRAGMNT (1<<0)    /* F  */
    968 #define USAGE_OP_USE_ICMP     (1<<1)    /* I  */
    969 #define USAGE_OP_TTL_FLAG     (1<<2)    /* l  */
    970 #define USAGE_OP_ADDR_NUM     (1<<3)    /* n  */
    971 #define USAGE_OP_BYPASS_ROUTE (1<<4)    /* r  */
    972 #define USAGE_OP_DEBUG        (1<<5)    /* d */
    973 #define USAGE_OP_VERBOSE      (1<<6)    /* v */
    974 #define USAGE_OP_IP_CHKSUM    (1<<7)    /* x */
    975 
    976 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     941    opt_complementary = "x-x";
     942#endif
     943
     944    op = getopt32(argv, "FIlnrdvxt:i:m:p:q:s:w:z:f:"
     945#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    977946                    "g:"
    978947#endif
    979     , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str,
    980     &source, &waittime_str, &pausemsecs_str, &first_ttl_str
    981 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    982     , &sourse_route_list
     948        , &tos_str, &device, &max_ttl_str, &port_str, &nprobes_str
     949        , &source, &waittime_str, &pausemsecs_str, &first_ttl_str
     950#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
     951        , &source_route_list
    983952#endif
    984953    );
    985954
    986     if(op & USAGE_OP_DONT_FRAGMNT)
     955    if (op & OPT_DONT_FRAGMNT)
    987956        off = IP_DF;
    988 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
    989     useicmp = op & USAGE_OP_USE_ICMP;
    990 #endif
    991     nflag = op & USAGE_OP_ADDR_NUM;
    992 #ifdef CONFIG_FEATURE_TRACEROUTE_VERBOSE
    993     verbose = op &  USAGE_OP_VERBOSE;
    994 #endif
    995     if(op & USAGE_OP_IP_CHKSUM) {
     957    if (op & OPT_IP_CHKSUM) {
    996958        doipcksum = 0;
    997         bb_error_msg("Warning: ip checksums disabled");
    998     }
    999     if (tos_str)
    1000         tos = str2val(tos_str, "tos", 0, 255);
    1001     if(max_ttl_str)
    1002         max_ttl = str2val(max_ttl_str, "max ttl", 1, 255);
    1003     if(port_str)
    1004         port = (u_short)str2val(port_str, "port", 1, (1 << 16) - 1);
    1005     if(nprobes_str)
    1006         nprobes = str2val(nprobes_str, "nprobes", 1, -1);
    1007     if(source) {
    1008         /*
    1009          * set the ip source address of the outbound
    1010          * probe (e.g., on a multi-homed host).
    1011          */
    1012          if (getuid()) bb_error_msg_and_die("-s %s: Permission denied", source);
    1013     }
    1014     if(waittime_str)
    1015         waittime = str2val(waittime_str, "wait time", 2, 24 * 60 * 60);
    1016     if(pausemsecs_str)
    1017         pausemsecs = str2val(pausemsecs_str, "pause msecs", 0, 60 * 60 * 1000);
    1018     if(first_ttl_str)
    1019         first_ttl = str2val(first_ttl_str, "first ttl", 1, 255);
    1020 
    1021 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
    1022     if(sourse_route_list) {
     959        bb_error_msg("warning: ip checksums disabled");
     960    }
     961    if (op & OPT_TOS)
     962        tos = xatou_range(tos_str, 0, 255);
     963    if (op & OPT_MAX_TTL)
     964        max_ttl = xatou_range(max_ttl_str, 1, 255);
     965    if (op & OPT_PORT)
     966        port = xatou16(port_str);
     967    if (op & OPT_NPROBES)
     968        nprobes = xatou_range(nprobes_str, 1, INT_MAX);
     969    if (op & OPT_SOURCE) {
     970        /*
     971         * set the ip source address of the outbound
     972         * probe (e.g., on a multi-homed host).
     973         */
     974        if (getuid())
     975            bb_error_msg_and_die("-s %s: permission denied", source);
     976    }
     977    if (op & OPT_WAITTIME)
     978        waittime = xatou_range(waittime_str, 2, 24 * 60 * 60);
     979    if (op & OPT_PAUSE_MS)
     980        pausemsecs = xatou_range(pausemsecs_str, 0, 60 * 60 * 1000);
     981    if (op & OPT_FIRST_TTL)
     982        first_ttl = xatou_range(first_ttl_str, 1, 255);
     983
     984#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
     985    if (source_route_list) {
    1023986        llist_t *l_sr;
    1024987
    1025         for(l_sr = sourse_route_list; l_sr; ) {
     988        l_sr = source_route_list;
     989        while (l_sr) {
    1026990            if (lsrr >= NGATEWAYS)
    1027                 bb_error_msg_and_die("No more than %d gateways", NGATEWAYS);
     991                bb_error_msg_and_die("no more than %d gateways", NGATEWAYS);
    1028992            getaddr(gwlist + lsrr, l_sr->data);
    1029993            ++lsrr;
    1030994            l_sr = l_sr->link;
    1031             free(sourse_route_list);
    1032             sourse_route_list = l_sr;
     995            free(source_route_list);
     996            source_route_list = l_sr;
    1033997        }
    1034998        optlen = (lsrr + 1) * sizeof(gwlist[0]);
     
    10441008    minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
    10451009
    1046 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     1010#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    10471011    if (useicmp)
    10481012        minpacket += 8;                 /* XXX magic number */
     
    10561020
    10571021    case 2:
    1058         packlen = str2val(argv[optind + 1],
    1059             "packet length", minpacket, maxpacket);
     1022        packlen = xatoul_range(argv[optind + 1], minpacket, maxpacket);
    10601023        /* Fall through */
    10611024
     
    10651028        setsin(to, hi->addrs[0]);
    10661029        if (hi->n > 1)
    1067             bb_error_msg(
    1068             "Warning: %s has multiple addresses; using %s",
     1030            bb_error_msg("warning: %s has multiple addresses; using %s",
    10691031                hostname, inet_ntoa(to->sin_addr));
    10701032        hostname = hi->name;
     
    10771039    }
    10781040
    1079     cp = "icmp";
    1080     if ((pe = getprotobyname(cp)) == NULL)
    1081         bb_perror_msg_and_die("unknown protocol %s", cp);
    1082 
    1083     /* Insure the socket fds won't be 0, 1 or 2 */
    1084     do n = bb_xopen(bb_dev_null, O_RDONLY); while (n < 2);
    1085     if (n > 2)
    1086         close(n);
    1087 
    1088     s = bb_xsocket(AF_INET, SOCK_RAW, pe->p_proto);
    1089 
    1090 #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
    1091     if (op & USAGE_OP_DEBUG)
    1092         (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
    1093             sizeof(on));
    1094 #endif
    1095     if (op & USAGE_OP_BYPASS_ROUTE)
    1096         (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    1097             sizeof(on));
    1098 
    1099     sndsock = bb_xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    1100 
    1101 #ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
     1041    /* Ensure the socket fds won't be 0, 1 or 2 */
     1042    bb_sanitize_stdio();
     1043
     1044    s = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
     1045
     1046#if TRACEROUTE_SO_DEBUG
     1047    if (op & OPT_DEBUG)
     1048        setsockopt(s, SOL_SOCKET, SO_DEBUG,
     1049                &const_int_1, sizeof(const_int_1));
     1050#endif
     1051    if (op & OPT_BYPASS_ROUTE)
     1052        setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
     1053                &const_int_1, sizeof(const_int_1));
     1054
     1055    sndsock = xsocket(AF_INET, SOCK_RAW, IPPROTO_RAW);
     1056
     1057#if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
    11021058#if defined(IP_OPTIONS)
    11031059    if (lsrr > 0) {
    11041060        unsigned char optlist[MAX_IPOPTLEN];
    1105 
    1106         cp = "ip";
    1107         if ((pe = getprotobyname(cp)) == NULL)
    1108             bb_perror_msg_and_die("unknown protocol");
    11091061
    11101062        /* final hop */
     
    11221074        memcpy(optlist + 4, gwlist, i);
    11231075
    1124         if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
     1076        if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS,
    11251077            (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
    11261078            bb_perror_msg_and_die("IP_OPTIONS");
    1127             }
     1079        }
    11281080    }
    11291081#endif /* IP_OPTIONS */
     
    11311083
    11321084#ifdef SO_SNDBUF
    1133     if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
    1134         sizeof(packlen)) < 0) {
     1085    if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
    11351086        bb_perror_msg_and_die("SO_SNDBUF");
    11361087    }
    11371088#endif
    11381089#ifdef IP_HDRINCL
    1139     if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    1140         sizeof(on)) < 0 && errno != ENOPROTOOPT) {
     1090    if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, &const_int_1, sizeof(const_int_1)) < 0
     1091     && errno != ENOPROTOOPT
     1092    ) {
    11411093        bb_perror_msg_and_die("IP_HDRINCL");
    11421094    }
    11431095#else
    11441096#ifdef IP_TOS
    1145     if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
    1146         (char *)&tos, sizeof(tos)) < 0) {
     1097    if (tos_str && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
    11471098        bb_perror_msg_and_die("setsockopt tos %d", tos);
    11481099    }
    11491100#endif
    11501101#endif
    1151 #ifdef CONFIG_FEATURE_TRACEROUTE_SO_DEBUG
    1152     if (op & USAGE_OP_DEBUG)
    1153         (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
    1154             sizeof(on));
    1155 #endif
    1156     if (op & USAGE_OP_BYPASS_ROUTE)
    1157         (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    1158             sizeof(on));
     1102#if TRACEROUTE_SO_DEBUG
     1103    if (op & OPT_DEBUG)
     1104        setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
     1105                &const_int_1, sizeof(const_int_1));
     1106#endif
     1107    if (op & OPT_BYPASS_ROUTE)
     1108        setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
     1109                &const_int_1, sizeof(const_int_1));
    11591110
    11601111    /* Revert to non-privileged user after opening sockets */
     
    11621113    xsetuid(getuid());
    11631114
    1164     outip = (struct ip *)xcalloc(1, (unsigned)packlen);
     1115    outip = xzalloc(packlen);
    11651116
    11661117    outip->ip_v = IPVERSION;
     
    11741125    outip->ip_hl = (outp - (unsigned char *)outip) >> 2;
    11751126    ident = (getpid() & 0xffff) | 0x8000;
    1176 #ifdef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
     1127#if ENABLE_FEATURE_TRACEROUTE_USE_ICMP
    11771128    if (useicmp) {
    11781129        outip->ip_p = IPPROTO_ICMP;
    1179 
    11801130        outicmp = (struct icmp *)outp;
    11811131        outicmp->icmp_type = ICMP_ECHO;
    11821132        outicmp->icmp_id = htons(ident);
    1183 
    11841133        outdata = (struct outdata *)(outp + 8); /* XXX magic number */
    11851134    } else
    11861135#endif
    1187            {
     1136    {
    11881137        outip->ip_p = IPPROTO_UDP;
    1189 
    11901138        outudp = (struct udphdr *)outp;
    11911139        outudp->source = htons(ident);
    1192         outudp->len =
    1193             htons((u_short)(packlen - (sizeof(*outip) + optlen)));
     1140        outudp->len = htons((uint16_t)(packlen - (sizeof(*outip) + optlen)));
    11941141        outdata = (struct outdata *)(outudp + 1);
    11951142    }
     
    11991146
    12001147    /* Look for a specific device */
    1201     if (device != NULL) {
     1148    if (op & OPT_DEVICE) {
    12021149        for (i = n; i > 0; --i, ++al)
    12031150            if (strcmp(device, al->device) == 0)
    1204                 break;
    1205         if (i <= 0) {
    1206             bb_error_msg_and_die("Can't find interface %s", device);
    1207         }
    1208     }
     1151                goto found_dev;
     1152        bb_error_msg_and_die("can't find interface %s", device);
     1153    }
     1154 found_dev:
    12091155
    12101156    /* Determine our source address */
    1211     if (source == NULL) {
     1157    if (!(op & OPT_SOURCE)) {
    12121158        /*
    12131159         * If a device was specified, use the interface address.
    12141160         * Otherwise, try to determine our source address.
    12151161         */
    1216         if (device != NULL)
     1162        if (op & OPT_DEVICE)
    12171163            setsin(from, al->addr);
    12181164        findsaddr(to, from);
     
    12271173         * there are more than one).
    12281174         */
    1229         if (device != NULL) {
     1175        if (op & OPT_DEVICE) {
    12301176            for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
    12311177                if (*ap == al->addr)
    1232                     break;
    1233             if (i <= 0) {
    1234                 bb_error_msg_and_die(
    1235                     "%s is not on interface %s",
    1236                     source, device);
    1237             }
     1178                    goto found_dev2;
     1179            bb_error_msg_and_die("%s is not on interface %s",
     1180                    source, device);
     1181 found_dev2:
    12381182            setsin(from, *ap);
    12391183        } else {
     
    12411185            if (hi->n > 1)
    12421186                bb_error_msg(
    1243             "Warning: %s has multiple addresses; using %s",
     1187            "warning: %s has multiple addresses; using %s",
    12441188                    source, inet_ntoa(from->sin_addr));
    12451189        }
     
    12491193    outip->ip_src = from->sin_addr;
    12501194#ifndef IP_HDRINCL
    1251     bb_xbind(sndsock, (struct sockaddr *)from, sizeof(*from));
    1252 #endif
    1253 
    1254     fprintf(stderr, "traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
    1255     if (source)
    1256         fprintf(stderr, " from %s", source);
    1257     fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
    1258     (void)fflush(stderr);
     1195    xbind(sndsock, (struct sockaddr *)from, sizeof(*from));
     1196#endif
     1197
     1198    printf("traceroute to %s (%s)", hostname, inet_ntoa(to->sin_addr));
     1199    if (op & OPT_SOURCE)
     1200        printf(" from %s", source);
     1201    printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
     1202    fflush(stdout);
    12591203
    12601204    for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
    1261         u_int32_t lastaddr = 0;
     1205        uint32_t lastaddr = 0;
    12621206        int gotlastaddr = 0;
    12631207        int got_there = 0;
     
    12681212        for (probe = 0; probe < nprobes; ++probe) {
    12691213            int cc;
    1270             struct timeval t1, t2;
    1271             struct timezone tz;
     1214            unsigned t1;
     1215            unsigned t2;
    12721216            struct ip *ip;
    12731217
    12741218            if (sentfirst && pausemsecs > 0)
    12751219                usleep(pausemsecs * 1000);
    1276             (void)gettimeofday(&t1, &tz);
    1277             send_probe(++seq, ttl, &t1);
     1220            t1 = monotonic_us();
     1221            send_probe(++seq, ttl);
    12781222            ++sentfirst;
    1279             while ((cc = wait_for_reply(s, from, &t1)) != 0) {
    1280                 (void)gettimeofday(&t2, &tz);
     1223            while ((cc = wait_for_reply(s, from)) != 0) {
     1224                t2 = monotonic_us();
    12811225                i = packet_ok(packet, cc, from, seq);
    12821226                /* Skip short packet */
     
    12891233                    ++gotlastaddr;
    12901234                }
    1291                 printf("  %.3f ms", deltaT(&t1, &t2));
     1235                print_delta_ms(t1, t2);
    12921236                ip = (struct ip *)packet;
    1293                 if (op & USAGE_OP_TTL_FLAG)
     1237                if (op & OPT_TTL_FLAG)
    12941238                    printf(" (%d)", ip->ip_ttl);
    12951239                if (i == -2) {
Note: See TracChangeset for help on using the changeset viewer.