Não é possível obter o protocolo ao capturar qualquer interface com libpcap [duplicado]

Nov 02 2020

Estou usando o libpcapcódigo para capturar o tráfego de rede no meu Ubuntu com o seguinte código, tenho problema para analisar o protocolo do pacote:

#include <stdio.h> 
#include <stdlib.h> 
#include <stddef.h>
#include <stdio.h>
#include <time.h>
#include <pcap.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>



int main(int argc, char *argv[]) {
    char *device = "any";
    char error_buffer[PCAP_ERRBUF_SIZE];
    pcap_t *handle;
    const u_char *packet;
    struct pcap_pkthdr packet_header;
    int packet_count_limit = 1;
    int timeout_limit = 20000; /* In milliseconds */
    bpf_u_int32 net;
    bpf_u_int32 mask;

    if ( -1 == pcap_lookupnet(device ,&net,&mask,error_buffer))
    printf("error netmask\n");


    /* Open device for live capture */
    handle = pcap_open_live(
            device ,
            BUFSIZ,
            packet_count_limit,
            timeout_limit,
            error_buffer
        );
    if(NULL == handle)
        printf("error! %s\n",error_buffer);
    struct pcap_pkthdr* header;
    u_char *buffer;

    while(1)
    {
    
        int ret  = pcap_next_ex(handle,&header, &buffer);
    if(header->len ==0)
    {
        printf("cont\n");
        continue;

    }

    struct  iphdr *iph = (struct iphdr*) (buffer + sizeof(struct ethhdr));
    printf("protocol = %d \n", iph->protocol);
    }

    return 0;
}

O problema é que quando eu escolho capturar em anyinterfaces char *device = "any";sempre obtenho protocolo = 0

Mas quando escolhi char *device = "ens33";, obtive o protocolo correto (como 6 para TCP)

por que é que ?

Respostas

1 DanielWalker Nov 02 2020 at 00:55

A libpcap irá algumas vezes, dependendo da interface escolhida, substituir o cabeçalho da camada 2 (ethernet, neste caso) por um cabeçalho Linux que não tem o mesmo comprimento de um cabeçalho Ethernet. Você pode verificar o tipo de link de dados do seu pcap_tcom a pcap_datalinkfunção.

unsigned int layer_2_header_length;

switch ( pcap_datalink(handle) ) {
case DLT_EN10MB: // Ethernet header
    layer_2_header_length = 14;
    break;

case DLT_LINUX_SLL: // Linux cooked header
    layer_2_header_length = 16;
    break;

// other options
}