extcap: Add list of extcaps to about dialog
authorRoland Knall <roland.knall@br-automation.com>
Tue, 12 Jan 2016 12:45:20 +0000 (13:45 +0100)
committerRoland Knall <rknall@gmail.com>
Fri, 15 Jan 2016 11:30:39 +0000 (11:30 +0000)
Adds the list of available extcaps to the plugin list in the
About dialog of Wireshark (Qt only). To do this, and additional
sentence is provided in the extcap arguments list, which allows
for additional information to be passed (as of right now, just
version and display is used)

Additionally, cleans up the code when using g_free.

Bug: 11683
Change-Id: I04a958e2b73c9a707ab1cb4f2fc8345833a854a9
Reviewed-on: https://code.wireshark.org/review/13224
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org>
Reviewed-by: Roland Knall <rknall@gmail.com>
doc/README.extcap
doc/extcap_example.py
extcap.c
extcap.h
extcap_parser.c
extcap_parser.h
ui/qt/about_dialog.cpp

index cb32683eed0d1b5003cb2b76fdd47ffbc31325d2..50dc1a82f3034e9ca1d8d7d5b537b4b5e2feff3b 100644 (file)
@@ -44,13 +44,17 @@ in the doc/extcap.4 generated man page (in the build dir).
 Example:
 
 $ extcapbin --extcap-interfaces
+extcap {version=1.0}
 interface {value=example1}{display=Example interface 1 for extcap}
 interface {value=example2}{display=Example interface 2 for extcap}
 
+The version for the extcap sentence (which may exist as often as wanted, but only the
+last one will be used) will be used for displaying the version information of the extcap
+interface in the about dialog of Wireshark (Qt only).
+
 The value for each interface will be used in subsequent calls as the interface
 name IFACE.
 
-
 STEP2: the extcap is queried for valid DLTs (Data Link Types) for all the
 interfaces returned by the step 1.
 
index 13c079d0ec39ad9933aa9b7adede1c949f4ff367..39bb571075c09e197bc92899c1ef9b10cb90994a 100755 (executable)
@@ -90,6 +90,7 @@ def extcap_config(interface):
 
 
 def extcap_interfaces():
+       print ("extcap {version=1.0}")
        print ("interface {value=example1}{display=Example interface usage for extcap}")
 
 def extcap_dlts(interface):
index 6bb079ae1ecefa21825578d41f743a6cab962a83..2d0d85fefb4e104799d7495ae4e998fd9141cdcb 100644 (file)
--- a/extcap.c
+++ b/extcap.c
@@ -62,6 +62,12 @@ static HANDLE pipe_h = NULL;
  */
 static GHashTable *ifaces = NULL;
 
+/* internal container, for all the extcap executables that have been found.
+ * will be resetted by every call to extcap_interface_list() and is being
+ * used for printing information about all extcap interfaces found
+ */
+static GHashTable *tools = NULL;
+
 /* Callback definition for extcap_foreach */
 typedef gboolean (*extcap_cb_t)(const gchar *extcap, gchar *output, void *data,
         gchar **err_str);
@@ -116,15 +122,6 @@ extcap_if_executable(const char *ifname)
     return (gchar *)NULL;
 }
 
-static void
-extcap_if_reset(void)
-{
-    if (ifaces == NULL)
-        ifaces = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-
-    g_hash_table_remove_all(ifaces);
-}
-
 static void
 extcap_if_add(gchar *ifname, gchar *extcap)
 {
@@ -136,6 +133,32 @@ extcap_if_add(gchar *ifname, gchar *extcap)
     }
 }
 
+static void
+extcap_tool_add(gchar *extcap, extcap_interface *tool)
+{
+    char * toolname = NULL;
+    extcap_info * extcap_tool = NULL;
+
+    if ( extcap == NULL )
+        return;
+
+    toolname = g_path_get_basename(extcap);
+    extcap_tool = (extcap_info *)g_hash_table_lookup(tools, toolname);
+
+    if ( tools != NULL && extcap_tool == NULL ) {
+        extcap_info * store = (extcap_info *)g_new0(extcap_info, 1);
+        store->version = g_strdup ( tool->version );
+        store->full_path = extcap;
+        store->basename = g_strdup ( toolname );
+
+        g_hash_table_insert(tools, g_strdup(toolname), store);
+    } else {
+        g_free(extcap);
+    }
+
+    g_free(toolname);
+}
+
 /* Note: args does not need to be NULL-terminated. */
 static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
         void *cb_data, char **err_str, const char * ifname _U_) {
@@ -317,7 +340,7 @@ static gboolean interfaces_cb(const gchar *extcap, gchar *output, void *data,
 
     int_iter = interfaces;
     while (int_iter != NULL ) {
-        if ( extcap_if_exists(int_iter->call) )
+        if ( int_iter->if_type == EXTCAP_SENTENCE_INTERFACE && extcap_if_exists(int_iter->call) )
         {
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING, "Extcap interface \"%s\" is already provided by \"%s\" ",
                     int_iter->call, (gchar *)extcap_if_executable(int_iter->call) );
@@ -325,19 +348,29 @@ static gboolean interfaces_cb(const gchar *extcap, gchar *output, void *data,
             continue;
         }
 
-        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "  Interface [%s] \"%s\" ",
-                int_iter->call, int_iter->display);
+        if ( int_iter->if_type == EXTCAP_SENTENCE_INTERFACE )
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "  Interface [%s] \"%s\" ",
+                    int_iter->call, int_iter->display);
+        else if ( int_iter->if_type == EXTCAP_SENTENCE_EXTCAP )
+            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_info->type = IF_EXTCAP;
 
-        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->extcap = g_strdup(extcap);
+            *il = g_list_append(*il, if_info);
 
-        if_info->type = IF_EXTCAP;
+            extcap_if_add(g_strdup(int_iter->call), g_strdup(extcap) );
+        }
 
-        if_info->extcap = g_strdup(extcap);
-        *il = g_list_append(*il, if_info);
+        /* Call for interfaces and tools alike. Multiple calls (because a tool has multiple
+         * interfaces) are handled internally */
+        extcap_tool_add(g_strdup(extcap), int_iter);
 
-        extcap_if_add(g_strdup(int_iter->call), g_strdup(extcap) );
         int_iter = int_iter->next_interface;
     }
     extcap_free_interface(interfaces);
@@ -358,6 +391,23 @@ if_info_compare(gconstpointer a, gconstpointer b)
     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);
+}
+
 GList *
 extcap_interface_list(char **err_str) {
     gchar *argv;
@@ -369,7 +419,15 @@ extcap_interface_list(char **err_str) {
 
     /* ifaces is used as cache, do not destroy its contents when
      * returning or no extcap interfaces can be queried for options */
-    extcap_if_reset();
+    if (ifaces == NULL)
+        ifaces = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+    else
+        g_hash_table_remove_all(ifaces);
+
+    if (tools == NULL)
+        tools = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, extcap_free_info);
+    else
+        g_hash_table_remove_all(tools);
 
     argv = g_strdup(EXTCAP_ARGUMENT_LIST_INTERFACES);
 
@@ -393,7 +451,7 @@ static void extcap_free_if_configuration(GList *list)
             sl = g_list_first((GList *)elem->data);
             g_list_foreach(sl, (GFunc)g_free, NULL);
             g_list_free(sl);
-       }
+        }
     }
     g_list_free(list);
 }
index fa334c59c6e5cb3539a60887fdb7bdea629edcee..74fc0b3b6db013111e37b34be7efddb9b0e4a636 100644 (file)
--- a/extcap.h
+++ b/extcap.h
 #define EXTCAP_ARGUMENT_CAPTURE_FILTER          "--extcap-capture-filter"
 #define EXTCAP_ARGUMENT_RUN_PIPE                "--fifo"
 
+typedef struct _extcap_info {
+    gchar * basename;
+    gchar * full_path;
+    gchar * version;
+} extcap_info;
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -61,6 +67,10 @@ extcap_get_if_dlts(const gchar * ifname, char ** err_str);
 GList *
 extcap_interface_list(char **err_str);
 
+/* get a list of all available extcap tools */
+GHashTable *
+extcap_tools_list(void);
+
 /* returns the configuration for the given interface name, or an
  * empty list, if no configuration has been found */
 GList *
index ac75b50ab391f54ad2c668325c571f63411b84ca..000dd6307cfec1e82764c2bde0f78c8ef41de21d 100644 (file)
@@ -282,7 +282,7 @@ extcap_token_sentence *extcap_tokenize_sentence(const gchar *s) {
     rs->param_list = NULL;
 
     /* Regex for catching just the allowed values for sentences */
-    if ( ( regex = g_regex_new ( "^[\\t| ]*(arg|value|interface|dlt)(?=[\\t| ]+\\{)",
+    if ( ( regex = g_regex_new ( "^[\\t| ]*(arg|value|interface|extcap|dlt)(?=[\\t| ]+\\{)",
             (GRegexCompileFlags) G_REGEX_CASELESS, (GRegexMatchFlags) 0, NULL ) ) != NULL ) {
         g_regex_match ( regex, s, (GRegexMatchFlags) 0, &match_info );
 
@@ -347,6 +347,8 @@ extcap_token_sentence *extcap_tokenize_sentence(const gchar *s) {
                 tv->param_type = EXTCAP_PARAM_REQUIRED;
             } else if (g_ascii_strcasecmp(tv->arg, "validation") == 0) {
                 tv->param_type = EXTCAP_PARAM_VALIDATION;
+            } else if (g_ascii_strcasecmp(tv->arg, "version") == 0) {
+                tv->param_type = EXTCAP_PARAM_VERSION;
             } else {
                 tv->param_type = EXTCAP_PARAM_UNKNOWN;
             }
@@ -408,11 +410,8 @@ void extcap_free_value(extcap_value *v) {
     if (v == NULL)
         return;
 
-    if (v->call != NULL)
-        g_free(v->call);
-
-    if (v->display != NULL)
-        g_free(v->display);
+    g_free(v->call);
+    g_free(v->display);
 
     g_free(v);
 }
@@ -420,7 +419,8 @@ void extcap_free_value(extcap_value *v) {
 extcap_interface *extcap_new_interface(void) {
     extcap_interface *r = g_new(extcap_interface, 1);
 
-    r->call = r->display = NULL;
+    r->call = r->display = r->version = NULL;
+    r->if_type = EXTCAP_SENTENCE_UNKNOWN;
     r->next_interface = NULL;
 
     return r;
@@ -456,11 +456,8 @@ void extcap_free_dlt(extcap_dlt *d) {
     if (d == NULL)
         return;
 
-    if (d->name != NULL)
-        g_free(d->name);
-
-    if (d->display != NULL)
-        g_free(d->display);
+    g_free(d->name);
+    g_free(d->display);
 }
 
 extcap_arg *extcap_new_arg(void) {
@@ -493,20 +490,11 @@ void extcap_free_arg(extcap_arg *a) {
     if (a == NULL)
         return;
 
-    if (a->call != NULL)
-        g_free(a->call);
-
-    if (a->display != NULL)
-        g_free(a->display);
-
-    if (a->tooltip != NULL)
-        g_free(a->tooltip);
-
-    if (a->fileextension != NULL)
-        g_free(a->fileextension);
-
-    if (a->regexp != NULL)
-        g_free(a->regexp);
+    g_free(a->call);
+    g_free(a->display);
+    g_free(a->tooltip);
+    g_free(a->fileextension);
+    g_free(a->regexp);
 
     if (a->range_start != NULL)
         extcap_free_complex(a->range_start);
@@ -780,7 +768,8 @@ int extcap_parse_interface_sentence(extcap_token_sentence *s,
 
     if (g_ascii_strcasecmp(s->sentence, "interface") == 0) {
         sent = EXTCAP_SENTENCE_INTERFACE;
-        /* printf("INTERFACE sentence\n"); */
+    } else if (g_ascii_strcasecmp(s->sentence, "extcap") == 0) {
+        sent = EXTCAP_SENTENCE_EXTCAP;
     }
 
     if (sent == EXTCAP_SENTENCE_UNKNOWN)
@@ -788,21 +777,30 @@ int extcap_parse_interface_sentence(extcap_token_sentence *s,
 
     *ri = extcap_new_interface();
 
+    (*ri)->if_type = sent;
+
     if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_VALUE))
-            == NULL) {
+            == NULL && sent == EXTCAP_SENTENCE_INTERFACE) {
         printf("No value in INTERFACE sentence\n");
         extcap_free_interface(*ri);
         return -1;
     }
-    (*ri)->call = g_strdup(v->value);
+    if ( v != NULL )
+       (*ri)->call = g_strdup(v->value);
 
     if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_DISPLAY))
-            == NULL) {
+            == NULL && sent == EXTCAP_SENTENCE_INTERFACE) {
         printf("No display in INTERFACE sentence\n");
         extcap_free_interface(*ri);
         return -1;
     }
-    (*ri)->display = g_strdup(v->value);
+    if ( v != NULL )
+        (*ri)->display = g_strdup(v->value);
+
+    if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_VERSION))
+            != NULL) {
+        (*ri)->version = g_strdup(v->value);
+    }
 
     return 1;
 }
index 158838c16f9afe39ebb765468923dd1827baef40..d10c5cd8cc3f779be7279feeb40fb7cfc34feb6b 100644 (file)
@@ -30,7 +30,7 @@ typedef enum {
     EXTCAP_SENTENCE_UNKNOWN,
     EXTCAP_SENTENCE_ARG,
     EXTCAP_SENTENCE_VALUE,
-    EXTCAP_SENTENCE_FLAG,
+    EXTCAP_SENTENCE_EXTCAP,
     EXTCAP_SENTENCE_INTERFACE,
     EXTCAP_SENTENCE_DLT
 } extcap_sentence_type;
@@ -70,7 +70,8 @@ typedef enum {
     EXTCAP_PARAM_FILE_EXTENSION,
     EXTCAP_PARAM_PARENT,
     EXTCAP_PARAM_REQUIRED,
-    EXTCAP_PARAM_VALIDATION
+    EXTCAP_PARAM_VALIDATION,
+    EXTCAP_PARAM_VERSION
 } extcap_param_type;
 
 /* Values for a given sentence; values are all stored as a call
@@ -132,7 +133,9 @@ typedef struct _extcap_if {
 typedef struct _extcap_interface {
     gchar *call;
     gchar *display;
+    gchar *version;
 
+    extcap_sentence_type if_type;
     struct _extcap_interface *next_interface;
 } extcap_interface;
 
index c0899a0723cc2cc717815bce38168cf3b8b8cd24..83bbdf80049c505ec351f35c28ed2a434cb45f7d 100644 (file)
 #include "wsutil/copyright_info.h"
 #include "wsutil/ws_version_info.h"
 
+#ifdef HAVE_EXTCAP
+#include "extcap.h"
+#endif
+
 #include "qt_ui_utils.h"
 
 #include <QFontMetrics>
@@ -114,6 +118,28 @@ const QString AboutDialog::plugins_scan()
                 .arg(plugin_row[2]) // Type
                 .arg(short_file);
     }
+
+    GHashTable * tools = extcap_tools_list();
+    if ( tools != NULL && g_hash_table_size(tools) > 0 )
+    {
+        QString short_file;
+        GList * walker = g_list_first(g_hash_table_get_keys(tools));
+        while ( walker )
+        {
+            extcap_info * tool = (extcap_info *)g_hash_table_lookup(tools, walker->data);
+            if ( tool != NULL )
+            {
+                short_file = fontMetrics().elidedText(tool->full_path, Qt::ElideMiddle, one_em*22);
+                plugin_table += QString("<tr><td>%1</td><td>%2</td><td>%3</td><td>%4</td></tr>\n")
+                       .arg(tool->basename) // Name
+                       .arg(tool->version) // Version
+                       .arg("extcap") // Type
+                       .arg(short_file);
+            }
+            walker = g_list_next(walker);
+        }
+    }
+
     return plugin_table;
 }