summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco d'Itri <md@linux.it>2019-06-28 01:38:17 +0200
committerMarco d'Itri <md@linux.it>2019-06-28 01:38:17 +0200
commitb49ba5ecc0f66dc53a7e1b0eb26d3a01da1c89e6 (patch)
tree28e20430705ea35e78d9e57d165ec1a93d621396
parenta0c0bf7144effbc90bdb8f782c8411c8604eeffc (diff)
downloadwhois-b49ba5ecc0f66dc53a7e1b0eb26d3a01da1c89e6.tar.gz
Implement -I to use referrals from whois.iana.org
Closes: #774603
-rw-r--r--whois.18
-rw-r--r--whois.c54
-rw-r--r--whois.h1
3 files changed, 61 insertions, 2 deletions
diff --git a/whois.1 b/whois.1
index 0ed8ea2..8c940f8 100644
--- a/whois.1
+++ b/whois.1
@@ -5,7 +5,7 @@ whois \- client for the whois directory service
.B whois
[\~{\~\fB\-h\fP | \fB\-\-host\fP\~}\~\fIHOST\fP\~]
[\~{\~\fB\-p\fP | \fB\-\-port\fP\~}\~\fIPORT\fP\~]
-[\~\fB\-abBcdGHKlLmMrRx\fP\~]
+[\~\fB\-abBcdGHIKlLmMrRx\fP\~]
[\~\fB\-g\fP\~\fISOURCE:FIRST\-LAST\fP\~]
[\~\fB\-i\fP\~\fIATTR\fP[\fI,ATTR\fP]...\~]
[\~\fB\-s\fP\~\fISOURCE\fP[\fI,SOURCE\fP]...\~]
@@ -51,6 +51,12 @@ Do not display the legal disclaimers some registries like to show you.
.B \-p, \-\-port PORT
Connect to PORT.
.TP 8
+.B -I
+First query \fIwhois.iana.org\fP and then follow its referral to the
+whois server authoritative for that request. This works for IP addresses,
+AS numbers and domains. \fBBEWARE\fP: this means that the IANA server
+will see your complete query.
+.TP 8
.B \-\-verbose
Be verbose.
.TP 8
diff --git a/whois.c b/whois.c
index c5df6f4..608153b 100644
--- a/whois.c
+++ b/whois.c
@@ -159,7 +159,7 @@ int main(int argc, char *argv[])
argv = merge_args(getenv("WHOIS_OPTIONS"), argv, &argc);
while ((ch = GETOPT_LONGISH(argc, argv,
- "abBcdFg:Gh:Hi:KlLmMp:q:rRs:t:T:v:V:x",
+ "abBcdFg:Gh:Hi:IKlLmMp:q:rRs:t:T:v:V:x",
longopts, &longindex)) > 0) {
/* RIPE flags */
if (strchr(ripeflags, ch)) {
@@ -221,6 +221,9 @@ int main(int argc, char *argv[])
case 'H':
hide_discl = HIDE_NOT_STARTED; /* enable disclaimers hiding */
break;
+ case 'I':
+ server = strdup("\x0E");
+ break;
case 'p':
port = strdup(optarg);
break;
@@ -372,6 +375,13 @@ int handle_query(const char *hserver, const char *hport,
server = guess_server(p);
free(p);
goto retry;
+ case 0x0E:
+ if (verb)
+ printf(_("Using server %s.\n"), "whois.iana.org");
+ sockfd = openconn("whois.iana.org", NULL);
+ free(server);
+ server = query_iana(sockfd, query);
+ break;
default:
break;
}
@@ -921,6 +931,47 @@ char *query_afilias(const int sock, const char *query)
return referral_server;
}
+char *query_iana(const int sock, const char *query)
+{
+ char *temp, *p, buf[2000];
+ FILE *fi;
+ char *referral_server = NULL;
+ int state = 0;
+
+ temp = malloc(strlen(query) + 2 + 1);
+ strcpy(temp, query);
+ strcat(temp, "\r\n");
+
+ fi = fdopen(sock, "r");
+ if (write(sock, temp, strlen(temp)) < 0)
+ err_sys("write");
+ free(temp);
+
+ while (fgets(buf, sizeof(buf), fi)) {
+ /* If multiple attributes are returned then use the first result.
+ This is not supposed to happen. */
+ if (state == 0 && strneq(buf, "refer:", 6)) {
+ for (p = buf; *p != ':'; p++); /* skip until colon */
+ for (p++; *p == ' '; p++); /* skip colon and spaces */
+ referral_server = strdup(p);
+ if ((p = strpbrk(referral_server, "\r\n ")))
+ *p = '\0';
+ state = 2;
+ }
+
+ if ((p = strpbrk(buf, "\r\n")))
+ *p = '\0';
+ recode_fputs(buf, stdout);
+ fputc('\n', stdout);
+ }
+
+ if (ferror(fi))
+ err_sys("fgets");
+ fclose(fi);
+
+ return referral_server;
+}
+
int openconn(const char *server, const char *port)
{
int fd = -1;
@@ -1437,6 +1488,7 @@ void NORETURN usage(int error)
"Usage: whois [OPTION]... OBJECT...\n\n"
"-h HOST, --host HOST connect to server HOST\n"
"-p PORT, --port PORT connect to PORT\n"
+"-I query whois.iana.org and follow its referral\n"
"-H hide legal disclaimers\n"
));
fprintf((EXIT_SUCCESS == error) ? stdout : stderr, _(
diff --git a/whois.h b/whois.h
index 353d667..1f9115f 100644
--- a/whois.h
+++ b/whois.h
@@ -21,6 +21,7 @@ int hide_line(int *hiding, const char *const line);
char *do_query(const int, const char *);
char *query_crsnic(const int, const char *);
char *query_afilias(const int, const char *);
+char *query_iana(const int, const char *);
int openconn(const char *, const char *);
int connect_with_timeout(int, const struct sockaddr *, socklen_t, int);
void NORETURN usage(int error);