GCC Code Coverage Report


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