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