Skip Menu |

This queue is for tickets about the Net-Pcap CPAN distribution.

Report information
The Basics
Id: 64878
Status: open
Priority: 0/
Queue: Net-Pcap

People
Owner: Nobody in particular
Requestors: alex [...] digriz.org.uk
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: select() with pcap_dispatch()
Date: Tue, 18 Jan 2011 11:54:14 +0000
To: bug-Net-Pcap [...] rt.cpan.org
From: Alexander Clouter <alex [...] digriz.org.uk>
Hi, I have been working on some code to process some particular IPv6 traffic[1], and want a nice responsive while() loop. To do this I use a combination of select()/pcap_dispatch(). The following is conceptually what I use (stripped of error checking, check the footnote linky for the full version): ---- # not seen a packet larger than 86 bytes # FIXME when set to 86 bytes I get truncated packets of 78 bytes my $SNAPLEN = 96; my $pcap = pcap_open_live($interface, $SNAPLEN, 1, 0, $err); my $pcap_fd = pcap_get_selectable_fd($pcap); # select()/poll() manpage recommends on Linux to use O_NONBLOCK pcap_setnonblock($pcap, 0, \$err); my $sel = ''; vec($sel, $pcap_fd, 1) = 1; my $running = 1; $SIG{'TERM'} = $SIG{'INT'} = sub { print STDERR "received SIG$_[0], closing down\n"; $running = 0; pcap_breakloop($pcap); $SIG{'TERM'} = $SIG{'INT'} = 'DEFAULT'; }; while ($running) { my $rc = select $sel, undef, $sel, undef; if ($rc == -1) { next if ($! == EINTR); print STDERR "select(): $?\n"; exit EX_OSERR; } $rc = pcap_dispatch($pcap, -1, \&pcap_cb, $dpcap); if ($rc < 0) { if ($rc == -1) { print STDERR "pcap_dispatch() failed: " . pcap_geterr($pcap)) . "\n"; exit EX_SOFTWARE; } } } exit EX_OK; sub pcap_cb { my ($rec, $hdr, $pkt) = @_; pcap_dump($rec, $hdr, $pkt) if (defined($rec)); if ($hdr->{'len'} > $hdr->{'caplen'}) { if ($hdr->{'len'} > $SNAPLEN) { print STDERR "phat packet ($hdr->{'len'}), please record and contact author\n"; $SNAPLEN = $hdr->{'len'}; return; } print STDERR "dropping phat packet ($hdr->{'len'})\n"; return; } [do stuff] } ---- For the *first* select() call, when a packet is picked up by Net::Pcap, select() notices the fd can be read from, and so calls pcap_dispatch() with no problems. Once pcap_dispatch() clears out it's buffer, calls to select() pretty much just block forever (even though a simultaneous run of tcpdump alongside shows plenty of additional traffic should be processed). strace'ing the process just shows it hanging on select() as if nothing is appearing on the fd. If I move to using poll() instead, the problem disappears and everything works as expected: ---- my $p = IO::Poll->new; $p->mask($pcap_fd => POLLIN); [snipped] while ($running) { my $rc = $p->poll(); ---- Any ideas what is going wrong? I'm happy to just use poll(), but thought at least a documentation amendment might be called for. I vaguely recall when writing catnip[2], I chose to use poll() instead of select() for a similar reason. I have tried making the socket blockable, no change. Moving to pcap_loop() works, but I notice from an strace internally it uses poll() also; but then pcap_loop() is not suitable for my needs anyway. My guess is an underlying problem in the pcap library (I am using 1.1.1-2 from Debian 'unstable'). Let me know if you need more information. Cheers [1] http://stuff.digriz.org.uk/slaacer [2] http://www.digriz.org.uk/catnip -- Alexander Clouter .sigmonster says: BOFH excuse #189: SCSI's too wide.
Subject: Re: [rt.cpan.org #64878] select() with pcap_dispatch()
Date: Thu, 29 Nov 2012 01:05:34 +0100
To: bug-Net-Pcap [...] rt.cpan.org
From: Sébastien Aperghis-Tramoni <saper [...] cpan.org>
Alexander Clouter wrote via RT: Show quoted text
> Hi,
Hello and sorry for answering late, Show quoted text
> I have been working on some code to process some particular IPv6 > traffic[1], and want a nice responsive while() loop. To do this I use a > combination of select()/pcap_dispatch(). The following is conceptually > what I use (stripped of error checking, check the footnote linky for > the full version): […] > > For the *first* select() call, when a packet is picked up by Net::Pcap, > select() notices the fd can be read from, and so calls pcap_dispatch() > with no problems. Once pcap_dispatch() clears out it's buffer, calls to > select() pretty much just block forever (even though a simultaneous run > of tcpdump alongside shows plenty of additional traffic should be > processed). strace'ing the process just shows it hanging on select() as > if nothing is appearing on the fd.
Given POE::Component::Pcap and AnyEvent::Pcap both work and the reactors underneath use select(), I guess something is missing in your code, but I admit I don't know what. Show quoted text
> If I move to using poll() instead, the problem disappears and > everything works as expected: > ---- > my $p = IO::Poll->new; > $p->mask($pcap_fd => POLLIN); > > [snipped] > > while ($running) { > my $rc = $p->poll(); > ---- > > Any ideas what is going wrong? I'm happy to just use poll(), but > thought at least a documentation amendment might be called for. I > vaguely recall when writing catnip[2], I chose to use poll() instead of > select() for a similar reason. > > I have tried making the socket blockable, no change. Moving to > pcap_loop() works, but I notice from an strace internally it uses poll() > also; but then pcap_loop() is not suitable for my needs anyway. > > My guess is an underlying problem in the pcap library (I am using > 1.1.1-2 from Debian 'unstable').
At least, the problems, if any, should not be in Net::Pcap because most of the functions you are using are directly mapped to the C functions. Sorry for not being a better help. -- Sébastien Aperghis-Tramoni Close the world, txEn eht nepO.