ohmu
·
2026-10-15
1#include "detection/dns/dns.h"
2
3#include "common/io.h"
4#include "common/mallocHelper.h"
5#include "common/strutil.h"
6#include "common/debug.h"
7
8#ifdef __HAIKU__
9 #define RESOLV_CONF "/system/settings/network/resolv.conf"
10#else
11 #define RESOLV_CONF "/etc/resolv.conf"
12#endif
13
14static const char* detectDnsFromConf(const char* path, FFDNSOptions* options, FFlist* results) {
15 FF_DEBUG("Attempting to read DNS config from %s", path);
16
17 FF_AUTO_CLOSE_FILE FILE* file = fopen(path, "r");
18 if (!file) {
19 FF_DEBUG("Failed to open %s: %s", path, strerror(errno));
20 return "fopen(path, r) failed";
21 }
22
23 if (results->length > 0) {
24 FF_DEBUG("Clearing existing DNS entries (%u entries)", results->length);
25 FF_LIST_FOR_EACH (FFstrbuf, item, *results) {
26 ffStrbufDestroy(item);
27 }
28 ffListClear(results);
29 }
30
31 FF_AUTO_FREE char* line = nullptr;
32 size_t len = 0;
33
34 while (getline(&line, &len, file) != -1) {
35 if (ffStrStartsWith(line, "nameserver")) {
36 char* nameserver = line + strlen("nameserver");
37 while (*nameserver == ' ' || *nameserver == '\t') {
38 nameserver++;
39 }
40 if (*nameserver == '\0') {
41 continue;
42 }
43
44 char* comment = strchr(nameserver, '#');
45 if (comment) {
46 *comment = '\0';
47 }
48
49 if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) ||
50 (ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) {
51 continue;
52 }
53
54 FFstrbuf* item = FF_LIST_ADD(FFstrbuf, *results);
55 ffStrbufInitS(item, nameserver);
56 ffStrbufTrimRightSpace(item);
57 FF_DEBUG("Found DNS server: %s", item->chars);
58 }
59 }
60
61 FF_DEBUG("Found %u DNS servers in %s", results->length, path);
62 return nullptr;
63}
64
65const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) {
66 FF_DEBUG("Starting DNS detection");
67
68 const char* error = detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT RESOLV_CONF, options, results);
69 if (error != nullptr) {
70 FF_DEBUG("Error detecting DNS: %s", error);
71 return error;
72 }
73
74#if __linux__ && !__ANDROID__
75 // Handle different DNS management services
76 if (results->length == 1) {
77 const FFstrbuf* firstEntry = FF_LIST_FIRST(FFstrbuf, *results);
78
79 if (ffStrbufEqualS(firstEntry, "127.0.0.53")) {
80 FF_DEBUG("Detected systemd-resolved (127.0.0.53), checking actual DNS servers");
81 // Managed by systemd-resolved
82 if (detectDnsFromConf("/run/systemd/resolve/resolv.conf", options, results) == nullptr) {
83 return nullptr;
84 }
85 } else if (ffStrbufEqualS(firstEntry, "127.0.0.1")) {
86 FF_DEBUG("Detected possible NetworkManager (127.0.0.1), checking actual DNS servers");
87 // Managed by NetworkManager
88 if (detectDnsFromConf("/var/run/NetworkManager/resolv.conf", options, results) == nullptr) {
89 return nullptr;
90 }
91 }
92 }
93
94 // Check other possible DNS configuration files
95 if (results->length == 0) {
96 FF_DEBUG("No DNS servers found, trying alternative config files");
97
98 // Try resolvconf
99 FF_DEBUG("Trying resolvconf configuration");
100 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/run/resolvconf/resolv.conf", options, results) == nullptr && results->length > 0) {
101 return nullptr;
102 }
103
104 // Try dnsmasq
105 FF_DEBUG("Trying dnsmasq configuration");
106 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/dnsmasq/resolv.conf", options, results) == nullptr && results->length > 0) {
107 return nullptr;
108 }
109
110 // Try openresolv
111 FF_DEBUG("Trying openresolv configuration");
112 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/etc/resolv.conf.openresolv", options, results) == nullptr && results->length > 0) {
113 return nullptr;
114 }
115 }
116#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__NetBSD__) || defined(__OpenBSD__)
117 // Handle BSD-specific DNS configurations
118 if (results->length == 0) {
119 FF_DEBUG("No DNS servers found, trying BSD-specific config files");
120
121 // FreeBSD and other BSDs may use resolvconf service
122 FF_DEBUG("Trying BSD resolvconf configuration");
123 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/resolvconf/resolv.conf", options, results) == nullptr && results->length > 0) {
124 return nullptr;
125 }
126
127 // Some BSDs store DNS configuration here
128 FF_DEBUG("Trying BSD nameserver configuration");
129 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/var/run/nameserver", options, results) == nullptr && results->length > 0) {
130 return nullptr;
131 }
132
133 // Try common BSD paths
134 FF_DEBUG("Trying BSD common paths");
135 if (detectDnsFromConf(FASTFETCH_TARGET_DIR_ROOT "/etc/nameserver", options, results) == nullptr && results->length > 0) {
136 return nullptr;
137 }
138 }
139#endif
140
141 FF_DEBUG("DNS detection completed with %u servers found", results->length);
142 return nullptr;
143}