Imported Upstream version 2.6.3

This commit is contained in:
Arnaud Quette 2012-01-24 11:22:33 +01:00
parent 45043b58d0
commit fad6ced6f6
255 changed files with 11081 additions and 4629 deletions

View file

@ -18,15 +18,14 @@
*/
#include "common.h"
#ifdef HAVE_NET_SNMP_NET_SNMP_CONFIG_H
#include "nut-scan.h"
#ifdef WITH_SNMP
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <ltdl.h>
/* workaround for buggy Net-SNMP config
* from drivers/snmp-ups.h */
@ -63,18 +62,196 @@
static nutscan_device_t * dev_ret = NULL;
#ifdef HAVE_PTHREAD
static pthread_mutex_t dev_mutex;
static pthread_mutex_t lib_mutex;
static pthread_t * thread_array = NULL;
static int thread_count = 0;
#endif
long g_usec_timeout ;
/* dynamic link library stuff */
static lt_dlhandle dl_handle = NULL;
static const char *dl_error = NULL;
static void (*nut_init_snmp)(const char *type);
static void (*nut_snmp_sess_init)(netsnmp_session * session);
static void * (*nut_snmp_sess_open)(struct snmp_session *session);
static int (*nut_snmp_sess_close)(void *handle);
static struct snmp_session * (*nut_snmp_sess_session)(void *handle);
static void * (*nut_snmp_parse_oid)(const char *input, oid *objid,
size_t *objidlen);
static struct snmp_pdu * (*nut_snmp_pdu_create) (int command );
netsnmp_variable_list * (*nut_snmp_add_null_var)(netsnmp_pdu *pdu,
const oid *objid, size_t objidlen);
static int (*nut_snmp_sess_synch_response) (void *sessp, netsnmp_pdu *pdu,
netsnmp_pdu **response);
static int (*nut_snmp_oid_compare) (const oid *in_name1, size_t len1,
const oid *in_name2, size_t len2);
static void (*nut_snmp_free_pdu) (netsnmp_pdu *pdu);
static int (*nut_generate_Ku)(const oid * hashtype, u_int hashtype_len,
u_char * P, size_t pplen, u_char * Ku, size_t * kulen);
static const char * (*nut_snmp_api_errstring) (int snmp_errnumber);
static int (*nut_snmp_errno);
static oid * (*nut_usmAESPrivProtocol);
static oid * (*nut_usmHMACMD5AuthProtocol);
static oid * (*nut_usmHMACSHA1AuthProtocol);
static oid * (*nut_usmDESPrivProtocol);
/* return 0 on error */
int nutscan_load_snmp_library()
{
#ifdef HAVE_PTHREAD
pthread_mutex_lock(&lib_mutex);
#endif
if( dl_handle != NULL ) {
/* if previous init failed */
if( dl_handle == (void *)1 ) {
return 0;
}
/* init has already been done */
return 1;
}
if( lt_dlinit() != 0 ) {
fprintf(stderr, "Error initializing lt_init\n");
return 0;
}
dl_handle = lt_dlopenext("libnetsnmp");
if (!dl_handle) {
dl_error = lt_dlerror();
goto err;
}
lt_dlerror(); /* Clear any existing error */
*(void **) (&nut_init_snmp) = lt_dlsym(dl_handle, "init_snmp");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_sess_init) = lt_dlsym(dl_handle,
"snmp_sess_init");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_sess_open) = lt_dlsym(dl_handle,
"snmp_sess_open");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_sess_close) = lt_dlsym(dl_handle,
"snmp_sess_close");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_sess_session) = lt_dlsym(dl_handle,
"snmp_sess_session");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_parse_oid) = lt_dlsym(dl_handle,
"snmp_parse_oid");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_pdu_create) = lt_dlsym(dl_handle,
"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");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_sess_synch_response) = lt_dlsym(dl_handle,
"snmp_sess_synch_response");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_oid_compare) = lt_dlsym(dl_handle,
"snmp_oid_compare");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_free_pdu) = lt_dlsym(dl_handle,"snmp_free_pdu");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_generate_Ku) = lt_dlsym(dl_handle, "generate_Ku");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_api_errstring) = lt_dlsym(dl_handle,
"snmp_api_errstring");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_snmp_errno) = lt_dlsym(dl_handle, "snmp_errno");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_usmAESPrivProtocol) = lt_dlsym(dl_handle,
"usmAESPrivProtocol");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_usmHMACMD5AuthProtocol) = lt_dlsym(dl_handle,
"usmHMACMD5AuthProtocol");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_usmHMACSHA1AuthProtocol) = lt_dlsym(dl_handle,
"usmHMACSHA1AuthProtocol");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
*(void **) (&nut_usmDESPrivProtocol) = lt_dlsym(dl_handle,
"usmDESPrivProtocol");
if ((dl_error = lt_dlerror()) != NULL) {
goto err;
}
#ifdef HAVE_PTHREAD
pthread_mutex_unlock(&dev_mutex);
#endif
return 1;
err:
fprintf(stderr, "%s\n", dl_error);
dl_handle = (void *)1;
#ifdef HAVE_PTHREAD
pthread_mutex_unlock(&dev_mutex);
#endif
return 0;
}
/* end of dynamic link library stuff */
static void scan_snmp_add_device(nutscan_snmp_t * sec, struct snmp_pdu *response,char * mib)
{
nutscan_device_t * dev = NULL;
struct snmp_session * session;
char * buf;
session = snmp_sess_session(sec->handle);
session = (*nut_snmp_sess_session)(sec->handle);
if(session == NULL) {
return;
}
/* SNMP device found */
dev = nutscan_new_device();
dev->type = TYPE_SNMP;
@ -147,21 +324,21 @@ static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle)
/* create and send request. */
name_len = MAX_OID_LEN;
if (!snmp_parse_oid(oid_str, name, &name_len)) {
if (!(*nut_snmp_parse_oid)(oid_str, name, &name_len)) {
index++;
return NULL;
}
pdu = snmp_pdu_create(SNMP_MSG_GET);
pdu = (*nut_snmp_pdu_create)(SNMP_MSG_GET);
if (pdu == NULL) {
index++;
return NULL;
}
snmp_add_null_var(pdu, name, name_len);
(*nut_snmp_add_null_var)(pdu, name, name_len);
status = snmp_sess_synch_response(handle,pdu, &response);
status = (*nut_snmp_sess_synch_response)(handle,pdu, &response);
if( response == NULL ) {
index++;
return NULL;
@ -170,11 +347,11 @@ static struct snmp_pdu * scan_snmp_get_manufacturer(char* oid_str,void* handle)
if(status!=STAT_SUCCESS||response->errstat!=SNMP_ERR_NOERROR||
response->variables == NULL ||
response->variables->name == NULL ||
snmp_oid_compare(response->variables->name,
(*nut_snmp_oid_compare)(response->variables->name,
response->variables->name_length,
name, name_len) != 0 ||
response->variables->val.string == NULL ) {
snmp_free_pdu(response);
(*nut_snmp_free_pdu)(response);
index++;
return NULL;
}
@ -198,7 +375,7 @@ static void try_all_oid(void * arg)
scan_snmp_add_device(sec,response,snmp_device_table[index].mib);
snmp_free_pdu(response);
(*nut_snmp_free_pdu)(response);
response = NULL;
index++;
@ -207,7 +384,7 @@ static void try_all_oid(void * arg)
static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec)
{
snmp_sess_init(snmp_sess);
(*nut_snmp_sess_init)(snmp_sess);
snmp_sess->peername = sec->peername;
@ -279,16 +456,17 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec)
snmp_sess->securityAuthKeyLen = USM_AUTH_KU_LEN;
/* default to MD5 */
snmp_sess->securityAuthProto = usmHMACMD5AuthProtocol;
snmp_sess->securityAuthProtoLen =sizeof(usmHMACMD5AuthProtocol)/
sizeof(oid);
snmp_sess->securityAuthProto = (*nut_usmHMACMD5AuthProtocol);
snmp_sess->securityAuthProtoLen =
sizeof((*nut_usmHMACMD5AuthProtocol))/
sizeof(oid);
if( sec->authProtocol ) {
if (strcmp(sec->authProtocol, "SHA") == 0) {
snmp_sess->securityAuthProto =
usmHMACSHA1AuthProtocol;
(*nut_usmHMACSHA1AuthProtocol);
snmp_sess->securityAuthProtoLen =
sizeof(usmHMACSHA1AuthProtocol)/
sizeof((*nut_usmHMACSHA1AuthProtocol))/
sizeof(oid);
}
else {
@ -303,7 +481,7 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec)
/* set the authentication key to a MD5/SHA1 hashed version of
* our passphrase (must be at least 8 characters long) */
if (generate_Ku(snmp_sess->securityAuthProto,
if ((*nut_generate_Ku)(snmp_sess->securityAuthProto,
snmp_sess->securityAuthProtoLen,
(u_char *) sec->authPassword,
strlen(sec->authPassword),
@ -321,15 +499,17 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec)
}
/* default to DES */
snmp_sess->securityPrivProto=usmDESPrivProtocol;
snmp_sess->securityPrivProto=(*nut_usmDESPrivProtocol);
snmp_sess->securityPrivProtoLen =
sizeof(usmDESPrivProtocol)/sizeof(oid);
sizeof((*nut_usmDESPrivProtocol))/sizeof(oid);
if( sec->privProtocol ) {
if (strcmp(sec->privProtocol, "AES") == 0) {
snmp_sess->securityPrivProto=usmAESPrivProtocol;
snmp_sess->securityPrivProto=
(*nut_usmAESPrivProtocol);
snmp_sess->securityPrivProtoLen =
sizeof(usmAESPrivProtocol)/sizeof(oid);
sizeof((*nut_usmAESPrivProtocol))/
sizeof(oid);
}
else {
if (strcmp(sec->privProtocol, "DES") != 0) {
@ -344,7 +524,7 @@ static int init_session(struct snmp_session * snmp_sess, nutscan_snmp_t * sec)
/* set the private key to a MD5/SHA hashed version of
* our passphrase (must be at least 8 characters long) */
snmp_sess->securityPrivKeyLen = USM_PRIV_KU_LEN;
if (generate_Ku(snmp_sess->securityAuthProto,
if ((*nut_generate_Ku)(snmp_sess->securityAuthProto,
snmp_sess->securityAuthProtoLen,
(u_char *) sec->privPassword,
strlen(sec->privPassword),
@ -365,7 +545,7 @@ static void * try_SysOID(void * arg)
{
struct snmp_session snmp_sess;
void * handle;
struct snmp_pdu *pdu, *response = NULL;
struct snmp_pdu *pdu, *response = NULL, *resp = NULL;
oid name[MAX_OID_LEN];
size_t name_len = MAX_OID_LEN;
nutscan_snmp_t * sec = (nutscan_snmp_t *)arg;
@ -381,7 +561,7 @@ static void * try_SysOID(void * arg)
snmp_sess.timeout = g_usec_timeout;
/* Open the session */
handle = snmp_sess_open(&snmp_sess); /* establish the session */
handle = (*nut_snmp_sess_open)(&snmp_sess); /* establish the session */
if (handle == NULL) {
fprintf(stderr,"Failed to open SNMP session for %s.\n",
sec->peername);
@ -389,24 +569,24 @@ static void * try_SysOID(void * arg)
}
/* create and send request. */
if (!snmp_parse_oid(SysOID, name, &name_len)) {
if (!(*nut_snmp_parse_oid)(SysOID, name, &name_len)) {
fprintf(stderr,"SNMP errors: %s\n",
snmp_api_errstring(snmp_errno));
snmp_sess_close(handle);
(*nut_snmp_api_errstring)((*nut_snmp_errno)));
(*nut_snmp_sess_close)(handle);
goto try_SysOID_free;
}
pdu = snmp_pdu_create(SNMP_MSG_GET);
pdu = (*nut_snmp_pdu_create)(SNMP_MSG_GET);
if (pdu == NULL) {
fprintf(stderr,"Not enough memory\n");
snmp_sess_close(handle);
(*nut_snmp_sess_close)(handle);
goto try_SysOID_free;
}
snmp_add_null_var(pdu, name, name_len);
(*nut_snmp_add_null_var)(pdu, name, name_len);
snmp_sess_synch_response(handle,
(*nut_snmp_sess_synch_response)(handle,
pdu, &response);
if (response) {
@ -424,25 +604,27 @@ static void * try_SysOID(void * arg)
continue;
}
name_len = MAX_OID_LEN;
if (!snmp_parse_oid(
if (!(*nut_snmp_parse_oid)(
snmp_device_table[index].sysoid,
name, &name_len)) {
index++;
continue;
}
if ( snmp_oid_compare(
if ( (*nut_snmp_oid_compare)(
response->variables->val.objid,
response->variables->val_len/sizeof(oid),
name, name_len) == 0 ) {
/* we have found a relevent sysoid */
snmp_free_pdu(response);
response = scan_snmp_get_manufacturer(
resp = scan_snmp_get_manufacturer(
snmp_device_table[index].oid,
handle);
scan_snmp_add_device(sec,response,
snmp_device_table[index].mib);
sysoid_found = 1;
if( resp != NULL ) {
scan_snmp_add_device(sec,resp,
snmp_device_table[index].mib);
sysoid_found = 1;
(*nut_snmp_free_pdu)(resp);
}
}
index++;
}
@ -453,11 +635,11 @@ static void * try_SysOID(void * arg)
try_all_oid(sec);
}
snmp_free_pdu(response);
(*nut_snmp_free_pdu)(response);
response = NULL;
}
snmp_sess_close(handle);
(*nut_snmp_sess_close)(handle);
try_SysOID_free:
if( sec->peername ) {
@ -478,12 +660,18 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip
pthread_t thread;
pthread_mutex_init(&dev_mutex,NULL);
pthread_mutex_init(&lib_mutex,NULL);
#endif
if( !nutscan_avail_snmp ) {
return NULL;
}
g_usec_timeout = usec_timeout;
/* Initialize the SNMP library */
init_snmp("nut-scanner");
(*nut_init_snmp)("nut-scanner");
ip_str = nutscan_ip_iter_init(&ip, start_ip, stop_ip);
@ -515,6 +703,11 @@ nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip
return dev_ret;
}
#endif /* HAVE_NET_SNMP_NET_SNMP_CONFIG_H */
#else /* WITH_SNMP */
nutscan_device_t * nutscan_scan_snmp(const char * start_ip, const char * stop_ip,long usec_timeout, nutscan_snmp_t * sec)
{
return NULL;
}
#endif /* WITH_SNMP */