Currently, there's no way for a user of getaddrinfo(3) to easily learn
about the results of DNS search path processing. There's the
AI_CANONNAME flag, but that additionally takes into account CNAME
processing, which is not always desirable.
I noticed the other day that Windows 7 (yes yes, laugh) added an
AI_FQDN flag that offers this behavior. It signals to the resolver to
set ai_canonname according to the expanded name *without* considering
CNAME records.
It turns out this is a fairly non-invasive change to getaddrinfo(3),
so I went ahead and put together a diff yesterday (at least for the
code; man page bits are still necessary).
Anyway, I'm interested in knowing what people think of adding this
feature. I don't know of any other getaddrinfo(3) implementations
that support it, but djm@ mentioned that it would be nice to have in
OpenSSH for host key validation.
Index: include/netdb.h
===================================================================
RCS file: /cvs/src/include/netdb.h,v
retrieving revision 1.27
diff -u -p include/netdb.h
--- include/netdb.h 2 Jun 2009 16:47:50 -0000 1.27
+++ include/netdb.h 1 Apr 2011 01:48:24 -0000
@@ -155,9 +155,10 @@ struct protoent {
#define AI_NUMERICHOST 4 /* don't ever try hostname lookup */
#define AI_EXT 8 /* enable non-portable extensions */
#define AI_NUMERICSERV 16 /* don't ever try servname lookup */
+#define AI_FQDN 32 /* return the FQDN that was resolved */
/* valid flags for addrinfo */
#define AI_MASK \
- (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV)
+ (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_FQDN)
#define NI_NUMERICHOST 1 /* return the host address, not the name */
#define NI_NUMERICSERV 2 /* return the service address, not the name */
Index: lib/libc/net/getaddrinfo.c
===================================================================
RCS file: /cvs/src/lib/libc/net/getaddrinfo.c,v
retrieving revision 1.71
diff -u -p lib/libc/net/getaddrinfo.c
--- lib/libc/net/getaddrinfo.c 18 Nov 2009 07:43:22 -0000 1.71
+++ lib/libc/net/getaddrinfo.c 1 Apr 2011 01:48:24 -0000
@@ -309,7 +309,9 @@ getaddrinfo(const char *hostname, const char *servname
if (hints->ai_addrlen || hints->ai_canonname ||
hints->ai_addr || hints->ai_next)
ERR(EAI_BADHINTS); /* xxx */
- if (hints->ai_flags & ~AI_MASK)
+ if ((hints->ai_flags & ~AI_MASK) != 0 ||
+ (hints->ai_flags & (AI_CANONNAME | AI_FQDN)) ==
+ (AI_CANONNAME | AI_FQDN))
ERR(EAI_BADFLAGS);
switch (hints->ai_family) {
case PF_UNSPEC:
@@ -671,14 +673,13 @@ explore_numeric(const struct addrinfo *pai, const char
pai->ai_family == PF_UNSPEC /*?*/) {
GET_AI(cur->ai_next, afd, pton);
GET_PORT(cur->ai_next, servname);
- if ((pai->ai_flags & AI_CANONNAME)) {
- /*
- * Set the numeric address itself as
- * the canonical name, based on a
- * clarification in rfc2553bis-03.
- */
- GET_CANONNAME(cur->ai_next, canonname);
- }
+ /*
+ * Set the numeric address itself as
+ * the canonical name, based on a
+ * clarification in rfc2553bis-03.
+ */
+ GET_CANONNAME(cur->ai_next, canonname);
+
while (cur && cur->ai_next)
cur = cur->ai_next;
} else
@@ -764,7 +765,7 @@ explore_numeric_scope(const struct addrinfo *pai, cons
static int
get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
{
- if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ if ((pai->ai_flags & (AI_CANONNAME | AI_FQDN)) != 0) {
ai->ai_canonname = strdup(str);
if (ai->ai_canonname == NULL)
return EAI_MEMORY;
@@ -1129,7 +1130,7 @@ getanswer(const querybuf *answer, int anslen, const ch
haveanswer++;
}
if (haveanswer) {
- if (!canonname)
+ if (!canonname || (pai->ai_flags & AI_FQDN) != 0)
(void)get_canonname(pai, sentinel.ai_next, qname);
else
(void)get_canonname(pai, sentinel.ai_next, canonname);
@@ -1275,11 +1276,9 @@ found:
/* cover it up */
res->ai_flags = pai->ai_flags;
- if (pai->ai_flags & AI_CANONNAME) {
- if (get_canonname(pai, res, cname) != 0) {
- freeaddrinfo(res0);
- goto again;
- }
+ if (get_canonname(pai, res, cname) != 0) {
+ freeaddrinfo(res0);
+ goto again;
}
}
return res0;
@@ -1369,8 +1368,7 @@ nextline:
/* cover it up */
res->ai_flags = pai->ai_flags;
- if (pai->ai_flags & AI_CANONNAME)
- (void)get_canonname(pai, res, canonname);
+ (void)get_canonname(pai, res, canonname);
}
} else
res0 = NULL;