summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2002-08-30 07:23:51 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2002-08-30 07:23:51 +0000
commitfe561522dd072de9e9fba92b0958a0a3431e0a95 (patch)
treeb1ba2b635232451273cdfdf7204593c1cef5cb96
parenta777189c10128f3ffd2d6bd204192d8e93f16db1 (diff)
have -I option, which causes traceroute6 to use ICMPv6 echo request for probing
(instead of udp).
-rw-r--r--usr.sbin/traceroute6/traceroute6.812
-rw-r--r--usr.sbin/traceroute6/traceroute6.c107
2 files changed, 84 insertions, 35 deletions
diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8
index 9097c582118..dc270f796dd 100644
--- a/usr.sbin/traceroute6/traceroute6.8
+++ b/usr.sbin/traceroute6/traceroute6.8
@@ -1,5 +1,5 @@
-.\" $OpenBSD: traceroute6.8,v 1.6 2000/06/12 16:37:09 itojun Exp $
-.\" $KAME: traceroute6.8,v 1.8 2000/06/12 16:29:18 itojun Exp $
+.\" $OpenBSD: traceroute6.8,v 1.7 2002/08/30 07:23:50 itojun Exp $
+.\" $KAME: traceroute6.8,v 1.9 2002/08/30 03:56:20 onoe Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
.\" All rights reserved.
@@ -39,7 +39,7 @@
.Sh SYNOPSIS
.Nm traceroute6
.Bk -words
-.Op Fl dlnrv
+.Op Fl dIlnrv
.Ek
.Bk -words
.Op Fl f Ar firsthop
@@ -79,13 +79,15 @@ Specify intermediate gateway
.Nm
uses routing header
.Pc .
-.It Fl m Ar hoplimit
-Specify maximum hoplimit.
+.It Fl I
+Use ICMP6 ECHO instead of UDP datagrams.
.It Fl l
Print both host hostnames and numeric addresses.
Normally
.Nm
prints only hostnames if
+.It Fl m Ar hoplimit
+Specify maximum hoplimit.
.Fl n
is not specified, and only numeric addresses if
.Fl n
diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c
index deac9ce3449..007168e062d 100644
--- a/usr.sbin/traceroute6/traceroute6.c
+++ b/usr.sbin/traceroute6/traceroute6.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: traceroute6.c,v 1.27 2002/08/27 00:39:36 itojun Exp $ */
-/* $KAME: traceroute6.c,v 1.58 2002/08/27 00:33:39 itojun Exp $ */
+/* $OpenBSD: traceroute6.c,v 1.28 2002/08/30 07:23:50 itojun Exp $ */
+/* $KAME: traceroute6.c,v 1.60 2002/08/30 04:01:58 onoe Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -296,6 +296,10 @@ struct opacket {
u_char hops; /* hop limit of the packet */
struct timeval tv; /* time packet left */
};
+struct tv32 {
+ u_int32_t tv32_sec;
+ u_int32_t tv32_usec;
+};
u_char packet[512]; /* last inbound (icmp) packet */
struct opacket *outpacket; /* last output (udp) packet */
@@ -328,6 +332,7 @@ struct in6_pktinfo *rcvpktinfo;
struct sockaddr_in6 Src, Dst, Rcv;
int datalen; /* How much data */
+#define ICMP6ECHOLEN 8
/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
char rtbuf[2064];
#ifdef USE_RFC2292BIS
@@ -343,10 +348,12 @@ int first_hop = 1;
int max_hops = 30;
u_int16_t srcport;
u_int16_t port = 32768+666; /* start udp dest port # for probe packets */
+u_int16_t ident;
int options; /* socket options */
int verbose;
int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
+int useicmp;
int lflag; /* print both numerical address & hostname */
int
@@ -364,6 +371,7 @@ main(argc, argv)
int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
size_t size = sizeof(max_hops);
u_long lport;
+ int minlen;
/*
* Receive ICMP
@@ -406,7 +414,7 @@ main(argc, argv)
seq = 0;
- while ((ch = getopt(argc, argv, "df:g:lm:np:q:rs:w:v")) != -1)
+ while ((ch = getopt(argc, argv, "df:g:Ilm:np:q:rs:w:v")) != -1)
switch (ch) {
case 'd':
options |= SO_DEBUG;
@@ -462,6 +470,10 @@ main(argc, argv)
#endif
freehostent(hp);
break;
+ case 'I':
+ useicmp++;
+ ident = htons(getpid() & 0xffff); /* same as ping6 */
+ break;
case 'l':
lflag++;
break;
@@ -592,13 +604,18 @@ main(argc, argv)
exit(1);
}
}
- if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
+ if (useicmp)
+ minlen = ICMP6ECHOLEN + sizeof(struct tv32);
+ else
+ minlen = sizeof(struct opacket);
+ if (datalen < minlen)
+ datalen = minlen;
+ else if (datalen >= MAXPACKET) {
fprintf(stderr,
- "traceroute6: packet size must be 0 <= s < %ld.\n",
- (long)(MAXPACKET - sizeof(struct opacket)));
+ "traceroute6: packet size must be %d <= s < %ld.\n",
+ minlen, (long)MAXPACKET);
exit(1);
}
- datalen += sizeof(struct opacket);
outpacket = (struct opacket *)malloc((unsigned)datalen);
if (! outpacket) {
perror("malloc");
@@ -662,11 +679,15 @@ main(argc, argv)
#endif /*IPSEC*/
/*
- * Send UDP
+ * Send UDP or ICMP
*/
- if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- perror("socket(SOCK_DGRAM)");
- exit(5);
+ if (useicmp) {
+ sndsock = rcvsock;
+ } else {
+ if ((sndsock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("socket(SOCK_DGRAM)");
+ exit(5);
+ }
}
#ifdef SO_SNDBUF
if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
@@ -956,7 +977,6 @@ void
send_probe(seq, hops)
int seq, hops;
{
- struct opacket *op = outpacket;
int i;
if (setsockopt(sndsock, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
@@ -966,9 +986,26 @@ send_probe(seq, hops)
Dst.sin6_port = htons(port + seq);
- op->seq = seq;
- op->hops = hops;
- (void) gettimeofday(&op->tv, NULL);
+ if (useicmp) {
+ struct icmp6_hdr *icp = (struct icmp6_hdr *)outpacket;
+ struct timeval tv;
+ struct tv32 *tv32;
+
+ icp->icmp6_type = ICMP6_ECHO_REQUEST;
+ icp->icmp6_code = 0;
+ icp->icmp6_cksum = 0;
+ icp->icmp6_id = ident;
+ icp->icmp6_seq = htons(seq);
+ (void) gettimeofday(&tv, NULL);
+ tv32 = (struct tv32 *)((u_int8_t *)outpacket + ICMP6ECHOLEN);
+ tv32->tv32_sec = htonl(tv.tv_sec);
+ tv32->tv32_usec = htonl(tv.tv_usec);
+ } else {
+ struct opacket *op = outpacket;
+ op->seq = seq;
+ op->hops = hops;
+ (void) gettimeofday(&op->tv, NULL);
+ }
i = sendto(sndsock, (char *)outpacket, datalen , 0,
(struct sockaddr *)&Dst, Dst.sin6_len);
@@ -1155,9 +1192,18 @@ packet_ok(mhdr, cc, seq)
warnx("failed to get upper layer header");
return(0);
}
- if (up->uh_sport == htons(srcport) &&
+ if (useicmp &&
+ ((struct icmp6_hdr *)up)->icmp6_id == ident &&
+ ((struct icmp6_hdr *)up)->icmp6_seq == htons(seq))
+ return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);
+ else if (!useicmp &&
+ up->uh_sport == htons(srcport) &&
up->uh_dport == htons(port + seq))
return (type == ICMP6_TIME_EXCEEDED ? -1 : code + 1);
+ } else if (useicmp && type == ICMP6_ECHO_REPLY) {
+ if (icp->icmp6_id == ident &&
+ icp->icmp6_seq == htons(seq))
+ return (ICMP6_DST_UNREACH_NOPORT + 1);
}
if (verbose) {
int i;
@@ -1190,7 +1236,7 @@ packet_ok(mhdr, cc, seq)
}
/*
- * Increment pointer until find the UDP header.
+ * Increment pointer until find the UDP or ICMP header.
*/
struct udphdr *
get_udphdr(ip6, lim)
@@ -1210,22 +1256,23 @@ get_udphdr(ip6, lim)
switch (nh) {
case IPPROTO_ESP:
case IPPROTO_TCP:
+ return(NULL);
case IPPROTO_ICMPV6:
- return(NULL);
+ return(useicmp ? (struct udphdr *)cp : NULL);
case IPPROTO_UDP:
- return((struct udphdr *)cp);
+ return(useicmp ? NULL : (struct udphdr *)cp);
case IPPROTO_FRAGMENT:
- hlen = sizeof(struct ip6_frag);
- nh = ((struct ip6_frag *)cp)->ip6f_nxt;
- break;
+ hlen = sizeof(struct ip6_frag);
+ nh = ((struct ip6_frag *)cp)->ip6f_nxt;
+ break;
case IPPROTO_AH:
- hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
- nh = ((struct ip6_ext *)cp)->ip6e_nxt;
- break;
+ hlen = (((struct ip6_ext *)cp)->ip6e_len + 2) << 2;
+ nh = ((struct ip6_ext *)cp)->ip6e_nxt;
+ break;
default:
- hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
- nh = ((struct ip6_ext *)cp)->ip6e_nxt;
- break;
+ hlen = (((struct ip6_ext *)cp)->ip6e_len + 1) << 3;
+ nh = ((struct ip6_ext *)cp)->ip6e_nxt;
+ break;
}
cp += hlen;
@@ -1327,7 +1374,7 @@ usage()
{
fprintf(stderr,
-"usage: traceroute6 [-dlnrv] [-f firsthop] [-g gateway] [-m hoplimit] [-p port]\n"
-" [-q probes] [-s src] [-w waittime] target [datalen]\n");
+"usage: traceroute6 [-dIlnrv] [-f firsthop] [-g gateway] [-m hoplimit]\n"
+" [-p port] [-q probes] [-s src] [-w waittime] target [datalen]\n");
exit(1);
}