Added a port of BSD traceroute. needs work

svn path=/trunk/; revision=12989
This commit is contained in:
Steven Edwards 2005-01-12 20:18:50 +00:00
parent f387572e84
commit a0b2f40b73
6 changed files with 1383 additions and 0 deletions

View file

@ -0,0 +1,195 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip.h 8.2 (Berkeley) 6/1/94
* $FreeBSD: src/sys/netinet/ip.h,v 1.16 1999/08/28 00:49:19 peter Exp $
*/
#ifndef _NETINET_IP_H_
#define _NETINET_IP_H_
/*
* Definitions for internet protocol version 4.
* Per RFC 791, September 1981.
*/
#define IPVERSION 4
/* A little magic to make the Windows build happy. */
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <time.h>
typedef u_short n_short;
typedef u_int n_long;
typedef u_int n_time;
#define EMSGSIZE WSAEMSGSIZE
#define ENETUNREACH WSAENETUNREACH
#define EHOSTUNREACH WSAEHOSTUNREACH
#endif
/*
* Structure of an internet header, naked of options.
*/
struct ip {
#ifdef _IP_VHL
u_char ip_vhl; /* version << 4 | header length >> 2 */
#else
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ip_hl:4, /* header length */
ip_v:4; /* version */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
#endif /* not _IP_VHL */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* don't fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#ifdef _IP_VHL
#define IP_MAKE_VHL(v, hl) ((v) << 4 | (hl))
#define IP_VHL_HL(vhl) ((vhl) & 0x0f)
#define IP_VHL_V(vhl) ((vhl) >> 4)
#define IP_VHL_BORING 0x45
#endif
#define IP_MAXPACKET 65535 /* maximum packet size */
/*
* Definitions for IP type of service (ip_tos)
*/
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
#define IPTOS_MINCOST 0x02
/*
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
*/
#define IPTOS_PREC_NETCONTROL 0xe0
#define IPTOS_PREC_INTERNETCONTROL 0xc0
#define IPTOS_PREC_CRITIC_ECP 0xa0
#define IPTOS_PREC_FLASHOVERRIDE 0x80
#define IPTOS_PREC_FLASH 0x60
#define IPTOS_PREC_IMMEDIATE 0x40
#define IPTOS_PREC_PRIORITY 0x20
#define IPTOS_PREC_ROUTINE 0x00
/*
* Definitions for options.
*/
#define IPOPT_COPIED(o) ((o)&0x80)
#define IPOPT_CLASS(o) ((o)&0x60)
#define IPOPT_NUMBER(o) ((o)&0x1f)
#define IPOPT_CONTROL 0x00
#define IPOPT_RESERVED1 0x20
#define IPOPT_DEBMEAS 0x40
#define IPOPT_RESERVED2 0x60
#define IPOPT_EOL 0 /* end of option list */
#define IPOPT_NOP 1 /* no operation */
#define IPOPT_RR 7 /* record packet route */
#define IPOPT_TS 68 /* timestamp */
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
#define IPOPT_LSRR 131 /* loose source route */
#define IPOPT_SATID 136 /* satnet id */
#define IPOPT_SSRR 137 /* strict source route */
#define IPOPT_RA 148 /* router alert */
/*
* Offsets to fields in options other than EOL and NOP.
*/
#define IPOPT_OPTVAL 0 /* option ID */
#define IPOPT_OLEN 1 /* option length */
#define IPOPT_OFFSET 2 /* offset within option */
#define IPOPT_MINOFF 4 /* min value of above */
/*
* Time stamp option structure.
*/
struct ip_timestamp {
u_char ipt_code; /* IPOPT_TS */
u_char ipt_len; /* size of structure (variable) */
u_char ipt_ptr; /* index of current entry */
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ipt_flg:4, /* flags, see below */
ipt_oflw:4; /* overflow counter */
#endif
#if BYTE_ORDER == BIG_ENDIAN
u_int ipt_oflw:4, /* overflow counter */
ipt_flg:4; /* flags, see below */
#endif
union ipt_timestamp {
n_long ipt_time[1];
struct ipt_ta {
struct in_addr ipt_addr;
n_long ipt_time;
} ipt_ta[1];
} ipt_timestamp;
};
/* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
/* bits for security (not byte swapped) */
#define IPOPT_SECUR_UNCLASS 0x0000
#define IPOPT_SECUR_CONFID 0xf135
#define IPOPT_SECUR_EFTO 0x789a
#define IPOPT_SECUR_MMMM 0xbc4d
#define IPOPT_SECUR_RESTR 0xaf13
#define IPOPT_SECUR_SECRET 0xd788
#define IPOPT_SECUR_TOPSECRET 0x6bc5
/*
* Internet implementation parameters.
*/
#define MAXTTL 255 /* maximum time to live (seconds) */
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
#define IPTTLDEC 1 /* subtracted when forwarding */
#define IP_MSS 576 /* default maximum segment size */
#endif

View file

@ -0,0 +1,186 @@
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93
* $FreeBSD: src/sys/netinet/ip_icmp.h,v 1.13 1999/08/28 00:49:24 peter Exp $
*/
#ifndef _NETINET_IP_ICMP_H_
#define _NETINET_IP_ICMP_H_
/*
* Interface Control Message Protocol Definitions.
* Per RFC 792, September 1981.
*/
/*
* Internal of an ICMP Router Advertisement
*/
struct icmp_ra_addr {
u_int32_t ira_addr;
u_int32_t ira_preference;
};
/*
* Structure of an icmp header.
*/
struct icmp {
u_char icmp_type; /* type of message, see below */
u_char icmp_code; /* type sub code */
u_short icmp_cksum; /* ones complement cksum of struct */
union {
u_char ih_pptr; /* ICMP_PARAMPROB */
struct in_addr ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
n_short icd_id;
n_short icd_seq;
} ih_idseq;
int ih_void;
/* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
struct ih_pmtu {
n_short ipm_void;
n_short ipm_nextmtu;
} ih_pmtu;
struct ih_rtradv {
u_char irt_num_addrs;
u_char irt_wpa;
u_int16_t irt_lifetime;
} ih_rtradv;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void
#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu
#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs
#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa
#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime
union {
struct id_ts {
n_time its_otime;
n_time its_rtime;
n_time its_ttime;
} id_ts;
struct id_ip {
struct ip idi_ip;
/* options and then 64 bits of data */
} id_ip;
struct icmp_ra_addr id_radv;
u_int32_t id_mask;
char id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
/*
* Lower bounds on packet lengths for various types.
* For the error advice packets must first insure that the
* packet is large enough to contain the returned ip header.
* Only then can we do the check to see if 64 bits of packet
* data have been returned, since we need to check the returned
* ip header length.
*/
#define ICMP_MINLEN 8 /* abs minimum */
#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */
#define ICMP_MASKLEN 12 /* address mask */
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
#ifndef _IP_VHL
#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8)
/* N.B.: must separately check that ip_hl >= 5 */
#else
#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8)
/* N.B.: must separately check that header length >= 5 */
#endif
/*
* Definition of type and code field values.
*/
#define ICMP_ECHOREPLY 0 /* echo reply */
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
#define ICMP_UNREACH_NET 0 /* bad net */
#define ICMP_UNREACH_HOST 1 /* bad host */
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
#define ICMP_UNREACH_PORT 3 /* bad port */
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */
#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
#define ICMP_REDIRECT 5 /* shorter route, codes: */
#define ICMP_REDIRECT_NET 0 /* for network */
#define ICMP_REDIRECT_HOST 1 /* for host */
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
#define ICMP_ECHO 8 /* echo service */
#define ICMP_ROUTERADVERT 9 /* router advertisement */
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
#define ICMP_PARAMPROB 12 /* ip header bad */
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
#define ICMP_TSTAMP 13 /* timestamp request */
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
#define ICMP_IREQ 15 /* information request */
#define ICMP_IREQREPLY 16 /* information reply */
#define ICMP_MASKREQ 17 /* address mask request */
#define ICMP_MASKREPLY 18 /* address mask reply */
#define ICMP_MAXTYPE 18
#define ICMP_INFOTYPE(type) \
((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \
(type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \
(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY)
#ifdef KERNEL
void icmp_error __P((struct mbuf *, int, int, n_long, struct ifnet *));
void icmp_input __P((struct mbuf *, int));
#endif
#endif

View file

@ -0,0 +1,20 @@
PATH_TO_TOP = ../../../..
TARGET_TYPE = program
TARGET_APPTYPE = console
TARGET_NAME = traceroute
TARGET_INSTALLDIR = system32
TARGET_SDKLIBS = ws2_32.a iphlpapi.a ntdll.a
TARGET_OBJECTS = \
$(TARGET_NAME).o
TARGET_GCCLIBS =
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -0,0 +1,47 @@
#include <stdio.h>
#include <time.h>
#include <winsock.h>
#ifndef __GNUC__
#define EPOCHFILETIME (116444736000000000i64)
#else
#define EPOCHFILETIME (116444736000000000LL)
#endif
struct timezone {
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
__inline int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
if (tv)
{
GetSystemTimeAsFileTime(&ft);
//li.LowPart = ft.dwLowDateTime;
//li.HighPart = ft.dwHighDateTime;
t = li.QuadPart; /* In 100-nanosecond intervals */
t -= EPOCHFILETIME; /* Offset to the Epoch time */
t /= 10; /* In microseconds */
tv->tv_sec = (long)(t / 1000000);
tv->tv_usec = (long)(t % 1000000);
}
if (tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}

View file

@ -0,0 +1,929 @@
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Van Jacobson.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1990, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
/*
* traceroute host - trace the route ip packets follow going to "host".
*
* Attempt to trace the route an ip packet would follow to some
* internet host. We find out intermediate hops by launching probe
* packets with a small ttl (time to live) then listening for an
* icmp "time exceeded" reply from a gateway. We start our probes
* with a ttl of one and increase by one until we get an icmp "port
* unreachable" (which means we got to "host") or hit a max (which
* defaults to 30 hops & can be changed with the -m flag). Three
* probes (change with -q flag) are sent at each ttl setting and a
* line is printed showing the ttl, address of the gateway and
* round trip time of each probe. If the probe answers come from
* different gateways, the address of each responding system will
* be printed. If there is no response within a 5 sec. timeout
* interval (changed with the -w flag), a "*" is printed for that
* probe.
*
* Probe packets are UDP format. We don't want the destination
* host to process them so the destination port is set to an
* unlikely value (if some clod on the destination is using that
* value, it can be changed with the -p flag).
*
* A sample use might be:
*
* [yak 71]% traceroute nis.nsf.net.
* traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
* 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
* 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
* 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
* 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
* 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
* 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
* 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
* 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
* 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
* 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
* 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
*
* Note that lines 2 & 3 are the same. This is due to a buggy
* kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards
* packets with a zero ttl.
*
* A more interesting example is:
*
* [yak 72]% traceroute allspice.lcs.mit.edu.
* traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
* 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
* 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
* 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
* 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
* 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
* 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
* 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
* 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
* 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
* 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
* 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
* 12 * * *
* 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
* 14 * * *
* 15 * * *
* 16 * * *
* 17 * * *
* 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
*
* (I start to see why I'm having so much trouble with mail to
* MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away
* either don't send ICMP "time exceeded" messages or send them
* with a ttl too small to reach us. 14 - 17 are running the
* MIT C Gateway code that doesn't send "time exceeded"s. God
* only knows what's going on with 12.
*
* The silent gateway 12 in the above may be the result of a bug in
* the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3)
* sends an unreachable message using whatever ttl remains in the
* original datagram. Since, for gateways, the remaining ttl is
* zero, the icmp "time exceeded" is guaranteed to not make it back
* to us. The behavior of this bug is slightly more interesting
* when it appears on the destination system:
*
* 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
* 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
* 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
* 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
* 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
* 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
* 7 * * *
* 8 * * *
* 9 * * *
* 10 * * *
* 11 * * *
* 12 * * *
* 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
*
* Notice that there are 12 "gateways" (13 is the final
* destination) and exactly the last half of them are "missing".
* What's really happening is that rip (a Sun-3 running Sun OS3.5)
* is using the ttl from our arriving datagram as the ttl in its
* icmp reply. So, the reply will time out on the return path
* (with no notice sent to anyone since icmp's aren't sent for
* icmp's) until we probe with a ttl that's at least twice the path
* length. I.e., rip is really only 7 hops away. A reply that
* returns with a ttl of 1 is a clue this problem exists.
* Traceroute prints a "!" after the time if the ttl is <= 1.
* Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or
* non-standard (HPUX) software, expect to see this problem
* frequently and/or take care picking the target host of your
* probes.
*
* Other possible annotations after the time are !H, !N, !P (got a host,
* network or protocol unreachable, respectively), !S or !F (source
* route failed or fragmentation needed -- neither of these should
* ever occur and the associated gateway is busted if you see one). If
* almost all the probes result in some kind of unreachable, traceroute
* will give up and exit.
*
* Notes
* -----
* This program must be run by root or be setuid. (I suggest that
* you *don't* make it setuid -- casual use could result in a lot
* of unnecessary traffic on our poor, congested nets.)
*
* This program requires a kernel mod that does not appear in any
* system available from Berkeley: A raw ip socket using proto
* IPPROTO_RAW must interpret the data sent as an ip datagram (as
* opposed to data to be wrapped in a ip datagram). See the README
* file that came with the source to this program for a description
* of the mods I made to /sys/netinet/raw_ip.c. Your mileage may
* vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE
* MODIFIED TO RUN THIS PROGRAM.
*
* The udp port usage may appear bizarre (well, ok, it is bizarre).
* The problem is that an icmp message only contains 8 bytes of
* data from the original datagram. 8 bytes is the size of a udp
* header so, if we want to associate replies with the original
* datagram, the necessary information must be encoded into the
* udp header (the ip id could be used but there's no way to
* interlock with the kernel's assignment of ip id's and, anyway,
* it would have taken a lot more kernel hacking to allow this
* code to set the ip id). So, to allow two or more users to
* use traceroute simultaneously, we use this task's pid as the
* source port (the high bit is set to move the port number out
* of the "likely" range). To keep track of which probe is being
* replied to (so times and/or hop counts don't get confused by a
* reply that was delayed in transit), we increment the destination
* port number before each probe.
*
* Don't use this as a coding example. I was trying to find a
* routing problem and this code sort-of popped out after 48 hours
* without sleep. I was amazed it ever compiled, much less ran.
*
* I stole the idea for this program from Steve Deering. Since
* the first release, I've learned that had I attended the right
* IETF working group meetings, I also could have stolen it from Guy
* Almes or Matt Mathis. I don't know (or care) who came up with
* the idea first. I envy the originators' perspicacity and I'm
* glad they didn't keep the idea a secret.
*
* Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or
* enhancements to the original distribution.
*
* I've hacked up a round-trip-route version of this that works by
* sending a loose-source-routed udp datagram through the destination
* back to yourself. Unfortunately, SO many gateways botch source
* routing, the thing is almost worthless. Maybe one day...
*
* -- Van Jacobson (van@helios.ee.lbl.gov)
* Tue Dec 20 03:50:13 PST 1988
*/
#define caddr_t void *
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <winsock2.h>
#include <stdio.h>
#include <time.h>
#include <winsock.h>
//void print(buf, cc, from);
char * inetname(in);
double deltaT(t1p, t2p);
void usage();
void send_probe(seq, ttl);
#define bzero( ptr, count ) memset( ptr, 0, count )
#define bcopy(src,dest,len) memcpy(dest,src,len)
// setlinebuf is equivalent to the setvbuf call below.
inline int setlinebuf(FILE *stream)
{
return setvbuf( stream, (char*)0, _IONBF, 0 );
}
#ifndef __GNUC__
#define EPOCHFILETIME (116444736000000000i64)
#else
#define EPOCHFILETIME (116444736000000000LL)
#endif
struct timezone {
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
if (tv)
{
GetSystemTimeAsFileTime(&ft);
li.LowPart = ft.dwLowDateTime;
li.HighPart = ft.dwHighDateTime;
t = li.QuadPart; /* In 100-nanosecond intervals */
t -= EPOCHFILETIME; /* Offset to the Epoch time */
t /= 10; /* In microseconds */
tv->tv_sec = (long)(t / 1000000);
tv->tv_usec = (long)(t % 1000000);
}
if (tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}
return 0;
}
/* Set up endiannes macros for the ip and ip_icmp BSD headers */
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BYTE_ORDER
#ifdef WORDS_BIGENDIAN
#define BYTE_ORDER BIG_ENDIAN
#else
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif /* BYTE_ORDER */
#define u_int16_t WORD
#define u_int32_t DWORD
/* These are BSD headers. We use these here because they are needed on
* libc5 Linux systems. On other platforms they are usually simply more
* complete than the native stuff, and cause less portability problems
* so we use them anyway.
*/
#include "ip.h"
#include "ip_icmp.h"
#define MAXPACKET 65535 /* max ip packet size */
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 64
#endif
#ifndef FD_SET
#define NFDBITS (8*sizeof(fd_set))
#define FD_SETSIZE NFDBITS
#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
#endif
#define Fprintf (void)fprintf
#define Sprintf (void)sprintf
#define Printf (void)printf
// Define the UDP header
//
typedef struct udp_hdr
{
unsigned short src_portno; // Source port number
unsigned short dst_portno; // Destination port number
unsigned short udp_length; // UDP packet length
unsigned short udp_checksum; // UDP checksum (optional)
} UDP_HDR, *PUDP_HDR;
/*
* format of a (udp) probe packet.
*/
struct opacket {
struct ip ip;
UDP_HDR udp;
u_char seq; /* sequence number of this packet */
u_char ttl; /* ttl packet left with */
struct timeval tv; /* time packet left */
};
u_char packet[512]; /* last inbound (icmp) packet */
struct opacket *outpacket; /* last output (udp) packet */
#if 0
int wait_for_reply __P((int, struct sockaddr_in *));
void send_probe __P((int, int));
double deltaT __P((struct timeval *, struct timeval *));
int packet_ok __P((u_char *, int, struct sockaddr_in *, int));
//void print __P((u_char *, int, struct sockaddr_in *));
void tvsub __P((struct timeval *, struct timeval *));
char *inetname __P((struct in_addr));
void usage __P(());
#endif
int s; /* receive (icmp) socket file descriptor */
int sndsock; /* send (udp) socket file descriptor */
struct timezone tz; /* leftover */
struct sockaddr whereto; /* Who to try to reach */
int datalen; /* How much data */
char *source = 0;
char *hostname;
int nprobes = 3;
int max_ttl = 30;
u_short ident;
u_short port = 32768+666; /* start udp dest port # for probe packets */
int options; /* socket options */
int verbose;
int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
void
print(buf, cc, from)
u_char *buf;
int cc;
struct sockaddr_in *from;
{
struct ip *ip;
int hlen;
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
cc -= hlen;
if (nflag)
Printf(" %s", inet_ntoa(from->sin_addr));
else
Printf(" %s (%s)", inetname(from->sin_addr),
inet_ntoa(from->sin_addr));
if (verbose)
Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst));
}
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
struct hostent *hp;
struct protoent *pe;
struct sockaddr_in from, *to;
int ch, i, on, probe, seq, tos, ttl;
on = 1;
seq = tos = 0;
to = (struct sockaddr_in *)&whereto;
while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF)
switch(ch) {
case 'd':
options |= SO_DEBUG;
break;
case 'm':
max_ttl = atoi(optarg);
if (max_ttl <= 1) {
Fprintf(stderr,
"traceroute: max ttl must be >1.\n");
exit(1);
}
break;
case 'n':
nflag++;
break;
case 'p':
port = atoi(optarg);
if (port < 1) {
Fprintf(stderr,
"traceroute: port must be >0.\n");
exit(1);
}
break;
case 'q':
nprobes = atoi(optarg);
if (nprobes < 1) {
Fprintf(stderr,
"traceroute: nprobes must be >0.\n");
exit(1);
}
break;
case 'r':
options |= SO_DONTROUTE;
break;
case 's':
/*
* set the ip source address of the outbound
* probe (e.g., on a multi-homed host).
*/
source = optarg;
break;
case 't':
tos = atoi(optarg);
if (tos < 0 || tos > 255) {
Fprintf(stderr,
"traceroute: tos must be 0 to 255.\n");
exit(1);
}
break;
case 'v':
verbose++;
break;
case 'w':
waittime = atoi(optarg);
if (waittime <= 1) {
Fprintf(stderr,
"traceroute: wait must be >1 sec.\n");
exit(1);
}
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (argc < 1)
usage();
setlinebuf (stdout);
(void) bzero((char *)&whereto, sizeof(struct sockaddr));
to->sin_family = AF_INET;
to->sin_addr.s_addr = inet_addr(*argv);
if (to->sin_addr.s_addr != -1)
hostname = *argv;
else {
hp = gethostbyname(*argv);
if (hp) {
to->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
hostname = hp->h_name;
} else {
(void)fprintf(stderr,
"traceroute: unknown host %s\n", *argv);
exit(1);
}
}
if (*++argv)
datalen = atoi(*argv);
if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) {
Fprintf(stderr,
"traceroute: packet size must be 0 <= s < %ld.\n",
MAXPACKET - sizeof(struct opacket));
exit(1);
}
datalen += sizeof(struct opacket);
outpacket = (struct opacket *)malloc((unsigned)datalen);
if (! outpacket) {
perror("traceroute: malloc");
exit(1);
}
(void) bzero((char *)outpacket, datalen);
outpacket->ip.ip_dst = to->sin_addr;
outpacket->ip.ip_tos = tos;
outpacket->ip.ip_v = IPVERSION;
outpacket->ip.ip_id = 0;
ident = (getpid() & 0xffff) | 0x8000;
if ((pe = getprotobyname("icmp")) == NULL) {
Fprintf(stderr, "icmp: unknown protocol\n");
exit(10);
}
if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) {
perror("traceroute: icmp socket");
exit(5);
}
if (options & SO_DEBUG)
(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
(char *)&on, sizeof(on));
if (options & SO_DONTROUTE)
(void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE,
(char *)&on, sizeof(on));
if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
perror("traceroute: raw socket");
exit(5);
}
#ifdef SO_SNDBUF
if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen,
sizeof(datalen)) < 0) {
perror("traceroute: SO_SNDBUF");
exit(6);
}
#endif /* SO_SNDBUF */
#ifdef IP_HDRINCL
if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
sizeof(on)) < 0) {
perror("traceroute: IP_HDRINCL");
exit(6);
}
#endif /* IP_HDRINCL */
if (options & SO_DEBUG)
(void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG,
(char *)&on, sizeof(on));
if (options & SO_DONTROUTE)
(void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE,
(char *)&on, sizeof(on));
if (source) {
(void) bzero((char *)&from, sizeof(struct sockaddr));
from.sin_family = AF_INET;
from.sin_addr.s_addr = inet_addr(source);
if (from.sin_addr.s_addr == -1) {
Printf("traceroute: unknown host %s\n", source);
exit(1);
}
outpacket->ip.ip_src = from.sin_addr;
#ifndef IP_HDRINCL
if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) {
perror ("traceroute: bind:");
exit (1);
}
#endif /* IP_HDRINCL */
}
Fprintf(stderr, "traceroute to %s (%s)", hostname,
inet_ntoa(to->sin_addr));
if (source)
Fprintf(stderr, " from %s", source);
Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen);
(void) fflush(stderr);
for (ttl = 1; ttl <= max_ttl; ++ttl) {
u_long lastaddr = 0;
int got_there = 0;
int unreachable = 0;
Printf("%2d ", ttl);
for (probe = 0; probe < nprobes; ++probe) {
int cc;
struct timeval t1, t2;
struct timezone tz;
struct ip *ip;
(void) gettimeofday(&t1, &tz);
send_probe(++seq, ttl);
while (cc = wait_for_reply(s, &from)) {
(void) gettimeofday(&t2, &tz);
if ((i = packet_ok(packet, cc, &from, seq))) {
if (from.sin_addr.s_addr != lastaddr) {
print(packet, cc, &from);
lastaddr = from.sin_addr.s_addr;
}
Printf(" %g ms", deltaT(&t1, &t2));
switch(i - 1) {
case ICMP_UNREACH_PORT:
#ifndef ARCHAIC
ip = (struct ip *)packet;
if (ip->ip_ttl <= 1)
Printf(" !");
#endif /* ARCHAIC */
++got_there;
break;
case ICMP_UNREACH_NET:
++unreachable;
Printf(" !N");
break;
case ICMP_UNREACH_HOST:
++unreachable;
Printf(" !H");
break;
case ICMP_UNREACH_PROTOCOL:
++got_there;
Printf(" !P");
break;
case ICMP_UNREACH_NEEDFRAG:
++unreachable;
Printf(" !F");
break;
case ICMP_UNREACH_SRCFAIL:
++unreachable;
Printf(" !S");
break;
}
break;
}
}
if (cc == 0)
Printf(" *");
(void) fflush(stdout);
}
putchar('\n');
if (got_there || unreachable >= nprobes-1)
exit(0);
}
}
int
wait_for_reply(sock, from)
int sock;
struct sockaddr_in *from;
{
fd_set fds;
struct timeval wait;
int cc = 0;
int fromlen = sizeof (*from);
FD_ZERO(&fds);
FD_SET(sock, &fds);
wait.tv_sec = waittime; wait.tv_usec = 0;
if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0)
cc=recvfrom(s, (char *)packet, sizeof(packet), 0,
(struct sockaddr *)from, &fromlen);
return(cc);
}
void
send_probe(seq, ttl)
int seq, ttl;
{
struct opacket *op = outpacket;
struct ip *ip = &op->ip;
struct udphdr *up = &op->udp;
int i;
ip->ip_off = 0;
ip->ip_hl = sizeof(*ip) >> 2;
ip->ip_p = IPPROTO_UDP;
ip->ip_len = datalen;
ip->ip_ttl = ttl;
ip->ip_v = IPVERSION;
ip->ip_id = htons(ident+seq);
// up->uh_sport = htons(ident);
// up->uh_dport = htons(port+seq);
// up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip)));
// up->uh_sum = 0;
op->seq = seq;
op->ttl = ttl;
(void) gettimeofday(&op->tv, &tz);
i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto,
sizeof(struct sockaddr));
if (i < 0 || i != datalen) {
if (i<0)
perror("sendto");
Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname,
datalen, i);
(void) fflush(stdout);
}
}
double
deltaT(t1p, t2p)
struct timeval *t1p, *t2p;
{
register double dt;
dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 +
(double)(t2p->tv_usec - t1p->tv_usec) / 1000.0;
return (dt);
}
/*
* Convert an ICMP "type" field to a printable string.
*/
char *
pr_type(t)
u_char t;
{
static char *ttab[] = {
"Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable",
"Source Quench", "Redirect", "ICMP 6", "ICMP 7",
"Echo", "ICMP 9", "ICMP 10", "Time Exceeded",
"Param Problem", "Timestamp", "Timestamp Reply", "Info Request",
"Info Reply"
};
if(t > 16)
return("OUT-OF-RANGE");
return(ttab[t]);
}
int
packet_ok(buf, cc, from, seq)
u_char *buf;
int cc;
struct sockaddr_in *from;
int seq;
{
register struct icmp *icp;
u_char type, code;
int hlen;
#ifndef ARCHAIC
struct ip *ip;
ip = (struct ip *) buf;
hlen = ip->ip_hl << 2;
if (cc < hlen + ICMP_MINLEN) {
if (verbose)
Printf("packet too short (%d bytes) from %s\n", cc,
inet_ntoa(from->sin_addr));
return (0);
}
cc -= hlen;
icp = (struct icmp *)(buf + hlen);
#else
icp = (struct icmp *)buf;
#endif /* ARCHAIC */
type = icp->icmp_type; code = icp->icmp_code;
if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) ||
type == ICMP_UNREACH) {
struct ip *hip;
struct udphdr *up;
hip = &icp->icmp_ip;
hlen = hip->ip_hl << 2;
up = (struct udphdr *)((u_char *)hip + hlen);
// if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP &&
// up->uh_sport == htons(ident) &&
// up->uh_dport == htons(port+seq))
if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP)
return (type == ICMP_TIMXCEED? -1 : code+1);
}
#ifndef ARCHAIC
if (verbose) {
int i;
u_long *lp = (u_long *)&icp->icmp_ip;
Printf("\n%d bytes from %s to %s", cc,
inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst));
Printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
icp->icmp_code);
for (i = 4; i < cc ; i += sizeof(long))
Printf("%2d: x%8.8lx\n", i, *lp++);
}
#endif /* ARCHAIC */
return(0);
}
#ifdef notyet
/*
* Checksum routine for Internet Protocol family headers (C Version)
*/
u_short
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register u_short answer;
register int sum = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
sum += *(u_char *)w;
/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
#endif /* notyet */
/*
* Subtract 2 timeval structs: out = out - in.
* Out is assumed to be >= in.
*/
void
tvsub(out, in)
register struct timeval *out, *in;
{
if ((out->tv_usec -= in->tv_usec) < 0) {
out->tv_sec--;
out->tv_usec += 1000000;
}
out->tv_sec -= in->tv_sec;
}
/*
* Construct an Internet address representation.
* If the nflag has been supplied, give
* numeric value, otherwise try for symbolic name.
*/
char *
inetname(in)
struct in_addr in;
{
register char *cp;
static char line[50];
struct hostent *hp;
static char domain[MAXHOSTNAMELEN + 1];
static int first = 1;
if (first && !nflag) {
first = 0;
if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
(cp = strrchr(domain, '.')))
(void) strcpy(domain, cp + 1);
else
domain[0] = 0;
}
cp = 0;
if (!nflag && in.s_addr != INADDR_ANY) {
hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET);
if (hp) {
if ((cp = strrchr(hp->h_name, '.')) &&
!strcmp(cp + 1, domain))
*cp = 0;
cp = hp->h_name;
}
}
if (cp)
(void) strcpy(line, cp);
else {
in.s_addr = ntohl(in.s_addr);
#define C(x) ((x) & 0xff)
Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24),
C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
}
return (line);
}
void
usage()
{
(void)fprintf(stderr,
"usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\
[-s src_addr] [-t tos] [-w wait] host [data size]\n");
exit(1);
}

View file

@ -0,0 +1,6 @@
/* $Id: route.rc 11816 2004-11-26 06:51:47Z arty $ */
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 FTP Client\0"
#define REACTOS_STR_INTERNAL_NAME "ftp\0"
#define REACTOS_STR_ORIGINAL_FILENAME "ftp.exe\0"
#include <reactos/version.rc>