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>
