From b8f9530ad6ba3a55f129d259c705d9b5d4d3f4e5 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Wed, 24 Apr 2013 21:55:06 +0200 Subject: [PATCH] dns plugin: Resume after receiving a PCAP_ERROR from pcap_loop(). If an interface goes down while capturing, libpcap returns PCAP_ERROR. Handle this case gracefully. Github: #308 --- src/dns.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/src/dns.c b/src/dns.c index fe3b672a..aea41c43 100644 --- a/src/dns.c +++ b/src/dns.c @@ -208,7 +208,7 @@ static void dns_child_callback (const rfc1035_header_t *dns) pthread_mutex_unlock (&opcode_mutex); } -static void *dns_child_loop (__attribute__((unused)) void *dummy) +static int dns_run_pcap_loop (void) { pcap_t *pcap_obj; char pcap_error[PCAP_ERRBUF_SIZE]; @@ -236,19 +236,24 @@ static void *dns_child_loop (__attribute__((unused)) void *dummy) "failed: %s", (pcap_device != NULL) ? pcap_device : "any", pcap_error); - return (NULL); + return (PCAP_ERROR); } memset (&fp, 0, sizeof (fp)); - if (pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0) < 0) + status = pcap_compile (pcap_obj, &fp, "udp port 53", 1, 0); + if (status < 0) { - ERROR ("dns plugin: pcap_compile failed"); - return (NULL); + ERROR ("dns plugin: pcap_compile failed: %s", + pcap_statustostr (status)); + return (status); } - if (pcap_setfilter (pcap_obj, &fp) < 0) + + status = pcap_setfilter (pcap_obj, &fp); + if (status < 0) { - ERROR ("dns plugin: pcap_setfilter failed"); - return (NULL); + ERROR ("dns plugin: pcap_setfilter failed: %s", + pcap_statustostr (status)); + return (status); } DEBUG ("dns plugin: PCAP object created."); @@ -259,19 +264,30 @@ static void *dns_child_loop (__attribute__((unused)) void *dummy) status = pcap_loop (pcap_obj, -1 /* loop forever */, handle_pcap /* callback */, - NULL /* Whatever this means.. */); - if (status < 0) - ERROR ("dns plugin: Listener thread is exiting " - "abnormally: %s", pcap_geterr (pcap_obj)); - - DEBUG ("dns plugin: Child is exiting."); + NULL /* user data */); + INFO ("dns plugin: pcap_loop exited with status %i.", status); + /* We need to handle "PCAP_ERROR" specially because libpcap currently + * doesn't return PCAP_ERROR_IFACE_NOT_UP for compatibility reasons. */ + if (status == PCAP_ERROR) + status = PCAP_ERROR_IFACE_NOT_UP; pcap_close (pcap_obj); - listen_thread_init = 0; - pthread_exit (NULL); + return (status); +} /* int dns_run_pcap_loop */ + +static void *dns_child_loop (__attribute__((unused)) void *dummy) /* {{{ */ +{ + int status = PCAP_ERROR_IFACE_NOT_UP; + + while (status == PCAP_ERROR_IFACE_NOT_UP) + status = dns_run_pcap_loop (); + if (status != PCAP_ERROR_BREAK) + ERROR ("dns plugin: PCAP returned error %s.", + pcap_statustostr (status)); + listen_thread_init = 0; return (NULL); -} /* static void dns_child_loop (void) */ +} /* }}} void *dns_child_loop */ static int dns_init (void) { -- 2.30.2