--- 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\- --- 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 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 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 Fri, 9 Mar 2001 22:24:11 +1100 + +traceroute (1.4a12-2) unstable; urgency=low + + * Made changes for dpkg-statoverride (closes: #83817). + + -- Herbert Xu 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 Fri, 26 Jan 2001 20:57:21 +1100 + +traceroute (1.4a8-1) unstable; urgency=low + + * New upstream release. + + -- Herbert Xu 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 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 Fri, 31 Mar 2000 07:50:33 +1000 + +traceroute (1.4a5-1) unstable; urgency=low + + * Initial release (closes: #34166). + + -- Herbert Xu 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 +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 + +# 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