traceroute: fix traceroute6 -I (icmp mode)
function old new delta common_traceroute_main 3530 3544 +14 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
ef2366cdca
commit
3978adc445
@ -414,9 +414,32 @@ struct globals {
|
|||||||
waittime = 5; \
|
waittime = 5; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define outicmp ((struct icmp *)(outip + 1))
|
|
||||||
#define outudp ((struct udphdr *)(outip + 1))
|
#define outudp ((struct udphdr *)(outip + 1))
|
||||||
|
#define outudp6 ((struct udphdr *)(((struct ip6_hdr*)outip) + 1))
|
||||||
|
#define outicmp ((struct icmp *)(outip + 1))
|
||||||
|
#define outicmp6 ((struct icmp *)(((struct ip6_hdr*)outip) + 1))
|
||||||
|
/* NB: for icmp echo, IPv4 and IPv6 fields are the same size and offset:
|
||||||
|
* struct icmp:
|
||||||
|
* uint8_t icmp_type;
|
||||||
|
* uint8_t icmp_code;
|
||||||
|
* uint16_t icmp_cksum;
|
||||||
|
* uint16_t icmp_id;
|
||||||
|
* uint16_t icmp_seq;
|
||||||
|
* struct icmp6_hdr:
|
||||||
|
* uint8_t icmp6_type;
|
||||||
|
* uint8_t icmp6_code;
|
||||||
|
* uint16_t icmp6_cksum;
|
||||||
|
* uint16_t icmp6_id;
|
||||||
|
* uint16_t icmp6_seq;
|
||||||
|
* therefore both outicmp and outicmp6 are pointers to *IPv4* icmp struct.
|
||||||
|
* SIZEOF_ICMP_HDR == 8 is the same for both, as well.
|
||||||
|
* However, values of these pointers are not the same (since IPv6 IP header is larger),
|
||||||
|
* and icmp_type constants are not the same:
|
||||||
|
* #define ICMP_ECHO 8
|
||||||
|
* #define ICMP_ECHOREPLY 0
|
||||||
|
* #define ICMP6_ECHO_REQUEST 128
|
||||||
|
* #define ICMP6_ECHO_REPLY 129
|
||||||
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
|
wait_for_reply(len_and_sockaddr *from_lsa, struct sockaddr *to, unsigned *timestamp_us, int *left_ms)
|
||||||
@ -446,14 +469,16 @@ send_probe(int seq, int ttl)
|
|||||||
{
|
{
|
||||||
int len, res;
|
int len, res;
|
||||||
void *out;
|
void *out;
|
||||||
|
struct icmp *icp;
|
||||||
|
|
||||||
/* Payload */
|
/* Payload */
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (dest_lsa->u.sa.sa_family == AF_INET6) {
|
if (dest_lsa->u.sa.sa_family == AF_INET6) {
|
||||||
struct outdata6_t *pkt = (struct outdata6_t *) outdata;
|
struct outdata6_t *pkt = (void *) outdata;
|
||||||
pkt->ident6 = htonl(ident);
|
pkt->ident6 = htonl(ident);
|
||||||
pkt->seq6 = htonl(seq);
|
pkt->seq6 = htonl(seq);
|
||||||
/*gettimeofday(&pkt->tv, &tz);*/
|
/*gettimeofday(&pkt->tv, &tz);*/
|
||||||
|
icp = outicmp6;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -461,19 +486,23 @@ send_probe(int seq, int ttl)
|
|||||||
outdata->ttl = ttl;
|
outdata->ttl = ttl;
|
||||||
// UNUSED: was storing gettimeofday's result there, but never ever checked it
|
// UNUSED: was storing gettimeofday's result there, but never ever checked it
|
||||||
/*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
|
/*memcpy(&outdata->tv, tp, sizeof(outdata->tv));*/
|
||||||
|
icp = outicmp;
|
||||||
if (option_mask32 & OPT_USE_ICMP) {
|
|
||||||
outicmp->icmp_seq = htons(seq);
|
|
||||||
|
|
||||||
/* Always calculate checksum for icmp packets */
|
|
||||||
outicmp->icmp_cksum = 0;
|
|
||||||
outicmp->icmp_cksum = inet_cksum(
|
|
||||||
outicmp,
|
|
||||||
((char*)outip + packlen) - (char*)outicmp
|
|
||||||
);
|
|
||||||
if (outicmp->icmp_cksum == 0)
|
|
||||||
outicmp->icmp_cksum = 0xffff;
|
|
||||||
}
|
}
|
||||||
|
out = outdata;
|
||||||
|
if (option_mask32 & OPT_USE_ICMP) {
|
||||||
|
out = icp;
|
||||||
|
/*icp->icmp_type = ICMP[6]_ECHO; - already set */
|
||||||
|
/*icp->icmp_code = 0; - already set */
|
||||||
|
/*icp->icmp_id = ident; - already set */
|
||||||
|
icp->icmp_seq = htons(seq);
|
||||||
|
/* Always calculate checksum for icmp packets */
|
||||||
|
icp->icmp_cksum = 0;
|
||||||
|
icp->icmp_cksum = inet_cksum(
|
||||||
|
icp,
|
||||||
|
((char*)outip + packlen) - (char*)icp
|
||||||
|
);
|
||||||
|
if (icp->icmp_cksum == 0)
|
||||||
|
icp->icmp_cksum = 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BUG! verbose is (x & OPT_VERBOSE), not a counter!
|
//BUG! verbose is (x & OPT_VERBOSE), not a counter!
|
||||||
@ -502,7 +531,6 @@ send_probe(int seq, int ttl)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
out = outdata;
|
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (dest_lsa->u.sa.sa_family == AF_INET6) {
|
if (dest_lsa->u.sa.sa_family == AF_INET6) {
|
||||||
res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
|
res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl);
|
||||||
@ -516,8 +544,6 @@ send_probe(int seq, int ttl)
|
|||||||
if (res != 0)
|
if (res != 0)
|
||||||
bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
|
bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl);
|
||||||
#endif
|
#endif
|
||||||
if (option_mask32 & OPT_USE_ICMP)
|
|
||||||
out = outicmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(option_mask32 & OPT_USE_ICMP)) {
|
if (!(option_mask32 & OPT_USE_ICMP)) {
|
||||||
@ -579,7 +605,12 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
|
|||||||
int hlen;
|
int hlen;
|
||||||
const struct ip *ip;
|
const struct ip *ip;
|
||||||
|
|
||||||
|
/* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
|
||||||
|
* return the entire IP packet (IOW: they do not strip IP header).
|
||||||
|
* This differs from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) sockets!?
|
||||||
|
*/
|
||||||
ip = (struct ip *) recv_pkt;
|
ip = (struct ip *) recv_pkt;
|
||||||
|
|
||||||
hlen = ip->ip_hl << 2;
|
hlen = ip->ip_hl << 2;
|
||||||
if (read_len < hlen + ICMP_MINLEN) {
|
if (read_len < hlen + ICMP_MINLEN) {
|
||||||
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
#if ENABLE_FEATURE_TRACEROUTE_VERBOSE
|
||||||
@ -598,9 +629,20 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
|
|||||||
if (code == ICMP_UNREACH_NEEDFRAG)
|
if (code == ICMP_UNREACH_NEEDFRAG)
|
||||||
pmtu = ntohs(icp->icmp_nextmtu);
|
pmtu = ntohs(icp->icmp_nextmtu);
|
||||||
|
|
||||||
|
if ((option_mask32 & OPT_USE_ICMP)
|
||||||
|
&& type == ICMP_ECHOREPLY
|
||||||
|
&& icp->icmp_id == htons(ident)
|
||||||
|
&& icp->icmp_seq == htons(seq)
|
||||||
|
) {
|
||||||
|
/* In UDP mode, when we reach the machine, we (usually)
|
||||||
|
* would get "port unreachable" - in ICMP we got "echo reply".
|
||||||
|
* Simulate "port unreachable" for caller:
|
||||||
|
*/
|
||||||
|
return ICMP_UNREACH_PORT+1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS)
|
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS)
|
||||||
|| type == ICMP_UNREACH
|
|| type == ICMP_UNREACH
|
||||||
|| type == ICMP_ECHOREPLY
|
|
||||||
) {
|
) {
|
||||||
const struct ip *hip;
|
const struct ip *hip;
|
||||||
const struct udphdr *up;
|
const struct udphdr *up;
|
||||||
@ -610,14 +652,6 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
|
|||||||
if (option_mask32 & OPT_USE_ICMP) {
|
if (option_mask32 & OPT_USE_ICMP) {
|
||||||
struct icmp *hicmp;
|
struct icmp *hicmp;
|
||||||
|
|
||||||
/* XXX */
|
|
||||||
if (type == ICMP_ECHOREPLY
|
|
||||||
&& icp->icmp_id == htons(ident)
|
|
||||||
&& icp->icmp_seq == htons(seq)
|
|
||||||
) {
|
|
||||||
return ICMP_UNREACH_PORT+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
hicmp = (struct icmp *)((unsigned char *)hip + hlen);
|
hicmp = (struct icmp *)((unsigned char *)hip + hlen);
|
||||||
if (hlen + SIZEOF_ICMP_HDR <= read_len
|
if (hlen + SIZEOF_ICMP_HDR <= read_len
|
||||||
&& hip->ip_p == IPPROTO_ICMP
|
&& hip->ip_p == IPPROTO_ICMP
|
||||||
@ -648,6 +682,7 @@ packet4_ok(int read_len, const struct sockaddr_in *from, int seq)
|
|||||||
printf("\n%d bytes from %s to "
|
printf("\n%d bytes from %s to "
|
||||||
"%s: icmp type %d (%s) code %d\n",
|
"%s: icmp type %d (%s) code %d\n",
|
||||||
read_len, inet_ntoa(from->sin_addr),
|
read_len, inet_ntoa(from->sin_addr),
|
||||||
|
//BUG: inet_ntoa() returns static buf! x2 is NONO!
|
||||||
inet_ntoa(ip->ip_dst),
|
inet_ntoa(ip->ip_dst),
|
||||||
type, pr_type(type), icp->icmp_code);
|
type, pr_type(type), icp->icmp_code);
|
||||||
for (i = 4; i < read_len; i += sizeof(*lp))
|
for (i = 4; i < read_len; i += sizeof(*lp))
|
||||||
@ -673,11 +708,27 @@ packet_ok(int read_len, len_and_sockaddr *from_lsa,
|
|||||||
if (from_lsa->u.sa.sa_family == AF_INET)
|
if (from_lsa->u.sa.sa_family == AF_INET)
|
||||||
return packet4_ok(read_len, &from_lsa->u.sin, seq);
|
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!?
|
||||||
|
*/
|
||||||
icp = (struct icmp6_hdr *) recv_pkt;
|
icp = (struct icmp6_hdr *) recv_pkt;
|
||||||
|
|
||||||
type = icp->icmp6_type;
|
type = icp->icmp6_type;
|
||||||
code = icp->icmp6_code;
|
code = icp->icmp6_code;
|
||||||
|
|
||||||
|
if ((option_mask32 & OPT_USE_ICMP)
|
||||||
|
&& type == ICMP6_ECHO_REPLY
|
||||||
|
&& icp->icmp6_id == htons(ident)
|
||||||
|
&& icp->icmp6_seq == htons(seq)
|
||||||
|
) {
|
||||||
|
/* In UDP mode, when we reach the machine, we (usually)
|
||||||
|
* would get "port unreachable" - in ICMP we got "echo reply".
|
||||||
|
* Simulate "port unreachable" for caller:
|
||||||
|
*/
|
||||||
|
return (ICMP6_DST_UNREACH_NOPORT << 8) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
|
if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
|
||||||
|| type == ICMP6_DST_UNREACH
|
|| type == ICMP6_DST_UNREACH
|
||||||
) {
|
) {
|
||||||
@ -787,8 +838,13 @@ print(int read_len, const struct sockaddr *from, const struct sockaddr *to)
|
|||||||
if (verbose) {
|
if (verbose) {
|
||||||
char *ina = xmalloc_sockaddr2dotted_noport(to);
|
char *ina = xmalloc_sockaddr2dotted_noport(to);
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
|
/* NB: reads from (AF_INET, SOCK_RAW, IPPROTO_ICMP) socket
|
||||||
|
* return the entire IP packet (IOW: they do not strip IP header).
|
||||||
|
* Reads from (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) do strip IPv6
|
||||||
|
* header and return only ICMP6 packet. Weird.
|
||||||
|
*/
|
||||||
if (to->sa_family == AF_INET6) {
|
if (to->sa_family == AF_INET6) {
|
||||||
read_len -= sizeof(struct ip6_hdr);
|
/* read_len -= sizeof(struct ip6_hdr); - WRONG! */
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -844,6 +900,9 @@ common_traceroute_main(int op, char **argv)
|
|||||||
struct sockaddr *lastaddr;
|
struct sockaddr *lastaddr;
|
||||||
struct sockaddr *to;
|
struct sockaddr *to;
|
||||||
|
|
||||||
|
/* Ensure the socket fds won't be 0, 1 or 2 */
|
||||||
|
bb_sanitize_stdio();
|
||||||
|
|
||||||
INIT_G();
|
INIT_G();
|
||||||
|
|
||||||
op |= getopt32(argv, "^"
|
op |= getopt32(argv, "^"
|
||||||
@ -884,13 +943,15 @@ common_traceroute_main(int op, char **argv)
|
|||||||
first_ttl = xatou_range(first_ttl_str, 1, max_ttl);
|
first_ttl = xatou_range(first_ttl_str, 1, max_ttl);
|
||||||
|
|
||||||
/* Process destination and optional packet size */
|
/* Process destination and optional packet size */
|
||||||
minpacket = sizeof(struct ip)
|
|
||||||
+ SIZEOF_ICMP_HDR
|
|
||||||
+ sizeof(struct outdata_t);
|
|
||||||
if (!(op & OPT_USE_ICMP))
|
|
||||||
minpacket = sizeof(struct ip)
|
minpacket = sizeof(struct ip)
|
||||||
+ sizeof(struct udphdr)
|
+ sizeof(struct udphdr)
|
||||||
+ sizeof(struct outdata_t);
|
+ sizeof(struct outdata_t);
|
||||||
|
if (op & OPT_USE_ICMP) {
|
||||||
|
minpacket = sizeof(struct ip)
|
||||||
|
+ SIZEOF_ICMP_HDR
|
||||||
|
+ sizeof(struct outdata_t);
|
||||||
|
port = 0; /* on ICMP6 sockets, sendto(ipv6.nonzero_port) throws EINVAL */
|
||||||
|
}
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
af = AF_UNSPEC;
|
af = AF_UNSPEC;
|
||||||
if (op & OPT_IPV4)
|
if (op & OPT_IPV4)
|
||||||
@ -899,10 +960,15 @@ common_traceroute_main(int op, char **argv)
|
|||||||
af = AF_INET6;
|
af = AF_INET6;
|
||||||
dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
|
dest_lsa = xhost_and_af2sockaddr(argv[0], port, af);
|
||||||
af = dest_lsa->u.sa.sa_family;
|
af = dest_lsa->u.sa.sa_family;
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6) {
|
||||||
minpacket = sizeof(struct ip6_hdr)
|
minpacket = sizeof(struct ip6_hdr)
|
||||||
+ sizeof(struct udphdr)
|
+ sizeof(struct udphdr)
|
||||||
+ sizeof(struct outdata6_t);
|
+ sizeof(struct outdata6_t);
|
||||||
|
if (op & OPT_USE_ICMP)
|
||||||
|
minpacket = sizeof(struct ip6_hdr)
|
||||||
|
+ SIZEOF_ICMP_HDR
|
||||||
|
+ sizeof(struct outdata6_t);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
dest_lsa = xhost2sockaddr(argv[0], port);
|
dest_lsa = xhost2sockaddr(argv[0], port);
|
||||||
#endif
|
#endif
|
||||||
@ -910,13 +976,10 @@ common_traceroute_main(int op, char **argv)
|
|||||||
if (argv[1])
|
if (argv[1])
|
||||||
packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
|
packlen = xatoul_range(argv[1], minpacket, 32 * 1024);
|
||||||
|
|
||||||
/* Ensure the socket fds won't be 0, 1 or 2 */
|
|
||||||
bb_sanitize_stdio();
|
|
||||||
|
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (af == AF_INET6) {
|
if (af == AF_INET6) {
|
||||||
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock);
|
||||||
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO);
|
setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); //why?
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -934,7 +997,10 @@ common_traceroute_main(int op, char **argv)
|
|||||||
if (af == AF_INET6) {
|
if (af == AF_INET6) {
|
||||||
if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
|
if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0)
|
||||||
bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
|
bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM");
|
||||||
xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock);
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -943,6 +1009,7 @@ common_traceroute_main(int op, char **argv)
|
|||||||
else
|
else
|
||||||
xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
|
xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), sndsock);
|
||||||
}
|
}
|
||||||
|
//TODO xmove_fd to here!
|
||||||
|
|
||||||
#ifdef SO_SNDBUF
|
#ifdef SO_SNDBUF
|
||||||
if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
|
if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) {
|
||||||
@ -970,21 +1037,25 @@ common_traceroute_main(int op, char **argv)
|
|||||||
ident = getpid();
|
ident = getpid();
|
||||||
|
|
||||||
if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
|
if (!ENABLE_TRACEROUTE6 || af == AF_INET) {
|
||||||
|
outdata = (void*)(outudp + 1);
|
||||||
if (op & OPT_USE_ICMP) {
|
if (op & OPT_USE_ICMP) {
|
||||||
ident |= 0x8000;
|
ident |= 0x8000;
|
||||||
outicmp->icmp_type = ICMP_ECHO;
|
outicmp->icmp_type = ICMP_ECHO;
|
||||||
|
/*outicmp->icmp_code = 0; - set by xzalloc */
|
||||||
outicmp->icmp_id = htons(ident);
|
outicmp->icmp_id = htons(ident);
|
||||||
outdata = (struct outdata_t *)((char *)outicmp + SIZEOF_ICMP_HDR);
|
outdata = (void*)((char *)outicmp + SIZEOF_ICMP_HDR);
|
||||||
} else {
|
|
||||||
outdata = (struct outdata_t *)(outudp + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
if (af == AF_INET6) {
|
if (af == AF_INET6) {
|
||||||
outdata = (void*)((char*)outip
|
outdata = (void*)(outudp6 + 1);
|
||||||
+ sizeof(struct ip6_hdr)
|
if (op & OPT_USE_ICMP) {
|
||||||
+ sizeof(struct udphdr)
|
ident |= 0x8000;
|
||||||
);
|
outicmp6->icmp_type = ICMP6_ECHO_REQUEST;
|
||||||
|
/*outicmp->icmp_code = 0; - set by xzalloc */
|
||||||
|
outicmp6->icmp_id = htons(ident);
|
||||||
|
outdata = (void*)((char *)outicmp6 + SIZEOF_ICMP_HDR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1013,26 +1084,16 @@ common_traceroute_main(int op, char **argv)
|
|||||||
//TODO: why we don't do it for IPv4?
|
//TODO: why we don't do it for IPv4?
|
||||||
len_and_sockaddr *source_lsa;
|
len_and_sockaddr *source_lsa;
|
||||||
|
|
||||||
int probe_fd = xsocket(af, SOCK_DGRAM, 0);
|
|
||||||
if (op & OPT_DEVICE)
|
|
||||||
setsockopt_bindtodevice(probe_fd, device);
|
|
||||||
set_nport(&dest_lsa->u.sa, htons(1025));
|
|
||||||
/* dummy connect. makes kernel pick source IP (and port) */
|
|
||||||
xconnect(probe_fd, &dest_lsa->u.sa, dest_lsa->len);
|
|
||||||
set_nport(&dest_lsa->u.sa, htons(port));
|
set_nport(&dest_lsa->u.sa, htons(port));
|
||||||
|
/* Connect makes kernel pick source IP and port */
|
||||||
/* read IP and port */
|
xconnect(sndsock, &dest_lsa->u.sa, dest_lsa->len);
|
||||||
source_lsa = get_sock_lsa(probe_fd);
|
/* Read IP and port */
|
||||||
|
source_lsa = get_sock_lsa(sndsock);
|
||||||
if (source_lsa == NULL)
|
if (source_lsa == NULL)
|
||||||
bb_simple_error_msg_and_die("can't get probe addr");
|
bb_simple_error_msg_and_die("can't get probe addr");
|
||||||
|
/* bind our recv socket to this IP (but not port) */
|
||||||
close(probe_fd);
|
|
||||||
|
|
||||||
/* bind our sockets to this IP (but not port) */
|
|
||||||
set_nport(&source_lsa->u.sa, 0);
|
set_nport(&source_lsa->u.sa, 0);
|
||||||
xbind(sndsock, &source_lsa->u.sa, source_lsa->len);
|
|
||||||
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
xbind(rcvsock, &source_lsa->u.sa, source_lsa->len);
|
||||||
|
|
||||||
free(source_lsa);
|
free(source_lsa);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1067,10 +1128,9 @@ common_traceroute_main(int op, char **argv)
|
|||||||
unsigned t1;
|
unsigned t1;
|
||||||
unsigned t2;
|
unsigned t2;
|
||||||
int left_ms;
|
int left_ms;
|
||||||
struct ip *ip;
|
|
||||||
|
|
||||||
fflush_all();
|
fflush_all();
|
||||||
if (probe != 0 && pausemsecs > 0)
|
if (probe != 0)
|
||||||
msleep(pausemsecs);
|
msleep(pausemsecs);
|
||||||
|
|
||||||
send_probe(++seq, ttl);
|
send_probe(++seq, ttl);
|
||||||
@ -1099,15 +1159,18 @@ common_traceroute_main(int op, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
print_delta_ms(t1, t2);
|
print_delta_ms(t1, t2);
|
||||||
ip = (struct ip *)recv_pkt;
|
|
||||||
|
|
||||||
if (from_lsa->u.sa.sa_family == AF_INET)
|
if (from_lsa->u.sa.sa_family == AF_INET) {
|
||||||
if (op & OPT_TTL_FLAG)
|
if (op & OPT_TTL_FLAG) {
|
||||||
|
struct ip *ip = (struct ip *)recv_pkt;
|
||||||
printf(" (%d)", ip->ip_ttl);
|
printf(" (%d)", ip->ip_ttl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* time exceeded in transit */
|
/* Got a "time exceeded in transit" icmp message? */
|
||||||
if (icmp_code == -1)
|
if (icmp_code == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
icmp_code--;
|
icmp_code--;
|
||||||
switch (icmp_code) {
|
switch (icmp_code) {
|
||||||
#if ENABLE_TRACEROUTE6
|
#if ENABLE_TRACEROUTE6
|
||||||
@ -1115,12 +1178,13 @@ common_traceroute_main(int op, char **argv)
|
|||||||
got_there = 1;
|
got_there = 1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case ICMP_UNREACH_PORT:
|
case ICMP_UNREACH_PORT: {
|
||||||
|
struct ip *ip = (struct ip *)recv_pkt;
|
||||||
if (ip->ip_ttl <= 1)
|
if (ip->ip_ttl <= 1)
|
||||||
printf(" !");
|
printf(" !");
|
||||||
got_there = 1;
|
got_there = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case ICMP_UNREACH_NET:
|
case ICMP_UNREACH_NET:
|
||||||
#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET)
|
#if ENABLE_TRACEROUTE6 && (ICMP6_DST_UNREACH_NOROUTE != ICMP_UNREACH_NET)
|
||||||
case ICMP6_DST_UNREACH_NOROUTE << 8:
|
case ICMP6_DST_UNREACH_NOROUTE << 8:
|
||||||
|
Loading…
Reference in New Issue
Block a user