summaryrefslogtreecommitdiff
path: root/usr.bin/whois
diff options
context:
space:
mode:
authorTony Finch <fanf@FreeBSD.org>2015-05-14 10:33:01 +0000
committerTony Finch <fanf@FreeBSD.org>2015-05-14 10:33:01 +0000
commit1326bf51e64bcd95dde12fe5ccfa6330f567bb73 (patch)
tree342b340314de571eac5ad23940240ae9f9eaeb7b /usr.bin/whois
parent0279f129c6be907095fc22cdf5c91bfc7e476285 (diff)
downloadsrc-test-1326bf51e64bcd95dde12fe5ccfa6330f567bb73.tar.gz
src-test-1326bf51e64bcd95dde12fe5ccfa6330f567bb73.zip
whois: try whois.nic.TLD if TLD.whois-servers.net does not exist
Based on an idea from OpenBSD.
Notes
Notes: svn path=/head/; revision=282887
Diffstat (limited to 'usr.bin/whois')
-rw-r--r--usr.bin/whois/whois.126
-rw-r--r--usr.bin/whois/whois.c47
2 files changed, 47 insertions, 26 deletions
diff --git a/usr.bin/whois/whois.1 b/usr.bin/whois/whois.1
index 54c71fce5f0d8..ca1ceb5b5dc65 100644
--- a/usr.bin/whois/whois.1
+++ b/usr.bin/whois/whois.1
@@ -49,17 +49,18 @@ Network Information Centers
.Pp
By default
.Nm
-constructs the name of a whois server to use from the top-level domain
+automatically discovers the name of a whois server to use
+from the top-level domain
.Pq Tn TLD
-of the supplied (single) argument, and appending
-.Qq Li .whois-servers.net .
-This effectively allows a suitable whois server to be selected
-automatically for a large number of
-.Tn TLDs .
+of the supplied (single) argument.
+It tries
+.Qq Va TLD Ns Li .whois-servers.net
+and
+.Qq Li whois.nic. Ns Va TLD
+and if neither host exists it falls back to its default server.
.Pp
-In the event that an IP
-address is specified, the whois server will default to the American
-Registry for Internet Numbers
+If an IP address is specified, the whois server will default to
+the American Registry for Internet Numbers
.Pq Tn ARIN .
If a query to
.Tn ARIN
@@ -71,9 +72,10 @@ that server will be queried also, provided that the
.Fl Q
option is not specified.
.Pp
-If the query is not a domain name or IP address,
+If
.Nm
-will fall back to
+cannot automatically discover a server,
+it will fall back to
the host specified in the
.Ev WHOIS_SERVER
or
@@ -122,7 +124,7 @@ Use the US non-military federal government database, which contains points of
contact for subdomains of
.Pa .GOV .
.It Fl h Ar host
-Use the specified host instead of the default variant.
+Use the specified host instead of the default.
Either a host name or an IP address may be specified.
.It Fl i
Use the obsolete Network Solutions Registry for Internet Numbers
diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c
index 9fe979cca2102..9fdd0070612df 100644
--- a/usr.bin/whois/whois.c
+++ b/usr.bin/whois/whois.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#define RNICHOST "whois.ripe.net"
#define PNICHOST "whois.apnic.net"
#define MNICHOST "whois.ra.net"
+#define QNICHOST_HEAD "whois.nic."
#define QNICHOST_TAIL ".whois-servers.net"
#define BNICHOST "whois.registro.br"
#define IANAHOST "whois.iana.org"
@@ -101,7 +102,7 @@ static const char *ip_whois[] = { LNICHOST, RNICHOST, PNICHOST, BNICHOST,
static const char *port = DEFAULT_PORT;
static char *choose_server(char *);
-static struct addrinfo *gethostinfo(char const *host, int exit_on_error);
+static struct addrinfo *gethostinfo(char const *host, int exitnoname);
static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3);
static void usage(void);
static void whois(const char *, const char *, int);
@@ -214,14 +215,15 @@ main(int argc, char *argv[])
* caller must remember to free(3) the allocated memory.
*
* If the domain is an IPv6 address or has a known suffix, that determines
- * the server, else if the TLD is a number, query ARIN, else use
- * TLD.whois-server.net. Fail if the domain does not contain '.'.
+ * the server, else if the TLD is a number, query ARIN, else try a couple of
+ * formulaic server names. Fail if the domain does not contain '.'.
*/
static char *
choose_server(char *domain)
{
char *pos, *retval;
int i;
+ struct addrinfo *res;
if (strchr(domain, ':')) {
s_asprintf(&retval, "%s", ANICHOST);
@@ -243,15 +245,35 @@ choose_server(char *domain)
--pos;
if (pos <= domain)
return (NULL);
- if (isdigit((unsigned char)*++pos))
+ if (isdigit((unsigned char)*++pos)) {
s_asprintf(&retval, "%s", ANICHOST);
- else
- s_asprintf(&retval, "%s%s", pos, QNICHOST_TAIL);
- return (retval);
+ return (retval);
+ }
+ /* Try possible alternative whois server name formulae. */
+ for (i = 0; ; ++i) {
+ switch (i) {
+ case 0:
+ s_asprintf(&retval, "%s%s", pos, QNICHOST_TAIL);
+ break;
+ case 1:
+ s_asprintf(&retval, "%s%s", QNICHOST_HEAD, pos);
+ break;
+ default:
+ return (NULL);
+ }
+ res = gethostinfo(retval, 0);
+ if (res) {
+ freeaddrinfo(res);
+ return (retval);
+ } else {
+ free(retval);
+ continue;
+ }
+ }
}
static struct addrinfo *
-gethostinfo(char const *host, int exit_on_error)
+gethostinfo(char const *host, int exit_on_noname)
{
struct addrinfo hints, *res;
int error;
@@ -260,13 +282,10 @@ gethostinfo(char const *host, int exit_on_error)
hints.ai_flags = 0;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
+ res = NULL;
error = getaddrinfo(host, port, &hints, &res);
- if (error) {
- warnx("%s: %s", host, gai_strerror(error));
- if (exit_on_error)
- exit(EX_NOHOST);
- return (NULL);
- }
+ if (error && (exit_on_noname || error != EAI_NONAME))
+ err(EX_NOHOST, "%s: %s", host, gai_strerror(error));
return (res);
}