For TShark and Wireshark, get the list of link-layer types for an

interface by running dumpcap, so that if you need privileges to open an
interface, and dumpcap has those privileges, neither TShark nor
Wireshark need them.

svn path=/trunk/; revision=32710
This commit is contained in:
Guy Harris 2010-05-07 08:06:25 +00:00
parent 1bcecb4bcd
commit cc05b9250d
7 changed files with 202 additions and 160 deletions

View File

@ -438,111 +438,6 @@ pcap_datalink_val_to_description(int dlt)
#endif /* !defined(HAVE_PCAP_DATALINK_VAL_TO_NAME) || !defined(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) */
/*
* Get the data-link types available for a libpcap device.
*/
static data_link_info_t *
create_data_link_info(int dlt)
{
data_link_info_t *data_link_info;
const char *text;
data_link_info = (data_link_info_t *)g_malloc(sizeof (data_link_info_t));
data_link_info->dlt = dlt;
text = pcap_datalink_val_to_name(dlt);
if (text != NULL)
data_link_info->name = g_strdup(text);
else
data_link_info->name = g_strdup_printf("DLT %d", dlt);
text = pcap_datalink_val_to_description(dlt);
if (text != NULL)
data_link_info->description = g_strdup(text);
else
data_link_info->description = NULL;
return data_link_info;
}
GList *
get_pcap_linktype_list(const char *devname, char **err_str)
{
GList *linktype_list = NULL;
pcap_t *pch;
int deflt;
char errbuf[PCAP_ERRBUF_SIZE];
#ifdef HAVE_PCAP_LIST_DATALINKS
int *linktypes;
int i, nlt;
#endif
data_link_info_t *data_link_info;
#ifdef HAVE_PCAP_OPEN
pch = pcap_open(devname, MIN_PACKET_SIZE, 0, 0, NULL, errbuf);
#else
pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, errbuf);
#endif
if (pch == NULL) {
if (err_str != NULL)
*err_str = g_strdup(errbuf);
return NULL;
}
deflt = get_pcap_linktype(pch, devname);
#ifdef HAVE_PCAP_LIST_DATALINKS
nlt = pcap_list_datalinks(pch, &linktypes);
if (nlt == 0 || linktypes == NULL) {
pcap_close(pch);
if (err_str != NULL)
*err_str = NULL; /* an empty list doesn't mean an error */
return NULL;
}
for (i = 0; i < nlt; i++) {
data_link_info = create_data_link_info(linktypes[i]);
/*
* XXX - for 802.11, make the most detailed 802.11
* version the default, rather than the one the
* device has as the default?
*/
if (linktypes[i] == deflt)
linktype_list = g_list_prepend(linktype_list,
data_link_info);
else
linktype_list = g_list_append(linktype_list,
data_link_info);
}
#ifdef HAVE_PCAP_FREE_DATALINKS
pcap_free_datalinks(linktypes);
#else
/*
* In Windows, there's no guarantee that if you have a library
* built with one version of the MSVC++ run-time library, and
* it returns a pointer to allocated data, you can free that
* data from a program linked with another version of the
* MSVC++ run-time library.
*
* This is not an issue on UN*X.
*
* See the mail threads starting at
*
* http://www.winpcap.org/pipermail/winpcap-users/2006-September/001421.html
*
* and
*
* http://www.winpcap.org/pipermail/winpcap-users/2008-May/002498.html
*/
#ifndef _WIN32
#define xx_free free /* hack so checkAPIs doesn't complain */
xx_free(linktypes);
#endif /* _WIN32 */
#endif /* HAVE_PCAP_FREE_DATALINKS */
#else /* HAVE_PCAP_LIST_DATALINKS */
data_link_info = create_data_link_info(deflt);
linktype_list = g_list_append(linktype_list, data_link_info);
#endif /* HAVE_PCAP_LIST_DATALINKS */
pcap_close(pch);
return linktype_list;
}
static void
free_linktype_cb(gpointer data, gpointer user_data _U_)
{

View File

@ -49,8 +49,6 @@ GList *get_remote_interface_list(const char *hostname, const char *port,
const char *passwd, int *err, char **err_str);
#endif
GList *get_pcap_linktype_list(const char *devname, char **err_str);
/* get/set the link type of an interface */
/* (only used in capture_loop.c / capture-pcap-util.c) */
int get_pcap_linktype(pcap_t *pch, const char *devname);

View File

@ -571,56 +571,23 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg_
return 0;
}
/*
* If you change the output format of this function, you MUST update
* capture_sync.c:sync_linktype_list_open() accordingly!
*/
int
capture_opts_list_link_layer_types(capture_options *capture_opts, gboolean machine_readable)
void
capture_opts_print_link_layer_types(GList *lt_list)
{
gchar *err_str;
const gchar *desc_str;
GList *lt_list, *lt_entry;
GList *lt_entry;
data_link_info_t *data_link_info;
/* Get the list of link-layer types for the capture device. */
lt_list = get_pcap_linktype_list(capture_opts->iface, &err_str);
if (lt_list == NULL) {
if (err_str != NULL) {
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", capture_opts->iface, err_str);
g_free(err_str);
} else
cmdarg_err("The capture device \"%s\" has no data link types.", capture_opts->iface);
return 2;
}
if (machine_readable) { /* tab-separated values to stdout */
for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
if (data_link_info->description != NULL)
desc_str = data_link_info->description;
else
desc_str = "(not supported)";
printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name,
desc_str);
}
} else {
cmdarg_err_cont("Data link types (use option -y to set):");
for (lt_entry = lt_list; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
cmdarg_err_cont(" %s", data_link_info->name);
if (data_link_info->description != NULL)
cmdarg_err_cont("Data link types (use option -y to set):");
for (lt_entry = lt_list; lt_entry != NULL;
lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
cmdarg_err_cont(" %s", data_link_info->name);
if (data_link_info->description != NULL)
cmdarg_err_cont(" (%s)", data_link_info->description);
else
else
cmdarg_err_cont(" (not supported)");
putchar('\n');
}
putchar('\n');
}
free_pcap_linktype_list(lt_list);
return 0;
}
/* Return an ASCII-formatted list of interfaces. */

View File

@ -175,9 +175,9 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg,
extern void
capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_options *capture_opts);
/* list link layer types */
extern int
capture_opts_list_link_layer_types(capture_options *capture_opts, gboolean machine_readable);
/* print list of link layer types */
extern void
capture_opts_print_link_layer_types(GList *lt_list);
/* list interfaces */
extern int

152
dumpcap.c
View File

@ -449,6 +449,135 @@ capture_interface_list(int *err, char **err_str)
return get_interface_list(err, err_str);
}
/*
* Get the data-link types available for a libpcap device.
*/
static data_link_info_t *
create_data_link_info(int dlt)
{
data_link_info_t *data_link_info;
const char *text;
data_link_info = (data_link_info_t *)g_malloc(sizeof (data_link_info_t));
data_link_info->dlt = dlt;
text = pcap_datalink_val_to_name(dlt);
if (text != NULL)
data_link_info->name = g_strdup(text);
else
data_link_info->name = g_strdup_printf("DLT %d", dlt);
text = pcap_datalink_val_to_description(dlt);
if (text != NULL)
data_link_info->description = g_strdup(text);
else
data_link_info->description = NULL;
return data_link_info;
}
static GList *
get_pcap_linktype_list(const char *devname, char **err_str)
{
GList *linktype_list = NULL;
pcap_t *pch;
int deflt;
char errbuf[PCAP_ERRBUF_SIZE];
#ifdef HAVE_PCAP_LIST_DATALINKS
int *linktypes;
int i, nlt;
#endif
data_link_info_t *data_link_info;
#ifdef HAVE_PCAP_OPEN
pch = pcap_open(devname, MIN_PACKET_SIZE, 0, 0, NULL, errbuf);
#else
pch = pcap_open_live(devname, MIN_PACKET_SIZE, 0, 0, errbuf);
#endif
if (pch == NULL) {
if (err_str != NULL)
*err_str = g_strdup(errbuf);
return NULL;
}
deflt = get_pcap_linktype(pch, devname);
#ifdef HAVE_PCAP_LIST_DATALINKS
nlt = pcap_list_datalinks(pch, &linktypes);
if (nlt == 0 || linktypes == NULL) {
pcap_close(pch);
if (err_str != NULL)
*err_str = NULL; /* an empty list doesn't mean an error */
return NULL;
}
for (i = 0; i < nlt; i++) {
data_link_info = create_data_link_info(linktypes[i]);
/*
* XXX - for 802.11, make the most detailed 802.11
* version the default, rather than the one the
* device has as the default?
*/
if (linktypes[i] == deflt)
linktype_list = g_list_prepend(linktype_list, data_link_info);
else
linktype_list = g_list_append(linktype_list, data_link_info);
}
#ifdef HAVE_PCAP_FREE_DATALINKS
pcap_free_datalinks(linktypes);
#else
/*
* In Windows, there's no guarantee that if you have a library
* built with one version of the MSVC++ run-time library, and
* it returns a pointer to allocated data, you can free that
* data from a program linked with another version of the
* MSVC++ run-time library.
*
* This is not an issue on UN*X.
*
* See the mail threads starting at
*
* http://www.winpcap.org/pipermail/winpcap-users/2006-September/001421.html
*
* and
*
* http://www.winpcap.org/pipermail/winpcap-users/2008-May/002498.html
*/
#ifndef _WIN32
#define xx_free free /* hack so checkAPIs doesn't complain */
xx_free(linktypes);
#endif /* _WIN32 */
#endif /* HAVE_PCAP_FREE_DATALINKS */
#else /* HAVE_PCAP_LIST_DATALINKS */
data_link_info = create_data_link_info(deflt);
linktype_list = g_list_append(linktype_list, data_link_info);
#endif /* HAVE_PCAP_LIST_DATALINKS */
pcap_close(pch);
if (err_str != NULL)
*err_str = NULL;
return linktype_list;
}
/*
* If you change the machine-readable output format of this function,
* you MUST update capture_sync.c:sync_linktype_list_open() accordingly!
*/
static void
print_machine_readable_link_layer_types(GList *lt_list)
{
GList *lt_entry;
data_link_info_t *data_link_info;
const gchar *desc_str;
for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
data_link_info = (data_link_info_t *)lt_entry->data;
if (data_link_info->description != NULL)
desc_str = data_link_info->description;
else
desc_str = "(not supported)";
printf("%d\t%s\t%s\n", data_link_info->dlt, data_link_info->name,
desc_str);
}
}
typedef struct {
char *name;
pcap_t *pch;
@ -3123,8 +3252,27 @@ main(int argc, char *argv[])
status = capture_opts_list_interfaces(machine_readable);
exit_main(status);
} else if (list_link_layer_types) {
status = capture_opts_list_link_layer_types(&global_capture_opts, machine_readable);
exit_main(status);
/* Get the list of link-layer types for the capture device. */
GList *lt_list;
gchar *err_str;
lt_list = get_pcap_linktype_list(global_capture_opts.iface, &err_str);
if (lt_list == NULL) {
if (err_str != NULL) {
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", global_capture_opts.iface, err_str);
g_free(err_str);
} else
cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
exit_main(2);
}
if (machine_readable) /* tab-separated values to stdout */
print_machine_readable_link_layer_types(lt_list);
else
capture_opts_print_link_layer_types(lt_list);
free_pcap_linktype_list(lt_list);
exit_main(0);
} else if (print_statistics) {
status = print_statistics_loop(machine_readable);
exit_main(status);

View File

@ -108,6 +108,7 @@
#ifdef HAVE_LIBPCAP
#include "../capture-pcap-util.h"
#include "../capture_ifinfo.h"
#include "../capture.h"
#include "../capture_sync.h"
#endif
@ -2703,8 +2704,24 @@ main(int argc, char *argv[])
}
if (list_link_layer_types) {
status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
exit(status);
/* Get the list of link-layer types for the capture device. */
GList *lt_list;
gchar *err_str;
lt_list = capture_pcap_linktype_list(global_capture_opts.iface, &err_str);
if (lt_list == NULL) {
if (err_str != NULL) {
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", global_capture_opts.iface, err_str);
g_free(err_str);
} else
cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
exit(2);
}
capture_opts_print_link_layer_types(lt_list);
free_pcap_linktype_list(lt_list);
exit(0);
}
capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);

View File

@ -89,6 +89,7 @@
#ifdef HAVE_LIBPCAP
#include "capture_ui_utils.h"
#include "capture_ifinfo.h"
#include "capture-pcap-util.h"
#ifdef _WIN32
#include "capture-wpcap.h"
@ -1620,8 +1621,24 @@ main(int argc, char *argv[])
/* if requested, list the link layer types and exit */
if (list_link_layer_types) {
status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
exit(status);
/* Get the list of link-layer types for the capture device. */
GList *lt_list;
gchar *err_str;
lt_list = capture_pcap_linktype_list(global_capture_opts.iface, &err_str);
if (lt_list == NULL) {
if (err_str != NULL) {
cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
"Please check to make sure you have sufficient permissions, and that\n"
"you have the proper interface or pipe specified.\n", global_capture_opts.iface, err_str);
g_free(err_str);
} else
cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
exit(2);
}
capture_opts_print_link_layer_types(lt_list);
free_pcap_linktype_list(lt_list);
exit(0);
}
if (print_packet_info) {