712 lines
19 KiB
C
712 lines
19 KiB
C
|
/*
|
||
|
* Dynamic Loadable Agent Modules MIB (UCD-DLMOD-MIB) - dlmod.c
|
||
|
*
|
||
|
*/
|
||
|
#include <net-snmp/net-snmp-config.h>
|
||
|
#include <net-snmp/net-snmp-features.h>
|
||
|
|
||
|
#include <ctype.h>
|
||
|
#if HAVE_STDLIB_H
|
||
|
#include <stdlib.h>
|
||
|
#endif
|
||
|
#include <stdio.h>
|
||
|
#if HAVE_STRING_H
|
||
|
#include <string.h>
|
||
|
#else
|
||
|
#include <strings.h>
|
||
|
#endif
|
||
|
|
||
|
#include <net-snmp/net-snmp-includes.h>
|
||
|
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
||
|
|
||
|
#if defined(WIN32)
|
||
|
#include <windows.h>
|
||
|
#else
|
||
|
#include <dlfcn.h>
|
||
|
#endif
|
||
|
#include "dlmod.h"
|
||
|
|
||
|
#ifndef SNMPDLMODPATH
|
||
|
#define SNMPDLMODPATH "/usr/local/lib/snmp/dlmod"
|
||
|
#endif
|
||
|
|
||
|
struct dlmod {
|
||
|
struct dlmod *next;
|
||
|
int index;
|
||
|
char name[64 + 1];
|
||
|
char path[255 + 1];
|
||
|
char *error;
|
||
|
void *handle;
|
||
|
int status;
|
||
|
};
|
||
|
|
||
|
#define DLMOD_LOADED 1
|
||
|
#define DLMOD_UNLOADED 2
|
||
|
#define DLMOD_ERROR 3
|
||
|
#define DLMOD_LOAD 4
|
||
|
#define DLMOD_UNLOAD 5
|
||
|
#define DLMOD_CREATE 6
|
||
|
#define DLMOD_DELETE 7
|
||
|
|
||
|
static struct dlmod *dlmods;
|
||
|
static unsigned int dlmod_next_index = 1;
|
||
|
static char dlmod_path[1024];
|
||
|
|
||
|
static struct dlmod *
|
||
|
dlmod_create_module(void)
|
||
|
{
|
||
|
struct dlmod **pdlmod, *dlm;
|
||
|
|
||
|
DEBUGMSGTL(("dlmod", "dlmod_create_module\n"));
|
||
|
dlm = calloc(1, sizeof(struct dlmod));
|
||
|
if (dlm == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
dlm->index = dlmod_next_index++;
|
||
|
dlm->status = DLMOD_UNLOADED;
|
||
|
|
||
|
for (pdlmod = &dlmods; *pdlmod != NULL; pdlmod = &((*pdlmod)->next))
|
||
|
;
|
||
|
*pdlmod = dlm;
|
||
|
|
||
|
return dlm;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dlmod_delete_module(struct dlmod *dlm)
|
||
|
{
|
||
|
struct dlmod **pdlmod;
|
||
|
|
||
|
DEBUGMSGTL(("dlmod", "dlmod_delete_module\n"));
|
||
|
if (!dlm || dlm->status != DLMOD_UNLOADED)
|
||
|
return;
|
||
|
|
||
|
for (pdlmod = &dlmods; *pdlmod; pdlmod = &((*pdlmod)->next))
|
||
|
if (*pdlmod == dlm) {
|
||
|
*pdlmod = dlm->next;
|
||
|
free(dlm->error);
|
||
|
free(dlm);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if defined(WIN32)
|
||
|
/*
|
||
|
* See also Microsoft, "Overview of x64 Calling Conventions", MSDN
|
||
|
* (http://msdn.microsoft.com/en-us/library/ms235286.aspx).
|
||
|
*/
|
||
|
#ifdef _M_X64
|
||
|
typedef int (*dl_function_ptr)(void);
|
||
|
#else
|
||
|
typedef int (__stdcall *dl_function_ptr)(void);
|
||
|
#endif
|
||
|
#else
|
||
|
typedef int (*dl_function_ptr)(void);
|
||
|
#endif
|
||
|
|
||
|
#if defined(WIN32)
|
||
|
static const char dlmod_dl_suffix[] = "dll";
|
||
|
#else
|
||
|
static const char dlmod_dl_suffix[] = "so";
|
||
|
#endif
|
||
|
|
||
|
static void* dlmod_dlopen(const char *path)
|
||
|
{
|
||
|
#if defined(WIN32)
|
||
|
return LoadLibrary(path);
|
||
|
#elif defined(RTLD_NOW)
|
||
|
return dlopen(path, RTLD_NOW);
|
||
|
#else
|
||
|
return dlopen(path, RTLD_LAZY);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void dlmod_dlclose(void *handle)
|
||
|
{
|
||
|
#if defined(WIN32)
|
||
|
FreeLibrary(handle);
|
||
|
#else
|
||
|
dlclose(handle);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void *dlmod_dlsym(void *handle, const char *symbol)
|
||
|
{
|
||
|
#if defined(WIN32)
|
||
|
return GetProcAddress(handle, symbol);
|
||
|
#else
|
||
|
return dlsym(handle, symbol);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static const char *dlmod_dlerror(void)
|
||
|
{
|
||
|
#if defined(WIN32)
|
||
|
static char errstr[256];
|
||
|
const DWORD dwErrorcode = GetLastError();
|
||
|
LPTSTR lpMsgBuf;
|
||
|
|
||
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||
|
NULL, dwErrorcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||
|
(LPTSTR) &lpMsgBuf, 0, NULL);
|
||
|
if (lpMsgBuf) {
|
||
|
LPTSTR p;
|
||
|
|
||
|
/*
|
||
|
* Remove trailing "\r\n".
|
||
|
*/
|
||
|
p = strchr(lpMsgBuf, '\r');
|
||
|
if (p)
|
||
|
*p = '\0';
|
||
|
snprintf(errstr, sizeof(errstr), "%s", lpMsgBuf);
|
||
|
LocalFree(lpMsgBuf);
|
||
|
} else {
|
||
|
snprintf(errstr, sizeof(errstr), "error code %ld", dwErrorcode);
|
||
|
}
|
||
|
return errstr;
|
||
|
#else
|
||
|
return dlerror();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static int dlmod_is_abs_path(const char *path)
|
||
|
{
|
||
|
#if defined(WIN32)
|
||
|
return (strncmp(path, "//", 2) == 0 || strncmp(path, "\\\\", 2) == 0) ||
|
||
|
(isalpha((u_char)path[0]) && path[1] == ':' &&
|
||
|
(path[2] == '/' || path[2] == '\\'));
|
||
|
#else
|
||
|
return path[0] == '/';
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dlmod_load_module(struct dlmod *dlm)
|
||
|
{
|
||
|
DEBUGMSGTL(("dlmod", "dlmod_load_module %s: %s\n", dlm->name,
|
||
|
dlm->path));
|
||
|
|
||
|
if (!dlm || !dlm->path || !dlm->name ||
|
||
|
(dlm->status != DLMOD_UNLOADED && dlm->status != DLMOD_ERROR))
|
||
|
return;
|
||
|
|
||
|
free(dlm->error);
|
||
|
dlm->error = NULL;
|
||
|
|
||
|
if (dlmod_is_abs_path(dlm->path)) {
|
||
|
dlm->handle = dlmod_dlopen(dlm->path);
|
||
|
if (dlm->handle == NULL) {
|
||
|
if (asprintf(&dlm->error, "dlopen(%s) failed: %s", dlm->path,
|
||
|
dlmod_dlerror()) < 0)
|
||
|
dlm->error = NULL;
|
||
|
dlm->status = DLMOD_ERROR;
|
||
|
return;
|
||
|
}
|
||
|
} else {
|
||
|
char *st, *p, *tmp_path = NULL;
|
||
|
|
||
|
for (p = strtok_r(dlmod_path, ENV_SEPARATOR, &st); p;
|
||
|
p = strtok_r(NULL, ENV_SEPARATOR, &st)) {
|
||
|
free(tmp_path);
|
||
|
if (asprintf(&tmp_path, "%s/%s.%s", p, dlm->path, dlmod_dl_suffix)
|
||
|
< 0) {
|
||
|
dlm->status = DLMOD_ERROR;
|
||
|
return;
|
||
|
}
|
||
|
DEBUGMSGTL(("dlmod", "p: %s tmp_path: %s\n", p, tmp_path));
|
||
|
dlm->handle = tmp_path ? dlmod_dlopen(tmp_path) : NULL;
|
||
|
if (dlm->handle == NULL) {
|
||
|
free(dlm->error);
|
||
|
if (asprintf(&dlm->error, "dlopen(%s) failed: %s", tmp_path,
|
||
|
dlmod_dlerror()) < 0)
|
||
|
dlm->error = NULL;
|
||
|
dlm->status = DLMOD_ERROR;
|
||
|
}
|
||
|
}
|
||
|
strlcpy(dlm->path, tmp_path, sizeof(dlm->path));
|
||
|
free(tmp_path);
|
||
|
if (dlm->status == DLMOD_ERROR)
|
||
|
return;
|
||
|
}
|
||
|
{
|
||
|
char sym_init[64 + sizeof("init_")];
|
||
|
dl_function_ptr dl_init;
|
||
|
|
||
|
snprintf(sym_init, sizeof(sym_init), "init_%s", dlm->name);
|
||
|
dl_init = dlmod_dlsym(dlm->handle, sym_init);
|
||
|
if (dl_init == NULL) {
|
||
|
dlmod_dlclose(dlm->handle);
|
||
|
free(dlm->error);
|
||
|
if (asprintf(&dlm->error, "dlsym failed: can't find \'%s\'",
|
||
|
sym_init) < 0)
|
||
|
dlm->error = NULL;
|
||
|
dlm->status = DLMOD_ERROR;
|
||
|
return;
|
||
|
}
|
||
|
dl_init();
|
||
|
}
|
||
|
|
||
|
dlm->error = NULL;
|
||
|
dlm->status = DLMOD_LOADED;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dlmod_unload_module(struct dlmod *dlm)
|
||
|
{
|
||
|
char sym_deinit[64 + sizeof("shutdown_")];
|
||
|
dl_function_ptr dl_deinit;
|
||
|
|
||
|
if (!dlm || dlm->status != DLMOD_LOADED)
|
||
|
return;
|
||
|
|
||
|
snprintf(sym_deinit, sizeof(sym_deinit), "deinit_%s", dlm->name);
|
||
|
dl_deinit = dlmod_dlsym(dlm->handle, sym_deinit);
|
||
|
if (!dl_deinit) {
|
||
|
snprintf(sym_deinit, sizeof(sym_deinit), "shutdown_%s", dlm->name);
|
||
|
dl_deinit = dlmod_dlsym(dlm->handle, sym_deinit);
|
||
|
}
|
||
|
if (dl_deinit) {
|
||
|
DEBUGMSGTL(("dlmod", "Calling %s()\n", sym_deinit));
|
||
|
dl_deinit();
|
||
|
} else {
|
||
|
DEBUGMSGTL(("dlmod", "No destructor for %s\n", dlm->name));
|
||
|
}
|
||
|
dlmod_dlclose(dlm->handle);
|
||
|
dlm->status = DLMOD_UNLOADED;
|
||
|
DEBUGMSGTL(("dlmod", "Module %s unloaded\n", dlm->name));
|
||
|
}
|
||
|
|
||
|
static struct dlmod *
|
||
|
dlmod_get_by_index(int iindex)
|
||
|
{
|
||
|
struct dlmod *dlmod;
|
||
|
|
||
|
for (dlmod = dlmods; dlmod; dlmod = dlmod->next)
|
||
|
if (dlmod->index == iindex)
|
||
|
return dlmod;
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Functions to parse config lines
|
||
|
*/
|
||
|
|
||
|
static void
|
||
|
dlmod_parse_config(const char *token, char *cptr)
|
||
|
{
|
||
|
char *dlm_name, *dlm_path;
|
||
|
struct dlmod *dlm;
|
||
|
char *st;
|
||
|
|
||
|
if (cptr == NULL) {
|
||
|
config_perror("Bad dlmod line");
|
||
|
return;
|
||
|
}
|
||
|
/*
|
||
|
* remove comments
|
||
|
*/
|
||
|
*(cptr + strcspn(cptr, "#;\r\n")) = '\0';
|
||
|
|
||
|
dlm = dlmod_create_module();
|
||
|
if (!dlm)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
* dynamic module name
|
||
|
*/
|
||
|
dlm_name = strtok_r(cptr, "\t ", &st);
|
||
|
if (dlm_name == NULL) {
|
||
|
config_perror("Bad dlmod line");
|
||
|
dlmod_delete_module(dlm);
|
||
|
return;
|
||
|
}
|
||
|
strlcpy(dlm->name, dlm_name, sizeof(dlm->name));
|
||
|
|
||
|
/*
|
||
|
* dynamic module path
|
||
|
*/
|
||
|
dlm_path = strtok_r(NULL, "\t ", &st);
|
||
|
if (dlm_path)
|
||
|
strlcpy(dlm->path, dlm_path, sizeof(dlm->path));
|
||
|
else
|
||
|
strlcpy(dlm->path, dlm_name, sizeof(dlm->path));
|
||
|
|
||
|
dlmod_load_module(dlm);
|
||
|
|
||
|
if (dlm->status == DLMOD_ERROR)
|
||
|
snmp_log(LOG_ERR, "%s\n", dlm->error);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dlmod_free_config(void)
|
||
|
{
|
||
|
struct dlmod *dtmp, *dtmp2;
|
||
|
|
||
|
for (dtmp = dlmods; dtmp != NULL;) {
|
||
|
dtmp2 = dtmp;
|
||
|
dtmp = dtmp->next;
|
||
|
dlmod_unload_module(dtmp2);
|
||
|
free(dtmp2->error);
|
||
|
free(dtmp2);
|
||
|
}
|
||
|
dlmods = NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Functions to handle SNMP management
|
||
|
*/
|
||
|
|
||
|
#define DLMODNEXTINDEX 1
|
||
|
#define DLMODINDEX 2
|
||
|
#define DLMODNAME 3
|
||
|
#define DLMODPATH 4
|
||
|
#define DLMODERROR 5
|
||
|
#define DLMODSTATUS 6
|
||
|
|
||
|
/*
|
||
|
* header_dlmod(...
|
||
|
* Arguments:
|
||
|
* vp IN - pointer to variable entry that points here
|
||
|
* name IN/OUT - IN/name requested, OUT/name found
|
||
|
* length IN/OUT - length of IN/OUT oid's
|
||
|
* exact IN - TRUE if an exact match was requested
|
||
|
* var_len OUT - length of variable or 0 if function returned
|
||
|
* write_method
|
||
|
*/
|
||
|
|
||
|
static int
|
||
|
header_dlmod(struct variable *vp,
|
||
|
oid * name,
|
||
|
size_t * length,
|
||
|
int exact, size_t * var_len, WriteMethod ** write_method)
|
||
|
{
|
||
|
#define DLMOD_NAME_LENGTH 10
|
||
|
oid newname[MAX_OID_LEN];
|
||
|
int result;
|
||
|
|
||
|
memcpy(newname, vp->name, vp->namelen * sizeof(oid));
|
||
|
newname[DLMOD_NAME_LENGTH] = 0;
|
||
|
|
||
|
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
|
||
|
if ((exact && (result != 0)) || (!exact && (result >= 0))) {
|
||
|
return MATCH_FAILED;
|
||
|
}
|
||
|
|
||
|
memcpy(name, newname, (vp->namelen + 1) * sizeof(oid));
|
||
|
*length = vp->namelen + 1;
|
||
|
*write_method = NULL;
|
||
|
*var_len = sizeof(long); /* default to 'long' results */
|
||
|
return MATCH_SUCCEEDED;
|
||
|
}
|
||
|
|
||
|
|
||
|
static u_char *
|
||
|
var_dlmod(struct variable * vp,
|
||
|
oid * name,
|
||
|
size_t * length,
|
||
|
int exact, size_t * var_len, WriteMethod ** write_method)
|
||
|
{
|
||
|
|
||
|
/*
|
||
|
* variables we may use later
|
||
|
*/
|
||
|
|
||
|
*write_method = NULL; /* assume it isn't writable for the time being */
|
||
|
*var_len = sizeof(int); /* assume an integer and change later if not */
|
||
|
|
||
|
if (header_dlmod(vp, name, length, exact,
|
||
|
var_len, write_method) == MATCH_FAILED)
|
||
|
return NULL;
|
||
|
|
||
|
/*
|
||
|
* this is where we do the value assignments for the mib results.
|
||
|
*/
|
||
|
switch (vp->magic) {
|
||
|
case DLMODNEXTINDEX:
|
||
|
long_return = dlmod_next_index;
|
||
|
return (unsigned char *) &long_return;
|
||
|
default:
|
||
|
DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmod\n",
|
||
|
vp->magic));
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int
|
||
|
write_dlmodName(int action,
|
||
|
u_char * var_val,
|
||
|
u_char var_val_type,
|
||
|
size_t var_val_len,
|
||
|
u_char * statP, oid * name, size_t name_len)
|
||
|
{
|
||
|
static struct dlmod *dlm;
|
||
|
|
||
|
if (var_val_type != ASN_OCTET_STR) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodName not ASN_OCTET_STR\n");
|
||
|
return SNMP_ERR_WRONGTYPE;
|
||
|
}
|
||
|
if (var_val_len > sizeof(dlm->name)-1) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodName: bad length: too long\n");
|
||
|
return SNMP_ERR_WRONGLENGTH;
|
||
|
}
|
||
|
if (action == COMMIT) {
|
||
|
dlm = dlmod_get_by_index(name[12]);
|
||
|
if (!dlm || dlm->status == DLMOD_LOADED)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
strncpy(dlm->name, (const char *) var_val, var_val_len);
|
||
|
dlm->name[var_val_len] = 0;
|
||
|
}
|
||
|
return SNMP_ERR_NOERROR;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
write_dlmodPath(int action,
|
||
|
u_char * var_val,
|
||
|
u_char var_val_type,
|
||
|
size_t var_val_len,
|
||
|
u_char * statP, oid * name, size_t name_len)
|
||
|
{
|
||
|
static struct dlmod *dlm;
|
||
|
|
||
|
if (var_val_type != ASN_OCTET_STR) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodPath not ASN_OCTET_STR\n");
|
||
|
return SNMP_ERR_WRONGTYPE;
|
||
|
}
|
||
|
if (var_val_len > sizeof(dlm->path)-1) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodPath: bad length: too long\n");
|
||
|
return SNMP_ERR_WRONGLENGTH;
|
||
|
}
|
||
|
if (action == COMMIT) {
|
||
|
dlm = dlmod_get_by_index(name[12]);
|
||
|
if (!dlm || dlm->status == DLMOD_LOADED)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
strncpy(dlm->path, (const char *) var_val, var_val_len);
|
||
|
dlm->path[var_val_len] = 0;
|
||
|
}
|
||
|
return SNMP_ERR_NOERROR;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
write_dlmodStatus(int action,
|
||
|
u_char * var_val,
|
||
|
u_char var_val_type,
|
||
|
size_t var_val_len,
|
||
|
u_char * statP, oid * name, size_t name_len)
|
||
|
{
|
||
|
/*
|
||
|
* variables we may use later
|
||
|
*/
|
||
|
struct dlmod *dlm;
|
||
|
|
||
|
if (var_val_type != ASN_INTEGER) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodStatus not ASN_INTEGER\n");
|
||
|
return SNMP_ERR_WRONGTYPE;
|
||
|
}
|
||
|
if (var_val_len > sizeof(long)) {
|
||
|
snmp_log(LOG_ERR, "write to dlmodStatus: bad length\n");
|
||
|
return SNMP_ERR_WRONGLENGTH;
|
||
|
}
|
||
|
if (action == COMMIT) {
|
||
|
/*
|
||
|
* object identifier in form .1.3.6.1.4.1.2021.13.14.2.1.4.x
|
||
|
* where X is index with offset 12
|
||
|
*/
|
||
|
|
||
|
dlm = dlmod_get_by_index(name[12]);
|
||
|
switch (*((long *) var_val)) {
|
||
|
case DLMOD_CREATE:
|
||
|
if (dlm || (name[12] != dlmod_next_index))
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
dlm = dlmod_create_module();
|
||
|
if (!dlm)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
break;
|
||
|
case DLMOD_LOAD:
|
||
|
if (!dlm || dlm->status == DLMOD_LOADED)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
dlmod_load_module(dlm);
|
||
|
break;
|
||
|
case DLMOD_UNLOAD:
|
||
|
if (!dlm || dlm->status != DLMOD_LOADED)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
dlmod_unload_module(dlm);
|
||
|
break;
|
||
|
case DLMOD_DELETE:
|
||
|
if (!dlm || dlm->status == DLMOD_LOADED)
|
||
|
return SNMP_ERR_RESOURCEUNAVAILABLE;
|
||
|
dlmod_delete_module(dlm);
|
||
|
break;
|
||
|
default:
|
||
|
return SNMP_ERR_WRONGVALUE;
|
||
|
}
|
||
|
}
|
||
|
return SNMP_ERR_NOERROR;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* header_dlmodEntry(...
|
||
|
* Arguments:
|
||
|
* vp IN - pointer to variable entry that points here
|
||
|
* name IN/OUT - IN/name requested, OUT/name found
|
||
|
* length IN/OUT - length of IN/OUT oid's
|
||
|
* exact IN - TRUE if an exact match was requested
|
||
|
* var_len OUT - length of variable or 0 if function returned
|
||
|
* write_method
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
|
||
|
static struct dlmod *
|
||
|
header_dlmodEntry(struct variable *vp,
|
||
|
oid * name,
|
||
|
size_t * length,
|
||
|
int exact, size_t * var_len, WriteMethod ** write_method)
|
||
|
{
|
||
|
#define DLMODENTRY_NAME_LENGTH 12
|
||
|
oid newname[MAX_OID_LEN];
|
||
|
int result;
|
||
|
struct dlmod *dlm = NULL;
|
||
|
unsigned int dlmod_index;
|
||
|
|
||
|
memcpy(newname, vp->name, vp->namelen * sizeof(oid));
|
||
|
*write_method = NULL;
|
||
|
|
||
|
for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++) {
|
||
|
dlm = dlmod_get_by_index(dlmod_index);
|
||
|
|
||
|
DEBUGMSGTL(("dlmod", "dlmodEntry dlm: %p dlmod_index: %d\n",
|
||
|
dlm, dlmod_index));
|
||
|
|
||
|
if (dlm) {
|
||
|
newname[12] = dlmod_index;
|
||
|
result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
|
||
|
|
||
|
if ((exact && (result == 0)) || (!exact && (result < 0)))
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dlmod_index >= dlmod_next_index) {
|
||
|
if (dlmod_index == dlmod_next_index &&
|
||
|
exact && vp->magic == DLMODSTATUS)
|
||
|
|
||
|
*write_method = write_dlmodStatus;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
memcpy(name, newname, (vp->namelen + 1) * sizeof(oid));
|
||
|
*length = vp->namelen + 1;
|
||
|
*var_len = sizeof(long);
|
||
|
return dlm;
|
||
|
}
|
||
|
|
||
|
static u_char *
|
||
|
var_dlmodEntry(struct variable * vp,
|
||
|
oid * name,
|
||
|
size_t * length,
|
||
|
int exact, size_t * var_len, WriteMethod ** write_method)
|
||
|
{
|
||
|
/*
|
||
|
* variables we may use later
|
||
|
*/
|
||
|
struct dlmod *dlm;
|
||
|
|
||
|
*var_len = sizeof(int); /* assume an integer and change later
|
||
|
* if not */
|
||
|
|
||
|
dlm = header_dlmodEntry(vp, name, length, exact, var_len, write_method);
|
||
|
if (dlm == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
/*
|
||
|
* this is where we do the value assignments for the mib results.
|
||
|
*/
|
||
|
switch (vp->magic) {
|
||
|
case DLMODNAME:
|
||
|
*write_method = write_dlmodName;
|
||
|
*var_len = strlen(dlm->name);
|
||
|
return (unsigned char *) dlm->name;
|
||
|
case DLMODPATH:
|
||
|
*write_method = write_dlmodPath;
|
||
|
*var_len = strlen(dlm->path);
|
||
|
return (unsigned char *) dlm->path;
|
||
|
case DLMODERROR:
|
||
|
*var_len = dlm->error ? strlen(dlm->error) : 0;
|
||
|
return (unsigned char *) dlm->error;
|
||
|
case DLMODSTATUS:
|
||
|
*write_method = write_dlmodStatus;
|
||
|
long_return = dlm->status;
|
||
|
return (unsigned char *) &long_return;
|
||
|
default:
|
||
|
DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmodEntry\n",
|
||
|
vp->magic));
|
||
|
}
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* this variable defines function callbacks and type return
|
||
|
* information for the dlmod mib
|
||
|
*/
|
||
|
static struct variable4 dlmod_variables[] = {
|
||
|
{DLMODNEXTINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY,
|
||
|
var_dlmod, 1, {1}},
|
||
|
{DLMODNAME, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
|
||
|
var_dlmodEntry, 3, {2, 1, 2}},
|
||
|
{DLMODPATH, ASN_OCTET_STR, NETSNMP_OLDAPI_RWRITE,
|
||
|
var_dlmodEntry, 3, {2, 1, 3}},
|
||
|
{DLMODERROR, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY,
|
||
|
var_dlmodEntry, 3, {2, 1, 4}},
|
||
|
{DLMODSTATUS, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE,
|
||
|
var_dlmodEntry, 3, {2, 1, 5}},
|
||
|
};
|
||
|
|
||
|
static oid dlmod_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 14 };
|
||
|
|
||
|
void
|
||
|
init_dlmod(void)
|
||
|
{
|
||
|
REGISTER_MIB("dlmod", dlmod_variables, variable4, dlmod_variables_oid);
|
||
|
|
||
|
/*
|
||
|
* TODO: REGISTER_SYSOR_ENTRY
|
||
|
*/
|
||
|
|
||
|
DEBUGMSGTL(("dlmod", "register mib\n"));
|
||
|
|
||
|
snmpd_register_config_handler("dlmod", dlmod_parse_config,
|
||
|
dlmod_free_config,
|
||
|
"module-name module-path");
|
||
|
|
||
|
{
|
||
|
const char * const p = getenv("SNMPDLMODPATH");
|
||
|
strncpy(dlmod_path, SNMPDLMODPATH, sizeof(dlmod_path));
|
||
|
dlmod_path[ sizeof(dlmod_path) - 1 ] = 0;
|
||
|
if (p) {
|
||
|
if (p[0] == ':') {
|
||
|
int len = strlen(dlmod_path);
|
||
|
if (dlmod_path[len - 1] != ':') {
|
||
|
strncat(dlmod_path, ":", sizeof(dlmod_path) - len - 1);
|
||
|
len++;
|
||
|
}
|
||
|
strncat(dlmod_path, p + 1, sizeof(dlmod_path) - len);
|
||
|
} else
|
||
|
strncpy(dlmod_path, p, sizeof(dlmod_path));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
|
||
|
DEBUGMSGTL(("dlmod", "dlmod_path: %s\n", dlmod_path));
|
||
|
}
|
||
|
|
||
|
netsnmp_feature_require(snmpd_unregister_config_handler)
|
||
|
|
||
|
void
|
||
|
shutdown_dlmod(void)
|
||
|
{
|
||
|
snmpd_unregister_config_handler("dlmod");
|
||
|
unregister_mib(dlmod_variables_oid, OID_LENGTH(dlmod_variables_oid));
|
||
|
}
|