diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/traceroute/traceroute.8 | 20 | ||||
-rw-r--r-- | contrib/traceroute/traceroute.c | 58 |
2 files changed, 72 insertions, 6 deletions
diff --git a/contrib/traceroute/traceroute.8 b/contrib/traceroute/traceroute.8 index 710ecde..3592c51 100644 --- a/contrib/traceroute/traceroute.8 +++ b/contrib/traceroute/traceroute.8 @@ -24,7 +24,7 @@ traceroute \- print the route packets take to network host .na .B traceroute [ -.B \-deFISdnrvx +.B \-dDeFISdnrvx ] [ .B \-f .I first_ttl @@ -112,6 +112,18 @@ Set the "don't fragment" bit. .B \-d Enable socket level debugging. .TP +.B \-D +When an ICMP response to our probe datagram is received, +print the differences between the transmitted packet and +the packet quoted by the ICMP response. +A key showing the location of fields within the transmitted packet is printed, +followed by the original packet in hex, +followed by the quoted packet in hex. +Bytes that are unchanged in the quoted packet are shown as underscores. +Note, +the IP checksum and the TTL of the quoted packet are not expected to match. +By default, only one probe per hop is sent with this option. +.TP .B \-g Specify a loose source route gateway (8 maximum). .TP @@ -163,7 +175,11 @@ listening on a port in the default range, this option can be used to pick an unused port range. .TP .B \-q -Set the number of probes per hop (default is 3). +Set the number of probes per hop (default is 3, +unless +.B -D +is specified, +when it is 1). .TP .B \-r Bypass the normal routing tables and send directly to a host on an attached diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c index fd4165a..d727ccc 100644 --- a/contrib/traceroute/traceroute.c +++ b/contrib/traceroute/traceroute.c @@ -316,6 +316,9 @@ u_char packet[512]; /* last inbound (icmp) packet */ struct ip *outip; /* last output ip packet */ u_char *outp; /* last output inner protocol packet */ +struct ip *hip = NULL; /* Quoted IP header */ +int hiplen = 0; + /* loose source route gateway list (including room for final destination) */ u_int32_t gwlist[NGATEWAYS + 1]; @@ -337,7 +340,7 @@ char *hostname; char *device; static const char devnull[] = "/dev/null"; -int nprobes = 3; +int nprobes = -1; int max_ttl; int first_ttl = 1; u_short ident; @@ -354,6 +357,7 @@ int doipcksum = 1; /* calculate ip checksums by default */ #endif int optlen; /* length of ip options */ int fixedPort = 0; /* Use fixed destination port for TCP and UDP */ +int printdiff = 0; /* Print the difference between sent and quoted */ extern int optind; extern int opterr; @@ -380,6 +384,7 @@ int str2val(const char *, const char *, int, int); void tvsub(struct timeval *, struct timeval *); void usage(void); int wait_for_reply(int, struct sockaddr_in *, const struct timeval *); +void pkt_compare(const u_char *, int, const u_char *, int); #ifndef HAVE_USLEEP int usleep(u_int); #endif @@ -398,6 +403,7 @@ int icmp_check(const u_char *, int); /* Descriptor structure for each outgoing protocol we support */ struct outproto { char *name; /* name of protocol */ + const char *key; /* An ascii key for the bytes of the header */ u_char num; /* IP protocol number */ u_short hdrlen; /* max size of protocol header */ u_short port; /* default base protocol-specific "port" */ @@ -412,6 +418,7 @@ struct outproto { struct outproto protos[] = { { "udp", + "spt dpt len sum", IPPROTO_UDP, sizeof(struct udphdr), 32768 + 666, @@ -420,6 +427,7 @@ struct outproto protos[] = { }, { "tcp", + "spt dpt seq ack xxflwin sum urp", IPPROTO_TCP, sizeof(struct tcphdr), 32768 + 666, @@ -428,6 +436,7 @@ struct outproto protos[] = { }, { "gre", + "flg pro len clid", IPPROTO_GRE, sizeof(struct grehdr), GRE_PPTP_PROTO, @@ -436,6 +445,7 @@ struct outproto protos[] = { }, { "icmp", + "typ cod sum ", IPPROTO_ICMP, sizeof(struct icmp), 0, @@ -444,6 +454,7 @@ struct outproto protos[] = { }, { NULL, + NULL, 0, 2 * sizeof(u_short), 0, @@ -453,6 +464,8 @@ struct outproto protos[] = { }; struct outproto *proto = &protos[0]; +const char *ip_hdr_key = "vhtslen id off tlprsum srcip dstip opts"; + int main(int argc, char **argv) { @@ -522,13 +535,17 @@ main(int argc, char **argv) prog = argv[0]; opterr = 0; - while ((op = getopt(argc, argv, "edFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) + while ((op = getopt(argc, argv, "edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) switch (op) { case 'd': options |= SO_DEBUG; break; + case 'D': + printdiff = 1; + break; + case 'e': fixedPort = 1; break; @@ -628,6 +645,9 @@ main(int argc, char **argv) /* Set requested port, if any, else default for this protocol */ port = (requestPort != -1) ? requestPort : proto->port; + if (nprobes == -1) + nprobes = printdiff ? 1 : 3; + if (first_ttl > max_ttl) { Fprintf(stderr, "%s: first ttl (%d) may not be greater than max ttl (%d)\n", @@ -968,6 +988,16 @@ main(int argc, char **argv) #endif precis = 3; Printf(" %.*f ms", precis, T); + if (printdiff) { + Printf("\n"); + Printf("%*.*s%s\n", + -(outip->ip_hl << 3), + outip->ip_hl << 3, + ip_hdr_key, + proto->key); + pkt_compare((void *)outip, packlen, + (void *)hip, hiplen); + } if (i == -2) { #ifndef ARCHAIC ip = (struct ip *)packet; @@ -1275,10 +1305,10 @@ packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from, return -2; if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || type == ICMP_UNREACH) { - struct ip *hip; u_char *inner; hip = &icp->icmp_ip; + hiplen = ((u_char *)icp + cc) - (u_char *)hip; hlen = hip->ip_hl << 2; inner = (u_char *)((u_char *)hip + hlen); if (hlen + 12 <= cc @@ -1708,13 +1738,33 @@ setproto(char *pname) } void +pkt_compare(const u_char *a, int la, const u_char *b, int lb) { + int l; + int i; + + for (i = 0; i < la; i++) + Printf("%02x", (unsigned int)a[i]); + Printf("\n"); + l = (la <= lb) ? la : lb; + for (i = 0; i < l; i++) + if (a[i] == b[i]) + Printf("__"); + else + Printf("%02x", (unsigned int)b[i]); + for (; i < lb; i++) + Printf("%02x", (unsigned int)b[i]); + Printf("\n"); +} + + +void usage(void) { extern char version[]; Fprintf(stderr, "Version %s\n", version); Fprintf(stderr, - "Usage: %s [-dFInrSvx] [-g gateway] [-i iface] [-f first_ttl]\n" + "Usage: %s [-dDFInrSvx] [-g gateway] [-i iface] [-f first_ttl]\n" "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n" "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog); exit(1); |