DNS.cpp 10 KB

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