Bug #633 » icmp-mpls.patch
usr.sbin/traceroute/traceroute.8 Mon May 21 08:57:33 2007 +0300 → usr.sbin/traceroute/traceroute.8 Mon May 21 23:37:11 2007 +0300 | ||
---|---|---|
.\" @(#)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
|
||
... | ... | |
.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
|
||
... | ... | |
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
|
usr.sbin/traceroute/traceroute.c Mon May 21 08:57:33 2007 +0300 → usr.sbin/traceroute/traceroute.c Mon May 21 23:37:11 2007 +0300 | ||
---|---|---|
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;
|
||
... | ... | |
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 *);
|
||
... | ... | |
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[])
|
||
... | ... | |
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;
|
||
... | ... | |
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++;
|
||
... | ... | |
timeout++;
|
||
loss++;
|
||
}
|
||
else if (cc && probe == nprobes - 1 && Mflag)
|
||
decode_extensions(packet, cc);
|
||
fflush(stdout);
|
||
}
|
||
if (sump)
|
||
... | ... | |
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
|
||
... | ... | |
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);
|