]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/traceroute/traceroute.c
This commit was generated by cvs2svn to compensate for changes in r157181,
[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                                         if (gotlastaddr) printf("\n   ");
950                                         print(packet, cc, from);
951                                         lastaddr = from->sin_addr.s_addr;
952                                         ++gotlastaddr;
953                                 }
954                                 T = deltaT(&t1, &t2);
955 #ifdef SANE_PRECISION
956                                 if (T >= 1000.0)
957                                         precis = 0;
958                                 else if (T >= 100.0)
959                                         precis = 1;
960                                 else if (T >= 10.0)
961                                         precis = 2;
962                                 else
963 #endif
964                                         precis = 3;
965                                 Printf("  %.*f ms", precis, T);
966                                 if (i == -2) {
967 #ifndef ARCHAIC
968                                         ip = (struct ip *)packet;
969                                         if (ip->ip_ttl <= 1)
970                                                 Printf(" !");
971 #endif
972                                         ++got_there;
973                                         break;
974                                 }
975                                 /* time exceeded in transit */
976                                 if (i == -1)
977                                         break;
978                                 code = i - 1;
979                                 switch (code) {
980
981                                 case ICMP_UNREACH_PORT:
982 #ifndef ARCHAIC
983                                         ip = (struct ip *)packet;
984                                         if (ip->ip_ttl <= 1)
985                                                 Printf(" !");
986 #endif
987                                         ++got_there;
988                                         break;
989
990                                 case ICMP_UNREACH_NET:
991                                         ++unreachable;
992                                         Printf(" !N");
993                                         break;
994
995                                 case ICMP_UNREACH_HOST:
996                                         ++unreachable;
997                                         Printf(" !H");
998                                         break;
999
1000                                 case ICMP_UNREACH_PROTOCOL:
1001                                         ++got_there;
1002                                         Printf(" !P");
1003                                         break;
1004
1005                                 case ICMP_UNREACH_NEEDFRAG:
1006                                         ++unreachable;
1007                                         Printf(" !F-%d", pmtu);
1008                                         break;
1009
1010                                 case ICMP_UNREACH_SRCFAIL:
1011                                         ++unreachable;
1012                                         Printf(" !S");
1013                                         break;
1014
1015                                 case ICMP_UNREACH_FILTER_PROHIB:
1016                                         ++unreachable;
1017                                         Printf(" !X");
1018                                         break;
1019
1020                                 case ICMP_UNREACH_HOST_PRECEDENCE:
1021                                         ++unreachable;
1022                                         Printf(" !V");
1023                                         break;
1024
1025                                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
1026                                         ++unreachable;
1027                                         Printf(" !C");
1028                                         break;
1029
1030                                 default:
1031                                         ++unreachable;
1032                                         Printf(" !<%d>", code);
1033                                         break;
1034                                 }
1035                                 break;
1036                         }
1037                         if (cc == 0) {
1038                                 loss++;
1039                                 Printf(" *");
1040                         }
1041                         (void)fflush(stdout);
1042                 }
1043                 if (sump) {
1044                         Printf(" (%d%% loss)", (loss * 100) / nprobes);
1045                 }
1046                 putchar('\n');
1047                 if (got_there ||
1048                     (unreachable > 0 && unreachable >= nprobes - 1))
1049                         break;
1050         }
1051         exit(0);
1052 }
1053
1054 int
1055 wait_for_reply(register int sock, register struct sockaddr_in *fromp,
1056     register const struct timeval *tp)
1057 {
1058         fd_set *fdsp;
1059         size_t nfds;
1060         struct timeval now, wait;
1061         struct timezone tz;
1062         register int cc = 0;
1063         register int error;
1064         int fromlen = sizeof(*fromp);
1065
1066         nfds = howmany(sock + 1, NFDBITS);
1067         if ((fdsp = malloc(nfds * sizeof(fd_mask))) == NULL)
1068                 err(1, "malloc");
1069         memset(fdsp, 0, nfds * sizeof(fd_mask));
1070         FD_SET(sock, fdsp);
1071
1072         wait.tv_sec = tp->tv_sec + waittime;
1073         wait.tv_usec = tp->tv_usec;
1074         (void)gettimeofday(&now, &tz);
1075         tvsub(&wait, &now);
1076         if (wait.tv_sec < 0) {
1077                 wait.tv_sec = 0;
1078                 wait.tv_usec = 1;
1079         }
1080
1081         error = select(sock + 1, fdsp, NULL, NULL, &wait);
1082         if (error == -1 && errno == EINVAL) {
1083                 Fprintf(stderr, "%s: botched select() args\n", prog);
1084                 exit(1);
1085         }
1086         if (error > 0)
1087                 cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
1088                             (struct sockaddr *)fromp, &fromlen);
1089
1090         free(fdsp);
1091         return(cc);
1092 }
1093
1094 void
1095 send_probe(int seq, int ttl)
1096 {
1097         register int cc;
1098
1099         outip->ip_ttl = ttl;
1100         outip->ip_id = htons(ident + seq);
1101
1102         /* XXX undocumented debugging hack */
1103         if (verbose > 1) {
1104                 register const u_short *sp;
1105                 register int nshorts, i;
1106
1107                 sp = (u_short *)outip;
1108                 nshorts = (u_int)packlen / sizeof(u_short);
1109                 i = 0;
1110                 Printf("[ %d bytes", packlen);
1111                 while (--nshorts >= 0) {
1112                         if ((i++ % 8) == 0)
1113                                 Printf("\n\t");
1114                         Printf(" %04x", ntohs(*sp++));
1115                 }
1116                 if (packlen & 1) {
1117                         if ((i % 8) == 0)
1118                                 Printf("\n\t");
1119                         Printf(" %02x", *(u_char *)sp);
1120                 }
1121                 Printf("]\n");
1122         }
1123
1124 #if !defined(IP_HDRINCL) && defined(IP_TTL)
1125         if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
1126             (char *)&ttl, sizeof(ttl)) < 0) {
1127                 Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
1128                     prog, ttl, strerror(errno));
1129                 exit(1);
1130         }
1131 #endif
1132
1133         cc = sendto(sndsock, (char *)outip,
1134             packlen, 0, &whereto, sizeof(whereto));
1135         if (cc < 0 || cc != packlen)  {
1136                 if (cc < 0)
1137                         Fprintf(stderr, "%s: sendto: %s\n",
1138                             prog, strerror(errno));
1139                 Printf("%s: wrote %s %d chars, ret=%d\n",
1140                     prog, hostname, packlen, cc);
1141                 (void)fflush(stdout);
1142         }
1143 }
1144
1145 #if     defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
1146 int
1147 setpolicy(so, policy)
1148         int so;
1149         char *policy;
1150 {
1151         char *buf;
1152
1153         buf = ipsec_set_policy(policy, strlen(policy));
1154         if (buf == NULL) {
1155                 warnx("%s", ipsec_strerror());
1156                 return -1;
1157         }
1158         (void)setsockopt(so, IPPROTO_IP, IP_IPSEC_POLICY,
1159                 buf, ipsec_get_policylen(buf));
1160
1161         free(buf);
1162
1163         return 0;
1164 }
1165 #endif
1166
1167 double
1168 deltaT(struct timeval *t1p, struct timeval *t2p)
1169 {
1170         register double dt;
1171
1172         dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
1173              (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
1174         return (dt);
1175 }
1176
1177 /*
1178  * Convert an ICMP "type" field to a printable string.
1179  */
1180 char *
1181 pr_type(register u_char t)
1182 {
1183         static char *ttab[] = {
1184         "Echo Reply",   "ICMP 1",       "ICMP 2",       "Dest Unreachable",
1185         "Source Quench", "Redirect",    "ICMP 6",       "ICMP 7",
1186         "Echo",         "ICMP 9",       "ICMP 10",      "Time Exceeded",
1187         "Param Problem", "Timestamp",   "Timestamp Reply", "Info Request",
1188         "Info Reply"
1189         };
1190
1191         if (t > 16)
1192                 return("OUT-OF-RANGE");
1193
1194         return(ttab[t]);
1195 }
1196
1197 int
1198 packet_ok(register u_char *buf, int cc, register struct sockaddr_in *from,
1199     register int seq)
1200 {
1201         register struct icmp *icp;
1202         register u_char type, code;
1203         register int hlen;
1204 #ifndef ARCHAIC
1205         register struct ip *ip;
1206
1207         ip = (struct ip *) buf;
1208         hlen = ip->ip_hl << 2;
1209         if (cc < hlen + ICMP_MINLEN) {
1210                 if (verbose)
1211                         Printf("packet too short (%d bytes) from %s\n", cc,
1212                                 inet_ntoa(from->sin_addr));
1213                 return (0);
1214         }
1215         cc -= hlen;
1216         icp = (struct icmp *)(buf + hlen);
1217 #else
1218         icp = (struct icmp *)buf;
1219 #endif
1220         type = icp->icmp_type;
1221         code = icp->icmp_code;
1222         /* Path MTU Discovery (RFC1191) */
1223         if (code != ICMP_UNREACH_NEEDFRAG)
1224                 pmtu = 0;
1225         else {
1226 #ifdef HAVE_ICMP_NEXTMTU
1227                 pmtu = ntohs(icp->icmp_nextmtu);
1228 #else
1229                 pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
1230 #endif
1231         }
1232         if (type == ICMP_ECHOREPLY
1233             && proto->num == IPPROTO_ICMP
1234             && (*proto->check)((u_char *)icp, (u_char)seq))
1235                 return -2;
1236         if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
1237             type == ICMP_UNREACH) {
1238                 struct ip *hip;
1239                 u_char *inner;
1240
1241                 hip = &icp->icmp_ip;
1242                 hlen = hip->ip_hl << 2;
1243                 inner = (u_char *)((u_char *)hip + hlen);
1244                 if (hlen + 12 <= cc
1245                     && hip->ip_p == proto->num
1246                     && (*proto->check)(inner, (u_char)seq))
1247                         return (type == ICMP_TIMXCEED ? -1 : code + 1);
1248         }
1249 #ifndef ARCHAIC
1250         if (verbose) {
1251                 register int i;
1252                 u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
1253
1254                 Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
1255                 Printf("%s: icmp type %d (%s) code %d\n",
1256                     inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
1257                 for (i = 4; i < cc ; i += sizeof(*lp))
1258                         Printf("%2d: x%8.8x\n", i, *lp++);
1259         }
1260 #endif
1261         return(0);
1262 }
1263
1264 void
1265 icmp_prep(struct outdata *outdata)
1266 {
1267         struct icmp *const icmpheader = (struct icmp *) outp;
1268
1269         icmpheader->icmp_type = ICMP_ECHO;
1270         icmpheader->icmp_id = htons(ident);
1271         icmpheader->icmp_seq = htons(outdata->seq);
1272         icmpheader->icmp_cksum = 0;
1273         icmpheader->icmp_cksum = in_cksum((u_short *)icmpheader, protlen);
1274         if (icmpheader->icmp_cksum == 0)
1275                 icmpheader->icmp_cksum = 0xffff;
1276 }
1277
1278 int
1279 icmp_check(const u_char *data, int seq)
1280 {
1281         struct icmp *const icmpheader = (struct icmp *) data;
1282
1283         return (icmpheader->icmp_id == htons(ident)
1284             && icmpheader->icmp_seq == htons(seq));
1285 }
1286
1287 void
1288 udp_prep(struct outdata *outdata)
1289 {
1290         struct udphdr *const outudp = (struct udphdr *) outp;
1291
1292         outudp->uh_sport = htons(ident);
1293         outudp->uh_dport = htons(port + outdata->seq);
1294         outudp->uh_ulen = htons((u_short)protlen);
1295         outudp->uh_sum = 0;
1296         if (doipcksum) {
1297             u_short sum = p_cksum(outip, (u_short*)outudp, protlen);
1298             outudp->uh_sum = (sum) ? sum : 0xffff;
1299         }
1300
1301         return;
1302 }
1303
1304 int
1305 udp_check(const u_char *data, int seq)
1306 {
1307         struct udphdr *const udp = (struct udphdr *) data;
1308
1309         return (ntohs(udp->uh_sport) == ident
1310             && ntohs(udp->uh_dport) == port + seq);
1311 }
1312
1313 void
1314 tcp_prep(struct outdata *outdata)
1315 {
1316         struct tcphdr *const tcp = (struct tcphdr *) outp;
1317
1318         tcp->th_sport = htons(ident);
1319         tcp->th_dport = htons(port + outdata->seq);
1320         tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
1321         tcp->th_ack = 0;
1322         tcp->th_off = 5;
1323         tcp->th_flags = TH_SYN;
1324         tcp->th_sum = 0;
1325
1326         if (doipcksum) {
1327             u_short sum = p_cksum(outip, (u_short*)tcp, protlen);
1328             tcp->th_sum = (sum) ? sum : 0xffff;
1329         }
1330 }
1331
1332 int
1333 tcp_check(const u_char *data, int seq)
1334 {
1335         struct tcphdr *const tcp = (struct tcphdr *) data;
1336
1337         return (ntohs(tcp->th_sport) == ident
1338             && ntohs(tcp->th_dport) == port + seq);
1339 }
1340
1341 void
1342 gre_prep(struct outdata *outdata)
1343 {
1344         struct grehdr *const gre = (struct grehdr *) outp;
1345
1346         gre->flags = htons(0x2001);
1347         gre->proto = htons(port);
1348         gre->length = 0;
1349         gre->callId = htons(ident + outdata->seq);
1350 }
1351
1352 int
1353 gre_check(const u_char *data, int seq)
1354 {
1355         struct grehdr *const gre = (struct grehdr *) data;
1356
1357         return(ntohs(gre->proto) == port
1358             && ntohs(gre->callId) == ident + seq);
1359 }
1360
1361 void
1362 gen_prep(struct outdata *outdata)
1363 {
1364         u_int16_t *const ptr = (u_int16_t *) outp;
1365
1366         ptr[0] = htons(ident);
1367         ptr[1] = htons(port + outdata->seq);
1368 }
1369
1370 int
1371 gen_check(const u_char *data, int seq)
1372 {
1373         u_int16_t *const ptr = (u_int16_t *) data;
1374
1375         return(ntohs(ptr[0]) == ident
1376             && ntohs(ptr[1]) == port + seq);
1377 }
1378
1379 void
1380 print(register u_char *buf, register int cc, register struct sockaddr_in *from)
1381 {
1382         register struct ip *ip;
1383         register int hlen;
1384
1385         ip = (struct ip *) buf;
1386         hlen = ip->ip_hl << 2;
1387         cc -= hlen;
1388
1389         if (nflag)
1390                 Printf(" %s", inet_ntoa(from->sin_addr));
1391         else
1392                 Printf(" %s (%s)", inetname(from->sin_addr),
1393                     inet_ntoa(from->sin_addr));
1394
1395         if (verbose)
1396                 Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
1397 }
1398
1399 /*
1400  * Checksum routine for UDP and TCP headers.
1401  */
1402 u_short 
1403 p_cksum(struct ip *ip, u_short *data, int len)
1404 {
1405         static struct ipovly ipo;
1406         u_short sumh, sumd;
1407         u_long sumt;
1408
1409         ipo.ih_pr = ip->ip_p;
1410         ipo.ih_len = htons(len);
1411         ipo.ih_src = ip->ip_src;
1412         ipo.ih_dst = ip->ip_dst;
1413
1414         sumh = in_cksum((u_short*)&ipo, sizeof(ipo)); /* pseudo ip hdr cksum */
1415         sumd = in_cksum((u_short*)data, len);         /* payload data cksum */
1416         sumt = (sumh << 16) | (sumd);
1417
1418         return ~in_cksum((u_short*)&sumt, sizeof(sumt));
1419 }
1420
1421 /*
1422  * Checksum routine for Internet Protocol family headers (C Version)
1423  */
1424 u_short
1425 in_cksum(register u_short *addr, register int len)
1426 {
1427         register int nleft = len;
1428         register u_short *w = addr;
1429         register u_short answer;
1430         register int sum = 0;
1431
1432         /*
1433          *  Our algorithm is simple, using a 32 bit accumulator (sum),
1434          *  we add sequential 16 bit words to it, and at the end, fold
1435          *  back all the carry bits from the top 16 bits into the lower
1436          *  16 bits.
1437          */
1438         while (nleft > 1)  {
1439                 sum += *w++;
1440                 nleft -= 2;
1441         }
1442
1443         /* mop up an odd byte, if necessary */
1444         if (nleft == 1)
1445                 sum += *(u_char *)w;
1446
1447         /*
1448          * add back carry outs from top 16 bits to low 16 bits
1449          */
1450         sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
1451         sum += (sum >> 16);                     /* add carry */
1452         answer = ~sum;                          /* truncate to 16 bits */
1453         return (answer);
1454 }
1455
1456 /*
1457  * Subtract 2 timeval structs:  out = out - in.
1458  * Out is assumed to be within about LONG_MAX seconds of in.
1459  */
1460 void
1461 tvsub(register struct timeval *out, register struct timeval *in)
1462 {
1463
1464         if ((out->tv_usec -= in->tv_usec) < 0)   {
1465                 --out->tv_sec;
1466                 out->tv_usec += 1000000;
1467         }
1468         out->tv_sec -= in->tv_sec;
1469 }
1470
1471 /*
1472  * Construct an Internet address representation.
1473  * If the nflag has been supplied, give
1474  * numeric value, otherwise try for symbolic name.
1475  */
1476 char *
1477 inetname(struct in_addr in)
1478 {
1479         register char *cp;
1480         register struct hostent *hp;
1481         static int first = 1;
1482         static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
1483
1484         if (first && !nflag) {
1485                 first = 0;
1486                 if (gethostname(domain, sizeof(domain) - 1) < 0)
1487                         domain[0] = '\0';
1488                 else {
1489                         cp = strchr(domain, '.');
1490                         if (cp == NULL) {
1491                                 hp = gethostbyname(domain);
1492                                 if (hp != NULL)
1493                                         cp = strchr(hp->h_name, '.');
1494                         }
1495                         if (cp == NULL)
1496                                 domain[0] = '\0';
1497                         else {
1498                                 ++cp;
1499                                 (void)strncpy(domain, cp, sizeof(domain) - 1);
1500                                 domain[sizeof(domain) - 1] = '\0';
1501                         }
1502                 }
1503         }
1504         if (!nflag && in.s_addr != INADDR_ANY) {
1505                 hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
1506                 if (hp != NULL) {
1507                         if ((cp = strchr(hp->h_name, '.')) != NULL &&
1508                             strcmp(cp + 1, domain) == 0)
1509                                 *cp = '\0';
1510                         (void)strncpy(line, hp->h_name, sizeof(line) - 1);
1511                         line[sizeof(line) - 1] = '\0';
1512                         return (line);
1513                 }
1514         }
1515         return (inet_ntoa(in));
1516 }
1517
1518 struct hostinfo *
1519 gethostinfo(register char *hostname)
1520 {
1521         register int n;
1522         register struct hostent *hp;
1523         register struct hostinfo *hi;
1524         register char **p;
1525         register u_int32_t addr, *ap;
1526
1527         if (strlen(hostname) > 64) {
1528                 Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
1529                     prog, hostname);
1530                 exit(1);
1531         }
1532         hi = calloc(1, sizeof(*hi));
1533         if (hi == NULL) {
1534                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1535                 exit(1);
1536         }
1537         addr = inet_addr(hostname);
1538         if ((int32_t)addr != -1) {
1539                 hi->name = strdup(hostname);
1540                 hi->n = 1;
1541                 hi->addrs = calloc(1, sizeof(hi->addrs[0]));
1542                 if (hi->addrs == NULL) {
1543                         Fprintf(stderr, "%s: calloc %s\n",
1544                             prog, strerror(errno));
1545                         exit(1);
1546                 }
1547                 hi->addrs[0] = addr;
1548                 return (hi);
1549         }
1550
1551         hp = gethostbyname(hostname);
1552         if (hp == NULL) {
1553                 Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
1554                 exit(1);
1555         }
1556         if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
1557                 Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
1558                 exit(1);
1559         }
1560         hi->name = strdup(hp->h_name);
1561         for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
1562                 continue;
1563         hi->n = n;
1564         hi->addrs = calloc(n, sizeof(hi->addrs[0]));
1565         if (hi->addrs == NULL) {
1566                 Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
1567                 exit(1);
1568         }
1569         for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
1570                 memcpy(ap, *p, sizeof(*ap));
1571         return (hi);
1572 }
1573
1574 void
1575 freehostinfo(register struct hostinfo *hi)
1576 {
1577         if (hi->name != NULL) {
1578                 free(hi->name);
1579                 hi->name = NULL;
1580         }
1581         free((char *)hi->addrs);
1582         free((char *)hi);
1583 }
1584
1585 void
1586 getaddr(register u_int32_t *ap, register char *hostname)
1587 {
1588         register struct hostinfo *hi;
1589
1590         hi = gethostinfo(hostname);
1591         *ap = hi->addrs[0];
1592         freehostinfo(hi);
1593 }
1594
1595 void
1596 setsin(register struct sockaddr_in *sin, register u_int32_t addr)
1597 {
1598
1599         memset(sin, 0, sizeof(*sin));
1600 #ifdef HAVE_SOCKADDR_SA_LEN
1601         sin->sin_len = sizeof(*sin);
1602 #endif
1603         sin->sin_family = AF_INET;
1604         sin->sin_addr.s_addr = addr;
1605 }
1606
1607 /* String to value with optional min and max. Handles decimal and hex. */
1608 int
1609 str2val(register const char *str, register const char *what,
1610     register int mi, register int ma)
1611 {
1612         register const char *cp;
1613         register int val;
1614         char *ep;
1615
1616         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
1617                 cp = str + 2;
1618                 val = (int)strtol(cp, &ep, 16);
1619         } else
1620                 val = (int)strtol(str, &ep, 10);
1621         if (*ep != '\0') {
1622                 Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
1623                     prog, str, what);
1624                 exit(1);
1625         }
1626         if (val < mi && mi >= 0) {
1627                 if (mi == 0)
1628                         Fprintf(stderr, "%s: %s must be >= %d\n",
1629                             prog, what, mi);
1630                 else
1631                         Fprintf(stderr, "%s: %s must be > %d\n",
1632                             prog, what, mi - 1);
1633                 exit(1);
1634         }
1635         if (val > ma && ma >= 0) {
1636                 Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
1637                 exit(1);
1638         }
1639         return (val);
1640 }
1641
1642 struct outproto *
1643 setproto(char *pname)
1644 {
1645         struct outproto *proto;
1646         int i;
1647
1648         for (i = 0; protos[i].name != NULL; i++) {
1649                 if (strcasecmp(protos[i].name, pname) == 0) {
1650                         break;
1651                 }
1652         }
1653         proto = &protos[i];
1654         if (proto->name == NULL) {      /* generic handler */
1655                 struct protoent *pe;
1656                 u_long pnum;
1657
1658                 /* Determine the IP protocol number */
1659                 if ((pe = getprotobyname(pname)) != NULL)
1660                         pnum = pe->p_proto;
1661                 else
1662                         pnum = str2val(optarg, "proto number", 1, 255);
1663                 proto->num = pnum;
1664         }
1665         return proto;
1666 }
1667
1668 void
1669 usage(void)
1670 {
1671         extern char version[];
1672
1673         Fprintf(stderr, "Version %s\n", version);
1674         Fprintf(stderr,
1675             "Usage: %s [-dFInrSvx] [-g gateway] [-i iface] [-f first_ttl]\n"
1676             "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
1677             "\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
1678         exit(1);
1679 }