sulogin: use bb_error_msg instead of bb_info_msg; better message
[oweals/busybox.git] / networking / traceroute.c
index d197e54101058933120c64d2180d23f3b1a1bb3f..eee4f8873a1230723cb05d2f23e896378742659d 100644 (file)
  */
 
 //usage:#define traceroute_trivial_usage
-//usage:       "[-"IF_TRACEROUTE6("46")"FIldnrv] [-f 1ST_TTL] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
-//usage:       "       [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-g GATEWAY] [-i IFACE]\n"
+//usage:       "[-"IF_TRACEROUTE6("46")"FIlnrv] [-f 1ST_TTL] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
+//usage:       "       [-t TOS] [-w WAIT_SEC]"
+//usage:       IF_FEATURE_TRACEROUTE_SOURCE_ROUTE(" [-g GATEWAY]")" [-s SRC_IP] [-i IFACE]\n"
 //usage:       "       [-z PAUSE_MSEC] HOST [BYTES]"
 //usage:#define traceroute_full_usage "\n\n"
 //usage:       "Trace the route to HOST\n"
 //usage:       IF_TRACEROUTE6(
 //usage:     "\n       -4,-6   Force IP or IPv6 name resolution"
 //usage:       )
-//usage:     "\n       -F      Set the don't fragment bit"
+//usage:     "\n       -F      Set don't fragment bit"
+//usage:       IF_FEATURE_TRACEROUTE_USE_ICMP(
 //usage:     "\n       -I      Use ICMP ECHO instead of UDP datagrams"
-//usage:     "\n       -l      Display the TTL value of the returned packet"
-//usage:     "\n       -d      Set SO_DEBUG options to socket"
+//usage:       )
+//usage:     "\n       -l      Display TTL value of the returned packet"
+//Currently disabled (TRACEROUTE_SO_DEBUG==0)
+////usage:     "\n     -d      Set SO_DEBUG options to socket"
 //usage:     "\n       -n      Print numeric addresses"
 //usage:     "\n       -r      Bypass routing tables, send directly to HOST"
+//usage:       IF_FEATURE_TRACEROUTE_VERBOSE(
 //usage:     "\n       -v      Verbose"
-//usage:     "\n       -m      Max time-to-live (max number of hops)"
-//usage:     "\n       -p      Base UDP port number used in probes"
+//usage:       )
+//usage:     "\n       -f N    First number of hops (default 1)"
+//usage:     "\n       -m N    Max number of hops"
+//usage:     "\n       -q N    Number of probes per hop (default 3)"
+//usage:     "\n       -p N    Base UDP port number used in probes"
 //usage:     "\n               (default 33434)"
-//usage:     "\n       -q      Number of probes per TTL (default 3)"
-//usage:     "\n       -s      IP address to use as the source address"
-//usage:     "\n       -t      Type-of-service in probe packets (default 0)"
-//usage:     "\n       -w      Time in seconds to wait for a response (default 3)"
-//usage:     "\n       -g      Loose source route gateway (8 max)"
+//usage:     "\n       -s IP   Source address"
+//usage:     "\n       -i IFACE Source interface"
+//usage:     "\n       -t N    Type-of-service in probe packets (default 0)"
+//usage:     "\n       -w SEC  Time to wait for a response (default 3)"
+//usage:     "\n       -g IP   Loose source route gateway (8 max)"
 //usage:
 //usage:#define traceroute6_trivial_usage
-//usage:       "[-dnrv] [-m MAXTTL] [-p PORT] [-q PROBES]\n"
-//usage:       "       [-s SRC_IP] [-t TOS] [-w WAIT_SEC] [-i IFACE]\n"
+//usage:       "[-nrv] [-m MAXTTL] [-q PROBES] [-p PORT]\n"
+//usage:       "       [-t TOS] [-w WAIT_SEC] [-s SRC_IP] [-i IFACE]\n"
 //usage:       "       HOST [BYTES]"
 //usage:#define traceroute6_full_usage "\n\n"
 //usage:       "Trace the route to HOST\n"
-//usage:     "\n       -d      Set SO_DEBUG options to socket"
+//Currently disabled (TRACEROUTE_SO_DEBUG==0)
+////usage:     "\n     -d      Set SO_DEBUG options to socket"
 //usage:     "\n       -n      Print numeric addresses"
 //usage:     "\n       -r      Bypass routing tables, send directly to HOST"
+//usage:       IF_FEATURE_TRACEROUTE_VERBOSE(
 //usage:     "\n       -v      Verbose"
-//usage:     "\n       -m      Max time-to-live (max number of hops)"
-//usage:     "\n       -p      Base UDP port number used in probes"
-//usage:     "\n               (default is 33434)"
-//usage:     "\n       -q      Number of probes per TTL (default 3)"
-//usage:     "\n       -s      IP address to use as the source address"
-//usage:     "\n       -t      Type-of-service in probe packets (default 0)"
-//usage:     "\n       -w      Time in seconds to wait for a response (default 3)"
+//usage:       )
+//usage:     "\n       -m N    Max number of hops"
+//usage:     "\n       -q N    Number of probes per hop (default 3)"
+//usage:     "\n       -p N    Base UDP port number used in probes"
+//usage:     "\n               (default 33434)"
+//usage:     "\n       -s IP   Source address"
+//usage:     "\n       -i IFACE Source interface"
+//usage:     "\n       -t N    Type-of-service in probe packets (default 0)"
+//usage:     "\n       -w SEC  Time wait for a response (default 3)"
 
 #define TRACEROUTE_SO_DEBUG 0
 
-/* TODO: undefs were uncommented - ??! we have config system for that! */
-/* probably ok to remove altogether */
-//#undef CONFIG_FEATURE_TRACEROUTE_VERBOSE
-//#define CONFIG_FEATURE_TRACEROUTE_VERBOSE
-//#undef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
-//#define CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
-//#undef CONFIG_FEATURE_TRACEROUTE_USE_ICMP
-//#define CONFIG_FEATURE_TRACEROUTE_USE_ICMP
-
-
 #include <net/if.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #endif
 
 
-#define OPT_STRING "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
-                   IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
-                   "4" IF_TRACEROUTE6("6")
+#define OPT_STRING \
+       "FIlnrdvxt:i:m:p:q:s:w:z:f:" \
+       IF_FEATURE_TRACEROUTE_SOURCE_ROUTE("g:") \
+       "4" IF_TRACEROUTE6("6")
 enum {
        OPT_DONT_FRAGMNT = (1 << 0),    /* F */
        OPT_USE_ICMP     = (1 << 1) * ENABLE_FEATURE_TRACEROUTE_USE_ICMP, /* I */
@@ -386,15 +389,6 @@ struct globals {
 #define outudp  ((struct udphdr *)(outip + 1))
 
 
-/* libbb candidate? tftp uses this idiom too */
-static len_and_sockaddr* dup_sockaddr(const len_and_sockaddr *lsa)
-{
-       len_and_sockaddr *new_lsa = xzalloc(LSA_LEN_SIZE + lsa->len);
-       memcpy(new_lsa, lsa, LSA_LEN_SIZE + lsa->len);
-       return new_lsa;
-}
-
-
 static int
 wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
 {
@@ -479,18 +473,18 @@ send_probe(int seq, int ttl)
 
 #if ENABLE_TRACEROUTE6
        if (dest_lsa->u.sa.sa_family == AF_INET6) {
-               res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
-               if (res < 0)
-                       bb_perror_msg_and_die("setsockopt UNICAST_HOPS %d", ttl);
+               res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
+               if (res != 0)
+                       bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl);
                out = outip;
                len = packlen;
        } else
 #endif
        {
 #if defined IP_TTL
-               res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
-               if (res < 0)
-                       bb_perror_msg_and_die("setsockopt ttl %d", ttl);
+               res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl);
+               if (res != 0)
+                       bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
 #endif
                out = outicmp;
                len = packlen - sizeof(*outip);
@@ -503,7 +497,7 @@ send_probe(int seq, int ttl)
 
        res = xsendto(sndsock, out, len, &dest_lsa->u.sa, dest_lsa->len);
        if (res != len)
-               bb_info_msg("sent %d octets, ret=%d", len, res);
+               bb_error_msg("sent %d octets, ret=%d", len, res);
 }
 
 #if ENABLE_FEATURE_TRACEROUTE_VERBOSE
@@ -790,7 +784,9 @@ static int
 common_traceroute_main(int op, char **argv)
 {
        int minpacket;
+#ifdef IP_TOS
        int tos = 0;
+#endif
        int max_ttl = 30;
        int nprobes = 3;
        int first_ttl = 1;
@@ -804,6 +800,7 @@ common_traceroute_main(int op, char **argv)
        char *waittime_str;
        char *pausemsecs_str;
        char *first_ttl_str;
+       char *dest_str;
 #if ENABLE_FEATURE_TRACEROUTE_SOURCE_ROUTE
        llist_t *source_route_list = NULL;
        int lsrr = 0;
@@ -836,8 +833,10 @@ common_traceroute_main(int op, char **argv)
        if (op & OPT_IP_CHKSUM)
                bb_error_msg("warning: ip checksums disabled");
 #endif
+#ifdef IP_TOS
        if (op & OPT_TOS)
                tos = xatou_range(tos_str, 0, 255);
+#endif
        if (op & OPT_MAX_TTL)
                max_ttl = xatou_range(max_ttl_str, 1, 255);
        if (op & OPT_PORT)
@@ -903,13 +902,10 @@ common_traceroute_main(int op, char **argv)
        if (af == AF_INET6) {
                xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
 # ifdef IPV6_RECVPKTINFO
-               setsockopt(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO,
-                               &const_int_1, sizeof(const_int_1));
-               setsockopt(rcvsock, SOL_IPV6, IPV6_2292PKTINFO,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
+               setsockopt_1(rcvsock, SOL_IPV6, IPV6_2292PKTINFO);
 # else
-               setsockopt(rcvsock, SOL_IPV6, IPV6_PKTINFO,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_1(rcvsock, SOL_IPV6, IPV6_PKTINFO);
 # endif
        } else
 #endif
@@ -919,18 +915,15 @@ common_traceroute_main(int op, char **argv)
 
 #if TRACEROUTE_SO_DEBUG
        if (op & OPT_DEBUG)
-               setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG);
 #endif
        if (op & OPT_BYPASS_ROUTE)
-               setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE);
 
 #if ENABLE_TRACEROUTE6
        if (af == AF_INET6) {
-               static const int two = 2;
-               if (setsockopt(rcvsock, SOL_RAW, IPV6_CHECKSUM, &two, sizeof(two)) < 0)
-                       bb_perror_msg_and_die("setsockopt RAW_CHECKSUM");
+               if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
+                       bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
                xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock);
        } else
 #endif
@@ -967,28 +960,25 @@ common_traceroute_main(int op, char **argv)
        }
 
 #ifdef SO_SNDBUF
-       if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) {
-               bb_perror_msg_and_die("SO_SNDBUF");
+       if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
+               bb_perror_msg_and_die("setsockopt(%s)", "SO_SNDBUF");
        }
 #endif
 #ifdef IP_TOS
-       if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) {
-               bb_perror_msg_and_die("setsockopt tos %d", tos);
+       if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) {
+               bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos);
        }
 #endif
 #ifdef IP_DONTFRAG
        if (op & OPT_DONT_FRAGMNT)
-               setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_1(sndsock, IPPROTO_IP, IP_DONTFRAG);
 #endif
 #if TRACEROUTE_SO_DEBUG
        if (op & OPT_DEBUG)
-               setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_SOL_SOCKET_1(sndsock, SO_DEBUG);
 #endif
        if (op & OPT_BYPASS_ROUTE)
-               setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
-                               &const_int_1, sizeof(const_int_1));
+               setsockopt_SOL_SOCKET_1(sndsock, SO_DONTROUTE);
 
        outip = xzalloc(packlen);
 
@@ -1058,13 +1048,17 @@ common_traceroute_main(int op, char **argv)
        xsetgid(getgid());
        xsetuid(getuid());
 
-       printf("traceroute to %s (%s)", argv[0],
-                       xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa));
+       dest_str = xmalloc_sockaddr2dotted_noport(&dest_lsa->u.sa);
+       printf("traceroute to %s (%s)", argv[0], dest_str);
+       if (ENABLE_FEATURE_CLEAN_UP) {
+               free(dest_str);
+       }
+
        if (op & OPT_SOURCE)
                printf(" from %s", source);
        printf(", %d hops max, %d byte packets\n", max_ttl, packlen);
 
-       from_lsa = dup_sockaddr(dest_lsa);
+       from_lsa = xmemdup(dest_lsa, LSA_LEN_SIZE + dest_lsa->len);
        lastaddr = xzalloc(dest_lsa->len);
        to = xzalloc(dest_lsa->len);
        seq = 0;
@@ -1215,6 +1209,12 @@ common_traceroute_main(int op, char **argv)
                }
        }
 
+       if (ENABLE_FEATURE_CLEAN_UP) {
+               free(to);
+               free(lastaddr);
+               free(from_lsa);
+       }
+
        return 0;
 }