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