Add Ipv6 support for non-Ipv6 platforms. Bugzilla 23815. NSPRPUB_RELEASE_4_0_BRANCH
authorsrinivas%netscape.com
Tue, 25 Jan 2000 18:01:19 +0000
branchNSPRPUB_RELEASE_4_0_BRANCH
changeset 1077 b2383c7689c88841d54fe52bcf095dc1abbb15aa
parent 1074 076063ccaa48edad522318d144b61264dfb39fbb
child 1079 220d8b3fb55e869f10d8db77262b61cca5662b59
push idunknown
push userunknown
push dateunknown
bugs23815
Add Ipv6 support for non-Ipv6 platforms. Bugzilla 23815.
pr/include/prio.h
pr/include/prnetdb.h
pr/src/Makefile
pr/src/io/Makefile
pr/src/io/pripv6.c
pr/src/io/prsocket.c
pr/src/misc/prnetdb.c
pr/src/pthreads/ptio.c
pr/tests/cltsrv.c
pr/tests/gethost.c
--- a/pr/include/prio.h
+++ b/pr/include/prio.h
@@ -99,41 +99,63 @@ typedef enum PRTransmitFileFlags {
 #define PR_INADDR_ANY (unsigned long)0x00000000
 #define PR_INADDR_LOOPBACK 0x7f000001
 #define PR_INADDR_BROADCAST (unsigned long)0xffffffff
 
 #else /* WIN32 */
 
 #define PR_AF_INET AF_INET
 #define PR_AF_LOCAL AF_UNIX
-#ifdef AF_INET6
-#define PR_AF_INET6 AF_INET6
-#endif
 #define PR_INADDR_ANY INADDR_ANY
 #define PR_INADDR_LOOPBACK INADDR_LOOPBACK
 #define PR_INADDR_BROADCAST INADDR_BROADCAST
 
 #endif /* WIN32 */
 
+#define PR_AF_INET6 100
 /*
 **************************************************************************
 ** A network address
 **
 ** Only Internet Protocol (IPv4 and IPv6) addresses are supported.
 ** The address family must always represent IPv4 (AF_INET, probably == 2)
 ** or IPv6 (AF_INET6).
 **************************************************************************
 *************************************************************************/
 #if defined(_PR_INET6)
 
 #if !defined(AF_INET6)
 #error "AF_INET6 is not defined"
 #endif
 
 typedef struct in6_addr PRIPv6Addr;
+typedef struct sockaddr_in6 _pr_sockaddr_in6_t;
+
+#else
+
+struct _pr_in6_addr {
+	union {
+		PRUint8  _S6_u8[16];
+		PRUint32 _S6_u32[4];
+		PRUint64 _S6_u64[2];
+	} _S6_un;
+};
+#define s6_addr		_S6_un._S6_u8
+#define s6_addr32	_S6_un._S6_u32
+#define s6_addr64 	_S6_un._S6_addr64
+
+typedef struct _pr_in6_addr PRIPv6Addr;
+struct _pr_sockaddr_in6 {
+    PRUint16     		sin6_family;    /* AF_INET6 */
+    PRUint16       		sin6_port;      /* transport layer port # */
+    PRUint32        	sin6_flowinfo;  /* IPv6 traffic class & flow info */
+    struct _pr_in6_addr sin6_addr;      /* IPv6 address */
+    PRUint32        	sin6_scope_id;  /* set of interfaces for a scope */
+};
+typedef struct _pr_sockaddr_in6 _pr_sockaddr_in6_t;
 
 #endif /* defined(_PR_INET6) */
 
 union PRNetAddr {
     struct {
         PRUint16 family;                /* address family (0x00ff maskable) */
 #ifdef XP_BEOS
         char data[10];                  /* Be has a smaller structure */
@@ -146,25 +168,23 @@ union PRNetAddr {
         PRUint16 port;                  /* port number */
         PRUint32 ip;                    /* The actual 32 bits of address */
 #ifdef XP_BEOS
         char pad[4];                    /* Be has a smaller structure */
 #else
         char pad[8];
 #endif
     } inet;
-#if defined(_PR_INET6)
     struct {
         PRUint16 family;                /* address family (AF_INET6) */
         PRUint16 port;                  /* port number */
         PRUint32 flowinfo;              /* routing information */
         PRIPv6Addr ip;                  /* the actual 128 bits of address */
         PRUint32 scope_id;              /* set of interfaces for a scope */
     } ipv6;
-#endif /* defined(_PR_INET6) */
 #if defined(XP_UNIX)
     struct {                            /* Unix domain socket address */
         PRUint16 family;                /* address family (AF_UNIX) */
         char path[104];                 /* null-terminated pathname */
     } local;
 #endif
 };
 
@@ -176,22 +196,27 @@ union PRNetAddr {
 
 #if defined(_PR_INET6)
 
 #define PR_NETADDR_SIZE(_addr) PR_NetAddrSize(_addr)
 
 #else
 
 #if defined(XP_UNIX)
-#define PR_NETADDR_SIZE(_addr) \
-        ((_addr)->raw.family == AF_UNIX \
-        ? sizeof((_addr)->local) \
-        : sizeof((_addr)->inet))
+#define PR_NETADDR_SIZE(_addr) 					\
+        ((_addr)->raw.family == PR_AF_INET		\
+        ? sizeof((_addr)->inet)					\
+        : ((_addr)->raw.family == PR_AF_INET6	\
+        ? sizeof((_addr)->ipv6)					\
+        : sizeof((_addr)->local)))
 #else
-#define PR_NETADDR_SIZE(_addr) sizeof((_addr)->inet)
+#define PR_NETADDR_SIZE(_addr) 					\
+        ((_addr)->raw.family == PR_AF_INET		\
+        ? sizeof((_addr)->inet)					\
+        : sizeof((_addr)->ipv6))
 #endif /* defined(XP_UNIX) */
 
 #endif /* defined(_PR_INET6) */
 
 /*
 ***************************************************************************
 ** PRSockOption
 **
--- a/pr/include/prnetdb.h
+++ b/pr/include/prnetdb.h
@@ -212,17 +212,18 @@ NSPR_API(PRIntn) PR_EnumerateHostEnt(
 **  PRStatus            To indicate success or failure. If the latter, the
 **                      reason for the failure can be retrieved by calling
 **                      PR_GetError();
 ***********************************************************************/
 typedef enum PRNetAddrValue
 {
     PR_IpAddrNull,      /* do NOT overwrite the IP address */
     PR_IpAddrAny,       /* assign logical INADDR_ANY to IP address */
-    PR_IpAddrLoopback   /* assign logical INADDR_LOOPBACK */
+    PR_IpAddrLoopback,  /* assign logical INADDR_LOOPBACK  */
+    PR_IpAddrV4Mapped   /* IPv4 mapped address */
 } PRNetAddrValue;
 
 NSPR_API(PRStatus) PR_InitializeNetAddr(
     PRNetAddrValue val, PRUint16 port, PRNetAddr *addr);
 
 /***********************************************************************
 ** FUNCTION: PR_SetNetAddr(), 
 ** DESCRIPTION:
--- a/pr/src/Makefile
+++ b/pr/src/Makefile
@@ -150,16 +150,17 @@ endif
 #
 
 OBJS = \
     $(OBJDIR)/prvrsion.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prfdcach.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prmwait.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prmapopt.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/priometh.$(OBJ_SUFFIX) \
+    io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prlayer.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prlog.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prmmap.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prpolevt.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prprf.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prscanf.$(OBJ_SUFFIX) \
     io/$(OBJDIR)/prstdio.$(OBJ_SUFFIX) \
     threads/$(OBJDIR)/prcmon.$(OBJ_SUFFIX) \
@@ -222,20 +223,16 @@ OBJS += \
 	threads/combined/$(OBJDIR)/prucv.$(OBJ_SUFFIX) \
 	threads/combined/$(OBJDIR)/prulock.$(OBJ_SUFFIX) \
 	threads/combined/$(OBJDIR)/prustack.$(OBJ_SUFFIX) \
 	threads/combined/$(OBJDIR)/pruthr.$(OBJ_SUFFIX)
 endif
 
 endif
 
-ifeq ($(USE_IPV6), 1)
-OBJS += io/$(OBJDIR)/pripv6.$(OBJ_SUFFIX)
-endif
-
 ifeq ($(USE_CPLUS), 1)
 OBJS += \
 	cplus/$(OBJDIR)/rcbase.$(OBJ_SUFFIX) \
 	cplus/$(OBJDIR)/rccv.$(OBJ_SUFFIX) \
 	cplus/$(OBJDIR)/rcfileio.$(OBJ_SUFFIX) \
 	cplus/$(OBJDIR)/rcinrval.$(OBJ_SUFFIX) \
 	cplus/$(OBJDIR)/rcio.$(OBJ_SUFFIX) \
 	cplus/$(OBJDIR)/rclock.$(OBJ_SUFFIX) \
--- a/pr/src/io/Makefile
+++ b/pr/src/io/Makefile
@@ -27,16 +27,17 @@ ifeq ($(OS_RELEASE),4.1.3_U1)
 OPTIMIZER =
 endif
 endif
 
 CSRCS = \
     prfdcach.c \
     prmwait.c \
     priometh.c \
+    pripv6.c \
 	prmapopt.c \
     prlayer.c \
     prlog.c \
 	prmmap.c \
     prpolevt.c \
 	prprf.c \
 	prscanf.c \
 	prstdio.c  \
@@ -46,20 +47,16 @@ ifndef USE_PTHREADS
     CSRCS += \
 	    prdir.c \
 	    prfile.c \
 	    prio.c \
 	    prsocket.c \
 	    $(NULL)
 endif
 
-ifdef USE_IPV6
-CSRCS += pripv6.c
-endif
-
 TARGETS	= $(OBJS)
 
 INCLUDES = -I$(DIST)/include -I$(MOD_DEPTH)/pr/include -I$(MOD_DEPTH)/pr/include/private
 
 DEFINES     += -D_NSPR_BUILD_
 
 include $(MOD_DEPTH)/config/rules.mk
 
--- a/pr/src/io/pripv6.c
+++ b/pr/src/io/pripv6.c
@@ -15,12 +15,270 @@
  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  * Reserved.
  */
 
 /*
 ** File:        pripv6.c
 ** Description: Support for various functions unique to IPv6
 */
+#include "primpl.h"
+#include <string.h>
 
+static PRIOMethods ipv6_to_v4_tcpMethods;
+static PRIOMethods ipv6_to_v4_udpMethods;
+static PRDescIdentity _pr_ipv6_to_ipv4_id;
+extern PRBool IsValidNetAddr(const PRNetAddr *addr);
+
+/*
+ * convert an IPv4-mapped IPv6 addr to an IPv4 addr
+ */
+void ConvertToIpv4NetAddr(const PRNetAddr *src_v6addr,
+											PRNetAddr *dst_v4addr)
+{
+	dst_v4addr->inet.family = PR_AF_INET;
+	dst_v4addr->inet.port = src_v6addr->ipv6.port;
+	memcpy((char *) &dst_v4addr->inet.ip,
+				(char *) &src_v6addr->ipv6.ip.s6_addr + 12, 4);
+}
+
+/*
+ * convert an IPv4 addr to an IPv4-mapped IPv6 addr
+ */
+void ConvertToIpv6NetAddr(const PRNetAddr *src_v4addr,
+                                            PRNetAddr *dst_v6addr)
+{
+	dst_v6addr->ipv6.family = PR_AF_INET6;
+	dst_v6addr->ipv6.port = src_v4addr->inet.port;
+	memset(dst_v6addr->ipv6.ip.s6_addr, 0, 10);
+	memset(dst_v6addr->ipv6.ip.s6_addr + 10, 0xff, 2);
+	memcpy(dst_v6addr->ipv6.ip.s6_addr + 12,(char *) &src_v4addr->inet.ip, 4);
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketBind(PRFileDesc *fd,
+								const PRNetAddr *addr)
+{
+	PRNetAddr tmp_ipv4addr;
+	const PRNetAddr *tmp_addrp;
+	PRFileDesc *lo = fd->lower;
+
+	if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
+		ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+		tmp_addrp = &tmp_ipv4addr;
+	} else {
+        PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+		return PR_FAILURE;
+	}
+	return((lo->methods->bind)(lo,tmp_addrp));
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketConnect(
+    PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+	PRNetAddr tmp_ipv4addr;
+	const PRNetAddr *tmp_addrp;
+
+	if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
+		ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+		tmp_addrp = &tmp_ipv4addr;
+	} else {
+        PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+		return PR_FAILURE;
+	}
+	return (fd->lower->methods->connect)(fd->lower, tmp_addrp, timeout);
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketSendTo(
+    PRFileDesc *fd, const void *buf, PRInt32 amount,
+    PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
+{
+	PRNetAddr tmp_ipv4addr;
+	const PRNetAddr *tmp_addrp;
+
+	if (PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
+		ConvertToIpv4NetAddr(addr, &tmp_ipv4addr);
+		tmp_addrp = &tmp_ipv4addr;
+	} else {
+        PR_SetError(PR_NETWORK_UNREACHABLE_ERROR, 0);
+		return PR_FAILURE;
+	}
+    return (fd->lower->methods->sendto)(
+        fd->lower, buf, amount, flags, tmp_addrp, timeout);
+}
+
+static PRFileDesc* PR_CALLBACK Ipv6ToIpv4SocketAccept (
+    PRFileDesc *fd, PRNetAddr *addr, PRIntervalTime timeout)
+{
+    PRStatus rv;
+    PRFileDesc *newfd;
+    PRFileDesc *newstack;
+	PRNetAddr tmp_ipv4addr;
+
+    PR_ASSERT(fd != NULL);
+    PR_ASSERT(fd->lower != NULL);
+
+    newstack = PR_NEW(PRFileDesc);
+    if (NULL == newstack)
+    {
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return NULL;
+    }
+    *newstack = *fd;  /* make a copy of the accepting layer */
+
+    newfd = (fd->lower->methods->accept)(fd->lower, &tmp_ipv4addr, timeout);
+    if (NULL == newfd)
+    {
+        PR_DELETE(newstack);
+        return NULL;
+    }
+	ConvertToIpv6NetAddr(&tmp_ipv4addr, addr);
+
+    rv = PR_PushIOLayer(newfd, PR_TOP_IO_LAYER, newstack);
+    PR_ASSERT(PR_SUCCESS == rv);
+    return newfd;  /* that's it */
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketAcceptRead(PRFileDesc *sd,
+			PRFileDesc **nd, PRNetAddr **ipv6_raddr, void *buf, PRInt32 amount,
+							PRIntervalTime timeout)
+{
+    PRInt32 nbytes;
+    PRStatus rv;
+	PRNetAddr tmp_ipv4addr;
+    PRFileDesc *newstack;
+
+    PR_ASSERT(sd != NULL);
+    PR_ASSERT(sd->lower != NULL);
 
-/* pripv6.c */
+    newstack = PR_NEW(PRFileDesc);
+    if (NULL == newstack)
+    {
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return -1;
+    }
+    *newstack = *sd;  /* make a copy of the accepting layer */
+
+    nbytes = sd->lower->methods->acceptread(
+        sd->lower, nd, ipv6_raddr, buf, amount, timeout);
+    if (-1 == nbytes)
+    {
+        PR_DELETE(newstack);
+        return nbytes;
+    }
+	tmp_ipv4addr = **ipv6_raddr;	/* copy */
+	ConvertToIpv6NetAddr(&tmp_ipv4addr, *ipv6_raddr);
+
+    /* this PR_PushIOLayer call cannot fail */
+    rv = PR_PushIOLayer(*nd, PR_TOP_IO_LAYER, newstack);
+    PR_ASSERT(PR_SUCCESS == rv);
+    return nbytes;
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetName(PRFileDesc *fd,
+										PRNetAddr *ipv6addr)
+{
+	PRStatus result;
+	PRNetAddr tmp_ipv4addr;
+
+	result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr);
+	if (PR_SUCCESS == result) {
+		ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+		PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+	}
+	return result;
+}
+
+static PRStatus PR_CALLBACK Ipv6ToIpv4SocketGetPeerName(PRFileDesc *fd,
+										PRNetAddr *ipv6addr)
+{
+	PRStatus result;
+	PRNetAddr tmp_ipv4addr;
+
+	result = (fd->lower->methods->getsockname)(fd->lower, &tmp_ipv4addr);
+	if (PR_SUCCESS == result) {
+		ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+		PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+	}
+	return result;
+}
+
+static PRInt32 PR_CALLBACK Ipv6ToIpv4SocketRecvFrom(PRFileDesc *fd, void *buf,
+			PRInt32 amount, PRIntn flags, PRNetAddr *ipv6addr,
+				PRIntervalTime timeout)
+{
+	PRNetAddr tmp_ipv4addr;
+	PRInt32 result;
 
+    result = (fd->lower->methods->recvfrom)(
+        fd->lower, buf, amount, flags, &tmp_ipv4addr, timeout);
+	if (-1 != result) {
+		ConvertToIpv6NetAddr(&tmp_ipv4addr, ipv6addr);
+		PR_ASSERT(IsValidNetAddr(ipv6addr) == PR_TRUE);
+	}
+	return result;
+}
+
+PRStatus _pr_init_ipv6()
+{
+const PRIOMethods *stubMethods;
+
+    _pr_ipv6_to_ipv4_id = PR_GetUniqueIdentity("Ipv6_to_Ipv4 layer");
+    PR_ASSERT(PR_INVALID_IO_LAYER != _pr_ipv6_to_ipv4_id);
+
+	stubMethods = PR_GetDefaultIOMethods();
+
+	ipv6_to_v4_tcpMethods = *stubMethods;  /* first get the entire batch */
+	/* then override the ones we care about */
+	ipv6_to_v4_tcpMethods.connect = Ipv6ToIpv4SocketConnect;
+	ipv6_to_v4_tcpMethods.bind = Ipv6ToIpv4SocketBind;
+	ipv6_to_v4_tcpMethods.accept = Ipv6ToIpv4SocketAccept;
+	ipv6_to_v4_tcpMethods.acceptread = Ipv6ToIpv4SocketAcceptRead;
+	ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName;
+	ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName;
+/*
+	ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption;
+	ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption;
+*/
+	ipv6_to_v4_udpMethods = *stubMethods;  /* first get the entire batch */
+	/* then override the ones we care about */
+	ipv6_to_v4_udpMethods.connect = Ipv6ToIpv4SocketConnect;
+	ipv6_to_v4_udpMethods.bind = Ipv6ToIpv4SocketBind;
+	ipv6_to_v4_udpMethods.sendto = Ipv6ToIpv4SocketSendTo;
+	ipv6_to_v4_udpMethods.recvfrom = Ipv6ToIpv4SocketRecvFrom;
+	ipv6_to_v4_tcpMethods.getsockname = Ipv6ToIpv4SocketGetName;
+	ipv6_to_v4_tcpMethods.getpeername = Ipv6ToIpv4SocketGetPeerName;
+/*
+	ipv6_to_v4_tcpMethods.getsocketoption = Ipv6ToIpv4GetSocketOption;
+	ipv6_to_v4_tcpMethods.setsocketoption = Ipv6ToIpv4SetSocketOption;
+*/
+	return PR_SUCCESS;
+}
+
+PR_IMPLEMENT(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd)
+{
+	PRFileDesc *ipv6_fd = NULL;
+
+	/*
+	 * For platforms with no support for IPv6 
+	 * create layered socket for IPv4-mapped IPv6 addresses
+	 */
+	if (fd->methods->file_type == PR_DESC_SOCKET_TCP)
+		ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id,
+									&ipv6_to_v4_tcpMethods);
+	else
+		ipv6_fd = PR_CreateIOLayerStub(_pr_ipv6_to_ipv4_id,
+									&ipv6_to_v4_udpMethods);
+	if (NULL == ipv6_fd) {
+		goto errorExit;
+	} 
+	ipv6_fd->secret = NULL;
+
+	if (PR_PushIOLayer(fd, PR_TOP_IO_LAYER, ipv6_fd) == PR_FAILURE) {
+		goto errorExit;
+	}
+
+	return PR_SUCCESS;
+errorExit:
+
+	if (ipv6_fd)
+		ipv6_fd->dtor(ipv6_fd);
+	return PR_FAILURE;
+}
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -20,26 +20,24 @@
 
 #include <string.h>
 
 /************************************************************************/
 
 /* These two functions are only used in assertions. */
 #if defined(DEBUG)
 
-static PRBool IsValidNetAddr(const PRNetAddr *addr)
+PRBool IsValidNetAddr(const PRNetAddr *addr)
 {
     if ((addr != NULL)
 #ifdef XP_UNIX
-	    && (addr->raw.family != AF_UNIX)
+	    && (addr->raw.family != PR_AF_LOCAL)
 #endif
-#ifdef _PR_INET6
-	    && (addr->raw.family != AF_INET6)
-#endif
-	    && (addr->raw.family != AF_INET)) {
+	    && (addr->raw.family != PR_AF_INET6)
+	    && (addr->raw.family != PR_AF_INET)) {
         return PR_FALSE;
     }
     return PR_TRUE;
 }
 
 static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
 {
     /*
@@ -223,25 +221,33 @@ PR_IMPLEMENT(PRStatus) PR_DestroySocketP
     _PR_Putfd(fd);
     return PR_SUCCESS;
 }  /* PR_DestroySocketPollFd */
 
 static PRStatus PR_CALLBACK SocketConnect(
     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
 {
 	PRInt32 rv;    /* Return value of _PR_MD_CONNECT */
+    const PRNetAddr *addrp = addr;
 	PRThread *me = _PR_MD_CURRENT_THREAD();
 
 	if (_PR_PENDING_INTERRUPT(me)) {
 		me->flags &= ~_PR_INTERRUPT;
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
 		return PR_FAILURE;
 	}
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+	}
+#endif
 
-	rv = _PR_MD_CONNECT(fd, addr, PR_NETADDR_SIZE(addr), timeout);
+	rv = _PR_MD_CONNECT(fd, addrp, PR_NETADDR_SIZE(addr), timeout);
 	PR_LOG(_pr_io_lm, PR_LOG_MAX, ("connect -> %d", rv));
 	if (rv == 0)
 		return PR_SUCCESS;
 	else
 		return PR_FAILURE;
 }
 
 PR_IMPLEMENT(PRStatus) PR_GetConnectStatus(const PRPollDesc *pd)
@@ -409,16 +415,20 @@ PRIntervalTime timeout)
 	 * (which maps to _MD_makenonblock, see macsockotpt.c)
 	 * installs the async notifier routine needed to make blocking
 	 * I/O work properly.
 	 */
 #if !defined(SOLARIS) && !defined(IRIX) && !defined(WINNT)
 	_PR_MD_MAKE_NONBLOCK(fd2);
 #endif
 
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
 	PR_ASSERT(IsValidNetAddrLen(addr, al) == PR_TRUE);
 
 	return fd2;
 }
 
 #ifdef WINNT
 PR_IMPLEMENT(PRFileDesc*) PR_NTFast_Accept(PRFileDesc *fd, PRNetAddr *addr,
@@ -462,30 +472,38 @@ PRIntervalTime timeout)
 	return fd2;
 }
 #endif /* WINNT */
 
 
 static PRStatus PR_CALLBACK SocketBind(PRFileDesc *fd, const PRNetAddr *addr)
 {
 	PRInt32 result;
+    const PRNetAddr *addrp = addr;
 
 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
 
 #ifdef XP_UNIX
 	if (addr->raw.family == AF_UNIX) {
 		/* Disallow relative pathnames */
 		if (addr->local.path[0] != '/') {
 			PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
 			return PR_FAILURE;
 		}
 	}
 #endif /* XP_UNIX */
 
-	result = _PR_MD_BIND(fd, addr, PR_NETADDR_SIZE(addr));
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+	}
+#endif
+	result = _PR_MD_BIND(fd, addrp, PR_NETADDR_SIZE(addr));
 	if (result < 0) {
 		return PR_FAILURE;
 	}
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketListen(PRFileDesc *fd, PRIntn backlog)
 {
@@ -625,34 +643,42 @@ static PRStatus PR_CALLBACK SocketSync(P
 	return PR_SUCCESS;
 }
 
 static PRInt32 PR_CALLBACK SocketSendTo(
     PRFileDesc *fd, const void *buf, PRInt32 amount,
     PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
 {
 	PRInt32 temp, count;
+    const PRNetAddr *addrp = addr;
 	PRThread *me = _PR_MD_CURRENT_THREAD();
 
 	if (_PR_PENDING_INTERRUPT(me)) {
 		me->flags &= ~_PR_INTERRUPT;
 		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
 		return -1;
 	}
 	if (_PR_IO_PENDING(me)) {
 		PR_SetError(PR_IO_PENDING_ERROR, 0);
 		return -1;
 	}
 
 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+	}
+#endif
 
 	count = 0;
 	while (amount > 0) {
 		temp = _PR_MD_SENDTO(fd, buf, amount, flags,
-		    addr, PR_NETADDR_SIZE(addr), timeout);
+		    addrp, PR_NETADDR_SIZE(addr), timeout);
 		if (temp < 0) {
 					count = -1;
 					break;
 				}
 		count += temp;
 		if (fd->secret->nonblocking) {
 			break;
 		}
@@ -676,16 +702,20 @@ PRIntn flags, PRNetAddr *addr, PRInterva
 	}
 	if (_PR_IO_PENDING(me)) {
 		PR_SetError(PR_IO_PENDING_ERROR, 0);
 		return -1;
 	}
 
 	al = sizeof(PRNetAddr);
 	rv = _PR_MD_RECVFROM(fd, buf, amount, flags, addr, &al, timeout);
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
 	return rv;
 }
 
 static PRInt32 PR_CALLBACK SocketAcceptRead(PRFileDesc *sd, PRFileDesc **nd, 
 PRNetAddr **raddr, void *buf, PRInt32 amount,
 PRIntervalTime timeout)
 {
 	PRInt32 rv;
@@ -728,16 +758,20 @@ PRIntervalTime timeout)
 		} else {
 			(*nd)->secret->md.io_model_committed = PR_TRUE;
 			(*nd)->secret->md.accepted_socket = PR_TRUE;
 			memcpy(&(*nd)->secret->md.peer_addr, *raddr,
 				PR_NETADDR_SIZE(*raddr));
 		}
 	}
 	}
+#ifdef _PR_INET6
+	if (AF_INET6 == *raddr->raw.family)
+        *raddr->raw.family = PR_AF_INET6;
+#endif
 #else
 	rv = _PR_EmulateAcceptRead(sd, nd, raddr, buf, amount, timeout);
 #endif
 	return rv;
 }
 
 #ifdef WINNT
 PR_IMPLEMENT(PRInt32) PR_NTFast_AcceptRead(PRFileDesc *sd, PRFileDesc **nd, 
@@ -905,31 +939,39 @@ static PRStatus PR_CALLBACK SocketGetNam
 	PRInt32 result;
 	PRUint32 addrlen;
 
 	addrlen = sizeof(PRNetAddr);
 	result = _PR_MD_GETSOCKNAME(fd, addr, &addrlen);
 	if (result < 0) {
 		return PR_FAILURE;
 	}
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
 	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
 {
 	PRInt32 result;
 	PRUint32 addrlen;
 
 	addrlen = sizeof(PRNetAddr);
 	result = _PR_MD_GETPEERNAME(fd, addr, &addrlen);
 	if (result < 0) {
 		return PR_FAILURE;
 	}
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
 	PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
 	PR_ASSERT(IsValidNetAddrLen(addr, addrlen) == PR_TRUE);
 	return PR_SUCCESS;
 }
 
 static PRStatus PR_CALLBACK SocketGetSockOpt(
     PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen)
 {
@@ -1178,49 +1220,70 @@ PR_IMPLEMENT(const PRIOMethods*) PR_GetU
 	return &udpMethods;
 }
 
 static const PRIOMethods* PR_GetSocketPollFdMethods()
 {
     return &socketpollfdMethods;
 }  /* PR_GetSocketPollFdMethods */
 
+PR_EXTERN(PRStatus) _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
 
 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
 {
 	PRInt32 osfd;
 	PRFileDesc *fd;
+	PRInt32 tmp_domain = domain;
 
 	if (!_pr_initialized) _PR_ImplicitInitialization();
-	if (AF_INET != domain
-#if defined(_PR_INET6)
-			&& AF_INET6 != domain
-#endif
+	if (PR_AF_INET != domain
+			&& PR_AF_INET6 != domain
 #if defined(XP_UNIX)
-			&& AF_UNIX != domain
+			&& PR_AF_LOCAL != domain
 #endif
 			) {
 		PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
 		return NULL;
 	}
+
+#if defined(_PR_INET6)
+	if (PR_AF_INET6 == domain)
+		domain = AF_INET6;
+#else
+	if (PR_AF_INET6 == domain)
+		domain = AF_INET;
+#endif
 	osfd = _PR_MD_SOCKET(domain, type, proto);
 	if (osfd == -1) {
 		return 0;
 	}
 	if (type == SOCK_STREAM)
 		fd = PR_AllocFileDesc(osfd, PR_GetTCPMethods());
 	else
 		fd = PR_AllocFileDesc(osfd, PR_GetUDPMethods());
 	/*
 	 * Make the sockets non-blocking
 	 */
-	if (fd != NULL)
+	if (fd != NULL) {
 		_PR_MD_MAKE_NONBLOCK(fd);
-	else
+#if !defined(_PR_INET6)
+		/*
+		 * For platforms with no support for IPv6 
+		 * create layered socket for IPv4-mapped IPv6 addresses
+		 */
+		if (PR_AF_INET6 == tmp_domain) {
+			if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
+				PR_Close(fd);
+				fd = NULL;
+			}
+		}
+#endif
+	} else
 		_PR_MD_CLOSE_SOCKET(osfd);
+
 	return fd;
 }
 
 PR_IMPLEMENT(PRFileDesc *) PR_NewTCPSocket(void)
 {
 	PRInt32 domain = AF_INET;
 
 #if defined(_PR_INET6)
--- a/pr/src/misc/prnetdb.c
+++ b/pr/src/misc/prnetdb.c
@@ -95,19 +95,43 @@ static sigset_t timer_set;
 PRLock* _getproto_lock = NULL;
 #endif
 
 #if defined(_PR_INET6)
 PRBool _pr_ipv6_enabled = PR_FALSE;
 #if defined(AIX)
 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
 const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#define _PR_IN6_IS_ADDR_V4MAPPED	IN6_IS_ADDR_V4MAPPED
+#define _PR_IN6_IS_ADDR_V4COMPAT	IN6_IS_ADDR_V4COMPAT
 #endif /* AIX */
+#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)		\
+		(((a)->s6_addr32[0] == 0) 	&&	\
+		((a)->s6_addr32[1] == 0)	&&	\
+		((a)->s6_addr[8] == 0)		&&	\
+		((a)->s6_addr[9] == 0)		&&	\
+		((a)->s6_addr[10] == 0xff)	&&	\
+		((a)->s6_addr[11] == 0xff))
+
+#define _PR_IN6_IS_ADDR_V4COMPAT(a)			\
+		(((a)->s6_addr32[0] == 0) &&		\
+		((a)->s6_addr32[1] == 0) &&			\
+		((a)->s6_addr32[2] == 0))
+
 #endif /* _PR_INET6 */
 
+extern PRStatus _pr_init_ipv6();
+
 void _PR_InitNet(void)
 {
 #if defined(XP_UNIX)
 #ifdef HAVE_NETCONFIG
 	/*
 	 * This one-liner prevents the endless re-open's and re-read's of
 	 * /etc/netconfig on EACH and EVERY call to accept(), connect(), etc.
 	 */
@@ -117,17 +141,17 @@ void _PR_InitNet(void)
 	sigaddset(&timer_set, SIGALRM);
 #endif
 #if !defined(_PR_NO_PREEMPT)
 	_pr_dnsLock = PR_NewLock();
 #endif
 #if !defined(_PR_HAVE_GETPROTO_R)
 	_getproto_lock = PR_NewLock();
 #endif
-
+	_pr_init_ipv6();
 }
 
 PR_IMPLEMENT(PRStatus) PR_SetIPv6Enable(PRBool itIs)
 {
 #if defined(XP_MAC)
 #pragma unused (itIs)
 #endif
 
@@ -169,78 +193,69 @@ static char *Alloc(PRIntn amount, char *
 	if (buflen < amount) {
 		return 0;
 	}
 	*bufp = buf + amount;
 	*buflenp = buflen - amount;
 	return buf;
 }
 
-#if defined(_PR_INET6)
-
 typedef enum _PRIPAddrConversion {
     _PRIPAddrNoConversion,
     _PRIPAddrIPv4Mapped,
     _PRIPAddrIPv4Compat
 } _PRIPAddrConversion;
 
 /*
 ** Convert an IPv4 address (v4) to an IPv4-mapped IPv6 address (v6).
 */
 static void MakeIPv4MappedAddr(const char *v4, char *v6)
 {
     memset(v6, 0, 10);
     memset(v6 + 10, 0xff, 2);
     memcpy(v6 + 12, v4, 4);
-    PR_ASSERT(IN6_IS_ADDR_V4MAPPED((struct in6_addr *) v6));
+    PR_ASSERT(_PR_IN6_IS_ADDR_V4MAPPED(((PRIPv6Addr *) v6)));
 }
 
 /*
 ** Convert an IPv4 address (v4) to an IPv4-compatible IPv6 address (v6).
 */
 static void MakeIPv4CompatAddr(const char *v4, char *v6)
 {
     memset(v6, 0, 12);
     memcpy(v6 + 12, v4, 4);
-    PR_ASSERT(IN6_IS_ADDR_V4COMPAT((struct in6_addr *) v6));
+    PR_ASSERT(_PR_IN6_IS_ADDR_V4COMPAT(((PRIPv6Addr *) v6)));
 }
 
-#endif /* _PR_INET6 */
-
 /*
 ** 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,
-#if defined(_PR_INET6)
     _PRIPAddrConversion conversion,
-#endif
     PRHostEnt *to)
 {
 	PRIntn len, na;
 	char **ap;
 
-	/* Do the easy stuff */
-#if defined(_PR_INET6)
 	if (conversion != _PRIPAddrNoConversion
 			&& from->h_addrtype == AF_INET) {
 		PR_ASSERT(from->h_length == 4);
-		to->h_addrtype = AF_INET6;
+		to->h_addrtype = PR_AF_INET6;
 		to->h_length = 16;
 	} else {
-		to->h_addrtype = from->h_addrtype;
+		if (AF_INET6 == from->h_addrtype)
+			to->h_addrtype = PR_AF_INET6;
+		else
+			to->h_addrtype = from->h_addrtype;
 		to->h_length = from->h_length;
 	}
-#else
-	to->h_addrtype = from->h_addrtype;
-	to->h_length = from->h_length;
-#endif
 
 	/* 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);
 	if (!to->h_name) return PR_FAILURE;
 	memcpy(to->h_name, from->h_name, len);
 
@@ -272,31 +287,27 @@ static PRStatus CopyHostent(
 	to->h_addr_list = (char**)Alloc(
 	    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);
 		if (!to->h_addr_list[na]) return PR_FAILURE;
-#if defined(_PR_INET6)
 		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]);
 			}
 		} else {
 			memcpy(to->h_addr_list[na], *ap, to->h_length);
 		}
-#else
-		memcpy(to->h_addr_list[na], *ap, to->h_length);
-#endif
 	}
 	to->h_addr_list[na] = 0;
 	return PR_SUCCESS;
 }
 
 #if !defined(_PR_HAVE_GETPROTO_R)
 /*
 ** Copy a protoent, and all of the memory that it refers to into
@@ -392,24 +403,22 @@ PR_IMPLEMENT(PRStatus) PR_GetHostByName(
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 	    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
 #else
 	    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
 #endif
 	}
 	else
 	{
+		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
 #if defined(_PR_INET6)
-		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
-
-		if (_pr_ipv6_enabled) conversion = _PRIPAddrIPv4Mapped;
+		if (_pr_ipv6_enabled)
+			conversion = _PRIPAddrIPv4Mapped;
+#endif
 		rv = CopyHostent(h, buf, bufsize, conversion, hp);
-#else
-		rv = CopyHostent(h, buf, bufsize, hp);
-#endif
 		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
@@ -428,29 +437,21 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 	sigset_t oldset;
 #endif
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 	int error_num;
 #endif
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
-#if defined(_PR_INET6)
-    PR_ASSERT(af == AF_INET || af == AF_INET6);
-    if (af != AF_INET && af != AF_INET6) {
+    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;
     }
-#else
-    PR_ASSERT(af == AF_INET);
-    if (af != AF_INET) {
-        PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
-        return PR_FAILURE;
-    }
-#endif
 
     /*
      * 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;
@@ -458,19 +459,19 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 
 #ifdef XP_UNIX
 	DISABLECLOCK(&oldset);
 #endif
 	LOCK_DNS();
 
 #ifdef _PR_INET6
 #ifdef _PR_HAVE_GETHOSTBYNAME2
-    if (af == AF_INET6)
+    if (af == PR_AF_INET6)
     {
-        h = gethostbyname2(name, af); 
+        h = gethostbyname2(name, AF_INET6); 
         if (NULL == h)
         {
             h = gethostbyname2(name, AF_INET);
         }
     }
     else
     {
         h = gethostbyname2(name, af);
@@ -493,24 +494,20 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYNAME)
 	    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
 #else
 	    PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
 #endif
 	}
 	else
 	{
-#if defined(_PR_INET6)
 		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
 
-		if (af == AF_INET6) conversion = _PRIPAddrIPv4Mapped;
+		if (af == PR_AF_INET6) conversion = _PRIPAddrIPv4Mapped;
 		rv = CopyHostent(h, buf, bufsize, conversion, hp);
-#else
-		rv = CopyHostent(h, buf, bufsize, hp);
-#endif
 		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
@@ -521,74 +518,75 @@ PR_IMPLEMENT(PRStatus) PR_GetIPNodeByNam
 
 PR_IMPLEMENT(PRStatus) PR_GetHostByAddr(
     const PRNetAddr *hostaddr, char *buf, PRIntn bufsize, PRHostEnt *hostentry)
 {
 	struct hostent *h;
 	PRStatus rv = PR_FAILURE;
 	const void *addr;
 	int addrlen;
+	PRInt32 af;
 #ifdef XP_UNIX
 	sigset_t oldset;
 #endif
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
 	int error_num;
 #endif
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
 #ifdef XP_UNIX
 	DISABLECLOCK(&oldset);
 #endif
 	LOCK_DNS();
-#if defined(_PR_INET6)
-	if (hostaddr->raw.family == AF_INET6)
+	if (hostaddr->raw.family == PR_AF_INET6)
 	{
 		addr = &hostaddr->ipv6.ip;
 		addrlen = sizeof(hostaddr->ipv6.ip);
 	}
 	else
-#endif /* defined(_PR_INET6) */
 	{
 		PR_ASSERT(hostaddr->raw.family == AF_INET);
 		addr = &hostaddr->inet.ip;
 		addrlen = sizeof(hostaddr->inet.ip);
 	}
+	if (PR_AF_INET6 == hostaddr->raw.family)
+		af = AF_INET6;
+	else
+		af = hostaddr->raw.family;
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
-	h = getipnodebyaddr(addr, addrlen, hostaddr->raw.family, &error_num);
+	h = getipnodebyaddr(addr, addrlen, af, &error_num);
 #else
 #ifdef XP_OS2_VACPP
-	h = gethostbyaddr((char *)addr, addrlen, hostaddr->raw.family);
+	h = gethostbyaddr((char *)addr, addrlen, af);
 #else
-	h = gethostbyaddr(addr, addrlen, hostaddr->raw.family);
+	h = gethostbyaddr(addr, addrlen, af);
 #endif
 #endif /* _PR_INET6 && _PR_HAVE_GETIPNODEBYADDR */
 	if (NULL == h)
 	{
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
 		PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, error_num);
 #else
 		PR_SetError(PR_DIRECTORY_LOOKUP_ERROR, _MD_GETHOST_ERRNO());
 #endif
 	}
 	else
 	{
+		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
 #if defined(_PR_INET6)
-		_PRIPAddrConversion conversion = _PRIPAddrNoConversion;
-		if (hostaddr->raw.family == AF_INET6) {
+		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);
-#else
-		rv = CopyHostent(h, buf, bufsize, hostentry);
-#endif
 		if (PR_SUCCESS != rv) {
 		    PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
 		}
 #if defined(_PR_INET6) && defined(_PR_HAVE_GETIPNODEBYADDR)
 		freehostent(h);
 #endif
 	}
 	UNLOCK_DNS();
@@ -802,20 +800,18 @@ PR_IMPLEMENT(PRUintn) PR_NetAddrSize(con
      * struct sockaddr_in6.  PRNetAddr's ipv6 member has a
      * scope_id field to match the new field.  In order to
      * work with older implementations supporting RFC 2133,
      * we take the size of struct sockaddr_in6 instead of
      * addr->ipv6.
      */
     if (AF_INET == addr->raw.family)
         addrsize = sizeof(addr->inet);
-#if defined(_PR_INET6)
-    else if (AF_INET6 == addr->raw.family)
-        addrsize = sizeof(struct sockaddr_in6);
-#endif
+    else if (PR_AF_INET6 == addr->raw.family)
+        addrsize = sizeof(_pr_sockaddr_in6_t);
 #if defined(XP_UNIX)
     else if (AF_UNIX == addr->raw.family)
         addrsize = sizeof(addr->local);
 #endif
     else addrsize = 0;
 
     return addrsize;
 }  /* PR_NetAddrSize */
@@ -824,24 +820,22 @@ PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt
     PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address)
 {
     void *addr = hostEnt->h_addr_list[enumIndex++];
     memset(address, 0, sizeof(PRNetAddr));
     if (NULL == addr) enumIndex = 0;
     else
     {
         address->raw.family = hostEnt->h_addrtype;
-#if defined(_PR_INET6)
-        if (AF_INET6 == hostEnt->h_addrtype)
+        if (PR_AF_INET6 == hostEnt->h_addrtype)
         {
             address->ipv6.port = htons(port);
             memcpy(&address->ipv6.ip, addr, hostEnt->h_length);
         }
         else
-#endif /* defined(_PR_INET6) */
         {
             PR_ASSERT(AF_INET == hostEnt->h_addrtype);
             address->inet.port = htons(port);
             memcpy(&address->inet.ip, addr, hostEnt->h_length);
         }
     }
     return enumIndex;
 }  /* PR_EnumerateHostEnt */
@@ -850,17 +844,17 @@ PR_IMPLEMENT(PRStatus) PR_InitializeNetA
     PRNetAddrValue val, PRUint16 port, PRNetAddr *addr)
 {
     PRStatus rv = PR_SUCCESS;
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
 #if defined(_PR_INET6)
     if (_pr_ipv6_enabled)
     {
-        addr->ipv6.family = AF_INET6;
+        addr->ipv6.family = PR_AF_INET6;
         addr->ipv6.port = htons(port);
         switch (val)
         {
         case PR_IpAddrNull:
             break;  /* don't overwrite the address */
         case PR_IpAddrAny:
             addr->ipv6.ip = in6addr_any;
             break;
@@ -898,17 +892,17 @@ PR_IMPLEMENT(PRStatus) PR_InitializeNetA
 PR_IMPLEMENT(PRStatus) PR_SetNetAddr(
     PRNetAddrValue val, PRUint16 af, PRUint16 port, PRNetAddr *addr)
 {
     PRStatus rv = PR_SUCCESS;
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     addr->raw.family = af;
 #if defined(_PR_INET6)
-    if (af == AF_INET6)
+    if (af == PR_AF_INET6)
     {
         addr->ipv6.port = htons(port);
         switch (val)
         {
         case PR_IpAddrNull:
             break;  /* don't overwrite the address */
         case PR_IpAddrAny:
             addr->ipv6.ip = in6addr_any;
@@ -917,17 +911,42 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr(
             addr->ipv6.ip = in6addr_loopback;
             break;
         default:
             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
             rv = PR_FAILURE;
         }
     }
     else
-#endif  /* defined(_PR_INET6) */
+#else
+    if (af == PR_AF_INET6)
+    {
+		PRUint32 ipv4_in_addr;		
+        addr->ipv6.port = htons(port);
+        switch (val)
+        {
+        case PR_IpAddrNull:
+            break;  /* don't overwrite the address */
+        case PR_IpAddrAny:
+            ipv4_in_addr = htonl(INADDR_ANY);
+			MakeIPv4MappedAddr((char *) &ipv4_in_addr,
+								(char *) addr->ipv6.ip.s6_addr);
+            break;
+        case PR_IpAddrLoopback:
+            ipv4_in_addr = htonl(INADDR_LOOPBACK);
+			MakeIPv4MappedAddr((char *) &ipv4_in_addr,
+								(char *) addr->ipv6.ip.s6_addr);
+            break;
+        default:
+            PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
+            rv = PR_FAILURE;
+        }
+    }
+    else
+#endif
     {
         addr->inet.port = htons(port);
         switch (val)
         {
         case PR_IpAddrNull:
             break;  /* don't overwrite the address */
         case PR_IpAddrAny:
             addr->inet.ip = htonl(INADDR_ANY);
@@ -938,27 +957,49 @@ PR_IMPLEMENT(PRStatus) PR_SetNetAddr(
         default:
             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
             rv = PR_FAILURE;
         }
     }
     return rv;
 }  /* 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 == AF_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;
+        } else if (val == PR_IpAddrV4Mapped
+                && _PR_IN6_IS_ADDR_V4MAPPED((PRIPv6Addr *)&addr->ipv6.ip)) {
+            return PR_TRUE;
         }
     }
     else
 #endif
     {
         if (addr->raw.family == AF_INET) {
             if (val == PR_IpAddrAny && addr->inet.ip == htonl(INADDR_ANY)) {
                 return PR_TRUE;
@@ -999,17 +1040,17 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAdd
     PRStatus status = PR_SUCCESS;
 
 #if defined(_PR_INET6)
     PRIntn rv;
 
     rv = inet_pton(AF_INET6, string, &addr->ipv6.ip);
     if (1 == rv)
     {
-        addr->raw.family = AF_INET6;
+        addr->raw.family = PR_AF_INET6;
     }
     else
     {
         PR_ASSERT(0 == rv);
         rv = inet_pton(AF_INET, string, &addr->inet.ip);
         if (1 == rv)
         {
             addr->raw.family = AF_INET;
@@ -1040,25 +1081,39 @@ PR_IMPLEMENT(PRStatus) PR_StringToNetAdd
 
     return status;
 }
 
 PR_IMPLEMENT(PRStatus) PR_NetAddrToString(
     const PRNetAddr *addr, char *string, PRUint32 size)
 {
 #if defined(_PR_INET6)
-    if (AF_INET6 == addr->raw.family)
+    if (PR_AF_INET6 == addr->raw.family)
     {
         if (NULL == inet_ntop(AF_INET6, &addr->ipv6.ip, string, size))
         {
             PR_SetError(PR_INVALID_ARGUMENT_ERROR, errno);
             return PR_FAILURE;
         }
     }
     else
+#else
+    if (PR_AF_INET6 == addr->raw.family)
+    {
+		unsigned char *byte = (unsigned char *) addr->ipv6.ip.s6_addr;
+		int i, len;
+
+		len = 0;
+		for(i=0; i < 15;i++) {
+			PR_snprintf(string + len, size - len, "%u.", byte[i]);
+			len = strlen(string);
+		}
+		PR_snprintf(string + len, size - len, "%u", byte[i]);
+    }
+    else
 #endif  /* defined(_PR_INET6) */
     {
         PR_ASSERT(AF_INET == addr->raw.family);
         PR_ASSERT(size >= 16);
         if (size < 16) goto failed;
         if (AF_INET != addr->raw.family) goto failed;
         else
         {
--- a/pr/src/pthreads/ptio.c
+++ b/pr/src/pthreads/ptio.c
@@ -149,23 +149,21 @@ static PRFileDesc *pt_SetMethods(
 static PRLock *_pr_flock_lock;  /* For PR_LockFile() etc. */
 static PRLock *_pr_rename_lock;  /* For PR_Rename() */
 
 /**************************************************************************/
 
 /* These two functions are only used in assertions. */
 #if defined(DEBUG)
 
-static PRBool IsValidNetAddr(const PRNetAddr *addr)
+PRBool IsValidNetAddr(const PRNetAddr *addr)
 {
     if ((addr != NULL)
             && (addr->raw.family != AF_UNIX)
-#ifdef _PR_INET6
-            && (addr->raw.family != AF_INET6)
-#endif
+            && (addr->raw.family != PR_AF_INET6)
             && (addr->raw.family != AF_INET)) {
         return PR_FALSE;
     }
     return PR_TRUE;
 }
 
 static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
 {
@@ -770,16 +768,17 @@ void _PR_InitIO()
     PR_ASSERT(NULL != _pr_rename_lock); 
 
     _PR_InitFdCache();  /* do that */   
 
     _pr_stdin = pt_SetMethods(0, PR_DESC_FILE, PR_FALSE);
     _pr_stdout = pt_SetMethods(1, PR_DESC_FILE, PR_FALSE);
     _pr_stderr = pt_SetMethods(2, PR_DESC_FILE, PR_FALSE);
     PR_ASSERT(_pr_stdin && _pr_stdout && _pr_stderr);
+
 }  /* _PR_InitIO */
 
 PR_IMPLEMENT(PRFileDesc*) PR_GetSpecialFD(PRSpecialFD osfd)
 {
     PRFileDesc *result = NULL;
     PR_ASSERT(osfd >= PR_StandardInput && osfd <= PR_StandardError);
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
@@ -1105,31 +1104,44 @@ static PRStatus pt_Fsync(PRFileDesc *fd)
     return PR_SUCCESS;
 }  /* pt_Fsync */
 
 static PRStatus pt_Connect(
     PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime timeout)
 {
     PRIntn rv = -1, syserrno;
     pt_SockLen addr_len;
-#ifdef _PR_HAVE_SOCKADDR_LEN
+	const PRNetAddr *addrp = addr;
+	PRUint16 md_af = addr->raw.family;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
     PRNetAddr addrCopy;
 #endif
 
     if (pt_TestAbort()) return PR_FAILURE;
 
     PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
     addr_len = PR_NETADDR_SIZE(addr);
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+#endif
+	}
+#endif
+
 #ifdef _PR_HAVE_SOCKADDR_LEN
     addrCopy = *addr;
     ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
-    ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family;
+    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
     rv = connect(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);
 #else
-    rv = connect(fd->secret->md.osfd, (struct sockaddr*)addr, addr_len);
+    rv = connect(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);
 #endif
     syserrno = errno;
     if ((-1 == rv) && (EINPROGRESS == syserrno) && (!fd->secret->nonblocking))
     {
         if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
         else
         {
             pt_Continuation op;
@@ -1221,16 +1233,20 @@ static PRFileDesc* pt_Accept(
     }
 #ifdef _PR_HAVE_SOCKADDR_LEN
     /* ignore the sa_len field of struct sockaddr */
     if (addr)
     {
         addr->raw.family = ((struct sockaddr*)addr)->sa_family;
     }
 #endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
     newfd = pt_SetMethods(osfd, PR_DESC_SOCKET_TCP, PR_TRUE);
     if (newfd == NULL) close(osfd);  /* $$$ whoops! this doesn't work $$$ */
     else
     {
         PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
         PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
     }
     return newfd;
@@ -1239,42 +1255,54 @@ failed:
     pt_MapError(_PR_MD_MAP_ACCEPT_ERROR, syserrno);
     return NULL;
 }  /* pt_Accept */
 
 static PRStatus pt_Bind(PRFileDesc *fd, const PRNetAddr *addr)
 {
     PRIntn rv;
     pt_SockLen addr_len;
-#ifdef _PR_HAVE_SOCKADDR_LEN
+	const PRNetAddr *addrp = addr;
+	PRUint16 md_af = addr->raw.family;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
     PRNetAddr addrCopy;
 #endif
 
     if (pt_TestAbort()) return PR_FAILURE;
 
     PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
-
     if (addr->raw.family == AF_UNIX)
     {
         /* Disallow relative pathnames */
         if (addr->local.path[0] != '/')
         {
             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
             return PR_FAILURE;
         }
     }
 
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+#endif
+	}
+#endif
+
     addr_len = PR_NETADDR_SIZE(addr);
 #ifdef _PR_HAVE_SOCKADDR_LEN
     addrCopy = *addr;
     ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
-    ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family;
+    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
     rv = bind(fd->secret->md.osfd, (struct sockaddr*)&addrCopy, addr_len);
 #else
-    rv = bind(fd->secret->md.osfd, (struct sockaddr*)addr, addr_len);
+    rv = bind(fd->secret->md.osfd, (struct sockaddr*)addrp, addr_len);
 #endif
 
     if (rv == -1) {
         pt_MapError(_PR_MD_MAP_BIND_ERROR, errno);
         return PR_FAILURE;
     }
     return PR_SUCCESS;
 }  /* pt_Bind */
@@ -1445,35 +1473,48 @@ static PRInt32 pt_SocketWrite(PRFileDesc
 static PRInt32 pt_SendTo(
     PRFileDesc *fd, const void *buf,
     PRInt32 amount, PRIntn flags, const PRNetAddr *addr,
     PRIntervalTime timeout)
 {
     PRInt32 syserrno, bytes = -1;
     PRBool fNeedContinue = PR_FALSE;
     pt_SockLen addr_len;
-#ifdef _PR_HAVE_SOCKADDR_LEN
+	const PRNetAddr *addrp = addr;
+	PRUint16 md_af = addr->raw.family;
+#if defined(_PR_HAVE_SOCKADDR_LEN) || defined(_PR_INET6)
     PRNetAddr addrCopy;
 #endif
 
     if (pt_TestAbort()) return bytes;
 
     PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
+#if defined(_PR_INET6)
+	if (addr->raw.family == PR_AF_INET6) {
+		md_af = AF_INET6;
+#ifndef _PR_HAVE_SOCKADDR_LEN
+		addrCopy = *addr;
+		addrCopy.raw.family = AF_INET6;
+		addrp = &addrCopy;
+#endif
+	}
+#endif
+
     addr_len = PR_NETADDR_SIZE(addr);
 #ifdef _PR_HAVE_SOCKADDR_LEN
     addrCopy = *addr;
     ((struct sockaddr*)&addrCopy)->sa_len = addr_len;
-    ((struct sockaddr*)&addrCopy)->sa_family = addr->raw.family;
+    ((struct sockaddr*)&addrCopy)->sa_family = md_af;
     bytes = sendto(
         fd->secret->md.osfd, buf, amount, flags,
         (struct sockaddr*)&addrCopy, addr_len);
 #else
     bytes = sendto(
         fd->secret->md.osfd, buf, amount, flags,
-        (struct sockaddr*)addr, addr_len);
+        (struct sockaddr*)addrp, addr_len);
 #endif
     syserrno = errno;
     if ( (bytes == -1) && (syserrno == EWOULDBLOCK || syserrno == EAGAIN)
         && (!fd->secret->nonblocking) )
     {
         if (PR_INTERVAL_NO_WAIT == timeout) syserrno = ETIMEDOUT;
         else fNeedContinue = PR_TRUE;
     }
@@ -1541,16 +1582,20 @@ static PRInt32 pt_RecvFrom(PRFileDesc *f
     {
         /* ignore the sa_len field of struct sockaddr */
         if (addr)
         {
             addr->raw.family = ((struct sockaddr*)addr)->sa_family;
         }
     }
 #endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+	if (AF_INET6 == addr->raw.family)
+        addr->raw.family = PR_AF_INET6;
+#endif
     if (bytes < 0)
         pt_MapError(_PR_MD_MAP_RECVFROM_ERROR, syserrno);
     return bytes;
 }  /* pt_RecvFrom */
 
 #ifdef AIX
 #ifndef HAVE_SEND_FILE
 static pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT;
@@ -1910,16 +1955,20 @@ static PRStatus pt_GetSockName(PRFileDes
     } else {
 #ifdef _PR_HAVE_SOCKADDR_LEN
         /* ignore the sa_len field of struct sockaddr */
         if (addr)
         {
             addr->raw.family = ((struct sockaddr*)addr)->sa_family;
         }
 #endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+		if (AF_INET6 == addr->raw.family)
+			addr->raw.family = PR_AF_INET6;
+#endif
         PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
         PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
         return PR_SUCCESS;
     }
 }  /* pt_GetSockName */
 
 static PRStatus pt_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
 {
@@ -1937,16 +1986,20 @@ static PRStatus pt_GetPeerName(PRFileDes
     } else {
 #ifdef _PR_HAVE_SOCKADDR_LEN
         /* ignore the sa_len field of struct sockaddr */
         if (addr)
         {
             addr->raw.family = ((struct sockaddr*)addr)->sa_family;
         }
 #endif /* _PR_HAVE_SOCKADDR_LEN */
+#ifdef _PR_INET6
+		if (AF_INET6 == addr->raw.family)
+        	addr->raw.family = PR_AF_INET6;
+#endif
         PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
         PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
         return PR_SUCCESS;
     }
 }  /* pt_GetPeerName */
 
 static PRStatus pt_GetSockOpt(
     PRFileDesc *fd, PRSockOption optname, void* optval, PRInt32* optlen)
@@ -2432,17 +2485,16 @@ static PRIOMethods _pr_udp_methods = {
     (PRSendfileFN)_PR_InvalidInt, 
     (PRReservedFN)_PR_InvalidInt, 
     (PRReservedFN)_PR_InvalidInt, 
     (PRReservedFN)_PR_InvalidInt, 
     (PRReservedFN)_PR_InvalidInt, 
     (PRReservedFN)_PR_InvalidInt
 };
 
-
 static PRIOMethods _pr_socketpollfd_methods = {
     (PRDescType) 0,
     (PRCloseFN)_PR_InvalidStatus,
     (PRReadFN)_PR_InvalidInt,
     (PRWriteFN)_PR_InvalidInt,
     (PRAvailableFN)_PR_InvalidInt,
     (PRAvailable64FN)_PR_InvalidInt64,
     (PRFsyncFN)_PR_InvalidStatus,
@@ -2631,50 +2683,72 @@ PR_IMPLEMENT(PRFileDesc*) PR_AllocFileDe
     fd->secret->inheritable = PR_TRUE;
     return fd;
     
 failed:
     PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
     return fd;
 }  /* PR_AllocFileDesc */
 
+extern PRStatus _pr_push_ipv6toipv4_layer(PRFileDesc *fd);
+
 PR_IMPLEMENT(PRFileDesc*) PR_Socket(PRInt32 domain, PRInt32 type, PRInt32 proto)
 {
     PRIntn osfd;
     PRDescType ftype;
     PRFileDesc *fd = NULL;
+	PRInt32 tmp_domain = domain;
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     if (pt_TestAbort()) return NULL;
 
     if (PF_INET != domain
-#if defined(_PR_INET6)
-        && PF_INET6 != domain
-#endif
+        && PR_AF_INET6 != domain
         && PF_UNIX != domain)
     {
         PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
         return fd;
     }
-    if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;
-    else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;
-    else
-    {
-        (void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
-        return fd;
-    }
+	if (type == SOCK_STREAM) ftype = PR_DESC_SOCKET_TCP;
+	else if (type == SOCK_DGRAM) ftype = PR_DESC_SOCKET_UDP;
+	else
+	{
+		(void)PR_SetError(PR_ADDRESS_NOT_SUPPORTED_ERROR, 0);
+		return fd;
+	}
+#if defined(_PR_INET6)
+	if (PR_AF_INET6 == domain)
+		domain = AF_INET6;
+#else
+	if (PR_AF_INET6 == domain)
+		domain = AF_INET;
+#endif
 
     osfd = socket(domain, type, proto);
     if (osfd == -1) pt_MapError(_PR_MD_MAP_SOCKET_ERROR, errno);
     else
     {
         fd = pt_SetMethods(osfd, ftype, PR_FALSE);
         if (fd == NULL) close(osfd);
     }
+#if !defined(_PR_INET6)
+	if (fd != NULL) {
+		/*
+		 * For platforms with no support for IPv6 
+		 * create layered socket for IPv4-mapped IPv6 addresses
+		 */
+		if (PR_AF_INET6 == tmp_domain) {
+			if (PR_FAILURE == _pr_push_ipv6toipv4_layer(fd)) {
+				PR_Close(fd);
+				fd = NULL;
+			}
+		}
+	}
+#endif
     return fd;
 }  /* PR_Socket */
 
 /*****************************************************************************/
 /****************************** I/O public methods ***************************/
 /*****************************************************************************/
 
 PR_IMPLEMENT(PRFileDesc*) PR_OpenFile(
--- a/pr/tests/cltsrv.c
+++ b/pr/tests/cltsrv.c
@@ -78,17 +78,17 @@
 */
 
 #define RECV_FLAGS 0
 #define SEND_FLAGS 0
 #define DEFAULT_LOW 0
 #define DEFAULT_HIGH 0
 #define BUFFER_SIZE 1024
 #define DEFAULT_BACKLOG 5
-#define DEFAULT_PORT 12848
+#define DEFAULT_PORT 12849
 #define DEFAULT_CLIENTS 1
 #define ALLOWED_IN_ACCEPT 1
 #define DEFAULT_CLIPPING 1000
 #define DEFAULT_WORKERS_MIN 1
 #define DEFAULT_WORKERS_MAX 1
 #define DEFAULT_SERVER "localhost"
 #define DEFAULT_EXECUTION_TIME 10
 #define DEFAULT_CLIENT_TIMEOUT 4000
@@ -768,18 +768,21 @@ static void PR_CALLBACK Server(void *arg
     server->listener = PR_Socket(domain, SOCK_STREAM, protocol);
 
     sockOpt.option = PR_SockOpt_Reuseaddr;
     sockOpt.value.reuse_addr = PR_TRUE;
     rv = PR_SetSocketOption(server->listener, &sockOpt);
     TEST_ASSERT(PR_SUCCESS == rv);
 
     memset(&serverAddress, 0, sizeof(serverAddress));
-    rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
-
+	if (PR_AF_INET6 != domain)
+		rv = PR_InitializeNetAddr(PR_IpAddrAny, DEFAULT_PORT, &serverAddress);
+	else
+		rv = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, DEFAULT_PORT,
+													&serverAddress);
     rv = PR_Bind(server->listener, &serverAddress);
     TEST_ASSERT(PR_SUCCESS == rv);
 
     rv = PR_Listen(server->listener, server->backlog);
     TEST_ASSERT(PR_SUCCESS == rv);
 
     server->started = PR_IntervalNow();
     TimeOfDayMessage("Server started at", me);
@@ -883,19 +886,17 @@ static void Help(void)
     PR_fprintf(debug_out, "\t-f <low>     low water mark for fd caching    (0)\n");
     PR_fprintf(debug_out, "\t-F <high>    high water mark for fd caching   (0)\n");
     PR_fprintf(debug_out, "\t-w <threads> minimal number of server threads (1)\n");
     PR_fprintf(debug_out, "\t-W <threads> maximum number of server threads (1)\n");
     PR_fprintf(debug_out, "\t-e <seconds> duration of the test in seconds  (10)\n");
     PR_fprintf(debug_out, "\t-s <string>  dsn name of server               (localhost)\n");
     PR_fprintf(debug_out, "\t-G           use GLOBAL threads               (LOCAL)\n");
     PR_fprintf(debug_out, "\t-X           use XTP as transport             (TCP)\n");
-#ifdef _PR_INET6
     PR_fprintf(debug_out, "\t-6           Use IPv6                         (IPv4)\n");
-#endif /* _PR_INET6 */
     PR_fprintf(debug_out, "\t-v           verbosity (accumulative)         (0)\n");
     PR_fprintf(debug_out, "\t-p           pthread statistics               (FALSE)\n");
     PR_fprintf(debug_out, "\t-d           debug mode                       (FALSE)\n");
     PR_fprintf(debug_out, "\t-h           this message\n");
 }  /* Help */
 
 static Verbosity IncrementVerbosity(void)
 {
@@ -946,22 +947,20 @@ PRIntn main(PRIntn argc, char** argv)
         switch (opt->option)
         {
         case 'G':  /* use global threads */
             thread_scope = PR_GLOBAL_THREAD;
             break;
         case 'X':  /* use XTP as transport */
             protocol = 36;
             break;
-#ifdef _PR_INET6
-	case '6':  /* Use IPv6 */
-            domain = AF_INET6;
+        case '6':  /* Use IPv6 */
+            domain = PR_AF_INET6;
             PR_SetIPv6Enable(PR_TRUE);
             break;
-#endif /* _PR_INET6 */
         case 'a':  /* the value for accepting */
             accepting = atoi(opt->value);
             break;
         case 'b':  /* the value for backlock */
             backlog = atoi(opt->value);
             break;
         case 'c':  /* number of client threads */
             clients = atoi(opt->value);
@@ -1092,19 +1091,23 @@ PRIntn main(PRIntn argc, char** argv)
         }
 
         for (index = 0; index < clients; ++index)
         {
             client[index].state = cs_init;
             client[index].ml = PR_NewLock();
             if (serverIsLocal)
             {
-                (void)PR_InitializeNetAddr(
-                    PR_IpAddrLoopback, DEFAULT_PORT,
-                    &client[index].serverAddress);
+				if (PR_AF_INET6 != domain)
+                	(void)PR_InitializeNetAddr(
+                    	PR_IpAddrLoopback, DEFAULT_PORT,
+                    	&client[index].serverAddress);
+				else
+					rv = PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6,
+							DEFAULT_PORT, &client[index].serverAddress);
             }
             else
             {
                 (void)PR_EnumerateHostEnt(
                     0, &host, DEFAULT_PORT, &client[index].serverAddress);
             }
             client[index].stateChange = PR_NewCondVar(client[index].ml);
             TEST_LOG(
--- a/pr/tests/gethost.c
+++ b/pr/tests/gethost.c
@@ -31,17 +31,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 
 #define DEFAULT_HOST_NAME "www.netscape.com"
 
 static void Help(void)
 {
     fprintf(stderr, "Usage: gethost [-6h] [hostname]\n");
-    fprintf(stderr, "\t-6          IPv6 mode       (default: FALSE)\n");
     fprintf(stderr, "\t-h          help\n");
     fprintf(stderr, "\thostname    Name of host    (default: %s)\n",
             DEFAULT_HOST_NAME);
 }  /* Help */
 
 /*
  * Prints the contents of a PRHostEnt structure
  */
@@ -70,27 +69,21 @@ int main(int argc, char **argv)
 {
     const char *hostName = DEFAULT_HOST_NAME;
     PRHostEnt he, reversehe;
     char buf[PR_NETDB_BUF_SIZE];
     char reversebuf[PR_NETDB_BUF_SIZE];
     PRIntn idx;
     PRNetAddr addr;
     PLOptStatus os;
-    PLOptState *opt = PL_CreateOptState(argc, argv, "6h");
+    PLOptState *opt = PL_CreateOptState(argc, argv, "h");
 
     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
         if (PL_OPT_BAD == os) continue;
         switch (opt->option) {
-            case '6':  /* Enable IPv6 */
-                if (PR_SetIPv6Enable(PR_TRUE) == PR_FAILURE) {
-                    fprintf(stderr, "PR_SetIPv6Enable failed\n");
-                    exit(1);
-                }
-                break;
             case 0:  /* naked */
                 hostName = opt->value;
                 break;
             case 'h':  /* Help message */
             default:
                 Help();
                 return 2;
         }
@@ -121,25 +114,23 @@ int main(int argc, char **argv)
 
     printf("PR_GetIPNodeByName with PR_AF_INET\n");
     if (PR_GetIPNodeByName(hostName, PR_AF_INET, PR_AI_DEFAULT,
             buf, sizeof(buf), &he) == PR_FAILURE) {
         fprintf(stderr, "PR_GetIPNodeByName failed\n");
         exit(1);
     }
     PrintHostent(&he);
-#ifdef _PR_INET6
     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);
-#endif
 
     PR_StringToNetAddr("::1", &addr);
     PR_StringToNetAddr("127.0.0.1", &addr);
 
     if (PR_InitializeNetAddr(PR_IpAddrAny, 0, &addr) == PR_FAILURE) {
         fprintf(stderr, "PR_InitializeNetAddr failed\n");
         exit(1);
     }
@@ -175,53 +166,56 @@ int main(int argc, char **argv)
 
     addr.inet.family = PR_AF_INET;
     addr.inet.port = 0;
     addr.inet.ip = PR_htonl(PR_INADDR_ANY);
     if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
         fprintf(stderr, "addr should be unspecified address\n");
         exit(1);
     }
+	{
+		char buf[256];
+		PR_NetAddrToString(&addr, buf, 256);
+		printf("IPv4 INADDRANY: %s\n", buf);
+	}
     addr.inet.family = PR_AF_INET;
     addr.inet.port = 0;
     addr.inet.ip = PR_htonl(PR_INADDR_LOOPBACK);
     if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
         fprintf(stderr, "addr should be loopback address\n");
         exit(1);
     }
+	{
+		char buf[256];
+		PR_NetAddrToString(&addr, buf, 256);
+		printf("IPv4 LOOPBACK: %s\n", buf);
+	}
 
-#if defined(_PR_INET6)
     if (PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
         fprintf(stderr, "PR_SetNetAddr failed\n");
         exit(1);
     }
     if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
         fprintf(stderr, "addr should be unspecified address\n");
         exit(1);
     }
+	{
+		char buf[256];
+		PR_NetAddrToString(&addr, buf, 256);
+		printf("IPv6 INADDRANY: %s\n", buf);
+	}
     if (PR_SetNetAddr(PR_IpAddrLoopback, PR_AF_INET6, 0, &addr) == PR_FAILURE) {
         fprintf(stderr, "PR_SetNetAddr failed\n");
         exit(1);
     }
     if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
         fprintf(stderr, "addr should be loopback address\n");
         exit(1);
     }
-
-    addr.ipv6.family = PR_AF_INET6;
-    addr.ipv6.port = 0;
-    addr.ipv6.ip = in6addr_any;
-    if (PR_IsNetAddrType(&addr, PR_IpAddrAny) == PR_FALSE) {
-        fprintf(stderr, "addr should be unspecified address\n");
-        exit(1);
-    }
-    addr.ipv6.family = PR_AF_INET6;
-    addr.ipv6.port = 0;
-    addr.ipv6.ip = in6addr_loopback;
-    if (PR_IsNetAddrType(&addr, PR_IpAddrLoopback) == PR_FALSE) {
-        fprintf(stderr, "addr should be loopback address\n");
-        exit(1);
-    }
-#endif /* _PR_INET6 */
+	{
+		char buf[256];
+		PR_NetAddrToString(&addr, buf, 256);
+		printf("IPv6 LOOPBACK: %s\n", buf);
+	}
 
     printf("PASS\n");
     return 0;
 }