I've appended the set of patches for the traceroute bugs that I just commited to NetBSD. (It should work for other BSDs, and perhaps Linux too, if it's using the 4.4BSD traceroute.) This fixes two problems: 1. If uid != 0 (you're not superuser), it checks to see that the source address it's going to use is an address from a local interface that's up and not marked loopback. 2. It checks the return value from select() and, if select fails, exits. I believe that my solution for #2 is better than the one recently committed to FreeBSD because mine exits on all select() errors, not just EINVAL. So if you could somehow convince select() to fail with, for example, EINTR, you still can't utilise this to get around the inter-packet delay. (I don't believe you can do this as it stands, but if someone later adds a signal handler to this program that doesn't exit when a signal is caught, you'd probably be able to do it by sending a rapid stream of that signal to the program.) Also, I don't arbitrarially limit the timeout to a day, though I doubt that makes much difference to anyone. cjs -- Curt Sampson <cjsat_private> 604 801 5335 De gustibus, aut bene aut nihil. The most widely ported operating system in the world: http://www.netbsd.org Index: traceroute.c =================================================================== RCS file: /cvsroot/src/usr.sbin/traceroute/traceroute.c,v retrieving revision 1.26 retrieving revision 1.28 diff -u -r1.26 -r1.28 --- traceroute.c 1998/12/09 22:53:29 1.26 +++ traceroute.c 1999/02/16 23:18:40 1.28 @@ -378,7 +379,7 @@ int tos = 0, settos = 0, ttl_flag = 0; register int lsrr = 0; register u_short off = 0; - struct ifaddrlist *al; + struct ifaddrlist *al, *al2; char errbuf[132]; if ((cp = strrchr(argv[0], '/')) != NULL) @@ -699,6 +700,7 @@ /* Get the interface address list */ n = ifaddrlist(&al, errbuf, sizeof errbuf); + al2 = al; if (n < 0) { Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf); exit(1); @@ -711,8 +713,8 @@ /* Look for a specific device */ if (device != NULL) { - for (i = n; i > 0; --i, ++al) - if (strcmp(device, al->device) == 0) + for (i = n; i > 0; --i, ++al2) + if (strcmp(device, al2->device) == 0) break; if (i <= 0) { Fprintf(stderr, "%s: Can't find interface %s\n", @@ -728,11 +730,11 @@ * Otherwise, use the first interface found. * Warn if there are more than one. */ - setsin(from, al->addr); + setsin(from, al2->addr); if (n > 1 && device == NULL && !find_local_ip(from, to)) { Fprintf(stderr, "%s: Warning: Multiple interfaces found; using %s @ %s\n", - prog, inet_ntoa(from->sin_addr), al->device); + prog, inet_ntoa(from->sin_addr), al2->device); } } else { hi = gethostinfo(source); @@ -754,7 +756,7 @@ * interface address. */ for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap) - if (*ap == al->addr) + if (*ap == al2->addr) break; if (i <= 0) { Fprintf(stderr, @@ -766,6 +768,25 @@ } freehostinfo(hi); } + + /* + * If not root, make sure source address matches a local interface. + * (The list of addresses produced by ifaddrlist() automatically + * excludes interfaces that are marked down and/or loopback.) + */ + if (getuid()) { + al2 = al; + for (i = n; i > 0; --i, ++al2) + if (from->sin_addr.s_addr == al2->addr) + break; + if (i <= 0) { + Fprintf(stderr, "%s: %s is not a valid local address " + "and you are not superuser.\n", prog, + inet_ntoa(from->sin_addr)); + exit(1); + } + } + outip->ip_src = from->sin_addr; #ifndef IP_HDRINCL if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) { @@ -911,6 +932,7 @@ struct timezone tz; register int cc = 0; int fromlen = sizeof(*fromp); + int retval; FD_ZERO(&fds); FD_SET(sock, &fds); @@ -920,9 +942,16 @@ (void)gettimeofday(&now, &tz); tvsub(&wait, &now); - if (select(sock + 1, &fds, NULL, NULL, &wait) > 0) + retval = select(sock + 1, &fds, NULL, NULL, &wait); + if (retval < 0) { + /* If we continue, we probably just flood the remote host. */ + Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno)); + exit(1); + } + if (retval > 0) { cc = recvfrom(s, (char *)packet, sizeof(packet), 0, (struct sockaddr *)fromp, &fromlen); + } return(cc); }
This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:35:34 PDT