proxygen
IPAddressV4.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-present 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>
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 }
44  result->append(addr.str());
45 }
46 
48  return tryFromString(ip).hasValue();
49 }
50 
51 // public static
53  in_addr addr;
54  addr.s_addr = src;
55  return IPAddressV4(addr);
56 }
57 
59  in_addr addr;
60  addr.s_addr = htonl(src);
61  return IPAddressV4(addr);
62 }
63 
64 // static public
66  auto str = ip.str();
67  in_addr addr;
68  if (inet_pton(AF_INET, str.c_str(), &addr) != 1) {
70  sformat("Can't convert invalid IP '{}' to long", ip));
71  }
72  return addr.s_addr;
73 }
74 
75 // static public
77  return ntohl(IPAddressV4::toLong(ip));
78 }
79 
80 // public default constructor
82 
83 // ByteArray4 constructor
85 
86 // public string constructor
88  auto maybeIp = tryFromString(addr);
89  if (maybeIp.hasError()) {
91  to<std::string>("Invalid IPv4 address '", addr, "'"));
92  }
93  *this = std::move(maybeIp.value());
94 }
95 
98  struct in_addr inAddr;
99  if (inet_pton(AF_INET, str.str().c_str(), &inAddr) != 1) {
101  }
102  return IPAddressV4(inAddr);
103 }
104 
105 // in_addr constructor
106 IPAddressV4::IPAddressV4(const in_addr src) noexcept : addr_(src) {}
107 
109  auto maybeIp = tryFromBinary(bytes);
110  if (maybeIp.hasError()) {
111  throw IPAddressFormatException(to<std::string>(
112  "Invalid IPv4 binary data: length must be 4 bytes, got ",
113  bytes.size()));
114  }
115  return maybeIp.value();
116 }
117 
121  auto setResult = addr.trySetFromBinary(bytes);
122  if (setResult.hasError()) {
123  return makeUnexpected(std::move(setResult.error()));
124  }
125  return addr;
126 }
127 
130  if (bytes.size() != 4) {
132  }
133  memcpy(&addr_.inAddr_.s_addr, bytes.data(), sizeof(in_addr));
134  return folly::unit;
135 }
136 
137 // static
139  auto piece = StringPiece(arpaname);
140  // input must be something like 1.0.168.192.in-addr.arpa
141  if (!piece.removeSuffix(".in-addr.arpa")) {
143  sformat("input does not end with '.in-addr.arpa': '{}'", arpaname));
144  }
145  std::vector<StringPiece> pieces;
146  split(".", piece, pieces);
147  if (pieces.size() != 4) {
148  throw IPAddressFormatException(sformat("Invalid input. Got {}", piece));
149  }
150  // reverse 1.0.168.192 -> 192.168.0.1
151  return IPAddressV4(join(".", pieces.rbegin(), pieces.rend()));
152 }
154  ByteArray16 ba{};
155  ba[10] = 0xff;
156  ba[11] = 0xff;
157  std::memcpy(&ba[12], bytes(), 4);
158  return IPAddressV6(ba);
159 }
160 
161 // public
163  ByteArray16 ba{};
164  ba[0] = (uint8_t)((IPAddressV6::PREFIX_6TO4 & 0xFF00) >> 8);
165  ba[1] = (uint8_t)(IPAddressV6::PREFIX_6TO4 & 0x00FF);
166  std::memcpy(&ba[2], bytes(), 4);
167  return IPAddressV6(ba);
168 }
169 
170 // public
171 string IPAddressV4::toJson() const {
172  return sformat("{{family:'AF_INET', addr:'{}', hash:{}}}", str(), hash());
173 }
174 
175 // public
176 bool IPAddressV4::inSubnet(StringPiece cidrNetwork) const {
177  auto subnetInfo = IPAddress::createNetwork(cidrNetwork);
178  auto addr = subnetInfo.first;
179  if (!addr.isV4()) {
181  sformat("Address '{}' is not a V4 address", addr.toJson()));
182  }
183  return inSubnetWithMask(addr.asV4(), fetchMask(subnetInfo.second));
184 }
185 
186 // public
188  const IPAddressV4& subnet,
189  const ByteArray4 cidrMask) const {
190  const auto mask = detail::Bytes::mask(toByteArray(), cidrMask);
191  const auto subMask = detail::Bytes::mask(subnet.toByteArray(), cidrMask);
192  return (mask == subMask);
193 }
194 
195 // public
197  static IPAddressV4 loopback_addr("127.0.0.0");
198  return inSubnetWithMask(loopback_addr, fetchMask(8));
199 }
200 
201 // public
203  static IPAddressV4 linklocal_addr("169.254.0.0");
204  return inSubnetWithMask(linklocal_addr, fetchMask(16));
205 }
206 
207 // public
209  auto ip = toLongHBO();
210  return isPrivate() ||
211  (/* align */ true && ip <= 0x00FFFFFF) || // 0.0.0.0-0.255.255.255
212  (ip >= 0xC0000000 && ip <= 0xC00000FF) || // 192.0.0.0-192.0.0.255
213  (ip >= 0xC0000200 && ip <= 0xC00002FF) || // 192.0.2.0-192.0.2.255
214  (ip >= 0xC6120000 && ip <= 0xC613FFFF) || // 198.18.0.0-198.19.255.255
215  (ip >= 0xC6336400 && ip <= 0xC63364FF) || // 198.51.100.0-198.51.100.255
216  (ip >= 0xCB007100 && ip <= 0xCB0071FF) || // 203.0.113.0-203.0.113.255
217  (ip >= 0xE0000000 && ip <= 0xFFFFFFFF) || // 224.0.0.0-255.255.255.255
218  false;
219 }
220 
221 // public
223  auto ip = toLongHBO();
224  return // some ranges below
225  (ip >= 0x0A000000 && ip <= 0x0AFFFFFF) || // 10.0.0.0-10.255.255.255
226  (ip >= 0x7F000000 && ip <= 0x7FFFFFFF) || // 127.0.0.0-127.255.255.255
227  (ip >= 0xA9FE0000 && ip <= 0xA9FEFFFF) || // 169.254.0.0-169.254.255.255
228  (ip >= 0xAC100000 && ip <= 0xAC1FFFFF) || // 172.16.0.0-172.31.255.255
229  (ip >= 0xC0A80000 && ip <= 0xC0A8FFFF) || // 192.168.0.0-192.168.255.255
230  false;
231 }
232 
233 // public
235  return (toLongHBO() & 0xf0000000) == 0xe0000000;
236 }
237 
238 // public
239 IPAddressV4 IPAddressV4::mask(size_t numBits) const {
240  static const auto bits = bitCount();
241  if (numBits > bits) {
243  sformat("numBits({}) > bitsCount({})", numBits, bits));
244  }
245 
247  return IPAddressV4(ba);
248 }
249 
250 // public
251 string IPAddressV4::str() const {
253 }
254 
255 // public
258 }
259 
260 // public
262  return sformat(
263  "{}.{}.{}.{}.in-addr.arpa",
264  addr_.bytes_[3],
265  addr_.bytes_[2],
266  addr_.bytes_[1],
267  addr_.bytes_[0]);
268 }
269 
270 // public
271 uint8_t IPAddressV4::getNthMSByte(size_t byteIndex) const {
272  const auto highestIndex = byteCount() - 1;
273  if (byteIndex > highestIndex) {
274  throw std::invalid_argument(sformat(
275  "Byte index must be <= {} for addresses of type: {}",
276  highestIndex,
277  detail::familyNameStr(AF_INET)));
278  }
279  return bytes()[byteIndex];
280 }
281 // protected
282 const ByteArray4 IPAddressV4::fetchMask(size_t numBits) {
283  static const size_t bits = bitCount();
284  if (numBits > bits) {
285  throw IPAddressFormatException("IPv4 addresses are 32 bits");
286  }
287  auto const val = Endian::big(uint32_t(~uint64_t(0) << (32 - numBits)));
288  ByteArray4 arr;
289  std::memcpy(arr.data(), &val, sizeof(val));
290  return arr;
291 }
292 // public static
294  const CIDRNetworkV4& one,
295  const CIDRNetworkV4& two) {
297  one.first.addr_.bytes_, one.second, two.first.addr_.bytes_, two.second);
298  return {IPAddressV4(prefix.first), prefix.second};
299 }
300 
301 } // namespace folly
IPAddressV4 mask(size_t numBits) const
std::string toInverseArpaName() const
static CIDRNetworkV4 longestCommonPrefix(const CIDRNetworkV4 &one, const CIDRNetworkV4 &two)
static const uint32_t PREFIX_6TO4
Definition: IPAddressV6.h:90
std::string str() const
Definition: Range.h:591
std::string sformat(StringPiece fmt, Args &&...args)
Definition: Format.h:280
bool isNonroutable() const
bool isLinkLocal() const
static size_t byteCount()
Definition: IPAddressV4.h:262
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
static std::array< uint8_t, N > mask(const std::array< uint8_t, N > &a, const std::array< uint8_t, N > &b)
constexpr size_type size() const
Definition: Range.h:431
double val
Definition: String.cpp:273
static IPAddressV4 fromBinary(ByteRange bytes)
bool isLoopback() const
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
uint8_t getNthMSByte(size_t byteIndex) const
requires E e noexcept(noexcept(s.error(std::move(e))))
bool prefix(Cursor &c, uint32_t expected)
static Expected< IPAddressV4, IPAddressFormatError > tryFromString(StringPiece str) noexcept
Definition: IPAddressV4.cpp:96
void split(const Delim &delimiter, const String &input, std::vector< OutputType > &out, bool ignoreEmpty)
Definition: String-inl.h:382
ByteArray4 toByteArray() const
Definition: IPAddressV4.h:227
static Expected< IPAddressV4, IPAddressFormatError > tryFromBinary(ByteRange bytes) noexcept
union folly::IPAddressV4::AddressStorage addr_
bool isPrivate() const
bool inSubnetWithMask(const IPAddressV4 &subnet, const ByteArray4 mask) const
static IPAddressV4 fromLong(uint32_t src)
Definition: IPAddressV4.cpp:52
static T big(T x)
Definition: Bits.h:259
constexpr Unexpected< typename std::decay< Error >::type > makeUnexpected(Error &&)
Definition: Expected.h:785
size_t hash() const
Definition: IPAddressV4.h:165
static const ByteArray4 fetchMask(size_t numBits)
std::array< uint8_t, 16 > ByteArray16
Definition: IPAddressV6.h:50
IPAddressV6 getIPv6For6To4() const
size_t hash_value(const IPAddress &addr)
Definition: IPAddress.cpp:34
uint32_t toLong() const
Definition: IPAddressV4.h:142
const unsigned char * bytes() const
Definition: IPAddressV4.h:280
std::pair< IPAddressV4, uint8_t > CIDRNetworkV4
Definition: IPAddressV4.h:36
constexpr Unit unit
Definition: Unit.h:45
static std::pair< std::array< uint8_t, N >, uint8_t > longestCommonPrefix(const std::array< uint8_t, N > &one, uint8_t oneMask, const std::array< uint8_t, N > &two, uint8_t twoMask)
void toFullyQualifiedAppend(std::string &out) const
void toAppend(char value, Tgt *result)
Definition: Conv.h:406
Expected< Unit, IPAddressFormatError > trySetFromBinary(ByteRange bytes) noexcept
std::string toJson() const
uint32_t toLongHBO() const
Definition: IPAddressV4.h:148
const char * string
Definition: Conv.cpp:212
static IPAddressV4 fromLongHBO(uint32_t src)
Definition: IPAddressV4.cpp:58
static bool validate(StringPiece ip) noexcept
Definition: IPAddressV4.cpp:47
void join(const Delim &delimiter, Iterator begin, Iterator end, String &output)
Definition: String-inl.h:498
bool inSubnet(StringPiece cidrNetwork) const
std::string fastIpv4ToString(const in_addr &inAddr)
std::string str() const
basic_fbstring & append(const basic_fbstring &str)
Definition: FBString.h:1953
void fastIpv4AppendToString(const in_addr &inAddr, std::string &out)
std::array< uint8_t, 4 > ByteArray4
Definition: IPAddressV4.h:46
static constexpr size_t bitCount()
Definition: IPAddressV4.h:156
Range< const char * > StringPiece
static IPAddressV4 fromInverseArpaName(const std::string &arpaname)
std::string familyNameStr(sa_family_t family)
Definition: IPAddress.h:30
bool isMulticast() const
ThreadPoolListHook * addr
IPAddressV6 createIPv6() const
std::ostream & operator<<(std::ostream &out, dynamic const &d)
Definition: dynamic-inl.h:1158