If we have pcap_breakloop(), at least on UN*X we can stop the capture
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 21 May 2006 21:32:04 +0000 (21:32 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Sun, 21 May 2006 21:32:04 +0000 (21:32 +0000)
with a pcap_breakloop() call - we don't need to call select() before
calling pcap_dispatch().

Even if we do need to call select(), we don't need to supply it with a
timeout - it's OK if we block indefinitely, as the signal will interrupt
select().

That also means we can pass -1 as the count to pcap_dispatch(), as
pcap_breakloop() will terminate the loop in pcap_dispatch().

Use sigaction() to catch SIGUSR1, so we can make sure that the signal
handler doesn't get reset when the signal is delivered, and that system
calls don't restart when we return from the signal handler.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@18201 f5534014-38df-0310-8fa8-9805f1628bb7

Makefile.nmake
acinclude.m4
capture-wpcap.c
capture_loop.c
capture_loop.h
config.h.win32
config.nmake

index 5ab48184802ec7638904314d64574ee28cddd85f..ef6bf13272cbf255869e4a48e4969c69273b1b81 100644 (file)
@@ -229,6 +229,7 @@ config.h    : config.h.win32 config.nmake
            -e "s/@HAVE_PCAP_FINDALLDEVS@/$(PCAP_FINDALLDEVS_CONFIG)/" \
            -e "s/@HAVE_PCAP_DATALINK_NAME_TO_VAL@/$(PCAP_DATALINK_NAME_TO_VAL_CONFIG)/" \
            -e "s/@HAVE_PCAP_DATALINK_VAL_TO_NAME@/$(PCAP_DATALINK_VAL_TO_NAME_CONFIG)/" \
+           -e "s/@HAVE_PCAP_BREAKLOOP@/$(PCAP_BREAKLOOP_CONFIG)/" \
            -e "s/@HAVE_LIBETHEREALDLL@/$(LIBETHEREAL_CONFIG)/" \
            -e "s/@WPCAP_CONSTIFIED@/$(WPCAP_CONSTIFIED_CONFIG)/" \
            -e "s/@HAVE_GNUTLS@/$(GNUTLS_CONFIG)/" \
index e831c7372b8907efaaab118e153211cc848c1913..df4e712543a9d3071851a5cf2a96e7068ae9e388 100644 (file)
@@ -437,7 +437,7 @@ and did you also install that package?]]))
        else
                AC_MSG_RESULT(no)
        fi
-       AC_CHECK_FUNCS(pcap_open_dead pcap_freecode)
+       AC_CHECK_FUNCS(pcap_open_dead pcap_freecode pcap_breakloop)
        #
        # Later versions of Mac OS X 10.3[.x] ship a pcap.h that
        # doesn't define pcap_if_t but ship an 0.8[.x] libpcap,
index ebff52e05eb1a0d48950f52448b8fa2e43527f7b..bb0606735222c62c9b48ea5bbead15c33153401d 100644 (file)
@@ -49,6 +49,11 @@ gboolean has_wpcap = FALSE;
 
 #ifdef HAVE_LIBPCAP
 
+/*
+ * XXX - should we require at least WinPcap 3.1 both for building an
+ * for using Wireshark?
+ */
+
 static char*   (*p_pcap_lookupdev) (char *);
 static void    (*p_pcap_close) (pcap_t *);
 static int     (*p_pcap_stats) (pcap_t *, struct pcap_stat *);
@@ -80,6 +85,9 @@ static int (*p_pcap_datalink_name_to_val) (const char *);
 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
 static const char *(*p_pcap_datalink_val_to_name) (int);
 #endif
+#ifdef HAVE_PCAP_BREAKLOOP
+static void    (*p_pcap_breakloop) (pcap_t *);
+#endif
 static const char *(*p_pcap_lib_version) (void);
 static int     (*p_pcap_setbuff) (pcap_t *, int dim);
 static int     (*p_pcap_next_ex) (pcap_t *, struct pcap_pkthdr **pkt_header, const u_char **pkt_data);
@@ -120,6 +128,14 @@ load_wpcap(void)
 #endif
 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
                SYM(pcap_datalink_val_to_name, TRUE),
+#endif
+#ifdef HAVE_PCAP_BREAKLOOP
+               /*
+                * We don't try to work around the lack of this at
+                * run time; it's present in WinPcap 3.1, which is
+                * the version we build with and ship with.
+                */
+               SYM(pcap_breakloop, FALSE),
 #endif
                SYM(pcap_lib_version, TRUE),
                SYM(pcap_setbuff, TRUE),
@@ -422,6 +438,13 @@ pcap_datalink_val_to_name(int dlt)
 }
 #endif
 
+#ifdef HAVE_PCAP_BREAKLOOP
+void pcap_breakloop(pcap_t *a)
+{
+       p_pcap_breakloop(a);
+}
+#endif
+
 /* setbuff is win32 specific! */
 int pcap_setbuff(pcap_t *a, int b)
 {
index 16d32bb3507d64627a4153e4c0a687e1c3b42598..02508fc46d352213bf4ea3b9e3d347e0be7befa5 100644 (file)
@@ -811,154 +811,154 @@ capture_loop_dispatch(capture_options *capture_opts _U_, loop_data *ld,
 #endif
 
 #ifndef _WIN32
-    if (ld->from_cap_pipe) {
-      /* dispatch from capture pipe */
+  if (ld->from_cap_pipe) {
+    /* dispatch from capture pipe */
 #ifdef LOG_CAPTURE_VERBOSE
-      g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe");
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe");
 #endif
+    FD_ZERO(&set1);
+    FD_SET(ld->cap_pipe_fd, &set1);
+    timeout.tv_sec = 0;
+    timeout.tv_usec = CAP_READ_TIMEOUT*1000;
+    sel_ret = select(ld->cap_pipe_fd+1, &set1, NULL, NULL, &timeout);
+    if (sel_ret <= 0) {
+      inpkts = 0;
+      if (sel_ret < 0 && errno != EINTR) {
+        g_snprintf(errmsg, errmsg_len,
+          "Unexpected error from select: %s", strerror(errno));
+        report_capture_error(errmsg, please_report);
+        ld->go = FALSE;
+      }
+    } else {
+      /*
+       * "select()" says we can read from the pipe without blocking
+       */
+      inpkts = cap_pipe_dispatch(ld, pcap_data, errmsg, errmsg_len);
+      if (inpkts < 0) {
+        ld->go = FALSE;
+      }
+    }
+  }
+  else
+#endif /* _WIN32 */
+  {
+    /* dispatch from pcap */
+#ifdef MUST_DO_SELECT
+    /*
+     * If we have "pcap_get_selectable_fd()", we use it to get the
+     * descriptor on which to select; if that's -1, it means there
+     * is no descriptor on which you can do a "select()" (perhaps
+     * because you're capturing on a special device, and that device's
+     * driver unfortunately doesn't support "select()", in which case
+     * we don't do the select - which means it might not be possible
+     * to stop a capture until a packet arrives.  If that's unacceptable,
+     * plead with whoever supplies the software for that device to add
+     * "select()" support, or upgrade to libpcap 0.8.1 or later, and
+     * rebuild Ethereal or get a version built with libpcap 0.8.1 or
+     * later, so it can use pcap_breakloop().
+     */
+#ifdef LOG_CAPTURE_VERBOSE
+    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select");
+#endif
+    if (ld->pcap_fd != -1) {
       FD_ZERO(&set1);
-      FD_SET(ld->cap_pipe_fd, &set1);
-      timeout.tv_sec = 0;
-      timeout.tv_usec = CAP_READ_TIMEOUT*1000;
-      sel_ret = select(ld->cap_pipe_fd+1, &set1, NULL, NULL, &timeout);
-      if (sel_ret <= 0) {
-       inpkts = 0;
+      FD_SET(ld->pcap_fd, &set1);
+      sel_ret = select(ld->pcap_fd+1, &set1, NULL, NULL, NULL);
+      if (sel_ret > 0) {
+        /*
+         * "select()" says we can read from it without blocking; go for
+         * it.
+         *
+         * We don't have pcap_breakloop(), so we only process one packet
+         * per pcap_dispatch() call, to allow a signal to stop the
+         * processing immediately, rather than processing all packets
+         * in a batch before quitting.
+         */
+        inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *)ld);
+        if (inpkts < 0) {
+          ld->pcap_err = TRUE;
+          ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */
+        }
+      } else {
+        inpkts = 0;
         if (sel_ret < 0 && errno != EINTR) {
           g_snprintf(errmsg, errmsg_len,
             "Unexpected error from select: %s", strerror(errno));
           report_capture_error(errmsg, please_report);
           ld->go = FALSE;
         }
-      } else {
-       /*
-        * "select()" says we can read from the pipe without blocking
-        */
-       inpkts = cap_pipe_dispatch(ld, pcap_data, errmsg, errmsg_len);
-       if (inpkts < 0) {
-         ld->go = FALSE;
-        }
       }
     }
     else
-#endif /* _WIN32 */
-    {
-      /* dispatch from pcap */
-#ifdef MUST_DO_SELECT
-      /*
-       * Sigh.  The semantics of the read timeout argument to
-       * "pcap_open_live()" aren't particularly well specified by
-       * the "pcap" man page - at least with the BSD BPF code, the
-       * intent appears to be, at least in part, a way of cutting
-       * down the number of reads done on a capture, by blocking
-       * until the buffer fills or a timer expires - and the Linux
-       * libpcap doesn't actually support it, so we can't use it
-       * to break out of the "pcap_dispatch()" every 1/4 of a second
-       * or so.  Linux's libpcap is not the only libpcap that doesn't
-       * support the read timeout.
-       *
-       * Furthermore, at least on Solaris, the bufmod STREAMS module's
-       * read timeout won't go off if no data has arrived, i.e. it cannot
-       * be used to guarantee that a read from a DLPI stream will return
-       * within a specified amount of time regardless of whether any
-       * data arrives or not.
-       *
-       * Thus, on all platforms other than BSD, we do a "select()" on the
-       * file descriptor for the capture, with a timeout of CAP_READ_TIMEOUT
-       * milliseconds, or CAP_READ_TIMEOUT*1000 microseconds.
-       *
-       * "select()", on BPF devices, doesn't work as you might expect;
-       * at least on some versions of some flavors of BSD, the timer
-       * doesn't start until a read is done, so it won't expire if
-       * only a "select()" or "poll()" is posted.
-       *
-       * If we have "pcap_get_selectable_fd()", we use it to get the
-       * descriptor on which to select; if that's -1, it means there
-       * is no descriptor on which you can do a "select()" (perhaps
-       * because you're capturing on a special device, and that device's
-       * driver unfortunately doesn't support "select()", in which case
-       * we don't do the select - which means Ethereal might block,
-       * unable to accept user input, until a packet arrives.  If
-       * that's unacceptable, plead with whoever supplies the software
-       * for that device to add "select()" support.
-       */
-#ifdef LOG_CAPTURE_VERBOSE
-      g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch with select");
-#endif
-      if (ld->pcap_fd != -1) {
-        FD_ZERO(&set1);
-        FD_SET(ld->pcap_fd, &set1);
-        timeout.tv_sec = 0;
-        timeout.tv_usec = CAP_READ_TIMEOUT*1000;
-        sel_ret = select(ld->pcap_fd+1, &set1, NULL, NULL, &timeout);
-        if (sel_ret > 0) {
-          /*
-           * "select()" says we can read from it without blocking; go for
-           * it.
-           */
-          inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *)ld);
-          if (inpkts < 0) {
-            ld->pcap_err = TRUE;
-            ld->go = FALSE;
-          }
-        } else {
-          inpkts = 0;
-          if (sel_ret < 0 && errno != EINTR) {
-            g_snprintf(errmsg, errmsg_len,
-              "Unexpected error from select: %s", strerror(errno));
-            report_capture_error(errmsg, please_report);
-            ld->go = FALSE;
-          }
-        }
-      }
-      else
 #endif /* MUST_DO_SELECT */
-      {
-        /* dispatch from pcap without select */
+    {
+      /* dispatch from pcap without select */
 #if 1
 #ifdef LOG_CAPTURE_VERBOSE
-        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch");
+      g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_dispatch");
 #endif
-        inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *) ld);
-        if (inpkts < 0) {
+#ifdef _WIN32
+      /*
+       * On Windows, we don't support asynchronously telling a process to
+       * stop capturing; instead, we check for an indication on a pipe
+       * after processing packets.  We therefore process only one packet
+       * at a time, so that we can check the pipe after every packet.
+       */
+      inpkts = pcap_dispatch(ld->pcap_h, 1, ld->packet_cb, (u_char *) ld);
+#else
+      inpkts = pcap_dispatch(ld->pcap_h, -1, ld->packet_cb, (u_char *) ld);
+#endif
+      if (inpkts < 0) {
+        if (inpkts == -1) {
+          /* Error, rather than pcap_breakloop(). */
           ld->pcap_err = TRUE;
-          ld->go = FALSE;
         }
-#else
-        {
+        ld->go = FALSE; /* error or pcap_breakloop() - stop capturing */
+      }
+#else /* pcap_next_ex */
 #ifdef LOG_CAPTURE_VERBOSE
-            g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_next_ex");
+      g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from pcap_next_ex");
 #endif
-            /* XXX - this is currently unused, as there is some confusion with pcap_next_ex() vs. pcap_dispatch() */
-
-            /* WinPcap's remote capturing feature doesn't work, see http://wiki.ethereal.com/CaptureSetup_2fWinPcapRemote */
-            /* for reference, an example remote interface: rpcap://[1.2.3.4]/\Device\NPF_{39993D68-7C9B-4439-A329-F2D888DA7C5C} */
+      /* XXX - this is currently unused, as there is some confusion with pcap_next_ex() vs. pcap_dispatch() */
 
-            /* emulate dispatch from pcap */
-            int in;
-            struct pcap_pkthdr *pkt_header;
-                   u_char *pkt_data;
+      /*
+       * WinPcap's remote capturing feature doesn't work with pcap_dispatch(),
+       * see http://wiki.ethereal.com/CaptureSetup_2fWinPcapRemote
+       * This should be fixed in the WinPcap 4.0 alpha release.
+       *
+       * For reference, an example remote interface:
+       * rpcap://[1.2.3.4]/\Device\NPF_{39993D68-7C9B-4439-A329-F2D888DA7C5C}
+       */
 
-            inpkts = 0;
-            while( (in = pcap_next_ex(ld->pcap_h, &pkt_header, &pkt_data)) == 1) {
-                ld->packet_cb( (u_char *) ld, pkt_header, pkt_data);
-                inpkts++;
-            }
+      /* emulate dispatch from pcap */
+      {
+        int in;
+        struct pcap_pkthdr *pkt_header;
+        u_char *pkt_data;
+
+        inpkts = 0;
+        in = 0;
+        while(ld->go &&
+              (in = pcap_next_ex(ld->pcap_h, &pkt_header, &pkt_data)) == 1) {
+          ld->packet_cb( (u_char *) ld, pkt_header, pkt_data);
+          inpkts++;
+        }
 
-            if(in < 0) {
-              ld->pcap_err = TRUE;
-              ld->go = FALSE;
-              inpkts = in;
-            }
+        if(in < 0) {
+          ld->pcap_err = TRUE;
+          ld->go = FALSE;
+          inpkts = in;
         }
-#endif
       }
+#endif /* pcap_next_ex */
     }
+  }
 
 #ifdef LOG_CAPTURE_VERBOSE
-    g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: %d new packet%s", inpkts, plurality(inpkts, "", "s"));
+  g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: %d new packet%s", inpkts, plurality(inpkts, "", "s"));
 #endif
 
-    return inpkts;
+  return inpkts;
 }
 
 
@@ -1069,6 +1069,9 @@ capture_loop_stop_signal_handler(int signo _U_)
 int
 capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
 {
+#ifndef _WIN32
+  struct sigaction act;
+#endif
   time_t      upd_time, cur_time;
   time_t      start_time;
   int         err_close;
@@ -1116,8 +1119,16 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
    * Catch SIGUSR1, so that we exit cleanly if the parent process
    * kills us with it due to the user selecting "Capture->Stop".
    */
-  signal(SIGUSR1, capture_loop_stop_signal_handler);
-#endif
+  act.sa_handler = capture_loop_stop_signal_handler;
+  /*
+   * Arrange that system calls not get restarted, because when
+   * our signal handler returns we don't want to restart
+   * a call that was waiting for packets to arrive.
+   */
+  act.sa_flags = 0;
+  sigemptyset(&act.sa_mask);
+  sigaction(SIGUSR1, &act, NULL);
+#endif /* _WIN32 */
 
   g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_INFO, "Capture loop starting ...");
   capture_opts_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, capture_opts);
@@ -1452,7 +1463,11 @@ error:
 
 void capture_loop_stop(void)
 {
-    ld.go = FALSE;
+#ifdef HAVE_PCAP_BREAKLOOP
+  pcap_breakloop(ld.pcap_h);
+#else
+  ld.go = FALSE;
+#endif
 }
  
 
@@ -1542,4 +1557,3 @@ capture_loop_packet_cb(u_char *user, const struct pcap_pkthdr *phdr,
 }
 
 #endif /* HAVE_LIBPCAP */
-
index c0a91e2e24c9be6875831892c23fd931a6c8402b..839ba528b97515504a5a7f3883fe8c63651be113 100644 (file)
@@ -51,28 +51,49 @@ extern void capture_loop_stop(void);
 /*** the following is internal only (should be moved to capture_loop_int.h) ***/
 
 
+#ifndef HAVE_PCAP_BREAKLOOP
 /*
- * We don't want to do a "select()" on the pcap_t's file descriptor on
- * BSD (because "select()" doesn't work correctly on BPF devices on at
- * least some releases of some flavors of BSD), and we don't want to do
- * it on Windows (because "select()" is something for sockets, not for
- * arbitrary handles).  (Note that "Windows" here includes Cygwin;
- * even in its pretend-it's-UNIX environment, we're using WinPcap, not
- * a UNIX libpcap.)
+ * We don't have pcap_breakloop(), which is the only way to ensure that
+ * pcap_dispatch(), pcap_loop(), or even pcap_next() or pcap_next_ex()
+ * won't, if the call to read the next packet or batch of packets is
+ * is interrupted by a signal on UN*X, just go back and try again to
+ * read again.
  *
- * We *do* want to do it on other platforms, as, on other platforms (with
- * the possible exception of Ultrix and Digital UNIX), the read timeout
- * doesn't expire if no packets have arrived, so a "pcap_dispatch()" call
- * will block until packets arrive, causing the UI to hang.
+ * On UN*X, we catch SIGUSR1 as a "stop capturing" signal, and, in
+ * the signal handler, set a flag to stop capturing; however, without
+ * a guarantee of that sort, we can't guarantee that we'll stop capturing
+ * if the read will be retried and won't time out if no packets arrive.
+ *
+ * Therefore, on at least some platforms, we work around the lack of
+ * pcap_breakloop() by doing a select() on the pcap_t's file descriptor
+ * to wait for packets to arrive, so that we're probably going to be
+ * blocked in the select() when the signal arrives, and can just bail
+ * out of the loop at that point.
+ *
+ * However, we don't want to that on BSD (because "select()" doesn't work
+ * correctly on BPF devices on at least some releases of some flavors of
+ * BSD), and we don't want to do it on Windows (because "select()" is
+ * something for sockets, not for arbitrary handles).  (Note that "Windows"
+ * here includes Cygwin; even in its pretend-it's-UNIX environment, we're
+ * using WinPcap, not a UNIX libpcap.)
+ *
+ * Fortunately, we don't need to do it on BSD, because the libpcap timeout
+ * on BSD times out even if no packets have arrived, so we'll eventually
+ * exit pcap_dispatch() with an indication that no packets have arrived,
+ * and will break out of the capture loop at that point.
+ *
+ * On Windows, we can't send a SIGUSR1 to stop capturing, so none of this
+ * applies in any case.
  *
  * XXX - the various BSDs appear to define BSD in <sys/param.h>; we don't
  * want to include it if it's not present on this platform, however.
  */
-#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \
+# if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__) && \
     !defined(__bsdi__) && !defined(__APPLE__) && !defined(_WIN32) && \
     !defined(__CYGWIN__)
-# define MUST_DO_SELECT
-#endif
+#  define MUST_DO_SELECT
+# endif /* avoid select */
+#endif /* HAVE_PCAP_BREAKLOOP */
 
 typedef void (*capture_packet_cb_fct)(u_char *, const struct pcap_pkthdr *, const u_char *);
 
index a78f6254bcd2bba023eaf2efd2e348e5472325a8..46f0ccdbaf1f576fbfc1735c9729f5e5996cef07 100644 (file)
@@ -56,6 +56,7 @@
 #define NEED_MKSTEMP 1
 
 @HAVE_LIBPCAP@
+@HAVE_PCAP_BREAKLOOP@
 @HAVE_PCAP_FINDALLDEVS@
 @HAVE_PCAP_DATALINK_NAME_TO_VAL@
 @HAVE_PCAP_DATALINK_VAL_TO_NAME@
index b02347ec71c7c600649f84de0777e76050b7a81c..c78fd8b933ff483e707e451799423a0181b6bd53 100644 (file)
@@ -354,10 +354,16 @@ WINPCAP_CONFIG=^#define HAVE_LIBPCAP 1
 PCAP_FINDALLDEVS_CONFIG=^#define HAVE_PCAP_FINDALLDEVS 1
 PCAP_DATALINK_NAME_TO_VAL_CONFIG=^#define HAVE_PCAP_DATALINK_NAME_TO_VAL 1
 PCAP_DATALINK_VAL_TO_NAME_CONFIG=^#define HAVE_PCAP_DATALINK_VAL_TO_NAME 1
+!IF "$(WINPCAP_VERSION)" == "3.1"
+PCAP_BREAKLOOP_CONFIG=^#define HAVE_PCAP_BREAKLOOP 1
+!ELSE
+PCAP_BREAKLOOP_CONFIG=
+!ENDIF
 WPCAP_CONSTIFIED_CONFIG=^#define WPCAP_CONSTIFIED 1
 !ELSE
 PCAP_FINDALLDEVS_CONFIG=
 PCAP_DATALINK_VAL_TO_NAME_CONFIG=
+PCAP_BREAKLOOP_CONFIG=
 WPCAP_CONSTIFIED=
 !ENDIF
 !ELSE
@@ -365,6 +371,7 @@ WINPCAP_CONFIG=
 PCAP_FINDALLDEVS_CONFIG=
 PCAP_DATALINK_NAME_TO_VAL_CONFIG=
 PCAP_DATALINK_VAL_TO_NAME_CONFIG=
+PCAP_BREAKLOOP_CONFIG=
 WPCAP_CONSTIFIED=
 !ENDIF