Результаты заголовка TCPNET будут равны нулю

Я пишу несколько строк кода на C, используя libnet и pcap.

Цель состоит в том, чтобы выполнить трехстороннее рукопожатие вручную, отслеживая отфильтрованный трафик на моей сетевой карте, ища пакет SYN и создавая ответ SYN-ACK, используя необработанный сокет ipv4.

Я успешно получаю сырой пакет SYN, используя pcap_loop(),

По моему обычаю packet_handler() Я делаю следующее:

void packet_handler(u_char *user_args, const struct pcap_pkthdr *cap_header, const u_char *packet) {

    struct libnet_ipv4_hdr *ip = (struct libnet_ipv4_hdr *)(packet + LIBNET_ETH_H);
    struct libnet_tcp_hdr *tcp = (struct libnet_tcp_hdr *)(ip + (ip->ip_hl << 2));

    printf(
        "%s:%"PRIu16" > %s:%"PRIu16"\t[seq: %"PRIu32"\tack: %"PRIu32"]\n",
        libnet_addr2name4(ip->ip_src.s_addr, LIBNET_DONT_RESOLVE),
        ntohs(tcp->th_sport),
        libnet_addr2name4(ip->ip_dst.s_addr, LIBNET_DONT_RESOLVE),
        ntohs(tcp->th_dport),
        ntohl(tcp->th_seq), ntohl(tcp->th_ack)
    );
}

В результате открытия TCP-соединения я получил следующий результат:

192.168.1.64:0 > 192.168.1.64:0 [seq: 0 ack: 0]

Как видите, заголовок IP правильно читается, а заголовок TCP - нет. В частности, проблема заключается в libnet_tcp_hdr поля заголовка, которые приводят к нулю.

Я делаю что-то не так в назначении указателя?

1 ответ

Решение

Во-первых, вам нужно убедиться, что ваш обработчик пакетов принимает только IP-пакеты, содержащие TCP, а не, например, UDP.

Тем не менее, ваша арифметика указателя неверна. Арифметика указателя выполняется на основе типа указателя, она не основана на байтах. Это означает, что этот код:

struct libnet_tcp_hdr *tcp = (struct libnet_tcp_hdr *)(ip + (ip->ip_hl << 2));

добавляет ip->ip_hl << 2 * sizeof(struct struct libnet_ipv4_hdr байтов к вашему ip указатель.

Или, если вы посмотрите на это по-другому, приведенный выше код точно такой же, как:

struct libnet_tcp_hdr *tcp = (struct libnet_tcp_hdr *)(&ip[ip->ip_hl << 2]);

Это может показать более четко, что происходит.

Вам нужно изменить этот код на что-то вроде:

struct libnet_tcp_hdr *tcp = (struct libnet_tcp_hdr *)((unsigned char*)ip + (ip->ip_hl << 2));
Другие вопросы по тегам