Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 24 Jul 2001 03:23:44 +0900 (JST)
From:      Hajimu UMEMOTO <ume@mahoroba.org>
To:        brian@Awfulhak.org
Cc:        brian@FreeBSD.org, cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/lib/libutil realhostname.c 
Message-ID:  <20010724.032344.71142385.ume@mahoroba.org>
In-Reply-To: <200107230040.f6N0efg12288@hak.lan.Awfulhak.org>
References:  <ume@mahoroba.org> <200107230040.f6N0efg12288@hak.lan.Awfulhak.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,

>>>>> On Mon, 23 Jul 2001 01:40:40 +0100
>>>>> Brian Somers <brian@Awfulhak.org> said:

brian> It seems to me that realhostname_sa() already has to deal specially 
brian> with ipv4 mapped ipv6 addresses.  Surely the correct answer is to 
brian> special-case such addresses in the getaddrinfo() hints (see the 
brian> attached patch - based on what's in -current at the moment).

It seems working for IPv4 mapped IPv6 address to me.  However, I still
cannot understand why changing AF_UNSPEC to AF_INET6 solves your
problem.  If AF_INET6 returns FQDN, I think AF_UNSPEC also returns
FQDN.

brian> The only alternative that I can think of is to have getaddrinfo() 
brian> with a hint of AF_UNSPEC end up finding all A and AAAA records.  If 
brian> it returns only one type of address, then it can't satisfy both the 
brian> ipv4 mapped address case *and* the normal ipv6 case (as per my 
brian> fec0::* addresses that I mentioned before).

It is actually expected behavior of getaddrinfo().  It seems working
so for global, and I could not find special case for site-local in
getaddrinfo().

In anyway, existing realhostname_sa() is too complex around handling
IPv4 mapped IPv6 address.  I propose to simplify it.  Here is a patch
from -current.

Index: lib/libutil/realhostname.c
===================================================================
RCS file: /home/ncvs/src/lib/libutil/realhostname.c,v
retrieving revision 1.12
diff -u -r1.12 realhostname.c
--- lib/libutil/realhostname.c	2001/07/21 00:18:54	1.12
+++ lib/libutil/realhostname.c	2001/07/23 17:53:51
@@ -93,31 +93,47 @@
 {
 	int result, error;
 	char buf[NI_MAXHOST];
+	struct sockaddr_in sin;
 
 	result = HOSTNAME_INVALIDADDR;
 
-	error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, 0);
+#ifdef INET6
+	/* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
+	if (addr->sa_family == AF_INET6 &&
+	    addrlen == sizeof(struct sockaddr_in6) &&
+	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) {
+		struct sockaddr_in6 *sin6;
+
+		sin6 = (struct sockaddr_in6 *)addr;
+
+		memset(&sin, 0, sizeof(sin));
+		sin.sin_len = sizeof(struct sockaddr_in);
+		sin.sin_family = AF_INET;
+		sin.sin_port = sin6->sin6_port;
+		memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+		       sizeof(struct in_addr));
+		addr = (struct sockaddr *)&sin;
+		addrlen = sin.sin_len;
+	}
+#endif
+
+	error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
+			    NI_WITHSCOPEID);
 	if (error == 0) {
 		struct addrinfo hints, *res, *ores;
 		struct sockaddr *sa;
 
 		memset(&hints, 0, sizeof(struct addrinfo));
-		switch (addr->sa_family) {
-		case AF_INET:
-		case AF_INET6:
-			hints.ai_family = addr->sa_family;
-			break;
-		default:
-			hints.ai_family = AF_UNSPEC;
-			break;
-		}
-		hints.ai_flags = AI_CANONNAME;
+		hints.ai_family = addr->sa_family;
+		hints.ai_flags = AI_CANONNAME | AI_PASSIVE;
+		hints.ai_socktype = SOCK_STREAM;
 
 		error = getaddrinfo(buf, NULL, &hints, &res);
 		if (error) {
 			result = HOSTNAME_INVALIDNAME;
 			goto numeric;
-		} else for (ores = res; ; res = res->ai_next) {
+		}
+		for (ores = res; ; res = res->ai_next) {
 			if (res == NULL) {
 				freeaddrinfo(ores);
 				result = HOSTNAME_INCORRECTNAME;
@@ -131,15 +147,19 @@
 			}
 			if (sa->sa_len == addrlen &&
 			    sa->sa_family == addr->sa_family) {
-				u_int16_t port;
-
-				port = ((struct sockinet *)addr)->si_port;
-				((struct sockinet *)addr)->si_port = 0;
+				((struct sockinet *)sa)->si_port = ((struct sockinet *)addr)->si_port;
+#ifdef INET6
+				/*
+				 * XXX: sin6_socpe_id may not been
+				 * filled by DNS
+				 */
+				if (sa->sa_family == AF_INET6 &&
+				    ((struct sockaddr_in6 *)sa)->sin6_scope_id == 0)
+					((struct sockaddr_in6 *)sa)->sin6_scope_id = ((struct sockaddr_in6 *)addr)->sin6_scope_id;
+#endif
 				if (!memcmp(sa, addr, sa->sa_len)) {
 					result = HOSTNAME_FOUND;
-					((struct sockinet *)addr)->si_port =
-						port;
-					if (ores->ai_canonname == 0) {
+					if (ores->ai_canonname == NULL) {
 						freeaddrinfo(ores);
 						goto numeric;
 					}
@@ -154,58 +174,11 @@
 					strncpy(host, buf, hsize);
 					break;
 				}
-				((struct sockinet *)addr)->si_port = port;
-			}
-#ifdef INET6
-			/*
-			 * XXX IPv4 mapped IPv6 addr consideraton,
-			 * specified in rfc2373.
-			 */
-			if (sa->sa_family == AF_INET &&
-			    addr->sa_family == AF_INET6) {
-				struct in_addr *in;
-				struct in6_addr *in6;
-
-				in = &((struct sockaddr_in *)sa)->sin_addr;
-				in6 = &((struct sockaddr_in6 *)addr)->sin6_addr;
-				if (IN6_IS_ADDR_V4MAPPED(in6) &&
-				    !memcmp(&in6->s6_addr[12], in,
-					    sizeof(*in))) {
-					result = HOSTNAME_FOUND;
-					if (ores->ai_canonname == 0 ||
-					    strlen(ores->ai_canonname) > hsize) {
-						freeaddrinfo(ores);
-						goto numeric;
-					}
-					strncpy(host, ores->ai_canonname,
-						hsize);
-					break;
-				}
 			}
-#endif
 		}
 		freeaddrinfo(ores);
 	} else {
-		struct sockaddr_in sin;
     numeric:
-#ifdef INET6
-		if (addr->sa_family == AF_INET6) {
-			struct sockaddr_in6 *sin6;
-
-			sin6 = (struct sockaddr_in6 *)addr;
-			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
-				memset(&sin, 0, sizeof(sin));
-				sin.sin_len = sizeof(struct sockaddr_in);
-				sin.sin_family = AF_INET;
-				sin.sin_port = sin6->sin6_port;
-				memcpy(&sin.sin_addr,
-				       &sin6->sin6_addr.s6_addr[12],
-				       sizeof(struct in_addr));
-				addr = (struct sockaddr *)&sin;
-				addrlen = sin.sin_len;
-			}
-		}
-#endif
 		if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
 				NI_NUMERICHOST|NI_WITHSCOPEID) == 0)
 			strncpy(host, buf, hsize);

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

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?20010724.032344.71142385.ume>