aboutsummaryrefslogtreecommitdiffstats
path: root/extcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'extcap.c')
-rw-r--r--extcap.c171
1 files changed, 169 insertions, 2 deletions
diff --git a/extcap.c b/extcap.c
index 87ec4f5d00..c9e357bf19 100644
--- a/extcap.c
+++ b/extcap.c
@@ -49,6 +49,8 @@
#include <epan/prefs.h>
+#include "ui/iface_toolbar.h"
+
#include <wsutil/file_util.h>
#include <wsutil/filesystem.h>
#include <wsutil/tempfile.h>
@@ -77,6 +79,11 @@ static GHashTable * _loaded_interfaces = NULL;
*/
static GHashTable * _tool_for_ifname = NULL;
+/* internal container, for all the extcap executables that have been found
+ * and that provides a toolbar with controls to be added to a Interface Toolbar
+ */
+static GHashTable *_toolbars = NULL;
+
/* internal container, to map preference names to pointers that hold preference
* values. These ensure that preferences can survive extcap if garbage
* collection, and does not lead to dangling pointers in the prefs subsystem.
@@ -198,6 +205,56 @@ extcap_find_interface_for_ifname(const gchar *ifname)
return result;
}
+static void
+extcap_free_toolbar_value(iface_toolbar_value *value)
+{
+ if (!value)
+ {
+ return;
+ }
+
+ g_free(value->value);
+ g_free(value->display);
+ g_free(value);
+}
+
+static void
+extcap_free_toolbar_control(iface_toolbar_control *control)
+{
+ if (!control)
+ {
+ return;
+ }
+
+ g_free(control->display);
+ g_free(control->validation);
+ g_free(control->tooltip);
+ if (control->ctrl_type == INTERFACE_TYPE_STRING) {
+ g_free(control->default_value.string);
+ }
+ g_list_foreach(control->values, (GFunc)extcap_free_toolbar_value, NULL);
+ g_list_free(control->values);
+ g_free(control);
+}
+
+static void
+extcap_free_toolbar(gpointer data)
+{
+ if (!data)
+ {
+ return;
+ }
+
+ iface_toolbar *toolbar = (iface_toolbar *)data;
+
+ g_free(toolbar->menu_title);
+ g_free(toolbar->help);
+ g_list_free_full(toolbar->ifnames, g_free);
+ g_list_foreach(toolbar->controls, (GFunc)extcap_free_toolbar_control, NULL);
+ g_list_free(toolbar->controls);
+ g_free(toolbar);
+}
+
static gboolean
extcap_if_exists_for_extcap(const gchar *ifname, const gchar *extcap)
{
@@ -218,6 +275,26 @@ extcap_if_executable(const gchar *ifname)
return interface != NULL ? interface->extcap_path : NULL;
}
+static void
+extcap_iface_toolbar_add(const gchar *extcap, iface_toolbar *toolbar_entry)
+{
+ char *toolname;
+
+ if (!extcap || !toolbar_entry)
+ {
+ return;
+ }
+
+ toolname = g_path_get_basename(extcap);
+
+ if (!g_hash_table_lookup(_toolbars, toolname))
+ {
+ g_hash_table_insert(_toolbars, g_strdup(toolname), toolbar_entry);
+ }
+
+ g_free(toolname);
+}
+
/* Note: args does not need to be NULL-terminated. */
static gboolean extcap_foreach(gint argc, gchar **args,
extcap_cb_t cb, extcap_callback_info_t cb_info)
@@ -815,6 +892,27 @@ extcap_has_configuration(const char *ifname, gboolean is_required)
return found;
}
+gboolean
+extcap_has_toolbar(const char *ifname)
+{
+ if (!iface_toolbar_use())
+ {
+ return FALSE;
+ }
+
+ GList *toolbar_list = g_hash_table_get_values (_toolbars);
+ for (GList *walker = toolbar_list; walker; walker = walker->next)
+ {
+ iface_toolbar *toolbar = (iface_toolbar *) walker->data;
+ if (g_list_find_custom(toolbar->ifnames, ifname, (GCompareFunc) strcmp))
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
/* taken from capchild/capture_sync.c */
static gboolean pipe_data_available(int pipe_fd)
{
@@ -896,6 +994,16 @@ void extcap_if_cleanup(capture_options *capture_opts, gchar **errormsg)
ws_unlink(interface_opts.extcap_fifo);
interface_opts.extcap_fifo = NULL;
}
+ if (interface_opts.extcap_control_in && file_exists(interface_opts.extcap_control_in))
+ {
+ ws_unlink(interface_opts.extcap_control_in);
+ interface_opts.extcap_control_in = NULL;
+ }
+ if (interface_opts.extcap_control_out && file_exists(interface_opts.extcap_control_out))
+ {
+ ws_unlink(interface_opts.extcap_control_out);
+ interface_opts.extcap_control_out = NULL;
+ }
#endif
/* Maybe the client closed and removed fifo, but ws should check if
* pid should be closed */
@@ -1088,6 +1196,16 @@ GPtrArray *extcap_prepare_arguments(interface_options interface_opts)
}
add_arg(EXTCAP_ARGUMENT_RUN_PIPE);
add_arg(interface_opts.extcap_fifo);
+ if (interface_opts.extcap_control_in)
+ {
+ add_arg(EXTCAP_ARGUMENT_CONTROL_OUT);
+ add_arg(interface_opts.extcap_control_in);
+ }
+ if (interface_opts.extcap_control_out)
+ {
+ add_arg(EXTCAP_ARGUMENT_CONTROL_IN);
+ add_arg(interface_opts.extcap_control_out);
+ }
if (interface_opts.extcap_args == NULL || g_hash_table_size(interface_opts.extcap_args) == 0)
{
/* User did not perform interface configuration.
@@ -1189,6 +1307,13 @@ extcap_init_interfaces(capture_options *capture_opts)
continue;
}
+ /* create control pipes if having toolbar */
+ if (extcap_has_toolbar(interface_opts.name))
+ {
+ extcap_create_pipe(&interface_opts.extcap_control_in);
+ extcap_create_pipe(&interface_opts.extcap_control_out);
+ }
+
/* create pipe for fifo */
if (!extcap_create_pipe(&interface_opts.extcap_fifo))
{
@@ -1393,15 +1518,22 @@ static void remove_extcap_entry(gpointer entry, gpointer data _U_)
static gboolean cb_load_interfaces(extcap_callback_info_t cb_info)
{
- GList * interfaces = NULL, * walker = NULL;
+ GList * interfaces = NULL, * control_items = NULL, * walker = NULL;
extcap_interface * int_iter = NULL;
extcap_info * element = NULL;
+ iface_toolbar * toolbar_entry = NULL;
gchar * toolname = g_path_get_basename(cb_info.extcap);
GList * interface_keys = g_hash_table_get_keys(_loaded_interfaces);
/* Load interfaces from utility */
- interfaces = extcap_parse_interfaces(cb_info.output);
+ interfaces = extcap_parse_interfaces(cb_info.output, &control_items);
+
+ if (control_items)
+ {
+ toolbar_entry = g_new0(iface_toolbar, 1);
+ toolbar_entry->controls = control_items;
+ }
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Loading interface list for %s ", cb_info.extcap);
@@ -1447,6 +1579,11 @@ static gboolean cb_load_interfaces(extcap_callback_info_t cb_info)
}
help = int_iter->help;
+ if (toolbar_entry)
+ {
+ toolbar_entry->menu_title = g_strdup(int_iter->display);
+ toolbar_entry->help = g_strdup(int_iter->help);
+ }
walker = g_list_next(walker);
continue;
@@ -1476,11 +1613,26 @@ static gboolean cb_load_interfaces(extcap_callback_info_t cb_info)
element->interfaces = g_list_append(element->interfaces, int_iter);
g_hash_table_insert(_tool_for_ifname, g_strdup(int_iter->call), g_strdup(toolname));
+
+ if (toolbar_entry)
+ {
+ if (!toolbar_entry->menu_title)
+ {
+ toolbar_entry->menu_title = g_strdup(int_iter->display);
+ }
+ toolbar_entry->ifnames = g_list_append(toolbar_entry->ifnames, g_strdup(int_iter->call));
+ }
}
walker = g_list_next(walker);
}
+ if (toolbar_entry && toolbar_entry->menu_title)
+ {
+ iface_toolbar_add(toolbar_entry);
+ extcap_iface_toolbar_add(cb_info.extcap, toolbar_entry);
+ }
+
g_list_foreach(interfaces, remove_extcap_entry, NULL);
g_list_free(interfaces);
g_list_free(interface_keys);
@@ -1499,6 +1651,21 @@ extcap_load_interface_list(void)
gchar *argv;
gchar *error;
+ if (_toolbars)
+ {
+ // Remove existing interface toolbars here instead of in extcap_clear_interfaces()
+ // to avoid flicker in shown toolbars when refreshing interfaces.
+ GList *toolbar_list = g_hash_table_get_values (_toolbars);
+ for (GList *walker = toolbar_list; walker; walker = walker->next)
+ {
+ iface_toolbar *toolbar = (iface_toolbar *) walker->data;
+ iface_toolbar_remove(toolbar->menu_title);
+ }
+ g_hash_table_remove_all(_toolbars);
+ } else {
+ _toolbars = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, extcap_free_toolbar);
+ }
+
if (_loaded_interfaces == NULL)
{
_loaded_interfaces = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, extcap_free_interface_info);