1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#include "detection/dns/dns.h"
#include "common/io.h"
#include "common/mallocHelper.h"
#include "common/strutil.h"
#include "common/apple/cf_helpers.h"
#include "common/debug.h"
#include <SystemConfiguration/SystemConfiguration.h>
static const char* detectDnsFromConf(const char* path, FFDNSOptions* options, FFlist* results) {
FF_DEBUG("Attempting to read DNS config from %s", path);
FF_AUTO_CLOSE_FILE FILE* file = fopen(path, "r");
if (!file) {
FF_DEBUG("Failed to open %s: %s", path, strerror(errno));
return "fopen(path, r) failed";
}
if (results->length > 0) {
FF_DEBUG("Clearing existing DNS entries (%u entries)", results->length);
FF_LIST_FOR_EACH (FFstrbuf, item, *results) {
ffStrbufDestroy(item);
}
ffListClear(results);
}
FF_AUTO_FREE char* line = NULL;
size_t len = 0;
while (getline(&line, &len, file) != -1) {
if (ffStrStartsWith(line, "nameserver")) {
char* nameserver = line + strlen("nameserver");
while (*nameserver == ' ' || *nameserver == '\t') {
nameserver++;
}
if (*nameserver == '\0') {
continue;
}
char* comment = strchr(nameserver, '#');
if (comment) {
*comment = '\0';
}
if ((ffStrContainsC(nameserver, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) ||
(ffStrContainsC(nameserver, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) {
continue;
}
FFstrbuf* item = FF_LIST_ADD(FFstrbuf, *results);
ffStrbufInitS(item, nameserver);
ffStrbufTrimRightSpace(item);
FF_DEBUG("Found DNS server: %s", item->chars);
}
}
FF_DEBUG("Found %u DNS servers in %s", results->length, path);
return NULL;
}
const char* ffDetectDNS(FFDNSOptions* options, FFlist* results) {
// Handle macOS-specific DNS configurations
FF_DEBUG("Using SystemConfiguration framework for macOS");
// Create a reference to the dynamic store
FF_CFTYPE_AUTO_RELEASE SCDynamicStoreRef store = SCDynamicStoreCreate(NULL, CFSTR("fastfetch"), NULL, NULL);
if (store) {
// Get the network global IPv4 and IPv6 configuration
FF_CFTYPE_AUTO_RELEASE CFStringRef key = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetDNS);
if (key) {
FF_CFTYPE_AUTO_RELEASE CFDictionaryRef dict = SCDynamicStoreCopyValue(store, key);
if (dict) {
// Get the DNS server addresses array
CFArrayRef dnsServers = CFDictionaryGetValue(dict, kSCPropNetDNSServerAddresses);
if (dnsServers) {
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
for (CFIndex i = 0; i < CFArrayGetCount(dnsServers); i++) {
if (ffCfStrGetString(CFArrayGetValueAtIndex(dnsServers, i), &buffer) == NULL) {
// Check if the address matches our filter
if ((ffStrbufContainC(&buffer, ':') && !(options->showType & FF_DNS_TYPE_IPV6_BIT)) ||
(ffStrbufContainC(&buffer, '.') && !(options->showType & FF_DNS_TYPE_IPV4_BIT))) {
continue;
}
// Add to results
FFstrbuf* item = FF_LIST_ADD(FFstrbuf, *results);
ffStrbufInitMove(item, &buffer);
FF_DEBUG("Found DNS server on macOS: %s", item->chars);
}
}
}
}
}
}
// If we didn't find any servers, try resolv.conf as fallback
if (results->length > 0) {
return NULL;
}
FF_DEBUG("No DNS servers found via SystemConfiguration, trying resolv.conf");
// Try standard resolv.conf location on macOS as a fallback
return detectDnsFromConf("/var/run/resolv.conf", options, results);
}
|