diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2002-08-30 07:23:51 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2002-08-30 07:23:51 +0000 |
commit | fe561522dd072de9e9fba92b0958a0a3431e0a95 (patch) | |
tree | b1ba2b635232451273cdfdf7204593c1cef5cb96 | |
parent | a777189c10128f3ffd2d6bd204192d8e93f16db1 (diff) |
have -I option, which causes traceroute6 to use ICMPv6 echo request for probing
(instead of udp).
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.8 | 12 | ||||
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.c | 107 |
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); } |