📄 dlmod.c
字号:
/* * Dynamic Loadable Agent Modules MIB (UCD-DLMOD-MIB) - dlmod.c * */#include <config.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#include <stdio.h>#if HAVE_STRING_H#include <string.h>#else#include <strings.h>#endif#if HAVE_UNISTD_H#include <unistd.h>#endif#include <ctype.h>#if HAVE_WINSOCK_H#include <winsock.h>#endif#include "mibincl.h"#include "struct.h"#include "read_config.h"#include "agent_read_config.h"#include "util_funcs.h"#include "snmp_debug.h"#if defined(HAVE_DLFCN_H) && defined(HAVE_DLOPEN)#include <dlfcn.h>#include "dlmod.h"static struct dlmod *dlmods = NULL;static int dlmod_next_index = 1;static char dlmod_path[1024];static void dlmod_parse_config(const char *, char *);static void dlmod_free_config(void);/* * this variable defines function callbacks and type return * information for the dlmod mib */static struct variable4 dlmod_variables[] = { {DLMODNEXTINDEX, ASN_INTEGER, RONLY, var_dlmod, 1, {1}}, {DLMODNAME, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 2}}, {DLMODPATH, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 3}}, {DLMODERROR, ASN_OCTET_STR, RONLY, var_dlmodEntry, 3, {2, 1, 4}}, {DLMODSTATUS, ASN_INTEGER, RWRITE, var_dlmodEntry, 3, {2, 1, 5}},};static oid dlmod_variables_oid[] = {1, 3, 6, 1, 4, 1, 2021, 13, 14};static int dlmod_variables_oid_len = 9;void init_dlmod (void) { char *p; int l; 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"); p = getenv("SNMPDLMODPATH"); strncpy(dlmod_path, SNMPDLMODPATH, sizeof(dlmod_path)); if (p) { if (p[0] == ':') { l = strlen(dlmod_path); if (dlmod_path[l - 1] != ':') strncat(dlmod_path, ":", sizeof(dlmod_path) - l); strncat(dlmod_path, p + 1, sizeof(dlmod_path) - strlen(dlmod_path)); } else strncpy(dlmod_path, p, sizeof(dlmod_path)); } DEBUGMSGTL(("dlmod", "dlmod_path: %s\n", dlmod_path));}void deinit_dlmod (void){ unregister_mib(dlmod_variables_oid, dlmod_variables_oid_len); snmpd_unregister_config_handler("dlmod");}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;}voiddlmod_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); return; }}voiddlmod_load_module(struct dlmod *dlm){ char sym_init[64]; char *p, tmp_path[255]; int (*dl_init)(void); 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; if (dlm->path[0] == '/') { #ifdef RTLD_NOW dlm->handle = dlopen(dlm->path, RTLD_NOW);#else dlm->handle = dlopen(dlm->path, RTLD_LAZY);#endif if (dlm->handle == NULL) { snprintf(dlm->error, sizeof(dlm->error), "dlopen failed: %s", dlerror()); dlm->status = DLMOD_ERROR; return; } } else { for (p = strtok(dlmod_path, ":"); p; p = strtok(NULL, ":")) { snprintf(tmp_path, sizeof(tmp_path), "%s/%s.so", p, dlm->path); DEBUGMSGTL(("dlmod", "p: %s tmp_path: %s\n", p, tmp_path));#ifdef RTLD_NOW dlm->handle = dlopen(tmp_path, RTLD_NOW);#else dlm->handle = dlopen(tmp_path, RTLD_LAZY);#endif if (dlm->handle == NULL) { snprintf(dlm->error, sizeof(dlm->error), "dlopen failed: %s", dlerror()); dlm->status = DLMOD_ERROR; } } strncpy(dlm->path, tmp_path, sizeof(dlm->path)); if (dlm->status == DLMOD_ERROR) return; } snprintf(sym_init, sizeof(sym_init), "init_%s", dlm->name); dl_init = dlsym(dlm->handle, sym_init); if (dl_init == NULL) { dlclose(dlm->handle); snprintf(dlm->error, sizeof(dlm->error), "dlsym failed: can't find \'%s\'", sym_init); dlm->status = DLMOD_ERROR; return; } dl_init(); dlm->error[0] = '\0'; dlm->status = DLMOD_LOADED;}void dlmod_unload_module (struct dlmod *dlm){ char sym_deinit[64]; int (* dl_deinit)(void); if (!dlm || dlm->status != DLMOD_LOADED) return; snprintf(sym_deinit, sizeof(sym_deinit), "deinit_%s", dlm->name); dl_deinit = dlsym(dlm->handle, sym_deinit); if (dl_deinit == NULL) { snprintf(dlm->error, sizeof(dlm->error), "dlsym failed: can't find \'%s\'", sym_deinit); } else { dl_deinit(); } dlclose(dlm->handle); dlm->status = DLMOD_UNLOADED; DEBUGMSGTL(("dlmod", "Module %s unloaded\n", dlm->name));}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;}static void dlmod_parse_config(const char *token, char *cptr){ char *dlm_name, *dlm_path; struct dlmod *dlm; 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(cptr, "\t "); if (dlm_name == NULL) { config_perror("Bad dlmod line"); dlmod_delete_module(dlm); return; } strncpy(dlm->name, dlm_name, sizeof(dlm->name)); /* dynamic module path */ dlm_path = strtok(NULL, "\t "); if (dlm_path) strncpy(dlm->path, dlm_path, sizeof(dlm->path)); else strncpy(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); } dlmods = NULL;}/* 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 intheader_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((char *)newname, (char *)vp->name, (int) vp->namelen * sizeof(oid)); newname[DLMOD_NAME_LENGTH] = 0; result = snmp_oid_compare(name, *length, newname, (int)vp->namelen + 1); if ((exact && (result != 0)) || (!exact && (result >= 0))) { return MATCH_FAILED; } memcpy((char *)name, (char *)newname, ((int)vp->namelen + 1) * sizeof(oid)); *length = vp->namelen + 1; *write_method = 0; *var_len = sizeof(long); /* default to 'long' results */ return MATCH_SUCCEEDED;}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 = 0; /* assume it isnt 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 0; /* 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 0;}/* 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 = 0; int dlmod_index; memcpy((char *)newname, (char *)vp->name, (int)vp->namelen * sizeof(oid)); *write_method = 0; for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++) { dlm = dlmod_get_by_index(dlmod_index); DEBUGMSGTL(("dlmod", "dlmodEntry dlm: %x dlmod_index: %d\n", (int)dlm, dlmod_index)); if (dlm) { newname[12] = dlmod_index; result = snmp_oid_compare(name, *length, newname, (int)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((char *)name, (char *)newname, ((int)vp->namelen + 1) * sizeof(oid)); *length = vp->namelen + 1; *var_len = sizeof(long); return dlm;}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 0; /* 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 = strlen(dlm->error); 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 0;}intwrite_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)) { snmp_log(LOG_ERR, "write to dlmodName: bad length\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;}intwrite_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)) { snmp_log(LOG_ERR, "write to dlmodPath: bad length\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;}intwrite_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;}#else /* no dlopen support */void init_dlmod (void){ DEBUGMSGTL(("dlmod","Dynamic modules not support on this platform\n"));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -