diff options
Diffstat (limited to 'agent/mibgroup/ucd-snmp/pass.c')
-rw-r--r-- | agent/mibgroup/ucd-snmp/pass.c | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/agent/mibgroup/ucd-snmp/pass.c b/agent/mibgroup/ucd-snmp/pass.c new file mode 100644 index 0000000..4aae728 --- /dev/null +++ b/agent/mibgroup/ucd-snmp/pass.c @@ -0,0 +1,325 @@ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-features.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> +#include <sys/types.h> +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_SYS_WAIT_H +# include <sys/wait.h> +#endif +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#ifdef WIN32 +#include <limits.h> +#endif + +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "struct.h" +#include "pass.h" +#include "pass_common.h" +#include "extensible.h" +#include "util_funcs.h" + +netsnmp_feature_require(get_exten_instance) +netsnmp_feature_require(parse_miboid) + +struct extensible *passthrus = NULL; +int numpassthrus = 0; + +/* + * the relocatable extensible commands variables + */ +struct variable2 extensible_passthru_variables[] = { + /* + * bogus entry. Only some of it is actually used. + */ + {MIBINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, + var_extensible_pass, 0, {MIBINDEX}}, +}; + + + +void +init_pass(void) +{ + snmpd_register_config_handler("pass", pass_parse_config, + pass_free_config, "miboid command"); +} + +void +pass_parse_config(const char *token, char *cptr) +{ + struct extensible **ppass = &passthrus, **etmp, *ptmp; + char *tcptr, *endopt; + int i; + unsigned long priority; + + /* + * options + */ + priority = DEFAULT_MIB_PRIORITY; + while (*cptr == '-') { + cptr++; + switch (*cptr) { + case 'p': + /* change priority level */ + cptr++; + cptr = skip_white(cptr); + if (! isdigit((unsigned char)(*cptr))) { + config_perror("priority must be an integer"); + return; + } + priority = strtol((const char*) cptr, &endopt, 0); + if ((priority == LONG_MIN) || (priority == LONG_MAX)) { + config_perror("priority under/overflow"); + return; + } + cptr = endopt; + cptr = skip_white(cptr); + break; + default: + config_perror("unknown option for pass directive"); + return; + } + } + + /* + * MIB + */ + if (*cptr == '.') + cptr++; + if (!isdigit((unsigned char)(*cptr))) { + config_perror("second token is not a OID"); + return; + } + numpassthrus++; + + while (*ppass != NULL) + ppass = &((*ppass)->next); + (*ppass) = (struct extensible *) malloc(sizeof(struct extensible)); + if (*ppass == NULL) + return; + (*ppass)->type = PASSTHRU; + (*ppass)->mibpriority = priority; + + (*ppass)->miblen = parse_miboid(cptr, (*ppass)->miboid); + while (isdigit((unsigned char)(*cptr)) || *cptr == '.') + cptr++; + /* + * path + */ + cptr = skip_white(cptr); + if (cptr == NULL) { + config_perror("No command specified on pass line"); + (*ppass)->command[0] = 0; + } else { + for (tcptr = cptr; *tcptr != 0 && *tcptr != '#' && *tcptr != ';'; + tcptr++); + sprintf((*ppass)->command, "%.*s", (int) (tcptr - cptr), cptr); + } + strlcpy((*ppass)->name, (*ppass)->command, sizeof((*ppass)->name)); + (*ppass)->next = NULL; + + register_mib_priority("pass", + (struct variable *) extensible_passthru_variables, + sizeof(struct variable2), 1, (*ppass)->miboid, + (*ppass)->miblen, (*ppass)->mibpriority); + + /* + * argggg -- pasthrus must be sorted + */ + if (numpassthrus > 1) { + etmp = (struct extensible **) + malloc(((sizeof(struct extensible *)) * numpassthrus)); + if (etmp == NULL) + return; + + for (i = 0, ptmp = (struct extensible *) passthrus; + i < numpassthrus && ptmp != NULL; i++, ptmp = ptmp->next) + etmp[i] = ptmp; + qsort(etmp, numpassthrus, sizeof(struct extensible *), + pass_compare); + passthrus = (struct extensible *) etmp[0]; + ptmp = (struct extensible *) etmp[0]; + + for (i = 0; i < numpassthrus - 1; i++) { + ptmp->next = etmp[i + 1]; + ptmp = ptmp->next; + } + ptmp->next = NULL; + free(etmp); + } +} + +void +pass_free_config(void) +{ + struct extensible *etmp, *etmp2; + + for (etmp = passthrus; etmp != NULL;) { + etmp2 = etmp; + etmp = etmp->next; + unregister_mib_priority(etmp2->miboid, etmp2->miblen, etmp2->mibpriority); + free(etmp2); + } + passthrus = NULL; + numpassthrus = 0; +} + +u_char * +var_extensible_pass(struct variable *vp, + oid * name, + size_t * length, + int exact, + size_t * var_len, WriteMethod ** write_method) +{ + oid newname[MAX_OID_LEN]; + int i, rtest, fd, newlen; + char buf[SNMP_MAXBUF]; + static char buf2[SNMP_MAXBUF]; + struct extensible *passthru; + FILE *file; + + for (i = 1; i <= numpassthrus; i++) { + passthru = get_exten_instance(passthrus, i); + rtest = snmp_oidtree_compare(name, *length, + passthru->miboid, passthru->miblen); + if ((exact && rtest == 0) || (!exact && rtest <= 0)) { + /* + * setup args + */ + if (passthru->miblen >= *length || rtest < 0) + sprint_mib_oid(buf, passthru->miboid, passthru->miblen); + else + sprint_mib_oid(buf, name, *length); + if (exact) + snprintf(passthru->command, sizeof(passthru->command), + "%s -g %s", passthru->name, buf); + else + snprintf(passthru->command, sizeof(passthru->command), + "%s -n %s", passthru->name, buf); + passthru->command[ sizeof(passthru->command)-1 ] = 0; + DEBUGMSGTL(("ucd-snmp/pass", "pass-running: %s\n", + passthru->command)); + /* + * valid call. Exec and get output + */ + if ((fd = get_exec_output(passthru)) != -1) { + file = fdopen(fd, "r"); + if (fgets(buf, sizeof(buf), file) == NULL) { + fclose(file); + wait_on_exec(passthru); + if (exact) { + /* + * to enable creation + */ + *write_method = setPass; + *var_len = 0; + return (NULL); + } + continue; + } + newlen = parse_miboid(buf, newname); + + /* + * its good, so copy onto name/length + */ + memcpy((char *) name, (char *) newname, + (int) newlen * sizeof(oid)); + *length = newlen; + + /* + * set up return pointer for setable stuff + */ + *write_method = setPass; + + if (newlen == 0 || fgets(buf, sizeof(buf), file) == NULL + || fgets(buf2, sizeof(buf2), file) == NULL) { + *var_len = 0; + fclose(file); + wait_on_exec(passthru); + return (NULL); + } + fclose(file); + wait_on_exec(passthru); + + return netsnmp_internal_pass_parse(buf, buf2, var_len, vp); + } + *var_len = 0; + return (NULL); + } + } + if (var_len) + *var_len = 0; + *write_method = NULL; + return (NULL); +} + +int +setPass(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) +{ + int i, rtest; + struct extensible *passthru; + char buf[SNMP_MAXBUF], buf2[SNMP_MAXBUF]; + + for (i = 1; i <= numpassthrus; i++) { + passthru = get_exten_instance(passthrus, i); + rtest = snmp_oidtree_compare(name, name_len, + passthru->miboid, passthru->miblen); + if (rtest <= 0) { + if (action != ACTION) + return SNMP_ERR_NOERROR; + /* + * setup args + */ + if (passthru->miblen >= name_len || rtest < 0) + sprint_mib_oid(buf, passthru->miboid, passthru->miblen); + else + sprint_mib_oid(buf, name, name_len); + snprintf(passthru->command, sizeof(passthru->command), + "%s -s %s ", passthru->name, buf); + passthru->command[ sizeof(passthru->command)-1 ] = 0; + netsnmp_internal_pass_set_format(buf, var_val, var_val_type, var_val_len); + strlcat(passthru->command, buf, sizeof(passthru->command)); + DEBUGMSGTL(("ucd-snmp/pass", "pass-running: %s", + passthru->command)); + exec_command(passthru); + DEBUGMSGTL(("ucd-snmp/pass", "pass-running returned: %s", + passthru->output)); + return netsnmp_internal_pass_str_to_errno(passthru->output); + } + } + if (snmp_get_do_debugging()) { + sprint_mib_oid(buf2, name, name_len); + DEBUGMSGTL(("ucd-snmp/pass", "pass-notfound: %s\n", buf2)); + } + return SNMP_ERR_NOSUCHNAME; +} + +int +pass_compare(const void *a, const void *b) +{ + const struct extensible *const *ap, *const *bp; + ap = (const struct extensible * const *) a; + bp = (const struct extensible * const *) b; + return snmp_oid_compare((*ap)->miboid, (*ap)->miblen, (*bp)->miboid, + (*bp)->miblen); +} |