1 #include "DNS-fcrdns.hpp"
13 #include <experimental/iterator>
15 #include <fmt/format.h>
17 void check_dnsrbl(DNS::Resolver
& res
, char const* a
)
20 "b.barracudacentral.org",
25 auto const reversed
{IP4::reverse(a
)};
27 for (auto rbl
: rbls
) {
28 auto as
= DNS::get_strings(res
, DNS::RR_type::A
, reversed
+ rbl
);
30 std::cout
<< a
<< " blocked on advice from " << rbl
<< '\n';
35 void check_uribls(DNS::Resolver
& res
, char const* dom
)
43 for (auto uribl
: uribls
) {
44 auto const lookup
= fmt::format("{}.{}", dom
, uribl
);
45 auto as
= DNS::get_strings(res
, DNS::RR_type::A
, lookup
);
47 if (as
.front() == "127.0.0.1")
49 std::cout
<< dom
<< " blocked on advice from " << uribl
<< '\n';
54 void do_addr(DNS::Resolver
& res
, char const* a
)
56 auto const names
= DNS::fcrdns(res
, a
);
57 std::vector
<Domain
> doms
;
58 for (auto const& name
: names
) {
59 doms
.emplace_back(name
);
62 std::cout
<< a
<< " [";
63 std::copy(begin(doms
), end(doms
),
64 std::experimental::make_ostream_joiner(std::cout
, ", "));
68 if (IP4::is_address(a
)) {
69 auto const reversed
{IP4::reverse(a
)};
71 = res
.get_strings(DNS::RR_type::PTR
, reversed
+ "in-addr.arpa");
72 for (auto const& ptr
: ptrs
) {
73 std::cout
<< a
<< " has a PTR to " << ptr
<< '\n';
76 if (IP6::is_address(a
)) {
77 auto const reversed
{IP6::reverse(a
)};
79 = res
.get_strings(DNS::RR_type::PTR
, reversed
+ "ip6.arpa");
80 for (auto const& ptr
: ptrs
) {
81 std::cout
<< a
<< " has a PTR to " << ptr
<< '\n';
84 if (IP4::is_address(a
)) {
87 std::cout
<< a
<< '\n';
91 void do_domain(DNS::Resolver
& res
, char const* dom_cp
)
93 auto const dom
{Domain
{dom_cp
}};
95 auto cnames
= res
.get_strings(DNS::RR_type::CNAME
, dom
.ascii().c_str());
96 if (!cnames
.empty()) {
97 // RFC 2181 section 10.1. CNAME resource records
98 CHECK_EQ(cnames
.size(), 1);
99 std::cout
<< dom
<< " is an alias for " << cnames
.front() << '\n';
102 auto as
= res
.get_strings(DNS::RR_type::A
, dom
.ascii().c_str());
103 for (auto const& a
: as
) {
104 do_addr(res
, a
.c_str());
107 auto aaaas
= res
.get_strings(DNS::RR_type::AAAA
, dom
.ascii().c_str());
108 for (auto const& aaaa
: aaaas
) {
109 do_addr(res
, aaaa
.c_str());
112 auto q
{DNS::Query
{res
, DNS::RR_type::MX
, dom
.ascii()}};
113 if (!q
.has_record()) {
114 std::cout
<< "no MX records\n";
118 auto reg_dom
{tld_db
.get_registered_domain(dom
.ascii())};
119 if (dom
!= reg_dom
) {
120 std::cout
<< "registered domain is " << reg_dom
<< '\n';
123 auto txts
= res
.get_strings(DNS::RR_type::TXT
, dom
.ascii().c_str());
124 for (auto const& txt
: txts
) {
125 std::cout
<< "TXT " << txt
<< '\n';
128 if (q
.has_record()) {
129 check_uribls(res
, dom
.ascii().c_str());
132 if (q
.has_record() && q
.authentic_data()) {
133 std::cout
<< "MX records authentic for domain " << dom
<< '\n';
136 auto mxs
{q
.get_records()};
138 mxs
.erase(std::remove_if(begin(mxs
), end(mxs
),
140 return !std::holds_alternative
<DNS::RR_MX
>(rr
);
145 std::cout
<< "mail for " << dom
<< " is handled by\n";
148 std::sort(begin(mxs
), end(mxs
), [](auto const& a
, auto const& b
) {
149 auto mxa
= std::get
<DNS::RR_MX
>(a
);
150 auto mxb
= std::get
<DNS::RR_MX
>(b
);
151 if (mxa
.preference() == mxb
.preference())
152 return mxa
.exchange() < mxb
.exchange();
153 return mxa
.preference() < mxb
.preference();
156 for (auto const& mx
: mxs
) {
157 if (std::holds_alternative
<DNS::RR_MX
>(mx
)) {
158 auto x
= std::get
<DNS::RR_MX
>(mx
);
159 std::cout
<< std::setfill(' ') << std::setw(3) << x
.preference() << ' '
160 << x
.exchange() << '\n';
165 int main(int argc
, char* argv
[])
167 fs::path config_path
= osutil::get_config_dir();
168 DNS::Resolver
res(config_path
);
170 for (int i
= 1; i
< argc
; ++i
) {
171 auto const arg
= argv
[i
];
172 if (IP::is_address(arg
)) {