home *** CD-ROM | disk | FTP | other *** search
/ ftp.shrubbery.net / 2015-02-07.ftp.shrubbery.net.tar / ftp.shrubbery.net / pub / astraceroute / astraceroute-1.4.a12.2.tar.gz / astraceroute-1.4.a12.2.tar / astraceroute-1.4.a12.2 / traceroute.c < prev    next >
C/C++ Source or Header  |  2008-11-17  |  37KB  |  1,400 lines

  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. static const char rcsid[] =
  27.     "@(#)$Id: traceroute.c,v 1.8 2008/11/17 07:33:17 heas Exp $ (LBL)";
  28. #endif
  29.  
  30. /*
  31.  * traceroute host  - trace the route ip packets follow going to "host".
  32.  *
  33.  * Attempt to trace the route an ip packet would follow to some
  34.  * internet host.  We find out intermediate hops by launching probe
  35.  * packets with a small ttl (time to live) then listening for an
  36.  * icmp "time exceeded" reply from a gateway.  We start our probes
  37.  * with a ttl of one and increase by one until we get an icmp "port
  38.  * unreachable" (which means we got to "host") or hit a max (which
  39.  * defaults to 30 hops & can be changed with the -m flag).  Three
  40.  * probes (change with -q flag) are sent at each ttl setting and a
  41.  * line is printed showing the ttl, address of the gateway and
  42.  * round trip time of each probe.  If the probe answers come from
  43.  * different gateways, the address of each responding system will
  44.  * be printed.  If there is no response within a 5 sec. timeout
  45.  * interval (changed with the -w flag), a "*" is printed for that
  46.  * probe.
  47.  *
  48.  * Probe packets are UDP format.  We don't want the destination
  49.  * host to process them so the destination port is set to an
  50.  * unlikely value (if some clod on the destination is using that
  51.  * value, it can be changed with the -p flag).
  52.  *
  53.  * A sample use might be:
  54.  *
  55.  *     [yak 71]% traceroute nis.nsf.net.
  56.  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
  57.  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
  58.  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
  59.  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
  60.  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
  61.  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
  62.  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
  63.  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
  64.  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
  65.  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
  66.  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
  67.  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
  68.  *
  69.  * Note that lines 2 & 3 are the same.  This is due to a buggy
  70.  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
  71.  * packets with a zero ttl.
  72.  *
  73.  * A more interesting example is:
  74.  *
  75.  *     [yak 72]% traceroute allspice.lcs.mit.edu.
  76.  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
  77.  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
  78.  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
  79.  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
  80.  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
  81.  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
  82.  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
  83.  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
  84.  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
  85.  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
  86.  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
  87.  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
  88.  *     12  * * *
  89.  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
  90.  *     14  * * *
  91.  *     15  * * *
  92.  *     16  * * *
  93.  *     17  * * *
  94.  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
  95.  *
  96.  * (I start to see why I'm having so much trouble with mail to
  97.  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
  98.  * either don't send ICMP "time exceeded" messages or send them
  99.  * with a ttl too small to reach us.  14 - 17 are running the
  100.  * MIT C Gateway code that doesn't send "time exceeded"s.  God
  101.  * only knows what's going on with 12.
  102.  *
  103.  * The silent gateway 12 in the above may be the result of a bug in
  104.  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
  105.  * sends an unreachable message using whatever ttl remains in the
  106.  * original datagram.  Since, for gateways, the remaining ttl is
  107.  * zero, the icmp "time exceeded" is guaranteed to not make it back
  108.  * to us.  The behavior of this bug is slightly more interesting
  109.  * when it appears on the destination system:
  110.  *
  111.  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
  112.  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
  113.  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
  114.  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
  115.  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
  116.  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
  117.  *      7  * * *
  118.  *      8  * * *
  119.  *      9  * * *
  120.  *     10  * * *
  121.  *     11  * * *
  122.  *     12  * * *
  123.  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
  124.  *
  125.  * Notice that there are 12 "gateways" (13 is the final
  126.  * destination) and exactly the last half of them are "missing".
  127.  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
  128.  * is using the ttl from our arriving datagram as the ttl in its
  129.  * icmp reply.  So, the reply will time out on the return path
  130.  * (with no notice sent to anyone since icmp's aren't sent for
  131.  * icmp's) until we probe with a ttl that's at least twice the path
  132.  * length.  I.e., rip is really only 7 hops away.  A reply that
  133.  * returns with a ttl of 1 is a clue this problem exists.
  134.  * Traceroute prints a "!" after the time if the ttl is <= 1.
  135.  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
  136.  * non-standard (HPUX) software, expect to see this problem
  137.  * frequently and/or take care picking the target host of your
  138.  * probes.
  139.  *
  140.  * Other possible annotations after the time are !H, !N, !P (got a host,
  141.  * network or protocol unreachable, respectively), !S or !F (source
  142.  * route failed or fragmentation needed -- neither of these should
  143.  * ever occur and the associated gateway is busted if you see one).  If
  144.  * almost all the probes result in some kind of unreachable, traceroute
  145.  * will give up and exit.
  146.  *
  147.  * Notes
  148.  * -----
  149.  * This program must be run by root or be setuid.  (I suggest that
  150.  * you *don't* make it setuid -- casual use could result in a lot
  151.  * of unnecessary traffic on our poor, congested nets.)
  152.  *
  153.  * This program requires a kernel mod that does not appear in any
  154.  * system available from Berkeley:  A raw ip socket using proto
  155.  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
  156.  * opposed to data to be wrapped in a ip datagram).  See the README
  157.  * file that came with the source to this program for a description
  158.  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
  159.  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
  160.  * MODIFIED TO RUN THIS PROGRAM.
  161.  *
  162.  * The udp port usage may appear bizarre (well, ok, it is bizarre).
  163.  * The problem is that an icmp message only contains 8 bytes of
  164.  * data from the original datagram.  8 bytes is the size of a udp
  165.  * header so, if we want to associate replies with the original
  166.  * datagram, the necessary information must be encoded into the
  167.  * udp header (the ip id could be used but there's no way to
  168.  * interlock with the kernel's assignment of ip id's and, anyway,
  169.  * it would have taken a lot more kernel hacking to allow this
  170.  * code to set the ip id).  So, to allow two or more users to
  171.  * use traceroute simultaneously, we use this task's pid as the
  172.  * source port (the high bit is set to move the port number out
  173.  * of the "likely" range).  To keep track of which probe is being
  174.  * replied to (so times and/or hop counts don't get confused by a
  175.  * reply that was delayed in transit), we increment the destination
  176.  * port number before each probe.
  177.  *
  178.  * Don't use this as a coding example.  I was trying to find a
  179.  * routing problem and this code sort-of popped out after 48 hours
  180.  * without sleep.  I was amazed it ever compiled, much less ran.
  181.  *
  182.  * I stole the idea for this program from Steve Deering.  Since
  183.  * the first release, I've learned that had I attended the right
  184.  * IETF working group meetings, I also could have stolen it from Guy
  185.  * Almes or Matt Mathis.  I don't know (or care) who came up with
  186.  * the idea first.  I envy the originators' perspicacity and I'm
  187.  * glad they didn't keep the idea a secret.
  188.  *
  189.  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
  190.  * enhancements to the original distribution.
  191.  *
  192.  * I've hacked up a round-trip-route version of this that works by
  193.  * sending a loose-source-routed udp datagram through the destination
  194.  * back to yourself.  Unfortunately, SO many gateways botch source
  195.  * routing, the thing is almost worthless.  Maybe one day...
  196.  *
  197.  *  -- Van Jacobson (van@ee.lbl.gov)
  198.  *     Tue Dec 20 03:50:13 PST 1988
  199.  */
  200.  
  201. #include <sys/param.h>
  202. #include <sys/file.h>
  203. #include <sys/ioctl.h>
  204. #ifdef HAVE_SYS_SELECT_H
  205. #include <sys/select.h>
  206. #endif
  207. #include <sys/socket.h>
  208. #include <sys/time.h>
  209.  
  210. #include <netinet/in_systm.h>
  211. #include <netinet/in.h>
  212. #include <netinet/ip.h>
  213. #include <netinet/ip_var.h>
  214. #include <netinet/ip_icmp.h>
  215. #include <netinet/udp.h>
  216. #include <netinet/udp_var.h>
  217.  
  218. #include <arpa/inet.h>
  219.  
  220. #include <ctype.h>
  221. #include <errno.h>
  222. #include <fcntl.h>
  223. #ifdef HAVE_MALLOC_H
  224. #include <malloc.h>
  225. #endif
  226. #include <memory.h>
  227. #include <netdb.h>
  228. #include <stdio.h>
  229. #include <stdlib.h>
  230. #include <string.h>
  231. #include <unistd.h>
  232.  
  233. #include "gnuc.h"
  234. #include "version.h"
  235. #ifdef HAVE_OS_PROTO_H
  236. #include "os-proto.h"
  237. #endif
  238.  
  239. /* rfc1716 */
  240. #ifndef ICMP_UNREACH_FILTER_PROHIB
  241. #define ICMP_UNREACH_FILTER_PROHIB    13    /* admin prohibited filter */
  242. #endif
  243. #ifndef ICMP_UNREACH_HOST_PRECEDENCE
  244. #define ICMP_UNREACH_HOST_PRECEDENCE    14    /* host precedence violation */
  245. #endif
  246. #ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
  247. #define ICMP_UNREACH_PRECEDENCE_CUTOFF    15    /* precedence cutoff */
  248. #endif
  249.  
  250. #include "findsaddr.h"
  251. #include "ifaddrlist.h"
  252. #include "traceroute.h"
  253.  
  254. /* Maximum number of gateways (include room for one noop) */
  255. #define NGATEWAYS ((int)((MAX_IPOPTLEN - IPOPT_MINOFF - 1) / sizeof(u_int32_t)))
  256.  
  257. #ifndef MAXHOSTNAMELEN
  258. #define MAXHOSTNAMELEN    64
  259. #endif
  260.  
  261. #define Fprintf (void)fprintf
  262. #define Printf (void)printf
  263.  
  264. /* Host name and address list */
  265. struct hostinfo {
  266.     char *name;
  267.     int n;
  268.     u_int32_t *addrs;
  269. };
  270.  
  271. /* Data section of the probe packet */
  272. struct outdata {
  273.     u_char seq;        /* sequence number of this packet */
  274.     u_char ttl;        /* ttl packet left with */
  275.     struct timeval tv;    /* time packet left */
  276. };
  277.  
  278. #ifndef HAVE_ICMP_NEXTMTU
  279. /* Path MTU Discovery (RFC1191) */
  280. struct my_pmtu {
  281.     u_short ipm_void;
  282.     u_short ipm_nextmtu;
  283. };
  284. #endif
  285.  
  286. u_char    packet[512];        /* last inbound (icmp) packet */
  287.  
  288. struct ip *outip;        /* last output (udp) packet */
  289. struct udphdr *outudp;        /* last output (udp) packet */
  290. struct outdata *outdata;    /* last output (udp) packet */
  291. struct outdata outsetup;    /* last output (udp) packet */
  292.  
  293. struct icmp *outicmp;        /* last output (icmp) packet */
  294.  
  295. /* loose source route gateway list (including room for final destination) */
  296. u_int32_t gwlist[NGATEWAYS + 1];
  297.  
  298. int s;                /* receive (icmp) socket file descriptor */
  299. int sndsock;            /* send (udp/icmp) socket file descriptor */
  300.  
  301. struct sockaddr whereto;    /* Who to try to reach */
  302. struct sockaddr wherefrom;    /* Who we are */
  303. int packlen;            /* total length of packet */
  304. int minpacket;            /* min ip packet size */
  305. int maxpacket = 32 * 1024;    /* max ip packet size */
  306. int pmtu;            /* Path MTU Discovery (RFC1191) */
  307. u_int pausemsecs;
  308.  
  309. char *prog;
  310. char *source;
  311. char *hostname;
  312. char *device;
  313. static const char devnull[] = "/dev/null";
  314.  
  315. int nprobes = 3;
  316. int max_ttl = 30;
  317. int first_ttl = 1;
  318. u_short ident;
  319. u_short port = 32768 + 666;    /* start udp dest port # for probe packets */
  320.  
  321. int asns;            /* print AS numbers for each hop */
  322. int options;            /* socket options */
  323. int verbose;
  324. int waittime = 5;        /* time to wait for response (in seconds) */
  325. int nflag;            /* print addresses numerically */
  326. int useicmp;            /* use icmp echo instead of udp packets */
  327. #ifdef CANT_HACK_IPCKSUM
  328. int doipcksum = 0;        /* don't calculate ip checksums by default */
  329. #else
  330. int doipcksum = 1;        /* calculate ip checksums by default */
  331. #endif
  332. int optlen;            /* length of ip options */
  333.  
  334. extern int optind;
  335. extern int opterr;
  336. extern char *optarg;
  337.  
  338. /* Forwards */
  339. double    deltaT(struct timeval *, struct timeval *);
  340. void    freehostinfo(struct hostinfo *);
  341. void    getaddr(u_int32_t *, char *);
  342. struct    hostinfo *gethostinfo(char *);
  343. u_short    in_cksum(u_short *, int);
  344. char    *inetname(struct in_addr);
  345. int    main(int, char **);
  346. int    packet_ok(u_char *, int, struct sockaddr_in *, int);
  347. char    *pr_type(u_char);
  348. void    print(u_char *, int, struct sockaddr_in *);
  349. void    send_probe(int, int, struct timeval *);
  350. int    str2val(const char *, const char *, int, int);
  351. void    tvsub(struct timeval *, struct timeval *);
  352. void    usage(void);
  353. int    wait_for_reply(int, struct sockaddr_in *, const struct timeval *);
  354. #ifndef HAVE_USLEEP
  355. int    usleep(u_int);
  356. #endif
  357.  
  358. int
  359. main(int argc, char **argv)
  360. {
  361.     int op, code, n;
  362.     char *cp;
  363.     const char *err;
  364.     u_char *outp;
  365.     u_int32_t *ap;
  366.     struct sockaddr_in *from = (struct sockaddr_in *)&wherefrom;
  367.     struct sockaddr_in *to = (struct sockaddr_in *)&whereto;
  368.     struct hostinfo *hi;
  369.     int on = 1;
  370.     struct protoent *pe;
  371.     int ttl, probe, i;
  372.     int seq = 0;
  373.     int tos = 0, settos = 0;
  374.     int lsrr = 0;
  375.     u_short off = 0;
  376.     struct ifaddrlist *al;
  377.     char errbuf[132];
  378.  
  379.     if (argv[0] == NULL)
  380.         prog = "traceroute";
  381.     else if ((cp = strrchr(argv[0], '/')) != NULL)
  382.         prog = cp + 1;
  383.     else
  384.         prog = argv[0];
  385.  
  386.     opterr = 0;
  387.     while ((op = getopt(argc, argv, "adFInrvxf:g:i:m:p:q:s:t:w:z:")) != EOF)
  388.         switch (op) {
  389.  
  390.         case 'a':
  391.             asns = 1;
  392.             break;
  393.  
  394.         case 'd':
  395.             options |= SO_DEBUG;
  396.             break;
  397.  
  398.         case 'f':
  399.             first_ttl = str2val(optarg, "first ttl", 1, 255);
  400.             break;
  401.  
  402.         case 'F':
  403.             off = IP_DF;
  404.             break;
  405.  
  406.         case 'g':
  407.             if (lsrr >= NGATEWAYS) {
  408.                 Fprintf(stderr,
  409.                     "%s: No more than %d gateways\n",
  410.                     prog, NGATEWAYS);
  411.                 exit(1);
  412.             }
  413.             getaddr(gwlist + lsrr, optarg);
  414.             ++lsrr;
  415.             break;
  416.  
  417.         case 'i':
  418.             device = optarg;
  419.             break;
  420.  
  421.         case 'I':
  422.             ++useicmp;
  423.             break;
  424.  
  425.         case 'm':
  426.             max_ttl = str2val(optarg, "max ttl", 1, 255);
  427.             break;
  428.  
  429.         case 'n':
  430.             ++nflag;
  431.             break;
  432.  
  433.         case 'p':
  434.             port = (u_short)str2val(optarg, "port",
  435.                 1, (1 << 16) - 1);
  436.             break;
  437.  
  438.         case 'q':
  439.             nprobes = str2val(optarg, "nprobes", 1, -1);
  440.             break;
  441.  
  442.         case 'r':
  443.             options |= SO_DONTROUTE;
  444.             break;
  445.  
  446.         case 's':
  447.             /*
  448.              * set the ip source address of the outbound
  449.              * probe (e.g., on a multi-homed host).
  450.              */
  451.             source = optarg;
  452.             break;
  453.  
  454.         case 't':
  455.             tos = str2val(optarg, "tos", 0, 255);
  456.             ++settos;
  457.             break;
  458.  
  459.         case 'v':
  460.             ++verbose;
  461.             break;
  462.  
  463.         case 'x':
  464.             doipcksum = (doipcksum == 0);
  465.             break;
  466.  
  467.         case 'w':
  468.             waittime = str2val(optarg, "wait time",
  469.                 2, 24 * 60 * 60);
  470.             break;
  471.  
  472.         case 'z':
  473.             pausemsecs = str2val(optarg, "pause msecs",
  474.                 0, 60 * 60 * 1000);
  475.             break;
  476.  
  477.         default:
  478.             usage();
  479.         }
  480.  
  481.     if (first_ttl > max_ttl) {
  482.         Fprintf(stderr,
  483.             "%s: first ttl (%d) may not be greater than max ttl (%d)\n",
  484.             prog, first_ttl, max_ttl);
  485.         exit(1);
  486.     }
  487.  
  488.     if (!doipcksum)
  489.         Fprintf(stderr, "%s: Warning: ip checksums disabled\n", prog);
  490.  
  491.     if (lsrr > 0)
  492.         optlen = (lsrr + 1) * sizeof(gwlist[0]);
  493.     minpacket = sizeof(*outip) + sizeof(*outdata) + optlen;
  494.     if (useicmp)
  495.         minpacket += 8;            /* XXX magic number */
  496.     else
  497.         minpacket += sizeof(*outudp);
  498.     packlen = minpacket;            /* minimum sized packet */
  499.  
  500.     /* Process destination and optional packet size */
  501.     switch (argc - optind) {
  502.  
  503.     case 2:
  504.         packlen = str2val(argv[optind + 1],
  505.             "packet length", minpacket, maxpacket);
  506.         /* Fall through */
  507.  
  508.     case 1:
  509.         hostname = argv[optind];
  510.         hi = gethostinfo(hostname);
  511.         setsin(to, hi->addrs[0]);
  512.         if (hi->n > 1)
  513.             Fprintf(stderr,
  514.             "%s: Warning: %s has multiple addresses; using %s\n",
  515.                 prog, hostname, inet_ntoa(to->sin_addr));
  516.         hostname = hi->name;
  517.         hi->name = NULL;
  518.         freehostinfo(hi);
  519.         break;
  520.  
  521.     default:
  522.         usage();
  523.     }
  524.  
  525. #ifdef HAVE_SETLINEBUF
  526.     setlinebuf (stdout);
  527. #else
  528.     setvbuf(stdout, NULL, _IOLBF, 0);
  529. #endif
  530.  
  531.     outip = (struct ip *)malloc((unsigned)packlen);
  532.     if (outip == NULL) {
  533.         Fprintf(stderr, "%s: malloc: %s\n", prog, strerror(errno));
  534.         exit(1);
  535.     }
  536.     memset((char *)outip, 0, packlen);
  537.  
  538.     outip->ip_v = IPVERSION;
  539.     if (settos)
  540.         outip->ip_tos = tos;
  541. #ifdef BYTESWAP_IP_HDR
  542.     outip->ip_len = htons(packlen);
  543.     outip->ip_off = htons(off);
  544. #else
  545.     outip->ip_len = packlen;
  546.     outip->ip_off = off;
  547. #endif
  548.     outp = (u_char *)(outip + 1);
  549. #ifdef HAVE_RAW_OPTIONS
  550.     if (lsrr > 0) {
  551.         u_char *optlist;
  552.  
  553.         optlist = outp;
  554.         outp += optlen;
  555.  
  556.         /* final hop */
  557.         gwlist[lsrr] = to->sin_addr.s_addr;
  558.  
  559.         outip->ip_dst.s_addr = gwlist[0];
  560.  
  561.         /* force 4 byte alignment */
  562.         optlist[0] = IPOPT_NOP;
  563.         /* loose source route option */
  564.         optlist[1] = IPOPT_LSRR;
  565.         i = lsrr * sizeof(gwlist[0]);
  566.         optlist[2] = i + 3;
  567.         /* Pointer to LSRR addresses */
  568.         optlist[3] = IPOPT_MINOFF;
  569.         memcpy(optlist + 4, gwlist + 1, i);
  570.     } else
  571. #endif
  572.         outip->ip_dst = to->sin_addr;
  573.  
  574.     outip->ip_hl = (outp - (u_char *)outip) >> 2;
  575.     ident = (getpid() & 0xffff) | 0x8000;
  576.     if (useicmp) {
  577.         outip->ip_p = IPPROTO_ICMP;
  578.  
  579.         outicmp = (struct icmp *)outp;
  580.         outicmp->icmp_type = ICMP_ECHO;
  581.         outicmp->icmp_id = htons(ident);
  582.  
  583.         outdata = (struct outdata *)(outp + 8);    /* XXX magic number */
  584.     } else {
  585.         outip->ip_p = IPPROTO_UDP;
  586.  
  587.         outudp = (struct udphdr *)outp;
  588.         outudp->uh_sport = htons(ident);
  589.         outudp->uh_ulen =
  590.             htons((u_short)(packlen - (sizeof(*outip) + optlen)));
  591.         outdata = (struct outdata *)(outudp + 1);
  592.     }
  593.  
  594.     cp = "icmp";
  595.     if ((pe = getprotobyname(cp)) == NULL) {
  596.         Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
  597.         exit(1);
  598.     }
  599.  
  600.     /* Insure the socket fds won't be 0, 1 or 2 */
  601.     if (open(devnull, O_RDONLY) < 0 ||
  602.         open(devnull, O_RDONLY) < 0 ||
  603.         open(devnull, O_RDONLY) < 0) {
  604.         Fprintf(stderr, "%s: open \"%s\": %s\n",
  605.             prog, devnull, strerror(errno));
  606.         exit(1);
  607.     }
  608.     if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
  609.         Fprintf(stderr, "%s: icmp socket: %s\n", prog, strerror(errno));
  610.         exit(1);
  611.     }
  612.     if (options & SO_DEBUG)
  613.         (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&on,
  614.             sizeof(on));
  615.     if (options & SO_DONTROUTE)
  616.         (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
  617.             sizeof(on));
  618.  
  619. #ifndef __hpux
  620.     sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
  621. #else
  622.     sndsock = socket(AF_INET, SOCK_RAW,
  623.         useicmp ? IPPROTO_ICMP : IPPROTO_UDP);
  624. #endif
  625.     if (sndsock < 0) {
  626.         Fprintf(stderr, "%s: raw socket: %s\n", prog, strerror(errno));
  627.         exit(1);
  628.     }
  629.  
  630. #if defined(IP_OPTIONS) && !defined(HAVE_RAW_OPTIONS)
  631.     if (lsrr > 0) {
  632.         u_char optlist[MAX_IPOPTLEN];
  633.  
  634.         cp = "ip";
  635.         if ((pe = getprotobyname(cp)) == NULL) {
  636.             Fprintf(stderr, "%s: unknown protocol %s\n", prog, cp);
  637.             exit(1);
  638.         }
  639.  
  640.         /* final hop */
  641.         gwlist[lsrr] = to->sin_addr.s_addr;
  642.         ++lsrr;
  643.  
  644.         /* force 4 byte alignment */
  645.         optlist[0] = IPOPT_NOP;
  646.         /* loose source route option */
  647.         optlist[1] = IPOPT_LSRR;
  648.         i = lsrr * sizeof(gwlist[0]);
  649.         optlist[2] = i + 3;
  650.         /* Pointer to LSRR addresses */
  651.         optlist[3] = IPOPT_MINOFF;
  652.         memcpy(optlist + 4, gwlist, i);
  653.  
  654.         if ((setsockopt(sndsock, pe->p_proto, IP_OPTIONS,
  655.             (char *)optlist, i + sizeof(gwlist[0]))) < 0) {
  656.             Fprintf(stderr, "%s: IP_OPTIONS: %s\n",
  657.                 prog, strerror(errno));
  658.             exit(1);
  659.             }
  660.     }
  661. #endif
  662.  
  663. #ifdef SO_SNDBUF
  664.     if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&packlen,
  665.         sizeof(packlen)) < 0) {
  666.         Fprintf(stderr, "%s: SO_SNDBUF: %s\n", prog, strerror(errno));
  667.         exit(1);
  668.     }
  669. #endif
  670. #ifdef IP_HDRINCL
  671.     if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
  672.         sizeof(on)) < 0) {
  673.         Fprintf(stderr, "%s: IP_HDRINCL: %s\n", prog, strerror(errno));
  674.         exit(1);
  675.     }
  676. #else
  677. #ifdef IP_TOS
  678.     if (settos && setsockopt(sndsock, IPPROTO_IP, IP_TOS,
  679.         (char *)&tos, sizeof(tos)) < 0) {
  680.         Fprintf(stderr, "%s: setsockopt tos %d: %s\n",
  681.             prog, tos, strerror(errno));
  682.         exit(1);
  683.     }
  684. #endif
  685. #endif
  686.     if (options & SO_DEBUG)
  687.         (void)setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, (char *)&on,
  688.             sizeof(on));
  689.     if (options & SO_DONTROUTE)
  690.         (void)setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, (char *)&on,
  691.             sizeof(on));
  692.  
  693.     /* Get the interface address list */
  694.     n = ifaddrlist(&al, errbuf);
  695.     if (n < 0) {
  696.         Fprintf(stderr, "%s: ifaddrlist: %s\n", prog, errbuf);
  697.         exit(1);
  698.     }
  699.     if (n == 0) {
  700.         Fprintf(stderr,
  701.             "%s: Can't find any network interfaces\n", prog);
  702.         exit(1);
  703.     }
  704.  
  705.     /* Look for a specific device */
  706.     if (device != NULL) {
  707.         for (i = n; i > 0; --i, ++al)
  708.             if (strcmp(device, al->device) == 0)
  709.                 break;
  710.         if (i <= 0) {
  711.             Fprintf(stderr, "%s: Can't find interface %.32s\n",
  712.                 prog, device);
  713.             exit(1);
  714.         }
  715.     }
  716.  
  717.     /* Determine our source address */
  718.     if (source == NULL) {
  719.         /*
  720.          * If a device was specified, use the interface address.
  721.          * Otherwise, try to determine our source address.
  722.          */
  723.         if (device != NULL)
  724.             setsin(from, al->addr);
  725.         else if ((err = findsaddr(to, from)) != NULL) {
  726.             Fprintf(stderr, "%s: findsaddr: %s\n",
  727.                 prog, err);
  728.             exit(1);
  729.         }
  730.     } else {
  731.         hi = gethostinfo(source);
  732.         source = hi->name;
  733.         hi->name = NULL;
  734.         /*
  735.          * If the device was specified make sure it
  736.          * corresponds to the source address specified.
  737.          * Otherwise, use the first address (and warn if
  738.          * there are more than one).
  739.          */
  740.         if (device != NULL) {
  741.             for (i = hi->n, ap = hi->addrs; i > 0; --i, ++ap)
  742.                 if (*ap == al->addr)
  743.                     break;
  744.             if (i <= 0) {
  745.                 Fprintf(stderr,
  746.                     "%s: %s is not on interface %.32s\n",
  747.                     prog, source, device);
  748.                 exit(1);
  749.             }
  750.             setsin(from, *ap);
  751.         } else {
  752.             setsin(from, hi->addrs[0]);
  753.             if (hi->n > 1)
  754.                 Fprintf(stderr,
  755.             "%s: Warning: %s has multiple addresses; using %s\n",
  756.                     prog, source, inet_ntoa(from->sin_addr));
  757.         }
  758.         freehostinfo(hi);
  759.     }
  760.  
  761.     /* Revert to non-privileged user after opening sockets */
  762.     setgid(getgid());
  763.     setuid(getuid());
  764.  
  765.     outip->ip_src = from->sin_addr;
  766. #ifndef IP_HDRINCL
  767.     if (bind(sndsock, (struct sockaddr *)from, sizeof(*from)) < 0) {
  768.         Fprintf(stderr, "%s: bind: %s\n",
  769.             prog, strerror(errno));
  770.         exit (1);
  771.     }
  772. #endif
  773.  
  774.     Fprintf(stderr, "%s to %s (%s)",
  775.         prog, hostname, inet_ntoa(to->sin_addr));
  776.     if (source)
  777.         Fprintf(stderr, " from %s", source);
  778.     Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, packlen);
  779.     (void)fflush(stderr);
  780.  
  781.     for (ttl = first_ttl; ttl <= max_ttl; ++ttl) {
  782.         u_int32_t lastaddr = 0;
  783.         int gotlastaddr = 0;
  784.         int got_there = 0;
  785.         int unreachable = 0;
  786.         int sentfirst = 0;
  787.  
  788.         Printf("%2d ", ttl);
  789.         for (probe = 0; probe < nprobes; ++probe) {
  790.             int cc;
  791.             struct timeval t1, t2;
  792.             struct timezone tz;
  793.             struct ip *ip;
  794.  
  795.             if (sentfirst && pausemsecs > 0)
  796.                 usleep(pausemsecs * 1000);
  797.             (void)gettimeofday(&t1, &tz);
  798.             send_probe(++seq, ttl, &t1);
  799.             ++sentfirst;
  800.             while ((cc = wait_for_reply(s, from, &t1)) != 0) {
  801.                 (void)gettimeofday(&t2, &tz);
  802.                 i = packet_ok(packet, cc, from, seq);
  803.                 /* Skip short packet */
  804.                 if (i == 0)
  805.                     continue;
  806.                 if (!gotlastaddr ||
  807.                     from->sin_addr.s_addr != lastaddr) {
  808.                     print(packet, cc, from);
  809.                     lastaddr = from->sin_addr.s_addr;
  810.                     ++gotlastaddr;
  811.                 }
  812.                 Printf("  %.3f ms", deltaT(&t1, &t2));
  813.                 if (i == -2) {
  814. #ifndef ARCHAIC
  815.                     ip = (struct ip *)packet;
  816.                     if (ip->ip_ttl <= 1)
  817.                         Printf(" !");
  818. #endif
  819.                     ++got_there;
  820.                     break;
  821.                 }
  822.                 /* time exceeded in transit */
  823.                 if (i == -1)
  824.                     break;
  825.                 code = i - 1;
  826.                 switch (code) {
  827.  
  828.                 case ICMP_UNREACH_PORT:
  829. #ifndef ARCHAIC
  830.                     ip = (struct ip *)packet;
  831.                     if (ip->ip_ttl <= 1)
  832.                         Printf(" !");
  833. #endif
  834.                     ++got_there;
  835.                     break;
  836.  
  837.                 case ICMP_UNREACH_NET:
  838.                     ++unreachable;
  839.                     Printf(" !N");
  840.                     break;
  841.  
  842.                 case ICMP_UNREACH_HOST:
  843.                     ++unreachable;
  844.                     Printf(" !H");
  845.                     break;
  846.  
  847.                 case ICMP_UNREACH_PROTOCOL:
  848.                     ++got_there;
  849.                     Printf(" !P");
  850.                     break;
  851.  
  852.                 case ICMP_UNREACH_NEEDFRAG:
  853.                     ++unreachable;
  854.                     Printf(" !F-%d", pmtu);
  855.                     break;
  856.  
  857.                 case ICMP_UNREACH_SRCFAIL:
  858.                     ++unreachable;
  859.                     Printf(" !S");
  860.                     break;
  861.  
  862.                 case ICMP_UNREACH_FILTER_PROHIB:
  863.                     ++unreachable;
  864.                     Printf(" !X");
  865.                     break;
  866.  
  867.                 case ICMP_UNREACH_HOST_PRECEDENCE:
  868.                     ++unreachable;
  869.                     Printf(" !V");
  870.                     break;
  871.  
  872.                 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
  873.                     ++unreachable;
  874.                     Printf(" !C");
  875.                     break;
  876.  
  877.                 default:
  878.                     ++unreachable;
  879.                     Printf(" !<%d>", code);
  880.                     break;
  881.                 }
  882.                 break;
  883.             }
  884.             if (cc == 0)
  885.                 Printf(" *");
  886.             (void)fflush(stdout);
  887.         }
  888.         putchar('\n');
  889.         if (got_there ||
  890.             (unreachable > 0 && unreachable >= nprobes - 1))
  891.             break;
  892.     }
  893.     exit(0);
  894. }
  895.  
  896. int
  897. wait_for_reply(int sock, struct sockaddr_in *fromp,
  898.     const struct timeval *tp)
  899. {
  900.     fd_set fds;
  901.     struct timeval now, wait;
  902.     struct timezone tz;
  903.     int cc = 0;
  904.     int fromlen = sizeof(*fromp);
  905.  
  906.     FD_ZERO(&fds);
  907.     FD_SET(sock, &fds);
  908.  
  909.     wait.tv_sec = tp->tv_sec + waittime;
  910.     wait.tv_usec = tp->tv_usec;
  911.     (void)gettimeofday(&now, &tz);
  912.     tvsub(&wait, &now);
  913.  
  914.     if (select(sock + 1, &fds, NULL, NULL, &wait) > 0)
  915.         cc = recvfrom(sock, (char *)packet, sizeof(packet), 0,
  916.                 (struct sockaddr *)fromp, &fromlen);
  917.  
  918.     return(cc);
  919. }
  920.  
  921. void
  922. send_probe(int seq, int ttl, struct timeval *tp)
  923. {
  924.     int cc;
  925.     struct udpiphdr *ui, *oui;
  926.     struct ip tip;
  927.  
  928.     outip->ip_ttl = ttl;
  929. #ifndef __hpux
  930.     outip->ip_id = htons(ident + seq);
  931. #endif
  932.  
  933.     /*
  934.      * In most cases, the kernel will recalculate the ip checksum.
  935.      * But we must do it anyway so that the udp checksum comes out
  936.      * right.
  937.      */
  938.     if (doipcksum) {
  939.         outip->ip_sum =
  940.             in_cksum((u_short *)outip, sizeof(*outip) + optlen);
  941.         if (outip->ip_sum == 0)
  942.             outip->ip_sum = 0xffff;
  943.     }
  944.  
  945.     /* Payload */
  946.     outsetup.seq = seq;
  947.     outsetup.ttl = ttl;
  948.     outsetup.tv = *tp;
  949.     memcpy((uint8_t *)outdata, &outsetup, sizeof(outsetup));
  950.  
  951.     if (useicmp)
  952.         outicmp->icmp_seq = htons(seq);
  953.     else
  954.         outudp->uh_dport = htons(port + seq);
  955.  
  956.     if (useicmp) {
  957.         /* Always calculate checksum for icmp packets */
  958.         outicmp->icmp_cksum = 0;
  959.         outicmp->icmp_cksum = in_cksum((u_short *)outicmp,
  960.             packlen - (sizeof(*outip) + optlen));
  961.         if (outicmp->icmp_cksum == 0)
  962.             outicmp->icmp_cksum = 0xffff;
  963.     } else if (doipcksum) {
  964.         /* Checksum (we must save and restore ip header) */
  965.         tip = *outip;
  966.         ui = (struct udpiphdr *)outip;
  967.         oui = (struct udpiphdr *)&tip;
  968.         /* Easier to zero and put back things that are ok */
  969.         memset((char *)ui, 0, sizeof(ui->ui_i));
  970.         ui->ui_src = oui->ui_src;
  971.         ui->ui_dst = oui->ui_dst;
  972.         ui->ui_pr = oui->ui_pr;
  973.         ui->ui_len = outudp->uh_ulen;
  974.         outudp->uh_sum = 0;
  975.         outudp->uh_sum = in_cksum((u_short *)ui, packlen);
  976.         if (outudp->uh_sum == 0)
  977.             outudp->uh_sum = 0xffff;
  978.         *outip = tip;
  979.     }
  980.  
  981.     /* XXX undocumented debugging hack */
  982.     if (verbose > 1) {
  983.         const u_short *sp;
  984.         int nshorts, i;
  985.  
  986.         sp = (u_short *)outip;
  987.         nshorts = (u_int)packlen / sizeof(u_short);
  988.         i = 0;
  989.         Printf("[ %d bytes", packlen);
  990.         while (--nshorts >= 0) {
  991.             if ((i++ % 8) == 0)
  992.                 Printf("\n\t");
  993.             Printf(" %04x", ntohs(*sp++));
  994.         }
  995.         if (packlen & 1) {
  996.             if ((i % 8) == 0)
  997.                 Printf("\n\t");
  998.             Printf(" %02x", *(u_char *)sp);
  999.         }
  1000.         Printf("]\n");
  1001.     }
  1002.  
  1003. #if !defined(IP_HDRINCL) && defined(IP_TTL)
  1004.     if (setsockopt(sndsock, IPPROTO_IP, IP_TTL,
  1005.         (char *)&ttl, sizeof(ttl)) < 0) {
  1006.         Fprintf(stderr, "%s: setsockopt ttl %d: %s\n",
  1007.             prog, ttl, strerror(errno));
  1008.         exit(1);
  1009.     }
  1010. #endif
  1011.  
  1012. #ifdef __hpux
  1013.     cc = sendto(sndsock, useicmp ? (char *)outicmp : (char *)outudp,
  1014.         packlen - (sizeof(*outip) + optlen), 0, &whereto, sizeof(whereto));
  1015.     if (cc > 0)
  1016.         cc += sizeof(*outip) + optlen;
  1017. #else
  1018.     cc = sendto(sndsock, (char *)outip,
  1019.         packlen, 0, &whereto, sizeof(whereto));
  1020. #endif
  1021.     if (cc < 0 || cc != packlen)  {
  1022.         if (cc < 0)
  1023.             Fprintf(stderr, "%s: sendto: %s\n",
  1024.                 prog, strerror(errno));
  1025.         Printf("%s: wrote %s %d chars, ret=%d\n",
  1026.             prog, hostname, packlen, cc);
  1027.         (void)fflush(stdout);
  1028.     }
  1029. }
  1030.  
  1031. double
  1032. deltaT(struct timeval *t1p, struct timeval *t2p)
  1033. {
  1034.     double dt;
  1035.  
  1036.     dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
  1037.          (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
  1038.     return (dt);
  1039. }
  1040.  
  1041. /*
  1042.  * Convert an ICMP "type" field to a printable string.
  1043.  */
  1044. char *
  1045. pr_type(u_char t)
  1046. {
  1047.     static char *ttab[] = {
  1048.     "Echo Reply",    "ICMP 1",    "ICMP 2",    "Dest Unreachable",
  1049.     "Source Quench", "Redirect",    "ICMP 6",    "ICMP 7",
  1050.     "Echo",        "ICMP 9",    "ICMP 10",    "Time Exceeded",
  1051.     "Param Problem", "Timestamp",    "Timestamp Reply", "Info Request",
  1052.     "Info Reply"
  1053.     };
  1054.  
  1055.     if (t > 16)
  1056.         return("OUT-OF-RANGE");
  1057.  
  1058.     return(ttab[t]);
  1059. }
  1060.  
  1061. int
  1062. packet_ok(u_char *buf, int cc, struct sockaddr_in *from,
  1063.     int seq)
  1064. {
  1065.     struct icmp *icp;
  1066.     u_char type, code;
  1067.     int hlen;
  1068. #ifndef ARCHAIC
  1069.     struct ip *ip;
  1070.  
  1071.     ip = (struct ip *) buf;
  1072.     hlen = ip->ip_hl << 2;
  1073.     if (cc < hlen + ICMP_MINLEN) {
  1074.         if (verbose)
  1075.             Printf("packet too short (%d bytes) from %s\n", cc,
  1076.                 inet_ntoa(from->sin_addr));
  1077.         return (0);
  1078.     }
  1079.     cc -= hlen;
  1080.     icp = (struct icmp *)(buf + hlen);
  1081. #else
  1082.     icp = (struct icmp *)buf;
  1083. #endif
  1084.     type = icp->icmp_type;
  1085.     code = icp->icmp_code;
  1086.     /* Path MTU Discovery (RFC1191) */
  1087.     if (code != ICMP_UNREACH_NEEDFRAG)
  1088.         pmtu = 0;
  1089.     else {
  1090. #ifdef HAVE_ICMP_NEXTMTU
  1091.         pmtu = ntohs(icp->icmp_nextmtu);
  1092. #else
  1093.         pmtu = ntohs(((struct my_pmtu *)&icp->icmp_void)->ipm_nextmtu);
  1094. #endif
  1095.     }
  1096.     if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
  1097.         type == ICMP_UNREACH || type == ICMP_ECHOREPLY) {
  1098.         struct ip *hip;
  1099.         struct udphdr *up;
  1100.         struct icmp *hicmp;
  1101.  
  1102.         hip = &icp->icmp_ip;
  1103.         hlen = hip->ip_hl << 2;
  1104.         if (useicmp) {
  1105.             /* XXX */
  1106.             if (type == ICMP_ECHOREPLY &&
  1107.                 icp->icmp_id == htons(ident) &&
  1108.                 icp->icmp_seq == htons(seq))
  1109.                 return (-2);
  1110.  
  1111.             hicmp = (struct icmp *)((u_char *)hip + hlen);
  1112.             /* XXX 8 is a magic number */
  1113.             if (hlen + 8 <= cc &&
  1114.                 hip->ip_p == IPPROTO_ICMP &&
  1115.                 hicmp->icmp_id == htons(ident) &&
  1116.                 hicmp->icmp_seq == htons(seq))
  1117.                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
  1118.         } else {
  1119.             up = (struct udphdr *)((u_char *)hip + hlen);
  1120.             /* XXX 8 is a magic number */
  1121.             if (hlen + 12 <= cc &&
  1122.                 hip->ip_p == IPPROTO_UDP &&
  1123.                 up->uh_sport == htons(ident) &&
  1124.                 up->uh_dport == htons(port + seq))
  1125.                 return (type == ICMP_TIMXCEED ? -1 : code + 1);
  1126.         }
  1127.     }
  1128. #ifndef ARCHAIC
  1129.     if (verbose) {
  1130.         int i;
  1131.         u_int32_t *lp = (u_int32_t *)&icp->icmp_ip;
  1132.  
  1133.         Printf("\n%d bytes from %s to ", cc, inet_ntoa(from->sin_addr));
  1134.         Printf("%s: icmp type %d (%s) code %d\n",
  1135.             inet_ntoa(ip->ip_dst), type, pr_type(type), icp->icmp_code);
  1136.         for (i = 4; i < cc ; i += sizeof(*lp))
  1137.             Printf("%2d: x%8.8x\n", i, *lp++);
  1138.     }
  1139. #endif
  1140.     return(0);
  1141. }
  1142.  
  1143.  
  1144. void
  1145. print(u_char *buf, int cc, struct sockaddr_in *from)
  1146. {
  1147.     struct ip *ip;
  1148.     int hlen;
  1149.  
  1150.     ip = (struct ip *) buf;
  1151.     hlen = ip->ip_hl << 2;
  1152.     cc -= hlen;
  1153.  
  1154.     if (asns)
  1155.         Printf(" [AS%d]", asn_lookup(from));
  1156.  
  1157.     if (nflag)
  1158.         Printf(" %s", inet_ntoa(from->sin_addr));
  1159.     else
  1160.         Printf(" %s (%s)", inetname(from->sin_addr),
  1161.             inet_ntoa(from->sin_addr));
  1162.  
  1163.     if (verbose)
  1164.         Printf(" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
  1165. }
  1166.  
  1167. /*
  1168.  * Checksum routine for Internet Protocol family headers (C Version)
  1169.  */
  1170. u_short
  1171. in_cksum(u_short *addr, int len)
  1172. {
  1173.     int nleft = len;
  1174.     u_short *w = addr;
  1175.     u_short answer;
  1176.     int sum = 0;
  1177.  
  1178.     /*
  1179.      *  Our algorithm is simple, using a 32 bit accumulator (sum),
  1180.      *  we add sequential 16 bit words to it, and at the end, fold
  1181.      *  back all the carry bits from the top 16 bits into the lower
  1182.      *  16 bits.
  1183.      */
  1184.     while (nleft > 1)  {
  1185.         sum += *w++;
  1186.         nleft -= 2;
  1187.     }
  1188.  
  1189.     /* mop up an odd byte, if necessary */
  1190.     if (nleft == 1)
  1191.         sum += *(u_char *)w;
  1192.  
  1193.     /*
  1194.      * add back carry outs from top 16 bits to low 16 bits
  1195.      */
  1196.     sum = (sum >> 16) + (sum & 0xffff);    /* add hi 16 to low 16 */
  1197.     sum += (sum >> 16);            /* add carry */
  1198.     answer = ~sum;                /* truncate to 16 bits */
  1199.     return (answer);
  1200. }
  1201.  
  1202. /*
  1203.  * Subtract 2 timeval structs:  out = out - in.
  1204.  * Out is assumed to be >= in.
  1205.  */
  1206. void
  1207. tvsub(struct timeval *out, struct timeval *in)
  1208. {
  1209.  
  1210.     if ((out->tv_usec -= in->tv_usec) < 0)   {
  1211.         --out->tv_sec;
  1212.         out->tv_usec += 1000000;
  1213.     }
  1214.     out->tv_sec -= in->tv_sec;
  1215. }
  1216.  
  1217. /*
  1218.  * Construct an Internet address representation.
  1219.  * If the nflag has been supplied, give
  1220.  * numeric value, otherwise try for symbolic name.
  1221.  */
  1222. char *
  1223. inetname(struct in_addr in)
  1224. {
  1225.     char *cp;
  1226.     struct hostent *hp;
  1227.     static int first = 1;
  1228.     static char domain[MAXHOSTNAMELEN + 1], line[MAXHOSTNAMELEN + 1];
  1229.  
  1230.     if (first && !nflag) {
  1231.         first = 0;
  1232.         if (gethostname(domain, sizeof(domain) - 1) < 0)
  1233.             domain[0] = '\0';
  1234.         else {
  1235.             cp = strchr(domain, '.');
  1236.             if (cp == NULL) {
  1237.                 hp = gethostbyname(domain);
  1238.                 if (hp != NULL)
  1239.                     cp = strchr(hp->h_name, '.');
  1240.             }
  1241.             if (cp == NULL)
  1242.                 domain[0] = '\0';
  1243.             else {
  1244.                 ++cp;
  1245.                 (void)strncpy(domain, cp, sizeof(domain) - 1);
  1246.                 domain[sizeof(domain) - 1] = '\0';
  1247.             }
  1248.         }
  1249.     }
  1250.     if (!nflag && in.s_addr != INADDR_ANY) {
  1251.         hp = gethostbyaddr((char *)&in, sizeof(in), AF_INET);
  1252.         if (hp != NULL) {
  1253.             if ((cp = strchr(hp->h_name, '.')) != NULL &&
  1254.                 strcmp(cp + 1, domain) == 0)
  1255.                 *cp = '\0';
  1256.             (void)strncpy(line, hp->h_name, sizeof(line) - 1);
  1257.             line[sizeof(line) - 1] = '\0';
  1258.             return (line);
  1259.         }
  1260.     }
  1261.     return (inet_ntoa(in));
  1262. }
  1263.  
  1264. struct hostinfo *
  1265. gethostinfo(char *hostname)
  1266. {
  1267.     int n;
  1268.     struct hostent *hp;
  1269.     struct hostinfo *hi;
  1270.     char **p;
  1271.     u_int32_t addr, *ap;
  1272.  
  1273.     if (strlen(hostname) > 64) {
  1274.         Fprintf(stderr, "%s: hostname \"%.32s...\" is too long\n",
  1275.             prog, hostname);
  1276.         exit(1);
  1277.     }
  1278.     hi = calloc(1, sizeof(*hi));
  1279.     if (hi == NULL) {
  1280.         Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
  1281.         exit(1);
  1282.     }
  1283.     addr = inet_addr(hostname);
  1284.     if ((int32_t)addr != -1) {
  1285.         hi->name = strdup(hostname);
  1286.         hi->n = 1;
  1287.         hi->addrs = calloc(1, sizeof(hi->addrs[0]));
  1288.         if (hi->addrs == NULL) {
  1289.             Fprintf(stderr, "%s: calloc %s\n",
  1290.                 prog, strerror(errno));
  1291.             exit(1);
  1292.         }
  1293.         hi->addrs[0] = addr;
  1294.         return (hi);
  1295.     }
  1296.  
  1297.     hp = gethostbyname(hostname);
  1298.     if (hp == NULL) {
  1299.         Fprintf(stderr, "%s: unknown host %s\n", prog, hostname);
  1300.         exit(1);
  1301.     }
  1302.     if (hp->h_addrtype != AF_INET || hp->h_length != 4) {
  1303.         Fprintf(stderr, "%s: bad host %s\n", prog, hostname);
  1304.         exit(1);
  1305.     }
  1306.     hi->name = strdup(hp->h_name);
  1307.     for (n = 0, p = hp->h_addr_list; *p != NULL; ++n, ++p)
  1308.         continue;
  1309.     hi->n = n;
  1310.     hi->addrs = calloc(n, sizeof(hi->addrs[0]));
  1311.     if (hi->addrs == NULL) {
  1312.         Fprintf(stderr, "%s: calloc %s\n", prog, strerror(errno));
  1313.         exit(1);
  1314.     }
  1315.     for (ap = hi->addrs, p = hp->h_addr_list; *p != NULL; ++ap, ++p)
  1316.         memcpy(ap, *p, sizeof(*ap));
  1317.     return (hi);
  1318. }
  1319.  
  1320. void
  1321. freehostinfo(struct hostinfo *hi)
  1322. {
  1323.     if (hi->name != NULL) {
  1324.         free(hi->name);
  1325.         hi->name = NULL;
  1326.     }
  1327.     free((char *)hi->addrs);
  1328.     free((char *)hi);
  1329. }
  1330.  
  1331. void
  1332. getaddr(u_int32_t *ap, char *hostname)
  1333. {
  1334.     struct hostinfo *hi;
  1335.  
  1336.     hi = gethostinfo(hostname);
  1337.     *ap = hi->addrs[0];
  1338.     freehostinfo(hi);
  1339. }
  1340.  
  1341. void
  1342. setsin(struct sockaddr_in *sin, u_int32_t addr)
  1343. {
  1344.  
  1345.     memset(sin, 0, sizeof(*sin));
  1346. #ifdef HAVE_SOCKADDR_SA_LEN
  1347.     sin->sin_len = sizeof(*sin);
  1348. #endif
  1349.     sin->sin_family = AF_INET;
  1350.     sin->sin_addr.s_addr = addr;
  1351. }
  1352.  
  1353. /* String to value with optional min and max. Handles decimal and hex. */
  1354. int
  1355. str2val(const char *str, const char *what,
  1356.     int mi, int ma)
  1357. {
  1358.     const char *cp;
  1359.     int val;
  1360.     char *ep;
  1361.  
  1362.     if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
  1363.         cp = str + 2;
  1364.         val = (int)strtol(cp, &ep, 16);
  1365.     } else
  1366.         val = (int)strtol(str, &ep, 10);
  1367.     if (*ep != '\0') {
  1368.         Fprintf(stderr, "%s: \"%s\" bad value for %s \n",
  1369.             prog, str, what);
  1370.         exit(1);
  1371.     }
  1372.     if (val < mi && mi >= 0) {
  1373.         if (mi == 0)
  1374.             Fprintf(stderr, "%s: %s must be >= %d\n",
  1375.                 prog, what, mi);
  1376.         else
  1377.             Fprintf(stderr, "%s: %s must be > %d\n",
  1378.                 prog, what, mi - 1);
  1379.         exit(1);
  1380.     }
  1381.     if (val > ma && ma >= 0) {
  1382.         Fprintf(stderr, "%s: %s must be <= %d\n", prog, what, ma);
  1383.         exit(1);
  1384.     }
  1385.     return (val);
  1386. }
  1387.  
  1388. void
  1389. usage(void)
  1390. {
  1391.     extern char version[];
  1392.  
  1393.     Fprintf(stderr, "Version %s\n", version);
  1394.     Fprintf(stderr,
  1395.         "Usage: %s [-dFInrvx] [-g gateway] [-i iface] [-f first_ttl]\n"
  1396.         "\t[-m max_ttl] [ -p port] [-q nqueries] [-s src_addr] [-t tos]\n"
  1397.         "\t[-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
  1398.     exit(1);
  1399. }
  1400.