从名称服务器回复c ++

时间:2016-12-29 12:32:53

标签: c++ dns mail-server nslookup

我正在尝试使用以下代码获取具有低优先级的MX记录的主机名,但我无法从给定的名称服务器回复中解析所需的详细信息(主机名,ttl,优先级)。

u_char nsbuf[4096], dispbuf[4096];
ns_msg msg;
ns_rr rr;
int i, j, l;
std::string domain("gmail.com");
l = res_query(domain.c_str(), ns_c_any, ns_t_mx, nsbuf, sizeof (nsbuf));

    ns_initparse(nsbuf, l, &msg);
    printf("%s :\n", domain.c_str());
    l = ns_msg_count(msg, ns_s_an);
    for (j = 0; j < l; j++)
    {
        int prr = ns_parserr(&msg, ns_s_an, j, &rr);


        ns_sprintrr(&msg, &rr, NULL, NULL, reinterpret_cast<char*> (dispbuf), sizeof (dispbuf));

        printf("%s\n", dispbuf);
    }

上面的代码将结果显示为

  

gmail.com。 MX M 15M   alt3.gmail-smtp-in.l.google.com。

是否有任何可用的功能可以在下面的单独缓冲区中获取主机名,优先级,ttl等?

  

主持人 - &gt; alt3.gmail-smtp-in.l.google.com

     

优先级 - &gt; 30

     

ttl - &gt; 15M

而且,我们应该手动检查更高优先级的记录, 或者是否有任何可以满足要求的效用函数或代码?

修改

我尝试了以下代码来提取数据

#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <resolv.h>
#include <cstring>
#include <string>
#include <string.h>

using namespace std;
int main(int argc, char** argv) {

    u_char nsbuf[4096];
    u_char dispbuf[4096];
    ns_msg msg;
    ns_rr rr;
    int i, j, l;
    std::string domain("gmail.com");
    l = res_query(domain.c_str(), ns_c_any, ns_t_mx, nsbuf, sizeof (nsbuf));
    if (l < 0) {
        perror(domain.c_str());
    } else {
#ifdef USE_PQUERY
        res_pquery(&_res, nsbuf, l, stdout);
#else
        ns_initparse(nsbuf, l, &msg);
        l = ns_msg_count(msg, ns_s_an);
        for (j = 0; j < l; j++) {
            int prr = ns_parserr(&msg, ns_s_an, j, &rr);

            //BLOCK 1
            char *cp;
            cp = (char *) ns_rr_name(rr);
            printf("CP->%s\n", (char *) cp);
            int i1 = ns_rr_type(rr);
            printf("Type->%d\n", i1);
            int i2 = ns_rr_class(rr);
            printf("Class->%d\n", i2);
            int i3 = ns_rr_ttl(rr);
            printf("TTL->%d\n", i3);
            int i4 = ns_rr_rdlen(rr);
            printf("DataLength->%d\n", i4);

            //BLOCK 2
            const u_char *rdata = ns_rr_rdata(rr) +1;
            printf("DataU_char-> %s\n", reinterpret_cast<const char*> (rdata));

            int len = strlen(reinterpret_cast<const char*> (rdata));
            printf("len->%d\n", len);

            char rdatatemp[1024];
            strncpy(rdatatemp, reinterpret_cast<const char*> (rdata), sizeof (rdatatemp));
            printf("DataChar->%s\n", rdatatemp);

            ns_sprintrr(&msg, &rr, NULL, NULL, reinterpret_cast<char*> (dispbuf), sizeof (dispbuf));
            printf("FullRecord->%s\n", dispbuf);
            printf("\n");
        }
#endif
    }
    return 0;
}

上面的代码适用于txt记录,但是对于mx记录,它没有被正确解析,结果如下

输出:

CP-&GT; gmail.com
型 - →15个
讲座→1个
TTL-&GT; 130个
DataLength-&GT; 32个
DataU_char-&GT; Gmail的-SMTP-inlgoogle
len-&GT; 33
DataChar-&GT;的Gmail-SMTP-inlgoogle
FullRecord-&GT; gmail.com。 2m10s IN MX 30 alt3.gmail-smtp-in.l.google.com。

CP-&GT; gmail.com
型 - →15个
讲座→1个
TTL-&GT; 130个
DataLength-&GT; 9
DataU_char-&GT; ALT2。
len-→10
DataChar-&GT; ALT2
。 FullRecord-&GT; gmail.com。 2m10s IN MX 20 alt2.gmail-smtp-in.l.google.com。

所以在DataChar&amp;打印DataU_char特殊符号。
打印'alt2 . '而不是'alt2.gmail-smtp-in.l.google.com。'
DataLength值也是错误的 此外,我无法获得记录的优先权 我在这里遗漏了什么,还是c ++库本身的错误?

1 个答案:

答案 0 :(得分:1)

libresolv没有公开的功能来解压缩特定的资源记录类型,但中有函数可以帮助您自己完成。

特别是,查看可以读取(压缩)域名的dn_expandns_get16,它将从记录中读取一个大端的两个八位字节字段,所以在你的情况下:

char exchange[NS_MAXDNAME];

const u_char *rdata = ns_rr_rdata(rr);

const uint16_t pri = ns_get16(rdata);
int len = dn_expand(nsbuf, nsbuf + msg_len, rdata + 2, exchange, sizeof(exchange));

printf("Pri->%d\n", pri);
printf("Exchange->%s\n", exchange);

其中msg_len替换了覆盖的l变量,其中包含接收数据包的长度。

rdata + 2调用中的dn_expand()会跳过16位优先级字段。