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