Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.66
      1 /*	$NetBSD: traceroute.c,v 1.66 2006/09/24 11:34:35 elad 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.66 2006/09/24 11:34:35 elad Exp $");
     33 #endif
     34 #endif
     35 
     36 /*
     37  * traceroute host  - trace the route ip packets follow going to "host".
     38  *
     39  * Attempt to trace the route an ip packet would follow to some
     40  * internet host.  We find out intermediate hops by launching probe
     41  * packets with a small ttl (time to live) then listening for an
     42  * icmp "time exceeded" reply from a gateway.  We start our probes
     43  * with a ttl of one and increase by one until we get an icmp "port
     44  * unreachable" (which means we got to "host") or hit a max (which
     45  * defaults to 30 hops & can be changed with the -m flag).  Three
     46  * probes (change with -q flag) are sent at each ttl setting and a
     47  * line is printed showing the ttl, address of the gateway and
     48  * round trip time of each probe.  If the probe answers come from
     49  * different gateways, the address of each responding system will
     50  * be printed.  If there is no response within a 5 sec. timeout
     51  * interval (changed with the -w flag), a "*" is printed for that
     52  * probe.
     53  *
     54  * Probe packets are UDP format.  We don't want the destination
     55  * host to process them so the destination port is set to an
     56  * unlikely value (if some clod on the destination is using that
     57  * value, it can be changed with the -p flag).
     58  *
     59  * A sample use might be:
     60  *
     61  *     [yak 71]% traceroute nis.nsf.net.
     62  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
     63  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
     64  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     65  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     66  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
     67  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
     68  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
     69  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
     70  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
     71  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
     72  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
     73  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
     74  *
     75  * Note that lines 2 & 3 are the same.  This is due to a buggy
     76  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
     77  * packets with a zero ttl.
     78  *
     79  * A more interesting example is:
     80  *
     81  *     [yak 72]% traceroute allspice.lcs.mit.edu.
     82  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
     83  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
     84  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
     85  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
     86  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
     87  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
     88  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
     89  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
     90  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
     91  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
     92  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
     93  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
     94  *     12  * * *
     95  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
     96  *     14  * * *
     97  *     15  * * *
     98  *     16  * * *
     99  *     17  * * *
    100  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
    101  *
    102  * (I start to see why I'm having so much trouble with mail to
    103  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
    104  * either don't send ICMP "time exceeded" messages or send them
    105  * with a ttl too small to reach us.  14 - 17 are running the
    106  * MIT C Gateway code that doesn't send "time exceeded"s.  God
    107  * only knows what's going on with 12.
    108  *
    109  * The silent gateway 12 in the above may be the result of a bug in
    110  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
    111  * sends an unreachable message using whatever ttl remains in the
    112  * original datagram.  Since, for gateways, the remaining ttl is
    113  * zero, the icmp "time exceeded" is guaranteed to not make it back
    114  * to us.  The behavior of this bug is slightly more interesting
    115  * when it appears on the destination system:
    116  *
    117  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
    118  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
    119  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
    120  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
    121  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
    122  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
    123  *      7  * * *
    124  *      8  * * *
    125  *      9  * * *
    126  *     10  * * *
    127  *     11  * * *
    128  *     12  * * *
    129  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
    130  *
    131  * Notice that there are 12 "gateways" (13 is the final
    132  * destination) and exactly the last half of them are "missing".
    133  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
    134  * is using the ttl from our arriving datagram as the ttl in its
    135  * icmp reply.  So, the reply will time out on the return path
    136  * (with no notice sent to anyone since icmp's aren't sent for
    137  * icmp's) until we probe with a ttl that's at least twice the path
    138  * length.  I.e., rip is really only 7 hops away.  A reply that
    139  * returns with a ttl of 1 is a clue this problem exists.
    140  * Traceroute prints a "!" after the time if the ttl is <= 1.
    141  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
    142  * non-standard (HPUX) software, expect to see this problem
    143  * frequently and/or take care picking the target host of your
    144  * probes.
    145  *
    146  * Other possible annotations after the time are !H, !N, !P (got a host,
    147  * network or protocol unreachable, respectively), !S or !F (source
    148  * route failed or fragmentation needed -- neither of these should
    149  * ever occur and the associated gateway is busted if you see one).  If
    150  * almost all the probes result in some kind of unreachable, traceroute
    151  * will give up and exit.
    152  *
    153  * Notes
    154  * -----
    155  * This program must be run by root or be setuid.  (I suggest that
    156  * you *don't* make it setuid -- casual use could result in a lot
    157  * of unnecessary traffic on our poor, congested nets.)
    158  *
    159  * This program requires a kernel mod that does not appear in any
    160  * system available from Berkeley:  A raw ip socket using proto
    161  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
    162  * opposed to data to be wrapped in a ip datagram).  See the README
    163  * file that came with the source to this program for a description
    164  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
    165  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
    166  * MODIFIED TO RUN THIS PROGRAM.
    167  *
    168  * The udp port usage may appear bizarre (well, ok, it is bizarre).
    169  * The problem is that an icmp message only contains 8 bytes of
    170  * data from the original datagram.  8 bytes is the size of a udp
    171  * header so, if we want to associate replies with the original
    172  * datagram, the necessary information must be encoded into the
    173  * udp header (the ip id could be used but there's no way to
    174  * interlock with the kernel's assignment of ip id's and, anyway,
    175  * it would have taken a lot more kernel hacking to allow this
    176  * code to set the ip id).  So, to allow two or more users to
    177  * use traceroute simultaneously, we use this task's pid as the
    178  * source port (the high bit is set to move the port number out
    179  * of the "likely" range).  To keep track of which probe is being
    180  * replied to (so times and/or hop counts don't get confused by a
    181  * reply that was delayed in transit), we increment the destination
    182  * port number before each probe.
    183  *
    184  * Don't use this as a coding example.  I was trying to find a
    185  * routing problem and this code sort-of popped out after 48 hours
    186  * without sleep.  I was amazed it ever compiled, much less ran.
    187  *
    188  * I stole the idea for this program from Steve Deering.  Since
    189  * the first release, I've learned that had I attended the right
    190  * IETF working group meetings, I also could have stolen it from Guy
    191  * Almes or Matt Mathis.  I don't know (or care) who came up with
    192  * the idea first.  I envy the originators' perspicacity and I'm
    193  * glad they didn't keep the idea a secret.
    194  *
    195  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
    196  * enhancements to the original distribution.
    197  *
    198  * I've hacked up a round-trip-route version of this that works by
    199  * sending a loose-source-routed udp datagram through the destination
    200  * back to yourself.  Unfortunately, SO many gateways botch source
    201  * routing, the thing is almost worthless.  Maybe one day...
    202  *
    203  *  -- Van Jacobson (van (at) ee.lbl.gov)
    204  *     Tue Dec 20 03:50:13 PST 1988
    205  */
    206 
    207 #include <sys/param.h>
    208 #include <sys/file.h>
    209 #include <sys/ioctl.h>
    210 #include <sys/socket.h>
    211 #include <sys/time.h>
    212 #include <sys/sysctl.h>
    213 
    214 #include <netinet/in_systm.h>
    215 #include <netinet/in.h>
    216 #include <netinet/ip.h>
    217 #include <netinet/ip_var.h>
    218 #include <netinet/ip_icmp.h>
    219 #include <netinet/udp.h>
    220 #include <netinet/udp_var.h>
    221 
    222 #include <arpa/inet.h>
    223 
    224 #include <ctype.h>
    225 #include <errno.h>
    226 #ifdef HAVE_MALLOC_H
    227 #include <malloc.h>
    228 #endif
    229 #include <memory.h>
    230 #include <netdb.h>
    231 #include <stdio.h>
    232 #include <stdlib.h>
    233 #include <string.h>
    234 #include <unistd.h>
    235 #include <poll.h>
    236 #ifdef IPSEC
    237 #include <net/route.h>
    238 #include <netinet6/ipsec.h>
    239 #endif
    240 
    241 #include "gnuc.h"
    242 #ifdef HAVE_OS_PROTO_H
    243 #include "os-proto.h"
    244 #endif
    245 
    246 #include "ifaddrlist.h"
    247 #include "as.h"
    248 
    249 /* Maximum number of gateways (include room for one noop) */
    250 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
    251 
    252 #ifndef MAXHOSTNAMELEN
    253 #define MAXHOSTNAMELEN	64
    254 #endif
    255 
    256 #define Fprintf (void)fprintf
    257 #define Printf (void)printf
    258 
    259 /* Host name and address list */
    260 struct hostinfo {
    261 	char *name;
    262 	int n;
    263 	u_int32_t *addrs;
    264 };
    265 
    266 /* Data section of the probe packet */
    267 struct outdata {
    268 	u_char seq;		/* sequence number of this packet */
    269 	u_char ttl;		/* ttl packet left with */
    270 	struct timeval tv;	/* time packet left */
    271 };
    272 
    273 /*
    274  * Support for ICMP extensions
    275  *
    276  * http://www.ietf.org/proceedings/01aug/I-D/draft-ietf-mpls-icmp-02.txt
    277  */
    278 #define ICMP_EXT_OFFSET    8 /* ICMP type, code, checksum, unused */ + \
    279                          128 /* original datagram */
    280 #define ICMP_EXT_VERSION 2
    281 /*
    282  * ICMP extensions, common header
    283  */
    284 struct icmp_ext_cmn_hdr {
    285 #if BYTE_ORDER == BIG_ENDIAN
    286 	unsigned char   version:4;
    287 	unsigned char   reserved1:4;
    288 #else
    289 	unsigned char   reserved1:4;
    290 	unsigned char   version:4;
    291 #endif
    292 	unsigned char   reserved2;
    293 	unsigned short  checksum;
    294 };
    295 
    296 /*
    297  * ICMP extensions, object header
    298  */
    299 struct icmp_ext_obj_hdr {
    300     u_short length;
    301     u_char  class_num;
    302 #define MPLS_STACK_ENTRY_CLASS 1
    303     u_char  c_type;
    304 #define MPLS_STACK_ENTRY_C_TYPE 1
    305 };
    306 
    307 struct mpls_header {
    308 #if BYTE_ORDER == BIG_ENDIAN
    309 	 uint32_t	label:20;
    310 	 unsigned char  exp:3;
    311 	 unsigned char  s:1;
    312 	 unsigned char  ttl:8;
    313 #else
    314 	 unsigned char  ttl:8;
    315 	 unsigned char  s:1;
    316 	 unsigned char  exp:3;
    317 	 uint32_t	label:20;
    318 #endif
    319 };
    320 
    321 u_char	packet[512];		/* last inbound (icmp) packet */
    322 
    323 struct ip *outip;		/* last output (udp) packet */
    324 struct udphdr *outudp;		/* last output (udp) packet */
    325 void *outmark;			/* packed location of struct outdata */
    326 struct outdata outsetup;	/* setup and copy for alignment */
    327 
    328 struct icmp *outicmp;		/* last output (icmp) packet */
    329 
    330 /* loose source route gateway list (including room for final destination) */
    331 u_int32_t gwlist[NGATEWAYS + 1];
    332 
    333 int s;				/* receive (icmp) socket file descriptor */
    334 int sndsock;			/* send (udp/icmp) socket file descriptor */
    335 
    336 struct sockaddr whereto;	/* Who to try to reach */
    337 struct sockaddr_in wherefrom;	/* Who we are */
    338 int packlen;			/* total length of packet */
    339 int minpacket;			/* min ip packet size */
    340 int maxpacket = 32 * 1024;	/* max ip packet size */
    341 int printed_ttl = 0;
    342 
    343 char *prog;
    344 char *source;
    345 char *hostname;
    346 char *device;
    347 
    348 int nprobes = 3;
    349 int max_ttl = 30;
    350 int first_ttl = 1;
    351 u_int16_t ident;
    352 in_port_t port = 32768 + 666;	/* start udp dest port # for probe packets */
    353 
    354 int options;			/* socket options */
    355 int verbose;
    356 int waittime = 5;		/* time to wait for response (in seconds) */
    357 int nflag;			/* print addresses numerically */
    358 int dump;
    359 int Mflag;			/* show MPLS labels if any */
    360 int as_path;			/* print as numbers for each hop */
    361 char *as_server = NULL;
    362 void *asn;
    363 int useicmp = 0;		/* use icmp echo instead of udp packets */
    364 #ifdef CANT_HACK_CKSUM
    365 int docksum = 0;		/* don't calculate checksums */
    366 #else
    367 int docksum = 1;		/* calculate checksums */
    368 #endif
    369 int optlen;			/* length of ip options */
    370 
    371 int mtus[] = {
    372         17914,
    373          8166,
    374          4464,
    375          4352,
    376          2048,
    377          2002,
    378          1536,
    379          1500,
    380          1492,
    381 	 1480,
    382 	 1280,
    383          1006,
    384           576,
    385           552,
    386           544,
    387           512,
    388           508,
    389           296,
    390            68,
    391             0
    392 };
    393 int *mtuptr = &mtus[0];
    394 int mtudisc = 0;
    395 int nextmtu;   /* from ICMP error, set by packet_ok(), might be 0 */
    396 
    397 extern int optind;
    398 extern int opterr;
    399 extern char *optarg;
    400 
    401 /* Forwards */
    402 double	deltaT(struct timeval *, struct timeval *);
    403 void	freehostinfo(struct hostinfo *);
    404 void	getaddr(u_int32_t *, char *);
    405 struct	hostinfo *gethostinfo(char *);
    406 u_int16_t in_cksum(u_int16_t *, int);
    407 u_int16_t in_cksum2(u_int16_t, u_int16_t *, int);
    408 char	*inetname(struct in_addr);
    409 int	main(int, char **);
    410 int	packet_ok(u_char *, int, struct sockaddr_in *, int);
    411 char	*pr_type(u_char);
    412 void	print(u_char *, int, struct sockaddr_in *);
    413 void	resize_packet(void);
    414 void	dump_packet(void);
    415 void	send_probe(int, int, struct timeval *);
    416 void	setsin(struct sockaddr_in *, u_int32_t);
    417 int	str2val(const char *, const char *, int, int);
    418 void	tvsub(struct timeval *, struct timeval *);
    419 __dead	void usage(void);
    420 int	wait_for_reply(int, struct sockaddr_in *, struct timeval *);
    421 void	decode_extensions(unsigned char *buf, int ip_len);
    422 void	frag_err(void);
    423 int	find_local_ip(struct sockaddr_in *, struct sockaddr_in *);
    424 #ifdef IPSEC
    425 #ifdef IPSEC_POLICY_IPSEC
    426 int	setpolicy(int so, char *policy);
    427 #endif
    428 #endif
    429 
    430 int
    431 main(int argc, char **argv)
    432 {
    433 	int op, code, n;
    434 	char *cp;
    435 	u_char *outp;
    436 	u_int32_t *ap;
    437 	struct sockaddr_in *from = &wherefrom;
    438 	struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
    439 	struct hostinfo *hi;
    440 	int on = 1;
    441 	int ttl, probe, i;
    442 	int seq = 0;
    443 	int tos = 0, settos = 0, ttl_flag = 0;
    444 	int lsrr = 0;
    445 	u_int16_t off = 0;
    446 	struct ifaddrlist *al, *al2;
    447 	char errbuf[132];
    448 	int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
    449 	size_t size = sizeof(max_ttl);
    450 
    451 	if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
    452 		Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
    453 		exit(1);
    454 	}
    455 
    456 	/*
    457 	 * XXX 'useicmp' will always be zero here. I think the HP-UX users
    458 	 * running our traceroute code will forgive us.
    459 	 */
    460 #ifndef __hpux
    461 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
    462 #else
    463 	sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW
    464 	    useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
    465 #endif
    466 	if (sndsock < 0) {
    467 		Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
    468 		exit(1);
    469 	}
    470 
    471 	/* Revert to non-privileged user after opening sockets */
    472 	setuid(getuid());
    473 
    474 	(void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
    475 	    NULL, 0);
    476 
    477 	if ((cp = strrchr(argv[0], '/')) != NULL)
    478 		prog = cp + 1;
    479 	else
    480 		prog = argv[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)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)setsockopt(s, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    731 		sizeof(level));
    732 	(void)setsockopt(s, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    733 		sizeof(level));
    734 #ifdef IP_AUTH_TRANS_LEVEL
    735 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    736 		sizeof(level));
    737 #else
    738 	(void)setsockopt(s, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    739 		sizeof(level));
    740 #endif
    741 #ifdef IP_AUTH_NETWORK_LEVEL
    742 	(void)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)setsockopt(sndsock, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &level,
    764 		sizeof(level));
    765 	(void)setsockopt(sndsock, IPPROTO_IP, IP_ESP_NETWORK_LEVEL, &level,
    766 		sizeof(level));
    767 #ifdef IP_AUTH_TRANS_LEVEL
    768 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &level,
    769 		sizeof(level));
    770 #else
    771 	(void)setsockopt(sndsock, IPPROTO_IP, IP_AUTH_LEVEL, &level,
    772 		sizeof(level));
    773 #endif
    774 #ifdef IP_AUTH_NETWORK_LEVEL
    775 	(void)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 ((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 (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 (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 && 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)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
    834 		    sizeof(on));
    835 	if (options & SO_DONTROUTE)
    836 		(void)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 			send_probe(++seq, ttl, &t1);
    968 			while ((cc = wait_for_reply(s, from, &t1)) != 0) {
    969 				(void)gettimeofday(&t2, NULL);
    970 				/*
    971 				 * Since we'll be receiving all ICMP
    972 				 * messages to this host above, we may
    973 				 * never end up with cc=0, so we need
    974 				 * an additional termination check.
    975 				 */
    976 				if (t2.tv_sec - t1.tv_sec > waittime) {
    977 					cc = 0;
    978 					break;
    979 				}
    980 				i = packet_ok(packet, cc, from, seq);
    981 				/* Skip short packet */
    982 				if (i == 0)
    983 					continue;
    984 				if (from->sin_addr.s_addr != lastaddr) {
    985 					print(packet, cc, from);
    986 					lastaddr = from->sin_addr.s_addr;
    987 				}
    988 				ip = (struct ip *)packet;
    989 				Printf("  %.3f ms", deltaT(&t1, &t2));
    990 				if (ttl_flag)
    991 					Printf(" (ttl = %d)", ip->ip_ttl);
    992 				if (i == -2) {
    993 #ifndef ARCHAIC
    994 					if (ip->ip_ttl <= 1)
    995 						Printf(" !");
    996 #endif
    997 					++got_there;
    998 					break;
    999 				}
   1000 
   1001 				/* time exceeded in transit */
   1002 				if (i == -1)
   1003 					break;
   1004 				code = i - 1;
   1005 				switch (code) {
   1006 
   1007 				case ICMP_UNREACH_PORT:
   1008 #ifndef ARCHAIC
   1009 					if (ip->ip_ttl <= 1)
   1010 						Printf(" !");
   1011 #endif
   1012 					++got_there;
   1013 					break;
   1014 
   1015 				case ICMP_UNREACH_NET:
   1016 					++unreachable;
   1017 					Printf(" !N");
   1018 					break;
   1019 
   1020 				case ICMP_UNREACH_HOST:
   1021 					++unreachable;
   1022 					Printf(" !H");
   1023 					break;
   1024 
   1025 				case ICMP_UNREACH_PROTOCOL:
   1026 					++got_there;
   1027 					Printf(" !P");
   1028 					break;
   1029 
   1030 				case ICMP_UNREACH_NEEDFRAG:
   1031 					if (mtudisc) {
   1032 						frag_err();
   1033 						goto again;
   1034 					} else {
   1035 						++unreachable;
   1036 						Printf(" !F");
   1037 					}
   1038 					break;
   1039 
   1040 				case ICMP_UNREACH_SRCFAIL:
   1041 					++unreachable;
   1042 					Printf(" !S");
   1043 					break;
   1044 
   1045 /* rfc1716 */
   1046 #ifndef ICMP_UNREACH_FILTER_PROHIB
   1047 #define ICMP_UNREACH_FILTER_PROHIB	13	/* admin prohibited filter */
   1048 #endif
   1049 				case ICMP_UNREACH_FILTER_PROHIB:
   1050 					++unreachable;
   1051 					Printf(" !X");
   1052 					break;
   1053 
   1054 				default:
   1055 					++unreachable;
   1056 					Printf(" !<%d>", code);
   1057 					break;
   1058 				}
   1059 				break;
   1060 			}
   1061 			if (cc == 0)
   1062 				Printf(" *");
   1063 			else if (cc && probe == nprobes - 1 && Mflag)
   1064 				decode_extensions(packet, cc);
   1065 			(void)fflush(stdout);
   1066 		}
   1067 		putchar('\n');
   1068 		if (got_there ||
   1069 		    (unreachable > 0 && unreachable >= ((nprobes + 1) / 2)))
   1070 			break;
   1071 	}
   1072 
   1073 	if (as_path)
   1074 		as_shutdown(asn);
   1075 
   1076 	exit(0);
   1077 }
   1078 
   1079 int
   1080 wait_for_reply(int sock, struct sockaddr_in *fromp, struct timeval *tp)
   1081 {
   1082 	struct pollfd set[1];
   1083 	struct timeval now, wait;
   1084 	int cc = 0;
   1085 	socklen_t fromlen = sizeof(*fromp);
   1086 	int retval;
   1087 
   1088 	set[0].fd = sock;
   1089 	set[0].events = POLLIN;
   1090 
   1091 	wait.tv_sec = tp->tv_sec + waittime;
   1092 	wait.tv_usec = tp->tv_usec;
   1093 	(void)gettimeofday(&now, NULL);
   1094 	tvsub(&wait, &now);
   1095 
   1096 	if (wait.tv_sec < 0) {
   1097 		wait.tv_sec = 0;
   1098 		wait.tv_usec = 0;
   1099 	}
   1100 
   1101 	retval = poll(set, 1, wait.tv_sec * 1000 + wait.tv_usec / 1000);
   1102 	if (retval < 0)  {
   1103 		/* If we continue, we probably just flood the remote host. */
   1104 		Fprintf(stderr, "%s: select: %s\n", prog, strerror(errno));
   1105 		exit(1);
   1106 	}
   1107 	if (retval > 0)  {
   1108 		cc = recvfrom(s, (char *)packet, sizeof(packet), 0,
   1109 			    (struct sockaddr *)fromp, &fromlen);
   1110 	}
   1111 
   1112 	return(cc);
   1113 }
   1114 
   1115 void
   1116 decode_extensions(unsigned char *buf, int ip_len)
   1117 {
   1118         struct icmp_ext_cmn_hdr *cmn_hdr;
   1119         struct icmp_ext_obj_hdr *obj_hdr;
   1120         union {
   1121                 struct mpls_header mpls;
   1122                 uint32_t mpls_h;
   1123         } mpls;
   1124         int datalen, obj_len;
   1125         struct ip *ip;
   1126 
   1127         ip = (struct ip *)buf;
   1128 
   1129         if (ip_len <= sizeof(struct ip) + ICMP_EXT_OFFSET) {
   1130 		/*
   1131 		 * No support for ICMP extensions on this host
   1132 		 */
   1133 		return;
   1134         }
   1135 
   1136         /*
   1137          * Move forward to the start of the ICMP extensions, if present
   1138          */
   1139         buf += (ip->ip_hl << 2) + ICMP_EXT_OFFSET;
   1140         cmn_hdr = (struct icmp_ext_cmn_hdr *)buf;
   1141 
   1142         if (cmn_hdr->version != ICMP_EXT_VERSION) {
   1143 		/*
   1144 		 * Unknown version
   1145 		 */
   1146 		return;
   1147         }
   1148 
   1149         datalen = ip_len - ((u_char *)cmn_hdr - (u_char *)ip);
   1150 
   1151         /*
   1152          * Check the checksum, cmn_hdr->checksum == 0 means no checksum'ing
   1153          * done by sender.
   1154          *
   1155         * If the checksum is ok, we'll get 0, as the checksum is calculated
   1156          * with the checksum field being 0'd.
   1157          */
   1158         if (ntohs(cmn_hdr->checksum) &&
   1159             in_cksum((u_short *)cmn_hdr, datalen)) {
   1160 
   1161             return;
   1162         }
   1163 
   1164         buf += sizeof(*cmn_hdr);
   1165         datalen -= sizeof(*cmn_hdr);
   1166 
   1167         while (datalen > 0) {
   1168 		obj_hdr = (struct icmp_ext_obj_hdr *)buf;
   1169 		obj_len = ntohs(obj_hdr->length);
   1170 
   1171 		/*
   1172 		 * Sanity check the length field
   1173 		 */
   1174 		if (obj_len > datalen) {
   1175 			return;
   1176 		}
   1177 
   1178 		datalen -= obj_len;
   1179 
   1180 		/*
   1181 		 * Move past the object header
   1182 		 */
   1183 		buf += sizeof(struct icmp_ext_obj_hdr);
   1184 		obj_len -= sizeof(struct icmp_ext_obj_hdr);
   1185 
   1186 		switch (obj_hdr->class_num) {
   1187 		case MPLS_STACK_ENTRY_CLASS:
   1188 			switch (obj_hdr->c_type) {
   1189 			case MPLS_STACK_ENTRY_C_TYPE:
   1190 				while (obj_len >= sizeof(uint32_t)) {
   1191 					mpls.mpls_h = ntohl(*(uint32_t *)buf);
   1192 
   1193 					buf += sizeof(uint32_t);
   1194 					obj_len -= sizeof(uint32_t);
   1195 
   1196 					printf(" [MPLS: Label %d Exp %d]",
   1197 					    mpls.mpls.label, mpls.mpls.exp);
   1198 				}
   1199 				if (obj_len > 0) {
   1200 					/*
   1201 					 * Something went wrong, and we're at
   1202 					 * a unknown offset into the packet,
   1203 					 * ditch the rest of it.
   1204 					 */
   1205 					return;
   1206 				}
   1207 				break;
   1208 			default:
   1209 				/*
   1210 				 * Unknown object, skip past it
   1211 				 */
   1212 				buf += ntohs(obj_hdr->length) -
   1213 				    sizeof(struct icmp_ext_obj_hdr);
   1214 				break;
   1215 			}
   1216 			break;
   1217 
   1218 		default:
   1219 			/*
   1220 			 * Unknown object, skip past it
   1221 			 */
   1222 			buf += ntohs(obj_hdr->length) -
   1223 			    sizeof(struct icmp_ext_obj_hdr);
   1224 			break;
   1225 		}
   1226 	}
   1227 }
   1228 
   1229 void
   1230 dump_packet()
   1231 {
   1232 	u_char *p;
   1233 	int i;
   1234 
   1235 	Fprintf(stderr, "packet data:");
   1236 
   1237 #ifdef __hpux
   1238 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
   1239 	    i < packlen - (sizeof(*outip) + optlen); i++)
   1240 #else
   1241 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
   1242 #endif
   1243 	{
   1244 		if ((i % 24) == 0)
   1245 			Fprintf(stderr, "\n ");
   1246 		Fprintf(stderr, " %02x", *p++);
   1247 	}
   1248 	Fprintf(stderr, "\n");
   1249 }
   1250 
   1251 void
   1252 send_probe(int seq, int ttl, struct timeval *tp)
   1253 {
   1254 	int cc;
   1255 	struct udpiphdr * ui;
   1256 	int oldmtu = packlen;
   1257 
   1258 again:
   1259 #ifdef BYTESWAP_IP_LEN
   1260 	outip->ip_len = htons(packlen);
   1261 #else
   1262 	outip->ip_len = packlen;
   1263 #endif
   1264 	outip->ip_ttl = ttl;
   1265 #ifndef __hpux
   1266 	outip->ip_id = htons(ident + seq);
   1267 #endif
   1268 
   1269 	/*
   1270 	 * In most cases, the kernel will recalculate the ip checksum.
   1271 	 * But we must do it anyway so that the udp checksum comes out
   1272 	 * right.
   1273 	 */
   1274 	if (docksum) {
   1275 		outip->ip_sum =
   1276 		    in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
   1277 		if (outip->ip_sum == 0)
   1278 			outip->ip_sum = 0xffff;
   1279 	}
   1280 
   1281 	/* Payload */
   1282 	outsetup.seq = seq;
   1283 	outsetup.ttl = ttl;
   1284 	outsetup.tv  = *tp;
   1285 	memcpy(outmark,&outsetup,sizeof(outsetup));
   1286 
   1287 	if (useicmp)
   1288 		outicmp->icmp_seq = htons(seq);
   1289 	else
   1290 		outudp->uh_dport = htons(port + seq);
   1291 
   1292 	/* (We can only do the checksum if we know our ip address) */
   1293 	if (docksum) {
   1294 		if (useicmp) {
   1295 			outicmp->icmp_cksum = 0;
   1296 			outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1297 			    packlen - (sizeof(*outip) + optlen));
   1298 			if (outicmp->icmp_cksum == 0)
   1299 				outicmp->icmp_cksum = 0xffff;
   1300 		} else {
   1301 			u_int16_t sum;
   1302 			struct {
   1303 				struct in_addr src;
   1304 				struct in_addr dst;
   1305 				u_int8_t zero;
   1306 				u_int8_t protocol;
   1307 				u_int16_t len;
   1308 			} __attribute__((__packed__)) phdr;
   1309 
   1310 			/* Checksum */
   1311 			ui = (struct udpiphdr *)outip;
   1312 			memset(&phdr, 0, sizeof(phdr));
   1313 			phdr.src = ui->ui_src;
   1314 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
   1315 			phdr.protocol = ui->ui_pr;
   1316 			phdr.len = outudp->uh_ulen;
   1317 			outudp->uh_sum = 0;
   1318 			sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
   1319 			sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
   1320 			sum = ~sum;	/** XXXSCW: Quell SuperH Compiler Bug */
   1321 			outudp->uh_sum = sum;
   1322 			if (outudp->uh_sum == 0)
   1323 				outudp->uh_sum = 0xffff;
   1324 		}
   1325 	}
   1326 
   1327 	/* XXX undocumented debugging hack */
   1328 	if (verbose > 1) {
   1329 		const u_int16_t *sp;
   1330 		int nshorts, i;
   1331 
   1332 		sp = (u_int16_t *)outip;
   1333 		nshorts = (u_int)packlen / sizeof(u_int16_t);
   1334 		i = 0;
   1335 		Printf("[ %d bytes", packlen);
   1336 		while (--nshorts >= 0) {
   1337 			if ((i++ % 8) == 0)
   1338 				Printf("\n\t");
   1339 			Printf(" %04x", ntohs(*sp++));
   1340 		}
   1341 		if (packlen & 1) {
   1342 			if ((i % 8) == 0)
   1343 				Printf("\n\t");
   1344 			Printf(" %02x", *(u_char *)sp);
   1345 		}
   1346 		Printf("]\n");
   1347 	}
   1348 
   1349 #if !defined(IP_HDRINCL) && defined(IP_TTL)
   1350 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
   1351 	    (char *)&ttl, sizeof(ttl)) < 0) {
   1352 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
   1353 		    prog, ttl, strerror(errno));
   1354 		exit(1);
   1355 	}
   1356 #endif
   1357 	if (dump)
   1358 		dump_packet();
   1359 
   1360 #ifdef __hpux
   1361 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
   1362 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
   1363 	if (cc > 0)
   1364 		cc += sizeof(*outip) + optlen;
   1365 #else
   1366 	cc = sendto(sndsock, (char *)outip,
   1367 	    packlen, 0, &whereto, sizeof(whereto));
   1368 #endif
   1369 	if (cc < 0 || cc != packlen)  {
   1370 		if (cc < 0) {
   1371 			/*
   1372 			 * An errno of EMSGSIZE means we're writing too big a
   1373 			 * datagram for the interface.  We have to just
   1374 			 * decrease the packet size until we find one that
   1375 			 * works.
   1376 			 *
   1377 			 * XXX maybe we should try to read the outgoing if's
   1378 			 * mtu?
   1379 			 */
   1380 			if (errno == EMSGSIZE) {
   1381 				packlen = *mtuptr++;
   1382 				resize_packet();
   1383 				goto again;
   1384 			} else
   1385 				Fprintf(stderr, "%s: sendto: %s\n",
   1386 				    prog, strerror(errno));
   1387 		}
   1388 
   1389 		Printf("%s: wrote %s %d chars, ret=%d\n",
   1390 		    prog, hostname, packlen, cc);
   1391 		(void)fflush(stdout);
   1392 	}
   1393 	if (oldmtu != packlen) {
   1394 		Printf("message too big, "
   1395 		    "trying new MTU = %d\n", packlen);
   1396 		printed_ttl = 0;
   1397 	}
   1398 	if (!printed_ttl) {
   1399 		Printf("%2d ", ttl);
   1400 		printed_ttl = 1;
   1401 	}
   1402 
   1403 }
   1404 
   1405 double
   1406 deltaT(struct timeval *t1p, struct timeval *t2p)
   1407 {
   1408 	double dt;
   1409 
   1410 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
   1411 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
   1412 	return (dt);
   1413 }
   1414 
   1415 /*
   1416  * Convert an ICMP "type" field to a printable string.
   1417  */
   1418 char *
   1419 pr_type(u_char t)
   1420 {
   1421 	static char *ttab[] = {
   1422 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
   1423 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
   1424 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
   1425 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
   1426 	"Info Reply"
   1427 	};
   1428 
   1429 	if (t > 16)
   1430 		return("OUT-OF-RANGE");
   1431 
   1432 	return(ttab[t]);
   1433 }
   1434 
   1435 int
   1436 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
   1437 {
   1438 	struct icmp *icp;
   1439 	u_char type, code;
   1440 	int hlen;
   1441 #ifndef ARCHAIC
   1442 	struct ip *ip;
   1443 
   1444 	ip = (struct ip *) buf;
   1445 	hlen = ip->ip_hl << 2;
   1446 	if (cc < hlen + ICMP_MINLEN) {
   1447 		if (verbose)
   1448 			Printf("packet too short (%d bytes) from %s\n", cc,
   1449 				inet_ntoa(from->sin_addr));
   1450 		return (0);
   1451 	}
   1452 	cc -= hlen;
   1453 	icp = (struct icmp *)(buf + hlen);
   1454 #else
   1455 	icp = (struct icmp *)buf;
   1456 #endif
   1457 	type = icp->icmp_type;
   1458 	code = icp->icmp_code;
   1459 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
   1460 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
   1461 		struct ip *hip;
   1462 		struct udphdr *up;
   1463 		struct icmp *hicmp;
   1464 
   1465 		hip = &icp->icmp_ip;
   1466 		hlen = hip->ip_hl << 2;
   1467 
   1468 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
   1469 
   1470 		if (useicmp) {
   1471 			/* XXX */
   1472 			if (type == ICMP_ECHOREPLY &&
   1473 			    icp->icmp_id == htons(ident) &&
   1474 			    icp->icmp_seq == htons(seq))
   1475 				return (-2);
   1476 
   1477 			hicmp = (struct icmp *)((u_char *)hip + hlen);
   1478 			/* XXX 8 is a magic number */
   1479 			if (hlen + 8 <= cc &&
   1480 			    hip->ip_p == IPPROTO_ICMP &&
   1481 			    hicmp->icmp_id == htons(ident) &&
   1482 			    hicmp->icmp_seq == htons(seq))
   1483 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1484 		} else {
   1485 			up = (struct udphdr *)((u_char *)hip + hlen);
   1486 			/* XXX 8 is a magic number */
   1487 			if (hlen + 12 <= cc &&
   1488 			    hip->ip_p == IPPROTO_UDP &&
   1489 			    up->uh_sport == htons(ident) &&
   1490 			    up->uh_dport == htons(port + seq))
   1491 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1492 		}
   1493 	}
   1494 #ifndef ARCHAIC
   1495 	if (verbose) {
   1496 		int i;
   1497 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
   1498 
   1499 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
   1500 		Printf("%s: icmp type %d (%s) code %d\n",
   1501 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
   1502 		for (i = 4; i < cc ; i += sizeof(*lp))
   1503 			Printf("%2d: x%8.8x\n", i, *lp++);
   1504 	}
   1505 #endif
   1506 	return(0);
   1507 }
   1508 
   1509 void resize_packet(void)
   1510 {
   1511 	if (useicmp) {
   1512 		outicmp->icmp_cksum = 0;
   1513 		outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1514 		    packlen - (sizeof(*outip) + optlen));
   1515 		if (outicmp->icmp_cksum == 0)
   1516 			outicmp->icmp_cksum = 0xffff;
   1517 	} else {
   1518 		outudp->uh_ulen =
   1519 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
   1520 	}
   1521 }
   1522 
   1523 void
   1524 print(u_char *buf, int cc, struct sockaddr_in *from)
   1525 {
   1526 	struct ip *ip;
   1527 	int hlen;
   1528 
   1529 	ip = (struct ip *) buf;
   1530 	hlen = ip->ip_hl << 2;
   1531 	cc -= hlen;
   1532 
   1533 	if (as_path)
   1534 		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
   1535 
   1536 	if (nflag)
   1537 		Printf(" %s", inet_ntoa(from->sin_addr));
   1538 	else
   1539 		Printf(" %s (%s)", inetname(from->sin_addr),
   1540 		    inet_ntoa(from->sin_addr));
   1541 
   1542 	if (verbose)
   1543 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
   1544 }
   1545 
   1546 u_int16_t
   1547 in_cksum(u_int16_t *addr, int len)
   1548 {
   1549 
   1550 	return ~in_cksum2(0, addr, len);
   1551 }
   1552 
   1553 /*
   1554  * Checksum routine for Internet Protocol family headers (C Version)
   1555  */
   1556 u_int16_t
   1557 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
   1558 {
   1559 	int nleft = len;
   1560 	u_int16_t *w = addr;
   1561 	union {
   1562 		u_int16_t w;
   1563 		u_int8_t b[2];
   1564 	} answer;
   1565 	int32_t sum = seed;
   1566 
   1567 	/*
   1568 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
   1569 	 *  we add sequential 16 bit words to it, and at the end, fold
   1570 	 *  back all the carry bits from the top 16 bits into the lower
   1571 	 *  16 bits.
   1572 	 */
   1573 	while (nleft > 1)  {
   1574 		sum += *w++;
   1575 		nleft -= 2;
   1576 	}
   1577 
   1578 	/* mop up an odd byte, if necessary */
   1579 	if (nleft == 1) {
   1580 		answer.b[0] = *(u_char *)w;
   1581 		answer.b[1] = 0;
   1582 		sum += answer.w;
   1583 	}
   1584 
   1585 	/*
   1586 	 * add back carry outs from top 16 bits to low 16 bits
   1587 	 */
   1588 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
   1589 	sum += (sum >> 16);			/* add carry */
   1590 	answer.w = sum;				/* truncate to 16 bits */
   1591 	return (answer.w);
   1592 }
   1593 
   1594 /*
   1595  * Subtract 2 timeval structs:  out = out - in.
   1596  * Out is assumed to be >= in.
   1597  */
   1598 void
   1599 tvsub(struct timeval *out, struct timeval *in)
   1600 {
   1601 
   1602 	if ((out->tv_usec -= in->tv_usec) < 0)   {
   1603 		--out->tv_sec;
   1604 		out->tv_usec += 1000000;
   1605 	}
   1606 	out->tv_sec -= in->tv_sec;
   1607 }
   1608 
   1609 /*
   1610  * Construct an Internet address representation.
   1611  * If the nflag has been supplied, give
   1612  * numeric value, otherwise try for symbolic name.
   1613  */
   1614 char *
   1615 inetname(struct in_addr in)
   1616 {
   1617 	char *cp;
   1618 	struct hostent *hp;
   1619 	static int first = 1;
   1620 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
   1621 
   1622 	if (first && !nflag) {
   1623 		int rv;
   1624 
   1625 		first = 0;
   1626 		rv = gethostname(domain, sizeof domain);
   1627 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
   1628 			(void)strlcpy(domain, cp + 1, sizeof(domain));
   1629 		} else
   1630 			domain[0] = '\0';
   1631 	}
   1632 	if (!nflag && in.s_addr != INADDR_ANY) {
   1633 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
   1634 		if (hp != NULL) {
   1635 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
   1636 			    strcmp(cp + 1, domain) == 0)
   1637 				*cp = '\0';
   1638 			(void)strlcpy(line, hp->h_name, sizeof(line));
   1639 			return (line);
   1640 		}
   1641 	}
   1642 	return (inet_ntoa(in));
   1643 }
   1644 
   1645 struct hostinfo *
   1646 gethostinfo(char *hostname)
   1647 {
   1648 	int n;
   1649 	struct hostent *hp;
   1650 	struct hostinfo *hi;
   1651 	char **p;
   1652 	u_int32_t *ap;
   1653 	struct in_addr addr;
   1654 
   1655 	hi = calloc(1, sizeof(*hi));
   1656 	if (hi == NULL) {
   1657 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1658 		exit(1);
   1659 	}
   1660 	if (inet_aton(hostname, &addr) != 0) {
   1661 		hi->name = strdup(hostname);
   1662 		if (!hi->name) {
   1663 			Fprintf(stderr, "%s: strdup %s\n", prog,
   1664 			    strerror(errno));
   1665 			exit(1);
   1666 		}
   1667 		hi->n = 1;
   1668 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
   1669 		if (hi->addrs == NULL) {
   1670 			Fprintf(stderr, "%s: calloc %s\n",
   1671 			    prog, strerror(errno));
   1672 			exit(1);
   1673 		}
   1674 		hi->addrs[0] = addr.s_addr;
   1675 		return (hi);
   1676 	}
   1677 
   1678 	hp = gethostbyname(hostname);
   1679 	if (hp == NULL) {
   1680 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
   1681 		exit(1);
   1682 	}
   1683 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
   1684 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
   1685 		exit(1);
   1686 	}
   1687 	hi->name = strdup(hp->h_name);
   1688 	if (!hi->name) {
   1689 		Fprintf(stderr, "%s: strdup %s\n", prog, strerror(errno));
   1690 		exit(1);
   1691 	}
   1692 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
   1693 		continue;
   1694 	hi->n = n;
   1695 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
   1696 	if (hi->addrs == NULL) {
   1697 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1698 		exit(1);
   1699 	}
   1700 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
   1701 		memcpy(ap, *p, sizeof(*ap));
   1702 	return (hi);
   1703 }
   1704 
   1705 void
   1706 freehostinfo(struct hostinfo *hi)
   1707 {
   1708 	if (hi->name != NULL) {
   1709 		free(hi->name);
   1710 		hi->name = NULL;
   1711 	}
   1712 	free((char *)hi->addrs);
   1713 	free((char *)hi);
   1714 }
   1715 
   1716 void
   1717 getaddr(u_int32_t *ap, char *hostname)
   1718 {
   1719 	struct hostinfo *hi;
   1720 
   1721 	hi = gethostinfo(hostname);
   1722 	*ap = hi->addrs[0];
   1723 	freehostinfo(hi);
   1724 }
   1725 
   1726 void
   1727 setsin(struct sockaddr_in *sin, u_int32_t addr)
   1728 {
   1729 
   1730 	memset(sin, 0, sizeof(*sin));
   1731 #ifdef HAVE_SOCKADDR_SA_LEN
   1732 	sin->sin_len = sizeof(*sin);
   1733 #endif
   1734 	sin->sin_family = AF_INET;
   1735 	sin->sin_addr.s_addr = addr;
   1736 }
   1737 
   1738 /* String to value with optional min and max. Handles decimal and hex. */
   1739 int
   1740 str2val(const char *str, const char *what, int mi, int ma)
   1741 {
   1742 	const char *cp;
   1743 	long val;
   1744 	char *ep;
   1745 
   1746 	errno = 0;
   1747 	ep = NULL;
   1748 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
   1749 		cp = str + 2;
   1750 		val = strtol(cp, &ep, 16);
   1751 	} else
   1752 		val = strtol(str, &ep, 10);
   1753 	if (errno || str[0] == '\0' || *ep != '\0') {
   1754 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
   1755 		    prog, str, what);
   1756 		exit(1);
   1757 	}
   1758 	if (val < mi && mi >= 0) {
   1759 		if (mi == 0)
   1760 			Fprintf(stderr, "%s: %s must be >= %d\n",
   1761 			    prog, what, mi);
   1762 		else
   1763 			Fprintf(stderr, "%s: %s must be > %d\n",
   1764 			    prog, what, mi - 1);
   1765 		exit(1);
   1766 	}
   1767 	if (val > ma && ma >= 0) {
   1768 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
   1769 		exit(1);
   1770 	}
   1771 	return ((int)val);
   1772 }
   1773 
   1774 __dead void
   1775 usage(void)
   1776 {
   1777 	extern char version[];
   1778 
   1779 	Fprintf(stderr, "Version %s\n", version);
   1780 	Fprintf(stderr, "usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \
   1781 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
   1782 [-w waittime] [-A as_server] host [packetlen]\n",
   1783 	    prog);
   1784 	exit(1);
   1785 }
   1786 
   1787 /*
   1788  * Received ICMP unreachable (fragmentation required and DF set).
   1789  * If the ICMP error was from a "new" router, it'll contain the next-hop
   1790  * MTU that we should use next.  Otherwise we'll just keep going in the
   1791  * mtus[] table, trying until we hit a valid MTU.
   1792  */
   1793 
   1794 
   1795 void
   1796 frag_err()
   1797 {
   1798         int i;
   1799 
   1800         if (nextmtu > 0 && nextmtu < packlen) {
   1801                 Printf("\nfragmentation required and DF set, "
   1802 		     "next hop MTU = %d\n",
   1803                         nextmtu);
   1804                 packlen = nextmtu;
   1805                 for (i = 0; mtus[i] > 0; i++) {
   1806                         if (mtus[i] < nextmtu) {
   1807                                 mtuptr = &mtus[i];    /* next one to try */
   1808                                 break;
   1809                         }
   1810                 }
   1811         } else {
   1812                 Printf("\nfragmentation required and DF set. ");
   1813 		if (nextmtu)
   1814 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
   1815 			    nextmtu, packlen);
   1816                 packlen = *mtuptr++;
   1817 		Printf("Trying new MTU = %d\n", packlen);
   1818         }
   1819 	resize_packet();
   1820 }
   1821 
   1822 int
   1823 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
   1824 {
   1825 	int sock;
   1826 	struct sockaddr_in help;
   1827 	socklen_t help_len;
   1828 
   1829 	sock = socket(AF_INET, SOCK_DGRAM, 0);
   1830 	if (sock < 0) return (0);
   1831 
   1832 	help.sin_family = AF_INET;
   1833 	/*
   1834 	 * At this point the port number doesn't matter
   1835 	 * since it only has to be greater than zero.
   1836 	 */
   1837 	help.sin_port = 42;
   1838 	help.sin_addr.s_addr = to->sin_addr.s_addr;
   1839 	if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
   1840 		(void)close(sock);
   1841 		return (0);
   1842 	}
   1843 
   1844 	help_len = sizeof(help);
   1845 	if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
   1846 	    help_len != sizeof(help) ||
   1847 	    help.sin_addr.s_addr == INADDR_ANY) {
   1848 		(void)close(sock);
   1849 		return (0);
   1850 	}
   1851 
   1852 	(void)close(sock);
   1853 	setsin(from, help.sin_addr.s_addr);
   1854 	return (1);
   1855 }
   1856 
   1857 #ifdef IPSEC
   1858 #ifdef IPSEC_POLICY_IPSEC
   1859 int
   1860 setpolicy(so, policy)
   1861 	int so;
   1862 	char *policy;
   1863 {
   1864 	char *buf;
   1865 
   1866 	buf = ipsec_set_policy(policy, strlen(policy));
   1867 	if (buf == NULL) {
   1868 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
   1869 		return -1;
   1870 	}
   1871 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
   1872 		buf, ipsec_get_policylen(buf));
   1873 
   1874 	free(buf);
   1875 
   1876 	return 0;
   1877 }
   1878 #endif
   1879 #endif
   1880 
   1881