1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#include "resolv_conf_event_handler.h" |
6 |
|
|
|
7 |
|
|
#include <string> |
8 |
|
|
#include <vector> |
9 |
|
|
|
10 |
|
|
#include "backoff.h" |
11 |
|
|
#include "logging.h" |
12 |
|
|
#include "util/string.h" |
13 |
|
|
|
14 |
|
|
namespace { |
15 |
|
|
|
16 |
|
|
/** |
17 |
|
|
* Get the first address of type address_type from the list of addresses |
18 |
|
|
* |
19 |
|
|
* @param address_list List of IP addresses |
20 |
|
|
* @param address_type Type of IP address desired; Can be either 4 or 6 |
21 |
|
|
* @param address (out) The first address found |
22 |
|
|
*/ |
23 |
|
|
bool GetFirstAddress( |
24 |
|
|
const ResolvConfEventHandler::AddressList& address_list, |
25 |
|
|
int address_type, std::string* address) { |
26 |
|
|
bool found = false; |
27 |
|
|
|
28 |
|
|
for (size_t i = 0u; i < address_list.size(); ++i) { |
29 |
|
|
if (address_list[i].first == address_type) { |
30 |
|
|
*address = address_list[i].second; |
31 |
|
|
found = true; |
32 |
|
|
break; |
33 |
|
|
} |
34 |
|
|
} |
35 |
|
|
return found; |
36 |
|
|
} |
37 |
|
|
|
38 |
|
|
} // namespace |
39 |
|
|
|
40 |
|
|
ResolvConfEventHandler::ResolvConfEventHandler( |
41 |
|
|
download::DownloadManager* download_manager, |
42 |
|
|
download::DownloadManager* external_download_manager) |
43 |
|
|
: download_manager_(download_manager), |
44 |
|
|
external_download_manager_(external_download_manager) {} |
45 |
|
|
|
46 |
|
|
ResolvConfEventHandler::~ResolvConfEventHandler() {} |
47 |
|
|
|
48 |
|
|
bool ResolvConfEventHandler::Handle(const std::string& file_path, |
49 |
|
|
file_watcher::Event /*event*/, |
50 |
|
|
bool* clear_handler) { |
51 |
|
|
AddressList addresses; |
52 |
|
|
GetDnsAddresses(file_path, &addresses); |
53 |
|
|
if (!addresses.empty()) { |
54 |
|
|
SetDnsAddress(download_manager_, addresses); |
55 |
|
|
SetDnsAddress(external_download_manager_, addresses); |
56 |
|
|
} |
57 |
|
|
*clear_handler = false; |
58 |
|
|
return true; |
59 |
|
|
} |
60 |
|
|
|
61 |
|
|
/** |
62 |
|
|
* Returns any nameserver IP addresses from file |
63 |
|
|
* |
64 |
|
|
* Reads a file, line by line. Returns the IP addresses corresponding |
65 |
|
|
* to nameservers (i.e. from lines "nameserver <IP_ADDRESS>") |
66 |
|
|
*/ |
67 |
|
4 |
void ResolvConfEventHandler::GetDnsAddresses( |
68 |
|
|
const std::string& resolv_file, AddressList* addresses) { |
69 |
|
4 |
bool done = false; |
70 |
|
4 |
BackoffThrottle throttle(100, 1000, 5000); |
71 |
✓✓ |
4 |
while (!done) { |
72 |
|
4 |
FILE* f = std::fopen(resolv_file.c_str(), "r"); |
73 |
✗✓ |
4 |
if (!f) { |
74 |
|
|
LogCvmfs(kLogCvmfs, kLogDebug, |
75 |
|
|
"ResolvConfEventHandler - Could not open: %s", |
76 |
|
|
resolv_file.c_str()); |
77 |
|
|
throttle.Throttle(); |
78 |
|
|
continue; |
79 |
|
|
} |
80 |
|
4 |
std::string line; |
81 |
✓✓ |
4 |
while (GetLineFile(f, &line)) { |
82 |
|
11 |
std::vector<std::string> key_val = SplitString(line, ' '); |
83 |
✓✓✓✓ ✓✓ |
11 |
if (key_val.size() == 2 && key_val[0] == "nameserver") { |
84 |
|
|
// We have found a nameserver line |
85 |
✓✓ |
7 |
if (SplitString(key_val[1], '.').size() == 4) { |
86 |
|
|
// This looks like an IPv4 address |
87 |
|
3 |
addresses->push_back(std::make_pair(4, key_val[1])); |
88 |
✓✓ |
4 |
} else if (SplitString(key_val[1], ':').size() == 8) { |
89 |
|
|
// This looks like an IPv6 address |
90 |
|
2 |
addresses->push_back(std::make_pair(6, key_val[1])); |
91 |
|
|
} |
92 |
|
|
} |
93 |
|
|
} |
94 |
|
4 |
std::fclose(f); |
95 |
|
4 |
done = true; |
96 |
|
|
} |
97 |
|
4 |
} |
98 |
|
|
|
99 |
|
|
void ResolvConfEventHandler::SetDnsAddress( |
100 |
|
|
download::DownloadManager* download_manager, |
101 |
|
|
const AddressList& addresses) { |
102 |
|
|
// Default to IPv4 addresses unless kIpPreferV6 is specified |
103 |
|
|
const int address_type = |
104 |
|
|
download_manager->opt_ip_preference() == dns::kIpPreferV6 ? 6 : 4; |
105 |
|
|
|
106 |
|
|
std::string new_address; |
107 |
|
|
if (GetFirstAddress(addresses, address_type, &new_address)) { |
108 |
|
|
LogCvmfs(kLogCvmfs, kLogDebug, |
109 |
|
|
"ResolvConfEventhandler - resolv.conf file changed. " |
110 |
|
|
"Setting new DNS address: %s", |
111 |
|
|
new_address.c_str()); |
112 |
|
|
download_manager->SetDnsServer(new_address); |
113 |
|
|
} |
114 |
|
|
} |
115 |
|
|
|