OpenVPN 3 Core Library
Loading...
Searching...
No Matches
ipv4.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_IPV4_H
13#define OPENVPN_ADDR_IPV4_H
14
15#include <cstring> // for std::memcpy, std::memset
16#include <sstream>
17#include <cstdint> // for std::uint32_t
18
19#include <openvpn/io/io.hpp>
20
27
28namespace openvpn::IP {
29class Addr;
30}
31
32// Fundamental classes for representing an IPv4 IP address.
33
34namespace openvpn::IPv4 {
35
36OPENVPN_EXCEPTION(ipv4_exception);
37
38class Addr // NOTE: must be union-legal, so default constructor does not initialize
39{
40 friend class IP::Addr;
41
42 public:
43 enum
44 {
45 SIZE = 32
46 };
47
48 typedef std::uint32_t base_type;
49 typedef std::int32_t signed_base_type;
50
51 static constexpr int ip_version()
52 {
53 return 4;
54 }
55
56 static constexpr bool defined()
57 {
58 return true;
59 }
60
61 static Addr from_addr(const Addr &addr)
62 {
63 return addr;
64 }
65
66 static Addr from_in_addr(const in_addr *in4)
67 {
68 Addr ret;
69 ret.u.addr = ntohl(in4->s_addr);
70 return ret;
71 }
72
73 in_addr to_in_addr() const
74 {
75 in_addr ret;
76 ret.s_addr = htonl(u.addr);
77 return ret;
78 }
79
80 static Addr from_sockaddr(const sockaddr_in *sa)
81 {
82 Addr ret;
83 ret.u.addr = ntohl(sa->sin_addr.s_addr);
84 return ret;
85 }
86
87 sockaddr_in to_sockaddr(const unsigned short port = 0) const
88 {
89 sockaddr_in ret = {};
90 ret.sin_family = AF_INET;
91 ret.sin_port = htons(port);
92 ret.sin_addr.s_addr = htonl(u.addr);
93#if defined(__APPLE__) || defined(__FreeBSD__)
94 /* macOS and FreeBSD have the sin_len member */
95 ret.sin_len = sizeof(struct sockaddr_in);
96#endif
97 return ret;
98 }
99
100 static Addr from_uint32(const base_type addr) // host byte order
101 {
102 Addr ret;
103 ret.u.addr = addr;
104 return ret;
105 }
106
107 std::uint32_t to_uint32() const // host byte order
108 {
109 return u.addr;
110 }
111
112 static Addr from_uint32_net(const base_type addr) // addr in net byte order
113 {
114 Addr ret;
115 ret.u.addr = ntohl(addr);
116 return ret;
117 }
118
119 void to_byte_string(unsigned char *bytestr) const
120 {
121 *reinterpret_cast<base_type *>(bytestr) = ntohl(u.addr);
122 }
123
124 std::uint32_t to_uint32_net() const // return value in net byte order
125 {
126 return htonl(u.addr);
127 }
128
129 static Addr from_ulong(unsigned long ul)
130 {
131 Addr ret;
132 ret.u.addr = static_cast<base_type>(ul);
133 return ret;
134 }
135
136 unsigned long to_ulong() const
137 {
138 return u.addr;
139 }
140
141 static Addr from_long(long ul)
142 {
143 Addr ret;
144 ret.u.addr = static_cast<base_type>(ul);
145 return ret;
146 }
147
148 long to_long() const
149 {
150 return u.addr;
151 }
152
153 static Addr from_bytes(const unsigned char *bytes) // host byte order
154 {
155 Addr ret;
156 std::memcpy(ret.u.bytes, bytes, 4);
157 return ret;
158 }
159
160 static Addr from_bytes_net(const unsigned char *bytes) // network byte order
161 {
162 Addr ret;
163 std::memcpy(ret.u.bytes, bytes, 4);
164 ret.u.addr = ntohl(ret.u.addr);
165 return ret;
166 }
167
169 {
170 Addr ret;
171 ret.zero();
172 return ret;
173 }
174
175 static Addr from_one()
176 {
177 Addr ret;
178 ret.one();
179 return ret;
180 }
181
183 {
184 Addr ret;
186 return ret;
187 }
188
189 static Addr netmask_from_prefix_len(const unsigned int prefix_len)
190 {
191 Addr ret;
193 return ret;
194 }
195
197 {
198 const int lb = find_last_set(u.addr - 1);
199 return netmask_from_prefix_len(SIZE - lb);
200 }
201
202#ifndef OPENVPN_LEGACY_TITLE_ABSTRACTION
203
204 template <typename TITLE>
205 static Addr from_string(const std::string &ipstr, const TITLE &title)
206 {
207 openvpn_io::error_code ec;
208 openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec);
209 if (ec)
210 throw ipv4_exception(IP::internal::format_error(ipstr, title, "v4", ec));
211 return from_asio(a);
212 }
213
214 static Addr from_string(const std::string &ipstr)
215 {
216 return from_string(ipstr, nullptr);
217 }
218
219#else
220
221 static Addr from_string(const std::string &ipstr, const char *title = nullptr)
222 {
223 openvpn_io::error_code ec;
224 openvpn_io::ip::address_v4 a = openvpn_io::ip::make_address_v4(ipstr, ec);
225 if (ec)
226 throw ipv4_exception(IP::internal::format_error(ipstr, title, "v4", ec));
227 return from_asio(a);
228 }
229
230#endif
231
232 std::string to_string() const
233 {
234 const openvpn_io::ip::address_v4 a = to_asio();
235 std::string ret = a.to_string();
236 return ret;
237 }
238
239 static Addr from_hex(const std::string &s)
240 {
241 Addr ret;
242 ret.u.addr = 0;
243 size_t len = s.length();
244 size_t base = 0;
245 if (len > 0 && s[len - 1] == 'L')
246 len -= 1;
247 if (len >= 2 && s[0] == '0' && s[1] == 'x')
248 {
249 base = 2;
250 len -= 2;
251 }
252 if (len < 1 || len > 8)
253 throw ipv4_exception("parse hex error");
254 size_t di = (len - 1) >> 1;
255 for (int i = (len & 1) ? -1 : 0; i < static_cast<int>(len); i += 2)
256 {
257 const size_t idx = base + i;
258 const int bh = (i >= 0) ? parse_hex_char(s[idx]) : 0;
259 const int bl = parse_hex_char(s[idx + 1]);
260 if (bh == -1 || bl == -1)
261 throw ipv4_exception("parse hex error");
262 ret.u.bytes[Endian::e4(di--)] = static_cast<unsigned char>((bh << 4) + bl);
263 }
264 return ret;
265 }
266
267 std::string to_hex() const
268 {
269 std::string ret;
270 ret.reserve(8);
271 bool firstnonzero = false;
272 for (size_t i = 0; i < 4; ++i)
273 {
274 const unsigned char b = u.bytes[Endian::e4rev(i)];
275 if (b || firstnonzero || i == 3)
276 {
277 const char bh = static_cast<decltype(bh)>(b >> 4);
278 if (bh || firstnonzero)
279 ret += render_hex_char(bh);
280 ret += render_hex_char(b & 0x0F);
281 firstnonzero = true;
282 }
283 }
284 return ret;
285 }
286
287 std::string arpa() const
288 {
289 std::ostringstream os;
290 os << static_cast<int>(u.bytes[Endian::e4(0)]) << '.'
291 << static_cast<int>(u.bytes[Endian::e4(1)]) << '.'
292 << static_cast<int>(u.bytes[Endian::e4(2)]) << '.'
293 << static_cast<int>(u.bytes[Endian::e4(3)]) << ".in-addr.arpa";
294 return os.str();
295 }
296
297 static Addr from_asio(const openvpn_io::ip::address_v4 &asio_addr)
298 {
299 Addr ret;
300 ret.u.addr = asio_addr.to_uint();
301 return ret;
302 }
303
304 openvpn_io::ip::address_v4 to_asio() const
305 {
306 return openvpn_io::ip::address_v4(u.addr);
307 }
308
309 Addr operator&(const Addr &other) const
310 {
311 Addr ret;
312 ret.u.addr = u.addr & other.u.addr;
313 return ret;
314 }
315
316 Addr operator|(const Addr &other) const
317 {
318 Addr ret;
319 ret.u.addr = u.addr | other.u.addr;
320 return ret;
321 }
322
323 Addr operator+(const long delta) const
324 {
325 Addr ret;
326 ret.u.addr = u.addr + static_cast<base_type>(delta);
327 return ret;
328 }
329
330 Addr operator+(const Addr &other) const
331 {
332 Addr ret;
333 ret.u.addr = u.addr + other.u.addr;
334 return ret;
335 }
336
337 Addr operator-(const long delta) const
338 {
339 return operator+(-delta);
340 }
341
342 Addr operator-(const Addr &other) const
343 {
344 Addr ret;
345 ret.u.addr = u.addr - other.u.addr;
346 return ret;
347 }
348
349 Addr operator*(const Addr &other) const
350 {
351 Addr ret;
352 ret.u.addr = u.addr * other.u.addr;
353 return ret;
354 }
355
356 Addr operator/(const Addr &other) const
357 {
358 Addr ret;
359 ret.u.addr = u.addr / other.u.addr;
360 return ret;
361 }
362
363 Addr operator%(const Addr &other) const
364 {
365 Addr ret;
366 ret.u.addr = u.addr % other.u.addr;
367 return ret;
368 }
369
370 Addr operator<<(const unsigned int shift) const
371 {
372 Addr ret;
373 ret.u.addr = u.addr << shift;
374 return ret;
375 }
376
377 Addr operator>>(const unsigned int shift) const
378 {
379 Addr ret;
380 ret.u.addr = u.addr >> shift;
381 return ret;
382 }
383
385 {
386 Addr ret;
387 ret.u.addr = ~u.addr;
388 return ret;
389 }
390
391 // return the network that contains the current address
392 Addr network_addr(const unsigned int prefix_len) const
393 {
394 Addr ret;
396 return ret;
397 }
398
399 bool operator==(const Addr &other) const
400 {
401 return u.addr == other.u.addr;
402 }
403
404 bool operator!=(const Addr &other) const
405 {
406 return u.addr != other.u.addr;
407 }
408
409 bool operator<(const Addr &other) const
410 {
411 return u.addr < other.u.addr;
412 }
413
414 bool operator>(const Addr &other) const
415 {
416 return u.addr > other.u.addr;
417 }
418
419 bool operator<=(const Addr &other) const
420 {
421 return u.addr <= other.u.addr;
422 }
423
424 bool operator>=(const Addr &other) const
425 {
426 return u.addr >= other.u.addr;
427 }
428
429 bool unspecified() const
430 {
431 return all_zeros();
432 }
433
434 bool specified() const
435 {
436 return !unspecified();
437 }
438
439 bool all_zeros() const
440 {
441 return u.addr == 0;
442 }
443
444 bool all_ones() const
445 {
446 return ~u.addr == 0;
447 }
448
449 bool is_loopback() const
450 {
451 return (u.addr & 0x7F000000) == 0x7F000000;
452 }
453
454 // number of network bits in netmask,
455 // throws exception if addr is not a netmask
456 unsigned int prefix_len() const
457 {
458 const int ret = prefix_len_32(u.addr);
459 if (ret >= 0)
460 return ret;
461 throw ipv4_exception("malformed netmask");
462 }
463
465 {
466 return prefix_len_32(u.addr);
467 }
468
469 // number of host bits in netmask
470 unsigned int host_len() const
471 {
472 return SIZE - prefix_len();
473 }
474
475 // return the number of host addresses contained within netmask
477 {
478 Addr ret;
480 return ret;
481 }
482
483 std::uint32_t extent_from_netmask_uint32() const
484 {
485 const unsigned int hl = host_len();
486 if (hl < SIZE)
487 return 1 << hl;
488 if (hl == SIZE)
489 return 0;
490 throw ipv4_exception("extent overflow");
491 }
492
493 // convert netmask in addr to prefix_len, will return -1 on error
494 static int prefix_len_32(const std::uint32_t addr)
495 {
496 if (addr == ~std::uint32_t(0))
497 return 32;
498 if (addr == 0)
499 return 0;
500 unsigned int high = 32;
501 unsigned int low = 1;
502 for (unsigned int i = 0; i < 5; ++i)
503 {
504 const unsigned int mid = (high + low) / 2;
506 if (addr == test)
507 return mid;
508 if (addr > test)
509 low = mid;
510 else
511 high = mid;
512 }
513 return -1;
514 }
515
516 // address size in bits
517 static constexpr unsigned int size()
518 {
519 return SIZE;
520 }
521
522 template <typename HASH>
523 void hash(HASH &h) const
524 {
525 h(u.addr);
526 }
527
528#ifdef USE_OPENVPN_HASH
529 std::uint64_t hashval() const
530 {
531 Hash64 h;
532 hash(h);
533 return h.value();
534 }
535#endif
536
537#ifdef OPENVPN_IP_IMMUTABLE
538 private:
539#endif
540
541 void negate()
542 {
543 u.addr = ~u.addr;
544 }
545
546 void zero()
547 {
548 u.addr = 0;
549 }
550
552 {
553 u.addr = ~0;
554 }
555
556 void one()
557 {
558 u.addr = 1;
559 }
560
562 {
563 ++u.addr;
564 return *this;
565 }
566
567 Addr &operator+=(const long delta)
568 {
569 u.addr += (std::uint32_t)delta;
570 return *this;
571 }
572
573 Addr &operator-=(const long delta)
574 {
575 return operator+=(-delta);
576 }
577
578 private:
579 static base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) noexcept
580 {
581 if (prefix_len)
582 return ~((1u << (SIZE - prefix_len)) - 1);
583 return 0;
584 }
585
586 static base_type prefix_len_to_netmask(const unsigned int prefix_len)
587 {
588 if (prefix_len <= SIZE)
590 throw ipv4_exception("bad prefix len");
591 }
592
593 union {
594 base_type addr; // host byte order
595 unsigned char bytes[4];
596 } u;
597};
598
599OPENVPN_OSTREAM(Addr, to_string)
600} // namespace openvpn::IPv4
601
602#ifdef USE_OPENVPN_HASH
604#endif
605
606#endif // OPENVPN_ADDR_IPV4_H
void hash(HASH &h) const
Definition ipv4.hpp:523
Addr operator+(const long delta) const
Definition ipv4.hpp:323
void to_byte_string(unsigned char *bytestr) const
Definition ipv4.hpp:119
static Addr from_hex(const std::string &s)
Definition ipv4.hpp:239
unsigned char bytes[4]
Definition ipv4.hpp:595
bool operator!=(const Addr &other) const
Definition ipv4.hpp:404
bool all_ones() const
Definition ipv4.hpp:444
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
Definition ipv4.hpp:189
unsigned int prefix_len() const
Definition ipv4.hpp:456
unsigned long to_ulong() const
Definition ipv4.hpp:136
openvpn_io::ip::address_v4 to_asio() const
Definition ipv4.hpp:304
static Addr from_bytes_net(const unsigned char *bytes)
Definition ipv4.hpp:160
long to_long() const
Definition ipv4.hpp:148
static Addr from_asio(const openvpn_io::ip::address_v4 &asio_addr)
Definition ipv4.hpp:297
static Addr from_string(const std::string &ipstr)
Definition ipv4.hpp:214
Addr operator%(const Addr &other) const
Definition ipv4.hpp:363
void zero_complement()
Definition ipv4.hpp:551
unsigned int host_len() const
Definition ipv4.hpp:470
Addr operator<<(const unsigned int shift) const
Definition ipv4.hpp:370
static base_type prefix_len_to_netmask(const unsigned int prefix_len)
Definition ipv4.hpp:586
static int prefix_len_32(const std::uint32_t addr)
Definition ipv4.hpp:494
static Addr from_ulong(unsigned long ul)
Definition ipv4.hpp:129
static Addr from_sockaddr(const sockaddr_in *sa)
Definition ipv4.hpp:80
std::string to_hex() const
Definition ipv4.hpp:267
static Addr from_long(long ul)
Definition ipv4.hpp:141
static Addr from_uint32_net(const base_type addr)
Definition ipv4.hpp:112
Addr operator&(const Addr &other) const
Definition ipv4.hpp:309
Addr & operator++()
Definition ipv4.hpp:561
bool is_loopback() const
Definition ipv4.hpp:449
bool operator<(const Addr &other) const
Definition ipv4.hpp:409
Addr operator~() const
Definition ipv4.hpp:384
static Addr from_in_addr(const in_addr *in4)
Definition ipv4.hpp:66
static constexpr bool defined()
Definition ipv4.hpp:56
Addr operator-(const Addr &other) const
Definition ipv4.hpp:342
in_addr to_in_addr() const
Definition ipv4.hpp:73
bool operator==(const Addr &other) const
Definition ipv4.hpp:399
bool all_zeros() const
Definition ipv4.hpp:439
std::uint32_t base_type
Definition ipv4.hpp:48
Addr operator|(const Addr &other) const
Definition ipv4.hpp:316
std::uint32_t extent_from_netmask_uint32() const
Definition ipv4.hpp:483
Addr operator+(const Addr &other) const
Definition ipv4.hpp:330
Addr operator/(const Addr &other) const
Definition ipv4.hpp:356
int prefix_len_nothrow() const
Definition ipv4.hpp:464
static Addr from_zero()
Definition ipv4.hpp:168
Addr & operator+=(const long delta)
Definition ipv4.hpp:567
static base_type prefix_len_to_netmask_unchecked(const unsigned int prefix_len) noexcept
Definition ipv4.hpp:579
static Addr from_bytes(const unsigned char *bytes)
Definition ipv4.hpp:153
std::int32_t signed_base_type
Definition ipv4.hpp:49
std::uint32_t to_uint32_net() const
Definition ipv4.hpp:124
static Addr from_zero_complement()
Definition ipv4.hpp:182
Addr netmask_from_this_as_extent() const
Definition ipv4.hpp:196
static Addr from_addr(const Addr &addr)
Definition ipv4.hpp:61
bool specified() const
Definition ipv4.hpp:434
static constexpr int ip_version()
Definition ipv4.hpp:51
Addr operator-(const long delta) const
Definition ipv4.hpp:337
Addr operator*(const Addr &other) const
Definition ipv4.hpp:349
static constexpr unsigned int size()
Definition ipv4.hpp:517
bool operator<=(const Addr &other) const
Definition ipv4.hpp:419
static Addr from_uint32(const base_type addr)
Definition ipv4.hpp:100
std::string arpa() const
Definition ipv4.hpp:287
Addr & operator-=(const long delta)
Definition ipv4.hpp:573
static Addr from_one()
Definition ipv4.hpp:175
bool unspecified() const
Definition ipv4.hpp:429
std::string to_string() const
Definition ipv4.hpp:232
Addr network_addr(const unsigned int prefix_len) const
Definition ipv4.hpp:392
bool operator>(const Addr &other) const
Definition ipv4.hpp:414
std::uint32_t to_uint32() const
Definition ipv4.hpp:107
Addr extent_from_netmask() const
Definition ipv4.hpp:476
sockaddr_in to_sockaddr(const unsigned short port=0) const
Definition ipv4.hpp:87
base_type addr
Definition ipv4.hpp:594
static Addr from_string(const std::string &ipstr, const TITLE &title)
Definition ipv4.hpp:205
bool operator>=(const Addr &other) const
Definition ipv4.hpp:424
union openvpn::IPv4::Addr::@2 u
Addr operator>>(const unsigned int shift) const
Definition ipv4.hpp:377
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_HASH_METHOD(T, meth)
Definition hash.hpp:30
std::string format_error(const std::string &ipstr, const TITLE &title, const char *ipver, const std::string &message)
Definition iperr.hpp:29
int parse_hex_char(const int c)
Definition hexstr.hpp:65
char render_hex_char(const int c, const bool caps=false)
Definition hexstr.hpp:42
#define OPENVPN_OSTREAM(TYPE, METH)
Definition ostream.hpp:21
proxy_host_port port
std::string ret
std::ostringstream os
void test()
Definition test_rc.cpp:80