Результаты заголовка 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));