Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.46
      1 /*	$NetBSD: traceroute.c,v 1.46 2002/05/26 14:45:43 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.46 2002/05/26 14:45:43 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 #ifdef HAVE_SYS_SELECT_H
    211 #include <sys/select.h>
    212 #endif
    213 #include <sys/socket.h>
    214 #include <sys/time.h>
    215 #include <sys/sysctl.h>
    216 
    217 #include <netinet/in_systm.h>
    218 #include <netinet/in.h>
    219 #include <netinet/ip.h>
    220 #include <netinet/ip_var.h>
    221 #include <netinet/ip_icmp.h>
    222 #include <netinet/udp.h>
    223 #include <netinet/udp_var.h>
    224 
    225 #include <arpa/inet.h>
    226 
    227 #include <ctype.h>
    228 #include <errno.h>
    229 #ifdef HAVE_MALLOC_H
    230 #include <malloc.h>
    231 #endif
    232 #include <memory.h>
    233 #include <netdb.h>
    234 #include <stdio.h>
    235 #include <stdlib.h>
    236 #include <string.h>
    237 #include <unistd.h>
    238 #ifdef IPSEC
    239 #include <net/route.h>
    240 #include <netinet6/ipsec.h>
    241 #endif
    242 
    243 #include "gnuc.h"
    244 #ifdef HAVE_OS_PROTO_H
    245 #include "os-proto.h"
    246 #endif
    247 
    248 #include "ifaddrlist.h"
    249 #include "savestr.h"
    250 #include "as.h"
    251 
    252 /* Maximum number of gateways (include room for one noop) */
    253 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
    254 
    255 #ifndef MAXHOSTNAMELEN
    256 #define MAXHOSTNAMELEN	64
    257 #endif
    258 
    259 #define Fprintf (void)fprintf
    260 #define Printf (void)printf
    261 
    262 /* Host name and address list */
    263 struct hostinfo {
    264 	char *name;
    265 	int n;
    266 	u_int32_t *addrs;
    267 };
    268 
    269 /* Data section of the probe packet */
    270 struct outdata {
    271 	u_char seq;		/* sequence number of this packet */
    272 	u_char ttl;		/* ttl packet left with */
    273 	struct timeval tv;	/* time packet left */
    274 };
    275 
    276 u_char	packet[512];		/* last inbound (icmp) packet */
    277 
    278 struct ip *outip;		/* last output (udp) packet */
    279 struct udphdr *outudp;		/* last output (udp) packet */
    280 void *outmark;			/* packed location of struct outdata */
    281 struct outdata outsetup;	/* setup and copy for alignment */
    282 
    283 struct icmp *outicmp;		/* last output (icmp) packet */
    284 
    285 /* loose source route gateway list (including room for final destination) */
    286 u_int32_t gwlist[NGATEWAYS + 1];
    287 
    288 int s;				/* receive (icmp) socket file descriptor */
    289 int sndsock;			/* send (udp/icmp) socket file descriptor */
    290 
    291 struct sockaddr whereto;	/* Who to try to reach */
    292 struct sockaddr_in wherefrom;	/* Who we are */
    293 int packlen;			/* total length of packet */
    294 int minpacket;			/* min ip packet size */
    295 int maxpacket = 32 * 1024;	/* max ip packet size */
    296 int printed_ttl = 0;
    297 
    298 char *prog;
    299 char *source;
    300 char *hostname;
    301 char *device;
    302 
    303 int nprobes = 3;
    304 int max_ttl = 30;
    305 int first_ttl = 1;
    306 u_short ident;
    307 u_short port = 32768 + 666;	/* start udp dest port # for probe packets */
    308 
    309 int options;			/* socket options */
    310 int verbose;
    311 int waittime = 5;		/* time to wait for response (in seconds) */
    312 int nflag;			/* print addresses numerically */
    313 int dump;
    314 int as_path;			/* print as numbers for each hop */
    315 char *as_server = NULL;
    316 void *asn;
    317 int useicmp;			/* use icmp echo instead of udp packets */
    318 #ifdef CANT_HACK_CKSUM
    319 int docksum = 0;		/* don't calculate checksums */
    320 #else
    321 int docksum = 1;		/* calculate checksums */
    322 #endif
    323 int optlen;			/* length of ip options */
    324 
    325 int mtus[] = {
    326         17914,
    327          8166,
    328          4464,
    329          4352,
    330          2048,
    331          2002,
    332          1536,
    333          1500,
    334          1492,
    335 	 1480,
    336 	 1280,
    337          1006,
    338           576,
    339           552,
    340           544,
    341           512,
    342           508,
    343           296,
    344            68,
    345             0
    346 };
    347 int *mtuptr = &mtus[0];
    348 int mtudisc = 0;
    349 int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
    350 
    351 extern int optind;
    352 extern int opterr;
    353 extern char *optarg;
    354 
    355 /* Forwards */
    356 double	deltaT(struct timeval *, struct timeval *);
    357 void	freehostinfo(struct hostinfo *);
    358 void	getaddr(u_int32_t *, char *);
    359 struct	hostinfo *gethostinfo(char *);
    360 u_short	in_cksum(u_short *, int);
    361 u_short	in_cksum2(u_short, u_short *, int);
    362 char	*inetname(struct in_addr);
    363 int	main(int, char **);
    364 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
    365 char	*pr_type(u_char);
    366 void	print(u_char *, int, struct sockaddr_in *);
    367 void	resize_packet(void);
    368 void	dump_packet(void);
    369 void	send_probe(int, int, struct timeval *);
    370 void	setsin(struct sockaddr_in *, u_int32_t);
    371 int	str2val(const char *, const char *, int, int);
    372 void	tvsub(struct timeval *, struct timeval *);
    373 __dead	void usage(void);
    374 int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
    375 void	frag_err(void);
    376 int	find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
    377 #ifdef IPSEC
    378 #ifdef IPSEC_POLICY_IPSEC
    379 int	setpolicy(int so, char *policy);
    380 #endif
    381 #endif
    382 
    383 int
    384 main(int argc, char **argv)
    385 {
    386 	register int op, code, n;
    387 	register char *cp;
    388 	register u_char *outp;
    389 	register u_int32_t *ap;
    390 	register struct sockaddr_in *from = &wherefrom;
    391 	register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
    392 	register struct hostinfo *hi;
    393 	int on = 1;
    394 	register struct protoent *pe;
    395 	register int ttl, probe, i;
    396 	register int seq = 0;
    397 	int tos = 0, settos = 0, ttl_flag = 0;
    398 	register int lsrr = 0;
    399 	register u_short off = 0;
    400 	struct ifaddrlist *al, *al2;
    401 	char errbuf[132];
    402 	int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
    403 	size_t size = sizeof(max_ttl);
    404 
    405 	(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
    406 	    NULL, 0);
    407 
    408 	if ((cp = strrchr(argv[0], '/')) != NULL)
    409 		prog = cp + 1;
    410 	else
    411 		prog = argv[0];
    412 
    413 	opterr = 0;
    414 	while ((op = getopt(argc, argv, "aA:dDFPInlrvxf:g:i:m:p:q:s:t:w:")) != -1)
    415 		switch (op) {
    416 
    417 		case 'a':
    418 			as_path = 1;
    419 			break;
    420 
    421 		case 'A':
    422 			as_path = 1;
    423 			as_server = optarg;
    424 			break;
    425 
    426 		case 'd':
    427 			options |= SO_DEBUG;
    428 			break;
    429 
    430 		case 'D':
    431 			dump = 1;
    432 			break;
    433 
    434 		case 'f':
    435 			first_ttl = str2val(optarg, "first ttl", 1, 255);
    436 			break;
    437 
    438 		case 'F':
    439 			off = IP_DF;
    440 			break;
    441 
    442 		case 'g':
    443 			if (lsrr >= NGATEWAYS) {
    444 				Fprintf(stderr,
    445 				    "%s: No more than %d gateways\n",
    446 				    prog, NGATEWAYS);
    447 				exit(1);
    448 			}
    449 			getaddr(gwlist + lsrr, optarg);
    450 			++lsrr;
    451 			break;
    452 
    453 		case 'i':
    454 			device = optarg;
    455 			break;
    456 
    457 		case 'I':
    458 			++useicmp;
    459 			break;
    460 
    461 		case 'l':
    462 			++ttl_flag;
    463 			break;
    464 
    465 		case 'm':
    466 			max_ttl = str2val(optarg, "max ttl", 1, 255);
    467 			break;
    468 
    469 		case 'n':
    470 			++nflag;
    471 			break;
    472 
    473 		case 'p':
    474 			port = str2val(optarg, "port", 1, -1);
    475 			break;
    476 
    477 		case 'q':
    478 			nprobes = str2val(optarg, "nprobes", 1, -1);
    479 			break;
    480 
    481 		case 'r':
    482 			options |= SO_DONTROUTE;
    483 			break;
    484 
    485 		case 's':
    486 			/*
    487 			 * set the ip source address of the outbound
    488 			 * probe (e.g., on a multi-homed host).
    489 			 */
    490 			source = optarg;
    491 			break;
    492 
    493 		case 't':
    494 			tos = str2val(optarg, "tos", 0, 255);
    495 			++settos;
    496 			break;
    497 
    498 		case 'v':
    499 			++verbose;
    500 			break;
    501 
    502 		case 'x':
    503 			docksum = (docksum == 0);
    504 			break;
    505 
    506 		case 'w':
    507 			waittime = str2val(optarg, "wait time", 2, 24 * 3600);
    508 			break;
    509 
    510 		case 'P':
    511 			off = IP_DF;
    512 			mtudisc = 1;
    513 			break;
    514 
    515 		default:
    516 			usage();
    517 		}
    518 
    519 	if (first_ttl > max_ttl) {
    520 		Fprintf(stderr,
    521 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
    522 		    prog, first_ttl, max_ttl);
    523 		exit(1);
    524 	}
    525 
    526 	if (!docksum)
    527 		Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
    528 
    529 	if (lsrr > 0)
    530 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
    531 	minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
    532 	if (useicmp)
    533 		minpacket += 8;			/* XXX magic number */
    534 	else
    535 		minpacket += sizeof(*outudp);
    536 	if (packlen == 0)
    537 		packlen = minpacket;		/* minimum sized packet */
    538 	else if (minpacket > packlen || packlen > maxpacket) {
    539 		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
    540 		    prog, minpacket, maxpacket);
    541 		exit(1);
    542 	}
    543 
    544 	if (mtudisc)
    545 		packlen = *mtuptr++;
    546 
    547 	/* Process destination and optional packet size */
    548 	switch (argc - optind) {
    549 
    550 	case 2:
    551 		packlen = str2val(argv[optind + 1],
    552 		    "packet length", minpacket, -1);
    553 		/* Fall through */
    554 
    555 	case 1:
    556 		hostname = argv[optind];
    557 		hi = gethostinfo(hostname);
    558 		setsin(to, hi->addrs[0]);
    559 		if (hi->n > 1)
    560 			Fprintf(stderr,
    561 		    "%s: Warning: %s has multiple addresses; using %s\n",
    562 				prog, hostname, inet_ntoa(to->sin_addr));
    563 		hostname = hi->name;
    564 		hi->name = NULL;
    565 		freehostinfo(hi);
    566 		break;
    567 
    568 	default:
    569 		usage();
    570 	}
    571 
    572 #ifdef HAVE_SETLINEBUF
    573 	setlinebuf (stdout);
    574 #else
    575 	setvbuf(stdout, NULL, _IOLBF, 0);
    576 #endif
    577 
    578 	outip = (struct ip *)malloc((unsigned)packlen);
    579 	if (outip == NULL) {
    580 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
    581 		exit(1);
    582 	}
    583 	memset((char *)outip, 0, packlen);
    584 
    585 	outip->ip_v = IPVERSION;
    586 	if (settos)
    587 		outip->ip_tos = tos;
    588 #ifdef BYTESWAP_IP_LEN
    589 	outip->ip_len = htons(packlen);
    590 #else
    591 	outip->ip_len = packlen;
    592 #endif
    593 	outip->ip_off = off;
    594 	outp = (u_char *)(outip + 1);
    595 #ifdef HAVE_RAW_OPTIONS
    596 	if (lsrr > 0) {
    597 		register u_char *optlist;
    598 
    599 		optlist = outp;
    600 		outp += optlen;
    601 
    602 		/* final hop */
    603 		gwlist[lsrr] = to->sin_addr.s_addr;
    604 
    605 		outip->ip_dst.s_addr = gwlist[0];
    606 
    607 		/* force 4 byte alignment */
    608 		optlist[0] = IPOPT_NOP;
    609 		/* loose source route option */
    610 		optlist[1] = IPOPT_LSRR;
    611 		i = lsrr * sizeof(gwlist[0]);
    612 		optlist[2] = i + 3;
    613 		/* Pointer to LSRR addresses */
    614 		optlist[3] = IPOPT_MINOFF;
    615 		memcpy(optlist + 4, gwlist + 1, i);
    616 	} else
    617 #endif
    618 		outip->ip_dst = to->sin_addr;
    619 
    620 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
    621 	ident = (getpid() & 0xffff) | 0x8000;
    622 	if (useicmp) {
    623 		outip->ip_p = IPPROTO_ICMP;
    624 
    625 		outicmp = (struct icmp *)outp;
    626 		outicmp->icmp_type = ICMP_ECHO;
    627 		outicmp->icmp_id = htons(ident);
    628 
    629 		outmark = outp + 8;	/* XXX magic number */
    630 	} else {
    631 		outip->ip_p = IPPROTO_UDP;
    632 
    633 		outudp = (struct udphdr *)outp;
    634 		outudp->uh_sport = htons(ident);
    635 		outudp->uh_ulen =
    636 		    htons((u_short)(packlen - (sizeof(*outip) + optlen)));
    637 		outmark = outudp + 1;
    638 	}
    639 
    640 	cp = "icmp";
    641 	if ((pe = getprotobyname(cp)) == NULL) {
    642 		Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
    643 		exit(1);
    644 	}
    645 	if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
    646 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
    647 		exit(1);
    648 	}
    649 	if (options & SO_DEBUG)
    650 		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
    651 		    sizeof(on));
    652 	if (options & SO_DONTROUTE)
    653 		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    654 		    sizeof(on));
    655 #ifdef IPSEC
    656 #ifdef IPSEC_POLICY_IPSEC
    657 	/*
    658 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    659 	 * turned off.
    660 	 */
    661 	if (setpolicy(s, "in bypass") < 0)
    662 		exit(1);
    663 	if (setpolicy(s, "out bypass") < 0)
    664 		exit(1);
    665 #else
    666     {
    667 	int level = IPSEC_LEVEL_AVAIL;
    668 
    669 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    670 		sizeof(level));
    671 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    672 		sizeof(level));
    673 #ifdef IP_AUTH_TRANS_LEVEL
    674 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    675 		sizeof(level));
    676 #else
    677 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    678 		sizeof(level));
    679 #endif
    680 #ifdef IP_AUTH_NETWORK_LEVEL
    681 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    682 		sizeof(level));
    683 #endif
    684     }
    685 #endif /*IPSEC_POLICY_IPSEC*/
    686 #endif /*IPSEC*/
    687 
    688 #ifndef __hpux
    689 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    690 #else
    691 	sndsock = socket(AF_INET, SOCK_RAW,
    692 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
    693 #endif
    694 	if (sndsock < 0) {
    695 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
    696 		exit(1);
    697 	}
    698 
    699 #ifdef IPSEC
    700 #ifdef IPSEC_POLICY_IPSEC
    701 	/*
    702 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    703 	 * turned off.
    704 	 */
    705 	if (setpolicy(sndsock, "in bypass") < 0)
    706 		exit(1);
    707 	if (setpolicy(sndsock, "out bypass") < 0)
    708 		exit(1);
    709 #else
    710     {
    711 	int level = IPSEC_LEVEL_BYPASS;
    712 
    713 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    714 		sizeof(level));
    715 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    716 		sizeof(level));
    717 #ifdef IP_AUTH_TRANS_LEVEL
    718 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    719 		sizeof(level));
    720 #else
    721 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    722 		sizeof(level));
    723 #endif
    724 #ifdef IP_AUTH_NETWORK_LEVEL
    725 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    726 		sizeof(level));
    727 #endif
    728     }
    729 #endif /*IPSEC_POLICY_IPSEC*/
    730 #endif /*IPSEC*/
    731 
    732 	/* Revert to non-privileged user after opening sockets */
    733 	setuid(getuid());
    734 
    735 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
    736 	if (lsrr > 0) {
    737 		u_char optlist[MAX_IPOPTLEN];
    738 
    739 		cp = "ip";
    740 		if ((pe = getprotobyname(cp)) == NULL) {
    741 			Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
    742 			exit(1);
    743 		}
    744 
    745 		/* final hop */
    746 		gwlist[lsrr] = to->sin_addr.s_addr;
    747 		++lsrr;
    748 
    749 		/* force 4 byte alignment */
    750 		optlist[0] = IPOPT_NOP;
    751 		/* loose source route option */
    752 		optlist[1] = IPOPT_LSRR;
    753 		i = lsrr * sizeof(gwlist[0]);
    754 		optlist[2] = i + 3;
    755 		/* Pointer to LSRR addresses */
    756 		optlist[3] = IPOPT_MINOFF;
    757 		memcpy(optlist + 4, gwlist, i);
    758 
    759 		if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS, optlist,
    760 		    i + sizeof(gwlist[0]))) < 0) {
    761 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
    762 			    prog, strerror(errno));
    763 			exit(1);
    764 		    }
    765 	}
    766 #endif
    767 
    768 #ifdef SO_SNDBUF
    769 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
    770 	    sizeof(packlen)) < 0) {
    771 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
    772 		exit(1);
    773 	}
    774 #endif
    775 #ifdef IP_HDRINCL
    776 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    777 	    sizeof(on)) < 0) {
    778 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
    779 		exit(1);
    780 	}
    781 #else
    782 #ifdef IP_TOS
    783 	if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
    784 	    (char *)&tos, sizeof(tos)) < 0) {
    785 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
    786 		    prog, tos, strerror(errno));
    787 		exit(1);
    788 	}
    789 #endif
    790 #endif
    791 	if (options & SO_DEBUG)
    792 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
    793 		    sizeof(on));
    794 	if (options & SO_DONTROUTE)
    795 		(void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    796 		    sizeof(on));
    797 
    798 	/* Get the interface address list */
    799 	n = ifaddrlist(&al, errbuf, sizeof errbuf);
    800 	al2 = al;
    801 	if (n < 0) {
    802 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
    803 		exit(1);
    804 	}
    805 	if (n == 0) {
    806 		Fprintf(stderr,
    807 		    "%s: Can't find any network interfaces\n", prog);
    808 		exit(1);
    809 	}
    810 
    811 	/* Look for a specific device */
    812 	if (device != NULL) {
    813 		for (i = n; i > 0; --i, ++al2)
    814 			if (strcmp(device, al2->device) == 0)
    815 				break;
    816 		if (i <= 0) {
    817 			Fprintf(stderr, "%s: Can't find interface %s\n",
    818 			    prog, device);
    819 			exit(1);
    820 		}
    821 	}
    822 
    823 	/* Determine our source address */
    824 	if (source == NULL) {
    825 		/*
    826 		 * If a device was specified, use the interface address.
    827 		 * Otherwise, use the first interface found.
    828 		 * Warn if there are more than one.
    829 		 */
    830 		setsin(from, al2->addr);
    831 		if (n > 1 && device == NULL && !find_local_ip(from, to)) {
    832 			Fprintf(stderr,
    833 		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
    834 			    prog, inet_ntoa(from->sin_addr), al2->device);
    835 		}
    836 	} else {
    837 		hi = gethostinfo(source);
    838 		source = hi->name;
    839 		hi->name = NULL;
    840 		if (device == NULL) {
    841 			/*
    842 			 * Use the first interface found.
    843 			 * Warn if there are more than one.
    844 			 */
    845 			setsin(from, hi->addrs[0]);
    846 			if (hi->n > 1)
    847 				Fprintf(stderr,
    848 			"%s: Warning: %s has multiple addresses; using %s\n",
    849 				    prog, source, inet_ntoa(from->sin_addr));
    850 		} else {
    851 			/*
    852 			 * Make sure the source specified matches the
    853 			 * interface address.
    854 			 */
    855 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
    856 				if (*ap == al2->addr)
    857 					break;
    858 			if (i <= 0) {
    859 				Fprintf(stderr,
    860 				    "%s: %s is not on interface %s\n",
    861 				    prog, source, device);
    862 				exit(1);
    863 			}
    864 			setsin(from, *ap);
    865 		}
    866 		freehostinfo(hi);
    867 	}
    868 
    869 	/*
    870 	 * If not root, make sure source address matches a local interface.
    871 	 * (The list of addresses produced by ifaddrlist() automatically
    872 	 * excludes interfaces that are marked down and/or loopback.)
    873 	 */
    874 	if (getuid())  {
    875 		al2 = al;
    876 		for (i = n; i > 0; --i, ++al2)
    877 			if (from->sin_addr.s_addr == al2->addr)
    878 			    break;
    879 		if (i <= 0) {
    880 			Fprintf(stderr, "%s: %s is not a valid local address "
    881 			    "and you are not superuser.\n", prog,
    882 			    inet_ntoa(from->sin_addr));
    883 			exit(1);
    884 		}
    885 	}
    886 
    887 	outip->ip_src = from->sin_addr;
    888 #ifndef IP_HDRINCL
    889 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
    890 		Fprintf(stderr, "%s: bind: %s\n",
    891 		    prog, strerror(errno));
    892 		exit (1);
    893 	}
    894 #endif
    895 
    896 	if (as_path) {
    897 		asn = as_setup(as_server);
    898 		if (asn == NULL) {
    899 			Fprintf(stderr, "%s: as_setup failed, AS# lookups disabled\n",
    900 				prog);
    901 			(void)fflush(stderr);
    902 			as_path = 0;
    903 		}
    904 	}
    905 
    906 	setuid(getuid());
    907 	Fprintf(stderr, "%s to %s (%s)",
    908 	    prog, hostname, inet_ntoa(to->sin_addr));
    909 	if (source)
    910 		Fprintf(stderr, " from %s", source);
    911 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
    912 	(void)fflush(stderr);
    913 
    914 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
    915 		u_int32_t lastaddr = 0;
    916 		int got_there = 0;
    917 		int unreachable = 0;
    918 
    919 again:
    920 		printed_ttl = 0;
    921 		for (probe = 0; probe < nprobes; ++probe) {
    922 			register int cc;
    923 			struct timeval t1, t2;
    924 			struct timezone tz;
    925 			register struct ip *ip;
    926 			(void)gettimeofday(&t1, &tz);
    927 			send_probe(++seq, ttl, &t1);
    928 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
    929 				(void)gettimeofday(&t2, &tz);
    930 				/*
    931 				 * Since we'll be receiving all ICMP
    932 				 * messages to this host above, we may
    933 				 * never end up with cc=0, so we need
    934 				 * an additional termination check.
    935 				 */
    936 				if (t2.tv_sec - t1.tv_sec > waittime) {
    937 					cc = 0;
    938 					break;
    939 				}
    940 				i = packet_ok(packet, cc, from, seq);
    941 				/* Skip short packet */
    942 				if (i == 0)
    943 					continue;
    944 				if (from->sin_addr.s_addr != lastaddr) {
    945 					print(packet, cc, from);
    946 					lastaddr = from->sin_addr.s_addr;
    947 				}
    948 				ip = (struct ip *)packet;
    949 				Printf("  %.3f ms", deltaT(&t1, &t2));
    950 				if (ttl_flag)
    951 					Printf(" (ttl = %d)", ip->ip_ttl);
    952 				if (i == -2) {
    953 #ifndef ARCHAIC
    954 					if (ip->ip_ttl <= 1)
    955 						Printf(" !");
    956 #endif
    957 					++got_there;
    958 					break;
    959 				}
    960 
    961 				/* time exceeded in transit */
    962 				if (i == -1)
    963 					break;
    964 				code = i - 1;
    965 				switch (code) {
    966 
    967 				case ICMP_UNREACH_PORT:
    968 #ifndef ARCHAIC
    969 					if (ip->ip_ttl <= 1)
    970 						Printf(" !");
    971 #endif
    972 					++got_there;
    973 					break;
    974 
    975 				case ICMP_UNREACH_NET:
    976 					++unreachable;
    977 					Printf(" !N");
    978 					break;
    979 
    980 				case ICMP_UNREACH_HOST:
    981 					++unreachable;
    982 					Printf(" !H");
    983 					break;
    984 
    985 				case ICMP_UNREACH_PROTOCOL:
    986 					++got_there;
    987 					Printf(" !P");
    988 					break;
    989 
    990 				case ICMP_UNREACH_NEEDFRAG:
    991 					if (mtudisc) {
    992 						frag_err();
    993 						goto again;
    994 					} else {
    995 						++unreachable;
    996 						Printf(" !F");
    997 					}
    998 					break;
    999 
   1000 				case ICMP_UNREACH_SRCFAIL:
   1001 					++unreachable;
   1002 					Printf(" !S");
   1003 					break;
   1004 
   1005 /* rfc1716 */
   1006 #ifndef ICMP_UNREACH_FILTER_PROHIB
   1007 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
   1008 #endif
   1009 				case ICMP_UNREACH_FILTER_PROHIB:
   1010 					++unreachable;
   1011 					Printf(" !X");
   1012 					break;
   1013 
   1014 				default:
   1015 					++unreachable;
   1016 					Printf(" !<%d>", code);
   1017 					break;
   1018 				}
   1019 				break;
   1020 			}
   1021 			if (cc == 0)
   1022 				Printf(" *");
   1023 			(void)fflush(stdout);
   1024 		}
   1025 		putchar('\n');
   1026 		if (got_there ||
   1027 		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
   1028 			break;
   1029 	}
   1030 
   1031 	if (as_path)
   1032 		as_shutdown(asn);
   1033 
   1034 	exit(0);
   1035 }
   1036 
   1037 int
   1038 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
   1039     register struct timeval *tp)
   1040 {
   1041 	fd_set *fdsp;
   1042 	size_t nfds;
   1043 	struct timeval now, wait;
   1044 	struct timezone tz;
   1045 	register int cc = 0;
   1046 	int fromlen = sizeof(*fromp);
   1047 	int retval;
   1048 
   1049 	nfds = howmany(sock + 1, NFDBITS) * sizeof(fd_mask);
   1050 	if ((fdsp = malloc(nfds)) == NULL) {
   1051 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
   1052 		exit(1);
   1053 	}
   1054 	memset(fdsp, 0, nfds);
   1055 	FD_SET(sock, fdsp);
   1056 
   1057 	wait.tv_sec = tp->tv_sec + waittime;
   1058 	wait.tv_usec = tp->tv_usec;
   1059 	(void)gettimeofday(&now, &tz);
   1060 	tvsub(&wait, &now);
   1061 
   1062 	if (wait.tv_sec < 0) {
   1063 		wait.tv_sec = 0;
   1064 		wait.tv_usec = 0;
   1065 	}
   1066 
   1067 	retval = select(sock + 1, fdsp, NULL, NULL, &wait);
   1068 	free(fdsp);
   1069 	if (retval < 0)  {
   1070 		/* If we continue, we probably just flood the remote host. */
   1071 		Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
   1072 		exit(1);
   1073 	}
   1074 	if (retval > 0)  {
   1075 		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
   1076 			    (struct sockaddr *)fromp, &fromlen);
   1077 	}
   1078 
   1079 	return(cc);
   1080 }
   1081 
   1082 void
   1083 dump_packet()
   1084 {
   1085 	u_char *p;
   1086 	int i;
   1087 
   1088 	Fprintf(stderr, "packet data:");
   1089 
   1090 #ifdef __hpux
   1091 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
   1092 	    i < packlen - (sizeof(*outip) + optlen); i++)
   1093 #else
   1094 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
   1095 #endif
   1096 	{
   1097 		if ((i % 24) == 0)
   1098 			Fprintf(stderr, "\n ");
   1099 		Fprintf(stderr, " %02x", *p++);
   1100 	}
   1101 	Fprintf(stderr, "\n");
   1102 }
   1103 
   1104 void
   1105 send_probe(register int seq, int ttl, register struct timeval *tp)
   1106 {
   1107 	register int cc;
   1108 	register struct udpiphdr * ui;
   1109 	int oldmtu = packlen;
   1110 
   1111 again:
   1112 #ifdef BYTESWAP_IP_LEN
   1113 	outip->ip_len = htons(packlen);
   1114 #else
   1115 	outip->ip_len = packlen;
   1116 #endif
   1117 	outip->ip_ttl = ttl;
   1118 #ifndef __hpux
   1119 	outip->ip_id = htons(ident + seq);
   1120 #endif
   1121 
   1122 	/*
   1123 	 * In most cases, the kernel will recalculate the ip checksum.
   1124 	 * But we must do it anyway so that the udp checksum comes out
   1125 	 * right.
   1126 	 */
   1127 	if (docksum) {
   1128 		outip->ip_sum =
   1129 		    in_cksum((u_short *)outip, sizeof(*outip) + optlen);
   1130 		if (outip->ip_sum == 0)
   1131 			outip->ip_sum = 0xffff;
   1132 	}
   1133 
   1134 	/* Payload */
   1135 	outsetup.seq = seq;
   1136 	outsetup.ttl = ttl;
   1137 	outsetup.tv  = *tp;
   1138 	memcpy(outmark,&outsetup,sizeof(outsetup));
   1139 
   1140 	if (useicmp)
   1141 		outicmp->icmp_seq = htons(seq);
   1142 	else
   1143 		outudp->uh_dport = htons(port + seq);
   1144 
   1145 	/* (We can only do the checksum if we know our ip address) */
   1146 	if (docksum) {
   1147 		if (useicmp) {
   1148 			outicmp->icmp_cksum = 0;
   1149 			outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
   1150 			    packlen - (sizeof(*outip) + optlen));
   1151 			if (outicmp->icmp_cksum == 0)
   1152 				outicmp->icmp_cksum = 0xffff;
   1153 		} else {
   1154 			u_short sum;
   1155 			struct {
   1156 				struct in_addr src;
   1157 				struct in_addr dst;
   1158 				u_int8_t zero;
   1159 				u_int8_t protocol;
   1160 				u_int16_t len;
   1161 			} __attribute__((__packed__)) phdr;
   1162 
   1163 			/* Checksum */
   1164 			ui = (struct udpiphdr *)outip;
   1165 			memset(&phdr, 0, sizeof(phdr));
   1166 			phdr.src = ui->ui_src;
   1167 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
   1168 			phdr.protocol = ui->ui_pr;
   1169 			phdr.len = outudp->uh_ulen;
   1170 			outudp->uh_sum = 0;
   1171 			sum = in_cksum2(0, (u_short *)&phdr, sizeof(phdr));
   1172 			sum = in_cksum2(sum, (u_short *)outudp, ntohs(outudp->uh_ulen));
   1173 			outudp->uh_sum = ~sum;
   1174 			if (outudp->uh_sum == 0)
   1175 				outudp->uh_sum = 0xffff;
   1176 		}
   1177 	}
   1178 
   1179 	/* XXX undocumented debugging hack */
   1180 	if (verbose > 1) {
   1181 		register const u_short *sp;
   1182 		register int nshorts, i;
   1183 
   1184 		sp = (u_short *)outip;
   1185 		nshorts = (u_int)packlen / sizeof(u_short);
   1186 		i = 0;
   1187 		Printf("[ %d bytes", packlen);
   1188 		while (--nshorts >= 0) {
   1189 			if ((i++ % 8) == 0)
   1190 				Printf("\n\t");
   1191 			Printf(" %04x", ntohs(*sp++));
   1192 		}
   1193 		if (packlen & 1) {
   1194 			if ((i % 8) == 0)
   1195 				Printf("\n\t");
   1196 			Printf(" %02x", *(u_char *)sp);
   1197 		}
   1198 		Printf("]\n");
   1199 	}
   1200 
   1201 #if !defined(IP_HDRINCL) && defined(IP_TTL)
   1202 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
   1203 	    (char *)&ttl, sizeof(ttl)) < 0) {
   1204 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
   1205 		    prog, ttl, strerror(errno));
   1206 		exit(1);
   1207 	}
   1208 #endif
   1209 	if (dump)
   1210 		dump_packet();
   1211 
   1212 #ifdef __hpux
   1213 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
   1214 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
   1215 	if (cc > 0)
   1216 		cc += sizeof(*outip) + optlen;
   1217 #else
   1218 	cc = sendto(sndsock, (char *)outip,
   1219 	    packlen, 0, &whereto, sizeof(whereto));
   1220 #endif
   1221 	if (cc < 0 || cc != packlen)  {
   1222 		if (cc < 0) {
   1223 			/*
   1224 			 * An errno of EMSGSIZE means we're writing too big a
   1225 			 * datagram for the interface.  We have to just
   1226 			 * decrease the packet size until we find one that
   1227 			 * works.
   1228 			 *
   1229 			 * XXX maybe we should try to read the outgoing if's
   1230 			 * mtu?
   1231 			 */
   1232 			if (errno == EMSGSIZE) {
   1233 				packlen = *mtuptr++;
   1234 				resize_packet();
   1235 				goto again;
   1236 			} else
   1237 				Fprintf(stderr, "%s: sendto: %s\n",
   1238 				    prog, strerror(errno));
   1239 		}
   1240 
   1241 		Printf("%s: wrote %s %d chars, ret=%d\n",
   1242 		    prog, hostname, packlen, cc);
   1243 		(void)fflush(stdout);
   1244 	}
   1245 	if (oldmtu != packlen) {
   1246 		Printf("message too big, "
   1247 		    "trying new MTU = %d\n", packlen);
   1248 		printed_ttl = 0;
   1249 	}
   1250 	if (!printed_ttl) {
   1251 		Printf("%2d ", ttl);
   1252 		printed_ttl = 1;
   1253 	}
   1254 
   1255 }
   1256 
   1257 double
   1258 deltaT(struct timeval *t1p, struct timeval *t2p)
   1259 {
   1260 	register double dt;
   1261 
   1262 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
   1263 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
   1264 	return (dt);
   1265 }
   1266 
   1267 /*
   1268  * Convert an ICMP "type" field to a printable string.
   1269  */
   1270 char *
   1271 pr_type(register u_char t)
   1272 {
   1273 	static char *ttab[] = {
   1274 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
   1275 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
   1276 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
   1277 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
   1278 	"Info Reply"
   1279 	};
   1280 
   1281 	if (t > 16)
   1282 		return("OUT-OF-RANGE");
   1283 
   1284 	return(ttab[t]);
   1285 }
   1286 
   1287 int
   1288 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
   1289     register int seq)
   1290 {
   1291 	register struct icmp *icp;
   1292 	register u_char type, code;
   1293 	register int hlen;
   1294 #ifndef ARCHAIC
   1295 	register struct ip *ip;
   1296 
   1297 	ip = (struct ip *) buf;
   1298 	hlen = ip->ip_hl << 2;
   1299 	if (cc < hlen + ICMP_MINLEN) {
   1300 		if (verbose)
   1301 			Printf("packet too short (%d bytes) from %s\n", cc,
   1302 				inet_ntoa(from->sin_addr));
   1303 		return (0);
   1304 	}
   1305 	cc -= hlen;
   1306 	icp = (struct icmp *)(buf + hlen);
   1307 #else
   1308 	icp = (struct icmp *)buf;
   1309 #endif
   1310 	type = icp->icmp_type;
   1311 	code = icp->icmp_code;
   1312 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
   1313 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
   1314 		register struct ip *hip;
   1315 		register struct udphdr *up;
   1316 		register struct icmp *hicmp;
   1317 
   1318 		hip = &icp->icmp_ip;
   1319 		hlen = hip->ip_hl << 2;
   1320 
   1321 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
   1322 
   1323 		if (useicmp) {
   1324 			/* XXX */
   1325 			if (type == ICMP_ECHOREPLY &&
   1326 			    icp->icmp_id == htons(ident) &&
   1327 			    icp->icmp_seq == htons(seq))
   1328 				return (-2);
   1329 
   1330 			hicmp = (struct icmp *)((u_char *)hip + hlen);
   1331 			/* XXX 8 is a magic number */
   1332 			if (hlen + 8 <= cc &&
   1333 			    hip->ip_p == IPPROTO_ICMP &&
   1334 			    hicmp->icmp_id == htons(ident) &&
   1335 			    hicmp->icmp_seq == htons(seq))
   1336 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1337 		} else {
   1338 			up = (struct udphdr *)((u_char *)hip + hlen);
   1339 			/* XXX 8 is a magic number */
   1340 			if (hlen + 12 <= cc &&
   1341 			    hip->ip_p == IPPROTO_UDP &&
   1342 			    up->uh_sport == htons(ident) &&
   1343 			    up->uh_dport == htons(port + seq))
   1344 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1345 		}
   1346 	}
   1347 #ifndef ARCHAIC
   1348 	if (verbose) {
   1349 		register int i;
   1350 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
   1351 
   1352 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
   1353 		Printf("%s: icmp type %d (%s) code %d\n",
   1354 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
   1355 		for (i = 4; i < cc ; i += sizeof(*lp))
   1356 			Printf("%2d: x%8.8x\n", i, *lp++);
   1357 	}
   1358 #endif
   1359 	return(0);
   1360 }
   1361 
   1362 void resize_packet(void)
   1363 {
   1364 	if (useicmp) {
   1365 		outicmp->icmp_cksum = 0;
   1366 		outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
   1367 		    packlen - (sizeof(*outip) + optlen));
   1368 		if (outicmp->icmp_cksum == 0)
   1369 			outicmp->icmp_cksum = 0xffff;
   1370 	} else {
   1371 		outudp->uh_ulen =
   1372 		    htons((u_short)(packlen - (sizeof(*outip) + optlen)));
   1373 	}
   1374 }
   1375 
   1376 void
   1377 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
   1378 {
   1379 	register struct ip *ip;
   1380 	register int hlen;
   1381 
   1382 	ip = (struct ip *) buf;
   1383 	hlen = ip->ip_hl << 2;
   1384 	cc -= hlen;
   1385 
   1386 	if (as_path)
   1387 		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
   1388 
   1389 	if (nflag)
   1390 		Printf(" %s", inet_ntoa(from->sin_addr));
   1391 	else
   1392 		Printf(" %s (%s)", inetname(from->sin_addr),
   1393 		    inet_ntoa(from->sin_addr));
   1394 
   1395 	if (verbose)
   1396 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
   1397 }
   1398 
   1399 u_short
   1400 in_cksum(u_short *addr, int len)
   1401 {
   1402 
   1403 	return ~in_cksum2(0, addr, len);
   1404 }
   1405 
   1406 /*
   1407  * Checksum routine for Internet Protocol family headers (C Version)
   1408  */
   1409 u_short
   1410 in_cksum2(u_short seed, register u_short *addr, register int len)
   1411 {
   1412 	register int nleft = len;
   1413 	register u_short *w = addr;
   1414 	register u_short answer;
   1415 	register int sum = seed;
   1416 
   1417 	/*
   1418 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
   1419 	 *  we add sequential 16 bit words to it, and at the end, fold
   1420 	 *  back all the carry bits from the top 16 bits into the lower
   1421 	 *  16 bits.
   1422 	 */
   1423 	while (nleft > 1)  {
   1424 		sum += *w++;
   1425 		nleft -= 2;
   1426 	}
   1427 
   1428 	/* mop up an odd byte, if necessary */
   1429 	if (nleft == 1)
   1430 		sum += *(u_char *)w;
   1431 
   1432 	/*
   1433 	 * add back carry outs from top 16 bits to low 16 bits
   1434 	 */
   1435 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
   1436 	sum += (sum >> 16);			/* add carry */
   1437 	answer = sum;				/* truncate to 16 bits */
   1438 	return (answer);
   1439 }
   1440 
   1441 /*
   1442  * Subtract 2 timeval structs:  out = out - in.
   1443  * Out is assumed to be >= in.
   1444  */
   1445 void
   1446 tvsub(register struct timeval *out, register struct timeval *in)
   1447 {
   1448 
   1449 	if ((out->tv_usec -= in->tv_usec) < 0)   {
   1450 		--out->tv_sec;
   1451 		out->tv_usec += 1000000;
   1452 	}
   1453 	out->tv_sec -= in->tv_sec;
   1454 }
   1455 
   1456 /*
   1457  * Construct an Internet address representation.
   1458  * If the nflag has been supplied, give
   1459  * numeric value, otherwise try for symbolic name.
   1460  */
   1461 char *
   1462 inetname(struct in_addr in)
   1463 {
   1464 	register char *cp;
   1465 	register struct hostent *hp;
   1466 	static int first = 1;
   1467 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
   1468 
   1469 	if (first && !nflag) {
   1470 		int rv;
   1471 
   1472 		first = 0;
   1473 		rv = gethostname(domain, sizeof domain);
   1474 		domain[sizeof(domain) - 1] = '\0';
   1475 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
   1476 			(void)strncpy(domain, cp + 1, sizeof(domain) - 1);
   1477 		} else
   1478 			domain[0] = '\0';
   1479 	}
   1480 	if (!nflag && in.s_addr != INADDR_ANY) {
   1481 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
   1482 		if (hp != NULL) {
   1483 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
   1484 			    strcmp(cp + 1, domain) == 0)
   1485 				*cp = '\0';
   1486 			(void)strncpy(line, hp->h_name, sizeof(line) - 1);
   1487 			line[sizeof(line) - 1] = '\0';
   1488 			return (line);
   1489 		}
   1490 	}
   1491 	return (inet_ntoa(in));
   1492 }
   1493 
   1494 struct hostinfo *
   1495 gethostinfo(register char *hostname)
   1496 {
   1497 	register int n;
   1498 	register struct hostent *hp;
   1499 	register struct hostinfo *hi;
   1500 	register char **p;
   1501 	register u_int32_t *ap;
   1502 	struct in_addr addr;
   1503 
   1504 	hi = calloc(1, sizeof(*hi));
   1505 	if (hi == NULL) {
   1506 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1507 		exit(1);
   1508 	}
   1509 	if (inet_aton(hostname, &addr) != 0) {
   1510 		hi->name = strdup(hostname);
   1511 		hi->n = 1;
   1512 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
   1513 		if (hi->addrs == NULL) {
   1514 			Fprintf(stderr, "%s: calloc %s\n",
   1515 			    prog, strerror(errno));
   1516 			exit(1);
   1517 		}
   1518 		hi->addrs[0] = addr.s_addr;
   1519 		return (hi);
   1520 	}
   1521 
   1522 	hp = gethostbyname(hostname);
   1523 	if (hp == NULL) {
   1524 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
   1525 		exit(1);
   1526 	}
   1527 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
   1528 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
   1529 		exit(1);
   1530 	}
   1531 	hi->name = strdup(hp->h_name);
   1532 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
   1533 		continue;
   1534 	hi->n = n;
   1535 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
   1536 	if (hi->addrs == NULL) {
   1537 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1538 		exit(1);
   1539 	}
   1540 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
   1541 		memcpy(ap, *p, sizeof(*ap));
   1542 	return (hi);
   1543 }
   1544 
   1545 void
   1546 freehostinfo(register struct hostinfo *hi)
   1547 {
   1548 	if (hi->name != NULL) {
   1549 		free(hi->name);
   1550 		hi->name = NULL;
   1551 	}
   1552 	free((char *)hi->addrs);
   1553 	free((char *)hi);
   1554 }
   1555 
   1556 void
   1557 getaddr(register u_int32_t *ap, register char *hostname)
   1558 {
   1559 	register struct hostinfo *hi;
   1560 
   1561 	hi = gethostinfo(hostname);
   1562 	*ap = hi->addrs[0];
   1563 	freehostinfo(hi);
   1564 }
   1565 
   1566 void
   1567 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
   1568 {
   1569 
   1570 	memset(sin, 0, sizeof(*sin));
   1571 #ifdef HAVE_SOCKADDR_SA_LEN
   1572 	sin->sin_len = sizeof(*sin);
   1573 #endif
   1574 	sin->sin_family = AF_INET;
   1575 	sin->sin_addr.s_addr = addr;
   1576 }
   1577 
   1578 /* String to value with optional min and max. Handles decimal and hex. */
   1579 int
   1580 str2val(register const char *str, register const char *what,
   1581     register int mi, register int ma)
   1582 {
   1583 	register const char *cp;
   1584 	register int val;
   1585 	char *ep;
   1586 
   1587 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
   1588 		cp = str + 2;
   1589 		val = (int)strtol(cp, &ep, 16);
   1590 	} else
   1591 		val = (int)strtol(str, &ep, 10);
   1592 	if (*ep != '\0') {
   1593 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
   1594 		    prog, str, what);
   1595 		exit(1);
   1596 	}
   1597 	if (val < mi && mi >= 0) {
   1598 		if (mi == 0)
   1599 			Fprintf(stderr, "%s: %s must be >= %d\n",
   1600 			    prog, what, mi);
   1601 		else
   1602 			Fprintf(stderr, "%s: %s must be > %d\n",
   1603 			    prog, what, mi - 1);
   1604 		exit(1);
   1605 	}
   1606 	if (val > ma && ma >= 0) {
   1607 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
   1608 		exit(1);
   1609 	}
   1610 	return (val);
   1611 }
   1612 
   1613 __dead void
   1614 usage(void)
   1615 {
   1616 	extern char version[];
   1617 
   1618 	Fprintf(stderr, "Version %s\n", version);
   1619 	Fprintf(stderr, "Usage: %s [-adDFPIlnrvx] [-g gateway] [-i iface] \
   1620 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
   1621 [-w waittime] [-A as_server] host [packetlen]\n",
   1622 	    prog);
   1623 	exit(1);
   1624 }
   1625 
   1626 /*
   1627  * Received ICMP unreachable (fragmentation required and DF set).
   1628  * If the ICMP error was from a "new" router, it'll contain the next-hop
   1629  * MTU that we should use next.  Otherwise we'll just keep going in the
   1630  * mtus[] table, trying until we hit a valid MTU.
   1631  */
   1632 
   1633 
   1634 void
   1635 frag_err()
   1636 {
   1637         int i;
   1638 
   1639         if (nextmtu > 0 && nextmtu < packlen) {
   1640                 Printf("\nfragmentation required and DF set, "
   1641 		     "next hop MTU = %d\n",
   1642                         nextmtu);
   1643                 packlen = nextmtu;
   1644                 for (i = 0; mtus[i] > 0; i++) {
   1645                         if (mtus[i] < nextmtu) {
   1646                                 mtuptr = &mtus[i];    /* next one to try */
   1647                                 break;
   1648                         }
   1649                 }
   1650         } else {
   1651                 Printf("\nfragmentation required and DF set. ");
   1652 		if (nextmtu)
   1653 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
   1654 			    nextmtu, packlen);
   1655                 packlen = *mtuptr++;
   1656 		Printf("Trying new MTU = %d\n", packlen);
   1657         }
   1658 	resize_packet();
   1659 }
   1660 
   1661 int
   1662 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
   1663 {
   1664 	int sock;
   1665 	struct sockaddr_in help;
   1666 	int help_len;
   1667 
   1668 	sock = socket(AF_INET, SOCK_DGRAM, 0);
   1669 	if (sock < 0) return (0);
   1670 
   1671 	help.sin_family = AF_INET;
   1672 	/*
   1673 	 * At this point the port number doesn't matter
   1674 	 * since it only has to be greater than zero.
   1675 	 */
   1676 	help.sin_port = 42;
   1677 	help.sin_addr.s_addr = to->sin_addr.s_addr;
   1678 	if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
   1679 		(void)close(sock);
   1680 		return (0);
   1681 	}
   1682 
   1683 	help_len = sizeof(help);
   1684 	if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
   1685 	    help_len != sizeof(help) ||
   1686 	    help.sin_addr.s_addr == INADDR_ANY) {
   1687 		(void)close(sock);
   1688 		return (0);
   1689 	}
   1690 
   1691 	(void)close(sock);
   1692 	setsin(from, help.sin_addr.s_addr);
   1693 	return (1);
   1694 }
   1695 
   1696 #ifdef IPSEC
   1697 #ifdef IPSEC_POLICY_IPSEC
   1698 int
   1699 setpolicy(so, policy)
   1700 	int so;
   1701 	char *policy;
   1702 {
   1703 	char *buf;
   1704 
   1705 	buf = ipsec_set_policy(policy, strlen(policy));
   1706 	if (buf == NULL) {
   1707 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
   1708 		return -1;
   1709 	}
   1710 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
   1711 		buf, ipsec_get_policylen(buf));
   1712 
   1713 	free(buf);
   1714 
   1715 	return 0;
   1716 }
   1717 #endif
   1718 #endif
   1719 
   1720