13 #ifndef __STOUT_IP_HPP__ 14 #define __STOUT_IP_HPP__ 18 #include <arpa/inet.h> 21 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) 23 #endif // __linux__ || __APPLE__ || __FreeBSD__ 30 #include <net/if_dl.h> 31 #include <net/if_types.h> 38 #include <netinet/in.h> 39 #include <sys/socket.h> 42 #include <sys/types.h> 50 #include <boost/functional/hash.hpp> 85 static Try<IP> create(
const struct sockaddr_storage& _storage);
92 explicit IP(
const struct in_addr& _storage)
101 explicit IP(
const struct in6_addr& _storage)
110 explicit IP(uint32_t _ip)
148 return storage_.
in_.s_addr == htonl(INADDR_LOOPBACK);
150 return !memcmp(&
storage_.
in6_.s6_addr, &in6addr_loopback.s6_addr, 16);
163 return !memcmp(&
storage_.
in6_.s6_addr, &in6addr_any.s6_addr, 16);
180 return !(*
this == that);
225 const std::string& value,
273 struct in6_addr in6 =
netmask_->in6().get();
275 int prefix = std::accumulate(
276 std::begin(in6.s6_addr),
277 std::end(in6.s6_addr),
279 [](
int acc, uint8_t c) {
280 return acc + bits::countSetBits(c);
299 return !(*
this == that);
326 struct in6_addr in6_;
339 return IPv4(INADDR_LOOPBACK);
344 return IPv4(INADDR_ANY);
351 if (inet_pton(AF_INET, value.c_str(), &
in) == 1) {
355 return Error(
"Failed to parse IPv4: " + value);
383 return IPv6(in6addr_loopback);
388 return IPv6(in6addr_any);
394 if (inet_pton(AF_INET6, value.c_str(), &
in6) == 1) {
398 return Error(
"Failed to parse IPv6: " + value);
422 if (inet_pton(AF_INET, value.c_str(), &storage.
in_) == 1) {
423 return IP(storage.
in_);
426 return Error(
"Failed to parse IPv4: " + value);
429 if (inet_pton(AF_INET6, value.c_str(), &storage.
in6_) == 1) {
433 return Error(
"Failed to parse IPv6: " + value);
446 return Error(
"Failed to parse IP as either IPv4 or IPv6:" + value);
472 const struct sockaddr* addr =
473 reinterpret_cast<const struct sockaddr*
>(&_storage);
481 switch (addr.sa_family) {
483 const struct sockaddr_in& addr4 =
484 reinterpret_cast<const struct sockaddr_in&
>(addr);
486 return IP(addr4.sin_addr);
489 const struct sockaddr_in6& addr6 =
490 reinterpret_cast<const struct sockaddr_in6&
>(addr);
492 return IP(addr6.sin6_addr);
495 return Error(
"Unsupported family type: " +
stringify(addr.sa_family));
507 char buffer[INET_ADDRSTRLEN];
508 struct in_addr in = ip.
in().get();
509 if (inet_ntop(AF_INET, &in, buffer,
sizeof(buffer)) ==
nullptr) {
512 ABORT(
"Failed to get human-readable IPv4 for " +
515 return stream << buffer;
518 char buffer[INET6_ADDRSTRLEN];
519 struct in6_addr in6 = ip.
in6().get();
520 if (inet_ntop(AF_INET6, &in6, buffer,
sizeof(buffer)) ==
nullptr) {
523 return stream << buffer;
536 if (tokens.size() != 2) {
538 "Unexpected number of '/' detected: " +
545 return Error(
"Failed to parse the IP address: " + address.
error());
550 if (prefix.isError()) {
551 return Error(
"Subnet prefix is not a number");
554 return create(address.
get(), prefix.get());
560 return parse(
"127.0.0.1/8", AF_INET).get();
566 return parse(
"::1/128", AF_INET6).get();
576 "The network families of the IP address '" +
581 switch (address.
family()) {
583 uint32_t mask = ntohl(netmask.
in()->s_addr);
584 if (((~mask + 1) & (~mask)) != 0) {
585 return Error(
"IPv4 netmask is not valid");
590 in6_addr mask = netmask.
in6().get();
592 uint8_t testMask = 0xff;
593 for (
int i = 0; i < 16; i++) {
594 if (mask.s6_addr[i] != testMask) {
596 return Error(
"IPv6 netmask is not valid");
599 if (((uint8_t)(~mask.s6_addr[i] + 1) & (~mask.s6_addr[i])) != 0) {
600 return Error(
"IPv6 netmask is not valid");
620 return Error(
"Subnet prefix is negative");
623 switch (address.
family()) {
626 return Error(
"IPv4 subnet prefix is larger than 32");
632 mask = 0xffffffff << (32 -
prefix);
639 return Error(
"IPv6 subnet prefix is larger than 128");
643 memset(&mask, 0,
sizeof(mask));
646 while (prefix >= 8) {
647 mask.s6_addr[i++] = 0xff;
652 uint8_t _mask = 0xff << (8 -
prefix);
653 mask.s6_addr[i] = _mask;
668 std::ostream& stream,
694 boost::hash_combine(seed, htonl(ip.
in()->s_addr));
697 in6_addr
in6 = ip.
in6().get();
698 boost::hash_range(seed, std::begin(in6.s6_addr), std::end(in6.s6_addr));
714 boost::hash_combine(seed, htonl(ip.
in().s_addr));
727 boost::hash_range(seed, std::begin(in6.s6_addr), std::end(in6.s6_addr));
741 #endif // __WINDOWS__ 743 #endif // __STOUT_IP_HPP__ size_t result_type
Definition: ip.hpp:684
int countSetBits(uint32_t value)
Definition: bits.hpp:24
std::string strerror(int errno_)
A thread-safe version of strerror.
Definition: strerror.hpp:30
static IPv6 ANY()
Definition: ip.hpp:386
result_type operator()(const argument_type &ip) const
Definition: ip.hpp:688
IP address() const
Definition: ip.hpp:261
Definition: errorbase.hpp:36
#define ABORT(...)
Definition: abort.hpp:40
bool operator!=(const Network &that) const
Definition: ip.hpp:297
T & get()&
Definition: try.hpp:80
std::ostream & operator<<(std::ostream &stream, const IP &ip)
Definition: ip.hpp:503
in6_addr in6() const
Definition: ip.hpp:404
Try< struct in_addr > in() const
Definition: ip.hpp:124
static IPv4 ANY()
Definition: ip.hpp:342
IPv4(const in_addr &in)
Definition: ip.hpp:358
static Network LOOPBACK_V6()
Definition: ip.hpp:564
static Try< IPv6 > parse(const std::string &value)
Definition: ip.hpp:391
bool isAny() const
Definition: ip.hpp:157
Definition: type_utils.hpp:619
static Try< IP > parse(const std::string &value, int family=AF_UNSPEC)
Definition: ip.hpp:417
size_t operator()(const net::IPv6 &ip)
Definition: ip.hpp:723
Storage storage_
Definition: ip.hpp:330
struct in6_addr in6_
Definition: ip.hpp:326
IPv4(uint32_t ip)
Definition: ip.hpp:361
size_t operator()(const net::IPv4 &ip)
Definition: ip.hpp:711
#define CHECK_SOME(expression)
Definition: check.hpp:50
IP netmask() const
Definition: ip.hpp:263
static IPv4 LOOPBACK()
Definition: ip.hpp:337
bool isLoopback() const
Definition: ip.hpp:144
struct in_addr in_
Definition: ip.hpp:325
in_addr in() const
Definition: ip.hpp:365
bool isSome() const
Definition: try.hpp:77
Network(const IP &_address, const IP &_netmask)
Definition: ip.hpp:303
static Result< Network > fromLinkDevice(const std::string &name, int family)
Definition: ip.hpp:30
static Try< Network > parse(const std::string &value, int family=AF_UNSPEC)
Definition: ip.hpp:532
IP(const struct in6_addr &_storage)
Definition: ip.hpp:101
static Try error(const E &e)
Definition: try.hpp:43
static IPv6 LOOPBACK()
Definition: ip.hpp:381
#define UNREACHABLE()
Definition: unreachable.hpp:22
static Try< Network > create(const IP &address, const IP &netmask)
Definition: ip.hpp:570
IP(const struct in_addr &_storage)
Definition: ip.hpp:92
bool operator==(const IP &that) const
Definition: ip.hpp:169
std::unique_ptr< IP > address_
Definition: ip.hpp:311
bool isError() const
Definition: try.hpp:78
Try< struct in6_addr > in6() const
Definition: ip.hpp:134
bool operator>(const IP &that) const
Definition: ip.hpp:192
Network(const Network &network)
Definition: ip.hpp:247
int family() const
Definition: ip.hpp:118
bool operator==(const Network &that) const
Definition: ip.hpp:291
bool operator<(const IP &that) const
Definition: ip.hpp:183
std::vector< std::string > split(const std::string &s, const std::string &delims, const Option< size_t > &maxTokens=None())
Definition: strings.hpp:184
int family_
Definition: ip.hpp:329
Network & operator=(const Network &network)
Definition: ip.hpp:253
net::IP argument_type
Definition: ip.hpp:686
IPv6(const in6_addr &in6)
Definition: ip.hpp:401
std::string stringify(int flags)
bool operator!=(const IP &that) const
Definition: ip.hpp:178
IP(uint32_t _ip)
Definition: ip.hpp:110
std::unique_ptr< IP > netmask_
Definition: ip.hpp:312
static Try< IPv4 > parse(const std::string &value)
Definition: ip.hpp:347
static Network LOOPBACK_V4()
Definition: ip.hpp:558
static Try< IP > create(const struct sockaddr_storage &_storage)
Definition: ip.hpp:454
constexpr const char * name
Definition: shell.hpp:41
void clear()
Definition: ip.hpp:318
int prefix() const
Definition: ip.hpp:266