Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.62
      1 /*	$NetBSD: traceroute.c,v 1.62 2006/02/17 21:31:18 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.62 2006/02/17 21:31:18 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 	int 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: 0x%x,"
   1192 					    " ttl: %d]", mpls.mpls.label,
   1193 					    mpls.mpls.exp, mpls.mpls.ttl);
   1194 				}
   1195 				if (obj_len > 0) {
   1196 					/*
   1197 					 * Something went wrong, and we're at
   1198 					 * a unknown offset into the packet,
   1199 					 * ditch the rest of it.
   1200 					 */
   1201 					return;
   1202 				}
   1203 				break;
   1204 			default:
   1205 				/*
   1206 				 * Unknown object, skip past it
   1207 				 */
   1208 				buf += ntohs(obj_hdr->length) -
   1209 				    sizeof(struct icmp_ext_obj_hdr);
   1210 				break;
   1211 			}
   1212 			break;
   1213 
   1214 		default:
   1215 			/*
   1216 			 * Unknown object, skip past it
   1217 			 */
   1218 			buf += ntohs(obj_hdr->length) -
   1219 			    sizeof(struct icmp_ext_obj_hdr);
   1220 			break;
   1221 		}
   1222 	}
   1223 }
   1224 
   1225 void
   1226 dump_packet()
   1227 {
   1228 	u_char *p;
   1229 	int i;
   1230 
   1231 	Fprintf(stderr, "packet data:");
   1232 
   1233 #ifdef __hpux
   1234 	for (p = useicmp ? (u_char *)outicmp : (u_char *)outudp, i = 0; i <
   1235 	    i < packlen - (sizeof(*outip) + optlen); i++)
   1236 #else
   1237 	for (p = (u_char *)outip, i = 0; i < packlen; i++)
   1238 #endif
   1239 	{
   1240 		if ((i % 24) == 0)
   1241 			Fprintf(stderr, "\n ");
   1242 		Fprintf(stderr, " %02x", *p++);
   1243 	}
   1244 	Fprintf(stderr, "\n");
   1245 }
   1246 
   1247 void
   1248 send_probe(int seq, int ttl, struct timeval *tp)
   1249 {
   1250 	int cc;
   1251 	struct udpiphdr * ui;
   1252 	int oldmtu = packlen;
   1253 
   1254 again:
   1255 #ifdef BYTESWAP_IP_LEN
   1256 	outip->ip_len = htons(packlen);
   1257 #else
   1258 	outip->ip_len = packlen;
   1259 #endif
   1260 	outip->ip_ttl = ttl;
   1261 #ifndef __hpux
   1262 	outip->ip_id = htons(ident + seq);
   1263 #endif
   1264 
   1265 	/*
   1266 	 * In most cases, the kernel will recalculate the ip checksum.
   1267 	 * But we must do it anyway so that the udp checksum comes out
   1268 	 * right.
   1269 	 */
   1270 	if (docksum) {
   1271 		outip->ip_sum =
   1272 		    in_cksum((u_int16_t *)outip, sizeof(*outip) + optlen);
   1273 		if (outip->ip_sum == 0)
   1274 			outip->ip_sum = 0xffff;
   1275 	}
   1276 
   1277 	/* Payload */
   1278 	outsetup.seq = seq;
   1279 	outsetup.ttl = ttl;
   1280 	outsetup.tv  = *tp;
   1281 	memcpy(outmark,&outsetup,sizeof(outsetup));
   1282 
   1283 	if (useicmp)
   1284 		outicmp->icmp_seq = htons(seq);
   1285 	else
   1286 		outudp->uh_dport = htons(port + seq);
   1287 
   1288 	/* (We can only do the checksum if we know our ip address) */
   1289 	if (docksum) {
   1290 		if (useicmp) {
   1291 			outicmp->icmp_cksum = 0;
   1292 			outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1293 			    packlen - (sizeof(*outip) + optlen));
   1294 			if (outicmp->icmp_cksum == 0)
   1295 				outicmp->icmp_cksum = 0xffff;
   1296 		} else {
   1297 			u_int16_t sum;
   1298 			struct {
   1299 				struct in_addr src;
   1300 				struct in_addr dst;
   1301 				u_int8_t zero;
   1302 				u_int8_t protocol;
   1303 				u_int16_t len;
   1304 			} __attribute__((__packed__)) phdr;
   1305 
   1306 			/* Checksum */
   1307 			ui = (struct udpiphdr *)outip;
   1308 			memset(&phdr, 0, sizeof(phdr));
   1309 			phdr.src = ui->ui_src;
   1310 			phdr.dst = ((struct sockaddr_in *)&whereto)->sin_addr;
   1311 			phdr.protocol = ui->ui_pr;
   1312 			phdr.len = outudp->uh_ulen;
   1313 			outudp->uh_sum = 0;
   1314 			sum = in_cksum2(0, (u_int16_t *)&phdr, sizeof(phdr));
   1315 			sum = in_cksum2(sum, (u_int16_t *)outudp, ntohs(outudp->uh_ulen));
   1316 			sum = ~sum;	/** XXXSCW: Quell SuperH Compiler Bug */
   1317 			outudp->uh_sum = sum;
   1318 			if (outudp->uh_sum == 0)
   1319 				outudp->uh_sum = 0xffff;
   1320 		}
   1321 	}
   1322 
   1323 	/* XXX undocumented debugging hack */
   1324 	if (verbose > 1) {
   1325 		const u_int16_t *sp;
   1326 		int nshorts, i;
   1327 
   1328 		sp = (u_int16_t *)outip;
   1329 		nshorts = (u_int)packlen / sizeof(u_int16_t);
   1330 		i = 0;
   1331 		Printf("[ %d bytes", packlen);
   1332 		while (--nshorts >= 0) {
   1333 			if ((i++ % 8) == 0)
   1334 				Printf("\n\t");
   1335 			Printf(" %04x", ntohs(*sp++));
   1336 		}
   1337 		if (packlen & 1) {
   1338 			if ((i % 8) == 0)
   1339 				Printf("\n\t");
   1340 			Printf(" %02x", *(u_char *)sp);
   1341 		}
   1342 		Printf("]\n");
   1343 	}
   1344 
   1345 #if !defined(IP_HDRINCL) && defined(IP_TTL)
   1346 	if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
   1347 	    (char *)&ttl, sizeof(ttl)) < 0) {
   1348 		Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
   1349 		    prog, ttl, strerror(errno));
   1350 		exit(1);
   1351 	}
   1352 #endif
   1353 	if (dump)
   1354 		dump_packet();
   1355 
   1356 #ifdef __hpux
   1357 	cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
   1358 	    packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
   1359 	if (cc > 0)
   1360 		cc += sizeof(*outip) + optlen;
   1361 #else
   1362 	cc = sendto(sndsock, (char *)outip,
   1363 	    packlen, 0, &whereto, sizeof(whereto));
   1364 #endif
   1365 	if (cc < 0 || cc != packlen)  {
   1366 		if (cc < 0) {
   1367 			/*
   1368 			 * An errno of EMSGSIZE means we're writing too big a
   1369 			 * datagram for the interface.  We have to just
   1370 			 * decrease the packet size until we find one that
   1371 			 * works.
   1372 			 *
   1373 			 * XXX maybe we should try to read the outgoing if's
   1374 			 * mtu?
   1375 			 */
   1376 			if (errno == EMSGSIZE) {
   1377 				packlen = *mtuptr++;
   1378 				resize_packet();
   1379 				goto again;
   1380 			} else
   1381 				Fprintf(stderr, "%s: sendto: %s\n",
   1382 				    prog, strerror(errno));
   1383 		}
   1384 
   1385 		Printf("%s: wrote %s %d chars, ret=%d\n",
   1386 		    prog, hostname, packlen, cc);
   1387 		(void)fflush(stdout);
   1388 	}
   1389 	if (oldmtu != packlen) {
   1390 		Printf("message too big, "
   1391 		    "trying new MTU = %d\n", packlen);
   1392 		printed_ttl = 0;
   1393 	}
   1394 	if (!printed_ttl) {
   1395 		Printf("%2d ", ttl);
   1396 		printed_ttl = 1;
   1397 	}
   1398 
   1399 }
   1400 
   1401 double
   1402 deltaT(struct timeval *t1p, struct timeval *t2p)
   1403 {
   1404 	double dt;
   1405 
   1406 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
   1407 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
   1408 	return (dt);
   1409 }
   1410 
   1411 /*
   1412  * Convert an ICMP "type" field to a printable string.
   1413  */
   1414 char *
   1415 pr_type(u_char t)
   1416 {
   1417 	static char *ttab[] = {
   1418 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
   1419 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
   1420 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
   1421 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
   1422 	"Info Reply"
   1423 	};
   1424 
   1425 	if (t > 16)
   1426 		return("OUT-OF-RANGE");
   1427 
   1428 	return(ttab[t]);
   1429 }
   1430 
   1431 int
   1432 packet_ok(u_char *buf, int cc, struct sockaddr_in *from, int seq)
   1433 {
   1434 	struct icmp *icp;
   1435 	u_char type, code;
   1436 	int hlen;
   1437 #ifndef ARCHAIC
   1438 	struct ip *ip;
   1439 
   1440 	ip = (struct ip *) buf;
   1441 	hlen = ip->ip_hl << 2;
   1442 	if (cc < hlen + ICMP_MINLEN) {
   1443 		if (verbose)
   1444 			Printf("packet too short (%d bytes) from %s\n", cc,
   1445 				inet_ntoa(from->sin_addr));
   1446 		return (0);
   1447 	}
   1448 	cc -= hlen;
   1449 	icp = (struct icmp *)(buf + hlen);
   1450 #else
   1451 	icp = (struct icmp *)buf;
   1452 #endif
   1453 	type = icp->icmp_type;
   1454 	code = icp->icmp_code;
   1455 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
   1456 	    type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
   1457 		struct ip *hip;
   1458 		struct udphdr *up;
   1459 		struct icmp *hicmp;
   1460 
   1461 		hip = &icp->icmp_ip;
   1462 		hlen = hip->ip_hl << 2;
   1463 
   1464 		nextmtu = ntohs(icp->icmp_nextmtu);	/* for frag_err() */
   1465 
   1466 		if (useicmp) {
   1467 			/* XXX */
   1468 			if (type == ICMP_ECHOREPLY &&
   1469 			    icp->icmp_id == htons(ident) &&
   1470 			    icp->icmp_seq == htons(seq))
   1471 				return (-2);
   1472 
   1473 			hicmp = (struct icmp *)((u_char *)hip + hlen);
   1474 			/* XXX 8 is a magic number */
   1475 			if (hlen + 8 <= cc &&
   1476 			    hip->ip_p == IPPROTO_ICMP &&
   1477 			    hicmp->icmp_id == htons(ident) &&
   1478 			    hicmp->icmp_seq == htons(seq))
   1479 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1480 		} else {
   1481 			up = (struct udphdr *)((u_char *)hip + hlen);
   1482 			/* XXX 8 is a magic number */
   1483 			if (hlen + 12 <= cc &&
   1484 			    hip->ip_p == IPPROTO_UDP &&
   1485 			    up->uh_sport == htons(ident) &&
   1486 			    up->uh_dport == htons(port + seq))
   1487 				return (type == ICMP_TIMXCEED ? -1 : code + 1);
   1488 		}
   1489 	}
   1490 #ifndef ARCHAIC
   1491 	if (verbose) {
   1492 		int i;
   1493 		u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
   1494 
   1495 		Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
   1496 		Printf("%s: icmp type %d (%s) code %d\n",
   1497 		    inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
   1498 		for (i = 4; i < cc ; i += sizeof(*lp))
   1499 			Printf("%2d: x%8.8x\n", i, *lp++);
   1500 	}
   1501 #endif
   1502 	return(0);
   1503 }
   1504 
   1505 void resize_packet(void)
   1506 {
   1507 	if (useicmp) {
   1508 		outicmp->icmp_cksum = 0;
   1509 		outicmp->icmp_cksum = in_cksum((u_int16_t *)outicmp,
   1510 		    packlen - (sizeof(*outip) + optlen));
   1511 		if (outicmp->icmp_cksum == 0)
   1512 			outicmp->icmp_cksum = 0xffff;
   1513 	} else {
   1514 		outudp->uh_ulen =
   1515 		    htons((u_int16_t)(packlen - (sizeof(*outip) + optlen)));
   1516 	}
   1517 }
   1518 
   1519 void
   1520 print(u_char *buf, int cc, struct sockaddr_in *from)
   1521 {
   1522 	struct ip *ip;
   1523 	int hlen;
   1524 
   1525 	ip = (struct ip *) buf;
   1526 	hlen = ip->ip_hl << 2;
   1527 	cc -= hlen;
   1528 
   1529 	if (as_path)
   1530 		Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
   1531 
   1532 	if (nflag)
   1533 		Printf(" %s", inet_ntoa(from->sin_addr));
   1534 	else
   1535 		Printf(" %s (%s)", inetname(from->sin_addr),
   1536 		    inet_ntoa(from->sin_addr));
   1537 
   1538 	if (verbose)
   1539 		Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
   1540 }
   1541 
   1542 u_int16_t
   1543 in_cksum(u_int16_t *addr, int len)
   1544 {
   1545 
   1546 	return ~in_cksum2(0, addr, len);
   1547 }
   1548 
   1549 /*
   1550  * Checksum routine for Internet Protocol family headers (C Version)
   1551  */
   1552 u_int16_t
   1553 in_cksum2(u_int16_t seed, u_int16_t *addr, int len)
   1554 {
   1555 	int nleft = len;
   1556 	u_int16_t *w = addr;
   1557 	union {
   1558 		u_int16_t w;
   1559 		u_int8_t b[2];
   1560 	} answer;
   1561 	int32_t sum = seed;
   1562 
   1563 	/*
   1564 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
   1565 	 *  we add sequential 16 bit words to it, and at the end, fold
   1566 	 *  back all the carry bits from the top 16 bits into the lower
   1567 	 *  16 bits.
   1568 	 */
   1569 	while (nleft > 1)  {
   1570 		sum += *w++;
   1571 		nleft -= 2;
   1572 	}
   1573 
   1574 	/* mop up an odd byte, if necessary */
   1575 	if (nleft == 1) {
   1576 		answer.b[0] = *(u_char *)w;
   1577 		answer.b[1] = 0;
   1578 		sum += answer.w;
   1579 	}
   1580 
   1581 	/*
   1582 	 * add back carry outs from top 16 bits to low 16 bits
   1583 	 */
   1584 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
   1585 	sum += (sum >> 16);			/* add carry */
   1586 	answer.w = sum;				/* truncate to 16 bits */
   1587 	return (answer.w);
   1588 }
   1589 
   1590 /*
   1591  * Subtract 2 timeval structs:  out = out - in.
   1592  * Out is assumed to be >= in.
   1593  */
   1594 void
   1595 tvsub(struct timeval *out, struct timeval *in)
   1596 {
   1597 
   1598 	if ((out->tv_usec -= in->tv_usec) < 0)   {
   1599 		--out->tv_sec;
   1600 		out->tv_usec += 1000000;
   1601 	}
   1602 	out->tv_sec -= in->tv_sec;
   1603 }
   1604 
   1605 /*
   1606  * Construct an Internet address representation.
   1607  * If the nflag has been supplied, give
   1608  * numeric value, otherwise try for symbolic name.
   1609  */
   1610 char *
   1611 inetname(struct in_addr in)
   1612 {
   1613 	char *cp;
   1614 	struct hostent *hp;
   1615 	static int first = 1;
   1616 	static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
   1617 
   1618 	if (first && !nflag) {
   1619 		int rv;
   1620 
   1621 		first = 0;
   1622 		rv = gethostname(domain, sizeof domain);
   1623 		if (rv == 0 && (cp = strchr(domain, '.')) != NULL) {
   1624 			(void)strlcpy(domain, cp + 1, sizeof(domain));
   1625 		} else
   1626 			domain[0] = '\0';
   1627 	}
   1628 	if (!nflag && in.s_addr != INADDR_ANY) {
   1629 		hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
   1630 		if (hp != NULL) {
   1631 			if ((cp = strchr(hp->h_name, '.')) != NULL &&
   1632 			    strcmp(cp + 1, domain) == 0)
   1633 				*cp = '\0';
   1634 			(void)strlcpy(line, hp->h_name, sizeof(line));
   1635 			return (line);
   1636 		}
   1637 	}
   1638 	return (inet_ntoa(in));
   1639 }
   1640 
   1641 struct hostinfo *
   1642 gethostinfo(char *hostname)
   1643 {
   1644 	int n;
   1645 	struct hostent *hp;
   1646 	struct hostinfo *hi;
   1647 	char **p;
   1648 	u_int32_t *ap;
   1649 	struct in_addr addr;
   1650 
   1651 	hi = calloc(1, sizeof(*hi));
   1652 	if (hi == NULL) {
   1653 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1654 		exit(1);
   1655 	}
   1656 	if (inet_aton(hostname, &addr) != 0) {
   1657 		hi->name = strdup(hostname);
   1658 		if (!hi->name) {
   1659 			Fprintf(stderr, "%s: strdup %s\n", prog,
   1660 			    strerror(errno));
   1661 			exit(1);
   1662 		}
   1663 		hi->n = 1;
   1664 		hi->addrs = calloc(1, sizeof(hi->addrs[0]));
   1665 		if (hi->addrs == NULL) {
   1666 			Fprintf(stderr, "%s: calloc %s\n",
   1667 			    prog, strerror(errno));
   1668 			exit(1);
   1669 		}
   1670 		hi->addrs[0] = addr.s_addr;
   1671 		return (hi);
   1672 	}
   1673 
   1674 	hp = gethostbyname(hostname);
   1675 	if (hp == NULL) {
   1676 		Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
   1677 		exit(1);
   1678 	}
   1679 	if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
   1680 		Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
   1681 		exit(1);
   1682 	}
   1683 	hi->name = strdup(hp->h_name);
   1684 	if (!hi->name) {
   1685 		Fprintf(stderr, "%s: strdup %s\n", prog, strerror(errno));
   1686 		exit(1);
   1687 	}
   1688 	for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
   1689 		continue;
   1690 	hi->n = n;
   1691 	hi->addrs = calloc(n, sizeof(hi->addrs[0]));
   1692 	if (hi->addrs == NULL) {
   1693 		Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
   1694 		exit(1);
   1695 	}
   1696 	for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
   1697 		memcpy(ap, *p, sizeof(*ap));
   1698 	return (hi);
   1699 }
   1700 
   1701 void
   1702 freehostinfo(struct hostinfo *hi)
   1703 {
   1704 	if (hi->name != NULL) {
   1705 		free(hi->name);
   1706 		hi->name = NULL;
   1707 	}
   1708 	free((char *)hi->addrs);
   1709 	free((char *)hi);
   1710 }
   1711 
   1712 void
   1713 getaddr(u_int32_t *ap, char *hostname)
   1714 {
   1715 	struct hostinfo *hi;
   1716 
   1717 	hi = gethostinfo(hostname);
   1718 	*ap = hi->addrs[0];
   1719 	freehostinfo(hi);
   1720 }
   1721 
   1722 void
   1723 setsin(struct sockaddr_in *sin, u_int32_t addr)
   1724 {
   1725 
   1726 	memset(sin, 0, sizeof(*sin));
   1727 #ifdef HAVE_SOCKADDR_SA_LEN
   1728 	sin->sin_len = sizeof(*sin);
   1729 #endif
   1730 	sin->sin_family = AF_INET;
   1731 	sin->sin_addr.s_addr = addr;
   1732 }
   1733 
   1734 /* String to value with optional min and max. Handles decimal and hex. */
   1735 int
   1736 str2val(const char *str, const char *what, int mi, int ma)
   1737 {
   1738 	const char *cp;
   1739 	long val;
   1740 	char *ep;
   1741 
   1742 	errno = 0;
   1743 	ep = NULL;
   1744 	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
   1745 		cp = str + 2;
   1746 		val = strtol(cp, &ep, 16);
   1747 	} else
   1748 		val = strtol(str, &ep, 10);
   1749 	if (errno || str[0] == '\0' || *ep != '\0') {
   1750 		Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
   1751 		    prog, str, what);
   1752 		exit(1);
   1753 	}
   1754 	if (val < mi && mi >= 0) {
   1755 		if (mi == 0)
   1756 			Fprintf(stderr, "%s: %s must be >= %d\n",
   1757 			    prog, what, mi);
   1758 		else
   1759 			Fprintf(stderr, "%s: %s must be > %d\n",
   1760 			    prog, what, mi - 1);
   1761 		exit(1);
   1762 	}
   1763 	if (val > ma && ma >= 0) {
   1764 		Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
   1765 		exit(1);
   1766 	}
   1767 	return ((int)val);
   1768 }
   1769 
   1770 __dead void
   1771 usage(void)
   1772 {
   1773 	extern char version[];
   1774 
   1775 	Fprintf(stderr, "Version %s\n", version);
   1776 	Fprintf(stderr, "usage: %s [-adDFPIlMnrvx] [-g gateway] [-i iface] \
   1777 [-f first_ttl]\n\t[-m max_ttl] [-p port] [-q nqueries] [-s src_addr] [-t tos]\n\t\
   1778 [-w waittime] [-A as_server] host [packetlen]\n",
   1779 	    prog);
   1780 	exit(1);
   1781 }
   1782 
   1783 /*
   1784  * Received ICMP unreachable (fragmentation required and DF set).
   1785  * If the ICMP error was from a "new" router, it'll contain the next-hop
   1786  * MTU that we should use next.  Otherwise we'll just keep going in the
   1787  * mtus[] table, trying until we hit a valid MTU.
   1788  */
   1789 
   1790 
   1791 void
   1792 frag_err()
   1793 {
   1794         int i;
   1795 
   1796         if (nextmtu > 0 && nextmtu < packlen) {
   1797                 Printf("\nfragmentation required and DF set, "
   1798 		     "next hop MTU = %d\n",
   1799                         nextmtu);
   1800                 packlen = nextmtu;
   1801                 for (i = 0; mtus[i] > 0; i++) {
   1802                         if (mtus[i] < nextmtu) {
   1803                                 mtuptr = &mtus[i];    /* next one to try */
   1804                                 break;
   1805                         }
   1806                 }
   1807         } else {
   1808                 Printf("\nfragmentation required and DF set. ");
   1809 		if (nextmtu)
   1810 			Printf("\nBogus next hop MTU = %d > last MTU = %d. ",
   1811 			    nextmtu, packlen);
   1812                 packlen = *mtuptr++;
   1813 		Printf("Trying new MTU = %d\n", packlen);
   1814         }
   1815 	resize_packet();
   1816 }
   1817 
   1818 int
   1819 find_local_ip(struct sockaddr_in *from, struct sockaddr_in *to)
   1820 {
   1821 	int sock;
   1822 	struct sockaddr_in help;
   1823 	int help_len;
   1824 
   1825 	sock = socket(AF_INET, SOCK_DGRAM, 0);
   1826 	if (sock < 0) return (0);
   1827 
   1828 	help.sin_family = AF_INET;
   1829 	/*
   1830 	 * At this point the port number doesn't matter
   1831 	 * since it only has to be greater than zero.
   1832 	 */
   1833 	help.sin_port = 42;
   1834 	help.sin_addr.s_addr = to->sin_addr.s_addr;
   1835 	if (connect(sock, (struct sockaddr *)&help, sizeof(help)) < 0) {
   1836 		(void)close(sock);
   1837 		return (0);
   1838 	}
   1839 
   1840 	help_len = sizeof(help);
   1841 	if (getsockname(sock, (struct sockaddr *)&help, &help_len) < 0 ||
   1842 	    help_len != sizeof(help) ||
   1843 	    help.sin_addr.s_addr == INADDR_ANY) {
   1844 		(void)close(sock);
   1845 		return (0);
   1846 	}
   1847 
   1848 	(void)close(sock);
   1849 	setsin(from, help.sin_addr.s_addr);
   1850 	return (1);
   1851 }
   1852 
   1853 #ifdef IPSEC
   1854 #ifdef IPSEC_POLICY_IPSEC
   1855 int
   1856 setpolicy(so, policy)
   1857 	int so;
   1858 	char *policy;
   1859 {
   1860 	char *buf;
   1861 
   1862 	buf = ipsec_set_policy(policy, strlen(policy));
   1863 	if (buf == NULL) {
   1864 		Fprintf(stderr, "%s: %s\n", prog, ipsec_strerror());
   1865 		return -1;
   1866 	}
   1867 	(void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
   1868 		buf, ipsec_get_policylen(buf));
   1869 
   1870 	free(buf);
   1871 
   1872 	return 0;
   1873 }
   1874 #endif
   1875 #endif
   1876 
   1877