Botan 3.13.0
Crypto and TLS for C&
ipv4_address.h
Go to the documentation of this file.
1/*
2* (C) 2026 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#ifndef BOTAN_IPV4_ADDRESS_H_
8#define BOTAN_IPV4_ADDRESS_H_
9
10#include <botan/types.h>
11#include <array>
12#include <optional>
13#include <span>
14#include <string>
15#include <string_view>
16#include <vector>
17
18namespace Botan {
19
20/**
21* IPv4 Address
22*/
23class BOTAN_PUBLIC_API(3, 12) IPv4Address final {
24 public:
25 /**
26 * Create an address from its integer value
27 * @param ip the address as a 32-bit big-endian integer
28 */
29 explicit IPv4Address(uint32_t ip) : m_ip(ip) {}
30
31 /**
32 * Convert a dotted-decimal string to an IPv4Address
33 * @param str the address to parse
34 * @return the parsed address, or nullopt if str is not a valid IPv4 address
35 */
36 static std::optional<IPv4Address> from_string(std::string_view str);
37
38 /**
39 * Return an address with the leading @p bits set to one and the remainder
40 * zero. Throws Invalid_Argument if @p bits > 32.
41 */
42 static IPv4Address netmask(size_t bits);
43
44 /**
45 * Return the netmask matching a single host
46 * @return an address with all 32 bits set
47 */
48 static IPv4Address host_mask() { return netmask(32); }
49
50 /**
51 * Bitwise AND of two addresses, typically used to apply a netmask
52 * @param other the address to AND with
53 * @return the bitwise AND of the two addresses
54 */
55 IPv4Address operator&(const IPv4Address& other) const { return IPv4Address(m_ip & other.m_ip); }
56
57 /**
58 * Order two addresses numerically
59 * @return the ordering of this address relative to the other
60 */
61 auto operator<=>(const IPv4Address&) const = default;
62
63 /// The address as a 32-bit big-endian integer
64 BOTAN_DEPRECATED("Use IPv4Address::address") uint32_t value() const { return m_ip; }
65
66 /// The address as a 32-bit big-endian integer
67 uint32_t address() const { return m_ip; }
68
69 /// The address as four bytes, network-byte-order.
70 std::array<uint8_t, 4> to_bytes() const;
71
72 /// Dotted-decimal form, e.g. "10.0.0.1".
73 std::string to_string() const;
74
75 /**
76 * If this value is a netmask consisting of a run of one bits followed by
77 * a run of zero bits, return the number of one bits.
78 *
79 * Otherwise return nullopt.
80 */
81 std::optional<size_t> prefix_length() const;
82
83 private:
84 uint32_t m_ip;
85};
86
87/**
88* An IPv4 subnet in CIDR form: a network address paired with a prefix length
89*/
90class BOTAN_PUBLIC_API(3, 12) IPv4Subnet final {
91 public:
92 /**
93 * Construct from a network address and a prefix length in [0, 32].
94 * Host bits of @p address are cleared.
95 *
96 * Throws Invalid_Argument if @p prefix_length > 32.
97 */
99
100 /**
101 * Construct from a network address and a netmask (4 bytes each)
102 * Returns nullopt if netmask is not a valid contiguous CIDR prefix.
103 */
104 static std::optional<IPv4Subnet> from_address_and_mask(std::span<const uint8_t, 8> addr_and_mask);
105
106 /**
107 * Construct from a network address and a netmask (4 bytes each)
108 * Returns nullopt if netmask is not a valid contiguous CIDR prefix.
109 */
110 static std::optional<IPv4Subnet> from_address_and_mask(uint32_t addr, uint32_t mask);
111
112 /**
113 * Parse CIDR-style form "10.0.0.0/8".
114 *
115 * The "/N" suffix is required: bare addresses should be parsed via
116 * IPv4Address::from_string and wrapped with IPv4Subnet::host if needed.
117 * The input must already be canonical, such that from_string and
118 * to_string are exact inverses: the prefix length is canonical decimal
119 * ("/8", not "/08") and the host bits are clear ("10.0.0.0/8", not
120 * "10.1.2.3/8").
121 *
122 * Returns nullopt on parse failure or out-of-range prefix length.
123 */
124 static std::optional<IPv4Subnet> from_string(std::string_view str);
125
126 /**
127 * A single-host subnet (prefix length 32) covering exactly @p address.
128 */
130
131 /// The network address (host bits already zeroed).
132 const IPv4Address& address() const { return m_address; }
133
134 /// Prefix length in [0, 32].
135 size_t prefix_length() const { return m_prefix_length; }
136
137 /// True iff prefix_length() == 32.
138 bool is_host() const { return m_prefix_length == 32; }
139
140 /// True iff @p ip falls within this subnet.
141 bool contains(const IPv4Address& ip) const;
142
143 /// CIDR-style "10.0.0.0/8".
144 std::string to_string() const;
145
146 /**
147 * Bytes for use in a DER-encoded GeneralName iPAddress field.
148 *
149 * If this is an address (is_host returns true) the output is 4 bytes (the address in network order)
150 * Otherwise it is a subnet and the output is 8 bytes (address || netmask)
151 */
152 std::vector<uint8_t> serialize() const;
153
154 friend bool operator==(const IPv4Subnet&, const IPv4Subnet&) = default;
155
156 private:
157 IPv4Address m_address;
158 uint8_t m_prefix_length;
159};
160
161} // namespace Botan
162
163#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
IPv4Address operator&(const IPv4Address &other) const
auto operator<=>(const IPv4Address &) const =default
uint32_t address() const
The address as a 32-bit big-endian integer.
uint32_t value() const
The address as a 32-bit big-endian integer.
static IPv4Address host_mask()
IPv4Address(uint32_t ip)
static IPv4Address netmask(size_t bits)
static std::optional< IPv4Subnet > from_address_and_mask(std::span< const uint8_t, 8 > addr_and_mask)
bool is_host() const
True iff prefix_length() == 32.
friend bool operator==(const IPv4Subnet &, const IPv4Subnet &)=default
IPv4Subnet(IPv4Address address, size_t prefix_length)
size_t prefix_length() const
Prefix length in [0, 32].
static IPv4Subnet host(IPv4Address address)
static std::optional< IPv4Subnet > from_string(std::string_view str)
const IPv4Address & address() const
The network address (host bits already zeroed).
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition exceptn.cpp:13