proxygen
IPAddress.h
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 #pragma once
18 
19 #include <functional>
20 #include <iosfwd>
21 #include <memory>
22 #include <string>
23 #include <utility> // std::pair
24 
26 #include <folly/IPAddressV4.h>
27 #include <folly/IPAddressV6.h>
28 #include <folly/Range.h>
29 #include <folly/detail/IPAddress.h>
30 
31 namespace folly {
32 
33 class IPAddress;
34 
38 typedef std::pair<IPAddress, uint8_t> CIDRNetwork;
39 
67 class IPAddress {
68  private:
69  template <typename F>
70  auto pick(F f) const {
71  return isV4() ? f(asV4()) : f(asV6());
72  }
73 
74  public:
75  // returns true iff the input string can be parsed as an ip-address
76  static bool validate(StringPiece ip) noexcept;
77 
78  // return the V4 representation of the address, converting it from V6 to V4 if
79  // needed. Note that this will throw an IPAddressFormatException if the V6
80  // address is not IPv4Mapped.
81  static IPAddressV4 createIPv4(const IPAddress& addr);
82 
83  // return the V6 representation of the address, converting it from V4 to V6 if
84  // needed.
85  static IPAddressV6 createIPv6(const IPAddress& addr);
86 
97  static Expected<CIDRNetwork, CIDRNetworkError> tryCreateNetwork(
98  StringPiece ipSlashCidr,
99  int defaultCidr = -1,
100  bool mask = true);
101 
110  static CIDRNetwork createNetwork(
111  StringPiece ipSlashCidr,
112  int defaultCidr = -1,
113  bool mask = true);
114 
121  static std::string networkToString(const CIDRNetwork& network);
122 
128  static IPAddress fromBinary(ByteRange bytes);
129 
134  static Expected<IPAddress, IPAddressFormatError> tryFromBinary(
135  ByteRange bytes) noexcept;
136 
141  static Expected<IPAddress, IPAddressFormatError> tryFromString(
142  StringPiece str) noexcept;
143 
148  static IPAddress fromLong(uint32_t src);
149  // Same as above, but host byte order
150  static IPAddress fromLongHBO(uint32_t src);
151 
152  // Given 2 IPAddress,mask pairs extract the longest common IPAddress,
153  // mask pair
154  static CIDRNetwork longestCommonPrefix(
155  const CIDRNetwork& one,
156  const CIDRNetwork& two);
157 
161  IPAddress();
162 
173  explicit IPAddress(StringPiece ip);
174 
179  explicit IPAddress(const sockaddr* addr);
180 
181  // Create an IPAddress from a V4 address
182  /* implicit */ IPAddress(const IPAddressV4 ipV4Addr) noexcept;
183  /* implicit */ IPAddress(const in_addr addr) noexcept;
184 
185  // Create an IPAddress from a V6 address
186  /* implicit */ IPAddress(const IPAddressV6& ipV6Addr) noexcept;
187  /* implicit */ IPAddress(const in6_addr& addr) noexcept;
188 
189  // Assign from V4 address
190  IPAddress& operator=(const IPAddressV4& ipV4Addr) noexcept;
191 
192  // Assign from V6 address
193  IPAddress& operator=(const IPAddressV6& ipV6Addr) noexcept;
194 
202  const IPAddressV4& asV4() const {
203  if (UNLIKELY(!isV4())) {
204  asV4Throw();
205  }
206  return addr_.ipV4Addr;
207  }
208 
213  const IPAddressV6& asV6() const {
214  if (UNLIKELY(!isV6())) {
215  asV6Throw();
216  }
217  return addr_.ipV6Addr;
218  }
219 
220  // Return sa_family_t of IPAddress
221  sa_family_t family() const {
222  return family_;
223  }
224 
225  // Populate sockaddr_storage with an appropriate value
226  int toSockaddrStorage(sockaddr_storage* dest, uint16_t port = 0) const {
227  if (dest == nullptr) {
228  throw IPAddressFormatException("dest must not be null");
229  }
230  memset(dest, 0, sizeof(sockaddr_storage));
231  dest->ss_family = family();
232 
233  if (isV4()) {
234  sockaddr_in* sin = reinterpret_cast<sockaddr_in*>(dest);
235  sin->sin_addr = asV4().toAddr();
236  sin->sin_port = port;
237 #if defined(__APPLE__)
238  sin->sin_len = sizeof(*sin);
239 #endif
240  return sizeof(*sin);
241  } else if (isV6()) {
242  sockaddr_in6* sin = reinterpret_cast<sockaddr_in6*>(dest);
243  sin->sin6_addr = asV6().toAddr();
244  sin->sin6_port = port;
245  sin->sin6_scope_id = asV6().getScopeId();
246 #if defined(__APPLE__)
247  sin->sin6_len = sizeof(*sin);
248 #endif
249  return sizeof(*sin);
250  } else {
251  throw InvalidAddressFamilyException(family());
252  }
253  }
254 
269  bool inSubnet(StringPiece ipSlashCidr) const;
270 
277  bool inSubnet(const IPAddress& subnet, uint8_t cidr) const;
278 
287  bool inSubnetWithMask(const IPAddress& subnet, ByteRange mask) const;
288 
289  // @return true if address is a v4 mapped address
290  bool isIPv4Mapped() const {
291  return isV6() && asV6().isIPv4Mapped();
292  }
293 
294  // @return true if address is uninitialized
295  bool empty() const {
296  return family_ == AF_UNSPEC;
297  }
298 
299  // @return true if address is initialized
300  explicit operator bool() const {
301  return !empty();
302  }
303 
304  // @return true if this is an IPAddressV4 instance
305  bool isV4() const {
306  return family_ == AF_INET;
307  }
308 
309  // @return true if this is an IPAddressV6 instance
310  bool isV6() const {
311  return family_ == AF_INET6;
312  }
313 
314  // @return true if this address is all zeros
315  bool isZero() const {
316  return pick([&](auto& _) { return _.isZero(); });
317  }
318 
319  // Number of bits in the address representation.
320  size_t bitCount() const {
321  return pick([&](auto& _) { return _.bitCount(); });
322  }
323  // Number of bytes in the address representation.
324  size_t byteCount() const {
325  return bitCount() / 8;
326  }
327  // get nth most significant bit - 0 indexed
328  bool getNthMSBit(size_t bitIndex) const {
329  return detail::getNthMSBitImpl(*this, bitIndex, family());
330  }
331  // get nth most significant byte - 0 indexed
332  uint8_t getNthMSByte(size_t byteIndex) const;
333  // get nth bit - 0 indexed
334  bool getNthLSBit(size_t bitIndex) const {
335  return getNthMSBit(bitCount() - bitIndex - 1);
336  }
337  // get nth byte - 0 indexed
338  uint8_t getNthLSByte(size_t byteIndex) const {
339  return getNthMSByte(byteCount() - byteIndex - 1);
340  }
348  std::string toJson() const {
349  return pick([&](auto& _) { return _.toJson(); });
350  }
351 
352  // Hash of address
353  std::size_t hash() const {
354  return pick([&](auto& _) { return _.hash(); });
355  }
356 
357  // Return true if the address qualifies as localhost.
358  bool isLoopback() const {
359  return pick([&](auto& _) { return _.isLoopback(); });
360  }
361 
362  // Return true if the address qualifies as link local
363  bool isLinkLocal() const {
364  return pick([&](auto& _) { return _.isLinkLocal(); });
365  }
366 
367  // Return true if the address qualifies as broadcast.
368  bool isLinkLocalBroadcast() const {
369  return pick([&](auto& _) { return _.isLinkLocalBroadcast(); });
370  }
371 
378  bool isNonroutable() const {
379  return pick([&](auto& _) { return _.isNonroutable(); });
380  }
381 
386  bool isPrivate() const {
387  return pick([&](auto& _) { return _.isPrivate(); });
388  }
389 
390  // Return true if the address is a multicast address.
391  bool isMulticast() const {
392  return pick([&](auto& _) { return _.isMulticast(); });
393  }
394 
401  IPAddress mask(uint8_t numBits) const {
402  return pick([&](auto& _) { return IPAddress(_.mask(numBits)); });
403  }
404 
410  std::string str() const {
411  return pick([&](auto& _) { return _.str(); });
412  }
413 
419  std::string toFullyQualified() const {
420  return pick([&](auto& _) { return _.toFullyQualified(); });
421  }
422 
424  void toFullyQualifiedAppend(std::string& out) const {
425  return pick([&](auto& _) { return _.toFullyQualifiedAppend(out); });
426  }
427 
428  // Address version (4 or 6)
429  uint8_t version() const {
430  return pick([&](auto& _) { return _.version(); });
431  }
432 
436  const unsigned char* bytes() const {
437  return pick([&](auto& _) { return _.bytes(); });
438  }
439 
440  private:
441  [[noreturn]] void asV4Throw() const;
442  [[noreturn]] void asV6Throw() const;
443 
444  typedef union IPAddressV46 {
445  IPAddressV4 ipV4Addr;
446  IPAddressV6 ipV6Addr;
447  // default constructor
448  IPAddressV46() noexcept {
449  std::memset(this, 0, sizeof(IPAddressV46));
450  }
451  explicit IPAddressV46(const IPAddressV4& addr) noexcept : ipV4Addr(addr) {}
452  explicit IPAddressV46(const IPAddressV6& addr) noexcept : ipV6Addr(addr) {}
453  } IPAddressV46;
454  IPAddressV46 addr_;
455  sa_family_t family_;
456 };
457 
458 // boost::hash uses hash_value() so this allows boost::hash to work
459 // automatically for IPAddress
460 std::size_t hash_value(const IPAddress& addr);
461 std::ostream& operator<<(std::ostream& os, const IPAddress& addr);
462 // Define toAppend() to allow IPAddress to be used with folly::to<string>
463 void toAppend(IPAddress addr, std::string* result);
464 void toAppend(IPAddress addr, fbstring* result);
465 
474 bool operator==(const IPAddress& addr1, const IPAddress& addr2);
475 // Return true if addr1 < addr2
476 bool operator<(const IPAddress& addr1, const IPAddress& addr2);
477 // Derived operators
478 inline bool operator!=(const IPAddress& a, const IPAddress& b) {
479  return !(a == b);
480 }
481 inline bool operator>(const IPAddress& a, const IPAddress& b) {
482  return b < a;
483 }
484 inline bool operator<=(const IPAddress& a, const IPAddress& b) {
485  return !(a > b);
486 }
487 inline bool operator>=(const IPAddress& a, const IPAddress& b) {
488  return !(a < b);
489 }
490 
491 } // namespace folly
492 
493 namespace std {
494 template <>
495 struct hash<folly::IPAddress> {
496  size_t operator()(const folly::IPAddress& addr) const {
497  return addr.hash();
498  }
499 };
500 } // namespace std
bool getNthMSBitImpl(const IPAddrType &ip, size_t bitIndex, sa_family_t family)
Definition: IPAddress.h:49
bool operator>(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1349
auto f
char b
dest
Definition: upload.py:394
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
ProtocolVersion version
bool operator!=(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:766
constexpr auto empty(C const &c) -> decltype(c.empty())
Definition: Access.h:55
size_t hash_value(const IPAddress &addr)
Definition: IPAddress.cpp:34
char a
void toAppend(char value, Tgt *result)
Definition: Conv.h:406
bool operator>=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1358
bool operator==(const Unexpected< Error > &lhs, const Unexpected< Error > &rhs)
Definition: Expected.h:758
const char * string
Definition: Conv.cpp:212
bool operator<=(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1340
Range< const unsigned char * > ByteRange
Definition: Range.h:1163
const internal::AnythingMatcher _
basic_fbstring< char > fbstring
Definition: FBString.h:2904
Range< const char * > StringPiece
#define UNLIKELY(x)
Definition: Likely.h:48
std::string toJson(dynamic const &dyn)
Definition: json.cpp:915
ThreadPoolListHook * addr
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)
Definition: Expected.h:1321
std::ostream & operator<<(std::ostream &out, dynamic const &d)
Definition: dynamic-inl.h:1158