Show MPLS ICMP extensions. Only available if -M is passed.

Example:
	RC02-02 (195.245.142.66)  45.707 ms  20.418 ms  34.042 ms [MPLS: label: 515, exp: 0x0, ttl: 1]
	gr1-p340.attga.ip.att.net (12.123.20.190)  241.878 ms  251.945 ms [MPLS: label: 32133, exp: 0x0, ttl: 1]


Based on PR 22523: By Jesper Skriver (updated by ww@parc.styx.org and Mihai
CHELARU).

Things not in the PR that I changed/added:
       * changed exp and label to lower case
       * added ttl (probably not worth it but who knows..)
       * KNF/style/indent
       * C99 uintXX_t
This commit is contained in:
rpaulo 2006-02-17 21:31:18 +00:00
parent 951a531e19
commit 39c9cdcdbf
2 changed files with 181 additions and 7 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: traceroute.8,v 1.27 2005/11/09 23:43:59 wiz Exp $ .\" $NetBSD: traceroute.8,v 1.28 2006/02/17 21:31:18 rpaulo Exp $
.\" .\"
.\" Copyright (c) 1989, 1995, 1996, 1997 .\" Copyright (c) 1989, 1995, 1996, 1997
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -17,7 +17,7 @@
.\" .\"
.\" Header: traceroute.8,v 1.11 97/04/22 13:45:13 leres Exp .\" Header: traceroute.8,v 1.11 97/04/22 13:45:13 leres Exp
.\" .\"
.TH TRACEROUTE 8 "6 November 2005" .TH TRACEROUTE 8 "17 February 2006"
.UC 6 .UC 6
.SH NAME .SH NAME
traceroute \- print the route packets take to network host traceroute \- print the route packets take to network host
@ -25,7 +25,7 @@ traceroute \- print the route packets take to network host
.na .na
.B traceroute .B traceroute
[ [
.B \-aDFPIdlnrvx .B \-aDFPIdlMnrvx
] [ ] [
.B \-f .B \-f
.I first_ttl .I first_ttl
@ -131,6 +131,9 @@ packets. The default value is taken from the
.I net.inet.ip.ttl .I net.inet.ip.ttl
sysctl(3) variable. sysctl(3) variable.
.TP .TP
.B \-M
If found, show the MPLS Label and the Experimental (EXP) bit for the hop.
.TP
.B \-n .B \-n
Print hop addresses numerically rather than symbolically and numerically Print hop addresses numerically rather than symbolically and numerically
(saves a nameserver address-to-name lookup for each gateway found on the (saves a nameserver address-to-name lookup for each gateway found on the

View File

@ -1,4 +1,4 @@
/* $NetBSD: traceroute.c,v 1.61 2004/04/22 01:41:22 itojun Exp $ */ /* $NetBSD: traceroute.c,v 1.62 2006/02/17 21:31:18 rpaulo Exp $ */
/* /*
* Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997 * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997
@ -29,7 +29,7 @@ static const char rcsid[] =
#else #else
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997\n\ __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997\n\
The Regents of the University of California. All rights reserved.\n"); The Regents of the University of California. All rights reserved.\n");
__RCSID("$NetBSD: traceroute.c,v 1.61 2004/04/22 01:41:22 itojun Exp $"); __RCSID("$NetBSD: traceroute.c,v 1.62 2006/02/17 21:31:18 rpaulo Exp $");
#endif #endif
#endif #endif
@ -270,6 +270,54 @@ struct outdata {
struct timeval tv; /* time packet left */ struct timeval tv; /* time packet left */
}; };
/*
* Support for ICMP extensions
*
* http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
*/
#define ICMP_EXT_OFFSET 8 /* ICMP type, code, checksum, unused */ + \
128 /* original datagram */
#define ICMP_EXT_VERSION 2
/*
* ICMP extensions, common header
*/
struct icmp_ext_cmn_hdr {
#if BYTE_ORDER == BIG_ENDIAN
unsigned char version:4;
unsigned char reserved1:4;
#else
unsigned char reserved1:4;
unsigned char version:4;
#endif
unsigned char reserved2;
unsigned short checksum;
};
/*
* 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
};
struct mpls_header {
#if BYTE_ORDER == BIG_ENDIAN
uint32_t label:20;
unsigned char exp:3;
unsigned char s:1;
unsigned char ttl:8;
#else
unsigned char ttl:8;
unsigned char s:1;
unsigned char exp:3;
uint32_t label:20;
#endif
};
u_char packet[512]; /* last inbound (icmp) packet */ u_char packet[512]; /* last inbound (icmp) packet */
struct ip *outip; /* last output (udp) packet */ struct ip *outip; /* last output (udp) packet */
@ -308,6 +356,7 @@ int verbose;
int waittime = 5; /* time to wait for response (in seconds) */ int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */ int nflag; /* print addresses numerically */
int dump; int dump;
int Mflag; /* show MPLS labels if any */
int as_path; /* print as numbers for each hop */ int as_path; /* print as numbers for each hop */
char *as_server = NULL; char *as_server = NULL;
void *asn; void *asn;
@ -369,6 +418,7 @@ int str2val(const char *, const char *, int, int);
void tvsub(struct timeval *, struct timeval *); void tvsub(struct timeval *, struct timeval *);
__dead void usage(void); __dead void usage(void);
int wait_for_reply(int, struct sockaddr_in *, struct timeval *); int wait_for_reply(int, struct sockaddr_in *, struct timeval *);
void decode_extensions(unsigned char *buf, int ip_len);
void frag_err(void); void frag_err(void);
int find_local_ip(struct sockaddr_in *, struct sockaddr_in *); int find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
#ifdef IPSEC #ifdef IPSEC
@ -407,7 +457,7 @@ main(int argc, char **argv)
prog = argv[0]; prog = argv[0];
opterr = 0; opterr = 0;
while ((op = getopt(argc, argv, "aA:dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1) while ((op = getopt(argc, argv, "aA:dDFPIMnlrvxf:g:i:m:p:q:s:t:w:")) != -1)
switch (op) { switch (op) {
case 'a': case 'a':
@ -462,6 +512,10 @@ main(int argc, char **argv)
max_ttl = str2val(optarg, "max ttl", 1, 255); max_ttl = str2val(optarg, "max ttl", 1, 255);
break; break;
case 'M':
Mflag = 1;
break;
case 'n': case 'n':
++nflag; ++nflag;
break; break;
@ -1001,6 +1055,8 @@ again:
} }
if (cc == 0) if (cc == 0)
Printf(" *"); Printf(" *");
else if (cc && probe == nprobes - 1 && Mflag)
decode_extensions(packet, cc);
(void)fflush(stdout); (void)fflush(stdout);
} }
putchar('\n'); putchar('\n');
@ -1051,6 +1107,121 @@ wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
return(cc); return(cc);
} }
void
decode_extensions(unsigned char *buf, int ip_len)
{
struct icmp_ext_cmn_hdr *cmn_hdr;
struct icmp_ext_obj_hdr *obj_hdr;
union {
struct mpls_header mpls;
uint32_t mpls_h;
} mpls;
int datalen, obj_len;
struct ip *ip;
ip = (struct ip *)buf;
if (ip_len <= 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 = (struct icmp_ext_cmn_hdr *)buf;
if (cmn_hdr->version != ICMP_EXT_VERSION) {
/*
* Unknown version
*/
return;
}
datalen = 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 (ntohs(cmn_hdr->checksum) &&
in_cksum((u_short *)cmn_hdr, datalen)) {
return;
}
buf += sizeof(*cmn_hdr);
datalen -= sizeof(*cmn_hdr);
while (datalen > 0) {
obj_hdr = (struct icmp_ext_obj_hdr *)buf;
obj_len = ntohs(obj_hdr->length);
/*
* Sanity check the length field
*/
if (obj_len > datalen) {
return;
}
datalen -= 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 >= sizeof(uint32_t)) {
mpls.mpls_h = ntohl(*(uint32_t *)buf);
buf += sizeof(uint32_t);
obj_len -= sizeof(uint32_t);
printf(" [MPLS: label: %d, exp: 0x%x,"
" ttl: %d]", mpls.mpls.label,
mpls.mpls.exp, mpls.mpls.ttl);
}
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 void
dump_packet() dump_packet()
{ {
@ -1602,7 +1773,7 @@ usage(void)
extern char version[]; extern char version[];
Fprintf(stderr, "Version %s\n", version); Fprintf(stderr, "Version %s\n", version);
Fprintf(stderr, "usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \ Fprintf(stderr, "usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \
[-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\ [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
[-w waittime] [-A as_server] host [packetlen]\n", [-w waittime] [-A as_server] host [packetlen]\n",
prog); prog);