Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.57
      1 /*	$NetBSD: traceroute.c,v 1.57 2002/11/16 15:43:52 itojun Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that: (1) source code distributions
      9  * retain the above copyright notice and this paragraph in its entirety, (2)
     10  * distributions including binary code include the above copyright notice and
     11  * this paragraph in its entirety in the documentation or other materials
     12  * provided with the distribution, and (3) all advertising materials mentioning
     13  * features or use of this software display the following acknowledgement:
     14  * ``This product includes software developed by the University of California,
     15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     16  * the University nor the names of its contributors may be used to endorse
     17  * or promote products derived from this software without specific prior
     18  * written permission.
     19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     22  */
     23 
     24 #include <sys/cdefs.h>
     25 #ifndef lint
     26 #if 0
     27 static const char rcsid[] =
     28     "@(#)Header: traceroute.c,v 1.49 97/06/13 02:30:23 leres Exp  (LBL)";
     29 #else
     30 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997\n\
     31 The Regents of the University of California.  All rights reserved.\n");
     32 __RCSID("$NetBSD: traceroute.c,v 1.57 2002/11/16 15:43:52 itojun Exp $");
     33 #endif
     34 #endif
     35 
     36 /*
     37  * traceroute host  - trace the route ip packets follow going to "host".
     38  *
     39  * Attempt to trace the route an ip packet would follow to some
     40  * internet host.  We find out intermediate hops by launching probe
     41  * packets with a small ttl (time to live) then listening for an
     42  * icmp "time exceeded" reply from a gateway.  We start our probes
     43  * with a ttl of one and increase by one until we get an icmp "port
     44  * unreachable" (which means we got to "host") or hit a max (which
     45  * defaults to 30 hops & can be changed with the -m flag).  Three
     46  * probes (change with -q flag) are sent at each ttl setting and a
     47  * line is printed showing the ttl, address of the gateway and
     48  * round trip time of each probe.  If the probe answers come from
     49  * different gateways, the address of each responding system will
     50  * be printed.  If there is no response within a 5 sec. timeout
     51  * interval (changed with the -w flag), a "*" is printed for that
     52  * probe.
     53  *
     54  * Probe packets are UDP format.  We don't want the destination
     55  * host to process them so the destination port is set to an
     56  * unlikely value (if some clod on the destination is using that
     57  * value, it can be changed with the -p flag).
     58  *
     59  * A sample use might be:
     60  *
     61  *     [yak 71]% traceroute nis.nsf.net.
     62  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
     63  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
     64  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     65  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     66  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
     67  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
     68  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
     69  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
     70  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
     71  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
     72  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
     73  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
     74  *
     75  * Note that lines 2 & 3 are the same.  This is due to a buggy
     76  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
     77  * packets with a zero ttl.
     78  *
     79  * A more interesting example is:
     80  *
     81  *     [yak 72]% traceroute allspice.lcs.mit.edu.
     82  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
     83  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
     84  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
     85  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
     86  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
     87  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
     88  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
     89  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
     90  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
     91  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
     92  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
     93  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
     94  *     12  * * *
     95  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
     96  *     14  * * *
     97  *     15  * * *
     98  *     16  * * *
     99  *     17  * * *
    100  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
    101  *
    102  * (I start to see why I'm having so much trouble with mail to
    103  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
    104  * either don't send ICMP "time exceeded" messages or send them
    105  * with a ttl too small to reach us.  14 - 17 are running the
    106  * MIT C Gateway code that doesn't send "time exceeded"s.  God
    107  * only knows what's going on with 12.
    108  *
    109  * The silent gateway 12 in the above may be the result of a bug in
    110  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
    111  * sends an unreachable message using whatever ttl remains in the
    112  * original datagram.  Since, for gateways, the remaining ttl is
    113  * zero, the icmp "time exceeded" is guaranteed to not make it back
    114  * to us.  The behavior of this bug is slightly more interesting
    115  * when it appears on the destination system:
    116  *
    117  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
    118  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
    119  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
    120  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
    121  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
    122  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
    123  *      7  * * *
    124  *      8  * * *
    125  *      9  * * *
    126  *     10  * * *
    127  *     11  * * *
    128  *     12  * * *
    129  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
    130  *
    131  * Notice that there are 12 "gateways" (13 is the final
    132  * destination) and exactly the last half of them are "missing".
    133  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
    134  * is using the ttl from our arriving datagram as the ttl in its
    135  * icmp reply.  So, the reply will time out on the return path
    136  * (with no notice sent to anyone since icmp's aren't sent for
    137  * icmp's) until we probe with a ttl that's at least twice the path
    138  * length.  I.e., rip is really only 7 hops away.  A reply that
    139  * returns with a ttl of 1 is a clue this problem exists.
    140  * Traceroute prints a "!" after the time if the ttl is <= 1.
    141  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
    142  * non-standard (HPUX) software, expect to see this problem
    143  * frequently and/or take care picking the target host of your
    144  * probes.
    145  *
    146  * Other possible annotations after the time are !H, !N, !P (got a host,
    147  * network or protocol unreachable, respectively), !S or !F (source
    148  * route failed or fragmentation needed -- neither of these should
    149  * ever occur and the associated gateway is busted if you see one).  If
    150  * almost all the probes result in some kind of unreachable, traceroute
    151  * will give up and exit.
    152  *
    153  * Notes
    154  * -----
    155  * This program must be run by root or be setuid.  (I suggest that
    156  * you *don't* make it setuid -- casual use could result in a lot
    157  * of unnecessary traffic on our poor, congested nets.)
    158  *
    159  * This program requires a kernel mod that does not appear in any
    160  * system available from Berkeley:  A raw ip socket using proto
    161  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
    162  * opposed to data to be wrapped in a ip datagram).  See the README
    163  * file that came with the source to this program for a description
    164  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
    165  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
    166  * MODIFIED TO RUN THIS PROGRAM.
    167  *
    168  * The udp port usage may appear bizarre (well, ok, it is bizarre).
    169  * The problem is that an icmp message only contains 8 bytes of
    170  * data from the original datagram.  8 bytes is the size of a udp
    171  * header so, if we want to associate replies with the original
    172  * datagram, the necessary information must be encoded into the
    173  * udp header (the ip id could be used but there's no way to
    174  * interlock with the kernel's assignment of ip id's and, anyway,
    175  * it would have taken a lot more kernel hacking to allow this
    176  * code to set the ip id).  So, to allow two or more users to
    177  * use traceroute simultaneously, we use this task's pid as the
    178  * source port (the high bit is set to move the port number out
    179  * of the "likely" range).  To keep track of which probe is being
    180  * replied to (so times and/or hop counts don't get confused by a
    181  * reply that was delayed in transit), we increment the destination
    182  * port number before each probe.
    183  *
    184  * Don't use this as a coding example.  I was trying to find a
    185  * routing problem and this code sort-of popped out after 48 hours
    186  * without sleep.  I was amazed it ever compiled, much less ran.
    187  *
    188  * I stole the idea for this program from Steve Deering.  Since
    189  * the first release, I've learned that had I attended the right
    190  * IETF working group meetings, I also could have stolen it from Guy
    191  * Almes or Matt Mathis.  I don't know (or care) who came up with
    192  * the idea first.  I envy the originators' perspicacity and I'm
    193  * glad they didn't keep the idea a secret.
    194  *
    195  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
    196  * enhancements to the original distribution.
    197  *
    198  * I've hacked up a round-trip-route version of this that works by
    199  * sending a loose-source-routed udp datagram through the destination
    200  * back to yourself.  Unfortunately, SO many gateways botch source
    201  * routing, the thing is almost worthless.  Maybe one day...
    202  *
    203  *  -- Van Jacobson (van (at) ee.lbl.gov)
    204  *     Tue Dec 20 03:50:13 PST 1988
    205  */
    206 
    207 #include <sys/param.h>
    208 #include <sys/file.h>
    209 #include <sys/ioctl.h>
    210 #include <sys/socket.h>
    211 #include <sys/time.h>
    212 #include <sys/sysctl.h>
    213 
    214 #include <netinet/in_systm.h>
    215 #include <netinet/in.h>
    216 #include <netinet/ip.h>
    217 #include <netinet/ip_var.h>
    218 #include <netinet/ip_icmp.h>
    219 #include <netinet/udp.h>
    220 #include <netinet/udp_var.h>
    221 
    222 #include <arpa/inet.h>
    223 
    224 #include <ctype.h>
    225 #include <errno.h>
    226 #ifdef HAVE_MALLOC_H
    227 #include <malloc.h>
    228 #endif
    229 #include <memory.h>
    230 #include <netdb.h>
    231 #include <stdio.h>
    232 #include <stdlib.h>
    233 #include <string.h>
    234 #include <unistd.h>
    235 #include <poll.h>
    236 #ifdef IPSEC
    237 #include <net/route.h>
    238 #include <netinet6/ipsec.h>
    239 #endif
    240 
    241 #include "gnuc.h"
    242 #ifdef HAVE_OS_PROTO_H
    243 #include "os-proto.h"
    244 #endif
    245 
    246 #include "ifaddrlist.h"
    247 #include "savestr.h"
    248 #include "as.h"
    249 
    250 /* Maximum number of gateways (include room for one noop) */
    251 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
    252 
    253 #ifndef MAXHOSTNAMELEN
    254 #define MAXHOSTNAMELEN	64
    255 #endif
    256 
    257 #define Fprintf (void)fprintf
    258 #define Printf (void)printf
    259 
    260 /* Host name and address list */
    261 struct hostinfo {
    262 	char *name;
    263 	int n;
    264 	u_int32_t *addrs;
    265 };
    266 
    267 /* Data section of the probe packet */
    268 struct outdata {
    269 	u_char seq;		/* sequence number of this packet */
    270 	u_char ttl;		/* ttl packet left with */
    271 	struct timeval tv;	/* time packet left */
    272 };
    273 
    274 u_char	packet[512];		/* last inbound (icmp) packet */
    275 
    276 struct ip *outip;		/* last output (udp) packet */
    277 struct udphdr *outudp;		/* last output (udp) packet */
    278 void *outmark;			/* packed location of struct outdata */
    279 struct outdata outsetup;	/* setup and copy for alignment */
    280 
    281 struct icmp *outicmp;		/* last output (icmp) packet */
    282 
    283 /* loose source route gateway list (including room for final destination) */
    284 u_int32_t gwlist[NGATEWAYS + 1];
    285 
    286 int s;				/* receive (icmp) socket file descriptor */
    287 int sndsock;			/* send (udp/icmp) socket file descriptor */
    288 
    289 struct sockaddr whereto;	/* Who to try to reach */
    290 struct sockaddr_in wherefrom;	/* Who we are */
    291 int packlen;			/* total length of packet */
    292 int minpacket;			/* min ip packet size */
    293 int maxpacket = 32 * 1024;	/* max ip packet size */
    294 int printed_ttl = 0;
    295 
    296 char *prog;
    297 char *source;
    298 char *hostname;
    299 char *device;
    300 
    301 int nprobes = 3;
    302 int max_ttl = 30;
    303 int first_ttl = 1;
    304 u_int16_t ident;
    305 in_port_t port = 32768 + 666;	/* start udp dest port # for probe packets */
    306 
    307 int options;			/* socket options */
    308 int verbose;
    309 int waittime = 5;		/* time to wait for response (in seconds) */
    310 int nflag;			/* print addresses numerically */
    311 int dump;
    312 int as_path;			/* print as numbers for each hop */
    313 char *as_server = NULL;
    314 void *asn;
    315 int useicmp;			/* use icmp echo instead of udp packets */
    316 #ifdef CANT_HACK_CKSUM
    317 int docksum = 0;		/* don't calculate checksums */
    318 #else
    319 int docksum = 1;		/* calculate checksums */
    320 #endif
    321 int optlen;			/* length of ip options */
    322 
    323 int mtus[] = {
    324         17914,
    325          8166,
    326          4464,
    327          4352,
    328          2048,
    329          2002,
    330          1536,
    331          1500,
    332          1492,
    333 	 1480,
    334 	 1280,
    335          1006,
    336           576,
    337           552,
    338           544,
    339           512,
    340           508,
    341           296,
    342            68,
    343             0
    344 };
    345 int *mtuptr = &mtus[0];
    346 int mtudisc = 0;
    347 int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
    348 
    349 extern int optind;
    350 extern int opterr;
    351 extern char *optarg;
    352 
    353 /* Forwards */
    354 double	deltaT(struct timeval *, struct timeval *);
    355 void	freehostinfo(struct hostinfo *);
    356 void	getaddr(u_int32_t *, char *);
    357 struct	hostinfo *gethostinfo(char *);
    358 u_int16_t in_cksum(u_int16_t *, int);
    359 u_int16_t in_cksum2(u_int16_t, u_int16_t *, int);
    360 char	*inetname(struct in_addr);
    361 int	main(int, char **);
    362 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
    363 char	*pr_type(u_char);
    364 void	print(u_char *, int, struct sockaddr_in *);
    365 void	resize_packet(void);
    366 void	dump_packet(void);
    367 void	send_probe(int, int, struct timeval *);
    368 void	setsin(struct sockaddr_in *, u_int32_t);
    369 int	str2val(const char *, const char *, int, int);
    370 void	tvsub(struct timeval *, struct timeval *);
    371 __dead	void usage(void);
    372 int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
    373 void	frag_err(void);
    374 int	find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
    375 #ifdef IPSEC
    376 #ifdef IPSEC_POLICY_IPSEC
    377 int	setpolicy(int so, char *policy);
    378 #endif
    379 #endif
    380 
    381 int
    382 main(int argc, char **argv)
    383 {
    384 	int op, code, n;
    385 	char *cp;
    386 	u_char *outp;
    387 	u_int32_t *ap;
    388 	struct sockaddr_in *from = &wherefrom;
    389 	struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
    390 	struct hostinfo *hi;
    391 	int on = 1;
    392 	int ttl, probe, i;
    393 	int seq = 0;
    394 	int tos = 0, settos = 0, ttl_flag = 0;
    395 	int lsrr = 0;
    396 	u_int16_t off = 0;
    397 	struct ifaddrlist *al, *al2;
    398 	char errbuf[132];
    399 	int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
    400 	size_t size = sizeof(max_ttl);
    401 
    402 	(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
    403 	    NULL, 0);
    404 
    405 	if ((cp = strrchr(argv[0], '/')) != NULL)
    406 		prog = cp + 1;
    407 	else
    408 		prog = argv[0];
    409 
    410 	opterr = 0;
    411 	while ((op = getopt(argc, argv, "aA:dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1)
    412 		switch (op) {
    413 
    414 		case 'a':
    415 			as_path = 1;
    416 			break;
    417 
    418 		case 'A':
    419 			as_path = 1;
    420 			as_server = optarg;
    421 			break;
    422 
    423 		case 'd':
    424 			options |= SO_DEBUG;
    425 			break;
    426 
    427 		case 'D':
    428 			dump = 1;
    429 			break;
    430 
    431 		case 'f':
    432 			first_ttl = str2val(optarg, "first ttl", 1, 255);
    433 			break;
    434 
    435 		case 'F':
    436 			off = IP_DF;
    437 			break;
    438 
    439 		case 'g':
    440 			if (lsrr >= NGATEWAYS) {
    441 				Fprintf(stderr,
    442 				    "%s: No more than %d gateways\n",
    443 				    prog, NGATEWAYS);
    444 				exit(1);
    445 			}
    446 			getaddr(gwlist + lsrr, optarg);
    447 			++lsrr;
    448 			break;
    449 
    450 		case 'i':
    451 			device = optarg;
    452 			break;
    453 
    454 		case 'I':
    455 			++useicmp;
    456 			break;
    457 
    458 		case 'l':
    459 			++ttl_flag;
    460 			break;
    461 
    462 		case 'm':
    463 			max_ttl = str2val(optarg, "max ttl", 1, 255);
    464 			break;
    465 
    466 		case 'n':
    467 			++nflag;
    468 			break;
    469 
    470 		case 'p':
    471 			port = str2val(optarg, "port", 1, -1);
    472 			break;
    473 
    474 		case 'q':
    475 			nprobes = str2val(optarg, "nprobes", 1, -1);
    476 			break;
    477 
    478 		case 'r':
    479 			options |= SO_DONTROUTE;
    480 			break;
    481 
    482 		case 's':
    483 			/*
    484 			 * set the ip source address of the outbound
    485 			 * probe (e.g., on a multi-homed host).
    486 			 */
    487 			source = optarg;
    488 			break;
    489 
    490 		case 't':
    491 			tos = str2val(optarg, "tos", 0, 255);
    492 			++settos;
    493 			break;
    494 
    495 		case 'v':
    496 			++verbose;
    497 			break;
    498 
    499 		case 'x':
    500 			docksum = (docksum == 0);
    501 			break;
    502 
    503 		case 'w':
    504 			waittime = str2val(optarg, "wait time", 2, 24 * 3600);
    505 			break;
    506 
    507 		case 'P':
    508 			off = IP_DF;
    509 			mtudisc = 1;
    510 			break;
    511 
    512 		default:
    513 			usage();
    514 		}
    515 
    516 	if (first_ttl > max_ttl) {
    517 		Fprintf(stderr,
    518 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
    519 		    prog, first_ttl, max_ttl);
    520 		exit(1);
    521 	}
    522 
    523 	if (!docksum)
    524 		Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
    525 
    526 	if (lsrr > 0)
    527 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
    528 	minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
    529 	if (useicmp)
    530 		minpacket += 8;			/* XXX magic number */
    531 	else
    532 		minpacket += sizeof(*outudp);
    533 	if (packlen == 0)
    534 		packlen = minpacket;		/* minimum sized packet */
    535 	else if (minpacket > packlen || packlen > maxpacket) {
    536 		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
    537 		    prog, minpacket, maxpacket);
    538 		exit(1);
    539 	}
    540 
    541 	if (mtudisc)
    542 		packlen = *mtuptr++;
    543 
    544 	/* Process destination and optional packet size */
    545 	switch (argc - optind) {
    546 
    547 	case 2:
    548 		packlen = str2val(argv[optind + 1],
    549 		    "packet length", minpacket, -1);
    550 		/* Fall through */
    551 
    552 	case 1:
    553 		hostname = argv[optind];
    554 		hi = gethostinfo(hostname);
    555 		setsin(to, hi->addrs[0]);
    556 		if (hi->n > 1)
    557 			Fprintf(stderr,
    558 		    "%s: Warning: %s has multiple addresses; using %s\n",
    559 				prog, hostname, inet_ntoa(to->sin_addr));
    560 		hostname = hi->name;
    561 		hi->name = NULL;
    562 		freehostinfo(hi);
    563 		break;
    564 
    565 	default:
    566 		usage();
    567 	}
    568 
    569 #ifdef HAVE_SETLINEBUF
    570 	setlinebuf (stdout);
    571 #else
    572 	setvbuf(stdout, NULL, _IOLBF, 0);
    573 #endif
    574 
    575 	outip = (struct ip *)malloc((unsigned)packlen);
    576 	if (outip == NULL) {
    577 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
    578 		exit(1);
    579 	}
    580 	memset((char *)outip, 0, packlen);
    581 
    582 	outip->ip_v = IPVERSION;
    583 	if (settos)
    584 		outip->ip_tos = tos;
    585 #ifdef BYTESWAP_IP_LEN
    586 	outip->ip_len = htons(packlen);
    587 #else
    588 	outip->ip_len = packlen;
    589 #endif
    590 	outip->ip_off = off;
    591 	outp = (u_char *)(outip + 1);
    592 #ifdef HAVE_RAW_OPTIONS
    593 	if (lsrr > 0) {
    594 		u_char *optlist;
    595 
    596 		optlist = outp;
    597 		outp += optlen;
    598 
    599 		/* final hop */
    600 		gwlist[lsrr] = to->sin_addr.s_addr;
    601 
    602 		outip->ip_dst.s_addr = gwlist[0];
    603 
    604 		/* force 4 byte alignment */
    605 		optlist[0] = IPOPT_NOP;
    606 		/* loose source route option */
    607 		optlist[1] = IPOPT_LSRR;
    608 		i = lsrr * sizeof(gwlist[0]);
    609 		optlist[2] = i + 3;
    610 		/* Pointer to LSRR addresses */
    611 		optlist[3] = IPOPT_MINOFF;
    612 		memcpy(optlist + 4, gwlist + 1, i);
    613 	} else
    614 #endif
    615 		outip->ip_dst = to->sin_addr;
    616 
    617 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
    618 	ident = (getpid() & 0xffff) | 0x8000;
    619 	if (useicmp) {
    620 		outip->ip_p = IPPROTO_ICMP;
    621 
    622 		outicmp = (struct icmp *)outp;
    623 		outicmp->icmp_type = ICMP_ECHO;
    624 		outicmp->icmp_id = htons(ident);
    625 
    626 		outmark = outp + 8;	/* XXX magic number */
    627 	} else {
    628 		outip->ip_p = IPPROTO_UDP;
    629 
    630 		outudp = (struct udphdr *)outp;
    631 		outudp->uh_sport = htons(ident);
    632 		outudp->uh_ulen =
    633 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
    634 		outmark = outudp + 1;
    635 	}
    636 
    637 	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
    638 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
    639 		exit(1);
    640 	}
    641 	if (options & SO_DEBUG)
    642 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
    643 		    sizeof(on));
    644 #ifdef IPSEC
    645 #ifdef IPSEC_POLICY_IPSEC
    646 	/*
    647 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    648 	 * turned off.
    649 	 */
    650 	if (setpolicy(s, "in bypass") < 0)
    651 		exit(1);
    652 	if (setpolicy(s, "out bypass") < 0)
    653 		exit(1);
    654 #else
    655     {
    656 	int level = IPSEC_LEVEL_AVAIL;
    657 
    658 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    659 		sizeof(level));
    660 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    661 		sizeof(level));
    662 #ifdef IP_AUTH_TRANS_LEVEL
    663 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    664 		sizeof(level));
    665 #else
    666 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    667 		sizeof(level));
    668 #endif
    669 #ifdef IP_AUTH_NETWORK_LEVEL
    670 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    671 		sizeof(level));
    672 #endif
    673     }
    674 #endif /*IPSEC_POLICY_IPSEC*/
    675 #endif /*IPSEC*/
    676 
    677 #ifndef __hpux
    678 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    679 #else
    680 	sndsock = socket(AF_INET, SOCK_RAW,
    681 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
    682 #endif
    683 	if (sndsock < 0) {
    684 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
    685 		exit(1);
    686 	}
    687 
    688 #ifdef IPSEC
    689 #ifdef IPSEC_POLICY_IPSEC
    690 	/*
    691 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    692 	 * turned off.
    693 	 */
    694 	if (setpolicy(sndsock, "in bypass") < 0)
    695 		exit(1);
    696 	if (setpolicy(sndsock, "out bypass") < 0)
    697 		exit(1);
    698 #else
    699     {
    700 	int level = IPSEC_LEVEL_BYPASS;
    701 
    702 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    703 		sizeof(level));
    704 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    705 		sizeof(level));
    706 #ifdef IP_AUTH_TRANS_LEVEL
    707 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    708 		sizeof(level));
    709 #else
    710 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    711 		sizeof(level));
    712 #endif
    713 #ifdef IP_AUTH_NETWORK_LEVEL
    714 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    715 		sizeof(level));
    716 #endif
    717     }
    718 #endif /*IPSEC_POLICY_IPSEC*/
    719 #endif /*IPSEC*/
    720 
    721 	/* Revert to non-privileged user after opening sockets */
    722 	setuid(getuid());
    723 
    724 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
    725 	if (lsrr > 0) {
    726 		u_char optlist[MAX_IPOPTLEN];
    727 
    728 		/* final hop */
    729 		gwlist[lsrr] = to->sin_addr.s_addr;
    730 		++lsrr;
    731 
    732 		/* force 4 byte alignment */
    733 		optlist[0] = IPOPT_NOP;
    734 		/* loose source route option */
    735 		optlist[1] = IPOPT_LSRR;
    736 		i = lsrr * sizeof(gwlist[0]);
    737 		optlist[2] = i + 3;
    738 		/* Pointer to LSRR addresses */
    739 		optlist[3] = IPOPT_MINOFF;
    740 		memcpy(optlist + 4, gwlist, i);
    741 
    742 		if ((setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, optlist,
    743 		    i + sizeof(gwlist[0]))) < 0) {
    744 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
    745 			    prog, strerror(errno));
    746 			exit(1);
    747 		    }
    748 	}
    749 #endif
    750 
    751 #ifdef SO_SNDBUF
    752 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
    753 	    sizeof(packlen)) < 0) {
    754 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
    755 		exit(1);
    756 	}
    757 #endif
    758 #ifdef IP_HDRINCL
    759 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    760 	    sizeof(on)) < 0) {
    761 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
    762 		exit(1);
    763 	}
    764 #else
    765 #ifdef IP_TOS
    766 	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
    767 	    (char *)&tos, sizeof(tos)) < 0) {
    768 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
    769 		    prog, tos, strerror(errno));
    770 		exit(1);
    771 	}
    772 #endif
    773 #endif
    774 	if (options & SO_DEBUG)
    775 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
    776 		    sizeof(on));
    777 	if (options & SO_DONTROUTE)
    778 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    779 		    sizeof(on));
    780 
    781 	/* Get the interface address list */
    782 	n = ifaddrlist(&al, errbuf, sizeof errbuf);
    783 	al2 = al;
    784 	if (n < 0) {
    785 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
    786 		exit(1);
    787 	}
    788 	if (n == 0) {
    789 		Fprintf(stderr,
    790 		    "%s: Can't find any network interfaces\n", prog);
    791 		exit(1);
    792 	}
    793 
    794 	/* Look for a specific device */
    795 	if (device != NULL) {
    796 		for (i = n; i > 0; --i, ++al2)
    797 			if (strcmp(device, al2->device) == 0)
    798 				break;
    799 		if (i <= 0) {
    800 			Fprintf(stderr, "%s: Can't find interface %s\n",
    801 			    prog, device);
    802 			exit(1);
    803 		}
    804 	}
    805 
    806 	/* Determine our source address */
    807 	if (source == NULL) {
    808 		/*
    809 		 * If a device was specified, use the interface address.
    810 		 * Otherwise, use the first interface found.
    811 		 * Warn if there are more than one.
    812 		 */
    813 		setsin(from, al2->addr);
    814 		if (n > 1 && device == NULL && !find_local_ip(from, to)) {
    815 			Fprintf(stderr,
    816 		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
    817 			    prog, inet_ntoa(from->sin_addr), al2->device);
    818 		}
    819 	} else {
    820 		hi = gethostinfo(source);
    821 		source = hi->name;
    822 		hi->name = NULL;
    823 		if (device == NULL) {
    824 			/*
    825 			 * Use the first interface found.
    826 			 * Warn if there are more than one.
    827 			 */
    828 			setsin(from, hi->addrs[0]);
    829 			if (hi->n > 1)
    830 				Fprintf(stderr,
    831 			"%s: Warning: %s has multiple addresses; using %s\n",
    832 				    prog, source, inet_ntoa(from->sin_addr));
    833 		} else {
    834 			/*
    835 			 * Make sure the source specified matches the
    836 			 * interface address.
    837 			 */
    838 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
    839 				if (*ap == al2->addr)
    840 					break;
    841 			if (i <= 0) {
    842 				Fprintf(stderr,
    843 				    "%s: %s is not on interface %s\n",
    844 				    prog, source, device);
    845 				exit(1);
    846 			}
    847 			setsin(from, *ap);
    848 		}
    849 		freehostinfo(hi);
    850 	}
    851 
    852 	/*
    853 	 * If not root, make sure source address matches a local interface.
    854 	 * (The list of addresses produced by ifaddrlist() automatically
    855 	 * excludes interfaces that are marked down and/or loopback.)
    856 	 */
    857 	if (getuid())  {
    858 		al2 = al;
    859 		for (i = n; i > 0; --i, ++al2)
    860 			if (from->sin_addr.s_addr == al2->addr)
    861 			    break;
    862 		if (i <= 0) {
    863 			Fprintf(stderr, "%s: %s is not a valid local address "
    864 			    "and you are not superuser.\n", prog,
    865 			    inet_ntoa(from->sin_addr));
    866 			exit(1);
    867 		}
    868 	}
    869 
    870 	outip->ip_src = from->sin_addr;
    871 #ifndef IP_HDRINCL
    872 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
    873 		Fprintf(stderr, "%s: bind: %s\n",
    874 		    prog, strerror(errno));
    875 		exit (1);
    876 	}
    877 #endif
    878 
    879 	if (as_path) {
    880 		asn = as_setup(as_server);
    881 		if (asn == NULL) {
    882 			Fprintf(stderr, "%s: as_setup failed, AS# lookups disabled\n",
    883 				prog);
    884 			(void)fflush(stderr);
    885 			as_path = 0;
    886 		}
    887 	}
    888 
    889 	setuid(getuid());
    890 	Fprintf(stderr, "%s to %s (%s)",
    891 	    prog, hostname, inet_ntoa(to->sin_addr));
    892 	if (source)
    893 		Fprintf(stderr, " from %s", source);
    894 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
    895 	(void)fflush(stderr);
    896 
    897 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
    898 		u_int32_t lastaddr = 0;
    899 		int got_there = 0;
    900 		int unreachable = 0;
    901 
    902 again:
    903 		printed_ttl = 0;
    904 		for (probe = 0; probe < nprobes; ++probe) {
    905 			int cc;
    906 			struct timeval t1, t2;
    907 			struct ip *ip;
    908 			(void)gettimeofday(&t1, NULL);
    909 			send_probe(++seq, ttl, &t1);
    910 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
    911 				(void)gettimeofday(&t2, NULL);
    912 				/*
    913 				 * Since we'll be receiving all ICMP
    914 				 * messages to this host above, we may
    915 				 * never end up with cc=0, so we need
    916 				 * an additional termination check.
    917 				 */
    918 				if (t2.tv_sec - t1.tv_sec > waittime) {
    919 					cc = 0;
    920 					break;
    921 				}
    922 				i = packet_ok(packet, cc, from, seq);
    923 				/* Skip short packet */
    924 				if (i == 0)
    925 					continue;
    926 				if (from->sin_addr.s_addr != lastaddr) {
    927 					print(packet, cc, from);
    928 					lastaddr = from->sin_addr.s_addr;
    929 				}
    930 				ip = (struct ip *)packet;
    931 				Printf("  %.3f ms", deltaT(&t1, &t2));
    932 				if (ttl_flag)
    933 					Printf(" (ttl = %d)", ip->ip_ttl);
    934 				if (i == -2) {
    935 #ifndef ARCHAIC
    936 					if (ip->ip_ttl <= 1)
    937 						Printf(" !");
    938 #endif
    939 					++got_there;
    940 					break;
    941 				}
    942 
    943 				/* time exceeded in transit */
    944 				if (i == -1)
    945 					break;
    946 				code = i - 1;
    947 				switch (code) {
    948 
    949 				case ICMP_UNREACH_PORT:
    950 #ifndef ARCHAIC
    951 					if (ip->ip_ttl <= 1)
    952 						Printf(" !");
    953 #endif
    954 					++got_there;
    955 					break;
    956 
    957 				case ICMP_UNREACH_NET:
    958 					++unreachable;
    959 					Printf(" !N");
    960 					break;
    961 
    962 				case ICMP_UNREACH_HOST:
    963 					++unreachable;
    964 					Printf(" !H");
    965 					break;
    966 
    967 				case ICMP_UNREACH_PROTOCOL:
    968 					++got_there;
    969 					Printf(" !P");
    970 					break;
    971 
    972 				case ICMP_UNREACH_NEEDFRAG:
    973 					if (mtudisc) {
    974 						frag_err();
    975 						goto again;
    976 					} else {
    977 						++unreachable;
    978 						Printf(" !F");
    979 					}
    980 					break;
    981 
    982 				case ICMP_UNREACH_SRCFAIL:
    983 					++unreachable;
    984 					Printf(" !S");
    985 					break;
    986 
    987 /* rfc1716 */
    988 #ifndef ICMP_UNREACH_FILTER_PROHIB
    989 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
    990 #endif
    991 				case ICMP_UNREACH_FILTER_PROHIB:
    992 					++unreachable;
    993 					Printf(" !X");
    994 					break;
    995 
    996 				default:
    997 					++unreachable;
    998 					Printf(" !<%d>", code);
    999 					break;
   1000 				}
   1001 				break;
   1002 			}
   1003 			if (cc == 0)
   1004 				Printf(" *");
   1005 			(void)fflush(stdout);
   1006 		}
   1007 		putchar('\n');
   1008 		if (got_there ||
   1009 		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
   1010 			break;
   1011 	}
   1012 
   1013 	if (as_path)
   1014 		as_shutdown(asn);
   1015 
   1016 	exit(0);
   1017 }
   1018 
   1019 int
   1020 wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
   1021 {
   1022 	struct pollfd set[1];
   1023 	struct timeval now, wait;
   1024 	int cc = 0;
   1025 	int fromlen = sizeof(*fromp);
   1026 	int retval;
   1027 
   1028 	set[0].fd = sock;
   1029 	set[0].events = POLLIN;
   1030 
   1031 	wait.tv_sec = tp->tv_sec + waittime;
   1032 	wait.tv_usec = tp->tv_usec;
   1033 	(void)gettimeofday(&now, NULL);
   1034 	tvsub(&wait, &now);
   1035 
   1036 	if (wait.tv_sec < 0) {
   1037 		wait.tv_sec = 0;
   1038 		wait.tv_usec = 0;
   1039 	}
   1040 
   1041 	retval = poll(set, 1, wait.tv_sec * 1000 + wait.tv_usec / 1000);
   1042 	if (retval < 0)  {
   1043 		/* If we continue, we probably just flood the remote host. */
   1044 		Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
   1045 		exit(1);
   1046 	}
   1047 	if (retval > 0)  {
   1048 		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
   1049 			    (struct sockaddr *)fromp, &fromlen);
   1050 	}
   1051 
   1052 	return(cc);
   1053 }
   1054 
   1055 void
   1056 dump_packet()
   1057 {
   1058 	u_char *p;
   1059 	int i;
   1060 
   1061 	Fprintf(stderr, "packet data:");
   1062 
   1063 #ifdef __hpux
   1064 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
   1065 	    i < packlen - (sizeof(*outip) + optlen); i++)
   1066 #else
   1067 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
   1068 #endif
   1069 	{
   1070 		if ((i % 24) == 0)
   1071 			Fprintf(stderr, "\n ");
   1072 		Fprintf(stderr, " %02x", *p++);
   1073 	}
   1074 	Fprintf(stderr, "\n");
   1075 }
   1076 
   1077 void
   1078 send_probe(int seq, int ttl, struct timeval *tp)
   1079 {
   1080 	int cc;
   1081 	struct udpiphdr * ui;
   1082 	int oldmtu = packlen;
   1083 
   1084 again:
   1085 #ifdef BYTESWAP_IP_LEN
   1086 	outip->ip_len = htons(packlen);
   1087 #else
   1088 	outip->ip_len = packlen;
   1089 #endif
   1090 	outip->ip_ttl = ttl;
   1091 #ifndef __hpux
   1092 	outip->ip_id = htons(ident + seq);
   1093 #endif
   1094 
   1095 	/*
   1096 	 * In most cases, the kernel will recalculate the ip checksum.
   1097 	 * But we must do it anyway so that the udp checksum comes out
   1098 	 * right.
   1099 	 */
   1100 	if (docksum) {
   1101 		outip->ip_sum =
   1102 		    in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
   1103 		if (outip->ip_sum == 0)
   1104 			outip->ip_sum = 0xffff;
   1105 	}
   1106 
   1107 	/* Payload */
   1108 	outsetup.seq = seq;
   1109 	outsetup.ttl = ttl;
   1110 	outsetup.tv  = *tp;
   1111 	memcpy(outmark,&outsetup,sizeof(outsetup));
   1112 
   1113 	if (useicmp)
   1114 		outicmp->icmp_seq = htons(seq);
   1115 	else
   1116 		outudp->uh_dport = htons(port + seq);
   1117 
   1118 	/* (We can only do the checksum if we know our ip address) */
   1119 	if (docksum) {
   1120 		if (useicmp) {
   1121 			outicmp->icmp_cksum = 0;
   1122 			outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1123 			    packlen - (sizeof(*outip) + optlen));
   1124 			if (outicmp->icmp_cksum == 0)
   1125 				outicmp->icmp_cksum = 0xffff;
   1126 		} else {
   1127 			u_int16_t sum;
   1128 			struct {
   1129 				struct in_addr src;
   1130 				struct in_addr dst;
   1131 				u_int8_t zero;
   1132 				u_int8_t protocol;
   1133 				u_int16_t len;
   1134 			} __attribute__((__packed__)) phdr;
   1135 
   1136 			/* Checksum */
   1137 			ui = (struct udpiphdr *)outip;
   1138 			memset(&phdr, 0, sizeof(phdr));
   1139 			phdr.src = ui->ui_src;
   1140 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
   1141 			phdr.protocol = ui->ui_pr;
   1142 			phdr.len = outudp->uh_ulen;
   1143 			outudp->uh_sum = 0;
   1144 			sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
   1145 			sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
   1146 			sum = ~sum;	/** XXXSCW: Quell SuperH Compiler Bug */
   1147 			outudp->uh_sum = sum;
   1148 			if (outudp->uh_sum == 0)
   1149 				outudp->uh_sum = 0xffff;
   1150 		}
   1151 	}
   1152 
   1153 	/* XXX undocumented debugging hack */
   1154 	if (verbose > 1) {
   1155 		const u_int16_t *sp;
   1156 		int nshorts, i;
   1157 
   1158 		sp = (u_int16_t *)outip;
   1159 		nshorts = (u_int)packlen / sizeof(u_int16_t);
   1160 		i = 0;
   1161 		Printf("[ %d bytes", packlen);
   1162 		while (--nshorts >= 0) {
   1163 			if ((i++ % 8) == 0)
   1164 				Printf("\n\t");
   1165 			Printf(" %04x", ntohs(*sp++));
   1166 		}
   1167 		if (packlen & 1) {
   1168 			if ((i % 8) == 0)
   1169 				Printf("\n\t");
   1170 			Printf(" %02x", *(u_char *)sp);
   1171 		}
   1172 		Printf("]\n");
   1173 	}
   1174 
   1175 #if !defined(IP_HDRINCL) && defined(IP_TTL)
   1176 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
   1177 	    (char *)&ttl, sizeof(ttl)) < 0) {
   1178 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
   1179 		    prog, ttl, strerror(errno));
   1180 		exit(1);
   1181 	}
   1182 #endif
   1183 	if (dump)
   1184 		dump_packet();
   1185 
   1186 #ifdef __hpux
   1187 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
   1188 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
   1189 	if (cc > 0)
   1190 		cc += sizeof(*outip) + optlen;
   1191 #else
   1192 	cc = sendto(sndsock, (char *)outip,
   1193 	    packlen, 0, &whereto, sizeof(whereto));
   1194 #endif
   1195 	if (cc < 0 || cc != packlen)  {
   1196 		if (cc < 0) {
   1197 			/*
   1198 			 * An errno of EMSGSIZE means we're writing too big a
   1199 			 * datagram for the interface.  We have to just
   1200 			 * decrease the packet size until we find one that
   1201 			 * works.
   1202 			 *
   1203 			 * XXX maybe we should try to read the outgoing if's
   1204 			 * mtu?
   1205 			 */
   1206 			if (errno == EMSGSIZE) {
   1207 				packlen = *mtuptr++;
   1208 				resize_packet();
   1209 				goto again;
   1210 			} else
   1211 				Fprintf(stderr, "%s: sendto: %s\n",
   1212 				    prog, strerror(errno));
   1213 		}
   1214 
   1215 		Printf("%s: wrote %s %d chars, ret=%d\n",
   1216 		    prog, hostname, packlen, cc);
   1217 		(void)fflush(stdout);
   1218 	}
   1219 	if (oldmtu != packlen) {
   1220 		Printf("message too big, "
   1221 		    "trying new MTU = %d\n", packlen);
   1222 		printed_ttl = 0;
   1223 	}
   1224 	if (!printed_ttl) {
   1225 		Printf("%2d ", ttl);
   1226 		printed_ttl = 1;
   1227 	}
   1228 
   1229 }
   1230 
   1231 double
   1232 deltaT(struct timeval *t1p, struct timeval *t2p)
   1233 {
   1234 	double dt;
   1235 
   1236 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
   1237 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
   1238 	return (dt);
   1239 }
   1240 
   1241 /*
   1242  * Convert an ICMP "type" field to a printable string.
   1243  */
   1244 char *
   1245 pr_type(u_char t)
   1246 {
   1247 	static char *ttab[] = {
   1248 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
   1249 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
   1250 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
   1251 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
   1252 	"Info Reply"
   1253 	};
   1254 
   1255 	if (t > 16)
   1256 		return("OUT-OF-RANGE");
   1257 
   1258 	return(ttab[t]);
   1259 }
   1260 
   1261 int
   1262 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
   1263 {
   1264 	struct icmp *icp;
   1265 	u_char type, code;
   1266 	int hlen;
   1267 #ifndef ARCHAIC
   1268 	struct ip *ip;
   1269 
   1270 	ip = (struct ip *) buf;
   1271 	hlen = ip->ip_hl << 2;
   1272 	if (cc < hlen + ICMP_MINLEN) {
   1273 		if (verbose)
   1274 			Printf("packet too short (%d bytes) from %s\n", cc,
   1275 				inet_ntoa(from->sin_addr));
   1276 		return (0);
   1277 	}
   1278 	cc -= hlen;
   1279 	icp = (struct icmp *)(buf + hlen);
   1280 #else
   1281 	icp = (struct icmp *)buf;
   1282 #endif
   1283 	type = icp->icmp_type;
   1284 	code = icp->icmp_code;
   1285 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
   1286 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
   1287 		struct ip *hip;
   1288 		struct udphdr *up;
   1289 		struct icmp *hicmp;
   1290 
   1291 		hip = &icp->icmp_ip;
   1292 		hlen = hip->ip_hl << 2;
   1293 
   1294 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
   1295 
   1296 		if (useicmp) {
   1297 			/* XXX */
   1298 			if (type == ICMP_ECHOREPLY &&
   1299 			    icp->icmp_id == htons(ident) &&
   1300 			    icp->icmp_seq == htons(seq))
   1301 				return (-2);
   1302 
   1303 			hicmp = (struct icmp *)((u_char *)hip + hlen);
   1304 			/* XXX 8 is a magic number */
   1305 			if (hlen + 8 <= cc &&
   1306 			    hip->ip_p == IPPROTO_ICMP &&
   1307 			    hicmp->icmp_id == htons(ident) &&
   1308 			    hicmp->icmp_seq == htons(seq))
   1309 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1310 		} else {
   1311 			up = (struct udphdr *)((u_char *)hip + hlen);
   1312 			/* XXX 8 is a magic number */
   1313 			if (hlen + 12 <= cc &&
   1314 			    hip->ip_p == IPPROTO_UDP &&
   1315 			    up->uh_sport == htons(ident) &&
   1316 			    up->uh_dport == htons(port + seq))
   1317 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1318 		}
   1319 	}
   1320 #ifndef ARCHAIC
   1321 	if (verbose) {
   1322 		int i;
   1323 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
   1324 
   1325 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
   1326 		Printf("%s: icmp type %d (%s) code %d\n",
   1327 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
   1328 		for (i = 4; i < cc ; i += sizeof(*lp))
   1329 			Printf("%2d: x%8.8x\n", i, *lp++);
   1330 	}
   1331 #endif
   1332 	return(0);
   1333 }
   1334 
   1335 void resize_packet(void)
   1336 {
   1337 	if (useicmp) {
   1338 		outicmp->icmp_cksum = 0;
   1339 		outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1340 		    packlen - (sizeof(*outip) + optlen));
   1341 		if (outicmp->icmp_cksum == 0)
   1342 			outicmp->icmp_cksum = 0xffff;
   1343 	} else {
   1344 		outudp->uh_ulen =
   1345 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
   1346 	}
   1347 }
   1348 
   1349 void
   1350 print(u_char *buf, int cc, struct sockaddr_in *from)
   1351 {
   1352 	struct ip *ip;
   1353 	int hlen;
   1354 
   1355 	ip = (struct ip *) buf;
   1356 	hlen = ip->ip_hl << 2;
   1357 	cc -= hlen;
   1358 
   1359 	if (as_path)
   1360 		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
   1361 
   1362 	if (nflag)
   1363 		Printf(" %s", inet_ntoa(from->sin_addr));
   1364 	else
   1365 		Printf(" %s (%s)", inetname(from->sin_addr),
   1366 		    inet_ntoa(from->sin_addr));
   1367 
   1368 	if (verbose)
   1369 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
   1370 }
   1371 
   1372 u_int16_t
   1373 in_cksum(u_int16_t *addr, int len)
   1374 {
   1375 
   1376 	return ~in_cksum2(0, addr, len);
   1377 }
   1378 
   1379 /*
   1380  * Checksum routine for Internet Protocol family headers (C Version)
   1381  */
   1382 u_int16_t
   1383 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
   1384 {
   1385 	int nleft = len;
   1386 	u_int16_t *w = addr;
   1387 	union {
   1388 		u_int16_t w;
   1389 		u_int8_t b[2];
   1390 	} answer;
   1391 	int32_t sum = seed;
   1392 
   1393 	/*
   1394 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
   1395 	 *  we add sequential 16 bit words to it, and at the end, fold
   1396 	 *  back all the carry bits from the top 16 bits into the lower
   1397 	 *  16 bits.
   1398 	 */
   1399 	while (nleft > 1)  {
   1400 		sum += *w++;
   1401 		nleft -= 2;
   1402 	}
   1403 
   1404 	/* mop up an odd byte, if necessary */
   1405 	if (nleft == 1) {
   1406 		answer.b[0] = *(u_char *)w;
   1407 		answer.b[1] = 0;
   1408 		sum += answer.w;
   1409 	}
   1410 
   1411 	/*
   1412 	 * add back carry outs from top 16 bits to low 16 bits
   1413 	 */
   1414 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
   1415 	sum += (sum >> 16);			/* add carry */
   1416 	answer.w = sum;				/* truncate to 16 bits */
   1417 	return (answer.w);
   1418 }
   1419 
   1420 /*
   1421  * Subtract 2 timeval structs:  out = out - in.
   1422  * Out is assumed to be >= in.
   1423  */
   1424 void
   1425 tvsub(struct timeval *out, struct timeval *in)
   1426 {
   1427 
   1428 	if ((out->tv_usec -= in->tv_usec) < 0)   {
   1429 		--out->tv_sec;
   1430 		out->tv_usec += 1000000;
   1431 	}
   1432 	out->tv_sec -= in->tv_sec;
   1433 }
   1434 
   1435 /*
   1436  * Construct an Internet address representation.
   1437  * If the nflag has been supplied, give
   1438  * numeric value, otherwise try for symbolic name.
   1439  */
   1440 char *
   1441 inetname(struct in_addr in)
   1442 {
   1443 	char *cp;
   1444 	struct hostent *hp;
   1445 	static int first = 1;
   1446 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
   1447 
   1448 	if (first && !nflag) {
   1449 		int rv;
   1450 
   1451 		first = 0;
   1452 		rv = gethostname(domain, sizeof domain);
   1453 		domain[sizeof(domain) - 1] = '\0';
   1454 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
   1455 			(void)strncpy(domain, cp + 1, sizeof(domain) - 1);
   1456 		} else
   1457 			domain[0] = '\0';
   1458 	}
   1459 	if (!nflag && in.s_addr != INADDR_ANY) {
   1460 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
   1461 		if (hp != NULL) {
   1462 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
   1463 			    strcmp(cp + 1, domain) == 0)
   1464 				*cp = '\0';
   1465 			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
   1466 			line[sizeof(line) - 1] = '\0';
   1467 			return (line);
   1468 		}
   1469 	}
   1470 	return (inet_ntoa(in));
   1471 }
   1472 
   1473 struct hostinfo *
   1474 gethostinfo(char *hostname)
   1475 {
   1476 	int n;
   1477 	struct hostent *hp;
   1478 	struct hostinfo *hi;
   1479 	char **p;
   1480 	u_int32_t *ap;
   1481 	struct in_addr addr;
   1482 
   1483 	hi = calloc(1, sizeof(*hi));
   1484 	if (hi == NULL) {
   1485 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1486 		exit(1);
   1487 	}
   1488 	if (inet_aton(hostname, &addr) != 0) {
   1489 		hi->name = strdup(hostname);
   1490 		if (!hi->name) {
   1491 			Fprintf(stderr, "%s: strdup %s\n", prog,
   1492 			    strerror(errno));
   1493 			exit(1);
   1494 		}
   1495 		hi->n = 1;
   1496 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
   1497 		if (hi->addrs == NULL) {
   1498 			Fprintf(stderr, "%s: calloc %s\n",
   1499 			    prog, strerror(errno));
   1500 			exit(1);
   1501 		}
   1502 		hi->addrs[0] = addr.s_addr;
   1503 		return (hi);
   1504 	}
   1505 
   1506 	hp = gethostbyname(hostname);
   1507 	if (hp == NULL) {
   1508 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
   1509 		exit(1);
   1510 	}
   1511 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
   1512 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
   1513 		exit(1);
   1514 	}
   1515 	hi->name = strdup(hp->h_name);
   1516 	if (!hi->name) {
   1517 		Fprintf(stderr, "%s: strdup %s\n", prog, strerror(errno));
   1518 		exit(1);
   1519 	}
   1520 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
   1521 		continue;
   1522 	hi->n = n;
   1523 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
   1524 	if (hi->addrs == NULL) {
   1525 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1526 		exit(1);
   1527 	}
   1528 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
   1529 		memcpy(ap, *p, sizeof(*ap));
   1530 	return (hi);
   1531 }
   1532 
   1533 void
   1534 freehostinfo(struct hostinfo *hi)
   1535 {
   1536 	if (hi->name != NULL) {
   1537 		free(hi->name);
   1538 		hi->name = NULL;
   1539 	}
   1540 	free((char *)hi->addrs);
   1541 	free((char *)hi);
   1542 }
   1543 
   1544 void
   1545 getaddr(u_int32_t *ap, char *hostname)
   1546 {
   1547 	struct hostinfo *hi;
   1548 
   1549 	hi = gethostinfo(hostname);
   1550 	*ap = hi->addrs[0];
   1551 	freehostinfo(hi);
   1552 }
   1553 
   1554 void
   1555 setsin(struct sockaddr_in *sin, u_int32_t addr)
   1556 {
   1557 
   1558 	memset(sin, 0, sizeof(*sin));
   1559 #ifdef HAVE_SOCKADDR_SA_LEN
   1560 	sin->sin_len = sizeof(*sin);
   1561 #endif
   1562 	sin->sin_family = AF_INET;
   1563 	sin->sin_addr.s_addr = addr;
   1564 }
   1565 
   1566 /* String to value with optional min and max. Handles decimal and hex. */
   1567 int
   1568 str2val(const char *str, const char *what, int mi, int ma)
   1569 {
   1570 	const char *cp;
   1571 	long val;
   1572 	char *ep;
   1573 
   1574 	errno = 0;
   1575 	ep = NULL;
   1576 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
   1577 		cp = str + 2;
   1578 		val = strtol(cp, &ep, 16);
   1579 	} else
   1580 		val = strtol(str, &ep, 10);
   1581 	if (errno || str[0] == '\0' || *ep != '\0') {
   1582 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
   1583 		    prog, str, what);
   1584 		exit(1);
   1585 	}
   1586 	if (val < mi && mi >= 0) {
   1587 		if (mi == 0)
   1588 			Fprintf(stderr, "%s: %s must be >= %d\n",
   1589 			    prog, what, mi);
   1590 		else
   1591 			Fprintf(stderr, "%s: %s must be > %d\n",
   1592 			    prog, what, mi - 1);
   1593 		exit(1);
   1594 	}
   1595 	if (val > ma && ma >= 0) {
   1596 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
   1597 		exit(1);
   1598 	}
   1599 	return ((int)val);
   1600 }
   1601 
   1602 __dead void
   1603 usage(void)
   1604 {
   1605 	extern char version[];
   1606 
   1607 	Fprintf(stderr, "Version %s\n", version);
   1608 	Fprintf(stderr, "Usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \
   1609 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
   1610 [-w waittime] [-A as_server] host [packetlen]\n",
   1611 	    prog);
   1612 	exit(1);
   1613 }
   1614 
   1615 /*
   1616  * Received ICMP unreachable (fragmentation required and DF set).
   1617  * If the ICMP error was from a "new" router, it'll contain the next-hop
   1618  * MTU that we should use next.  Otherwise we'll just keep going in the
   1619  * mtus[] table, trying until we hit a valid MTU.
   1620  */
   1621 
   1622 
   1623 void
   1624 frag_err()
   1625 {
   1626         int i;
   1627 
   1628         if (nextmtu > 0 && nextmtu < packlen) {
   1629                 Printf("\nfragmentation required and DF set, "
   1630 		     "next hop MTU = %d\n",
   1631                         nextmtu);
   1632                 packlen = nextmtu;
   1633                 for (i = 0; mtus[i] > 0; i++) {
   1634                         if (mtus[i] < nextmtu) {
   1635                                 mtuptr = &mtus[i];    /* next one to try */
   1636                                 break;
   1637                         }
   1638                 }
   1639         } else {
   1640                 Printf("\nfragmentation required and DF set. ");
   1641 		if (nextmtu)
   1642 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
   1643 			    nextmtu, packlen);
   1644                 packlen = *mtuptr++;
   1645 		Printf("Trying new MTU = %d\n", packlen);
   1646         }
   1647 	resize_packet();
   1648 }
   1649 
   1650 int
   1651 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
   1652 {
   1653 	int sock;
   1654 	struct sockaddr_in help;
   1655 	int help_len;
   1656 
   1657 	sock = socket(AF_INET, SOCK_DGRAM, 0);
   1658 	if (sock < 0) return (0);
   1659 
   1660 	help.sin_family = AF_INET;
   1661 	/*
   1662 	 * At this point the port number doesn't matter
   1663 	 * since it only has to be greater than zero.
   1664 	 */
   1665 	help.sin_port = 42;
   1666 	help.sin_addr.s_addr = to->sin_addr.s_addr;
   1667 	if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
   1668 		(void)close(sock);
   1669 		return (0);
   1670 	}
   1671 
   1672 	help_len = sizeof(help);
   1673 	if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
   1674 	    help_len != sizeof(help) ||
   1675 	    help.sin_addr.s_addr == INADDR_ANY) {
   1676 		(void)close(sock);
   1677 		return (0);
   1678 	}
   1679 
   1680 	(void)close(sock);
   1681 	setsin(from, help.sin_addr.s_addr);
   1682 	return (1);
   1683 }
   1684 
   1685 #ifdef IPSEC
   1686 #ifdef IPSEC_POLICY_IPSEC
   1687 int
   1688 setpolicy(so, policy)
   1689 	int so;
   1690 	char *policy;
   1691 {
   1692 	char *buf;
   1693 
   1694 	buf = ipsec_set_policy(policy, strlen(policy));
   1695 	if (buf == NULL) {
   1696 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
   1697 		return -1;
   1698 	}
   1699 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
   1700 		buf, ipsec_get_policylen(buf));
   1701 
   1702 	free(buf);
   1703 
   1704 	return 0;
   1705 }
   1706 #endif
   1707 #endif
   1708 
   1709