Enable the use of all values for the 'flags' argument in NSPRPUB_RELEASE_4_0_BRANCH
authorsrinivas%netscape.com
Wed, 26 Jan 2000 01:07:48 +0000
branchNSPRPUB_RELEASE_4_0_BRANCH
changeset 1079 220d8b3fb55e869f10d8db77262b61cca5662b59
parent 1077 b2383c7689c88841d54fe52bcf095dc1abbb15aa
child 1080 11d7a7ecaf59e5a2f039f8c0d7264b324bc0bca4
push idunknown
push userunknown
push dateunknown
bugs24763
Enable the use of all values for the 'flags' argument in PR_GetIPNodeByName. For _PR_HAVE_GETHOSTBYNAME2 systems,include Ipv4-mapped Ipv6 addresses. Bugzilla 24763.
pr/include/prnetdb.h
pr/src/misc/prnetdb.c
--- a/pr/include/prnetdb.h
+++ b/pr/include/prnetdb.h
@@ -112,23 +112,21 @@ NSPR_API(PRStatus) PR_GetHostByName(
 **                      the function returns PR_SUCCESS. This structure
 **                      is allocated by the caller.
 ** RETURN:
 **  PRStatus            PR_SUCCESS if the lookup succeeds. If it fails
 **                      the result will be PR_FAILURE and the reason
 **                      for the failure can be retrieved by PR_GetError().
 ***********************************************************************/
 
-/*
- * #define PR_AI_ALL        0x08
- * #define PR_AI_V4MAPPED   0x10
- * #define PR_AI_ADDRCONFIG 0x20
- * #define PR_AI_DEFAULT    (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG)
- */
-#define PR_AI_DEFAULT 0x30
+
+#define PR_AI_ALL        0x08
+#define PR_AI_V4MAPPED   0x10
+#define PR_AI_ADDRCONFIG 0x20
+#define PR_AI_DEFAULT    (PR_AI_V4MAPPED | PR_AI_ADDRCONFIG)
 
 NSPR_API(PRStatus) PR_GetIPNodeByName(
     const char *hostname,
     PRUint16 af,
     PRIntn flags,
     char *buf,
     PRIntn bufsize,
     PRHostEnt *hostentry);
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -226,18 +226,18 @@ static void MakeIPv4CompatAddr(const cha
 }
 
 /*
 ** Copy a hostent, and all of the memory that it refers to into
 ** (hopefully) stacked buffers.
 */
 static PRStatus CopyHostent(
     struct hostent *from,
-    char *buf,
-    PRIntn bufsize,
+    char **buf,
+    PRIntn *bufsize,
     _PRIPAddrConversion conversion,
     PRHostEnt *to)
 {
 	PRIntn len, na;
 	char **ap;
 
 	if (conversion != _PRIPAddrNoConversion
 			&& from->h_addrtype == AF_INET) {
@@ -250,52 +250,52 @@ static PRStatus CopyHostent(
 		else
 			to->h_addrtype = from->h_addrtype;
 		to->h_length = from->h_length;
 	}
 
 	/* Copy the official name */
 	if (!from->h_name) return PR_FAILURE;
 	len = strlen(from->h_name) + 1;
-	to->h_name = Alloc(len, &buf, &bufsize, 0);
+	to->h_name = Alloc(len, buf, bufsize, 0);
 	if (!to->h_name) return PR_FAILURE;
 	memcpy(to->h_name, from->h_name, len);
 
 	/* Count the aliases, then allocate storage for the pointers */
 	if (!from->h_aliases) {
 		na = 1;
 	} else {
 		for (na = 1, ap = from->h_aliases; *ap != 0; na++, ap++){;} /* nothing to execute */
 	}
 	to->h_aliases = (char**)Alloc(
-	    na * sizeof(char*), &buf, &bufsize, sizeof(char**));
+	    na * sizeof(char*), buf, bufsize, sizeof(char**));
 	if (!to->h_aliases) return PR_FAILURE;
 
 	/* Copy the aliases, one at a time */
 	if (!from->h_aliases) {
 		to->h_aliases[0] = 0;
 	} else {
 		for (na = 0, ap = from->h_aliases; *ap != 0; na++, ap++) {
 			len = strlen(*ap) + 1;
-			to->h_aliases[na] = Alloc(len, &buf, &bufsize, 0);
+			to->h_aliases[na] = Alloc(len, buf, bufsize, 0);
 			if (!to->h_aliases[na]) return PR_FAILURE;
 			memcpy(to->h_aliases[na], *ap, len);
 		}
 		to->h_aliases[na] = 0;
 	}
 
 	/* Count the addresses, then allocate storage for the pointers */
 	for (na = 1, ap = from->h_addr_list; *ap != 0; na++, ap++){;} /* nothing to execute */
 	to->h_addr_list = (char**)Alloc(
-	    na * sizeof(char*), &buf, &bufsize, sizeof(char**));
+	    na * sizeof(char*), buf, bufsize, sizeof(char**));
 	if (!to->h_addr_list) return PR_FAILURE;
 
 	/* Copy the addresses, one at a time */
 	for (na = 0, ap = from->h_addr_list; *ap != 0; na++, ap++) {
-		to->h_addr_list[na] = Alloc(to->h_length, &buf, &bufsize, 0);
+		to->h_addr_list[na] = Alloc(to->h_length, buf, bufsize, 0);
 		if (!to->h_addr_list[na]) return PR_FAILURE;
 		if (conversion != _PRIPAddrNoConversion
 				&& from->h_addrtype == AF_INET) {
 			if (conversion == _PRIPAddrIPv4Mapped) {
 				MakeIPv4MappedAddr(*ap, to->h_addr_list[na]);
 			} else {
 				PR_ASSERT(conversion == _PRIPAddrIPv4Compat);
 				MakeIPv4CompatAddr(*ap, to->h_addr_list[na]);
@@ -408,17 +408,17 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName(
 	}
 	else
 	{
 		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
 #if defined(_PR_INET6)
 		if (_pr_ipv6_enabled)
 			conversion = _PRIPAddrIPv4Mapped;
 #endif
-		rv = CopyHostent(h, buf, bufsize, conversion, hp);
+		rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
 		if (PR_SUCCESS != rv)
 		    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 		freehostent(h);
 #endif
 	}
 	UNLOCK_DNS();
 #ifdef XP_UNIX
@@ -433,56 +433,60 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 {
 	struct hostent *h;
 	PRStatus rv = PR_FAILURE;
 #ifdef XP_UNIX
 	sigset_t oldset;
 #endif
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 	int error_num;
+	int tmp_flags = 0;
+#endif
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+    PRBool did_af_inet = PR_FALSE;
+    char **new_addr_list;
 #endif
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     PR_ASSERT(af == PR_AF_INET || af == PR_AF_INET6);
     if (af != PR_AF_INET && af != PR_AF_INET6) {
         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
         return PR_FAILURE;
     }
 
-    /*
-     * Flags other than PR_AI_DEFAULT are not yet supported.
-     */
-    PR_ASSERT(flags == PR_AI_DEFAULT);
-    if (flags != PR_AI_DEFAULT) {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return PR_FAILURE;
-    }
-
 #ifdef XP_UNIX
 	DISABLECLOCK(&oldset);
 #endif
 	LOCK_DNS();
 
 #ifdef _PR_INET6
 #ifdef _PR_HAVE_GETHOSTBYNAME2
     if (af == PR_AF_INET6)
     {
         h = gethostbyname2(name, AF_INET6); 
-        if (NULL == h)
+        if ((NULL == h) && (flags & (PR_AI_V4MAPPED|PR_AI_ALL)))
         {
+            did_af_inet = PR_TRUE;
             h = gethostbyname2(name, AF_INET);
         }
     }
     else
     {
+        did_af_inet = PR_TRUE;
         h = gethostbyname2(name, af);
     }
 #elif defined(_PR_HAVE_GETIPNODEBYNAME)
-    h = getipnodebyname(name, af, AI_DEFAULT, &error_num);
+	if (flags & PR_AI_V4MAPPED)
+		tmp_flags |= AI_V4MAPPED;
+	if (flags & PR_AI_ADDRCONFIG)
+		tmp_flags |= AI_ADDRCONFIG;
+	if (flags & PR_AI_ALL)
+		tmp_flags |= AI_ALL;
+    h = getipnodebyname(name, af, tmp_flags, &error_num);
 #else
 #error "Unknown name-to-address translation function"
 #endif
 #else /* _PR_INET6 */
 #ifdef XP_OS2_VACPP
 	h = gethostbyname((char *)name);
 #else
     h = gethostbyname(name);
@@ -497,23 +501,55 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 	    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
 #endif
 	}
 	else
 	{
 		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
 
 		if (af == PR_AF_INET6) conversion = _PRIPAddrIPv4Mapped;
-		rv = CopyHostent(h, buf, bufsize, conversion, hp);
+		rv = CopyHostent(h, &buf, &bufsize, conversion, hp);
 		if (PR_SUCCESS != rv)
 		    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 		freehostent(h);
 #endif
 	}
+#if defined(_PR_INET6) && defined(_PR_HAVE_GETHOSTBYNAME2)
+    if ((flags & PR_AI_ALL) && !did_af_inet &&
+						(h = gethostbyname2(name, AF_INET)) != 0) {
+        /* Append the V4 addresses to the end of the list */
+        PRIntn na, na_old;
+        char **ap;
+        
+        /* Count the addresses, then grow storage for the pointers */
+        for (na_old = 0, ap = hp->h_addr_list; *ap != 0; na_old++, ap++)
+				{;} /* nothing to execute */
+        for (na = na_old + 1, ap = h->h_addr_list; *ap != 0; na++, ap++)
+				{;} /* nothing to execute */
+        new_addr_list = (char**)Alloc(
+            na * sizeof(char*), &buf, &bufsize, sizeof(char**));
+        if (!new_addr_list) return PR_FAILURE;
+
+        /* Copy the V6 addresses, one at a time */
+        for (na = 0, ap = hp->h_addr_list; *ap != 0; na++, ap++) {
+            new_addr_list[na] = hp->h_addr_list[na];
+        }
+        hp->h_addr_list = new_addr_list;
+
+        /* Copy the V4 addresses, one at a time */
+        for (ap = h->h_addr_list; *ap != 0; na++, ap++) {
+            hp->h_addr_list[na] = Alloc(hp->h_length, &buf, &bufsize, 0);
+            if (!hp->h_addr_list[na]) return PR_FAILURE;
+            MakeIPv4MappedAddr(*ap, hp->h_addr_list[na]);
+        }
+        hp->h_addr_list[na] = 0;
+    }
+#endif
+
 	UNLOCK_DNS();
 #ifdef XP_UNIX
 	ENABLECLOCK(&oldset);
 #endif
 	return rv;
 }
 
 PR_IMPLEMENT(PRStatus) PR_GetHostByAddr(
@@ -576,17 +612,17 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByAddr(
 		if (hostaddr->raw.family == PR_AF_INET6) {
 			if (IN6_IS_ADDR_V4MAPPED((struct in6_addr*)addr)) {
 				conversion = _PRIPAddrIPv4Mapped;
 			} else if (IN6_IS_ADDR_V4COMPAT((struct in6_addr*)addr)) {
 				conversion = _PRIPAddrIPv4Compat;
 			}
 		}
 #endif
-		rv = CopyHostent(h, buf, bufsize, conversion, hostentry);
+		rv = CopyHostent(h, &buf, &bufsize, conversion, hostentry);
 		if (PR_SUCCESS != rv) {
 		    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
 		}
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
 		freehostent(h);
 #endif
 	}
 	UNLOCK_DNS();