Coverage Report

Created: 2018-09-25 14:53

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