DNS.h (9273B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 #ifndef DNS_h_ 8 #define DNS_h_ 9 10 #include "nsILoadInfo.h" 11 #include "nscore.h" 12 #include "nsString.h" 13 #include "prio.h" 14 #include "prnetdb.h" 15 #include "nsISupportsImpl.h" 16 #include "mozilla/MemoryReporting.h" 17 #include "nsTArray.h" 18 19 #if !defined(XP_WIN) 20 # include <arpa/inet.h> 21 #endif 22 23 #ifdef XP_WIN 24 # include "winsock2.h" 25 #endif 26 27 #ifndef AF_LOCAL 28 # define AF_LOCAL 1 // used for named pipe 29 #endif 30 31 #define IPv6ADDR_IS_LOOPBACK(a) \ 32 (((a)->u32[0] == 0) && ((a)->u32[1] == 0) && ((a)->u32[2] == 0) && \ 33 ((a)->u8[12] == 0) && ((a)->u8[13] == 0) && ((a)->u8[14] == 0) && \ 34 ((a)->u8[15] == 0x1U)) 35 36 #define IPv6ADDR_IS_V4MAPPED(a) \ 37 (((a)->u32[0] == 0) && ((a)->u32[1] == 0) && ((a)->u8[8] == 0) && \ 38 ((a)->u8[9] == 0) && ((a)->u8[10] == 0xff) && ((a)->u8[11] == 0xff)) 39 40 #define IPv6ADDR_V4MAPPED_TO_IPADDR(a) ((a)->u32[3]) 41 42 #define IPv6ADDR_IS_UNSPECIFIED(a) \ 43 (((a)->u32[0] == 0) && ((a)->u32[1] == 0) && ((a)->u32[2] == 0) && \ 44 ((a)->u32[3] == 0)) 45 46 namespace mozilla { 47 namespace net { 48 49 // IMPORTANT: when adding new values, always add them to the end, otherwise 50 // it will mess up telemetry. 51 // Stage_0: Receive the record before the http transaction is created. 52 // Stage_1: Receive the record after the http transaction is created and the 53 // transaction is not dispatched. 54 // Stage_2: Receive the record after the http transaction is dispatched. 55 enum HTTPSSVC_RECEIVED_STAGE : uint32_t { 56 HTTPSSVC_NOT_PRESENT = 0, 57 HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0 = 1, 58 HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0 = 2, 59 HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_1 = 3, 60 HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_1 = 4, 61 HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2 = 5, 62 HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_2 = 6, 63 HTTPSSVC_NOT_USED = 7, 64 HTTPSSVC_NO_USABLE_RECORD = 8, 65 }; 66 67 #define HTTPS_RR_IS_USED(s) \ 68 (s > HTTPSSVC_NOT_PRESENT && s < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2) 69 70 // Required buffer size for text form of an IP address. 71 // Includes space for null termination. We make our own contants 72 // because we don't want higher-level code depending on things 73 // like INET6_ADDRSTRLEN and having to include the associated 74 // platform-specific headers. 75 #ifdef XP_WIN 76 // Windows requires longer buffers for some reason. 77 const int kIPv4CStrBufSize = 22; 78 const int kIPv6CStrBufSize = 65; 79 const int kNetAddrMaxCStrBufSize = kIPv6CStrBufSize; 80 #else 81 const int kIPv4CStrBufSize = 16; 82 const int kIPv6CStrBufSize = 46; 83 const int kLocalCStrBufSize = 108; 84 const int kNetAddrMaxCStrBufSize = kLocalCStrBufSize; 85 #endif 86 87 // This was all created at a time in which we were using NSPR for host 88 // resolution and we were propagating NSPR types like "PRAddrInfo" and 89 // "PRNetAddr" all over Gecko. This made it hard to use another host 90 // resolver -- we were locked into NSPR. The goal here is to get away 91 // from that. We'll translate what we get from NSPR or any other host 92 // resolution library into the types below and use them in Gecko. 93 94 union IPv6Addr { 95 uint8_t u8[16]; 96 uint16_t u16[8]; 97 uint32_t u32[4]; 98 uint64_t u64[2]; 99 }; 100 101 // This struct is similar to operating system structs like "sockaddr", used for 102 // things like "connect" and "getsockname". When tempted to cast or do dumb 103 // copies of this struct to another struct, bear compiler-computed padding 104 // in mind. The size of this struct, and the layout of the data in it, may 105 // not be what you expect. 106 union NetAddr { 107 struct { 108 uint16_t family; /* address family (0x00ff maskable) */ 109 char data[14]; /* raw address data */ 110 } raw{}; 111 struct { 112 uint16_t family; /* address family (AF_INET) */ 113 uint16_t port; /* port number */ 114 uint32_t ip; /* The actual 32 bits of address */ 115 } inet; 116 struct { 117 uint16_t family; /* address family (AF_INET6) */ 118 uint16_t port; /* port number */ 119 uint32_t flowinfo; /* routing information */ 120 IPv6Addr ip; /* the actual 128 bits of address */ 121 uint32_t scope_id; /* set of interfaces for a scope */ 122 } inet6; 123 #if defined(XP_UNIX) || defined(XP_WIN) 124 struct { /* Unix domain socket or 125 Windows Named Pipes address */ 126 uint16_t family; /* address family (AF_UNIX) */ 127 char path[104]; /* null-terminated pathname */ 128 } local; 129 #endif 130 // introduced to support nsTArray<NetAddr> comparisons and sorting 131 bool operator==(const NetAddr& other) const; 132 bool operator<(const NetAddr& other) const; 133 134 // Use the default copy constructor/assignment operator, which will memcpy 135 // under the hood. 136 NetAddr(const NetAddr&) = default; 137 inline NetAddr& operator=(const NetAddr& other) = default; 138 139 NetAddr() { memset((void*)this, 0, sizeof(NetAddr)); } 140 explicit NetAddr(const PRNetAddr* prAddr); 141 142 // Will parse aString into a NetAddr using PR_StringToNetAddr. 143 // Returns an error code if parsing fails. 144 // If aPort is non-0 will set the NetAddr's port to (the network endian 145 // value of) that. 146 nsresult InitFromString(const nsACString& aString, uint16_t aPort = 0); 147 148 bool IsIPAddrAny() const; 149 bool IsLoopbackAddr() const; 150 bool IsLoopBackAddressWithoutIPv6Mapping() const; 151 bool IsIPAddrV4() const; 152 bool IsBenchMarkingAddress() const; 153 bool IsIPAddrV4Mapped() const; 154 bool IsIPAddrLocal() const; 155 bool IsIPAddrShared() const; 156 nsresult GetPort(uint16_t* aResult) const; 157 bool ToStringBuffer(char* buf, uint32_t bufSize) const; 158 nsCString ToString() const; 159 void ToAddrPortString(nsACString& aOutput) const; 160 nsILoadInfo::IPAddressSpace GetIpAddressSpace() const; 161 }; 162 163 enum class DNSResolverType : uint32_t { Native = 0, TRR }; 164 165 class AddrInfo { 166 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AddrInfo) 167 168 public: 169 static const uint32_t NO_TTL_DATA = (uint32_t)-1; 170 171 // Creates an AddrInfo object. 172 explicit AddrInfo(const nsACString& host, const PRAddrInfo* prAddrInfo, 173 bool disableIPv4, bool filterNameCollision, 174 const nsACString& cname); 175 176 // Creates a basic AddrInfo object (initialize only the host, cname and TRR 177 // type). 178 explicit AddrInfo(const nsACString& host, const nsACString& cname, 179 DNSResolverType aResolverType, unsigned int aTRRType, 180 nsTArray<NetAddr>&& addresses); 181 182 // Creates a basic AddrInfo object (initialize only the host and TRR 183 // status). 184 explicit AddrInfo(const nsACString& host, DNSResolverType aResolverType, 185 unsigned int aTRRType, nsTArray<NetAddr>&& addresses, 186 uint32_t aTTL = NO_TTL_DATA); 187 188 explicit AddrInfo(const AddrInfo* src); // copy 189 190 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 191 192 bool IsTRR() const { return mResolverType == DNSResolverType::TRR; } 193 DNSResolverType ResolverType() const { return mResolverType; } 194 unsigned int TRRType() { return mTRRType; } 195 196 double GetTrrFetchDuration() { return mTrrFetchDuration; } 197 double GetTrrFetchDurationNetworkOnly() { 198 return mTrrFetchDurationNetworkOnly; 199 } 200 201 const nsTArray<NetAddr>& Addresses() { return mAddresses; } 202 const nsCString& Hostname() { return mHostName; } 203 const nsCString& CanonicalHostname() { return mCanonicalName; } 204 uint32_t TTL() { return ttl; } 205 206 class MOZ_STACK_CLASS AddrInfoBuilder { 207 public: 208 explicit AddrInfoBuilder(AddrInfo* aInfo) { 209 mInfo = new AddrInfo(aInfo); // Clone it 210 } 211 212 void SetTrrFetchDurationNetworkOnly(double aTime) { 213 mInfo->mTrrFetchDurationNetworkOnly = aTime; 214 } 215 216 void SetTrrFetchDuration(double aTime) { mInfo->mTrrFetchDuration = aTime; } 217 218 void SetTTL(uint32_t aTTL) { mInfo->ttl = aTTL; } 219 220 void SetAddresses(nsTArray<NetAddr>&& addresses) { 221 mInfo->mAddresses = std::move(addresses); 222 } 223 224 template <class Comparator> 225 void SortAddresses(const Comparator& aComp) { 226 mInfo->mAddresses.Sort(aComp); 227 } 228 229 void SetCanonicalHostname(const nsACString& aCname) { 230 mInfo->mCanonicalName = aCname; 231 } 232 233 already_AddRefed<AddrInfo> Finish() { return mInfo.forget(); } 234 235 private: 236 RefPtr<AddrInfo> mInfo; 237 }; 238 239 AddrInfoBuilder Build() { return AddrInfoBuilder(this); } 240 241 private: 242 ~AddrInfo(); 243 uint32_t ttl = NO_TTL_DATA; 244 245 nsCString mHostName; 246 nsCString mCanonicalName; 247 DNSResolverType mResolverType = DNSResolverType::Native; 248 unsigned int mTRRType = 0; 249 double mTrrFetchDuration = 0; 250 double mTrrFetchDurationNetworkOnly = 0; 251 252 nsTArray<NetAddr> mAddresses; 253 }; 254 255 // Copies the contents of a PRNetAddr to a NetAddr. 256 // Does not do a ptr safety check! 257 void PRNetAddrToNetAddr(const PRNetAddr* prAddr, NetAddr* addr); 258 259 // Copies the contents of a NetAddr to a PRNetAddr. 260 // Does not do a ptr safety check! 261 void NetAddrToPRNetAddr(const NetAddr* addr, PRNetAddr* prAddr); 262 263 bool IsLoopbackHostname(const nsACString& aAsciiHost); 264 265 bool HostIsIPLiteral(const nsACString& aAsciiHost); 266 267 } // namespace net 268 } // namespace mozilla 269 270 #endif // DNS_h_