blob: 70c862caf0c2821a120d5adb105092109ce8d504 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_BASE_IP_ADDRESS_H_
#define NET_BASE_IP_ADDRESS_H_
#include <sys/socket.h>
#include <optional>
#include <string>
#include <variant>
#include <vector>
#include <base/containers/span.h>
#include "net-base/export.h"
#include "net-base/ipv4_address.h"
#include "net-base/ipv6_address.h"
namespace net_base {
// Represents the family of the IP protocol.
enum class NET_BASE_EXPORT IPFamily {
kIPv4,
kIPv6,
};
// Helper const for iterating through both IP families.
constexpr std::initializer_list<IPFamily> kIPFamilies = {IPFamily::kIPv4,
IPFamily::kIPv6};
// Converts from IPFamily enum to sa_family_t.
NET_BASE_EXPORT sa_family_t ToSAFamily(IPFamily family);
// Converts from sa_family_t to IPFamily enum.
// Returns std::nullopt if the value cannot be converted.
NET_BASE_EXPORT std::optional<IPFamily> FromSAFamily(sa_family_t family);
// Converts from IPFamily enum to std::String.
NET_BASE_EXPORT std::string ToString(IPFamily family);
// Represents an family-agnostic IP address, either a IPv4 or a IPv6 address.
class NET_BASE_EXPORT IPAddress {
public:
// Creates the IPAddress from IPv4 dotted-decimal notation or IPv6 network
// address format.
// If |family| is not nullopt, then only returns the valid IP address with the
// assigned IP family.
static std::optional<IPAddress> CreateFromString(
const std::string& address_string,
std::optional<IPFamily> family = std::nullopt);
static std::optional<IPAddress> CreateFromString(
const char* address_string,
std::optional<IPFamily> family = std::nullopt);
// Creates the IPAddress from the raw byte buffer |bytes|.
// Returns std::nullopt if |bytes|'s size is not the same as
// IPv4Address::kAddressLength or IPv6Address::kAddressLength.
// If |family| is not nullopt, then only returns the valid IP address with the
// assigned IP family.
static std::optional<IPAddress> CreateFromBytes(
base::span<const char> bytes,
std::optional<IPFamily> family = std::nullopt);
static std::optional<IPAddress> CreateFromBytes(
base::span<const uint8_t> bytes,
std::optional<IPFamily> family = std::nullopt);
// Creates the IPAddress by the family. The created address is all-zero.
// (i.e. "0.0.0.0" for IPv4, "::" for IPv6)
explicit constexpr IPAddress(IPFamily family)
: address_(family == IPFamily::kIPv4
? std::variant<IPv4Address, IPv6Address>(IPv4Address())
: std::variant<IPv4Address, IPv6Address>(IPv6Address())) {}
explicit constexpr IPAddress(const IPv4Address& address)
: address_(address) {}
explicit constexpr IPAddress(const IPv6Address& address)
: address_(address) {}
// Returns true if the address is "0.0.0.0" or "::".
bool IsZero() const;
// Compares with |rhs|. The comparation rule follows IPv4Address and
// IPv6Address if the family of |rhs| is the same. Otherwise, the IPv4Address
// is less than IPv6Address.
bool operator==(const IPAddress& rhs) const;
bool operator!=(const IPAddress& rhs) const;
bool operator<(const IPAddress& rhs) const;
// Returns the family of the IP address.
IPFamily GetFamily() const;
// Returns the length in bytes of the address.
size_t GetAddressLength() const;
// Converts to the family-specific classes. Returns std::nullopt if the IP
// family is not the same.
std::optional<IPv4Address> ToIPv4Address() const;
std::optional<IPv6Address> ToIPv6Address() const;
// Returns the address in byte, stored in network order (i.e. big endian).
std::vector<uint8_t> ToBytes() const;
std::string ToByteString() const;
// Returns the address in the IPv4 dotted-decimal notation or IPv6 network
// address format.
std::string ToString() const;
private:
std::variant<IPv4Address, IPv6Address> address_;
};
// Represents an family-agnostic IP CIDR, either a IPv4 or a IPv6 CIDR.
class NET_BASE_EXPORT IPCIDR {
public:
// Returns the maximum prefix length for address family |family|, i.e.,
// the length of this address type in bits.
static int GetMaxPrefixLength(IPFamily family);
// Creates the CIDR from either IPv4 or IPv6 CIDR notation.
// Returns std::nullopt if the string format is invalid.
// If |family| is not nullopt, then only returns the valid result with the
// assigned IP family.
static std::optional<IPCIDR> CreateFromCIDRString(
const std::string& cidr_string,
std::optional<IPFamily> family = std::nullopt);
// Creates the CIDR from the IP address notation string and the prefix length.
// Returns std::nullopt if the string format or the prefix length is invalid.
// If |family| is not nullopt, then only returns the valid result with the
// assigned IP family.
static std::optional<IPCIDR> CreateFromStringAndPrefix(
const std::string& address_string,
int prefix_length,
std::optional<IPFamily> family = std::nullopt);
// Creates the CIDR from the the raw byte buffer |bytes| and the prefix
// length. Returns std::nullopt if the |bytes|'s size or the prefix length is
// invalid. If |family| is not nullopt, then only returns the valid result
// with the assigned IP family.
static std::optional<IPCIDR> CreateFromBytesAndPrefix(
base::span<const char> bytes,
int prefix_length,
std::optional<IPFamily> family = std::nullopt);
static std::optional<IPCIDR> CreateFromBytesAndPrefix(
base::span<const uint8_t> bytes,
int prefix_length,
std::optional<IPFamily> family = std::nullopt);
// Creates the CIDR from the Address and the prefix length. Returns
// std::nullopt if the prefix length is invalid.
static std::optional<IPCIDR> CreateFromAddressAndPrefix(
const IPAddress& address, int prefix_length);
// Creates the IPCIDR by the family. The created CIDR is all-zero.
// (i.e. "0.0.0.0/0" for IPv4, "::/0" for IPv6)
explicit constexpr IPCIDR(IPFamily family)
: cidr_(family == IPFamily::kIPv4
? std::variant<IPv4CIDR, IPv6CIDR>(IPv4CIDR())
: std::variant<IPv4CIDR, IPv6CIDR>(IPv6CIDR())) {}
explicit constexpr IPCIDR(const IPv4CIDR& cidr) : cidr_(cidr) {}
explicit constexpr IPCIDR(const IPv6CIDR& cidr) : cidr_(cidr) {}
explicit constexpr IPCIDR(const IPv4Address& addr) : cidr_(IPv4CIDR(addr)) {}
explicit constexpr IPCIDR(const IPv6Address& addr) : cidr_(IPv6CIDR(addr)) {}
// Getter methods for the internal data.
IPAddress address() const;
int prefix_length() const;
bool operator==(const IPCIDR& rhs) const;
bool operator!=(const IPCIDR& rhs) const;
// Returns the family of the CIDR.
IPFamily GetFamily() const;
// Converts to the family-specific classes. Returns std::nullopt if the IP
// family is not the same.
std::optional<IPv4CIDR> ToIPv4CIDR() const;
std::optional<IPv6CIDR> ToIPv6CIDR() const;
// Creates the Address that has all the high-order of prefix length bits set.
IPAddress ToNetmask() const;
// Returns an CIDR that represents the network-part of the address
// (i.e, the address with all but the prefix bits masked out) and the same
// prefix length as |this|.
IPCIDR GetPrefixCIDR() const;
// Returns the broadcast address for the IP address, by setting all of the
// host-part bits to 1.
IPAddress GetBroadcast() const;
// Returns true is the address |b| is in the same subnet with |*this| CIDR.
bool InSameSubnetWith(const IPAddress& b) const;
// Returns the string in the CIDR notation.
std::string ToString() const;
private:
std::variant<IPv4CIDR, IPv6CIDR> cidr_;
};
NET_BASE_EXPORT std::ostream& operator<<(std::ostream& os, IPFamily family);
NET_BASE_EXPORT std::ostream& operator<<(std::ostream& os,
const IPAddress& address);
NET_BASE_EXPORT std::ostream& operator<<(std::ostream& os, const IPCIDR& cidr);
} // namespace net_base
#endif // NET_BASE_IP_ADDRESS_H_