OpenVPN 3 Core Library
Loading...
Searching...
No Matches
ip.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_IP_H
13#define OPENVPN_ADDR_IP_H
14
15#include <algorithm>
16#include <functional>
17#include <string>
18#include <cstring> // for std::memset
19
20#include <openvpn/io/io.hpp>
21
25#include <openvpn/addr/ipv4.hpp>
26#include <openvpn/addr/ipv6.hpp>
28
29#define OPENVPN_IP_THROW(ERR) throw openvpn::IP::ip_exception(ERR)
30
31namespace openvpn::IP {
32
33OPENVPN_EXCEPTION(ip_exception);
34
35// This is our fundamental IP address class that handles IPv4 or IPv6
36// IP addresses. It is implemented as a discriminated union of IPv4::Addr
37// and IPv6::Addr.
38class Addr
39{
40 public:
42 {
45 V6
46 };
47
48 enum
49 {
50 V4_MASK = (1 << 0),
51 V6_MASK = (1 << 1)
52 };
53 typedef unsigned int VersionMask;
54
60
61#ifndef OPENVPN_LEGACY_TITLE_ABSTRACTION
62
63 template <typename TITLE>
64 Addr(const Addr &other, const TITLE &title, const Version required_version)
65 : ver(other.ver)
66 {
67 other.validate_version(title, required_version);
68 switch (ver)
69 {
70 case V4:
71 u.v4 = other.u.v4;
72 break;
73 case V6:
74 u.v6 = other.u.v6;
75 break;
76 default:
77 break;
78 }
79 }
80
81 template <typename TITLE>
82 Addr(const Addr &other, const TITLE &title)
83 : Addr(other, title, UNSPEC)
84 {
85 }
86
87 template <typename TITLE>
88 Addr(const std::string &ipstr, const TITLE &title, const Version required_version)
89 : Addr(from_string(ipstr, title, required_version))
90 {
91 }
92
93 template <typename TITLE>
94 Addr(const std::string &ipstr, const TITLE &title)
95 : Addr(from_string(ipstr, title, UNSPEC))
96 {
97 }
98
99 Addr(const std::string &ipstr)
100 : Addr(from_string(ipstr, nullptr, UNSPEC))
101 {
102 }
103
104 template <typename TITLE>
105 static Addr from_string(const std::string &ipstr,
106 const TITLE &title,
107 const Version required_version)
108 {
109 openvpn_io::error_code ec;
110 openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec);
111 if (ec)
112 OPENVPN_IP_THROW(internal::format_error(ipstr, title, "", ec));
113 const Addr ret = from_asio(a);
114 if (required_version != UNSPEC && required_version != ret.ver)
115 OPENVPN_IP_THROW(internal::format_error(ipstr, title, version_string_static(required_version), "wrong IP version"));
116 return ret;
117 }
118
119 template <typename TITLE>
120 static Addr from_string(const std::string &ipstr, const TITLE &title)
121 {
122 return from_string(ipstr, title, UNSPEC);
123 }
124
125 static Addr from_string(const std::string &ipstr)
126 {
127 return from_string(ipstr, nullptr, UNSPEC);
128 }
129
130 template <typename TITLE>
131 static std::string validate(const std::string &ipstr,
132 const TITLE &title,
133 const Version required_version)
134 {
135 const Addr a = from_string(ipstr, title, required_version);
136 return a.to_string();
137 }
138
139 template <typename TITLE>
140 static std::string validate(const std::string &ipstr, const TITLE &title)
141 {
142 return validate(ipstr, title, UNSPEC);
143 }
144
145 static std::string validate(const std::string &ipstr)
146 {
147 return validate(ipstr, nullptr, UNSPEC);
148 }
149
150 template <typename TITLE>
151 void validate_version(const TITLE &title, const Version required_version) const
152 {
153 if (required_version != UNSPEC && required_version != ver)
154 OPENVPN_IP_THROW(internal::format_error(to_string(), title, version_string_static(required_version), "wrong IP version"));
155 }
156
157#else
158
159 Addr(const Addr &other, const char *title = nullptr, Version required_version = UNSPEC)
160 : ver(other.ver)
161 {
162 other.validate_version(title, required_version);
163 switch (ver)
164 {
165 case V4:
166 u.v4 = other.u.v4;
167 break;
168 case V6:
169 u.v6 = other.u.v6;
170 break;
171 default:
172 break;
173 }
174 }
175
176 Addr(const std::string &ipstr, const char *title = nullptr, Version required_version = UNSPEC)
177 : Addr(from_string(ipstr, title, required_version))
178 {
179 }
180
181#ifndef SWIGPYTHON
182 // When calling IP:Addr with None as the second parameter, Swig will
183 // always pick this function and complain about not being able to convert
184 // a null pointer to a const std::string reference. Hide this function, so
185 // swig is forced to take the const char* variant of this function instead
186 Addr(const std::string &ipstr, const std::string &title, Version required_version = UNSPEC)
187 : Addr(from_string(ipstr, title.c_str(), required_version))
188 {
189 }
190#endif
191
192 void validate_version(const char *title, Version required_version) const
193 {
194 if (required_version != UNSPEC && required_version != ver)
195 OPENVPN_IP_THROW(internal::format_error(to_string(), title, version_string_static(required_version), "wrong IP version"));
196 }
197
198#ifndef SWIGPYTHON
199 void validate_version(const std::string &title, Version required_version) const
200 {
201 validate_version(title.c_str(), required_version);
202 }
203#endif
204
205 static std::string validate(const std::string &ipstr, const char *title = nullptr, Version required_version = UNSPEC)
206 {
207 Addr a = from_string(ipstr, title, required_version);
208 return a.to_string();
209 }
210
211#ifndef SWIGPYTHON
212 static std::string validate(const std::string &ipstr, const std::string &title, Version required_version = UNSPEC)
213 {
214 return validate(ipstr, title.c_str(), required_version);
215 }
216#endif
217
218 static Addr from_string(const std::string &ipstr, const char *title = nullptr, Version required_version = UNSPEC)
219 {
220 openvpn_io::error_code ec;
221 openvpn_io::ip::address a = openvpn_io::ip::make_address(ipstr, ec);
222 if (ec)
223 OPENVPN_IP_THROW(internal::format_error(ipstr, title, "", ec));
224 const Addr ret = from_asio(a);
225 if (required_version != UNSPEC && required_version != ret.ver)
226 OPENVPN_IP_THROW(internal::format_error(ipstr, title, version_string_static(required_version), "wrong IP version"));
227 return ret;
228 }
229
230#endif
231
232 static bool is_valid(const std::string &ipstr)
233 {
234 // fast path -- rule out validity if invalid chars
235 if (std::any_of(ipstr.begin(), ipstr.end(), [](auto c)
236 { return !(std::isxdigit(c) || c == '.' || c == ':' || c == '%'); }))
237 return false;
238
239 // slow path
240 {
241 openvpn_io::error_code ec;
242 openvpn_io::ip::make_address(ipstr, ec);
243 return !ec;
244 }
245 }
246
247 static Addr from_hex(Version v, const std::string &s)
248 {
249 switch (v)
250 {
251 case V4:
253 case V6:
255 default:
256 OPENVPN_IP_THROW("from_hex: address unspecified");
257 }
258 }
259
261 {
262 Addr a;
263 a.ver = V4;
264 a.u.v4 = std::move(addr);
265 return a;
266 }
267
269 {
270 Addr a;
271 a.ver = V6;
272 a.u.v6 = std::move(addr);
273 return a;
274 }
275
276 const IPv4::Addr &to_ipv4() const
277 {
278 if (ver == V4)
279 return u.v4;
280 OPENVPN_IP_THROW("to_ipv4: address is not IPv4");
281 }
282
284 {
285 switch (ver)
286 {
287 case V4:
288 return u.v4;
289 case UNSPEC:
290 return IPv4::Addr::from_zero();
291 default:
292 OPENVPN_IP_THROW("to_ipv4_zero: address is not IPv4");
293 }
294 }
295
296 const IPv6::Addr &to_ipv6() const
297 {
298 if (ver == V6)
299 return u.v6;
300 OPENVPN_IP_THROW("to_ipv6: address is not IPv6");
301 }
302
304 {
305 switch (ver)
306 {
307 case V6:
308 return u.v6;
309 case UNSPEC:
310 return IPv6::Addr::from_zero();
311 default:
312 OPENVPN_IP_THROW("to_ipv6_zero: address is not IPv6");
313 }
314 }
315
317 {
318 return u.v4;
319 }
320
322 {
323 return u.v6;
324 }
325
326 static Addr from_sockaddr(const struct sockaddr *sa)
327 {
328 if (sa->sa_family == AF_INET)
329 return from_ipv4(IPv4::Addr::from_sockaddr(reinterpret_cast<const struct sockaddr_in *>(sa)));
330 if (sa->sa_family == AF_INET6)
331 return from_ipv6(IPv6::Addr::from_sockaddr(reinterpret_cast<const struct sockaddr_in6 *>(sa)));
332 return Addr();
333 }
334
335 static bool sockaddr_defined(const struct sockaddr *sa)
336 {
337 return sa && (sa->sa_family == AF_INET || sa->sa_family == AF_INET6);
338 }
339
340 static Addr from_ulong(Version v, unsigned long ul)
341 {
342 switch (v)
343 {
344 case V4:
346 case V6:
348 default:
349 OPENVPN_IP_THROW("from_ulong: address unspecified");
350 }
351 }
352
353 // return *this as a ulong, will raise exception on overflow
354 unsigned long to_ulong() const
355 {
356 switch (ver)
357 {
358 case V4:
359 return u.v4.to_ulong();
360 case V6:
361 return u.v6.to_ulong();
362 default:
363 OPENVPN_IP_THROW("to_ulong: address unspecified");
364 }
365 }
366
367 static Addr from_long(Version v, const long ul)
368 {
369 switch (v)
370 {
371 case V4:
373 case V6:
375 default:
376 OPENVPN_IP_THROW("from_long: address unspecified");
377 }
378 }
379
380 // return *this as a long, will raise exception on overflow
381 long to_long() const
382 {
383 switch (ver)
384 {
385 case V4:
386 return u.v4.to_long();
387 case V6:
388 return u.v6.to_long();
389 default:
390 OPENVPN_IP_THROW("to_long: address unspecified");
391 }
392 }
393
394 // return Addr from 16 byte binary string
395 static Addr from_byte_string(const unsigned char *bytestr)
396 {
397 Addr a;
399 {
400 a.ver = V4;
402 }
403 else
404 {
405 a.ver = V6;
406 a.u.v6 = IPv6::Addr::from_byte_string(bytestr);
407 }
408 return a;
409 }
410
411 // convert Addr to 16 byte binary string
412 void to_byte_string(unsigned char *bytestr) const
413 {
414 switch (ver)
415 {
416 case V4:
417 IPv6::Addr::v4_to_byte_string(bytestr, u.v4.to_uint32_net());
418 break;
419 case V6:
420 u.v6.to_byte_string(bytestr);
421 break;
422 default:
423 std::memset(bytestr, 0, 16);
424 break;
425 }
426 }
427
428 // convert Addr to variable length byte string
429 void to_byte_string_variable(unsigned char *bytestr) const
430 {
431 switch (ver)
432 {
433 case V4:
434 u.v4.to_byte_string(bytestr);
435 break;
436 case V6:
437 u.v6.to_byte_string(bytestr);
438 break;
439 default:
440 OPENVPN_IP_THROW("to_byte_string_variable: address unspecified");
441 }
442 }
443
444 std::uint32_t to_uint32_net() const // return value in net byte order
445 {
446 return (ver == V4) ? u.v4.to_uint32_net() : 0;
447 }
448
449 // construct an address where all bits are zero
450 static Addr from_zero(const Version v)
451 {
452 switch (v)
453 {
454 case V4:
456 case V6:
458 default:
459 OPENVPN_IP_THROW("from_zero: IP version unspecified");
460 }
461 }
462
463 // construct the "one" address
464 static Addr from_one(const Version v)
465 {
466 switch (v)
467 {
468 case V4:
470 case V6:
472 default:
473 OPENVPN_IP_THROW("from_one: IP version unspecified");
474 }
475 }
476
477 // construct an address where all bits are one
479 {
480 switch (v)
481 {
482 case V4:
484 case V6:
486 default:
487 OPENVPN_IP_THROW("from_zero_complement: IP version unspecified");
488 }
489 }
490
491 // validate the prefix length for the IP version
492 static bool validate_prefix_len(Version v, const unsigned int prefix_len)
493 {
494 if (v == V4 && prefix_len <= V4_SIZE)
495 return true;
496 if (v == V6 && prefix_len <= V6_SIZE)
497 return true;
498 return false;
499 }
500
501 // build a netmask using given prefix_len
502 static Addr netmask_from_prefix_len(Version v, const unsigned int prefix_len)
503 {
504 switch (v)
505 {
506 case V4:
508 case V6:
510 default:
511 OPENVPN_IP_THROW("netmask_from_prefix_len: address unspecified");
512 }
513 }
514
516 {
517 switch (ver)
518 {
519 case V4:
520 return from_ipv4(u.v4.netmask_from_this_as_extent());
521 case V6:
522 return from_ipv6(u.v6.netmask_from_this_as_extent());
523 default:
524 OPENVPN_IP_THROW("netmask_from_extent: address unspecified");
525 }
526 }
527
528 std::string to_string() const
529 {
530 if (ver != UNSPEC)
531 {
532 const openvpn_io::ip::address a = to_asio();
533 std::string ret = a.to_string();
534 return ret;
535 }
536 return "UNSPEC";
537 }
538
539 std::string to_string_bracket_ipv6() const
540 {
541 std::string ret;
542 if (ver == V6)
543 ret += '[';
544 ret += to_string();
545 if (ver == V6)
546 ret += ']';
547 return ret;
548 }
549
550 std::string to_hex() const
551 {
552 switch (ver)
553 {
554 case V4:
555 return u.v4.to_hex();
556 case V6:
557 return u.v6.to_hex();
558 default:
559 OPENVPN_IP_THROW("to_hex: address unspecified");
560 }
561 }
562
563 std::string arpa() const
564 {
565 switch (ver)
566 {
567 case V4:
568 return u.v4.arpa();
569 case V6:
570 return u.v6.arpa();
571 default:
572 OPENVPN_IP_THROW("arpa: address unspecified");
573 }
574 }
575
576 static Addr from_asio(const openvpn_io::ip::address &addr)
577 {
578 Addr ret;
579 if (addr.is_v4())
580 {
581 ret.ver = V4;
582 ret.u.v4 = IPv4::Addr::from_asio(addr.to_v4());
583 }
584 else if (addr.is_v6())
585 {
586 ret.ver = V6;
587 ret.u.v6 = IPv6::Addr::from_asio(addr.to_v6());
588 }
589 else if (ret.ver == UNSPEC)
590 OPENVPN_IP_THROW("from_asio: address unspecified");
591 return ret;
592 }
593
594 openvpn_io::ip::address to_asio() const
595 {
596 switch (ver)
597 {
598 case V4:
599 return openvpn_io::ip::address_v4(u.v4.to_asio());
600 case V6:
601 return openvpn_io::ip::address_v6(u.v6.to_asio());
602 default:
603 OPENVPN_IP_THROW("to_asio: address unspecified");
604 }
605 }
606
607 Addr operator+(const long delta) const
608 {
609 switch (ver)
610 {
611 case V4:
612 {
613 Addr ret;
614 ret.ver = V4;
615 ret.u.v4 = u.v4 + delta;
616 return ret;
617 }
618 case V6:
619 {
620 Addr ret;
621 ret.ver = V6;
622 ret.u.v6 = u.v6 + delta;
623 return ret;
624 }
625 default:
626 OPENVPN_IP_THROW("operator+: address unspecified");
627 }
628 }
629
630 Addr operator-(const long delta) const
631 {
632 return operator+(-delta);
633 }
634
635 Addr operator<<(const unsigned int shift) const
636 {
637 switch (ver)
638 {
639 case V4:
640 {
641 Addr ret;
642 ret.ver = V4;
643 ret.u.v4 = u.v4 << shift;
644 return ret;
645 }
646 case V6:
647 {
648 Addr ret;
649 ret.ver = V6;
650 ret.u.v6 = u.v6 << shift;
651 return ret;
652 }
653 default:
654 OPENVPN_IP_THROW("operator<<: address unspecified");
655 }
656 }
657
658 Addr operator>>(const unsigned int shift) const
659 {
660 switch (ver)
661 {
662 case V4:
663 {
664 Addr ret;
665 ret.ver = V4;
666 ret.u.v4 = u.v4 >> shift;
667 return ret;
668 }
669 case V6:
670 {
671 Addr ret;
672 ret.ver = V6;
673 ret.u.v6 = u.v6 >> shift;
674 return ret;
675 }
676 default:
677 OPENVPN_IP_THROW("operator>>: address unspecified");
678 }
679 }
680
682 {
683 switch (ver)
684 {
685 case V4:
686 {
687 Addr ret;
688 ret.ver = V4;
689 ret.u.v4 = ~u.v4;
690 return ret;
691 }
692 case V6:
693 {
694 Addr ret;
695 ret.ver = V6;
696 ret.u.v6 = ~u.v6;
697 return ret;
698 }
699 default:
700 OPENVPN_IP_THROW("operator~: address unspecified");
701 }
702 }
703
704 Addr network_addr(const unsigned int prefix_len) const
705 {
706 switch (ver)
707 {
708 case V4:
709 {
710 Addr ret;
711 ret.ver = V4;
712 ret.u.v4 = u.v4.network_addr(prefix_len);
713 return ret;
714 }
715 case V6:
716 {
717 Addr ret;
718 ret.ver = V6;
719 ret.u.v6 = u.v6.network_addr(prefix_len);
720 return ret;
721 }
722 default:
723 OPENVPN_IP_THROW("network_addr: address unspecified");
724 }
725 }
726
727 bool operator==(const Addr &other) const
728 {
729 switch (ver)
730 {
731 case UNSPEC:
732 return other.ver == UNSPEC;
733 case V4:
734 if (ver == other.ver)
735 return u.v4 == other.u.v4;
736 break;
737 case V6:
738 if (ver == other.ver)
739 return u.v6 == other.u.v6;
740 break;
741 }
742 return false;
743 }
744
745 bool operator!=(const Addr &other) const
746 {
747 return !operator==(other);
748 }
749
750 bool operator<(const Addr &other) const
751 {
752 return compare(other, std::less<>{});
753 }
754
755 bool operator>(const Addr &other) const
756 {
757 return compare(other, std::greater<>{});
758 }
759
760 bool operator<=(const Addr &other) const
761 {
762 return compare(other, std::less_equal<>{});
763 }
764
765 bool operator>=(const Addr &other) const
766 {
767 return compare(other, std::greater_equal<>{});
768 }
769
770 // Operator overloads for binary operations
771 Addr operator+(const Addr &other) const
772 {
773 return binary_op(other, std::plus<>{});
774 }
775
776 Addr operator-(const Addr &other) const
777 {
778 return binary_op(other, std::minus<>{});
779 }
780
781 Addr operator*(const Addr &other) const
782 {
783 return binary_op(other, std::multiplies<>{});
784 }
785
786 Addr operator/(const Addr &other) const
787 {
788 return binary_op(other, std::divides<>{});
789 }
790
791 Addr operator%(const Addr &other) const
792 {
793 return binary_op(other, std::modulus<>{});
794 }
795
796 Addr operator&(const Addr &other) const
797 {
798 return binary_op(other, std::bit_and<>{});
799 }
800
801 Addr operator|(const Addr &other) const
802 {
803 return binary_op(other, std::bit_or<>{});
804 }
805
806 bool unspecified() const
807 {
808 return all_zeros();
809 }
810
811 bool specified() const
812 {
813 return !unspecified();
814 }
815
816 bool all_zeros() const
817 {
818 switch (ver)
819 {
820 case V4:
821 return u.v4.all_zeros();
822 case V6:
823 return u.v6.all_zeros();
824 default:
825 return true;
826 }
827 }
828
829 bool all_ones() const
830 {
831 switch (ver)
832 {
833 case V4:
834 return u.v4.all_ones();
835 case V6:
836 return u.v6.all_ones();
837 default:
838 return false;
839 }
840 }
841
842 bool is_loopback() const
843 {
844 switch (ver)
845 {
846 case V4:
847 return u.v4.is_loopback();
848 case V6:
849 return u.v6.is_loopback();
850 default:
851 return false;
852 }
853 }
854
858 bool is_mapped_address() const
859 {
860 if (ver != V6)
861 return false;
862
863 return u.v6.is_mapped_address();
864 }
865
867 {
868 const std::uint32_t ipv4 = u.v6.get_mapped_ipv4_address();
870 };
871
872 bool defined() const
873 {
874 return ver != UNSPEC;
875 }
876
877 const char *version_string() const
878 {
880 }
881
883 {
884 switch (ver)
885 {
886 case V4:
887 return "v4";
888 case V6:
889 return "v6";
890 default:
891 return "UNSPEC";
892 }
893 }
894
896 {
897 return ver;
898 }
899
901 {
902 switch (ver)
903 {
904 case V4:
905 return V4_MASK;
906 case V6:
907 return V6_MASK;
908 default:
909 return 0;
910 }
911 }
912
914 {
915 return version_mask(ver);
916 }
917
918 int version_index() const
919 {
920 switch (ver)
921 {
922 case V4:
923 return 0;
924 case V6:
925 return 1;
926 default:
927 OPENVPN_IP_THROW("version_index: version index undefined");
928 }
929 }
930
931 int family() const
932 {
933 switch (ver)
934 {
935 case V4:
936 return AF_INET;
937 case V6:
938 return AF_INET6;
939 default:
940 return -1;
941 }
942 }
943
944 bool is_compatible(const Addr &other) const
945 {
946 return ver == other.ver;
947 }
948
949 bool is_ipv6() const
950 {
951 return ver == V6;
952 }
953
954 void verify_version_consistency(const Addr &other) const
955 {
956 if (!is_compatible(other))
957 OPENVPN_IP_THROW("verify_version_consistency: version inconsistency");
958 }
959
960 // throw exception if address is not a valid netmask
961 void validate_netmask() const
962 {
963 prefix_len();
964 }
965
966 // number of network bits in netmask,
967 // throws exception if addr is not a netmask
968 unsigned int prefix_len() const
969 {
970 switch (ver)
971 {
972 case V4:
973 return u.v4.prefix_len();
974 case V6:
975 return u.v6.prefix_len();
976 default:
977 OPENVPN_IP_THROW("prefix_len: address unspecified");
978 }
979 }
980
981 // IPv6 scope ID or -1 if not IPv6
982 int scope_id() const
983 {
984 return ver == V6 ? u.v6.scope_id() : -1;
985 }
986
987 // number of host bits in netmask
988 unsigned int host_len() const
989 {
990 switch (ver)
991 {
992 case V4:
993 return u.v4.host_len();
994 case V6:
995 return u.v6.host_len();
996 default:
997 OPENVPN_IP_THROW("host_len: address unspecified");
998 }
999 }
1000
1001 // return the number of host addresses contained within netmask
1003 {
1004 switch (ver)
1005 {
1006 case V4:
1007 return from_ipv4(u.v4.extent_from_netmask());
1008 case V6:
1009 return from_ipv6(u.v6.extent_from_netmask());
1010 default:
1011 OPENVPN_IP_THROW("extent_from_netmask: address unspecified");
1012 }
1013 }
1014
1015 // address size in bits
1016 unsigned int size() const
1017 {
1018 return version_size(ver);
1019 }
1020
1021 // address size in bytes
1022 unsigned int size_bytes() const
1023 {
1024 return size() / 8;
1025 }
1026
1027 // address size in bits of particular IP version
1028 static unsigned int version_size(Version v)
1029 {
1030 switch (v)
1031 {
1032 case V4:
1033 return IPv4::Addr::SIZE;
1034 case V6:
1035 return IPv6::Addr::SIZE;
1036 default:
1037 return 0;
1038 }
1039 }
1040
1041 template <typename HASH>
1042 void hash(HASH &h) const
1043 {
1044 switch (ver)
1045 {
1046 case Addr::V4:
1047 u.v4.hash(h);
1048 break;
1049 case Addr::V6:
1050 u.v6.hash(h);
1051 break;
1052 default:
1053 break;
1054 }
1055 }
1056
1057#ifdef USE_OPENVPN_HASH
1058 std::uint64_t hashval() const
1059 {
1060 Hash64 h;
1061 hash(h);
1062 return h.value();
1063 }
1064#endif
1065
1066#ifdef OPENVPN_IP_IMMUTABLE
1067 private:
1068#endif
1069
1071 : ver(UNSPEC)
1072 {
1073 }
1074
1075 void reset()
1076 {
1077 ver = UNSPEC;
1078 }
1079
1080 Addr &operator=(const Addr &other)
1081 {
1082 ver = other.ver;
1083 u = other.u;
1084 return *this;
1085 }
1086
1088 {
1089 switch (ver)
1090 {
1091 case V4:
1092 ++u.v4;
1093 break;
1094 case V6:
1095 ++u.v6;
1096 break;
1097 default:
1098 break;
1099 }
1100 return *this;
1101 }
1102
1103 Addr &operator+=(const long delta)
1104 {
1105 switch (ver)
1106 {
1107 case V4:
1108 u.v4 += delta;
1109 break;
1110 case V6:
1111 u.v6 += delta;
1112 break;
1113 default:
1114 break;
1115 }
1116 return *this;
1117 }
1118
1119 Addr &operator-=(const long delta)
1120 {
1121 switch (ver)
1122 {
1123 case V4:
1124 u.v4 -= delta;
1125 break;
1126 case V6:
1127 u.v6 -= delta;
1128 break;
1129 default:
1130 break;
1131 }
1132 return *this;
1133 }
1134
1136 {
1137 ver = V4;
1138 u.v4 = IPv4::Addr::from_uint32(addr);
1139 }
1140
1141 private:
1142 union {
1145 } u{};
1146
1148
1149 template <typename Comparator>
1150 bool compare(const Addr &other, Comparator comp) const
1151 {
1152 if (ver == other.ver)
1153 {
1154 switch (ver)
1155 {
1156 case V4:
1157 return comp(u.v4, other.u.v4);
1158 case V6:
1159 return comp(u.v6, other.u.v6);
1160 default:
1161 return false;
1162 }
1163 }
1164 return comp(ver, other.ver);
1165 }
1166
1167 template <typename BinaryOp>
1168 Addr binary_op(const Addr &other, BinaryOp op) const
1169 {
1170 if (ver != other.ver)
1171 {
1172 OPENVPN_IP_THROW("binop: version inconsistency");
1173 }
1174
1175 Addr ret;
1176 ret.ver = ver;
1177
1178 switch (ver)
1179 {
1180 case V4:
1181 ret.u.v4 = op(u.v4, other.u.v4);
1182 break;
1183 case V6:
1184 ret.u.v6 = op(u.v6, other.u.v6);
1185 break;
1186 default:
1187 OPENVPN_IP_THROW("binop: address unspecified");
1188 }
1189
1190 return ret;
1191 }
1192};
1193
1194OPENVPN_OSTREAM(Addr, to_string)
1195} // namespace openvpn::IP
1196
1197#ifdef USE_OPENVPN_HASH
1199#endif
1200
1201#endif
static Addr from_asio(const openvpn_io::ip::address &addr)
Definition ip.hpp:576
static bool validate_prefix_len(Version v, const unsigned int prefix_len)
Definition ip.hpp:492
bool operator==(const Addr &other) const
Definition ip.hpp:727
static Addr from_string(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:105
int version_index() const
Definition ip.hpp:918
Addr operator/(const Addr &other) const
Definition ip.hpp:786
bool specified() const
Definition ip.hpp:811
std::uint32_t to_uint32_net() const
Definition ip.hpp:444
Version version() const
Definition ip.hpp:895
void verify_version_consistency(const Addr &other) const
Definition ip.hpp:954
Addr operator-(const long delta) const
Definition ip.hpp:630
union openvpn::IP::Addr::@4 u
IPv4::Addr to_ipv4_zero() const
Definition ip.hpp:283
Addr(const Addr &other, const TITLE &title)
Definition ip.hpp:82
void hash(HASH &h) const
Definition ip.hpp:1042
static Addr from_sockaddr(const struct sockaddr *sa)
Definition ip.hpp:326
bool all_ones() const
Definition ip.hpp:829
std::string to_string() const
Definition ip.hpp:528
unsigned int size() const
Definition ip.hpp:1016
static std::string validate(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:131
unsigned int size_bytes() const
Definition ip.hpp:1022
bool all_zeros() const
Definition ip.hpp:816
void validate_version(const TITLE &title, const Version required_version) const
Definition ip.hpp:151
Addr netmask_from_this_as_extent() const
Definition ip.hpp:515
const IPv4::Addr & to_ipv4() const
Definition ip.hpp:276
std::string to_string_bracket_ipv6() const
Definition ip.hpp:539
Addr & operator=(const Addr &other)
Definition ip.hpp:1080
bool defined() const
Definition ip.hpp:872
unsigned int VersionMask
Definition ip.hpp:53
Addr operator>>(const unsigned int shift) const
Definition ip.hpp:658
Addr(const std::string &ipstr, const TITLE &title)
Definition ip.hpp:94
const IPv6::Addr & to_ipv6_nocheck() const
Definition ip.hpp:321
Addr operator%(const Addr &other) const
Definition ip.hpp:791
static std::string validate(const std::string &ipstr, const TITLE &title)
Definition ip.hpp:140
Version ver
Definition ip.hpp:1147
Addr operator~() const
Definition ip.hpp:681
static Addr from_long(Version v, const long ul)
Definition ip.hpp:367
static bool is_valid(const std::string &ipstr)
Definition ip.hpp:232
Addr & operator-=(const long delta)
Definition ip.hpp:1119
static Addr from_one(const Version v)
Definition ip.hpp:464
bool compare(const Addr &other, Comparator comp) const
Definition ip.hpp:1150
Addr binary_op(const Addr &other, BinaryOp op) const
Definition ip.hpp:1168
const IPv4::Addr & to_ipv4_nocheck() const
Definition ip.hpp:316
static Addr netmask_from_prefix_len(Version v, const unsigned int prefix_len)
Definition ip.hpp:502
std::string arpa() const
Definition ip.hpp:563
bool is_compatible(const Addr &other) const
Definition ip.hpp:944
std::string to_hex() const
Definition ip.hpp:550
bool operator<=(const Addr &other) const
Definition ip.hpp:760
Addr operator+(const long delta) const
Definition ip.hpp:607
IP::Addr to_v4_addr() const
Definition ip.hpp:866
void reset_ipv4_from_uint32(const IPv4::Addr::base_type addr)
Definition ip.hpp:1135
Addr extent_from_netmask() const
Definition ip.hpp:1002
IPv6::Addr v6
Definition ip.hpp:1144
long to_long() const
Definition ip.hpp:381
static Addr from_hex(Version v, const std::string &s)
Definition ip.hpp:247
bool operator>=(const Addr &other) const
Definition ip.hpp:765
static std::string validate(const std::string &ipstr)
Definition ip.hpp:145
static bool sockaddr_defined(const struct sockaddr *sa)
Definition ip.hpp:335
Addr operator|(const Addr &other) const
Definition ip.hpp:801
const IPv6::Addr & to_ipv6() const
Definition ip.hpp:296
int family() const
Definition ip.hpp:931
Addr(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:88
static Addr from_ipv6(IPv6::Addr addr)
Definition ip.hpp:268
static Addr from_ipv4(IPv4::Addr addr)
Definition ip.hpp:260
static const char * version_string_static(Version ver)
Definition ip.hpp:882
IPv6::Addr to_ipv6_zero() const
Definition ip.hpp:303
bool operator<(const Addr &other) const
Definition ip.hpp:750
void to_byte_string_variable(unsigned char *bytestr) const
Definition ip.hpp:429
int scope_id() const
Definition ip.hpp:982
static Addr from_byte_string(const unsigned char *bytestr)
Definition ip.hpp:395
Addr & operator++()
Definition ip.hpp:1087
Addr & operator+=(const long delta)
Definition ip.hpp:1103
bool operator>(const Addr &other) const
Definition ip.hpp:755
void validate_netmask() const
Definition ip.hpp:961
unsigned int prefix_len() const
Definition ip.hpp:968
static Addr from_ulong(Version v, unsigned long ul)
Definition ip.hpp:340
unsigned long to_ulong() const
Definition ip.hpp:354
openvpn_io::ip::address to_asio() const
Definition ip.hpp:594
bool operator!=(const Addr &other) const
Definition ip.hpp:745
bool is_loopback() const
Definition ip.hpp:842
IPv4::Addr v4
Definition ip.hpp:1143
void to_byte_string(unsigned char *bytestr) const
Definition ip.hpp:412
static unsigned int version_size(Version v)
Definition ip.hpp:1028
Addr operator-(const Addr &other) const
Definition ip.hpp:776
static VersionMask version_mask(const Version ver)
Definition ip.hpp:900
Addr(const std::string &ipstr)
Definition ip.hpp:99
Addr operator<<(const unsigned int shift) const
Definition ip.hpp:635
const char * version_string() const
Definition ip.hpp:877
Addr(const Addr &other, const TITLE &title, const Version required_version)
Definition ip.hpp:64
static Addr from_string(const std::string &ipstr)
Definition ip.hpp:125
Addr network_addr(const unsigned int prefix_len) const
Definition ip.hpp:704
VersionMask version_mask() const
Definition ip.hpp:913
bool is_mapped_address() const
Definition ip.hpp:858
Addr operator&(const Addr &other) const
Definition ip.hpp:796
unsigned int host_len() const
Definition ip.hpp:988
Addr operator+(const Addr &other) const
Definition ip.hpp:771
Addr operator*(const Addr &other) const
Definition ip.hpp:781
static Addr from_zero(const Version v)
Definition ip.hpp:450
bool is_ipv6() const
Definition ip.hpp:949
static Addr from_string(const std::string &ipstr, const TITLE &title)
Definition ip.hpp:120
bool unspecified() const
Definition ip.hpp:806
static Addr from_zero_complement(const Version v)
Definition ip.hpp:478
static Addr from_hex(const std::string &s)
Definition ipv4.hpp:239
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
Definition ipv4.hpp:189
static Addr from_asio(const openvpn_io::ip::address_v4 &asio_addr)
Definition ipv4.hpp:297
static Addr from_ulong(unsigned long ul)
Definition ipv4.hpp:129
static Addr from_sockaddr(const sockaddr_in *sa)
Definition ipv4.hpp:80
static Addr from_long(long ul)
Definition ipv4.hpp:141
static Addr from_uint32_net(const base_type addr)
Definition ipv4.hpp:112
std::uint32_t base_type
Definition ipv4.hpp:48
static Addr from_zero()
Definition ipv4.hpp:168
static Addr from_zero_complement()
Definition ipv4.hpp:182
static Addr from_uint32(const base_type addr)
Definition ipv4.hpp:100
static Addr from_one()
Definition ipv4.hpp:175
static Addr from_sockaddr(const sockaddr_in6 *sa)
Definition ipv6.hpp:82
static Addr from_one()
Definition ipv6.hpp:314
static Addr from_byte_string(const unsigned char *bytestr)
Definition ipv6.hpp:254
static Addr from_long(long ul)
Definition ipv6.hpp:207
static bool byte_string_is_v4(const unsigned char *bytestr)
Definition ipv6.hpp:286
static Addr from_hex(const std::string &s)
Definition ipv6.hpp:142
static Addr from_zero_complement()
Definition ipv6.hpp:321
static Addr netmask_from_prefix_len(const unsigned int prefix_len)
Definition ipv6.hpp:328
static void v4_to_byte_string(unsigned char *bytestr, const std::uint32_t v4addr)
Definition ipv6.hpp:276
static std::uint32_t v4_from_byte_string(const unsigned char *bytestr)
Definition ipv6.hpp:293
static Addr from_zero()
Definition ipv6.hpp:307
static Addr from_asio(const openvpn_io::ip::address_v6 &asio_addr)
Definition ipv6.hpp:244
std::uint32_t get_mapped_ipv4_address() const
Definition ipv6.hpp:512
static Addr from_ulong(unsigned long ul)
Definition ipv6.hpp:190
#define OPENVPN_EXCEPTION(C)
#define OPENVPN_HASH_METHOD(T, meth)
Definition hash.hpp:30
#define OPENVPN_IP_THROW(ERR)
Definition ip.hpp:29
std::string format_error(const std::string &ipstr, const TITLE &title, const char *ipver, const std::string &message)
Definition iperr.hpp:29
#define OPENVPN_OSTREAM(TYPE, METH)
Definition ostream.hpp:21
reroute_gw ipv4
std::string ret