tshark: Cache the interface list
For tshark, cache the interface list the first time it is retrieved, instead of launching dumpcap once for each interface specified in the capture options, and when getting each interfaces descriptive name at the start of the capture. If the interface list changes when in the middle of processing options before the capture starts we have problems anyway. On Windows, this means not getting multiple UAC pop-ups if npcap is installed limited to Administrator privileges. We can probably do this for the GUI as well, since the command line options for capture are only parsed at startup. Fix #16625
This commit is contained in:
parent
c62e98c0f5
commit
3b9de4df3d
|
@ -407,6 +407,31 @@ if_info_get(const char *name)
|
|||
return if_info;
|
||||
}
|
||||
|
||||
if_addr_t *
|
||||
if_addr_copy(const if_addr_t *addr)
|
||||
{
|
||||
if_addr_t *new_addr = g_new(if_addr_t, 1);
|
||||
new_addr->ifat_type = addr->ifat_type;
|
||||
switch (addr->ifat_type) {
|
||||
case IF_AT_IPv4:
|
||||
new_addr->addr.ip4_addr = addr->addr.ip4_addr;
|
||||
break;
|
||||
case IF_AT_IPv6:
|
||||
memcpy(new_addr->addr.ip6_addr, addr->addr.ip6_addr, sizeof(addr->addr));
|
||||
break;
|
||||
default:
|
||||
/* In case we add non-IP addresses */
|
||||
break;
|
||||
}
|
||||
return new_addr;
|
||||
}
|
||||
|
||||
static void*
|
||||
if_addr_copy_cb(const void *data, void *user_data _U_)
|
||||
{
|
||||
return if_addr_copy((if_addr_t*)data);
|
||||
}
|
||||
|
||||
void
|
||||
if_info_free(if_info_t *if_info)
|
||||
{
|
||||
|
@ -418,6 +443,29 @@ if_info_free(if_info_t *if_info)
|
|||
g_free(if_info);
|
||||
}
|
||||
|
||||
if_info_t *
|
||||
if_info_copy(const if_info_t *if_info)
|
||||
{
|
||||
if_info_t *new_if_info;
|
||||
new_if_info = g_new(if_info_t, 1);
|
||||
new_if_info->name = g_strdup(if_info->name);
|
||||
/* g_strdup accepts NULL as input and returns NULL. */
|
||||
new_if_info->friendly_name = g_strdup(if_info->friendly_name);
|
||||
new_if_info->vendor_description = g_strdup(if_info->vendor_description);
|
||||
new_if_info->addrs = g_slist_copy_deep(if_info->addrs, if_addr_copy_cb, NULL);
|
||||
new_if_info->type = if_info->type;
|
||||
new_if_info->loopback = if_info->loopback;
|
||||
new_if_info->extcap = g_strdup(if_info->extcap);
|
||||
|
||||
return new_if_info;
|
||||
}
|
||||
|
||||
static void*
|
||||
if_info_copy_cb(const void* data, void *user_data _U_)
|
||||
{
|
||||
return if_info_copy((const if_info_t*)data);
|
||||
}
|
||||
|
||||
if_info_t *
|
||||
if_info_new(const char *name, const char *description, bool loopback)
|
||||
{
|
||||
|
@ -739,6 +787,12 @@ free_interface_list(GList *if_list)
|
|||
g_list_free(if_list);
|
||||
}
|
||||
|
||||
GList*
|
||||
interface_list_copy(GList *if_list)
|
||||
{
|
||||
return g_list_copy_deep(if_list, if_info_copy_cb, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
free_linktype_cb(void * data, void * user_data _U_)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,11 @@ extern GList *capture_interface_list(int *err, char **err_str, void (*update_cb)
|
|||
|
||||
void free_interface_list(GList *if_list);
|
||||
|
||||
/**
|
||||
* Deep copy an interface list
|
||||
*/
|
||||
GList * interface_list_copy(GList *if_list);
|
||||
|
||||
/**
|
||||
* Get an if_info_t for a particular interface.
|
||||
* (May require privilege, so should only be used by dumpcap.)
|
||||
|
@ -94,6 +99,16 @@ extern if_info_t *if_info_get(const char *name);
|
|||
*/
|
||||
void if_info_free(if_info_t *if_info);
|
||||
|
||||
/**
|
||||
* Deep copy an if_info_t.
|
||||
*/
|
||||
if_info_t *if_info_copy(const if_info_t *if_info);
|
||||
|
||||
/**
|
||||
* Deep copy an if_addr_t.
|
||||
*/
|
||||
if_addr_t *if_addr_copy(const if_addr_t *if_addr);
|
||||
|
||||
/*
|
||||
* "get_if_capabilities()" and "capture_if_capabilities()" return a pointer
|
||||
* to an allocated instance of this structure. "free_if_capabilities()"
|
||||
|
|
14
tshark.c
14
tshark.c
|
@ -905,13 +905,22 @@ warn_about_capture_filter(const char *rfilter)
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_LIBPCAP
|
||||
static GList *cached_if_list = NULL;
|
||||
|
||||
static GList *
|
||||
capture_opts_get_interface_list(int *err, char **err_str)
|
||||
{
|
||||
if (cached_if_list == NULL) {
|
||||
/*
|
||||
* This isn't a GUI tool, so no need for a callback.
|
||||
*/
|
||||
return capture_interface_list(err, err_str, NULL);
|
||||
cached_if_list = capture_interface_list(err, err_str, NULL);
|
||||
}
|
||||
/*
|
||||
* Routines expect to free the returned interface list, so return
|
||||
* a deep copy.
|
||||
*/
|
||||
return interface_list_copy(cached_if_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2716,6 +2725,9 @@ clean_exit:
|
|||
g_free(output_file_name);
|
||||
#ifdef HAVE_LIBPCAP
|
||||
capture_opts_cleanup(&global_capture_opts);
|
||||
if (cached_if_list) {
|
||||
free_interface_list(cached_if_list);
|
||||
}
|
||||
#endif
|
||||
col_cleanup(&cfile.cinfo);
|
||||
wtap_cleanup();
|
||||
|
|
Loading…
Reference in New Issue