needed for fmt::join
[ghsmtp.git] / IP4.cpp
blobbf9e98fddb84b64cb71b1408ef4b330bb6a0fd25
1 #include "IP4.hpp"
3 #include <charconv>
5 #include <glog/logging.h>
7 #include <fmt/format.h>
9 #include <tao/pegtl.hpp>
10 #include <tao/pegtl/contrib/abnf.hpp>
12 using tao::pegtl::action;
13 using tao::pegtl::eof;
14 using tao::pegtl::memory_input;
15 using tao::pegtl::nothing;
16 using tao::pegtl::one;
17 using tao::pegtl::parse;
18 using tao::pegtl::range;
19 using tao::pegtl::rep;
20 using tao::pegtl::rep_min_max;
21 using tao::pegtl::seq;
22 using tao::pegtl::sor;
23 using tao::pegtl::string;
25 using tao::pegtl::abnf::DIGIT;
27 namespace IP4 {
29 using dot = one<'.'>;
31 // clang-format off
33 struct dec_octet : sor<seq<string<'2','5'>, range<'0','5'>>,
34 seq<one<'2'>, range<'0','4'>, DIGIT>,
35 seq<one<'1'>, rep<2, DIGIT>>,
36 seq<range<'1', '9'>, DIGIT>,
37 DIGIT
38 > {};
40 struct ipv4_address
41 : seq<dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet, eof> {
44 struct ipv4_address_lit : seq<one<'['>,
45 dec_octet,
46 dot,
47 dec_octet,
48 dot,
49 dec_octet,
50 dot,
51 dec_octet,
52 one<']'>,
53 eof> {
56 // clang-format on
58 template <typename Rule>
59 struct action : nothing<Rule> {
62 template <>
63 struct action<dec_octet> {
64 template <typename Input>
65 static void apply(Input const& in, std::vector<std::string>& a)
67 a.push_back(in.string());
71 // <https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses>
73 auto is_private(std::string_view addr) -> bool
75 std::vector<std::string> a;
76 a.reserve(4);
78 memory_input<> in{addr.data(), addr.size(), "addr"};
79 CHECK((parse<ipv4_address, action>(in, a)));
81 // <https://tools.ietf.org/html/rfc1918#section-3>
83 // 10.0.0.0 - 10.255.255.255 (10/8 prefix)
84 // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
85 // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
87 if (a[0] == "10")
88 return true;
90 if (a[0] == "172") {
91 // auto const oct = atoi(a[1].c_str());
93 uint8_t oct{};
94 std::from_chars(a[1].data(), a[1].data() + a[1].size(), oct);
96 return (16 <= oct) && (oct <= 31);
99 return (a[0] == "192") && (a[1] == "168");
102 auto is_address(std::string_view addr) -> bool
104 memory_input<> in{addr.data(), addr.size(), "addr"};
105 return parse<ipv4_address>(in);
108 auto is_address_literal(std::string_view addr) -> bool
110 memory_input<> in{addr.data(), addr.size(), "addr"};
111 return parse<ipv4_address_lit>(in);
114 auto to_address_literal(std::string_view addr) -> std::string
116 CHECK(is_address(addr));
117 return fmt::format("{}{}{}", lit_pfx, addr, lit_sfx);
120 std::string reverse(std::string_view addr)
122 std::vector<std::string> a;
123 a.reserve(4);
125 auto in{memory_input<>{addr.data(), addr.size(), "addr"}};
126 CHECK((parse<ipv4_address, action>(in, a)));
128 return fmt::format("{}.{}.{}.{}.", a[3], a[2], a[1], a[0]);
130 } // namespace IP4