summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/head/netdb.h5
-rw-r--r--usr/src/lib/libnsl/nss/getipnodeby.c26
-rw-r--r--usr/src/lib/libsocket/inet/getaddrinfo.c13
3 files changed, 41 insertions, 3 deletions
diff --git a/usr/src/head/netdb.h b/usr/src/head/netdb.h
index b26c26d40b..8d8a6a8b80 100644
--- a/usr/src/head/netdb.h
+++ b/usr/src/head/netdb.h
@@ -123,7 +123,10 @@ struct addrinfo {
struct addrinfo *ai_next; /* next structure in linked list */
};
-
+/*
+ * The flag 0x8000 is currently reserved for private use between libnsl and
+ * libsocket. See lib/libsocket/inet/getaddrinfo.c for more information.
+ */
/* addrinfo flags */
#define AI_PASSIVE 0x0008 /* intended for bind() + listen() */
#define AI_CANONNAME 0x0010 /* return canonical version of host */
diff --git a/usr/src/lib/libnsl/nss/getipnodeby.c b/usr/src/lib/libnsl/nss/getipnodeby.c
index 112b54ec5a..f84b641157 100644
--- a/usr/src/lib/libnsl/nss/getipnodeby.c
+++ b/usr/src/lib/libnsl/nss/getipnodeby.c
@@ -73,6 +73,8 @@
* IPNODE_LOOKUPIPNODES getipnodebyname() needs to lookup the name in ipnodes.
* IPNODE_LOOKUPHOSTS getipnodebyname() needs to lookup the name in hosts.
* IPNODE_ISLITERAL The name supplied is a literal address string.
+ * IPNODE_UNMAP The user doesn't want v4 mapped addresses if no IPv6
+ * interfaces are plumbed on the system.
*/
#define IPNODE_WANTIPV6 0x00000001u
#define IPNODE_WANTIPV4 0x00000002u
@@ -80,9 +82,16 @@
#define IPNODE_LOOKUPIPNODES 0x00000008u
#define IPNODE_LOOKUPHOSTS 0x00000010u
#define IPNODE_LITERAL 0x00000020u
+#define IPNODE_UNMAP 0x00000040u
#define IPNODE_IPV4 (IPNODE_WANTIPV4 | IPNODE_IPV4IFNOIPV6)
/*
+ * The private flag between libsocket and libnsl. See
+ * lib/libsocket/inet/getaddrinfo.c for more information.
+ */
+#define AI_ADDRINFO 0x8000
+
+/*
* The default set of bits corresponding to a getipnodebyname() flags
* argument of AI_DEFAULT.
*/
@@ -162,6 +171,10 @@ getipnodebyname_processflags(const char *name, int af, int flags)
} else if (flags & AI_ALL) {
ipnode_bits &= ~IPNODE_IPV4IFNOIPV6;
}
+ if ((flags & AI_ADDRCONFIG) && !ipv6configured &&
+ (flags & AI_ADDRINFO)) {
+ ipnode_bits |= IPNODE_UNMAP;
+ }
} else {
ipnode_bits &= ~IPNODE_IPV4;
}
@@ -343,7 +356,18 @@ getipnodebyname(const char *name, int af, int flags, int *error_num)
else if (!(ipnode_bits & IPNODE_WANTIPV6))
hp = __filter_addresses(AF_INET6, buf6->result);
- if (hp == NULL)
+ /*
+ * We've been asked to unmap v4 addresses. This
+ * situation implies IPNODE_WANTIPV4 and
+ * !IPNODE_WANTIPV6.
+ */
+ if (hp != NULL && (ipnode_bits & IPNODE_UNMAP)) {
+ /*
+ * Just set hp to a new value, cleanup: will
+ * free the old one
+ */
+ hp = __mappedtov4(hp, error_num);
+ } else if (hp == NULL)
*error_num = NO_ADDRESS;
}
diff --git a/usr/src/lib/libsocket/inet/getaddrinfo.c b/usr/src/lib/libsocket/inet/getaddrinfo.c
index ec72a9974e..99b769e41e 100644
--- a/usr/src/lib/libsocket/inet/getaddrinfo.c
+++ b/usr/src/lib/libsocket/inet/getaddrinfo.c
@@ -69,6 +69,17 @@ const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST \
| AI_ADDRCONFIG | AI_NUMERICSERV | AI_V4MAPPED | AI_ALL)
#define ANY 0
+
+/*
+ * This is a private, undocumented, flag that getaddrinfo() uses for
+ * getipnodebyname(). In the case of AI_ADDRCONFIG && AI_V4MAPPED, if there are
+ * no IPv6 addresses, getaddrinfo() should return non-IPv4 mapped addresses. On
+ * the flip side, getipnodebyname() is defined by RFC 2553 to explicitly do so.
+ * Therefore this private flag indicates to getaddrinfo that we shouldn't do
+ * this.
+ */
+#define AI_ADDRINFO 0x8000
+
/* function prototypes for used by getaddrinfo() routine */
static int get_addr(int family, const char *hostname, struct addrinfo *aip,
struct addrinfo *cur, ushort_t port, int version);
@@ -602,7 +613,7 @@ get_addr(int family, const char *hostname, struct addrinfo *aip, struct
/* if hostname argument is literal, name service doesn't get called */
if (family == PF_UNSPEC) {
hp = getipnodebyname(_hostname, AF_INET6, AI_ALL |
- aip->ai_flags | AI_V4MAPPED, &errnum);
+ aip->ai_flags | AI_V4MAPPED | AI_ADDRINFO, &errnum);
} else {
hp = getipnodebyname(_hostname, family, aip->ai_flags, &errnum);
}