pure evil
[ghsmtp.git] / IP4.cpp
blob63de8fd5d349ee5b1c6eeaa4b7e70f5fd41aed19
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
32 struct dec_octet : sor<seq<string<'2','5'>, range<'0','5'>>,
33 seq<one<'2'>, range<'0','4'>, DIGIT>,
34 seq<range<'0', '1'>, rep<2, DIGIT>>,
35 rep_min_max<1, 2, DIGIT>> {};
37 // clang-format on
39 struct ipv4_address
40 : seq<dec_octet, dot, dec_octet, dot, dec_octet, dot, dec_octet, eof> {
43 struct ipv4_address_lit : seq<one<'['>,
44 dec_octet,
45 dot,
46 dec_octet,
47 dot,
48 dec_octet,
49 dot,
50 dec_octet,
51 one<']'>,
52 eof> {
55 template <typename Rule>
56 struct action : nothing<Rule> {
59 template <>
60 struct action<dec_octet> {
61 template <typename Input>
62 static void apply(Input const& in, std::vector<std::string>& a)
64 a.push_back(in.string());
68 // <https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses>
70 auto is_private(std::string_view addr) -> bool
72 std::vector<std::string> a;
73 a.reserve(4);
75 memory_input<> in{addr.data(), addr.size(), "addr"};
76 CHECK((parse<ipv4_address, action>(in, a)));
78 // <https://tools.ietf.org/html/rfc1918#section-3>
80 // 10.0.0.0 - 10.255.255.255 (10/8 prefix)
81 // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix)
82 // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix)
84 if (a[0] == "10")
85 return true;
87 if (a[0] == "172") {
88 // auto const oct = atoi(a[1].c_str());
90 uint8_t oct{};
91 std::from_chars(a[1].data(), a[1].data() + a[1].size(), oct);
93 return (16 <= oct) && (oct <= 31);
96 return (a[0] == "192") && (a[1] == "168");
99 auto is_address(std::string_view addr) -> bool
101 memory_input<> in{addr.data(), addr.size(), "addr"};
102 return parse<ipv4_address>(in);
105 auto is_address_literal(std::string_view addr) -> bool
107 memory_input<> in{addr.data(), addr.size(), "addr"};
108 return parse<ipv4_address_lit>(in);
111 auto to_address_literal(std::string_view addr) -> std::string
113 // CHECK(is_address(addr));
114 return fmt::format("{}{}{}", lit_pfx, addr, lit_sfx);
117 auto reverse(std::string_view addr) -> std::string
119 std::vector<std::string> a;
120 a.reserve(4);
122 auto in{memory_input<>{addr.data(), addr.size(), "addr"}};
123 CHECK((parse<ipv4_address, action>(in, a)));
125 return fmt::format("{}.{}.{}.{}.", a[3], a[2], a[1], a[0]);
127 } // namespace IP4