Directory: | cvmfs/ |
---|---|
File: | cvmfs/resolv_conf_event_handler.cc |
Date: | 2025-02-09 02:34:19 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 19 | 49 | 38.8% |
Branches: | 26 | 64 | 40.6% |
Line | Branch | Exec | Source |
---|---|---|---|
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 "util/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 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | BackoffThrottle throttle(100, 1000, 5000); |
71 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | while (!done) { |
72 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | FILE* f = std::fopen(resolv_file.c_str(), "r"); |
73 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
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 |
3/4✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 4 times.
|
15 | while (GetLineFile(f, &line)) { |
82 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | std::vector<std::string> key_val = SplitString(line, ' '); |
83 |
6/6✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 7 times.
✓ Branch 8 taken 4 times.
|
11 | if (key_val.size() == 2 && key_val[0] == "nameserver") { |
84 | // We have found a nameserver line | ||
85 |
3/4✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 4 times.
|
7 | if (SplitString(key_val[1], '.').size() == 4) { |
86 | // This looks like an IPv4 address | ||
87 |
2/4✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
3 | addresses->push_back(std::make_pair(4, key_val[1])); |
88 |
3/4✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
|
4 | } else if (SplitString(key_val[1], ':').size() == 8) { |
89 | // This looks like an IPv6 address | ||
90 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | addresses->push_back(std::make_pair(6, key_val[1])); |
91 | } | ||
92 | } | ||
93 | 11 | } | |
94 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | std::fclose(f); |
95 | 4 | done = true; | |
96 | 4 | } | |
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 | |||
116 |