Разбор CNAME, NS в DNS, ответ - PullRequest
0 голосов
/ 12 октября 2018

У меня есть следующий код, который проверяет тип запроса в ответе DNS, а затем распечатывает его соответствующим образом.Мне нужен способ разбора CNAME и NS с использованием указанных параметров, но я не могу этого сделать.Здесь tmp - это переменная, определенная как tmp = (u_char *)(dpkt->payload + 12);, а dns_label_to_str - это функция для преобразования DNS-имени в строковый формат, определенный как: *dns_label_to_str(u_char **label, u_char *dest,size_t dest_size,const u_char *payload,const u_char *end)

Код:

   switch (qtype) {
            case 1: /* A */
                    data = inet_ntop(AF_INET, tmp, dbuf, BUFSIZ);
            break;
            case 2:  /* NS */
            case 5:  /* CNAME */
            case 12: /* PTR */
                    data = (char *)dns_label_to_str(
                            &tmp, (u_char *)dbuf, BUFSIZ,
                            dpkt->payload, tmp + len
                    );
            break;
            case 10: /* NULL */
                    data = "NULL";
            break;
            case 15: /* MX (16-bit priority / label) */
                    i = snprintf(dbuf, 7, "%u ", ntohs(*(uint16_t *)tmp));
                    tmp += 2;
                    data = (char *)dns_label_to_str(
                            &tmp, (u_char *)(dbuf + i), BUFSIZ - i,
                            dpkt->payload, tmp + len - 2
                    );
                    data = dbuf;
            break;
            case 16: /* TXT (1 byte text length / text) */
                    if (*tmp <= len && tmp + len < end) {
                            memcpy(dbuf, tmp+1, *tmp);
                            dbuf[*tmp+1] = '\0';
                    } else *dbuf = '\0';
                    data = dbuf;
            break;
            case 17: /* AAAA */
                    data = inet_ntop(AF_INET6, tmp, dbuf, BUFSIZ);
            break;
            default:
                    /* Ignore unhandled RR types */
                    *dbuf = '\0';
                    data = dbuf;
    }

    /* Print the output. */
    printf("%ld %-5s %-30s %s\n", hdr->ts.tv_sec,
           dns_types[qtype], label, data);

ret:
    return 0;
}

Если бы кто-нибудь мог помочь с тем, как я могу получить CNAME, когда qtype == 5 будет полезным.Спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Данные в dpkt->payload + 12 представляют собой раздел вопросов , то есть копию того, что было в исходном запросе, и будет содержать (несжатый) ярлык, известный как QNAME, за которым следует 16-поля QTYPE и QCLASS.

Только после этого вы начнете находить данные ответов, каждая запись которых следует этой структуре из RFC 1035 , раздел 4, в котором яНастоятельно рекомендуем вам прочитать, прежде чем идти дальше:

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                                               /
/                      NAME                     /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     CLASS                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TTL                      |
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                   RDLENGTH                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/                     RDATA                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Обратите внимание, что структура данных в разделе вопросов идентична первым трем полям выше.

0 голосов
/ 12 октября 2018

Мне не совсем понятно, что делает функция dns_label_to_str, но наиболее вероятное значение параметров:

  • label: указатель науказатель.*label изначально указывает на начало имени в пакете и обновляется, чтобы указывать на следующий байт после имени в пакете.
  • dest: адресцелевой буфер.(Это может быть строка (текстовый формат) или несжатое имя (проводной формат).
  • dest: длина буфера назначения. В зависимости от выходного формата функции,это должно быть не менее 256 (проводной формат) или не менее 1024 (текстовый формат из-за экранирования). Конечно, целевой буфер должен быть достаточно большим, t oo.
  • payload: указатель на начало всего DNS-пакета ( не данных текущей записи ресурса!).
  • end: Указатель на один последний байт во всем DNS-пакете.

Причиной, по которой функции типа dns_label_to_str должны ссылаться на весь пакет, является сжатие метки DNS: имена могут содержать ссылку на сжатиекоторый указывает на другое, более раннее место в пакете, повторно используя хвост другого имени в пакете, с меньшим смещением. Эти ссылки никогда не будут указывать в данных записи ресурса, поскольку для записей CNAME он содержит только одно имя: if compression используется, имя tail должно быть откуда-то еще.

EDIT У нас есть небольшая дискуссия в комментариях по поводу указателей прямого сжатия.BIND 9 отклоняет их, но многие другие реализации принимают их.

...