Package: nut-snmp
Version: 2.6.4-2.3
Severity: normal
Tags: upstream patch
Dear Maintainer,
After upgrading to Debian 7 I discovered that snmp-ups would no longer work
with our HP UPSs that use the CPQPOWER-MIB. It would crash on start-up.
A build from source of 2.6.5 had the same problem. A build from the nut svn
trunk, however did not crash.
I have managed to build a debian package that works by taking the nut-2.6.4
source package, taking the snmp-ups.c and snmp-ups.h files from trunk,
removing the delta-ups and pulizzi references and building the package. I will
attempt to attach the necessary patch to this bug report.
Thanks,
Philip Ward.
-- System Information:
Debian Release: 7.1
APT prefers stable
APT policy: (500, 'stable')
Architecture: amd64 (x86_64)
Kernel: Linux 3.2.0-4-amd64 (SMP w/24 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Versions of packages nut-snmp depends on:
ii libc6 2.13-38
ii libsnmp15 5.4.3~dfsg-2.7
ii nut 2.6.4-2.3
nut-snmp recommends no packages.
nut-snmp suggests no packages.
-- no debconf information
--
The University of Stirling has been ranked in the top 12 of UK universities for
graduate employment*.
94% of our 2012 graduates were in work and/or further study within six months
of graduation.
*The Telegraph
The University of Stirling is a charity registered in Scotland, number SC
011159.
--- /root/snmp-ups.c 2013-08-29 15:13:21.901303987 +0100
+++ snmp-ups.c 2013-08-29 15:21:25.983297855 +0100
@@ -91,7 +91,7 @@
static void disable_transfer_oids(void);
#define DRIVER_NAME "Generic SNMP UPS driver"
-#define DRIVER_VERSION "0.66"
+#define DRIVER_VERSION "0.69"
/* driver description structure */
upsdrv_info_t upsdrv_info = {
@@ -122,13 +122,10 @@
void upsdrv_initinfo(void)
{
snmp_info_t *su_info_p;
- char version[128];
upsdebugx(1, "SNMP UPS driver : entering upsdrv_initinfo()");
- snprintf(version, sizeof version, "%s (mib: %s %s)",
- DRIVER_VERSION, mibname, mibvers);
- dstate_setinfo("driver.version.internal", "%s", version);
+ dstate_setinfo("driver.version.data", "%s MIB %s", mibname, mibvers);
/* add instant commands to the info database.
* outlet commands are processed later, during initial walk */
@@ -955,7 +952,7 @@
info_lkp_t *info_lkp;
for (info_lkp = oid2info; (info_lkp != NULL) &&
- (strcmp(info_lkp->info_value, "NULL")); info_lkp++) {
+ (strcmp(info_lkp->info_value, "NULL")) && (info_lkp->info_value != NULL); info_lkp++) {
if (info_lkp->oid_value == value) {
upsdebugx(1, "su_find_infoval: found %s (value: %ld)",
@@ -1055,6 +1052,32 @@
return (outlet_index_base==0)?1:0;
}
+/* try to determine the number of outlets, using a template definition,
+ * that we walk, until we can't get anymore values */
+static int guestimate_outlet_count(const char *OID_template)
+{
+ int base_index = 0;
+ char test_OID[SU_INFOSIZE];
+ int base_count;
+
+ upsdebugx(1, "guestimate_outlet_count(%s)", OID_template);
+
+ /* Determine if OID index starts from 0 or 1? */
+ sprintf(test_OID, OID_template, base_index);
+ if (nut_snmp_get(test_OID) == NULL)
+ base_index++;
+
+ /* Now, actually iterate */
+ for (base_count = 0 ; ; base_count++) {
+ sprintf(test_OID, OID_template, base_index + base_count);
+ if (nut_snmp_get(test_OID) == NULL)
+ break;
+ }
+
+ upsdebugx(3, "guestimate_outlet_count: %i", base_count);
+ return base_count;
+}
+
/* process a single data from a walk */
bool_t get_and_process_data(int mode, snmp_info_t *su_info_p)
{
@@ -1236,55 +1259,71 @@
if(dstate_getinfo("outlet.count") == NULL) {
/* FIXME: should we disable it?
- * su_info_p->flags &= ~SU_FLAG_OK; */
- continue;
+ * su_info_p->flags &= ~SU_FLAG_OK;
+ * or rely on guestimation? */
+ if ((outlet_count = guestimate_outlet_count(su_info_p->OID)) == -1) {
+ /* Failed */
+ continue;
+ }
+ else {
+ /* Publish the count estimation */
+ dstate_setinfo("outlet.count", "%i", outlet_count);
+ }
+ }
+ else {
+ outlet_count = atoi(dstate_getinfo("outlet.count"));
}
- outlet_count = atoi(dstate_getinfo("outlet.count"));
-
- /* general init of data using the template */
- instantiate_info(su_info_p, &cur_info_p);
-
- for (cur_outlet_number = base_snmp_outlet_index(su_info_p->OID) ;
- cur_outlet_number < (outlet_count + base_snmp_outlet_index(su_info_p->OID)) ;
- cur_outlet_number++)
- {
- cur_nut_index = cur_outlet_number + base_nut_outlet_offset();
- sprintf((char*)cur_info_p.info_type, su_info_p->info_type,
- cur_nut_index);
- /* check if default value is also a template */
- if ((cur_info_p.dfl != NULL) &&
- (strstr(su_info_p->dfl, "%i") != NULL)) {
- cur_info_p.dfl = (char *)xmalloc(SU_INFOSIZE);
- sprintf((char *)cur_info_p.dfl, su_info_p->dfl, cur_nut_index);
- }
+ /* Only instantiate outlets if needed! */
+ if (outlet_count > 0) {
+ /* general init of data using the template */
+ instantiate_info(su_info_p, &cur_info_p);
+
+ for (cur_outlet_number = base_snmp_outlet_index(su_info_p->OID) ;
+ cur_outlet_number < (outlet_count + base_snmp_outlet_index(su_info_p->OID)) ;
+ cur_outlet_number++)
+ {
+ cur_nut_index = cur_outlet_number + base_nut_outlet_offset();
+ sprintf((char*)cur_info_p.info_type, su_info_p->info_type,
+ cur_nut_index);
+
+ /* check if default value is also a template */
+ if ((cur_info_p.dfl != NULL) &&
+ (strstr(su_info_p->dfl, "%i") != NULL)) {
+ cur_info_p.dfl = (char *)xmalloc(SU_INFOSIZE);
+ sprintf((char *)cur_info_p.dfl, su_info_p->dfl, cur_nut_index);
+ }
- if (cur_info_p.OID != NULL) {
- sprintf((char *)cur_info_p.OID, su_info_p->OID, cur_outlet_number);
+ if (cur_info_p.OID != NULL) {
+ sprintf((char *)cur_info_p.OID, su_info_p->OID, cur_outlet_number);
- /* add outlet instant commands to the info database. */
- if (SU_TYPE(su_info_p) == SU_TYPE_CMD) {
- /* FIXME: only add if "su_ups_get(cur_info_p) == TRUE" */
- if (mode == SU_WALKMODE_INIT)
- dstate_addcmd(cur_info_p.info_type);
+ /* add outlet instant commands to the info database. */
+ if (SU_TYPE(su_info_p) == SU_TYPE_CMD) {
+ /* FIXME: only add if "su_ups_get(cur_info_p) == TRUE" */
+ if (mode == SU_WALKMODE_INIT)
+ dstate_addcmd(cur_info_p.info_type);
+ }
+ else /* get and process this data */
+ status = get_and_process_data(mode, &cur_info_p);
+ } else {
+ /* server side (ABSENT) data */
+ su_setinfo(&cur_info_p, NULL);
}
- else /* get and process this data */
- status = get_and_process_data(mode, &cur_info_p);
- } else {
- /* server side (ABSENT) data */
- su_setinfo(&cur_info_p, NULL);
+ /* set back the flag */
+ su_info_p->flags = cur_info_p.flags;
}
- /* set back the flag */
- su_info_p->flags = cur_info_p.flags;
+ free((char*)cur_info_p.info_type);
+ if (cur_info_p.OID != NULL)
+ free((char*)cur_info_p.OID);
+ if ((cur_info_p.dfl != NULL) &&
+ (strstr(su_info_p->dfl, "%i") != NULL))
+ free((char*)cur_info_p.dfl);
}
- free((char*)cur_info_p.info_type);
- if (cur_info_p.OID != NULL)
- free((char*)cur_info_p.OID);
- if ((cur_info_p.dfl != NULL) &&
- (strstr(su_info_p->dfl, "%i") != NULL))
- free((char*)cur_info_p.dfl);
-
- } else {
+ else {
+ upsdebugx(1, "No outlet present, discarding template definition...");
+ }
+ }
+ else {
/* get and process this data */
status = get_and_process_data(mode, su_info_p);
}
@@ -1495,11 +1534,14 @@
snmp_info_t *su_info_p = NULL;
int status;
int retval = STAT_INSTCMD_FAILED;
+ int cmd_offset = 0;
upsdebugx(2, "entering su_instcmd(%s, %s)", cmdname, extradata);
- if (strncmp(cmdname, "outlet", 6))
+ /* FIXME: this should only apply if strchr(%)! */
+ if (strncmp(cmdname, "outlet", 6)) {
su_info_p = su_find_info(cmdname);
+ }
else {
snmp_info_t *tmp_info_p;
char *outlet_number_ptr = strchr(cmdname, '.');
@@ -1539,8 +1581,15 @@
}
/* adapt the OID */
if (su_info_p->OID != NULL) {
+ /* Workaround buggy Eaton Pulizzi implementation
+ * which have different offsets index for data & commands! */
+ if (su_info_p->flags & SU_CMD_OFFSET) {
+ upsdebugx(3, "Adding command offset");
+ cmd_offset++;
+ }
+
sprintf((char *)su_info_p->OID, tmp_info_p->OID,
- outlet_number - base_nut_outlet_offset());
+ outlet_number - base_nut_outlet_offset() + cmd_offset);
} else {
free_info(su_info_p);
return STAT_INSTCMD_UNKNOWN;