Modified PR_IsNetAddrType to recognize Ipv4-mapped loopback and unspecified NSPRPUB_RELEASE_4_0_BRANCH
authorsrinivas%netscape.com
Wed, 26 Jan 2000 22:50:34 +0000
branchNSPRPUB_RELEASE_4_0_BRANCH
changeset 1098 2fe6994a1592eea21e8889c341237d894edd12aa
parent 1094 8115e504809f832393a49c3ae94499b0179c390e
child 1099 e383e69269014ca7621a83150884efea602feeac
push idunknown
push userunknown
push dateunknown
bugs24906
Modified PR_IsNetAddrType to recognize Ipv4-mapped loopback and unspecified addresses. Bugzilla #24906.
pr/src/misc/prnetdb.c
pr/tests/gethost.c
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -93,39 +93,61 @@ static sigset_t timer_set;
 
 #if !defined(_PR_HAVE_GETPROTO_R)
 PRLock* _getproto_lock = NULL;
 #endif
 
 #if defined(_PR_INET6)
 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#define _PR_IN6_IS_ADDR_UNSPECIFIED	IN6_IS_ADDR_UNSPECIFIED
+#define _PR_IN6_IS_ADDR_LOOPBACK	IN6_IS_ADDR_LOOPBACK
 #define _PR_IN6_IS_ADDR_V4MAPPED	IN6_IS_ADDR_V4MAPPED
 #define _PR_IN6_IS_ADDR_V4COMPAT	IN6_IS_ADDR_V4COMPAT
 
+#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->s6_addr32[3])
+
 #else  /* _PR_INET6 */
 
 /*
  * The values at bytes 10 and 11 are compared using pointers to
  * 8-bit fields, and not 32-bit fields, to make the comparison work on
  * both big-endian and little-endian systems
-*/
-#define _PR_IN6_IS_ADDR_V4MAPPED(a)		\
+ */
+
+#define _PR_IN6_IS_ADDR_UNSPECIFIED(a)			\
+				(((a)->_pr_s6_addr32[0] == 0) &&	\
+				((a)->_pr_s6_addr32[1] == 0) &&		\
+				((a)->_pr_s6_addr32[2] == 0) &&		\
+				((a)->_pr_s6_addr32[3] == 0))
+ 
+#define _PR_IN6_IS_ADDR_LOOPBACK(a)				\
+               (((a)->_pr_s6_addr32[0] == 0)	&&	\
+               ((a)->_pr_s6_addr32[1] == 0)		&&	\
+               ((a)->_pr_s6_addr32[2] == 0)		&&	\
+               ((a)->_pr_s6_addr[12] == 0)		&&	\
+               ((a)->_pr_s6_addr[13] == 0)		&&	\
+               ((a)->_pr_s6_addr[14] == 0)		&&	\
+               ((a)->_pr_s6_addr[15] == 0x01))
+ 
+#define _PR_IN6_IS_ADDR_V4MAPPED(a)			\
 		(((a)->_pr_s6_addr32[0] == 0) 	&&	\
 		((a)->_pr_s6_addr32[1] == 0)	&&	\
 		((a)->_pr_s6_addr[8] == 0)		&&	\
 		((a)->_pr_s6_addr[9] == 0)		&&	\
 		((a)->_pr_s6_addr[10] == 0xff)	&&	\
 		((a)->_pr_s6_addr[11] == 0xff))
 
 #define _PR_IN6_IS_ADDR_V4COMPAT(a)			\
-		(((a)->_pr_s6_addr32[0] == 0) &&		\
-		((a)->_pr_s6_addr32[1] == 0) &&			\
+		(((a)->_pr_s6_addr32[0] == 0) &&	\
+		((a)->_pr_s6_addr32[1] == 0) &&		\
 		((a)->_pr_s6_addr32[2] == 0))
 
+#define _PR_IN6_V4MAPPED_TO_IPADDR(a) ((a)->_pr_s6_addr32[3])
+
 #endif /* _PR_INET6 */
 
 extern PRStatus _pr_init_ipv6();
 
 void _PR_InitNet(void)
 {
 #if defined(XP_UNIX)
 #ifdef HAVE_NETCONFIG
@@ -933,48 +955,38 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr(
 }  /* PR_SetNetAddr */
 
 extern void ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr,
                                             PRNetAddr *dst_v4addr);
 
 PR_IMPLEMENT(PRBool)
 PR_IsNetAddrType(const PRNetAddr *addr, PRNetAddrValue val)
 {
-#if defined(_PR_INET6)
     if (addr->raw.family == PR_AF_INET6) {
-        if (val == PR_IpAddrAny
-                && IN6_IS_ADDR_UNSPECIFIED((struct in6_addr*)&addr->ipv6.ip)) {
-            return PR_TRUE;
-        } else if (val == PR_IpAddrLoopback
-                && IN6_IS_ADDR_LOOPBACK((struct in6_addr*)&addr->ipv6.ip)) {
-            return PR_TRUE;
-        } else if (val == PR_IpAddrV4Mapped
-                && IN6_IS_ADDR_V4MAPPED((struct in6_addr*)&addr->ipv6.ip)) {
-            return PR_TRUE;
-        }
-    }
-    else
-#else
-	PRNetAddr tmp_ipv4addr;
-
-    if (addr->raw.family == PR_AF_INET6) {
-		ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
-		if (val == PR_IpAddrAny && tmp_ipv4addr.inet.ip == htonl(INADDR_ANY)) {
-			return PR_TRUE;
-		} else if (val == PR_IpAddrLoopback
-				&& tmp_ipv4addr.inet.ip == htonl(INADDR_LOOPBACK)) {
-			return PR_TRUE;
+        if (val == PR_IpAddrAny) {
+			if (_PR_IN6_IS_ADDR_UNSPECIFIED((PRIPv6Addr *)&addr->ipv6.ip)) {
+            	return PR_TRUE;
+			} else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)
+					&& _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip)
+							== htonl(INADDR_ANY)) {
+            	return PR_TRUE;
+			}
+        } else if (val == PR_IpAddrLoopback) {
+            if (_PR_IN6_IS_ADDR_LOOPBACK((PRIPv6Addr *)&addr->ipv6.ip)) {
+            	return PR_TRUE;
+			} else if (_PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)
+					&& _PR_IN6_V4MAPPED_TO_IPADDR((PRIPv6Addr *)&addr->ipv6.ip)
+							== htonl(INADDR_LOOPBACK)) {
+            	return PR_TRUE;
+			}
         } else if (val == PR_IpAddrV4Mapped
                 && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) {
             return PR_TRUE;
         }
-    }
-    else
-#endif
-    {
+    } else {
         if (addr->raw.family == AF_INET) {
             if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) {
                 return PR_TRUE;
             } else if (val == PR_IpAddrLoopback
                     && addr->inet.ip == htonl(INADDR_LOOPBACK)) {
                 return PR_TRUE;
             }
         }
--- a/pr/tests/gethost.c
+++ b/pr/tests/gethost.c
@@ -121,19 +121,44 @@ int main(int argc, char **argv)
     PrintHostent(&he);
     printf("PR_GetIPNodeByName with PR_AF_INET6\n");
     if (PR_GetIPNodeByName(hostName, PR_AF_INET6, PR_AI_DEFAULT,
             buf, sizeof(buf), &he) == PR_FAILURE) {
         fprintf(stderr, "PR_GetIPNodeByName failed\n");
         exit(1);
     }
     PrintHostent(&he);
-
+#ifdef _PR_INET6
     PR_StringToNetAddr("::1", &addr);
+    if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_TRUE) {
+        fprintf(stderr, "addr should not be ipv4 mapped address\n");
+        exit(1);
+    }
+    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+        fprintf(stderr, "addr should be loopback address\n");
+        exit(1);
+    }
+#endif
+
     PR_StringToNetAddr("127.0.0.1", &addr);
+    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+        fprintf(stderr, "addr should be loopback address\n");
+        exit(1);
+    }
+#ifdef _PR_INET6
+    PR_StringToNetAddr("::FFFF:127.0.0.1", &addr);
+    if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped) == PR_FALSE) {
+        fprintf(stderr, "addr should be ipv4 mapped address\n");
+        exit(1);
+    }
+    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
+        fprintf(stderr, "addr should be loopback address\n");
+        exit(1);
+    }
+#endif
 
     if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
         fprintf(stderr, "PR_InitializeNetAddr failed\n");
         exit(1);
     }
     if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
         fprintf(stderr, "addr should be unspecified address\n");
         exit(1);