]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/traceroute/traceroute.c
This commit was generated by cvs2svn to compensate for changes in r161561,
[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 /* loose source route gateway list (including room for final destination) */
320 u_int32_t gwlist[NGATEWAYS + 1];
321
322 int s;                          /* receive (icmp) socket file descriptor */
323 int sndsock;                    /* send (udp) socket file descriptor */
324
325 struct sockaddr whereto;        /* Who to try to reach */
326 struct sockaddr wherefrom;      /* Who we are */
327 int packlen;                    /* total length of packet */
328 int protlen;                    /* length of protocol part of packet */
329 int minpacket;                  /* min ip packet size */
330 int maxpacket = 32 * 1024;      /* max ip packet size */
331 int pmtu;                       /* Path MTU Discovery (RFC1191) */
332 u_int pausemsecs;
333
334 char *prog;
335 char *source;
336 char *hostname;
337 char *device;
338 static const char devnull[] = "/dev/null";
339
340 int nprobes = 3;
341 int max_ttl;
342 int first_ttl = 1;
343 u_short ident;
344 u_short port;                   /* protocol specific base "port" */
345
346 int options;                    /* socket options */
347 int verbose;
348 int waittime = 5;               /* time to wait for response (in seconds) */
349 int nflag;                      /* print addresses numerically */
350 #ifdef CANT_HACK_IPCKSUM
351 int doipcksum = 0;              /* don't calculate ip checksums by default */
352 #else
353 int doipcksum = 1;              /* calculate ip checksums by default */
354 #endif
355 int optlen;                     /* length of ip options */
356 int fixedPort = 0;              /* Use fixed destination port for TCP and UDP */
357
358 extern int optind;
359 extern int opterr;
360 extern char *optarg;
361
362 /* Forwards */
363 double  deltaT(struct timeval *, struct timeval *);
364 void    freehostinfo(struct hostinfo *);
365 void    getaddr(u_int32_t *, char *);
366 struct  hostinfo *gethostinfo(char *);
367 u_short in_cksum(u_short *, int);
368 char    *inetname(struct in_addr);
369 int     main(int, char **);
370 u_short p_cksum(struct ip *, u_short *, int);
371 int     packet_ok(u_char *, int, struct sockaddr_in *, int);
372 char    *pr_type(u_char);
373 void    print(u_char *, int, struct sockaddr_in *);
374 #ifdef  IPSEC
375 int     setpolicy __P((int so, char *policy));
376 #endif
377 void    send_probe(int, int);
378 struct outproto *setproto(char *);
379 int     str2val(const char *, const char *, int, int);
380 void    tvsub(struct timeval *, struct timeval *);
381 void usage(void);
382 int     wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
383 #ifndef HAVE_USLEEP
384 int     usleep(u_int);
385 #endif
386
387 void    udp_prep(struct outdata *);
388 int     udp_check(const u_char *, int);
389 void    tcp_prep(struct outdata *);
390 int     tcp_check(const u_char *, int);
391 void    gre_prep(struct outdata *);
392 int     gre_check(const u_char *, int);
393 void    gen_prep(struct outdata *);
394 int     gen_check(const u_char *, int);
395 void    icmp_prep(struct outdata *);
396 int     icmp_check(const u_char *, int);
397
398 /* Descriptor structure for each outgoing protocol we support */
399 struct outproto {
400         char    *name;          /* name of protocol */
401         u_char  num;            /* IP protocol number */
402         u_short hdrlen;         /* max size of protocol header */
403         u_short port;           /* default base protocol-specific "port" */
404         void    (*prepare)(struct outdata *);
405                                 /* finish preparing an outgoing packet */
406         int     (*check)(const u_char *, int);
407                                 /* check an incoming packet */
408 };
409
410 /* List of supported protocols. The first one is the default. The last
411    one is the handler for generic protocols not explicitly listed. */
412 struct  outproto protos[] = {
413         {
414                 "udp",
415                 IPPROTO_UDP,
416                 sizeof(struct udphdr),
417                 32768 + 666,
418                 udp_prep,
419                 udp_check
420         },
421         {
422                 "tcp",
423                 IPPROTO_TCP,
424                 sizeof(struct tcphdr),
425                 32768 + 666,
426                 tcp_prep,
427                 tcp_check
428         },
429         {
430                 "gre",
431                 IPPROTO_GRE,
432                 sizeof(struct grehdr),
433                 GRE_PPTP_PROTO,
434                 gre_prep,
435                 gre_check
436         },
437         {
438                 "icmp",
439                 IPPROTO_ICMP,
440                 sizeof(struct icmp),
441                 0,
442                 icmp_prep,
443                 icmp_check
444         },
445         {
446                 NULL,
447                 0,
448                 2 * sizeof(u_short),
449                 0,
450                 gen_prep,
451                 gen_check
452         },
453 };
454 struct  outproto *proto = &protos[0];
455
456 int
457 main(int argc, char **argv)
458 {
459         register int op, code, n;
460         register char *cp;
461         register const char *err;
462         register u_int32_t *ap;
463         register struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
464         register struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
465         register struct hostinfo *hi;
466         int on = 1;
467         register struct protoent *pe;
468         register int ttl, probe, i;
469         register int seq = 0;
470         int tos = 0, settos = 0;
471         register int lsrr = 0;
472         register u_short off = 0;
473         struct ifaddrlist *al;
474         char errbuf[132];
475         int requestPort = -1;
476         int sump = 0;
477         int sockerrno;
478
479         /* Insure the socket fds won't be 0, 1 or 2 */
480         if (open(devnull, O_RDONLY) < 0 ||
481             open(devnull, O_RDONLY) < 0 ||
482             open(devnull, O_RDONLY) < 0) {
483                 Fprintf(stderr, "%s: open \"%s\": %s\n",
484                     prog, devnull, strerror(errno));
485                 exit(1);
486         }
487         /*
488          * Do the setuid-required stuff first, then lose priveleges ASAP.
489          * Do error checking for these two calls where they appeared in
490          * the original code.
491          */
492         cp = "icmp";
493         pe = getprotobyname(cp);
494         if (pe) {
495                 if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0)
496                         sockerrno = errno;
497                 else if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
498                         sockerrno = errno;
499         }
500
501         setuid(getuid());
502
503 #ifdef IPCTL_DEFTTL
504         {
505                 int mib[4] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL };
506                 size_t sz = sizeof(max_ttl);
507
508                 if (sysctl(mib, 4, &max_ttl, &sz, NULL, 0) == -1) {
509                         perror("sysctl(net.inet.ip.ttl)");
510                         exit(1);
511                 }
512         }
513 #else
514         max_ttl = 30;
515 #endif
516
517         if (argv[0] == NULL)
518                 prog = "traceroute";
519         else if ((cp = strrchr(argv[0], '/')) != NULL)
520                 prog = cp + 1;
521         else
522                 prog = argv[0];
523
524         opterr = 0;
525         while ((op = getopt(argc, argv, "edFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
526                 switch (op) {
527
528                 case 'd':
529                         options |= SO_DEBUG;
530                         break;
531
532                 case 'e':
533                         fixedPort = 1;
534                         break;
535
536                 case 'f':
537                 case 'M':       /* FreeBSD compat. */
538                         first_ttl = str2val(optarg, "first ttl", 1, 255);
539                         break;
540
541                 case 'F':
542                         off = IP_DF;
543                         break;
544
545                 case 'g':
546                         if (lsrr >= NGATEWAYS) {
547                                 Fprintf(stderr,
548                                     "%s: No more than %d gateways\n",
549                                     prog, NGATEWAYS);
550                                 exit(1);
551                         }
552                         getaddr(gwlist + lsrr, optarg);
553                         ++lsrr;
554                         break;
555
556                 case 'i':
557                         device = optarg;
558                         break;
559
560                 case 'I':
561                         proto = setproto("icmp");
562                         break;
563
564                 case 'm':
565                         max_ttl = str2val(optarg, "max ttl", 1, 255);
566                         break;
567
568                 case 'n':
569                         ++nflag;
570                         break;
571
572                 case 'P':
573                         proto = setproto(optarg);
574                         break;
575
576                 case 'p':
577                         requestPort = (u_short)str2val(optarg, "port",
578                             1, (1 << 16) - 1);
579                         break;
580
581                 case 'q':
582                         nprobes = str2val(optarg, "nprobes", 1, -1);
583                         break;
584
585                 case 'r':
586                         options |= SO_DONTROUTE;
587                         break;
588
589                 case 's':
590                         /*
591                          * set the ip source address of the outbound
592                          * probe (e.g., on a multi-homed host).
593                          */
594                         source = optarg;
595                         break;
596
597                 case 'S':
598                         sump = 1;
599                         break;
600
601                 case 't':
602                         tos = str2val(optarg, "tos", 0, 255);
603                         ++settos;
604                         break;
605
606                 case 'v':
607                         ++verbose;
608                         break;
609
610                 case 'x':
611                         doipcksum = (doipcksum == 0);
612                         break;
613
614                 case 'w':
615                         waittime = str2val(optarg, "wait time",
616                             2, 24 * 60 * 60);
617                         break;
618
619                 case 'z':
620                         pausemsecs = str2val(optarg, "pause msecs",
621                             0, 60 * 60 * 1000);
622                         break;
623
624                 default:
625                         usage();
626                 }
627
628         /* Set requested port, if any, else default for this protocol */
629         port = (requestPort != -1) ? requestPort : proto->port;
630
631         if (first_ttl > max_ttl) {
632                 Fprintf(stderr,
633                     "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
634                     prog, first_ttl, max_ttl);
635                 exit(1);
636         }
637
638         if (!doipcksum)
639                 Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
640
641         if (lsrr > 0)
642                 optlen = (lsrr + 1) * sizeof(gwlist[0]);
643         minpacket = sizeof(*outip) + proto->hdrlen + sizeof(struct outdata) + optlen;
644         packlen = minpacket;                    /* minimum sized packet */
645
646         /* Process destination and optional packet size */
647         switch (argc - optind) {
648
649         case 2:
650                 packlen = str2val(argv[optind + 1],
651                     "packet length", minpacket, maxpacket);
652                 /* Fall through */
653
654         case 1:
655                 hostname = argv[optind];
656                 hi = gethostinfo(hostname);
657                 setsin(to, hi->addrs[0]);
658                 if (hi->n > 1)
659                         Fprintf(stderr,
660                     "%s: Warning: %s has multiple addresses; using %s\n",
661                                 prog, hostname, inet_ntoa(to->sin_addr));
662                 hostname = hi->name;
663                 hi->name = NULL;
664                 freehostinfo(hi);
665                 break;
666
667         default:
668                 usage();
669         }
670
671 #ifdef HAVE_SETLINEBUF
672         setlinebuf (stdout);
673 #else
674         setvbuf(stdout, NULL, _IOLBF, 0);
675 #endif
676
677         protlen = packlen - sizeof(*outip) - optlen;
678
679         outip = (struct ip *)malloc((unsigned)packlen);
680         if (outip == NULL) {
681                 Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
682                 exit(1);
683         }
684         memset((char *)outip, 0, packlen);
685
686         outip->ip_v = IPVERSION;
687         if (settos)
688                 outip->ip_tos = tos;
689 #ifdef BYTESWAP_IP_HDR
690         outip->ip_len = htons(packlen);
691         outip->ip_off = htons(off);
692 #else
693         outip->ip_len = packlen;
694         outip->ip_off = off;
695 #endif
696         outip->ip_p = proto->num;
697         outp = (u_char *)(outip + 1);
698 #ifdef HAVE_RAW_OPTIONS
699         if (lsrr > 0) {
700                 register u_char *optlist;
701
702                 optlist = outp;
703                 outp += optlen;
704
705                 /* final hop */
706                 gwlist[lsrr] = to->sin_addr.s_addr;
707
708                 outip->ip_dst.s_addr = gwlist[0];
709
710                 /* force 4 byte alignment */
711                 optlist[0] = IPOPT_NOP;
712                 /* loose source route option */
713                 optlist[1] = IPOPT_LSRR;
714                 i = lsrr * sizeof(gwlist[0]);
715                 optlist[2] = i + 3;
716                 /* Pointer to LSRR addresses */
717                 optlist[3] = IPOPT_MINOFF;
718                 memcpy(optlist + 4, gwlist + 1, i);
719         } else
720 #endif
721                 outip->ip_dst = to->sin_addr;
722
723         outip->ip_hl = (outp - (u_char *)outip) >> 2;
724         ident = (getpid() & 0xffff) | 0x8000;
725
726         if (pe == NULL) {
727                 Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
728                 exit(1);
729         }
730         if (s < 0) {
731                 errno = sockerrno;
732                 Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
733                 exit(1);
734         }
735         if (options & SO_DEBUG)
736                 (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
737                     sizeof(on));
738         if (options & SO_DONTROUTE)
739                 (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
740                     sizeof(on));
741
742 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
743         if (setpolicy(s, "in bypass") < 0)
744                 errx(1, "%s", ipsec_strerror());
745
746         if (setpolicy(s, "out bypass") < 0)
747                 errx(1, "%s", ipsec_strerror());
748 #endif  /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
749
750         if (sndsock < 0) {
751                 errno = sockerrno;
752                 Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
753                 exit(1);
754         }
755
756 #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
757         if (lsrr > 0) {
758                 u_char optlist[MAX_IPOPTLEN];
759
760                 cp = "ip";
761                 if ((pe = getprotobyname(cp)) == NULL) {
762                         Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
763                         exit(1);
764                 }
765
766                 /* final hop */
767                 gwlist[lsrr] = to->sin_addr.s_addr;
768                 ++lsrr;
769
770                 /* force 4 byte alignment */
771                 optlist[0] = IPOPT_NOP;
772                 /* loose source route option */
773                 optlist[1] = IPOPT_LSRR;
774                 i = lsrr * sizeof(gwlist[0]);
775                 optlist[2] = i + 3;
776                 /* Pointer to LSRR addresses */
777                 optlist[3] = IPOPT_MINOFF;
778                 memcpy(optlist + 4, gwlist, i);
779
780                 if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
781                     (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
782                         Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
783                             prog, strerror(errno));
784                         exit(1);
785                     }
786         }
787 #endif
788
789 #ifdef SO_SNDBUF
790         if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
791             sizeof(packlen)) < 0) {
792                 Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
793                 exit(1);
794         }
795 #endif
796 #ifdef IP_HDRINCL
797         if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
798             sizeof(on)) < 0) {
799                 Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
800                 exit(1);
801         }
802 #else
803 #ifdef IP_TOS
804         if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
805             (char *)&tos, sizeof(tos)) < 0) {
806                 Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
807                     prog, tos, strerror(errno));
808                 exit(1);
809         }
810 #endif
811 #endif
812         if (options & SO_DEBUG)
813                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
814                     sizeof(on));
815         if (options & SO_DONTROUTE)
816                 (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
817                     sizeof(on));
818
819         /* Get the interface address list */
820         n = ifaddrlist(&al, errbuf);
821         if (n < 0) {
822                 Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
823                 exit(1);
824         }
825         if (n == 0) {
826                 Fprintf(stderr,
827                     "%s: Can't find any network interfaces\n", prog);
828                 exit(1);
829         }
830
831         /* Look for a specific device */
832         if (device != NULL) {
833                 for (i = n; i > 0; --i, ++al)
834                         if (strcmp(device, al->device) == 0)
835                                 break;
836                 if (i <= 0) {
837                         Fprintf(stderr, "%s: Can't find interface %.32s\n",
838                             prog, device);
839                         exit(1);
840                 }
841         }
842
843         /* Determine our source address */
844         if (source == NULL) {
845                 /*
846                  * If a device was specified, use the interface address.
847                  * Otherwise, try to determine our source address.
848                  */
849                 if (device != NULL)
850                         setsin(from, al->addr);
851                 else if ((err = findsaddr(to, from)) != NULL) {
852                         Fprintf(stderr, "%s: findsaddr: %s\n",
853                             prog, err);
854                         exit(1);
855                 }
856         } else {
857                 hi = gethostinfo(source);
858                 source = hi->name;
859                 hi->name = NULL;
860                 /*
861                  * If the device was specified make sure it
862                  * corresponds to the source address specified.
863                  * Otherwise, use the first address (and warn if
864                  * there are more than one).
865                  */
866                 if (device != NULL) {
867                         for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
868                                 if (*ap == al->addr)
869                                         break;
870                         if (i <= 0) {
871                                 Fprintf(stderr,
872                                     "%s: %s is not on interface %.32s\n",
873                                     prog, source, device);
874                                 exit(1);
875                         }
876                         setsin(from, *ap);
877                 } else {
878                         setsin(from, hi->addrs[0]);
879                         if (hi->n > 1)
880                                 Fprintf(stderr,
881                         "%s: Warning: %s has multiple addresses; using %s\n",
882                                     prog, source, inet_ntoa(from->sin_addr));
883                 }
884                 freehostinfo(hi);
885         }
886
887         outip->ip_src = from->sin_addr;
888
889         /* Check the source address (-s), if any, is valid */
890         if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
891                 Fprintf(stderr, "%s: bind: %s\n",
892                     prog, strerror(errno));
893                 exit (1);
894         }
895
896 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
897         if (setpolicy(sndsock, "in bypass") < 0)
898                 errx(1, "%s", ipsec_strerror());
899
900         if (setpolicy(sndsock, "out bypass") < 0)
901                 errx(1, "%s", ipsec_strerror());
902 #endif  /* defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) */
903
904         Fprintf(stderr, "%s to %s (%s)",
905             prog, hostname, inet_ntoa(to->sin_addr));
906         if (source)
907                 Fprintf(stderr, " from %s", source);
908         Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
909         (void)fflush(stderr);
910
911         for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
912                 u_int32_t lastaddr = 0;
913                 int gotlastaddr = 0;
914                 int got_there = 0;
915                 int unreachable = 0;
916                 int sentfirst = 0;
917                 int loss;
918
919                 Printf("%2d ", ttl);
920                 for (probe = 0, loss = 0; probe < nprobes; ++probe) {
921                         register int cc;
922                         struct timeval t1, t2;
923                         struct timezone tz;
924                         register struct ip *ip;
925                         struct outdata outdata;
926
927                         if (sentfirst && pausemsecs > 0)
928                                 usleep(pausemsecs * 1000);
929                         /* Prepare outgoing data */
930                         outdata.seq = ++seq;
931                         outdata.ttl = ttl;
932
933                         /* Avoid alignment problems by copying bytewise: */
934                         (void)gettimeofday(&t1, &tz);
935                         memcpy(&outdata.tv, &t1, sizeof(outdata.tv));
936
937                         /* Finalize and send packet */
938                         (*proto->prepare)(&outdata);
939                         send_probe(seq, ttl);
940                         ++sentfirst;
941
942                         /* Wait for a reply */
943                         while ((cc = wait_for_reply(s, from, &t1)) != 0) {
944                                 double T;
945                                 int precis;
946
947                                 (void)gettimeofday(&t2, &tz);
948                                 i = packet_ok(packet, cc, from, seq);
949                                 /* Skip short packet */
950                                 if (i == 0)
951                                         continue;
952                                 if (!gotlastaddr ||
953                                     from->sin_addr.s_addr != lastaddr) {
954                                         if (gotlastaddr) printf("\n   ");
955                                         print(packet, cc, from);
956                                         lastaddr = from->sin_addr.s_addr;
957                                         ++gotlastaddr;
958                                 }
959                                 T = deltaT(&t1, &t2);
960 #ifdef SANE_PRECISION
961                                 if (T >= 1000.0)
962                                         precis = 0;
963                                 else if (T >= 100.0)
964                                         precis = 1;
965                                 else if (T >= 10.0)
966                                         precis = 2;
967                                 else
968 #endif
969                                         precis = 3;
970                                 Printf("  %.*f ms", precis, T);
971                                 if (i == -2) {
972 #ifndef ARCHAIC
973                                         ip = (struct ip *)packet;
974                                         if (ip->ip_ttl <= 1)
975                                                 Printf(" !");
976 #endif
977                                         ++got_there;
978                                         break;
979                                 }
980                                 /* time exceeded in transit */
981                                 if (i == -1)
982                                         break;
983                                 code = i - 1;
984                                 switch (code) {
985
986                                 case ICMP_UNREACH_PORT:
987 #ifndef ARCHAIC
988                                         ip = (struct ip *)packet;
989                                         if (ip->ip_ttl <= 1)
990                                                 Printf(" !");
991 #endif
992                                         ++got_there;
993                                         break;
994
995                                 case ICMP_UNREACH_NET:
996                                         ++unreachable;
997                                         Printf(" !N");
998                                         break;
999
1000                                 case ICMP_UNREACH_HOST:
1001                                         ++unreachable;
1002                                         Printf(" !H");
1003                                         break;
1004
1005                                 case ICMP_UNREACH_PROTOCOL:
1006                                         ++got_there;
1007                                         Printf(" !P");
1008                                         break;
1009
1010                                 case ICMP_UNREACH_NEEDFRAG:
1011                                         ++unreachable;
1012                                         Printf(" !F-%d", pmtu);
1013                                         break;
1014
1015                                 case ICMP_UNREACH_SRCFAIL:
1016                                         ++unreachable;
1017                                         Printf(" !S");
1018                                         break;
1019
1020                                 case ICMP_UNREACH_NET_UNKNOWN:
1021                                         ++unreachable;
1022                                         Printf(" !U");
1023                                         break;
1024
1025                                 case ICMP_UNREACH_HOST_UNKNOWN:
1026                                         ++unreachable;
1027                                         Printf(" !W");
1028                                         break;
1029
1030                                 case ICMP_UNREACH_ISOLATED:
1031                                         ++unreachable;
1032                                         Printf(" !I");
1033                                         break;
1034
1035                                 case ICMP_UNREACH_NET_PROHIB:
1036                                         ++unreachable;
1037                                         Printf(" !A");
1038                                         break;
1039
1040                                 case ICMP_UNREACH_HOST_PROHIB:
1041                                         ++unreachable;
1042                                         Printf(" !Z");
1043                                         break;
1044
1045                                 case ICMP_UNREACH_TOSNET:
1046                                         ++unreachable;
1047                                         Printf(" !Q");
1048                                         break;
1049
1050                                 case ICMP_UNREACH_TOSHOST:
1051                                         ++unreachable;
1052                                         Printf(" !T");
1053                                         break;
1054
1055                                 case ICMP_UNREACH_FILTER_PROHIB:
1056                                         ++unreachable;
1057                                         Printf(" !X");
1058                                         break;
1059
1060                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1061                                         ++unreachable;
1062                                         Printf(" !V");
1063                                         break;
1064
1065                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1066                                         ++unreachable;
1067                                         Printf(" !C");
1068                                         break;
1069
1070                                 default:
1071                                         ++unreachable;
1072                                         Printf(" !<%d>", code);
1073                                         break;
1074                                 }
1075                                 break;
1076                         }
1077                         if (cc == 0) {
1078                                 loss++;
1079                                 Printf(" *");
1080                         }
1081                         (void)fflush(stdout);
1082                 }
1083                 if (sump) {
1084                         Printf(" (%d%% loss)", (loss * 100) / nprobes);
1085                 }
1086                 putchar('\n');
1087                 if (got_there ||
1088                     (unreachable > 0 && unreachable >= nprobes - 1))
1089                         break;
1090         }
1091         exit(0);
1092 }
1093
1094 int
1095 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1096     register const struct timeval *tp)
1097 {
1098         fd_set *fdsp;
1099         size_t nfds;
1100         struct timeval now, wait;
1101         struct timezone tz;
1102         register int cc = 0;
1103         register int error;
1104         int fromlen = sizeof(*fromp);
1105
1106         nfds = howmany(sock + 1, NFDBITS);
1107         if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
1108                 err(1, "malloc");
1109         memset(fdsp, 0, nfds * sizeof(fd_mask));
1110         FD_SET(sock, fdsp);
1111
1112         wait.tv_sec = tp->tv_sec + waittime;
1113         wait.tv_usec = tp->tv_usec;
1114         (void)gettimeofday(&now, &tz);
1115         tvsub(&wait, &now);
1116         if (wait.tv_sec < 0) {
1117                 wait.tv_sec = 0;
1118                 wait.tv_usec = 1;
1119         }
1120
1121         error = select(sock + 1, fdsp, NULL, NULL, &wait);
1122         if (error == -1 && errno == EINVAL) {
1123                 Fprintf(stderr, "%s: botched select() args\n", prog);
1124                 exit(1);
1125         }
1126         if (error > 0)
1127                 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
1128                             (struct sockaddr *)fromp, &fromlen);
1129
1130         free(fdsp);
1131         return(cc);
1132 }
1133
1134 void
1135 send_probe(int seq, int ttl)
1136 {
1137         register int cc;
1138
1139         outip->ip_ttl = ttl;
1140         outip->ip_id = htons(ident + seq);
1141
1142         /* XXX undocumented debugging hack */
1143         if (verbose > 1) {
1144                 register const u_short *sp;
1145                 register int nshorts, i;
1146
1147                 sp = (u_short *)outip;
1148                 nshorts = (u_int)packlen / sizeof(u_short);
1149                 i = 0;
1150                 Printf("[ %d bytes", packlen);
1151                 while (--nshorts >= 0) {
1152                         if ((i++ % 8) == 0)
1153                                 Printf("\n\t");
1154                         Printf(" %04x", ntohs(*sp++));
1155                 }
1156                 if (packlen & 1) {
1157                         if ((i % 8) == 0)
1158                                 Printf("\n\t");
1159                         Printf(" %02x", *(u_char *)sp);
1160                 }
1161                 Printf("]\n");
1162         }
1163
1164 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1165         if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1166             (char *)&ttl, sizeof(ttl)) < 0) {
1167                 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1168                     prog, ttl, strerror(errno));
1169                 exit(1);
1170         }
1171 #endif
1172
1173         cc = sendto(sndsock, (char *)outip,
1174             packlen, 0, &whereto, sizeof(whereto));
1175         if (cc < 0 || cc != packlen)  {
1176                 if (cc < 0)
1177                         Fprintf(stderr, "%s: sendto: %s\n",
1178                             prog, strerror(errno));
1179                 Printf("%s: wrote %s %d chars, ret=%d\n",
1180                     prog, hostname, packlen, cc);
1181                 (void)fflush(stdout);
1182         }
1183 }
1184
1185 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1186 int
1187 setpolicy(so, policy)
1188         int so;
1189         char *policy;
1190 {
1191         char *buf;
1192
1193         buf = ipsec_set_policy(policy, strlen(policy));
1194         if (buf == NULL) {
1195                 warnx("%s", ipsec_strerror());
1196                 return -1;
1197         }
1198         (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1199                 buf, ipsec_get_policylen(buf));
1200
1201         free(buf);
1202
1203         return 0;
1204 }
1205 #endif
1206
1207 double
1208 deltaT(struct timeval *t1p, struct timeval *t2p)
1209 {
1210         register double dt;
1211
1212         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1213              (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1214         return (dt);
1215 }
1216
1217 /*
1218  * Convert an ICMP "type" field to a printable string.
1219  */
1220 char *
1221 pr_type(register u_char t)
1222 {
1223         static char *ttab[] = {
1224         "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
1225         "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
1226         "Echo",         "ICMP 9",       "ICMP 10",      "Time Exceeded",
1227         "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
1228         "Info Reply"
1229         };
1230
1231         if (t > 16)
1232                 return("OUT-OF-RANGE");
1233
1234         return(ttab[t]);
1235 }
1236
1237 int
1238 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1239     register int seq)
1240 {
1241         register struct icmp *icp;
1242         register u_char type, code;
1243         register int hlen;
1244 #ifndef ARCHAIC
1245         register struct ip *ip;
1246
1247         ip = (struct ip *) buf;
1248         hlen = ip->ip_hl << 2;
1249         if (cc < hlen + ICMP_MINLEN) {
1250                 if (verbose)
1251                         Printf("packet too short (%d bytes) from %s\n", cc,
1252                                 inet_ntoa(from->sin_addr));
1253                 return (0);
1254         }
1255         cc -= hlen;
1256         icp = (struct icmp *)(buf + hlen);
1257 #else
1258         icp = (struct icmp *)buf;
1259 #endif
1260         type = icp->icmp_type;
1261         code = icp->icmp_code;
1262         /* Path MTU Discovery (RFC1191) */
1263         if (code != ICMP_UNREACH_NEEDFRAG)
1264                 pmtu = 0;
1265         else {
1266 #ifdef HAVE_ICMP_NEXTMTU
1267                 pmtu = ntohs(icp->icmp_nextmtu);
1268 #else
1269                 pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
1270 #endif
1271         }
1272         if (type == ICMP_ECHOREPLY
1273             && proto->num == IPPROTO_ICMP
1274             && (*proto->check)((u_char *)icp, (u_char)seq))
1275                 return -2;
1276         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1277             type == ICMP_UNREACH) {
1278                 struct ip *hip;
1279                 u_char *inner;
1280
1281                 hip = &icp->icmp_ip;
1282                 hlen = hip->ip_hl << 2;
1283                 inner = (u_char *)((u_char *)hip + hlen);
1284                 if (hlen + 12 <= cc
1285                     && hip->ip_p == proto->num
1286                     && (*proto->check)(inner, (u_char)seq))
1287                         return (type == ICMP_TIMXCEED ? -1 : code + 1);
1288         }
1289 #ifndef ARCHAIC
1290         if (verbose) {
1291                 register int i;
1292                 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1293
1294                 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1295                 Printf("%s: icmp type %d (%s) code %d\n",
1296                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1297                 for (i = 4; i < cc ; i += sizeof(*lp))
1298                         Printf("%2d: x%8.8x\n", i, *lp++);
1299         }
1300 #endif
1301         return(0);
1302 }
1303
1304 void
1305 icmp_prep(struct outdata *outdata)
1306 {
1307         struct icmp *const icmpheader = (struct icmp *) outp;
1308
1309         icmpheader->icmp_type = ICMP_ECHO;
1310         icmpheader->icmp_id = htons(ident);
1311         icmpheader->icmp_seq = htons(outdata->seq);
1312         icmpheader->icmp_cksum = 0;
1313         icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
1314         if (icmpheader->icmp_cksum == 0)
1315                 icmpheader->icmp_cksum = 0xffff;
1316 }
1317
1318 int
1319 icmp_check(const u_char *data, int seq)
1320 {
1321         struct icmp *const icmpheader = (struct icmp *) data;
1322
1323         return (icmpheader->icmp_id == htons(ident)
1324             && icmpheader->icmp_seq == htons(seq));
1325 }
1326
1327 void
1328 udp_prep(struct outdata *outdata)
1329 {
1330         struct udphdr *const outudp = (struct udphdr *) outp;
1331
1332         outudp->uh_sport = htons(ident + (fixedPort ? outdata->seq : 0));
1333         outudp->uh_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1334         outudp->uh_ulen = htons((u_short)protlen);
1335         outudp->uh_sum = 0;
1336         if (doipcksum) {
1337             u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
1338             outudp->uh_sum = (sum) ? sum : 0xffff;
1339         }
1340
1341         return;
1342 }
1343
1344 int
1345 udp_check(const u_char *data, int seq)
1346 {
1347         struct udphdr *const udp = (struct udphdr *) data;
1348
1349         return (ntohs(udp->uh_sport) == ident + (fixedPort ? seq : 0) &&
1350             ntohs(udp->uh_dport) == port + (fixedPort ? 0 : seq));
1351 }
1352
1353 void
1354 tcp_prep(struct outdata *outdata)
1355 {
1356         struct tcphdr *const tcp = (struct tcphdr *) outp;
1357
1358         tcp->th_sport = htons(ident);
1359         tcp->th_dport = htons(port + (fixedPort ? 0 : outdata->seq));
1360         tcp->th_seq = (tcp->th_sport << 16) | (tcp->th_dport +
1361             (fixedPort ? outdata->seq : 0));
1362         tcp->th_ack = 0;
1363         tcp->th_off = 5;
1364         tcp->th_flags = TH_SYN;
1365         tcp->th_sum = 0;
1366
1367         if (doipcksum) {
1368             u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
1369             tcp->th_sum = (sum) ? sum : 0xffff;
1370         }
1371 }
1372
1373 int
1374 tcp_check(const u_char *data, int seq)
1375 {
1376         struct tcphdr *const tcp = (struct tcphdr *) data;
1377
1378         return (ntohs(tcp->th_sport) == ident
1379             && ntohs(tcp->th_dport) == port + (fixedPort ? 0 : seq))
1380             && tcp->th_seq == (ident << 16) | (port + seq);
1381 }
1382
1383 void
1384 gre_prep(struct outdata *outdata)
1385 {
1386         struct grehdr *const gre = (struct grehdr *) outp;
1387
1388         gre->flags = htons(0x2001);
1389         gre->proto = htons(port);
1390         gre->length = 0;
1391         gre->callId = htons(ident + outdata->seq);
1392 }
1393
1394 int
1395 gre_check(const u_char *data, int seq)
1396 {
1397         struct grehdr *const gre = (struct grehdr *) data;
1398
1399         return(ntohs(gre->proto) == port
1400             && ntohs(gre->callId) == ident + seq);
1401 }
1402
1403 void
1404 gen_prep(struct outdata *outdata)
1405 {
1406         u_int16_t *const ptr = (u_int16_t *) outp;
1407
1408         ptr[0] = htons(ident);
1409         ptr[1] = htons(port + outdata->seq);
1410 }
1411
1412 int
1413 gen_check(const u_char *data, int seq)
1414 {
1415         u_int16_t *const ptr = (u_int16_t *) data;
1416
1417         return(ntohs(ptr[0]) == ident
1418             && ntohs(ptr[1]) == port + seq);
1419 }
1420
1421 void
1422 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1423 {
1424         register struct ip *ip;
1425         register int hlen;
1426
1427         ip = (struct ip *) buf;
1428         hlen = ip->ip_hl << 2;
1429         cc -= hlen;
1430
1431         if (nflag)
1432                 Printf(" %s", inet_ntoa(from->sin_addr));
1433         else
1434                 Printf(" %s (%s)", inetname(from->sin_addr),
1435                     inet_ntoa(from->sin_addr));
1436
1437         if (verbose)
1438                 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1439 }
1440
1441 /*
1442  * Checksum routine for UDP and TCP headers.
1443  */
1444 u_short 
1445 p_cksum(struct ip *ip, u_short *data, int len)
1446 {
1447         static struct ipovly ipo;
1448         u_short sumh, sumd;
1449         u_long sumt;
1450
1451         ipo.ih_pr = ip->ip_p;
1452         ipo.ih_len = htons(len);
1453         ipo.ih_src = ip->ip_src;
1454         ipo.ih_dst = ip->ip_dst;
1455
1456         sumh = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
1457         sumd = in_cksum((u_short*)data, len);         /* payload data cksum */
1458         sumt = (sumh << 16) | (sumd);
1459
1460         return ~in_cksum((u_short*)&sumt, sizeof(sumt));
1461 }
1462
1463 /*
1464  * Checksum routine for Internet Protocol family headers (C Version)
1465  */
1466 u_short
1467 in_cksum(register u_short *addr, register int len)
1468 {
1469         register int nleft = len;
1470         register u_short *w = addr;
1471         register u_short answer;
1472         register int sum = 0;
1473
1474         /*
1475          *  Our algorithm is simple, using a 32 bit accumulator (sum),
1476          *  we add sequential 16 bit words to it, and at the end, fold
1477          *  back all the carry bits from the top 16 bits into the lower
1478          *  16 bits.
1479          */
1480         while (nleft > 1)  {
1481                 sum += *w++;
1482                 nleft -= 2;
1483         }
1484
1485         /* mop up an odd byte, if necessary */
1486         if (nleft == 1)
1487                 sum += *(u_char *)w;
1488
1489         /*
1490          * add back carry outs from top 16 bits to low 16 bits
1491          */
1492         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1493         sum += (sum >> 16);                     /* add carry */
1494         answer = ~sum;                          /* truncate to 16 bits */
1495         return (answer);
1496 }
1497
1498 /*
1499  * Subtract 2 timeval structs:  out = out - in.
1500  * Out is assumed to be within about LONG_MAX seconds of in.
1501  */
1502 void
1503 tvsub(register struct timeval *out, register struct timeval *in)
1504 {
1505
1506         if ((out->tv_usec -= in->tv_usec) < 0)   {
1507                 --out->tv_sec;
1508                 out->tv_usec += 1000000;
1509         }
1510         out->tv_sec -= in->tv_sec;
1511 }
1512
1513 /*
1514  * Construct an Internet address representation.
1515  * If the nflag has been supplied, give
1516  * numeric value, otherwise try for symbolic name.
1517  */
1518 char *
1519 inetname(struct in_addr in)
1520 {
1521         register char *cp;
1522         register struct hostent *hp;
1523         static int first = 1;
1524         static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1525
1526         if (first && !nflag) {
1527                 first = 0;
1528                 if (gethostname(domain, sizeof(domain) - 1) < 0)
1529                         domain[0] = '\0';
1530                 else {
1531                         cp = strchr(domain, '.');
1532                         if (cp == NULL) {
1533                                 hp = gethostbyname(domain);
1534                                 if (hp != NULL)
1535                                         cp = strchr(hp->h_name, '.');
1536                         }
1537                         if (cp == NULL)
1538                                 domain[0] = '\0';
1539                         else {
1540                                 ++cp;
1541                                 (void)strncpy(domain, cp, sizeof(domain) - 1);
1542                                 domain[sizeof(domain) - 1] = '\0';
1543                         }
1544                 }
1545         }
1546         if (!nflag && in.s_addr != INADDR_ANY) {
1547                 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1548                 if (hp != NULL) {
1549                         if ((cp = strchr(hp->h_name, '.')) != NULL &&
1550                             strcmp(cp + 1, domain) == 0)
1551                                 *cp = '\0';
1552                         (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1553                         line[sizeof(line) - 1] = '\0';
1554                         return (line);
1555                 }
1556         }
1557         return (inet_ntoa(in));
1558 }
1559
1560 struct hostinfo *
1561 gethostinfo(register char *hostname)
1562 {
1563         register int n;
1564         register struct hostent *hp;
1565         register struct hostinfo *hi;
1566         register char **p;
1567         register u_int32_t addr, *ap;
1568
1569         if (strlen(hostname) > 64) {
1570                 Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
1571                     prog, hostname);
1572                 exit(1);
1573         }
1574         hi = calloc(1, sizeof(*hi));
1575         if (hi == NULL) {
1576                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1577                 exit(1);
1578         }
1579         addr = inet_addr(hostname);
1580         if ((int32_t)addr != -1) {
1581                 hi->name = strdup(hostname);
1582                 hi->n = 1;
1583                 hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1584                 if (hi->addrs == NULL) {
1585                         Fprintf(stderr, "%s: calloc %s\n",
1586                             prog, strerror(errno));
1587                         exit(1);
1588                 }
1589                 hi->addrs[0] = addr;
1590                 return (hi);
1591         }
1592
1593         hp = gethostbyname(hostname);
1594         if (hp == NULL) {
1595                 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1596                 exit(1);
1597         }
1598         if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1599                 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1600                 exit(1);
1601         }
1602         hi->name = strdup(hp->h_name);
1603         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1604                 continue;
1605         hi->n = n;
1606         hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1607         if (hi->addrs == NULL) {
1608                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1609                 exit(1);
1610         }
1611         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1612                 memcpy(ap, *p, sizeof(*ap));
1613         return (hi);
1614 }
1615
1616 void
1617 freehostinfo(register struct hostinfo *hi)
1618 {
1619         if (hi->name != NULL) {
1620                 free(hi->name);
1621                 hi->name = NULL;
1622         }
1623         free((char *)hi->addrs);
1624         free((char *)hi);
1625 }
1626
1627 void
1628 getaddr(register u_int32_t *ap, register char *hostname)
1629 {
1630         register struct hostinfo *hi;
1631
1632         hi = gethostinfo(hostname);
1633         *ap = hi->addrs[0];
1634         freehostinfo(hi);
1635 }
1636
1637 void
1638 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1639 {
1640
1641         memset(sin, 0, sizeof(*sin));
1642 #ifdef HAVE_SOCKADDR_SA_LEN
1643         sin->sin_len = sizeof(*sin);
1644 #endif
1645         sin->sin_family = AF_INET;
1646         sin->sin_addr.s_addr = addr;
1647 }
1648
1649 /* String to value with optional min and max. Handles decimal and hex. */
1650 int
1651 str2val(register const char *str, register const char *what,
1652     register int mi, register int ma)
1653 {
1654         register const char *cp;
1655         register int val;
1656         char *ep;
1657
1658         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1659                 cp = str + 2;
1660                 val = (int)strtol(cp, &ep, 16);
1661         } else
1662                 val = (int)strtol(str, &ep, 10);
1663         if (*ep != '\0') {
1664                 Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1665                     prog, str, what);
1666                 exit(1);
1667         }
1668         if (val < mi && mi >= 0) {
1669                 if (mi == 0)
1670                         Fprintf(stderr, "%s: %s must be >= %d\n",
1671                             prog, what, mi);
1672                 else
1673                         Fprintf(stderr, "%s: %s must be > %d\n",
1674                             prog, what, mi - 1);
1675                 exit(1);
1676         }
1677         if (val > ma && ma >= 0) {
1678                 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1679                 exit(1);
1680         }
1681         return (val);
1682 }
1683
1684 struct outproto *
1685 setproto(char *pname)
1686 {
1687         struct outproto *proto;
1688         int i;
1689
1690         for (i = 0; protos[i].name != NULL; i++) {
1691                 if (strcasecmp(protos[i].name, pname) == 0) {
1692                         break;
1693                 }
1694         }
1695         proto = &protos[i];
1696         if (proto->name == NULL) {      /* generic handler */
1697                 struct protoent *pe;
1698                 u_long pnum;
1699
1700                 /* Determine the IP protocol number */
1701                 if ((pe = getprotobyname(pname)) != NULL)
1702                         pnum = pe->p_proto;
1703                 else
1704                         pnum = str2val(optarg, "proto number", 1, 255);
1705                 proto->num = pnum;
1706         }
1707         return proto;
1708 }
1709
1710 void
1711 usage(void)
1712 {
1713         extern char version[];
1714
1715         Fprintf(stderr, "Version %s\n", version);
1716         Fprintf(stderr,
1717             "Usage: %s [-dFInrSvx] [-g gateway] [-i iface] [-f first_ttl]\n"
1718             "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1719             "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
1720         exit(1);
1721 }