Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Jun 2000 03:43:10 +0900 (JST)
From:      Hajimu UMEMOTO (=?iso-2022-jp?B?GyRCR19LXBsoQiAbJEJIJRsoQg==?=) <ume@mahoroba.org>
To:        ache@freebsd.org
Cc:        alex@big.endian.de, cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/lib/libc/net res_init.c res_send.c
Message-ID:  <20000616.034310.74757991.ume@mahoroba.org>
In-Reply-To: <20000615111427.A20272@freebsd.org>
References:  <20000615095829.D2544@cichlids.cichlids.com> <20000616.030308.59461838.ume@mahoroba.org> <20000615111427.A20272@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
----Next_Part(Fri_Jun_16_03:43:10_2000_697)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

>>>>> On Thu, 15 Jun 2000 11:14:27 -0700
>>>>> "Andrey A. Chernov" <ache@freebsd.org> said:

ache> Not so simple. I have no resolv.conf at all and your code fails because default 
ache> NS localhost is set to AF_INET6. When I create this file and add some 
ache> nameservers to it, your code still fails because they assigned to AF_INET6 too 
ache> which socket() not understands.

Yes, I know and it was also fixed.  Above explanation is why alex
doesn't met the problem. :)

ache> It means that 1) you need to set AF_INET6 only for INET6 nameservers 2) you 
ache> must not set default NS localhost to AF_INET6. The case 2) is harder because 
ache> you can't run INET6 named by default, so some detection code required which 
ache> not affect performance.

Now, default is AF_INET.
I attach the diff.  Please review it.

Thanks itojun.


----Next_Part(Fri_Jun_16_03:43:10_2000_697)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Description: resolver-ipv6.diff
Content-Disposition: attachment; filename="resolver-ipv6.diff"

Index: lib/libc/net/res_init.c
diff -u lib/libc/net/res_init.c.orig lib/libc/net/res_init.c
--- lib/libc/net/res_init.c.orig	Thu Jun 15 05:51:55 2000
+++ lib/libc/net/res_init.c	Thu Jun 15 20:15:45 2000
@@ -87,6 +87,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <netdb.h>
 
 #include "res_config.h"
 
@@ -112,9 +113,7 @@
 # endif
 	;
 
-#ifdef INET6
 struct __res_state_ext _res_ext;
-#endif /* INET6 */
 
 /*
  * Set up default settings.  If the configuration file exist, the values
@@ -195,6 +194,8 @@
 #endif
 	_res.nsaddr.sin_family = AF_INET;
 	_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
+	if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len)
+		memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len);
 	_res.nscount = 1;
 	_res.ndots = 1;
 	_res.pfcode = 0;
@@ -300,16 +301,41 @@
 		}
 		/* read nameservers to query */
 		if (MATCH(buf, "nameserver") && nserv < MAXNS) {
-		    struct in_addr a;
+		    char *q;
+		    struct addrinfo hints, *res;
+		    char pbuf[NI_MAXSERV];
 
 		    cp = buf + sizeof("nameserver") - 1;
 		    while (*cp == ' ' || *cp == '\t')
 			cp++;
-		    if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
-			_res.nsaddr_list[nserv].sin_addr = a;
-			_res.nsaddr_list[nserv].sin_family = AF_INET;
-			_res.nsaddr_list[nserv].sin_port =
-				htons(NAMESERVER_PORT);
+		    if ((*cp == '\0') || (*cp == '\n'))
+			continue;
+		    for (q = cp; *q; q++) {
+			if (isspace(*q)) {
+			    *q = '\0';
+			    break;
+			}
+		    }
+		    memset(&hints, 0, sizeof(hints));
+		    hints.ai_flags = AI_NUMERICHOST;
+		    hints.ai_socktype = SOCK_DGRAM;
+		    snprintf(pbuf, sizeof(pbuf), "%d", NAMESERVER_PORT);
+		    if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
+			    res->ai_next == NULL) {
+			if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) {
+			    memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr,
+				res->ai_addrlen);
+			} else {
+			    memset(&_res_ext.nsaddr_list[nserv], 0,
+				sizeof(_res_ext.nsaddr_list[nserv]));
+			}
+			if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) {
+			    memcpy(&_res.nsaddr_list[nserv], res->ai_addr,
+				res->ai_addrlen);
+			} else {
+			    memset(&_res.nsaddr_list[nserv], 0,
+				sizeof(_res.nsaddr_list[nserv]));
+			}
 			nserv++;
 		    }
 		    continue;
@@ -317,9 +343,9 @@
 #ifdef RESOLVSORT
 		if (MATCH(buf, "sortlist")) {
 		    struct in_addr a;
-#ifdef INET6
 		    struct in6_addr a6;
-#endif /* INET6 */
+		    int m, i;
+		    u_char *u;
 
 		    cp = buf + sizeof("sortlist") - 1;
 		    while (nsort < MAXRESOLVSORT) {
@@ -353,19 +379,14 @@
 				_res.sort_list[nsort].mask = 
 				    net_mask(_res.sort_list[nsort].addr);
 			    }
-#ifdef INET6
 			    _res_ext.sort_list[nsort].af = AF_INET;
 			    _res_ext.sort_list[nsort].addr.ina =
 				_res.sort_list[nsort].addr;
 			    _res_ext.sort_list[nsort].mask.ina.s_addr =
 				_res.sort_list[nsort].mask;
-#endif /* INET6 */
 			    nsort++;
 			}
-#ifdef INET6
 			else if (inet_pton(AF_INET6, net, &a6) == 1) {
-			    int m, i;
-			    u_char *u;
 
 			    _res_ext.sort_list[nsort].af = AF_INET6;
 			    _res_ext.sort_list[nsort].addr.in6a = a6;
@@ -407,7 +428,6 @@
 			    }
 			    nsort++;
 			}
-#endif /* INET6 */
 			*cp = n;
 		    }
 		    continue;
Index: lib/libc/net/res_send.c
diff -u lib/libc/net/res_send.c.orig lib/libc/net/res_send.c
--- lib/libc/net/res_send.c.orig	Thu Jun 15 05:51:55 2000
+++ lib/libc/net/res_send.c	Fri Jun 16 02:53:38 2000
@@ -109,6 +109,7 @@
 static int s = -1;		/* socket used for communications */
 static int connected = 0;	/* is the socket connected */
 static int vc = 0;		/* is the socket a virtual circuit? */
+static int af = 0;		/* address family of socket */
 static res_send_qhook Qhook = NULL;
 static res_send_rhook Rhook = NULL;
 
@@ -126,21 +127,26 @@
 			fprintf args;\
 			__fp_nquery(query, size, stdout);\
 		} else {}
+static char abuf[NI_MAXHOST];
+static char pbuf[NI_MAXSERV];
+static void Aerror __P((FILE *, char *, int, struct sockaddr *));
+static void Perror __P((FILE *, char *, int));
+
     static void
     Aerror(file, string, error, address)
 	FILE *file;
 	char *string;
 	int error;
-	struct sockaddr_in address;
+	struct sockaddr *address;
     {
 	int save = errno;
 
 	if (_res.options & RES_DEBUG) {
-		fprintf(file, "res_send: %s ([%s].%u): %s\n",
-			string,
-			inet_ntoa(address.sin_addr),
-			ntohs(address.sin_port),
-			strerror(error));
+		getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
+			    pbuf, sizeof(pbuf),
+			    NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID);
+		fprintf(file, "res_send: %s ([%s].%s): %s\n",
+			string, abuf, pbuf, strerror(error));
 	}
 	errno = save;
     }
@@ -176,6 +182,33 @@
 	Rhook = hook;
 }
 
+static struct sockaddr * get_nsaddr __P((size_t));
+
+/*
+ * pick appropriate nsaddr_list for use.  see res_init() for initialization.
+ */
+static struct sockaddr *
+get_nsaddr(n)
+	size_t n;
+{
+
+	if (!_res.nsaddr_list[n].sin_family) {
+		/*
+		 * - _res_ext.nsaddr_list[n] holds an address that is larger
+		 *   than struct sockaddr, and
+		 * - user code did not update _res.nsaddr_list[n].
+		 */
+		return (struct sockaddr *)&_res_ext.nsaddr_list[n];
+	} else {
+		/*
+		 * - user code updated _res.nsaddr_list[n], or
+		 * - _res.nsaddr_list[n] has the same content as
+		 *   _res_ext.nsaddr_list[n].
+		 */
+		return (struct sockaddr *)&_res.nsaddr_list[n];
+	}
+}
+
 /* int
  * res_isourserver(ina)
  *	looks up "ina" in _res.ns_addr_list[]
@@ -189,21 +222,39 @@
 res_isourserver(inp)
 	const struct sockaddr_in *inp;
 {
-	struct sockaddr_in ina;
+	const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
+	const struct sockaddr_in6 *srv6;
+	const struct sockaddr_in *srv;
 	int ns, ret;
 
-	ina = *inp;
 	ret = 0;
-	for (ns = 0;  ns < _res.nscount;  ns++) {
-		const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
-
-		if (srv->sin_family == ina.sin_family &&
-		    srv->sin_port == ina.sin_port &&
-		    (srv->sin_addr.s_addr == INADDR_ANY ||
-		     srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
-			ret++;
-			break;
+	switch (inp->sin_family) {
+	case AF_INET6:
+		for (ns = 0; ns < _res.nscount; ns++) {
+			srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
+			if (srv6->sin6_family == in6p->sin6_family &&
+			    srv6->sin6_port == in6p->sin6_port &&
+			    srv6->sin6_scope_id == in6p->sin6_scope_id &&
+			    (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
+			     IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
+			         &in6p->sin6_addr))) {
+				ret++;
+				break;
+			}
+		}
+		break;
+	case AF_INET:
+		for (ns = 0; ns < _res.nscount; ns++) {
+			srv = (struct sockaddr_in *)get_nsaddr(ns);
+			if (srv->sin_family == inp->sin_family &&
+			    srv->sin_port == inp->sin_port &&
+			    (srv->sin_addr.s_addr == INADDR_ANY ||
+			     srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
+				ret++;
+				break;
+			}
 		}
+		break;
 	}
 	return (ret);
 }
@@ -332,7 +383,8 @@
 	 */
 	for (try = 0; try < _res.retry; try++) {
 	    for (ns = 0; ns < _res.nscount; ns++) {
-		struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
+		struct sockaddr *nsap = get_nsaddr(ns);
+
     same_ns:
 		if (badns & (1 << ns)) {
 			res_close();
@@ -345,7 +397,8 @@
 			do {
 				res_sendhookact act;
 
-				act = (*Qhook)(&nsap, &buf, &buflen,
+				act = (*Qhook)((struct sockaddr_in **)&nsap,
+					       &buf, &buflen,
 					       ans, anssiz, &resplen);
 				switch (act) {
 				case res_goahead:
@@ -369,9 +422,11 @@
 			} while (!done);
 		}
 
-		Dprint(_res.options & RES_DEBUG,
+		Dprint((_res.options & RES_DEBUG) &&
+		       getnameinfo(nsap, nsap->sa_len, abuf, sizeof(abuf),
+				   NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
 		       (stdout, ";; Querying server (# %d) address = %s\n",
-			ns + 1, inet_ntoa(nsap->sin_addr)));
+			ns + 1, abuf));
 
 		if (v_circuit) {
 			int truncated;
@@ -385,22 +440,25 @@
 			 */
 			try = _res.retry;
 			truncated = 0;
-			if (s < 0 || !vc || hp->opcode == ns_o_update) {
+			if (s < 0 || !vc || hp->opcode == ns_o_update ||
+			    af != nsap->sa_family) {
 				if (s >= 0)
 					res_close();
 
-				s = socket(PF_INET, SOCK_STREAM, 0);
+				af = nsap->sa_family;
+				s = socket(af, SOCK_STREAM, 0);
 				if (s < 0) {
 					terrno = errno;
 					Perror(stderr, "socket(vc)", errno);
-					return (-1);
+					badns |= (1 << ns);
+					res_close();
+					goto next_ns;
 				}
 				errno = 0;
-				if (connect(s, (struct sockaddr *)nsap,
-					    sizeof *nsap) < 0) {
+				if (connect(s, nsap, nsap->sa_len) < 0) {
 					terrno = errno;
 					Aerror(stderr, "connect/vc",
-					       errno, *nsap);
+					       errno, nsap);
 					badns |= (1 << ns);
 					res_close();
 					goto next_ns;
@@ -530,20 +588,23 @@
 			struct timeval timeout;
 			fd_set dsmask, *dsmaskp;
 			int dsmasklen;
-			struct sockaddr_in from;
+			struct sockaddr_storage from;
 			int fromlen;
 
-			if ((s < 0) || vc) {
+			if (s < 0 || vc || af != nsap->sa_family) {
 				if (vc)
 					res_close();
-				s = socket(PF_INET, SOCK_DGRAM, 0);
+				af = nsap->sa_family;
+				s = socket(af, SOCK_DGRAM, 0);
 				if (s < 0) {
 #ifndef CAN_RECONNECT
  bad_dg_sock:
 #endif
 					terrno = errno;
 					Perror(stderr, "socket(dg)", errno);
-					return (-1);
+					badns |= (1 << ns);
+					res_close();
+					goto next_ns;
 				}
 				connected = 0;
 			}
@@ -569,12 +630,10 @@
 				 * receive a response from another server.
 				 */
 				if (!connected) {
-					if (connect(s, (struct sockaddr *)nsap,
-						    sizeof *nsap
-						    ) < 0) {
+					if (connect(s, nsap, nsap->sa_len) < 0) {
 						Aerror(stderr,
 						       "connect(dg)",
-						       errno, *nsap);
+						       errno, nsap);
 						badns |= (1 << ns);
 						res_close();
 						goto next_ns;
@@ -594,6 +653,7 @@
 				 */
 				if (connected) {
 #ifdef CAN_RECONNECT
+					/* XXX: any errornous address */
 					struct sockaddr_in no_addr;
 
 					no_addr.sin_family = AF_INET;
@@ -604,7 +664,7 @@
 						        &no_addr,
 						       sizeof no_addr);
 #else
-					int s1 = socket(PF_INET, SOCK_DGRAM,0);
+					int s1 = socket(af, SOCK_DGRAM,0);
 					if (s1 < 0)
 						goto bad_dg_sock;
 					(void)dup2(s1, s);
@@ -617,10 +677,8 @@
 				}
 #endif /* !CANNOT_CONNECT_DGRAM */
 				if (sendto(s, (char*)buf, buflen, 0,
-					   (struct sockaddr *)nsap,
-					   sizeof *nsap)
-				    != buflen) {
-					Aerror(stderr, "sendto", errno, *nsap);
+					   nsap, nsap->sa_len) != buflen) {
+					Aerror(stderr, "sendto", errno, nsap);
 					badns |= (1 << ns);
 					res_close();
 					goto next_ns;
@@ -749,7 +807,7 @@
 				goto next_ns;
 			}
 			errno = 0;
-			fromlen = sizeof(struct sockaddr_in);
+			fromlen = sizeof(from);
 			resplen = recvfrom(s, (char*)ans, anssiz, 0,
 					   (struct sockaddr *)&from, &fromlen);
 			if (resplen <= 0) {
@@ -784,7 +842,7 @@
 			}
 #ifdef CHECK_SRVR_ADDR
 			if (!(_res.options & RES_INSECURE1) &&
-			    !res_isourserver(&from)) {
+			    !res_isourserver((struct sockaddr_in *)&from)) {
 				/*
 				 * response from wrong server? ignore it.
 				 * XXX - potential security hazard could
@@ -861,7 +919,8 @@
 			do {
 				res_sendhookact act;
 
-				act = (*Rhook)(nsap, buf, buflen,
+				act = (*Rhook)((struct sockaddr_in *)nsap,
+					       buf, buflen,
 					       ans, anssiz, &resplen);
 				switch (act) {
 				case res_goahead:
@@ -914,6 +973,7 @@
 		s = -1;
 		connected = 0;
 		vc = 0;
+		af = 0;
 	}
 }
 

----Next_Part(Fri_Jun_16_03:43:10_2000_697)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Description: My Signature
Content-Disposition: attachment; filename=".signature-world"

Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume@mahoroba.org  ume@bisd.hitachi.co.jp  ume@FreeBSD.org
http://www.imasy.org/~ume/

----Next_Part(Fri_Jun_16_03:43:10_2000_697)----


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000616.034310.74757991.ume>