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