Blame agent/mibgroup/ucd-snmp/dlmod.c

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