diff options
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/whois/whois.1 | 106 | ||||
-rw-r--r-- | usr.bin/whois/whois.c | 222 |
2 files changed, 139 insertions, 189 deletions
diff --git a/usr.bin/whois/whois.1 b/usr.bin/whois/whois.1 index bcc770c..0b74cc5 100644 --- a/usr.bin/whois/whois.1 +++ b/usr.bin/whois/whois.1 @@ -28,7 +28,7 @@ .\" From: @(#)whois.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd January 22, 2016 +.Dd January 23, 2016 .Dt WHOIS 1 .Os .Sh NAME @@ -49,31 +49,22 @@ Network Information Centers .Pp By default .Nm -automatically discovers the name of a whois server to use -from the top-level domain -.Pq Tn TLD -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. +starts by querying the Internet Assigned Numbers Authority (IANA) whois server, +and follows referrals to whois servers +that have more specific details about the query +.Ar name . +The IANA whois server knows about +IP address and AS numbers +as well as domain names. .Pp -If an IP address or AS number is specified, -the whois server will default to -the American Registry for Internet Numbers -.Pq Tn ARIN . -.Pp -If +There are a few special cases where referrals do not work, so .Nm -cannot automatically discover a server, -it will fall back to -the host specified in the -.Ev WHOIS_SERVER -or -.Ev RA_SERVER -environment variables, or if those are not set, it will use -.Pa whois.crsnic.net . +goes directly to the appropriate server. +These include point-of-contact handles for ARIN, +.Pa nic.at , +NORID, and RIPE, +and domain names under +.Pa ac.uk . .Pp The options are as follows: .Bl -tag -width indent @@ -85,17 +76,16 @@ It contains network numbers used in those parts of the world covered neither by .Tn APNIC , AfriNIC , LACNIC , nor by .Tn RIPE . -.Pp -(Hint: All point of contact handles in the -.Tn ARIN -whois database end with -.Qq Li -ARIN . ) +The query syntax is documented at +.Pa https://www.arin.net/resources/whoisrws/whois_api.html#nicname .It Fl A 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. +Get query syntax documentation using +.Ic whois -A help .It Fl b Use the Network Abuse Clearinghouse database. It contains addresses to which network abuse should be reported, @@ -111,6 +101,8 @@ Use the African Network Information Centre database. It contains network numbers used in Africa and the islands of the western Indian Ocean. +Get query syntax documentation using +.Ic whois -f help .It Fl g Use the US non-military federal government database, which contains points of contact for subdomains of @@ -119,14 +111,28 @@ contact for subdomains of 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 -.Pq Pa whois.networksolutions.com +Use the traditional Network Information Center (InterNIC) +.Pq Pa whois.internic.net database. +This now contains only registrations for domain names under +.Pa .COM , +.Pa .NET , +.Pa .EDU . +You can specify the type of object to search for like +.Ic whois -i ' Ns Ar type Ar name Ns Ic ' +where +.Ar type +can be +.Nm domain , nameserver , registrar . +The +.Ar name +can contain +.Li * +wildcards. .It Fl I Use the Internet Assigned Numbers Authority .Pq Tn IANA database. -It contains network information for top-level domains. .It Fl k Use the National Internet Development Agency of Korea's .Pq Tn KRNIC @@ -160,7 +166,7 @@ Do a quick lookup; .Nm will not attempt to follow referrals to other whois servers. This is the default if a server is explicitly specified -using one of the other options. +using one of the other options or in an environment variable. See also the .Fl R option. @@ -170,6 +176,8 @@ Use the R\(aaeseaux IP Europ\(aaeens database. It contains network numbers and domain contact information for Europe. +Get query syntax documentation using +.Ic whois -r help .It Fl R Do a recursive lookup; .Nm @@ -179,19 +187,16 @@ See also the .Fl Q option. .It Fl S -By default, if the whois server is -.Pa whois.verisign-grs.com -(or a CNAME alias pointing at that name) -then +By default .Nm -will query for -.Dl domain Ar name -The +adjusts simple queries (without spaces) to produce more useful output +from certain whois servers, +and it suppresses some uninformative output. +With the .Fl S -option suppresses this behaviour, -allowing you to make a loose-matching query, -or query for host objects using the syntax -.Dl nameserver Ar name +option, +.Nm +sends the query and prints the output verbatim. .El .Pp The operands specified to @@ -212,22 +217,11 @@ The secondary default whois server. If this is unset, .Nm will use -.Pa whois.crsnic.net . +.Pa whois.iana.org . .El .Sh EXIT STATUS .Ex -std .Sh EXAMPLES -Most types of data, such as domain names and -.Tn IP -addresses, can be used as arguments to -.Nm -without any options, and -.Nm -will choose the correct whois server to query. -Some exceptions, where -.Nm -will not be able to handle data correctly, are detailed below. -.Pp To obtain contact information about an administrator located in the Russian .Tn TLD diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c index 6be6c40..e7bf94f 100644 --- a/usr.bin/whois/whois.c +++ b/usr.bin/whois/whois.c @@ -61,31 +61,35 @@ __FBSDID("$FreeBSD$"); #define ABUSEHOST "whois.abuse.net" #define ANICHOST "whois.arin.net" -#define BNICHOST "whois.registro.br" +#define DENICHOST "de" QNICHOST_TAIL #define FNICHOST "whois.afrinic.net" -#define GERMNICHOST "de" QNICHOST_TAIL #define GNICHOST "whois.nic.gov" #define IANAHOST "whois.iana.org" -#define INICHOST "whois.networksolutions.com" +#define INICHOST "whois.internic.net" #define KNICHOST "whois.krnic.net" #define LNICHOST "whois.lacnic.net" #define MNICHOST "whois.ra.net" -#define NICHOST "whois.crsnic.net" #define PDBHOST "whois.peeringdb.com" #define PNICHOST "whois.apnic.net" -#define QNICHOST_HEAD "whois.nic." #define QNICHOST_TAIL ".whois-servers.net" #define RNICHOST "whois.ripe.net" #define VNICHOST "whois.verisign-grs.com" #define DEFAULT_PORT "whois" -#define WHOIS_RECURSE 0x01 -#define WHOIS_QUICK 0x02 -#define WHOIS_SPAM_ME 0x04 +#define WHOIS_RECURSE 0x01 +#define WHOIS_QUICK 0x02 +#define WHOIS_SPAM_ME 0x04 + +#define CHOPSPAM ">>> Last update of WHOIS database:" #define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') +#define SCAN(p, end, check) \ + while ((p) < (end)) \ + if (check) ++(p); \ + else break + static struct { const char *suffix, *server; } whoiswhere[] = { @@ -96,7 +100,8 @@ static struct { { "-RIPE", RNICHOST }, /* Nominet's whois server doesn't return referrals to JANET */ { ".ac.uk", "ac.uk" QNICHOST_TAIL }, - { NULL, NULL } + { "", IANAHOST }, /* default */ + { NULL, NULL } /* safety belt */ }; #define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 } @@ -104,18 +109,16 @@ static struct { const char *prefix; size_t len; } whois_referral[] = { - WHOIS_REFERRAL("Whois Server: "), - WHOIS_REFERRAL("WHOIS Server: "), - WHOIS_REFERRAL(" Whois Server: "), - WHOIS_REFERRAL("refer: "), - WHOIS_REFERRAL("Registrant Street1:Whois Server:"), - WHOIS_REFERRAL("ReferralServer: whois://"), + WHOIS_REFERRAL("whois:"), /* IANA */ + WHOIS_REFERRAL("Whois Server:"), + WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */ + WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */ { NULL, 0 } }; static const char *port = DEFAULT_PORT; -static char *choose_server(char *); +static const char *choose_server(char *); 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); @@ -125,15 +128,14 @@ int main(int argc, char *argv[]) { const char *country, *host; - char *qnichost; - int ch, flags, use_qnichost; + int ch, flags; #ifdef SOCKS SOCKSinit(argv[0]); #endif - country = host = qnichost = NULL; - flags = use_qnichost = 0; + country = host = NULL; + flags = 0; while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) { switch (ch) { case 'a': @@ -203,103 +205,43 @@ main(int argc, char *argv[]) usage(); /* - * If no host or country is specified, try to determine the top - * level domain from the query, or fall back to NICHOST. + * If no host or country is specified, rely on referrals from IANA. */ if (host == NULL && country == NULL) { if ((host = getenv("WHOIS_SERVER")) == NULL && (host = getenv("RA_SERVER")) == NULL) { - use_qnichost = 1; - host = NICHOST; if (!(flags & WHOIS_QUICK)) flags |= WHOIS_RECURSE; } } while (argc-- > 0) { if (country != NULL) { + char *qnichost; 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) - whois(*argv, host, flags); - free(qnichost); - qnichost = NULL; + free(qnichost); + } else + whois(*argv, host != NULL ? host : + choose_server(*argv), flags); 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. - * - * 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 try a couple of - * formulaic server names. Fail if the domain does not contain '.'. - */ -static char * +static const char * choose_server(char *domain) { - char *pos, *retval; + size_t len = strlen(domain); int i; - struct addrinfo *res; - if (strchr(domain, ':')) { - s_asprintf(&retval, "%s", ANICHOST); - return (retval); - } - if (strncasecmp(domain, "AS", 2) == 0) { - size_t len = strspn(domain + 2, "0123456789"); - if (domain[len + 2] == '\0') { - s_asprintf(&retval, "%s", ANICHOST); - return (retval); - } - } - for (pos = strchr(domain, '\0'); pos > domain && pos[-1] == '.';) - *--pos = '\0'; - if (*domain == '\0') - errx(EX_USAGE, "can't search for a null string"); for (i = 0; whoiswhere[i].suffix != NULL; i++) { size_t suffix_len = strlen(whoiswhere[i].suffix); - if (domain + suffix_len < pos && - strcasecmp(pos - suffix_len, whoiswhere[i].suffix) == 0) { - s_asprintf(&retval, "%s", whoiswhere[i].server); - return (retval); - } - } - while (pos > domain && *pos != '.') - --pos; - if (pos <= domain) - return (NULL); - if (isdigit((unsigned char)*++pos)) { - s_asprintf(&retval, "%s", ANICHOST); - 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; - } + if (len > suffix_len && + strcasecmp(domain + len - suffix_len, + whoiswhere[i].suffix) == 0) + return (whoiswhere[i].server); } + errx(EX_SOFTWARE, "no default whois server"); } static struct addrinfo * @@ -341,7 +283,7 @@ whois(const char *query, const char *hostname, int flags) FILE *fp; struct addrinfo *hostres, *res; char *buf, *host, *nhost, *p; - int s = -1, f, antispam; + int s = -1, f; nfds_t i, j; size_t len, count; struct pollfd *fds; @@ -350,10 +292,6 @@ whois(const char *query, const char *hostname, int flags) hostres = gethostinfo(hostname, 1); for (res = hostres, count = 0; res; res = res->ai_next) count++; - - antispam = (flags & WHOIS_SPAM_ME) == 0 && - strcmp(hostres->ai_canonname, VNICHOST) == 0; - fds = calloc(count, sizeof(*fds)); if (fds == NULL) err(EX_OSERR, "calloc()"); @@ -420,8 +358,8 @@ whois(const char *query, const char *hostname, int flags) break; } else if (n < 0) { /* - * errno here can only be EINTR which we would want - * to clean up and bail out. + * errno here can only be EINTR which we would + * want to clean up and bail out. */ s = -1; goto done; @@ -455,66 +393,84 @@ whois(const char *query, const char *hostname, int flags) s = -1; if (count == 0) errno = ETIMEDOUT; - done: + if (s == -1) + err(EX_OSERR, "connect()"); + /* Close all watched fds except the succeeded one */ for (j = 0; j < i; j++) if (fds[j].fd != s && fds[j].fd != -1) close(fds[j].fd); - - if (s != -1) { - /* Restore default blocking behavior. */ - if ((f = fcntl(s, F_GETFL)) != -1) { - f &= ~O_NONBLOCK; - if (fcntl(s, F_SETFL, f) == -1) - err(EX_OSERR, "fcntl()"); - } else - err(EX_OSERR, "fcntl()"); - } - free(fds); - freeaddrinfo(hostres); - if (s == -1) - err(EX_OSERR, "connect()"); + + /* Restore default blocking behavior. */ + if ((f = fcntl(s, F_GETFL)) == -1) + err(EX_OSERR, "fcntl()"); + f &= ~O_NONBLOCK; + if (fcntl(s, F_SETFL, f) == -1) + err(EX_OSERR, "fcntl()"); fp = fdopen(s, "r+"); if (fp == NULL) err(EX_OSERR, "fdopen()"); - if (strcmp(hostname, GERMNICHOST) == 0) { + + if (!(flags & WHOIS_SPAM_ME) && + strcmp(hostname, DENICHOST) == 0) fprintf(fp, "-T dn,ace -C ISO-8859-1 %s\r\n", query); - } else if (strcmp(hostname, "dk" QNICHOST_TAIL) == 0) { + else if (!(flags & WHOIS_SPAM_ME) && + strcmp(hostname, "dk" QNICHOST_TAIL) == 0) fprintf(fp, "--show-handles %s\r\n", query); - } else if (antispam) { + else if ((flags & WHOIS_SPAM_ME) || + strchr(query, ' ') != NULL) + fprintf(fp, "%s\r\n", query); + else if (strcmp(hostname, ANICHOST) == 0) + fprintf(fp, "+ %s\r\n", query); + else if (strcmp(hostres->ai_canonname, VNICHOST) == 0) fprintf(fp, "domain %s\r\n", query); - } else { + else fprintf(fp, "%s\r\n", query); - } fflush(fp); + nhost = NULL; while ((buf = fgetln(fp, &len)) != NULL) { - while (len > 0 && isspace((unsigned char)buf[len - 1])) - buf[--len] = '\0'; - printf("%.*s\n", (int)len, buf); + /* Nominet */ + if (!(flags & WHOIS_SPAM_ME) && + len == 5 && strncmp(buf, "-- \r\n", 5) == 0) + break; + + printf("%.*s", (int)len, buf); if ((flags & WHOIS_RECURSE) && nhost == NULL) { for (i = 0; whois_referral[i].prefix != NULL; i++) { - if (strncmp(buf, - whois_referral[i].prefix, - whois_referral[i].len) != 0) + p = buf; + SCAN(p, buf+len, *p == ' '); + if (strncasecmp(p, whois_referral[i].prefix, + whois_referral[i].len) != 0) continue; - host = buf + whois_referral[i].len; - for (p = host; p < buf + len; p++) - if (!ishost(*p)) - break; - s_asprintf(&nhost, "%.*s", - (int)(p - host), host); + p += whois_referral[i].len; + SCAN(p, buf+len, *p == ' '); + host = p; + SCAN(p, buf+len, ishost(*p)); + /* avoid loops */ + if (strncmp(hostname, host, p - host) != 0) + s_asprintf(&nhost, "%.*s", + (int)(p - host), host); break; } } + /* Verisign etc. */ + if (!(flags & WHOIS_SPAM_ME) && + len >= sizeof(CHOPSPAM)-1 && + (strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 || + strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) { + printf("\n"); + break; + } } fclose(fp); + freeaddrinfo(hostres); if (nhost != NULL) { - whois(query, nhost, 0); + whois(query, nhost, flags); free(nhost); } } |