1 #include <net-snmp/net-snmp-config.h>
12 #if TIME_WITH_SYS_TIME
14 # include <sys/timeb.h>
16 # include <sys/time.h>
21 # include <sys/time.h>
27 #if HAVE_MACHINE_PARAM_H
28 #include <machine/param.h>
31 #include <sys/param.h>
33 #if HAVE_SYS_VMMETER_H
34 #if !(defined(bsdi2) || defined(netbsd1))
35 #include <sys/vmmeter.h>
53 #if HAVE_UFS_UFS_DINODE_H
54 #include <ufs/ufs/dinode.h>
57 #include <ufs/ffs/fs.h>
70 #include <sys/statfs.h>
72 #if HAVE_SYS_STATVFS_H
73 #include <sys/statvfs.h>
78 #if (!defined(HAVE_STATVFS)) && defined(HAVE_STATFS)
80 #include <sys/mount.h>
83 #include <sys/sysctl.h>
85 #define statvfs statfs
90 #if HAVE_VM_SWAP_PAGER_H
91 #include <vm/swap_pager.h>
93 #if HAVE_SYS_FIXPOINT_H
94 #include <sys/fixpoint.h>
106 #ifndef HAVE_STRNCASECMP
107 int strncasecmp(const char *s1, const char *s2, size_t n);
114 #include <net-snmp/net-snmp-includes.h>
115 #include <net-snmp/agent/net-snmp-agent-includes.h>
116 #include <net-snmp/agent/auto_nlist.h>
119 #include "extensible.h"
120 #include "util_funcs.h"
122 extern struct myproc *procwatch; /* moved to proc.c */
123 extern int numprocs; /* ditto */
124 extern struct extensible *extens; /* In exec.c */
125 extern struct extensible *relocs; /* In exec.c */
126 extern int numextens; /* ditto */
127 extern int numrelocs; /* ditto */
128 extern struct extensible *passthrus; /* In pass.c */
129 extern int numpassthrus; /* ditto */
130 extern char sysName[];
131 extern netsnmp_subtree *subtrees;
132 extern struct variable2 extensible_relocatable_variables[];
133 extern struct variable2 extensible_passthru_variables[];
136 init_extensible(void)
139 struct variable2 extensible_extensible_variables[] = {
140 {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_shell, 1,
142 {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_shell, 1,
144 {SHELLCOMMAND, ASN_OCTET_STR, RONLY, var_extensible_shell, 1,
146 {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_shell, 1,
148 {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_shell, 1,
150 {ERRORFIX, ASN_INTEGER, RWRITE, var_extensible_shell, 1,
152 {ERRORFIXCMD, ASN_OCTET_STR, RONLY, var_extensible_shell, 1,
157 * Define the OID pointer to the top of the mib tree that we're
158 * registering underneath
160 oid extensible_variables_oid[] =
161 { UCDAVIS_MIB, SHELLMIBNUM, 1 };
164 * register ourselves with the agent to handle our mib tree
166 REGISTER_MIB("ucd-snmp/extensible", extensible_extensible_variables,
167 variable2, extensible_variables_oid);
169 snmpd_register_config_handler("exec", extensible_parse_config,
170 extensible_free_config,
171 "[miboid] name program arguments");
172 snmpd_register_config_handler("sh", extensible_parse_config,
173 extensible_free_config,
174 "[miboid] name program-or-script arguments");
175 snmpd_register_config_handler("execfix", execfix_parse_config, NULL,
176 "exec-or-sh-name program [arguments...]");
180 extensible_parse_config(const char *token, char *cptr)
182 struct extensible *ptmp, **pp;
186 * allocate and clear memory structure
188 ptmp = (struct extensible *) calloc(1, sizeof(struct extensible));
190 return; /* XXX memory alloc error */
194 if (isdigit(*cptr)) {
196 * its a relocatable extensible mib
198 for (pp = &relocs, numrelocs++; *pp; pp = &((*pp)->next));
202 * it goes in with the general extensible table
204 for (pp = &extens, numextens++; *pp; pp = &((*pp)->next));
209 * the rest is pretty much handled the same
211 if (!strncasecmp(token, "sh", 2))
214 ptmp->type = EXECPROC;
215 if (isdigit(*cptr)) {
216 ptmp->miblen = parse_miboid(cptr, ptmp->miboid);
217 while (isdigit(*cptr) || *cptr == '.')
224 cptr = skip_white(cptr);
225 copy_nword(cptr, ptmp->name, sizeof(ptmp->name));
226 cptr = skip_not_white(cptr);
227 cptr = skip_white(cptr);
232 config_perror("No command specified on line");
234 for (tcptr = cptr; *tcptr != 0 && *tcptr != '#' && *tcptr != ';';
236 strncpy(ptmp->command, cptr, tcptr - cptr);
237 ptmp->command[tcptr - cptr] = 0;
240 sprintf(ptmp->fixcmd, EXECFIXCMD, ptmp->name);
242 if (ptmp->miblen > 0) {
244 (struct variable *) extensible_relocatable_variables,
245 sizeof(struct variable2), 6, ptmp->miboid,
251 extensible_free_config(void)
253 struct extensible *etmp, *etmp2;
255 for (etmp = extens; etmp != NULL;) {
261 for (etmp = relocs; etmp != NULL;) {
264 unregister_mib(etmp2->miboid, etmp2->miblen);
276 get_exten_instance(struct extensible *exten, size_t inst)
282 for (i = 1; i != (int) inst && exten != NULL; i++)
287 #define MAXMSGLINES 1000
289 struct extensible *extens = NULL; /* In exec.c */
290 struct extensible *relocs = NULL; /* In exec.c */
291 int numextens = 0, numrelocs = 0; /* ditto */
295 * var_extensible_shell(...
297 * vp IN - pointer to variable entry that points here
298 * name IN/OUT - IN/name requested, OUT/name found
299 * length IN/OUT - length of IN/OUT oid's
300 * exact IN - TRUE if an exact match was requested
301 * var_len OUT - length of variable or 0 if function returned
307 * find a give entry in the linked list associated with a proc name
310 get_exec_by_name(char *name)
312 struct extensible *etmp;
317 for (etmp = extens; etmp != NULL && strcmp(etmp->name, name) != 0;
323 execfix_parse_config(const char *token, char *cptr)
325 char tmpname[STRMAX];
326 struct extensible *execp;
329 * don't allow two entries with the same name
331 cptr = copy_nword(cptr, tmpname, sizeof(tmpname));
332 if ((execp = get_exec_by_name(tmpname)) == NULL) {
333 config_perror("No exec entry registered for this exec name yet.");
337 if (strlen(cptr) > sizeof(execp->fixcmd)) {
338 config_perror("fix command too long.");
342 strncpy(execp->fixcmd, cptr, sizeof(execp->fixcmd));
343 execp->fixcmd[ sizeof(execp->fixcmd)-1 ] = 0;
347 var_extensible_shell(struct variable * vp,
351 size_t * var_len, WriteMethod ** write_method)
354 static struct extensible *exten = 0;
355 static long long_ret;
357 if (header_simple_table
358 (vp, name, length, exact, var_len, write_method, numextens))
361 if ((exten = get_exten_instance(extens, name[*length - 1]))) {
364 long_ret = name[*length - 1];
365 return ((u_char *) (&long_ret));
366 case ERRORNAME: /* name defined in config file */
367 *var_len = strlen(exten->name);
368 return ((u_char *) (exten->name));
370 *var_len = strlen(exten->command);
371 return ((u_char *) (exten->command));
372 case ERRORFLAG: /* return code from the process */
373 if (exten->type == EXECPROC)
376 shell_command(exten);
377 long_ret = exten->result;
378 return ((u_char *) (&long_ret));
379 case ERRORMSG: /* first line of text returned from the process */
380 if (exten->type == EXECPROC)
383 shell_command(exten);
384 *var_len = strlen(exten->output);
385 if (exten->output[*var_len - 1] == '\n')
386 exten->output[--(*var_len)] = '\0';
387 return ((u_char *) (exten->output));
389 *write_method = fixExecError;
391 return ((u_char *) & long_return);
394 *var_len = strlen(exten->fixcmd);
395 return ((u_char *) exten->fixcmd);
403 fixExecError(int action,
407 u_char * statP, oid * name, size_t name_len)
410 struct extensible *exten;
413 static struct extensible ex;
416 if ((exten = get_exten_instance(extens, name[10]))) {
417 if (var_val_type != ASN_INTEGER) {
418 snmp_log(LOG_ERR, "Wrong type != int\n");
419 return SNMP_ERR_WRONGTYPE;
421 tmp = *((long *) var_val);
422 if ((tmp == 1) && (action == COMMIT) && (exten->fixcmd[0] != 0)) {
423 sprintf(ex.command, exten->fixcmd);
424 if ((fd = get_exec_output(&ex)) != -1) {
425 file = fdopen(fd, "r");
426 while (fgets(ex.output, sizeof(ex.output), file) != NULL);
431 return SNMP_ERR_NOERROR;
433 return SNMP_ERR_WRONGTYPE;
437 * the relocatable extensible commands variables
439 struct variable2 extensible_relocatable_variables[] = {
440 {MIBINDEX, ASN_INTEGER, RONLY, var_extensible_relocatable, 1,
442 {ERRORNAME, ASN_OCTET_STR, RONLY, var_extensible_relocatable, 1,
444 {SHELLCOMMAND, ASN_OCTET_STR, RONLY, var_extensible_relocatable, 1,
446 {ERRORFLAG, ASN_INTEGER, RONLY, var_extensible_relocatable, 1,
448 {ERRORMSG, ASN_OCTET_STR, RONLY, var_extensible_relocatable, 1,
450 {ERRORFIX, ASN_INTEGER, RWRITE, var_extensible_relocatable, 1,
455 var_extensible_relocatable(struct variable *vp,
459 size_t * var_len, WriteMethod ** write_method)
465 struct extensible *exten = 0;
466 static long long_ret;
467 static char errmsg[STRMAX];
468 struct variable myvp;
469 oid tname[MAX_OID_LEN];
471 memcpy(&myvp, vp, sizeof(struct variable));
474 for (i = 1; i <= (int) numrelocs; i++) {
475 exten = get_exten_instance(relocs, i);
476 if ((int) exten->miblen == (int) vp->namelen - 1) {
477 memcpy(myvp.name, exten->miboid, exten->miblen * sizeof(oid));
478 myvp.namelen = exten->miblen;
479 *length = vp->namelen;
480 memcpy(tname, vp->name, vp->namelen * sizeof(oid));
481 if (!header_simple_table
482 (&myvp, tname, length, -1, var_len, write_method, -1))
488 if (i > (int) numrelocs || exten == NULL) {
491 *write_method = NULL;
496 if (header_simple_table(vp, name, length, exact, var_len, write_method,
497 ((vp->magic == ERRORMSG) ? MAXMSGLINES : 1)))
502 long_ret = name[*length - 1];
503 return ((u_char *) (&long_ret));
504 case ERRORNAME: /* name defined in config file */
505 *var_len = strlen(exten->name);
506 return ((u_char *) (exten->name));
508 *var_len = strlen(exten->command);
509 return ((u_char *) (exten->command));
510 case ERRORFLAG: /* return code from the process */
511 if (exten->type == EXECPROC)
514 shell_command(exten);
515 long_ret = exten->result;
516 return ((u_char *) (&long_ret));
517 case ERRORMSG: /* first line of text returned from the process */
518 if (exten->type == EXECPROC) {
519 if ((fd = get_exec_output(exten)) != -1) {
520 file = fdopen(fd, "r");
521 for (i = 0; i != (int) name[*length - 1]; i++) {
522 if (fgets(errmsg, sizeof(errmsg), file) == NULL) {
538 shell_command(exten);
539 strncpy(errmsg, exten->output, sizeof(errmsg));
540 errmsg[ sizeof(errmsg)-1 ] = 0;
542 *var_len = strlen(errmsg);
543 if (errmsg[*var_len - 1] == '\n')
544 errmsg[--(*var_len)] = '\0';
545 return ((u_char *) (errmsg));
547 *write_method = fixExecError;
549 return ((u_char *) & long_return);
555 find_extensible(netsnmp_subtree *tp, oid *tname, size_t tnamelen, int exact)
559 struct extensible *exten = 0;
560 struct variable myvp;
561 oid name[MAX_OID_LEN];
562 static netsnmp_subtree mysubtree[2] =
563 { { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0,
564 NULL, NULL, NULL, 0, 0, NULL, 0, 0 },
565 { NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL, 0, 0, 0,
566 NULL, NULL, NULL, 0, 0, NULL, 0, 0 } };
568 for (i = 1; i <= (int) numrelocs; i++) {
569 exten = get_exten_instance(relocs, i);
570 if (exten->miblen != 0) {
571 memcpy(myvp.name, exten->miboid, exten->miblen * sizeof(oid));
572 memcpy(name, tname, tnamelen * sizeof(oid));
573 myvp.name[exten->miblen] = name[exten->miblen];
574 myvp.namelen = exten->miblen + 1;
575 tmp = exten->miblen + 1;
576 if (!header_simple_table(&myvp, name, &tmp, -1,
577 NULL, NULL, numrelocs)) {
582 if (i > (int)numrelocs || exten == NULL) {
586 if (mysubtree[0].name_a != NULL) {
587 free(mysubtree[0].name_a);
588 mysubtree[0].name_a = NULL;
590 mysubtree[0].name_a = snmp_duplicate_objid(exten->miboid, exten->miblen);
591 mysubtree[0].namelen = exten->miblen;
592 mysubtree[0].variables = (struct variable *)extensible_relocatable_variables;
593 mysubtree[0].variables_len = sizeof(extensible_relocatable_variables) /
594 sizeof(*extensible_relocatable_variables);
595 mysubtree[0].variables_width = sizeof(*extensible_relocatable_variables);
596 mysubtree[1].namelen = 0;