OpenVPN 3 Core Library
Loading...
Searching...
No Matches
addrpair.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12#ifndef OPENVPN_ADDR_ADDRPAIR_H
13#define OPENVPN_ADDR_ADDRPAIR_H
14
15#include <sstream>
16
20#include <openvpn/addr/ip.hpp>
21
22namespace openvpn::IP {
23
24// AddrMaskPair is basically an object that combines an IP address (v4 or v6)
25// with a netmask or prefix length.
27{
28 public:
29 OPENVPN_EXCEPTION(addr_pair_mask_parse_error);
30
32 {
33 public:
34 OPENVPN_SIMPLE_EXCEPTION(addr_pair_string_error);
35
37 : size_(0)
38 {
39 }
40
41 explicit StringPair(const std::string &s1)
42 : size_(1)
43 {
44 data[0] = s1;
45 }
46
47 explicit StringPair(const std::string &s1, const std::string &s2)
48 : size_(2)
49 {
50 data[0] = s1;
51 data[1] = s2;
52 }
53
54 void push_back(const std::string &s)
55 {
56 if (size_ < 2)
57 data[size_++] = s;
58 else
59 throw addr_pair_string_error();
60 }
61
62 const std::string &operator[](const size_t i) const
63 {
64 if (i >= 2)
65 throw addr_pair_string_error();
66 return data[i];
67 }
68
69 std::string &operator[](const size_t i)
70 {
71 if (i >= 2)
72 throw addr_pair_string_error();
73 return data[i];
74 }
75
76 size_t size() const
77 {
78 return size_;
79 }
80
81 std::string render() const
82 {
83 switch (size_)
84 {
85 case 1:
86 return data[0];
87 case 2:
88 return data[0] + "/" + data[1];
89 default:
90 return "";
91 }
92 }
93
94 private:
95 std::string data[2];
96 unsigned int size_;
97 };
98
99 static AddrMaskPair from_string(const std::string &s1, const std::string &s2, const char *title = nullptr)
100 {
101 try
102 {
103 if (s2.empty())
104 {
105 const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s1, '/');
106 return from_string_impl(pair, title);
107 }
108 else
109 {
110 const StringPair pair(s1, s2);
111 return from_string_impl(pair, title);
112 }
113 }
114 catch (const std::exception &e)
115 {
116 const StringPair pair(s1, s2);
117 error(e, pair.render(), title);
118 }
119 return AddrMaskPair(); // NOTREACHED
120 }
121
122 static AddrMaskPair from_string(const std::string &s, const char *title = nullptr)
123 {
124 try
125 {
126 const StringPair pair = Split::by_char<StringPair, NullLex, Split::NullLimit>(s, '/');
127 return from_string_impl(pair, title);
128 }
129 catch (const std::exception &e)
130 {
131 error(e, s, title);
132 }
133 return AddrMaskPair(); // NOTREACHED
134 }
135
136 static AddrMaskPair from_string(const StringPair &pair, const char *title = nullptr)
137 {
138 try
139 {
140 return from_string_impl(pair, title);
141 }
142 catch (const std::exception &e)
143 {
144 error(e, pair.render(), title);
145 }
146 return AddrMaskPair(); // NOTREACHED
147 }
148
149 std::string to_string(const bool netmask_form = false) const
150 {
151 std::ostringstream os;
152 if (netmask_form)
153 os << addr.to_string() << '/' << netmask.to_string();
154 else
155 os << addr.to_string() << '/' << netmask.prefix_len();
156 return os.str();
157 }
158
159 bool is_canonical() const
160 {
161 return (addr & netmask) == addr;
162 }
163
165 {
166 const Addr::Version v1 = addr.version();
167 const Addr::Version v2 = netmask.version();
168 if (v1 == v2)
169 return v1;
170 else
171 return Addr::UNSPEC;
172 }
173
176
177 private:
178 static void error(const std::exception &e, const std::string &s, const char *title)
179 {
180 if (!title)
181 title = "";
182 OPENVPN_THROW(addr_pair_mask_parse_error, "AddrMaskPair parse error '" << title << "': " << s << " : " << e.what());
183 }
184
185 static AddrMaskPair from_string_impl(const StringPair &pair, const char *title = nullptr)
186 {
188 if (pair.size() == 1 || pair.size() == 2)
189 {
190 ret.addr = Addr::from_string(pair[0], title);
191 if (pair.size() == 2 && !pair[1].empty())
192 {
193 if (is_number(pair[1].c_str()))
194 ret.netmask = Addr::netmask_from_prefix_len(ret.addr.version(),
195 parse_number_throw<unsigned int>(pair[1], "prefix length"));
196 else
197 ret.netmask = Addr::from_string(pair[1]);
198 ret.netmask.prefix_len(); // verify that netmask is ok
199 }
200 else
201 ret.netmask = Addr::from_zero_complement(ret.addr.version());
202 ret.addr.verify_version_consistency(ret.netmask);
203 }
204 else
205 throw addr_pair_mask_parse_error("only one or two address terms allowed");
206 return ret;
207 }
208};
209OPENVPN_OSTREAM(AddrMaskPair, to_string)
210} // namespace openvpn::IP
211
212#endif
std::string & operator[](const size_t i)
Definition addrpair.hpp:69
void push_back(const std::string &s)
Definition addrpair.hpp:54
OPENVPN_SIMPLE_EXCEPTION(addr_pair_string_error)
StringPair(const std::string &s1)
Definition addrpair.hpp:41
const std::string & operator[](const size_t i) const
Definition addrpair.hpp:62
StringPair(const std::string &s1, const std::string &s2)
Definition addrpair.hpp:47
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:105
Version version() const
Definition ip.hpp:895
std::string to_string() const
Definition ip.hpp:528
static Addr netmask_from_prefix_len(Version v, const unsigned int prefix_len)
Definition ip.hpp:502
unsigned int prefix_len() const
Definition ip.hpp:968
static Addr from_zero_complement(const Version v)
Definition ip.hpp:478
#define OPENVPN_THROW(exc, stuff)
std::string to_string(T value)
Definition to_string.hpp:33
bool is_number(const char *str)
Definition number.hpp:126
#define OPENVPN_OSTREAM(TYPE, METH)
Definition ostream.hpp:21
static AddrMaskPair from_string(const StringPair &pair, const char *title=nullptr)
Definition addrpair.hpp:136
static void error(const std::exception &e, const std::string &s, const char *title)
Definition addrpair.hpp:178
std::string to_string(const bool netmask_form=false) const
Definition addrpair.hpp:149
OPENVPN_EXCEPTION(addr_pair_mask_parse_error)
static AddrMaskPair from_string(const std::string &s1, const std::string &s2, const char *title=nullptr)
Definition addrpair.hpp:99
static AddrMaskPair from_string_impl(const StringPair &pair, const char *title=nullptr)
Definition addrpair.hpp:185
static AddrMaskPair from_string(const std::string &s, const char *title=nullptr)
Definition addrpair.hpp:122
Addr::Version version() const
Definition addrpair.hpp:164
std::string ret