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