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