* Update function definitions.

* Ensure that the datalen always describes the length after the IPv6
  header consistently, not matter which protocol us used for probes..
* Document that the default length is 20, not 12.
* Don't send inormation in probe packets which is not needed or
  even checked when the responses are processed.
* Address CID 978587.

This is mainly a cleanup preparing the addition of SCTP and TCP
as possible probe packet protocols.

MFC after:	4 weeks
This commit is contained in:
Michael Tuexen 2017-09-30 11:40:18 +00:00
parent 2a811fc0b8
commit aa96470cc9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324119
2 changed files with 39 additions and 75 deletions

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 24, 2009
.Dd September 30, 2017
.Dt TRACEROUTE6 8
.Os
.\"
@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Nm
.Bk -words
.Op Fl adIlnNrvU
.Op Fl adIlnNrUv
.Ek
.Bk -words
.Op Fl f Ar firsthop
@ -79,7 +79,7 @@ uses the IPv6 protocol hop limit field to elicit an ICMPv6 TIME_EXCEEDED
response from each gateway along the path to some host.
.Pp
The only mandatory parameter is the destination host name or IPv6 address.
The default probe datagram carries 12 bytes of payload,
The default probe datagram carries 20 bytes of payload,
in addition to the IPv6 header.
The size of the payload can be specified by giving a length
(in bytes)
@ -96,9 +96,9 @@ Debug mode.
.It Fl f Ar firsthop
Specify how many hops to skip in trace.
.It Fl g Ar gateway
Specify intermediate gateway
.Nm (
uses routing header).
Specify intermediate gateway. Please note that
.Nm
tries to use routing headers.
.It Fl I
Use ICMP6 ECHO instead of UDP datagrams.
.It Fl l

View File

@ -289,23 +289,8 @@ static const char rcsid[] =
#define freehostent(x)
#endif
/*
* format of a (udp) probe packet.
*/
struct tv32 {
u_int32_t tv32_sec;
u_int32_t tv32_usec;
};
struct opacket {
u_char seq; /* sequence number of this packet */
u_char hops; /* hop limit of the packet */
u_char pad[2];
struct tv32 tv; /* time packet left */
} __attribute__((__packed__));
u_char packet[512]; /* last inbound (icmp) packet */
struct opacket *outpacket; /* last output (udp) packet */
char *outpacket; /* last output packet */
int main(int, char *[]);
int wait_for_reply(int, struct msghdr *);
@ -333,7 +318,7 @@ int rcvhlim;
struct in6_pktinfo *rcvpktinfo;
struct sockaddr_in6 Src, Dst, Rcv;
u_long datalen; /* How much data */
u_long datalen = 20; /* How much data */
#define ICMP6ECHOLEN 8
/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
char rtbuf[2064];
@ -362,9 +347,7 @@ char *as_server = NULL;
void *asn;
int
main(argc, argv)
int argc;
char *argv[];
main(int argc, char *argv[])
{
int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
@ -533,12 +516,12 @@ main(argc, argv)
*/
source = optarg;
break;
case 'v':
verbose++;
break;
case 'U':
useproto = IPPROTO_UDP;
break;
case 'v':
verbose++;
break;
case 'w':
ep = NULL;
errno = 0;
@ -574,13 +557,13 @@ main(argc, argv)
}
break;
case IPPROTO_NONE:
if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
perror("socket(SOCK_RAW)");
exit(5);
}
break;
default:
fprintf(stderr, "traceroute6: unknown probe protocol %d",
fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
useproto);
exit(5);
}
@ -641,7 +624,7 @@ main(argc, argv)
ep = NULL;
errno = 0;
datalen = strtoul(*argv, &ep, 0);
if (errno || !*argv || *ep) {
if (errno || *ep) {
fprintf(stderr,
"traceroute6: invalid packet length.\n");
exit(1);
@ -649,10 +632,10 @@ main(argc, argv)
}
switch (useproto) {
case IPPROTO_ICMPV6:
minlen = ICMP6ECHOLEN + sizeof(struct tv32);
minlen = ICMP6ECHOLEN;
break;
case IPPROTO_UDP:
minlen = sizeof(struct opacket);
minlen = sizeof(struct udphdr);
break;
case IPPROTO_NONE:
minlen = 0;
@ -671,6 +654,8 @@ main(argc, argv)
minlen, MAXPACKET);
exit(1);
}
if (useproto == IPPROTO_UDP)
datalen -= sizeof(struct udphdr);
outpacket = malloc(datalen);
if (!outpacket) {
perror("malloc");
@ -735,8 +720,10 @@ main(argc, argv)
#ifdef SO_SNDBUF
i = datalen;
if (i == 0)
i = 1;
if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
sizeof(i)) < 0 && useproto != IPPROTO_NONE) {
sizeof(i)) < 0) {
perror("setsockopt(SO_SNDBUF)");
exit(6);
}
@ -977,9 +964,7 @@ main(argc, argv)
}
int
wait_for_reply(sock, mhdr)
int sock;
struct msghdr *mhdr;
wait_for_reply(int sock, struct msghdr *mhdr)
{
#ifdef HAVE_POLL
struct pollfd pfd[1];
@ -1038,14 +1023,9 @@ setpolicy(so, policy)
#endif
void
send_probe(seq, hops)
int seq;
u_long hops;
send_probe(int seq, u_long hops)
{
struct icmp6_hdr *icp;
struct opacket *op;
struct timeval tv;
struct tv32 tv32;
int i;
i = hops;
@ -1055,9 +1035,6 @@ send_probe(seq, hops)
}
Dst.sin6_port = htons(port + seq);
(void) gettimeofday(&tv, NULL);
tv32.tv32_sec = htonl(tv.tv_sec);
tv32.tv32_usec = htonl(tv.tv_usec);
switch (useproto) {
case IPPROTO_ICMPV6:
@ -1068,15 +1045,8 @@ send_probe(seq, hops)
icp->icmp6_cksum = 0;
icp->icmp6_id = ident;
icp->icmp6_seq = htons(seq);
bcopy(&tv32, ((u_int8_t *)outpacket + ICMP6ECHOLEN),
sizeof(tv32));
break;
case IPPROTO_UDP:
op = outpacket;
op->seq = seq;
op->hops = hops;
bcopy(&tv32, &op->tv, sizeof tv32);
break;
case IPPROTO_NONE:
/* No space for anything. No harm as seq/tv32 are decorative. */
@ -1098,8 +1068,7 @@ send_probe(seq, hops)
}
int
get_hoplim(mhdr)
struct msghdr *mhdr;
get_hoplim(struct msghdr *mhdr)
{
struct cmsghdr *cm;
@ -1115,8 +1084,7 @@ get_hoplim(mhdr)
}
double
deltaT(t1p, t2p)
struct timeval *t1p, *t2p;
deltaT(struct timeval *t1p, struct timeval *t2p)
{
double dt;
@ -1185,10 +1153,7 @@ pr_type(int t0)
}
int
packet_ok(mhdr, cc, seq)
struct msghdr *mhdr;
int cc;
int seq;
packet_ok(struct msghdr *mhdr, int cc, int seq)
{
struct icmp6_hdr *icp;
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
@ -1262,6 +1227,8 @@ packet_ok(mhdr, cc, seq)
if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
|| type == ICMP6_DST_UNREACH) {
struct ip6_hdr *hip;
struct icmp6_hdr *icmp;
struct udphdr *udp;
void *up;
hip = (struct ip6_hdr *)(icp + 1);
@ -1272,14 +1239,16 @@ packet_ok(mhdr, cc, seq)
}
switch (useproto) {
case IPPROTO_ICMPV6:
if (((struct icmp6_hdr *)up)->icmp6_id == ident &&
((struct icmp6_hdr *)up)->icmp6_seq == htons(seq))
icmp = (struct icmp6_hdr *)up;
if (icmp->icmp6_id == ident &&
icmp->icmp6_seq == htons(seq))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
case IPPROTO_UDP:
if (((struct udphdr *)up)->uh_sport == htons(srcport) &&
((struct udphdr *)up)->uh_dport == htons(port + seq))
udp = (struct udphdr *)up;
if (udp->uh_sport == htons(srcport) &&
udp->uh_dport == htons(port + seq))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
@ -1328,9 +1297,7 @@ packet_ok(mhdr, cc, seq)
* Increment pointer until find the UDP or ICMP header.
*/
void *
get_uphdr(ip6, lim)
struct ip6_hdr *ip6;
u_char *lim;
get_uphdr(struct ip6_hdr *ip6, u_char *lim)
{
u_char *cp = (u_char *)ip6, nh;
int hlen;
@ -1374,9 +1341,7 @@ get_uphdr(ip6, lim)
}
void
print(mhdr, cc)
struct msghdr *mhdr;
int cc;
print(struct msghdr *mhdr, int cc)
{
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
char hbuf[NI_MAXHOST];
@ -1412,8 +1377,7 @@ print(mhdr, cc)
* numeric value, otherwise try for symbolic name.
*/
const char *
inetname(sa)
struct sockaddr *sa;
inetname(struct sockaddr *sa)
{
static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
static int first = 1;
@ -1447,7 +1411,7 @@ inetname(sa)
}
void
usage()
usage(void)
{
fprintf(stderr,