pynetwork / pypcap

pypcap - python libpcap module, forked from code.google.com/p/pypcap
Other
299 stars 75 forks source link

immediate os error in osx and linux platform #12

Closed yangbh closed 8 years ago

yangbh commented 8 years ago

pypcap v1.1.4

in mac osx, if i set immediate=False, can not sniff any packet if i set immediate=True, my code works right

in linux, if i set immediate=True, it will throws this execption File "/root/work/pytscan/pytscan/scan.py", line 735, in pypcapParse pc = pcap.pcap(name=self.iface,immediate=True) File "pcap.pyx", line 210, in pcap.pcap.init (pcap.c:1773) OSError: couldn't enable immediate mode

thank you, guys

brifordwylie commented 8 years ago

@yangbh so this code seems to work fine for me on OSX

import pcap

print 'Opening interface...'
pc = pcap.pcap(promisc=True)
for timestamp, packet in pc: 
    print 'Packet...', repr(packet)

On OSX, if I set immediate=True obviously I get packets right away.. if I don't I have to wait about 45 seconds and then stuff starts spitting out.. I think because I don't see that much traffic on my home network.

On Linux I have to do some defensive coding.. as you often can't get immediate mode...

            try:
                self.pcap = pcap.pcap(name=self.iface_name, promisc=True, immediate=True)
            except OSError:
                try:
                    logging.warning('Could not get immediate mode, turning flag off')
                    self.pcap = pcap.pcap(name=self.iface_name, promisc=True, immediate=False)

The above code is pulled from https://github.com/SuperCowPowers/chains

yangbh commented 8 years ago

@brifordwylie 3ks for answer Your code works fin, but here is another problem.

On Linux, if set immediate=False, pcap.loop() will exit if there is no packet in a few seconds, so i must restart pcap.loop(), but this causes packet loss. Here is my code:

def startloop(timestamp,pkt):
    eth=dpkt.ethernet.Ethernet(pkt)
print eth
        while True:
            try:
                pc.loop(0, startloop)
                nrecv,ndrop,nifdrop=pc.stats()
                logging.warning('%s, %s, %s' % (nrecv,ndrop,nifdrop))
            except Exception,e:
                logging.error(str(e))

Do you have any good idea? Thanks very much.

hellais commented 8 years ago

@yangbh can you check to see if the fix introduce in PR#15 addresses the issues you had?

It will be included inside of a new release of pypcap.

yangbh commented 8 years ago

@hellais yes, it works fine now, thanks very much

hellais commented 8 years ago

@yangbh excellent. I will make a new release of pypcap today then.

guyharris commented 8 years ago

There's no guarantee that you can set immediate mode after you've opened a capture device; it doesn't work on Linux systems using TPACKET_V3 (which will be the case with newer kernels and newer versions of libpcap).

If libpcap has pcap_set_immediate_mode() - which means it also has pcap_create() and pcap_activate() - you can, at open time, set immediate mode by doing:

pcap_t *p;
char errbuf[PCAP_ERRBUF_SIZE];
int status;

p = pcap_create(<device name>, errbuf);
if (p == NULL) {
    /* the attempt failed; errbuf has the error message */
}
pcap_set_timeout(p, <the timeout value>);
pcap_set_snaplen(p, <the snapshot length>);
if (you want immediate mode)
    pcap_set_immediate_mode(p, 1);
status = pcap_activate(p);
if (status < 0) {
    /* the attempt failed */
    if (status == PCAP_ERROR)
        /* pcap_geterr(p) returns an error message */
    else {
        /* pcap_statustostr(p) returns an error message */
        if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
            status == PCAP_ERROR_PERM_DENIED) {
            /* pcap_geterr(p) gives more details, if the string it returns isn't a null string */
        }
    }
}

This works on all UN*Xes, and works on Windows if you have a version of WinPcap/Npcap that supports pcap_set_immediate_mode() (current versions of WinPcap don't).