From owner-freebsd-bugs@FreeBSD.ORG Mon Mar 30 23:00:09 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B38FD1065670 for ; Mon, 30 Mar 2009 23:00:09 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 8E7AF8FC16 for ; Mon, 30 Mar 2009 23:00:09 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n2UN09aS019586 for ; Mon, 30 Mar 2009 23:00:09 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n2UN09PK019585; Mon, 30 Mar 2009 23:00:09 GMT (envelope-from gnats) Resent-Date: Mon, 30 Mar 2009 23:00:09 GMT Resent-Message-Id: <200903302300.n2UN09PK019585@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Aragon Gouveia Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8A1081065670 for ; Mon, 30 Mar 2009 22:56:35 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 777F68FC16 for ; Mon, 30 Mar 2009 22:56:35 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n2UMuYOb034598 for ; Mon, 30 Mar 2009 22:56:34 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id n2UMuYcs034597; Mon, 30 Mar 2009 22:56:34 GMT (envelope-from nobody) Message-Id: <200903302256.n2UMuYcs034597@www.freebsd.org> Date: Mon, 30 Mar 2009 22:56:34 GMT From: Aragon Gouveia To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: bin/133227: Add support for SLD whois server lookups and IPv6 address lookups X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 Mar 2009 23:00:10 -0000 >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@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 .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: