[PATCH] ICMP extensions for MPLS support for traceroute(8)
Hasso Tepper
hasso at estpak.ee
Mon May 21 16:38:26 PDT 2007
On Thursday 10 May 2007 Matthew Dillon wrote:
> What Joerg is saying is that the patch looks great! But we're
> trying to get away from using bitfields so if it would not be too
> much trouble, could you just make that a u_char and extract the fields
> manually with a macro?
Does attached patch looks better?
--
Hasso Tepper
Elion Enterprises Ltd. [AS3249]
IP & Data Networking Expert
# HG changeset patch
# User Hasso Tepper <hasso at estpak.ee>
# Date 1179779831 -10800
# Node ID 15e09c561ecd9e8a33ca2f4b98298e2f8f170cf2
# Parent 334b28b6842d0f65c6339c592f3bfd1cbfe7b79b
ICMP extensions for MPLS support for traceroute(8).
Obtained-from: NetBSD
diff -r 334b28b6842d -r 15e09c561ecd usr.sbin/traceroute/traceroute.8
--- a/usr.sbin/traceroute/traceroute.8 Mon May 21 08:57:33 2007 +0300
+++ b/usr.sbin/traceroute/traceroute.8 Mon May 21 23:37:11 2007 +0300
@@ -34,7 +34,7 @@
.\" @(#)traceroute.8 8.1 (Berkeley) 6/6/93
.\"
.\" $DragonFly: src/usr.sbin/traceroute/traceroute.8,v 1.3 2006/02/28 02:25:11 swildner Exp $
-.Dd June 6, 1993
+.Dd May 22, 2007
.Dt TRACEROUTE 8
.Os
.Sh NAME
@@ -43,7 +43,7 @@
.Sh SYNOPSIS
.Nm traceroute
.Bk -words
-.Op Fl cdDIlnrSv
+.Op Fl cdDIlMnrSv
.Op Fl f Ar first_ttl
.Op Fl g Ar gateway_addr
.Op Fl m Ar max_ttl
@@ -109,6 +109,8 @@ The default is the value of the system's
The default is the value of the system's
.Cm net.inet.ip.ttl
MIB variable, which defaults to 64.
+.It Fl M
+If found, show the MPLS Label and the Experimental (EXP) bit for the hop.
.It Fl n
Print hop addresses numerically rather than symbolically and numerically
(saves a nameserver address-to-name lookup for each gateway found on the
diff -r 334b28b6842d -r 15e09c561ecd usr.sbin/traceroute/traceroute.c
--- a/usr.sbin/traceroute/traceroute.c Mon May 21 08:57:33 2007 +0300
+++ b/usr.sbin/traceroute/traceroute.c Mon May 21 23:37:11 2007 +0300
@@ -244,6 +244,36 @@ struct packetdata {
u_int32_t usec;
};
+/*
+ * Support for ICMP extensions
+ *
+ * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
+ */
+#define ICMP_EXT_OFFSET 8 + 128 /* ICMP type, code, checksum (unused)
+ * + original datagram */
+#define ICMP_EXT_VERSION 2
+
+/* ICMP Extension Header according to draft-bonica-internet-icmp-16.txt. */
+#define EXT_VERSION(x) (((x) & 0xf0000000) >> 28)
+#define EXT_CHECKSUM(x) ((x) & 0x0000ffff)
+
+/*
+ * ICMP extensions, object header
+ */
+struct icmp_ext_obj_hdr {
+ u_short length;
+ u_char class_num;
+#define MPLS_STACK_ENTRY_CLASS 1
+ u_char c_type;
+#define MPLS_STACK_ENTRY_C_TYPE 1
+};
+
+/* MPLS Label Stack Object. */
+#define MPLS_LABEL(x) (((x) & 0xfffff000) >> 12)
+#define MPLS_EXP(x) (((x) & 0x00000e00) >> 9)
+#define MPLS_STACK(x) (((x) & 0x00000100) >> 8)
+#define MPLS_TTL(x) ((x) & 0x000000ff)
+
struct in_addr gateway[MAX_LSRR + 1];
int lsrrlen = 0;
int32_t sec_perturb;
@@ -251,6 +281,7 @@ int32_t usec_perturb;
u_char packet[512], *outpacket; /* last inbound (icmp) packet */
+void decode_extensions(unsigned char *, int);
void dump_packet(void);
int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
void send_probe(int, u_int8_t, int, struct sockaddr_in *);
@@ -283,6 +314,7 @@ int waittime = 5; /* time to wait for r
int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
int dump;
+int Mflag; /* show MPLS labels if any */
int
main(int argc, char *argv[])
@@ -310,7 +342,7 @@ main(int argc, char *argv[])
sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size, NULL, 0);
- while ((ch = getopt(argc, argv, "SDIdg:f:m:np:q:rs:t:w:vlP:c")) != -1)
+ while ((ch = getopt(argc, argv, "SDIdg:f:m:np:q:rs:t:w:vlP:cM")) != -1)
switch (ch) {
case 'S':
sump = 1;
@@ -363,6 +395,9 @@ main(int argc, char *argv[])
errx(1, "max ttl must be %u to %u.", first_ttl,
MAXTTL);
max_ttl = (u_int8_t)l;
+ break;
+ case 'M':
+ Mflag = 1;
break;
case 'n':
nflag++;
@@ -681,6 +716,8 @@ main(int argc, char *argv[])
timeout++;
loss++;
}
+ else if (cc && probe == nprobes - 1 && Mflag)
+ decode_extensions(packet, cc);
fflush(stdout);
}
if (sump)
@@ -721,6 +758,115 @@ wait_for_reply(int sock, struct sockaddr
free(fdsp);
return (cc);
+}
+
+void
+decode_extensions(unsigned char *buf, int ip_len)
+{
+ uint32_t *cmn_hdr;
+ struct icmp_ext_obj_hdr *obj_hdr;
+ uint32_t mpls_hdr;
+ int data_len, obj_len;
+ struct ip *ip;
+
+ ip = (struct ip *)buf;
+
+ if (ip_len <= (int)(sizeof(struct ip) + ICMP_EXT_OFFSET)) {
+ /*
+ * No support for ICMP extensions on this host
+ */
+ return;
+ }
+
+ /*
+ * Move forward to the start of the ICMP extensions, if present
+ */
+ buf += (ip->ip_hl << 2) + ICMP_EXT_OFFSET;
+ cmn_hdr = (uint32_t *)buf;
+
+ if (EXT_VERSION(ntohl(*cmn_hdr)) != ICMP_EXT_VERSION) {
+ /*
+ * Unknown version
+ */
+ return;
+ }
+
+ data_len = ip_len - ((u_char *)cmn_hdr - (u_char *)ip);
+
+ /*
+ * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
+ * done by sender.
+ *
+ * If the checksum is ok, we'll get 0, as the checksum is calculated
+ * with the checksum field being 0'd.
+ */
+ if (EXT_CHECKSUM(ntohl(*cmn_hdr)) &&
+ in_cksum((u_short *)cmn_hdr, data_len)) {
+ return;
+ }
+
+ buf += sizeof(*cmn_hdr);
+ data_len -= sizeof(*cmn_hdr);
+
+ while (data_len > 0) {
+ obj_hdr = (struct icmp_ext_obj_hdr *)buf;
+ obj_len = ntohs(obj_hdr->length);
+
+ /*
+ * Sanity check the length field
+ */
+ if (obj_len > data_len) {
+ return;
+ }
+
+ data_len -= obj_len;
+
+ /*
+ * Move past the object header
+ */
+ buf += sizeof(struct icmp_ext_obj_hdr);
+ obj_len -= sizeof(struct icmp_ext_obj_hdr);
+
+ switch (obj_hdr->class_num) {
+ case MPLS_STACK_ENTRY_CLASS:
+ switch (obj_hdr->c_type) {
+ case MPLS_STACK_ENTRY_C_TYPE:
+ while (obj_len >= (int)sizeof(uint32_t)) {
+ mpls_hdr = ntohl(*(uint32_t *)buf);
+
+ buf += sizeof(uint32_t);
+ obj_len -= sizeof(uint32_t);
+ printf(" [MPLS: Label %d Exp %d]",
+ MPLS_LABEL(mpls_hdr), MPLS_EXP(mpls_hdr));
+ }
+ if (obj_len > 0) {
+ /*
+ * Something went wrong, and we're at
+ * a unknown offset into the packet,
+ * ditch the rest of it.
+ */
+ return;
+ }
+ break;
+ default:
+ /*
+ * Unknown object, skip past it
+ */
+ buf += ntohs(obj_hdr->length) -
+ sizeof(struct icmp_ext_obj_hdr);
+ break;
+ }
+ break;
+
+ default:
+ /*
+ * Unknown object, skip past it
+ */
+ buf += ntohs(obj_hdr->length) -
+ sizeof(struct icmp_ext_obj_hdr);
+ break;
+ }
+ }
}
void
@@ -1022,7 +1168,7 @@ usage(void)
usage(void)
{
fprintf(stderr,
- "usage: %s [-cdDIlnrSv] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n"
+ "usage: %s [-cdDIlMnrSv] [-f first_ttl] [-g gateway_addr] [-m max_ttl]\n"
"\t[-p port] [-P proto] [-q nqueries] [-s src_addr] [-t tos]\n"
"\t[-w waittime] host [packetsize]\n", getprogname());
exit(1);
More information about the Submit
mailing list