summaryrefslogtreecommitdiffstats
path: root/contrib/traceroute/traceroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/traceroute/traceroute.c')
-rw-r--r--contrib/traceroute/traceroute.c58
1 files changed, 54 insertions, 4 deletions
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);
OpenPOWER on IntegriCloud