You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下获取域名服务器列表的非res_(n)init类API及可移植方案咨询

Linux下获取域名服务器列表的可移植方案

1. 使用dns_getservers与dns_setservers(libbind)

这组函数是BIND库提供的标准接口,在Linux、BSD等类UNIX系统中都能兼容,可直接获取当前系统的DNS服务器列表,无需手动解析配置文件或依赖res_init的内部结构体:

#include <arpa/nameser.h>
#include <resolv.h>

void get_dns_servers() {
    struct in_addr servers[MAXNS];
    int count = dns_getservers(servers, MAXNS);
    for (int i = 0; i < count; i++) {
        printf("DNS Server %d: %s\n", i+1, inet_ntoa(servers[i]));
    }
}

编译时需链接BIND库:gcc your_code.c -lbind

2. 标准化配置文件解析

如果选择手动解析配置,可遵循POSIX标准的resolv.conf格式,兼容多数类UNIX系统的配置路径(如Linux、BSD、macOS的/etc/resolv.conf),直接提取nameserver字段即可。这种方法的可移植性源于遵循通用格式,不受特定API限制:

#include <stdio.h>
#include <string.h>

void parse_resolv_conf() {
    FILE *fp = fopen("/etc/resolv.conf", "r");
    if (!fp) return;
    char line[256];
    while (fgets(line, sizeof(line), fp)) {
        char *ptr = strtok(line, " \t\n");
        if (ptr && strcmp(ptr, "nameserver") == 0) {
            ptr = strtok(NULL, " \t\n");
            if (ptr) {
                printf("DNS Server: %s\n", ptr);
            }
        }
    }
    fclose(fp);
}

注:使用systemd-resolved、NetworkManager等工具的系统,/etc/resolv.conf通常是动态生成的符号链接,解析结果仍能反映当前生效的DNS配置。

3. 借助res_ninit的标准化用法

你提到的res_(n)init其实具备一定可移植性——只要遵循POSIX标准的resolv.h接口,在多数类UNIX系统中都能通过初始化后的_res结构体获取DNS服务器信息,无需依赖系统特定扩展:

#include <resolv.h>
#include <arpa/inet.h>
#include <stdio.h>

void get_resolv_dns() {
    struct __res_state res;
    if (res_ninit(&res) == 0) {
        for (int i = 0; i < res.nscount; i++) {
            printf("DNS Server %d: %s\n", i+1, inet_ntoa(res.nsaddr_list[i].sin_addr));
        }
        res_nclose(&res);
    }
}

这种方法避免了直接访问全局_res变量,线程安全性更好,跨平台兼容性也更强。

4. systemd环境下的DBus接口(针对性方案)

如果目标系统统一使用systemd-resolved,可通过DBus API查询动态更新的DNS配置,适用于现代Linux发行版:

#include <dbus/dbus.h>
#include <stdint.h>

void get_systemd_dns() {
    DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
    if (!conn) return;

    DBusMessage *msg = dbus_message_new_method_call(
        "org.freedesktop.resolve1",
        "/org/freedesktop/resolve1",
        "org.freedesktop.resolve1.Manager",
        "GetLinkDNS"
    );
    uint32_t if_index = 2; // 替换为实际网络接口索引,可通过getifaddrs获取
    dbus_message_append_args(msg, DBUS_TYPE_UINT32, &if_index, DBUS_TYPE_INVALID);

    DBusMessage *reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, NULL);
    if (reply) {
        // 此处可解析回复中的DNS服务器数组,需处理DBus的变体类型
        dbus_message_unref(reply);
    }

    dbus_message_unref(msg);
    dbus_connection_unref(conn);
}

编译时需链接dbus库:gcc your_code.c -ldbus-1


内容的提问来源于stack exchange,提问作者yvs2014

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:37:55