Imported Upstream version 2.7.1
This commit is contained in:
parent
a1fa151fc7
commit
0121794af9
451 changed files with 41339 additions and 10887 deletions
|
|
@ -29,6 +29,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/* NUT SNMP common functions */
|
||||
#include "main.h"
|
||||
#include "snmp-ups.h"
|
||||
|
|
@ -45,6 +47,7 @@
|
|||
#include "compaq-mib.h"
|
||||
#include "bestpower-mib.h"
|
||||
#include "cyberpower-mib.h"
|
||||
#include "delta_ups-mib.h"
|
||||
#include "ietf-mib.h"
|
||||
|
||||
/* Address API change */
|
||||
|
|
@ -67,6 +70,7 @@ static mib2nut_info_t *mib2nut[] = {
|
|||
&compaq,
|
||||
&bestpower,
|
||||
&cyberpower,
|
||||
&delta_ups,
|
||||
/*
|
||||
* Prepend vendor specific MIB mappings before IETF, so that
|
||||
* if a device supports both IETF and vendor specific MIB,
|
||||
|
|
@ -87,13 +91,14 @@ int input_phases, output_phases, bypass_phases;
|
|||
mib2nut_info_t *mib2nut_info;
|
||||
/* FIXME: to be trashed */
|
||||
snmp_info_t *snmp_info;
|
||||
alarms_info_t *alarms_info;
|
||||
const char *mibname;
|
||||
const char *mibvers;
|
||||
|
||||
static void disable_transfer_oids(void);
|
||||
|
||||
#define DRIVER_NAME "Generic SNMP UPS driver"
|
||||
#define DRIVER_VERSION "0.68"
|
||||
#define DRIVER_VERSION "0.70"
|
||||
|
||||
/* driver description structure */
|
||||
upsdrv_info_t upsdrv_info = {
|
||||
|
|
@ -469,77 +474,139 @@ void nut_snmp_cleanup(void)
|
|||
SOCK_CLEANUP; /* wrapper not needed on Unix! */
|
||||
}
|
||||
|
||||
struct snmp_pdu *nut_snmp_get(const char *OID)
|
||||
/* Free a struct snmp_pdu * returned by nut_snmp_walk */
|
||||
void nut_snmp_free(struct snmp_pdu ** array_to_free)
|
||||
{
|
||||
struct snmp_pdu ** current_element;
|
||||
|
||||
current_element = array_to_free;
|
||||
|
||||
while (*current_element != NULL) {
|
||||
snmp_free_pdu(*current_element);
|
||||
current_element++;
|
||||
}
|
||||
|
||||
free( array_to_free );
|
||||
}
|
||||
|
||||
/* Return a NULL terminated array of snmp_pdu * */
|
||||
struct snmp_pdu **nut_snmp_walk(const char *OID, int max_iteration)
|
||||
{
|
||||
int status;
|
||||
struct snmp_pdu *pdu, *response = NULL;
|
||||
oid name[MAX_OID_LEN];
|
||||
size_t name_len = MAX_OID_LEN;
|
||||
oid * current_name;
|
||||
size_t current_name_len;
|
||||
static unsigned int numerr = 0;
|
||||
int nb_iteration = 0;
|
||||
struct snmp_pdu ** ret_array = NULL;
|
||||
int type = SNMP_MSG_GET;
|
||||
|
||||
upsdebugx(3, "nut_snmp_get(%s)", OID);
|
||||
upsdebugx(3, "nut_snmp_walk(%s)", OID);
|
||||
|
||||
/* create and send request. */
|
||||
if (!snmp_parse_oid(OID, name, &name_len)) {
|
||||
upsdebugx(2, "[%s] nut_snmp_get: %s: %s",
|
||||
upsdebugx(2, "[%s] nut_snmp_walk: %s: %s",
|
||||
upsname?upsname:device_name, OID, snmp_api_errstring(snmp_errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdu = snmp_pdu_create(SNMP_MSG_GET);
|
||||
current_name = name;
|
||||
current_name_len = name_len;
|
||||
|
||||
if (pdu == NULL)
|
||||
fatalx(EXIT_FAILURE, "Not enough memory");
|
||||
|
||||
snmp_add_null_var(pdu, name, name_len);
|
||||
|
||||
status = snmp_synch_response(g_snmp_sess_p, pdu, &response);
|
||||
|
||||
if (!response)
|
||||
return NULL;
|
||||
|
||||
if (!((status == STAT_SUCCESS) && (response->errstat == SNMP_ERR_NOERROR)))
|
||||
{
|
||||
if (mibname == NULL) {
|
||||
/* We are probing for proper mib - ignore errors */
|
||||
snmp_free_pdu(response);
|
||||
return NULL;
|
||||
while( nb_iteration < max_iteration ) {
|
||||
/* Going to a shorter OID means we are outside our sub-tree */
|
||||
if( current_name_len < name_len ) {
|
||||
break;
|
||||
}
|
||||
|
||||
numerr++;
|
||||
pdu = snmp_pdu_create(type);
|
||||
|
||||
if ((numerr == SU_ERR_LIMIT) || ((numerr % SU_ERR_RATE) == 0))
|
||||
upslogx(LOG_WARNING, "[%s] Warning: excessive poll "
|
||||
"failures, limiting error reporting",
|
||||
upsname?upsname:device_name);
|
||||
if (pdu == NULL) {
|
||||
fatalx(EXIT_FAILURE, "Not enough memory");
|
||||
}
|
||||
|
||||
if ((numerr < SU_ERR_LIMIT) || ((numerr % SU_ERR_RATE) == 0))
|
||||
nut_snmp_perror(g_snmp_sess_p, status, response,
|
||||
"nut_snmp_get: %s", OID);
|
||||
snmp_add_null_var(pdu, current_name, current_name_len);
|
||||
|
||||
snmp_free_pdu(response);
|
||||
response = NULL;
|
||||
} else {
|
||||
numerr = 0;
|
||||
status = snmp_synch_response(g_snmp_sess_p, pdu, &response);
|
||||
|
||||
if (!response) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!((status == STAT_SUCCESS) && (response->errstat == SNMP_ERR_NOERROR))) {
|
||||
if (mibname == NULL) {
|
||||
/* We are probing for proper mib - ignore errors */
|
||||
snmp_free_pdu(response);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
numerr++;
|
||||
|
||||
if ((numerr == SU_ERR_LIMIT) || ((numerr % SU_ERR_RATE) == 0)) {
|
||||
upslogx(LOG_WARNING, "[%s] Warning: excessive poll "
|
||||
"failures, limiting error reporting",
|
||||
upsname?upsname:device_name);
|
||||
}
|
||||
|
||||
if ((numerr < SU_ERR_LIMIT) || ((numerr % SU_ERR_RATE) == 0)) {
|
||||
if (type == SNMP_MSG_GETNEXT) {
|
||||
upsdebugx(2, "=> No more OID, walk complete");
|
||||
}
|
||||
else {
|
||||
nut_snmp_perror(g_snmp_sess_p, status, response,
|
||||
"nut_snmp_walk: %s", OID);
|
||||
}
|
||||
}
|
||||
|
||||
snmp_free_pdu(response);
|
||||
break;
|
||||
} else {
|
||||
numerr = 0;
|
||||
}
|
||||
|
||||
nb_iteration++;
|
||||
/* +1 is for the terminating NULL */
|
||||
ret_array = realloc(ret_array,sizeof(struct snmp_pdu*)*(nb_iteration+1));
|
||||
ret_array[nb_iteration-1] = response;
|
||||
ret_array[nb_iteration]=NULL;
|
||||
|
||||
current_name = response->variables->name;
|
||||
current_name_len = response->variables->name_length;
|
||||
|
||||
type = SNMP_MSG_GETNEXT;
|
||||
}
|
||||
|
||||
return response;
|
||||
return ret_array;
|
||||
}
|
||||
|
||||
bool_t nut_snmp_get_str(const char *OID, char *buf, size_t buf_len, info_lkp_t *oid2info)
|
||||
struct snmp_pdu *nut_snmp_get(const char *OID)
|
||||
{
|
||||
size_t len = 0;
|
||||
struct snmp_pdu *pdu;
|
||||
struct snmp_pdu ** pdu_array;
|
||||
struct snmp_pdu * ret_pdu;
|
||||
|
||||
upsdebugx(3, "Entering nut_snmp_get_str()");
|
||||
upsdebugx(3, "nut_snmp_get(%s)", OID);
|
||||
|
||||
pdu_array = nut_snmp_walk(OID,1);
|
||||
|
||||
if(pdu_array == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret_pdu = snmp_clone_pdu(*pdu_array);
|
||||
|
||||
nut_snmp_free(pdu_array);
|
||||
|
||||
return ret_pdu;
|
||||
}
|
||||
|
||||
static bool_t decode_str(struct snmp_pdu *pdu, char *buf, size_t buf_len, info_lkp_t *oid2info) {
|
||||
size_t len = 0;
|
||||
|
||||
/* zero out buffer. */
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
pdu = nut_snmp_get(OID);
|
||||
if (pdu == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (pdu->variables->type) {
|
||||
case ASN_OCTET_STR:
|
||||
case ASN_OPAQUE:
|
||||
|
|
@ -573,14 +640,33 @@ bool_t nut_snmp_get_str(const char *OID, char *buf, size_t buf_len, info_lkp_t *
|
|||
len = snprint_objid (buf, buf_len, pdu->variables->val.objid, pdu->variables->val_len / sizeof(oid));
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool_t nut_snmp_get_str(const char *OID, char *buf, size_t buf_len, info_lkp_t *oid2info)
|
||||
{
|
||||
struct snmp_pdu *pdu;
|
||||
bool_t ret;
|
||||
|
||||
upsdebugx(3, "Entering nut_snmp_get_str()");
|
||||
|
||||
pdu = nut_snmp_get(OID);
|
||||
if (pdu == NULL)
|
||||
return FALSE;
|
||||
|
||||
ret = decode_str(pdu,buf,buf_len,oid2info);
|
||||
|
||||
if(ret == FALSE) {
|
||||
upsdebugx(2, "[%s] unhandled ASN 0x%x received from %s",
|
||||
upsname?upsname:device_name, pdu->variables->type, OID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
snmp_free_pdu(pdu);
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool_t nut_snmp_get_int(const char *OID, long *pval)
|
||||
|
|
@ -917,6 +1003,7 @@ bool_t load_mib2nut(const char *mib)
|
|||
OID_pwr_status = m2n->oid_pwr_status;
|
||||
mibname = m2n->mib_name;
|
||||
mibvers = m2n->mib_version;
|
||||
alarms_info = m2n->alarms_info;
|
||||
upsdebugx(1, "load_mib2nut: using %s mib", mibname);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1276,50 +1363,56 @@ bool_t snmp_ups_walk(int mode)
|
|||
outlet_count = atoi(dstate_getinfo("outlet.count"));
|
||||
}
|
||||
|
||||
/* general init of data using the template */
|
||||
instantiate_info(su_info_p, &cur_info_p);
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
upsdebugx(1, "No outlet present, discarding template definition...");
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* get and process this data */
|
||||
status = get_and_process_data(mode, su_info_p);
|
||||
}
|
||||
|
|
@ -1335,6 +1428,10 @@ bool_t su_ups_get(snmp_info_t *su_info_p)
|
|||
static char buf[SU_INFOSIZE];
|
||||
bool_t status;
|
||||
long value;
|
||||
struct snmp_pdu ** pdu_array;
|
||||
struct snmp_pdu * current_pdu;
|
||||
alarms_info_t * alarms;
|
||||
int index = 0;
|
||||
|
||||
upsdebugx(2, "su_ups_get: %s %s", su_info_p->info_type, su_info_p->OID);
|
||||
|
||||
|
|
@ -1351,6 +1448,43 @@ bool_t su_ups_get(snmp_info_t *su_info_p)
|
|||
return status;
|
||||
}
|
||||
|
||||
if (!strcasecmp(su_info_p->info_type, "ups.alarms")) {
|
||||
status = nut_snmp_get_int(su_info_p->OID, &value);
|
||||
if (status == TRUE) {
|
||||
upsdebugx(2, "=> value: %ld", value);
|
||||
if( value > 0 ) {
|
||||
pdu_array = nut_snmp_walk(su_info_p->OID,INT_MAX);
|
||||
if(pdu_array == NULL) {
|
||||
upsdebugx(2, "=> Walk failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
current_pdu = pdu_array[index];
|
||||
while(current_pdu) {
|
||||
decode_str(current_pdu,buf,sizeof(buf),NULL);
|
||||
alarms = alarms_info;
|
||||
while( alarms->OID ) {
|
||||
if(!strcmp(buf+1,alarms_info->OID)) {
|
||||
upsdebugx(3, "Alarm OID %s found => %s", alarms->OID, alarms->info_value);
|
||||
status_set(alarms->info_value);
|
||||
break;
|
||||
}
|
||||
alarms++;
|
||||
}
|
||||
index++;
|
||||
current_pdu = pdu_array[index];
|
||||
}
|
||||
nut_snmp_free(pdu_array);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
upsdebugx(2, "=> Failed");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* another special case */
|
||||
if (!strcasecmp(su_info_p->info_type, "ambient.temperature")) {
|
||||
float temp=0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue