summaryrefslogtreecommitdiffstats
path: root/source/n/traceroute/traceroute_1.4a12-5.diff
diff options
context:
space:
mode:
Diffstat (limited to 'source/n/traceroute/traceroute_1.4a12-5.diff')
-rw-r--r--source/n/traceroute/traceroute_1.4a12-5.diff1152
1 files changed, 1152 insertions, 0 deletions
diff --git a/source/n/traceroute/traceroute_1.4a12-5.diff b/source/n/traceroute/traceroute_1.4a12-5.diff
new file mode 100644
index 000000000..8cf3d1fe1
--- /dev/null
+++ b/source/n/traceroute/traceroute_1.4a12-5.diff
@@ -0,0 +1,1152 @@
+--- traceroute-1.4a12.orig/aclocal.m4
++++ traceroute-1.4a12/aclocal.m4
+@@ -47,7 +47,7 @@
+ AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+ AC_BEFORE([$0], [AC_LBL_DEVEL])
+ AC_ARG_WITH(gcc, [ --without-gcc don't use gcc])
+- $1="-O"
++ $1="-g -O"
+ $2=""
+ if test "${srcdir}" != "." ; then
+ $2="-I\$\(srcdir\)"
+@@ -677,12 +677,11 @@
+ AC_TRY_LINK(dnl
+ ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+ [/* Override any gcc2 internal prototype to avoid an error. */
+-]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
++#ifdef __cplusplus
+ extern "C"
+ #endif
+-])dnl
+-[/* We use char because int might match the return type of a gcc2
+- builtin and then its argument prototype would still apply. */
++/* We use char because int might match the return type of a gcc2
++ builtin and then its argument prototype would still apply. */
+ char $2();
+ ]),
+ [$2()],
+--- traceroute-1.4a12.orig/configure.in
++++ traceroute-1.4a12/configure.in
+@@ -22,7 +22,7 @@
+ net/if_dl.h inet/mib2.h)
+
+ AC_REPLACE_FUNCS(strerror usleep)
+-AC_CHECK_FUNCS(setlinebuf)
++AC_CHECK_FUNCS(setlinebuf snprintf)
+ if test $ac_cv_func_usleep = "no" ; then
+ AC_CHECK_FUNCS(nanosleep)
+ fi
+@@ -44,8 +44,9 @@
+ ;;
+
+ linux*)
+- V_INCLS="$V_INCLS -Ilinux-include"
++ V_INCLS="$V_INCLS -Ilinux-include -DUSE_KERNEL_ROUTING_TABLE"
+ AC_DEFINE(BYTESWAP_IP_HDR)
++ AC_DEFINE(HAVE_RAW_OPTIONS)
+ ;;
+
+ osf3*)
+--- traceroute-1.4a12.orig/findsaddr-generic.c
++++ traceroute-1.4a12/findsaddr-generic.c
+@@ -82,7 +82,11 @@
+ static char errbuf[132];
+
+ /* Get the interface address list */
++#if HAVE_SNPRINTF
++ if ((n = ifaddrlist(&al, errbuf, sizeof(errbuf))) < 0)
++#else
+ if ((n = ifaddrlist(&al, errbuf)) < 0)
++#endif
+ return (errbuf);
+
+ if (n == 0)
+--- traceroute-1.4a12.orig/findsaddr-linux.c
++++ traceroute-1.4a12/findsaddr-linux.c
+@@ -90,7 +90,11 @@
+ static char errbuf[132];
+
+ if ((f = fopen(route, "r")) == NULL) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "open %s: %.128s", route, strerror(errno));
++#else
+ sprintf(errbuf, "open %s: %.128s", route, strerror(errno));
++#endif
+ return (errbuf);
+ }
+
+@@ -102,7 +106,7 @@
+ ++n;
+ if (n == 1 && strncmp(buf, "Iface", 5) == 0)
+ continue;
+- if ((i = sscanf(buf, "%s %x %*s %*s %*s %*s %*s %x",
++ if ((i = sscanf(buf, "%255s %x %*s %*s %*s %*s %*s %x",
+ tdevice, &dest, &tmask)) != 3)
+ return ("junk in buffer");
+ if ((to->sin_addr.s_addr & tmask) == dest &&
+@@ -117,7 +121,11 @@
+ return ("Can't find interface");
+
+ /* Get the interface address list */
++#if HAVE_SNPRINTF
++ if ((n = ifaddrlist(&al, errbuf, sizeof(errbuf))) < 0)
++#else
+ if ((n = ifaddrlist(&al, errbuf)) < 0)
++#endif
+ return (errbuf);
+
+ if (n == 0)
+@@ -128,7 +136,11 @@
+ if (strcmp(device, al->device) == 0)
+ break;
+ if (i <= 0) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "Can't find interface \"%.32s\"", device);
++#else
+ sprintf(errbuf, "Can't find interface \"%.32s\"", device);
++#endif
+ return (errbuf);
+ }
+
+--- traceroute-1.4a12.orig/findsaddr-socket.c
++++ traceroute-1.4a12/findsaddr-socket.c
+@@ -114,7 +114,11 @@
+
+ s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
+ if (s < 0) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "socket: %.128s", strerror(errno));
++#else
+ sprintf(errbuf, "socket: %.128s", strerror(errno));
++#endif
+ return (errbuf);
+ }
+
+@@ -134,12 +138,20 @@
+
+ cc = write(s, (char *)rp, size);
+ if (cc < 0) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "write: %.128s", strerror(errno));
++#else
+ sprintf(errbuf, "write: %.128s", strerror(errno));
++#endif
+ close(s);
+ return (errbuf);
+ }
+ if (cc != size) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "short write (%d != %d)", cc, size);
++#else
+ sprintf(errbuf, "short write (%d != %d)", cc, size);
++#endif
+ close(s);
+ return (errbuf);
+ }
+@@ -149,7 +161,11 @@
+ memset(rp, 0, size);
+ cc = read(s, (char *)rp, size);
+ if (cc < 0) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "read: %.128s", strerror(errno));
++#else
+ sprintf(errbuf, "read: %.128s", strerror(errno));
++#endif
+ close(s);
+ return (errbuf);
+ }
+@@ -159,15 +175,27 @@
+
+
+ if (rp->rtm_version != RTM_VERSION) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "bad version %d", rp->rtm_version);
++#else
+ sprintf(errbuf, "bad version %d", rp->rtm_version);
++#endif
+ return (errbuf);
+ }
+ if (rp->rtm_msglen > cc) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "bad msglen %d > %d", rp->rtm_msglen, cc);
++#else
+ sprintf(errbuf, "bad msglen %d > %d", rp->rtm_msglen, cc);
++#endif
+ return (errbuf);
+ }
+ if (rp->rtm_errno != 0) {
++#if HAVE_SNPRINTF
++ snprintf(errbuf, sizeof(errbuf), "rtm_errno: %.128s", strerror(rp->rtm_errno));
++#else
+ sprintf(errbuf, "rtm_errno: %.128s", strerror(rp->rtm_errno));
++#endif
+ return (errbuf);
+ }
+
+--- traceroute-1.4a12.orig/ifaddrlist.c
++++ traceroute-1.4a12/ifaddrlist.c
+@@ -72,7 +72,12 @@
+ * Return the interface list
+ */
+ int
++#if HAVE_SNPRINTF
++ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf,
++ size_t nerrbuf)
++#else
+ ifaddrlist(register struct ifaddrlist **ipaddrp, register char *errbuf)
++#endif
+ {
+ register int fd, nipaddr;
+ #ifdef HAVE_SOCKADDR_SA_LEN
+@@ -89,7 +94,11 @@
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf, "socket: %s", strerror(errno));
++#else
+ (void)sprintf(errbuf, "socket: %s", strerror(errno));
++#endif
+ return (-1);
+ }
+ ifc.ifc_len = sizeof(ibuf);
+@@ -98,12 +107,23 @@
+ if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
+ ifc.ifc_len < sizeof(struct ifreq)) {
+ if (errno == EINVAL)
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf,
++ "SIOCGIFCONF: ifreq struct too small (%d bytes)",
++ sizeof(ibuf));
++#else
+ (void)sprintf(errbuf,
+ "SIOCGIFCONF: ifreq struct too small (%d bytes)",
+ sizeof(ibuf));
++#endif
+ else
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf, "SIOCGIFCONF: %s",
++ strerror(errno));
++#else
+ (void)sprintf(errbuf, "SIOCGIFCONF: %s",
+ strerror(errno));
++#endif
+ (void)close(fd);
+ return (-1);
+ }
+@@ -135,9 +155,15 @@
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ if (errno == ENXIO)
+ continue;
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf, "SIOCGIFFLAGS: %.*s: %s",
++ (int)sizeof(ifr.ifr_name), ifr.ifr_name,
++ strerror(errno));
++#else
+ (void)sprintf(errbuf, "SIOCGIFFLAGS: %.*s: %s",
+ (int)sizeof(ifr.ifr_name), ifr.ifr_name,
+ strerror(errno));
++#endif
+ (void)close(fd);
+ return (-1);
+ }
+@@ -155,21 +181,35 @@
+ continue;
+ #endif
+ if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf, "SIOCGIFADDR: %s: %s",
++ device, strerror(errno));
++#else
+ (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
+ device, strerror(errno));
++#endif
+ (void)close(fd);
+ return (-1);
+ }
+
+ if (nipaddr >= MAX_IPADDR) {
++#if HAVE_SNPRINTF
++ (void)snprintf(errbuf, nerrbuf, "Too many interfaces (%d)",
++ MAX_IPADDR);
++#else
+ (void)sprintf(errbuf, "Too many interfaces (%d)",
+ MAX_IPADDR);
++#endif
+ (void)close(fd);
+ return (-1);
+ }
+ sin = (struct sockaddr_in *)&ifr.ifr_addr;
+ al->addr = sin->sin_addr.s_addr;
+ al->device = strdup(device);
++ if (al->device == NULL) {
++ fputs("ifaddrlist: strdup\n", stderr);
++ exit(1);
++ }
+ ++al;
+ ++nipaddr;
+ }
+--- traceroute-1.4a12.orig/ifaddrlist.h
++++ traceroute-1.4a12/ifaddrlist.h
+@@ -26,4 +26,8 @@
+ char *device;
+ };
+
++#if HAVE_SNPRINTF
++int ifaddrlist(struct ifaddrlist **, char *, size_t);
++#else
+ int ifaddrlist(struct ifaddrlist **, char *);
++#endif
+--- traceroute-1.4a12.orig/traceroute.8
++++ traceroute-1.4a12/traceroute.8
+@@ -23,7 +23,7 @@
+ .na
+ .B traceroute
+ [
+-.B \-dFInrvx
++.B \-dFIlnrvx
+ ] [
+ .B \-f
+ .I first_ttl
+@@ -110,6 +110,10 @@
+ .B \-I
+ Use ICMP ECHO instead of UDP datagrams.
+ .TP
++.B \-l
++Display the ttl value of the returned packet. This is useful for
++checking for assymetric routing.
++.TP
+ .B \-m
+ Set the max time-to-live (max number of hops) used in outgoing probe
+ packets. The default is 30 hops (the same default used for TCP
+@@ -146,9 +150,8 @@
+ multi-homed hosts (those with more than one IP
+ address), this option can be used to
+ force the source address to be something other than the IP address
+-of the interface the probe packet is sent on. If the IP address
+-is not one of this machine's interface addresses, an error is
+-returned and nothing is sent. (See the
++of the interface the probe packet is sent on. This option can only
++be used by the super-user. (See the
+ .B \-i
+ flag for another way to do this.)
+ .TP
+@@ -329,6 +332,9 @@
+ or
+ .B !P
+ (host, network or protocol unreachable),
++.BR !A ,
++.BR !C
++(access to the network or host, respectively, is prohibited),
+ .B !S
+ (source route failed),
+ .B !F\-<pmtu>
+--- traceroute-1.4a12.orig/traceroute.c
++++ traceroute-1.4a12/traceroute.c
+@@ -271,7 +271,7 @@
+ struct outdata {
+ u_char seq; /* sequence number of this packet */
+ u_char ttl; /* ttl packet left with */
+- struct timeval tv; /* time packet left */
++ struct timeval tv __attribute__((packed)); /* time packet left */
+ };
+
+ #ifndef HAVE_ICMP_NEXTMTU
+@@ -296,8 +296,8 @@
+ int s; /* receive (icmp) socket file descriptor */
+ int sndsock; /* send (udp/icmp) socket file descriptor */
+
+-struct sockaddr whereto; /* Who to try to reach */
+-struct sockaddr wherefrom; /* Who we are */
++struct sockaddr_storage whereto; /* Who to try to reach */
++struct sockaddr_storage wherefrom; /* Who we are */
+ int packlen; /* total length of packet */
+ int minpacket; /* min ip packet size */
+ int maxpacket = 32 * 1024; /* max ip packet size */
+@@ -352,6 +352,11 @@
+ int usleep(u_int);
+ #endif
+
++#ifdef USE_KERNEL_ROUTING_TABLE
++struct ifaddrlist *search_routing_table(struct sockaddr_in *to, struct ifaddrlist *al, int n);
++#endif
++
++
+ int
+ main(int argc, char **argv)
+ {
+@@ -370,8 +375,12 @@
+ int tos = 0, settos = 0;
+ register int lsrr = 0;
+ register u_short off = 0;
+- struct ifaddrlist *al;
++ struct ifaddrlist *al, *allist;
+ char errbuf[132];
++ int ttl_flag = 0;
++ int uid;
++
++ uid = getuid();
+
+ if (argv[0] == NULL)
+ prog = "traceroute";
+@@ -381,7 +390,7 @@
+ prog = argv[0];
+
+ opterr = 0;
+- while ((op = getopt(argc, argv, "dFInrvxf:g:i:m:p:q:s:t:w:z:")) != EOF)
++ while ((op = getopt(argc, argv, "dFIlnrvxf:g:i:m:p:q:s:t:w:z:")) != EOF)
+ switch (op) {
+
+ case 'd':
+@@ -397,6 +406,10 @@
+ break;
+
+ case 'g':
++ if (strlen(optarg) >= MAXHOSTNAMELEN) {
++ Fprintf(stderr, "%s: Nice Try !\n", prog);
++ exit(-1);
++ }
+ if (lsrr >= NGATEWAYS) {
+ Fprintf(stderr,
+ "%s: No more than %d gateways\n",
+@@ -409,12 +422,21 @@
+
+ case 'i':
+ device = optarg;
++ if (strlen(device) >= 16) { /* that is the IFNAMSIZ
++ * from kernel headers */
++ Fprintf(stderr, "%s: Nice try !\n", prog);
++ exit(-1);
++ }
+ break;
+
+ case 'I':
+ ++useicmp;
+ break;
+
++ case 'l':
++ ++ttl_flag;
++ break;
++
+ case 'm':
+ max_ttl = str2val(optarg, "max ttl", 1, 255);
+ break;
+@@ -441,7 +463,19 @@
+ * set the ip source address of the outbound
+ * probe (e.g., on a multi-homed host).
+ */
++ if (uid) {
++ Fprintf(
++ stderr,
++ "%s: -s %s: Permission denied\n",
++ prog, optarg
++ );
++ exit(-1);
++ }
+ source = optarg;
++ if (strlen(source) >= MAXHOSTNAMELEN) {
++ Fprintf(stderr, "%s: Nice Try !\n", prog);
++ exit(-1);
++ }
+ break;
+
+ case 't':
+@@ -500,6 +534,10 @@
+
+ case 1:
+ hostname = argv[optind];
++ if (strlen(hostname) >= MAXHOSTNAMELEN) {
++ Fprintf(stderr, "%s: Nice try !\n", prog);
++ exit(-1);
++ }
+ hi = gethostinfo(hostname);
+ setsin(to, hi->addrs[0]);
+ if (hi->n > 1)
+@@ -515,75 +553,6 @@
+ usage();
+ }
+
+-#ifdef HAVE_SETLINEBUF
+- setlinebuf (stdout);
+-#else
+- setvbuf(stdout, NULL, _IOLBF, 0);
+-#endif
+-
+- outip = (struct ip *)malloc((unsigned)packlen);
+- if (outip == NULL) {
+- Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
+- exit(1);
+- }
+- memset((char *)outip, 0, packlen);
+-
+- outip->ip_v = IPVERSION;
+- if (settos)
+- outip->ip_tos = tos;
+-#ifdef BYTESWAP_IP_HDR
+- outip->ip_len = htons(packlen);
+- outip->ip_off = htons(off);
+-#else
+- outip->ip_len = packlen;
+- outip->ip_off = off;
+-#endif
+- outp = (u_char *)(outip + 1);
+-#ifdef HAVE_RAW_OPTIONS
+- if (lsrr > 0) {
+- register u_char *optlist;
+-
+- optlist = outp;
+- outp += optlen;
+-
+- /* final hop */
+- gwlist[lsrr] = to->sin_addr.s_addr;
+-
+- outip->ip_dst.s_addr = gwlist[0];
+-
+- /* force 4 byte alignment */
+- optlist[0] = IPOPT_NOP;
+- /* loose source route option */
+- optlist[1] = IPOPT_LSRR;
+- i = lsrr * sizeof(gwlist[0]);
+- optlist[2] = i + 3;
+- /* Pointer to LSRR addresses */
+- optlist[3] = IPOPT_MINOFF;
+- memcpy(optlist + 4, gwlist + 1, i);
+- } else
+-#endif
+- outip->ip_dst = to->sin_addr;
+-
+- outip->ip_hl = (outp - (u_char *)outip) >> 2;
+- ident = (getpid() & 0xffff) | 0x8000;
+- if (useicmp) {
+- outip->ip_p = IPPROTO_ICMP;
+-
+- outicmp = (struct icmp *)outp;
+- outicmp->icmp_type = ICMP_ECHO;
+- outicmp->icmp_id = htons(ident);
+-
+- outdata = (struct outdata *)(outp + 8); /* XXX magic number */
+- } else {
+- outip->ip_p = IPPROTO_UDP;
+-
+- outudp = (struct udphdr *)outp;
+- outudp->uh_sport = htons(ident);
+- outudp->uh_ulen =
+- htons((u_short)(packlen - (sizeof(*outip) + optlen)));
+- outdata = (struct outdata *)(outudp + 1);
+- }
+-
+ cp = "icmp";
+ if ((pe = getprotobyname(cp)) == NULL) {
+ Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
+@@ -591,12 +560,15 @@
+ }
+
+ /* Insure the socket fds won't be 0, 1 or 2 */
+- if (open(devnull, O_RDONLY) < 0 ||
+- open(devnull, O_RDONLY) < 0 ||
+- open(devnull, O_RDONLY) < 0) {
+- Fprintf(stderr, "%s: open \"%s\": %s\n",
+- prog, devnull, strerror(errno));
+- exit(1);
++ do {
++ if ((n = open(devnull, O_RDONLY)) < 0) {
++ Fprintf(stderr, "%s: open \"%s\": %s\n",
++ prog, devnull, strerror(errno));
++ exit(1);
++ }
++ } while (n < 2);
++ if (n > 2) {
++ close(n);
+ }
+ if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
+ Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
+@@ -662,7 +634,7 @@
+ #endif
+ #ifdef IP_HDRINCL
+ if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
+- sizeof(on)) < 0) {
++ sizeof(on)) < 0 && errno != ENOPROTOOPT) {
+ Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
+ exit(1);
+ }
+@@ -683,8 +655,88 @@
+ (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
+ sizeof(on));
+
++ /* Revert to non-privileged user after opening sockets */
++ setgid(getgid());
++ setuid(uid);
++
++#ifndef __GLIBC__
++#ifdef HAVE_SETLINEBUF
++ setlinebuf (stdout);
++#else
++ setvbuf(stdout, NULL, _IOLBF, 0);
++#endif
++#endif
++
++ outip = (struct ip *)malloc((unsigned)packlen);
++ if (outip == NULL) {
++ Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
++ exit(1);
++ }
++ memset((char *)outip, 0, packlen);
++
++ outip->ip_v = IPVERSION;
++ if (settos)
++ outip->ip_tos = tos;
++#ifdef BYTESWAP_IP_HDR
++ outip->ip_len = htons(packlen);
++ outip->ip_off = htons(off);
++#else
++ outip->ip_len = packlen;
++ outip->ip_off = off;
++#endif
++ outp = (u_char *)(outip + 1);
++#ifdef HAVE_RAW_OPTIONS
++ if (lsrr > 0) {
++ register u_char *optlist;
++
++ optlist = outp;
++ outp += optlen;
++
++ /* final hop */
++ gwlist[lsrr] = to->sin_addr.s_addr;
++
++ outip->ip_dst.s_addr = gwlist[0];
++
++ /* force 4 byte alignment */
++ optlist[0] = IPOPT_NOP;
++ /* loose source route option */
++ optlist[1] = IPOPT_LSRR;
++ i = lsrr * sizeof(gwlist[0]);
++ optlist[2] = i + 3;
++ /* Pointer to LSRR addresses */
++ optlist[3] = IPOPT_MINOFF;
++ memcpy(optlist + 4, gwlist + 1, i);
++ } else
++#endif
++ outip->ip_dst = to->sin_addr;
++
++ outip->ip_hl = (outp - (u_char *)outip) >> 2;
++ ident = (getpid() & 0xffff) | 0x8000;
++ if (useicmp) {
++ outip->ip_p = IPPROTO_ICMP;
++
++ outicmp = (struct icmp *)outp;
++ outicmp->icmp_type = ICMP_ECHO;
++ outicmp->icmp_id = htons(ident);
++
++ outdata = (struct outdata *)(outp + 8); /* XXX magic number */
++ } else {
++ outip->ip_p = IPPROTO_UDP;
++
++ outudp = (struct udphdr *)outp;
++ outudp->uh_sport = htons(ident);
++ outudp->uh_ulen =
++ htons((u_short)(packlen - (sizeof(*outip) + optlen)));
++ outdata = (struct outdata *)(outudp + 1);
++ }
++
+ /* Get the interface address list */
+- n = ifaddrlist(&al, errbuf);
++#if HAVE_SNPRINTF
++ n = ifaddrlist(&allist, errbuf, sizeof(errbuf));
++#else
++ n = ifaddrlist(&allist, errbuf);
++#endif
++ al = allist;
+ if (n < 0) {
+ Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
+ exit(1);
+@@ -709,6 +761,15 @@
+
+ /* Determine our source address */
+ if (source == NULL) {
++#ifdef USE_KERNEL_ROUTING_TABLE
++ /* Search the kernel routing table for a match with the
++ * destination address. Then use that interface. If
++ * there is no match, default to using the first
++ * interface found.
++ */
++ al = search_routing_table(to, allist, n);
++ setsin(from, al->addr);
++#else
+ /*
+ * If a device was specified, use the interface address.
+ * Otherwise, try to determine our source address.
+@@ -720,6 +781,7 @@
+ prog, err);
+ exit(1);
+ }
++#endif
+ } else {
+ hi = gethostinfo(source);
+ source = hi->name;
+@@ -751,10 +813,6 @@
+ freehostinfo(hi);
+ }
+
+- /* Revert to non-privileged user after opening sockets */
+- setgid(getgid());
+- setuid(getuid());
+-
+ outip->ip_src = from->sin_addr;
+ #ifndef IP_HDRINCL
+ if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
+@@ -803,9 +861,11 @@
+ ++gotlastaddr;
+ }
+ Printf(" %.3f ms", deltaT(&t1, &t2));
++ ip = (struct ip *)packet;
++ if (ttl_flag)
++ Printf(" (%d)", ip->ip_ttl);
+ if (i == -2) {
+ #ifndef ARCHAIC
+- ip = (struct ip *)packet;
+ if (ip->ip_ttl <= 1)
+ Printf(" !");
+ #endif
+@@ -820,7 +880,6 @@
+
+ case ICMP_UNREACH_PORT:
+ #ifndef ARCHAIC
+- ip = (struct ip *)packet;
+ if (ip->ip_ttl <= 1)
+ Printf(" !");
+ #endif
+@@ -853,8 +912,14 @@
+ break;
+
+ case ICMP_UNREACH_FILTER_PROHIB:
++ case ICMP_UNREACH_NET_PROHIB: /* misuse */
++ ++unreachable;
++ Printf(" !A");
++ break;
++
++ case ICMP_UNREACH_HOST_PROHIB:
+ ++unreachable;
+- Printf(" !X");
++ Printf(" !C");
+ break;
+
+ case ICMP_UNREACH_HOST_PRECEDENCE:
+@@ -867,6 +932,23 @@
+ Printf(" !C");
+ break;
+
++ case ICMP_UNREACH_NET_UNKNOWN:
++ case ICMP_UNREACH_HOST_UNKNOWN:
++ ++unreachable;
++ Printf(" !U");
++ break;
++
++ case ICMP_UNREACH_ISOLATED:
++ ++unreachable;
++ Printf(" !I");
++ break;
++
++ case ICMP_UNREACH_TOSNET:
++ case ICMP_UNREACH_TOSHOST:
++ ++unreachable;
++ Printf(" !T");
++ break;
++
+ default:
+ ++unreachable;
+ Printf(" !<%d>", code);
+@@ -894,7 +976,7 @@
+ struct timeval now, wait;
+ struct timezone tz;
+ register int cc = 0;
+- int fromlen = sizeof(*fromp);
++ socklen_t fromlen = sizeof(*fromp);
+
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+@@ -938,7 +1020,7 @@
+ /* Payload */
+ outdata->seq = seq;
+ outdata->ttl = ttl;
+- outdata->tv = *tp;
++ memcpy(&outdata->tv, tp, sizeof(outdata->tv));
+
+ if (useicmp)
+ outicmp->icmp_seq = htons(seq);
+@@ -1003,12 +1085,13 @@
+
+ #ifdef __hpux
+ cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
+- packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
++ packlen - (sizeof(*outip) + optlen), 0,
++ (struct sockaddr *)&whereto, sizeof(whereto));
+ if (cc > 0)
+ cc += sizeof(*outip) + optlen;
+ #else
+ cc = sendto(sndsock, (char *)outip,
+- packlen, 0, &whereto, sizeof(whereto));
++ packlen, 0, (struct sockaddr *)&whereto, sizeof(whereto));
+ #endif
+ if (cc < 0 || cc != packlen) {
+ if (cc < 0)
+@@ -1039,12 +1122,12 @@
+ static char *ttab[] = {
+ "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
+ "Source Quench", "Redirect", "ICMP 6", "ICMP 7",
+- "Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
++ "Echo", "Router Advert", "Router Solicit", "Time Exceeded",
+ "Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
+- "Info Reply"
++ "Info Reply", "Mask Request", "Mask Reply"
+ };
+
+- if (t > 16)
++ if (t > 18)
+ return("OUT-OF-RANGE");
+
+ return(ttab[t]);
+@@ -1272,6 +1355,11 @@
+ addr = inet_addr(hostname);
+ if ((int32_t)addr != -1) {
+ hi->name = strdup(hostname);
++ if (hi->name == NULL) {
++ Fprintf(stderr, "%s: strdup %s\n",
++ prog, strerror(errno));
++ exit(1);
++ }
+ hi->n = 1;
+ hi->addrs = calloc(1, sizeof(hi->addrs[0]));
+ if (hi->addrs == NULL) {
+@@ -1293,6 +1381,11 @@
+ exit(1);
+ }
+ hi->name = strdup(hp->h_name);
++ if (hi->name == NULL) {
++ Fprintf(stderr, "%s: strdup %s\n",
++ prog, strerror(errno));
++ exit(1);
++ }
+ for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
+ continue;
+ hi->n = n;
+@@ -1381,8 +1474,96 @@
+
+ Fprintf(stderr, "Version %s\n", version);
+ Fprintf(stderr,
+- "Usage: %s [-dFInrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
++ "Usage: %s [-dFIlnrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
+ "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
+ "\t[-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
+ exit(1);
+ }
++
++
++#ifdef USE_KERNEL_ROUTING_TABLE
++
++/* This function currently only supports IPv4. Someone who knows
++ * more about multi-protocol socket stuff should take a look at this.
++ *
++ * (But does it make any sense for traceroute to support other
++ * protocols? Maybe IPv6...
++ */
++
++struct ifaddrlist *search_routing_table(struct sockaddr_in *to, struct ifaddrlist *al, int n)
++{
++ struct ifaddrlist *first_if;
++ FILE *fp;
++ char buf[1024];
++ char ifname[128];
++ unsigned int route_dest;
++ unsigned int mask;
++ char best_name[128];
++ unsigned int best_mask;
++ unsigned int dest_addr;
++ unsigned int convs;
++
++ /* How come using ntohl(to->sin_addr.s_addr) doesn't work here? */
++ dest_addr = to->sin_addr.s_addr;
++
++ fp = fopen("/proc/net/route", "r");
++ if (fp == NULL) {
++ return al;
++ }
++
++ /* Skip the first line (the column headings) */
++ if (fgets(buf, sizeof(buf), fp) == NULL) {
++ fclose(fp);
++ return al;
++ }
++
++ best_name[0] = '\0';
++ best_mask = 0;
++
++ while (fgets(buf, sizeof(buf), fp) != NULL) {
++ /* Field 1: interface name
++ * Field 2: dest addr
++ * Field 8: genmask
++ */
++ convs = sscanf(buf, "%127s %x %*s %*s %*s %*s %*s %x",
++ ifname, &route_dest, &mask);
++ if (convs != 3) {
++ /* format error .... */
++ fclose(fp);
++ return al;
++ }
++
++ if ((dest_addr & mask) == route_dest) {
++ /* This routing entry applies to
++ * our destination addr
++ */
++ if ((mask > best_mask) || (best_mask == 0)) {
++ /* And it is more specific than any
++ * previous match (or is the first match)
++ */
++ best_mask = mask;
++ strncpy(best_name, ifname,
++ sizeof(best_name) - 1);
++ best_name[sizeof(best_name) - 1] = 0;
++ }
++ }
++ }
++
++ fclose(fp);
++
++ /* If we don't find a match, we'll return the first entry */
++ first_if = al;
++
++ while (al < first_if + n) {
++ if (strcmp(best_name, al->device) == 0) {
++ /* Got a match */
++ return al;
++ }
++ al++;
++ }
++
++ return first_if;
++}
++
++#endif
++
+--- traceroute-1.4a12.orig/debian/changelog
++++ traceroute-1.4a12/debian/changelog
+@@ -0,0 +1,63 @@
++traceroute (1.4a12-5) unstable; urgency=low
++
++ * Restrict the -s option to the super-user.
++ * Updated documentation for the -s option (closes: #105362).
++
++ -- Herbert Xu <herbert@debian.org> Mon, 16 Jul 2001 19:28:45 +1000
++
++traceroute (1.4a12-4) unstable; urgency=low
++
++ * Updated aclocal.m4 for autoconf 2.50 (closes: #98367).
++
++ -- Herbert Xu <herbert@debian.org> Wed, 23 May 2001 18:48:59 +1000
++
++traceroute (1.4a12-3) unstable; urgency=low
++
++ * Drop privileges earlier.
++ * Applied "paranoia" patch from Richard Kettlewell (closes: #85619).
++ - eliminate unbounded sprintf calls
++ - eliminate unbounded sscanf calls
++ - strncpy final-null paranoia
++ * Set HAVE_RAW_OPTIONS (closes: #78475).
++ * Added missing option to usage (Neale Banks, closes: #88892).
++
++ -- Herbert Xu <herbert@debian.org> Fri, 9 Mar 2001 22:24:11 +1100
++
++traceroute (1.4a12-2) unstable; urgency=low
++
++ * Made changes for dpkg-statoverride (closes: #83817).
++
++ -- Herbert Xu <herbert@debian.org> Sun, 28 Jan 2001 21:49:35 +1100
++
++traceroute (1.4a12-1) unstable; urgency=low
++
++ * New upstream release (closes: #79920, #81395).
++ * Use struct sockaddr_stroage (closes: #79348).
++
++ -- Herbert Xu <herbert@debian.org> Fri, 26 Jan 2001 20:57:21 +1100
++
++traceroute (1.4a8-1) unstable; urgency=low
++
++ * New upstream release.
++
++ -- Herbert Xu <herbert@debian.org> Sat, 9 Dec 2000 14:18:00 +1100
++
++traceroute (1.4a5-3) stable unstable; urgency=low
++
++ * Fixed a bug where free(3) was called on non-malloced memory.
++
++ -- Herbert Xu <herbert@debian.org> Thu, 24 Aug 2000 20:44:51 +1000
++
++traceroute (1.4a5-2) frozen unstable; urgency=low
++
++ * Use config.* from automake, needed for building traceroute on ARM
++ (closes: #61267).
++
++ -- Herbert Xu <herbert@debian.org> Fri, 31 Mar 2000 07:50:33 +1000
++
++traceroute (1.4a5-1) unstable; urgency=low
++
++ * Initial release (closes: #34166).
++
++ -- Herbert Xu <herbert@debian.org> Mon, 1 Nov 1999 15:11:06 +1100
++
+--- traceroute-1.4a12.orig/debian/control
++++ traceroute-1.4a12/debian/control
+@@ -0,0 +1,22 @@
++Source: traceroute
++Section: net
++Priority: optional
++Maintainer: Herbert Xu <herbert@debian.org>
++Standards-Version: 3.5.5
++Build-Depends: automake, autoconf, debhelper
++
++Package: traceroute
++Architecture: any
++Depends: ${shlibs:Depends}
++Conflicts: suidmanager (<< 0.50)
++Replaces: netstd
++Description: Traces the route taken by packets over a TCP/IP network.
++ The traceroute utility displays the route used by IP packets on their way to a
++ specified network (or Internet) host. Traceroute displays the IP number and
++ host name (if possible) of the machines along the route taken by the packets.
++ Traceroute is used as a network debugging tool. If you're having network
++ connectivity problems, traceroute will show you where the trouble is coming
++ from along the route.
++ .
++ Install traceroute if you need a tool for diagnosing network connectivity
++ problems.
+--- traceroute-1.4a12.orig/debian/copyright
++++ traceroute-1.4a12/debian/copyright
+@@ -0,0 +1,16 @@
++This package was split from netstd by Herbert Xu herbert@debian.org on
++Mon, 1 Nov 1999 15:14:03 +1100.
++
++netstd was created by Peter Tobias tobias@et-inf.fho-emden.de on
++Wed, 20 Jul 1994 17:23:21 +0200.
++
++It was downloaded from ftp://ftp.ee.lbl.gov/.
++
++Copyright:
++
++Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997
++The Regents of the University of California. All rights reserved.
++
++The license can be found in /usr/share/common-licenses/BSD.
++
++$Id: copyright,v 1.1 1999/11/01 04:34:49 herbert Exp $
+--- traceroute-1.4a12.orig/debian/rules
++++ traceroute-1.4a12/debian/rules
+@@ -0,0 +1,96 @@
++#!/usr/bin/make -f
++# GNU copyright 1997 to 1999 by Joey Hess.
++# Copyright (c) 1999 Herbert Xu <herbert@debian.org>
++
++# Uncomment this to turn on verbose mode.
++#export DH_VERBOSE=1
++
++# This is the debhelper compatability version to use.
++export DH_COMPAT=2
++
++build: build-stamp
++build-stamp:
++ dh_testdir
++
++ if [ ! -f configure.old ]; then \
++ mv configure configure.old; \
++ mv config.guess config.guess.old; \
++ mv config.sub config.sub.old; \
++ mv linux-include/netinet/in_systm.h linux-include; \
++ mv linux-include/netinet/ip.h linux-include; \
++ mv linux-include/netinet/ip_icmp.h linux-include; \
++ cp /usr/share/automake/config.guess .; \
++ cp /usr/share/automake/config.sub .; \
++ autoconf; \
++ fi
++ if [ ! -f Makefile ]; then ./configure; fi
++ $(MAKE) CCOPT="-g -O2"
++
++ touch build-stamp
++
++clean:
++ dh_testdir
++ dh_testroot
++ rm -f build-stamp install-stamp
++
++ -$(MAKE) distclean
++ if [ -f configure.old ]; then \
++ mv configure.old configure; \
++ mv config.guess.old config.guess; \
++ mv config.sub.old config.sub; \
++ mv linux-include/in_systm.h linux-include/netinet; \
++ mv linux-include/ip.h linux-include/netinet; \
++ mv linux-include/ip_icmp.h linux-include/netinet; \
++ fi
++
++ dh_clean
++
++install: build install-stamp
++install-stamp:
++ dh_testdir
++ dh_testroot
++ dh_clean -k
++ dh_installdirs
++
++ install traceroute debian/traceroute/usr/sbin
++ cp traceroute.8 debian/traceroute/usr/share/man/man8
++
++ touch install-stamp
++
++# Build architecture-independent files here.
++binary-indep: build install
++# We have nothing to do by default.
++
++# Build architecture-dependent files here.
++binary-arch: build install
++# dh_testversion
++ dh_testdir
++ dh_testroot
++# dh_installdebconf
++ dh_installdocs
++ dh_installexamples
++ dh_installmenu
++# dh_installemacsen
++# dh_installpam
++# dh_installinit
++ dh_installcron
++ dh_installmanpages
++ dh_installinfo
++# dh_undocumented
++ dh_installchangelogs CHANGES
++ dh_link
++ dh_strip
++ dh_compress
++ dh_fixperms
++ # You may want to make some executables suid here.
++ chmod u+s debian/traceroute/usr/sbin/traceroute
++# dh_makeshlibs
++ dh_installdeb
++# dh_perl
++ dh_shlibdeps
++ dh_gencontrol
++ dh_md5sums
++ dh_builddeb
++
++binary: binary-indep binary-arch
++.PHONY: build clean binary-indep binary-arch binary install
+--- traceroute-1.4a12.orig/debian/traceroute.dirs
++++ traceroute-1.4a12/debian/traceroute.dirs
+@@ -0,0 +1,2 @@
++usr/sbin
++usr/share/man/man8
+--- traceroute-1.4a12.orig/debian/traceroute.docs
++++ traceroute-1.4a12/debian/traceroute.docs
+@@ -0,0 +1 @@
++README
+--- traceroute-1.4a12.orig/debian/traceroute.examples
++++ traceroute-1.4a12/debian/traceroute.examples
+@@ -0,0 +1,2 @@
++mean.awk
++median.awk