aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--acinclude.m41
-rw-r--r--capture_loop.c84
2 files changed, 53 insertions, 32 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index 334c13d7c9..f60a387d49 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -469,6 +469,7 @@ and did you also install that package?]]))
[Define to 1 if you have the `pcap_findalldevs' function and a pcap.h that declares pcap_if_t.])
AC_CHECK_FUNCS(pcap_datalink_val_to_name pcap_datalink_name_to_val)
AC_CHECK_FUNCS(pcap_list_datalinks pcap_set_datalink pcap_lib_version)
+ AC_CHECK_FUNCS(pcap_get_selectable_fd)
fi
LIBS="$ac_save_LIBS"
])
diff --git a/capture_loop.c b/capture_loop.c
index 906bdf0656..fd1a6c53b1 100644
--- a/capture_loop.c
+++ b/capture_loop.c
@@ -671,7 +671,13 @@ static int capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
}
#ifdef MUST_DO_SELECT
- if (!ld->from_cap_pipe) ld->pcap_fd = pcap_fileno(ld->pcap_h);
+ if (!ld->from_cap_pipe) {
+#ifdef HAVE_PCAP_GET_SELECTABLE_FD
+ ld->pcap_fd = pcap_get_selectable_fd(ld->pcap_h);
+#else
+ ld->pcap_fd = pcap_fileno(ld->pcap_h);
+#endif
+ }
#endif
/* Does "open_err_str" contain a non-empty string? If so, "pcap_open_live()"
@@ -864,8 +870,8 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
#endif
#ifndef _WIN32
- /* dispatch from capture pipe */
if (ld->from_cap_pipe) {
+ /* dispatch from capture pipe */
FD_ZERO(&set1);
FD_SET(ld->cap_pipe_fd, &set1);
timeout.tv_sec = 0;
@@ -893,7 +899,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
else
#endif /* _WIN32 */
{
- /* dispatch from pcap using select */
+ /* dispatch from pcap */
#ifdef MUST_DO_SELECT
/*
* Sigh. The semantics of the read timeout argument to
@@ -921,39 +927,53 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld,
* 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.
*/
- 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, capture_loop_packet_cb, (gchar *)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));
- capture_loop_popup_errmsg(capture_opts, errmsg);
- ld->go = FALSE;
+ 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, capture_loop_packet_cb, (gchar *)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));
+ capture_loop_popup_errmsg(capture_opts, errmsg);
+ ld->go = FALSE;
+ }
}
}
-#else
- /* dispatch from pcap without select */
- inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (gchar *) ld);
- if (inpkts < 0) {
- ld->pcap_err = TRUE;
- ld->go = FALSE;
- }
+ else
#endif /* MUST_DO_SELECT */
+ {
+ /* dispatch from pcap without select */
+ inpkts = pcap_dispatch(ld->pcap_h, 1, capture_loop_packet_cb, (gchar *) ld);
+ if (inpkts < 0) {
+ ld->pcap_err = TRUE;
+ ld->go = FALSE;
+ }
+ }
}
return inpkts;