#include <glib.h>
#include <log.h>
+#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+
#include <wsutil/file_util.h>
#include <wsutil/filesystem.h>
#include <wsutil/tempfile.h>
static GHashTable *tools = NULL;
/* Callback definition for extcap_foreach */
-typedef gboolean (*extcap_cb_t)(const gchar *extcap, gchar *output, void *data,
+typedef gboolean (*extcap_cb_t)(const gchar *extcap, const gchar *ifname, gchar *output, void *data,
gchar **err_str);
/* #define ARG_DEBUG */
g_hash_table_insert(ifaces, g_strdup(ifname), g_strdup(extcap));
}
+static void
+extcap_free_info (gpointer data) {
+ extcap_info * info = (extcap_info *)data;
+
+ g_free (info->basename);
+ g_free (info->full_path);
+ g_free (info->version);
+ g_free (info);
+}
+
static void
extcap_tool_add(const gchar *extcap, const extcap_interface *interface)
{
gchar *command_output = NULL;
gboolean status = FALSE;
gint exit_status = 0;
- GError *error = NULL;
gchar **envp = NULL;
/* full path to extcap binary */
status = g_spawn_sync(dirname, argv, envp,
(GSpawnFlags) 0, NULL, NULL,
- &command_output, NULL, &exit_status, &error);
+ &command_output, NULL, &exit_status, NULL);
if (status && exit_status == 0)
- keep_going = cb(extcap_path->str, command_output, cb_data, err_str);
+ keep_going = cb(extcap_path->str, ifname, command_output, cb_data, err_str);
g_free(argv[0]);
g_free(command_output);
g_free(argv);
}
-static gboolean dlt_cb(const gchar *extcap _U_, gchar *output, void *data,
+static gboolean dlt_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data,
char **err_str) {
extcap_token_sentence *tokens;
extcap_dlt *dlts, *dlt_iter, *next;
gint i;
if_capabilities_t *caps = NULL;
- if (ifname != NULL && err_str != NULL)
+ if (err_str != NULL)
*err_str = NULL;
if ( extcap_if_exists(ifname) )
argv[1] = g_strdup(EXTCAP_ARGUMENT_INTERFACE);
argv[2] = g_strdup(ifname);
- if (err_str)
- *err_str = NULL;
extcap_foreach(3, argv, dlt_cb, &caps, err_str, ifname);
for (i = 0; i < 3; ++i)
return caps;
}
-static gboolean interfaces_cb(const gchar *extcap, gchar *output, void *data,
+static gboolean interfaces_cb(const gchar *extcap, const gchar *ifname _U_, gchar *output, void *data,
char **err_str _U_) {
GList **il = (GList **) data;
extcap_token_sentence *tokens;
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, " Extcap [%s] ", int_iter->call);
if ( int_iter->if_type == EXTCAP_SENTENCE_INTERFACE ) {
- if_info = g_new0(if_info_t, 1);
- if_info->name = g_strdup(int_iter->call);
- if_info->friendly_name = g_strdup(int_iter->display);
+ if (il != NULL) {
+ if_info = g_new0(if_info_t, 1);
+ if_info->name = g_strdup(int_iter->call);
+ if_info->friendly_name = g_strdup(int_iter->display);
- if_info->type = IF_EXTCAP;
+ if_info->type = IF_EXTCAP;
- if_info->extcap = g_strdup(extcap);
- *il = g_list_append(*il, if_info);
+ if_info->extcap = g_strdup(extcap);
+ *il = g_list_append(*il, if_info);
+ }
extcap_if_add(int_iter->call, extcap);
}
return comp;
}
-GHashTable *
-extcap_tools_list(void) {
- if ( tools == NULL || g_hash_table_size(tools) == 0 )
- extcap_interface_list(NULL);
-
- return tools;
-}
-
static void
-extcap_free_info (gpointer data) {
- extcap_info * info = (extcap_info *)data;
-
- g_free (info->basename);
- g_free (info->full_path);
- g_free (info->version);
- g_free (info);
-}
-
-GList *
-extcap_interface_list(char **err_str) {
+extcap_reload_interface_list(GList **retp, char **err_str) {
gchar *argv;
- /* gint i; */
- GList *ret = NULL;
if (err_str != NULL)
- *err_str = NULL;
+ *err_str = NULL;
/* ifaces is used as cache, do not destroy its contents when
* returning or no extcap interfaces can be queried for options */
argv = g_strdup(EXTCAP_ARGUMENT_LIST_INTERFACES);
- if (err_str)
- *err_str = NULL;
- extcap_foreach(1, &argv, interfaces_cb, &ret, err_str, NULL);
+ extcap_foreach(1, &argv, interfaces_cb, retp, err_str, NULL);
g_free(argv);
+}
+
+GHashTable *
+extcap_tools_list(void) {
+ if ( tools == NULL || g_hash_table_size(tools) == 0 )
+ extcap_reload_interface_list(NULL, NULL);
- return g_list_sort ( ret, if_info_compare );
+ return tools;
+}
+
+GList *
+append_extcap_interface_list(GList *list, char **err_str) {
+ GList *ret = NULL;
+ GList *entry;
+ void *data;
+
+ /* Update the extcap interfaces and get a list of their if_infos */
+ extcap_reload_interface_list(&ret, err_str);
+
+ /* Sort that list */
+ ret = g_list_sort(ret, if_info_compare);
+
+ /* Append the interfaces in that list to the list we're handed. */
+ while (ret != NULL) {
+ entry = g_list_first(ret);
+ data = entry->data;
+ ret = g_list_delete_link(ret, entry);
+ list = g_list_append(list, data);
+ }
+ return list;
+}
+
+static void extcap_free_arg_elem(gpointer data, gpointer user_data _U_) {
+ extcap_free_arg((extcap_arg *) data);
+ g_free(data);
+}
+
+void extcap_register_preferences(void)
+{
+ GList * interfaces = NULL;
+
+ module_t * dev_module = prefs_find_module("extcap");
+
+ if ( !dev_module )
+ return;
+
+ if ( ! ifaces || g_hash_table_size(ifaces) == 0 )
+ extcap_reload_interface_list(NULL, NULL);
+
+ interfaces = g_hash_table_get_keys(ifaces);
+
+ while ( interfaces ) {
+ extcap_get_if_configuration((gchar *)interfaces->data);
+
+ interfaces = g_list_next(interfaces);
+ }
}
static void extcap_free_if_configuration(GList *list)
if (elem->data != NULL) {
/* g_list_free_full() only exists since 2.28. */
sl = g_list_first((GList *)elem->data);
- g_list_foreach(sl, (GFunc)g_free, NULL);
+ g_list_foreach(sl, (GFunc)extcap_free_arg_elem, NULL);
g_list_free(sl);
}
}
g_list_free(list);
}
-static gboolean search_cb(const gchar *extcap _U_, gchar *output, void *data,
+gchar * extcap_settings_key(const gchar * ifname, const gchar * setting)
+{
+ gchar * setting_nohyphen;
+ gchar * ifname_underscore;
+ gchar * ifname_lower;
+ gchar * key;
+ GRegex * regex = g_regex_new ("(?![a-zA-Z1-9_]).", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL );
+
+ if (!regex)
+ return NULL;
+
+ setting_nohyphen =
+ g_regex_replace_literal(regex, setting, strlen(setting), 0,
+ "", (GRegexMatchFlags) 0, NULL );
+ ifname_underscore =
+ g_regex_replace_literal(regex, ifname, strlen(ifname), 0,
+ "_", (GRegexMatchFlags) 0, NULL );
+ ifname_lower = g_utf8_strdown(ifname_underscore, -1);
+ key = g_strconcat(ifname_lower, ".", setting_nohyphen, NULL);
+
+ g_free(setting_nohyphen);
+ g_free(ifname_underscore);
+ g_free(ifname_lower);
+ g_regex_unref(regex);
+
+ return key;
+}
+
+static gboolean search_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data,
char **err_str _U_) {
extcap_token_sentence *tokens = NULL;
GList *arguments = NULL;
GList **il = (GList **) data;
+ module_t * dev_module = NULL;
tokens = extcap_tokenize_sentences(output);
arguments = extcap_parse_args(tokens);
extcap_debug_arguments ( arguments );
#endif
+ dev_module = prefs_find_module("extcap");
+
+ if ( dev_module ) {
+ GList * walker = arguments;
+
+ while ( walker != NULL ) {
+ extcap_arg * arg = (extcap_arg *)walker->data;
+
+ if ( arg->save ) {
+ struct preference * pref = NULL;
+ gchar * pref_ifname = extcap_settings_key(ifname, arg->call);
+
+ if ( ( pref = prefs_find_preference(dev_module, pref_ifname) ) == NULL ) {
+ /* Set an initial value */
+ if ( ! arg->storeval && arg->default_complex )
+ arg->storeval = g_strdup(arg->default_complex->_val);
+
+ prefs_register_string_preference(dev_module, g_strdup(pref_ifname),
+ arg->display, arg->display, (const gchar **)&(arg->storeval));
+ } else {
+ /* Been here before, restore stored value */
+ if (! arg->storeval && pref->varp.string)
+ arg->storeval = g_strdup(*(pref->varp.string));
+ }
+ g_free(pref_ifname);
+ }
+
+ walker = g_list_next(walker);
+ }
+ }
+
*il = g_list_append(*il, arguments);
/* By returning false, extcap_foreach will break on first found */
arguments = extcap_get_if_configuration((const char *)( ifname ) );
walker = g_list_first(arguments);
- while ( walker != NULL && ! found )
- {
+ while ( walker != NULL && ! found ) {
item = g_list_first((GList *)(walker->data));
- while ( item != NULL && ! found )
- {
- if ( (extcap_arg *)(item->data) != NULL )
- {
+ while ( item != NULL && ! found ) {
+ if ( (extcap_arg *)(item->data) != NULL ) {
+ extcap_arg * arg = (extcap_arg *)(item->data);
/* Should required options be present, or any kind of options */
- if ( ! is_required || ((extcap_arg *)(item->data))->is_required )
+ if ( ! is_required )
found = TRUE;
+ else if ( arg->is_required ) {
+ gchar * stored = NULL;
+ gchar * defval = NULL;
+
+ if ( arg->storeval != NULL )
+ stored = arg->storeval;
+
+ if ( arg->default_complex != NULL && arg->default_complex->_val != NULL )
+ defval = arg->default_complex->_val;
+
+ if ( arg->is_required ) {
+ /* If stored and defval is identical and the argument is required,
+ * configuration is needed */
+ if ( defval && stored && g_strcmp0(stored, defval) == 0 )
+ found = TRUE;
+ else if ( ! defval && (!stored || strlen(g_strchomp(stored)) <= (size_t)0) )
+ found = TRUE;
+ }
+
+ if ( arg->arg_type == EXTCAP_ARG_FILESELECT ) {
+ if ( arg->fileexists && ! ( file_exists(defval) || file_exists(stored) ) )
+ found = TRUE;
+ }
+ }
}
item = item->next;
}
walker = walker->next;
}
+ extcap_free_if_configuration(arguments);
return found;
}
"Extcap [%s] - Closing spawned PID: %d", interface_opts.name,
interface_opts.extcap_pid);
- if (interface_opts.extcap_child_watch > 0)
- {
- g_source_remove(interface_opts.extcap_child_watch);
- interface_opts.extcap_child_watch = 0;
- }
-
if (interface_opts.extcap_pid != INVALID_EXTCAP_PID)
{
#ifdef _WIN32
}
}
-static void
-extcap_arg_cb(gpointer key, gpointer value, gpointer data) {
+static gboolean
+extcap_add_arg_and_remove_cb(gpointer key, gpointer value, gpointer data) {
GPtrArray *args = (GPtrArray *)data;
if ( key != NULL )
if ( value != NULL )
g_ptr_array_add(args, g_strdup((const gchar*)value));
+
+ return TRUE;
}
+
+ return FALSE;
}
static void extcap_child_watch_cb(GPid pid, gint status _U_, gpointer user_data)
if (interface_opts.extcap_pid == pid)
{
interface_opts.extcap_pid = INVALID_EXTCAP_PID;
+ g_source_remove(interface_opts.extcap_child_watch);
interface_opts.extcap_child_watch = 0;
+
capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
g_array_insert_val(capture_opts->ifaces, i, interface_opts);
break;
}
add_arg(EXTCAP_ARGUMENT_RUN_PIPE);
add_arg(interface_opts.extcap_fifo);
- if (interface_opts.extcap_args == NULL)
+ if (interface_opts.extcap_args == NULL || g_hash_table_size(interface_opts.extcap_args) == 0)
{
/* User did not perform interface configuration.
*
}
arg_list = g_list_first((GList *)elem->data);
- while (arg_list != NULL)
- {
+ while (arg_list != NULL) {
+ gchar * stored = NULL, * defval = NULL;
/* In case of boolflags only first element in arg_list is relevant. */
arg_iter = (extcap_arg*) (arg_list->data);
-
- if (arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG)
- {
- if (arg_iter->default_complex != NULL
- && extcap_complex_get_bool(arg_iter->default_complex))
- {
- add_arg(arg_iter->call);
+ if ( arg_iter->storeval != NULL )
+ stored = arg_iter->storeval;
+
+ if ( arg_iter->default_complex != NULL && arg_iter->default_complex->_val != NULL )
+ defval = arg_iter->default_complex->_val;
+
+ /* Different data in storage then set for default */
+ if ( g_strcmp0(stored, defval) != 0 ) {
+ if ( arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG ) {
+ if ( g_strcmp0(stored, "true") == 0 )
+ add_arg(arg_iter->call);
+ } else {
+ gchar * call = g_strconcat(arg_iter->call, " ", stored, NULL);
+ add_arg(call);
+ g_free(call);
}
+ } else if (arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG) {
+ if (extcap_complex_get_bool(arg_iter->default_complex))
+ add_arg(arg_iter->call);
}
arg_list = arg_list->next;
}
else
{
- g_hash_table_foreach(interface_opts.extcap_args, extcap_arg_cb, args);
+ g_hash_table_foreach_remove(interface_opts.extcap_args, extcap_add_arg_and_remove_cb, args);
}
add_arg(NULL);
#undef add_arg