0

I tried to read in the raw packet with libpcap (1.4.0 on CentOS 6).

However, for some reasons, rawPacket is always NULL after pcap_next_ex().

However, pcap_next_ex() does return 1 though it could mean timeout expired (where the timeout is set by the way?).

First, I thought that the filter string I passed into pcap_compile() was wrong. But I tried to copy and paste the same string to tcpdump, it worked fine -- I see expected packets being captured.


    struct pcap_pkthdr *pHeader;
    const u_char* rawPacket = NULL;
    int rc = 0;
    while (1) {
        rc = pcap_next_ex(pDevice, &pHeader, &rawPacket);
        if (-1 != rc && NULL != rawPacket) {
            // process
            struct ether_header* eptr = (struct ether_header *) rawPacket;
            if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
                    printf("Ethernet type hex:%x dec:%d is an IP packet\n",
                            ntohs(eptr->ether_type),
                            ntohs(eptr->ether_type));
            }
        }
    }


Any idea?

Thanks in advance.

Hei
  • 1,844
  • 3
  • 21
  • 35
  • Are you sure that the packets were captured prior to calling pcap_next_ex or maybe the data wasn't transferred yet? What if you try compiling it with an empty filter? – in need of help Feb 06 '14 at 15:19

1 Answers1

0

Actually, what the pcap_next_ex() man page says is

   pcap_next_ex() returns 1 if the packet was read without problems, 0  if
   packets are being read from a live capture, and the timeout expired, -1
   if an error occurred while reading the packet, and -2  if  packets  are
   being  read  from a ``savefile'', and there are no more packets to read
   from the savefile.  If -1 is returned, pcap_geterr()  or  pcap_perror()
   may be called with p as an argument to fetch or display the error text.

I need to edit it to remove the comment between "live capture" and "and the timeout expired", because what that means is that pcap_next_ex() returns:

  • 1, if a packet was read or captured, in which case the pointer should be set to the raw packet;
  • 0, if this is a live capture and the timeout (as specified in pcap_open_live() or, if you used pcap_create() and pcap_activate(), pcap_set_timeout()) expired while waiting for a packet, in which case no packet was read and the pointer will be set to NULL;
  • -1, if an error occurred while reading or capturing, in which case no packet was read and the pointer will be set to NULL;
  • -2, if this is a file being read and there are no more packets left to be read, in which case no packet was read and the pointer will be set to NULL.

So what you should do, after the pcap_next_ex() call, is:

    if (1 == rc) {
        // process
        struct ether_header* eptr = (struct ether_header *) rawPacket;
        if (ntohs (eptr->ether_type) == ETHERTYPE_IP) {
                printf("Ethernet type hex:%x dec:%d is an IP packet\n",
                        ntohs(eptr->ether_type),
                        ntohs(eptr->ether_type));
        }
    } else if (0 == rc) {
        // do nothing here - this isn't an error, but you have no packet
        ;
    } else if (-1 == rc) {
        // error
        fprintf(stderr, "Error capturing or reading: %s\n", pcap_geterr(pDevice));
        // quit trying to read or capture packets here
    } else if (-2 == rc) {
        // end of file if you're reading from a file
        // this isn't an error, but there are no more packets to read
        // so quit trying to read packets here
    }