Skip to content

Commit ee46e7f

Browse files
author
Konur
committed
Use shorter pcap buffer timeout for response capture
dhcp-probe uses response_wait_time as the total window for listening for DHCP/BOOTP replies, enforced by alarm() and pcap_breakloop(). The timeout passed to pcap_open_live(), however, is a packet buffer timeout. When both values are the same, replies can remain buffered inside libpcap until dhcp_probe's alarm fires. In that case pcap_dispatch() can return due to pcap_breakloop() before the buffered reply is delivered to process_response(), causing the alert path to be missed. This is an undesired race condition resulting in the dhcp-probe tool to fail to detect DHCP servers nearly 100 percent of the time (at least on certian networks). Use a shorter pcap buffer timeout derived from response_wait_time so pcap_dispatch() wakes periodically and processes captured replies before the overall response window expires. Change-Id: If4b9d6076447fcecdbe069277325d067dfb0fd55
1 parent ea66e80 commit ee46e7f

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

src/dhcp_probe.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ static const char copyright[] = "Copyright 2000-2021, The Trustees of Princeton
3232
static const char contact[] = "networking at princeton dot edu";
3333
#endif
3434

35+
#define PCAP_PACKET_BUFFER_TIMEOUT_DIVISOR 20
36+
#define PCAP_PACKET_BUFFER_TIMEOUT_MIN_MS 1
37+
3538
/* initialize options to defaults */
3639
int debug = 0;
3740
int dont_fork = 0;
@@ -75,6 +78,9 @@ struct ether_addr my_eaddr;
7578
int use_8021q = 0;
7679
int vlan_id = 0;
7780

81+
/* Forward Declarations */
82+
static int get_pcap_packet_buffer_timeout_ms(void);
83+
7884
int
7985
main(int argc, char **argv)
8086
{
@@ -517,7 +523,7 @@ main(int argc, char **argv)
517523
pcap_open_retries = PCAP_OPEN_LIVE_RETRY_MAX;
518524
while (pcap_open_retries--) {
519525
pcap_errbuf[0] = '\0'; /* so we can tell if a warning was produced on success */
520-
if ((pd = pcap_open_live(ifname, snaplen, promiscuous, GetResponse_wait_time(), pcap_errbuf)) != NULL) {
526+
if ((pd = pcap_open_live(ifname, snaplen, promiscuous, get_pcap_packet_buffer_timeout_ms(), pcap_errbuf)) != NULL) {
521527
break; /* success */
522528
} else { /* failure */
523529
if (pcap_open_retries == 0) {
@@ -1297,3 +1303,22 @@ usage(void)
12971303
return;
12981304
}
12991305

1306+
/*
1307+
* pcap_open_live()'s timeout is a packet buffer timeout, not the
1308+
* total amount of time dhcp_probe should wait for responses. Keep
1309+
* the pcap buffer timeout shorter than response_wait_time so
1310+
* pcap_dispatch() periodically returns and processes any buffered
1311+
* replies before our SIGALRM-based response window expires.
1312+
*/
1313+
static int
1314+
get_pcap_packet_buffer_timeout_ms(void)
1315+
{
1316+
int pcap_timeout;
1317+
1318+
pcap_timeout = GetResponse_wait_time() / PCAP_PACKET_BUFFER_TIMEOUT_DIVISOR;
1319+
1320+
if (pcap_timeout < PCAP_PACKET_BUFFER_TIMEOUT_MIN_MS)
1321+
pcap_timeout = PCAP_PACKET_BUFFER_TIMEOUT_MIN_MS;
1322+
1323+
return pcap_timeout;
1324+
}

0 commit comments

Comments
 (0)