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:
parent
951a531e19
commit
39c9cdcdbf
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue