1 #include "DNS-fcrdns.hpp"
2 #include "DNS-iostream.hpp"
14 #include <experimental/iterator>
16 #include <fmt/format.h>
18 void check_dnsrbl(DNS::Resolver
& res
, char const* a
)
21 "b.barracudacentral.org",
22 "dnsbl-1.uceprotect.net",
27 auto const reversed
{IP4::reverse(a
)};
29 for (auto rbl
: rbls
) {
30 auto as
= DNS::get_strings(res
, DNS::RR_type::A
, reversed
+ rbl
);
32 std::cout
<< a
<< " blocked on advice from " << rbl
<< '\n';
37 void check_uribls(DNS::Resolver
& res
, char const* dom
)
45 for (auto uribl
: uribls
) {
46 auto const lookup
= fmt::format("{}.{}", dom
, uribl
);
47 auto as
= DNS::get_strings(res
, DNS::RR_type::A
, lookup
);
49 if (as
.front() == "127.0.0.1")
51 std::cout
<< dom
<< " blocked on advice from " << uribl
<< '\n';
56 void do_addr(DNS::Resolver
& res
, char const* a
)
58 auto const names
= DNS::fcrdns(res
, a
);
59 std::vector
<Domain
> doms
;
60 for (auto const& name
: names
) {
61 doms
.emplace_back(name
);
64 std::cout
<< a
<< " [";
65 std::copy(begin(doms
), end(doms
),
66 std::experimental::make_ostream_joiner(std::cout
, ", "));
70 if (IP4::is_address(a
)) {
71 auto const reversed
{IP4::reverse(a
)};
73 = res
.get_strings(DNS::RR_type::PTR
, reversed
+ "in-addr.arpa");
74 for (auto const& ptr
: ptrs
) {
75 std::cout
<< a
<< " has a PTR to " << ptr
<< '\n';
78 if (IP6::is_address(a
)) {
79 auto const reversed
{IP6::reverse(a
)};
81 = res
.get_strings(DNS::RR_type::PTR
, reversed
+ "ip6.arpa");
82 for (auto const& ptr
: ptrs
) {
83 std::cout
<< a
<< " has a PTR to " << ptr
<< '\n';
86 if (IP4::is_address(a
)) {
89 std::cout
<< a
<< '\n';
94 get_tlsa_rrs(DNS::Resolver
& res
, Domain
const& domain
, uint16_t port
)
96 auto const tlsa
= fmt::format("_{}._tcp.{}", port
, domain
.ascii());
98 DNS::Query
q(res
, DNS::RR_type::TLSA
, tlsa
);
101 LOG(INFO
) << "TLSA data not found for " << domain
<< ':' << port
;
104 if (q
.bogus_or_indeterminate()) {
105 LOG(WARNING
) << "TLSA data is bogus or indeterminate";
108 auto tlsa_rrs
= q
.get_records();
109 if (!tlsa_rrs
.empty()) {
110 LOG(INFO
) << "### TLSA data found for " << domain
<< ':' << port
<< " ###";
116 void do_domain(DNS::Resolver
& res
, char const* dom_cp
)
118 auto const dom
{Domain
{dom_cp
}};
120 auto cnames
= res
.get_strings(DNS::RR_type::CNAME
, dom
.ascii().c_str());
121 if (!cnames
.empty()) {
122 // RFC 2181 section 10.1. CNAME resource records
123 CHECK_EQ(cnames
.size(), 1);
124 std::cout
<< dom
<< " is an alias for " << cnames
.front() << '\n';
127 auto as
= res
.get_strings(DNS::RR_type::A
, dom
.ascii().c_str());
128 for (auto const& a
: as
) {
129 do_addr(res
, a
.c_str());
132 auto aaaas
= res
.get_strings(DNS::RR_type::AAAA
, dom
.ascii().c_str());
133 for (auto const& aaaa
: aaaas
) {
134 do_addr(res
, aaaa
.c_str());
138 auto tlsa_rrs
{get_tlsa_rrs(res
, dom
, port
)};
139 if (!tlsa_rrs
.empty()) {
140 for (auto const& tlsa_rr
: tlsa_rrs
) {
141 auto const rp
= std::get
<DNS::RR_TLSA
>(tlsa_rr
);
142 std::cout
<< rp
<< "\n";
146 auto q
{DNS::Query
{res
, DNS::RR_type::MX
, dom
.ascii()}};
147 if (!q
.has_record()) {
148 std::cout
<< "no MX records\n";
152 auto reg_dom
{tld_db
.get_registered_domain(dom
.ascii())};
153 if (reg_dom
&& dom
!= reg_dom
) {
154 std::cout
<< "registered domain is " << reg_dom
<< '\n';
157 auto txts
= res
.get_strings(DNS::RR_type::TXT
, dom
.ascii().c_str());
158 for (auto const& txt
: txts
) {
159 std::cout
<< "TXT " << txt
<< '\n';
162 if (q
.has_record()) {
163 check_uribls(res
, dom
.ascii().c_str());
166 if (q
.has_record() && q
.authentic_data()) {
167 std::cout
<< "MX records authentic for domain " << dom
<< '\n';
170 auto mxs
{q
.get_records()};
172 mxs
.erase(std::remove_if(begin(mxs
), end(mxs
),
174 return !std::holds_alternative
<DNS::RR_MX
>(rr
);
179 std::cout
<< "mail for " << dom
<< " is handled by\n";
182 std::sort(begin(mxs
), end(mxs
), [](auto const& a
, auto const& b
) {
183 auto mxa
= std::get
<DNS::RR_MX
>(a
);
184 auto mxb
= std::get
<DNS::RR_MX
>(b
);
185 if (mxa
.preference() == mxb
.preference())
186 return mxa
.exchange() < mxb
.exchange();
187 return mxa
.preference() < mxb
.preference();
190 for (auto const& mx
: mxs
) {
191 if (std::holds_alternative
<DNS::RR_MX
>(mx
)) {
192 auto x
= std::get
<DNS::RR_MX
>(mx
);
193 std::cout
<< std::setfill(' ') << std::setw(3) << x
.preference() << ' '
194 << x
.exchange() << '\n';
199 int main(int argc
, char* argv
[])
201 fs::path config_path
= osutil::get_config_dir();
202 DNS::Resolver
res(config_path
);
204 for (int i
= 1; i
< argc
; ++i
) {
205 auto const arg
= argv
[i
];
206 if (IP::is_address(arg
)) {