Home | History | Annotate | Line # | Download | only in traceroute
traceroute.c revision 1.3
      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.3  mycroft static char *rcsid = "$Id: traceroute.c,v 1.3 1994/05/16 19:16:01 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.1      cgd #include <netinet/udp.h>
    230  1.3  mycroft 
    231  1.3  mycroft #include <arpa/inet.h>
    232  1.3  mycroft 
    233  1.1      cgd #include <netdb.h>
    234  1.1      cgd #include <stdio.h>
    235  1.1      cgd #include <errno.h>
    236  1.3  mycroft #include <stdlib.h>
    237  1.1      cgd #include <string.h>
    238  1.3  mycroft #include <unistd.h>
    239  1.1      cgd 
    240  1.1      cgd #define	MAXPACKET	65535	/* max ip packet size */
    241  1.1      cgd #ifndef MAXHOSTNAMELEN
    242  1.1      cgd #define MAXHOSTNAMELEN	64
    243  1.1      cgd #endif
    244  1.1      cgd 
    245  1.1      cgd #ifndef FD_SET
    246  1.1      cgd #define NFDBITS         (8*sizeof(fd_set))
    247  1.1      cgd #define FD_SETSIZE      NFDBITS
    248  1.1      cgd #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
    249  1.1      cgd #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
    250  1.1      cgd #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
    251  1.1      cgd #define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
    252  1.1      cgd #endif
    253  1.1      cgd 
    254  1.1      cgd #define Fprintf (void)fprintf
    255  1.1      cgd #define Sprintf (void)sprintf
    256  1.1      cgd #define Printf (void)printf
    257  1.1      cgd 
    258  1.1      cgd /*
    259  1.1      cgd  * format of a (udp) probe packet.
    260  1.1      cgd  */
    261  1.1      cgd struct opacket {
    262  1.1      cgd 	struct ip ip;
    263  1.1      cgd 	struct udphdr udp;
    264  1.1      cgd 	u_char seq;		/* sequence number of this packet */
    265  1.1      cgd 	u_char ttl;		/* ttl packet left with */
    266  1.1      cgd 	struct timeval tv;	/* time packet left */
    267  1.1      cgd };
    268  1.1      cgd 
    269  1.1      cgd u_char	packet[512];		/* last inbound (icmp) packet */
    270  1.1      cgd struct opacket	*outpacket;	/* last output (udp) packet */
    271  1.3  mycroft 
    272  1.3  mycroft int wait_for_reply __P((int, struct sockaddr_in *));
    273  1.3  mycroft void send_probe __P((int, int));
    274  1.3  mycroft double deltaT __P((struct timeval *, struct timeval *));
    275  1.3  mycroft int packet_ok __P((u_char *, int, struct sockaddr_in *, int));
    276  1.3  mycroft void print __P((u_char *, int, struct sockaddr_in *));
    277  1.3  mycroft void tvsub __P((struct timeval *, struct timeval *));
    278  1.3  mycroft char *inetname __P((struct in_addr));
    279  1.3  mycroft void usage __P(());
    280  1.1      cgd 
    281  1.1      cgd int s;				/* receive (icmp) socket file descriptor */
    282  1.1      cgd int sndsock;			/* send (udp) socket file descriptor */
    283  1.1      cgd struct timezone tz;		/* leftover */
    284  1.1      cgd 
    285  1.1      cgd struct sockaddr whereto;	/* Who to try to reach */
    286  1.1      cgd int datalen;			/* How much data */
    287  1.1      cgd 
    288  1.1      cgd char *source = 0;
    289  1.1      cgd char *hostname;
    290  1.1      cgd 
    291  1.1      cgd int nprobes = 3;
    292  1.1      cgd int max_ttl = 30;
    293  1.1      cgd u_short ident;
    294  1.1      cgd u_short port = 32768+666;	/* start udp dest port # for probe packets */
    295  1.1      cgd int options;			/* socket options */
    296  1.1      cgd int verbose;
    297  1.1      cgd int waittime = 5;		/* time to wait for response (in seconds) */
    298  1.1      cgd int nflag;			/* print addresses numerically */
    299  1.1      cgd 
    300  1.3  mycroft int
    301  1.1      cgd main(argc, argv)
    302  1.3  mycroft 	int argc;
    303  1.1      cgd 	char *argv[];
    304  1.1      cgd {
    305  1.1      cgd 	extern char *optarg;
    306  1.1      cgd 	extern int optind;
    307  1.1      cgd 	struct hostent *hp;
    308  1.1      cgd 	struct protoent *pe;
    309  1.1      cgd 	struct sockaddr_in from, *to;
    310  1.1      cgd 	int ch, i, on, probe, seq, tos, ttl;
    311  1.1      cgd 
    312  1.1      cgd 	on = 1;
    313  1.1      cgd 	seq = tos = 0;
    314  1.1      cgd 	to = (struct sockaddr_in *)&whereto;
    315  1.1      cgd 	while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
    316  1.1      cgd 		switch(ch) {
    317  1.1      cgd 		case 'd':
    318  1.1      cgd 			options |= SO_DEBUG;
    319  1.1      cgd 			break;
    320  1.1      cgd 		case 'm':
    321  1.1      cgd 			max_ttl = atoi(optarg);
    322  1.1      cgd 			if (max_ttl <= 1) {
    323  1.1      cgd 				Fprintf(stderr,
    324  1.1      cgd 				    "traceroute: max ttl must be >1.\n");
    325  1.1      cgd 				exit(1);
    326  1.1      cgd 			}
    327  1.1      cgd 			break;
    328  1.1      cgd 		case 'n':
    329  1.1      cgd 			nflag++;
    330  1.1      cgd 			break;
    331  1.1      cgd 		case 'p':
    332  1.1      cgd 			port = atoi(optarg);
    333  1.1      cgd 			if (port < 1) {
    334  1.1      cgd 				Fprintf(stderr,
    335  1.1      cgd 				    "traceroute: port must be >0.\n");
    336  1.1      cgd 				exit(1);
    337  1.1      cgd 			}
    338  1.1      cgd 			break;
    339  1.1      cgd 		case 'q':
    340  1.1      cgd 			nprobes = atoi(optarg);
    341  1.1      cgd 			if (nprobes < 1) {
    342  1.1      cgd 				Fprintf(stderr,
    343  1.1      cgd 				    "traceroute: nprobes must be >0.\n");
    344  1.1      cgd 				exit(1);
    345  1.1      cgd 			}
    346  1.1      cgd 			break;
    347  1.1      cgd 		case 'r':
    348  1.1      cgd 			options |= SO_DONTROUTE;
    349  1.1      cgd 			break;
    350  1.1      cgd 		case 's':
    351  1.1      cgd 			/*
    352  1.1      cgd 			 * set the ip source address of the outbound
    353  1.1      cgd 			 * probe (e.g., on a multi-homed host).
    354  1.1      cgd 			 */
    355  1.1      cgd 			source = optarg;
    356  1.1      cgd 			break;
    357  1.1      cgd 		case 't':
    358  1.1      cgd 			tos = atoi(optarg);
    359  1.1      cgd 			if (tos < 0 || tos > 255) {
    360  1.1      cgd 				Fprintf(stderr,
    361  1.1      cgd 				    "traceroute: tos must be 0 to 255.\n");
    362  1.1      cgd 				exit(1);
    363  1.1      cgd 			}
    364  1.1      cgd 			break;
    365  1.1      cgd 		case 'v':
    366  1.1      cgd 			verbose++;
    367  1.1      cgd 			break;
    368  1.1      cgd 		case 'w':
    369  1.1      cgd 			waittime = atoi(optarg);
    370  1.1      cgd 			if (waittime <= 1) {
    371  1.1      cgd 				Fprintf(stderr,
    372  1.1      cgd 				    "traceroute: wait must be >1 sec.\n");
    373  1.1      cgd 				exit(1);
    374  1.1      cgd 			}
    375  1.1      cgd 			break;
    376  1.1      cgd 		default:
    377  1.1      cgd 			usage();
    378  1.1      cgd 		}
    379  1.1      cgd 	argc -= optind;
    380  1.1      cgd 	argv += optind;
    381  1.1      cgd 
    382  1.3  mycroft 	if (argc < 1)
    383  1.1      cgd 		usage();
    384  1.1      cgd 
    385  1.1      cgd 	setlinebuf (stdout);
    386  1.1      cgd 
    387  1.1      cgd 	(void) bzero((char *)&whereto, sizeof(struct sockaddr));
    388  1.1      cgd 	to->sin_family = AF_INET;
    389  1.1      cgd 	to->sin_addr.s_addr = inet_addr(*argv);
    390  1.3  mycroft 	if (to->sin_addr.s_addr != -1)
    391  1.1      cgd 		hostname = *argv;
    392  1.1      cgd 	else {
    393  1.1      cgd 		hp = gethostbyname(*argv);
    394  1.1      cgd 		if (hp) {
    395  1.1      cgd 			to->sin_family = hp->h_addrtype;
    396  1.1      cgd 			bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
    397  1.1      cgd 			hostname = hp->h_name;
    398  1.1      cgd 		} else {
    399  1.1      cgd 			(void)fprintf(stderr,
    400  1.1      cgd 			    "traceroute: unknown host %s\n", *argv);
    401  1.1      cgd 			exit(1);
    402  1.1      cgd 		}
    403  1.1      cgd 	}
    404  1.3  mycroft 	if (*++argv)
    405  1.1      cgd 		datalen = atoi(*argv);
    406  1.1      cgd 	if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
    407  1.1      cgd 		Fprintf(stderr,
    408  1.1      cgd 		    "traceroute: packet size must be 0 <= s < %ld.\n",
    409  1.1      cgd 		    MAXPACKET - sizeof(struct opacket));
    410  1.1      cgd 		exit(1);
    411  1.1      cgd 	}
    412  1.1      cgd 	datalen += sizeof(struct opacket);
    413  1.1      cgd 	outpacket = (struct opacket *)malloc((unsigned)datalen);
    414  1.1      cgd 	if (! outpacket) {
    415  1.1      cgd 		perror("traceroute: malloc");
    416  1.1      cgd 		exit(1);
    417  1.1      cgd 	}
    418  1.1      cgd 	(void) bzero((char *)outpacket, datalen);
    419  1.1      cgd 	outpacket->ip.ip_dst = to->sin_addr;
    420  1.1      cgd 	outpacket->ip.ip_tos = tos;
    421  1.3  mycroft 	outpacket->ip.ip_v = IPVERSION;
    422  1.3  mycroft 	outpacket->ip.ip_id = 0;
    423  1.1      cgd 
    424  1.1      cgd 	ident = (getpid() & 0xffff) | 0x8000;
    425  1.1      cgd 
    426  1.1      cgd 	if ((pe = getprotobyname("icmp")) == NULL) {
    427  1.1      cgd 		Fprintf(stderr, "icmp: unknown protocol\n");
    428  1.1      cgd 		exit(10);
    429  1.1      cgd 	}
    430  1.1      cgd 	if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
    431  1.1      cgd 		perror("traceroute: icmp socket");
    432  1.1      cgd 		exit(5);
    433  1.1      cgd 	}
    434  1.1      cgd 	if (options & SO_DEBUG)
    435  1.1      cgd 		(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
    436  1.1      cgd 				  (char *)&on, sizeof(on));
    437  1.1      cgd 	if (options & SO_DONTROUTE)
    438  1.1      cgd 		(void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
    439  1.1      cgd 				  (char *)&on, sizeof(on));
    440  1.1      cgd 
    441  1.1      cgd 	if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    442  1.1      cgd 		perror("traceroute: raw socket");
    443  1.1      cgd 		exit(5);
    444  1.1      cgd 	}
    445  1.1      cgd #ifdef SO_SNDBUF
    446  1.1      cgd 	if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
    447  1.1      cgd 		       sizeof(datalen)) < 0) {
    448  1.1      cgd 		perror("traceroute: SO_SNDBUF");
    449  1.1      cgd 		exit(6);
    450  1.1      cgd 	}
    451  1.1      cgd #endif SO_SNDBUF
    452  1.1      cgd #ifdef IP_HDRINCL
    453  1.1      cgd 	if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
    454  1.1      cgd 		       sizeof(on)) < 0) {
    455  1.1      cgd 		perror("traceroute: IP_HDRINCL");
    456  1.1      cgd 		exit(6);
    457  1.1      cgd 	}
    458  1.1      cgd #endif IP_HDRINCL
    459  1.1      cgd 	if (options & SO_DEBUG)
    460  1.1      cgd 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
    461  1.1      cgd 				  (char *)&on, sizeof(on));
    462  1.1      cgd 	if (options & SO_DONTROUTE)
    463  1.1      cgd 		(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
    464  1.1      cgd 				  (char *)&on, sizeof(on));
    465  1.1      cgd 
    466  1.1      cgd 	if (source) {
    467  1.1      cgd 		(void) bzero((char *)&from, sizeof(struct sockaddr));
    468  1.1      cgd 		from.sin_family = AF_INET;
    469  1.1      cgd 		from.sin_addr.s_addr = inet_addr(source);
    470  1.1      cgd 		if (from.sin_addr.s_addr == -1) {
    471  1.1      cgd 			Printf("traceroute: unknown host %s\n", source);
    472  1.1      cgd 			exit(1);
    473  1.1      cgd 		}
    474  1.1      cgd 		outpacket->ip.ip_src = from.sin_addr;
    475  1.1      cgd #ifndef IP_HDRINCL
    476  1.1      cgd 		if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
    477  1.1      cgd 			perror ("traceroute: bind:");
    478  1.1      cgd 			exit (1);
    479  1.1      cgd 		}
    480  1.1      cgd #endif IP_HDRINCL
    481  1.1      cgd 	}
    482  1.1      cgd 
    483  1.1      cgd 	Fprintf(stderr, "traceroute to %s (%s)", hostname,
    484  1.1      cgd 		inet_ntoa(to->sin_addr));
    485  1.1      cgd 	if (source)
    486  1.1      cgd 		Fprintf(stderr, " from %s", source);
    487  1.1      cgd 	Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
    488  1.1      cgd 	(void) fflush(stderr);
    489  1.1      cgd 
    490  1.1      cgd 	for (ttl = 1; ttl <= max_ttl; ++ttl) {
    491  1.1      cgd 		u_long lastaddr = 0;
    492  1.1      cgd 		int got_there = 0;
    493  1.1      cgd 		int unreachable = 0;
    494  1.1      cgd 
    495  1.1      cgd 		Printf("%2d ", ttl);
    496  1.1      cgd 		for (probe = 0; probe < nprobes; ++probe) {
    497  1.1      cgd 			int cc;
    498  1.3  mycroft 			struct timeval t1, t2;
    499  1.3  mycroft 			struct timezone tz;
    500  1.1      cgd 			struct ip *ip;
    501  1.1      cgd 
    502  1.3  mycroft 			(void) gettimeofday(&t1, &tz);
    503  1.1      cgd 			send_probe(++seq, ttl);
    504  1.1      cgd 			while (cc = wait_for_reply(s, &from)) {
    505  1.3  mycroft 				(void) gettimeofday(&t2, &tz);
    506  1.1      cgd 				if ((i = packet_ok(packet, cc, &from, seq))) {
    507  1.1      cgd 					if (from.sin_addr.s_addr != lastaddr) {
    508  1.1      cgd 						print(packet, cc, &from);
    509  1.1      cgd 						lastaddr = from.sin_addr.s_addr;
    510  1.1      cgd 					}
    511  1.3  mycroft 					Printf("  %g ms", deltaT(&t1, &t2));
    512  1.1      cgd 					switch(i - 1) {
    513  1.1      cgd 					case ICMP_UNREACH_PORT:
    514  1.1      cgd #ifndef ARCHAIC
    515  1.1      cgd 						ip = (struct ip *)packet;
    516  1.1      cgd 						if (ip->ip_ttl <= 1)
    517  1.1      cgd 							Printf(" !");
    518  1.1      cgd #endif ARCHAIC
    519  1.1      cgd 						++got_there;
    520  1.1      cgd 						break;
    521  1.1      cgd 					case ICMP_UNREACH_NET:
    522  1.1      cgd 						++unreachable;
    523  1.1      cgd 						Printf(" !N");
    524  1.1      cgd 						break;
    525  1.1      cgd 					case ICMP_UNREACH_HOST:
    526  1.1      cgd 						++unreachable;
    527  1.1      cgd 						Printf(" !H");
    528  1.1      cgd 						break;
    529  1.1      cgd 					case ICMP_UNREACH_PROTOCOL:
    530  1.1      cgd 						++got_there;
    531  1.1      cgd 						Printf(" !P");
    532  1.1      cgd 						break;
    533  1.1      cgd 					case ICMP_UNREACH_NEEDFRAG:
    534  1.1      cgd 						++unreachable;
    535  1.1      cgd 						Printf(" !F");
    536  1.1      cgd 						break;
    537  1.1      cgd 					case ICMP_UNREACH_SRCFAIL:
    538  1.1      cgd 						++unreachable;
    539  1.1      cgd 						Printf(" !S");
    540  1.1      cgd 						break;
    541  1.1      cgd 					}
    542  1.1      cgd 					break;
    543  1.1      cgd 				}
    544  1.1      cgd 			}
    545  1.1      cgd 			if (cc == 0)
    546  1.1      cgd 				Printf(" *");
    547  1.1      cgd 			(void) fflush(stdout);
    548  1.1      cgd 		}
    549  1.1      cgd 		putchar('\n');
    550  1.1      cgd 		if (got_there || unreachable >= nprobes-1)
    551  1.1      cgd 			exit(0);
    552  1.1      cgd 	}
    553  1.1      cgd }
    554  1.1      cgd 
    555  1.3  mycroft int
    556  1.1      cgd wait_for_reply(sock, from)
    557  1.1      cgd 	int sock;
    558  1.1      cgd 	struct sockaddr_in *from;
    559  1.1      cgd {
    560  1.1      cgd 	fd_set fds;
    561  1.1      cgd 	struct timeval wait;
    562  1.1      cgd 	int cc = 0;
    563  1.1      cgd 	int fromlen = sizeof (*from);
    564  1.1      cgd 
    565  1.1      cgd 	FD_ZERO(&fds);
    566  1.1      cgd 	FD_SET(sock, &fds);
    567  1.1      cgd 	wait.tv_sec = waittime; wait.tv_usec = 0;
    568  1.1      cgd 
    569  1.1      cgd 	if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
    570  1.1      cgd 		cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
    571  1.1      cgd 			    (struct sockaddr *)from, &fromlen);
    572  1.1      cgd 
    573  1.1      cgd 	return(cc);
    574  1.1      cgd }
    575  1.1      cgd 
    576  1.1      cgd 
    577  1.3  mycroft void
    578  1.1      cgd send_probe(seq, ttl)
    579  1.3  mycroft 	int seq, ttl;
    580  1.1      cgd {
    581  1.1      cgd 	struct opacket *op = outpacket;
    582  1.1      cgd 	struct ip *ip = &op->ip;
    583  1.1      cgd 	struct udphdr *up = &op->udp;
    584  1.1      cgd 	int i;
    585  1.1      cgd 
    586  1.1      cgd 	ip->ip_off = 0;
    587  1.3  mycroft 	ip->ip_hl = sizeof(*ip) >> 2;
    588  1.1      cgd 	ip->ip_p = IPPROTO_UDP;
    589  1.1      cgd 	ip->ip_len = datalen;
    590  1.1      cgd 	ip->ip_ttl = ttl;
    591  1.3  mycroft 	ip->ip_v = IPVERSION;
    592  1.3  mycroft 	ip->ip_id = htons(ident+seq);
    593  1.1      cgd 
    594  1.1      cgd 	up->uh_sport = htons(ident);
    595  1.1      cgd 	up->uh_dport = htons(port+seq);
    596  1.1      cgd 	up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip)));
    597  1.1      cgd 	up->uh_sum = 0;
    598  1.1      cgd 
    599  1.1      cgd 	op->seq = seq;
    600  1.1      cgd 	op->ttl = ttl;
    601  1.1      cgd 	(void) gettimeofday(&op->tv, &tz);
    602  1.1      cgd 
    603  1.1      cgd 	i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
    604  1.1      cgd 		   sizeof(struct sockaddr));
    605  1.1      cgd 	if (i < 0 || i != datalen)  {
    606  1.1      cgd 		if (i<0)
    607  1.1      cgd 			perror("sendto");
    608  1.1      cgd 		Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
    609  1.1      cgd 			datalen, i);
    610  1.1      cgd 		(void) fflush(stdout);
    611  1.1      cgd 	}
    612  1.1      cgd }
    613  1.1      cgd 
    614  1.1      cgd 
    615  1.3  mycroft double
    616  1.3  mycroft deltaT(t1p, t2p)
    617  1.3  mycroft 	struct timeval *t1p, *t2p;
    618  1.3  mycroft {
    619  1.3  mycroft 	register double dt;
    620  1.3  mycroft 
    621  1.3  mycroft 	dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
    622  1.3  mycroft 	     (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
    623  1.3  mycroft 	return (dt);
    624  1.1      cgd }
    625  1.1      cgd 
    626  1.1      cgd 
    627  1.1      cgd /*
    628  1.1      cgd  * Convert an ICMP "type" field to a printable string.
    629  1.1      cgd  */
    630  1.1      cgd char *
    631  1.1      cgd pr_type(t)
    632  1.1      cgd 	u_char t;
    633  1.1      cgd {
    634  1.1      cgd 	static char *ttab[] = {
    635  1.1      cgd 	"Echo Reply",	"ICMP 1",	"ICMP 2",	"Dest Unreachable",
    636  1.1      cgd 	"Source Quench", "Redirect",	"ICMP 6",	"ICMP 7",
    637  1.1      cgd 	"Echo",		"ICMP 9",	"ICMP 10",	"Time Exceeded",
    638  1.1      cgd 	"Param Problem", "Timestamp",	"Timestamp Reply", "Info Request",
    639  1.1      cgd 	"Info Reply"
    640  1.1      cgd 	};
    641  1.1      cgd 
    642  1.1      cgd 	if(t > 16)
    643  1.1      cgd 		return("OUT-OF-RANGE");
    644  1.1      cgd 
    645  1.1      cgd 	return(ttab[t]);
    646  1.1      cgd }
    647  1.1      cgd 
    648  1.1      cgd 
    649  1.3  mycroft int
    650  1.1      cgd packet_ok(buf, cc, from, seq)
    651  1.1      cgd 	u_char *buf;
    652  1.1      cgd 	int cc;
    653  1.1      cgd 	struct sockaddr_in *from;
    654  1.1      cgd 	int seq;
    655  1.1      cgd {
    656  1.1      cgd 	register struct icmp *icp;
    657  1.1      cgd 	u_char type, code;
    658  1.1      cgd 	int hlen;
    659  1.1      cgd #ifndef ARCHAIC
    660  1.1      cgd 	struct ip *ip;
    661  1.1      cgd 
    662  1.1      cgd 	ip = (struct ip *) buf;
    663  1.1      cgd 	hlen = ip->ip_hl << 2;
    664  1.1      cgd 	if (cc < hlen + ICMP_MINLEN) {
    665  1.1      cgd 		if (verbose)
    666  1.1      cgd 			Printf("packet too short (%d bytes) from %s\n", cc,
    667  1.1      cgd 				inet_ntoa(from->sin_addr));
    668  1.1      cgd 		return (0);
    669  1.1      cgd 	}
    670  1.1      cgd 	cc -= hlen;
    671  1.1      cgd 	icp = (struct icmp *)(buf + hlen);
    672  1.1      cgd #else
    673  1.1      cgd 	icp = (struct icmp *)buf;
    674  1.1      cgd #endif ARCHAIC
    675  1.1      cgd 	type = icp->icmp_type; code = icp->icmp_code;
    676  1.1      cgd 	if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
    677  1.1      cgd 	    type == ICMP_UNREACH) {
    678  1.1      cgd 		struct ip *hip;
    679  1.1      cgd 		struct udphdr *up;
    680  1.1      cgd 
    681  1.1      cgd 		hip = &icp->icmp_ip;
    682  1.1      cgd 		hlen = hip->ip_hl << 2;
    683  1.1      cgd 		up = (struct udphdr *)((u_char *)hip + hlen);
    684  1.1      cgd 		if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
    685  1.1      cgd 		    up->uh_sport == htons(ident) &&
    686  1.1      cgd 		    up->uh_dport == htons(port+seq))
    687  1.1      cgd 			return (type == ICMP_TIMXCEED? -1 : code+1);
    688  1.1      cgd 	}
    689  1.1      cgd #ifndef ARCHAIC
    690  1.1      cgd 	if (verbose) {
    691  1.1      cgd 		int i;
    692  1.1      cgd 		u_long *lp = (u_long *)&icp->icmp_ip;
    693  1.1      cgd 
    694  1.1      cgd 		Printf("\n%d bytes from %s to %s", cc,
    695  1.1      cgd 			inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
    696  1.1      cgd 		Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
    697  1.1      cgd 		       icp->icmp_code);
    698  1.1      cgd 		for (i = 4; i < cc ; i += sizeof(long))
    699  1.1      cgd 			Printf("%2d: x%8.8lx\n", i, *lp++);
    700  1.1      cgd 	}
    701  1.1      cgd #endif ARCHAIC
    702  1.1      cgd 	return(0);
    703  1.1      cgd }
    704  1.1      cgd 
    705  1.1      cgd 
    706  1.3  mycroft void
    707  1.1      cgd print(buf, cc, from)
    708  1.1      cgd 	u_char *buf;
    709  1.1      cgd 	int cc;
    710  1.1      cgd 	struct sockaddr_in *from;
    711  1.1      cgd {
    712  1.1      cgd 	struct ip *ip;
    713  1.1      cgd 	int hlen;
    714  1.1      cgd 
    715  1.1      cgd 	ip = (struct ip *) buf;
    716  1.1      cgd 	hlen = ip->ip_hl << 2;
    717  1.1      cgd 	cc -= hlen;
    718  1.1      cgd 
    719  1.1      cgd 	if (nflag)
    720  1.1      cgd 		Printf(" %s", inet_ntoa(from->sin_addr));
    721  1.1      cgd 	else
    722  1.1      cgd 		Printf(" %s (%s)", inetname(from->sin_addr),
    723  1.1      cgd 		       inet_ntoa(from->sin_addr));
    724  1.1      cgd 
    725  1.1      cgd 	if (verbose)
    726  1.1      cgd 		Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
    727  1.1      cgd }
    728  1.1      cgd 
    729  1.1      cgd 
    730  1.1      cgd #ifdef notyet
    731  1.1      cgd /*
    732  1.1      cgd  * Checksum routine for Internet Protocol family headers (C Version)
    733  1.1      cgd  */
    734  1.3  mycroft u_short
    735  1.1      cgd in_cksum(addr, len)
    736  1.3  mycroft 	u_short *addr;
    737  1.3  mycroft 	int len;
    738  1.1      cgd {
    739  1.1      cgd 	register int nleft = len;
    740  1.1      cgd 	register u_short *w = addr;
    741  1.1      cgd 	register u_short answer;
    742  1.1      cgd 	register int sum = 0;
    743  1.1      cgd 
    744  1.1      cgd 	/*
    745  1.1      cgd 	 *  Our algorithm is simple, using a 32 bit accumulator (sum),
    746  1.1      cgd 	 *  we add sequential 16 bit words to it, and at the end, fold
    747  1.1      cgd 	 *  back all the carry bits from the top 16 bits into the lower
    748  1.1      cgd 	 *  16 bits.
    749  1.1      cgd 	 */
    750  1.1      cgd 	while (nleft > 1)  {
    751  1.1      cgd 		sum += *w++;
    752  1.1      cgd 		nleft -= 2;
    753  1.1      cgd 	}
    754  1.1      cgd 
    755  1.1      cgd 	/* mop up an odd byte, if necessary */
    756  1.1      cgd 	if (nleft == 1)
    757  1.1      cgd 		sum += *(u_char *)w;
    758  1.1      cgd 
    759  1.1      cgd 	/*
    760  1.1      cgd 	 * add back carry outs from top 16 bits to low 16 bits
    761  1.1      cgd 	 */
    762  1.1      cgd 	sum = (sum >> 16) + (sum & 0xffff);	/* add hi 16 to low 16 */
    763  1.1      cgd 	sum += (sum >> 16);			/* add carry */
    764  1.1      cgd 	answer = ~sum;				/* truncate to 16 bits */
    765  1.1      cgd 	return (answer);
    766  1.1      cgd }
    767  1.1      cgd #endif notyet
    768  1.1      cgd 
    769  1.1      cgd /*
    770  1.1      cgd  * Subtract 2 timeval structs:  out = out - in.
    771  1.1      cgd  * Out is assumed to be >= in.
    772  1.1      cgd  */
    773  1.3  mycroft void
    774  1.1      cgd tvsub(out, in)
    775  1.3  mycroft 	register struct timeval *out, *in;
    776  1.1      cgd {
    777  1.1      cgd 	if ((out->tv_usec -= in->tv_usec) < 0)   {
    778  1.1      cgd 		out->tv_sec--;
    779  1.1      cgd 		out->tv_usec += 1000000;
    780  1.1      cgd 	}
    781  1.1      cgd 	out->tv_sec -= in->tv_sec;
    782  1.1      cgd }
    783  1.1      cgd 
    784  1.1      cgd 
    785  1.1      cgd /*
    786  1.1      cgd  * Construct an Internet address representation.
    787  1.3  mycroft  * If the nflag has been supplied, give
    788  1.1      cgd  * numeric value, otherwise try for symbolic name.
    789  1.1      cgd  */
    790  1.1      cgd char *
    791  1.1      cgd inetname(in)
    792  1.1      cgd 	struct in_addr in;
    793  1.1      cgd {
    794  1.1      cgd 	register char *cp;
    795  1.1      cgd 	static char line[50];
    796  1.1      cgd 	struct hostent *hp;
    797  1.1      cgd 	static char domain[MAXHOSTNAMELEN + 1];
    798  1.1      cgd 	static int first = 1;
    799  1.1      cgd 
    800  1.1      cgd 	if (first && !nflag) {
    801  1.1      cgd 		first = 0;
    802  1.1      cgd 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
    803  1.1      cgd 		    (cp = index(domain, '.')))
    804  1.1      cgd 			(void) strcpy(domain, cp + 1);
    805  1.1      cgd 		else
    806  1.1      cgd 			domain[0] = 0;
    807  1.1      cgd 	}
    808  1.1      cgd 	cp = 0;
    809  1.1      cgd 	if (!nflag && in.s_addr != INADDR_ANY) {
    810  1.1      cgd 		hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
    811  1.1      cgd 		if (hp) {
    812  1.1      cgd 			if ((cp = index(hp->h_name, '.')) &&
    813  1.1      cgd 			    !strcmp(cp + 1, domain))
    814  1.1      cgd 				*cp = 0;
    815  1.1      cgd 			cp = hp->h_name;
    816  1.1      cgd 		}
    817  1.1      cgd 	}
    818  1.1      cgd 	if (cp)
    819  1.1      cgd 		(void) strcpy(line, cp);
    820  1.1      cgd 	else {
    821  1.1      cgd 		in.s_addr = ntohl(in.s_addr);
    822  1.1      cgd #define C(x)	((x) & 0xff)
    823  1.1      cgd 		Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24),
    824  1.1      cgd 			C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
    825  1.1      cgd 	}
    826  1.1      cgd 	return (line);
    827  1.1      cgd }
    828  1.1      cgd 
    829  1.3  mycroft void
    830  1.1      cgd usage()
    831  1.1      cgd {
    832  1.3  mycroft 	(void)fprintf(stderr,
    833  1.1      cgd "usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
    834  1.1      cgd [-s src_addr] [-t tos] [-w wait] host [data size]\n");
    835  1.1      cgd 	exit(1);
    836  1.1      cgd }
    837