6 #include <fmt/format.h>
9 #include <arpa/nameser.h>
11 #include <tao/pegtl.hpp>
12 #include <tao/pegtl/contrib/abnf.hpp>
14 using tao::pegtl::eof
;
15 using tao::pegtl::memory_input
;
16 using tao::pegtl::one
;
17 using tao::pegtl::opt
;
18 using tao::pegtl::parse
;
19 using tao::pegtl::range
;
20 using tao::pegtl::rep
;
21 using tao::pegtl::rep_min_max
;
22 using tao::pegtl::rep_opt
;
23 using tao::pegtl::seq
;
24 using tao::pegtl::sor
;
25 using tao::pegtl::string
;
26 using tao::pegtl::two
;
28 using tao::pegtl::abnf::DIGIT
;
29 using tao::pegtl::abnf::HEXDIG
;
31 #include <glog/logging.h>
36 using colon
= one
<':'>;
39 struct dec_octet
: sor
<seq
<string
<'2','5'>, range
<'0','5'>>,
40 seq
<one
<'2'>, range
<'0','4'>, DIGIT
>,
41 seq
<one
<'1'>, rep
<2, DIGIT
>>,
42 seq
<range
<'1', '9'>, DIGIT
>,
46 : seq
<dec_octet
, dot
, dec_octet
, dot
, dec_octet
, dot
, dec_octet
> {};
48 struct h16
: rep_min_max
<1, 4, HEXDIG
> {};
50 struct ls32
: sor
<seq
<h16
, colon
, h16
>, ipv4_address
> {};
52 struct dcolon
: two
<':'> {};
54 struct ipv6_address
: sor
<seq
< rep
<6, h16
, colon
>, ls32
>,
55 seq
< dcolon
, rep
<5, h16
, colon
>, ls32
>,
56 seq
<opt
<h16
>, dcolon
, rep
<4, h16
, colon
>, ls32
>,
57 seq
<opt
<h16
, opt
< colon
, h16
>>, dcolon
, rep
<3, h16
, colon
>, ls32
>,
58 seq
<opt
<h16
, rep_opt
<2, colon
, h16
>>, dcolon
, rep
<2, h16
, colon
>, ls32
>,
59 seq
<opt
<h16
, rep_opt
<3, colon
, h16
>>, dcolon
, h16
, colon
, ls32
>,
60 seq
<opt
<h16
, rep_opt
<4, colon
, h16
>>, dcolon
, ls32
>,
61 seq
<opt
<h16
, rep_opt
<5, colon
, h16
>>, dcolon
, h16
>,
62 seq
<opt
<h16
, rep_opt
<6, colon
, h16
>>, dcolon
>> {};
64 struct ipv6_address_literal
65 : seq
<TAO_PEGTL_ISTRING("[IPv6:"), ipv6_address
, one
<']'>> {};
67 struct ipv6_address_only
: seq
<ipv6_address
, eof
> {};
68 struct ipv6_address_literal_only
: seq
<ipv6_address_literal
, eof
> {};
71 // <https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses>
73 auto is_private(std::string_view addr
) -> bool
75 CHECK(is_address(addr
));
76 return istarts_with(addr
, "fd");
79 auto is_address(std::string_view addr
) -> bool
81 memory_input
<> in
{addr
.data(), addr
.size(), "ip6"};
82 return parse
<IP6::ipv6_address_only
>(in
);
85 auto is_address_literal(std::string_view addr
) -> bool
87 memory_input
<> in
{addr
.data(), addr
.size(), "ip6"};
88 return parse
<IP6::ipv6_address_literal_only
>(in
);
91 auto to_address_literal(std::string_view addr
) -> std::string
93 CHECK(is_address(addr
));
94 return fmt::format("{}{}{}", lit_pfx
, addr
, lit_sfx
);
97 auto reverse(std::string_view addr_str
) -> std::string
101 static_assert(sizeof(addr
) == 16, "in6_addr is the wrong size");
103 const auto addr_void
{reinterpret_cast<void*>(&addr
)};
104 const auto addr_uint
{reinterpret_cast<uint8_t const*>(&addr
)};
106 CHECK_EQ(1, inet_pton(AF_INET6
, addr_str
.data(), addr_void
));
108 auto q
{std::string
{}};
109 q
.reserve(4 * NS_IN6ADDRSZ
);
111 for (auto n
{NS_IN6ADDRSZ
- 1}; n
>= 0; --n
) {
112 const auto ch
= addr_uint
[n
];
114 const auto lo
= ch
& 0xF;
115 const auto hi
= (ch
>> 4) & 0xF;
117 using namespace std::literals::string_view_literals
;
118 auto constexpr hex_digits
{"0123456789abcdef"sv
};