summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2010-07-08 20:23:03 +0000
committerclaudio <claudio@openbsd.org>2010-07-08 20:23:03 +0000
commit0b10b01e8e15d57aff52e3e07464f293a02d35fe (patch)
tree00e5c3f57d3c87d636b52d2beb9f8f528af2e916
parentAdd definitions for ICMP extended headers available for some ICMP messages (diff)
downloadwireguard-openbsd-0b10b01e8e15d57aff52e3e07464f293a02d35fe.tar.xz
wireguard-openbsd-0b10b01e8e15d57aff52e3e07464f293a02d35fe.zip
Let traceroute parse extended ICMP messages as defined by RFC 4884.
Currently only the MPLS label can be shown (RFC 4950). The extended information is only printed if either -x or -v was used. Initialy based on a port from NetBSD done by dhill@ but mostly rewritten now. OK deraadt@, dhill@
-rw-r--r--usr.sbin/traceroute/traceroute.88
-rw-r--r--usr.sbin/traceroute/traceroute.c138
2 files changed, 137 insertions, 9 deletions
diff --git a/usr.sbin/traceroute/traceroute.8 b/usr.sbin/traceroute/traceroute.8
index fcc4a417446..d699c7543d8 100644
--- a/usr.sbin/traceroute/traceroute.8
+++ b/usr.sbin/traceroute/traceroute.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: traceroute.8,v 1.43 2010/07/03 04:44:52 guenther Exp $
+.\" $OpenBSD: traceroute.8,v 1.44 2010/07/08 20:23:03 claudio Exp $
.\" $NetBSD: traceroute.8,v 1.6 1995/10/12 03:05:50 mycroft Exp $
.\"
.\" Copyright (c) 1990, 1991, 1993
@@ -33,7 +33,7 @@
.\"
.\" @(#)traceroute.8 8.1 (Berkeley) 6/6/93
.\"
-.Dd $Mdocdate: July 3 2010 $
+.Dd $Mdocdate: July 8 2010 $
.Dt TRACEROUTE 8
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Sh SYNOPSIS
.Nm traceroute
.Bk -words
-.Op Fl cDdIlnrSv
+.Op Fl cDdIlnrSvx
.Op Fl f Ar first_ttl
.Op Fl g Ar gateway_addr
.Op Fl m Ar max_ttl
@@ -205,6 +205,8 @@ and
are listed.
.It Fl w Ar waittime
Set the time (in seconds) to wait for a response to a probe (default 5).
+.It Fl x
+Print the ICMP extended headers if available.
.El
.Pp
This program attempts to trace the route an IP packet would follow to some
diff --git a/usr.sbin/traceroute/traceroute.c b/usr.sbin/traceroute/traceroute.c
index 5a142aabd94..1c3771fa230 100644
--- a/usr.sbin/traceroute/traceroute.c
+++ b/usr.sbin/traceroute/traceroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: traceroute.c,v 1.70 2010/07/05 21:44:48 robert Exp $ */
+/* $OpenBSD: traceroute.c,v 1.71 2010/07/08 20:23:03 claudio Exp $ */
/* $NetBSD: traceroute.c,v 1.10 1995/05/21 15:50:45 mycroft Exp $ */
/*-
@@ -220,6 +220,8 @@
#include <arpa/inet.h>
+#include <netmpls/mpls.h>
+
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -229,7 +231,10 @@
#include <string.h>
#include <unistd.h>
-#define MAX_LSRR ((MAX_IPOPTLEN - 4) / 4)
+#define MAX_LSRR ((MAX_IPOPTLEN - 4) / 4)
+
+#define MPLS_LABEL(m) ((m & MPLS_LABEL_MASK) >> MPLS_LABEL_OFFSET)
+#define MPLS_EXP(m) ((m & MPLS_EXP_MASK) >> MPLS_EXP_OFFSET)
/*
* Format of the data in a (udp) probe packet.
@@ -252,6 +257,7 @@ u_char packet[512], *outpacket; /* last inbound (icmp) packet */
int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
void send_probe(int, u_int8_t, int, struct sockaddr_in *);
int packet_ok(u_char *, int, struct sockaddr_in *, int, int);
+void print_exthdr(u_char *, int);
void print(u_char *, int, struct sockaddr_in *);
char *inetname(struct in_addr);
u_short in_cksum(u_short *, int);
@@ -279,6 +285,7 @@ int verbose;
int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
int dump;
+int xflag; /* show ICMP extension header */
int
main(int argc, char *argv[])
@@ -311,7 +318,8 @@ main(int argc, char *argv[])
(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
NULL, 0);
- while ((ch = getopt(argc, argv, "cDdf:g:Ilm:nP:p:q:rSs:t:V:vw:")) != -1)
+ while ((ch = getopt(argc, argv, "cDdf:g:Ilm:nP:p:q:rSs:t:V:vw:x"))
+ != -1)
switch (ch) {
case 'S':
sump = 1;
@@ -445,6 +453,9 @@ main(int argc, char *argv[])
errx(1, "wait must be >1 sec.");
waittime = (int)l;
break;
+ case 'x':
+ xflag = 1;
+ break;
default:
usage();
}
@@ -695,7 +706,9 @@ main(int argc, char *argv[])
printf(" *");
timeout++;
loss++;
- }
+ } else if (cc && probe == nprobes - 1 &&
+ (xflag || verbose))
+ print_exthdr(packet, cc);
(void) fflush(stdout);
}
if (sump)
@@ -707,6 +720,119 @@ main(int argc, char *argv[])
exit(0);
}
+void
+print_exthdr(u_char *buf, int cc)
+{
+ struct icmp_ext_hdr exthdr;
+ struct icmp_ext_obj_hdr objhdr;
+ struct ip *ip;
+ struct icmp *icp;
+ int hlen, first;
+ u_int32_t label;
+ u_int16_t off, olen;
+ u_int8_t type;
+
+ ip = (struct ip *)buf;
+ hlen = ip->ip_hl << 2;
+ if (cc < hlen + ICMP_MINLEN)
+ return;
+ icp = (struct icmp *)(buf + hlen);
+ cc -= hlen + ICMP_MINLEN;
+ buf += hlen + ICMP_MINLEN;
+
+ type = icp->icmp_type;
+ if (type != ICMP_TIMXCEED && type != ICMP_UNREACH &&
+ type != ICMP_PARAMPROB)
+ /* Wrong ICMP type for extension */
+ return;
+
+ off = icp->icmp_length * sizeof(u_int32_t);
+ if (off == 0)
+ /*
+ * rfc 4884 Section 5.5: traceroute MUST try to parse
+ * broken ext headers. Again IETF bent over to please
+ * idotic corporations.
+ */
+ off = ICMP_EXT_OFFSET;
+ else if (off < 128)
+ /* rfc 4884 requires an offset of at least 128 bytes */
+ return;
+
+ /* make sure that at least one extension is present */
+ if (cc < off + sizeof(exthdr) + sizeof(objhdr))
+ /* Not enough space for ICMP extensions */
+ return;
+
+ cc -= off;
+ buf += off;
+ memcpy(&exthdr, buf, sizeof(exthdr));
+
+ /* verify version */
+ if ((exthdr.ieh_version & ICMP_EXT_HDR_VMASK) != ICMP_EXT_HDR_VERSION)
+ return;
+
+ /* verify checksum */
+ if (exthdr.ieh_cksum && in_cksum((u_short *)buf, cc))
+ return;
+
+ buf += sizeof(exthdr);
+ cc -= sizeof(exthdr);
+
+ while (cc > sizeof(objhdr)) {
+ memcpy(&objhdr, buf, sizeof(objhdr));
+ olen = ntohs(objhdr.ieo_length);
+
+ /* Sanity check the length field */
+ if (olen < sizeof(objhdr) || olen > cc)
+ return;
+
+ cc -= olen;
+
+ /* Move past the object header */
+ buf += sizeof(objhdr);
+ olen -= sizeof(objhdr);
+
+ switch (objhdr.ieo_cnum) {
+ case ICMP_EXT_MPLS:
+ /* RFC 4950: ICMP Extensions for MPLS */
+ switch (objhdr.ieo_ctype) {
+ case 1:
+ first = 0;
+ while (olen >= sizeof(u_int32_t)) {
+ memcpy(&label, buf, sizeof(u_int32_t));
+ label = htonl(label);
+ buf += sizeof(u_int32_t);
+ olen -= sizeof(u_int32_t);
+
+ if (first == 0) {
+ printf(" [MPLS: ");
+ first++;
+ } else
+ printf(", ");
+ printf("Label %d Exp %d",
+ MPLS_LABEL(label),
+ MPLS_EXP(label));
+ }
+ if (olen > 0) {
+ printf("|]");
+ return;
+ }
+ if (first != 0)
+ printf("]");
+ break;
+ default:
+ buf += olen;
+ break;
+ }
+ break;
+ case ICMP_EXT_IFINFO:
+ default:
+ buf += olen;
+ break;
+ }
+ }
+}
+
int
wait_for_reply(int sock, struct sockaddr_in *from, struct timeval *sent)
{
@@ -964,7 +1090,7 @@ print(u_char *buf, int cc, struct sockaddr_in *from)
inet_ntoa(from->sin_addr));
if (verbose)
- printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
+ printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
}
@@ -1040,7 +1166,7 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-cDdIlnrSv] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n"
+ "usage: %s [-cDdIlnrSvx] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n"
"\t[-P proto] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n"
"\t[-V rtable] [-w waittime] host [packetsize]\n", __progname);
exit(1);