diff options
-rw-r--r-- | networking/traceroute.c | 107 |
1 files changed, 58 insertions, 49 deletions
diff --git a/networking/traceroute.c b/networking/traceroute.c index ddde922bf..764d66ef8 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -475,7 +475,7 @@ send_probe(int seq, int ttl) #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { struct outdata6_t *pkt = (void *) outdata; - pkt->ident6 = htonl(ident); + pkt->ident6 = ident; pkt->seq6 = htonl(seq); /*gettimeofday(&pkt->tv, &tz);*/ icp = outicmp6; @@ -631,7 +631,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) if ((option_mask32 & OPT_USE_ICMP) && type == ICMP_ECHOREPLY - && icp->icmp_id == htons(ident) + && icp->icmp_id == ident && icp->icmp_seq == htons(seq) ) { /* In UDP mode, when we reach the machine, we (usually) @@ -655,7 +655,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) hicmp = (struct icmp *)((unsigned char *)hip + hlen); if (hlen + SIZEOF_ICMP_HDR <= read_len && hip->ip_p == IPPROTO_ICMP - && hicmp->icmp_id == htons(ident) + && hicmp->icmp_id == ident && hicmp->icmp_seq == htons(seq) ) { return (type == ICMP_TIMXCEED ? -1 : code + 1); @@ -667,7 +667,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) // Off: since we do not form the entire IP packet, // but defer it to kernel, we can't set source port, // and thus can't check it here in the reply - /* && up->source == htons(ident) */ + /* && up->source == ident */ && up->dest == htons(port + seq) ) { return (type == ICMP_TIMXCEED ? -1 : code + 1); @@ -679,10 +679,10 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) int i; uint32_t *lp = (uint32_t *)&icp->icmp_ip; - printf("\n%d bytes from %s to " - "%s: icmp type %d (%s) code %d\n", - read_len, inet_ntoa(from->sin_addr), -//BUG: inet_ntoa() returns static buf! x2 is NONO! + printf("\n%d bytes from %s", + read_len, inet_ntoa(from->sin_addr)); + /* Two separate printf() because inet_ntoa() returns static string */ + printf(" to %s: icmp type %d (%s) code %d\n", inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code); for (i = 4; i < read_len; i += sizeof(*lp)) @@ -693,21 +693,19 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq) } #if ENABLE_TRACEROUTE6 + # if !ENABLE_FEATURE_TRACEROUTE_VERBOSE -#define packet_ok(read_len, from_lsa, to, seq) \ - packet_ok(read_len, from_lsa, seq) +#define packet6_ok(read_len, from_lsa, to, seq) \ + packet6_ok(read_len, from_lsa, seq) # endif static int -packet_ok(int read_len, len_and_sockaddr *from_lsa, +packet6_ok(int read_len, const struct sockaddr_in6 *from, struct sockaddr *to, int seq) { const struct icmp6_hdr *icp; unsigned char type, code; - if (from_lsa->u.sa.sa_family == AF_INET) - return packet4_ok(read_len, &from_lsa->u.sin, seq); - /* NB: reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) socket * return only ICMP packet (IOW: they strip IPv6 header). * This differs from (AF_INET, SOCK_RAW, IPPROTO_ICMP) sockets!? @@ -719,7 +717,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, if ((option_mask32 & OPT_USE_ICMP) && type == ICMP6_ECHO_REPLY - && icp->icmp6_id == htons(ident) + && icp->icmp6_id == ident && icp->icmp6_seq == htons(seq) ) { /* In UDP mode, when we reach the machine, we (usually) @@ -749,7 +747,7 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, pkt = (struct outdata6_t *) (up + 1); - if (ntohl(pkt->ident6) == ident + if (pkt->ident6 == ident && ntohl(pkt->seq6) == seq ) { return (type == ICMP6_TIME_EXCEEDED ? -1 : (code<<8)+1); @@ -763,17 +761,17 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, # define MAXHOSTNAMELEN 80 # endif unsigned char *p; - char pa1[MAXHOSTNAMELEN]; - char pa2[MAXHOSTNAMELEN]; + char pa[MAXHOSTNAMELEN]; int i; p = (unsigned char *) (icp + 1); - printf("\n%d bytes from %s to " - "%s: icmp type %d (%s) code %d\n", + printf("\n%d bytes from %s", read_len, - inet_ntop(AF_INET6, &from_lsa->u.sin6.sin6_addr, pa1, sizeof(pa1)), - inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa2, sizeof(pa2)), + inet_ntop(AF_INET6, &from->sin6_addr, pa, sizeof(pa))); + /* Two printf() instead of one - reuse string constants */ + printf(" to %s: icmp type %d (%s) code %d\n", + inet_ntop(AF_INET6, &((struct sockaddr_in6*)to)->sin6_addr, pa, sizeof(pa)), type, pr_type(type), icp->icmp6_code); read_len -= sizeof(struct icmp6_hdr); @@ -792,7 +790,22 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa, return 0; } +# if !ENABLE_FEATURE_TRACEROUTE_VERBOSE +#define packet_ok(read_len, from_lsa, to, seq) \ + packet_ok(read_len, from_lsa, seq) +# endif +static int +packet_ok(int read_len, len_and_sockaddr *from_lsa, + struct sockaddr *to, + int seq) +{ + if (from_lsa->u.sa.sa_family == AF_INET) + return packet4_ok(read_len, &from_lsa->u.sin, seq); + return packet6_ok(read_len, &from_lsa->u.sin6, to, seq); +} + #else /* !ENABLE_TRACEROUTE6 */ + static ALWAYS_INLINE int packet_ok(int read_len, len_and_sockaddr *from_lsa IF_NOT_FEATURE_TRACEROUTE_VERBOSE(UNUSED_PARAM), @@ -801,6 +814,7 @@ packet_ok(int read_len, { return packet4_ok(read_len, &from_lsa->u.sin, seq); } + #endif /* @@ -927,14 +941,6 @@ common_traceroute_main(int op, char **argv) port = xatou16(port_str); if (op & OPT_NPROBES) nprobes = xatou_range(nprobes_str, 1, INT_MAX); - if (op & OPT_SOURCE) { - /* - * set the ip source address of the outbound - * probe (e.g., on a multi-homed host). - */ - if (getuid() != 0) - bb_simple_error_msg_and_die(bb_msg_you_must_be_root); - } if (op & OPT_WAITTIME) waittime = xatou_range(waittime_str, 1, 24 * 60 * 60); if (op & OPT_PAUSE_MS) @@ -993,23 +999,26 @@ common_traceroute_main(int op, char **argv) if (op & OPT_BYPASS_ROUTE) setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); + { + int snd; #if ENABLE_TRACEROUTE6 - if (af == AF_INET6) { - if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) - bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); - if (op & OPT_USE_ICMP) - xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), sndsock); - else - xmove_fd(xsocket(AF_INET6, SOCK_DGRAM, 0), sndsock); - } else + if (af == AF_INET6) { + if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) + bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); + if (op & OPT_USE_ICMP) + snd = xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + else + snd = xsocket(AF_INET6, SOCK_DGRAM, 0); + } else #endif - { - if (op & OPT_USE_ICMP) - xmove_fd(xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP), sndsock); - else - xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock); + { + if (op & OPT_USE_ICMP) + snd = xsocket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + else + snd = xsocket(AF_INET, SOCK_DGRAM, 0); + } + xmove_fd(snd, sndsock); } -//TODO xmove_fd to here! #ifdef SO_SNDBUF if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { @@ -1036,13 +1045,12 @@ common_traceroute_main(int op, char **argv) ident = getpid(); + outdata = (void*)(outudp + 1); if (!ENABLE_TRACEROUTE6 || af == AF_INET) { - outdata = (void*)(outudp + 1); if (op & OPT_USE_ICMP) { - ident |= 0x8000; outicmp->icmp_type = ICMP_ECHO; /*outicmp->icmp_code = 0; - set by xzalloc */ - outicmp->icmp_id = htons(ident); + outicmp->icmp_id = ident; outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR); } } @@ -1050,10 +1058,9 @@ common_traceroute_main(int op, char **argv) if (af == AF_INET6) { outdata = (void*)(outudp6 + 1); if (op & OPT_USE_ICMP) { - ident |= 0x8000; outicmp6->icmp_type = ICMP6_ECHO_REQUEST; /*outicmp->icmp_code = 0; - set by xzalloc */ - outicmp6->icmp_id = htons(ident); + outicmp6->icmp_id = ident; outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR); } } @@ -1069,6 +1076,8 @@ common_traceroute_main(int op, char **argv) #else len_and_sockaddr *source_lsa = xdotted2sockaddr(source, 0); #endif + if (getuid() != 0) + bb_simple_error_msg_and_die(bb_msg_you_must_be_root); /* Ping4 does this (why?) */ if (af == AF_INET) if (setsockopt(sndsock, IPPROTO_IP, IP_MULTICAST_IF, |