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