shithub: riscv

Download patch

ref: 7113f730dec2aba58935fdf0eb2b13ad58e63a69
parent: 16c87febd3875c4b0c9648c681735be3de8358bd
author: cinap_lenrek <[email protected]>
date: Fri Jun 1 19:53:09 EDT 2018

ndb/cs: make ipv6 only host practical by checking ip version on local interfaces

avoid returning ip addresses that cannot be reached due
to lack of a compatible ip address. this means when here
is no ipv4 address configured, we wont return ipv4 addresses
and would not query dns for an A record.

likewise, when here is no ipv6 address configured then
we wont query dns for an AAAA record.

ipv6 lookups can still be disabled with the -4 flag just
as before.

--- a/sys/src/cmd/ndb/cs.c
+++ b/sys/src/cmd/ndb/cs.c
@@ -80,7 +80,7 @@
 Mlist	*mlist;
 int	mfd[2];
 int	debug;
-int	ipv6lookups = 1;
+
 jmp_buf	masterjmp;	/* return through here after a slave process has been created */
 int	*isslave;	/* *isslave non-zero means this is a slave process */
 long	active;		/* number of active slaves */
@@ -136,7 +136,9 @@
 char*		iptrans(Ndbtuple*, Network*, char*, char*, int);
 Ndbtuple*	telcolookup(Network*, char*, char*);
 char*		telcotrans(Ndbtuple*, Network*, char*, char*, int);
+
 Ndbtuple*	dnsiplookup(char*, Ndbs*, int);
+Ndbtuple*	myipinfo(Ndb *db, char **list, int n);
 
 struct Network
 {
@@ -145,9 +147,8 @@
 	char		*(*trans)(Ndbtuple*, Network*, char*, char*, int);
 
 	char		considered;		/* flag: ignored for "net!"? */
-	char		fasttimeouthack;	/* flag. was for IL */
-	char		v4only;
-	char		v6only;
+	char		fasttimeout;		/* flag. was for IL */
+	char		ipvers;			/* flag: V4, V6 */
 
 	Network		*next;
 };
@@ -154,6 +155,9 @@
 
 enum {
 	Ntcp = 1,
+
+	V4 = 1,
+	V6 = 2,
 };
 
 /*
@@ -160,21 +164,22 @@
  *  net doesn't apply to (r)udp, icmp(v6), or telco (for speed).
  */
 Network network[] = {
-	{ "il",		iplookup,	iptrans,	0, 1, 1, 0, },
-	{ "tcp",	iplookup,	iptrans,	0, 0, 0, 0, },
-	{ "il",		iplookup,	iptrans,	0, 0, 1, 0, },
-	{ "udp",	iplookup,	iptrans,	1, 0, 0, 0, },
-	{ "icmp",	iplookup,	iptrans,	1, 0, 1, 0, },
-	{ "icmpv6",	iplookup,	iptrans,	1, 0, 0, 1, },
-	{ "rudp",	iplookup,	iptrans,	1, 0, 1, 0, },
-	{ "ssh",	iplookup,	iptrans,	1, 0, 0, 0, },
-	{ "telco",	telcolookup,	telcotrans,	1, 0, 0, 0, },
+	{ "il",		iplookup,	iptrans,	0, 1, V4,	},
+	{ "tcp",	iplookup,	iptrans,	0, 0, V4|V6,	},
+	{ "il",		iplookup,	iptrans,	0, 0, V4,	},
+	{ "udp",	iplookup,	iptrans,	1, 0, V4|V6,	},
+	{ "icmp",	iplookup,	iptrans,	1, 0, V4,	},
+	{ "icmpv6",	iplookup,	iptrans,	1, 0, V6,	},
+	{ "rudp",	iplookup,	iptrans,	1, 0, V4,	},
+	{ "ssh",	iplookup,	iptrans,	1, 0, V4|V6,	},
+	{ "telco",	telcolookup,	telcotrans,	1, 0, 0,	},
 	{ 0 },
 };
 
 QLock ipifclock;
 Ipifc *ipifcs;
-static Ndbtuple* myipinfo(Ndb *db, char **list, int n);
+int confipvers;
+int lookipvers = V4|V6;
 
 char *mysysname;
 
@@ -231,7 +236,7 @@
 	ext[0] = 0;
 	ARGBEGIN{
 	case '4':
-		ipv6lookups = 0;
+		lookipvers = V4;
 		break;
 	case 'd':
 		debug = 1;
@@ -798,8 +803,8 @@
 	 *  toggle ipv6 lookups
 	 */
 	if(strncmp(job->request.data, "ipv6", 4)==0){
-		ipv6lookups ^= 1;
-		syslog(1, logfile, "ipv6lookups %d", ipv6lookups);
+		lookipvers ^= V6;
+		syslog(1, logfile, "ipv6lookups %d", (lookipvers & V6) != 0);
 		goto send;
 	}
 
@@ -967,18 +972,26 @@
 	_exits(0);
 }
 
-static int
-isvalidip(uchar *ip)
-{
-	return ipcmp(ip, IPnoaddr) != 0 && ipcmp(ip, v4prefix) != 0;
-}
-
 void
 readipinterfaces(void)
 {
+	Ipifc *ifc;
+	Iplifc *lifc;
+	int v;
+
+	v = 0;
 	qlock(&ipifclock);
 	ipifcs = readipifc(mntpt, ipifcs, -1);
+	for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
+		for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
+			if(isv4(lifc->ip))
+				v |= V4;
+			else
+				v |= V6;
+		}
+	}
 	qunlock(&ipifclock);
+	confipvers = v;
 }
 
 /*
@@ -1165,8 +1178,7 @@
 	char *cp;
 	Ndbtuple *nt, *t;
 	char reply[Maxreply];
-	int i, rv;
-	int hack;
+	int i, rv, fasttimeout;
 
 	/* open up the standard db files */
 	if(db == nil)
@@ -1186,9 +1198,9 @@
 			nt = (*np->lookup)(np, mf->host, mf->serv);
 			if(nt == nil)
 				continue;
-			hack = np->fasttimeouthack && !lookforproto(nt, np->net);
+			fasttimeout = np->fasttimeout && !lookforproto(nt, np->net);
 			for(t = nt; mf->nreply < Nreply && t != nil; t = t->entry){
-				cp = (*np->trans)(t, np, mf->serv, mf->rem, hack);
+				cp = (*np->trans)(t, np, mf->serv, mf->rem, fasttimeout);
 				if(cp != nil){
 					/* avoid duplicates */
 					for(i = 0; i < mf->nreply; i++)
@@ -1219,7 +1231,7 @@
 	 *  look for a specific network
 	 */
 	for(np = network; np->net != nil; np++){
-		if(np->fasttimeouthack)
+		if(np->fasttimeout)
 			continue;
 		if(strcmp(np->net, mf->net) == 0)
 			break;
@@ -1315,7 +1327,7 @@
 	return buf;
 }
 
-static Ndbtuple*
+Ndbtuple*
 myipinfo(Ndb *db, char **list, int n)
 {
 	Ndbtuple *t, *nt;
@@ -1375,13 +1387,6 @@
 	return t;
 }
 
-static int
-isv4str(char *s)
-{
-	uchar ip[IPaddrlen];
-	return parseip(ip, s) != -1 && isv4(ip);
-}
-
 static Ndbtuple*
 ndbline(Ndbtuple *t)
 {
@@ -1441,7 +1446,7 @@
 	 */
 	t = nil;
 	if(strcmp(attr, "dom") == 0)
-		t = dnsiplookup(host, &s, !np->v4only);
+		t = dnsiplookup(host, &s, np->ipvers);
 	if(t == nil){
 		for(nt = ndbsearch(db, &s, attr, host); nt != nil; nt = ndbsnext(&s, attr, host)){
 			if(ndbfindattr(nt, s.t, "ip") == nil){
@@ -1456,12 +1461,12 @@
 		if(strcmp(attr, "dom") != 0){
 			dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil);
 			if(dnsname != nil){
-				t = dnsiplookup(dnsname, &s, !np->v4only);
+				t = dnsiplookup(dnsname, &s, np->ipvers);
 				free(dnsname);
 			}
 		}
 		if(t == nil)
-			t = dnsiplookup(host, &s, !np->v4only);
+			t = dnsiplookup(host, &s, np->ipvers);
 	}
 	if(t == nil)
 		return nil;
@@ -1514,11 +1519,12 @@
  *  translate an ip address
  */
 char*
-iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
+iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int fasttimeout)
 {
 	char ts[Maxservice];
 	char reply[Maxreply];
 	char x[Maxservice];
+	uchar ip[IPaddrlen];
 
 	if(strcmp(t->attr, "ip") != 0)
 		return nil;
@@ -1537,14 +1543,12 @@
 		snprint(reply, sizeof(reply), "%s/%s/clone %s%s",
 			mntpt, np->net, ts, x);
 	else {
-		if(np->v4only && !isv4str(t->val))
+		if(parseip(ip, t->val) == -1)
 			return nil;
-
-		if(np->v6only && isv4str(t->val))
+		if((np->ipvers & confipvers & (isv4(ip) ? V4 : V6)) == 0)
 			return nil;
-
-		snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s",
-			mntpt, np->net, t->val, ts, x, hack? "!fasttimeout": "");
+		snprint(reply, sizeof(reply), "%s/%s/clone %I!%s%s%s",
+			mntpt, np->net, ip, ts, x, fasttimeout? "!fasttimeout": "");
 	}
 
 	return estrdup(reply);
@@ -1564,7 +1568,7 @@
 	werrstr("can't translate address");
 	free(ndbgetvalue(db, &s, "sys", host, "telco", &t));
 	if(t == nil)
-		return ndbnew("telco", host);
+		return ndbline(ndbnew("telco", host));
 
 	return ndbreorder(t, s.t);
 }
@@ -1682,11 +1686,16 @@
  *  call the dns process and have it try to translate a name
  */
 Ndbtuple*
-dnsiplookup(char *host, Ndbs *s, int v6)
+dnsiplookup(char *host, Ndbs *s, int ipvers)
 {
 	char buf[Maxreply];
 	Ndbtuple *t;
 
+	ipvers &= confipvers & lookipvers;
+	if(ipvers == 0){
+		werrstr("no ip address");
+		return nil;
+	}
 	qunlock(&dblock);
 	slave(host);
 	if(*isslave == 0){
@@ -1703,9 +1712,10 @@
 	if(strcmp(ipattr(host), "ip") == 0)
 		t = dnsquery(mntpt, host, "ptr");
 	else {
-		t = dnsquery(mntpt, host, "ip");
-		/* special case: query ipv6 (AAAA dns RR) too */
-		if (v6 && ipv6lookups)
+		t = nil;
+		if(ipvers & V4)
+			t = dnsquery(mntpt, host, "ip");
+		if(ipvers & V6)
 			t = dnsip6lookup(mntpt, host, t);
 	}
 	s->t = t;
@@ -1811,7 +1821,7 @@
 
 	/* give dns a chance */
 	if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){
-		t = dnsiplookup(val[0], &s, ipv6lookups);
+		t = dnsiplookup(val[0], &s, lookipvers);
 		if(t != nil){
 			if(qmatch(t, attr, val, n)){
 				qreply(mf, t);
@@ -1863,12 +1873,35 @@
 	return t;
 }
 
+/*
+ *  remove duplicates
+ */
+static Ndbtuple*
+ndbdedup(Ndbtuple *t)
+{
+	Ndbtuple *tt, *nt, **l;
+
+	for(nt = t; nt != nil; nt = nt->entry){
+		for(l = &nt->entry; (tt = *l) != nil;){
+			if(strcmp(nt->attr, tt->attr) != 0
+			|| strcmp(nt->val, tt->val) != 0){
+				l = &tt->entry;
+				continue;
+			}
+			*l = tt->entry;
+			tt->entry = nil;
+			ndbfree(tt);
+		}
+	}
+	return t;
+}
+
 char*
 ipinfoquery(Mfile *mf, char **list, int n)
 {
 	int i, nresolve;
 	uchar resolve[Maxattr];
-	Ndbtuple *t, *nt, *tt, **l;
+	Ndbtuple *t, *nt, **l;
 	char *attr, *val;
 
 	/* skip 'ipinfo' */
@@ -1912,21 +1945,8 @@
 	if(t == nil)
 		return "no match";
 
-	/* remove duplicates */
-	for(nt = t; nt != nil; nt = nt->entry){
-		for(l = &nt->entry; (tt = *l) != nil;){
-			if(strcmp(nt->attr, tt->attr) != 0
-			|| strcmp(nt->val, tt->val) != 0){
-				l = &tt->entry;
-				continue;
-			}
-			*l = tt->entry;
-			tt->entry = nil;
-			ndbfree(tt);
-		}
-	}
-
 	if(nresolve != 0){
+		t = ndbdedup(t);
 		for(l = &t; *l != nil;){
 			nt = *l;
 
@@ -1955,6 +1975,7 @@
 			ndbfree(nt);
 		}
 	}
+	t = ndbdedup(t);
 
 	/* make it all one line */
 	t = ndbline(t);