Bug 807678: Don't proliferate NSPR DNS types beyond the host resolver itself. Make it possible to easily hook up other host resolvers. r=sworkman
authorJosh Aas <joshmoz@gmail.com>
Thu, 13 Dec 2012 09:18:33 -0500
changeset 115930 744b40b75241
parent 115929 5aed5087fb7b
child 115931 097b8aa46e57
push id24034
push useremorley@mozilla.com
push dateFri, 14 Dec 2012 15:28:57 +0000
treeherdermozilla-central@50d8f411d305 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssworkman
bugs807678
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 807678: Don't proliferate NSPR DNS types beyond the host resolver itself. Make it possible to easily hook up other host resolvers. r=sworkman
netwerk/base/public/nsINetAddr.idl
netwerk/base/public/nsISocketTransport.idl
netwerk/base/src/ProxyAutoConfig.cpp
netwerk/base/src/ProxyAutoConfig.h
netwerk/base/src/nsNetAddr.cpp
netwerk/base/src/nsNetAddr.h
netwerk/base/src/nsServerSocket.cpp
netwerk/base/src/nsSocketTransport2.cpp
netwerk/base/src/nsSocketTransport2.h
netwerk/dns/DNS.cpp
netwerk/dns/DNS.h
netwerk/dns/Makefile.in
netwerk/dns/nsDNSService2.cpp
netwerk/dns/nsHostResolver.cpp
netwerk/dns/nsHostResolver.h
netwerk/dns/nsIDNSRecord.idl
netwerk/ipc/NeckoMessageUtils.h
netwerk/protocol/ftp/nsFtpConnectionThread.cpp
netwerk/protocol/ftp/nsFtpConnectionThread.h
netwerk/protocol/http/HttpBaseChannel.cpp
netwerk/protocol/http/HttpBaseChannel.h
netwerk/protocol/http/HttpChannelChild.cpp
netwerk/protocol/http/HttpChannelChild.h
netwerk/protocol/http/PHttpChannel.ipdl
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/socket/nsISOCKSSocketInfo.idl
netwerk/socket/nsSOCKSIOLayer.cpp
--- a/netwerk/base/public/nsINetAddr.idl
+++ b/netwerk/base/public/nsINetAddr.idl
@@ -1,37 +1,35 @@
 /* vim: et ts=4 sw=4 tw=80 
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-native PRNetAddr(union PRNetAddr);
-
 /**
  * nsINetAddr
  *
- * This interface represents a (native) PRNetAddr struct in a readonly
+ * This interface represents a native NetAddr struct in a readonly
  * interface.
  */
 [scriptable, uuid(c407ab6c-c3ca-4cb2-a99b-a7dfbb88af33)]
 interface nsINetAddr : nsISupports
 {
     /**
      * @return the address family of the network address, which corresponds to
      * one of the FAMILY_ constants.
      */
     readonly attribute unsigned short family;
 
     /**
      * @return Either the IP address (FAMILY_INET, FAMILY_INET6) or the path
      * (FAMILY_LOCAL) in string form. IP addresses are in the format produced by
-     * PR_NetAddrToString.
+     * mozilla::net::NetAddrToString.
      *
      * Note: Paths for FAMILY_LOCAL may have length limitations which are
      * implementation dependent and not documented as part of this interface.
      */
     readonly attribute AUTF8String address;
 
     /**
      * @return the port number for a FAMILY_INET or FAMILY_INET6 address.
@@ -56,14 +54,14 @@ interface nsINetAddr : nsISupports
      * @see http://tools.ietf.org/html/rfc4007
      *
      * @throws NS_ERROR_NOT_AVAILABLE if the address family is not FAMILY_INET6
      */
     readonly attribute unsigned long scope;
 
     /**
      * Network address families. These correspond to all the network address
-     * families supported by the PRNetAddr struct.
+     * families supported by the NetAddr struct.
      */
     const unsigned long FAMILY_INET = 1;
     const unsigned long FAMILY_INET6 = 2;
     const unsigned long FAMILY_LOCAL = 3;
 };
--- a/netwerk/base/public/nsISocketTransport.idl
+++ b/netwerk/base/public/nsISocketTransport.idl
@@ -3,52 +3,55 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsITransport.idl"
 #include "nsINetAddr.idl"
 
 interface nsIInterfaceRequestor;
 
-native PRNetAddr(union PRNetAddr);
+%{ C++
+#include "mozilla/net/DNS.h"
+%}
+native NetAddr(mozilla::net::NetAddr);
 
 /**
  * nsISocketTransport
  *
  * NOTE: Connection setup is triggered by opening an input or output stream,
  * it does not start on its own. Completion of the connection setup is
  * indicated by a STATUS_CONNECTED_TO notification to the event sink (if set).
  *
  * NOTE: This is a free-threaded interface, meaning that the methods on
  * this interface may be called from any thread.
  */
-[scriptable, uuid(91ca3523-fc52-4dea-b167-ef8f56473dde)]
+[scriptable, uuid(A8318027-0DDC-4E60-A89B-D81AFE3B5020)]
 interface nsISocketTransport : nsITransport 
 {
     /**
      * Get the host for the underlying socket connection.
      */
     readonly attribute AUTF8String host;
 
     /**
      * Get the port for the underlying socket connection.
      */
     readonly attribute long port;
 
     /** 
      * Returns the IP address of the socket connection peer. This
      * attribute is defined only once a connection has been established.
      */
-    [noscript] PRNetAddr getPeerAddr();
+    [noscript] NetAddr getPeerAddr();
 
     /** 
      * Returns the IP address of the initiating end. This attribute
      * is defined only once a connection has been established.
      */
-    [noscript] PRNetAddr getSelfAddr();
+    [noscript] NetAddr getSelfAddr();
 
     /** 
      * Returns a scriptable version of getPeerAddr. This attribute is defined
      * only once a connection has been established.
      */
     nsINetAddr getScriptablePeerAddr();
 
     /** 
--- a/netwerk/base/src/ProxyAutoConfig.cpp
+++ b/netwerk/base/src/ProxyAutoConfig.cpp
@@ -10,16 +10,17 @@
 #include "nsIDNSRecord.h"
 #include "nsIDNSService.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsIConsoleService.h"
 #include "nsJSUtils.h"
 #include "prnetdb.h"
 #include "nsITimer.h"
+#include "mozilla/net/DNS.h"
 
 namespace mozilla {
 namespace net {
 
 // These are some global helper symbols the PAC format requires that we provide that
 // are initialized as part of the global javascript context used for PAC evaluations.
 // Additionally dnsResolve(host) and myIpAddress() are supplied in the same context
 // but are implemented as c++ helpers. alert(msg) is similarly defined.
@@ -308,30 +309,30 @@ PACErrorReporter(JSContext *cx, const ch
   formattedMessage += report->uclinebuf;
   formattedMessage += NS_LITERAL_STRING("]");
   PACLogToConsole(formattedMessage);
 }
 
 // timeout of 0 means the normal necko timeout strategy, otherwise the dns request
 // will be canceled after aTimeout milliseconds
 static
-JSBool PACResolve(const nsCString &aHostName, PRNetAddr *aNetAddr,
+JSBool PACResolve(const nsCString &aHostName, NetAddr *aNetAddr,
                   unsigned int aTimeout)
 {
   if (!sRunning) {
     NS_WARNING("PACResolve without a running ProxyAutoConfig object");
     return false;
   }
 
   return sRunning->ResolveAddress(aHostName, aNetAddr, aTimeout);
 }
 
 bool
 ProxyAutoConfig::ResolveAddress(const nsCString &aHostName,
-                                PRNetAddr *aNetAddr,
+                                NetAddr *aNetAddr,
                                 unsigned int aTimeout)
 {
   nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID);
   if (!dns)
     return false;
 
   nsRefPtr<PACResolver> helper = new PACResolver();
 
@@ -361,22 +362,22 @@ ProxyAutoConfig::ResolveAddress(const ns
   return true;
 }
 
 static
 bool PACResolveToString(const nsCString &aHostName,
                         nsCString &aDottedDecimal,
                         unsigned int aTimeout)
 {
-  PRNetAddr netAddr;
+  NetAddr netAddr;
   if (!PACResolve(aHostName, &netAddr, aTimeout))
     return false;
 
   char dottedDecimal[128];
-  if (PR_NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal)) != PR_SUCCESS)
+  if (!NetAddrToString(&netAddr, dottedDecimal, sizeof(dottedDecimal)))
     return false;
 
   aDottedDecimal.Assign(dottedDecimal);
   return true;
 }
 
 // dnsResolve(host) javascript implementation
 static
@@ -681,24 +682,26 @@ ProxyAutoConfig::Shutdown()
     return;
 
   mShutdown = true;
   delete mJSRuntime;
   mJSRuntime = nullptr;
 }
 
 bool
-ProxyAutoConfig::SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress)
+ProxyAutoConfig::SrcAddress(const NetAddr *remoteAddress, nsCString &localAddress)
 {
   PRFileDesc *fd;
   fd = PR_OpenUDPSocket(remoteAddress->raw.family);
   if (!fd)
     return false;
 
-  if (PR_Connect(fd, remoteAddress, 0) != PR_SUCCESS) {
+  PRNetAddr prRemoteAddress;
+  NetAddrToPRNetAddr(remoteAddress, &prRemoteAddress);
+  if (PR_Connect(fd, &prRemoteAddress, 0) != PR_SUCCESS) {
     PR_Close(fd);
     return false;
   }
 
   PRNetAddr localName;
   if (PR_GetSockName(fd, &localName) != PR_SUCCESS) {
     PR_Close(fd);
     return false;
@@ -719,17 +722,17 @@ ProxyAutoConfig::SrcAddress(const PRNetA
 // to the result. If that all works, the local IP address of the socket is
 // returned to the javascript caller and true is returned from this function.
 // otherwise false is returned.
 bool
 ProxyAutoConfig::MyIPAddressTryHost(const nsCString &hostName,
                                     unsigned int timeout,
                                     jsval *vp)
 {
-  PRNetAddr remoteAddress;
+  NetAddr remoteAddress;
   nsAutoCString localDottedDecimal;
   JSContext *cx = mJSRuntime->Context();
 
   if (PACResolve(hostName, &remoteAddress, timeout) &&
       SrcAddress(&remoteAddress, localDottedDecimal)) {
     JSString *dottedDecimalString =
       JS_NewStringCopyZ(cx, localDottedDecimal.get());
     JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(dottedDecimalString));
--- a/netwerk/base/src/ProxyAutoConfig.h
+++ b/netwerk/base/src/ProxyAutoConfig.h
@@ -7,16 +7,17 @@
 #ifndef ProxyAutoConfig_h__
 #define ProxyAutoConfig_h__
 
 #include "nsString.h"
 #include "jsapi.h"
 #include "prio.h"
 #include "nsITimer.h"
 #include "nsAutoPtr.h"
+#include "mozilla/net/DNS.h"
 
 namespace mozilla { namespace net {
 
 class JSRuntimeWrapper;
 
 // The ProxyAutoConfig class is meant to be created and run on a
 // non main thread. It synchronously resolves PAC files by blocking that
 // thread and running nested event loops. GetProxyForURI is not re-entrant.
@@ -33,17 +34,17 @@ public:
   ~ProxyAutoConfig();
 
   nsresult Init(const nsCString &aPACURI,
                 const nsCString &aPACScript);
   void     Shutdown();
   void     GC();
   bool     MyIPAddress(jsval *vp);
   bool     ResolveAddress(const nsCString &aHostName,
-                          PRNetAddr *aNetAddr, unsigned int aTimeout);
+                          NetAddr *aNetAddr, unsigned int aTimeout);
 
   /**
    * Get the proxy string for the specified URI.  The proxy string is
    * given by the following:
    *
    *   result      = proxy-spec *( proxy-sep proxy-spec )
    *   proxy-spec  = direct-type | proxy-type LWS proxy-host [":" proxy-port]
    *   direct-type = "DIRECT"
@@ -79,17 +80,17 @@ public:
                           nsACString &result);
 
 private:
   const static unsigned int kTimeout = 1000; // ms to allow for myipaddress dns queries
 
   // used to compile the PAC file and setup the execution context
   nsresult SetupJS();
 
-  bool SrcAddress(const PRNetAddr *remoteAddress, nsCString &localAddress);
+  bool SrcAddress(const NetAddr *remoteAddress, nsCString &localAddress);
   bool MyIPAddressTryHost(const nsCString &hostName, unsigned int timeout,
                           jsval *vp);
 
   JSRuntimeWrapper *mJSRuntime;
   bool              mJSNeedsSetup;
   bool              mShutdown;
   nsCString         mPACScript;
   nsCString         mPACURI;
--- a/netwerk/base/src/nsNetAddr.cpp
+++ b/netwerk/base/src/nsNetAddr.cpp
@@ -1,123 +1,132 @@
 /* vim: et ts=2 sw=2 tw=80 
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsNetAddr.h"
 #include "nsString.h"
+#include "prnetdb.h"
 
-#include "prnetdb.h"
+using namespace mozilla::net;
 
 NS_IMPL_ISUPPORTS1(nsNetAddr, nsINetAddr)
 
 /* Makes a copy of |addr| */
-nsNetAddr::nsNetAddr(PRNetAddr* addr)
+nsNetAddr::nsNetAddr(NetAddr* addr)
 {
   NS_ASSERTION(addr, "null addr");
   mAddr = *addr;
 }
 
 /* readonly attribute unsigned short family; */
 NS_IMETHODIMP nsNetAddr::GetFamily(uint16_t *aFamily)
 {
   switch(mAddr.raw.family) {
-  case PR_AF_INET: 
+  case AF_INET:
     *aFamily = nsINetAddr::FAMILY_INET;
     break;
-  case PR_AF_INET6:
+  case AF_INET6:
     *aFamily = nsINetAddr::FAMILY_INET6;
     break;
-  case PR_AF_LOCAL:
+#if defined(XP_UNIX) || defined(XP_OS2)
+  case AF_LOCAL:
     *aFamily = nsINetAddr::FAMILY_LOCAL;
     break;
+#endif
   default:
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 /* readonly attribute AUTF8String address; */
 NS_IMETHODIMP nsNetAddr::GetAddress(nsACString & aAddress)
 {
   switch(mAddr.raw.family) {
   /* PR_NetAddrToString can handle INET and INET6, but not LOCAL. */
-  case PR_AF_INET: 
-    aAddress.SetCapacity(16);
-    PR_NetAddrToString(&mAddr, aAddress.BeginWriting(), 16);
+  case AF_INET:
+    aAddress.SetCapacity(kIPv4CStrBufSize);
+    NetAddrToString(&mAddr, aAddress.BeginWriting(), kIPv4CStrBufSize);
     aAddress.SetLength(strlen(aAddress.BeginReading()));
     break;
-  case PR_AF_INET6:
-    aAddress.SetCapacity(46);
-    PR_NetAddrToString(&mAddr, aAddress.BeginWriting(), 46);
+  case AF_INET6:
+    aAddress.SetCapacity(kIPv6CStrBufSize);
+    NetAddrToString(&mAddr, aAddress.BeginWriting(), kIPv6CStrBufSize);
     aAddress.SetLength(strlen(aAddress.BeginReading()));
     break;
 #if defined(XP_UNIX) || defined(XP_OS2)
-  case PR_AF_LOCAL:
+  case AF_LOCAL:
     aAddress.Assign(mAddr.local.path);
     break;
 #endif
   // PR_AF_LOCAL falls through to default when not XP_UNIX || XP_OS2
   default:
     return NS_ERROR_UNEXPECTED;
   }
   
   return NS_OK;
 }
 
 /* readonly attribute unsigned short port; */
 NS_IMETHODIMP nsNetAddr::GetPort(uint16_t *aPort)
 {
   switch(mAddr.raw.family) {
-  case PR_AF_INET: 
-    *aPort = PR_ntohs(mAddr.inet.port);
+  case AF_INET:
+    *aPort = ntohs(mAddr.inet.port);
     break;
-  case PR_AF_INET6:
-    *aPort = PR_ntohs(mAddr.ipv6.port);
+  case AF_INET6:
+    *aPort = ntohs(mAddr.inet6.port);
     break;
-  case PR_AF_LOCAL:
+#if defined(XP_UNIX) || defined(XP_OS2)
+  case AF_LOCAL:
     // There is no port number for local / connections.
     return NS_ERROR_NOT_AVAILABLE;
+#endif
   default:
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 /* readonly attribute unsigned long flow; */
 NS_IMETHODIMP nsNetAddr::GetFlow(uint32_t *aFlow)
 {
   switch(mAddr.raw.family) {
-  case PR_AF_INET6:
-    *aFlow = PR_ntohl(mAddr.ipv6.flowinfo);
+  case AF_INET6:
+    *aFlow = ntohl(mAddr.inet6.flowinfo);
     break;
-  case PR_AF_INET: 
-  case PR_AF_LOCAL:
+  case AF_INET:
+#if defined(XP_UNIX) || defined(XP_OS2)
+  case AF_LOCAL:
+#endif
     // only for IPv6
     return NS_ERROR_NOT_AVAILABLE;
   default:
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
 /* readonly attribute unsigned long scope; */
 NS_IMETHODIMP nsNetAddr::GetScope(uint32_t *aScope)
 {
   switch(mAddr.raw.family) {
-  case PR_AF_INET6:
-    *aScope = PR_ntohl(mAddr.ipv6.scope_id);
+  case AF_INET6:
+    *aScope = ntohl(mAddr.inet6.scope_id);
     break;
-  case PR_AF_INET: 
-  case PR_AF_LOCAL:
+  case AF_INET:
+#if defined(XP_UNIX) || defined(XP_OS2)
+  case AF_LOCAL:
+#endif
     // only for IPv6
     return NS_ERROR_NOT_AVAILABLE;
   default:
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
--- a/netwerk/base/src/nsNetAddr.h
+++ b/netwerk/base/src/nsNetAddr.h
@@ -3,27 +3,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsNetAddr_h__
 #define nsNetAddr_h__
 
 #include "nsINetAddr.h"
-#include "prio.h"
+#include "mozilla/net/DNS.h"
 #include "mozilla/Attributes.h"
 
 class nsNetAddr MOZ_FINAL : public nsINetAddr
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSINETADDR
 
-  nsNetAddr(PRNetAddr* addr);
+  nsNetAddr(mozilla::net::NetAddr* addr);
 
 private:
-  PRNetAddr mAddr;
+  mozilla::net::NetAddr mAddr;
 
 protected:
   /* additional members */
 };
 
 #endif // !nsNetAddr_h__
--- a/netwerk/base/src/nsServerSocket.cpp
+++ b/netwerk/base/src/nsServerSocket.cpp
@@ -8,18 +8,20 @@
 #include "nsServerSocket.h"
 #include "nsProxyRelease.h"
 #include "nsAutoPtr.h"
 #include "nsError.h"
 #include "nsNetCID.h"
 #include "prnetdb.h"
 #include "prio.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/net/DNS.h"
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
 
 //-----------------------------------------------------------------------------
 
 typedef void (nsServerSocket:: *nsServerSocketFunc)(void);
 
 static nsresult
@@ -162,19 +164,21 @@ nsServerSocket::OnSocketReady(PRFileDesc
   if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL))
   {
     NS_WARNING("error polling on listening socket");
     mCondition = NS_ERROR_UNEXPECTED;
     return;
   }
 
   PRFileDesc *clientFD;
-  PRNetAddr clientAddr;
+  PRNetAddr prClientAddr;
+  NetAddr clientAddr;
 
-  clientFD = PR_Accept(mFD, &clientAddr, PR_INTERVAL_NO_WAIT);
+  clientFD = PR_Accept(mFD, &prClientAddr, PR_INTERVAL_NO_WAIT);
+  PRNetAddrToNetAddr(&prClientAddr, &clientAddr);
   if (!clientFD)
   {
     NS_WARNING("PR_Accept failed");
     mCondition = NS_ERROR_UNEXPECTED;
   }
   else
   {
     nsRefPtr<nsSocketTransport> trans = new nsSocketTransport;
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -34,16 +34,17 @@
 #include "nsIProgrammingLanguage.h"
 #include "nsIClassInfoImpl.h"
 
 #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
 #include "nsNativeConnectionHelper.h"
 #endif
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 //-----------------------------------------------------------------------------
 
 static NS_DEFINE_CID(kSocketProviderServiceCID, NS_SOCKETPROVIDERSERVICE_CID);
 static NS_DEFINE_CID(kDNSServiceCID, NS_DNSSERVICE_CID);
 
 //-----------------------------------------------------------------------------
 
@@ -801,32 +802,32 @@ nsSocketTransport::Init(const char **typ
             }
         }
     }
 
     return NS_OK;
 }
 
 nsresult
-nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const PRNetAddr *addr)
+nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
 {
     NS_ASSERTION(!mFD, "already initialized");
 
-    char buf[64];
-    PR_NetAddrToString(addr, buf, sizeof(buf));
+    char buf[kIPv6CStrBufSize];
+    NetAddrToString(addr, buf, sizeof(buf));
     mHost.Assign(buf);
 
     uint16_t port;
-    if (addr->raw.family == PR_AF_INET)
+    if (addr->raw.family == AF_INET)
         port = addr->inet.port;
     else
-        port = addr->ipv6.port;
-    mPort = PR_ntohs(port);
+        port = addr->inet6.port;
+    mPort = ntohs(port);
 
-    memcpy(&mNetAddr, addr, sizeof(PRNetAddr));
+    memcpy(&mNetAddr, addr, sizeof(NetAddr));
 
     mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
     mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
     mState = STATE_TRANSFERRING;
     mNetAddrIsSet = true;
 
     mFD = fd;
     mFDref = 1;
@@ -902,17 +903,19 @@ nsSocketTransport::ResolveHost()
             // Name resolution is done on the server side.  Just pretend
             // client resolution is complete, this will get picked up later.
             // since we don't need to do DNS now, we bypass the resolving
             // step by initializing mNetAddr to an empty address, but we
             // must keep the port. The SOCKS IO layer will use the hostname
             // we send it when it's created, rather than the empty address
             // we send with the connect call.
             mState = STATE_RESOLVING;
-            PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, SocketPort(), &mNetAddr);
+            mNetAddr.raw.family = AF_INET;
+            mNetAddr.inet.port = htons(SocketPort());
+            mNetAddr.inet.ip = htonl(INADDR_ANY);
             return PostEvent(MSG_DNS_LOOKUP_COMPLETE, NS_OK, nullptr);
         }
     }
 
     nsCOMPtr<nsIDNSService> dns = do_GetService(kDNSServiceCID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     mResolving = true;
@@ -1047,17 +1050,17 @@ nsSocketTransport::BuildSocket(PRFileDes
 nsresult
 nsSocketTransport::InitiateSocket()
 {
     SOCKET_LOG(("nsSocketTransport::InitiateSocket [this=%x]\n", this));
 
     nsresult rv;
 
     if (gIOService->IsOffline() &&
-        !PR_IsNetAddrType(&mNetAddr, PR_IpAddrLoopback))
+        !IsLoopBackAddress(&mNetAddr))
         return NS_ERROR_OFFLINE;
 
     //
     // find out if it is going to be ok to attach another socket to the STS.
     // if not then we have to wait for the STS to tell us that it is ok.
     // the notification is asynchronous, which means that when we could be
     // in a race to call AttachSocket once notified.  for this reason, when
     // we get notified, we just re-enter this function.  as a result, we are
@@ -1153,26 +1156,28 @@ nsSocketTransport::InitiateSocket()
 
     SOCKET_LOG(("  advancing to STATE_CONNECTING\n"));
     mState = STATE_CONNECTING;
     mPollTimeout = mTimeouts[TIMEOUT_CONNECT];
     SendStatus(NS_NET_STATUS_CONNECTING_TO);
 
 #if defined(PR_LOGGING)
     if (SOCKET_LOG_ENABLED()) {
-        char buf[64];
-        PR_NetAddrToString(&mNetAddr, buf, sizeof(buf));
+        char buf[kIPv6CStrBufSize];
+        NetAddrToString(&mNetAddr, buf, sizeof(buf));
         SOCKET_LOG(("  trying address: %s\n", buf));
     }
 #endif
 
     // 
     // Initiate the connect() to the host...  
     //
-    status = PR_Connect(fd, &mNetAddr, NS_SOCKET_CONNECT_TIMEOUT);
+    PRNetAddr prAddr;
+    NetAddrToPRNetAddr(&mNetAddr, &prAddr);
+    status = PR_Connect(fd, &prAddr, NS_SOCKET_CONNECT_TIMEOUT);
     if (status == PR_SUCCESS) {
         // 
         // we are connected!
         //
         OnSocketConnected();
     }
     else {
         PRErrorCode code = PR_GetError();
@@ -1674,17 +1679,17 @@ nsSocketTransport::OnSocketDetached(PRFi
     }
 }
 
 void
 nsSocketTransport::IsLocal(bool *aIsLocal)
 {
     {
         MutexAutoLock lock(mLock);
-        *aIsLocal = PR_IsNetAddrType(&mNetAddr, PR_IpAddrLoopback);
+        *aIsLocal = IsLoopBackAddress(&mNetAddr);
     }
 }
 
 //-----------------------------------------------------------------------------
 // xpcom api
 
 NS_IMPL_THREADSAFE_ISUPPORTS4(nsSocketTransport,
                               nsISocketTransport,
@@ -1895,81 +1900,84 @@ nsSocketTransport::GetHost(nsACString &h
 NS_IMETHODIMP
 nsSocketTransport::GetPort(int32_t *port)
 {
     *port = (int32_t) SocketPort();
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSocketTransport::GetPeerAddr(PRNetAddr *addr)
+nsSocketTransport::GetPeerAddr(NetAddr *addr)
 {
     // once we are in the connected state, mNetAddr will not change.
     // so if we can verify that we are in the connected state, then
     // we can freely access mNetAddr from any thread without being
     // inside a critical section.
 
     if (!mNetAddrIsSet) {
         SOCKET_LOG(("nsSocketTransport::GetPeerAddr [this=%p state=%d] "
                     "NOT_AVAILABLE because not yet connected.", this, mState));
         return NS_ERROR_NOT_AVAILABLE;
     }
 
-    memcpy(addr, &mNetAddr, sizeof(mNetAddr));
+    memcpy(addr, &mNetAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSocketTransport::GetSelfAddr(PRNetAddr *addr)
+nsSocketTransport::GetSelfAddr(NetAddr *addr)
 {
     // we must not call any PR methods on our file descriptor
     // while holding mLock since those methods might re-enter
     // socket transport code.
 
     PRFileDesc *fd;
     {
         MutexAutoLock lock(mLock);
         fd = GetFD_Locked();
     }
 
-    if (!fd)
+    if (!fd) {
         return NS_ERROR_NOT_CONNECTED;
+    }
 
+    PRNetAddr prAddr;
     nsresult rv =
-        (PR_GetSockName(fd, addr) == PR_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
+        (PR_GetSockName(fd, &prAddr) == PR_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
+    PRNetAddrToNetAddr(&prAddr, addr);
 
     {
         MutexAutoLock lock(mLock);
         ReleaseFD_Locked(fd);
     }
 
     return rv;
 }
 
 /* nsINetAddr getScriptablePeerAddr (); */
 NS_IMETHODIMP
 nsSocketTransport::GetScriptablePeerAddr(nsINetAddr * *addr)
 {
-    PRNetAddr rawAddr;
+    NetAddr rawAddr;
 
     nsresult rv;
     rv = GetPeerAddr(&rawAddr);
     if (NS_FAILED(rv))
         return rv;
 
     NS_ADDREF(*addr = new nsNetAddr(&rawAddr));
 
     return NS_OK;
 }
 
 /* nsINetAddr getScriptableSelfAddr (); */
 NS_IMETHODIMP
 nsSocketTransport::GetScriptableSelfAddr(nsINetAddr * *addr)
 {
-    PRNetAddr rawAddr;
+    NetAddr rawAddr;
 
     nsresult rv;
     rv = GetSelfAddr(&rawAddr);
     if (NS_FAILED(rv))
         return rv;
 
     NS_ADDREF(*addr = new nsNetAddr(&rawAddr));
 
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -17,16 +17,17 @@
 #include "nsISocketTransport.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIAsyncOutputStream.h"
 #include "nsIDNSListener.h"
 #include "nsIDNSRecord.h"
 #include "nsICancelable.h"
 #include "nsIClassInfo.h"
+#include "mozilla/net/DNS.h"
 
 class nsSocketTransport;
 
 //-----------------------------------------------------------------------------
 
 // after this short interval, we will return to PR_Poll
 #define NS_SOCKET_CONNECT_TIMEOUT PR_MillisecondsToInterval(20)
 
@@ -116,17 +117,17 @@ public:
     // given type(s) to the given host or proxy.
     nsresult Init(const char **socketTypes, uint32_t typeCount,
                   const nsACString &host, uint16_t port,
                   nsIProxyInfo *proxyInfo);
 
     // this method instructs the socket transport to use an already connected
     // socket with the given address.
     nsresult InitWithConnectedSocket(PRFileDesc *socketFD,
-                                     const PRNetAddr *addr);
+                                     const mozilla::net::NetAddr *addr);
 
     // nsASocketHandler methods:
     void OnSocketReady(PRFileDesc *, int16_t outFlags); 
     void OnSocketDetached(PRFileDesc *);
     void IsLocal(bool *aIsLocal);
 
     // called when a socket event is handled
     void OnSocketEvent(uint32_t type, nsresult status, nsISupports *param);
@@ -194,17 +195,17 @@ private:
     // recursively or not.  this flag is not protected by any lock.
     bool mResolving;
 
     nsCOMPtr<nsICancelable> mDNSRequest;
     nsCOMPtr<nsIDNSRecord>  mDNSRecord;
 
     // mNetAddr is valid from GetPeerAddr() once we have
     // reached STATE_TRANSFERRING. It must not change after that.
-    PRNetAddr               mNetAddr;
+    mozilla::net::NetAddr   mNetAddr;
     bool                    mNetAddrIsSet;
 
     // socket methods (these can only be called on the socket thread):
 
     void     SendStatus(nsresult status);
     nsresult ResolveHost();
     nsresult BuildSocket(PRFileDesc *&, bool &, bool &); 
     nsresult InitiateSocket();
new file mode 100644
--- /dev/null
+++ b/netwerk/dns/DNS.cpp
@@ -0,0 +1,199 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/net/DNS.h"
+
+#include "mozilla/Assertions.h"
+#include "mozilla/mozalloc.h"
+#include <string.h>
+
+#ifdef XP_WIN
+#include "Ws2tcpip.h"
+#endif
+
+namespace mozilla {
+namespace net {
+
+const char *inet_ntop_internal(int af, const void *src, char *dst, socklen_t size)
+{
+#ifdef XP_WIN
+  if (af == AF_INET) {
+    struct sockaddr_in s;
+    memset(&s, 0, sizeof(s));
+    s.sin_family = AF_INET;
+    memcpy(&s.sin_addr, src, sizeof(struct in_addr));
+    getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in), dst, size, NULL, 0, NI_NUMERICHOST);
+    return dst;
+  }
+  else if (af == AF_INET6) {
+    struct sockaddr_in6 s;
+    memset(&s, 0, sizeof(s));
+    s.sin6_family = AF_INET6;
+    memcpy(&s.sin6_addr, src, sizeof(struct in_addr6));
+    getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in6), dst, size, NULL, 0, NI_NUMERICHOST);
+    return dst;
+  }
+  return NULL;
+#else
+  return inet_ntop(af, src, dst, size);
+#endif
+}
+
+// Copies the contents of a PRNetAddr to a NetAddr.
+// Does not do a ptr safety check!
+void PRNetAddrToNetAddr(const PRNetAddr *prAddr, NetAddr *addr)
+{
+  if (prAddr->raw.family == PR_AF_INET) {
+    addr->inet.family = AF_INET;
+    addr->inet.port = prAddr->inet.port;
+    addr->inet.ip = prAddr->inet.ip;
+  }
+  else if (prAddr->raw.family == PR_AF_INET6) {
+    addr->inet6.family = AF_INET6;
+    addr->inet6.port = prAddr->ipv6.port;
+    addr->inet6.flowinfo = prAddr->ipv6.flowinfo;
+    memcpy(&addr->inet6.ip, &prAddr->ipv6.ip, sizeof(addr->inet6.ip.u8));
+    addr->inet6.scope_id = prAddr->ipv6.scope_id;
+  }
+#if defined(XP_UNIX) || defined(XP_OS2)
+  else if (prAddr->raw.family == PR_AF_LOCAL) {
+    addr->local.family = AF_LOCAL;
+    memcpy(addr->local.path, prAddr->local.path, sizeof(addr->local.path));
+  }
+#endif
+}
+
+// Copies the contents of a NetAddr to a PRNetAddr.
+// Does not do a ptr safety check!
+void NetAddrToPRNetAddr(const NetAddr *addr, PRNetAddr *prAddr)
+{
+  if (addr->raw.family == AF_INET) {
+    prAddr->inet.family = PR_AF_INET;
+    prAddr->inet.port = addr->inet.port;
+    prAddr->inet.ip = addr->inet.ip;
+  }
+  else if (addr->raw.family == AF_INET6) {
+    prAddr->ipv6.family = PR_AF_INET6;
+    prAddr->ipv6.port = addr->inet6.port;
+    prAddr->ipv6.flowinfo = addr->inet6.flowinfo;
+    memcpy(&prAddr->ipv6.ip, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
+    prAddr->ipv6.scope_id = addr->inet6.scope_id;
+  }
+#if defined(XP_UNIX) || defined(XP_OS2)
+  else if (addr->raw.family == AF_LOCAL) {
+    prAddr->local.family = PR_AF_LOCAL;
+    memcpy(prAddr->local.path, addr->local.path, sizeof(addr->local.path));
+  }
+#endif
+}
+
+bool NetAddrToString(const NetAddr *addr, char *buf, uint32_t bufSize)
+{
+  if (addr->raw.family == AF_INET) {
+    if (bufSize < INET_ADDRSTRLEN) {
+      return false;
+    }
+    struct in_addr nativeAddr = {};
+    nativeAddr.s_addr = addr->inet.ip;
+    return !!inet_ntop_internal(AF_INET, &nativeAddr, buf, bufSize);
+  }
+  else if (addr->raw.family == AF_INET6) {
+    if (bufSize < INET6_ADDRSTRLEN) {
+      return false;
+    }
+    struct in6_addr nativeAddr = {};
+    memcpy(&nativeAddr.s6_addr, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
+    return !!inet_ntop_internal(AF_INET6, &nativeAddr, buf, bufSize);
+  }
+#if defined(XP_UNIX) || defined(XP_OS2)
+  else if (addr->raw.family == AF_LOCAL) {
+    if (bufSize < sizeof(addr->local.path)) {
+      return false;
+    }
+    memcpy(buf, addr->local.path, bufSize);
+    return true;
+  }
+#endif
+  return false;
+}
+
+bool IsLoopBackAddress(const NetAddr *addr)
+{
+  if (addr->raw.family == AF_INET) {
+    return (addr->inet.ip == htonl(INADDR_LOOPBACK));
+  }
+  else if (addr->raw.family == AF_INET6) {
+    if (IPv6ADDR_IS_LOOPBACK(&addr->inet6.ip)) {
+      return true;
+    } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
+               IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_LOOPBACK)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool IsIPAddrAny(const NetAddr *addr)
+{
+  if (addr->raw.family == AF_INET) {
+    if (addr->inet.ip == htonl(INADDR_ANY)) {
+      return true;
+    }
+  }
+  else if (addr->raw.family == AF_INET6) {
+    if (IPv6ADDR_IS_UNSPECIFIED(&addr->inet6.ip)) {
+      return true;
+    } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
+               IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_ANY)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool IsIPAddrV4Mapped(const NetAddr *addr)
+{
+  if (addr->raw.family == AF_INET6) {
+    return IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip);
+  }
+  return false;
+}
+
+NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
+{
+  PRNetAddrToNetAddr(prNetAddr, &mAddress);
+}
+
+NetAddrElement::~NetAddrElement()
+{
+}
+
+AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo)
+{
+  size_t hostlen = strlen(host);
+  mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
+  memcpy(mHostName, host, hostlen + 1);
+
+  PRNetAddr tmpAddr;
+  void *iter = nullptr;
+  do {
+    iter = PR_EnumerateAddrInfo(iter, prAddrInfo, 0, &tmpAddr);
+    if (iter) {
+      NetAddrElement *addrElement = new NetAddrElement(&tmpAddr);
+      mAddresses.insertBack(addrElement);
+    }
+  } while (iter);
+}
+
+AddrInfo::~AddrInfo()
+{
+  NetAddrElement *addrElement;
+  while ((addrElement = mAddresses.popLast())) {
+    delete addrElement;
+  }
+  free(mHostName);
+}
+
+} // namespace dns
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/dns/DNS.h
@@ -0,0 +1,141 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef DNS_h_
+#define DNS_h_
+
+#include "nscore.h"
+#include "prio.h"
+#include "prnetdb.h"
+#include "mozilla/LinkedList.h"
+
+#if !defined(XP_WIN) && !defined(XP_OS2)
+#include <arpa/inet.h>
+#endif
+
+#ifdef XP_WIN
+#include "Winsock2.h"
+#endif
+
+#define IPv6ADDR_IS_LOOPBACK(a) \
+  (((a)->u32[0] == 0)     &&    \
+   ((a)->u32[1] == 0)     &&    \
+   ((a)->u32[2] == 0)     &&    \
+   ((a)->u8[12] == 0)     &&    \
+   ((a)->u8[13] == 0)     &&    \
+   ((a)->u8[14] == 0)     &&    \
+   ((a)->u8[15] == 0x1U))
+
+#define IPv6ADDR_IS_V4MAPPED(a) \
+  (((a)->u32[0] == 0)     &&    \
+   ((a)->u32[1] == 0)     &&    \
+   ((a)->u8[8] == 0)      &&    \
+   ((a)->u8[9] == 0)      &&    \
+   ((a)->u8[10] == 0xff)  &&    \
+   ((a)->u8[11] == 0xff))
+
+#define IPv6ADDR_V4MAPPED_TO_IPADDR(a) ((a)->u32[3])
+
+#define IPv6ADDR_IS_UNSPECIFIED(a) \
+  (((a)->u32[0] == 0)  &&          \
+   ((a)->u32[1] == 0)  &&          \
+   ((a)->u32[2] == 0)  &&          \
+   ((a)->u32[3] == 0))
+
+namespace mozilla {
+namespace net {
+
+// Required buffer size for text form of an IP address.
+// Includes space for null termination.
+const int kIPv4CStrBufSize = 16;
+const int kIPv6CStrBufSize = 46;
+
+// This was all created at a time in which we were using NSPR for host
+// resolution and we were propagating NSPR types like "PRAddrInfo" and
+// "PRNetAddr" all over Gecko. This made it hard to use another host
+// resolver -- we were locked into NSPR. The goal here is to get away
+// from that. We'll translate what we get from NSPR or any other host
+// resolution library into the types below and use them in Gecko.
+
+union IPv6Addr {
+  uint8_t  u8[16];
+  uint16_t u16[8];
+  uint32_t u32[4];
+  uint64_t u64[2];
+};
+
+// This struct is similar to operating system structs like "sockaddr", used for
+// things like "connect" and "getsockname". When tempted to cast or do dumb
+// copies of this struct to another struct, bear compiler-computed padding
+// in mind. The size of this struct, and the layout of the data in it, may
+// not be what you expect.
+union NetAddr {
+  struct {
+    uint16_t family;                /* address family (0x00ff maskable) */
+    char data[14];                  /* raw address data */
+  } raw;
+  struct {
+    uint16_t family;                /* address family (AF_INET) */
+    uint16_t port;                  /* port number */
+    uint32_t ip;                    /* The actual 32 bits of address */
+  } inet;
+  struct {
+    uint16_t family;                /* address family (AF_INET6) */
+    uint16_t port;                  /* port number */
+    uint32_t flowinfo;              /* routing information */
+    IPv6Addr ip;                    /* the actual 128 bits of address */
+    uint32_t scope_id;              /* set of interfaces for a scope */
+  } inet6;
+#if defined(XP_UNIX) || defined(XP_OS2)
+  struct {                          /* Unix domain socket address */
+    uint16_t family;                /* address family (AF_UNIX) */
+#ifdef XP_OS2
+    char path[108];                 /* null-terminated pathname */
+#else
+    char path[104];                 /* null-terminated pathname */
+#endif
+  } local;
+#endif
+};
+
+// This class wraps a NetAddr union to provide C++ linked list
+// capabilities and other methods. It is created from a PRNetAddr,
+// which is converted to a mozilla::dns::NetAddr.
+class NetAddrElement : public LinkedListElement<NetAddrElement> {
+public:
+  NetAddrElement(const PRNetAddr *prNetAddr);
+  ~NetAddrElement();
+
+  NetAddr mAddress;
+};
+    
+class AddrInfo {
+public:
+  AddrInfo(const char *host, const PRAddrInfo *prAddrInfo);
+  ~AddrInfo();
+
+  char *mHostName;
+  LinkedList<NetAddrElement> mAddresses;
+};
+
+// Copies the contents of a PRNetAddr to a NetAddr.
+// Does not do a ptr safety check!
+void PRNetAddrToNetAddr(const PRNetAddr *prAddr, NetAddr *addr);
+
+// Copies the contents of a NetAddr to a PRNetAddr.
+// Does not do a ptr safety check!
+void NetAddrToPRNetAddr(const NetAddr *addr, PRNetAddr *prAddr);
+
+bool NetAddrToString(const NetAddr *addr, char *buf, uint32_t bufSize);
+
+bool IsLoopBackAddress(const NetAddr *addr);
+
+bool IsIPAddrAny(const NetAddr *addr);
+
+bool IsIPAddrV4Mapped(const NetAddr *addr);
+
+} // namespace net
+} // namespace mozilla
+
+#endif // DNS_h_
--- a/netwerk/dns/Makefile.in
+++ b/netwerk/dns/Makefile.in
@@ -22,28 +22,35 @@ XPIDLSRCS = \
   nsIDNSRecord.idl \
   nsIDNSService.idl \
   nsIEffectiveTLDService.idl \
   nsIIDNService.idl \
   nsPIDNSService.idl \
   $(NULL)
 
 CPPSRCS = \
+  DNS.cpp \
   nsIDNService.cpp \
+  nsHostResolver.cpp \
   nsDNSService2.cpp \
-  nsHostResolver.cpp \
   nsEffectiveTLDService.cpp \
   $(NULL)
 
 CSRCS = \
   race.c \
   nameprep.c \
   punycode.c \
   $(NULL)
 
+EXPORTS_NAMESPACES = mozilla/net
+
+EXPORTS_mozilla/net = \
+  DNS.h \
+  $(null)
+
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
 # need to include etld_data.inc
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base/src \
   -I. \
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -25,16 +25,17 @@
 #include "prio.h"
 #include "plstr.h"
 #include "nsIOService.h"
 #include "nsCharSeparatedTokenizer.h"
 
 #include "mozilla/Attributes.h"
 
 using namespace mozilla;
+using namespace mozilla::net;
 
 static const char kPrefDnsCacheEntries[]    = "network.dnsCacheEntries";
 static const char kPrefDnsCacheExpiration[] = "network.dnsCacheExpiration";
 static const char kPrefDnsCacheGrace[]      = "network.dnsCacheExpirationGracePeriod";
 static const char kPrefEnableIDN[]          = "network.enableIDN";
 static const char kPrefIPv4OnlyDomains[]    = "network.dns.ipv4OnlyDomains";
 static const char kPrefDisableIPv6[]        = "network.dns.disableIPv6";
 static const char kPrefDisablePrefetch[]    = "network.dns.disablePrefetch";
@@ -46,27 +47,24 @@ class nsDNSRecord : public nsIDNSRecord
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIDNSRECORD
 
     nsDNSRecord(nsHostRecord *hostRecord)
         : mHostRecord(hostRecord)
         , mIter(nullptr)
-        , mLastIter(nullptr)
         , mIterGenCnt(-1)
         , mDone(false) {}
 
 private:
     virtual ~nsDNSRecord() {}
 
     nsRefPtr<nsHostRecord>  mHostRecord;
-    void                   *mIter;       // enum ptr for PR_EnumerateAddrInfo
-    void                   *mLastIter;   // previous enum ptr, for use in
-                                         // getting addrinfo in ReportUnusable
+    NetAddrElement         *mIter;
     int                     mIterGenCnt; // the generation count of
                                          // mHostRecord->addr_info when we
                                          // start iterating
     bool                    mDone;
 };
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsDNSRecord, nsIDNSRecord)
 
@@ -78,131 +76,132 @@ nsDNSRecord::GetCanonicalName(nsACString
                    NS_ERROR_NOT_AVAILABLE);
 
     // if the record is for an IP address literal, then the canonical
     // host name is the IP address literal.
     const char *cname;
     {
         MutexAutoLock lock(mHostRecord->addr_info_lock);
         if (mHostRecord->addr_info)
-            cname = PR_GetCanonNameFromAddrInfo(mHostRecord->addr_info);
+            cname = mHostRecord->addr_info->mHostName;
         else
             cname = mHostRecord->host;
         result.Assign(cname);
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDNSRecord::GetNextAddr(uint16_t port, PRNetAddr *addr)
+nsDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
 {
-    // not a programming error to poke the DNS record when it has no more
-    // entries.  just fail without any debug warnings.  this enables consumers
-    // to enumerate the DNS record without calling HasMore.
-    if (mDone)
+    if (mDone) {
         return NS_ERROR_NOT_AVAILABLE;
-
-    mHostRecord->addr_info_lock.Lock();
-    bool startedFresh = !mIter;
+    }
 
     if (mHostRecord->addr_info) {
-        if (!mIter)
-            mIterGenCnt = mHostRecord->addr_info_gencnt;
-        else if (mIterGenCnt != mHostRecord->addr_info_gencnt) {
-            // mHostRecord->addr_info has changed, so mIter is invalid.
-            // Restart the iteration.  Alternatively, we could just fail.
+        mHostRecord->addr_info_lock.Lock();
+
+        if (mIterGenCnt != mHostRecord->addr_info_gencnt) {
+            // mHostRecord->addr_info has changed, restart the iteration.
             mIter = nullptr;
             mIterGenCnt = mHostRecord->addr_info_gencnt;
-            startedFresh = true;
         }
 
+        bool startedFresh = !mIter;
+
         do {
-            mLastIter = mIter;
-            mIter = PR_EnumerateAddrInfo(mIter, mHostRecord->addr_info,
-                                         port, addr);
+            if (!mIter) {
+                mIter = mHostRecord->addr_info->mAddresses.getFirst();
+            } else {
+                mIter = mIter->getNext();
+            }
         }
-        while (mIter && mHostRecord->Blacklisted(addr));
+        while (mIter && mHostRecord->Blacklisted(&mIter->mAddress));
 
-        if (startedFresh && !mIter) {
-            // if everything was blacklisted we want to reset the blacklist (and
+        if (!mIter && startedFresh) {
+            // If everything was blacklisted we want to reset the blacklist (and
             // likely relearn it) and return the first address. That is better
-            // than nothing
+            // than nothing.
             mHostRecord->ResetBlacklist();
-            mLastIter = nullptr;
-            mIter = PR_EnumerateAddrInfo(nullptr, mHostRecord->addr_info,
-                                         port, addr);
+            mIter = mHostRecord->addr_info->mAddresses.getFirst();
         }
-            
+
+        if (mIter) {
+            memcpy(addr, &mIter->mAddress, sizeof(NetAddr));
+        }
+
         mHostRecord->addr_info_lock.Unlock();
+
         if (!mIter) {
             mDone = true;
             return NS_ERROR_NOT_AVAILABLE;
         }
     }
     else {
-        mHostRecord->addr_info_lock.Unlock();
         if (!mHostRecord->addr) {
             // Both mHostRecord->addr_info and mHostRecord->addr are null.
             // This can happen if mHostRecord->addr_info expired and the
             // attempt to reresolve it failed.
             return NS_ERROR_NOT_AVAILABLE;
         }
-        memcpy(addr, mHostRecord->addr, sizeof(PRNetAddr));
-        // set given port
-        port = PR_htons(port);
-        if (addr->raw.family == PR_AF_INET)
-            addr->inet.port = port;
-        else
-            addr->ipv6.port = port;
-        mDone = true; // no iterations
+        memcpy(addr, mHostRecord->addr, sizeof(NetAddr));
+        mDone = true;
     }
-        
-    return NS_OK; 
+
+    // set given port
+    port = htons(port);
+    if (addr->raw.family == AF_INET) {
+        addr->inet.port = port;
+    }
+    else if (addr->raw.family == AF_INET6) {
+        addr->inet6.port = port;
+    }
+
+    return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSRecord::GetNextAddrAsString(nsACString &result)
 {
-    PRNetAddr addr;
+    NetAddr addr;
     nsresult rv = GetNextAddr(0, &addr);
     if (NS_FAILED(rv)) return rv;
 
-    char buf[64];
-    if (PR_NetAddrToString(&addr, buf, sizeof(buf)) == PR_SUCCESS) {
+    char buf[kIPv6CStrBufSize];
+    if (NetAddrToString(&addr, buf, sizeof(buf))) {
         result.Assign(buf);
         return NS_OK;
     }
-    NS_ERROR("PR_NetAddrToString failed unexpectedly");
+    NS_ERROR("NetAddrToString failed unexpectedly");
     return NS_ERROR_FAILURE; // conversion failed for some reason
 }
 
 NS_IMETHODIMP
 nsDNSRecord::HasMore(bool *result)
 {
-    if (mDone)
+    if (mDone) {
         *result = false;
-    else {
-        // unfortunately, NSPR does not provide a way for us to determine if
-        // there is another address other than to simply get the next address.
-        void *iterCopy = mIter;
-        void *iterLastCopy = mLastIter;
-        PRNetAddr addr;
-        *result = NS_SUCCEEDED(GetNextAddr(0, &addr));
-        mIter = iterCopy; // backup iterator
-        mLastIter = iterLastCopy; // backup iterator
-        mDone = false;
+        return NS_OK;
     }
+
+    NetAddrElement *iterCopy = mIter;
+
+    NetAddr addr;
+    *result = NS_SUCCEEDED(GetNextAddr(0, &addr));
+
+    mIter = iterCopy;
+    mDone = false;
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSRecord::Rewind()
 {
     mIter = nullptr;
-    mLastIter = nullptr;
     mIterGenCnt = -1;
     mDone = false;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDNSRecord::ReportUnusable(uint16_t aPort)
 {
@@ -211,24 +210,21 @@ nsDNSRecord::ReportUnusable(uint16_t aPo
     mHostRecord->addr_info_lock.Lock();
 
     // Check that we are using a real addr_info (as opposed to a single
     // constant address), and that the generation count is valid. Otherwise,
     // ignore the report.
 
     if (mHostRecord->addr_info &&
         mIterGenCnt == mHostRecord->addr_info_gencnt) {
-        PRNetAddr addr;
-        void *id = PR_EnumerateAddrInfo(mLastIter, mHostRecord->addr_info,
-                                        aPort, &addr);
-        if (id)
-            mHostRecord->ReportUnusable(&addr);
+        mHostRecord->ReportUnusable(&mIter->mAddress);
     }
-    
+
     mHostRecord->addr_info_lock.Unlock();
+
     return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
 class nsDNSAsyncRequest MOZ_FINAL : public nsResolveHostCallback
                                   , public nsICancelable
 {
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -180,50 +180,50 @@ nsHostRecord::Create(const nsHostKey *ke
 
 nsHostRecord::~nsHostRecord()
 {
     if (addr)
         free(addr);
 }
 
 bool
-nsHostRecord::Blacklisted(PRNetAddr *aQuery)
+nsHostRecord::Blacklisted(NetAddr *aQuery)
 {
     // must call locked
     LOG(("Checking blacklist for host [%s], host record [%p].\n", host, this));
 
     // skip the string conversion for the common case of no blacklist
     if (!mBlacklistedItems.Length()) {
         return false;
     }
 
-    char buf[64];
-    if (PR_NetAddrToString(aQuery, buf, sizeof(buf)) != PR_SUCCESS) {
+    char buf[kIPv6CStrBufSize];
+    if (!NetAddrToString(aQuery, buf, sizeof(buf))) {
         return false;
     }
     nsDependentCString strQuery(buf);
 
     for (uint32_t i = 0; i < mBlacklistedItems.Length(); i++) {
         if (mBlacklistedItems.ElementAt(i).Equals(strQuery)) {
             LOG(("Address [%s] is blacklisted for host [%s].\n", buf, host));
             return true;
         }
     }
 
     return false;
 }
 
 void
-nsHostRecord::ReportUnusable(PRNetAddr *aAddress)
+nsHostRecord::ReportUnusable(NetAddr *aAddress)
 {
     // must call locked
     LOG(("Adding address to blacklist for host [%s], host record [%p].\n", host, this));
 
-    char buf[64];
-    if (PR_NetAddrToString(aAddress, buf, sizeof(buf)) == PR_SUCCESS) {
+    char buf[kIPv6CStrBufSize];
+    if (NetAddrToString(aAddress, buf, sizeof(buf))) {
         LOG(("Successfully adding address [%s] to blacklist for host [%s].\n", buf, host));
         mBlacklistedItems.AppendElement(nsCString(buf));
     }
 }
 
 void
 nsHostRecord::ResetBlacklist()
 {
@@ -276,24 +276,20 @@ HostDB_ClearEntry(PLDHashTable *table,
     LOG(("Clearing cache db entry for host [%s].\n", he->rec->host));
 #if defined(DEBUG) && defined(PR_LOGGING)
     if (!he->rec->addr_info) {
         LOG(("No address info for host [%s].\n", he->rec->host));
     } else {
         int32_t now = (int32_t) NowInMinutes();
         int32_t diff = (int32_t) he->rec->expiration - now;
         LOG(("Record for [%s] expires in %d minute(s).\n", he->rec->host, diff));
-        void *iter = nullptr;
-        PRNetAddr addr;
-        char buf[64];
-        for (;;) {
-            iter = PR_EnumerateAddrInfo(iter, he->rec->addr_info, 0, &addr);
-            if (!iter)
-                break;
-            PR_NetAddrToString(&addr, buf, sizeof(buf));
+        NetAddrElement *addrElement;
+        char buf[kIPv6CStrBufSize];
+        while ((addrElement = he->rec->addr_info->mAddresses.popLast())) {
+            NetAddrToString(&addrElement->mAddress, buf, sizeof(buf));
             LOG(("  [%s]\n", buf));
         }
     }
 #endif
     NS_RELEASE(he->rec);
 }
 
 static bool
@@ -501,20 +497,20 @@ nsHostResolver::ResolveHost(const char  
     nsRefPtr<nsHostRecord> result;
     nsresult status = NS_OK, rv = NS_OK;
     {
         MutexAutoLock lock(mLock);
 
         if (mShutdown)
             rv = NS_ERROR_NOT_INITIALIZED;
         else {
+            // Used to try to parse to an IP address literal.
             PRNetAddr tempAddr;
-
-            // unfortunately, PR_StringToNetAddr does not properly initialize
-            // the output buffer in the case of IPv6 input.  see bug 223145.
+            // Unfortunately, PR_StringToNetAddr does not properly initialize
+            // the output buffer in the case of IPv6 input. See bug 223145.
             memset(&tempAddr, 0, sizeof(PRNetAddr));
             
             // check to see if there is already an entry for this |host|
             // in the hash table.  if so, then check to see if we can't
             // just reuse the lookup result.  otherwise, if there are
             // any pending callbacks, then add to pending callbacks queue,
             // and return.  otherwise, add ourselves as first pending
             // callback, and proceed to do the lookup.
@@ -567,21 +563,18 @@ nsHostResolver::ResolveHost(const char  
                 result = he->rec;
             }
             // try parsing the host name as an IP address literal to short
             // circuit full host resolution.  (this is necessary on some
             // platforms like Win9x.  see bug 219376 for more details.)
             else if (PR_StringToNetAddr(host, &tempAddr) == PR_SUCCESS) {
                 // ok, just copy the result into the host record, and be done
                 // with it! ;-)
-                he->rec->addr = (PRNetAddr *) malloc(sizeof(PRNetAddr));
-                if (!he->rec->addr)
-                    status = NS_ERROR_OUT_OF_MEMORY;
-                else
-                    memcpy(he->rec->addr, &tempAddr, sizeof(PRNetAddr));
+                he->rec->addr = new NetAddr();
+                PRNetAddrToNetAddr(&tempAddr, he->rec->addr);
                 // put reference to host record on stack...
                 Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
                                       METHOD_LITERAL);
                 result = he->rec;
             }
             else if (mPendingCount >= MAX_NON_PRIORITY_REQUESTS &&
                      !IsHighPriority(flags) &&
                      !he->rec->resolving) {
@@ -815,39 +808,39 @@ nsHostResolver::GetHostToLookup(nsHostRe
     }
     
     // tell thread to exit...
     mThreadCount--;
     return false;
 }
 
 void
-nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, PRAddrInfo *result)
+nsHostResolver::OnLookupComplete(nsHostRecord *rec, nsresult status, AddrInfo *result)
 {
     // get the list of pending callbacks for this lookup, and notify
     // them that the lookup is complete.
     PRCList cbs;
     PR_INIT_CLIST(&cbs);
     {
         MutexAutoLock lock(mLock);
 
         // grab list of callbacks to notify
         MoveCList(rec->callbacks, cbs);
 
         // update record fields.  We might have a rec->addr_info already if a
         // previous lookup result expired and we're reresolving it..
-        PRAddrInfo  *old_addr_info;
+        AddrInfo  *old_addr_info;
         {
             MutexAutoLock lock(rec->addr_info_lock);
             old_addr_info = rec->addr_info;
             rec->addr_info = result;
             rec->addr_info_gencnt++;
         }
-        if (old_addr_info)
-            PR_FreeAddrInfo(old_addr_info);
+        delete old_addr_info;
+
         rec->expiration = NowInMinutes();
         if (result) {
             rec->expiration += mMaxCacheLifetime;
             rec->negative = false;
         }
         else {
             rec->expiration += 1;                 /* one minute for negative cache */
             rec->negative = true;
@@ -953,38 +946,41 @@ nsHostResolver::ThreadFunc(void *arg)
     static nsThreadPoolNaming naming;
     naming.SetThreadPoolName(NS_LITERAL_CSTRING("DNS Resolver"));
 
 #if defined(RES_RETRY_ON_FAILURE)
     nsResState rs;
 #endif
     nsHostResolver *resolver = (nsHostResolver *)arg;
     nsHostRecord *rec;
-    PRAddrInfo *ai;
+    PRAddrInfo *prai = nullptr;
     while (resolver->GetHostToLookup(&rec)) {
         LOG(("Calling getaddrinfo for host [%s].\n", rec->host));
 
         int flags = PR_AI_ADDRCONFIG;
         if (!(rec->flags & RES_CANON_NAME))
             flags |= PR_AI_NOCANONNAME;
 
         TimeStamp startTime = TimeStamp::Now();
 
-        ai = PR_GetAddrInfoByName(rec->host, rec->af, flags);
+        prai = PR_GetAddrInfoByName(rec->host, rec->af, flags);
 #if defined(RES_RETRY_ON_FAILURE)
-        if (!ai && rs.Reset())
-            ai = PR_GetAddrInfoByName(rec->host, rec->af, flags);
+        if (!prai && rs.Reset())
+            prai = PR_GetAddrInfoByName(rec->host, rec->af, flags);
 #endif
 
         TimeDuration elapsed = TimeStamp::Now() - startTime;
         uint32_t millis = static_cast<uint32_t>(elapsed.ToMilliseconds());
 
-        // convert error code to nsresult.
+        // convert error code to nsresult
         nsresult status;
-        if (ai) {
+        AddrInfo *ai = nullptr;
+        if (prai) {
+            ai = new AddrInfo(rec->host, prai);
+
             status = NS_OK;
 
             Telemetry::Accumulate(!rec->addr_info_gencnt ?
                                     Telemetry::DNS_LOOKUP_TIME :
                                     Telemetry::DNS_RENEWAL_TIME,
                                   millis);
         }
         else {
@@ -1027,54 +1023,54 @@ nsHostResolver::Create(uint32_t         
     *result = res;
     return rv;
 }
 
 PLDHashOperator
 CacheEntryEnumerator(PLDHashTable *table, PLDHashEntryHdr *entry,
                      uint32_t number, void *arg)
 {
-    nsHostDBEnt *ent = static_cast<nsHostDBEnt *> (entry);
-    nsTArray<DNSCacheEntries> *args =
-        static_cast<nsTArray<DNSCacheEntries> *> (arg);
-    nsHostRecord *rec = ent->rec;
-    // Without addr_info, there is no meaning of adding this entry
-    if (rec->addr_info) {
-        DNSCacheEntries info;
-        const char *hostname;
-        PRNetAddr addr;
+    // We don't pay attention to address literals, only resolved domains.
+    // Also require a host.
+    nsHostRecord *rec = static_cast<nsHostDBEnt*>(entry)->rec;
+    if (!rec->addr_info || !rec->host) {
+        return PL_DHASH_NEXT;
+    }
 
-        if (rec->host)
-            hostname = rec->host;
-        else // No need to add this entry if no host name is there
-            return PL_DHASH_NEXT;
+    DNSCacheEntries info;
+    info.hostname = rec->host;
+    info.family = rec->af;
+    info.expiration = ((int64_t)rec->expiration - NowInMinutes()) * 60;
+    if (info.expiration <= 0) {
+        // We only need valid DNS cache entries
+        return PL_DHASH_NEXT;
+    }
 
-        uint32_t now = NowInMinutes();
-        info.expiration = ((int64_t) rec->expiration - now) * 60;
-
-        // We only need valid DNS cache entries
-        if (info.expiration <= 0)
-            return PL_DHASH_NEXT;
+    {
+        MutexAutoLock lock(rec->addr_info_lock);
 
-        info.family = rec->af;
-        info.hostname = hostname;
-
-        {
-            MutexAutoLock lock(rec->addr_info_lock);
-            void *ptr = PR_EnumerateAddrInfo(nullptr, rec->addr_info, 0, &addr);
-            while (ptr) {
-                char buf[64];
-                if (PR_NetAddrToString(&addr, buf, sizeof(buf)) == PR_SUCCESS)
-                    info.hostaddr.AppendElement(buf);
-                ptr = PR_EnumerateAddrInfo(ptr, rec->addr_info, 0, &addr);
+        NetAddr *addr = nullptr;
+        NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst();
+        if (addrElement) {
+            addr = &addrElement->mAddress;
+        }
+        while (addr) {
+            char buf[kIPv6CStrBufSize];
+            if (NetAddrToString(addr, buf, sizeof(buf))) {
+                info.hostaddr.AppendElement(buf);
+            }
+            addrElement = addrElement->getNext();
+            if (addrElement) {
+                addr = &addrElement->mAddress;
             }
         }
+    }
 
-        args->AppendElement(info);
-    }
+    nsTArray<DNSCacheEntries> *args = static_cast<nsTArray<DNSCacheEntries> *>(arg);
+    args->AppendElement(info);
 
     return PL_DHASH_NEXT;
 }
 
 void
 nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries> *args)
 {
     PL_DHashTableEnumerate(&mDB, CacheEntryEnumerator, args);
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -12,16 +12,17 @@
 #include "prnetdb.h"
 #include "pldhash.h"
 #include "mozilla/CondVar.h"
 #include "mozilla/Mutex.h"
 #include "nsISupportsImpl.h"
 #include "nsIDNSListener.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "mozilla/net/DNS.h"
 #include "mozilla/net/DashboardTypes.h"
 
 class nsHostResolver;
 class nsHostRecord;
 class nsResolveHostCallback;
 
 #define MAX_RESOLVER_THREADS_FOR_ANY_PRIORITY  3
 #define MAX_RESOLVER_THREADS_FOR_HIGH_PRIORITY 5
@@ -64,31 +65,31 @@ public:
      * nsDNSService2 class.  |addr| doesn't change after it has been
      * assigned a value.  only the resolver worker thread modifies
      * nsHostRecord (and only in nsHostResolver::OnLookupComplete);
      * the other threads just read it.  therefore the resolver worker
      * thread doesn't need to lock when reading |addr_info|.
      */
     Mutex        addr_info_lock;
     int          addr_info_gencnt; /* generation count of |addr_info| */
-    PRAddrInfo  *addr_info;
-    PRNetAddr   *addr;
+    mozilla::net::AddrInfo *addr_info;
+    mozilla::net::NetAddr  *addr;
     bool         negative;   /* True if this record is a cache of a failed lookup.
                                 Negative cache entries are valid just like any other
                                 (though never for more than 60 seconds), but a use
                                 of that negative entry forces an asynchronous refresh. */
 
     uint32_t     expiration; /* measured in minutes since epoch */
 
     bool HasResult() const { return addr_info || addr || negative; }
 
     // hold addr_info_lock when calling the blacklist functions
-    bool Blacklisted(PRNetAddr *query);
+    bool   Blacklisted(mozilla::net::NetAddr *query);
     void   ResetBlacklist();
-    void   ReportUnusable(PRNetAddr *addr);
+    void   ReportUnusable(mozilla::net::NetAddr *addr);
 
 private:
     friend class nsHostResolver;
 
     PRCList callbacks; /* list of callbacks */
 
     bool    resolving; /* true if this record is being resolved, which means
                         * that it is either on the pending queue or owned by
@@ -233,17 +234,17 @@ public:
 private:
     nsHostResolver(uint32_t maxCacheEntries = 50, uint32_t maxCacheLifetime = 1,
                    uint32_t lifetimeGracePeriod = 0);
    ~nsHostResolver();
 
     nsresult Init();
     nsresult IssueLookup(nsHostRecord *);
     bool     GetHostToLookup(nsHostRecord **m);
-    void     OnLookupComplete(nsHostRecord *, nsresult, PRAddrInfo *);
+    void     OnLookupComplete(nsHostRecord *, nsresult, mozilla::net::AddrInfo *);
     void     DeQueue(PRCList &aQ, nsHostRecord **aResult);
     void     ClearPendingQueue(PRCList *aPendingQueue);
     nsresult ConditionallyCreateThread(nsHostRecord *rec);
     
     static void  MoveQueue(nsHostRecord *aRec, PRCList &aDestQ);
     
     static void ThreadFunc(void *);
 
--- a/netwerk/dns/nsIDNSRecord.idl
+++ b/netwerk/dns/nsIDNSRecord.idl
@@ -1,46 +1,49 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-native PRNetAddr(union PRNetAddr);
+%{ C++
+#include "mozilla/net/DNS.h"
+%}
+native NetAddr(mozilla::net::NetAddr);
 
 /**
  * nsIDNSRecord
  *
  * this interface represents the result of a DNS lookup.  since a DNS
  * query may return more than one resolved IP address, the record acts
  * like an enumerator, allowing the caller to easily step through the
  * list of IP addresses.
  */
-[scriptable, uuid(ead9e9d8-7eef-4dae-a7f0-a1edcfb20478)]
+[scriptable, uuid(67E6CF03-12C7-4AF4-AE5F-AE362C7AF8FF)]
 interface nsIDNSRecord : nsISupports
 {
     /**
      * @return the canonical hostname for this record.  this value is empty if
      * the record was not fetched with the RESOLVE_CANONICAL_NAME flag.
      *
      * e.g., www.mozilla.org --> rheet.mozilla.org
      */
     readonly attribute ACString canonicalName;
 
     /**
      * this function copies the value of the next IP address into the
-     * given PRNetAddr struct and increments the internal address iterator.
+     * given NetAddr struct and increments the internal address iterator.
      *
      * @param aPort
-     *        A port number to initialize the PRNetAddr with.
+     *        A port number to initialize the NetAddr with.
      *
      * @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
      * the record.
      */
-    [noscript] PRNetAddr getNextAddr(in uint16_t aPort);
+    [noscript] NetAddr getNextAddr(in uint16_t aPort);
 
     /**
      * this function returns the value of the next IP address as a
      * string and increments the internal address iterator.
      *
      * @throws NS_ERROR_NOT_AVAILABLE if there is not another IP address in
      * the record.
      */
--- a/netwerk/ipc/NeckoMessageUtils.h
+++ b/netwerk/ipc/NeckoMessageUtils.h
@@ -5,16 +5,17 @@
 
 #ifndef mozilla_net_NeckoMessageUtils_h
 #define mozilla_net_NeckoMessageUtils_h
 
 #include "ipc/IPCMessageUtils.h"
 #include "nsStringGlue.h"
 #include "prio.h"
 #include "mozilla/Util.h" // for DebugOnly
+#include "mozilla/net/DNS.h"
 
 namespace IPC {
 
 // nsIPermissionManager utilities
 
 struct Permission
 {
   nsCString host, type;
@@ -79,65 +80,65 @@ struct ParamTraits<Permission>
     LogParam(p.expireTime, l);
     l->append(L", ");
     LogParam(p.expireType, l);
     l->append(L")");
   }
 };
 
 template<>
-struct ParamTraits<PRNetAddr>
+struct ParamTraits<mozilla::net::NetAddr>
 {
-  static void Write(Message* aMsg, const PRNetAddr &aParam)
+  static void Write(Message* aMsg, const mozilla::net::NetAddr &aParam)
   {
     WriteParam(aMsg, aParam.raw.family);
-    if (aParam.raw.family == PR_AF_UNSPEC) {
+    if (aParam.raw.family == AF_UNSPEC) {
       aMsg->WriteBytes(aParam.raw.data, sizeof(aParam.raw.data));
-    } else if (aParam.raw.family == PR_AF_INET) {
+    } else if (aParam.raw.family == AF_INET) {
       WriteParam(aMsg, aParam.inet.port);
       WriteParam(aMsg, aParam.inet.ip);
-    } else if (aParam.raw.family == PR_AF_INET6) {
-      WriteParam(aMsg, aParam.ipv6.port);
-      WriteParam(aMsg, aParam.ipv6.flowinfo);
-      WriteParam(aMsg, aParam.ipv6.ip.pr_s6_addr64[0]);
-      WriteParam(aMsg, aParam.ipv6.ip.pr_s6_addr64[1]);
-      WriteParam(aMsg, aParam.ipv6.scope_id);
+    } else if (aParam.raw.family == AF_INET6) {
+      WriteParam(aMsg, aParam.inet6.port);
+      WriteParam(aMsg, aParam.inet6.flowinfo);
+      WriteParam(aMsg, aParam.inet6.ip.u64[0]);
+      WriteParam(aMsg, aParam.inet6.ip.u64[1]);
+      WriteParam(aMsg, aParam.inet6.scope_id);
 #if defined(XP_UNIX) || defined(XP_OS2)
-    } else if (aParam.raw.family == PR_AF_LOCAL) {
+    } else if (aParam.raw.family == AF_LOCAL) {
       // Train's already off the rails:  let's get a stack trace at least...
       NS_RUNTIMEABORT("Error: please post stack trace to "
                       "https://bugzilla.mozilla.org/show_bug.cgi?id=661158");
       aMsg->WriteBytes(aParam.local.path, sizeof(aParam.local.path));
 #endif
     }
 
     /* If we get here without hitting any of the cases above, there's not much
      * we can do but let the deserializer fail when it gets this message */
   }
 
-  static bool Read(const Message* aMsg, void** aIter, PRNetAddr* aResult)
+  static bool Read(const Message* aMsg, void** aIter, mozilla::net::NetAddr* aResult)
   {
     if (!ReadParam(aMsg, aIter, &aResult->raw.family))
       return false;
 
-    if (aResult->raw.family == PR_AF_UNSPEC) {
+    if (aResult->raw.family == AF_UNSPEC) {
       return aMsg->ReadBytes(aIter,
                              reinterpret_cast<const char**>(&aResult->raw.data),
                              sizeof(aResult->raw.data));
-    } else if (aResult->raw.family == PR_AF_INET) {
+    } else if (aResult->raw.family == AF_INET) {
       return ReadParam(aMsg, aIter, &aResult->inet.port) &&
              ReadParam(aMsg, aIter, &aResult->inet.ip);
-    } else if (aResult->raw.family == PR_AF_INET6) {
-      return ReadParam(aMsg, aIter, &aResult->ipv6.port) &&
-             ReadParam(aMsg, aIter, &aResult->ipv6.flowinfo) &&
-             ReadParam(aMsg, aIter, &aResult->ipv6.ip.pr_s6_addr64[0]) &&
-             ReadParam(aMsg, aIter, &aResult->ipv6.ip.pr_s6_addr64[1]) &&
-             ReadParam(aMsg, aIter, &aResult->ipv6.scope_id);
+    } else if (aResult->raw.family == AF_INET6) {
+      return ReadParam(aMsg, aIter, &aResult->inet6.port) &&
+             ReadParam(aMsg, aIter, &aResult->inet6.flowinfo) &&
+             ReadParam(aMsg, aIter, &aResult->inet6.ip.u64[0]) &&
+             ReadParam(aMsg, aIter, &aResult->inet6.ip.u64[1]) &&
+             ReadParam(aMsg, aIter, &aResult->inet6.scope_id);
 #if defined(XP_UNIX) || defined(XP_OS2)
-    } else if (aResult->raw.family == PR_AF_LOCAL) {
+    } else if (aResult->raw.family == AF_LOCAL) {
       return aMsg->ReadBytes(aIter,
                              reinterpret_cast<const char**>(&aResult->local.path),
                              sizeof(aResult->local.path));
 #endif
     }
 
     /* We've been tricked by some socket family we don't know about! */
     return false;
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.cpp
@@ -37,16 +37,18 @@
 #include "nsICancelable.h"
 
 #if defined(PR_LOGGING)
 extern PRLogModuleInfo* gFTPLog;
 #endif
 #define LOG(args)         PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
 #define LOG_ALWAYS(args)  PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
 
+using namespace mozilla::net;
+
 // remove FTP parameters (starting with ";") from the path
 static void
 removeParamsFromPath(nsCString& path)
 {
   int32_t index = path.FindChar(';');
   if (index >= 0) {
     path.SetLength(index);
   }
@@ -1287,45 +1289,46 @@ nsFtpState::R_stor() {
 }
 
 
 nsresult
 nsFtpState::S_pasv() {
     if (!mAddressChecked) {
         // Find socket address
         mAddressChecked = true;
-        PR_InitializeNetAddr(PR_IpAddrAny, 0, &mServerAddress);
+        mServerAddress.raw.family = AF_INET;
+        mServerAddress.inet.ip = htonl(INADDR_ANY);
+        mServerAddress.inet.port = htons(0);
 
         nsITransport *controlSocket = mControlConnection->Transport();
         if (!controlSocket)
             // XXX Invalid cast of FTP_STATE to nsresult -- FTP_ERROR has
             // value < 0x80000000 and will pass NS_SUCCEEDED() (bug 778109)
             return (nsresult)FTP_ERROR;
 
         nsCOMPtr<nsISocketTransport> sTrans = do_QueryInterface(controlSocket);
         if (sTrans) {
             nsresult rv = sTrans->GetPeerAddr(&mServerAddress);
             if (NS_SUCCEEDED(rv)) {
-                if (!PR_IsNetAddrType(&mServerAddress, PR_IpAddrAny))
-                    mServerIsIPv6 = mServerAddress.raw.family == PR_AF_INET6 &&
-                        !PR_IsNetAddrType(&mServerAddress, PR_IpAddrV4Mapped);
+                if (!IsIPAddrAny(&mServerAddress))
+                    mServerIsIPv6 = (mServerAddress.raw.family == AF_INET6) &&
+                                    !IsIPAddrV4Mapped(&mServerAddress);
                 else {
                     /*
                      * In case of SOCKS5 remote DNS resolution, we do
                      * not know the remote IP address. Still, if it is
                      * an IPV6 host, then the external address of the
                      * socks server should also be IPv6, and this is the
                      * self address of the transport.
                      */
-                    PRNetAddr selfAddress;
+                    NetAddr selfAddress;
                     rv = sTrans->GetSelfAddr(&selfAddress);
                     if (NS_SUCCEEDED(rv))
-                        mServerIsIPv6 = selfAddress.raw.family == PR_AF_INET6
-                            && !PR_IsNetAddrType(&selfAddress,
-                                                 PR_IpAddrV4Mapped);
+                        mServerIsIPv6 = (selfAddress.raw.family == AF_INET6) &&
+                                        !IsIPAddrV4Mapped(&selfAddress);
                 }
             }
         }
     }
 
     const char *string;
     if (mServerIsIPv6) {
         string = "EPSV" CRLF;
@@ -1441,19 +1444,19 @@ nsFtpState::R_pasv() {
         nsCOMPtr<nsISocketTransportService> sts =
             do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
         if (!sts)
             return FTP_ERROR;
        
         nsCOMPtr<nsISocketTransport> strans;
 
         nsAutoCString host;
-        if (!PR_IsNetAddrType(&mServerAddress, PR_IpAddrAny)) {
-            char buf[64];
-            PR_NetAddrToString(&mServerAddress, buf, sizeof(buf));
+        if (!IsIPAddrAny(&mServerAddress)) {
+            char buf[kIPv6CStrBufSize];
+            NetAddrToString(&mServerAddress, buf, sizeof(buf));
             host.Assign(buf);
         } else {
             /*
              * In case of SOCKS5 remote DNS resolving, the peer address
              * fetched previously will be invalid (0.0.0.0): it is unknown
              * to us. But we can pass on the original hostname to the
              * connect for the data connection.
              */
--- a/netwerk/protocol/ftp/nsFtpConnectionThread.h
+++ b/netwerk/protocol/ftp/nsFtpConnectionThread.h
@@ -25,16 +25,17 @@
 #include "nsIProtocolHandler.h"
 #include "nsCOMPtr.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIOutputStream.h"
 #include "nsAutoPtr.h"
 #include "nsIPrompt.h"
 #include "nsITransport.h"
 #include "nsIProxyInfo.h"
+#include "mozilla/net/DNS.h"
 
 #include "nsFtpControlConnection.h"
 
 #include "nsICacheEntryDescriptor.h"
 #include "nsICacheListener.h"
 #include "nsIProtocolProxyCallback.h"
 
 // ftp server types
@@ -253,17 +254,17 @@ private:
     nsCOMPtr<nsITransport>        mDataTransport;
     nsCOMPtr<nsIAsyncInputStream> mDataStream;
     nsCOMPtr<nsIRequest>    mUploadRequest;
     bool                    mAddressChecked;
     bool                    mServerIsIPv6;
     
     static uint32_t         mSessionStartTime;
 
-    PRNetAddr               mServerAddress;
+    mozilla::net::NetAddr   mServerAddress;
 
     // ***** control read gvars
     nsresult                mControlStatus;
     nsCString               mControlReadCarryOverBuf;
 
     nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
     bool                    mDoomCache;
     
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -1269,63 +1269,63 @@ HttpBaseChannel::SetCacheKeysRedirectCha
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetLocalAddress(nsACString& addr)
 {
   if (mSelfAddr.raw.family == PR_AF_UNSPEC)
     return NS_ERROR_NOT_AVAILABLE;
 
-  addr.SetCapacity(64);
-  PR_NetAddrToString(&mSelfAddr, addr.BeginWriting(), 64);
+  addr.SetCapacity(kIPv6CStrBufSize);
+  NetAddrToString(&mSelfAddr, addr.BeginWriting(), kIPv6CStrBufSize);
   addr.SetLength(strlen(addr.BeginReading()));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetLocalPort(int32_t* port)
 {
   NS_ENSURE_ARG_POINTER(port);
 
   if (mSelfAddr.raw.family == PR_AF_INET) {
-    *port = (int32_t)PR_ntohs(mSelfAddr.inet.port);
+    *port = (int32_t)ntohs(mSelfAddr.inet.port);
   }
   else if (mSelfAddr.raw.family == PR_AF_INET6) {
-    *port = (int32_t)PR_ntohs(mSelfAddr.ipv6.port);
+    *port = (int32_t)ntohs(mSelfAddr.inet6.port);
   }
   else
     return NS_ERROR_NOT_AVAILABLE;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetRemoteAddress(nsACString& addr)
 {
   if (mPeerAddr.raw.family == PR_AF_UNSPEC)
     return NS_ERROR_NOT_AVAILABLE;
 
-  addr.SetCapacity(64);
-  PR_NetAddrToString(&mPeerAddr, addr.BeginWriting(), 64);
+  addr.SetCapacity(kIPv6CStrBufSize);
+  NetAddrToString(&mPeerAddr, addr.BeginWriting(), kIPv6CStrBufSize);
   addr.SetLength(strlen(addr.BeginReading()));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HttpBaseChannel::GetRemotePort(int32_t* port)
 {
   NS_ENSURE_ARG_POINTER(port);
 
   if (mPeerAddr.raw.family == PR_AF_INET) {
-    *port = (int32_t)PR_ntohs(mPeerAddr.inet.port);
+    *port = (int32_t)ntohs(mPeerAddr.inet.port);
   }
   else if (mPeerAddr.raw.family == PR_AF_INET6) {
-    *port = (int32_t)PR_ntohs(mPeerAddr.ipv6.port);
+    *port = (int32_t)ntohs(mPeerAddr.inet6.port);
   }
   else
     return NS_ERROR_NOT_AVAILABLE;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/netwerk/protocol/http/HttpBaseChannel.h
+++ b/netwerk/protocol/http/HttpBaseChannel.h
@@ -26,16 +26,17 @@
 #include "nsISupportsPriority.h"
 #include "nsIApplicationCache.h"
 #include "nsIResumableChannel.h"
 #include "nsITraceableChannel.h"
 #include "nsILoadContext.h"
 #include "mozilla/net/NeckoCommon.h"
 #include "nsThreadUtils.h"
 #include "PrivateBrowsingChannel.h"
+#include "mozilla/net/DNS.h"
 
 namespace mozilla {
 namespace net {
 
 /*
  * This class is a partial implementation of nsIHttpChannel.  It contains code
  * shared by nsHttpChannel and HttpChannelChild. 
  * - Note that this class has nothing to do with nsBaseChannel, which is an
@@ -183,18 +184,18 @@ public:
         nsCOMPtr<nsIHttpChannel> mChannel;
         
         bool mReady;
     };
 
     nsHttpResponseHead * GetResponseHead() const { return mResponseHead; }
     nsHttpRequestHead * GetRequestHead() { return &mRequestHead; }
 
-    const PRNetAddr& GetSelfAddr() { return mSelfAddr; }
-    const PRNetAddr& GetPeerAddr() { return mPeerAddr; }
+    const NetAddr& GetSelfAddr() { return mSelfAddr; }
+    const NetAddr& GetPeerAddr() { return mPeerAddr; }
 
 public: /* Necko internal use only... */
 
 protected:
 
   // Handle notifying listener, removing from loadgroup if request failed.
   void     DoNotifyListener();
   virtual void DoNotifyListenerCleanup() = 0;
@@ -238,18 +239,18 @@ protected:
   nsRefPtr<nsHttpConnectionInfo>    mConnectionInfo;
   nsCOMPtr<nsIProxyInfo>            mProxyInfo;
 
   nsCString                         mSpec; // ASCII encoded URL spec
   nsCString                         mContentTypeHint;
   nsCString                         mContentCharsetHint;
   nsCString                         mUserSetCookieHeader;
 
-  PRNetAddr                         mSelfAddr;
-  PRNetAddr                         mPeerAddr;
+  NetAddr                           mSelfAddr;
+  NetAddr                           mPeerAddr;
 
   // HTTP Upgrade Data
   nsCString                        mUpgradeProtocol;
   nsCOMPtr<nsIHttpUpgradeListener> mUpgradeProtocolCallback;
 
   // Resumable channel specific data
   nsCString                         mEntityID;
   uint64_t                          mStartPos;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -13,16 +13,17 @@
 #include "nsStringStream.h"
 #include "nsHttpHandler.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsSerializationHelper.h"
 #include "base/compiler_specific.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/ipc/URIUtils.h"
+#include "mozilla/net/DNS.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
@@ -168,18 +169,18 @@ class StartRequestEvent : public Channel
                     const nsHttpResponseHead& responseHead,
                     const bool& useResponseHead,
                     const nsHttpHeaderArray& requestHeaders,
                     const bool& isFromCache,
                     const bool& cacheEntryAvailable,
                     const uint32_t& cacheExpirationTime,
                     const nsCString& cachedCharset,
                     const nsCString& securityInfoSerialization,
-                    const PRNetAddr& selfAddr,
-                    const PRNetAddr& peerAddr)
+                    const NetAddr& selfAddr,
+                    const NetAddr& peerAddr)
   : mChild(child)
   , mResponseHead(responseHead)
   , mRequestHeaders(requestHeaders)
   , mUseResponseHead(useResponseHead)
   , mIsFromCache(isFromCache)
   , mCacheEntryAvailable(cacheEntryAvailable)
   , mCacheExpirationTime(cacheExpirationTime)
   , mCachedCharset(cachedCharset)
@@ -200,31 +201,31 @@ class StartRequestEvent : public Channel
   nsHttpResponseHead mResponseHead;
   nsHttpHeaderArray mRequestHeaders;
   bool mUseResponseHead;
   bool mIsFromCache;
   bool mCacheEntryAvailable;
   uint32_t mCacheExpirationTime;
   nsCString mCachedCharset;
   nsCString mSecurityInfoSerialization;
-  PRNetAddr mSelfAddr;
-  PRNetAddr mPeerAddr;
+  NetAddr mSelfAddr;
+  NetAddr mPeerAddr;
 };
 
 bool 
 HttpChannelChild::RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                                      const bool& useResponseHead,
                                      const nsHttpHeaderArray& requestHeaders,
                                      const bool& isFromCache,
                                      const bool& cacheEntryAvailable,
                                      const uint32_t& cacheExpirationTime,
                                      const nsCString& cachedCharset,
                                      const nsCString& securityInfoSerialization,
-                                     const PRNetAddr& selfAddr,
-                                     const PRNetAddr& peerAddr)
+                                     const NetAddr& selfAddr,
+                                     const NetAddr& peerAddr)
 {
   if (mEventQ.ShouldEnqueue()) {
     mEventQ.Enqueue(new StartRequestEvent(this, responseHead, useResponseHead,
                                           requestHeaders, isFromCache,
                                           cacheEntryAvailable,
                                           cacheExpirationTime, cachedCharset,
                                           securityInfoSerialization, selfAddr,
                                           peerAddr));
@@ -240,18 +241,18 @@ void
 HttpChannelChild::OnStartRequest(const nsHttpResponseHead& responseHead,
                                  const bool& useResponseHead,
                                  const nsHttpHeaderArray& requestHeaders,
                                  const bool& isFromCache,
                                  const bool& cacheEntryAvailable,
                                  const uint32_t& cacheExpirationTime,
                                  const nsCString& cachedCharset,
                                  const nsCString& securityInfoSerialization,
-                                 const PRNetAddr& selfAddr,
-                                 const PRNetAddr& peerAddr)
+                                 const NetAddr& selfAddr,
+                                 const NetAddr& peerAddr)
 {
   LOG(("HttpChannelChild::RecvOnStartRequest [this=%x]\n", this));
 
   if (useResponseHead && !mCanceled)
     mResponseHead = new nsHttpResponseHead(responseHead);
 
   if (!securityInfoSerialization.IsEmpty()) {
     NS_DeserializeObject(securityInfoSerialization, 
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -22,16 +22,17 @@
 #include "nsIApplicationCacheChannel.h"
 #include "nsIUploadChannel2.h"
 #include "nsIResumableChannel.h"
 #include "nsIProxiedChannel.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIAssociatedContentSecurity.h"
 #include "nsIChildChannel.h"
 #include "nsIHttpChannelChild.h"
+#include "mozilla/net/DNS.h"
 
 namespace mozilla {
 namespace net {
 
 class HttpChannelChild : public PHttpChannelChild
                        , public HttpBaseChannel
                        , public HttpAsyncAborter<HttpChannelChild>
                        , public nsICacheInfoChannel
@@ -92,18 +93,18 @@ protected:
   bool RecvOnStartRequest(const nsHttpResponseHead& responseHead,
                           const bool& useResponseHead,
                           const nsHttpHeaderArray& requestHeaders,
                           const bool& isFromCache,
                           const bool& cacheEntryAvailable,
                           const uint32_t& cacheExpirationTime,
                           const nsCString& cachedCharset,
                           const nsCString& securityInfoSerialization,
-                          const PRNetAddr& selfAddr,
-                          const PRNetAddr& peerAddr);
+                          const mozilla::net::NetAddr& selfAddr,
+                          const mozilla::net::NetAddr& peerAddr);
   bool RecvOnTransportAndData(const nsresult& status,
                               const uint64_t& progress,
                               const uint64_t& progressMax,
                               const nsCString& data,
                               const uint64_t& offset,
                               const uint32_t& count);
   bool RecvOnStopRequest(const nsresult& statusCode);
   bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax);
@@ -146,18 +147,18 @@ private:
   void OnStartRequest(const nsHttpResponseHead& responseHead,
                       const bool& useResponseHead,
                       const nsHttpHeaderArray& requestHeaders,
                       const bool& isFromCache,
                       const bool& cacheEntryAvailable,
                       const uint32_t& cacheExpirationTime,
                       const nsCString& cachedCharset,
                       const nsCString& securityInfoSerialization,
-                      const PRNetAddr& selfAddr,
-                      const PRNetAddr& peerAddr);
+                      const mozilla::net::NetAddr& selfAddr,
+                      const mozilla::net::NetAddr& peerAddr);
   void OnTransportAndData(const nsresult& status,
                           const uint64_t progress,
                           const uint64_t& progressMax,
                           const nsCString& data,
                           const uint64_t& offset,
                           const uint32_t& count);
   void OnStopRequest(const nsresult& statusCode);
   void OnProgress(const uint64_t& progress, const uint64_t& progressMax);
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -8,23 +8,24 @@
 include protocol PNecko;
 include InputStreamParams;
 include URIParams;
 
 include protocol PBlob; //FIXME: bug #792908
 
 include "mozilla/net/PHttpChannelParams.h";
 include "mozilla/net/NeckoMessageUtils.h";
+include "mozilla/net/DNS.h";
 include "prio.h";
 
 using RequestHeaderTuples;
 using nsHttpHeaderArray;
 using nsHttpResponseHead;
 using nsHttpAtom;
-using PRNetAddr;
+using mozilla::net::NetAddr;
 
 namespace mozilla {
 namespace net {
 
 //-------------------------------------------------------------------
 protocol PHttpChannel
 {
   manager PNecko;
@@ -97,18 +98,18 @@ child:
   OnStartRequest(nsHttpResponseHead  responseHead,
                  bool                useResponseHead,
                  nsHttpHeaderArray   requestHeaders,
                  bool                isFromCache,
                  bool                cacheEntryAvailable,
                  uint32_t            cacheExpirationTime,
                  nsCString           cachedCharset,
                  nsCString           securityInfoSerialization,
-                 PRNetAddr           selfAddr,
-                 PRNetAddr           peerAddr);
+                 NetAddr             selfAddr,
+                 NetAddr             peerAddr);
 
   // Combines a single OnDataAvailable and its associated OnProgress &
   // OnStatus calls into one IPDL message
   OnTransportAndData(nsresult  status,
                      uint64_t  progress,
                      uint64_t  progressMax,
                      nsCString data,
                      uint64_t  offset,
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -6,16 +6,17 @@
 #include "nsHttpConnectionMgr.h"
 #include "nsHttpConnection.h"
 #include "nsHttpPipeline.h"
 #include "nsHttpHandler.h"
 #include "nsIHttpChannelInternal.h"
 #include "nsNetCID.h"
 #include "nsCOMPtr.h"
 #include "nsNetUtil.h"
+#include "mozilla/net/DNS.h"
 
 #include "nsIServiceManager.h"
 
 #include "nsIObserverService.h"
 
 #include "nsISSLSocketControl.h"
 #include "prnetdb.h"
 #include "mozilla/Telemetry.h"
@@ -2833,21 +2834,21 @@ nsHttpConnectionMgr::nsHalfOpenSocket::O
 
     if (status == NS_NET_STATUS_CONNECTED_TO &&
         gHttpHandler->IsSpdyEnabled() &&
         gHttpHandler->CoalesceSpdy() &&
         mEnt && mEnt->mConnInfo && mEnt->mConnInfo->UsingSSL() &&
         !mEnt->mConnInfo->UsingProxy() &&
         mEnt->mCoalescingKey.IsEmpty()) {
 
-        PRNetAddr addr;
+        NetAddr addr;
         nsresult rv = mSocketTransport->GetPeerAddr(&addr);
         if (NS_SUCCEEDED(rv)) {
-            mEnt->mCoalescingKey.SetCapacity(72);
-            PR_NetAddrToString(&addr, mEnt->mCoalescingKey.BeginWriting(), 64);
+            mEnt->mCoalescingKey.SetCapacity(kIPv6CStrBufSize + 26);
+            NetAddrToString(&addr, mEnt->mCoalescingKey.BeginWriting(), kIPv6CStrBufSize);
             mEnt->mCoalescingKey.SetLength(
                 strlen(mEnt->mCoalescingKey.BeginReading()));
 
             if (mEnt->mConnInfo->GetAnonymous())
                 mEnt->mCoalescingKey.AppendLiteral("~A:");
             else
                 mEnt->mCoalescingKey.AppendLiteral("~.:");
             mEnt->mCoalescingKey.AppendInt(mEnt->mConnInfo->Port());
--- a/netwerk/socket/nsISOCKSSocketInfo.idl
+++ b/netwerk/socket/nsISOCKSSocketInfo.idl
@@ -1,17 +1,20 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-[ptr] native PRNetAddrPtr(union PRNetAddr);
+%{ C++
+#include "mozilla/net/DNS.h"
+%}
+[ptr] native NetAddrPtr(mozilla::net::NetAddr);
 
-[scriptable, uuid(8f755c44-1dd2-11b2-a613-91117453fa95)]
+[scriptable, uuid(D5C0D1F9-22D7-47DC-BF91-D9AC6E1251A6)]
 interface nsISOCKSSocketInfo : nsISupports
 {
-    [noscript] attribute PRNetAddrPtr destinationAddr;
-    [noscript] attribute PRNetAddrPtr externalProxyAddr;
-    [noscript] attribute PRNetAddrPtr internalProxyAddr;
+    [noscript] attribute NetAddrPtr destinationAddr;
+    [noscript] attribute NetAddrPtr externalProxyAddr;
+    [noscript] attribute NetAddrPtr internalProxyAddr;
 };
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -14,19 +14,22 @@
 #include "nsIDNSRecord.h"
 #include "nsISOCKSSocketInfo.h"
 #include "nsISocketProvider.h"
 #include "nsSOCKSIOLayer.h"
 #include "nsNetCID.h"
 #include "nsIDNSListener.h"
 #include "nsICancelable.h"
 #include "nsThreadUtils.h"
+#include "mozilla/net/DNS.h"
 
-static PRDescIdentity	nsSOCKSIOLayerIdentity;
-static PRIOMethods	nsSOCKSIOLayerMethods;
+using namespace mozilla::net;
+
+static PRDescIdentity nsSOCKSIOLayerIdentity;
+static PRIOMethods nsSOCKSIOLayerMethods;
 static bool firstTime = true;
 static bool ipv6Supported = true;
 
 #if defined(PR_LOGGING)
 static PRLogModuleInfo *gSOCKSLog;
 #define LOGDEBUG(args) PR_LOG(gSOCKSLog, PR_LOG_DEBUG, args)
 #define LOGERROR(args) PR_LOG(gSOCKSLog, PR_LOG_ERROR , args)
 
@@ -79,39 +82,39 @@ public:
     int16_t GetPollFlags() const;
     bool IsConnected() const { return mState == SOCKS_CONNECTED; }
     void ForgetFD() { mFD = nullptr; }
 
 private:
     void HandshakeFinished(PRErrorCode err = 0);
     PRStatus StartDNS(PRFileDesc *fd);
     PRStatus ConnectToProxy(PRFileDesc *fd);
-    void FixupAddressFamily(PRFileDesc *fd, PRNetAddr *proxy);
+    void FixupAddressFamily(PRFileDesc *fd, NetAddr *proxy);
     PRStatus ContinueConnectingToProxy(PRFileDesc *fd, int16_t oflags);
     PRStatus WriteV4ConnectRequest();
     PRStatus ReadV4ConnectResponse();
     PRStatus WriteV5AuthRequest();
     PRStatus ReadV5AuthResponse();
     PRStatus WriteV5ConnectRequest();
     PRStatus ReadV5AddrTypeAndLength(uint8_t *type, uint32_t *len);
     PRStatus ReadV5ConnectResponseTop();
     PRStatus ReadV5ConnectResponseBottom();
 
     void WriteUint8(uint8_t d);
     void WriteUint16(uint16_t d);
     void WriteUint32(uint32_t d);
-    void WriteNetAddr(const PRNetAddr *addr);
-    void WriteNetPort(const PRNetAddr *addr);
+    void WriteNetAddr(const NetAddr *addr);
+    void WriteNetPort(const NetAddr *addr);
     void WriteString(const nsACString &str);
 
     uint8_t ReadUint8();
     uint16_t ReadUint16();
     uint32_t ReadUint32();
-    void ReadNetAddr(PRNetAddr *addr, uint16_t fam);
-    void ReadNetPort(PRNetAddr *addr);
+    void ReadNetAddr(NetAddr *addr, uint16_t fam);
+    void ReadNetPort(NetAddr *addr);
 
     void WantRead(uint32_t sz);
     PRStatus ReadFromSocket(PRFileDesc *fd);
     PRStatus WriteToSocket(PRFileDesc *fd);
 
 private:
     State     mState;
     uint8_t * mData;
@@ -125,92 +128,101 @@ private:
     PRFileDesc             *mFD;
 
     nsCString mDestinationHost;
     nsCString mProxyHost;
     int32_t   mProxyPort;
     int32_t   mVersion;   // SOCKS version 4 or 5
     int32_t   mDestinationFamily;
     uint32_t  mFlags;
-    PRNetAddr mInternalProxyAddr;
-    PRNetAddr mExternalProxyAddr;
-    PRNetAddr mDestinationAddr;
+    NetAddr   mInternalProxyAddr;
+    NetAddr   mExternalProxyAddr;
+    NetAddr   mDestinationAddr;
     PRIntervalTime mTimeout;
 };
 
 nsSOCKSSocketInfo::nsSOCKSSocketInfo()
     : mState(SOCKS_INITIAL)
     , mDataIoPtr(nullptr)
     , mDataLength(0)
     , mReadOffset(0)
     , mAmountToRead(0)
     , mProxyPort(-1)
     , mVersion(-1)
-    , mDestinationFamily(PR_AF_INET)
+    , mDestinationFamily(AF_INET)
     , mFlags(0)
     , mTimeout(PR_INTERVAL_NO_TIMEOUT)
 {
     mData = new uint8_t[BUFFER_SIZE];
-    PR_InitializeNetAddr(PR_IpAddrAny, 0, &mInternalProxyAddr);
-    PR_InitializeNetAddr(PR_IpAddrAny, 0, &mExternalProxyAddr);
-    PR_InitializeNetAddr(PR_IpAddrAny, 0, &mDestinationAddr);
+
+    mInternalProxyAddr.raw.family = AF_INET;
+    mInternalProxyAddr.inet.ip = htonl(INADDR_ANY);
+    mInternalProxyAddr.inet.port = htons(0);
+
+    mExternalProxyAddr.raw.family = AF_INET;
+    mExternalProxyAddr.inet.ip = htonl(INADDR_ANY);
+    mExternalProxyAddr.inet.port = htons(0);
+
+    mDestinationAddr.raw.family = AF_INET;
+    mDestinationAddr.inet.ip = htonl(INADDR_ANY);
+    mDestinationAddr.inet.port = htons(0);
 }
 
 void
 nsSOCKSSocketInfo::Init(int32_t version, int32_t family, const char *proxyHost, int32_t proxyPort, const char *host, uint32_t flags)
 {
     mVersion         = version;
     mDestinationFamily = family;
     mProxyHost       = proxyHost;
     mProxyPort       = proxyPort;
     mDestinationHost = host;
     mFlags           = flags;
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS2(nsSOCKSSocketInfo, nsISOCKSSocketInfo, nsIDNSListener)
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::GetExternalProxyAddr(PRNetAddr * *aExternalProxyAddr)
+nsSOCKSSocketInfo::GetExternalProxyAddr(NetAddr * *aExternalProxyAddr)
 {
-    memcpy(*aExternalProxyAddr, &mExternalProxyAddr, sizeof(PRNetAddr));
+    memcpy(*aExternalProxyAddr, &mExternalProxyAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::SetExternalProxyAddr(PRNetAddr *aExternalProxyAddr)
+nsSOCKSSocketInfo::SetExternalProxyAddr(NetAddr *aExternalProxyAddr)
 {
-    memcpy(&mExternalProxyAddr, aExternalProxyAddr, sizeof(PRNetAddr));
+    memcpy(&mExternalProxyAddr, aExternalProxyAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::GetDestinationAddr(PRNetAddr * *aDestinationAddr)
+nsSOCKSSocketInfo::GetDestinationAddr(NetAddr * *aDestinationAddr)
 {
-    memcpy(*aDestinationAddr, &mDestinationAddr, sizeof(PRNetAddr));
+    memcpy(*aDestinationAddr, &mDestinationAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::SetDestinationAddr(PRNetAddr *aDestinationAddr)
+nsSOCKSSocketInfo::SetDestinationAddr(NetAddr *aDestinationAddr)
 {
-    memcpy(&mDestinationAddr, aDestinationAddr, sizeof(PRNetAddr));
+    memcpy(&mDestinationAddr, aDestinationAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::GetInternalProxyAddr(PRNetAddr * *aInternalProxyAddr)
+nsSOCKSSocketInfo::GetInternalProxyAddr(NetAddr * *aInternalProxyAddr)
 {
-    memcpy(*aInternalProxyAddr, &mInternalProxyAddr, sizeof(PRNetAddr));
+    memcpy(*aInternalProxyAddr, &mInternalProxyAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 NS_IMETHODIMP 
-nsSOCKSSocketInfo::SetInternalProxyAddr(PRNetAddr *aInternalProxyAddr)
+nsSOCKSSocketInfo::SetInternalProxyAddr(NetAddr *aInternalProxyAddr)
 {
-    memcpy(&mInternalProxyAddr, aInternalProxyAddr, sizeof(PRNetAddr));
+    memcpy(&mInternalProxyAddr, aInternalProxyAddr, sizeof(NetAddr));
     return NS_OK;
 }
 
 // There needs to be a means of distinguishing between connection errors
 // that the SOCKS server reports when it rejects a connection request, and
 // connection errors that happen while attempting to connect to the SOCKS
 // server. Otherwise, Firefox will report incorrectly that the proxy server
 // is refusing connections when a SOCKS request is rejected by the proxy.
@@ -292,17 +304,17 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFile
 
     if (NS_FAILED(mLookupStatus)) {
         PR_SetError(PR_BAD_ADDRESS_ERROR, 0);
         return PR_FAILURE;
     }
 
     // Try socks5 if the destination addrress is IPv6
     if (mVersion == 4 &&
-        PR_NetAddrFamily(&mDestinationAddr) == PR_AF_INET6) {
+        mDestinationAddr.raw.family == AF_INET6) {
         mVersion = 5;
     }
 
     int32_t addresses = 0;
     do {
         if (addresses++)
             mDnsRec->ReportUnusable(mProxyPort);
         
@@ -310,24 +322,26 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFile
         // No more addresses to try? If so, we'll need to bail
         if (NS_FAILED(rv)) {
             LOGERROR(("socks: unable to connect to SOCKS proxy, %s",
                      mProxyHost.get()));
             return PR_FAILURE;
         }
 
 #if defined(PR_LOGGING)
-        char buf[64];
-        PR_NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf));
+        char buf[kIPv6CStrBufSize];
+        NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf));
         LOGDEBUG(("socks: trying proxy server, %s:%hu",
-                 buf, PR_ntohs(PR_NetAddrInetPort(&mInternalProxyAddr))));
+                 buf, ntohs(mInternalProxyAddr.inet.port)));
 #endif
-        PRNetAddr proxy = mInternalProxyAddr;
+        NetAddr proxy = mInternalProxyAddr;
         FixupAddressFamily(fd, &proxy);
-        status = fd->lower->methods->connect(fd->lower, &proxy, mTimeout);
+        PRNetAddr prProxy;
+        NetAddrToPRNetAddr(&proxy, &prProxy);
+        status = fd->lower->methods->connect(fd->lower, &prProxy, mTimeout);
         if (status != PR_SUCCESS) {
             PRErrorCode c = PR_GetError();
             // If EINPROGRESS, return now and check back later after polling
             if (c == PR_WOULD_BLOCK_ERROR || c == PR_IN_PROGRESS_ERROR) {
                 mState = SOCKS_CONNECTING_TO_PROXY;
                 return status;
             }
         }
@@ -335,35 +349,35 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFile
 
     // Connected now, start SOCKS
     if (mVersion == 4)
         return WriteV4ConnectRequest();
     return WriteV5AuthRequest();
 }
 
 void
-nsSOCKSSocketInfo::FixupAddressFamily(PRFileDesc *fd, PRNetAddr *proxy)
+nsSOCKSSocketInfo::FixupAddressFamily(PRFileDesc *fd, NetAddr *proxy)
 {
-    int32_t proxyFamily = PR_NetAddrFamily(&mInternalProxyAddr);
+    int32_t proxyFamily = mInternalProxyAddr.raw.family;
     // Do nothing if the address family is already matched
     if (proxyFamily == mDestinationFamily) {
         return;
     }
     // If the system does not support IPv6 and the proxy address is IPv6,
     // We can do nothing here.
-    if (proxyFamily == PR_AF_INET6 && !ipv6Supported) {
+    if (proxyFamily == AF_INET6 && !ipv6Supported) {
         return;
     }
     // If the system does not support IPv6 and the destination address is
     // IPv6, convert IPv4 address to IPv4-mapped IPv6 address to satisfy
     // the emulation layer
-    if (mDestinationFamily == PR_AF_INET6 && !ipv6Supported) {
-        proxy->ipv6.family = PR_AF_INET6;
-        proxy->ipv6.port = mInternalProxyAddr.inet.port;
-        uint8_t *proxyp = proxy->ipv6.ip.pr_s6_addr;
+    if (mDestinationFamily == AF_INET6 && !ipv6Supported) {
+        proxy->inet6.family = AF_INET6;
+        proxy->inet6.port = mInternalProxyAddr.inet.port;
+        uint8_t *proxyp = proxy->inet6.ip.u8;
         memset(proxyp, 0, 10);
         memset(proxyp + 10, 0xff, 2);
         memcpy(proxyp + 12,(char *) &mInternalProxyAddr.inet.ip, 4);
         // mDestinationFamily should not be updated
         return;
     }
     // Get an OS native handle from a specified FileDesc
     PROsfd osfd = PR_FileDesc2NativeHandle(fd);
@@ -419,17 +433,17 @@ nsSOCKSSocketInfo::ContinueConnectingToP
     if (mVersion == 4)
         return WriteV4ConnectRequest();
     return WriteV5AuthRequest();
 }
 
 PRStatus
 nsSOCKSSocketInfo::WriteV4ConnectRequest()
 {
-    PRNetAddr *addr = &mDestinationAddr;
+    NetAddr *addr = &mDestinationAddr;
     int32_t proxy_resolve;
 
     NS_ABORT_IF_FALSE(mState == SOCKS_CONNECTING_TO_PROXY,
                       "Invalid state!");
     
     proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
 
     mDataLength = 0;
@@ -443,29 +457,29 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest
     WriteUint8(0x01); // command -- connect
     WriteNetPort(addr);
     if (proxy_resolve) {
         // Add the full name, null-terminated, to the request
         // according to SOCKS 4a. A fake IP address, with the first
         // four bytes set to 0 and the last byte set to something other
         // than 0, is used to notify the proxy that this is a SOCKS 4a
         // request. This request type works for Tor and perhaps others.
-        WriteUint32(PR_htonl(0x00000001)); // Fake IP
+        WriteUint32(htonl(0x00000001)); // Fake IP
         WriteUint8(0x00); // Send an emtpy username
         if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
             LOGERROR(("socks4: destination host name is too long!"));
             HandshakeFinished(PR_BAD_ADDRESS_ERROR);
             return PR_FAILURE;
         }
         WriteString(mDestinationHost); // Hostname
         WriteUint8(0x00);
-    } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
+    } else if (addr->raw.family == AF_INET) {
         WriteNetAddr(addr); // Add the IPv4 address
         WriteUint8(0x00); // Send an emtpy username
-    } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
+    } else if (addr->raw.family == AF_INET6) {
         LOGERROR(("socks: SOCKS 4 can't handle IPv6 addresses!"));
         HandshakeFinished(PR_BAD_ADDRESS_ERROR);
         return PR_FAILURE;
     }
 
     return PR_SUCCESS;
 }
 
@@ -539,17 +553,17 @@ nsSOCKSSocketInfo::ReadV5AuthResponse()
 
     return WriteV5ConnectRequest();
 }
 
 PRStatus
 nsSOCKSSocketInfo::WriteV5ConnectRequest()
 {
     // Send SOCKS 5 connect request
-    PRNetAddr *addr = &mDestinationAddr;
+    NetAddr *addr = &mDestinationAddr;
     int32_t proxy_resolve;
     proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST;
 
     LOGDEBUG(("socks5: sending connection request (socks5 resolve? %s)",
              proxy_resolve? "yes" : "no"));
 
     mDataLength = 0;
     mState = SOCKS5_WRITE_CONNECT_REQUEST;
@@ -566,20 +580,20 @@ nsSOCKSSocketInfo::WriteV5ConnectRequest
         if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
             LOGERROR(("socks5: destination host name is too long!"));
             HandshakeFinished(PR_BAD_ADDRESS_ERROR);
             return PR_FAILURE;
         }
         WriteUint8(0x03); // addr type -- domainname
         WriteUint8(mDestinationHost.Length()); // name length
         WriteString(mDestinationHost);
-    } else if (PR_NetAddrFamily(addr) == PR_AF_INET) {
+    } else if (addr->raw.family == AF_INET) {
         WriteUint8(0x01); // addr type -- IPv4
         WriteNetAddr(addr);
-    } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
+    } else if (addr->raw.family == AF_INET6) {
         WriteUint8(0x04); // addr type -- IPv6
         WriteNetAddr(addr);
     } else {
         LOGERROR(("socks5: destination address of unknown type!"));
         HandshakeFinished(PR_BAD_ADDRESS_ERROR);
         return PR_FAILURE;
     }
 
@@ -713,24 +727,24 @@ nsSOCKSSocketInfo::ReadV5ConnectResponse
 
     NS_ABORT_IF_FALSE(mDataLength == 7+len,
                       "SOCKS 5 unexpected length of connection reply!");
 
     LOGDEBUG(("socks5: loading source addr and port"));
     // Read what the proxy says is our source address
     switch (type) {
         case 0x01: // ipv4
-            ReadNetAddr(&mExternalProxyAddr, PR_AF_INET);
+            ReadNetAddr(&mExternalProxyAddr, AF_INET);
             break;
         case 0x04: // ipv6
-            ReadNetAddr(&mExternalProxyAddr, PR_AF_INET6);
+            ReadNetAddr(&mExternalProxyAddr, AF_INET6);
             break;
         case 0x03: // fqdn (skip)
             mReadOffset += len;
-            mExternalProxyAddr.raw.family = PR_AF_INET;
+            mExternalProxyAddr.raw.family = AF_INET;
             break;
     }
 
     ReadNetPort(&mExternalProxyAddr);
 
     LOGDEBUG(("socks5: connected!"));
     HandshakeFinished();
 
@@ -860,41 +874,41 @@ nsSOCKSSocketInfo::WriteUint32(uint32_t 
 {
     NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
                       "Can't write that much data!");
     memcpy(mData + mDataLength, &v, sizeof(v));
     mDataLength += sizeof(v);
 }
 
 void
-nsSOCKSSocketInfo::WriteNetAddr(const PRNetAddr *addr)
+nsSOCKSSocketInfo::WriteNetAddr(const NetAddr *addr)
 {
     const char *ip = NULL;
     uint32_t len = 0;
 
-    if (PR_NetAddrFamily(addr) == PR_AF_INET) {
+    if (addr->raw.family == AF_INET) {
         ip = (const char*)&addr->inet.ip;
         len = sizeof(addr->inet.ip);
-    } else if (PR_NetAddrFamily(addr) == PR_AF_INET6) {
-        ip = (const char*)addr->ipv6.ip.pr_s6_addr;
-        len = sizeof(addr->ipv6.ip.pr_s6_addr);
+    } else if (addr->raw.family == AF_INET6) {
+        ip = (const char*)addr->inet6.ip.u8;
+        len = sizeof(addr->inet6.ip.u8);
     }
 
     NS_ABORT_IF_FALSE(ip != NULL, "Unknown address");
     NS_ABORT_IF_FALSE(mDataLength + len <= BUFFER_SIZE,
                       "Can't write that much data!");
  
     memcpy(mData + mDataLength, ip, len);
     mDataLength += len;
 }
 
 void
-nsSOCKSSocketInfo::WriteNetPort(const PRNetAddr *addr)
+nsSOCKSSocketInfo::WriteNetPort(const NetAddr *addr)
 {
-    WriteUint16(PR_NetAddrInetPort(addr));
+    WriteUint16(addr->inet.port);
 }
 
 void
 nsSOCKSSocketInfo::WriteString(const nsACString &str)
 {
     NS_ABORT_IF_FALSE(mDataLength + str.Length() <= BUFFER_SIZE,
                       "Can't write that much data!");
     memcpy(mData + mDataLength, str.Data(), str.Length());
@@ -930,39 +944,39 @@ nsSOCKSSocketInfo::ReadUint32()
     NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
                       "Not enough space to pop a uint32_t!");
     memcpy(&rv, mData + mReadOffset, sizeof(rv));
     mReadOffset += sizeof(rv);
     return rv;
 }
 
 void
-nsSOCKSSocketInfo::ReadNetAddr(PRNetAddr *addr, uint16_t fam)
+nsSOCKSSocketInfo::ReadNetAddr(NetAddr *addr, uint16_t fam)
 {
     uint32_t amt = 0;
     const uint8_t *ip = mData + mReadOffset;
 
     addr->raw.family = fam;
-    if (fam == PR_AF_INET) {
+    if (fam == AF_INET) {
         amt = sizeof(addr->inet.ip);
         NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
                           "Not enough space to pop an ipv4 addr!");
         memcpy(&addr->inet.ip, ip, amt);
-    } else if (fam == PR_AF_INET6) {
-        amt = sizeof(addr->ipv6.ip.pr_s6_addr);
+    } else if (fam == AF_INET6) {
+        amt = sizeof(addr->inet6.ip.u8);
         NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
                           "Not enough space to pop an ipv6 addr!");
-        memcpy(addr->ipv6.ip.pr_s6_addr, ip, amt);
+        memcpy(addr->inet6.ip.u8, ip, amt);
     }
 
     mReadOffset += amt;
 }
 
 void
-nsSOCKSSocketInfo::ReadNetPort(PRNetAddr *addr)
+nsSOCKSSocketInfo::ReadNetPort(NetAddr *addr)
 {
     addr->inet.port = ReadUint16();
 }
 
 void
 nsSOCKSSocketInfo::WantRead(uint32_t sz)
 {
     NS_ABORT_IF_FALSE(mDataIoPtr == NULL,
@@ -1055,32 +1069,34 @@ nsSOCKSSocketInfo::WriteToSocket(PRFileD
     
     return PR_FAILURE;
 }
 
 static PRStatus
 nsSOCKSIOLayerConnect(PRFileDesc *fd, const PRNetAddr *addr, PRIntervalTime to)
 {
     PRStatus status;
-    PRNetAddr dst;
+    NetAddr dst;
 
     nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
     if (info == NULL) return PR_FAILURE;
 
-    if (PR_NetAddrFamily(addr) == PR_AF_INET6 &&
+    if (addr->raw.family == PR_AF_INET6 &&
         PR_IsNetAddrType(addr, PR_IpAddrV4Mapped)) {
         const uint8_t *srcp;
 
         LOGDEBUG(("socks: converting ipv4-mapped ipv6 address to ipv4"));
 
         // copied from _PR_ConvertToIpv4NetAddr()
-        PR_InitializeNetAddr(PR_IpAddrAny, 0, &dst);
+        dst.raw.family = AF_INET;
+        dst.inet.ip = htonl(INADDR_ANY);
+        dst.inet.port = htons(0);
         srcp = addr->ipv6.ip.pr_s6_addr;
         memcpy(&dst.inet.ip, srcp + 12, 4);
-        dst.inet.family = PR_AF_INET;
+        dst.inet.family = AF_INET;
         dst.inet.port = addr->ipv6.port;
     } else {
         memcpy(&dst, addr, sizeof(dst));
     }
 
     info->SetDestinationAddr(&dst);
     info->SetConnectTimeout(to);
 
@@ -1158,31 +1174,39 @@ nsSOCKSIOLayerBind(PRFileDesc *fd, const
 }
 
 static PRStatus
 nsSOCKSIOLayerGetName(PRFileDesc *fd, PRNetAddr *addr)
 {
     nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
     
     if (info != NULL && addr != NULL) {
-        if (info->GetExternalProxyAddr(&addr) == NS_OK)
+        NetAddr temp;
+        NetAddr *tempPtr = &temp;
+        if (info->GetExternalProxyAddr(&tempPtr) == NS_OK) {
+            NetAddrToPRNetAddr(tempPtr, addr);
             return PR_SUCCESS;
+        }
     }
 
     return PR_FAILURE;
 }
 
 static PRStatus
 nsSOCKSIOLayerGetPeerName(PRFileDesc *fd, PRNetAddr *addr)
 {
     nsSOCKSSocketInfo * info = (nsSOCKSSocketInfo*) fd->secret;
 
     if (info != NULL && addr != NULL) {
-        if (info->GetDestinationAddr(&addr) == NS_OK)
+        NetAddr temp;
+        NetAddr *tempPtr = &temp;
+        if (info->GetDestinationAddr(&tempPtr) == NS_OK) {
+            NetAddrToPRNetAddr(tempPtr, addr);
             return PR_SUCCESS;
+        }
     }
 
     return PR_FAILURE;
 }
 
 static PRStatus
 nsSOCKSIOLayerListen(PRFileDesc *fd, int backlog)
 {
@@ -1214,42 +1238,42 @@ nsSOCKSIOLayerAddToSocket(int32_t family
             ipv6Supported = false;
         } else {
             // If the system does not support IPv6, NSPR will push
             // IPv6-to-IPv4 emulation layer onto the native layer
             ipv6Supported = PR_GetIdentitiesLayer(tmpfd, PR_NSPR_IO_LAYER) == tmpfd;
             PR_Close(tmpfd);
         }
 
-        nsSOCKSIOLayerIdentity		= PR_GetUniqueIdentity("SOCKS layer");
-        nsSOCKSIOLayerMethods		= *PR_GetDefaultIOMethods();
+        nsSOCKSIOLayerIdentity = PR_GetUniqueIdentity("SOCKS layer");
+        nsSOCKSIOLayerMethods = *PR_GetDefaultIOMethods();
 
-        nsSOCKSIOLayerMethods.connect	= nsSOCKSIOLayerConnect;
-        nsSOCKSIOLayerMethods.connectcontinue	= nsSOCKSIOLayerConnectContinue;
-        nsSOCKSIOLayerMethods.poll	= nsSOCKSIOLayerPoll;
-        nsSOCKSIOLayerMethods.bind	= nsSOCKSIOLayerBind;
+        nsSOCKSIOLayerMethods.connect = nsSOCKSIOLayerConnect;
+        nsSOCKSIOLayerMethods.connectcontinue = nsSOCKSIOLayerConnectContinue;
+        nsSOCKSIOLayerMethods.poll = nsSOCKSIOLayerPoll;
+        nsSOCKSIOLayerMethods.bind = nsSOCKSIOLayerBind;
         nsSOCKSIOLayerMethods.acceptread = nsSOCKSIOLayerAcceptRead;
         nsSOCKSIOLayerMethods.getsockname = nsSOCKSIOLayerGetName;
         nsSOCKSIOLayerMethods.getpeername = nsSOCKSIOLayerGetPeerName;
-        nsSOCKSIOLayerMethods.accept	= nsSOCKSIOLayerAccept;
-        nsSOCKSIOLayerMethods.listen	= nsSOCKSIOLayerListen;
-        nsSOCKSIOLayerMethods.close	= nsSOCKSIOLayerClose;
+        nsSOCKSIOLayerMethods.accept = nsSOCKSIOLayerAccept;
+        nsSOCKSIOLayerMethods.listen = nsSOCKSIOLayerListen;
+        nsSOCKSIOLayerMethods.close = nsSOCKSIOLayerClose;
 
-        firstTime			= false;
+        firstTime = false;
 
 #if defined(PR_LOGGING)
         gSOCKSLog = PR_NewLogModule("SOCKS");
 #endif
 
     }
 
     LOGDEBUG(("Entering nsSOCKSIOLayerAddToSocket()."));
 
-    PRFileDesc *	layer;
-    PRStatus	rv;
+    PRFileDesc *layer;
+    PRStatus rv;
 
     layer = PR_CreateIOLayerStub(nsSOCKSIOLayerIdentity, &nsSOCKSIOLayerMethods);
     if (! layer)
     {
         LOGERROR(("PR_CreateIOLayerStub() failed."));
         return NS_ERROR_FAILURE;
     }