2
* Dynamic Loadable Agent Modules MIB (UCD-DLMOD-MIB) - dlmod.c
5
#include <net-snmp/net-snmp-config.h>
25
#include <net-snmp/net-snmp-includes.h>
26
#include <net-snmp/agent/net-snmp-agent-includes.h>
29
#include "util_funcs.h"
31
#if defined(HAVE_DLFCN_H) && ( defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) )
36
static struct dlmod *dlmods = NULL;
37
static int dlmod_next_index = 1;
38
static char dlmod_path[1024];
40
static void dlmod_parse_config(const char *, char *);
41
static void dlmod_free_config(void);
44
* this variable defines function callbacks and type return
45
* information for the dlmod mib
47
static struct variable4 dlmod_variables[] = {
48
{DLMODNEXTINDEX, ASN_INTEGER, RONLY, var_dlmod, 1, {1}},
49
{DLMODNAME, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 2}},
50
{DLMODPATH, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 3}},
51
{DLMODERROR, ASN_OCTET_STR, RONLY, var_dlmodEntry, 3, {2, 1, 4}},
52
{DLMODSTATUS, ASN_INTEGER, RWRITE, var_dlmodEntry, 3, {2, 1, 5}},
55
static oid dlmod_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 14 };
56
static int dlmod_variables_oid_len = 9;
64
REGISTER_MIB("dlmod", dlmod_variables, variable4, dlmod_variables_oid);
67
* TODO: REGISTER_SYSOR_ENTRY
70
DEBUGMSGTL(("dlmod", "register mib\n"));
72
snmpd_register_config_handler("dlmod", dlmod_parse_config,
74
"module-name module-path");
76
p = getenv("SNMPDLMODPATH");
77
strncpy(dlmod_path, SNMPDLMODPATH, sizeof(dlmod_path));
78
dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
81
len = strlen(dlmod_path);
82
if (dlmod_path[len - 1] != ':') {
83
strncat(dlmod_path, ":", sizeof(dlmod_path) - len -1);
86
strncat(dlmod_path, p + 1, sizeof(dlmod_path) - len);
88
strncpy(dlmod_path, p, sizeof(dlmod_path));
90
dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
91
DEBUGMSGTL(("dlmod", "dlmod_path: %s\n", dlmod_path));
97
unregister_mib(dlmod_variables_oid, dlmod_variables_oid_len);
98
snmpd_unregister_config_handler("dlmod");
102
dlmod_create_module(void)
104
struct dlmod **pdlmod, *dlm;
106
DEBUGMSGTL(("dlmod", "dlmod_create_module\n"));
107
dlm = (struct dlmod *) calloc(1, sizeof(struct dlmod));
111
dlm->index = dlmod_next_index++;
112
dlm->status = DLMOD_UNLOADED;
114
for (pdlmod = &dlmods; *pdlmod != NULL; pdlmod = &((*pdlmod)->next));
121
dlmod_delete_module(struct dlmod *dlm)
123
struct dlmod **pdlmod;
125
DEBUGMSGTL(("dlmod", "dlmod_delete_module\n"));
126
if (!dlm || dlm->status != DLMOD_UNLOADED)
129
for (pdlmod = &dlmods; *pdlmod; pdlmod = &((*pdlmod)->next))
130
if (*pdlmod == dlm) {
138
dlmod_load_module(struct dlmod *dlm)
141
char *p, tmp_path[255];
142
int (*dl_init) (void);
144
DEBUGMSGTL(("dlmod", "dlmod_load_module %s: %s\n", dlm->name,
147
if (!dlm || !dlm->path || !dlm->name ||
148
(dlm->status != DLMOD_UNLOADED && dlm->status != DLMOD_ERROR))
151
if (dlm->path[0] == '/') {
153
dlm->handle = dlopen(dlm->path, RTLD_NOW);
155
dlm->handle = dlopen(dlm->path, RTLD_LAZY);
157
if (dlm->handle == NULL) {
158
snprintf(dlm->error, sizeof(dlm->error),
159
"dlopen failed: %s", dlerror());
160
dlm->status = DLMOD_ERROR;
164
for (p = strtok(dlmod_path, ":"); p; p = strtok(NULL, ":")) {
165
snprintf(tmp_path, sizeof(tmp_path), "%s/%s.so", p, dlm->path);
166
DEBUGMSGTL(("dlmod", "p: %s tmp_path: %s\n", p, tmp_path));
168
dlm->handle = dlopen(tmp_path, RTLD_NOW);
170
dlm->handle = dlopen(tmp_path, RTLD_LAZY);
172
if (dlm->handle == NULL) {
173
snprintf(dlm->error, sizeof(dlm->error),
174
"dlopen failed: %s", dlerror());
175
dlm->status = DLMOD_ERROR;
178
strncpy(dlm->path, tmp_path, sizeof(dlm->path));
179
if (dlm->status == DLMOD_ERROR)
182
snprintf(sym_init, sizeof(sym_init), "init_%s", dlm->name);
183
dl_init = dlsym(dlm->handle, sym_init);
184
if (dl_init == NULL) {
185
dlclose(dlm->handle);
186
snprintf(dlm->error, sizeof(dlm->error),
187
"dlsym failed: can't find \'%s\'", sym_init);
188
dlm->status = DLMOD_ERROR;
193
dlm->error[0] = '\0';
194
dlm->status = DLMOD_LOADED;
198
dlmod_unload_module(struct dlmod *dlm)
201
int (*dl_deinit) (void);
203
if (!dlm || dlm->status != DLMOD_LOADED)
206
snprintf(sym_deinit, sizeof(sym_deinit), "deinit_%s", dlm->name);
207
dl_deinit = dlsym(dlm->handle, sym_deinit);
208
if (dl_deinit == NULL) {
209
snprintf(dlm->error, sizeof(dlm->error),
210
"dlsym failed: can't find \'%s\'", sym_deinit);
214
dlclose(dlm->handle);
215
dlm->status = DLMOD_UNLOADED;
216
DEBUGMSGTL(("dlmod", "Module %s unloaded\n", dlm->name));
220
dlmod_get_by_index(int iindex)
224
for (dlmod = dlmods; dlmod; dlmod = dlmod->next)
225
if (dlmod->index == iindex)
232
dlmod_parse_config(const char *token, char *cptr)
234
char *dlm_name, *dlm_path;
238
config_perror("Bad dlmod line");
244
*(cptr + strcspn(cptr, "#;\r\n")) = '\0';
246
dlm = dlmod_create_module();
251
* dynamic module name
253
dlm_name = strtok(cptr, "\t ");
254
if (dlm_name == NULL) {
255
config_perror("Bad dlmod line");
256
dlmod_delete_module(dlm);
259
strncpy(dlm->name, dlm_name, sizeof(dlm->name));
262
* dynamic module path
264
dlm_path = strtok(NULL, "\t ");
266
strncpy(dlm->path, dlm_path, sizeof(dlm->path));
268
strncpy(dlm->path, dlm_name, sizeof(dlm->path));
270
dlmod_load_module(dlm);
272
if (dlm->status == DLMOD_ERROR)
273
snmp_log(LOG_ERR, "%s\n", dlm->error);
277
dlmod_free_config(void)
279
struct dlmod *dtmp, *dtmp2;
281
for (dtmp = dlmods; dtmp != NULL;) {
284
dlmod_unload_module(dtmp2);
294
* vp IN - pointer to variable entry that points here
295
* name IN/OUT - IN/name requested, OUT/name found
296
* length IN/OUT - length of IN/OUT oid's
297
* exact IN - TRUE if an exact match was requested
298
* var_len OUT - length of variable or 0 if function returned
303
header_dlmod(struct variable *vp,
306
int exact, size_t * var_len, WriteMethod ** write_method)
308
#define DLMOD_NAME_LENGTH 10
309
oid newname[MAX_OID_LEN];
312
memcpy((char *) newname, (char *) vp->name,
313
(int) vp->namelen * sizeof(oid));
314
newname[DLMOD_NAME_LENGTH] = 0;
317
snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
318
if ((exact && (result != 0)) || (!exact && (result >= 0))) {
322
memcpy((char *) name, (char *) newname,
323
((int) vp->namelen + 1) * sizeof(oid));
324
*length = vp->namelen + 1;
326
*var_len = sizeof(long); /* default to 'long' results */
327
return MATCH_SUCCEEDED;
332
var_dlmod(struct variable * vp,
335
int exact, size_t * var_len, WriteMethod ** write_method)
339
* variables we may use later
342
*write_method = 0; /* assume it isnt writable for the time being */
343
*var_len = sizeof(int); /* assume an integer and change later
346
if (header_dlmod(vp, name, length, exact,
347
var_len, write_method) == MATCH_FAILED)
351
* this is where we do the value assignments for the mib results.
355
long_return = dlmod_next_index;
356
return (unsigned char *) &long_return;
358
DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmod\n",
366
* header_dlmodEntry(...
368
* vp IN - pointer to variable entry that points here
369
* name IN/OUT - IN/name requested, OUT/name found
370
* length IN/OUT - length of IN/OUT oid's
371
* exact IN - TRUE if an exact match was requested
372
* var_len OUT - length of variable or 0 if function returned
378
static struct dlmod *
379
header_dlmodEntry(struct variable *vp,
382
int exact, size_t * var_len, WriteMethod ** write_method)
384
#define DLMODENTRY_NAME_LENGTH 12
385
oid newname[MAX_OID_LEN];
387
struct dlmod *dlm = 0;
390
memcpy((char *) newname, (char *) vp->name,
391
(int) vp->namelen * sizeof(oid));
394
for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++) {
395
dlm = dlmod_get_by_index(dlmod_index);
397
DEBUGMSGTL(("dlmod", "dlmodEntry dlm: %p dlmod_index: %d\n",
401
newname[12] = dlmod_index;
402
result = snmp_oid_compare(name, *length, newname,
403
(int) vp->namelen + 1);
405
if ((exact && (result == 0)) || (!exact && (result < 0)))
410
if (dlmod_index >= dlmod_next_index) {
411
if (dlmod_index == dlmod_next_index &&
412
exact && vp->magic == DLMODSTATUS)
414
*write_method = write_dlmodStatus;
418
memcpy((char *) name, (char *) newname,
419
((int) vp->namelen + 1) * sizeof(oid));
420
*length = vp->namelen + 1;
421
*var_len = sizeof(long);
426
var_dlmodEntry(struct variable * vp,
429
int exact, size_t * var_len, WriteMethod ** write_method)
432
* variables we may use later
436
*var_len = sizeof(int); /* assume an integer and change later
440
header_dlmodEntry(vp, name, length, exact, var_len, write_method);
445
* this is where we do the value assignments for the mib results.
449
*write_method = write_dlmodName;
450
*var_len = strlen(dlm->name);
451
return (unsigned char *) dlm->name;
453
*write_method = write_dlmodPath;
454
*var_len = strlen(dlm->path);
455
return (unsigned char *) dlm->path;
457
*var_len = strlen(dlm->error);
458
return (unsigned char *) dlm->error;
460
*write_method = write_dlmodStatus;
461
long_return = dlm->status;
462
return (unsigned char *) &long_return;
464
DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmodEntry\n",
471
write_dlmodName(int action,
475
u_char * statP, oid * name, size_t name_len)
477
static struct dlmod *dlm;
479
if (var_val_type != ASN_OCTET_STR) {
480
snmp_log(LOG_ERR, "write to dlmodName not ASN_OCTET_STR\n");
481
return SNMP_ERR_WRONGTYPE;
483
if (var_val_len > sizeof(dlm->name)) {
484
snmp_log(LOG_ERR, "write to dlmodName: bad length\n");
485
return SNMP_ERR_WRONGLENGTH;
487
if (action == COMMIT) {
488
dlm = dlmod_get_by_index(name[12]);
489
if (!dlm || dlm->status == DLMOD_LOADED)
490
return SNMP_ERR_RESOURCEUNAVAILABLE;
491
strncpy(dlm->name, (const char *) var_val, var_val_len);
492
dlm->name[var_val_len] = 0;
494
return SNMP_ERR_NOERROR;
498
write_dlmodPath(int action,
502
u_char * statP, oid * name, size_t name_len)
504
static struct dlmod *dlm;
506
if (var_val_type != ASN_OCTET_STR) {
507
snmp_log(LOG_ERR, "write to dlmodPath not ASN_OCTET_STR\n");
508
return SNMP_ERR_WRONGTYPE;
510
if (var_val_len > sizeof(dlm->path)) {
511
snmp_log(LOG_ERR, "write to dlmodPath: bad length\n");
512
return SNMP_ERR_WRONGLENGTH;
514
if (action == COMMIT) {
515
dlm = dlmod_get_by_index(name[12]);
516
if (!dlm || dlm->status == DLMOD_LOADED)
517
return SNMP_ERR_RESOURCEUNAVAILABLE;
518
strncpy(dlm->path, (const char *) var_val, var_val_len);
519
dlm->path[var_val_len] = 0;
521
return SNMP_ERR_NOERROR;
525
write_dlmodStatus(int action,
529
u_char * statP, oid * name, size_t name_len)
532
* variables we may use later
536
if (var_val_type != ASN_INTEGER) {
537
snmp_log(LOG_ERR, "write to dlmodStatus not ASN_INTEGER\n");
538
return SNMP_ERR_WRONGTYPE;
540
if (var_val_len > sizeof(long)) {
541
snmp_log(LOG_ERR, "write to dlmodStatus: bad length\n");
542
return SNMP_ERR_WRONGLENGTH;
544
if (action == COMMIT) {
546
* object identifier in form .1.3.6.1.4.1.2021.13.14.2.1.4.x
547
* where X is index with offset 12
550
dlm = dlmod_get_by_index(name[12]);
551
switch (*((long *) var_val)) {
553
if (dlm || (name[12] != dlmod_next_index))
554
return SNMP_ERR_RESOURCEUNAVAILABLE;
555
dlm = dlmod_create_module();
557
return SNMP_ERR_RESOURCEUNAVAILABLE;
560
if (!dlm || dlm->status == DLMOD_LOADED)
561
return SNMP_ERR_RESOURCEUNAVAILABLE;
562
dlmod_load_module(dlm);
565
if (!dlm || dlm->status != DLMOD_LOADED)
566
return SNMP_ERR_RESOURCEUNAVAILABLE;
567
dlmod_unload_module(dlm);
570
if (!dlm || dlm->status == DLMOD_LOADED)
571
return SNMP_ERR_RESOURCEUNAVAILABLE;
572
dlmod_delete_module(dlm);
575
return SNMP_ERR_WRONGVALUE;
578
return SNMP_ERR_NOERROR;
581
#else /* no dlopen support */
587
"Dynamic modules not support on this platform\n"));