Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.5
      1  1.1      cgd /*-
      2  1.3  mycroft  * Copyright (c) 1990, 1993
      3  1.3  mycroft  *	The Regents of the University of California.  All rights reserved.
      4  1.1      cgd  *
      5  1.1      cgd  * This code is derived from software contributed to Berkeley by
      6  1.1      cgd  * Van Jacobson.
      7  1.1      cgd  *
      8  1.1      cgd  * Redistribution and use in source and binary forms, with or without
      9  1.1      cgd  * modification, are permitted provided that the following conditions
     10  1.1      cgd  * are met:
     11  1.1      cgd  * 1. Redistributions of source code must retain the above copyright
     12  1.1      cgd  *    notice, this list of conditions and the following disclaimer.
     13  1.1      cgd  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1      cgd  *    notice, this list of conditions and the following disclaimer in the
     15  1.1      cgd  *    documentation and/or other materials provided with the distribution.
     16  1.1      cgd  * 3. All advertising materials mentioning features or use of this software
     17  1.1      cgd  *    must display the following acknowledgement:
     18  1.1      cgd  *	This product includes software developed by the University of
     19  1.1      cgd  *	California, Berkeley and its contributors.
     20  1.1      cgd  * 4. Neither the name of the University nor the names of its contributors
     21  1.1      cgd  *    may be used to endorse or promote products derived from this software
     22  1.1      cgd  *    without specific prior written permission.
     23  1.1      cgd  *
     24  1.1      cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25  1.1      cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  1.1      cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  1.1      cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28  1.1      cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  1.1      cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  1.1      cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  1.1      cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  1.1      cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  1.1      cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  1.1      cgd  * SUCH DAMAGE.
     35  1.1      cgd  */
     36  1.1      cgd 
     37  1.1      cgd #ifndef lint
     38  1.3  mycroft static char copyright[] =
     39  1.3  mycroft "@(#) Copyright (c) 1990, 1993\n\
     40  1.3  mycroft 	The Regents of the University of California.  All rights reserved.\n";
     41  1.1      cgd #endif /* not lint */
     42  1.1      cgd 
     43  1.1      cgd #ifndef lint
     44  1.3  mycroft /*static char sccsid[] = "from: @(#)traceroute.c	8.1 (Berkeley) 6/6/93";*/
     45  1.5  mycroft static char *rcsid = "$Id: traceroute.c,v 1.5 1995/01/04 04:42:09 mycroft Exp $";
     46  1.1      cgd #endif /* not lint */
     47  1.1      cgd 
     48  1.1      cgd /*
     49  1.1      cgd  * traceroute host  - trace the route ip packets follow going to "host".
     50  1.1      cgd  *
     51  1.1      cgd  * Attempt to trace the route an ip packet would follow to some
     52  1.1      cgd  * internet host.  We find out intermediate hops by launching probe
     53  1.1      cgd  * packets with a small ttl (time to live) then listening for an
     54  1.1      cgd  * icmp "time exceeded" reply from a gateway.  We start our probes
     55  1.1      cgd  * with a ttl of one and increase by one until we get an icmp "port
     56  1.1      cgd  * unreachable" (which means we got to "host") or hit a max (which
     57  1.1      cgd  * defaults to 30 hops & can be changed with the -m flag).  Three
     58  1.1      cgd  * probes (change with -q flag) are sent at each ttl setting and a
     59  1.1      cgd  * line is printed showing the ttl, address of the gateway and
     60  1.1      cgd  * round trip time of each probe.  If the probe answers come from
     61  1.1      cgd  * different gateways, the address of each responding system will
     62  1.1      cgd  * be printed.  If there is no response within a 5 sec. timeout
     63  1.1      cgd  * interval (changed with the -w flag), a "*" is printed for that
     64  1.1      cgd  * probe.
     65  1.1      cgd  *
     66  1.1      cgd  * Probe packets are UDP format.  We don't want the destination
     67  1.1      cgd  * host to process them so the destination port is set to an
     68  1.1      cgd  * unlikely value (if some clod on the destination is using that
     69  1.1      cgd  * value, it can be changed with the -p flag).
     70  1.1      cgd  *
     71  1.1      cgd  * A sample use might be:
     72  1.1      cgd  *
     73  1.1      cgd  *     [yak 71]% traceroute nis.nsf.net.
     74  1.1      cgd  *     traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
     75  1.1      cgd  *      1  helios.ee.lbl.gov (128.3.112.1)  19 ms  19 ms  0 ms
     76  1.1      cgd  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     77  1.1      cgd  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  39 ms  19 ms
     78  1.1      cgd  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  39 ms
     79  1.1      cgd  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  39 ms  39 ms  39 ms
     80  1.1      cgd  *      6  128.32.197.4 (128.32.197.4)  40 ms  59 ms  59 ms
     81  1.1      cgd  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  59 ms
     82  1.1      cgd  *      8  129.140.70.13 (129.140.70.13)  99 ms  99 ms  80 ms
     83  1.1      cgd  *      9  129.140.71.6 (129.140.71.6)  139 ms  239 ms  319 ms
     84  1.1      cgd  *     10  129.140.81.7 (129.140.81.7)  220 ms  199 ms  199 ms
     85  1.1      cgd  *     11  nic.merit.edu (35.1.1.48)  239 ms  239 ms  239 ms
     86  1.1      cgd  *
     87  1.1      cgd  * Note that lines 2 & 3 are the same.  This is due to a buggy
     88  1.1      cgd  * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
     89  1.1      cgd  * packets with a zero ttl.
     90  1.1      cgd  *
     91  1.1      cgd  * A more interesting example is:
     92  1.1      cgd  *
     93  1.1      cgd  *     [yak 72]% traceroute allspice.lcs.mit.edu.
     94  1.1      cgd  *     traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
     95  1.1      cgd  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
     96  1.1      cgd  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  19 ms  19 ms
     97  1.1      cgd  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  19 ms
     98  1.1      cgd  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  19 ms  39 ms  39 ms
     99  1.1      cgd  *      5  ccn-nerif22.Berkeley.EDU (128.32.168.22)  20 ms  39 ms  39 ms
    100  1.1      cgd  *      6  128.32.197.4 (128.32.197.4)  59 ms  119 ms  39 ms
    101  1.1      cgd  *      7  131.119.2.5 (131.119.2.5)  59 ms  59 ms  39 ms
    102  1.1      cgd  *      8  129.140.70.13 (129.140.70.13)  80 ms  79 ms  99 ms
    103  1.1      cgd  *      9  129.140.71.6 (129.140.71.6)  139 ms  139 ms  159 ms
    104  1.1      cgd  *     10  129.140.81.7 (129.140.81.7)  199 ms  180 ms  300 ms
    105  1.1      cgd  *     11  129.140.72.17 (129.140.72.17)  300 ms  239 ms  239 ms
    106  1.1      cgd  *     12  * * *
    107  1.1      cgd  *     13  128.121.54.72 (128.121.54.72)  259 ms  499 ms  279 ms
    108  1.1      cgd  *     14  * * *
    109  1.1      cgd  *     15  * * *
    110  1.1      cgd  *     16  * * *
    111  1.1      cgd  *     17  * * *
    112  1.1      cgd  *     18  ALLSPICE.LCS.MIT.EDU (18.26.0.115)  339 ms  279 ms  279 ms
    113  1.1      cgd  *
    114  1.1      cgd  * (I start to see why I'm having so much trouble with mail to
    115  1.1      cgd  * MIT.)  Note that the gateways 12, 14, 15, 16 & 17 hops away
    116  1.1      cgd  * either don't send ICMP "time exceeded" messages or send them
    117  1.1      cgd  * with a ttl too small to reach us.  14 - 17 are running the
    118  1.1      cgd  * MIT C Gateway code that doesn't send "time exceeded"s.  God
    119  1.1      cgd  * only knows what's going on with 12.
    120  1.1      cgd  *
    121  1.1      cgd  * The silent gateway 12 in the above may be the result of a bug in
    122  1.1      cgd  * the 4.[23]BSD network code (and its derivatives):  4.x (x <= 3)
    123  1.1      cgd  * sends an unreachable message using whatever ttl remains in the
    124  1.1      cgd  * original datagram.  Since, for gateways, the remaining ttl is
    125  1.1      cgd  * zero, the icmp "time exceeded" is guaranteed to not make it back
    126  1.1      cgd  * to us.  The behavior of this bug is slightly more interesting
    127  1.1      cgd  * when it appears on the destination system:
    128  1.1      cgd  *
    129  1.1      cgd  *      1  helios.ee.lbl.gov (128.3.112.1)  0 ms  0 ms  0 ms
    130  1.1      cgd  *      2  lilac-dmc.Berkeley.EDU (128.32.216.1)  39 ms  19 ms  39 ms
    131  1.1      cgd  *      3  lilac-dmc.Berkeley.EDU (128.32.216.1)  19 ms  39 ms  19 ms
    132  1.1      cgd  *      4  ccngw-ner-cc.Berkeley.EDU (128.32.136.23)  39 ms  40 ms  19 ms
    133  1.1      cgd  *      5  ccn-nerif35.Berkeley.EDU (128.32.168.35)  39 ms  39 ms  39 ms
    134  1.1      cgd  *      6  csgw.Berkeley.EDU (128.32.133.254)  39 ms  59 ms  39 ms
    135  1.1      cgd  *      7  * * *
    136  1.1      cgd  *      8  * * *
    137  1.1      cgd  *      9  * * *
    138  1.1      cgd  *     10  * * *
    139  1.1      cgd  *     11  * * *
    140  1.1      cgd  *     12  * * *
    141  1.1      cgd  *     13  rip.Berkeley.EDU (128.32.131.22)  59 ms !  39 ms !  39 ms !
    142  1.1      cgd  *
    143  1.1      cgd  * Notice that there are 12 "gateways" (13 is the final
    144  1.1      cgd  * destination) and exactly the last half of them are "missing".
    145  1.1      cgd  * What's really happening is that rip (a Sun-3 running Sun OS3.5)
    146  1.1      cgd  * is using the ttl from our arriving datagram as the ttl in its
    147  1.1      cgd  * icmp reply.  So, the reply will time out on the return path
    148  1.1      cgd  * (with no notice sent to anyone since icmp's aren't sent for
    149  1.1      cgd  * icmp's) until we probe with a ttl that's at least twice the path
    150  1.1      cgd  * length.  I.e., rip is really only 7 hops away.  A reply that
    151  1.1      cgd  * returns with a ttl of 1 is a clue this problem exists.
    152  1.1      cgd  * Traceroute prints a "!" after the time if the ttl is <= 1.
    153  1.1      cgd  * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
    154  1.1      cgd  * non-standard (HPUX) software, expect to see this problem
    155  1.1      cgd  * frequently and/or take care picking the target host of your
    156  1.1      cgd  * probes.
    157  1.1      cgd  *
    158  1.1      cgd  * Other possible annotations after the time are !H, !N, !P (got a host,
    159  1.1      cgd  * network or protocol unreachable, respectively), !S or !F (source
    160  1.1      cgd  * route failed or fragmentation needed -- neither of these should
    161  1.1      cgd  * ever occur and the associated gateway is busted if you see one).  If
    162  1.1      cgd  * almost all the probes result in some kind of unreachable, traceroute
    163  1.1      cgd  * will give up and exit.
    164  1.1      cgd  *
    165  1.1      cgd  * Notes
    166  1.1      cgd  * -----
    167  1.1      cgd  * This program must be run by root or be setuid.  (I suggest that
    168  1.1      cgd  * you *don't* make it setuid -- casual use could result in a lot
    169  1.1      cgd  * of unnecessary traffic on our poor, congested nets.)
    170  1.1      cgd  *
    171  1.1      cgd  * This program requires a kernel mod that does not appear in any
    172  1.1      cgd  * system available from Berkeley:  A raw ip socket using proto
    173  1.1      cgd  * IPPROTO_RAW must interpret the data sent as an ip datagram (as
    174  1.1      cgd  * opposed to data to be wrapped in a ip datagram).  See the README
    175  1.1      cgd  * file that came with the source to this program for a description
    176  1.1      cgd  * of the mods I made to /sys/netinet/raw_ip.c.  Your mileage may
    177  1.1      cgd  * vary.  But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
    178  1.1      cgd  * MODIFIED TO RUN THIS PROGRAM.
    179  1.1      cgd  *
    180  1.1      cgd  * The udp port usage may appear bizarre (well, ok, it is bizarre).
    181  1.1      cgd  * The problem is that an icmp message only contains 8 bytes of
    182  1.1      cgd  * data from the original datagram.  8 bytes is the size of a udp
    183  1.1      cgd  * header so, if we want to associate replies with the original
    184  1.1      cgd  * datagram, the necessary information must be encoded into the
    185  1.1      cgd  * udp header (the ip id could be used but there's no way to
    186  1.1      cgd  * interlock with the kernel's assignment of ip id's and, anyway,
    187  1.1      cgd  * it would have taken a lot more kernel hacking to allow this
    188  1.1      cgd  * code to set the ip id).  So, to allow two or more users to
    189  1.1      cgd  * use traceroute simultaneously, we use this task's pid as the
    190  1.1      cgd  * source port (the high bit is set to move the port number out
    191  1.1      cgd  * of the "likely" range).  To keep track of which probe is being
    192  1.1      cgd  * replied to (so times and/or hop counts don't get confused by a
    193  1.1      cgd  * reply that was delayed in transit), we increment the destination
    194  1.1      cgd  * port number before each probe.
    195  1.1      cgd  *
    196  1.1      cgd  * Don't use this as a coding example.  I was trying to find a
    197  1.1      cgd  * routing problem and this code sort-of popped out after 48 hours
    198  1.1      cgd  * without sleep.  I was amazed it ever compiled, much less ran.
    199  1.1      cgd  *
    200  1.1      cgd  * I stole the idea for this program from Steve Deering.  Since
    201  1.1      cgd  * the first release, I've learned that had I attended the right
    202  1.1      cgd  * IETF working group meetings, I also could have stolen it from Guy
    203  1.1      cgd  * Almes or Matt Mathis.  I don't know (or care) who came up with
    204  1.1      cgd  * the idea first.  I envy the originators' perspicacity and I'm
    205  1.1      cgd  * glad they didn't keep the idea a secret.
    206  1.1      cgd  *
    207  1.1      cgd  * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
    208  1.1      cgd  * enhancements to the original distribution.
    209  1.1      cgd  *
    210  1.1      cgd  * I've hacked up a round-trip-route version of this that works by
    211  1.1      cgd  * sending a loose-source-routed udp datagram through the destination
    212  1.1      cgd  * back to yourself.  Unfortunately, SO many gateways botch source
    213  1.1      cgd  * routing, the thing is almost worthless.  Maybe one day...
    214  1.1      cgd  *
    215  1.1      cgd  *  -- Van Jacobson (van (at) helios.ee.lbl.gov)
    216  1.1      cgd  *     Tue Dec 20 03:50:13 PST 1988
    217  1.1      cgd  */
    218  1.1      cgd 
    219  1.1      cgd #include <sys/param.h>
    220  1.1      cgd #include <sys/time.h>
    221  1.1      cgd #include <sys/socket.h>
    222  1.1      cgd #include <sys/file.h>
    223  1.1      cgd #include <sys/ioctl.h>
    224  1.1      cgd 
    225  1.1      cgd #include <netinet/in_systm.h>
    226  1.1      cgd #include <netinet/in.h>
    227  1.1      cgd #include <netinet/ip.h>
    228  1.1      cgd #include <netinet/ip_icmp.h>
    229  1.4  mycroft #include <netinet/ip_var.h>
    230  1.1      cgd #include <netinet/udp.h>
    231  1.3  mycroft 
    232  1.3  mycroft #include <arpa/inet.h>
    233  1.3  mycroft 
    234  1.4  mycroft #include <ctype.h>
    235  1.5  mycroft #include <err.h>
    236  1.4  mycroft #include <errno.h>
    237  1.1      cgd #include <netdb.h>
    238  1.1      cgd #include <stdio.h>
    239  1.3  mycroft #include <stdlib.h>
    240  1.1      cgd #include <string.h>
    241  1.3  mycroft #include <unistd.h>
    242  1.1      cgd 
    243  1.1      cgd #define Fprintf (void)fprintf
    244  1.1      cgd #define Sprintf (void)sprintf
    245  1.1      cgd #define Printf (void)printf
    246  1.1      cgd 
    247  1.4  mycroft #define	HEADERSIZE	(sizeof(struct ip) + lsrrlen + sizeof(struct udphdr) + sizeof(struct packetdata))
    248  1.4  mycroft #define	MAX_LSRR	((MAX_IPOPTLEN - 4) / 4)
    249  1.4  mycroft 
    250  1.1      cgd /*
    251  1.4  mycroft  * Format of the data in a (udp) probe packet.
    252  1.1      cgd  */
    253  1.4  mycroft struct packetdata {
    254  1.1      cgd 	u_char seq;		/* sequence number of this packet */
    255  1.1      cgd 	u_char ttl;		/* ttl packet left with */
    256  1.1      cgd 	struct timeval tv;	/* time packet left */
    257  1.1      cgd };
    258  1.1      cgd 
    259  1.4  mycroft struct in_addr gateway[MAX_LSRR + 1];
    260  1.4  mycroft int lsrrlen = 0;
    261  1.4  mycroft 
    262  1.4  mycroft u_char packet[512], *outpacket;	/* last inbound (icmp) packet */
    263  1.3  mycroft 
    264  1.3  mycroft int wait_for_reply __P((int, struct sockaddr_in *));
    265  1.4  mycroft void send_probe __P((int, int, struct sockaddr_in *));
    266  1.3  mycroft double deltaT __P((struct timeval *, struct timeval *));
    267  1.3  mycroft int packet_ok __P((u_char *, int, struct sockaddr_in *, int));
    268  1.3  mycroft void print __P((u_char *, int, struct sockaddr_in *));
    269  1.3  mycroft void tvsub __P((struct timeval *, struct timeval *));
    270  1.3  mycroft char *inetname __P((struct in_addr));
    271  1.4  mycroft void usage __P((void));
    272  1.1      cgd 
    273  1.1      cgd int s;				/* receive (icmp) socket file descriptor */
    274  1.1      cgd int sndsock;			/* send (udp) socket file descriptor */
    275  1.1      cgd struct timezone tz;		/* leftover */
    276  1.1      cgd 
    277  1.1      cgd int datalen;			/* How much data */
    278  1.1      cgd 
    279  1.1      cgd char *source = 0;
    280  1.1      cgd char *hostname;
    281  1.1      cgd 
    282  1.1      cgd int nprobes = 3;
    283  1.1      cgd int max_ttl = 30;
    284  1.1      cgd u_short ident;
    285  1.1      cgd u_short port = 32768+666;	/* start udp dest port # for probe packets */
    286  1.1      cgd int options;			/* socket options */
    287  1.1      cgd int verbose;
    288  1.1      cgd int waittime = 5;		/* time to wait for response (in seconds) */
    289  1.1      cgd int nflag;			/* print addresses numerically */
    290  1.4  mycroft int dump;
    291  1.1      cgd 
    292  1.3  mycroft int
    293  1.1      cgd main(argc, argv)
    294  1.3  mycroft 	int argc;
    295  1.1      cgd 	char *argv[];
    296  1.1      cgd {
    297  1.1      cgd 	struct hostent *hp;
    298  1.1      cgd 	struct protoent *pe;
    299  1.4  mycroft 	struct sockaddr_in from, to;
    300  1.4  mycroft 	int ch, i, lsrr, on, probe, seq, tos, ttl;
    301  1.4  mycroft 	u_long gw;
    302  1.4  mycroft 	struct ip *ip;
    303  1.1      cgd 
    304  1.4  mycroft 	lsrr = 0;
    305  1.1      cgd 	on = 1;
    306  1.1      cgd 	seq = tos = 0;
    307  1.4  mycroft 	while ((ch = getopt(argc, argv, "dDg:m:np:q:rs:t:w:v")) != -1)
    308  1.4  mycroft 		switch (ch) {
    309  1.1      cgd 		case 'd':
    310  1.1      cgd 			options |= SO_DEBUG;
    311  1.1      cgd 			break;
    312  1.4  mycroft 		case 'D':
    313  1.4  mycroft 			dump = 1;
    314  1.4  mycroft 			break;
    315  1.4  mycroft 		case 'g':
    316  1.5  mycroft 			if (lsrr >= MAX_LSRR)
    317  1.5  mycroft 				errx(1, "too many gateways; max %d", MAX_LSRR);
    318  1.4  mycroft 			gw = inet_addr(optarg);
    319  1.4  mycroft 			if (gw == -1) {
    320  1.4  mycroft 				hp = gethostbyname(optarg);
    321  1.5  mycroft 				if (hp == 0)
    322  1.5  mycroft 					errx(1, "unknown host %s", optarg);
    323  1.4  mycroft 				bcopy(hp->h_addr, &gw, 4);
    324  1.4  mycroft 			}
    325  1.4  mycroft 			gateway[lsrr++].s_addr = gw;
    326  1.4  mycroft 			if (lsrr == 1)
    327  1.4  mycroft 				lsrrlen = 4;
    328  1.4  mycroft 			lsrrlen += 4;
    329  1.4  mycroft 			break;
    330  1.1      cgd 		case 'm':
    331  1.1      cgd 			max_ttl = atoi(optarg);
    332  1.5  mycroft 			if (max_ttl < 1 || max_ttl > MAXTTL)
    333  1.5  mycroft 				errx(1, "max ttl must be 1 to %d.", MAXTTL);
    334  1.1      cgd 			break;
    335  1.1      cgd 		case 'n':
    336  1.1      cgd 			nflag++;
    337  1.1      cgd 			break;
    338  1.1      cgd 		case 'p':
    339  1.1      cgd 			port = atoi(optarg);
    340  1.5  mycroft 			if (port < 1)
    341  1.5  mycroft 				errx(1, "port must be >0.");
    342  1.1      cgd 			break;
    343  1.1      cgd 		case 'q':
    344  1.1      cgd 			nprobes = atoi(optarg);
    345  1.5  mycroft 			if (nprobes < 1)
    346  1.5  mycroft 				errx(1, "nprobes must be >0.");
    347  1.1      cgd 			break;
    348  1.1      cgd 		case 'r':
    349  1.1      cgd 			options |= SO_DONTROUTE;
    350  1.1      cgd 			break;
    351  1.1      cgd 		case 's':
    352  1.1      cgd 			/*
    353  1.1      cgd 			 * set the ip source address of the outbound
    354  1.1      cgd 			 * probe (e.g., on a multi-homed host).
    355  1.1      cgd 			 */
    356  1.1      cgd 			source = optarg;
    357  1.1      cgd 			break;
    358  1.1      cgd 		case 't':
    359  1.1      cgd 			tos = atoi(optarg);
    360  1.5  mycroft 			if (tos < 0 || tos > 255)
    361  1.5  mycroft 				errx(1, "tos must be 0 to 255.");
    362  1.1      cgd 			break;
    363  1.1      cgd 		case 'v':
    364  1.1      cgd 			verbose++;
    365  1.1      cgd 			break;
    366  1.1      cgd 		case 'w':
    367  1.1      cgd 			waittime = atoi(optarg);
    368  1.5  mycroft 			if (waittime <= 1)
    369  1.5  mycroft 				errx(1, "wait must be >1 sec.");
    370  1.1      cgd 			break;
    371  1.1      cgd 		default:
    372  1.1      cgd 			usage();
    373  1.1      cgd 		}
    374  1.1      cgd 	argc -= optind;
    375  1.1      cgd 	argv += optind;
    376  1.1      cgd 
    377  1.3  mycroft 	if (argc < 1)
    378  1.1      cgd 		usage();
    379  1.1      cgd 
    380  1.1      cgd 	setlinebuf (stdout);
    381  1.1      cgd 
    382  1.4  mycroft 	(void) bzero((char *)&to, sizeof(struct sockaddr));
    383  1.4  mycroft 	to.sin_family = AF_INET;
    384  1.4  mycroft 	to.sin_addr.s_addr = inet_addr(*argv);
    385  1.4  mycroft 	if (to.sin_addr.s_addr != -1)
    386  1.1      cgd 		hostname = *argv;
    387  1.1      cgd 	else {
    388  1.1      cgd 		hp = gethostbyname(*argv);
    389  1.5  mycroft 		if (hp == 0)
    390  1.5  mycroft 			errx(1, "unknown host %s", *argv);
    391  1.4  mycroft 		to.sin_family = hp->h_addrtype;
    392  1.4  mycroft 		bcopy(hp->h_addr, (caddr_t)&to.sin_addr, hp->h_length);
    393  1.4  mycroft 		hostname = hp->h_name;
    394  1.1      cgd 	}
    395  1.3  mycroft 	if (*++argv)
    396  1.1      cgd 		datalen = atoi(*argv);
    397  1.5  mycroft 	if (datalen < 0 || datalen > IP_MAXPACKET - HEADERSIZE)
    398  1.5  mycroft 		errx(1, "packet size must be 0 to %d.",
    399  1.4  mycroft 		    IP_MAXPACKET - HEADERSIZE);
    400  1.4  mycroft 	datalen += HEADERSIZE;
    401  1.4  mycroft 	outpacket = (u_char *)malloc(datalen);
    402  1.4  mycroft 	if (outpacket == 0) {
    403  1.1      cgd 		perror("traceroute: malloc");
    404  1.1      cgd 		exit(1);
    405  1.1      cgd 	}
    406  1.4  mycroft 
    407  1.4  mycroft 	(void) bzero(outpacket, datalen);
    408  1.4  mycroft 	ip = (struct ip *)outpacket;
    409  1.4  mycroft 	if (lsrr != 0) {
    410  1.4  mycroft 		u_char *p;
    411  1.4  mycroft 		p = (u_char *)(ip + 1);
    412  1.4  mycroft 		*p++ = IPOPT_NOP;
    413  1.4  mycroft 		*p++ = IPOPT_LSRR;
    414  1.4  mycroft 		*p++ = lsrrlen - 1;
    415  1.4  mycroft 		*p++ = IPOPT_MINOFF;
    416  1.4  mycroft 		gateway[lsrr] = to.sin_addr;
    417  1.4  mycroft 		for (i = 1; i <= lsrr; i++)
    418  1.4  mycroft 			*((struct in_addr *)p)++ = gateway[i];
    419  1.4  mycroft 		ip->ip_dst = gateway[0];
    420  1.4  mycroft 	} else
    421  1.4  mycroft 		ip->ip_dst = to.sin_addr;
    422  1.4  mycroft 	ip->ip_off = 0;
    423  1.4  mycroft 	ip->ip_hl = (sizeof(struct ip) + lsrrlen) >> 2;
    424  1.4  mycroft 	ip->ip_p = IPPROTO_UDP;
    425  1.4  mycroft 	ip->ip_v = IPVERSION;
    426  1.4  mycroft 	ip->ip_tos = tos;
    427  1.1      cgd 
    428  1.1      cgd 	ident = (getpid() & 0xffff) | 0x8000;
    429  1.1      cgd 
    430  1.1      cgd 	if ((pe = getprotobyname("icmp")) == NULL) {
    431  1.1      cgd 		Fprintf(stderr, "icmp: unknown protocol\n");
    432  1.1      cgd 		exit(10);
    433  1.1      cgd 	}
    434  1.1      cgd 	if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
    435  1.1      cgd 		perror("traceroute: icmp socket");
    436  1.1      cgd 		exit(5);
    437  1.1      cgd 	}
    438  1.1      cgd 	if (options & SO_DEBUG)
    439  1.1      cgd 		(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
    440  1.1      cgd 				  (char *)&on, sizeof(on));
    441  1.1      cgd 	if (options & SO_DONTROUTE)
    442  1.1      cgd 		(void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
    443  1.1      cgd 				  (char *)&on, sizeof(on));
    444  1.1      cgd 
    445  1.1      cgd 	if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    446  1.1      cgd 		perror("traceroute: raw socket");
    447  1.1      cgd 		exit(5);
    448  1.1      cgd 	}
    449  1.4  mycroft 
    450  1.1      cgd #ifdef SO_SNDBUF
    451  1.1      cgd 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
    452  1.1      cgd 		       sizeof(datalen)) < 0) {
    453  1.1      cgd 		perror("traceroute: SO_SNDBUF");
    454  1.1      cgd 		exit(6);
    455  1.1      cgd 	}
    456  1.1      cgd #endif SO_SNDBUF
    457  1.1      cgd #ifdef IP_HDRINCL
    458  1.1      cgd 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    459  1.1      cgd 		       sizeof(on)) < 0) {
    460  1.1      cgd 		perror("traceroute: IP_HDRINCL");
    461  1.1      cgd 		exit(6);
    462  1.1      cgd 	}
    463  1.1      cgd #endif IP_HDRINCL
    464  1.1      cgd 	if (options & SO_DEBUG)
    465  1.1      cgd 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
    466  1.1      cgd 				  (char *)&on, sizeof(on));
    467  1.1      cgd 	if (options & SO_DONTROUTE)
    468  1.1      cgd 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
    469  1.1      cgd 				  (char *)&on, sizeof(on));
    470  1.1      cgd 
    471  1.1      cgd 	if (source) {
    472  1.1      cgd 		(void) bzero((char *)&from, sizeof(struct sockaddr));
    473  1.1      cgd 		from.sin_family = AF_INET;
    474  1.1      cgd 		from.sin_addr.s_addr = inet_addr(source);
    475  1.1      cgd 		if (from.sin_addr.s_addr == -1) {
    476  1.1      cgd 			Printf("traceroute: unknown host %s\n", source);
    477  1.1      cgd 			exit(1);
    478  1.1      cgd 		}
    479  1.4  mycroft 		ip->ip_src = from.sin_addr;
    480  1.1      cgd #ifndef IP_HDRINCL
    481  1.1      cgd 		if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
    482  1.1      cgd 			perror ("traceroute: bind:");
    483  1.1      cgd 			exit (1);
    484  1.1      cgd 		}
    485  1.1      cgd #endif IP_HDRINCL
    486  1.1      cgd 	}
    487  1.1      cgd 
    488  1.1      cgd 	Fprintf(stderr, "traceroute to %s (%s)", hostname,
    489  1.4  mycroft 		inet_ntoa(to.sin_addr));
    490  1.1      cgd 	if (source)
    491  1.1      cgd 		Fprintf(stderr, " from %s", source);
    492  1.1      cgd 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
    493  1.1      cgd 	(void) fflush(stderr);
    494  1.1      cgd 
    495  1.1      cgd 	for (ttl = 1; ttl <= max_ttl; ++ttl) {
    496  1.1      cgd 		u_long lastaddr = 0;
    497  1.1      cgd 		int got_there = 0;
    498  1.1      cgd 		int unreachable = 0;
    499  1.1      cgd 
    500  1.1      cgd 		Printf("%2d ", ttl);
    501  1.1      cgd 		for (probe = 0; probe < nprobes; ++probe) {
    502  1.1      cgd 			int cc;
    503  1.3  mycroft 			struct timeval t1, t2;
    504  1.3  mycroft 			struct timezone tz;
    505  1.1      cgd 
    506  1.3  mycroft 			(void) gettimeofday(&t1, &tz);
    507  1.4  mycroft 			send_probe(++seq, ttl, &to);
    508  1.1      cgd 			while (cc = wait_for_reply(s, &from)) {
    509  1.3  mycroft 				(void) gettimeofday(&t2, &tz);
    510  1.1      cgd 				if ((i = packet_ok(packet, cc, &from, seq))) {
    511  1.1      cgd 					if (from.sin_addr.s_addr != lastaddr) {
    512  1.1      cgd 						print(packet, cc, &from);
    513  1.1      cgd 						lastaddr = from.sin_addr.s_addr;
    514  1.1      cgd 					}
    515  1.3  mycroft 					Printf("  %g ms", deltaT(&t1, &t2));
    516  1.1      cgd 					switch(i - 1) {
    517  1.1      cgd 					case ICMP_UNREACH_PORT:
    518  1.1      cgd #ifndef ARCHAIC
    519  1.1      cgd 						ip = (struct ip *)packet;
    520  1.1      cgd 						if (ip->ip_ttl <= 1)
    521  1.1      cgd 							Printf(" !");
    522  1.1      cgd #endif ARCHAIC
    523  1.1      cgd 						++got_there;
    524  1.1      cgd 						break;
    525  1.1      cgd 					case ICMP_UNREACH_NET:
    526  1.1      cgd 						++unreachable;
    527  1.1      cgd 						Printf(" !N");
    528  1.1      cgd 						break;
    529  1.1      cgd 					case ICMP_UNREACH_HOST:
    530  1.1      cgd 						++unreachable;
    531  1.1      cgd 						Printf(" !H");
    532  1.1      cgd 						break;
    533  1.1      cgd 					case ICMP_UNREACH_PROTOCOL:
    534  1.1      cgd 						++got_there;
    535  1.1      cgd 						Printf(" !P");
    536  1.1      cgd 						break;
    537  1.1      cgd 					case ICMP_UNREACH_NEEDFRAG:
    538  1.1      cgd 						++unreachable;
    539  1.1      cgd 						Printf(" !F");
    540  1.1      cgd 						break;
    541  1.1      cgd 					case ICMP_UNREACH_SRCFAIL:
    542  1.1      cgd 						++unreachable;
    543  1.1      cgd 						Printf(" !S");
    544  1.1      cgd 						break;
    545  1.1      cgd 					}
    546  1.1      cgd 					break;
    547  1.1      cgd 				}
    548  1.1      cgd 			}
    549  1.1      cgd 			if (cc == 0)
    550  1.1      cgd 				Printf(" *");
    551  1.1      cgd 			(void) fflush(stdout);
    552  1.1      cgd 		}
    553  1.1      cgd 		putchar('\n');
    554  1.4  mycroft 		if (got_there || unreachable >= nprobes)
    555  1.1      cgd 			exit(0);
    556  1.1      cgd 	}
    557  1.1      cgd }
    558  1.1      cgd 
    559  1.3  mycroft int
    560  1.1      cgd wait_for_reply(sock, from)
    561  1.1      cgd 	int sock;
    562  1.1      cgd 	struct sockaddr_in *from;
    563  1.1      cgd {
    564  1.1      cgd 	fd_set fds;
    565  1.1      cgd 	struct timeval wait;
    566  1.1      cgd 	int cc = 0;
    567  1.1      cgd 	int fromlen = sizeof (*from);
    568  1.1      cgd 
    569  1.1      cgd 	FD_ZERO(&fds);
    570  1.1      cgd 	FD_SET(sock, &fds);
    571  1.1      cgd 	wait.tv_sec = waittime; wait.tv_usec = 0;
    572  1.1      cgd 
    573  1.1      cgd 	if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
    574  1.1      cgd 		cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
    575  1.1      cgd 			    (struct sockaddr *)from, &fromlen);
    576  1.1      cgd 
    577  1.1      cgd 	return(cc);
    578  1.1      cgd }
    579  1.1      cgd 
    580  1.4  mycroft void
    581  1.4  mycroft dump_packet()
    582  1.4  mycroft {
    583  1.4  mycroft 	u_char *p;
    584  1.4  mycroft 	int i;
    585  1.4  mycroft 
    586  1.4  mycroft 	Fprintf(stderr, "packet data:");
    587  1.4  mycroft 	for (p = outpacket, i = 0; i < datalen; i++) {
    588  1.4  mycroft 		if ((i % 24) == 0)
    589  1.4  mycroft 			Fprintf(stderr, "\n ");
    590  1.4  mycroft 		Fprintf(stderr, " %02x", *p++);
    591  1.4  mycroft 	}
    592  1.4  mycroft 	Fprintf(stderr, "\n");
    593  1.4  mycroft }
    594  1.1      cgd 
    595  1.3  mycroft void
    596  1.4  mycroft send_probe(seq, ttl, to)
    597  1.3  mycroft 	int seq, ttl;
    598  1.4  mycroft 	struct sockaddr_in *to;
    599  1.1      cgd {
    600  1.4  mycroft 	struct ip *ip = (struct ip *)outpacket;
    601  1.4  mycroft 	u_char *p = (u_char *)(ip + 1);
    602  1.4  mycroft 	struct udphdr *up = (struct udphdr *)(p + lsrrlen);
    603  1.4  mycroft 	struct packetdata *op = (struct packetdata *)(up + 1);
    604  1.1      cgd 	int i;
    605  1.1      cgd 
    606  1.1      cgd 	ip->ip_len = datalen;
    607  1.1      cgd 	ip->ip_ttl = ttl;
    608  1.3  mycroft 	ip->ip_id = htons(ident+seq);
    609  1.1      cgd 
    610  1.1      cgd 	up->uh_sport = htons(ident);
    611  1.1      cgd 	up->uh_dport = htons(port+seq);
    612  1.4  mycroft 	up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip) - lsrrlen));
    613  1.1      cgd 	up->uh_sum = 0;
    614  1.1      cgd 
    615  1.1      cgd 	op->seq = seq;
    616  1.1      cgd 	op->ttl = ttl;
    617  1.1      cgd 	(void) gettimeofday(&op->tv, &tz);
    618  1.1      cgd 
    619  1.4  mycroft 	if (dump)
    620  1.4  mycroft 		dump_packet();
    621  1.4  mycroft 
    622  1.4  mycroft 	i = sendto(sndsock, outpacket, datalen, 0, (struct sockaddr *)to,
    623  1.4  mycroft 		   sizeof(struct sockaddr_in));
    624  1.1      cgd 	if (i < 0 || i != datalen)  {
    625  1.1      cgd 		if (i<0)
    626  1.1      cgd 			perror("sendto");
    627  1.1      cgd 		Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
    628  1.1      cgd 			datalen, i);
    629  1.1      cgd 		(void) fflush(stdout);
    630  1.1      cgd 	}
    631  1.1      cgd }
    632  1.1      cgd 
    633  1.1      cgd 
    634  1.3  mycroft double
    635  1.3  mycroft deltaT(t1p, t2p)
    636  1.3  mycroft 	struct timeval *t1p, *t2p;
    637  1.3  mycroft {
    638  1.3  mycroft 	register double dt;
    639  1.3  mycroft 
    640  1.3  mycroft 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
    641  1.3  mycroft 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
    642  1.3  mycroft 	return (dt);
    643  1.1      cgd }
    644  1.1      cgd 
    645  1.1      cgd 
    646  1.1      cgd /*
    647  1.1      cgd  * Convert an ICMP "type" field to a printable string.
    648  1.1      cgd  */
    649  1.1      cgd char *
    650  1.1      cgd pr_type(t)
    651  1.1      cgd 	u_char t;
    652  1.1      cgd {
    653  1.1      cgd 	static char *ttab[] = {
    654  1.1      cgd 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
    655  1.1      cgd 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
    656  1.1      cgd 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
    657  1.1      cgd 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
    658  1.1      cgd 	"Info Reply"
    659  1.1      cgd 	};
    660  1.1      cgd 
    661  1.1      cgd 	if(t > 16)
    662  1.1      cgd 		return("OUT-OF-RANGE");
    663  1.1      cgd 
    664  1.1      cgd 	return(ttab[t]);
    665  1.1      cgd }
    666  1.1      cgd 
    667  1.1      cgd 
    668  1.3  mycroft int
    669  1.1      cgd packet_ok(buf, cc, from, seq)
    670  1.1      cgd 	u_char *buf;
    671  1.1      cgd 	int cc;
    672  1.1      cgd 	struct sockaddr_in *from;
    673  1.1      cgd 	int seq;
    674  1.1      cgd {
    675  1.1      cgd 	register struct icmp *icp;
    676  1.1      cgd 	u_char type, code;
    677  1.1      cgd 	int hlen;
    678  1.1      cgd #ifndef ARCHAIC
    679  1.1      cgd 	struct ip *ip;
    680  1.1      cgd 
    681  1.1      cgd 	ip = (struct ip *) buf;
    682  1.1      cgd 	hlen = ip->ip_hl << 2;
    683  1.1      cgd 	if (cc < hlen + ICMP_MINLEN) {
    684  1.1      cgd 		if (verbose)
    685  1.1      cgd 			Printf("packet too short (%d bytes) from %s\n", cc,
    686  1.1      cgd 				inet_ntoa(from->sin_addr));
    687  1.1      cgd 		return (0);
    688  1.1      cgd 	}
    689  1.1      cgd 	cc -= hlen;
    690  1.1      cgd 	icp = (struct icmp *)(buf + hlen);
    691  1.1      cgd #else
    692  1.1      cgd 	icp = (struct icmp *)buf;
    693  1.1      cgd #endif ARCHAIC
    694  1.1      cgd 	type = icp->icmp_type; code = icp->icmp_code;
    695  1.1      cgd 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
    696  1.1      cgd 	    type == ICMP_UNREACH) {
    697  1.1      cgd 		struct ip *hip;
    698  1.1      cgd 		struct udphdr *up;
    699  1.1      cgd 
    700  1.1      cgd 		hip = &icp->icmp_ip;
    701  1.1      cgd 		hlen = hip->ip_hl << 2;
    702  1.1      cgd 		up = (struct udphdr *)((u_char *)hip + hlen);
    703  1.1      cgd 		if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
    704  1.1      cgd 		    up->uh_sport == htons(ident) &&
    705  1.1      cgd 		    up->uh_dport == htons(port+seq))
    706  1.1      cgd 			return (type == ICMP_TIMXCEED? -1 : code+1);
    707  1.1      cgd 	}
    708  1.1      cgd #ifndef ARCHAIC
    709  1.1      cgd 	if (verbose) {
    710  1.1      cgd 		int i;
    711  1.1      cgd 		u_long *lp = (u_long *)&icp->icmp_ip;
    712  1.1      cgd 
    713  1.1      cgd 		Printf("\n%d bytes from %s to %s", cc,
    714  1.1      cgd 			inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
    715  1.1      cgd 		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
    716  1.1      cgd 		       icp->icmp_code);
    717  1.1      cgd 		for (i = 4; i < cc ; i += sizeof(long))
    718  1.1      cgd 			Printf("%2d: x%8.8lx\n", i, *lp++);
    719  1.1      cgd 	}
    720  1.1      cgd #endif ARCHAIC
    721  1.1      cgd 	return(0);
    722  1.1      cgd }
    723  1.1      cgd 
    724  1.1      cgd 
    725  1.3  mycroft void
    726  1.1      cgd print(buf, cc, from)
    727  1.1      cgd 	u_char *buf;
    728  1.1      cgd 	int cc;
    729  1.1      cgd 	struct sockaddr_in *from;
    730  1.1      cgd {
    731  1.1      cgd 	struct ip *ip;
    732  1.1      cgd 	int hlen;
    733  1.1      cgd 
    734  1.1      cgd 	ip = (struct ip *) buf;
    735  1.1      cgd 	hlen = ip->ip_hl << 2;
    736  1.1      cgd 	cc -= hlen;
    737  1.1      cgd 
    738  1.1      cgd 	if (nflag)
    739  1.1      cgd 		Printf(" %s", inet_ntoa(from->sin_addr));
    740  1.1      cgd 	else
    741  1.1      cgd 		Printf(" %s (%s)", inetname(from->sin_addr),
    742  1.1      cgd 		       inet_ntoa(from->sin_addr));
    743  1.1      cgd 
    744  1.1      cgd 	if (verbose)
    745  1.1      cgd 		Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
    746  1.1      cgd }
    747  1.1      cgd 
    748  1.1      cgd 
    749  1.1      cgd #ifdef notyet
    750  1.1      cgd /*
    751  1.1      cgd  * Checksum routine for Internet Protocol family headers (C Version)
    752  1.1      cgd  */
    753  1.3  mycroft u_short
    754  1.1      cgd in_cksum(addr, len)
    755  1.3  mycroft 	u_short *addr;
    756  1.3  mycroft 	int len;
    757  1.1      cgd {
    758  1.1      cgd 	register int nleft = len;
    759  1.1      cgd 	register u_short *w = addr;
    760  1.1      cgd 	register u_short answer;
    761  1.1      cgd 	register int sum = 0;
    762  1.1      cgd 
    763  1.1      cgd 	/*
    764  1.1      cgd 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
    765  1.1      cgd 	 *  we add sequential 16 bit words to it, and at the end, fold
    766  1.1      cgd 	 *  back all the carry bits from the top 16 bits into the lower
    767  1.1      cgd 	 *  16 bits.
    768  1.1      cgd 	 */
    769  1.1      cgd 	while (nleft > 1)  {
    770  1.1      cgd 		sum += *w++;
    771  1.1      cgd 		nleft -= 2;
    772  1.1      cgd 	}
    773  1.1      cgd 
    774  1.1      cgd 	/* mop up an odd byte, if necessary */
    775  1.1      cgd 	if (nleft == 1)
    776  1.1      cgd 		sum += *(u_char *)w;
    777  1.1      cgd 
    778  1.1      cgd 	/*
    779  1.1      cgd 	 * add back carry outs from top 16 bits to low 16 bits
    780  1.1      cgd 	 */
    781  1.1      cgd 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
    782  1.1      cgd 	sum += (sum >> 16);			/* add carry */
    783  1.1      cgd 	answer = ~sum;				/* truncate to 16 bits */
    784  1.1      cgd 	return (answer);
    785  1.1      cgd }
    786  1.1      cgd #endif notyet
    787  1.1      cgd 
    788  1.1      cgd /*
    789  1.1      cgd  * Subtract 2 timeval structs:  out = out - in.
    790  1.1      cgd  * Out is assumed to be >= in.
    791  1.1      cgd  */
    792  1.3  mycroft void
    793  1.1      cgd tvsub(out, in)
    794  1.3  mycroft 	register struct timeval *out, *in;
    795  1.1      cgd {
    796  1.1      cgd 	if ((out->tv_usec -= in->tv_usec) < 0)   {
    797  1.1      cgd 		out->tv_sec--;
    798  1.1      cgd 		out->tv_usec += 1000000;
    799  1.1      cgd 	}
    800  1.1      cgd 	out->tv_sec -= in->tv_sec;
    801  1.1      cgd }
    802  1.1      cgd 
    803  1.1      cgd 
    804  1.1      cgd /*
    805  1.1      cgd  * Construct an Internet address representation.
    806  1.3  mycroft  * If the nflag has been supplied, give
    807  1.1      cgd  * numeric value, otherwise try for symbolic name.
    808  1.1      cgd  */
    809  1.1      cgd char *
    810  1.1      cgd inetname(in)
    811  1.1      cgd 	struct in_addr in;
    812  1.1      cgd {
    813  1.1      cgd 	register char *cp;
    814  1.1      cgd 	static char line[50];
    815  1.1      cgd 	struct hostent *hp;
    816  1.1      cgd 	static char domain[MAXHOSTNAMELEN + 1];
    817  1.1      cgd 	static int first = 1;
    818  1.1      cgd 
    819  1.1      cgd 	if (first && !nflag) {
    820  1.1      cgd 		first = 0;
    821  1.1      cgd 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
    822  1.1      cgd 		    (cp = index(domain, '.')))
    823  1.1      cgd 			(void) strcpy(domain, cp + 1);
    824  1.1      cgd 		else
    825  1.1      cgd 			domain[0] = 0;
    826  1.1      cgd 	}
    827  1.1      cgd 	cp = 0;
    828  1.1      cgd 	if (!nflag && in.s_addr != INADDR_ANY) {
    829  1.1      cgd 		hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
    830  1.1      cgd 		if (hp) {
    831  1.1      cgd 			if ((cp = index(hp->h_name, '.')) &&
    832  1.1      cgd 			    !strcmp(cp + 1, domain))
    833  1.1      cgd 				*cp = 0;
    834  1.1      cgd 			cp = hp->h_name;
    835  1.1      cgd 		}
    836  1.1      cgd 	}
    837  1.1      cgd 	if (cp)
    838  1.1      cgd 		(void) strcpy(line, cp);
    839  1.1      cgd 	else {
    840  1.1      cgd 		in.s_addr = ntohl(in.s_addr);
    841  1.1      cgd #define C(x)	((x) & 0xff)
    842  1.1      cgd 		Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24),
    843  1.1      cgd 			C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
    844  1.1      cgd 	}
    845  1.1      cgd 	return (line);
    846  1.1      cgd }
    847  1.1      cgd 
    848  1.3  mycroft void
    849  1.1      cgd usage()
    850  1.1      cgd {
    851  1.3  mycroft 	(void)fprintf(stderr,
    852  1.4  mycroft "usage: traceroute [-dDnrv] [-g gateway_addr] ... [-m max_ttl] [-p port#]\n\t\
    853  1.4  mycroft [-q nqueries] [-s src_addr] [-t tos] [-w wait] host [data size]\n");
    854  1.5  mycroft 	exit(1);
    855  1.5  mycroft }
    856