From 6df63fe455745d8d74010d9ad4f85a30f40b5c08 Mon Sep 17 00:00:00 2001 From: Frederic Bohe Date: Mon, 10 Sep 2012 13:28:35 +0000 Subject: [PATCH] [nut-scanner] Fix a crash when no start IP is provided. Fossil-ID: SVN r3722 --- tools/nut-scanner/nut-scanner.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index db582be..52e0da7 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -371,6 +371,7 @@ display_help: if( allow_snmp && nutscan_avail_snmp ) { if( start_ip == NULL ) { printq(quiet,"No start IP, skipping SNMP\n"); + nutscan_avail_snmp = 0; } else { printq(quiet,"Scanning SNMP bus.\n"); @@ -398,6 +399,7 @@ display_help: if( allow_oldnut && nutscan_avail_nut) { if( start_ip == NULL ) { printq(quiet,"No start IP, skipping NUT bus (old connect method)\n"); + nutscan_avail_nut = 0; } else { printq(quiet,"Scanning NUT bus (old connect method).\n"); -- 1.7.10.2 From dc729c5c3da7efb4632f7d9f7a031108540282d9 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Wed, 19 Sep 2012 19:35:45 +0000 Subject: [PATCH] Support for FreeIPMI 1.1.x and 1.2.x (#2) Prepare for supporting API changes in FreeIPMI 1.1.x and 1.2.x. This 2nd patch, which completes [[SVN:3675]], addresses FRU API changes, and removes code redundancy. This code has been tested with FreeIPMI 0.8.12 and the latest [[FreeIPMI SVN]] trunk r9505 (reported as 1.2.0.beta2 by pkgconfig) [[SVN:3675]] = 2012-07-16T13:18:18Z!arnaud.quette@free.fr Fossil-ID: SVN r3733 --- drivers/nut-libfreeipmi.c | 375 ++++++++++++++--------------------------- m4/nut_check_libfreeipmi.m4 | 1 - tools/nut-scanner/scan_ipmi.c | 103 +++++++---- 3 files changed, 192 insertions(+), 287 deletions(-) diff --git a/drivers/nut-libfreeipmi.c b/drivers/nut-libfreeipmi.c index 1539e75..dd06369 100644 --- a/drivers/nut-libfreeipmi.c +++ b/drivers/nut-libfreeipmi.c @@ -42,10 +42,12 @@ #include #include #include "timehead.h" +#include "common.h" #include #include +#if HAVE_FREEIPMI_MONITORING #include -#include "common.h" +#endif #include "nut-ipmi.h" #include "dstate.h" @@ -57,18 +59,46 @@ /* FreeIPMI contexts and configuration*/ ipmi_ctx_t ipmi_ctx = NULL; -ipmi_fru_parse_ctx_t fru_parse_ctx = NULL; ipmi_monitoring_ctx_t mon_ctx = NULL; struct ipmi_monitoring_ipmi_config ipmi_config; + /* SDR management API has changed with 1.1.X and later */ #ifdef HAVE_FREEIPMI_11X_12X ipmi_sdr_ctx_t sdr_ctx = NULL; + ipmi_fru_ctx_t fru_ctx = NULL; + #define SDR_PARSE_CTX sdr_ctx #else - ipmi_sdr_cache_ctx_t sdr_cache_ctx = NULL; + ipmi_sdr_cache_ctx_t sdr_ctx = NULL; ipmi_sdr_parse_ctx_t sdr_parse_ctx = NULL; -#ifndef IPMI_SDR_MAX_RECORD_LENGTH - #define IPMI_SDR_MAX_RECORD_LENGTH IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH -#endif + #define SDR_PARSE_CTX sdr_parse_ctx + ipmi_fru_parse_ctx_t fru_ctx = NULL; + /* Functions remapping */ + #define ipmi_sdr_ctx_create ipmi_sdr_cache_ctx_create + #define ipmi_sdr_ctx_destroy ipmi_sdr_cache_ctx_destroy + #define ipmi_sdr_ctx_errnum ipmi_sdr_cache_ctx_errnum + #define ipmi_sdr_ctx_errormsg ipmi_sdr_cache_ctx_errormsg + #define ipmi_fru_ctx_create ipmi_fru_parse_ctx_create + #define ipmi_fru_ctx_destroy ipmi_fru_parse_ctx_destroy + #define ipmi_fru_ctx_set_flags ipmi_fru_parse_ctx_set_flags + #define ipmi_fru_ctx_strerror ipmi_fru_parse_ctx_strerror + #define ipmi_fru_ctx_errnum ipmi_fru_parse_ctx_errnum + #define ipmi_fru_open_device_id ipmi_fru_parse_open_device_id + #define ipmi_fru_close_device_id ipmi_fru_parse_close_device_id + #define ipmi_fru_ctx_errormsg ipmi_fru_parse_ctx_errormsg + #define ipmi_fru_read_data_area ipmi_fru_parse_read_data_area + #define ipmi_fru_next ipmi_fru_parse_next + #define ipmi_fru_type_length_field_to_string ipmi_fru_parse_type_length_field_to_string + #define ipmi_fru_multirecord_power_supply_information ipmi_fru_parse_multirecord_power_supply_information + #define ipmi_fru_board_info_area ipmi_fru_parse_board_info_area + #define ipmi_fru_field_t ipmi_fru_parse_field_t + /* Constants */ + #define IPMI_SDR_MAX_RECORD_LENGTH IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH + #define IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST IPMI_SDR_CACHE_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST + #define IPMI_FRU_AREA_SIZE_MAX IPMI_FRU_PARSE_AREA_SIZE_MAX + #define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS + #define IPMI_FRU_AREA_TYPE_BOARD_INFO_AREA IPMI_FRU_PARSE_AREA_TYPE_BOARD_INFO_AREA + #define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION + #define IPMI_FRU_AREA_STRING_MAX IPMI_FRU_PARSE_AREA_STRING_MAX #endif /* HAVE_FREEIPMI_11X_12X */ /* FIXME: freeipmi auto selects a cache based on the hostname you are @@ -78,7 +108,7 @@ struct ipmi_monitoring_ipmi_config ipmi_config; /* Support functions */ static const char* libfreeipmi_getfield (uint8_t language_code, - ipmi_fru_parse_field_t *field); + ipmi_fru_field_t *field); static void libfreeipmi_cleanup(); @@ -97,7 +127,7 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev); int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) { int ret = -1; - uint8_t areabuf[IPMI_FRU_PARSE_AREA_SIZE_MAX+1]; + uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1]; unsigned int area_type = 0; unsigned int area_length = 0; @@ -134,26 +164,26 @@ int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) upsdebugx(1, "FreeIPMI initialized..."); /* Parse FRU information */ - if (!(fru_parse_ctx = ipmi_fru_parse_ctx_create (ipmi_ctx))) + if (!(fru_ctx = ipmi_fru_ctx_create (ipmi_ctx))) { libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_fru_parse_ctx_create()"); + fatal_with_errno(EXIT_FAILURE, "ipmi_fru_ctx_create()"); } /* lots of motherboards calculate checksums incorrectly */ - if (ipmi_fru_parse_ctx_set_flags (fru_parse_ctx, IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) + if (ipmi_fru_ctx_set_flags (fru_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) { libfreeipmi_cleanup(); - fatalx(EXIT_FAILURE, "ipmi_fru_parse_ctx_set_flags: %s\n", - ipmi_fru_parse_ctx_strerror (ipmi_fru_parse_ctx_errnum (fru_parse_ctx))); + fatalx(EXIT_FAILURE, "ipmi_fru_ctx_set_flags: %s\n", + ipmi_fru_ctx_strerror (ipmi_fru_ctx_errnum (fru_ctx))); } /* Now open the requested (local) PSU */ - if (ipmi_fru_parse_open_device_id (fru_parse_ctx, ipmi_id) < 0) + if (ipmi_fru_open_device_id (fru_ctx, ipmi_id) < 0) { libfreeipmi_cleanup(); - fatalx(EXIT_FAILURE, "ipmi_fru_parse_open_device_id: %s\n", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + fatalx(EXIT_FAILURE, "ipmi_fru_open_device_id: %s\n", + ipmi_fru_ctx_errormsg (fru_ctx)); } /* Set IPMI identifier */ @@ -164,19 +194,19 @@ int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) /* clear fields */ area_type = 0; area_length = 0; - memset (areabuf, '\0', IPMI_FRU_PARSE_AREA_SIZE_MAX + 1); + memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1); /* parse FRU buffer */ - if (ipmi_fru_parse_read_data_area (fru_parse_ctx, + if (ipmi_fru_read_data_area (fru_ctx, &area_type, &area_length, areabuf, - IPMI_FRU_PARSE_AREA_SIZE_MAX) < 0) + IPMI_FRU_AREA_SIZE_MAX) < 0) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, - "ipmi_fru_parse_open_device_id: %s\n", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + "ipmi_fru_read_data_area: %s\n", + ipmi_fru_ctx_errormsg (fru_ctx)); } if (area_length) @@ -184,7 +214,7 @@ int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) switch (area_type) { /* get generic board information */ - case IPMI_FRU_PARSE_AREA_TYPE_BOARD_INFO_AREA: + case IPMI_FRU_AREA_TYPE_BOARD_INFO_AREA: if(libfreeipmi_get_board_info (areabuf, area_length, ipmi_dev) < 0) @@ -193,7 +223,7 @@ int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) } break; /* get specific PSU information */ - case IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION: + case IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION: if(libfreeipmi_get_psu_info (areabuf, area_length, ipmi_dev) < 0) { @@ -205,13 +235,13 @@ int nut_ipmi_open(int ipmi_id, IPMIDevice_t *ipmi_dev) break; } } - } while ((ret = ipmi_fru_parse_next (fru_parse_ctx)) == 1); + } while ((ret = ipmi_fru_next (fru_ctx)) == 1); /* check for errors */ if (ret < 0) { libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_fru_parse_next: %s", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + fatal_with_errno(EXIT_FAILURE, "ipmi_fru_next: %s", + ipmi_fru_ctx_errormsg (fru_ctx)); } else { /* Get all related sensors information */ @@ -232,25 +262,25 @@ void nut_ipmi_close(void) } static const char* libfreeipmi_getfield (uint8_t language_code, - ipmi_fru_parse_field_t *field) + ipmi_fru_field_t *field) { - static char strbuf[IPMI_FRU_PARSE_AREA_STRING_MAX + 1]; - unsigned int strbuflen = IPMI_FRU_PARSE_AREA_STRING_MAX; + static char strbuf[IPMI_FRU_AREA_STRING_MAX + 1]; + unsigned int strbuflen = IPMI_FRU_AREA_STRING_MAX; if (!field->type_length_field_length) return NULL; - memset (strbuf, '\0', IPMI_FRU_PARSE_AREA_STRING_MAX + 1); + memset (strbuf, '\0', IPMI_FRU_AREA_STRING_MAX + 1); - if (ipmi_fru_parse_type_length_field_to_string (fru_parse_ctx, + if (ipmi_fru_type_length_field_to_string (fru_ctx, field->type_length_field, field->type_length_field_length, language_code, strbuf, &strbuflen) < 0) { - upsdebugx (2, "ipmi_fru_parse_type_length_field_to_string: %s", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + upsdebugx (2, "ipmi_fru_type_length_field_to_string: %s", + ipmi_fru_ctx_errormsg (fru_ctx)); return NULL; } @@ -279,24 +309,20 @@ static float libfreeipmi_get_voltage (uint8_t voltage_code) static void libfreeipmi_cleanup() { /* cleanup */ - if (fru_parse_ctx) { - ipmi_fru_parse_close_device_id (fru_parse_ctx); - ipmi_fru_parse_ctx_destroy (fru_parse_ctx); + if (fru_ctx) { + ipmi_fru_close_device_id (fru_ctx); + ipmi_fru_ctx_destroy (fru_ctx); } -#ifdef HAVE_FREEIPMI_11X_12X if (sdr_ctx) { ipmi_sdr_ctx_destroy (sdr_ctx); } -#else /* HAVE_FREEIPMI_11X_12X */ - if (sdr_cache_ctx) { - ipmi_sdr_cache_ctx_destroy (sdr_cache_ctx); - } +#ifndef HAVE_FREEIPMI_11X_12X if (sdr_parse_ctx) { ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx); } -#endif /* HAVE_FREEIPMI_11X_12X */ +#endif if (ipmi_ctx) { ipmi_ctx_close (ipmi_ctx); @@ -342,7 +368,7 @@ static int libfreeipmi_get_psu_info (const void *areabuf, upsdebugx(1, "entering libfreeipmi_get_psu_info()"); - if (ipmi_fru_parse_multirecord_power_supply_information (fru_parse_ctx, + if (ipmi_fru_multirecord_power_supply_information (fru_ctx, areabuf, area_length, &overall_capacity, @@ -368,8 +394,8 @@ static int libfreeipmi_get_psu_info (const void *areabuf, &total_combined_wattage, &predictive_fail_tachometer_lower_threshold) < 0) { - fatalx(EXIT_FAILURE, "ipmi_fru_parse_multirecord_power_supply_information: %s", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + fatalx(EXIT_FAILURE, "ipmi_fru_multirecord_power_supply_information: %s", + ipmi_fru_ctx_errormsg (fru_ctx)); } ipmi_dev->overall_capacity = overall_capacity; @@ -383,6 +409,8 @@ static int libfreeipmi_get_psu_info (const void *areabuf, ipmi_dev->voltage = libfreeipmi_get_voltage(voltage_1); + upsdebugx(1, "libfreeipmi_get_psu_info() retrieved successfully"); + return (0); } @@ -392,12 +420,12 @@ static int libfreeipmi_get_board_info (const void *areabuf, { uint8_t language_code; uint32_t mfg_date_time; - ipmi_fru_parse_field_t board_manufacturer; - ipmi_fru_parse_field_t board_product_name; - ipmi_fru_parse_field_t board_serial_number; - ipmi_fru_parse_field_t board_part_number; - ipmi_fru_parse_field_t board_fru_file_id; - ipmi_fru_parse_field_t board_custom_fields[IPMI_FRU_CUSTOM_FIELDS]; + ipmi_fru_field_t board_manufacturer; + ipmi_fru_field_t board_product_name; + ipmi_fru_field_t board_serial_number; + ipmi_fru_field_t board_part_number; + ipmi_fru_field_t board_fru_file_id; + ipmi_fru_field_t board_custom_fields[IPMI_FRU_CUSTOM_FIELDS]; const char *string = NULL; time_t timetmp; struct tm mfg_date_time_tm; @@ -406,15 +434,15 @@ static int libfreeipmi_get_board_info (const void *areabuf, upsdebugx(1, "entering libfreeipmi_get_board_info()"); /* clear fields */ - memset (&board_manufacturer, '\0', sizeof (ipmi_fru_parse_field_t)); - memset (&board_product_name, '\0', sizeof (ipmi_fru_parse_field_t)); - memset (&board_serial_number, '\0', sizeof (ipmi_fru_parse_field_t)); - memset (&board_fru_file_id, '\0', sizeof (ipmi_fru_parse_field_t)); + memset (&board_manufacturer, '\0', sizeof (ipmi_fru_field_t)); + memset (&board_product_name, '\0', sizeof (ipmi_fru_field_t)); + memset (&board_serial_number, '\0', sizeof (ipmi_fru_field_t)); + memset (&board_fru_file_id, '\0', sizeof (ipmi_fru_field_t)); memset (&board_custom_fields[0], '\0', - sizeof (ipmi_fru_parse_field_t) * IPMI_FRU_CUSTOM_FIELDS); + sizeof (ipmi_fru_field_t) * IPMI_FRU_CUSTOM_FIELDS); /* parse FRU buffer */ - if (ipmi_fru_parse_board_info_area (fru_parse_ctx, + if (ipmi_fru_board_info_area (fru_ctx, areabuf, area_length, &language_code, @@ -428,8 +456,8 @@ static int libfreeipmi_get_board_info (const void *areabuf, IPMI_FRU_CUSTOM_FIELDS) < 0) { libfreeipmi_cleanup(); - fatalx(EXIT_FAILURE, "ipmi_fru_parse_board_info_area: %s", - ipmi_fru_parse_ctx_errormsg (fru_parse_ctx)); + fatalx(EXIT_FAILURE, "ipmi_fru_board_info_area: %s", + ipmi_fru_ctx_errormsg (fru_ctx)); } @@ -498,113 +526,64 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) ipmi_dev->sensors_count = 0; memset(ipmi_dev->sensors_id_list, 0, sizeof(ipmi_dev->sensors_id_list)); -#ifdef HAVE_FREEIPMI_11X_12X if (!(sdr_ctx = ipmi_sdr_ctx_create ())) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_ctx_create()"); } - if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0) - { - if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) - { - libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s", - ipmi_sdr_ctx_errormsg (sdr_ctx)); - } - } -#else /* HAVE_FREEIPMI_11X_12X */ - if (!(sdr_cache_ctx = ipmi_sdr_cache_ctx_create ())) - { - libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_ctx_create()"); - } - +#ifndef HAVE_FREEIPMI_11X_12X if (!(sdr_parse_ctx = ipmi_sdr_parse_ctx_create ())) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_parse_ctx_create()"); } +#endif - if (ipmi_sdr_cache_open (sdr_cache_ctx, ipmi_ctx, CACHE_LOCATION) < 0) + if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0) { - if (ipmi_sdr_cache_ctx_errnum (sdr_cache_ctx) != IPMI_SDR_CACHE_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) + if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); + ipmi_sdr_ctx_errormsg (sdr_ctx)); } } -#endif /* HAVE_FREEIPMI_11X_12X */ -#ifdef HAVE_FREEIPMI_11X_12X if (ipmi_sdr_ctx_errnum (sdr_ctx) == IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) { if (ipmi_sdr_cache_create (sdr_ctx, ipmi_ctx, CACHE_LOCATION, IPMI_SDR_CACHE_CREATE_FLAGS_DEFAULT, +#ifndef HAVE_FREEIPMI_11X_12X + IPMI_SDR_CACHE_VALIDATION_FLAGS_DEFAULT, +#endif NULL, NULL) < 0) { libfreeipmi_cleanup(); fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_create: %s", ipmi_sdr_ctx_errormsg (sdr_ctx)); } - if (ipmi_sdr_cache_open (sdr_ctx, - ipmi_ctx, CACHE_LOCATION) < 0) + if (ipmi_sdr_cache_open (sdr_ctx, ipmi_ctx, CACHE_LOCATION) < 0) { if (ipmi_sdr_ctx_errnum (sdr_ctx) != IPMI_SDR_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) { - libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s", - ipmi_sdr_ctx_errormsg (sdr_ctx)); - } - } - } -#else /* HAVE_FREEIPMI_11X_12X */ - if (ipmi_sdr_cache_ctx_errnum (sdr_cache_ctx) == IPMI_SDR_CACHE_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) - { - if (ipmi_sdr_cache_create (sdr_cache_ctx, - ipmi_ctx, CACHE_LOCATION, - IPMI_SDR_CACHE_CREATE_FLAGS_DEFAULT, - IPMI_SDR_CACHE_VALIDATION_FLAGS_DEFAULT, - NULL, NULL) < 0) - { - libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_create: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); - } - if (ipmi_sdr_cache_open (sdr_cache_ctx, - ipmi_ctx, CACHE_LOCATION) < 0) - { - if (ipmi_sdr_cache_ctx_errnum (sdr_cache_ctx) != IPMI_SDR_CACHE_ERR_CACHE_READ_CACHE_DOES_NOT_EXIST) - { - libfreeipmi_cleanup(); - fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); + libfreeipmi_cleanup(); + fatal_with_errno(EXIT_FAILURE, "ipmi_sdr_cache_open: %s", + ipmi_sdr_ctx_errormsg (sdr_ctx)); } } } -#endif /* HAVE_FREEIPMI_11X_12X */ -#ifdef HAVE_FREEIPMI_11X_12X - if (ipmi_sdr_cache_record_count (sdr_ctx, &record_count) < 0) { + if (ipmi_sdr_cache_record_count (sdr_ctx, &record_count) < 0) { fprintf (stderr, - "ipmi_sdr_cache_record_count: %s", + "ipmi_sdr_cache_record_count: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else - if (ipmi_sdr_cache_record_count (sdr_cache_ctx, &record_count) < 0) - { - fprintf (stderr, - "ipmi_sdr_cache_record_count: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ -#ifdef HAVE_FREEIPMI_11X_12X + upsdebugx(3, "Found %i records in SDR cache", record_count); + for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_ctx)) { memset (sdr_record, '\0', IPMI_SDR_MAX_RECORD_LENGTH); @@ -613,50 +592,29 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) sdr_record, IPMI_SDR_MAX_RECORD_LENGTH)) < 0) { - fprintf (stderr, "ipmi_sdr_cache_record_read: %s", + fprintf (stderr, "ipmi_sdr_cache_record_read: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } - if (ipmi_sdr_parse_record_id_and_type (sdr_ctx, + if (ipmi_sdr_parse_record_id_and_type (SDR_PARSE_CTX, sdr_record, sdr_record_len, NULL, &record_type) < 0) { - fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s", + fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else - for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_cache_ctx)) - { - memset (sdr_record, '\0', IPMI_SDR_MAX_RECORD_LENGTH); - if ((sdr_record_len = ipmi_sdr_cache_record_read (sdr_cache_ctx, - sdr_record, - IPMI_SDR_MAX_RECORD_LENGTH)) < 0) - { - fprintf (stderr, "ipmi_sdr_cache_record_read: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); - goto cleanup; - } - if (ipmi_sdr_parse_record_id_and_type (sdr_parse_ctx, - sdr_record, - sdr_record_len, - NULL, - &record_type) < 0) - { - fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s", - ipmi_sdr_parse_ctx_errormsg (sdr_parse_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ + upsdebugx (5, "Checking record %i (/%i)", i, record_count); - if (record_type != IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD) + if (record_type != IPMI_SDR_FORMAT_FRU_DEVICE_LOCATOR_RECORD) { + upsdebugx(1, "=======> not device locator (%i)!!", record_type); continue; + } -#ifdef HAVE_FREEIPMI_11X_12X - if (ipmi_sdr_parse_fru_device_locator_parameters (sdr_ctx, + if (ipmi_sdr_parse_fru_device_locator_parameters (SDR_PARSE_CTX, sdr_record, sdr_record_len, NULL, @@ -666,86 +624,49 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) &logical_physical_fru_device, NULL) < 0) { - fprintf (stderr, "ipmi_sdr_parse_fru_device_locator_parameters: %s", + fprintf (stderr, "ipmi_sdr_parse_fru_device_locator_parameters: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else /* HAVE_FREEIPMI_11X_12X */ - if (ipmi_sdr_parse_fru_device_locator_parameters (sdr_parse_ctx, - sdr_record, - sdr_record_len, - NULL, - &logical_fru_device_device_slave_address, - NULL, - NULL, - &logical_physical_fru_device, - NULL) < 0) - { - fprintf (stderr, "ipmi_sdr_parse_fru_device_locator_parameters: %s", - ipmi_sdr_parse_ctx_errormsg (sdr_parse_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ + + upsdebugx(2, "Checking device %i/%i", logical_physical_fru_device, + logical_fru_device_device_slave_address); if (logical_physical_fru_device && logical_fru_device_device_slave_address == ipmi_dev->ipmi_id) { found_device_id++; -#ifdef HAVE_FREEIPMI_11X_12X - if (ipmi_sdr_parse_fru_entity_id_and_instance (sdr_ctx, + if (ipmi_sdr_parse_fru_entity_id_and_instance (SDR_PARSE_CTX, sdr_record, sdr_record_len, &entity_id, &entity_instance) < 0) { fprintf (stderr, - "ipmi_sdr_parse_fru_entity_id_and_instance: %s", + "ipmi_sdr_parse_fru_entity_id_and_instance: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else /* HAVE_FREEIPMI_11X_12X */ - if (ipmi_sdr_parse_fru_entity_id_and_instance (sdr_parse_ctx, - sdr_record, - sdr_record_len, - &entity_id, - &entity_instance) < 0) - { - fprintf (stderr, - "ipmi_sdr_parse_fru_entity_id_and_instance: %s", - ipmi_sdr_parse_ctx_errormsg (sdr_parse_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ break; } } if (!found_device_id) { - fprintf (stderr, "Couldn't find device id %d", ipmi_dev->ipmi_id); + fprintf (stderr, "Couldn't find device id %d\n", ipmi_dev->ipmi_id); goto cleanup; } else upsdebugx(1, "Found device id %d", ipmi_dev->ipmi_id); -#ifdef HAVE_FREEIPMI_11X_12X if (ipmi_sdr_cache_first (sdr_ctx) < 0) { - fprintf (stderr, "ipmi_sdr_cache_first: %s", + fprintf (stderr, "ipmi_sdr_cache_first: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else /* HAVE_FREEIPMI_11X_12X */ - if (ipmi_sdr_cache_first (sdr_cache_ctx) < 0) - { - fprintf (stderr, "ipmi_sdr_cache_first: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ -#ifdef HAVE_FREEIPMI_11X_12X for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_ctx)) { /* uint8_t sdr_record[IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH]; @@ -757,49 +678,21 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) sdr_record, IPMI_SDR_MAX_RECORD_LENGTH)) < 0) { - fprintf (stderr, "ipmi_sdr_cache_record_read: %s", + fprintf (stderr, "ipmi_sdr_cache_record_read: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } - if (ipmi_sdr_parse_record_id_and_type (sdr_ctx, + if (ipmi_sdr_parse_record_id_and_type (SDR_PARSE_CTX, sdr_record, sdr_record_len, &record_id, &record_type) < 0) { - fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s", + fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else /* HAVE_FREEIPMI_11X_12X */ - for (i = 0; i < record_count; i++, ipmi_sdr_cache_next (sdr_cache_ctx)) - { - /* uint8_t sdr_record[IPMI_SDR_CACHE_MAX_SDR_RECORD_LENGTH]; - uint8_t record_type, tmp_entity_id, tmp_entity_instance; - int sdr_record_len; */ - - memset (sdr_record, '\0', IPMI_SDR_MAX_RECORD_LENGTH); - if ((sdr_record_len = ipmi_sdr_cache_record_read (sdr_cache_ctx, - sdr_record, - IPMI_SDR_MAX_RECORD_LENGTH)) < 0) - { - fprintf (stderr, "ipmi_sdr_cache_record_read: %s", - ipmi_sdr_cache_ctx_errormsg (sdr_cache_ctx)); - goto cleanup; - } - - if (ipmi_sdr_parse_record_id_and_type (sdr_parse_ctx, - sdr_record, - sdr_record_len, - &record_id, - &record_type) < 0) - { - fprintf (stderr, "ipmi_sdr_parse_record_id_and_type: %s", - ipmi_sdr_parse_ctx_errormsg (sdr_parse_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ upsdebugx (5, "Checking record %i (/%i)", record_id, record_count); @@ -809,31 +702,17 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) continue; } -#ifdef HAVE_FREEIPMI_11X_12X - if (ipmi_sdr_parse_entity_id_instance_type (sdr_ctx, + if (ipmi_sdr_parse_entity_id_instance_type (SDR_PARSE_CTX, sdr_record, sdr_record_len, &tmp_entity_id, &tmp_entity_instance, NULL) < 0) { - fprintf (stderr, "ipmi_sdr_parse_entity_instance_type: %s", + fprintf (stderr, "ipmi_sdr_parse_entity_instance_type: %s\n", ipmi_sdr_ctx_errormsg (sdr_ctx)); goto cleanup; } -#else /* HAVE_FREEIPMI_11X_12X */ - if (ipmi_sdr_parse_entity_id_instance_type (sdr_parse_ctx, - sdr_record, - sdr_record_len, - &tmp_entity_id, - &tmp_entity_instance, - NULL) < 0) - { - fprintf (stderr, "ipmi_sdr_parse_entity_instance_type: %s", - ipmi_sdr_parse_ctx_errormsg (sdr_parse_ctx)); - goto cleanup; - } -#endif /* HAVE_FREEIPMI_11X_12X */ if (tmp_entity_id == entity_id && tmp_entity_instance == entity_instance) @@ -850,15 +729,11 @@ static int libfreeipmi_get_sensors_info (IPMIDevice_t *ipmi_dev) cleanup: /* Cleanup */ -#ifdef HAVE_FREEIPMI_11X_12X if (sdr_ctx) { ipmi_sdr_ctx_destroy (sdr_ctx); } -#else /* HAVE_FREEIPMI_11X_12X */ - if (sdr_cache_ctx) { - ipmi_sdr_cache_ctx_destroy (sdr_cache_ctx); - } +#ifndef HAVE_FREEIPMI_11X_12X if (sdr_parse_ctx) { ipmi_sdr_parse_ctx_destroy (sdr_parse_ctx); } diff --git a/m4/nut_check_libfreeipmi.m4 b/m4/nut_check_libfreeipmi.m4 index 72e7819..5b2eae9 100644 --- a/m4/nut_check_libfreeipmi.m4 +++ b/m4/nut_check_libfreeipmi.m4 @@ -66,7 +66,6 @@ if test -z "${nut_have_libfreeipmi_seen}"; then dnl when version cannot be tested (prior to 1.0.5, with no pkg-config) dnl we have to check for some specific functions AC_SEARCH_LIBS([ipmi_ctx_find_inband], [freeipmi], [], [nut_have_freeipmi=no]) - AC_SEARCH_LIBS([ipmi_fru_parse_ctx_create], [freeipmi], [], [nut_have_freeipmi=no]) AC_SEARCH_LIBS([ipmi_monitoring_init], [ipmimonitoring], [nut_have_freeipmi_monitoring=yes], [nut_have_freeipmi_monitoring=no]) AC_SEARCH_LIBS([ipmi_monitoring_sensor_read_record_id], [ipmimonitoring], [], [nut_have_freeipmi_monitoring=no]) diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index d650efa..c1ec78a 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -34,24 +34,51 @@ static char * libname = "libfreeipmi"; static lt_dlhandle dl_handle = NULL; static const char *dl_error = NULL; -static int (*nut_ipmi_fru_parse_close_device_id) (ipmi_fru_parse_ctx_t ctx); -static void (*nut_ipmi_fru_parse_ctx_destroy) (ipmi_fru_parse_ctx_t ctx); #ifdef HAVE_FREEIPMI_11X_12X -static void (*nut_ipmi_sdr_ctx_destroy) (ipmi_sdr_ctx_t ctx); + /* Functions symbols remapping */ + #define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_close_device_id" + #define IPMI_FRU_CTX_DESTROY "ipmi_fru_ctx_destroy" + #define IPMI_FRU_CTX_CREATE "ipmi_fru_ctx_create" + #define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_ctx_set_flags" + #define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_open_device_id" + #define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_ctx_errormsg" + #define IPMI_FRU_READ_DATA_AREA "ipmi_fru_read_data_area" + #define IPMI_FRU_PARSE_NEXT "ipmi_fru_next" + typedef ipmi_fru_ctx_t ipmi_fru_parse_ctx_t; + typedef ipmi_sdr_ctx_t ipmi_sdr_cache_ctx_t; + /* Functions remapping */ + static void (*nut_ipmi_sdr_ctx_destroy) (ipmi_sdr_ctx_t ctx); #else /* HAVE_FREEIPMI_11X_12X */ -static void (*nut_ipmi_sdr_cache_ctx_destroy) (ipmi_sdr_cache_ctx_t ctx); -static void (*nut_ipmi_sdr_parse_ctx_destroy) (ipmi_sdr_parse_ctx_t ctx); + #define IPMI_FRU_AREA_SIZE_MAX IPMI_FRU_PARSE_AREA_SIZE_MAX + #define IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS + #define IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION + /* Functions symbols remapping */ + #define IPMI_FRU_CLOSE_DEVICE_ID "ipmi_fru_parse_close_device_id" + #define IPMI_FRU_CTX_DESTROY "ipmi_fru_parse_ctx_destroy" + #define IPMI_FRU_CTX_CREATE "ipmi_fru_parse_ctx_create" + #define IPMI_FRU_CTX_SET_FLAGS "ipmi_fru_parse_ctx_set_flags" + #define IPMI_FRU_OPEN_DEVICE_ID "ipmi_fru_parse_open_device_id" + #define IPMI_FRU_CTX_ERRORMSG "ipmi_fru_parse_ctx_errormsg" + #define IPMI_FRU_READ_DATA_AREA "ipmi_fru_parse_read_data_area" + #define IPMI_FRU_PARSE_NEXT "ipmi_fru_parse_next" + /* Functions remapping */ + static void (*nut_ipmi_sdr_cache_ctx_destroy) (ipmi_sdr_cache_ctx_t ctx); + static void (*nut_ipmi_sdr_parse_ctx_destroy) (ipmi_sdr_parse_ctx_t ctx); #endif /* HAVE_FREEIPMI_11X_12X */ -static ipmi_fru_parse_ctx_t (*nut_ipmi_fru_parse_ctx_create) (ipmi_ctx_t ipmi_ctx); -static int (*nut_ipmi_fru_parse_ctx_set_flags) (ipmi_fru_parse_ctx_t ctx, unsigned int flags); -static int (*nut_ipmi_fru_parse_open_device_id) (ipmi_fru_parse_ctx_t ctx, uint8_t fru_device_id); -static char * (*nut_ipmi_fru_parse_ctx_errormsg) (ipmi_fru_parse_ctx_t ctx); -static int (*nut_ipmi_fru_parse_read_data_area) (ipmi_fru_parse_ctx_t ctx, + + +static int (*nut_ipmi_fru_close_device_id) (ipmi_fru_parse_ctx_t ctx); +static void (*nut_ipmi_fru_ctx_destroy) (ipmi_fru_parse_ctx_t ctx); +static ipmi_fru_parse_ctx_t (*nut_ipmi_fru_ctx_create) (ipmi_ctx_t ipmi_ctx); +static int (*nut_ipmi_fru_ctx_set_flags) (ipmi_fru_parse_ctx_t ctx, unsigned int flags); +static int (*nut_ipmi_fru_open_device_id) (ipmi_fru_parse_ctx_t ctx, uint8_t fru_device_id); +static char * (*nut_ipmi_fru_ctx_errormsg) (ipmi_fru_parse_ctx_t ctx); +static int (*nut_ipmi_fru_read_data_area) (ipmi_fru_parse_ctx_t ctx, unsigned int *area_type, unsigned int *area_length, void *areabuf, unsigned int areabuflen); -static int (*nut_ipmi_fru_parse_next) (ipmi_fru_parse_ctx_t ctx); +static int (*nut_ipmi_fru_next) (ipmi_fru_parse_ctx_t ctx); static ipmi_ctx_t (*nut_ipmi_ctx_create) (void); static int (*nut_ipmi_ctx_find_inband) (ipmi_ctx_t ctx, ipmi_driver_type_t *driver_type, @@ -92,12 +119,12 @@ int nutscan_load_ipmi_library() /* Clear any existing error */ lt_dlerror(); - *(void **) (&nut_ipmi_fru_parse_close_device_id) = lt_dlsym(dl_handle, "ipmi_fru_parse_close_device_id"); + *(void **) (&nut_ipmi_fru_close_device_id) = lt_dlsym(dl_handle, IPMI_FRU_CLOSE_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_ctx_destroy) = lt_dlsym(dl_handle, "ipmi_fru_parse_ctx_destroy"); + *(void **) (&nut_ipmi_fru_ctx_destroy) = lt_dlsym(dl_handle, IPMI_FRU_CTX_DESTROY); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -122,32 +149,32 @@ int nutscan_load_ipmi_library() } #endif /* HAVE_FREEIPMI_11X_12X */ - *(void **) (&nut_ipmi_fru_parse_ctx_create) = lt_dlsym(dl_handle, "ipmi_fru_parse_ctx_create"); + *(void **) (&nut_ipmi_fru_ctx_create) = lt_dlsym(dl_handle, IPMI_FRU_CTX_CREATE); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_ctx_set_flags) = lt_dlsym(dl_handle, "ipmi_fru_parse_ctx_set_flags"); + *(void **) (&nut_ipmi_fru_ctx_set_flags) = lt_dlsym(dl_handle, IPMI_FRU_CTX_SET_FLAGS); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_open_device_id) = lt_dlsym(dl_handle, "ipmi_fru_parse_open_device_id"); + *(void **) (&nut_ipmi_fru_open_device_id) = lt_dlsym(dl_handle, IPMI_FRU_OPEN_DEVICE_ID); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_fru_parse_ctx_errormsg"); + *(void **) (&nut_ipmi_fru_ctx_errormsg) = lt_dlsym(dl_handle, IPMI_FRU_CTX_ERRORMSG); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_read_data_area) = lt_dlsym(dl_handle, "ipmi_fru_parse_read_data_area"); + *(void **) (&nut_ipmi_fru_read_data_area) = lt_dlsym(dl_handle, IPMI_FRU_READ_DATA_AREA); if ((dl_error = lt_dlerror()) != NULL) { goto err; } - *(void **) (&nut_ipmi_fru_parse_next) = lt_dlsym(dl_handle, "ipmi_fru_parse_next"); + *(void **) (&nut_ipmi_fru_next) = lt_dlsym(dl_handle, IPMI_FRU_PARSE_NEXT); if ((dl_error = lt_dlerror()) != NULL) { goto err; } @@ -179,7 +206,7 @@ int nutscan_load_ipmi_library() return 1; err: - fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname, dl_error); + fprintf(stderr, "Cannot load IPMI library (%s) : %s. IPMI search disabled.\n", libname, dl_error); dl_handle = (void *)1; lt_dlexit(); return 0; @@ -197,8 +224,8 @@ static void nut_freeipmi_cleanup(ipmi_fru_parse_ctx_t fru_parse_ctx, #endif /* HAVE_FREEIPMI_11X_12X */ { if (fru_parse_ctx) { - (*nut_ipmi_fru_parse_close_device_id) (fru_parse_ctx); - (*nut_ipmi_fru_parse_ctx_destroy) (fru_parse_ctx); + (*nut_ipmi_fru_close_device_id) (fru_parse_ctx); + (*nut_ipmi_fru_ctx_destroy) (fru_parse_ctx); } #ifdef HAVE_FREEIPMI_11X_12X @@ -226,7 +253,7 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) int ret = -1; unsigned int area_type = 0; unsigned int area_length = 0; - uint8_t areabuf[IPMI_FRU_PARSE_AREA_SIZE_MAX+1]; + uint8_t areabuf[IPMI_FRU_AREA_SIZE_MAX+1]; ipmi_fru_parse_ctx_t fru_parse_ctx = NULL; #ifdef HAVE_FREEIPMI_11X_12X ipmi_sdr_ctx_t sdr_ctx = NULL; @@ -236,14 +263,14 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) #endif /* HAVE_FREEIPMI_11X_12X */ /* Parse FRU information */ - if (!(fru_parse_ctx = (*nut_ipmi_fru_parse_ctx_create) (ipmi_ctx))) + if (!(fru_parse_ctx = (*nut_ipmi_fru_ctx_create) (ipmi_ctx))) { fprintf(stderr, "ipmi_fru_parse_ctx_create()\n"); return 0; } - +fprintf(stdout, "There.1\n"); /* lots of motherboards calculate checksums incorrectly */ - if ((*nut_ipmi_fru_parse_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_PARSE_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) + if ((*nut_ipmi_fru_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); @@ -252,8 +279,8 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } - - if ((*nut_ipmi_fru_parse_open_device_id) (fru_parse_ctx, ipmi_id) < 0) +fprintf(stdout, "There.2\n"); + if ((*nut_ipmi_fru_open_device_id) (fru_parse_ctx, ipmi_id) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); @@ -265,17 +292,18 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) do { +fprintf(stdout, "There.3\n"); /* clear fields */ area_type = 0; area_length = 0; - memset (areabuf, '\0', IPMI_FRU_PARSE_AREA_SIZE_MAX + 1); + memset (areabuf, '\0', IPMI_FRU_AREA_SIZE_MAX + 1); /* parse FRU buffer */ - if ((*nut_ipmi_fru_parse_read_data_area) (fru_parse_ctx, + if ((*nut_ipmi_fru_read_data_area) (fru_parse_ctx, &area_type, &area_length, areabuf, - IPMI_FRU_PARSE_AREA_SIZE_MAX) < 0) + IPMI_FRU_AREA_SIZE_MAX) < 0) { #ifdef HAVE_FREEIPMI_11X_12X nut_freeipmi_cleanup(fru_parse_ctx, sdr_ctx); @@ -287,7 +315,7 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) if (area_length) { - if (area_type == IPMI_FRU_PARSE_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION) + if (area_type == IPMI_FRU_AREA_TYPE_MULTIRECORD_POWER_SUPPLY_INFORMATION) { /* Found a POWER_SUPPLY record */ #ifdef HAVE_FREEIPMI_11X_12X @@ -298,7 +326,7 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) return 1; } } - } while ((ret = (*nut_ipmi_fru_parse_next) (fru_parse_ctx)) == 1); + } while ((ret = (*nut_ipmi_fru_next) (fru_parse_ctx)) == 1); /* No need for further errors checking */ #ifdef HAVE_FREEIPMI_11X_12X @@ -322,7 +350,7 @@ nutscan_device_t * nutscan_scan_ipmi() if( !nutscan_avail_ipmi ) { return NULL; } - +fprintf(stdout, "There1\n"); /* Initialize the FreeIPMI library. */ if (!(ipmi_ctx = (*nut_ipmi_ctx_create) ())) { @@ -331,6 +359,7 @@ nutscan_device_t * nutscan_scan_ipmi() return NULL; } +fprintf(stdout, "There2\n"); if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx, NULL, 0, /* don't disable auto-probe */ @@ -338,7 +367,7 @@ nutscan_device_t * nutscan_scan_ipmi() 0, NULL, 0, /* workaround flags, none by default */ - 0 /* flags */ + IPMI_FLAGS_NONBLOCKING /* flags */ )) < 0) { fprintf(stderr, "ipmi_ctx_find_inband: %s\n", @@ -350,12 +379,14 @@ nutscan_device_t * nutscan_scan_ipmi() /* No local IPMI device detected */ return NULL; } +fprintf(stdout, "There3 (ret = %i)\n", ret); /* Loop through all possible components */ for (ipmi_id = 0 ; ipmi_id <= IPMI_FRU_DEVICE_ID_MAX ; ipmi_id++) { - +fprintf(stdout, "There4\n"); if (is_ipmi_device_supported(ipmi_ctx, ipmi_id)) { +fprintf(stdout, "There4.%i\n", ipmi_id); if ( (nut_dev = nutscan_new_device()) == NULL ) { fprintf(stderr,"Memory allocation error\n"); nutscan_free_device(current_nut_dev); -- 1.7.10.2 From 64add831fe9cd779f125f52782c4c58cbd62d64b Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Thu, 4 Oct 2012 22:50:52 +0000 Subject: [PATCH] Support power supplies scan over the network nut-scanner can now scan for power supplies with IPMI over LAN. This is currently limited to IPMI 1.5 only Fossil-ID: SVN r3739 --- docs/man/nut-scanner.txt | 108 +++++++++-------- drivers/nut-ipmipsu.c | 15 ++- tools/nut-scanner/nut-scan.h | 39 ++++++- tools/nut-scanner/nut-scanner.c | 74 +++++++++++- tools/nut-scanner/scan_ipmi.c | 243 ++++++++++++++++++++++++++++++++++----- 5 files changed, 388 insertions(+), 91 deletions(-) diff --git a/docs/man/nut-scanner.txt b/docs/man/nut-scanner.txt index 6948449..efe0e58 100644 --- a/docs/man/nut-scanner.txt +++ b/docs/man/nut-scanner.txt @@ -36,118 +36,128 @@ DISPLAY OPTIONS --------------- *-N* | *--disp_nut_conf*:: - - Display result in the 'ups.conf' format. +Display result in the 'ups.conf' format. *-P* | *--disp_parsable*:: - - Display result in a parsable format. +Display result in a parsable format. BUS OPTIONS ----------- *-C* | *--complete_scan*:: - - Scan all available communication buses (default behavior) +Scan all available communication buses (default behavior) *-U* | *--usb_scan*:: - - List all NUT-compatible USB devices currently plugged in. +List all NUT-compatible USB devices currently plugged in. *-S* | *--snmp_scan*:: - - Scan SNMP devices. Requires at least a 'start IP', and optionally, an 'end IP'. See specific SNMP OPTIONS for community and security settings. +Scan SNMP devices. Requires at least a 'start IP', and optionally, an 'end IP'. See specific SNMP OPTIONS for community and security settings. *-M* | *--xml_scan*:: - - Scan XML/HTTP devices. Broadcast a network message on the current network interfaces to retrieve XML/HTTP capable devices. No IP required. +Scan XML/HTTP devices. Broadcast a network message on the current network interfaces to retrieve XML/HTTP capable devices. No IP required. *-O* | *--oldnut_scan*:: - - Scan NUT devices (i.e. upsd daemon) on IP ranging from 'start IP' to 'end IP'. +Scan NUT devices (i.e. upsd daemon) on IP ranging from 'start IP' to 'end IP'. *-A* | *--avahi_scan*:: - - Scan NUT servers using Avahi request on the current network interfaces. No IP required. +Scan NUT servers using Avahi request on the current network interfaces. No IP required. *-I* | *--ipmi_scan*:: - - Scan NUT compatible devices available via IPMI on the current host. +Scan NUT compatible power supplies available via IPMI on the current host, or over the network. NETWORK OPTIONS --------------- *-t* | *--timeout* 'timeout':: - - Set the network timeout in seconds. Default timeout is 5 seconds. +Set the network timeout in seconds. Default timeout is 5 seconds. *-s* | *--start_ip* 'start IP':: - - Set the first IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). +Set the first IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). *-e* | *--end_ip* 'end IP':: - - Set the last IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). If this parameter is omitted, only the 'start IP' is scanned. If 'end IP' is less than 'start IP', both parameters are internally permuted. +Set the last IP (IPv4 or IPv6) when a range of IP is required (SNMP, old_nut). If this parameter is omitted, only the 'start IP' is scanned. If 'end IP' is less than 'start IP', both parameters are internally permuted. *-m* | *--mask_cidr* 'IP address/mask':: - - Set a range of IP using CIDR notation. +Set a range of IP using CIDR notation. NUT DEVICE OPTION ----------------- *-p* | *--port* 'port number':: - - Set the port number of scanned NUT devices (default 3493). +Set the port number of scanned NUT devices (default 3493). SNMP V1 OPTION -------------- *-c* | *--community* 'community':: - - Set SNMP v1 community name (default = public). +Set SNMP v1 community name (default = public). SNMP V3 OPTIONS --------------- *-l* | *--secLevel* 'security level':: - - Set the 'security level' used for SNMPv3 messages. Allowed values are: noAuthNoPriv, authNoPriv and authPriv. +Set the 'security level' used for SNMPv3 messages. Allowed values are: noAuthNoPriv, authNoPriv and authPriv. *-u* | *--secName* 'security name':: - - Set the 'security name' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level'. +Set the 'security name' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level'. *-w* | *--authProtocol* 'authentication protocol':: - - Set the 'authentication protocol' used for authenticated SNMPv3 messages. Allowed values are MD5 or SHA. Default value is MD5. +Set the 'authentication protocol' used for authenticated SNMPv3 messages. Allowed values are MD5 or SHA. Default value is MD5. *-W* | *--authPassword* 'authentication pass phrase':: - - Set the 'authentication pass phrase' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level' to authNoPriv or authPriv. +Set the 'authentication pass phrase' used for authenticated SNMPv3 messages. This parameter is mandatory if you set 'security level' to authNoPriv or authPriv. *-x* | *--privProtocol* 'privacy protocol':: - - Set the 'privacy protocol' used for encrypted SNMPv3 messages. Allowed values are DES or AES. Default value is DES. +Set the 'privacy protocol' used for encrypted SNMPv3 messages. Allowed values are DES or AES. Default value is DES. *-X* | *--privPassword* 'privacy pass phrase':: +Set the 'privacy pass phrase' used for encrypted SNMPv3 messages. This parameter is mandatory if you set 'security level' to authPriv. - Set the 'privacy pass phrase' used for encrypted SNMPv3 messages. This parameter is mandatory if you set 'security level' to authPriv. +IPMI OPTIONS +------------ + +*-b* | *--username* 'username':: +Set the username used for authenticating IPMI over LAN connections (mandatory for IPMI over LAN. No default). + +*-B* | *--password* 'password':: +Specify the password to use when authenticationg with the remote host (mandatory for IPMI over LAN. No default). + +*-d* | *--authType* 'authentication type':: +Specify the IPMI 1.5 authentication type to use (NONE, STRAIGHT_PASSWORD_KEY, MD2, and MD5) with the remote host (default=MD5). +This forces connection through the 'lan' IPMI interface , thus in IPMI 1.5 mode. + +*-D* | *--cipher_suite_id* 'cipher suite identifier':: +Specify the IPMI 2.0 cipher suite ID to use. The Cipher Suite ID identifies a set of authentication, integrity, and +confidentiality algorithms to use for IPMI 2.0 communication. The authentication algorithm identifies the algorithm +to use for session setup, the integrity algorithm identifies the algorithm to use for session packet signatures, and the +confidentiality algorithm identifies the algorithm to use for payload encryption (default=3). ++ +The following cipher suite ids are currently supported (Authentication; Integrity; Confidentiality): + +- *0*: None; None; None +- *1*: HMAC-SHA1; None; None +- *2*: HMAC-SHA1; HMAC-SHA1-96; None +- *3*: HMAC-SHA1; HMAC-SHA1-96; AES-CBC-128 +- *6*: HMAC-MD5; None; None +- *7*: HMAC-MD5; HMAC-MD5-128; None +- *8*: HMAC-MD5; HMAC-MD5-128; AES-CBC-128 +- *11*: HMAC-MD5; MD5-128; None +- *12*: HMAC-MD5; MD5-128; AES-CBC-128 +- *15*: HMAC-SHA256; None; None +- *16*: HMAC-SHA256; HMAC_SHA256_128; None +- *17*: HMAC-SHA256; HMAC_SHA256_128; AES-CBC-128 MISCELLANEOUS OPTIONS --------------------- *-V* | *--version*:: - - Display NUT version. +Display NUT version. *-a* | *--available*:: - - Display available bus that can be scanned , depending on how the binary has been compiled. (OLDNUT, USB, SNMP, XML, AVAHI, IPMI). +Display available bus that can be scanned , depending on how the binary has been compiled. (OLDNUT, USB, SNMP, XML, AVAHI, IPMI). *-q* | *--quiet*:: - - Display only scan result. No information on currently scanned bus is displayed. +Display only scan result. No information on currently scanned bus is displayed. EXAMPLES -------- @@ -168,6 +178,10 @@ To scan NUT servers with a timeout of 10 seconds on IP range 192.168.0.0 to 192. *nut-scanner -O -t 10 -m 192.168.0.0/25* +To scan for power supplies, through IPMI (1.5 mode) over the network, on address range 192.168.0.0 to 192.168.0.255: + +*nut-scanner -I -m 192.168.0.0/24 -b username -B password* + SEE ALSO -------- diff --git a/drivers/nut-ipmipsu.c b/drivers/nut-ipmipsu.c index b7382a8..2991cfc 100644 --- a/drivers/nut-ipmipsu.c +++ b/drivers/nut-ipmipsu.c @@ -27,7 +27,7 @@ #include "nut-ipmi.h" #define DRIVER_NAME "IPMI PSU driver" -#define DRIVER_VERSION "0.07" +#define DRIVER_VERSION "0.30" /* driver description structure */ upsdrv_info_t upsdrv_info = { @@ -183,17 +183,20 @@ void upsdrv_makevartable(void) "Type of the device to match ('psu' for \"Power Supply\")"); addvar(VAR_VALUE, "serial", "Serial number to match a specific device"); - addvar(VAR_VALUE, "fruid", "FRU identifier to match a specific device"); - addvar(VAR_VALUE, "sensorid", "Sensor identifier to match a specific device"); */ + addvar(VAR_VALUE, "fruid", "FRU identifier to match a specific device"); */ } void upsdrv_initups(void) { upsdebugx(1, "upsdrv_initups..."); - /* port can be expressed using: - * "id?" for device (FRU) ID 0x? - * "psu?" for PSU number ? + /* port can be expressed in various forms: + * - inband: + * "id?" for device (FRU) ID 0x? + * "psu?" for PSU number ? + * - out of band + * "id?@host" + * "host" => requires serial or ... */ if (!strncmp( device_path, "id", 2)) { diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index affcc77..8b9f1ab 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -1,6 +1,8 @@ /* nut-scan.h: detect NUT services * - * Copyright (C) 2011 - Frederic Bohe + * Copyright (C) + * 2011 - Frederic Bohe + * 2012 - Arnaud Quette * * 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 @@ -16,6 +18,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #ifndef NUT_SCAN_H #define NUT_SCAN_H @@ -23,6 +26,10 @@ #include #include +#ifdef WITH_IPMI +#include +#endif + /* SNMP structure */ typedef struct nutscan_snmp { char * community; @@ -36,8 +43,34 @@ typedef struct nutscan_snmp { void * handle; } nutscan_snmp_t; +/* IPMI structure */ +/* Settings for OutofBand (remote) connection */ +typedef struct nutscan_ipmi { + char* username; /* IPMI 1.5 and 2.0 */ + char* password; /* IPMI 1.5 and 2.0 */ + int authentication_type; /* IPMI 1.5 */ + int cipher_suite_id; /* IPMI 2.0 */ + char* K_g_BMC_key; /* IPMI 2.0, optional key for 2 key auth. */ + int privilege_level; /* for both */ + unsigned int workaround_flags; /* for both */ + int ipmi_version; /* IPMI 1.5 or 2.0? */ +} nutscan_ipmi_t; + +/* IPMI auth defines, simply using FreeIPMI defines */ +#ifndef IPMI_AUTHENTICATION_TYPE_NONE + #define IPMI_AUTHENTICATION_TYPE_NONE 0x00 + #define IPMI_AUTHENTICATION_TYPE_MD2 0x01 + #define IPMI_AUTHENTICATION_TYPE_MD5 0x02 + #define IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY 0x04 + #define IPMI_AUTHENTICATION_TYPE_OEM_PROP 0x05 + #define IPMI_AUTHENTICATION_TYPE_RMCPPLUS 0x06 +#endif /* IPMI_AUTHENTICATION_TYPE_NONE */ + +#define IPMI_1_5 1 +#define IPMI_2_0 0 + /* Scanning */ -nutscan_device_t * nutscan_scan_snmp(const char * start_ip,const char * stop_ip,long usec_timeout, nutscan_snmp_t * sec); +nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip, long usec_timeout, nutscan_snmp_t * sec); nutscan_device_t * nutscan_scan_usb(); @@ -47,7 +80,7 @@ nutscan_device_t * nutscan_scan_nut(const char * startIP, const char * stopIP, c nutscan_device_t * nutscan_scan_avahi(long usec_timeout); -nutscan_device_t * nutscan_scan_ipmi(void); +nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec); /* Display functions */ void nutscan_display_ups_conf(nutscan_device_t * device); diff --git a/tools/nut-scanner/nut-scanner.c b/tools/nut-scanner/nut-scanner.c index 52e0da7..7ca1554 100644 --- a/tools/nut-scanner/nut-scanner.c +++ b/tools/nut-scanner/nut-scanner.c @@ -35,7 +35,7 @@ #define ERR_BAD_OPTION (-1) -const char optstring[] = "?ht:s:e:c:l:u:W:X:w:x:p:CUSMOAm:NPqIVa"; +const char optstring[] = "?ht:s:e:c:l:u:W:X:w:x:p:b:B:d:D:CUSMOAm:NPqIVa"; #ifdef HAVE_GETOPT_LONG const struct option longopts[] = @@ -50,6 +50,10 @@ const struct option longopts[] = { "privPassword",required_argument,NULL,'X' }, { "authProtocol",required_argument,NULL,'w' }, { "privProtocol",required_argument,NULL,'x' }, + { "username",required_argument,NULL,'b' }, + { "password",required_argument,NULL,'B' }, + { "authType",required_argument,NULL,'d' }, + { "cipher_suite_id",required_argument,NULL,'D' }, { "port",required_argument,NULL,'p' }, { "complete_scan",no_argument,NULL,'C' }, { "usb_scan",no_argument,NULL,'U' }, @@ -110,7 +114,9 @@ static void * run_avahi(void * arg) } static void * run_ipmi(void * arg) { - dev[TYPE_IPMI] = nutscan_scan_ipmi(); + nutscan_ipmi_t * sec = (nutscan_ipmi_t *)arg; + + dev[TYPE_IPMI] = nutscan_scan_ipmi(start_ip,end_ip,sec); return NULL; } #endif /* HAVE_PTHREAD */ @@ -133,6 +139,7 @@ static int printq(int quiet,const char *fmt, ...) int main(int argc, char *argv[]) { nutscan_snmp_t snmp_sec; + nutscan_ipmi_t ipmi_sec; int opt_ret; char * cidr = NULL; int allow_all = 0; @@ -147,6 +154,12 @@ int main(int argc, char *argv[]) int ret_code = EXIT_SUCCESS; memset(&snmp_sec, 0, sizeof(snmp_sec)); + memset(&ipmi_sec, 0, sizeof(ipmi_sec)); + /* Set the default values for IPMI */ + ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD5; + ipmi_sec.ipmi_version = IPMI_1_5; /* default to IPMI 1.5, if not otherwise specified */ + ipmi_sec.cipher_suite_id = 3; /* default to HMAC-SHA1; HMAC-SHA1-96; AES-CBC-128 */ + ipmi_sec.privilege_level = IPMI_PRIVILEGE_LEVEL_ADMIN; /* should be sufficient */ nutscan_init(); @@ -220,6 +233,45 @@ int main(int argc, char *argv[]) } allow_snmp = 1; break; + case 'b': + if(!nutscan_avail_ipmi) { + goto display_help; + } + ipmi_sec.username = strdup(optarg); + break; + case 'B': + if(!nutscan_avail_ipmi) { + goto display_help; + } + ipmi_sec.password = strdup(optarg); + break; + case 'd': + if(!nutscan_avail_ipmi) { + goto display_help; + } + if (!strcmp(optarg, "NONE")) { + ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_NONE; + } + else if (!strcmp(optarg, "STRAIGHT_PASSWORD_KEY")) { + ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY; + } + else if (!strcmp(optarg, "MD2")) { + ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD2; + } + else if (!strcmp(optarg, "MD5")) { + ipmi_sec.authentication_type = IPMI_AUTHENTICATION_TYPE_MD5; + } + else { + fprintf(stderr,"Unknown authentication type (%s). Defaulting to MD5\n", optarg); + } + break; + case 'D': + if(!nutscan_avail_ipmi) { + goto display_help; + } + ipmi_sec.cipher_suite_id = atoi(optarg); + /* Force IPMI 2.0! */ + ipmi_sec.ipmi_version = IPMI_2_0; case 'p': port = strdup(optarg); break; @@ -307,6 +359,8 @@ display_help: if( nutscan_avail_ipmi ) { printf(" -I, --ipmi_scan: Scan IPMI devices.\n"); } + + printf("\nNetwork specific options:\n"); printf(" -t, --timeout : network operation timeout (default %d).\n",DEFAULT_TIMEOUT); printf(" -s, --start_ip : First IP address to scan.\n"); printf(" -e, --end_ip : Last IP address to scan.\n"); @@ -325,6 +379,18 @@ display_help: printf(" -X, --privPassword : Set the privacy pass phrase used for encrypted SNMPv3 messages (mandatory if you set secLevel to authPriv)\n"); } + if( nutscan_avail_ipmi ) { + printf("\nIPMI over LAN specific options:\n"); + printf(" -b, --username : Set the username used for authenticating IPMI over LAN connections (mandatory for IPMI over LAN. No default)\n"); + /* Specify the username to use when authenticating with the remote host. If not specified, a null (i.e. anonymous) username is assumed. The user must have + * at least ADMIN privileges in order for this tool to operate fully. */ + printf(" -B, --password : Specify the password to use when authenticationg with the remote host (mandatory for IPMI over LAN. No default)\n"); + /* Specify the password to use when authenticationg with the remote host. If not specified, a null password is assumed. Maximum password length is 16 for IPMI + * 1.5 and 20 for IPMI 2.0. */ + printf(" -d, --authType : Specify the IPMI 1.5 authentication type to use (NONE, STRAIGHT_PASSWORD_KEY, MD2, and MD5) with the remote host (default=MD5)\n"); + printf(" -D, --cipher_suite_id : Specify the IPMI 2.0 cipher suite ID to use, for authentication, integrity, and confidentiality (default=3)\n"); + } + printf("\nNUT specific options:\n"); printf(" -p, --port : Port number of remote NUT upsd\n"); printf("\ndisplay specific options:\n"); @@ -427,11 +493,11 @@ display_help: if( allow_ipmi && nutscan_avail_ipmi) { printq(quiet,"Scanning IPMI bus.\n"); #ifdef HAVE_PTHREAD - if(pthread_create(&thread[TYPE_IPMI],NULL,run_ipmi,NULL)) { + if(pthread_create(&thread[TYPE_IPMI],NULL,run_ipmi,&ipmi_sec)) { nutscan_avail_ipmi = 0; } #else - dev[TYPE_IPMI] = nutscan_scan_ipmi(); + dev[TYPE_IPMI] = nutscan_scan_ipmi(start_ip,end_ip,timeout,&ipmi_sec); #endif /* HAVE_PTHREAD */ } diff --git a/tools/nut-scanner/scan_ipmi.c b/tools/nut-scanner/scan_ipmi.c index c1ec78a..0288ad4 100644 --- a/tools/nut-scanner/scan_ipmi.c +++ b/tools/nut-scanner/scan_ipmi.c @@ -29,6 +29,11 @@ #define NUT_IPMI_DRV_NAME "nut-ipmipsu" +/* IPMI defines */ +/* 5 seconds for establishing an IPMI connection */ +#define IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT 5000 +#define IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT 250 + /* dynamic link library stuff */ static char * libname = "libfreeipmi"; static lt_dlhandle dl_handle = NULL; @@ -88,10 +93,23 @@ static int (*nut_ipmi_ctx_find_inband) (ipmi_ctx_t ctx, const char *driver_device, unsigned int workaround_flags, unsigned int flags); +static int (*nut_ipmi_ctx_open_outofband) (ipmi_ctx_t ctx, + const char *hostname, + const char *username, + const char *password, + uint8_t authentication_type, + uint8_t privilege_level, + unsigned int session_timeout, + unsigned int retransmission_timeout, + unsigned int workaround_flags, + unsigned int flags); +static int (*nut_ipmi_ctx_errnum) (ipmi_ctx_t ctx); static char * (*nut_ipmi_ctx_errormsg) (ipmi_ctx_t ctx); static int (*nut_ipmi_ctx_close) (ipmi_ctx_t ctx); static void (*nut_ipmi_ctx_destroy) (ipmi_ctx_t ctx); +/* Internal functions */ +static nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * sec); /* Return 0 on error */ int nutscan_load_ipmi_library() @@ -189,6 +207,16 @@ int nutscan_load_ipmi_library() goto err; } + *(void **) (&nut_ipmi_ctx_open_outofband) = lt_dlsym(dl_handle, "ipmi_ctx_open_outofband"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } + + *(void **) (&nut_ipmi_ctx_errnum) = lt_dlsym(dl_handle, "ipmi_ctx_errnum"); + if ((dl_error = lt_dlerror()) != NULL) { + goto err; + } + *(void **) (&nut_ipmi_ctx_errormsg) = lt_dlsym(dl_handle, "ipmi_ctx_errormsg"); if ((dl_error = lt_dlerror()) != NULL) { goto err; @@ -265,10 +293,10 @@ int is_ipmi_device_supported(ipmi_ctx_t ipmi_ctx, int ipmi_id) /* Parse FRU information */ if (!(fru_parse_ctx = (*nut_ipmi_fru_ctx_create) (ipmi_ctx))) { - fprintf(stderr, "ipmi_fru_parse_ctx_create()\n"); + fprintf(stderr, "Error with %s(): %s\n", IPMI_FRU_CTX_CREATE, (*nut_ipmi_ctx_errormsg)(ipmi_ctx)); return 0; } -fprintf(stdout, "There.1\n"); + /* lots of motherboards calculate checksums incorrectly */ if ((*nut_ipmi_fru_ctx_set_flags) (fru_parse_ctx, IPMI_FRU_FLAGS_SKIP_CHECKSUM_CHECKS) < 0) { @@ -279,7 +307,7 @@ fprintf(stdout, "There.1\n"); #endif /* HAVE_FREEIPMI_11X_12X */ return 0; } -fprintf(stdout, "There.2\n"); + if ((*nut_ipmi_fru_open_device_id) (fru_parse_ctx, ipmi_id) < 0) { #ifdef HAVE_FREEIPMI_11X_12X @@ -292,7 +320,6 @@ fprintf(stdout, "There.2\n"); do { -fprintf(stdout, "There.3\n"); /* clear fields */ area_type = 0; area_length = 0; @@ -337,20 +364,21 @@ fprintf(stdout, "There.3\n"); return 0; } -/* return NULL on error */ -nutscan_device_t * nutscan_scan_ipmi() +/* Check for IPMI support on a specific (local or remote) system + * Return NULL on error, or a valid nutscan_device_t otherwise */ +nutscan_device_t * nutscan_scan_ipmi_device(const char * IPaddr, nutscan_ipmi_t * ipmi_sec) { ipmi_ctx_t ipmi_ctx = NULL; nutscan_device_t * nut_dev = NULL; nutscan_device_t * current_nut_dev = NULL; int ret = -1; int ipmi_id = 0; - char port_id[10]; + char port_id[64]; if( !nutscan_avail_ipmi ) { return NULL; } -fprintf(stdout, "There1\n"); + /* Initialize the FreeIPMI library. */ if (!(ipmi_ctx = (*nut_ipmi_ctx_create) ())) { @@ -359,34 +387,138 @@ fprintf(stdout, "There1\n"); return NULL; } -fprintf(stdout, "There2\n"); - if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx, - NULL, - 0, /* don't disable auto-probe */ - 0, - 0, - NULL, - 0, /* workaround flags, none by default */ - IPMI_FLAGS_NONBLOCKING /* flags */ - )) < 0) + /* Are we scanning locally, or over the network? */ + if (IPaddr == NULL) { - fprintf(stderr, "ipmi_ctx_find_inband: %s\n", - (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); - return NULL; + /* FIXME: we need root right to access local IPMI! + if (!ipmi_is_root ()) { + fprintf(stderr, "IPMI scan: %s\n", ipmi_ctx_strerror (IPMI_ERR_PERMISSION)); + } */ + + if ((ret = (*nut_ipmi_ctx_find_inband) (ipmi_ctx, + NULL, + 0, /* don't disable auto-probe */ + 0, + 0, + NULL, + 0, /* workaround flags, none by default */ + 0 /* flags */ + )) < 0) + { + fprintf(stderr, "ipmi_ctx_find_inband: %s\n", + (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); + return NULL; + } + if (!ret) + { + /* No local IPMI device detected */ + return NULL; + } } - if (!ret) - { - /* No local IPMI device detected */ - return NULL; + else { + +#if 0 + if (ipmi_sec->ipmi_version == IPMI_2_0) { + + /* FIXME: need processing?! + * int parse_kg (void *out, unsigned int outlen, const char *in) + * if ((rv = parse_kg (common_cmd_args_config->k_g, IPMI_MAX_K_G_LENGTH + 1, data->string)) < 0) + * { + * fprintf (stderr, "Config File Error: k_g input formatted incorrectly\n"); + * exit (EXIT_FAILURE); + * }*/ + if ((ret = (*nut_ipmi_ctx_open_outofband_2_0) (ipmi_ctx, + IPaddr, + ipmi_sec->username, + ipmi_sec->password, + ipmi_sec->K_g_BMC_key, +??? (ipmi_sec->K_g_BMC_key) ? config->k_g_len : 0, + ipmi_sec->privilege_level, + ipmi_sec->cipher_suite_id, + IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, + IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, + ipmi_dev->workaround_flags, + flags) < 0) + { + IPMI_MONITORING_DEBUG (("ipmi_ctx_open_outofband_2_0: %s", ipmi_ctx_errormsg (c->ipmi_ctx))); + if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_USERNAME_INVALID) + c->errnum = IPMI_MONITORING_ERR_USERNAME_INVALID; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID) + c->errnum = IPMI_MONITORING_ERR_PASSWORD_INVALID; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT) + c->errnum = IPMI_MONITORING_ERR_PRIVILEGE_LEVEL_INSUFFICIENT; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED) + c->errnum = IPMI_MONITORING_ERR_PRIVILEGEL_LEVEL_CANNOT_BE_OBTAINED; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_K_G_INVALID) + c->errnum = IPMI_MONITORING_ERR_K_G_INVALID; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CIPHER_SUITE_ID_UNAVAILABLE) + c->errnum = IPMI_MONITORING_ERR_CIPHER_SUITE_ID_UNAVAILABLE; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT) + c->errnum = IPMI_MONITORING_ERR_PASSWORD_VERIFICATION_TIMEOUT; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_2_0_UNAVAILABLE) + c->errnum = IPMI_MONITORING_ERR_IPMI_2_0_UNAVAILABLE; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) + c->errnum = IPMI_MONITORING_ERR_CONNECTION_TIMEOUT; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SESSION_TIMEOUT) + c->errnum = IPMI_MONITORING_ERR_SESSION_TIMEOUT; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BAD_COMPLETION_CODE + || ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_IPMI_ERROR) + c->errnum = IPMI_MONITORING_ERR_IPMI_ERROR; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_BMC_BUSY) + c->errnum = IPMI_MONITORING_ERR_BMC_BUSY; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_OUT_OF_MEMORY) + c->errnum = IPMI_MONITORING_ERR_OUT_OF_MEMORY; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID) + c->errnum = IPMI_MONITORING_ERR_HOSTNAME_INVALID; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_PARAMETERS) + c->errnum = IPMI_MONITORING_ERR_PARAMETERS; + else if (ipmi_ctx_errnum (c->ipmi_ctx) == IPMI_ERR_SYSTEM_ERROR) + c->errnum = IPMI_MONITORING_ERR_SYSTEM_ERROR; + else + c->errnum = IPMI_MONITORING_ERR_INTERNAL_ERROR; + return (-1); + } + } + else { /* Not IPMI 2.0 */ + +#endif /* 0 */ + + /* Fall back to IPMI 1.5 */ + if ((ret = (*nut_ipmi_ctx_open_outofband) (ipmi_ctx, + IPaddr, + ipmi_sec->username, + ipmi_sec->password, + ipmi_sec->authentication_type, + ipmi_sec->privilege_level, + IPMI_SESSION_TIMEOUT_LENGTH_DEFAULT, + IPMI_RETRANSMISSION_TIMEOUT_LENGTH_DEFAULT, + ipmi_sec->workaround_flags, + IPMI_FLAGS_DEFAULT + )) < 0) + { + /* No IPMI device detected on this host! + if ((*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_USERNAME_INVALID + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_INVALID + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_INSUFFICIENT + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PRIVILEGE_LEVEL_CANNOT_BE_OBTAINED + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_AUTHENTICATION_TYPE_UNAVAILABLE + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_PASSWORD_VERIFICATION_TIMEOUT + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_HOSTNAME_INVALID + || (*nut_ipmi_ctx_errnum) (ipmi_ctx) == IPMI_ERR_CONNECTION_TIMEOUT) { */ + + /* FIXME: don't log timeout errors */ + fprintf(stderr, "nut_ipmi_ctx_open_outofband: %s\n", + (*nut_ipmi_ctx_errormsg) (ipmi_ctx)); + return NULL; + /*}*/ + } } -fprintf(stdout, "There3 (ret = %i)\n", ret); /* Loop through all possible components */ for (ipmi_id = 0 ; ipmi_id <= IPMI_FRU_DEVICE_ID_MAX ; ipmi_id++) { -fprintf(stdout, "There4\n"); + if (is_ipmi_device_supported(ipmi_ctx, ipmi_id)) { -fprintf(stdout, "There4.%i\n", ipmi_id); if ( (nut_dev = nutscan_new_device()) == NULL ) { fprintf(stderr,"Memory allocation error\n"); nutscan_free_device(current_nut_dev); @@ -396,9 +528,17 @@ fprintf(stdout, "There4.%i\n", ipmi_id); /* Fill the device structure (sufficient with driver and port) */ nut_dev->type = TYPE_IPMI; nut_dev->driver = strdup(NUT_IPMI_DRV_NAME); - sprintf(port_id, "id%x", ipmi_id); + if (IPaddr == NULL) { + sprintf(port_id, "id%x", ipmi_id); + } + else { + /* FIXME: also check against "localhost" and its IPv{4,6} */ + sprintf(port_id, "id%x@%s", ipmi_id, IPaddr); + } nut_dev->port = strdup(port_id); - + /* FIXME: also dump device.serial? + * using drivers/libfreeipmi_get_board_info() */ + current_nut_dev = nutscan_add_device_to_device( current_nut_dev, nut_dev); @@ -415,9 +555,50 @@ fprintf(stdout, "There4.%i\n", ipmi_id); return current_nut_dev; } + +/* General IPMI scan entry point: scan 1 to n devices, local or remote, + * for IPMI support + * Return NULL on error, or a valid nutscan_device_t otherwise */ +nutscan_device_t * nutscan_scan_ipmi(const char * start_ip, const char * stop_ip, nutscan_ipmi_t * sec) +{ + nutscan_ip_iter_t ip; + char * ip_str = NULL; + nutscan_ipmi_t * tmp_sec; + nutscan_device_t * nut_dev = NULL; + nutscan_device_t * current_nut_dev = NULL; + + if( !nutscan_avail_ipmi ) { + return NULL; + } + + + /* Are we scanning locally, or through the network? */ + if (start_ip == NULL) + { + /* Local PSU scan */ + current_nut_dev = nutscan_scan_ipmi_device(NULL, NULL); + } + else { + ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip); + + while(ip_str != NULL) { + tmp_sec = malloc(sizeof(nutscan_ipmi_t)); + memcpy(tmp_sec, sec, sizeof(nutscan_ipmi_t)); + + if ((current_nut_dev = nutscan_scan_ipmi_device(ip_str, tmp_sec)) != NULL) { + /* Store the positive result */ + current_nut_dev = nutscan_add_device_to_device(current_nut_dev, nut_dev); + } + /* Prepare the next iteration */ + ip_str = nutscan_ip_iter_inc(&ip); + }; + } + + return current_nut_dev; +} #else /* WITH_IPMI */ /* stub function */ -nutscan_device_t * nutscan_scan_ipmi() +nutscan_device_t * nutscan_scan_ipmi(const char * startIP, const char * stopIP, nutscan_ipmi_t * sec) { return NULL; } -- 1.7.10.2 From 3d0002653a506f2acb24be2201724e7b785de784 Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Fri, 5 Oct 2012 10:27:55 +0000 Subject: [PATCH] Fix compilation error Define IPMI_PRIVILEGE_LEVEL_ADMIN value, in case FreeIPMI is not available Fossil-ID: SVN r3741 --- tools/nut-scanner/nut-scan.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/nut-scanner/nut-scan.h b/tools/nut-scanner/nut-scan.h index 8b9f1ab..b853d96 100644 --- a/tools/nut-scanner/nut-scan.h +++ b/tools/nut-scanner/nut-scan.h @@ -64,7 +64,10 @@ typedef struct nutscan_ipmi { #define IPMI_AUTHENTICATION_TYPE_STRAIGHT_PASSWORD_KEY 0x04 #define IPMI_AUTHENTICATION_TYPE_OEM_PROP 0x05 #define IPMI_AUTHENTICATION_TYPE_RMCPPLUS 0x06 -#endif /* IPMI_AUTHENTICATION_TYPE_NONE */ +#endif +#ifndef IPMI_PRIVILEGE_LEVEL_ADMIN + #define IPMI_PRIVILEGE_LEVEL_ADMIN 0x04 +#endif #define IPMI_1_5 1 #define IPMI_2_0 0 -- 1.7.10.2 From 605ef0a46fbb8519b849683028f7e6cf35eb2fdd Mon Sep 17 00:00:00 2001 From: Arnaud Quette Date: Thu, 11 Apr 2013 23:15:51 +0200 Subject: [PATCH] Set USB timeout to 5 seconds Set the low level USB timeout back to the standard 5 seconds. This was set to 4 seconds, for performance reasons, but is now causing issues with some devices (reported by Stefan "stevenbg", GitHub issue #23) --- drivers/libusb.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/libusb.c b/drivers/libusb.c index 50bfc7f..234b9f1 100644 --- a/drivers/libusb.c +++ b/drivers/libusb.c @@ -33,12 +33,11 @@ #include "usb-common.h" #include "libusb.h" -/* USB standard state 5000, but we've decreased it to - * improve reactivity */ -#define USB_TIMEOUT 4000 +/* USB standard timeout */ +#define USB_TIMEOUT 5000 #define USB_DRIVER_NAME "USB communication driver" -#define USB_DRIVER_VERSION "0.31" +#define USB_DRIVER_VERSION "0.32" /* driver description structure */ upsdrv_info_t comm_upsdrv_info = { -- 1.7.10.2