PCAP_GET_R...CT_TIMEOUT(3)

πŸ“¦ version 15.1, in freebsd 14.5, freebsd 15.1

πŸ’… pcap_get_required_select_timeout β€” like, the timeout you NEED for select() on a live capture ✨

okay so real talk, this page is pcap_get_required_select_timeout(3) from the Library Functions Manual, and it's lowkey one of those functions that saves your whole event loop. sit down, bestie, we're learning 🫢


✨ SYNOPSIS ✨

#include <pcap/pcap.h>

const struct timeval *pcap_get_required_select_timeout(pcap_t *p);

literally just one function call, no cap. she takes a pcap_t *p and hands you back a const struct timeval *. slay πŸ’–


🌸 DESCRIPTION 🌸

so on UNIX, pcap_get_required_select_timeout() returns a pointer to a struct timeval that contains a value you must use as the minimum timeout in select(2), poll(2), epoll_wait(2), and kevent(2) calls. and if there's no such timeout? you get NULL. periodt.

and hear me on this one πŸ‘‘ β€” if a non-NULL value comes back, you must use it regardless of whether pcap_get_selectable_fd(3) returns -1 for any descriptor on which those calls are being done. like, it doesn't matter what -1 says, the timeout still applies. don't argue with her.

pcap_get_required_select_timeout() should be called for all pcap_ts before a call to select(), poll(), epoll_wait(), or kevent(), and any timeouts used for those calls should be updated as appropriate given the new value of the timeout. yes, that means every single time. it's giving "check your receipts before you check out" 🧾


πŸ¦‹ the kevent() era πŸ¦‹

for kevent(), you can use one EVFILT_TIMER filter per selectable descriptor rather than using the timeout argument to kevent(). and if the EVFILT_TIMER event for a particular selectable descriptor signals an event, pcap_dispatch(3) should be called for the corresponding pcap_t. iconic behaviour honestly 🌈

πŸ“ the Linux timerfd era πŸ“

on Linux systems with timerfd_create(2), you can use one timer object created by timerfd_create() per selectable descriptor rather than using the timeout argument to epoll_wait(). and if the timer object for a particular selectable descriptor signals an event, pcap_dispatch(3) should be called for the corresponding pcap_t. same energy, different syscall ✨

πŸ’œ otherwise (aka the "we ball" path) πŸ’œ

otherwise, you use a timeout value no larger than the smallest of all the timeouts returned by pcap_get_required_select_timeout() for devices from which packets will be captured, plus any other timeouts to be used in the call β€” that's your timeout for the call. and when the call returns, pcap_dispatch(3) should be called for all pcap_ts for which a non-NULL timeout was returned, regardless of whether it's indicated as having anything to read from it or not. like, even if it says "nope, nothing here," you still call her. respect the process πŸ’…

⚠️ important bestie note: all devices with a non-NULL timeout must be put in non-blocking mode with pcap_setnonblock(3). no exceptions, no vibes-based workarounds.

and one more lil heads-up πŸ™ˆ β€” a device on which a read can be done without blocking may, on some platforms, not have any packets to read if the packet buffer timeout has expired. a call to pcap_dispatch() or pcap_next_ex(3) will return 0 in this case, but will not block. so like, 0 doesn't mean broken, it means "buffer said no" 😭

πŸ’€ also pcap_get_required_select_timeout() is not available on Windows. sad but true.

πŸŽ€ RETURN VALUE πŸŽ€

a pointer to a struct timeval is returned if the timeout is required; otherwise NULL is returned. that's the whole thing. clean, simple, gorgeous ⭐


πŸ”₯ BACKWARD COMPATIBILITY πŸ”₯

this function became available in libpcap release 1.9.0. before that? in previous releases, select(), poll(), epoll_wait(), and kevent() could not be used for devices that don't provide a selectable file descriptor β€” in other words, on any capture source for that pcap_get_selectable_fd() returns -1. rough times, glad we're past them πŸ•―οΈ

in libpcap release 1.10.0 and later, the timeout value can change from call to call, so pcap_get_required_select_timeout() must be called before each call to select(), poll(), epoll_wait(), or kevent(), and the new value must be used to calculate timeouts for the call. so like, cache it once and you're cooked πŸ’€

code that does that will also work with libpcap 1.9.x releases, so code using pcap_get_required_select_timeout() should be changed to call it for each call to select(), poll(), epoll_wait(), or kevent() even if the code must also work with libpcap 1.9.x. future-proofing is self-care, bestie πŸ’–


🌈 SEE ALSO 🌈


okay that's the page!! this one's from the Library Functions Manual, dated 29 January 2020, and the header up top was PCAP_GET_R...CT_TIMEOUT(3) β€” yes they truncated it, no I don't know why, and honestly? we move πŸŽ€πŸ’…βœ¨ go call your timeouts, ily, bye πŸ¦‹

πŸ“¦ where this page comes from