Wireshark-users: Re: [Wireshark-users] Pcap library (Portability between linux and windows)

From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Fri, 16 Jan 2009 11:25:14 -0800

On Jan 16, 2009, at 1:58 AM, Benoit wrote:

I don't know if I'm on the good mailing list to post this thread but as this software use correctly the two libraries I thought about posting here.

The right mailing list for libpcap is tcpdump-workers@xxxxxxxxxxx (a bit confusing, perhaps, but as libpcap and tcpdump come from the same group...).

I'm trying to create a protocol (directly on the MAC layer) to communicate between FPGA and PC. And i would like it to be compatible between linux and windows. My code compile and seems to work correctly but the libpcap function doesn't act the same way as the winpcap function.

I want to use the pcap_next_ex() function to look if there is packet on the interface and return if true or after a timeout. It works correctly on windows, however on linux I need to set pcap to non blocking

Why do you need to set it to non-blocking?

and I'm loosing a lot of packet.

The packet capture mechanism libpcap uses on Linux - at least as it's used by libpcap prior to libpcap 1.0.0 - isn't as good at dealing with a high volume of packets.

If you're using libpcap to implement a protocol, you should probably use pcap_compile() and pcap_setfilter() to set a filter that filters out all packets except for the ones for your protocol.

//Open the interface.
#ifdef WIN32
adhandle= pcap_open(ifname, SIZEIB_MTU, PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL,errbuf);
#else
adhandle = pcap_open_live (ifname,SIZEIB_MTU,PCAP_OPENFLAG_PROMISCUOUS,timeout,errbuf);
    pcap_setnonblock(adhandle,timeout,errbuf);
#endif

The pcap_open_live() will work on Windows as well (it's marked as deprecated in some versions of the documentation, but it's not actually deprecated, and it's not marked as deprecated in current versions of the documentation).

Unless your protocol needs to see all traffic on your network, including unicast traffic between two machines other than your machine, you also don't want promiscuous mode - just pass 0, rather than PCAP_OPENFLAG_PROMISCUOUS.

...
while(TRUE) {

#ifdef WIN32
    ret = pcap_next_ex(adhandle, &(header), (const u_char**)(&p_pkt));
#else
    pcap_next_ex(adhandle, &(header), (const u_char**)(&p_pkt));
    ret = header->len;
#endif

That's not correct. pcap_next_ex() returns the same value on every platform - Linux, *BSD, Mac OS X, Solaris, Windows, etc..

You should just do

	ret = pcap_next_ex(adhandle, &(header), (const u_char**)(&p_pkt));

If you're running in non-blocking mode, that loop will consume a lot of CPU time, as it won't wait for packets to arrive.

if(ret > 0) {
     count++;
     printf("pkt %d has size %d\n",count,ret);

That's not right, either - pcap_next_ex() doesn't return the length of the packet, it returns a success/failure indication:

              1      the packet was read without problems

0 packets are being read from a live capture, and the time-
                     out expired

              -1     an error occurred while reading the packet

-2 packets are being read from a ``savefile'', and there are
                     no more packets to read from the savefile.

The length of the packet is header->len.