extcap: Really don't load extcap interfaces if disabled

If the capture.no_extcap preference is set, really don't load the
extcap interfaces. Previously, the extcap interfaces were loaded
before the preference was read, because otherwise the extcap
preferences wouldn't be registered and properly read out of the
configuration file.

Wait until after that preference is read to register the
extcap preferences and then re-read just the extcap module
preferences from the configuration files. Make sure to check
other times when the preference may be changed, such as
switching profiles.

Write extcap prefs to a separate file so that they don't get lost
if the extcap interfaces aren't loaded and the prefs are then
written out. Continue writing them to the main file for backwards
compability.

Related to #15295. Cuts ~100 ms off the loading time of Wireshark
in a normal situation if the capture.no_extcap preference is set,
more if an extcap has some kind of issue that makes it take a long
time to load.
This commit is contained in:
John Thacker 2024-02-14 20:22:00 -05:00 committed by AndersBroman
parent 48bb12831b
commit 4fb2ef8af8
7 changed files with 131 additions and 15 deletions

View File

@ -264,6 +264,16 @@ WS_DLL_PUBLIC
int
read_prefs_file(const char *pf_path, FILE *pf, pref_set_pair_cb pref_set_pair_fct, void *private_data);
/** Given a module name, read the preferences associated with only that module.
* Checks for a file in the personal configuration directory named after the
* module first.
*
* @param name The preference module name, e.g. "extcap".
*/
WS_DLL_PUBLIC
void
prefs_read_module(const char *name);
WS_DLL_PUBLIC
gboolean
prefs_pref_is_default(pref_t *pref);

View File

@ -4520,6 +4520,52 @@ read_registry(void)
}
#endif
void
prefs_read_module(const char *module)
{
int err;
char *pf_path;
FILE *pf;
module_t *target_module = prefs_find_module(module);
if (!target_module) {
return;
}
/* Construct the pathname of the user's preferences file for the module. */
pf_path = get_persconffile_path(module, TRUE);
/* Read the user's preferences file, if it exists. */
if ((pf = ws_fopen(pf_path, "r")) == NULL && errno == ENOENT) {
g_free(pf_path);
/* Fall back to the user's generic preferences file. */
pf_path = get_persconffile_path(PF_NAME, TRUE);
pf = ws_fopen(pf_path, "r");
}
if (pf != NULL) {
/* We succeeded in opening it; read it. */
err = read_prefs_file(pf_path, pf, set_pref, target_module);
if (err != 0) {
/* We had an error reading the file; report it. */
report_warning("Error reading your preferences file \"%s\": %s.",
pf_path, g_strerror(err));
} else
g_free(pf_path);
fclose(pf);
} else {
/* We failed to open it. If we failed for some reason other than
"it doesn't exist", return the errno and the pathname, so our
caller can report the error. */
if (errno != ENOENT) {
report_warning("Can't open your preferences file \"%s\": %s.",
pf_path, g_strerror(errno));
} else
g_free(pf_path);
}
return;
}
/* Read the preferences file, fill in "prefs", and return a pointer to it.
@ -5690,7 +5736,7 @@ deprecated_port_pref(gchar *pref_name, const gchar *value)
}
static prefs_set_pref_e
set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
set_pref(gchar *pref_name, const gchar *value, void *private_data,
gboolean return_range_errors)
{
guint cval;
@ -5700,11 +5746,13 @@ set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
gchar *dotp, *last_dotp;
static gchar *filter_label = NULL;
static gboolean filter_enabled = FALSE;
module_t *module, *containing_module;
module_t *module, *containing_module, *target_module;
pref_t *pref;
int type;
gboolean converted_pref = FALSE;
target_module = (module_t*)private_data;
//The PRS_GUI field names are here for backwards compatibility
//display filters have been converted to a UAT.
if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
@ -6149,6 +6197,11 @@ set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
return PREFS_SET_NO_SUCH_PREF; /* no such preference */
}
if (target_module && target_module != containing_module) {
/* Ignore */
return PREFS_SET_OK;
}
type = pref->type;
if (IS_PREF_OBSOLETE(type)) {
return PREFS_SET_OBSOLETE; /* no such preference any more */
@ -7055,6 +7108,31 @@ write_prefs(char **pf_path_return)
g_free(err);
}
}
module_t *extcap_module = prefs_find_module("extcap");
if (extcap_module && !prefs.capture_no_extcap) {
char *ext_path = get_persconffile_path("extcap", TRUE);
FILE *extf;
if ((extf = ws_fopen(ext_path, "w")) == NULL) {
*pf_path_return = ext_path;
return errno;
}
g_free(ext_path);
fputs("# Extcap configuration file for Wireshark " VERSION ".\n"
"#\n"
"# This file is regenerated each time preferences are saved within\n"
"# Wireshark. Making manual changes should be safe, however.\n"
"# Preferences that have been commented out have not been\n"
"# changed from their default value.\n", extf);
write_gui_pref_info.pf = extf;
write_gui_pref_info.is_gui_module = FALSE;
write_module_prefs(extcap_module, &write_gui_pref_info);
fclose(extf);
}
}
fputs("# Configuration file for Wireshark " VERSION ".\n"

View File

@ -31,6 +31,7 @@
#include <glib.h>
#include <epan/prefs.h>
#include <epan/prefs-int.h>
#include "ui/iface_toolbar.h"
@ -740,6 +741,12 @@ append_extcap_interface_list(GList *list)
void extcap_register_preferences(void)
{
/* Unconditionally register the extcap configuration file, so that
* it is copied if we copy the profile even if we're not going to
* read it because extcaps are disabled.
*/
profile_register_persconffile("extcap");
if (prefs.capture_no_extcap)
return;
@ -862,6 +869,7 @@ extcap_pref_for_argument(const gchar *ifname, struct _extcap_arg *arg)
static gboolean cb_preference(extcap_callback_info_t cb_info)
{
gboolean new_pref = false;
GList *arguments = NULL;
GList **il = (GList **) cb_info.data;
module_t *dev_module = NULL;
@ -894,7 +902,7 @@ static gboolean cb_preference(extcap_callback_info_t cb_info)
{
char *pref_name_for_prefs;
char *pref_title = wmem_strdup(wmem_epan_scope(), arg->display);
new_pref = TRUE;
arg->pref_valptr = extcap_prefs_dynamic_valptr(pref_ifname, &pref_name_for_prefs);
/* Set an initial value if any (the string will be copied at registration) */
if (arg->default_complex)
@ -945,7 +953,7 @@ static gboolean cb_preference(extcap_callback_info_t cb_info)
extcap_free_arg_list(arguments);
}
return TRUE;
return new_pref;
}
GList *
@ -2154,6 +2162,7 @@ extcap_list_interfaces_cb(thread_pool_t *pool, void *data, char *output)
static void
extcap_load_interface_list(void)
{
bool prefs_registered = false;
if (prefs.capture_no_extcap)
return;
@ -2219,12 +2228,17 @@ extcap_load_interface_list(void)
.output = iface_info->output,
.data = NULL,
};
cb_preference(cb_info);
prefs_registered = cb_preference(cb_info);
}
}
extcap_free_extcaps_info_array(infos, count);
g_free(arg_version);
}
if (prefs_registered)
{
prefs_read_module("extcap");
}
}
/*

View File

@ -800,11 +800,6 @@ int main(int argc, char *qt_argv[])
in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
}
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
splash_update(RA_EXTCAP, NULL, NULL);
extcap_register_preferences();
splash_update(RA_PREFERENCES, NULL, NULL);
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling module preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
@ -819,6 +814,16 @@ int main(int argc, char *qt_argv[])
*/
commandline_override_prefs(argc, argv, TRUE);
/* Register the extcap preferences. We do this after seeing if the
* capture_no_extcap preference is set in the configuration file
* or command line. This will re-read the extcap specific preferences.
*/
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" G_GUINT64_FORMAT " us \n", g_get_monotonic_time() - start_time);
#endif
splash_update(RA_EXTCAP, NULL, NULL);
extcap_register_preferences();
/* Some of the preferences affect the capture options. Apply those
* before getting the other command line arguments, which can also
* affect the capture options. The command line arguments should be

View File

@ -851,11 +851,6 @@ int main(int argc, char *qt_argv[])
in_file_type = open_info_name_to_type(ex_opt_get_next("read_format"));
}
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time);
#endif
splash_update(RA_EXTCAP, NULL, NULL);
extcap_register_preferences();
splash_update(RA_PREFERENCES, NULL, NULL);
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling module preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time);
@ -870,6 +865,16 @@ int main(int argc, char *qt_argv[])
*/
commandline_override_prefs(argc, argv, TRUE);
/* Register the extcap preferences. We do this after seeing if the
* capture_no_extcap preference is set in the configuration file
* or command line. This will re-read the extcap specific preferences.
*/
#ifdef DEBUG_STARTUP_TIME
ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_INFO, "Calling extcap_register_preferences, elapsed time %" PRIu64 " us \n", g_get_monotonic_time() - start_time);
#endif
splash_update(RA_EXTCAP, NULL, NULL);
extcap_register_preferences();
/* Some of the preferences affect the capture options. Apply those
* before getting the other command line arguments, which can also
* affect the capture options. The command line arguments should be

View File

@ -470,6 +470,7 @@ void MainApplication::setConfigurationProfile(const gchar *profile_name, bool wr
* they don't get reapplied later, e.g. when reloading Lua plugins)?
*/
commandline_options_free();
extcap_register_preferences();
/* Switching profile requires reloading the macro list. */
reloadDisplayFilterMacros();

View File

@ -22,6 +22,7 @@
#include <ui/simple_dialog.h>
#include <ui/recent.h>
#include <main_window.h>
#include <extcap.h>
#include <ui/qt/utils/qt_ui_utils.h>
@ -253,6 +254,8 @@ void PreferencesDialog::on_buttonBox_accepted()
// XXX - We're also too enthusiastic about setting must_redissect.
prefs_modules_foreach_submodules(NULL, module_prefs_unstash, (gpointer)&redissect_flags);
extcap_register_preferences();
if (redissect_flags & PREF_EFFECT_GUI_LAYOUT) {
// Layout type changed, reset sizes
recent.gui_geometry_main_upper_pane = 0;