Я пытаюсь получить имя узла записи 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. 15M IN MX 30
alt3.gmail-smtp-in.l.google.com.
Есть ли доступная функция для получения имени хоста, приоритета, ttl и т. Д. В отдельных буферах, как показано ниже?
хост -> alt3.gmail-smtp-in.l.google.com
приоритет -> 30
ттл -> 15 млн
И мы должны вручную проверить запись с более высоким приоритетом,
или есть какая-либо служебная функция или код, который может выполнить требование?
Редактировать:
Я попытался следующий код для извлечения данных
#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-записи он не анализируется корректно, и результатом является следующий результат
Выход:
СР-> gmail.com
Тип-> 15
Class-> 1
TTL-> 130
DataLength-> 32
DataU_char-> gmail-smtp-inlgoogle
len-> 33
DataChar-> Gmail-SMTP-inlgoogle
FullRecord-> gmail.com. 2m10s в MX 30 alt3.gmail-smtp-in.l.google.com.
СР-> gmail.com
Тип-> 15
Class-> 1
TTL-> 130
DataLength-> 9
DataU_char-> alt2 .
len-> 10
DataChar-> alt2.
FullRecord-> gmail.com. 2m10s в MX 20 alt2.gmail-smtp-in.l.google.com.
Так что в DataChar & Специальные символы DataU_char печатаются.
Вместо alt2.gmail-smtp-in.l.google.com печатается «alt2 . ».
Также значение DataLength неверно.
Также я не могу получить приоритет записи.
Я что-то здесь упускаю или это ошибка самой библиотеки c ++?
libresolv
не имеет открытых функций для распаковки определенных типов записей ресурсов, но есть являются функции внутри него, чтобы помочь вам сделать это самостоятельно.
В частности, посмотрите на dn_expand
который может прочитать (сжатое) доменное имя и ns_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-битное поле приоритета.
Других решений пока нет …