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