Line data Source code
1 : // Network Address -- classes functions to ease handling IP addresses
2 : // Copyright (C) 2012-2017 Made to Order Software Corp.
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 : #pragma once
18 :
19 : #include "libexcept/exception.h"
20 :
21 : #include <arpa/inet.h>
22 :
23 : #include <memory>
24 : #include <cstring>
25 :
26 : namespace addr
27 : {
28 :
29 :
30 1929 : class addr_invalid_argument_exception : public libexcept::exception_t
31 : {
32 : public:
33 338 : addr_invalid_argument_exception(char const * what_msg) : exception_t(what_msg) {}
34 305 : addr_invalid_argument_exception(std::string const & what_msg) : exception_t(what_msg) {}
35 : };
36 :
37 51 : class addr_invalid_state_exception : public libexcept::exception_t
38 : {
39 : public:
40 17 : addr_invalid_state_exception(char const * what_msg) : exception_t(what_msg) {}
41 : addr_invalid_state_exception(std::string const & what_msg) : exception_t(what_msg) {}
42 : };
43 :
44 : class addr_invalid_structure_exception : public libexcept::logic_exception_t
45 : {
46 : public:
47 : addr_invalid_structure_exception(char const * what_msg) : logic_exception_t(what_msg) {}
48 : addr_invalid_structure_exception(std::string const & what_msg) : logic_exception_t(what_msg) {}
49 : };
50 :
51 : class addr_invalid_parameter_exception : public libexcept::logic_exception_t
52 : {
53 : public:
54 : addr_invalid_parameter_exception(char const * what_msg) : logic_exception_t(what_msg) {}
55 : addr_invalid_parameter_exception(std::string const & what_msg) : logic_exception_t(what_msg) {}
56 : };
57 :
58 :
59 :
60 395641 : constexpr struct sockaddr_in6 init_in6()
61 : {
62 395641 : struct sockaddr_in6 in6 = sockaddr_in6();
63 395641 : in6.sin6_family = AF_INET6;
64 395641 : return in6;
65 : }
66 :
67 :
68 1318841 : class addr
69 : {
70 : public:
71 : enum class network_type_t
72 : {
73 : NETWORK_TYPE_UNDEFINED,
74 : NETWORK_TYPE_PRIVATE,
75 : NETWORK_TYPE_CARRIER,
76 : NETWORK_TYPE_LINK_LOCAL,
77 : NETWORK_TYPE_MULTICAST,
78 : NETWORK_TYPE_LOOPBACK,
79 : NETWORK_TYPE_ANY,
80 : NETWORK_TYPE_UNKNOWN,
81 : NETWORK_TYPE_PUBLIC = NETWORK_TYPE_UNKNOWN // we currently do not distinguish public and unknown
82 : };
83 :
84 : enum class computer_interface_address_t
85 : {
86 : COMPUTER_INTERFACE_ADDRESS_ERROR = -1,
87 : COMPUTER_INTERFACE_ADDRESS_FALSE,
88 : COMPUTER_INTERFACE_ADDRESS_TRUE
89 : };
90 :
91 : enum class string_ip_t
92 : {
93 : STRING_IP_ONLY,
94 : STRING_IP_BRACKETS, // IPv6 only
95 : STRING_IP_PORT,
96 : STRING_IP_MASK,
97 : STRING_IP_BRACKETS_MASK, // IPv6 only
98 : STRING_IP_ALL
99 : };
100 :
101 : typedef std::shared_ptr<addr> pointer_t;
102 : typedef std::vector<addr> vector_t;
103 :
104 : addr();
105 : addr(struct sockaddr_in const & in);
106 : addr(struct sockaddr_in6 const & in6);
107 :
108 : static vector_t get_local_addresses();
109 :
110 : void set_from_socket(int s);
111 : void set_ipv4(struct sockaddr_in const & in);
112 : void set_ipv6(struct sockaddr_in6 const & in6);
113 : void set_port(int port);
114 : void set_protocol(char const * protocol);
115 : void set_protocol(int protocol);
116 : void set_mask(uint8_t const * mask);
117 : void apply_mask();
118 :
119 : bool is_ipv4() const;
120 : void get_ipv4(struct sockaddr_in & in) const;
121 : void get_ipv6(struct sockaddr_in6 & in6) const;
122 : std::string to_ipv4_string(string_ip_t mode) const;
123 : std::string to_ipv6_string(string_ip_t mode) const;
124 : std::string to_ipv4or6_string(string_ip_t mode) const;
125 :
126 : network_type_t get_network_type() const;
127 : std::string get_network_type_string() const;
128 : computer_interface_address_t is_computer_interface_address() const;
129 :
130 : std::string get_iface_name() const;
131 : std::string get_name() const;
132 : std::string get_service() const;
133 : int get_port() const;
134 : int get_protocol() const;
135 : void get_mask(uint8_t * mask);
136 :
137 : bool match(addr const & ip) const;
138 : bool operator == (addr const & rhs) const;
139 : bool operator != (addr const & rhs) const;
140 : bool operator < (addr const & rhs) const;
141 : bool operator <= (addr const & rhs) const;
142 : bool operator > (addr const & rhs) const;
143 : bool operator >= (addr const & rhs) const;
144 :
145 : private:
146 : void address_changed();
147 :
148 : // always keep address in an IPv6 structure
149 : //
150 : struct sockaddr_in6 f_address = init_in6();
151 : uint8_t f_mask[16] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
152 : std::string f_iface_name;
153 : int f_protocol = IPPROTO_TCP;
154 : mutable network_type_t f_private_network_defined = network_type_t::NETWORK_TYPE_UNDEFINED;
155 : };
156 :
157 :
158 527480 : class addr_range
159 : {
160 : public:
161 : typedef std::shared_ptr<addr_range> pointer_t;
162 : typedef std::vector<addr_range> vector_t;
163 :
164 : bool has_from() const;
165 : bool has_to() const;
166 : bool is_range() const;
167 : bool is_empty() const;
168 : bool is_in(addr const & rhs) const;
169 :
170 : void set_from(addr const & from);
171 : addr & get_from();
172 : addr const & get_from() const;
173 : void set_to(addr const & to);
174 : addr & get_to();
175 : addr const & get_to() const;
176 :
177 : addr_range intersection(addr_range const & rhs) const;
178 :
179 : private:
180 : bool f_has_from = false;
181 : bool f_has_to = false;
182 : addr f_from;
183 : addr f_to;
184 : };
185 :
186 :
187 263614 : class addr_parser
188 : {
189 : public:
190 : enum class flag_t
191 : {
192 : ADDRESS, // address (IP)
193 : REQUIRED_ADDRESS, // address cannot be empty
194 : PORT, // port
195 : REQUIRED_PORT, // port cannot be empty
196 : MASK, // mask
197 : MULTI_ADDRESSES_COMMAS, // IP:port/mask,IP:port/mask,...
198 : MULTI_ADDRESSES_SPACES, // IP:port/mask IP:port/mask ...
199 : MULTI_ADDRESSES_COMMAS_AND_SPACES, // IP:port/mask, IP:port/mask, ...
200 :
201 : // the following are not yet implemented
202 : MULTI_PORTS_SEMICOLONS, // port1;port2;...
203 : MULTI_PORTS_COMMAS, // port1,port2,...
204 : PORT_RANGE, // port1-port2
205 : ADDRESS_RANGE, // IP-IP
206 :
207 : FLAG_max
208 : };
209 :
210 : void set_default_address(std::string const & addr);
211 : std::string const & get_default_address() const;
212 : void set_default_port(int const port);
213 : int get_default_port() const;
214 : void set_default_mask(std::string const & mask);
215 : std::string const & get_default_mask() const;
216 : void set_protocol(std::string const & protocol);
217 : void set_protocol(int const protocol);
218 : void clear_protocol();
219 : int get_protocol() const;
220 :
221 : void set_allow(flag_t const flag, bool const allow);
222 : bool get_allow(flag_t const flag) const;
223 :
224 : bool has_errors() const;
225 : void emit_error(std::string const & msg);
226 : std::string const & error_messages() const;
227 : int error_count() const;
228 : void clear_errors();
229 : addr_range::vector_t parse(std::string const & in);
230 :
231 : private:
232 : void parse_cidr(std::string const & in, addr_range::vector_t & result);
233 : void parse_address(std::string const & in, addr_range::vector_t & result);
234 : void parse_address4(std::string const & in, addr_range::vector_t & result);
235 : void parse_address6(std::string const & in, addr_range::vector_t & result);
236 : void parse_address_port(std::string const & address, std::string const & port_str, addr_range::vector_t & result);
237 : void parse_mask(std::string const & mask, addr & cidr);
238 :
239 : bool f_flags[static_cast<int>(flag_t::FLAG_max)] = { true, false, true, false, false, false, false, false, false, false, false, false };
240 : std::string f_default_address;
241 : std::string f_default_mask;
242 : int f_protocol = -1;
243 : int f_default_port = -1;
244 : std::string f_error;
245 : int f_error_count = 0;
246 : };
247 :
248 :
249 :
250 : } // addr namespace
251 :
252 :
253 : inline bool operator == (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
254 : {
255 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) == 0;
256 : }
257 :
258 :
259 : inline bool operator != (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
260 : {
261 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) != 0;
262 : }
263 :
264 :
265 : inline bool operator < (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
266 : {
267 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) < 0;
268 : }
269 :
270 :
271 : inline bool operator <= (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
272 : {
273 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) <= 0;
274 : }
275 :
276 :
277 : inline bool operator > (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
278 : {
279 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) > 0;
280 : }
281 :
282 :
283 : inline bool operator >= (struct sockaddr_in6 const & a, struct sockaddr_in6 const & b)
284 : {
285 : return memcmp(&a, &b, sizeof(struct sockaddr_in6)) >= 0;
286 : }
287 :
288 :
289 35 : inline bool operator == (in6_addr const & a, in6_addr const & b)
290 : {
291 35 : return memcmp(&a, &b, sizeof(in6_addr)) == 0;
292 : }
293 :
294 :
295 9 : inline bool operator != (in6_addr const & a, in6_addr const & b)
296 : {
297 9 : return memcmp(&a, &b, sizeof(in6_addr)) != 0;
298 : }
299 :
300 :
301 7 : inline bool operator < (in6_addr const & a, in6_addr const & b)
302 : {
303 7 : return memcmp(&a, &b, sizeof(in6_addr)) < 0;
304 : }
305 :
306 :
307 668 : inline bool operator <= (in6_addr const & a, in6_addr const & b)
308 : {
309 668 : return memcmp(&a, &b, sizeof(in6_addr)) <= 0;
310 : }
311 :
312 :
313 15 : inline bool operator > (in6_addr const & a, in6_addr const & b)
314 : {
315 15 : return memcmp(&a, &b, sizeof(in6_addr)) > 0;
316 : }
317 :
318 :
319 281 : inline bool operator >= (in6_addr const & a, in6_addr const & b)
320 : {
321 281 : return memcmp(&a, &b, sizeof(in6_addr)) >= 0;
322 : }
323 :
324 :
325 : // vim: ts=4 sw=4 et
|