-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.cpp
93 lines (78 loc) · 2.49 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <asio.hpp>
#include "dns.hpp"
using asio::ip::udp;
std::string resolve(std::string domain, dns_record_t type);
dns_packet send_query(std::string nameserver, std::string domain, dns_record_t type);
int main(int argc, char **argv) {
std::string domain = argv[1];
auto ipaddr = resolve(domain, dns_record_t::A);
std::cout << "IPv4 Address found: " << ipaddr << "\n";
}
std::optional<std::string> get_answer(const dns_packet &packet) {
for (const auto &record: packet.answers) {
if (record.type == dns_record_t::A) {
return record.parsed_rdata;
}
}
return std::nullopt;
}
std::optional<std::string> get_nameserver_ip(const dns_packet &packet) {
for (const auto &record: packet.additional) {
if (record.type == dns_record_t::A) {
return record.parsed_rdata;
}
}
return std::nullopt;
}
std::optional<std::string> get_nameserver(const dns_packet &packet) {
for (const auto &record: packet.authorities) {
if (record.type == dns_record_t::NS) {
return record.parsed_rdata;
}
}
return std::nullopt;
}
std::string resolve(std::string domain, dns_record_t type) {
std::string nameserver = "198.41.0.4";
while (true) {
std::cout << "Querying " << nameserver << " for " << domain << "\n";
auto resp = send_query(nameserver, domain, type);
std::optional<std::string> ans;
if (ans = get_answer(resp)) {
return ans.value();
} else if (ans = get_nameserver_ip(resp)) {
nameserver = ans.value();
} else if (ans = get_nameserver(resp)) {
nameserver = resolve(ans.value(), dns_record_t::A);
}
}
}
dns_packet send_query(std::string nameserver, std::string domain, dns_record_t type) {
dns_packet d(domain, type);
auto bytes = d.to_bytes();
try {
asio::io_context io_context;
udp::resolver resolver(io_context);
udp::endpoint endpoint(asio::ip::make_address(nameserver), 53);
udp::socket socket(io_context);
socket.open(udp::v4());
socket.send_to(asio::buffer(bytes, bytes.size()), endpoint);
std::vector<uint8_t> dns_response(1024);
udp::endpoint sender_endpoint;
size_t length = socket.receive_from(asio::buffer(dns_response), sender_endpoint);
dns_packet out(dns_response);
/*
auto v = out.to_bytes();
dns_packet vv{v};
auto vvv = vv.to_bytes();
hex_print(vvv);
dns_packet vvvv{vvv};
std::cout << vvvv << "\n";
*/
socket.close();
return out;
} catch (std::exception& e) {
std::cerr << "Error: " << e.what() << "\n";
throw e;
}
}