Skip to content

Add pcap_breakloop_flush API #1495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

benzea
Copy link

@benzea benzea commented Mar 27, 2025

I was a it annoyed because tcpdump on Linux can loose a second worth of packets (if there is little traffic and the mmap_v3 API is used). I had this code already, before reading that pcap_breakloop actually even documents this behaviour in a way.

I have not tested this properly. Even the first commit can probably be improved to clear break_loop for all errors.

So for now, more of a request for comments. Are you open to such an API, or do you think it is preferable to stick with the current limitations and let tcpdump work around the problem?

benzea added 2 commits March 27, 2025 13:46
The code is the same everywhere anyway, and there are just a few callers
of read_op that need to deal with this. So let the caller handle it.

This should be a bit nicer overall and will simplify the implementation
to permit breaking the loop in a way that also flushes out the queue.
It is useful to get all the packets up to the current point in time. Due
to input buffering this may not be the case. On Linux with tcpdump, one
can get up to a second worth of packets that are not processed.

Add a new pcap_breakloop_flush and set the internal break_loop variable
to separate values depending on which version of pcap_breakloop was
used. Then, on Linux, keep processing packets without polling if the
break_loop variable is set to PCAPINT_BREAK_FLUSH, but abort immediately
in the PCAPINT_BREAK_IMMEDIATE case.
@infrastation
Copy link
Member

It would help to state the problem in more detail, e.g. to give the steps to reproduce.

@benzea
Copy link
Author

benzea commented Mar 27, 2025

So, the problem here are automated tests that inspect packets after a certain scenario was run.

This could for example be:

  • Start tcpdump on a monitor interface (writing to a file)
  • Ask wpa_supplicant to connect to an AP
  • Wait until wpa_supplicant reports it is connected
  • Stop tcpdump by sending a SIGTERM
  • Inspect whether the captured association and 4-way handshake is well formed

The simple work-around is to add a one or two second delay, but if you forget that you will likely get random failures. But, I feel like such a workaround should not be needed as we are certain that the packet has been received by the kernel already. It is purely missing because tcpdump/libpcap is not flushing them out to the file.

To be more exact, part of the problem is that tcpdump sets a 1000ms timeout. When TPACKET3 is used, then libpcap configures the kernel with this timeout (tp_retire_blk_tov). And that results in the kernel waiting for up to one second before notifying userspace (if the next block is not fully filled with packets). When tcpdump receives the SIGTERM, it simply calls pcap_breakloop() and libpcap never processes these packets even though they must be available already.

@infrastation
Copy link
Member

Thank you. Does this look the same as the problem in #1374?

@benzea
Copy link
Author

benzea commented Mar 27, 2025

Yes, same problem, just worded differently. The proposal from the (currently) last comment is actually quite similar to the one used in my patch.

@infrastation
Copy link
Member

In this case a better solution may be introducing a more generic function for setting flags/options on the pcap_t handle (see the middle of #1375 and the end of #1050).

@benzea
Copy link
Author

benzea commented Mar 27, 2025

In this case a better solution may be introducing a more generic function for setting flags/options on the pcap_t handle …

To me this feels like this is a property of the "break"/"abort" operation rather than the pcap_t. So setting it separately (and in advanced due to signal-safety) seems a bit weird to me. It just isn't as obvious anymore what the pcap_breakloop call will do.

Maybe the internal API might be more interesting to talk about for a start? My approach was to pass a flag to breakloop_op and also store it in the break_loop. One the one hand, that should give the backend the information about what the user intended here. But, with the input stream open, it is hard to define where exactly it should stop.

The idea of closing the input seem nice. I imagine that in the case of the MMAP interface on Linux, this would work perfectly. You close the stream and then read all packets that the kernel has previously prepared in the buffer memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants