pynetwork/pypcap

Nonblocking option isn't available for MacOS because pcap.h file is parsed incorrectly

tzhenghao opened this issue · 3 comments

The pypcap library doesn't support nonblocking mode when fully built on MacOS version 10.13.4.

I see how pcap.h source files / dependencies are found via setup.py:

def get_extension():
    # A list of all the possible search directories
    dirs = ['/usr', sys.prefix] + glob.glob('/opt/libpcap*') + \
        glob.glob('../libpcap*') + glob.glob('../wpdpack*') + \
        glob.glob('/Applications/Xcode.app/Contents/Developer/Platforms/' +
                  'MacOSX.platform/Developer/SDKs/*')

    for d in dirs:
        search_dirs = [
            os.path.join(d, 'local', 'include'),
            os.path.join(d, 'usr', 'include'),
            os.path.join(d, 'include'),
            d
        ]

        pcap_h = recursive_search_dirs(search_dirs, ['pcap.h'])
        if pcap_h:
            print("Found pcap headers in %s" % pcap_h)
            break

    if not pcap_h:
        print("pcap.h not found")
        sys.exit(1)

    include_dirs = [os.path.dirname(pcap_h)]

My /usr/include/pcap.h has this:
#include <pcap/pcap.h>

while my /usr/include/pcap/pcap.h has this:

PCAP_API int    pcap_setdirection(pcap_t *, pcap_direction_t);                  
PCAP_API int    pcap_getnonblock(pcap_t *, char *);                                                                                                                       
PCAP_API int    pcap_setnonblock(pcap_t *, int, char *);                        
PCAP_API int    pcap_inject(pcap_t *, const void *, size_t);

Unfortunately, I believe you're looking for the function signatures in the wrong file (/usr/include/pcap.h), and that file in turn includes a separate header with the function signatures you're looking for.

I confirmed this too by running:

>>> from setup import get_extension
>>> get_extension()
Found pcap headers in /usr/include/pcap.h
Found libraries in /usr/lib/libpcap.dylib
<setuptools.extension.Extension('pcap') at 0x10e812160>

Nothing using libpcap should assume that /usr/include/pcap.h does anything other than include pcap/pcap.h; libpcap releases have worked that way for a while, so this is not macOS-specific - you'll see that on current Linux distributions and *BSDs as well, for example.

It should also, ideally, not assume that /usr/include/pcap.h does nothing other than include pcap/pcap.h, so that it supports older releases as well.

I have been struggling with this problem recently on Ubuntu 16.04 Server. timeout_ms and setnonblock() have no effect when calling __next__(). I modified the setup file to point to /usr/include/pcap/pcap.h and observed the "found * function" messages. But the module behaves the same. I also notices that getnonblock() returns False regardless of what is passed into setnonblock().