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
<range
<'0', '1'>, rep
<2, DIGIT
>>,
42 rep_min_max
<1, 2, DIGIT
>> {};
45 : seq
<dec_octet
, dot
, dec_octet
, dot
, dec_octet
, dot
, dec_octet
> {};
47 struct h16
: rep_min_max
<1, 4, HEXDIG
> {};
49 struct ls32
: sor
<seq
<h16
, colon
, h16
>, ipv4_address
> {};
51 struct dcolon
: two
<':'> {};
53 struct ipv6_address
: sor
<seq
< rep
<6, h16
, colon
>, ls32
>,
54 seq
< dcolon
, rep
<5, h16
, colon
>, ls32
>,
55 seq
<opt
<h16
>, dcolon
, rep
<4, h16
, colon
>, ls32
>,
56 seq
<opt
<h16
, opt
< colon
, h16
>>, dcolon
, rep
<3, h16
, colon
>, ls32
>,
57 seq
<opt
<h16
, rep_opt
<2, colon
, h16
>>, dcolon
, rep
<2, h16
, colon
>, ls32
>,
58 seq
<opt
<h16
, rep_opt
<3, colon
, h16
>>, dcolon
, h16
, colon
, ls32
>,
59 seq
<opt
<h16
, rep_opt
<4, colon
, h16
>>, dcolon
, ls32
>,
60 seq
<opt
<h16
, rep_opt
<5, colon
, h16
>>, dcolon
, h16
>,
61 seq
<opt
<h16
, rep_opt
<6, colon
, h16
>>, dcolon
>> {};
63 struct ipv6_address_literal
64 : seq
<TAO_PEGTL_ISTRING(lit_pfx
), ipv6_address
, TAO_PEGTL_ISTRING(lit_sfx
)> {};
66 struct ipv6_address_only
: seq
<ipv6_address
, eof
> {};
67 struct ipv6_address_literal_only
: seq
<ipv6_address_literal
, eof
> {};
70 // <https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses>
72 bool is_private(std::string_view addr
)
74 // CHECK(is_address(addr));
75 return istarts_with(addr
, "fd");
78 bool is_address(std::string_view addr
)
80 memory_input
<> in
{addr
.data(), addr
.size(), "ip6"};
81 return parse
<IP6::ipv6_address_only
>(in
);
84 bool is_address_literal(std::string_view addr
)
86 memory_input
<> in
{addr
.data(), addr
.size(), "ip6"};
87 return parse
<IP6::ipv6_address_literal_only
>(in
);
90 std::string
to_address_literal(std::string_view addr
)
92 // CHECK(is_address(addr));
93 return fmt::format("{}{}{}", lit_pfx
, addr
, lit_sfx
);
96 std::string
reverse(std::string_view addr_str
)
100 static_assert(sizeof(addr
) == 16, "in6_addr is the wrong size");
102 const auto addr_void
{reinterpret_cast<void*>(&addr
)};
103 const auto addr_uint
{reinterpret_cast<uint8_t const*>(&addr
)};
105 CHECK_EQ(1, inet_pton(AF_INET6
, addr_str
.data(), addr_void
));
107 auto q
{std::string
{}};
108 q
.reserve(4 * NS_IN6ADDRSZ
);
110 for (auto n
{NS_IN6ADDRSZ
- 1}; n
>= 0; --n
) {
111 const auto ch
= addr_uint
[n
];
113 const auto lo
= ch
& 0xF;
114 const auto hi
= (ch
>> 4) & 0xF;
116 constexpr auto hex_digits
= "0123456789abcdef";