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

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

mercurial