whois: Handle referrals to rwhois servers.

PR:		243862
Submitted by:	ben@desync.com
Differential Revision:	https://reviews.freebsd.org/D25156
This commit is contained in:
Mark Johnston 2020-07-09 17:27:14 +00:00
parent f4f16af1d3
commit aa949e8ace

View File

@ -117,6 +117,7 @@ static struct {
WHOIS_REFERRAL("Whois Server:"), WHOIS_REFERRAL("Whois Server:"),
WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */ WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */
WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */ WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */
WHOIS_REFERRAL("ReferralServer: rwhois://"), /* ARIN */
WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */ WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */
{ NULL, 0 } { NULL, 0 }
}; };
@ -156,10 +157,10 @@ reset_rir(void) {
static const char *port = DEFAULT_PORT; static const char *port = DEFAULT_PORT;
static const char *choose_server(char *); static const char *choose_server(char *);
static struct addrinfo *gethostinfo(char const *host, int exitnoname); static struct addrinfo *gethostinfo(const char *, const char *, int);
static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3); static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3);
static void usage(void); static void usage(void);
static void whois(const char *, const char *, int); static void whois(const char *, const char *, const char *, int);
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
@ -255,11 +256,11 @@ main(int argc, char *argv[])
if (country != NULL) { if (country != NULL) {
char *qnichost; char *qnichost;
s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL); s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL);
whois(*argv, qnichost, flags); whois(*argv, qnichost, port, flags);
free(qnichost); free(qnichost);
} else } else
whois(*argv, host != NULL ? host : whois(*argv, host != NULL ? host :
choose_server(*argv), flags); choose_server(*argv), port, flags);
reset_rir(); reset_rir();
argv++; argv++;
} }
@ -283,7 +284,7 @@ choose_server(char *domain)
} }
static struct addrinfo * static struct addrinfo *
gethostinfo(char const *host, int exit_on_noname) gethostinfo(const char *host, const char *hport, int exit_on_noname)
{ {
struct addrinfo hints, *res; struct addrinfo hints, *res;
int error; int error;
@ -293,7 +294,7 @@ gethostinfo(char const *host, int exit_on_noname)
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
res = NULL; res = NULL;
error = getaddrinfo(host, port, &hints, &res); error = getaddrinfo(host, hport, &hints, &res);
if (error && (exit_on_noname || error != EAI_NONAME)) if (error && (exit_on_noname || error != EAI_NONAME))
err(EX_NOHOST, "%s: %s", host, gai_strerror(error)); err(EX_NOHOST, "%s: %s", host, gai_strerror(error));
return (res); return (res);
@ -444,15 +445,15 @@ connect_to_any_host(struct addrinfo *hostres)
} }
static void static void
whois(const char *query, const char *hostname, int flags) whois(const char *query, const char *hostname, const char *hostport, int flags)
{ {
FILE *fp; FILE *fp;
struct addrinfo *hostres; struct addrinfo *hostres;
char *buf, *host, *nhost, *p; char *buf, *host, *nhost, *nport, *p;
int comment, s, f; int comment, s, f;
size_t len, i; size_t len, i;
hostres = gethostinfo(hostname, 1); hostres = gethostinfo(hostname, hostport, 1);
s = connect_to_any_host(hostres); s = connect_to_any_host(hostres);
if (s == -1) if (s == -1)
err(EX_OSERR, "connect()"); err(EX_OSERR, "connect()");
@ -532,14 +533,35 @@ whois(const char *query, const char *hostname, int flags)
SCAN(p, buf+len, *p == ' '); SCAN(p, buf+len, *p == ' ');
host = p; host = p;
SCAN(p, buf+len, ishost(*p)); SCAN(p, buf+len, ishost(*p));
if (p > host) if (p > host) {
char *pstr;
s_asprintf(&nhost, "%.*s", s_asprintf(&nhost, "%.*s",
(int)(p - host), host); (int)(p - host), host);
if (*p != ':') {
s_asprintf(&nport, "%s", port);
break;
}
pstr = ++p;
SCAN(p, buf+len, isdigit(*p));
if (p > pstr && (p - pstr) < 6) {
s_asprintf(&nport, "%.*s",
(int)(p - pstr), pstr);
break;
}
/* Invalid port; don't recurse */
free(nhost);
nhost = NULL;
}
break; break;
} }
for (i = 0; actually_arin[i] != NULL; i++) { for (i = 0; actually_arin[i] != NULL; i++) {
if (strncmp(buf, actually_arin[i], len) == 0) { if (strncmp(buf, actually_arin[i], len) == 0) {
s_asprintf(&nhost, "%s", ANICHOST); s_asprintf(&nhost, "%s", ANICHOST);
s_asprintf(&nport, "%s", port);
break; break;
} }
} }
@ -565,17 +587,19 @@ whois(const char *query, const char *hostname, int flags)
/* Do we need to find an alternative RIR? */ /* Do we need to find an alternative RIR? */
if (try_rir[i].loop != 0 && nhost != NULL && if (try_rir[i].loop != 0 && nhost != NULL &&
strcasecmp(try_rir[i].host, nhost) == 0) { strcasecmp(try_rir[i].host, nhost) == 0) {
free(nhost); free(nhost);
nhost = NULL; nhost = NULL;
f = 1; free(nport);
nport = NULL;
f = 1;
} }
} }
if (f) { if (f) {
/* Find a replacement RIR */ /* Find a replacement RIR */
for (i = 0; try_rir[i].host != NULL; i++) { for (i = 0; try_rir[i].host != NULL; i++) {
if (try_rir[i].loop == 0) { if (try_rir[i].loop == 0) {
s_asprintf(&nhost, "%s", s_asprintf(&nhost, "%s", try_rir[i].host);
try_rir[i].host); s_asprintf(&nport, "%s", port);
break; break;
} }
} }
@ -584,9 +608,10 @@ whois(const char *query, const char *hostname, int flags)
/* Ignore self-referrals */ /* Ignore self-referrals */
if (strcasecmp(hostname, nhost) != 0) { if (strcasecmp(hostname, nhost) != 0) {
printf("# %s\n\n", nhost); printf("# %s\n\n", nhost);
whois(query, nhost, flags); whois(query, nhost, nport, flags);
} }
free(nhost); free(nhost);
free(nport);
} }
} }