Hi,
I don't like AI_ADDRCONFIG. It's useless as specified, and making it
useful requires interpretations and deviations.
My understanding is that its goal is to solve a real world problem,
as in avoiding useless and potentially harmful DNS requests. So why not
make it do that, and just that? Because I don't think the end goal is
preventing IPv6 link-local communication, or communication with ::1 or
"localhost", etc.
What do you folks think?
The diff below seems to work well, as a bonus it avoids changing the
hints passed by the caller, and extends the use of local variable "ai"
("ai" could probably be renamed to "hints", btw).
Index: asr/getaddrinfo_async.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/getaddrinfo_async.c,v
retrieving revision 1.27
diff -u -p -r1.27 getaddrinfo_async.c
--- asr/getaddrinfo_async.c 28 Apr 2014 21:38:59 -0000 1.27
+++ asr/getaddrinfo_async.c 2 May 2014 06:25:03 -0000
@@ -129,7 +129,7 @@ getaddrinfo_async_run(struct asr_query *
#endif
char fqdn[MAXDNAME];
const char *str;
- struct addrinfo *ai;
+ struct addrinfo *ai, *saved_ai, addrconfig_hints;
int i, family, r, v4, v6;
FILE *f;
struct ifaddrs *ifa, *ifa0;
@@ -157,7 +157,7 @@ getaddrinfo_async_run(struct asr_query *
break;
}
- ai = &as->as.ai.hints;
+ ai = saved_ai = &as->as.ai.hints;
if (ai->ai_addrlen ||
ai->ai_canonname ||
@@ -219,17 +219,12 @@ getaddrinfo_async_run(struct asr_query *
v6 = 1;
}
freeifaddrs(ifa0);
- if (ai->ai_family == PF_UNSPEC && !v4 && !v6 ||
- ai->ai_family == PF_INET && !v4 ||
- ai->ai_family == PF_INET6 && !v6) {
- ar->ar_gai_errno = EAI_NONAME;
- async_set_state(as, ASR_STATE_HALT);
- break;
- }
+
+ memcpy(&addrconfig_hints, ai, sizeof(addrconfig_hints));
if (ai->ai_family == PF_UNSPEC && v4 && !v6)
- ai->ai_family = PF_INET;
+ addrconfig_hints.ai_family = PF_INET;
if (ai->ai_family == PF_UNSPEC && !v4 && v6)
- ai->ai_family = PF_INET6;
+ addrconfig_hints.ai_family = PF_INET6;
}
/* Make sure there is at least a valid combination */
@@ -246,10 +241,10 @@ getaddrinfo_async_run(struct asr_query *
if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_UDP)
as->as.ai.port_udp = get_port(as->as.ai.servname, "udp",
- as->as.ai.hints.ai_flags & AI_NUMERICSERV);
+ ai->ai_flags & AI_NUMERICSERV);
if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_TCP)
as->as.ai.port_tcp = get_port(as->as.ai.servname, "tcp",
- as->as.ai.hints.ai_flags & AI_NUMERICSERV);
+ ai->ai_flags & AI_NUMERICSERV);
if (as->as.ai.port_tcp == -2 || as->as.ai.port_udp == -2 ||
(as->as.ai.port_tcp == -1 && as->as.ai.port_udp == -1) ||
(ai->ai_protocol && (as->as.ai.port_udp == -1 ||
@@ -322,13 +317,24 @@ getaddrinfo_async_run(struct asr_query *
async_set_state(as, ASR_STATE_NOT_FOUND);
break;
}
+ ai = saved_ai;
+ /* AF filtering is only for dns */
+ if (ai->ai_flags & AI_ADDRCONFIG && AS_DB(as) == ASR_DB_DNS) {
+ if (ai->ai_family == PF_UNSPEC && !v4 && !v6 ||
+ ai->ai_family == PF_INET && !v4 ||
+ ai->ai_family == PF_INET6 && !v6) {
+ async_set_state(as, ASR_STATE_NEXT_DB);
+ break;
+ }
+ ai = &addrconfig_hints;
+ }
as->as_family_idx = 0;
async_set_state(as, ASR_STATE_SAME_DB);
break;
case ASR_STATE_NEXT_FAMILY:
as->as_family_idx += 1;
- if (as->as.ai.hints.ai_family != AF_UNSPEC ||
+ if (ai->ai_family != AF_UNSPEC ||
AS_FAMILY(as) == -1) {
/* The family was specified, or we have tried all
* families with this DB.
@@ -384,8 +390,8 @@ getaddrinfo_async_run(struct asr_query *
break;
}
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
+ family = (ai->ai_family == AF_UNSPEC) ?
+ AS_FAMILY(as) : ai->ai_family;
as->as.ai.subq = res_query_async_ctx(as->as.ai.fqdn,
C_IN, (family == AF_INET6) ? T_AAAA : T_A,
@@ -408,8 +414,8 @@ getaddrinfo_async_run(struct asr_query *
async_set_state(as, ASR_STATE_NEXT_DB);
break;
}
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
+ family = (ai->ai_family == AF_UNSPEC) ?
+ AS_FAMILY(as) : ai->ai_family;
r = addrinfo_from_file(as, family, f);
if (r == -1) {
@@ -429,8 +435,8 @@ getaddrinfo_async_run(struct asr_query *
async_set_state(as, ASR_STATE_NEXT_DB);
break;
}
- family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
- AS_FAMILY(as) : as->as.ai.hints.ai_family;
+ family = (ai->ai_family == AF_UNSPEC) ?
+ AS_FAMILY(as) : ai->ai_family;
name = as->as.ai.hostname;
Index: net/getaddrinfo.3
===================================================================
RCS file: /cvs/src/lib/libc/net/getaddrinfo.3,v
retrieving revision 1.55
diff -u -p -r1.55 getaddrinfo.3
--- net/getaddrinfo.3 28 Apr 2014 21:38:59 -0000 1.55
+++ net/getaddrinfo.3 2 May 2014 06:50:01 -0000
@@ -123,9 +123,10 @@ the following values:
.It Dv AI_ADDRCONFIG
If the
.Dv AI_ADDRCONFIG
-bit is set, IPv4 addresses will be returned only if an IPv4 address is
-configured on an interface, and IPv6 addresses will be returned only if an IPv6
-address is configured on an interface.
+bit is set, DNS requests for IPv4 addresses will be performed only if an
+IPv4 address is configured on an interface, and DNS requetsts for IPv6
+addresses will be performed only if an IPv6 address is configured on an
+interface.
Addresses on a loopback interface and link-local IPv6 addresses are not
considered valid as configured addresses.
.It Dv AI_CANONNAME
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE