Add AS lookup functionality. On each hop we query a whois server to

find the corresponding AS for that IP (-a switch).
We can also choose a different whois server with the -A switch. The
default is whois.radb.net.

Obtained from:	       NetBSD
Reviewed by:	       bms, njl (mentor)
Approved by:	       njl (mentor)
This commit is contained in:
Rui Paulo 2008-02-20 23:29:53 +00:00
parent 6f540420dd
commit 8ea0d8cff1
5 changed files with 332 additions and 7 deletions

242
contrib/traceroute/as.c Normal file
View File

@ -0,0 +1,242 @@
/* $FreeBSD$ */
/* $NetBSD: as.c,v 1.1 2001/11/04 23:14:36 atatat Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Brown.
*
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <stdio.h>
#include "as.h"
#define DEFAULT_AS_SERVER "whois.radb.net"
#undef AS_DEBUG_FILE
struct aslookup {
FILE *as_f;
#ifdef AS_DEBUG_FILE
FILE *as_debug;
#endif /* AS_DEBUG_FILE */
};
void *
as_setup(server)
char *server;
{
struct aslookup *asn;
struct hostent *he = NULL;
struct servent *se;
struct sockaddr_in in;
FILE *f;
int s;
if (server == NULL)
server = DEFAULT_AS_SERVER;
(void)memset(&in, 0, sizeof(in));
in.sin_family = AF_INET;
in.sin_len = sizeof(in);
if ((se = getservbyname("whois", "tcp")) == NULL) {
warnx("warning: whois/tcp service not found");
in.sin_port = ntohs(43);
} else
in.sin_port = se->s_port;
if (inet_aton(server, &in.sin_addr) == 0 &&
((he = gethostbyname(server)) == NULL ||
he->h_addr == NULL)) {
warnx("%s: %s", server, hstrerror(h_errno));
return (NULL);
}
if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
warn("socket");
return (NULL);
}
do {
if (he != NULL) {
memcpy(&in.sin_addr, he->h_addr, he->h_length);
he->h_addr_list++;
}
if (connect(s, (struct sockaddr *)&in, sizeof(in)) == 0)
break;
if (he == NULL || he->h_addr == NULL) {
close(s);
s = -1;
break;
}
} while (1);
if (s == -1) {
warn("connect");
return (NULL);
}
f = fdopen(s, "r+");
(void)fprintf(f, "!!\n");
(void)fflush(f);
asn = malloc(sizeof(struct aslookup));
if (asn == NULL)
(void)fclose(f);
else
asn->as_f = f;
#ifdef AS_DEBUG_FILE
asn->as_debug = fopen(AS_DEBUG_FILE, "w");
if (asn->as_debug) {
(void)fprintf(asn->as_debug, ">> !!\n");
(void)fflush(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
return (asn);
}
int
as_lookup(_asn, addr)
void *_asn;
struct in_addr *addr;
{
struct aslookup *asn = _asn;
char buf[1024];
int as, rc, dlen;
as = rc = dlen = 0;
(void)fprintf(asn->as_f, "!r%s/32,l\n", inet_ntoa(*addr));
(void)fflush(asn->as_f);
#ifdef AS_DEBUG_FILE
if (asn->as_debug) {
(void)fprintf(asn->as_debug, ">> !r%s/32,l\n",
inet_ntoa(*addr));
(void)fflush(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
while (fgets(buf, sizeof(buf), asn->as_f) != NULL) {
buf[sizeof(buf) - 1] = '\0';
#ifdef AS_DEBUG_FILE
if (asn->as_debug) {
(void)fprintf(asn->as_debug, "<< %s", buf);
(void)fflush(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
if (rc == 0) {
rc = buf[0];
switch (rc) {
case 'A':
/* A - followed by # bytes of answer */
sscanf(buf, "A%d\n", &dlen);
#ifdef AS_DEBUG_FILE
if (asn->as_debug) {
(void)fprintf(asn->as_debug,
"dlen: %d\n", dlen);
(void)fflush(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
break;
case 'C':
case 'D':
case 'E':
case 'F':
/* C - no data returned */
/* D - key not found */
/* E - multiple copies of key */
/* F - some other error */
break;
}
if (rc == 'A')
/* skip to next input line */
continue;
}
if (dlen == 0)
/* out of data, next char read is end code */
rc = buf[0];
if (rc != 'A')
/* either an error off the bat, or a done code */
break;
/* data received, thank you */
dlen -= strlen(buf);
/* origin line is the interesting bit */
if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) {
sscanf(buf + 7, " AS%d", &as);
#ifdef AS_DEBUG_FILE
if (asn->as_debug) {
(void)fprintf(asn->as_debug, "as: %d\n", as);
(void)fflush(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
}
}
return (as);
}
void
as_shutdown(_asn)
void *_asn;
{
struct aslookup *asn = _asn;
(void)fprintf(asn->as_f, "!q\n");
(void)fclose(asn->as_f);
#ifdef AS_DEBUG_FILE
if (asn->as_debug) {
(void)fprintf(asn->as_debug, ">> !q\n");
(void)fclose(asn->as_debug);
}
#endif /* AS_DEBUG_FILE */
free(asn);
}

42
contrib/traceroute/as.h Normal file
View File

@ -0,0 +1,42 @@
/* $FreeBSD$ */
/* $NetBSD: as.h,v 1.1 2001/11/04 23:14:36 atatat Exp $ */
/*
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Andrew Brown.
*
* 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 NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
void *as_setup __P((char *));
int as_lookup __P((void *, struct in_addr *));
void as_shutdown __P((void *));

View File

@ -16,7 +16,7 @@
.\" $Id: traceroute.8,v 1.19 2000/09/21 08:44:19 leres Exp $
.\" $FreeBSD$
.\"
.TH TRACEROUTE 8 "21 September 2000"
.TH TRACEROUTE 8 "19 February 2008"
.UC 6
.SH NAME
traceroute \- print the route packets take to network host
@ -24,7 +24,7 @@ traceroute \- print the route packets take to network host
.na
.B traceroute
[
.B \-dDeFISnrvx
.B \-adDeFISnrvx
] [
.B \-f
.I first_ttl
@ -71,6 +71,9 @@ traceroute \- print the route packets take to network host
.B \-w
.I waittime
] [
.B \-A
.I as_server
] [
.B \-z
.I pausemsecs
]
@ -98,6 +101,13 @@ name.
.PP
Other options are:
.TP
.B \-a
Turn on AS# lookups for each hop encountered.
.TP
.B -A
Turn on AS# lookups and use the given server instead of the
default.
.TP
.B \-e
Firewall evasion mode.
Use fixed destination ports for UDP and TCP probes.
@ -443,3 +453,7 @@ should listen for a RST from the destination host (or an intermediate
router that's filtering packets), but this is not implemented yet.
.PP
Please send bug reports to traceroute@ee.lbl.gov.
.PP
The AS number capability reports information that may sometimes be
inaccurate due to discrepancies between the contents of the
routing database server and the current state of the Internet.

View File

@ -263,6 +263,7 @@ static const char rcsid[] =
#include "findsaddr.h"
#include "ifaddrlist.h"
#include "as.h"
#include "traceroute.h"
/* Maximum number of gateways (include room for one noop) */
@ -350,6 +351,9 @@ int options; /* socket options */
int verbose;
int waittime = 5; /* time to wait for response (in seconds) */
int nflag; /* print addresses numerically */
int as_path; /* print as numbers for each hop */
char *as_server = NULL;
void *asn;
#ifdef CANT_HACK_IPCKSUM
int doipcksum = 0; /* don't calculate ip checksums by default */
#else
@ -535,9 +539,17 @@ main(int argc, char **argv)
prog = argv[0];
opterr = 0;
while ((op = getopt(argc, argv, "edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF)
switch (op) {
case 'a':
as_path = 1;
break;
case 'A':
as_path = 1;
as_server = optarg;
break;
case 'd':
options |= SO_DEBUG;
break;
@ -913,6 +925,16 @@ main(int argc, char **argv)
exit (1);
}
if (as_path) {
asn = as_setup(as_server);
if (asn == NULL) {
Fprintf(stderr, "%s: as_setup failed, AS# lookups"
" disabled\n", prog);
(void)fflush(stderr);
as_path = 0;
}
}
#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
if (setpolicy(sndsock, "in bypass") < 0)
errx(1, "%s", ipsec_strerror());
@ -1118,6 +1140,8 @@ main(int argc, char **argv)
(unreachable > 0 && unreachable >= nprobes - 1))
break;
}
if (as_path)
as_shutdown(asn);
exit(0);
}
@ -1458,6 +1482,9 @@ print(register u_char *buf, register int cc, register struct sockaddr_in *from)
hlen = ip->ip_hl << 2;
cc -= hlen;
if (as_path)
Printf(" [AS%d]", as_lookup(asn, &from->sin_addr));
if (nflag)
Printf(" %s", inet_ntoa(from->sin_addr));
else
@ -1764,8 +1791,8 @@ usage(void)
Fprintf(stderr, "Version %s\n", version);
Fprintf(stderr,
"Usage: %s [-dDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n"
"Usage: %s [-adDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n"
"\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n"
"\t[-t tos] [-w waittime] [-z pausemsecs] host [packetlen]\n", prog);
"\t[-t tos] [-w waittime] [-A as_server] [-z pausemsecs] host [packetlen]\n", prog);
exit(1);
}

View File

@ -5,7 +5,7 @@ TRACEROUTE_DISTDIR?= ${.CURDIR}/../../contrib/traceroute
PROG= traceroute
MAN= traceroute.8
SRCS= version.c traceroute.c ifaddrlist.c findsaddr-socket.c
SRCS= as.c version.c traceroute.c ifaddrlist.c findsaddr-socket.c
BINOWN= root
BINMODE=4555
CLEANFILES= version.c