netwerk/dns/DNS.cpp

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "mozilla/net/DNS.h"
     7 #include "mozilla/Assertions.h"
     8 #include "mozilla/mozalloc.h"
     9 #include "mozilla/ArrayUtils.h"
    10 #include <string.h>
    12 #ifdef XP_WIN
    13 #include "ws2tcpip.h"
    14 #endif
    16 namespace mozilla {
    17 namespace net {
    19 const char *inet_ntop_internal(int af, const void *src, char *dst, socklen_t size)
    20 {
    21 #ifdef XP_WIN
    22   if (af == AF_INET) {
    23     struct sockaddr_in s;
    24     memset(&s, 0, sizeof(s));
    25     s.sin_family = AF_INET;
    26     memcpy(&s.sin_addr, src, sizeof(struct in_addr));
    27     int result = getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in),
    28                              dst, size, nullptr, 0, NI_NUMERICHOST);
    29     if (result == 0) {
    30       return dst;
    31     }
    32   }
    33   else if (af == AF_INET6) {
    34     struct sockaddr_in6 s;
    35     memset(&s, 0, sizeof(s));
    36     s.sin6_family = AF_INET6;
    37     memcpy(&s.sin6_addr, src, sizeof(struct in_addr6));
    38     int result = getnameinfo((struct sockaddr *)&s, sizeof(struct sockaddr_in6),
    39                              dst, size, nullptr, 0, NI_NUMERICHOST);
    40     if (result == 0) {
    41       return dst;
    42     }
    43   }
    44   return nullptr;
    45 #else
    46   return inet_ntop(af, src, dst, size);
    47 #endif
    48 }
    50 // Copies the contents of a PRNetAddr to a NetAddr.
    51 // Does not do a ptr safety check!
    52 void PRNetAddrToNetAddr(const PRNetAddr *prAddr, NetAddr *addr)
    53 {
    54   if (prAddr->raw.family == PR_AF_INET) {
    55     addr->inet.family = AF_INET;
    56     addr->inet.port = prAddr->inet.port;
    57     addr->inet.ip = prAddr->inet.ip;
    58   }
    59   else if (prAddr->raw.family == PR_AF_INET6) {
    60     addr->inet6.family = AF_INET6;
    61     addr->inet6.port = prAddr->ipv6.port;
    62     addr->inet6.flowinfo = prAddr->ipv6.flowinfo;
    63     memcpy(&addr->inet6.ip, &prAddr->ipv6.ip, sizeof(addr->inet6.ip.u8));
    64     addr->inet6.scope_id = prAddr->ipv6.scope_id;
    65   }
    66 #if defined(XP_UNIX)
    67   else if (prAddr->raw.family == PR_AF_LOCAL) {
    68     addr->local.family = AF_LOCAL;
    69     memcpy(addr->local.path, prAddr->local.path, sizeof(addr->local.path));
    70   }
    71 #endif
    72 }
    74 // Copies the contents of a NetAddr to a PRNetAddr.
    75 // Does not do a ptr safety check!
    76 void NetAddrToPRNetAddr(const NetAddr *addr, PRNetAddr *prAddr)
    77 {
    78   if (addr->raw.family == AF_INET) {
    79     prAddr->inet.family = PR_AF_INET;
    80     prAddr->inet.port = addr->inet.port;
    81     prAddr->inet.ip = addr->inet.ip;
    82   }
    83   else if (addr->raw.family == AF_INET6) {
    84     prAddr->ipv6.family = PR_AF_INET6;
    85     prAddr->ipv6.port = addr->inet6.port;
    86     prAddr->ipv6.flowinfo = addr->inet6.flowinfo;
    87     memcpy(&prAddr->ipv6.ip, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
    88     prAddr->ipv6.scope_id = addr->inet6.scope_id;
    89   }
    90 #if defined(XP_UNIX)
    91   else if (addr->raw.family == AF_LOCAL) {
    92     prAddr->local.family = PR_AF_LOCAL;
    93     memcpy(prAddr->local.path, addr->local.path, sizeof(addr->local.path));
    94   }
    95 #endif
    96 }
    98 bool NetAddrToString(const NetAddr *addr, char *buf, uint32_t bufSize)
    99 {
   100   if (addr->raw.family == AF_INET) {
   101     if (bufSize < INET_ADDRSTRLEN) {
   102       return false;
   103     }
   104     struct in_addr nativeAddr = {};
   105     nativeAddr.s_addr = addr->inet.ip;
   106     return !!inet_ntop_internal(AF_INET, &nativeAddr, buf, bufSize);
   107   }
   108   else if (addr->raw.family == AF_INET6) {
   109     if (bufSize < INET6_ADDRSTRLEN) {
   110       return false;
   111     }
   112     struct in6_addr nativeAddr = {};
   113     memcpy(&nativeAddr.s6_addr, &addr->inet6.ip, sizeof(addr->inet6.ip.u8));
   114     return !!inet_ntop_internal(AF_INET6, &nativeAddr, buf, bufSize);
   115   }
   116 #if defined(XP_UNIX)
   117   else if (addr->raw.family == AF_LOCAL) {
   118     if (bufSize < sizeof(addr->local.path)) {
   119       // Many callers don't bother checking our return value, so
   120       // null-terminate just in case.
   121       if (bufSize > 0) {
   122           buf[0] = '\0';
   123       }
   124       return false;
   125     }
   127     // Usually, the size passed to memcpy should be the size of the
   128     // destination. Here, we know that the source is no larger than the
   129     // destination, so using the source's size is always safe, whereas
   130     // using the destination's size may cause us to read off the end of the
   131     // source.
   132     memcpy(buf, addr->local.path, sizeof(addr->local.path));
   133     return true;
   134   }
   135 #endif
   136   return false;
   137 }
   139 bool IsLoopBackAddress(const NetAddr *addr)
   140 {
   141   if (addr->raw.family == AF_INET) {
   142     return (addr->inet.ip == htonl(INADDR_LOOPBACK));
   143   }
   144   else if (addr->raw.family == AF_INET6) {
   145     if (IPv6ADDR_IS_LOOPBACK(&addr->inet6.ip)) {
   146       return true;
   147     } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
   148                IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_LOOPBACK)) {
   149       return true;
   150     }
   151   }
   152   return false;
   153 }
   155 bool IsIPAddrAny(const NetAddr *addr)
   156 {
   157   if (addr->raw.family == AF_INET) {
   158     if (addr->inet.ip == htonl(INADDR_ANY)) {
   159       return true;
   160     }
   161   }
   162   else if (addr->raw.family == AF_INET6) {
   163     if (IPv6ADDR_IS_UNSPECIFIED(&addr->inet6.ip)) {
   164       return true;
   165     } else if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip) &&
   166                IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip) == htonl(INADDR_ANY)) {
   167       return true;
   168     }
   169   }
   170   return false;
   171 }
   173 bool IsIPAddrV4Mapped(const NetAddr *addr)
   174 {
   175   if (addr->raw.family == AF_INET6) {
   176     return IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip);
   177   }
   178   return false;
   179 }
   181 bool IsIPAddrLocal(const NetAddr *addr)
   182 {
   183   MOZ_ASSERT(addr);
   185   // IPv4 RFC1918 and Link Local Addresses.
   186   if (addr->raw.family == AF_INET) {
   187     uint32_t addr32 = ntohl(addr->inet.ip);
   188     if (addr32 >> 24 == 0x0A ||    // 10/8 prefix (RFC 1918).
   189         addr32 >> 20 == 0xAC1 ||   // 172.16/12 prefix (RFC 1918).
   190         addr32 >> 16 == 0xC0A8 ||  // 192.168/16 prefix (RFC 1918).
   191         addr32 >> 16 == 0xA9FE) {  // 169.254/16 prefix (Link Local).
   192       return true;
   193     }
   194   }
   195   // IPv6 Unique and Link Local Addresses.
   196   if (addr->raw.family == AF_INET6) {
   197     uint16_t addr16 = ntohs(addr->inet6.ip.u16[0]);
   198     if (addr16 >> 9 == 0xfc >> 1 ||   // fc00::/7 Unique Local Address.
   199         addr16 >> 6 == 0xfe80 >> 6) { // fe80::/10 Link Local Address.
   200       return true;
   201     }
   202   }
   203   // Not an IPv4/6 local address.
   204   return false;
   205 }
   207 nsresult
   208 GetPort(const NetAddr *aAddr, uint16_t *aResult)
   209 {
   210   uint16_t port;
   211   if (aAddr->raw.family == PR_AF_INET) {
   212     port = aAddr->inet.port;
   213   } else if (aAddr->raw.family == PR_AF_INET6) {
   214     port = aAddr->inet6.port;
   215   } else {
   216     return NS_ERROR_NOT_INITIALIZED;
   217   }
   219   *aResult = ntohs(port);
   220   return NS_OK;
   221 }
   223 bool
   224 NetAddr::operator == (const NetAddr& other) const
   225 {
   226   if (this->raw.family != other.raw.family) {
   227     return false;
   228   } else if (this->raw.family == AF_INET) {
   229     return (this->inet.port == other.inet.port) &&
   230            (this->inet.ip == other.inet.ip);
   231   } else if (this->raw.family == AF_INET6) {
   232     return (this->inet6.port == other.inet6.port) &&
   233            (this->inet6.flowinfo == other.inet6.flowinfo) &&
   234            (memcmp(&this->inet6.ip, &other.inet6.ip,
   235                    sizeof(this->inet6.ip)) == 0) &&
   236            (this->inet6.scope_id == other.inet6.scope_id);
   237 #if defined(XP_UNIX)
   238   } else if (this->raw.family == AF_LOCAL) {
   239     return PL_strncmp(this->local.path, other.local.path,
   240                       ArrayLength(this->local.path));
   241 #endif
   242   }
   243   return false;
   244 }
   248 NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
   249 {
   250   PRNetAddrToNetAddr(prNetAddr, &mAddress);
   251 }
   253 NetAddrElement::NetAddrElement(const NetAddrElement& netAddr)
   254 {
   255   mAddress = netAddr.mAddress;
   256 }
   258 NetAddrElement::~NetAddrElement()
   259 {
   260 }
   262 AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
   263                    bool disableIPv4, const char *cname)
   264 {
   265   MOZ_ASSERT(prAddrInfo, "Cannot construct AddrInfo with a null prAddrInfo pointer!");
   267   Init(host, cname);
   268   PRNetAddr tmpAddr;
   269   void *iter = nullptr;
   270   do {
   271     iter = PR_EnumerateAddrInfo(iter, prAddrInfo, 0, &tmpAddr);
   272     if (iter && (!disableIPv4 || tmpAddr.raw.family != PR_AF_INET)) {
   273       NetAddrElement *addrElement = new NetAddrElement(&tmpAddr);
   274       mAddresses.insertBack(addrElement);
   275     }
   276   } while (iter);
   277 }
   279 AddrInfo::AddrInfo(const char *host, const char *cname)
   280 {
   281   Init(host, cname);
   282 }
   284 AddrInfo::~AddrInfo()
   285 {
   286   NetAddrElement *addrElement;
   287   while ((addrElement = mAddresses.popLast())) {
   288     delete addrElement;
   289   }
   290   moz_free(mHostName);
   291   moz_free(mCanonicalName);
   292 }
   294 void
   295 AddrInfo::Init(const char *host, const char *cname)
   296 {
   297   MOZ_ASSERT(host, "Cannot initialize AddrInfo with a null host pointer!");
   299   size_t hostlen = strlen(host);
   300   mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
   301   memcpy(mHostName, host, hostlen + 1);
   302   if (cname) {
   303     size_t cnameLen = strlen(cname);
   304     mCanonicalName = static_cast<char*>(moz_xmalloc(cnameLen + 1));
   305     memcpy(mCanonicalName, cname, cnameLen + 1);
   306   }
   307   else {
   308     mCanonicalName = nullptr;
   309   }
   310 }
   312 void
   313 AddrInfo::AddAddress(NetAddrElement *address)
   314 {
   315   MOZ_ASSERT(address, "Cannot add the address to an uninitialized list");
   317   mAddresses.insertBack(address);
   318 }
   320 size_t
   321 AddrInfo::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
   322 {
   323   size_t n = mallocSizeOf(this);
   324   n += mallocSizeOf(mHostName);
   325   n += mallocSizeOf(mCanonicalName);
   326   n += mAddresses.sizeOfExcludingThis(mallocSizeOf);
   327   return n;
   328 }
   330 } // namespace dns
   331 } // namespace mozilla

mercurial