aboutsummaryrefslogtreecommitdiffstats
path: root/caputils
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-06-09 23:39:12 -0700
committerAnders Broman <a.broman58@gmail.com>2018-06-10 14:26:37 +0000
commit5ecbcaf483a552a8b78d525b9f32c5cfa575d59c (patch)
tree18d7afa2184d7c2954685d6743e8119676f890f3 /caputils
parente0b8837d9a62c7fd5964a7f35ee0dee01002e0ee (diff)
Improve the secondary error messages for pcap errors.
On Windows, if WinPcap isn't installed, warn about that for errors other than failed attempts to start capturing. On HP-UX, if we appear to have an old version of libpcap, warn about that for errors other than failed attempts to start capturing. If we know the error is a permissions problem, don't make suggestions appropriate to other problems. If we know the error is *not* a permissions problem, don't make suggestions appropriate to permissions problems. For permissions problems, or possible permissions problems, on Linux, suggest doing dpkg-reconfigure wireshark-common if you've installed from a package on Debian or a Debian derivative such as Ubuntu. Change-Id: If4aac0343095ac0b984eebc21853920c3b6d3c63 Ping-Bug: 14847 Reviewed-on: https://code.wireshark.org/review/28189 Petri-Dish: Guy Harris <guy@alum.mit.edu> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'caputils')
-rw-r--r--caputils/capture-pcap-util-int.h13
-rw-r--r--caputils/capture-pcap-util-unix.c15
-rw-r--r--caputils/capture-pcap-util.c272
-rw-r--r--caputils/capture-pcap-util.h13
-rw-r--r--caputils/capture-wpcap.c12
5 files changed, 193 insertions, 132 deletions
diff --git a/caputils/capture-pcap-util-int.h b/caputils/capture-pcap-util-int.h
index 29105ea4c5..1ed8a7ffa5 100644
--- a/caputils/capture-pcap-util-int.h
+++ b/caputils/capture-pcap-util-int.h
@@ -34,21 +34,22 @@ extern void request_high_resolution_timestamp(pcap_t *pcap_h);
#endif
extern if_capabilities_t *get_if_capabilities_local(interface_options *interface_opts,
- char **err_str);
+ cap_device_open_err *err, char **err_str);
extern pcap_t *open_capture_device_local(capture_options *capture_opts,
- interface_options *interface_opts, int timeout,
+ interface_options *interface_opts, int timeout, cap_device_open_err *err,
char (*open_err_str)[PCAP_ERRBUF_SIZE]);
#ifdef HAVE_PCAP_CREATE
extern if_capabilities_t *get_if_capabilities_pcap_create(interface_options *interface_opts,
- char **err_str);
+ cap_device_open_err *err, char **err_str);
extern pcap_t *open_capture_device_pcap_create(capture_options *capture_opts,
- interface_options *interface_opts, int timeout,
+ interface_options *interface_opts, int timeout, cap_device_open_err *err,
char (*open_err_str)[PCAP_ERRBUF_SIZE]);
#endif /* HAVE_PCAP_CREATE */
extern if_capabilities_t *get_if_capabilities_pcap_open_live(interface_options *interface_opts,
- char **err_str);
+ cap_device_open_err *err, char **err_str);
extern pcap_t *open_capture_device_pcap_open_live(interface_options *interface_opts,
- int timeout, char (*open_err_str)[PCAP_ERRBUF_SIZE]);
+ int timeout, cap_device_open_err *err,
+ char (*open_err_str)[PCAP_ERRBUF_SIZE]);
/*
* Get an error message string for a CANT_GET_INTERFACE_LIST error from
diff --git a/caputils/capture-pcap-util-unix.c b/caputils/capture-pcap-util-unix.c
index cb6c10bd42..a5a847a08c 100644
--- a/caputils/capture-pcap-util-unix.c
+++ b/caputils/capture-pcap-util-unix.c
@@ -116,7 +116,7 @@ search_for_if_cb(gpointer data, gpointer user_data)
}
GList *
-get_interface_list(int *err, char **err_str)
+get_interface_list(cap_device_open_err *err, char **err_str)
{
GList *il = NULL;
gint nonloopback_pos = 0;
@@ -418,12 +418,13 @@ have_high_resolution_timestamp(pcap_t *pcap_h)
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
if_capabilities_t *
-get_if_capabilities_local(interface_options *interface_opts, char **err_str)
+get_if_capabilities_local(interface_options *interface_opts,
+ cap_device_open_err *err, char **err_str)
{
#ifdef HAVE_PCAP_CREATE
- return get_if_capabilities_pcap_create(interface_opts, err_str);
+ return get_if_capabilities_pcap_create(interface_opts, err, err_str);
#else
- return get_if_capabilities_pcap_open_live(interface_opts, err_str);
+ return get_if_capabilities_pcap_open_live(interface_opts, err, err_str);
#endif
}
@@ -434,7 +435,7 @@ open_capture_device_local(capture_options *capture_opts
#endif
,
interface_options *interface_opts, int timeout,
- char (*open_err_str)[PCAP_ERRBUF_SIZE])
+ cap_device_open_err *open_err, char (*open_err_str)[PCAP_ERRBUF_SIZE])
{
/*
* We're not opening a remote device; use pcap_create() and
@@ -443,10 +444,10 @@ open_capture_device_local(capture_options *capture_opts
*/
#ifdef HAVE_PCAP_CREATE
return open_capture_device_pcap_create(capture_opts,
- interface_opts, timeout, open_err_str);
+ interface_opts, timeout, open_err, open_err_str);
#else
return open_capture_device_pcap_open_live(interface_opts, timeout,
- open_err_str);
+ open_err, open_err_str);
#endif
}
diff --git a/caputils/capture-pcap-util.c b/caputils/capture-pcap-util.c
index e2fa5c26b7..1647511aa0 100644
--- a/caputils/capture-pcap-util.c
+++ b/caputils/capture-pcap-util.c
@@ -857,7 +857,7 @@ create_data_link_info(int dlt)
static GList *
get_data_link_types(pcap_t *pch, interface_options *interface_opts,
- char **err_str)
+ cap_device_open_err *err, char **err_str)
{
GList *data_link_types;
int deflt;
@@ -874,25 +874,30 @@ get_data_link_types(pcap_t *pch, interface_options *interface_opts,
/*
* A negative return is an error.
*/
- if (err_str != NULL) {
#ifdef HAVE_PCAP_CREATE
- /*
- * If we have pcap_create(), we have
- * pcap_statustostr(), and we can get back errors
- * other than PCAP_ERROR (-1), such as
- * PCAP_ERROR_NOT_ACTIVATED. and we should report
- * them properly.
- */
- if (nlt == PCAP_ERROR)
- *err_str = g_strdup_printf("pcap_list_datalinks() failed: %s",
- pcap_geterr(pch));
- else
- *err_str = g_strdup(pcap_statustostr(nlt));
-#else /* HAVE_PCAP_CREATE */
+ /*
+ * If we have pcap_create(), we have
+ * pcap_statustostr(), and we can get back errors
+ * other than PCAP_ERROR (-1), such as
+ * PCAP_ERROR_NOT_ACTIVATED. and we should report
+ * them properly.
+ */
+ if (nlt == PCAP_ERROR) {
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
*err_str = g_strdup_printf("pcap_list_datalinks() failed: %s",
pcap_geterr(pch));
-#endif /* HAVE_PCAP_CREATE */
+ } else {
+ if (nlt == PCAP_ERROR_PERM_DENIED)
+ *err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
+ else
+ *err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ *err_str = g_strdup(pcap_statustostr(nlt));
}
+#else /* HAVE_PCAP_CREATE */
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ *err_str = g_strdup_printf("pcap_list_datalinks() failed: %s",
+ pcap_geterr(pch));
+#endif /* HAVE_PCAP_CREATE */
return NULL;
}
data_link_types = NULL;
@@ -942,8 +947,7 @@ get_data_link_types(pcap_t *pch, interface_options *interface_opts,
data_link_types = g_list_append(data_link_types, data_link_info);
#endif /* HAVE_PCAP_LIST_DATALINKS */
- if (err_str != NULL)
- *err_str = NULL;
+ *err_str = NULL;
return data_link_types;
}
@@ -1017,7 +1021,7 @@ is_linux_bonding_device(const char *ifname _U_)
if_capabilities_t *
get_if_capabilities_pcap_create(interface_options *interface_opts,
- char **err_str)
+ cap_device_open_err *err, char **err_str)
{
if_capabilities_t *caps;
char errbuf[PCAP_ERRBUF_SIZE];
@@ -1026,8 +1030,8 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
pch = pcap_create(interface_opts->name, errbuf);
if (pch == NULL) {
- if (err_str != NULL)
- *err_str = g_strdup(errbuf);
+ *err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ *err_str = g_strdup(errbuf);
return NULL;
}
@@ -1046,11 +1050,17 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
}
if (status < 0) {
/* Error. */
- if (status == PCAP_ERROR)
+ if (status == PCAP_ERROR) {
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
*err_str = g_strdup_printf("pcap_can_set_rfmon() failed: %s",
pcap_geterr(pch));
- else
+ } else {
+ if (status == PCAP_ERROR_PERM_DENIED)
+ *err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
+ else
+ *err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
*err_str = g_strdup(pcap_statustostr(status));
+ }
pcap_close(pch);
return NULL;
}
@@ -1062,10 +1072,9 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
if (interface_opts->monitor_mode)
pcap_set_rfmon(pch, 1);
} else {
- if (err_str != NULL) {
- *err_str = g_strdup_printf("pcap_can_set_rfmon() returned %d",
- status);
- }
+ *err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ *err_str = g_strdup_printf("pcap_can_set_rfmon() returned %d",
+ status);
pcap_close(pch);
g_free(caps);
return NULL;
@@ -1074,12 +1083,16 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
status = pcap_activate(pch);
if (status < 0) {
/* Error. We ignore warnings (status > 0). */
- if (err_str != NULL) {
- if (status == PCAP_ERROR)
- *err_str = g_strdup_printf("pcap_activate() failed: %s",
- pcap_geterr(pch));
+ if (status == PCAP_ERROR) {
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ *err_str = g_strdup_printf("pcap_activate() failed: %s",
+ pcap_geterr(pch));
+ } else {
+ if (status == PCAP_ERROR_PERM_DENIED)
+ *err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
else
- *err_str = g_strdup(pcap_statustostr(status));
+ *err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ *err_str = g_strdup(pcap_statustostr(status));
}
pcap_close(pch);
g_free(caps);
@@ -1087,7 +1100,7 @@ get_if_capabilities_pcap_create(interface_options *interface_opts,
}
caps->data_link_types = get_data_link_types(pch, interface_opts,
- err_str);
+ err, err_str);
if (caps->data_link_types == NULL) {
pcap_close(pch);
g_free(caps);
@@ -1111,88 +1124,102 @@ open_capture_device_pcap_create(capture_options *capture_opts
_U_,
#endif
interface_options *interface_opts, int timeout,
+ cap_device_open_err *open_err,
char (*open_err_str)[PCAP_ERRBUF_SIZE])
{
pcap_t *pcap_h;
- int err;
+ int status;
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"Calling pcap_create() using %s.", interface_opts->name);
pcap_h = pcap_create(interface_opts->name, *open_err_str);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"pcap_create() returned %p.", (void *)pcap_h);
- if (pcap_h != NULL) {
- if (interface_opts->has_snaplen) {
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "Calling pcap_set_snaplen() with snaplen %d.",
- interface_opts->snaplen);
- pcap_set_snaplen(pcap_h, interface_opts->snaplen);
- }
+ if (pcap_h == NULL) {
+ *open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ return NULL;
+ }
+ if (interface_opts->has_snaplen) {
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "Calling pcap_set_promisc() with promisc_mode %d.",
- interface_opts->promisc_mode);
- pcap_set_promisc(pcap_h, interface_opts->promisc_mode);
- pcap_set_timeout(pcap_h, timeout);
+ "Calling pcap_set_snaplen() with snaplen %d.",
+ interface_opts->snaplen);
+ pcap_set_snaplen(pcap_h, interface_opts->snaplen);
+ }
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ "Calling pcap_set_promisc() with promisc_mode %d.",
+ interface_opts->promisc_mode);
+ pcap_set_promisc(pcap_h, interface_opts->promisc_mode);
+ pcap_set_timeout(pcap_h, timeout);
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
- /*
- * If we're writing pcapng files, try to enable
- * nanosecond-resolution capture; any code that
- * can read pcapng files must be able to handle
- * nanosecond-resolution time stamps. We don't
- * care whether it succeeds or fails - if it fails,
- * we just use the microsecond-precision time stamps
- * we get.
- *
- * If we're writing pcap files, don't try to enable
- * nanosecond-resolution capture, as not all code
- * that reads pcap files recognizes the nanosecond-
- * resolution pcap file magic number.
- * We don't care whether this succeeds or fails; if it
- * fails (because we don't have pcap_set_tstamp_precision(),
- * or because we do but the OS or device doesn't support
- * nanosecond resolution timing), we just use microsecond-
- * resolution time stamps.
- */
- if (capture_opts->use_pcapng)
- request_high_resolution_timestamp(pcap_h);
+ /*
+ * If we're writing pcapng files, try to enable
+ * nanosecond-resolution capture; any code that
+ * can read pcapng files must be able to handle
+ * nanosecond-resolution time stamps. We don't
+ * care whether it succeeds or fails - if it fails,
+ * we just use the microsecond-precision time stamps
+ * we get.
+ *
+ * If we're writing pcap files, don't try to enable
+ * nanosecond-resolution capture, as not all code
+ * that reads pcap files recognizes the nanosecond-
+ * resolution pcap file magic number.
+ * We don't care whether this succeeds or fails; if it
+ * fails (because we don't have pcap_set_tstamp_precision(),
+ * or because we do but the OS or device doesn't support
+ * nanosecond resolution timing), we just use microsecond-
+ * resolution time stamps.
+ */
+ if (capture_opts->use_pcapng)
+ request_high_resolution_timestamp(pcap_h);
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
- if (interface_opts->timestamp_type) {
- err = pcap_set_tstamp_type(pcap_h, interface_opts->timestamp_type_id);
- if (err == PCAP_ERROR) {
- g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
- sizeof *open_err_str);
- pcap_close(pcap_h);
- return NULL;
- }
+ if (interface_opts->timestamp_type) {
+ status = pcap_set_tstamp_type(pcap_h, interface_opts->timestamp_type_id);
+ /*
+ * XXX - what if it fails because that time stamp type
+ * isn't supported?
+ */
+ if (status == PCAP_ERROR) {
+ *open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
+ sizeof *open_err_str);
+ pcap_close(pcap_h);
+ return NULL;
}
+ }
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "buffersize %d.", interface_opts->buffer_size);
- if (interface_opts->buffer_size != 0)
- pcap_set_buffer_size(pcap_h,
- interface_opts->buffer_size * 1024 * 1024);
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "monitor_mode %d.", interface_opts->monitor_mode);
- if (interface_opts->monitor_mode)
- pcap_set_rfmon(pcap_h, 1);
- err = pcap_activate(pcap_h);
- g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
- "pcap_activate() returned %d.", err);
- if (err < 0) {
- /* Failed to activate, set to NULL */
- if (err == PCAP_ERROR)
- g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
- sizeof *open_err_str);
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ "buffersize %d.", interface_opts->buffer_size);
+ if (interface_opts->buffer_size != 0)
+ pcap_set_buffer_size(pcap_h,
+ interface_opts->buffer_size * 1024 * 1024);
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ "monitor_mode %d.", interface_opts->monitor_mode);
+ if (interface_opts->monitor_mode)
+ pcap_set_rfmon(pcap_h, 1);
+ status = pcap_activate(pcap_h);
+ g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
+ "pcap_activate() returned %d.", status);
+ if (status < 0) {
+ /* Failed to activate, set to NULL */
+ if (status == PCAP_ERROR) {
+ *open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ g_strlcpy(*open_err_str, pcap_geterr(pcap_h),
+ sizeof *open_err_str);
+ } else {
+ if (status == PCAP_ERROR_PERM_DENIED)
+ *open_err = CAP_DEVICE_OPEN_ERR_PERMISSIONS;
else
- g_strlcpy(*open_err_str, pcap_statustostr(err),
- sizeof *open_err_str);
- pcap_close(pcap_h);
- pcap_h = NULL;
+ *open_err = CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS;
+ g_strlcpy(*open_err_str, pcap_statustostr(status),
+ sizeof *open_err_str);
}
+ pcap_close(pcap_h);
+ return NULL;
}
return pcap_h;
}
@@ -1200,7 +1227,7 @@ open_capture_device_pcap_create(capture_options *capture_opts
if_capabilities_t *
get_if_capabilities_pcap_open_live(interface_options *interface_opts,
- char **err_str)
+ cap_device_open_err *err, char **err_str)
{
if_capabilities_t *caps;
char errbuf[PCAP_ERRBUF_SIZE];
@@ -1209,15 +1236,15 @@ get_if_capabilities_pcap_open_live(interface_options *interface_opts,
pch = pcap_open_live(interface_opts->name, MIN_PACKET_SIZE, 0, 0,
errbuf);
if (pch == NULL) {
- if (err_str != NULL)
- *err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ *err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
return NULL;
}
caps = (if_capabilities_t *)g_malloc(sizeof *caps);
caps->can_set_rfmon = FALSE;
caps->data_link_types = get_data_link_types(pch, interface_opts,
- err_str);
+ err, err_str);
if (caps->data_link_types == NULL) {
pcap_close(pch);
g_free(caps);
@@ -1228,14 +1255,14 @@ get_if_capabilities_pcap_open_live(interface_options *interface_opts,
pcap_close(pch);
- if (err_str != NULL)
- *err_str = NULL;
+ *err_str = NULL;
return caps;
}
pcap_t *
open_capture_device_pcap_open_live(interface_options *interface_opts,
- int timeout, char (*open_err_str)[PCAP_ERRBUF_SIZE])
+ int timeout, cap_device_open_err *open_err,
+ char (*open_err_str)[PCAP_ERRBUF_SIZE])
{
pcap_t *pcap_h;
int snaplen;
@@ -1259,10 +1286,14 @@ open_capture_device_pcap_open_live(interface_options *interface_opts,
interface_opts->promisc_mode, timeout, *open_err_str);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
"pcap_open_live() returned %p.", (void *)pcap_h);
+ if (pcap_h == NULL) {
+ *open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ return NULL;
+ }
#ifdef _WIN32
- /* If the open succeeded, try to set the capture buffer size. */
- if (pcap_h && interface_opts->buffer_size > 1) {
+ /* Try to set the capture buffer size. */
+ if (interface_opts->buffer_size > 1) {
/*
* We have no mechanism to report a warning if this
* fails; we just keep capturing with the smaller buffer,
@@ -1281,7 +1312,8 @@ open_capture_device_pcap_open_live(interface_options *interface_opts,
* Get the capabilities of a network device.
*/
if_capabilities_t *
-get_if_capabilities(interface_options *interface_opts, char **err_str)
+get_if_capabilities(interface_options *interface_opts,
+ cap_device_open_err *err, char **err_str)
{
#if defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE)
if_capabilities_t *caps;
@@ -1316,8 +1348,13 @@ get_if_capabilities(interface_options *interface_opts, char **err_str)
pch = pcap_open(interface_opts->name, MIN_PACKET_SIZE, 0, 0, &auth,
errbuf);
if (pch == NULL) {
- if (err_str != NULL)
- *err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
+ /*
+ * We don't know whether it's a permission error or not.
+ * (If it is, maybe we can give ourselves permission or
+ * maybe we just have to ask politely for permission.)
+ */
+ *err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ *err_str = g_strdup(errbuf[0] == '\0' ? "Unknown error (pcap bug; actual error cause not reported)" : errbuf);
return NULL;
}
@@ -1330,8 +1367,7 @@ get_if_capabilities(interface_options *interface_opts, char **err_str)
caps->timestamp_types = get_pcap_timestamp_types(pch, NULL);
pcap_close(pch);
- if (err_str != NULL)
- *err_str = NULL;
+ *err_str = NULL;
return caps;
}
#endif /* defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE) */
@@ -1339,12 +1375,13 @@ get_if_capabilities(interface_options *interface_opts, char **err_str)
/*
* Local interface.
*/
- return get_if_capabilities_local(interface_opts, err_str);
+ return get_if_capabilities_local(interface_opts, err, err_str);
}
pcap_t *
open_capture_device(capture_options *capture_opts,
interface_options *interface_opts, int timeout,
+ cap_device_open_err *open_err,
char (*open_err_str)[PCAP_ERRBUF_SIZE])
{
pcap_t *pcap_h;
@@ -1357,6 +1394,7 @@ open_capture_device(capture_options *capture_opts,
if they succeed; to tell if that's happened, we have to clear
the error buffer, and check if it's still a null string. */
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Entering open_capture_device().");
+ *open_err = CAP_DEVICE_OPEN_NO_ERR;
(*open_err_str)[0] = '\0';
#if defined(HAVE_PCAP_OPEN) && defined(HAVE_PCAP_REMOTE)
/*
@@ -1392,7 +1430,17 @@ open_capture_device(capture_options *capture_opts,
(interface_opts->nocap_rpcap ? PCAP_OPENFLAG_NOCAPTURE_RPCAP : 0),
timeout, &auth, *open_err_str);
if (pcap_h == NULL) {
- /* Error - did pcap actually supply an error message? */
+ /*
+ * Error.
+ *
+ * We don't know whether it's a permission error
+ * or not.
+ * (If it is, maybe we can give ourselves permission
+ * or maybe we just have to ask politely for
+ * permission.)
+ */
+ *open_err = CAP_DEVICE_OPEN_ERR_GENERIC;
+ /* Did pcap actually supply an error message? */
if ((*open_err_str)[0] == '\0') {
/*
* Work around known WinPcap bug wherein
@@ -1412,7 +1460,7 @@ open_capture_device(capture_options *capture_opts,
#endif
pcap_h = open_capture_device_local(capture_opts, interface_opts,
- timeout, open_err_str);
+ timeout, open_err, open_err_str);
g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "open_capture_device %s : %s", pcap_h ? "SUCCESS" : "FAILURE", interface_opts->name);
return pcap_h;
}
diff --git a/caputils/capture-pcap-util.h b/caputils/capture-pcap-util.h
index cfadf3f0bc..b8eb855b0e 100644
--- a/caputils/capture-pcap-util.h
+++ b/caputils/capture-pcap-util.h
@@ -54,10 +54,19 @@ gboolean set_pcap_datalink(pcap_t *pcap_h, int datalink, char *name,
gboolean have_high_resolution_timestamp(pcap_t *pcap_h);
#endif /* HAVE_PCAP_SET_TSTAMP_PRECISION */
+/*
+ * Error values.
+ */
+typedef enum {
+ CAP_DEVICE_OPEN_NO_ERR, /* No error */
+ CAP_DEVICE_OPEN_ERR_PERMISSIONS, /* Error is known to be a permissions error */
+ CAP_DEVICE_OPEN_ERR_NOT_PERMISSIONS, /* Error is known not to be a permissions error */
+ CAP_DEVICE_OPEN_ERR_GENERIC /* Error is not known to be one or the other */
+} cap_device_open_err;
extern if_capabilities_t *get_if_capabilities(interface_options *interface_opts,
- char **err_str);
+ cap_device_open_err *err, char **err_str);
extern pcap_t *open_capture_device(capture_options *capture_opts,
- interface_options *interface_opts, int timeout,
+ interface_options *interface_opts, int timeout, cap_device_open_err *err,
char (*open_err_str)[PCAP_ERRBUF_SIZE]);
#endif /* HAVE_LIBPCAP */
diff --git a/caputils/capture-wpcap.c b/caputils/capture-wpcap.c
index af2f4e6b5a..0b28494cc4 100644
--- a/caputils/capture-wpcap.c
+++ b/caputils/capture-wpcap.c
@@ -976,7 +976,8 @@ cant_get_if_list_error_message(const char *err_str)
}
if_capabilities_t *
-get_if_capabilities_local(interface_options *interface_opts, char **err_str)
+get_if_capabilities_local(interface_options *interface_opts,
+ cap_device_open_err *err, char **err_str)
{
/*
* We're not getting capaibilities for a remote device; use
@@ -985,14 +986,15 @@ get_if_capabilities_local(interface_options *interface_opts, char **err_str)
*/
#ifdef HAVE_PCAP_CREATE
if (p_pcap_create != NULL)
- return get_if_capabilities_pcap_create(interface_opts, err_str);
+ return get_if_capabilities_pcap_create(interface_opts, err, err_str);
#endif
- return get_if_capabilities_pcap_open_live(interface_opts, err_str);
+ return get_if_capabilities_pcap_open_live(interface_opts, err, err_str);
}
pcap_t *
open_capture_device_local(capture_options *capture_opts,
interface_options *interface_opts, int timeout,
+ cap_device_open_err *open_err,
char (*open_err_str)[PCAP_ERRBUF_SIZE])
{
/*
@@ -1003,10 +1005,10 @@ open_capture_device_local(capture_options *capture_opts,
#ifdef HAVE_PCAP_CREATE
if (p_pcap_create != NULL)
return open_capture_device_pcap_create(capture_opts,
- interface_opts, timeout, open_err_str);
+ interface_opts, timeout, open_err, open_err_str);
#endif
return open_capture_device_pcap_open_live(interface_opts, timeout,
- open_err_str);
+ open_err, open_err_str);
}
/*