svn commit: r308762 - head/usr.bin/whois

Tony Finch fanf at FreeBSD.org
Thu Nov 17 15:19:07 UTC 2016


Author: fanf
Date: Thu Nov 17 15:19:06 2016
New Revision: 308762
URL: https://svnweb.freebsd.org/changeset/base/308762

Log:
  More robust handling of whois referrals from RIRs.
  
  An example problem case is 163.1.0.0 (University of Oxford)
  which is in an APNIC ERX address range. Previously we assumed
  that ARIN has the correct information for all ERX allocations,
  but in this case ARIN refers back to APNIC, rather than referring
  to RIPE. This caused whois to loop.
  
  Whois will no longer loop back and forth forever between two RIRs
  that don't have an answer, but instead try the other RIRs in turn.

Modified:
  head/usr.bin/whois/whois.c

Modified: head/usr.bin/whois/whois.c
==============================================================================
--- head/usr.bin/whois/whois.c	Thu Nov 17 15:17:01 2016	(r308761)
+++ head/usr.bin/whois/whois.c	Thu Nov 17 15:19:06 2016	(r308762)
@@ -119,12 +119,38 @@ static struct {
 	{ NULL, 0 }
 };
 
+/*
+ * We have a list of patterns for RIRs that assert ignorance rather than
+ * providing referrals. If that happens, we guess that ARIN will be more
+ * helpful. But, before following a referral to an RIR, we check if we have
+ * asked that RIR already, and if so we make another guess.
+ */
 static const char *actually_arin[] = {
 	"netname:        ERX-NETBLOCK\n", /* APNIC */
 	"netname:        NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n",
 	NULL
 };
 
+static struct {
+	int loop;
+	const char *host;
+} try_rir[] = {
+	{ 0, ANICHOST },
+	{ 0, RNICHOST },
+	{ 0, PNICHOST },
+	{ 0, FNICHOST },
+	{ 0, LNICHOST },
+	{ 0, NULL }
+};
+
+static void
+reset_rir(void) {
+	int i;
+
+	for (i = 0; try_rir[i].host != NULL; i++)
+		try_rir[i].loop = 0;
+}
+
 static const char *port = DEFAULT_PORT;
 
 static const char *choose_server(char *);
@@ -232,6 +258,7 @@ main(int argc, char *argv[])
 		} else
 			whois(*argv, host != NULL ? host :
 			      choose_server(*argv), flags);
+		reset_rir();
 		argv++;
 	}
 	exit(0);
@@ -420,7 +447,7 @@ whois(const char *query, const char *hos
 	FILE *fp;
 	struct addrinfo *hostres;
 	char *buf, *host, *nhost, *p;
-	int s, f;
+	int comment, s, f;
 	size_t len, i;
 
 	hostres = gethostinfo(hostname, 1);
@@ -467,12 +494,28 @@ whois(const char *query, const char *hos
 		fprintf(fp, "%s\r\n", query);
 	fflush(fp);
 
+	comment = 0;
+	if (!(flags & WHOIS_SPAM_ME) &&
+	    (strcasecmp(hostname, ANICHOST) == 0 ||
+	     strcasecmp(hostname, RNICHOST) == 0)) {
+		comment = 2;
+	}
+
 	nhost = NULL;
 	while ((buf = fgetln(fp, &len)) != NULL) {
 		/* Nominet */
 		if (!(flags & WHOIS_SPAM_ME) &&
 		    len == 5 && strncmp(buf, "-- \r\n", 5) == 0)
 			break;
+		/* RIRs */
+		if (comment == 1 && buf[0] == '#')
+			break;
+		else if (comment == 2) {
+			if (strchr("#%\r\n", buf[0]) != NULL)
+				continue;
+			else
+				comment = 1;
+		}
 
 		printf("%.*s", (int)len, buf);
 
@@ -487,8 +530,7 @@ whois(const char *query, const char *hos
 				SCAN(p, buf+len, *p == ' ');
 				host = p;
 				SCAN(p, buf+len, ishost(*p));
-				/* avoid loops */
-				if (strncmp(hostname, host, p - host) != 0)
+				if (p > host)
 					s_asprintf(&nhost, "%.*s",
 						   (int)(p - host), host);
 				break;
@@ -511,8 +553,37 @@ whois(const char *query, const char *hos
 	}
 	fclose(fp);
 	freeaddrinfo(hostres);
+
+	f = 0;
+	for (i = 0; try_rir[i].host != NULL; i++) {
+		/* Remember visits to RIRs */
+		if (try_rir[i].loop == 0 &&
+		    strcasecmp(try_rir[i].host, hostname) == 0)
+			try_rir[i].loop = 1;
+		/* Do we need to find an alternative RIR? */
+		if (try_rir[i].loop != 0 && nhost != NULL &&
+		    strcasecmp(try_rir[i].host, nhost) == 0) {
+			    free(nhost);
+			    nhost = NULL;
+			    f = 1;
+		}
+	}
+	if (f) {
+		/* Find a replacement RIR */
+		for (i = 0; try_rir[i].host != NULL; i++) {
+			if (try_rir[i].loop == 0) {
+				s_asprintf(&nhost, "%s",
+					try_rir[i].host);
+				break;
+			}
+		}
+	}
 	if (nhost != NULL) {
-		whois(query, nhost, flags);
+		/* Ignore self-referrals */
+		if (strcasecmp(hostname, nhost) != 0) {
+			printf("# %s\n\n", nhost);
+			whois(query, nhost, flags);
+		}
 		free(nhost);
 	}
 }


More information about the svn-src-head mailing list