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