summaryrefslogtreecommitdiff
path: root/extcap.c
diff options
context:
space:
mode:
authorStig Bjørlykke <stig@bjorlykke.org>2017-04-15 23:30:30 +0200
committerStig Bjørlykke <stig@bjorlykke.org>2017-04-25 06:19:39 +0000
commit77751c94f17e2c110ae9e88b1780e279d610b96b (patch)
treecd3a06ccf7944b3e131234ac86ae7b26ced8ea6b /extcap.c
parentcd55bd29258b8e0ffae9ea9471059b457ebb59ae (diff)
downloadwireshark-77751c94f17e2c110ae9e88b1780e279d610b96b.tar.gz
Qt: Add interface toolbar support
An extcap utility can provide configuration for controls to use in a GUI interface toolbar. This controls are bidirectional and can be used to control the extcap utility while capturing. This is useful in scenarios where configuration can be done based on findings in the capture process, setting temporary values or give other inputs without restarting current capture. Todo: - Add support for Windows Change-Id: Ie15fa67f92eb27d8b73df6bb36f66b9a7d81932d Reviewed-on: https://code.wireshark.org/review/19982 Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org>
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);