Add AsyncSocketExceptionType for early data rejection.
[folly.git] / folly / IPAddressV4.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <folly/IPAddressV4.h>
18
19 #include <ostream>
20 #include <string>
21
22 #include <folly/Format.h>
23 #include <folly/IPAddress.h>
24 #include <folly/IPAddressV6.h>
25 #include <folly/detail/IPAddressSource.h>
26
27 using std::ostream;
28 using std::string;
29
30 namespace folly {
31
32 // free functions
33 size_t hash_value(const IPAddressV4& addr) {
34   return addr.hash();
35 }
36 ostream& operator<<(ostream& os, const IPAddressV4& addr) {
37   os << addr.str();
38   return os;
39 }
40 void toAppend(IPAddressV4 addr, string* result) {
41   result->append(addr.str());
42 }
43 void toAppend(IPAddressV4 addr, fbstring* result) {
44   result->append(addr.str());
45 }
46
47 bool IPAddressV4::validate(StringPiece ip) {
48   constexpr size_t kStrMaxLen = INET_ADDRSTRLEN;
49   std::array<char, kStrMaxLen + 1> ip_cstr;
50   const size_t len = std::min(ip.size(), kStrMaxLen);
51   std::memcpy(ip_cstr.data(), ip.data(), len);
52   ip_cstr[len] = 0;
53   struct in_addr addr;
54   return 1 == inet_pton(AF_INET, ip_cstr.data(), &addr);
55 }
56
57 // public static
58 IPAddressV4 IPAddressV4::fromLong(uint32_t src) {
59   in_addr addr;
60   addr.s_addr = src;
61   return IPAddressV4(addr);
62 }
63
64 IPAddressV4 IPAddressV4::fromLongHBO(uint32_t src) {
65   in_addr addr;
66   addr.s_addr = htonl(src);
67   return IPAddressV4(addr);
68 }
69
70 // static public
71 uint32_t IPAddressV4::toLong(StringPiece ip) {
72   auto str = ip.str();
73   in_addr addr;
74   if (inet_pton(AF_INET, str.c_str(), &addr) != 1) {
75     throw IPAddressFormatException(
76         sformat("Can't convert invalid IP '{}' to long", ip));
77   }
78   return addr.s_addr;
79 }
80
81 // static public
82 uint32_t IPAddressV4::toLongHBO(StringPiece ip) {
83   return ntohl(IPAddressV4::toLong(ip));
84 }
85
86 // public default constructor
87 IPAddressV4::IPAddressV4() {}
88
89 // ByteArray4 constructor
90 IPAddressV4::IPAddressV4(const ByteArray4& src) : addr_(src) {}
91
92 // public string constructor
93 IPAddressV4::IPAddressV4(StringPiece addr) : addr_() {
94   auto ip = addr.str();
95   if (inet_pton(AF_INET, ip.c_str(), &addr_.inAddr_) != 1) {
96     throw IPAddressFormatException(sformat("Invalid IPv4 address '{}'", addr));
97   }
98 }
99
100 // in_addr constructor
101 IPAddressV4::IPAddressV4(const in_addr src) : addr_(src) {}
102
103 // public
104 void IPAddressV4::setFromBinary(ByteRange bytes) {
105   if (bytes.size() != 4) {
106     throw IPAddressFormatException(sformat(
107         "Invalid IPv4 binary data: length must be 4 bytes, got {}",
108         bytes.size()));
109   }
110   memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr));
111 }
112
113 // static
114 IPAddressV4 IPAddressV4::fromInverseArpaName(const std::string& arpaname) {
115   auto piece = StringPiece(arpaname);
116   // input must be something like 1.0.168.192.in-addr.arpa
117   if (!piece.removeSuffix(".in-addr.arpa")) {
118     throw IPAddressFormatException(
119         sformat("input does not end with '.in-addr.arpa': '{}'", arpaname));
120   }
121   std::vector<StringPiece> pieces;
122   split(".", piece, pieces);
123   if (pieces.size() != 4) {
124     throw IPAddressFormatException(sformat("Invalid input. Got {}", piece));
125   }
126   // reverse 1.0.168.192 -> 192.168.0.1
127   return IPAddressV4(join(".", pieces.rbegin(), pieces.rend()));
128 }
129
130 // public
131 IPAddressV6 IPAddressV4::createIPv6() const {
132   ByteArray16 ba{};
133   ba[10] = 0xff;
134   ba[11] = 0xff;
135   std::memcpy(&ba[12], bytes(), 4);
136   return IPAddressV6(ba);
137 }
138
139 // public
140 IPAddressV6 IPAddressV4::getIPv6For6To4() const {
141   ByteArray16 ba{};
142   ba[0] = (uint8_t)((IPAddressV6::PREFIX_6TO4 & 0xFF00) >> 8);
143   ba[1] = (uint8_t)(IPAddressV6::PREFIX_6TO4 & 0x00FF);
144   std::memcpy(&ba[2], bytes(), 4);
145   return IPAddressV6(ba);
146 }
147
148 // public
149 string IPAddressV4::toJson() const {
150   return sformat("{{family:'AF_INET', addr:'{}', hash:{}}}", str(), hash());
151 }
152
153 // public
154 bool IPAddressV4::inSubnet(StringPiece cidrNetwork) const {
155   auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
156   auto addr = subnetInfo.first;
157   if (!addr.isV4()) {
158     throw IPAddressFormatException(
159         sformat("Address '{}' is not a V4 address", addr.toJson()));
160   }
161   return inSubnetWithMask(addr.asV4(), fetchMask(subnetInfo.second));
162 }
163
164 // public
165 bool IPAddressV4::inSubnetWithMask(
166     const IPAddressV4& subnet,
167     const ByteArray4 cidrMask) const {
168   const auto mask = detail::Bytes::mask(toByteArray(), cidrMask);
169   const auto subMask = detail::Bytes::mask(subnet.toByteArray(), cidrMask);
170   return (mask == subMask);
171 }
172
173 // public
174 bool IPAddressV4::isLoopback() const {
175   static IPAddressV4 loopback_addr("127.0.0.0");
176   return inSubnetWithMask(loopback_addr, fetchMask(8));
177 }
178
179 // public
180 bool IPAddressV4::isLinkLocal() const {
181   static IPAddressV4 linklocal_addr("169.254.0.0");
182   return inSubnetWithMask(linklocal_addr, fetchMask(16));
183 }
184
185 // public
186 bool IPAddressV4::isNonroutable() const {
187   auto ip = toLongHBO();
188   return isPrivate() ||
189       (/* align */ true && ip <= 0x00FFFFFF) || // 0.0.0.0-0.255.255.255
190       (ip >= 0xC0000000 && ip <= 0xC00000FF) || // 192.0.0.0-192.0.0.255
191       (ip >= 0xC0000200 && ip <= 0xC00002FF) || // 192.0.2.0-192.0.2.255
192       (ip >= 0xC6120000 && ip <= 0xC613FFFF) || // 198.18.0.0-198.19.255.255
193       (ip >= 0xC6336400 && ip <= 0xC63364FF) || // 198.51.100.0-198.51.100.255
194       (ip >= 0xCB007100 && ip <= 0xCB0071FF) || // 203.0.113.0-203.0.113.255
195       (ip >= 0xE0000000 && ip <= 0xFFFFFFFF) || // 224.0.0.0-255.255.255.255
196       false;
197 }
198
199 // public
200 bool IPAddressV4::isPrivate() const {
201   auto ip = toLongHBO();
202   return // some ranges below
203       (ip >= 0x0A000000 && ip <= 0x0AFFFFFF) || // 10.0.0.0-10.255.255.255
204       (ip >= 0x7F000000 && ip <= 0x7FFFFFFF) || // 127.0.0.0-127.255.255.255
205       (ip >= 0xA9FE0000 && ip <= 0xA9FEFFFF) || // 169.254.0.0-169.254.255.255
206       (ip >= 0xAC100000 && ip <= 0xAC1FFFFF) || // 172.16.0.0-172.31.255.255
207       (ip >= 0xC0A80000 && ip <= 0xC0A8FFFF) || // 192.168.0.0-192.168.255.255
208       false;
209 }
210
211 // public
212 bool IPAddressV4::isMulticast() const {
213   return (toLongHBO() & 0xf0000000) == 0xe0000000;
214 }
215
216 // public
217 IPAddressV4 IPAddressV4::mask(size_t numBits) const {
218   static const auto bits = bitCount();
219   if (numBits > bits) {
220     throw IPAddressFormatException(
221         sformat("numBits({}) > bitsCount({})", numBits, bits));
222   }
223
224   ByteArray4 ba = detail::Bytes::mask(fetchMask(numBits), addr_.bytes_);
225   return IPAddressV4(ba);
226 }
227
228 // public
229 string IPAddressV4::str() const {
230   return detail::fastIpv4ToString(addr_.inAddr_);
231 }
232
233 // public
234 void IPAddressV4::toFullyQualifiedAppend(std::string& out) const {
235   detail::fastIpv4AppendToString(addr_.inAddr_, out);
236 }
237
238 // public
239 string IPAddressV4::toInverseArpaName() const {
240   return sformat(
241       "{}.{}.{}.{}.in-addr.arpa",
242       addr_.bytes_[3],
243       addr_.bytes_[2],
244       addr_.bytes_[1],
245       addr_.bytes_[0]);
246 }
247
248 // public
249 uint8_t IPAddressV4::getNthMSByte(size_t byteIndex) const {
250   const auto highestIndex = byteCount() - 1;
251   if (byteIndex > highestIndex) {
252     throw std::invalid_argument(sformat(
253         "Byte index must be <= {} for addresses of type: {}",
254         highestIndex,
255         detail::familyNameStr(AF_INET)));
256   }
257   return bytes()[byteIndex];
258 }
259 // protected
260 const ByteArray4 IPAddressV4::fetchMask(size_t numBits) {
261   static const size_t bits = bitCount();
262   if (numBits > bits) {
263     throw IPAddressFormatException("IPv4 addresses are 32 bits");
264   }
265   auto const val = Endian::big(uint32_t(~uint64_t(0) << (32 - numBits)));
266   ByteArray4 arr;
267   std::memcpy(arr.data(), &val, sizeof(val));
268   return arr;
269 }
270 // public static
271 CIDRNetworkV4 IPAddressV4::longestCommonPrefix(
272     const CIDRNetworkV4& one,
273     const CIDRNetworkV4& two) {
274   auto prefix = detail::Bytes::longestCommonPrefix(
275       one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
276   return {IPAddressV4(prefix.first), prefix.second};
277 }
278
279 } // namespace folly