Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.77
      1 /*	$NetBSD: traceroute.c,v 1.77 2011/05/10 01:52:49 christos 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\
     31  The Regents of the University of California.  All rights reserved.");
     32 __RCSID("$NetBSD: traceroute.c,v 1.77 2011/05/10 01:52:49 christos Exp $");
     33 #endif
     34 #endif
     35 
     36 /*
     37  * traceroute host  - trace the route ip packets follow going to "host".
     38  *
     39  * Attempt to trace the route an ip packet would follow to some
     40  * internet host.  We find out intermediate hops by launching probe
     41  * packets with a small ttl (time to live) then listening for an
     42  * icmp "time exceeded" reply from a gateway.  We start our probes
     43  * with a ttl of one and increase by one until we get an icmp "port
     44  * unreachable" (which means we got to "host") or hit a max (which
     45  * defaults to 30 hops & can be changed with the -m flag).  Three
     46  * probes (change with -q flag) are sent at each ttl setting and a
     47  * line is printed showing the ttl, address of the gateway and
     48  * round trip time of each probe.  If the probe answers come from
     49  * different gateways, the address of each responding system will
     50  * be printed.  If there is no response within a 5 sec. timeout
     51  * interval (changed with the -w flag), a "*" is printed for that
     52  * probe.
     53  *
     54  * Probe packets are UDP format.  We don't want the destination
     55  * host to process them so the destination port is set to an
     56  * unlikely value (if some clod on the destination is using that
     57  * value, it can be changed with the -p flag).
     58  *
     59  * A sample use might be:
     60  *
     61  *     [yak 71]% traceroute nis.nsf.net.
     62  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
     63  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
     64  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     65  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     66  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
     67  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
     68  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
     69  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
     70  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
     71  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
     72  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
     73  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
     74  *
     75  * Note that lines 2 & 3 are the same.  This is due to a buggy
     76  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
     77  * packets with a zero ttl.
     78  *
     79  * A more interesting example is:
     80  *
     81  *     [yak 72]% traceroute allspice.lcs.mit.edu.
     82  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
     83  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
     84  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
     85  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
     86  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
     87  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
     88  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
     89  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
     90  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
     91  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
     92  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
     93  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
     94  *     12  * * *
     95  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
     96  *     14  * * *
     97  *     15  * * *
     98  *     16  * * *
     99  *     17  * * *
    100  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
    101  *
    102  * (I start to see why I'm having so much trouble with mail to
    103  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
    104  * either don't send ICMP "time exceeded" messages or send them
    105  * with a ttl too small to reach us.  14 - 17 are running the
    106  * MIT C Gateway code that doesn't send "time exceeded"s.  God
    107  * only knows what's going on with 12.
    108  *
    109  * The silent gateway 12 in the above may be the result of a bug in
    110  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
    111  * sends an unreachable message using whatever ttl remains in the
    112  * original datagram.  Since, for gateways, the remaining ttl is
    113  * zero, the icmp "time exceeded" is guaranteed to not make it back
    114  * to us.  The behavior of this bug is slightly more interesting
    115  * when it appears on the destination system:
    116  *
    117  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
    118  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
    119  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
    120  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
    121  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
    122  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
    123  *      7  * * *
    124  *      8  * * *
    125  *      9  * * *
    126  *     10  * * *
    127  *     11  * * *
    128  *     12  * * *
    129  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
    130  *
    131  * Notice that there are 12 "gateways" (13 is the final
    132  * destination) and exactly the last half of them are "missing".
    133  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
    134  * is using the ttl from our arriving datagram as the ttl in its
    135  * icmp reply.  So, the reply will time out on the return path
    136  * (with no notice sent to anyone since icmp's aren't sent for
    137  * icmp's) until we probe with a ttl that's at least twice the path
    138  * length.  I.e., rip is really only 7 hops away.  A reply that
    139  * returns with a ttl of 1 is a clue this problem exists.
    140  * Traceroute prints a "!" after the time if the ttl is <= 1.
    141  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
    142  * non-standard (HPUX) software, expect to see this problem
    143  * frequently and/or take care picking the target host of your
    144  * probes.
    145  *
    146  * Other possible annotations after the time are !H, !N, !P (got a host,
    147  * network or protocol unreachable, respectively), !S or !F (source
    148  * route failed or fragmentation needed -- neither of these should
    149  * ever occur and the associated gateway is busted if you see one).  If
    150  * almost all the probes result in some kind of unreachable, traceroute
    151  * will give up and exit.
    152  *
    153  * Notes
    154  * -----
    155  * This program must be run by root or be setuid.  (I suggest that
    156  * you *don't* make it setuid -- casual use could result in a lot
    157  * of unnecessary traffic on our poor, congested nets.)
    158  *
    159  * This program requires a kernel mod that does not appear in any
    160  * system available from Berkeley:  A raw ip socket using proto
    161  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
    162  * opposed to data to be wrapped in a ip datagram).  See the README
    163  * file that came with the source to this program for a description
    164  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
    165  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
    166  * MODIFIED TO RUN THIS PROGRAM.
    167  *
    168  * The udp port usage may appear bizarre (well, ok, it is bizarre).
    169  * The problem is that an icmp message only contains 8 bytes of
    170  * data from the original datagram.  8 bytes is the size of a udp
    171  * header so, if we want to associate replies with the original
    172  * datagram, the necessary information must be encoded into the
    173  * udp header (the ip id could be used but there's no way to
    174  * interlock with the kernel's assignment of ip id's and, anyway,
    175  * it would have taken a lot more kernel hacking to allow this
    176  * code to set the ip id).  So, to allow two or more users to
    177  * use traceroute simultaneously, we use this task's pid as the
    178  * source port (the high bit is set to move the port number out
    179  * of the "likely" range).  To keep track of which probe is being
    180  * replied to (so times and/or hop counts don't get confused by a
    181  * reply that was delayed in transit), we increment the destination
    182  * port number before each probe.
    183  *
    184  * Don't use this as a coding example.  I was trying to find a
    185  * routing problem and this code sort-of popped out after 48 hours
    186  * without sleep.  I was amazed it ever compiled, much less ran.
    187  *
    188  * I stole the idea for this program from Steve Deering.  Since
    189  * the first release, I've learned that had I attended the right
    190  * IETF working group meetings, I also could have stolen it from Guy
    191  * Almes or Matt Mathis.  I don't know (or care) who came up with
    192  * the idea first.  I envy the originators' perspicacity and I'm
    193  * glad they didn't keep the idea a secret.
    194  *
    195  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
    196  * enhancements to the original distribution.
    197  *
    198  * I've hacked up a round-trip-route version of this that works by
    199  * sending a loose-source-routed udp datagram through the destination
    200  * back to yourself.  Unfortunately, SO many gateways botch source
    201  * routing, the thing is almost worthless.  Maybe one day...
    202  *
    203  *  -- Van Jacobson (van (at) ee.lbl.gov)
    204  *     Tue Dec 20 03:50:13 PST 1988
    205  */
    206 
    207 #include <sys/param.h>
    208 #include <sys/file.h>
    209 #include <sys/ioctl.h>
    210 #include <sys/socket.h>
    211 #include <sys/time.h>
    212 #include <sys/sysctl.h>
    213 
    214 #include <netinet/in_systm.h>
    215 #include <netinet/in.h>
    216 #include <netinet/ip.h>
    217 #include <netinet/ip_var.h>
    218 #include <netinet/ip_icmp.h>
    219 #include <netinet/udp.h>
    220 #include <netinet/udp_var.h>
    221 
    222 #include <arpa/inet.h>
    223 
    224 #include <ctype.h>
    225 #include <err.h>
    226 #include <errno.h>
    227 #ifdef HAVE_MALLOC_H
    228 #include <malloc.h>
    229 #endif
    230 #include <memory.h>
    231 #include <netdb.h>
    232 #include <stdio.h>
    233 #include <stdlib.h>
    234 #include <string.h>
    235 #include <unistd.h>
    236 #include <poll.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 "as.h"
    249 #include "prog_ops.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 tv32 {
    273 		int32_t tv32_sec;
    274 		int32_t tv32_usec;
    275 	} tv;			/* time packet left */
    276 };
    277 
    278 /*
    279  * Support for ICMP extensions
    280  *
    281  * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
    282  */
    283 #define ICMP_EXT_OFFSET    8 /* ICMP type, code, checksum, unused */ + \
    284                          128 /* original datagram */
    285 #define ICMP_EXT_VERSION 2
    286 /*
    287  * ICMP extensions, common header
    288  */
    289 struct icmp_ext_cmn_hdr {
    290 #if BYTE_ORDER == BIG_ENDIAN
    291 	unsigned char   version:4;
    292 	unsigned char   reserved1:4;
    293 #else
    294 	unsigned char   reserved1:4;
    295 	unsigned char   version:4;
    296 #endif
    297 	unsigned char   reserved2;
    298 	unsigned short  checksum;
    299 };
    300 
    301 /*
    302  * ICMP extensions, object header
    303  */
    304 struct icmp_ext_obj_hdr {
    305     u_short length;
    306     u_char  class_num;
    307 #define MPLS_STACK_ENTRY_CLASS 1
    308     u_char  c_type;
    309 #define MPLS_STACK_ENTRY_C_TYPE 1
    310 };
    311 
    312 struct mpls_header {
    313 #if BYTE_ORDER == BIG_ENDIAN
    314 	 uint32_t	label:20;
    315 	 unsigned char  exp:3;
    316 	 unsigned char  s:1;
    317 	 unsigned char  ttl:8;
    318 #else
    319 	 unsigned char  ttl:8;
    320 	 unsigned char  s:1;
    321 	 unsigned char  exp:3;
    322 	 uint32_t	label:20;
    323 #endif
    324 };
    325 
    326 static u_char	packet[512];		/* last inbound (icmp) packet */
    327 
    328 static struct ip *outip;		/* last output (udp) packet */
    329 static struct udphdr *outudp;		/* last output (udp) packet */
    330 static void *outmark;			/* packed location of struct outdata */
    331 static struct outdata outsetup;	/* setup and copy for alignment */
    332 
    333 static struct icmp *outicmp;		/* last output (icmp) packet */
    334 
    335 /* loose source route gateway list (including room for final destination) */
    336 static u_int32_t gwlist[NGATEWAYS + 1];
    337 
    338 static int s;				/* receive (icmp) socket file descriptor */
    339 static int sndsock;			/* send (udp/icmp) socket file descriptor */
    340 
    341 static struct sockaddr whereto;	/* Who to try to reach */
    342 static struct sockaddr_in wherefrom;	/* Who we are */
    343 static int packlen;			/* total length of packet */
    344 static int minpacket;			/* min ip packet size */
    345 static int maxpacket = 32 * 1024;	/* max ip packet size */
    346 static int printed_ttl = 0;
    347 
    348 static const char *prog;
    349 static char *source;
    350 static char *hostname;
    351 static char *device;
    352 
    353 static int nprobes = 3;
    354 static int max_ttl = 30;
    355 static int first_ttl = 1;
    356 static u_int16_t ident;
    357 static in_port_t port = 32768 + 666;	/* start udp dest port # for probe packets */
    358 
    359 static int options;			/* socket options */
    360 static int verbose;
    361 static int waittime = 5;		/* time to wait for response (in seconds) */
    362 static int nflag;			/* print addresses numerically */
    363 static int dump;
    364 static int Mflag;			/* show MPLS labels if any */
    365 static int as_path;			/* print as numbers for each hop */
    366 static char *as_server = NULL;
    367 static void *asn;
    368 static int useicmp = 0;		/* use icmp echo instead of udp packets */
    369 #ifdef CANT_HACK_CKSUM
    370 static int docksum = 0;		/* don't calculate checksums */
    371 #else
    372 static int docksum = 1;		/* calculate checksums */
    373 #endif
    374 static int optlen;			/* length of ip options */
    375 
    376 static int mtus[] = {
    377         17914,
    378          8166,
    379          4464,
    380          4352,
    381          2048,
    382          2002,
    383          1536,
    384          1500,
    385          1492,
    386 	 1480,
    387 	 1280,
    388          1006,
    389           576,
    390           552,
    391           544,
    392           512,
    393           508,
    394           296,
    395            68,
    396             0
    397 };
    398 static int *mtuptr = &mtus[0];
    399 static int mtudisc = 0;
    400 static int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
    401 
    402 /* Forwards */
    403 static double deltaT(struct timeval *, struct timeval *);
    404 static void freehostinfo(struct hostinfo *);
    405 static void getaddr(u_int32_t *, char *);
    406 static struct hostinfo *gethostinfo(char *);
    407 static u_int16_t in_cksum(u_int16_t *, int);
    408 static u_int16_t in_cksum2(u_int16_t, u_int16_t *, int);
    409 static char *inetname(struct in_addr);
    410 static int packet_ok(u_char *, ssize_t, struct sockaddr_in *, int);
    411 static const char *pr_type(u_char);
    412 static void print(u_char *, int, struct sockaddr_in *);
    413 static void resize_packet(void);
    414 static void dump_packet(void);
    415 static void send_probe(int, int, struct timeval *);
    416 static void setsin(struct sockaddr_in *, u_int32_t);
    417 static int str2val(const char *, const char *, int, int);
    418 static void tvsub(struct timeval *, struct timeval *);
    419 static void usage(void) __attribute__((__noreturn__));
    420 static ssize_t wait_for_reply(int, struct sockaddr_in *, struct timeval *);
    421 static void decode_extensions(unsigned char *buf, int ip_len);
    422 static void frag_err(void);
    423 static int find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
    424 #ifdef IPSEC
    425 #ifdef IPSEC_POLICY_IPSEC
    426 static int setpolicy(int, const char *);
    427 #endif
    428 #endif
    429 
    430 int
    431 main(int argc, char **argv)
    432 {
    433 	int op, code, n;
    434 	u_char *outp;
    435 	u_int32_t *ap;
    436 	struct sockaddr_in *from = &wherefrom;
    437 	struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
    438 	struct hostinfo *hi;
    439 	int on = 1;
    440 	int ttl, probe, i;
    441 	int seq = 0;
    442 	int tos = 0, settos = 0, ttl_flag = 0;
    443 	int lsrr = 0;
    444 	u_int16_t off = 0;
    445 	struct ifaddrlist *al, *al2;
    446 	char errbuf[132];
    447 	int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
    448 	size_t size = sizeof(max_ttl);
    449 
    450 	setprogname(argv[0]);
    451 	prog = getprogname();
    452 
    453 	if (prog_init && prog_init() == -1)
    454 		err(1, "init failed");
    455 
    456 	if ((s = prog_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
    457 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
    458 		exit(1);
    459 	}
    460 
    461 	/*
    462 	 * XXX 'useicmp' will always be zero here. I think the HP-UX users
    463 	 * running our traceroute code will forgive us.
    464 	 */
    465 #ifndef __hpux
    466 	sndsock = prog_socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    467 #else
    468 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW
    469 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
    470 #endif
    471 	if (sndsock < 0) {
    472 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
    473 		exit(1);
    474 	}
    475 
    476 	/* Revert to non-privileged user after opening sockets */
    477 	setuid(getuid());
    478 
    479 	(void) prog_sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
    480 	    NULL, 0);
    481 
    482 	opterr = 0;
    483 	while ((op = getopt(argc, argv, "aA:dDFPIMnlrvxf:g:i:m:p:q:s:t:w:")) != -1)
    484 		switch (op) {
    485 
    486 		case 'a':
    487 			as_path = 1;
    488 			break;
    489 
    490 		case 'A':
    491 			as_path = 1;
    492 			as_server = optarg;
    493 			break;
    494 
    495 		case 'd':
    496 			options |= SO_DEBUG;
    497 			break;
    498 
    499 		case 'D':
    500 			dump = 1;
    501 			break;
    502 
    503 		case 'f':
    504 			first_ttl = str2val(optarg, "first ttl", 1, 255);
    505 			break;
    506 
    507 		case 'F':
    508 			off = IP_DF;
    509 			break;
    510 
    511 		case 'g':
    512 			if (lsrr >= NGATEWAYS) {
    513 				Fprintf(stderr,
    514 				    "%s: No more than %d gateways\n",
    515 				    prog, NGATEWAYS);
    516 				exit(1);
    517 			}
    518 			getaddr(gwlist + lsrr, optarg);
    519 			++lsrr;
    520 			break;
    521 
    522 		case 'i':
    523 			device = optarg;
    524 			break;
    525 
    526 		case 'I':
    527 			++useicmp;
    528 			break;
    529 
    530 		case 'l':
    531 			++ttl_flag;
    532 			break;
    533 
    534 		case 'm':
    535 			max_ttl = str2val(optarg, "max ttl", 1, 255);
    536 			break;
    537 
    538 		case 'M':
    539 			Mflag = 1;
    540 			break;
    541 
    542 		case 'n':
    543 			++nflag;
    544 			break;
    545 
    546 		case 'p':
    547 			port = str2val(optarg, "port", 1, -1);
    548 			break;
    549 
    550 		case 'q':
    551 			nprobes = str2val(optarg, "nprobes", 1, -1);
    552 			break;
    553 
    554 		case 'r':
    555 			options |= SO_DONTROUTE;
    556 			break;
    557 
    558 		case 's':
    559 			/*
    560 			 * set the ip source address of the outbound
    561 			 * probe (e.g., on a multi-homed host).
    562 			 */
    563 			source = optarg;
    564 			break;
    565 
    566 		case 't':
    567 			tos = str2val(optarg, "tos", 0, 255);
    568 			++settos;
    569 			break;
    570 
    571 		case 'v':
    572 			++verbose;
    573 			break;
    574 
    575 		case 'x':
    576 			docksum = (docksum == 0);
    577 			break;
    578 
    579 		case 'w':
    580 			waittime = str2val(optarg, "wait time", 2, 24 * 3600);
    581 			break;
    582 
    583 		case 'P':
    584 			off = IP_DF;
    585 			mtudisc = 1;
    586 			break;
    587 
    588 		default:
    589 			usage();
    590 		}
    591 
    592 	if (first_ttl > max_ttl) {
    593 		Fprintf(stderr,
    594 		    "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
    595 		    prog, first_ttl, max_ttl);
    596 		exit(1);
    597 	}
    598 
    599 	if (!docksum)
    600 		Fprintf(stderr, "%s: Warning: ckecksums disabled\n", prog);
    601 
    602 	if (lsrr > 0)
    603 		optlen = (lsrr + 1) * sizeof(gwlist[0]);
    604 	minpacket = sizeof(*outip) + sizeof(struct outdata) + optlen;
    605 	if (useicmp)
    606 		minpacket += 8;			/* XXX magic number */
    607 	else
    608 		minpacket += sizeof(*outudp);
    609 	if (packlen == 0)
    610 		packlen = minpacket;		/* minimum sized packet */
    611 	else if (minpacket > packlen || packlen > maxpacket) {
    612 		Fprintf(stderr, "%s: packet size must be %d <= s <= %d\n",
    613 		    prog, minpacket, maxpacket);
    614 		exit(1);
    615 	}
    616 
    617 	if (mtudisc)
    618 		packlen = *mtuptr++;
    619 
    620 	/* Process destination and optional packet size */
    621 	switch (argc - optind) {
    622 
    623 	case 2:
    624 		packlen = str2val(argv[optind + 1],
    625 		    "packet length", minpacket, -1);
    626 		/* Fall through */
    627 
    628 	case 1:
    629 		hostname = argv[optind];
    630 		hi = gethostinfo(hostname);
    631 		setsin(to, hi->addrs[0]);
    632 		if (hi->n > 1)
    633 			Fprintf(stderr,
    634 		    "%s: Warning: %s has multiple addresses; using %s\n",
    635 				prog, hostname, inet_ntoa(to->sin_addr));
    636 		hostname = hi->name;
    637 		hi->name = NULL;
    638 		freehostinfo(hi);
    639 		break;
    640 
    641 	default:
    642 		usage();
    643 	}
    644 
    645 #ifdef HAVE_SETLINEBUF
    646 	setlinebuf (stdout);
    647 #else
    648 	setvbuf(stdout, NULL, _IOLBF, 0);
    649 #endif
    650 
    651 	outip = (struct ip *)malloc((unsigned)packlen);
    652 	if (outip == NULL) {
    653 		Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
    654 		exit(1);
    655 	}
    656 	memset((char *)outip, 0, packlen);
    657 
    658 	outip->ip_v = IPVERSION;
    659 	if (settos)
    660 		outip->ip_tos = tos;
    661 #ifdef BYTESWAP_IP_LEN
    662 	outip->ip_len = htons(packlen);
    663 #else
    664 	outip->ip_len = packlen;
    665 #endif
    666 	outip->ip_off = off;
    667 	outp = (u_char *)(outip + 1);
    668 #ifdef HAVE_RAW_OPTIONS
    669 	if (lsrr > 0) {
    670 		u_char *optlist;
    671 
    672 		optlist = outp;
    673 		outp += optlen;
    674 
    675 		/* final hop */
    676 		gwlist[lsrr] = to->sin_addr.s_addr;
    677 
    678 		outip->ip_dst.s_addr = gwlist[0];
    679 
    680 		/* force 4 byte alignment */
    681 		optlist[0] = IPOPT_NOP;
    682 		/* loose source route option */
    683 		optlist[1] = IPOPT_LSRR;
    684 		i = lsrr * sizeof(gwlist[0]);
    685 		optlist[2] = i + 3;
    686 		/* Pointer to LSRR addresses */
    687 		optlist[3] = IPOPT_MINOFF;
    688 		memcpy(optlist + 4, gwlist + 1, i);
    689 	} else
    690 #endif
    691 		outip->ip_dst = to->sin_addr;
    692 
    693 	outip->ip_hl = (outp - (u_char *)outip) >> 2;
    694 	ident = htons(arc4random() & 0xffff) | 0x8000;
    695 	if (useicmp) {
    696 		outip->ip_p = IPPROTO_ICMP;
    697 
    698 		outicmp = (struct icmp *)outp;
    699 		outicmp->icmp_type = ICMP_ECHO;
    700 		outicmp->icmp_id = htons(ident);
    701 
    702 		outmark = outp + 8;	/* XXX magic number */
    703 	} else {
    704 		outip->ip_p = IPPROTO_UDP;
    705 
    706 		outudp = (struct udphdr *)outp;
    707 		outudp->uh_sport = htons(ident);
    708 		outudp->uh_ulen =
    709 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
    710 		outmark = outudp + 1;
    711 	}
    712 
    713 	if (options & SO_DEBUG)
    714 		(void)prog_setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
    715 		    sizeof(on));
    716 #ifdef IPSEC
    717 #ifdef IPSEC_POLICY_IPSEC
    718 	/*
    719 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    720 	 * turned off.
    721 	 */
    722 	if (setpolicy(s, "in bypass") < 0)
    723 		exit(1);
    724 	if (setpolicy(s, "out bypass") < 0)
    725 		exit(1);
    726 #else
    727     {
    728 	int level = IPSEC_LEVEL_AVAIL;
    729 
    730 	(void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    731 		sizeof(level));
    732 	(void)prog_setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    733 		sizeof(level));
    734 #ifdef IP_AUTH_TRANS_LEVEL
    735 	(void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    736 		sizeof(level));
    737 #else
    738 	(void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    739 		sizeof(level));
    740 #endif
    741 #ifdef IP_AUTH_NETWORK_LEVEL
    742 	(void)prog_setsockopt(s, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    743 		sizeof(level));
    744 #endif
    745     }
    746 #endif /*IPSEC_POLICY_IPSEC*/
    747 #endif /*IPSEC*/
    748 
    749 #ifdef IPSEC
    750 #ifdef IPSEC_POLICY_IPSEC
    751 	/*
    752 	 * do not raise error even if setsockopt fails, kernel may have ipsec
    753 	 * turned off.
    754 	 */
    755 	if (setpolicy(sndsock, "in bypass") < 0)
    756 		exit(1);
    757 	if (setpolicy(sndsock, "out bypass") < 0)
    758 		exit(1);
    759 #else
    760     {
    761 	int level = IPSEC_LEVEL_BYPASS;
    762 
    763 	(void)prog_setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    764 		sizeof(level));
    765 	(void)prog_setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    766 		sizeof(level));
    767 #ifdef IP_AUTH_TRANS_LEVEL
    768 	(void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    769 		sizeof(level));
    770 #else
    771 	(void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    772 		sizeof(level));
    773 #endif
    774 #ifdef IP_AUTH_NETWORK_LEVEL
    775 	(void)prog_setsockopt(sndsock, IPPROTO_IP, IP_AUTH_NETWORK_LEVEL, &level,
    776 		sizeof(level));
    777 #endif
    778     }
    779 #endif /*IPSEC_POLICY_IPSEC*/
    780 #endif /*IPSEC*/
    781 
    782 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
    783 	if (lsrr > 0) {
    784 		u_char optlist[MAX_IPOPTLEN];
    785 
    786 		/* final hop */
    787 		gwlist[lsrr] = to->sin_addr.s_addr;
    788 		++lsrr;
    789 
    790 		/* force 4 byte alignment */
    791 		optlist[0] = IPOPT_NOP;
    792 		/* loose source route option */
    793 		optlist[1] = IPOPT_LSRR;
    794 		i = lsrr * sizeof(gwlist[0]);
    795 		optlist[2] = i + 3;
    796 		/* Pointer to LSRR addresses */
    797 		optlist[3] = IPOPT_MINOFF;
    798 		memcpy(optlist + 4, gwlist, i);
    799 
    800 		if ((prog_setsockopt(sndsock, IPPROTO_IP, IP_OPTIONS, optlist,
    801 		    i + sizeof(gwlist[0]))) < 0) {
    802 			Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
    803 			    prog, strerror(errno));
    804 			exit(1);
    805 		    }
    806 	}
    807 #endif
    808 
    809 #ifdef SO_SNDBUF
    810 	if (prog_setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
    811 	    sizeof(packlen)) < 0) {
    812 		Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
    813 		exit(1);
    814 	}
    815 #endif
    816 #ifdef IP_HDRINCL
    817 	if (prog_setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    818 	    sizeof(on)) < 0) {
    819 		Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
    820 		exit(1);
    821 	}
    822 #else
    823 #ifdef IP_TOS
    824 	if (settos && prog_setsockopt(sndsock, IPPROTO_IP, IP_TOS,
    825 	    (char *)&tos, sizeof(tos)) < 0) {
    826 		Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
    827 		    prog, tos, strerror(errno));
    828 		exit(1);
    829 	}
    830 #endif
    831 #endif
    832 	if (options & SO_DEBUG)
    833 		(void)prog_setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
    834 		    sizeof(on));
    835 	if (options & SO_DONTROUTE)
    836 		(void)prog_setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
    837 		    sizeof(on));
    838 
    839 	/* Get the interface address list */
    840 	n = ifaddrlist(&al, errbuf, sizeof errbuf);
    841 	al2 = al;
    842 	if (n < 0) {
    843 		Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
    844 		exit(1);
    845 	}
    846 	if (n == 0) {
    847 		Fprintf(stderr,
    848 		    "%s: Can't find any network interfaces\n", prog);
    849 		exit(1);
    850 	}
    851 
    852 	/* Look for a specific device */
    853 	if (device != NULL) {
    854 		for (i = n; i > 0; --i, ++al2)
    855 			if (strcmp(device, al2->device) == 0)
    856 				break;
    857 		if (i <= 0) {
    858 			Fprintf(stderr, "%s: Can't find interface %s\n",
    859 			    prog, device);
    860 			exit(1);
    861 		}
    862 	}
    863 
    864 	/* Determine our source address */
    865 	if (source == NULL) {
    866 		/*
    867 		 * If a device was specified, use the interface address.
    868 		 * Otherwise, use the first interface found.
    869 		 * Warn if there are more than one.
    870 		 */
    871 		setsin(from, al2->addr);
    872 		if (n > 1 && device == NULL && !find_local_ip(from, to)) {
    873 			Fprintf(stderr,
    874 		    "%s: Warning: Multiple interfaces found; using %s @ %s\n",
    875 			    prog, inet_ntoa(from->sin_addr), al2->device);
    876 		}
    877 	} else {
    878 		hi = gethostinfo(source);
    879 		source = hi->name;
    880 		hi->name = NULL;
    881 		if (device == NULL) {
    882 			/*
    883 			 * Use the first interface found.
    884 			 * Warn if there are more than one.
    885 			 */
    886 			setsin(from, hi->addrs[0]);
    887 			if (hi->n > 1)
    888 				Fprintf(stderr,
    889 			"%s: Warning: %s has multiple addresses; using %s\n",
    890 				    prog, source, inet_ntoa(from->sin_addr));
    891 		} else {
    892 			/*
    893 			 * Make sure the source specified matches the
    894 			 * interface address.
    895 			 */
    896 			for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
    897 				if (*ap == al2->addr)
    898 					break;
    899 			if (i <= 0) {
    900 				Fprintf(stderr,
    901 				    "%s: %s is not on interface %s\n",
    902 				    prog, source, device);
    903 				exit(1);
    904 			}
    905 			setsin(from, *ap);
    906 		}
    907 		freehostinfo(hi);
    908 	}
    909 
    910 	/*
    911 	 * If not root, make sure source address matches a local interface.
    912 	 * (The list of addresses produced by ifaddrlist() automatically
    913 	 * excludes interfaces that are marked down and/or loopback.)
    914 	 */
    915 	if (getuid())  {
    916 		al2 = al;
    917 		for (i = n; i > 0; --i, ++al2)
    918 			if (from->sin_addr.s_addr == al2->addr)
    919 			    break;
    920 		if (i <= 0) {
    921 			Fprintf(stderr, "%s: %s is not a valid local address "
    922 			    "and you are not superuser.\n", prog,
    923 			    inet_ntoa(from->sin_addr));
    924 			exit(1);
    925 		}
    926 	}
    927 
    928 	outip->ip_src = from->sin_addr;
    929 #ifndef IP_HDRINCL
    930 	if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
    931 		Fprintf(stderr, "%s: bind: %s\n",
    932 		    prog, strerror(errno));
    933 		exit (1);
    934 	}
    935 #endif
    936 
    937 	if (as_path) {
    938 		asn = as_setup(as_server);
    939 		if (asn == NULL) {
    940 			Fprintf(stderr, "%s: as_setup failed, AS# lookups disabled\n",
    941 				prog);
    942 			(void)fflush(stderr);
    943 			as_path = 0;
    944 		}
    945 	}
    946 
    947 	setuid(getuid());
    948 	Fprintf(stderr, "%s to %s (%s)",
    949 	    prog, hostname, inet_ntoa(to->sin_addr));
    950 	if (source)
    951 		Fprintf(stderr, " from %s", source);
    952 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
    953 	(void)fflush(stderr);
    954 
    955 	for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
    956 		u_int32_t lastaddr = 0;
    957 		int got_there = 0;
    958 		int unreachable = 0;
    959 
    960 again:
    961 		printed_ttl = 0;
    962 		for (probe = 0; probe < nprobes; ++probe) {
    963 			int cc;
    964 			struct timeval t1, t2;
    965 			struct ip *ip;
    966 			(void)gettimeofday(&t1, NULL);
    967 			if (!useicmp && htons(port + seq + 1) == 0)
    968 				seq++;
    969 			send_probe(++seq, ttl, &t1);
    970 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
    971 				(void)gettimeofday(&t2, NULL);
    972 				/*
    973 				 * Since we'll be receiving all ICMP
    974 				 * messages to this host above, we may
    975 				 * never end up with cc=0, so we need
    976 				 * an additional termination check.
    977 				 */
    978 				if (t2.tv_sec - t1.tv_sec > waittime) {
    979 					cc = 0;
    980 					break;
    981 				}
    982 				i = packet_ok(packet, cc, from, seq);
    983 				/* Skip short packet */
    984 				if (i == 0)
    985 					continue;
    986 				if (from->sin_addr.s_addr != lastaddr) {
    987 					print(packet, cc, from);
    988 					lastaddr = from->sin_addr.s_addr;
    989 				}
    990 				ip = (struct ip *)packet;
    991 				Printf("  %.3f ms", deltaT(&t1, &t2));
    992 				if (ttl_flag)
    993 					Printf(" (ttl = %d)", ip->ip_ttl);
    994 				if (i == -2) {
    995 #ifndef ARCHAIC
    996 					if (ip->ip_ttl <= 1)
    997 						Printf(" !");
    998 #endif
    999 					++got_there;
   1000 					break;
   1001 				}
   1002 
   1003 				/* time exceeded in transit */
   1004 				if (i == -1)
   1005 					break;
   1006 				code = i - 1;
   1007 				switch (code) {
   1008 
   1009 				case ICMP_UNREACH_PORT:
   1010 #ifndef ARCHAIC
   1011 					if (ip->ip_ttl <= 1)
   1012 						Printf(" !");
   1013 #endif
   1014 					++got_there;
   1015 					break;
   1016 
   1017 				case ICMP_UNREACH_NET:
   1018 					++unreachable;
   1019 					Printf(" !N");
   1020 					break;
   1021 
   1022 				case ICMP_UNREACH_HOST:
   1023 					++unreachable;
   1024 					Printf(" !H");
   1025 					break;
   1026 
   1027 				case ICMP_UNREACH_PROTOCOL:
   1028 					++got_there;
   1029 					Printf(" !P");
   1030 					break;
   1031 
   1032 				case ICMP_UNREACH_NEEDFRAG:
   1033 					if (mtudisc) {
   1034 						frag_err();
   1035 						goto again;
   1036 					} else {
   1037 						++unreachable;
   1038 						Printf(" !F");
   1039 					}
   1040 					break;
   1041 
   1042 				case ICMP_UNREACH_SRCFAIL:
   1043 					++unreachable;
   1044 					Printf(" !S");
   1045 					break;
   1046 
   1047 /* rfc1716 */
   1048 #ifndef ICMP_UNREACH_FILTER_PROHIB
   1049 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
   1050 #endif
   1051 				case ICMP_UNREACH_FILTER_PROHIB:
   1052 					++unreachable;
   1053 					Printf(" !X");
   1054 					break;
   1055 
   1056 				default:
   1057 					++unreachable;
   1058 					Printf(" !<%d>", code);
   1059 					break;
   1060 				}
   1061 				break;
   1062 			}
   1063 			if (cc == 0)
   1064 				Printf(" *");
   1065 			else if (cc && probe == nprobes - 1 && Mflag)
   1066 				decode_extensions(packet, cc);
   1067 			(void)fflush(stdout);
   1068 		}
   1069 		putchar('\n');
   1070 		if (got_there ||
   1071 		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
   1072 			break;
   1073 	}
   1074 
   1075 	if (as_path)
   1076 		as_shutdown(asn);
   1077 
   1078 	exit(0);
   1079 }
   1080 
   1081 static ssize_t
   1082 wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
   1083 {
   1084 	struct pollfd set[1];
   1085 	struct timeval now, wait;
   1086 	ssize_t cc = 0;
   1087 	socklen_t fromlen = sizeof(*fromp);
   1088 	int retval;
   1089 
   1090 	set[0].fd = sock;
   1091 	set[0].events = POLLIN;
   1092 
   1093 	wait.tv_sec = tp->tv_sec + waittime;
   1094 	wait.tv_usec = tp->tv_usec;
   1095 	(void)gettimeofday(&now, NULL);
   1096 	tvsub(&wait, &now);
   1097 
   1098 	if (wait.tv_sec < 0) {
   1099 		wait.tv_sec = 0;
   1100 		wait.tv_usec = 0;
   1101 	}
   1102 
   1103 	retval = prog_poll(set, 1, wait.tv_sec * 1000 + wait.tv_usec / 1000);
   1104 	if (retval < 0)  {
   1105 		/* If we continue, we probably just flood the remote host. */
   1106 		Fprintf(stderr, "%s: poll: %s\n", prog, strerror(errno));
   1107 		exit(1);
   1108 	}
   1109 	if (retval > 0)  {
   1110 		cc = prog_recvfrom(s, (char *)packet, sizeof(packet), 0,
   1111 			    (struct sockaddr *)fromp, &fromlen);
   1112 	}
   1113 
   1114 	return cc;
   1115 }
   1116 
   1117 static void
   1118 decode_extensions(unsigned char *buf, int ip_len)
   1119 {
   1120         struct icmp_ext_cmn_hdr *cmn_hdr;
   1121         struct icmp_ext_obj_hdr *obj_hdr;
   1122         union {
   1123                 struct mpls_header mpls;
   1124                 uint32_t mpls_h;
   1125         } mpls;
   1126         size_t datalen, obj_len;
   1127         struct ip *ip;
   1128 
   1129         ip = (struct ip *)buf;
   1130 
   1131         if (ip_len < (int)((ip->ip_hl << 2) + ICMP_EXT_OFFSET +
   1132 	    sizeof(struct icmp_ext_cmn_hdr))) {
   1133 		/*
   1134 		 * No support for ICMP extensions on this host
   1135 		 */
   1136 		return;
   1137         }
   1138 
   1139         /*
   1140          * Move forward to the start of the ICMP extensions, if present
   1141          */
   1142         buf += (ip->ip_hl << 2) + ICMP_EXT_OFFSET;
   1143         cmn_hdr = (struct icmp_ext_cmn_hdr *)buf;
   1144 
   1145         if (cmn_hdr->version != ICMP_EXT_VERSION) {
   1146 		/*
   1147 		 * Unknown version
   1148 		 */
   1149 		return;
   1150         }
   1151 
   1152         datalen = ip_len - ((u_char *)cmn_hdr - (u_char *)ip);
   1153 
   1154         /*
   1155          * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
   1156          * done by sender.
   1157          *
   1158         * If the checksum is ok, we'll get 0, as the checksum is calculated
   1159          * with the checksum field being 0'd.
   1160          */
   1161         if (ntohs(cmn_hdr->checksum) &&
   1162             in_cksum((u_short *)cmn_hdr, datalen)) {
   1163 
   1164             return;
   1165         }
   1166 
   1167         buf += sizeof(*cmn_hdr);
   1168         datalen -= sizeof(*cmn_hdr);
   1169 
   1170         while (datalen >= sizeof(struct icmp_ext_obj_hdr)) {
   1171 		obj_hdr = (struct icmp_ext_obj_hdr *)buf;
   1172 		obj_len = ntohs(obj_hdr->length);
   1173 
   1174 		/*
   1175 		 * Sanity check the length field
   1176 		 */
   1177 		if (obj_len > datalen)
   1178 			return;
   1179 
   1180 		datalen -= obj_len;
   1181 
   1182 		/*
   1183 		 * Move past the object header
   1184 		 */
   1185 		buf += sizeof(struct icmp_ext_obj_hdr);
   1186 		obj_len -= sizeof(struct icmp_ext_obj_hdr);
   1187 
   1188 		switch (obj_hdr->class_num) {
   1189 		case MPLS_STACK_ENTRY_CLASS:
   1190 			switch (obj_hdr->c_type) {
   1191 			case MPLS_STACK_ENTRY_C_TYPE:
   1192 				while (obj_len >= sizeof(uint32_t)) {
   1193 					mpls.mpls_h = ntohl(*(uint32_t *)buf);
   1194 
   1195 					buf += sizeof(uint32_t);
   1196 					obj_len -= sizeof(uint32_t);
   1197 
   1198 					printf(" [MPLS: Label %d Exp %d]",
   1199 					    mpls.mpls.label, mpls.mpls.exp);
   1200 				}
   1201 				if (obj_len > 0) {
   1202 					/*
   1203 					 * Something went wrong, and we're at
   1204 					 * a unknown offset into the packet,
   1205 					 * ditch the rest of it.
   1206 					 */
   1207 					return;
   1208 				}
   1209 				break;
   1210 			default:
   1211 				/*
   1212 				 * Unknown object, skip past it
   1213 				 */
   1214 				buf += ntohs(obj_hdr->length) -
   1215 				    sizeof(struct icmp_ext_obj_hdr);
   1216 				break;
   1217 			}
   1218 			break;
   1219 
   1220 		default:
   1221 			/*
   1222 			 * Unknown object, skip past it
   1223 			 */
   1224 			buf += ntohs(obj_hdr->length) -
   1225 			    sizeof(struct icmp_ext_obj_hdr);
   1226 			break;
   1227 		}
   1228 	}
   1229 }
   1230 
   1231 static void
   1232 dump_packet(void)
   1233 {
   1234 	u_char *p;
   1235 	int i;
   1236 
   1237 	Fprintf(stderr, "packet data:");
   1238 
   1239 #ifdef __hpux
   1240 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
   1241 	    i < packlen - (sizeof(*outip) + optlen); i++)
   1242 #else
   1243 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
   1244 #endif
   1245 	{
   1246 		if ((i % 24) == 0)
   1247 			Fprintf(stderr, "\n ");
   1248 		Fprintf(stderr, " %02x", *p++);
   1249 	}
   1250 	Fprintf(stderr, "\n");
   1251 }
   1252 
   1253 void
   1254 send_probe(int seq, int ttl, struct timeval *tp)
   1255 {
   1256 	int cc;
   1257 	struct udpiphdr * ui;
   1258 	int oldmtu = packlen;
   1259 
   1260 again:
   1261 #ifdef BYTESWAP_IP_LEN
   1262 	outip->ip_len = htons(packlen);
   1263 #else
   1264 	outip->ip_len = packlen;
   1265 #endif
   1266 	outip->ip_ttl = ttl;
   1267 #ifndef __hpux
   1268 	outip->ip_id = htons(ident + seq);
   1269 #endif
   1270 
   1271 	/*
   1272 	 * In most cases, the kernel will recalculate the ip checksum.
   1273 	 * But we must do it anyway so that the udp checksum comes out
   1274 	 * right.
   1275 	 */
   1276 	if (docksum) {
   1277 		outip->ip_sum =
   1278 		    in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
   1279 		if (outip->ip_sum == 0)
   1280 			outip->ip_sum = 0xffff;
   1281 	}
   1282 
   1283 	/* Payload */
   1284 	outsetup.seq = seq;
   1285 	outsetup.ttl = ttl;
   1286 	outsetup.tv.tv32_sec = htonl(tp->tv_sec);
   1287 	outsetup.tv.tv32_usec = htonl(tp->tv_usec);
   1288 	memcpy(outmark,&outsetup,sizeof(outsetup));
   1289 
   1290 	if (useicmp)
   1291 		outicmp->icmp_seq = htons(seq);
   1292 	else
   1293 		outudp->uh_dport = htons(port + seq);
   1294 
   1295 	/* (We can only do the checksum if we know our ip address) */
   1296 	if (docksum) {
   1297 		if (useicmp) {
   1298 			outicmp->icmp_cksum = 0;
   1299 			outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1300 			    packlen - (sizeof(*outip) + optlen));
   1301 			if (outicmp->icmp_cksum == 0)
   1302 				outicmp->icmp_cksum = 0xffff;
   1303 		} else {
   1304 			u_int16_t sum;
   1305 			struct {
   1306 				struct in_addr src;
   1307 				struct in_addr dst;
   1308 				u_int8_t zero;
   1309 				u_int8_t protocol;
   1310 				u_int16_t len;
   1311 			} __packed phdr;
   1312 
   1313 			/* Checksum */
   1314 			ui = (struct udpiphdr *)outip;
   1315 			memset(&phdr, 0, sizeof(phdr));
   1316 			phdr.src = ui->ui_src;
   1317 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
   1318 			phdr.protocol = ui->ui_pr;
   1319 			phdr.len = outudp->uh_ulen;
   1320 			outudp->uh_sum = 0;
   1321 			sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
   1322 			sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
   1323 			outudp->uh_sum = ~sum;
   1324 			if (outudp->uh_sum == 0)
   1325 				outudp->uh_sum = 0xffff;
   1326 		}
   1327 	}
   1328 
   1329 	/* XXX undocumented debugging hack */
   1330 	if (verbose > 1) {
   1331 		const u_int16_t *sp;
   1332 		int nshorts, i;
   1333 
   1334 		sp = (u_int16_t *)outip;
   1335 		nshorts = (u_int)packlen / sizeof(u_int16_t);
   1336 		i = 0;
   1337 		Printf("[ %d bytes", packlen);
   1338 		while (--nshorts >= 0) {
   1339 			if ((i++ % 8) == 0)
   1340 				Printf("\n\t");
   1341 			Printf(" %04x", ntohs(*sp++));
   1342 		}
   1343 		if (packlen & 1) {
   1344 			if ((i % 8) == 0)
   1345 				Printf("\n\t");
   1346 			Printf(" %02x", *(const u_char *)sp);
   1347 		}
   1348 		Printf("]\n");
   1349 	}
   1350 
   1351 #if !defined(IP_HDRINCL) && defined(IP_TTL)
   1352 	if (prog_setsockopt(sndsock, IPPROTO_IP, IP_TTL,
   1353 	    (char *)&ttl, sizeof(ttl)) < 0) {
   1354 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
   1355 		    prog, ttl, strerror(errno));
   1356 		exit(1);
   1357 	}
   1358 #endif
   1359 	if (dump)
   1360 		dump_packet();
   1361 
   1362 #ifdef __hpux
   1363 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
   1364 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
   1365 	if (cc > 0)
   1366 		cc += sizeof(*outip) + optlen;
   1367 #else
   1368 	cc = prog_sendto(sndsock, (char *)outip,
   1369 	    packlen, 0, &whereto, sizeof(whereto));
   1370 #endif
   1371 	if (cc < 0 || cc != packlen)  {
   1372 		if (cc < 0) {
   1373 			/*
   1374 			 * An errno of EMSGSIZE means we're writing too big a
   1375 			 * datagram for the interface.  We have to just
   1376 			 * decrease the packet size until we find one that
   1377 			 * works.
   1378 			 *
   1379 			 * XXX maybe we should try to read the outgoing if's
   1380 			 * mtu?
   1381 			 */
   1382 			if (errno == EMSGSIZE) {
   1383 				packlen = *mtuptr++;
   1384 				resize_packet();
   1385 				goto again;
   1386 			} else
   1387 				Fprintf(stderr, "%s: sendto: %s\n",
   1388 				    prog, strerror(errno));
   1389 		}
   1390 
   1391 		Printf("%s: wrote %s %d chars, ret=%d\n",
   1392 		    prog, hostname, packlen, cc);
   1393 		(void)fflush(stdout);
   1394 	}
   1395 	if (oldmtu != packlen) {
   1396 		Printf("message too big, "
   1397 		    "trying new MTU = %d\n", packlen);
   1398 		printed_ttl = 0;
   1399 	}
   1400 	if (!printed_ttl) {
   1401 		Printf("%2d ", ttl);
   1402 		printed_ttl = 1;
   1403 	}
   1404 
   1405 }
   1406 
   1407 static double
   1408 deltaT(struct timeval *t1p, struct timeval *t2p)
   1409 {
   1410 	double dt;
   1411 
   1412 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
   1413 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
   1414 	return (dt);
   1415 }
   1416 
   1417 /*
   1418  * Convert an ICMP "type" field to a printable string.
   1419  */
   1420 static const char *
   1421 pr_type(u_char t)
   1422 {
   1423 	static const char *ttab[] = {
   1424 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
   1425 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
   1426 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
   1427 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
   1428 	"Info Reply"
   1429 	};
   1430 
   1431 	if (t > 16)
   1432 		return "OUT-OF-RANGE";
   1433 
   1434 	return ttab[t];
   1435 }
   1436 
   1437 static int
   1438 packet_ok(u_char *buf, ssize_t cc, struct sockaddr_in *from, int seq)
   1439 {
   1440 	struct icmp *icp;
   1441 	u_char type, code;
   1442 	int hlen;
   1443 #ifndef ARCHAIC
   1444 	struct ip *ip;
   1445 
   1446 	ip = (struct ip *) buf;
   1447 	hlen = ip->ip_hl << 2;
   1448 	if (cc < hlen + ICMP_MINLEN) {
   1449 		if (verbose)
   1450 			Printf("packet too short (%zd bytes) from %s\n", cc,
   1451 				inet_ntoa(from->sin_addr));
   1452 		return (0);
   1453 	}
   1454 	cc -= hlen;
   1455 	icp = (struct icmp *)(buf + hlen);
   1456 #else
   1457 	icp = (struct icmp *)buf;
   1458 #endif
   1459 	type = icp->icmp_type;
   1460 	code = icp->icmp_code;
   1461 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
   1462 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
   1463 		struct ip *hip;
   1464 		struct udphdr *up;
   1465 		struct icmp *hicmp;
   1466 
   1467 		hip = &icp->icmp_ip;
   1468 		hlen = hip->ip_hl << 2;
   1469 
   1470 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
   1471 
   1472 		if (useicmp) {
   1473 			/* XXX */
   1474 			if (type == ICMP_ECHOREPLY &&
   1475 			    icp->icmp_id == htons(ident) &&
   1476 			    icp->icmp_seq == htons(seq))
   1477 				return (-2);
   1478 
   1479 			hicmp = (struct icmp *)((u_char *)hip + hlen);
   1480 			/* XXX 8 is a magic number */
   1481 			if (hlen + 8 <= cc &&
   1482 			    hip->ip_p == IPPROTO_ICMP &&
   1483 			    hicmp->icmp_id == htons(ident) &&
   1484 			    hicmp->icmp_seq == htons(seq))
   1485 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1486 		} else {
   1487 			up = (struct udphdr *)((u_char *)hip + hlen);
   1488 			/* XXX 8 is a magic number */
   1489 			if (hlen + 12 <= cc &&
   1490 			    hip->ip_p == IPPROTO_UDP &&
   1491 			    up->uh_sport == htons(ident) &&
   1492 			    up->uh_dport == htons(port + seq))
   1493 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1494 		}
   1495 	}
   1496 #ifndef ARCHAIC
   1497 	if (verbose) {
   1498 		int i;
   1499 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
   1500 
   1501 		Printf("\n%zd bytes from %s to ", cc, inet_ntoa(from->sin_addr));
   1502 		Printf("%s: icmp type %d (%s) code %d\n",
   1503 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
   1504 		for (i = 4; i < cc ; i += sizeof(*lp))
   1505 			Printf("%2d: x%8.8x\n", i, *lp++);
   1506 	}
   1507 #endif
   1508 	return(0);
   1509 }
   1510 
   1511 static void
   1512 resize_packet(void)
   1513 {
   1514 	if (useicmp) {
   1515 		outicmp->icmp_cksum = 0;
   1516 		outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1517 		    packlen - (sizeof(*outip) + optlen));
   1518 		if (outicmp->icmp_cksum == 0)
   1519 			outicmp->icmp_cksum = 0xffff;
   1520 	} else {
   1521 		outudp->uh_ulen =
   1522 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
   1523 	}
   1524 }
   1525 
   1526 static void
   1527 print(u_char *buf, int cc, struct sockaddr_in *from)
   1528 {
   1529 	struct ip *ip;
   1530 	int hlen;
   1531 	char addr[INET_ADDRSTRLEN];
   1532 
   1533 	ip = (struct ip *) buf;
   1534 	hlen = ip->ip_hl << 2;
   1535 	cc -= hlen;
   1536 
   1537 	strlcpy(addr, inet_ntoa(from->sin_addr), sizeof(addr));
   1538 
   1539 	if (as_path)
   1540 		Printf(" [AS%u]", as_lookup(asn, addr, AF_INET));
   1541 
   1542 	if (nflag)
   1543 		Printf(" %s", addr);
   1544 	else
   1545 		Printf(" %s (%s)", inetname(from->sin_addr), addr);
   1546 
   1547 	if (verbose)
   1548 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
   1549 }
   1550 
   1551 static u_int16_t
   1552 in_cksum(u_int16_t *addr, int len)
   1553 {
   1554 
   1555 	return ~in_cksum2(0, addr, len);
   1556 }
   1557 
   1558 /*
   1559  * Checksum routine for Internet Protocol family headers (C Version)
   1560  */
   1561 static u_int16_t
   1562 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
   1563 {
   1564 	int nleft = len;
   1565 	u_int16_t *w = addr;
   1566 	union {
   1567 		u_int16_t w;
   1568 		u_int8_t b[2];
   1569 	} answer;
   1570 	int32_t sum = seed;
   1571 
   1572 	/*
   1573 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
   1574 	 *  we add sequential 16 bit words to it, and at the end, fold
   1575 	 *  back all the carry bits from the top 16 bits into the lower
   1576 	 *  16 bits.
   1577 	 */
   1578 	while (nleft > 1)  {
   1579 		sum += *w++;
   1580 		nleft -= 2;
   1581 	}
   1582 
   1583 	/* mop up an odd byte, if necessary */
   1584 	if (nleft == 1) {
   1585 		answer.b[0] = *(u_char *)w;
   1586 		answer.b[1] = 0;
   1587 		sum += answer.w;
   1588 	}
   1589 
   1590 	/*
   1591 	 * add back carry outs from top 16 bits to low 16 bits
   1592 	 */
   1593 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
   1594 	sum += (sum >> 16);			/* add carry */
   1595 	answer.w = sum;				/* truncate to 16 bits */
   1596 	return (answer.w);
   1597 }
   1598 
   1599 /*
   1600  * Subtract 2 timeval structs:  out = out - in.
   1601  * Out is assumed to be >= in.
   1602  */
   1603 static void
   1604 tvsub(struct timeval *out, struct timeval *in)
   1605 {
   1606 
   1607 	if ((out->tv_usec -= in->tv_usec) < 0)   {
   1608 		--out->tv_sec;
   1609 		out->tv_usec += 1000000;
   1610 	}
   1611 	out->tv_sec -= in->tv_sec;
   1612 }
   1613 
   1614 /*
   1615  * Construct an Internet address representation.
   1616  * If the nflag has been supplied, give
   1617  * numeric value, otherwise try for symbolic name.
   1618  */
   1619 static char *
   1620 inetname(struct in_addr in)
   1621 {
   1622 	char *cp;
   1623 	struct hostent *hp;
   1624 	static int first = 1;
   1625 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
   1626 
   1627 	if (first && !nflag) {
   1628 		int rv;
   1629 
   1630 		first = 0;
   1631 		rv = gethostname(domain, sizeof domain);
   1632 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
   1633 			(void)strlcpy(domain, cp + 1, sizeof(domain));
   1634 		} else
   1635 			domain[0] = '\0';
   1636 	}
   1637 	if (!nflag && in.s_addr != INADDR_ANY) {
   1638 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
   1639 		if (hp != NULL) {
   1640 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
   1641 			    strcmp(cp + 1, domain) == 0)
   1642 				*cp = '\0';
   1643 			(void)strlcpy(line, hp->h_name, sizeof(line));
   1644 			return (line);
   1645 		}
   1646 	}
   1647 	return (inet_ntoa(in));
   1648 }
   1649 
   1650 static struct hostinfo *
   1651 gethostinfo(char *hname)
   1652 {
   1653 	int n;
   1654 	struct hostent *hp;
   1655 	struct hostinfo *hi;
   1656 	char **p;
   1657 	u_int32_t *ap;
   1658 	struct in_addr addr;
   1659 
   1660 	hi = calloc(1, sizeof(*hi));
   1661 	if (hi == NULL) {
   1662 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1663 		exit(1);
   1664 	}
   1665 	if (inet_aton(hname, &addr) != 0) {
   1666 		hi->name = strdup(hname);
   1667 		if (!hi->name) {
   1668 			Fprintf(stderr, "%s: strdup %s\n", prog,
   1669 			    strerror(errno));
   1670 			exit(1);
   1671 		}
   1672 		hi->n = 1;
   1673 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
   1674 		if (hi->addrs == NULL) {
   1675 			Fprintf(stderr, "%s: calloc %s\n",
   1676 			    prog, strerror(errno));
   1677 			exit(1);
   1678 		}
   1679 		hi->addrs[0] = addr.s_addr;
   1680 		return (hi);
   1681 	}
   1682 
   1683 	hp = gethostbyname(hname);
   1684 	if (hp == NULL) {
   1685 		Fprintf(stderr, "%s: unknown host %s\n", prog, hname);
   1686 		exit(1);
   1687 	}
   1688 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
   1689 		Fprintf(stderr, "%s: bad host %s\n", prog, hname);
   1690 		exit(1);
   1691 	}
   1692 	hi->name = strdup(hp->h_name);
   1693 	if (!hi->name) {
   1694 		Fprintf(stderr, "%s: strdup %s\n", prog, strerror(errno));
   1695 		exit(1);
   1696 	}
   1697 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
   1698 		continue;
   1699 	hi->n = n;
   1700 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
   1701 	if (hi->addrs == NULL) {
   1702 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1703 		exit(1);
   1704 	}
   1705 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
   1706 		memcpy(ap, *p, sizeof(*ap));
   1707 	return (hi);
   1708 }
   1709 
   1710 static void
   1711 freehostinfo(struct hostinfo *hi)
   1712 {
   1713 	if (hi->name != NULL) {
   1714 		free(hi->name);
   1715 		hi->name = NULL;
   1716 	}
   1717 	free((char *)hi->addrs);
   1718 	free((char *)hi);
   1719 }
   1720 
   1721 static void
   1722 getaddr(u_int32_t *ap, char *hname)
   1723 {
   1724 	struct hostinfo *hi;
   1725 
   1726 	hi = gethostinfo(hname);
   1727 	*ap = hi->addrs[0];
   1728 	freehostinfo(hi);
   1729 }
   1730 
   1731 static void
   1732 setsin(struct sockaddr_in *sin, u_int32_t addr)
   1733 {
   1734 
   1735 	memset(sin, 0, sizeof(*sin));
   1736 #ifdef HAVE_SOCKADDR_SA_LEN
   1737 	sin->sin_len = sizeof(*sin);
   1738 #endif
   1739 	sin->sin_family = AF_INET;
   1740 	sin->sin_addr.s_addr = addr;
   1741 }
   1742 
   1743 /* String to value with optional min and max. Handles decimal and hex. */
   1744 static int
   1745 str2val(const char *str, const char *what, int mi, int ma)
   1746 {
   1747 	const char *cp;
   1748 	long val;
   1749 	char *ep;
   1750 
   1751 	errno = 0;
   1752 	ep = NULL;
   1753 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
   1754 		cp = str + 2;
   1755 		val = strtol(cp, &ep, 16);
   1756 	} else
   1757 		val = strtol(str, &ep, 10);
   1758 	if (errno || str[0] == '\0' || *ep != '\0') {
   1759 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
   1760 		    prog, str, what);
   1761 		exit(1);
   1762 	}
   1763 	if (val < mi && mi >= 0) {
   1764 		if (mi == 0)
   1765 			Fprintf(stderr, "%s: %s must be >= %d\n",
   1766 			    prog, what, mi);
   1767 		else
   1768 			Fprintf(stderr, "%s: %s must be > %d\n",
   1769 			    prog, what, mi - 1);
   1770 		exit(1);
   1771 	}
   1772 	if (val > ma && ma >= 0) {
   1773 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
   1774 		exit(1);
   1775 	}
   1776 	return ((int)val);
   1777 }
   1778 
   1779 __dead void
   1780 usage(void)
   1781 {
   1782 	extern char version[];
   1783 
   1784 	Fprintf(stderr, "Version %s\n", version);
   1785 	Fprintf(stderr, "usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \
   1786 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
   1787 [-w waittime] [-A as_server] host [packetlen]\n",
   1788 	    prog);
   1789 	exit(1);
   1790 }
   1791 
   1792 /*
   1793  * Received ICMP unreachable (fragmentation required and DF set).
   1794  * If the ICMP error was from a "new" router, it'll contain the next-hop
   1795  * MTU that we should use next.  Otherwise we'll just keep going in the
   1796  * mtus[] table, trying until we hit a valid MTU.
   1797  */
   1798 
   1799 
   1800 void
   1801 frag_err()
   1802 {
   1803         int i;
   1804 
   1805         if (nextmtu > 0 && nextmtu < packlen) {
   1806                 Printf("\nfragmentation required and DF set, "
   1807 		     "next hop MTU = %d\n",
   1808                         nextmtu);
   1809                 packlen = nextmtu;
   1810                 for (i = 0; mtus[i] > 0; i++) {
   1811                         if (mtus[i] < nextmtu) {
   1812                                 mtuptr = &mtus[i];    /* next one to try */
   1813                                 break;
   1814                         }
   1815                 }
   1816         } else {
   1817                 Printf("\nfragmentation required and DF set. ");
   1818 		if (nextmtu)
   1819 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
   1820 			    nextmtu, packlen);
   1821                 packlen = *mtuptr++;
   1822 		Printf("Trying new MTU = %d\n", packlen);
   1823         }
   1824 	resize_packet();
   1825 }
   1826 
   1827 int
   1828 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
   1829 {
   1830 	int sock;
   1831 	struct sockaddr_in help;
   1832 	socklen_t help_len;
   1833 
   1834 	sock = prog_socket(AF_INET, SOCK_DGRAM, 0);
   1835 	if (sock < 0) return (0);
   1836 
   1837 	help.sin_family = AF_INET;
   1838 	/*
   1839 	 * At this point the port number doesn't matter
   1840 	 * since it only has to be greater than zero.
   1841 	 */
   1842 	help.sin_port = 42;
   1843 	help.sin_addr.s_addr = to->sin_addr.s_addr;
   1844 	if (prog_connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
   1845 		(void)prog_close(sock);
   1846 		return (0);
   1847 	}
   1848 
   1849 	help_len = sizeof(help);
   1850 	if (prog_getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
   1851 	    help_len != sizeof(help) ||
   1852 	    help.sin_addr.s_addr == INADDR_ANY) {
   1853 		(void)prog_close(sock);
   1854 		return (0);
   1855 	}
   1856 
   1857 	(void)prog_close(sock);
   1858 	setsin(from, help.sin_addr.s_addr);
   1859 	return (1);
   1860 }
   1861 
   1862 #ifdef IPSEC
   1863 #ifdef IPSEC_POLICY_IPSEC
   1864 static int
   1865 setpolicy(int so, const char *policy)
   1866 {
   1867 	char *buf;
   1868 
   1869 	buf = ipsec_set_policy(policy, strlen(policy));
   1870 	if (buf == NULL) {
   1871 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
   1872 		return -1;
   1873 	}
   1874 	(void)prog_setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
   1875 		buf, ipsec_get_policylen(buf));
   1876 
   1877 	free(buf);
   1878 
   1879 	return 0;
   1880 }
   1881 #endif
   1882 #endif
   1883 
   1884