]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/traceroute/traceroute.c
This commit was generated by cvs2svn to compensate for changes in r168463,
[FreeBSD/FreeBSD.git] / contrib / traceroute / traceroute.c
1 /*
2  * Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 static const char copyright[] =
24     "@(#) Copyright (c) 1988, 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000\n\
25 The Regents of the University of California.  All rights reserved.\n";
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 #endif
30 static const char rcsid[] =
31     "$FreeBSD$";
32 #endif
33
34 /*
35  * traceroute host  - trace the route ip packets follow going to "host".
36  *
37  * Attempt to trace the route an ip packet would follow to some
38  * internet host.  We find out intermediate hops by launching probe
39  * packets with a small ttl (time to live) then listening for an
40  * icmp "time exceeded" reply from a gateway.  We start our probes
41  * with a ttl of one and increase by one until we get an icmp "port
42  * unreachable" (which means we got to "host") or hit a max (which
43  * defaults to net.inet.ip.ttl hops & can be changed with the -m flag).
44  * Three probes (change with -q flag) are sent at each ttl setting and
45  * a line is printed showing the ttl, address of the gateway and
46  * round trip time of each probe.  If the probe answers come from
47  * different gateways, the address of each responding system will
48  * be printed.  If there is no response within a 5 sec. timeout
49  * interval (changed with the -w flag), a "*" is printed for that
50  * probe.
51  *
52  * Probe packets are UDP format.  We don't want the destination
53  * host to process them so the destination port is set to an
54  * unlikely value (if some clod on the destination is using that
55  * value, it can be changed with the -p flag).
56  *
57  * A sample use might be:
58  *
59  *     [yak 71]% traceroute nis.nsf.net.
60  *     traceroute to nis.nsf.net (35.1.1.48), 64 hops max, 56 byte packet
61  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
62  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
63  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
64  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
65  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
66  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
67  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
68  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
69  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
70  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
71  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
72  *
73  * Note that lines 2 & 3 are the same.  This is due to a buggy
74  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
75  * packets with a zero ttl.
76  *
77  * A more interesting example is:
78  *
79  *     [yak 72]% traceroute allspice.lcs.mit.edu.
80  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 64 hops max
81  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
82  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
83  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
84  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
85  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
86  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
87  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
88  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
89  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
90  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
91  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
92  *     12  * * *
93  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
94  *     14  * * *
95  *     15  * * *
96  *     16  * * *
97  *     17  * * *
98  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
99  *
100  * (I start to see why I'm having so much trouble with mail to
101  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
102  * either don't send ICMP "time exceeded" messages or send them
103  * with a ttl too small to reach us.  14 - 17 are running the
104  * MIT C Gateway code that doesn't send "time exceeded"s.  God
105  * only knows what's going on with 12.
106  *
107  * The silent gateway 12 in the above may be the result of a bug in
108  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
109  * sends an unreachable message using whatever ttl remains in the
110  * original datagram.  Since, for gateways, the remaining ttl is
111  * zero, the icmp "time exceeded" is guaranteed to not make it back
112  * to us.  The behavior of this bug is slightly more interesting
113  * when it appears on the destination system:
114  *
115  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
116  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
117  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
118  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
119  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
120  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
121  *      7  * * *
122  *      8  * * *
123  *      9  * * *
124  *     10  * * *
125  *     11  * * *
126  *     12  * * *
127  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
128  *
129  * Notice that there are 12 "gateways" (13 is the final
130  * destination) and exactly the last half of them are "missing".
131  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
132  * is using the ttl from our arriving datagram as the ttl in its
133  * icmp reply.  So, the reply will time out on the return path
134  * (with no notice sent to anyone since icmp's aren't sent for
135  * icmp's) until we probe with a ttl that's at least twice the path
136  * length.  I.e., rip is really only 7 hops away.  A reply that
137  * returns with a ttl of 1 is a clue this problem exists.
138  * Traceroute prints a "!" after the time if the ttl is <= 1.
139  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
140  * non-standard (HPUX) software, expect to see this problem
141  * frequently and/or take care picking the target host of your
142  * probes.
143  *
144  * Other possible annotations after the time are !H, !N, !P (got a host,
145  * network or protocol unreachable, respectively), !S or !F (source
146  * route failed or fragmentation needed -- neither of these should
147  * ever occur and the associated gateway is busted if you see one).  If
148  * almost all the probes result in some kind of unreachable, traceroute
149  * will give up and exit.
150  *
151  * Notes
152  * -----
153  * This program must be run by root or be setuid.  (I suggest that
154  * you *don't* make it setuid -- casual use could result in a lot
155  * of unnecessary traffic on our poor, congested nets.)
156  *
157  * This program requires a kernel mod that does not appear in any
158  * system available from Berkeley:  A raw ip socket using proto
159  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
160  * opposed to data to be wrapped in a ip datagram).  See the README
161  * file that came with the source to this program for a description
162  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
163  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
164  * MODIFIED TO RUN THIS PROGRAM.
165  *
166  * The udp port usage may appear bizarre (well, ok, it is bizarre).
167  * The problem is that an icmp message only contains 8 bytes of
168  * data from the original datagram.  8 bytes is the size of a udp
169  * header so, if we want to associate replies with the original
170  * datagram, the necessary information must be encoded into the
171  * udp header (the ip id could be used but there's no way to
172  * interlock with the kernel's assignment of ip id's and, anyway,
173  * it would have taken a lot more kernel hacking to allow this
174  * code to set the ip id).  So, to allow two or more users to
175  * use traceroute simultaneously, we use this task's pid as the
176  * source port (the high bit is set to move the port number out
177  * of the "likely" range).  To keep track of which probe is being
178  * replied to (so times and/or hop counts don't get confused by a
179  * reply that was delayed in transit), we increment the destination
180  * port number before each probe.
181  *
182  * Don't use this as a coding example.  I was trying to find a
183  * routing problem and this code sort-of popped out after 48 hours
184  * without sleep.  I was amazed it ever compiled, much less ran.
185  *
186  * I stole the idea for this program from Steve Deering.  Since
187  * the first release, I've learned that had I attended the right
188  * IETF working group meetings, I also could have stolen it from Guy
189  * Almes or Matt Mathis.  I don't know (or care) who came up with
190  * the idea first.  I envy the originators' perspicacity and I'm
191  * glad they didn't keep the idea a secret.
192  *
193  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
194  * enhancements to the original distribution.
195  *
196  * I've hacked up a round-trip-route version of this that works by
197  * sending a loose-source-routed udp datagram through the destination
198  * back to yourself.  Unfortunately, SO many gateways botch source
199  * routing, the thing is almost worthless.  Maybe one day...
200  *
201  *  -- Van Jacobson (van@ee.lbl.gov)
202  *     Tue Dec 20 03:50:13 PST 1988
203  */
204
205 #include <sys/param.h>
206 #include <sys/file.h>
207 #include <sys/ioctl.h>
208 #ifdef HAVE_SYS_SELECT_H
209 #include <sys/select.h>
210 #endif
211 #include <sys/socket.h>
212 #ifdef HAVE_SYS_SYSCTL_H
213 #include <sys/sysctl.h>
214 #endif
215 #include <sys/time.h>
216
217 #include <netinet/in_systm.h>
218 #include <netinet/in.h>
219 #include <netinet/ip.h>
220 #include <netinet/ip_var.h>
221 #include <netinet/ip_icmp.h>
222 #include <netinet/udp.h>
223 #include <netinet/udp_var.h>
224 #include <netinet/tcp.h>
225 #include <netinet/tcpip.h>
226
227 #include <arpa/inet.h>
228
229 #ifdef  IPSEC
230 #include <net/route.h>
231 #include <netinet6/ipsec.h>     /* XXX */
232 #endif  /* IPSEC */
233
234 #include <ctype.h>
235 #include <err.h>
236 #include <errno.h>
237 #include <fcntl.h>
238 #ifdef HAVE_MALLOC_H
239 #include <malloc.h>
240 #endif
241 #include <memory.h>
242 #include <netdb.h>
243 #include <stdio.h>
244 #include <stdlib.h>
245 #include <string.h>
246 #include <unistd.h>
247
248 #include "gnuc.h"
249 #ifdef HAVE_OS_PROTO_H
250 #include "os-proto.h"
251 #endif
252
253 /* rfc1716 */
254 #ifndef ICMP_UNREACH_FILTER_PROHIB
255 #define ICMP_UNREACH_FILTER_PROHIB      13      /* admin prohibited filter */
256 #endif
257 #ifndef ICMP_UNREACH_HOST_PRECEDENCE
258 #define ICMP_UNREACH_HOST_PRECEDENCE    14      /* host precedence violation */
259 #endif
260 #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
261 #define ICMP_UNREACH_PRECEDENCE_CUTOFF  15      /* precedence cutoff */
262 #endif
263
264 #include "findsaddr.h"
265 #include "ifaddrlist.h"
266 #include "traceroute.h"
267
268 /* Maximum number of gateways (include room for one noop) */
269 #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
270
271 #ifndef MAXHOSTNAMELEN
272 #define MAXHOSTNAMELEN  64
273 #endif
274
275 #define Fprintf (void)fprintf
276 #define Printf (void)printf
277
278 /* What a GRE packet header looks like */
279 struct grehdr {
280         u_int16_t   flags;
281         u_int16_t   proto;
282         u_int16_t   length;     /* PPTP version of these fields */
283         u_int16_t   callId;
284 };
285 #ifndef IPPROTO_GRE
286 #define IPPROTO_GRE     47
287 #endif
288
289 /* For GRE, we prepare what looks like a PPTP packet */
290 #define GRE_PPTP_PROTO  0x880b
291
292 /* Host name and address list */
293 struct hostinfo {
294         char *name;
295         int n;
296         u_int32_t *addrs;
297 };
298
299 /* Data section of the probe packet */
300 struct outdata {
301         u_char seq;             /* sequence number of this packet */
302         u_char ttl;             /* ttl packet left with */
303         struct timeval tv;      /* time packet left */
304 };
305
306 #ifndef HAVE_ICMP_NEXTMTU
307 /* Path MTU Discovery (RFC1191) */
308 struct my_pmtu {
309         u_short ipm_void;
310         u_short ipm_nextmtu;
311 };
312 #endif
313
314 u_char  packet[512];            /* last inbound (icmp) packet */
315
316 struct ip *outip;               /* last output ip packet */
317 u_char *outp;           /* last output inner protocol packet */
318
319 struct ip *hip = NULL;          /* Quoted IP header */
320 int hiplen = 0;
321
322 /* loose source route gateway list (including room for final destination) */
323 u_int32_t gwlist[NGATEWAYS + 1];
324
325 int s;                          /* receive (icmp) socket file descriptor */
326 int sndsock;                    /* send (udp) socket file descriptor */
327
328 struct sockaddr whereto;        /* Who to try to reach */
329 struct sockaddr wherefrom;      /* Who we are */
330 int packlen;                    /* total length of packet */
331 int protlen;                    /* length of protocol part of packet */
332 int minpacket;                  /* min ip packet size */
333 int maxpacket = 32 * 1024;      /* max ip packet size */
334 int pmtu;                       /* Path MTU Discovery (RFC1191) */
335 u_int pausemsecs;
336
337 char *prog;
338 char *source;
339 char *hostname;
340 char *device;
341 static const char devnull[] = "/dev/null";
342
343 int nprobes = -1;
344 int max_ttl;
345 int first_ttl = 1;
346 u_short ident;
347 u_short port;                   /* protocol specific base "port" */
348
349 int options;                    /* socket options */
350 int verbose;
351 int waittime = 5;               /* time to wait for response (in seconds) */
352 int nflag;                      /* print addresses numerically */
353 #ifdef CANT_HACK_IPCKSUM
354 int doipcksum = 0;              /* don't calculate ip checksums by default */
355 #else
356 int doipcksum = 1;              /* calculate ip checksums by default */
357 #endif
358 int optlen;                     /* length of ip options */
359 int fixedPort = 0;              /* Use fixed destination port for TCP and UDP */
360 int printdiff = 0;              /* Print the difference between sent and quoted */
361
362 extern int optind;
363 extern int opterr;
364 extern char *optarg;
365
366 /* Forwards */
367 double  deltaT(struct timeval *, struct timeval *);
368 void    freehostinfo(struct hostinfo *);
369 void    getaddr(u_int32_t *, char *);
370 struct  hostinfo *gethostinfo(char *);
371 u_short in_cksum(u_short *, int);
372 char    *inetname(struct in_addr);
373 int     main(int, char **);
374 u_short p_cksum(struct ip *, u_short *, int);
375 int     packet_ok(u_char *, int, struct sockaddr_in *, int);
376 char    *pr_type(u_char);
377 void    print(u_char *, int, struct sockaddr_in *);
378 #ifdef  IPSEC
379 int     setpolicy __P((int so, char *policy));
380 #endif
381 void    send_probe(int, int);
382 struct outproto *setproto(char *);
383 int     str2val(const char *, const char *, int, int);
384 void    tvsub(struct timeval *, struct timeval *);
385 void usage(void);
386 int     wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
387 void pkt_compare(const u_char *, int, const u_char *, int);
388 #ifndef HAVE_USLEEP
389 int     usleep(u_int);
390 #endif
391
392 void    udp_prep(struct outdata *);
393 int     udp_check(const u_char *, int);
394 void    tcp_prep(struct outdata *);
395 int     tcp_check(const u_char *, int);
396 void    gre_prep(struct outdata *);
397 int     gre_check(const u_char *, int);
398 void    gen_prep(struct outdata *);
399 int     gen_check(const u_char *, int);
400 void    icmp_prep(struct outdata *);
401 int     icmp_check(const u_char *, int);
402
403 /* Descriptor structure for each outgoing protocol we support */
404 struct outproto {
405         char    *name;          /* name of protocol */
406         const char *key;        /* An ascii key for the bytes of the header */
407         u_char  num;            /* IP protocol number */
408         u_short hdrlen;         /* max size of protocol header */
409         u_short port;           /* default base protocol-specific "port" */
410         void    (*prepare)(struct outdata *);
411                                 /* finish preparing an outgoing packet */
412         int     (*check)(const u_char *, int);
413                                 /* check an incoming packet */
414 };
415
416 /* List of supported protocols. The first one is the default. The last
417    one is the handler for generic protocols not explicitly listed. */
418 struct  outproto protos[] = {
419         {
420                 "udp",
421                 "spt dpt len sum",
422                 IPPROTO_UDP,
423                 sizeof(struct udphdr),
424                 32768 + 666,
425                 udp_prep,
426                 udp_check
427         },
428         {
429                 "tcp",
430                 "spt dpt seq     ack     xxflwin sum urp",
431                 IPPROTO_TCP,
432                 sizeof(struct tcphdr),
433                 32768 + 666,
434                 tcp_prep,
435                 tcp_check
436         },
437         {
438                 "gre",
439                 "flg pro len clid",
440                 IPPROTO_GRE,
441                 sizeof(struct grehdr),
442                 GRE_PPTP_PROTO,
443                 gre_prep,
444                 gre_check
445         },
446         {
447                 "icmp",
448                 "typ cod sum ",
449                 IPPROTO_ICMP,
450                 sizeof(struct icmp),
451                 0,
452                 icmp_prep,
453                 icmp_check
454         },
455         {
456                 NULL,
457                 NULL,
458                 0,
459                 2 * sizeof(u_short),
460                 0,
461                 gen_prep,
462                 gen_check
463         },
464 };
465 struct  outproto *proto = &protos[0];
466
467 const char *ip_hdr_key = "vhtslen id  off tlprsum srcip   dstip   opts";
468
469 int
470 main(int argc, char **argv)
471 {
472         register int op, code, n;
473         register char *cp;
474         register const char *err;
475         register u_int32_t *ap;
476         register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
477         register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
478         register struct hostinfo *hi;
479         int on = 1;
480         register struct protoent *pe;
481         register int ttl, probe, i;
482         register int seq = 0;
483         int tos = 0, settos = 0;
484         register int lsrr = 0;
485         register u_short off = 0;
486         struct ifaddrlist *al;
487         char errbuf[132];
488         int requestPort = -1;
489         int sump = 0;
490         int sockerrno;
491
492         /* Insure the socket fds won't be 0, 1 or 2 */
493         if (open(devnull, O_RDONLY) < 0 ||
494             open(devnull, O_RDONLY) < 0 ||
495             open(devnull, O_RDONLY) < 0) {
496                 Fprintf(stderr, "%s: open \"%s\": %s\n",
497                     prog, devnull, strerror(errno));
498                 exit(1);
499         }
500         /*
501          * Do the setuid-required stuff first, then lose priveleges ASAP.
502          * Do error checking for these two calls where they appeared in
503          * the original code.
504          */
505         cp = "icmp";
506         pe = getprotobyname(cp);
507         if (pe) {
508                 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
509                         sockerrno = errno;
510                 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
511                         sockerrno = errno;
512         }
513
514         setuid(getuid());
515
516 #ifdef IPCTL_DEFTTL
517         {
518                 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
519                 size_t sz = sizeof(max_ttl);
520
521                 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) {
522                         perror("sysctl(net.inet.ip.ttl)");
523                         exit(1);
524                 }
525         }
526 #else
527         max_ttl = 30;
528 #endif
529
530         if (argv[0] == NULL)
531                 prog = "traceroute";
532         else if ((cp = strrchr(argv[0], '/')) != NULL)
533                 prog = cp + 1;
534         else
535                 prog = argv[0];
536
537         opterr = 0;
538         while ((op = getopt(argc, argv, "edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
539                 switch (op) {
540
541                 case 'd':
542                         options |= SO_DEBUG;
543                         break;
544
545                 case 'D':
546                         printdiff = 1;
547                         break;
548
549                 case 'e':
550                         fixedPort = 1;
551                         break;
552
553                 case 'f':
554                 case 'M':       /* FreeBSD compat. */
555                         first_ttl = str2val(optarg, "first ttl", 1, 255);
556                         break;
557
558                 case 'F':
559                         off = IP_DF;
560                         break;
561
562                 case 'g':
563                         if (lsrr >= NGATEWAYS) {
564                                 Fprintf(stderr,
565                                     "%s: No more than %d gateways\n",
566                                     prog, NGATEWAYS);
567                                 exit(1);
568                         }
569                         getaddr(gwlist + lsrr, optarg);
570                         ++lsrr;
571                         break;
572
573                 case 'i':
574                         device = optarg;
575                         break;
576
577                 case 'I':
578                         proto = setproto("icmp");
579                         break;
580
581                 case 'm':
582                         max_ttl = str2val(optarg, "max ttl", 1, 255);
583                         break;
584
585                 case 'n':
586                         ++nflag;
587                         break;
588
589                 case 'P':
590                         proto = setproto(optarg);
591                         break;
592
593                 case 'p':
594                         requestPort = (u_short)str2val(optarg, "port",
595                             1, (1 << 16) - 1);
596                         break;
597
598                 case 'q':
599                         nprobes = str2val(optarg, "nprobes", 1, -1);
600                         break;
601
602                 case 'r':
603                         options |= SO_DONTROUTE;
604                         break;
605
606                 case 's':
607                         /*
608                          * set the ip source address of the outbound
609                          * probe (e.g., on a multi-homed host).
610                          */
611                         source = optarg;
612                         break;
613
614                 case 'S':
615                         sump = 1;
616                         break;
617
618                 case 't':
619                         tos = str2val(optarg, "tos", 0, 255);
620                         ++settos;
621                         break;
622
623                 case 'v':
624                         ++verbose;
625                         break;
626
627                 case 'x':
628                         doipcksum = (doipcksum == 0);
629                         break;
630
631                 case 'w':
632                         waittime = str2val(optarg, "wait time",
633                             2, 24 * 60 * 60);
634                         break;
635
636                 case 'z':
637                         pausemsecs = str2val(optarg, "pause msecs",
638                             0, 60 * 60 * 1000);
639                         break;
640
641                 default:
642                         usage();
643                 }
644
645         /* Set requested port, if any, else default for this protocol */
646         port = (requestPort != -1) ? requestPort : proto->port;
647
648         if (nprobes == -1)
649                 nprobes = printdiff ? 1 : 3;
650
651         if (first_ttl > max_ttl) {
652                 Fprintf(stderr,
653                     "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
654                     prog, first_ttl, max_ttl);
655                 exit(1);
656         }
657
658         if (!doipcksum)
659                 Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
660
661         if (lsrr > 0)
662                 optlen = (lsrr + 1) * sizeof(gwlist[0]);
663         minpacket = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
664         packlen = minpacket;                    /* minimum sized packet */
665
666         /* Process destination and optional packet size */
667         switch (argc - optind) {
668
669         case 2:
670                 packlen = str2val(argv[optind + 1],
671                     "packet length", minpacket, maxpacket);
672                 /* Fall through */
673
674         case 1:
675                 hostname = argv[optind];
676                 hi = gethostinfo(hostname);
677                 setsin(to, hi->addrs[0]);
678                 if (hi->n > 1)
679                         Fprintf(stderr,
680                     "%s: Warning: %s has multiple addresses; using %s\n",
681                                 prog, hostname, inet_ntoa(to->sin_addr));
682                 hostname = hi->name;
683                 hi->name = NULL;
684                 freehostinfo(hi);
685                 break;
686
687         default:
688                 usage();
689         }
690
691 #ifdef HAVE_SETLINEBUF
692         setlinebuf (stdout);
693 #else
694         setvbuf(stdout, NULL, _IOLBF, 0);
695 #endif
696
697         protlen = packlen - sizeof(*outip) - optlen;
698
699         outip = (struct ip *)malloc((unsigned)packlen);
700         if (outip == NULL) {
701                 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
702                 exit(1);
703         }
704         memset((char *)outip, 0, packlen);
705
706         outip->ip_v = IPVERSION;
707         if (settos)
708                 outip->ip_tos = tos;
709 #ifdef BYTESWAP_IP_HDR
710         outip->ip_len = htons(packlen);
711         outip->ip_off = htons(off);
712 #else
713         outip->ip_len = packlen;
714         outip->ip_off = off;
715 #endif
716         outip->ip_p = proto->num;
717         outp = (u_char *)(outip + 1);
718 #ifdef HAVE_RAW_OPTIONS
719         if (lsrr > 0) {
720                 register u_char *optlist;
721
722                 optlist = outp;
723                 outp += optlen;
724
725                 /* final hop */
726                 gwlist[lsrr] = to->sin_addr.s_addr;
727
728                 outip->ip_dst.s_addr = gwlist[0];
729
730                 /* force 4 byte alignment */
731                 optlist[0] = IPOPT_NOP;
732                 /* loose source route option */
733                 optlist[1] = IPOPT_LSRR;
734                 i = lsrr * sizeof(gwlist[0]);
735                 optlist[2] = i + 3;
736                 /* Pointer to LSRR addresses */
737                 optlist[3] = IPOPT_MINOFF;
738                 memcpy(optlist + 4, gwlist + 1, i);
739         } else
740 #endif
741                 outip->ip_dst = to->sin_addr;
742
743         outip->ip_hl = (outp - (u_char *)outip) >> 2;
744         ident = (getpid() & 0xffff) | 0x8000;
745
746         if (pe == NULL) {
747                 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
748                 exit(1);
749         }
750         if (s < 0) {
751                 errno = sockerrno;
752                 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
753                 exit(1);
754         }
755         if (options & SO_DEBUG)
756                 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
757                     sizeof(on));
758         if (options & SO_DONTROUTE)
759                 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
760                     sizeof(on));
761
762 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
763         if (setpolicy(s, "in bypass") < 0)
764                 errx(1, "%s", ipsec_strerror());
765
766         if (setpolicy(s, "out bypass") < 0)
767                 errx(1, "%s", ipsec_strerror());
768 #endif  /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
769
770         if (sndsock < 0) {
771                 errno = sockerrno;
772                 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
773                 exit(1);
774         }
775
776 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
777         if (lsrr > 0) {
778                 u_char optlist[MAX_IPOPTLEN];
779
780                 cp = "ip";
781                 if ((pe = getprotobyname(cp)) == NULL) {
782                         Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
783                         exit(1);
784                 }
785
786                 /* final hop */
787                 gwlist[lsrr] = to->sin_addr.s_addr;
788                 ++lsrr;
789
790                 /* force 4 byte alignment */
791                 optlist[0] = IPOPT_NOP;
792                 /* loose source route option */
793                 optlist[1] = IPOPT_LSRR;
794                 i = lsrr * sizeof(gwlist[0]);
795                 optlist[2] = i + 3;
796                 /* Pointer to LSRR addresses */
797                 optlist[3] = IPOPT_MINOFF;
798                 memcpy(optlist + 4, gwlist, i);
799
800                 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
801                     (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
802                         Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
803                             prog, strerror(errno));
804                         exit(1);
805                     }
806         }
807 #endif
808
809 #ifdef SO_SNDBUF
810         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
811             sizeof(packlen)) < 0) {
812                 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
813                 exit(1);
814         }
815 #endif
816 #ifdef IP_HDRINCL
817         if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
818             sizeof(on)) < 0) {
819                 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
820                 exit(1);
821         }
822 #else
823 #ifdef IP_TOS
824         if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
825             (char *)&tos, sizeof(tos)) < 0) {
826                 Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
827                     prog, tos, strerror(errno));
828                 exit(1);
829         }
830 #endif
831 #endif
832         if (options & SO_DEBUG)
833                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
834                     sizeof(on));
835         if (options & SO_DONTROUTE)
836                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
837                     sizeof(on));
838
839         /* Get the interface address list */
840         n = ifaddrlist(&al, errbuf);
841         if (n < 0) {
842                 Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
843                 exit(1);
844         }
845         if (n == 0) {
846                 Fprintf(stderr,
847                     "%s: Can't find any network interfaces\n", prog);
848                 exit(1);
849         }
850
851         /* Look for a specific device */
852         if (device != NULL) {
853                 for (i = n; i > 0; --i, ++al)
854                         if (strcmp(device, al->device) == 0)
855                                 break;
856                 if (i <= 0) {
857                         Fprintf(stderr, "%s: Can't find interface %.32s\n",
858                             prog, device);
859                         exit(1);
860                 }
861         }
862
863         /* Determine our source address */
864         if (source == NULL) {
865                 /*
866                  * If a device was specified, use the interface address.
867                  * Otherwise, try to determine our source address.
868                  */
869                 if (device != NULL)
870                         setsin(from, al->addr);
871                 else if ((err = findsaddr(to, from)) != NULL) {
872                         Fprintf(stderr, "%s: findsaddr: %s\n",
873                             prog, err);
874                         exit(1);
875                 }
876         } else {
877                 hi = gethostinfo(source);
878                 source = hi->name;
879                 hi->name = NULL;
880                 /*
881                  * If the device was specified make sure it
882                  * corresponds to the source address specified.
883                  * Otherwise, use the first address (and warn if
884                  * there are more than one).
885                  */
886                 if (device != NULL) {
887                         for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
888                                 if (*ap == al->addr)
889                                         break;
890                         if (i <= 0) {
891                                 Fprintf(stderr,
892                                     "%s: %s is not on interface %.32s\n",
893                                     prog, source, device);
894                                 exit(1);
895                         }
896                         setsin(from, *ap);
897                 } else {
898                         setsin(from, hi->addrs[0]);
899                         if (hi->n > 1)
900                                 Fprintf(stderr,
901                         "%s: Warning: %s has multiple addresses; using %s\n",
902                                     prog, source, inet_ntoa(from->sin_addr));
903                 }
904                 freehostinfo(hi);
905         }
906
907         outip->ip_src = from->sin_addr;
908
909         /* Check the source address (-s), if any, is valid */
910         if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
911                 Fprintf(stderr, "%s: bind: %s\n",
912                     prog, strerror(errno));
913                 exit (1);
914         }
915
916 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
917         if (setpolicy(sndsock, "in bypass") < 0)
918                 errx(1, "%s", ipsec_strerror());
919
920         if (setpolicy(sndsock, "out bypass") < 0)
921                 errx(1, "%s", ipsec_strerror());
922 #endif  /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
923
924         Fprintf(stderr, "%s to %s (%s)",
925             prog, hostname, inet_ntoa(to->sin_addr));
926         if (source)
927                 Fprintf(stderr, " from %s", source);
928         Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
929         (void)fflush(stderr);
930
931         for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
932                 u_int32_t lastaddr = 0;
933                 int gotlastaddr = 0;
934                 int got_there = 0;
935                 int unreachable = 0;
936                 int sentfirst = 0;
937                 int loss;
938
939                 Printf("%2d ", ttl);
940                 for (probe = 0, loss = 0; probe < nprobes; ++probe) {
941                         register int cc;
942                         struct timeval t1, t2;
943                         struct timezone tz;
944                         register struct ip *ip;
945                         struct outdata outdata;
946
947                         if (sentfirst && pausemsecs > 0)
948                                 usleep(pausemsecs * 1000);
949                         /* Prepare outgoing data */
950                         outdata.seq = ++seq;
951                         outdata.ttl = ttl;
952
953                         /* Avoid alignment problems by copying bytewise: */
954                         (void)gettimeofday(&t1, &tz);
955                         memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
956
957                         /* Finalize and send packet */
958                         (*proto->prepare)(&outdata);
959                         send_probe(seq, ttl);
960                         ++sentfirst;
961
962                         /* Wait for a reply */
963                         while ((cc = wait_for_reply(s, from, &t1)) != 0) {
964                                 double T;
965                                 int precis;
966
967                                 (void)gettimeofday(&t2, &tz);
968                                 i = packet_ok(packet, cc, from, seq);
969                                 /* Skip short packet */
970                                 if (i == 0)
971                                         continue;
972                                 if (!gotlastaddr ||
973                                     from->sin_addr.s_addr != lastaddr) {
974                                         if (gotlastaddr) printf("\n   ");
975                                         print(packet, cc, from);
976                                         lastaddr = from->sin_addr.s_addr;
977                                         ++gotlastaddr;
978                                 }
979                                 T = deltaT(&t1, &t2);
980 #ifdef SANE_PRECISION
981                                 if (T >= 1000.0)
982                                         precis = 0;
983                                 else if (T >= 100.0)
984                                         precis = 1;
985                                 else if (T >= 10.0)
986                                         precis = 2;
987                                 else
988 #endif
989                                         precis = 3;
990                                 Printf("  %.*f ms", precis, T);
991                                 if (printdiff) {
992                                         Printf("\n");
993                                         Printf("%*.*s%s\n",
994                                             -(outip->ip_hl << 3),
995                                             outip->ip_hl << 3,
996                                             ip_hdr_key,
997                                             proto->key);
998                                         pkt_compare((void *)outip, packlen,
999                                             (void *)hip, hiplen);
1000                                 }
1001                                 if (i == -2) {
1002 #ifndef ARCHAIC
1003                                         ip = (struct ip *)packet;
1004                                         if (ip->ip_ttl <= 1)
1005                                                 Printf(" !");
1006 #endif
1007                                         ++got_there;
1008                                         break;
1009                                 }
1010                                 /* time exceeded in transit */
1011                                 if (i == -1)
1012                                         break;
1013                                 code = i - 1;
1014                                 switch (code) {
1015
1016                                 case ICMP_UNREACH_PORT:
1017 #ifndef ARCHAIC
1018                                         ip = (struct ip *)packet;
1019                                         if (ip->ip_ttl <= 1)
1020                                                 Printf(" !");
1021 #endif
1022                                         ++got_there;
1023                                         break;
1024
1025                                 case ICMP_UNREACH_NET:
1026                                         ++unreachable;
1027                                         Printf(" !N");
1028                                         break;
1029
1030                                 case ICMP_UNREACH_HOST:
1031                                         ++unreachable;
1032                                         Printf(" !H");
1033                                         break;
1034
1035                                 case ICMP_UNREACH_PROTOCOL:
1036                                         ++got_there;
1037                                         Printf(" !P");
1038                                         break;
1039
1040                                 case ICMP_UNREACH_NEEDFRAG:
1041                                         ++unreachable;
1042                                         Printf(" !F-%d", pmtu);
1043                                         break;
1044
1045                                 case ICMP_UNREACH_SRCFAIL:
1046                                         ++unreachable;
1047                                         Printf(" !S");
1048                                         break;
1049
1050                                 case ICMP_UNREACH_NET_UNKNOWN:
1051                                         ++unreachable;
1052                                         Printf(" !U");
1053                                         break;
1054
1055                                 case ICMP_UNREACH_HOST_UNKNOWN:
1056                                         ++unreachable;
1057                                         Printf(" !W");
1058                                         break;
1059
1060                                 case ICMP_UNREACH_ISOLATED:
1061                                         ++unreachable;
1062                                         Printf(" !I");
1063                                         break;
1064
1065                                 case ICMP_UNREACH_NET_PROHIB:
1066                                         ++unreachable;
1067                                         Printf(" !A");
1068                                         break;
1069
1070                                 case ICMP_UNREACH_HOST_PROHIB:
1071                                         ++unreachable;
1072                                         Printf(" !Z");
1073                                         break;
1074
1075                                 case ICMP_UNREACH_TOSNET:
1076                                         ++unreachable;
1077                                         Printf(" !Q");
1078                                         break;
1079
1080                                 case ICMP_UNREACH_TOSHOST:
1081                                         ++unreachable;
1082                                         Printf(" !T");
1083                                         break;
1084
1085                                 case ICMP_UNREACH_FILTER_PROHIB:
1086                                         ++unreachable;
1087                                         Printf(" !X");
1088                                         break;
1089
1090                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1091                                         ++unreachable;
1092                                         Printf(" !V");
1093                                         break;
1094
1095                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1096                                         ++unreachable;
1097                                         Printf(" !C");
1098                                         break;
1099
1100                                 default:
1101                                         ++unreachable;
1102                                         Printf(" !<%d>", code);
1103                                         break;
1104                                 }
1105                                 break;
1106                         }
1107                         if (cc == 0) {
1108                                 loss++;
1109                                 Printf(" *");
1110                         }
1111                         (void)fflush(stdout);
1112                 }
1113                 if (sump) {
1114                         Printf(" (%d%% loss)", (loss * 100) / nprobes);
1115                 }
1116                 putchar('\n');
1117                 if (got_there ||
1118                     (unreachable > 0 && unreachable >= nprobes - 1))
1119                         break;
1120         }
1121         exit(0);
1122 }
1123
1124 int
1125 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1126     register const struct timeval *tp)
1127 {
1128         fd_set *fdsp;
1129         size_t nfds;
1130         struct timeval now, wait;
1131         struct timezone tz;
1132         register int cc = 0;
1133         register int error;
1134         int fromlen = sizeof(*fromp);
1135
1136         nfds = howmany(sock + 1, NFDBITS);
1137         if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
1138                 err(1, "malloc");
1139         memset(fdsp, 0, nfds * sizeof(fd_mask));
1140         FD_SET(sock, fdsp);
1141
1142         wait.tv_sec = tp->tv_sec + waittime;
1143         wait.tv_usec = tp->tv_usec;
1144         (void)gettimeofday(&now, &tz);
1145         tvsub(&wait, &now);
1146         if (wait.tv_sec < 0) {
1147                 wait.tv_sec = 0;
1148                 wait.tv_usec = 1;
1149         }
1150
1151         error = select(sock + 1, fdsp, NULL, NULL, &wait);
1152         if (error == -1 && errno == EINVAL) {
1153                 Fprintf(stderr, "%s: botched select() args\n", prog);
1154                 exit(1);
1155         }
1156         if (error > 0)
1157                 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
1158                             (struct sockaddr *)fromp, &fromlen);
1159
1160         free(fdsp);
1161         return(cc);
1162 }
1163
1164 void
1165 send_probe(int seq, int ttl)
1166 {
1167         register int cc;
1168
1169         outip->ip_ttl = ttl;
1170         outip->ip_id = htons(ident + seq);
1171
1172         /* XXX undocumented debugging hack */
1173         if (verbose > 1) {
1174                 register const u_short *sp;
1175                 register int nshorts, i;
1176
1177                 sp = (u_short *)outip;
1178                 nshorts = (u_int)packlen / sizeof(u_short);
1179                 i = 0;
1180                 Printf("[ %d bytes", packlen);
1181                 while (--nshorts >= 0) {
1182                         if ((i++ % 8) == 0)
1183                                 Printf("\n\t");
1184                         Printf(" %04x", ntohs(*sp++));
1185                 }
1186                 if (packlen & 1) {
1187                         if ((i % 8) == 0)
1188                                 Printf("\n\t");
1189                         Printf(" %02x", *(u_char *)sp);
1190                 }
1191                 Printf("]\n");
1192         }
1193
1194 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1195         if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1196             (char *)&ttl, sizeof(ttl)) < 0) {
1197                 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1198                     prog, ttl, strerror(errno));
1199                 exit(1);
1200         }
1201 #endif
1202
1203         cc = sendto(sndsock, (char *)outip,
1204             packlen, 0, &whereto, sizeof(whereto));
1205         if (cc < 0 || cc != packlen)  {
1206                 if (cc < 0)
1207                         Fprintf(stderr, "%s: sendto: %s\n",
1208                             prog, strerror(errno));
1209                 Printf("%s: wrote %s %d chars, ret=%d\n",
1210                     prog, hostname, packlen, cc);
1211                 (void)fflush(stdout);
1212         }
1213 }
1214
1215 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1216 int
1217 setpolicy(so, policy)
1218         int so;
1219         char *policy;
1220 {
1221         char *buf;
1222
1223         buf = ipsec_set_policy(policy, strlen(policy));
1224         if (buf == NULL) {
1225                 warnx("%s", ipsec_strerror());
1226                 return -1;
1227         }
1228         (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1229                 buf, ipsec_get_policylen(buf));
1230
1231         free(buf);
1232
1233         return 0;
1234 }
1235 #endif
1236
1237 double
1238 deltaT(struct timeval *t1p, struct timeval *t2p)
1239 {
1240         register double dt;
1241
1242         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1243              (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1244         return (dt);
1245 }
1246
1247 /*
1248  * Convert an ICMP "type" field to a printable string.
1249  */
1250 char *
1251 pr_type(register u_char t)
1252 {
1253         static char *ttab[] = {
1254         "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
1255         "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
1256         "Echo",         "ICMP 9",       "ICMP 10",      "Time Exceeded",
1257         "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
1258         "Info Reply"
1259         };
1260
1261         if (t > 16)
1262                 return("OUT-OF-RANGE");
1263
1264         return(ttab[t]);
1265 }
1266
1267 int
1268 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1269     register int seq)
1270 {
1271         register struct icmp *icp;
1272         register u_char type, code;
1273         register int hlen;
1274 #ifndef ARCHAIC
1275         register struct ip *ip;
1276
1277         ip = (struct ip *) buf;
1278         hlen = ip->ip_hl << 2;
1279         if (cc < hlen + ICMP_MINLEN) {
1280                 if (verbose)
1281                         Printf("packet too short (%d bytes) from %s\n", cc,
1282                                 inet_ntoa(from->sin_addr));
1283                 return (0);
1284         }
1285         cc -= hlen;
1286         icp = (struct icmp *)(buf + hlen);
1287 #else
1288         icp = (struct icmp *)buf;
1289 #endif
1290         type = icp->icmp_type;
1291         code = icp->icmp_code;
1292         /* Path MTU Discovery (RFC1191) */
1293         if (code != ICMP_UNREACH_NEEDFRAG)
1294                 pmtu = 0;
1295         else {
1296 #ifdef HAVE_ICMP_NEXTMTU
1297                 pmtu = ntohs(icp->icmp_nextmtu);
1298 #else
1299                 pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
1300 #endif
1301         }
1302         if (type == ICMP_ECHOREPLY
1303             && proto->num == IPPROTO_ICMP
1304             && (*proto->check)((u_char *)icp, (u_char)seq))
1305                 return -2;
1306         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1307             type == ICMP_UNREACH) {
1308                 u_char *inner;
1309
1310                 hip = &icp->icmp_ip;
1311                 hiplen = ((u_char *)icp + cc) - (u_char *)hip;
1312                 hlen = hip->ip_hl << 2;
1313                 inner = (u_char *)((u_char *)hip + hlen);
1314                 if (hlen + 12 <= cc
1315                     && hip->ip_p == proto->num
1316                     && (*proto->check)(inner, (u_char)seq))
1317                         return (type == ICMP_TIMXCEED ? -1 : code + 1);
1318         }
1319 #ifndef ARCHAIC
1320         if (verbose) {
1321                 register int i;
1322                 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1323
1324                 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1325                 Printf("%s: icmp type %d (%s) code %d\n",
1326                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1327                 for (i = 4; i < cc ; i += sizeof(*lp))
1328                         Printf("%2d: x%8.8x\n", i, *lp++);
1329         }
1330 #endif
1331         return(0);
1332 }
1333
1334 void
1335 icmp_prep(struct outdata *outdata)
1336 {
1337         struct icmp *const icmpheader = (struct icmp *) outp;
1338
1339         icmpheader->icmp_type = ICMP_ECHO;
1340         icmpheader->icmp_id = htons(ident);
1341         icmpheader->icmp_seq = htons(outdata->seq);
1342         icmpheader->icmp_cksum = 0;
1343         icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
1344         if (icmpheader->icmp_cksum == 0)
1345                 icmpheader->icmp_cksum = 0xffff;
1346 }
1347
1348 int
1349 icmp_check(const u_char *data, int seq)
1350 {
1351         struct icmp *const icmpheader = (struct icmp *) data;
1352
1353         return (icmpheader->icmp_id == htons(ident)
1354             && icmpheader->icmp_seq == htons(seq));
1355 }
1356
1357 void
1358 udp_prep(struct outdata *outdata)
1359 {
1360         struct udphdr *const outudp = (struct udphdr *) outp;
1361
1362         outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
1363         outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1364         outudp->uh_ulen = htons((u_short)protlen);
1365         outudp->uh_sum = 0;
1366         if (doipcksum) {
1367             u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
1368             outudp->uh_sum = (sum) ? sum : 0xffff;
1369         }
1370
1371         return;
1372 }
1373
1374 int
1375 udp_check(const u_char *data, int seq)
1376 {
1377         struct udphdr *const udp = (struct udphdr *) data;
1378
1379         return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
1380             ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
1381 }
1382
1383 void
1384 tcp_prep(struct outdata *outdata)
1385 {
1386         struct tcphdr *const tcp = (struct tcphdr *) outp;
1387
1388         tcp->th_sport = htons(ident);
1389         tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1390         tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport +
1391             (fixedPort ? outdata->seq : 0));
1392         tcp->th_ack = 0;
1393         tcp->th_off = 5;
1394         tcp->th_flags = TH_SYN;
1395         tcp->th_sum = 0;
1396
1397         if (doipcksum) {
1398             u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
1399             tcp->th_sum = (sum) ? sum : 0xffff;
1400         }
1401 }
1402
1403 int
1404 tcp_check(const u_char *data, int seq)
1405 {
1406         struct tcphdr *const tcp = (struct tcphdr *) data;
1407
1408         return (ntohs(tcp->th_sport) == ident
1409             && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq))
1410             && tcp->th_seq == (ident << 16) | (port + seq);
1411 }
1412
1413 void
1414 gre_prep(struct outdata *outdata)
1415 {
1416         struct grehdr *const gre = (struct grehdr *) outp;
1417
1418         gre->flags = htons(0x2001);
1419         gre->proto = htons(port);
1420         gre->length = 0;
1421         gre->callId = htons(ident + outdata->seq);
1422 }
1423
1424 int
1425 gre_check(const u_char *data, int seq)
1426 {
1427         struct grehdr *const gre = (struct grehdr *) data;
1428
1429         return(ntohs(gre->proto) == port
1430             && ntohs(gre->callId) == ident + seq);
1431 }
1432
1433 void
1434 gen_prep(struct outdata *outdata)
1435 {
1436         u_int16_t *const ptr = (u_int16_t *) outp;
1437
1438         ptr[0] = htons(ident);
1439         ptr[1] = htons(port + outdata->seq);
1440 }
1441
1442 int
1443 gen_check(const u_char *data, int seq)
1444 {
1445         u_int16_t *const ptr = (u_int16_t *) data;
1446
1447         return(ntohs(ptr[0]) == ident
1448             && ntohs(ptr[1]) == port + seq);
1449 }
1450
1451 void
1452 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1453 {
1454         register struct ip *ip;
1455         register int hlen;
1456
1457         ip = (struct ip *) buf;
1458         hlen = ip->ip_hl << 2;
1459         cc -= hlen;
1460
1461         if (nflag)
1462                 Printf(" %s", inet_ntoa(from->sin_addr));
1463         else
1464                 Printf(" %s (%s)", inetname(from->sin_addr),
1465                     inet_ntoa(from->sin_addr));
1466
1467         if (verbose)
1468                 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1469 }
1470
1471 /*
1472  * Checksum routine for UDP and TCP headers.
1473  */
1474 u_short 
1475 p_cksum(struct ip *ip, u_short *data, int len)
1476 {
1477         static struct ipovly ipo;
1478         u_short sumh, sumd;
1479         u_long sumt;
1480
1481         ipo.ih_pr = ip->ip_p;
1482         ipo.ih_len = htons(len);
1483         ipo.ih_src = ip->ip_src;
1484         ipo.ih_dst = ip->ip_dst;
1485
1486         sumh = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
1487         sumd = in_cksum((u_short*)data, len);         /* payload data cksum */
1488         sumt = (sumh << 16) | (sumd);
1489
1490         return ~in_cksum((u_short*)&sumt, sizeof(sumt));
1491 }
1492
1493 /*
1494  * Checksum routine for Internet Protocol family headers (C Version)
1495  */
1496 u_short
1497 in_cksum(register u_short *addr, register int len)
1498 {
1499         register int nleft = len;
1500         register u_short *w = addr;
1501         register u_short answer;
1502         register int sum = 0;
1503
1504         /*
1505          *  Our algorithm is simple, using a 32 bit accumulator (sum),
1506          *  we add sequential 16 bit words to it, and at the end, fold
1507          *  back all the carry bits from the top 16 bits into the lower
1508          *  16 bits.
1509          */
1510         while (nleft > 1)  {
1511                 sum += *w++;
1512                 nleft -= 2;
1513         }
1514
1515         /* mop up an odd byte, if necessary */
1516         if (nleft == 1)
1517                 sum += *(u_char *)w;
1518
1519         /*
1520          * add back carry outs from top 16 bits to low 16 bits
1521          */
1522         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1523         sum += (sum >> 16);                     /* add carry */
1524         answer = ~sum;                          /* truncate to 16 bits */
1525         return (answer);
1526 }
1527
1528 /*
1529  * Subtract 2 timeval structs:  out = out - in.
1530  * Out is assumed to be within about LONG_MAX seconds of in.
1531  */
1532 void
1533 tvsub(register struct timeval *out, register struct timeval *in)
1534 {
1535
1536         if ((out->tv_usec -= in->tv_usec) < 0)   {
1537                 --out->tv_sec;
1538                 out->tv_usec += 1000000;
1539         }
1540         out->tv_sec -= in->tv_sec;
1541 }
1542
1543 /*
1544  * Construct an Internet address representation.
1545  * If the nflag has been supplied, give
1546  * numeric value, otherwise try for symbolic name.
1547  */
1548 char *
1549 inetname(struct in_addr in)
1550 {
1551         register char *cp;
1552         register struct hostent *hp;
1553         static int first = 1;
1554         static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1555
1556         if (first && !nflag) {
1557                 first = 0;
1558                 if (gethostname(domain, sizeof(domain) - 1) < 0)
1559                         domain[0] = '\0';
1560                 else {
1561                         cp = strchr(domain, '.');
1562                         if (cp == NULL) {
1563                                 hp = gethostbyname(domain);
1564                                 if (hp != NULL)
1565                                         cp = strchr(hp->h_name, '.');
1566                         }
1567                         if (cp == NULL)
1568                                 domain[0] = '\0';
1569                         else {
1570                                 ++cp;
1571                                 (void)strncpy(domain, cp, sizeof(domain) - 1);
1572                                 domain[sizeof(domain) - 1] = '\0';
1573                         }
1574                 }
1575         }
1576         if (!nflag && in.s_addr != INADDR_ANY) {
1577                 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1578                 if (hp != NULL) {
1579                         if ((cp = strchr(hp->h_name, '.')) != NULL &&
1580                             strcmp(cp + 1, domain) == 0)
1581                                 *cp = '\0';
1582                         (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1583                         line[sizeof(line) - 1] = '\0';
1584                         return (line);
1585                 }
1586         }
1587         return (inet_ntoa(in));
1588 }
1589
1590 struct hostinfo *
1591 gethostinfo(register char *hostname)
1592 {
1593         register int n;
1594         register struct hostent *hp;
1595         register struct hostinfo *hi;
1596         register char **p;
1597         register u_int32_t addr, *ap;
1598
1599         if (strlen(hostname) > 64) {
1600                 Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
1601                     prog, hostname);
1602                 exit(1);
1603         }
1604         hi = calloc(1, sizeof(*hi));
1605         if (hi == NULL) {
1606                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1607                 exit(1);
1608         }
1609         addr = inet_addr(hostname);
1610         if ((int32_t)addr != -1) {
1611                 hi->name = strdup(hostname);
1612                 hi->n = 1;
1613                 hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1614                 if (hi->addrs == NULL) {
1615                         Fprintf(stderr, "%s: calloc %s\n",
1616                             prog, strerror(errno));
1617                         exit(1);
1618                 }
1619                 hi->addrs[0] = addr;
1620                 return (hi);
1621         }
1622
1623         hp = gethostbyname(hostname);
1624         if (hp == NULL) {
1625                 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1626                 exit(1);
1627         }
1628         if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1629                 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1630                 exit(1);
1631         }
1632         hi->name = strdup(hp->h_name);
1633         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1634                 continue;
1635         hi->n = n;
1636         hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1637         if (hi->addrs == NULL) {
1638                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1639                 exit(1);
1640         }
1641         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1642                 memcpy(ap, *p, sizeof(*ap));
1643         return (hi);
1644 }
1645
1646 void
1647 freehostinfo(register struct hostinfo *hi)
1648 {
1649         if (hi->name != NULL) {
1650                 free(hi->name);
1651                 hi->name = NULL;
1652         }
1653         free((char *)hi->addrs);
1654         free((char *)hi);
1655 }
1656
1657 void
1658 getaddr(register u_int32_t *ap, register char *hostname)
1659 {
1660         register struct hostinfo *hi;
1661
1662         hi = gethostinfo(hostname);
1663         *ap = hi->addrs[0];
1664         freehostinfo(hi);
1665 }
1666
1667 void
1668 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1669 {
1670
1671         memset(sin, 0, sizeof(*sin));
1672 #ifdef HAVE_SOCKADDR_SA_LEN
1673         sin->sin_len = sizeof(*sin);
1674 #endif
1675         sin->sin_family = AF_INET;
1676         sin->sin_addr.s_addr = addr;
1677 }
1678
1679 /* String to value with optional min and max. Handles decimal and hex. */
1680 int
1681 str2val(register const char *str, register const char *what,
1682     register int mi, register int ma)
1683 {
1684         register const char *cp;
1685         register int val;
1686         char *ep;
1687
1688         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1689                 cp = str + 2;
1690                 val = (int)strtol(cp, &ep, 16);
1691         } else
1692                 val = (int)strtol(str, &ep, 10);
1693         if (*ep != '\0') {
1694                 Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1695                     prog, str, what);
1696                 exit(1);
1697         }
1698         if (val < mi && mi >= 0) {
1699                 if (mi == 0)
1700                         Fprintf(stderr, "%s: %s must be >= %d\n",
1701                             prog, what, mi);
1702                 else
1703                         Fprintf(stderr, "%s: %s must be > %d\n",
1704                             prog, what, mi - 1);
1705                 exit(1);
1706         }
1707         if (val > ma && ma >= 0) {
1708                 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1709                 exit(1);
1710         }
1711         return (val);
1712 }
1713
1714 struct outproto *
1715 setproto(char *pname)
1716 {
1717         struct outproto *proto;
1718         int i;
1719
1720         for (i = 0; protos[i].name != NULL; i++) {
1721                 if (strcasecmp(protos[i].name, pname) == 0) {
1722                         break;
1723                 }
1724         }
1725         proto = &protos[i];
1726         if (proto->name == NULL) {      /* generic handler */
1727                 struct protoent *pe;
1728                 u_long pnum;
1729
1730                 /* Determine the IP protocol number */
1731                 if ((pe = getprotobyname(pname)) != NULL)
1732                         pnum = pe->p_proto;
1733                 else
1734                         pnum = str2val(optarg, "proto number", 1, 255);
1735                 proto->num = pnum;
1736         }
1737         return proto;
1738 }
1739
1740 void
1741 pkt_compare(const u_char *a, int la, const u_char *b, int lb) {
1742         int l;
1743         int i;
1744
1745         for (i = 0; i < la; i++)
1746                 Printf("%02x", (unsigned int)a[i]);
1747         Printf("\n");
1748         l = (la <= lb) ? la : lb;
1749         for (i = 0; i < l; i++)
1750                 if (a[i] == b[i])
1751                         Printf("__");
1752                 else
1753                         Printf("%02x", (unsigned int)b[i]);
1754         for (; i < lb; i++)
1755                 Printf("%02x", (unsigned int)b[i]);
1756         Printf("\n");
1757 }
1758
1759
1760 void
1761 usage(void)
1762 {
1763         extern char version[];
1764
1765         Fprintf(stderr, "Version %s\n", version);
1766         Fprintf(stderr,
1767             "Usage: %s [-dDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n"
1768             "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1769             "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
1770         exit(1);
1771 }