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