From 3620b449a5f2cf74b4273b124c210529932a3ebd Mon Sep 17 00:00:00 2001 From: ache Date: Wed, 17 Nov 1999 19:11:51 +0000 Subject: Merge with OpenBSD whois (with bugfixes missed there) New features are: Automatic lookup using *.whois-servers.net Recursive lookup using Registrar's name Fallback to InterNIC for non-domains -m for RADB database -Q to turn recursion/fallback off Obtained from: OpenBSD --- usr.bin/whois/Makefile | 2 + usr.bin/whois/whois.1 | 28 ++++++-- usr.bin/whois/whois.c | 181 +++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 173 insertions(+), 38 deletions(-) diff --git a/usr.bin/whois/Makefile b/usr.bin/whois/Makefile index 3b6e7aa..299c963 100644 --- a/usr.bin/whois/Makefile +++ b/usr.bin/whois/Makefile @@ -1,7 +1,9 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 +# $FreeBSD$ PROG= whois +CFLAGS+=-Wall .if defined(SOCKS) CFLAGS+=-DSOCKS CFLAGS+=-Dconnect=Rconnect -Dgetsockname=Rgetsockname -Dlisten=Rlisten \ diff --git a/usr.bin/whois/whois.1 b/usr.bin/whois/whois.1 index a083496..4dd0184 100644 --- a/usr.bin/whois/whois.1 +++ b/usr.bin/whois/whois.1 @@ -32,7 +32,7 @@ .\" From: @(#)whois.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd February 1, 1999 +.Dd November 17, 1999 .Dt WHOIS 1 .Os BSD 4.3 .Sh NAME @@ -40,7 +40,7 @@ .Nd Internet domain name and network number directory service .Sh SYNOPSIS .Nm whois -.Op Fl adgiprR +.Op Fl adgimpQrR .Op Fl h Ar host .Ar name ... .Sh DESCRIPTION @@ -67,9 +67,18 @@ Use the US non-military federal government database, which contains points of contact for subdomains of .Tn \&.GOV . .It Fl h Ar host -Use the specified host instead of the default NIC -(whois.crsnic.net). +Use the specified host instead of the default variant. Either a host name or an IP address may be specified. +.Pp +By default +.Nm +construct the name of a whois server to use from the top-level domain +.Pq Tn TLD +of the supplied (single) argument, and appending ".whois-servers.net". +This effectively allows a suitable whois server to be selected +automatically for a large number of TLDs. +If no required whois-servers.net subdomain found, fallback +to whois.crsnic.net provided. .It Fl i Use the Network Solutions Registry for Internet Numbers .Pq Tn InterNIC @@ -81,11 +90,22 @@ for most of and .Tn \&.EDU domains. +.It Fl m +Use the Route Arbiter Database +.Pq Tn RADB +database. It contains route policy specifications for a large +number of operators' networks. .It Fl p Use the Asia/Pacific Network Information Center .Pq Tn APNIC database. It contains network numbers used in East Asia, Australia, New Zealand, and the Pacific islands. +.It Fl Q +Do a quick lookup. This means that +.Nm +will not attempt to lookup the name in the authoratative whois +server (if one is listed) nor will it contact InterNic if a lookup +fails. This flag has no effect when combined with any other flag. .It Fl r Use the R\(aaeseaux IP Europ\(aaeens .Pq Tn RIPE diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c index 5f33246..c6efe5c 100644 --- a/usr.bin/whois/whois.c +++ b/usr.bin/whois/whois.c @@ -52,41 +52,52 @@ static const char rcsid[] = #include #include #include +#include #include #include #include -#define NICHOST "whois.crsnic.net" -#define INICHOST "whois.internic.net" +#define NICHOST "whois.crsnic.net" +#define INICHOST "whois.internic.net" #define DNICHOST "whois.nic.mil" #define GNICHOST "whois.nic.gov" #define ANICHOST "whois.arin.net" #define RNICHOST "whois.ripe.net" #define PNICHOST "whois.apnic.net" -#define RUNICHOST "whois.ripn.net" +#define RUNICHOST "whois.ripn.net" +#define MNICHOST "whois.ra.net" +#define QNICHOST_TAIL ".whois-servers.net" #define WHOIS_PORT 43 +#define WHOIS_RECURSE 0x01 +#define WHOIS_INIC_FALLBACK 0x02 +#define WHOIS_QUICK 0x04 + static void usage __P((void)); +static void whois __P((char *, struct sockaddr_in *, int)); int main(argc, argv) int argc; char **argv; { - register FILE *sfi, *sfo; - register int ch; - struct sockaddr_in sin; - struct hostent *hp; - struct servent *sp; - int s; + int ch, i, j; + int use_qnichost, flags; char *host; + char *qnichost; + struct servent *sp; + struct hostent *hp; + struct sockaddr_in sin; #ifdef SOCKS SOCKSinit(argv[0]); #endif - host = NICHOST; - while ((ch = getopt(argc, argv, "adgh:iprR")) != -1) + host = NULL; + qnichost = NULL; + flags = 0; + use_qnichost = 0; + while ((ch = getopt(argc, argv, "adgh:impQrR")) != -1) switch((char)ch) { case 'a': host = ANICHOST; @@ -103,9 +114,15 @@ main(argc, argv) case 'i': host = INICHOST; break; + case 'm': + host = MNICHOST; + break; case 'p': host = PNICHOST; break; + case 'Q': + flags |= WHOIS_QUICK; + break; case 'r': host = RNICHOST; break; @@ -122,47 +139,143 @@ main(argc, argv) if (!argc) usage(); - s = socket(PF_INET, SOCK_STREAM, 0); - if (s < 0) - err(EX_OSERR, "socket"); - - memset(&sin, 0, sizeof sin); - sin.sin_len = sizeof sin; + memset(&sin, 0, sizeof(sin)); + sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; - - if (inet_aton(host, &sin.sin_addr) == 0) { - hp = gethostbyname2(host, AF_INET); - if (hp == NULL) - errx(EX_NOHOST, "%s: %s", host, hstrerror(h_errno)); - host = hp->h_name; - sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; - } - sp = getservbyname("whois", "tcp"); if (sp == NULL) sin.sin_port = htons(WHOIS_PORT); else sin.sin_port = sp->s_port; - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) + /* + * If no nic host is specified, use whois-servers.net + * if there is a '.' in the name, else fall back to NICHOST. + */ + if (host == NULL) { + use_qnichost = 1; + host = NICHOST; + if (!(flags & WHOIS_QUICK)) + flags |= WHOIS_INIC_FALLBACK | WHOIS_RECURSE; + } + while (argc--) { + if (use_qnichost) { + if (qnichost) { + free(qnichost); + qnichost = NULL; + } + for (i = j = 0; (*argv)[i]; i++) + if ((*argv)[i] == '.') + j = i; + if (j != 0) { + qnichost = (char *) calloc(i - j + 1 + + strlen(QNICHOST_TAIL), sizeof(char)); + if (!qnichost) + err(1, "calloc"); + strcpy(qnichost, *argv + j + 1); + strcat(qnichost, QNICHOST_TAIL); + + if (inet_aton(qnichost, &sin.sin_addr) == 0) { + hp = gethostbyname2(qnichost, AF_INET); + if (hp == NULL) { + free(qnichost); + qnichost = NULL; + } else { + sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; + } + } + } + } + if (!qnichost && inet_aton(host, &sin.sin_addr) == 0) { + hp = gethostbyname2(host, AF_INET); + if (hp == NULL) + errx(EX_NOHOST, "%s: %s", host, + hstrerror(h_errno)); + host = hp->h_name; + sin.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; + } + + whois(*argv++, &sin, flags); + } + exit(0); +} + +static void +whois(name, sinp, flags) + char *name; + struct sockaddr_in *sinp; + int flags; +{ + FILE *sfi, *sfo; + char *buf, *p, *nhost; + size_t len; + int s, nomatch; + + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) + err(EX_OSERR, "socket"); + + if (connect(s, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) err(EX_OSERR, "connect"); sfi = fdopen(s, "r"); sfo = fdopen(s, "w"); if (sfi == NULL || sfo == NULL) err(EX_OSERR, "fdopen"); - while (argc-- > 1) - (void)fprintf(sfo, "%s ", *argv++); - (void)fprintf(sfo, "%s\r\n", *argv); + (void)fprintf(sfo, "%s\r\n", name); (void)fflush(sfo); - while ((ch = getc(sfi)) != EOF) - putchar(ch); - exit(0); + nhost = NULL; + nomatch = 0; + while ((buf = fgetln(sfi, &len))) { + if (buf[len - 2] == '\r') + buf[len - 2] = '\0'; + else + buf[len - 1] = '\0'; + + if ((flags & WHOIS_RECURSE) && !nhost && + (p = strstr(buf, "Whois Server: "))) { + p += sizeof("Whois Server: ") - 1; + if ((len = strcspn(p, " \t\n\r"))) { + if ((nhost = malloc(len + 1)) == NULL) + err(1, "malloc"); + memcpy(nhost, p, len); + nhost[len] = '\0'; + } + } + if ((flags & WHOIS_INIC_FALLBACK) && !nhost && !nomatch && + (p = strstr(buf, "No match for \""))) { + p += sizeof("No match for \"") - 1; + if ((len = strcspn(p, "\"")) && + name[len] == '\0' && + strncasecmp(name, p, len) == 0 && + strchr(name, '.') == NULL) + nomatch = 1; + } + (void)puts(buf); + } + + /* Do second lookup as needed */ + if (nomatch && !nhost) { + (void)printf("Looking up %s at %s.\n\n", name, INICHOST); + nhost = INICHOST; + } + if (nhost) { + if (inet_aton(nhost, &sinp->sin_addr) == 0) { + struct hostent *hp = gethostbyname2(nhost, AF_INET); + if (hp == NULL) + return; + sinp->sin_addr = *(struct in_addr *)hp->h_addr_list[0]; + } + if (!nomatch) + free(nhost); + whois(name, sinp, 0); + } } static void usage() { - fprintf(stderr, "usage: whois [-adgiprR] [-h hostname] name ...\n"); + (void)fprintf(stderr, + "usage: whois [-adgimpQrR] [-h hostname] name ...\n"); exit(EX_USAGE); } -- cgit v1.1