diff --git a/NEWS.adoc b/NEWS.adoc index b618b57d3c..c2c93e87d2 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -277,6 +277,10 @@ https://github.com/networkupstools/nut/milestone/12 built-in NUT configuration path on all platforms, but to also consider `NUT_CONFPATH` and other fallback locations, like other code does. [PR #3249] + * Enhance debug-logging of dynamic library loading with information about + any missing method in the library discovered at run-time, if lack of such + prevents us from using that library, and blocks scanning of corresponding + protocol and/or media to discover possibly supported devices. [PR #3310] * Introduced `nut-scanner` support for new `nut-upower` driver. [PR #3293] - `upsd` data server updates: diff --git a/tools/nut-scanner/scan_avahi.c b/tools/nut-scanner/scan_avahi.c index f9afce3ef5..66f9b6f16c 100644 --- a/tools/nut-scanner/scan_avahi.c +++ b/tools/nut-scanner/scan_avahi.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2011-2024 Arnaud Quette (Design and part of implementation) * Copyright (C) 2011 - EATON - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -108,6 +108,8 @@ int nutscan_unload_avahi_library(void) int nutscan_load_avahi_library(const char *libname_path); int nutscan_load_avahi_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -133,99 +135,122 @@ int nutscan_load_avahi_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_avahi_service_browser_get_client) = lt_dlsym(dl_handle, "avahi_service_browser_get_client"); + *(void **) (&nut_avahi_service_browser_get_client) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_loop) = lt_dlsym(dl_handle, "avahi_simple_poll_loop"); + *(void **) (&nut_avahi_simple_poll_loop) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_loop"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_free) = lt_dlsym(dl_handle, "avahi_client_free"); + *(void **) (&nut_avahi_client_free) = lt_dlsym(dl_handle, + symbol = "avahi_client_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_errno) = lt_dlsym(dl_handle, "avahi_client_errno"); + *(void **) (&nut_avahi_client_errno) = lt_dlsym(dl_handle, + symbol = "avahi_client_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_free) = lt_dlsym(dl_handle, "avahi_free"); + *(void **) (&nut_avahi_free) = lt_dlsym(dl_handle, + symbol = "avahi_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_quit) = lt_dlsym(dl_handle, "avahi_simple_poll_quit"); + *(void **) (&nut_avahi_simple_poll_quit) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_quit"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_client_new) = lt_dlsym(dl_handle, "avahi_client_new"); + *(void **) (&nut_avahi_client_new) = lt_dlsym(dl_handle, + symbol = "avahi_client_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_free) = lt_dlsym(dl_handle, "avahi_simple_poll_free"); + *(void **) (&nut_avahi_simple_poll_free) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_new) = lt_dlsym(dl_handle, "avahi_service_resolver_new"); + *(void **) (&nut_avahi_service_resolver_new) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_strerror) = lt_dlsym(dl_handle, "avahi_strerror"); + *(void **) (&nut_avahi_strerror) = lt_dlsym(dl_handle, + symbol = "avahi_strerror"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_get_client) = lt_dlsym(dl_handle, "avahi_service_resolver_get_client"); + *(void **) (&nut_avahi_service_resolver_get_client) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_get_client"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_browser_new) = lt_dlsym(dl_handle, "avahi_service_browser_new"); + *(void **) (&nut_avahi_service_browser_new) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_resolver_free) = lt_dlsym(dl_handle, "avahi_service_resolver_free"); + *(void **) (&nut_avahi_service_resolver_free) = lt_dlsym(dl_handle, + symbol = "avahi_service_resolver_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_new) = lt_dlsym(dl_handle, "avahi_simple_poll_new"); + *(void **) (&nut_avahi_simple_poll_new) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_new"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_string_list_to_string) = lt_dlsym(dl_handle, "avahi_string_list_to_string"); + *(void **) (&nut_avahi_string_list_to_string) = lt_dlsym(dl_handle, + symbol = "avahi_string_list_to_string"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_service_browser_free) = lt_dlsym(dl_handle, "avahi_service_browser_free"); + *(void **) (&nut_avahi_service_browser_free) = lt_dlsym(dl_handle, + symbol = "avahi_service_browser_free"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_address_snprint) = lt_dlsym(dl_handle, "avahi_address_snprint"); + *(void **) (&nut_avahi_address_snprint) = lt_dlsym(dl_handle, + symbol = "avahi_address_snprint"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_avahi_simple_poll_get) = lt_dlsym(dl_handle, "avahi_simple_poll_get"); + *(void **) (&nut_avahi_simple_poll_get) = lt_dlsym(dl_handle, + symbol = "avahi_simple_poll_get"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -234,8 +259,12 @@ int nutscan_load_avahi_library(const char *libname_path) err: upsdebugx(0, - "Cannot load AVAHI library (%s) : %s. AVAHI search disabled.", - libname_path, dl_error); + "Cannot load AVAHI library (%s) : %s%s%s%s. AVAHI search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index 740381cba5..c7afdb4268 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -2,7 +2,7 @@ * Copyright (C) * 2011 - 2012 Arnaud Quette * 2016 - 2021 EATON - Various threads-related improvements - * 2020 - 2024 Jim Klimov + * 2020 - 2026 Jim Klimov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -150,6 +150,8 @@ int nutscan_unload_ipmi_library(void) int nutscan_load_ipmi_library(const char *libname_path); int nutscan_load_ipmi_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -175,104 +177,127 @@ int nutscan_load_ipmi_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID); + *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CLOSE_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY); + *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_DESTROY); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #ifdef HAVE_FREEIPMI_11X_12X - *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #else /* HAVE_FREEIPMI_11X_12X */ - *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_cache_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_cache_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_cache_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_sdr_parse_ctx_destroy"); + *(void **) (&nut_ipmi_sdr_parse_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_sdr_parse_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #endif /* HAVE_FREEIPMI_11X_12X */ - *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE); + *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_CREATE); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS); + *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_SET_FLAGS); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID); + *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_OPEN_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG); + *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_CTX_ERRORMSG); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA); + *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_READ_DATA_AREA); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT); + *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, + symbol = IPMI_FRU_PARSE_NEXT); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, "ipmi_ctx_create"); + *(void **) (&nut_ipmi_ctx_create) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, "ipmi_ctx_find_inband"); + *(void **) (&nut_ipmi_ctx_find_inband) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_find_inband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband"); + *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_open_outofband"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum"); + *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_errnum"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg"); + *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_errormsg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, "ipmi_ctx_close"); + *(void **) (&nut_ipmi_ctx_close) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_ctx_destroy"); + *(void **) (&nut_ipmi_ctx_destroy) = lt_dlsym(dl_handle, + symbol = "ipmi_ctx_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -281,8 +306,12 @@ int nutscan_load_ipmi_library(const char *libname_path) err: upsdebugx(0, - "Cannot load IPMI library (%s) : %s. IPMI search disabled.", - libname_path, dl_error); + "Cannot load IPMI library (%s) : %s%s%s%s. IPMI search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_nut.c b/tools/nut-scanner/scan_nut.c index b9465633ca..acdaa16c47 100644 --- a/tools/nut-scanner/scan_nut.c +++ b/tools/nut-scanner/scan_nut.c @@ -2,7 +2,7 @@ * Copyright (C) 2011 - 2023 Arnaud Quette (Design and part of implementation) * Copyright (C) 2011 - EATON * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,6 +86,8 @@ int nutscan_unload_upsclient_library(void) int nutscan_load_upsclient_library(const char *libname_path); int nutscan_load_upsclient_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -111,39 +113,44 @@ int nutscan_load_upsclient_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); *(void **) (&nut_upscli_splitaddr) = lt_dlsym(dl_handle, - "upscli_splitaddr"); + symbol = "upscli_splitaddr"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_tryconnect) = lt_dlsym(dl_handle, - "upscli_tryconnect"); + symbol = "upscli_tryconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_start) = lt_dlsym(dl_handle, - "upscli_list_start"); + symbol = "upscli_list_start"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_list_next) = lt_dlsym(dl_handle, - "upscli_list_next"); + symbol = "upscli_list_next"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_upscli_disconnect) = lt_dlsym(dl_handle, - "upscli_disconnect"); + symbol = "upscli_disconnect"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -152,8 +159,12 @@ int nutscan_load_upsclient_library(const char *libname_path) err: upsdebugx(0, - "Cannot load NUT library (%s) : %s. NUT search disabled.", - libname_path, dl_error); + "Cannot load NUT library (%s) : %s%s%s%s. NUT search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_snmp.c b/tools/nut-scanner/scan_snmp.c index d70a7917d2..5709cf05fe 100644 --- a/tools/nut-scanner/scan_snmp.c +++ b/tools/nut-scanner/scan_snmp.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2011 - EATON * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -295,6 +295,8 @@ int nutscan_load_snmp_library(const char *libname_path) # endif #else /* not WITH_SNMP_STATIC */ + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -320,98 +322,104 @@ int nutscan_load_snmp_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, "init_snmp"); + *(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, + symbol = "init_snmp"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_init) = lt_dlsym(dl_handle, - "snmp_sess_init"); + symbol = "snmp_sess_init"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_open) = lt_dlsym(dl_handle, - "snmp_sess_open"); + symbol = "snmp_sess_open"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_close) = lt_dlsym(dl_handle, - "snmp_sess_close"); + symbol = "snmp_sess_close"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_session) = lt_dlsym(dl_handle, - "snmp_sess_session"); + symbol = "snmp_sess_session"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_parse_oid) = lt_dlsym(dl_handle, - "snmp_parse_oid"); + symbol = "snmp_parse_oid"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_pdu_create) = lt_dlsym(dl_handle, - "snmp_pdu_create"); + symbol = "snmp_pdu_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_add_null_var) = lt_dlsym(dl_handle, - "snmp_add_null_var"); + symbol = "snmp_add_null_var"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_sess_synch_response) = lt_dlsym(dl_handle, - "snmp_sess_synch_response"); + symbol = "snmp_sess_synch_response"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_oid_compare) = lt_dlsym(dl_handle, - "snmp_oid_compare"); + symbol = "snmp_oid_compare"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle, "snmp_free_pdu"); + *(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle, + symbol = "snmp_free_pdu"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, "generate_Ku"); + *(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, + symbol = "generate_Ku"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_out_toggle_options) = lt_dlsym(dl_handle, - "snmp_out_toggle_options"); + symbol = "snmp_out_toggle_options"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_snmp_api_errstring) = lt_dlsym(dl_handle, - "snmp_api_errstring"); + symbol = "snmp_api_errstring"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, "snmp_errno"); + *(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, + symbol = "snmp_errno"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #if NUT_HAVE_LIBNETSNMP_usmAESPrivProtocol || NUT_HAVE_LIBNETSNMP_usmAES128PrivProtocol *(void **) (&nut_usmAESPrivProtocol) = lt_dlsym(dl_handle, - USMAESPRIVPROTOCOL); + symbol = USMAESPRIVPROTOCOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -419,7 +427,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACMD5AuthProtocol *(void **) (&nut_usmHMACMD5AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACMD5AuthProtocol"); + symbol = "usmHMACMD5AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -427,7 +435,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMACSHA1AuthProtocol *(void **) (&nut_usmHMACSHA1AuthProtocol) = lt_dlsym(dl_handle, - "usmHMACSHA1AuthProtocol"); + symbol = "usmHMACSHA1AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -435,7 +443,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmDESPrivProtocol *(void **) (&nut_usmDESPrivProtocol) = lt_dlsym(dl_handle, - "usmDESPrivProtocol"); + symbol = "usmDESPrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -444,7 +452,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_DRAFT_BLUMENTHAL_AES_04 # if NUT_HAVE_LIBNETSNMP_usmAES192PrivProtocol *(void **) (&nut_usmAES192PrivProtocol) = lt_dlsym(dl_handle, - "usmAES192PrivProtocol"); + symbol = "usmAES192PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -452,7 +460,7 @@ int nutscan_load_snmp_library(const char *libname_path) # if NUT_HAVE_LIBNETSNMP_usmAES256PrivProtocol *(void **) (&nut_usmAES256PrivProtocol) = lt_dlsym(dl_handle, - "usmAES256PrivProtocol"); + symbol = "usmAES256PrivProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -461,7 +469,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC192SHA256AuthProtocol *(void **) (&nut_usmHMAC192SHA256AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC192SHA256AuthProtocol"); + symbol = "usmHMAC192SHA256AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -469,7 +477,7 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC256SHA384AuthProtocol *(void **) (&nut_usmHMAC256SHA384AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC256SHA384AuthProtocol"); + symbol = "usmHMAC256SHA384AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -477,12 +485,15 @@ int nutscan_load_snmp_library(const char *libname_path) #if NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol *(void **) (&nut_usmHMAC384SHA512AuthProtocol) = lt_dlsym(dl_handle, - "usmHMAC384SHA512AuthProtocol"); + symbol = "usmHMAC384SHA512AuthProtocol"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #endif /* NUT_HAVE_LIBNETSNMP_usmHMAC384SHA512AuthProtocol */ + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -494,8 +505,12 @@ int nutscan_load_snmp_library(const char *libname_path) #ifndef WITH_SNMP_STATIC err: upsdebugx(0, - "Cannot load SNMP library (%s) : %s. SNMP search disabled.", - libname_path, dl_error); + "Cannot load SNMP library (%s) : %s%s%s%s. SNMP search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_upower.c b/tools/nut-scanner/scan_upower.c index 3f623ef5a8..d2ab2b8a2d 100644 --- a/tools/nut-scanner/scan_upower.c +++ b/tools/nut-scanner/scan_upower.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2026 Tim Niemueller + * Copyright (C) 2026 - Jim Klimov - support and modernization of codebase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,7 +48,6 @@ static GDBusConnection * (*nut_g_bus_get_sync)(GBusType bus_type, GCancellable * static GDBusProxy * (*nut_g_dbus_proxy_new_sync)(GDBusConnection *connection, GDBusProxyFlags flags, GDBusInterfaceInfo *info, const gchar *name, const gchar *object_path, const gchar *interface_name, GCancellable *cancellable, GError **error); static GVariant * (*nut_g_dbus_proxy_call_sync)(GDBusProxy *proxy, const gchar *method_name, GVariant *parameters, GDBusCallFlags flags, gint timeout_msec, GCancellable *cancellable, GError **error); static GVariant * (*nut_g_dbus_proxy_get_cached_property)(GDBusProxy *proxy, const gchar *property_name); -static void (*nut_g_variant_get)(GVariant *value, const gchar *format_string, ...); static void (*nut_g_variant_unref)(GVariant *value); static void (*nut_g_object_unref)(gpointer object); static void (*nut_g_error_free)(GError *error); @@ -70,6 +70,8 @@ int nutscan_unload_upower_library(void) int nutscan_load_upower_library(const char *libname_path); int nutscan_load_upower_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -94,48 +96,61 @@ int nutscan_load_upower_library(const char *libname_path) dl_error = lt_dlerror(); goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_g_bus_get_sync) = lt_dlsym(dl_handle, "g_bus_get_sync"); + *(void **) (&nut_g_bus_get_sync) = lt_dlsym(dl_handle, + symbol = "g_bus_get_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_new_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_new_sync"); + *(void **) (&nut_g_dbus_proxy_new_sync) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_new_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_call_sync) = lt_dlsym(dl_handle, "g_dbus_proxy_call_sync"); + *(void **) (&nut_g_dbus_proxy_call_sync) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_call_sync"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, "g_dbus_proxy_get_cached_property"); + *(void **) (&nut_g_dbus_proxy_get_cached_property) = lt_dlsym(dl_handle, + symbol = "g_dbus_proxy_get_cached_property"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get) = lt_dlsym(dl_handle, "g_variant_get"); + *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, + symbol = "g_variant_unref"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_unref) = lt_dlsym(dl_handle, "g_variant_unref"); + *(void **) (&nut_g_object_unref) = lt_dlsym(dl_handle, + symbol = "g_object_unref"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_object_unref) = lt_dlsym(dl_handle, "g_object_unref"); + *(void **) (&nut_g_error_free) = lt_dlsym(dl_handle, + symbol = "g_error_free"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_error_free) = lt_dlsym(dl_handle, "g_error_free"); + *(void **) (&nut_g_variant_get_string) = lt_dlsym(dl_handle, + symbol = "g_variant_get_string"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_string) = lt_dlsym(dl_handle, "g_variant_get_string"); + *(void **) (&nut_g_variant_iter_next) = lt_dlsym(dl_handle, + symbol = "g_variant_iter_next"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_iter_next) = lt_dlsym(dl_handle, "g_variant_iter_next"); + *(void **) (&nut_g_variant_iter_init) = lt_dlsym(dl_handle, + symbol = "g_variant_iter_init"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_iter_init) = lt_dlsym(dl_handle, "g_variant_iter_init"); + *(void **) (&nut_g_variant_get_uint32) = lt_dlsym(dl_handle, + symbol = "g_variant_get_uint32"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_uint32) = lt_dlsym(dl_handle, "g_variant_get_uint32"); + *(void **) (&nut_g_variant_get_child_value) = lt_dlsym(dl_handle, + symbol = "g_variant_get_child_value"); if ((dl_error = lt_dlerror()) != NULL) goto err; - *(void **) (&nut_g_variant_get_child_value) = lt_dlsym(dl_handle, "g_variant_get_child_value"); - if ((dl_error = lt_dlerror()) != NULL) goto err; + /* Passed final lt_dlsym() */ + symbol = NULL; if (dl_saved_libname) free(dl_saved_libname); @@ -145,8 +160,12 @@ int nutscan_load_upower_library(const char *libname_path) err: upsdebugx(0, - "Cannot load GIO library (%s) : %s. UPower search disabled.", - libname_path, dl_error); + "Cannot load GIO library (%s) : %s%s%s%s. UPower search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_usb.c b/tools/nut-scanner/scan_usb.c index 1e63191948..29bd9baf52 100644 --- a/tools/nut-scanner/scan_usb.c +++ b/tools/nut-scanner/scan_usb.c @@ -107,6 +107,8 @@ int nutscan_unload_usb_library(void) int nutscan_load_usb_library(const char *libname_path); int nutscan_load_usb_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -132,54 +134,62 @@ int nutscan_load_usb_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, USB_INIT_SYMBOL); + *(void **) (&nut_usb_init) = lt_dlsym(dl_handle, + symbol = USB_INIT_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, USB_OPEN_SYMBOL); + *(void **) (&nut_usb_open) = lt_dlsym(dl_handle, + symbol = USB_OPEN_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, USB_CLOSE_SYMBOL); + *(void **) (&nut_usb_close) = lt_dlsym(dl_handle, + symbol = USB_CLOSE_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, USB_STRERROR_SYMBOL); + *(void **) (&nut_usb_strerror) = lt_dlsym(dl_handle, + symbol = USB_STRERROR_SYMBOL); if ((dl_error = lt_dlerror()) != NULL) { goto err; } #if WITH_LIBUSB_1_0 - *(void **) (&nut_usb_exit) = lt_dlsym(dl_handle, "libusb_exit"); + *(void **) (&nut_usb_exit) = lt_dlsym(dl_handle, + symbol = "libusb_exit"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_usb_get_version) = lt_dlsym(dl_handle, "libusb_get_version"); + *(void **) (&nut_usb_get_version) = lt_dlsym(dl_handle, + symbol = "libusb_get_version"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_device_list) = lt_dlsym(dl_handle, - "libusb_get_device_list"); + symbol = "libusb_get_device_list"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_free_device_list) = lt_dlsym(dl_handle, - "libusb_free_device_list"); + symbol = "libusb_free_device_list"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_bus_number) = lt_dlsym(dl_handle, - "libusb_get_bus_number"); + symbol = "libusb_get_bus_number"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -189,7 +199,7 @@ int nutscan_load_usb_library(const char *libname_path) * not for too long (libusb-1.0.12...1.0.16) and now it is deprecated. */ *(void **) (&nut_usb_get_device_address) = lt_dlsym(dl_handle, - "libusb_get_device_address"); + symbol = "libusb_get_device_address"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -199,7 +209,7 @@ int nutscan_load_usb_library(const char *libname_path) * #if (defined WITH_USB_BUSPORT) && (WITH_USB_BUSPORT) */ *(void **) (&nut_usb_get_port_number) = lt_dlsym(dl_handle, - "libusb_get_port_number"); + symbol = "libusb_get_port_number"); if ((dl_error = lt_dlerror()) != NULL) { upsdebugx(0, "WARNING: %s: " "While loading USB library (%s), failed to find libusb_get_port_number() : %s. " @@ -209,19 +219,19 @@ int nutscan_load_usb_library(const char *libname_path) } *(void **) (&nut_usb_get_device_descriptor) = lt_dlsym(dl_handle, - "libusb_get_device_descriptor"); + symbol = "libusb_get_device_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "libusb_control_transfer"); + symbol = "libusb_control_transfer"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "libusb_get_string_descriptor"); + symbol = "libusb_get_string_descriptor"); if ((dl_error = lt_dlerror()) != NULL) { /* This one may be only defined in a header as an inline method; * then we are adapting it via nut_usb_control_transfer(). @@ -230,39 +240,39 @@ int nutscan_load_usb_library(const char *libname_path) } #else /* for libusb 0.1 */ *(void **) (&nut_usb_find_busses) = lt_dlsym(dl_handle, - "usb_find_busses"); + symbol = "usb_find_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # ifndef WIN32 *(void **) (&nut_usb_busses) = lt_dlsym(dl_handle, - "usb_busses"); + symbol = "usb_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # else *(void **) (&nut_usb_get_busses) = lt_dlsym(dl_handle, - "usb_get_busses"); + symbol = "usb_get_busses"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } # endif /* WIN32 */ *(void **)(&nut_usb_find_devices) = lt_dlsym(dl_handle, - "usb_find_devices"); + symbol = "usb_find_devices"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_control_transfer) = lt_dlsym(dl_handle, - "usb_control_msg"); + symbol = "usb_control_msg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } *(void **) (&nut_usb_get_string_with_langid) = lt_dlsym(dl_handle, - "usb_get_string"); + symbol = "usb_get_string"); if ((dl_error = lt_dlerror()) != NULL) { /* See comment above */ nut_usb_get_string_with_langid = NULL; @@ -273,6 +283,9 @@ int nutscan_load_usb_library(const char *libname_path) nut_usb_get_string_with_langid = nut_usb_get_string_with_langid_control_transfer; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -281,8 +294,12 @@ int nutscan_load_usb_library(const char *libname_path) err: upsdebugx(0, - "Cannot load USB library (%s) : %s. USB search disabled.", - libname_path, dl_error); + "Cannot load USB library (%s) : %s%s%s%s. USB search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) { diff --git a/tools/nut-scanner/scan_xml_http.c b/tools/nut-scanner/scan_xml_http.c index 23b0c96073..e0b0d0b992 100644 --- a/tools/nut-scanner/scan_xml_http.c +++ b/tools/nut-scanner/scan_xml_http.c @@ -2,7 +2,7 @@ * Copyright (C) 2011 - EATON * Copyright (C) 2016 - EATON - IP addressed XML scan * Copyright (C) 2016-2021 - EATON - Various threads-related improvements - * Copyright (C) 2020-2024 - Jim Klimov - support and modernization of codebase + * Copyright (C) 2020-2026 - Jim Klimov - support and modernization of codebase * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -102,6 +102,8 @@ int nutscan_unload_neon_library(void) int nutscan_load_neon_library(const char *libname_path); int nutscan_load_neon_library(const char *libname_path) { + char *symbol = NULL; + if (dl_handle != NULL) { /* if previous init failed */ if (dl_handle == (lt_dlhandle)1) { @@ -127,35 +129,44 @@ int nutscan_load_neon_library(const char *libname_path) goto err; } + upsdebugx(2, "%s: lt_dlopen() succeeded, searching for needed methods", __func__); + /* Clear any existing error */ lt_dlerror(); *(void **) (&nut_ne_xml_push_handler) = lt_dlsym(dl_handle, - "ne_xml_push_handler"); + symbol = "ne_xml_push_handler"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_destroy) = lt_dlsym(dl_handle, "ne_xml_destroy"); + *(void **) (&nut_ne_xml_destroy) = lt_dlsym(dl_handle, + symbol = "ne_xml_destroy"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_create) = lt_dlsym(dl_handle, "ne_xml_create"); + *(void **) (&nut_ne_xml_create) = lt_dlsym(dl_handle, + symbol = "ne_xml_create"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_parse) = lt_dlsym(dl_handle, "ne_xml_parse"); + *(void **) (&nut_ne_xml_parse) = lt_dlsym(dl_handle, + symbol = "ne_xml_parse"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ne_xml_failed) = lt_dlsym(dl_handle, "ne_xml_failed"); + *(void **) (&nut_ne_xml_failed) = lt_dlsym(dl_handle, + symbol = "ne_xml_failed"); if ((dl_error = lt_dlerror()) != NULL) { goto err; } + /* Passed final lt_dlsym() */ + symbol = NULL; + if (dl_saved_libname) free(dl_saved_libname); dl_saved_libname = xstrdup(libname_path); @@ -164,8 +175,12 @@ int nutscan_load_neon_library(const char *libname_path) err: upsdebugx(0, - "Cannot load XML library (%s) : %s. XML search disabled.", - libname_path, dl_error); + "Cannot load XML library (%s) : %s%s%s%s. XML search disabled.", + libname_path, dl_error, + symbol ? " Error happened during search for symbol '" : "", + symbol ? symbol : "", + symbol ? "'" : "" + ); dl_handle = (lt_dlhandle)1; lt_dlexit(); if (dl_saved_libname) {