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