Directory: | cvmfs/ |
---|---|
File: | cvmfs/resolv_conf_event_handler.cc |
Date: | 2025-06-22 02:36:02 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 19 | 51 | 37.3% |
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(const ResolvConfEventHandler::AddressList &address_list, | |
24 | int address_type, std::string *address) { | ||
25 | ✗ | bool found = false; | |
26 | |||
27 | ✗ | for (size_t i = 0u; i < address_list.size(); ++i) { | |
28 | ✗ | if (address_list[i].first == address_type) { | |
29 | ✗ | *address = address_list[i].second; | |
30 | ✗ | found = true; | |
31 | ✗ | break; | |
32 | } | ||
33 | } | ||
34 | ✗ | return found; | |
35 | } | ||
36 | |||
37 | } // namespace | ||
38 | |||
39 | ✗ | ResolvConfEventHandler::ResolvConfEventHandler( | |
40 | download::DownloadManager *download_manager, | ||
41 | ✗ | download::DownloadManager *external_download_manager) | |
42 | ✗ | : download_manager_(download_manager) | |
43 | ✗ | , external_download_manager_(external_download_manager) { } | |
44 | |||
45 | ✗ | ResolvConfEventHandler::~ResolvConfEventHandler() { } | |
46 | |||
47 | ✗ | bool ResolvConfEventHandler::Handle(const std::string &file_path, | |
48 | file_watcher::Event /*event*/, | ||
49 | bool *clear_handler) { | ||
50 | ✗ | AddressList addresses; | |
51 | ✗ | GetDnsAddresses(file_path, &addresses); | |
52 | ✗ | if (!addresses.empty()) { | |
53 | ✗ | SetDnsAddress(download_manager_, addresses); | |
54 | ✗ | SetDnsAddress(external_download_manager_, addresses); | |
55 | } | ||
56 | ✗ | *clear_handler = false; | |
57 | ✗ | return true; | |
58 | } | ||
59 | |||
60 | /** | ||
61 | * Returns any nameserver IP addresses from file | ||
62 | * | ||
63 | * Reads a file, line by line. Returns the IP addresses corresponding | ||
64 | * to nameservers (i.e. from lines "nameserver <IP_ADDRESS>") | ||
65 | */ | ||
66 | 56 | void ResolvConfEventHandler::GetDnsAddresses(const std::string &resolv_file, | |
67 | AddressList *addresses) { | ||
68 | 56 | bool done = false; | |
69 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | BackoffThrottle throttle(100, 1000, 5000); |
70 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 56 times.
|
112 | while (!done) { |
71 |
1/2✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | FILE *f = std::fopen(resolv_file.c_str(), "r"); |
72 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 56 times.
|
56 | if (!f) { |
73 | ✗ | LogCvmfs(kLogCvmfs, kLogDebug, | |
74 | "ResolvConfEventHandler - Could not open: %s", | ||
75 | resolv_file.c_str()); | ||
76 | ✗ | throttle.Throttle(); | |
77 | ✗ | continue; | |
78 | } | ||
79 | 56 | std::string line; | |
80 |
3/4✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 154 times.
✓ Branch 4 taken 56 times.
|
210 | while (GetLineFile(f, &line)) { |
81 |
1/2✓ Branch 1 taken 154 times.
✗ Branch 2 not taken.
|
154 | std::vector<std::string> key_val = SplitString(line, ' '); |
82 |
6/6✓ Branch 1 taken 140 times.
✓ Branch 2 taken 14 times.
✓ Branch 5 taken 98 times.
✓ Branch 6 taken 42 times.
✓ Branch 7 taken 98 times.
✓ Branch 8 taken 56 times.
|
154 | if (key_val.size() == 2 && key_val[0] == "nameserver") { |
83 | // We have found a nameserver line | ||
84 |
3/4✓ Branch 2 taken 98 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 42 times.
✓ Branch 7 taken 56 times.
|
98 | if (SplitString(key_val[1], '.').size() == 4) { |
85 | // This looks like an IPv4 address | ||
86 |
2/4✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 42 times.
✗ Branch 6 not taken.
|
42 | addresses->push_back(std::make_pair(4, key_val[1])); |
87 |
3/4✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✓ Branch 6 taken 28 times.
✓ Branch 7 taken 28 times.
|
56 | } else if (SplitString(key_val[1], ':').size() == 8) { |
88 | // This looks like an IPv6 address | ||
89 |
2/4✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
|
28 | addresses->push_back(std::make_pair(6, key_val[1])); |
90 | } | ||
91 | } | ||
92 | 154 | } | |
93 |
1/2✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
|
56 | std::fclose(f); |
94 | 56 | done = true; | |
95 | 56 | } | |
96 | 56 | } | |
97 | |||
98 | ✗ | void ResolvConfEventHandler::SetDnsAddress( | |
99 | download::DownloadManager *download_manager, const AddressList &addresses) { | ||
100 | // Default to IPv4 addresses unless kIpPreferV6 is specified | ||
101 | ✗ | const int address_type = download_manager->opt_ip_preference() | |
102 | == dns::kIpPreferV6 | ||
103 | ✗ | ? 6 | |
104 | ✗ | : 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 |