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