bin/133227: Add support for SLD whois server lookups and IPv6
address lookups
Aragon Gouveia
aragon at phat.za.net
Mon Mar 30 16:00:10 PDT 2009
>Number: 133227
>Category: bin
>Synopsis: Add support for SLD whois server lookups and IPv6 address lookups
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Mon Mar 30 23:00:09 UTC 2009
>Closed-Date:
>Last-Modified:
>Originator: Aragon Gouveia
>Release: 7.1-STABLE
>Organization:
>Environment:
FreeBSD igor.geek.sh 7.1-STABLE FreeBSD 7.1-STABLE #3: Wed Mar 11 14:24:50 SAST 2009 root at igor.geek.sh:/usr/src/sys/amd64/compile/IGOR amd64
>Description:
When performing a domain name whois lookup, whois(1) performs a DNS lookup on <tld>.whois-servers.net to discover the authoritative whois server address. This does not cater for some TLD registries that do not operate a TLD whois server, but operate one or many SLD whois servers below said TLD. For example:
domain test.co.za
$ host za.whois-servers.net
Host za.whois-servers.net not found: 3(NXDOMAIN)
$ host co.za.whois-servers.net
co.za.whois-servers.net is an alias for whois.coza.net.za.
$ whois test.co.za
whois: za.whois-servers.net: hostname nor servname provided, or not known
The attached patch resolves this by first attempting to resolve co.za.whois-servers.net and using it if it resolves. If not found, it will attempt za.whois-servers.net as normal.
In addition I have also integrated PR bin/128725 into my patch so that whois treats IPv6 address lookups the same as IPv4 addresses (sending the query to ARIN's whois server).
>How-To-Repeat:
>Fix:
Patch attached with submission follows:
--- whois.c.orig 2007-04-14 16:32:48.000000000 +0200
+++ whois.c 2009-03-31 00:42:33.000000000 +0200
@@ -91,7 +91,7 @@
FNICHOST, NULL };
const char *port = DEFAULT_PORT;
-static char *choose_server(char *);
+static struct addrinfo *choose_hostinfo(const char *domain, char const **hostname);
static struct addrinfo *gethostinfo(char const *host, int exit_on_error);
static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3);
static void usage(void);
@@ -187,7 +187,6 @@
*/
if (host == NULL && country == NULL) {
use_qnichost = 1;
- host = NICHOST;
if (!(flags & WHOIS_QUICK))
flags |= WHOIS_RECURSE;
}
@@ -195,29 +194,41 @@
if (country != NULL) {
s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL);
whois(*argv, qnichost, flags);
- } else if (use_qnichost)
- if ((qnichost = choose_server(*argv)) != NULL)
- whois(*argv, qnichost, flags);
- if (qnichost == NULL)
+ free(qnichost);
+ qnichost = NULL;
+ } else if (use_qnichost) {
+ whois(*argv, NULL, flags);
+ } else {
whois(*argv, host, flags);
- free(qnichost);
- qnichost = NULL;
+ }
argv++;
}
exit(0);
}
/*
- * This function will remove any trailing periods from domain, after which it
- * returns a pointer to newly allocated memory containing the whois server to
- * be queried, or a NULL if the correct server couldn't be determined. The
- * caller must remember to free(3) the allocated memory.
+ * This function takes the trailing subdomains of a domain
+ * prepends them to .whois-servers.net and attempts to resolve
+ * them. Starting from the highest it removes more subdomain
+ * parts until a successful resolution is found, or exits
+ * if none are found.
+ *
+ * However, before doing so it checks if we're doing a NORID,
+ * IP address, or non-hostname lookup. If so, it resolves
+ * the relevant hostname.
*/
-static char *
-choose_server(char *domain)
+static struct addrinfo *
+choose_hostinfo(const char *domain, char const **hostname)
{
- char *pos, *retval;
+ char *pos, *last, *lookup;
+ struct addrinfo *res;
+ if (strchr(domain, ':')) {
+ s_asprintf(&lookup, "%s", ANICHOST);
+ res = gethostinfo(lookup, 1);
+ *hostname = lookup;
+ return res;
+ }
for (pos = strchr(domain, '\0'); pos > domain && *--pos == '.';)
*pos = '\0';
if (*domain == '\0')
@@ -225,18 +236,35 @@
if (strlen(domain) > sizeof("-NORID")-1 &&
strcasecmp(domain + strlen(domain) - sizeof("-NORID") + 1,
"-NORID") == 0) {
- s_asprintf(&retval, "%s", NORIDHOST);
- return (retval);
+ s_asprintf(&lookup, "%s", NORIDHOST);
+ res = gethostinfo(lookup, 1);
+ *hostname = lookup;
+ return res;
}
- while (pos > domain && *pos != '.')
- --pos;
- if (pos <= domain)
- return (NULL);
- if (isdigit((unsigned char)*++pos))
- s_asprintf(&retval, "%s", ANICHOST);
- else
- s_asprintf(&retval, "%s%s", pos, QNICHOST_TAIL);
- return (retval);
+ if (!(last = strrchr(domain, '.'))) {
+ s_asprintf(&lookup, "%s", NICHOST);
+ res = gethostinfo(lookup, 1);
+ *hostname = lookup;
+ return res;
+ }
+ pos = last+1;
+ if (isdigit((unsigned char)*pos)) {
+ s_asprintf(&lookup, "%s", ANICHOST);
+ res = gethostinfo(lookup, 1);
+ *hostname = lookup;
+ return res;
+ }
+ while (pos = strchr(domain, '.')) {
+ domain = ++pos;
+ s_asprintf(&lookup, "%s%s", pos, QNICHOST_TAIL);
+ res = gethostinfo(lookup, pos>last?1:0);
+ if (res) {
+ *hostname = lookup;
+ break;
+ } else
+ free(lookup);
+ }
+ return res;
}
static struct addrinfo *
@@ -251,9 +279,10 @@
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host, port, &hints, &res);
if (error) {
- warnx("%s: %s", host, gai_strerror(error));
- if (exit_on_error)
+ if (exit_on_error) {
+ warnx("%s: %s", host, gai_strerror(error));
exit(EX_NOHOST);
+ }
return (NULL);
}
return (res);
@@ -280,12 +309,17 @@
{
FILE *sfi, *sfo;
struct addrinfo *hostres, *res;
- char *buf, *host, *nhost, *p;
+ char *fhost, *buf, *host, *nhost, *p;
int i, s;
size_t c, len;
s = -1;
- hostres = gethostinfo(hostname, 1);
+ fhost = NULL;
+ if (hostname == NULL) {
+ hostres = choose_hostinfo(query, &hostname);
+ fhost = (char *)hostname;
+ } else
+ hostres = gethostinfo(hostname, 1);
for (res = hostres; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0)
@@ -353,6 +387,7 @@
}
}
}
+ if (fhost) free(fhost);
if (nhost != NULL) {
whois(query, nhost, 0);
free(nhost);
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list