res_query不遵循res_init,则取消设置

时间:2019-02-16 07:23:54

标签: dns debian glibc resolve

请考虑以下代码,我在这里致电ClickableSpan yourstringClick2 = new ClickableSpan() { @Override public void onClick(View view) { openyourdialoghere() } }; makeLinks(tvLink, new String[]{"your string","your string 2"}, new ClickableSpan[]{ yourstringClick,yourStringClick2 }); ,并将192.168.1.77设置为唯一的名称服务器。但是,当res_init()运行时,显然是在重新执行res_init,然后从resolv.conf返回到前三个名称服务器。

res_query

下面是我们可以看到这种情况的输出:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main (int argc, char *argv[])
{
    u_char nsbuf[4096];
    char dispbuf[4096];
    ns_msg msg;
    ns_rr rr;
    int i, j, l;

    if (argc < 2) {
        printf ("Usage: %s <domain>[...]\n", argv[0]);
        exit (1);
    }
    res_init();
    char str[INET_ADDRSTRLEN];

    for (int i = 0 ; i < _res.nscount; i++){
        inet_ntop(AF_INET,&(_res.nsaddr_list[i].sin_addr.s_addr) , str, INET_ADDRSTRLEN);
        printf("Before:  nameserver %d : %s\n", i,str);
    }

    // set to use 192.168.1.77 as nameserver
     _res.nscount = 1;
     _res.nsaddr_list[0].sin_family = AF_INET;
     _res.nsaddr_list[0].sin_addr.s_addr = inet_addr("192.168.1.77");
     _res.nsaddr_list[0].sin_port = htons(53);

    for (int i = 0 ; i < _res.nscount; i++){
        inet_ntop(AF_INET,&(_res.nsaddr_list[i].sin_addr.s_addr) , str, INET_ADDRSTRLEN);
        printf("After:  nameserver %d : %s\n", i,str);
    }

    for (i = 1; i < argc; i++) {
    printf("ns count before res_query %d\n", _res.nscount);
       l = res_query (argv[i], ns_c_any, ns_t_a, nsbuf, sizeof (nsbuf));
    printf("ns count after res_query %d\n", _res.nscount);

    for (int i = 0 ; i < _res.nscount; i++){
        inet_ntop(AF_INET,&(_res.nsaddr_list[i].sin_addr.s_addr) , str, INET_ADDRSTRLEN);
        printf("After res_query:  nameserver %d : %s\n", i,str);
    }

        if (l < 0) {
            perror (argv[i]);
        } else {
            ns_initparse (nsbuf, l, &msg);
            printf ("---------------------\n%s :\n", argv[i]);
            l = ns_msg_count (msg, ns_s_an);
            for (j = 0; j < l; j++) {
                ns_parserr (&msg, ns_s_an, j, &rr);
                ns_sprintrr (&msg, &rr, NULL, NULL, dispbuf, sizeof (dispbuf));
                printf ("%s\n", dispbuf);
            }
        }
    }

    exit (0);
}

我在做什么错?我该怎么做$ ./a.out cnn.com Before: nameserver 0 : 127.0.0.1 Before: nameserver 1 : 192.168.1.1 Before: nameserver 2 : 1.1.1.1 After: nameserver 0 : 192.168.1.77 ns count before res_query 1 ns count after res_query 3 After res_query: nameserver 0 : 127.0.0.1 /// <----- these... After res_query: nameserver 1 : 192.168.1.1 /// <----- these... After res_query: nameserver 2 : 1.1.1.1 /// <----- these... --------------------- cnn.com : cnn.com. 58S IN A 151.101.129.67 cnn.com. 58S IN A 151.101.1.67 cnn.com. 58S IN A 151.101.65.67 cnn.com. 58S IN A 151.101.193.67 而又不做另一个res_query呢?

更新1

感谢您的详尽而彻底的答复。在下面,我将修改为先调用res_init()然后再调用res_init后,可以保留添加的名称服务器。

但是,更多的是错过:

res_mkquery()

尽管我看到流量达到8.8.8.8。

warm.c

 $ time ./warm cnn.com 8.8.8.8
PACKETSZ: 512
Before:  nameserver 0 : 127.0.0.1
Before:  nameserver 1 : 192.168.1.1
Before:  nameserver 2 : 1.1.1.1
queryLen is 25
setting 8.8.8.8 as nameserver
After:  nameserver 0 : 8.8.8.8
ns count before res_query 1
res_query failed!
ns count after res_query 1
After res_query:  nameserver 0 : 8.8.8.8
cnn.com: Connection timed out
ns count before res_query 1
res_query failed!
ns count after res_query 1
After res_query:  nameserver 0 : 8.8.8.8
8.8.8.8: Connection timed out

real    0m0.131s
user    0m0.008s
sys     0m0.000s

1 个答案:

答案 0 :(得分:1)

Debian 9(拉伸)和更早的版本使用custom, downstream-only patch to automatically reload /etc/resolv.conf if it has changed。编写此补丁的方式只有在调用内部__res_maybe_init函数时才会更新缓存,而res_init则不执行。这意味着对实际解析器功能(例如res_query)的调用会导致__res_maybe_init中的冷缓存,发生重新加载,并且您对_res所做的更改将被丢弃。

上游已实施automatic /etc/resolv.conf reloading glibc 2.26。上游方法非常不同,它尝试处理应用程序的_res修补程序:

  • 有一个统一的缓存,调用res_init会对其进行更新。
  • 如果需要重新加载/etc/resolv.conf,则glibc会检查_res的值是否仍然反映了从/etc/resolv.conf加载的先前值,以及是否值a不同的是,新的/etc/resolv.conf内容未应用 ,并且当前的_res设置不会被覆盖。
  • 有一个新的RES_NORELOAD / noreload解析器选项,它会完全禁用自动重新加载。

这些更改将成为即将发布的Debian版本10(破坏者)的一部分。

如果您不想升级glibc,则可以在修补__res_maybe_init之前触发对_res的调用而不是Debian特定的重载代码覆盖更改的可能性,而不是呼叫res_init。一种无需发送查询即可执行此操作的方法是使用一些伪参数调用res_mkquery。这将预热缓存,并且仅在磁盘上更改/etc/resolv.conf文件时才会重新加载(此时,您的更改仍将被覆盖-我认为无法通过以下方法来防止这种情况:旧的Debian版本)。