summaryrefslogtreecommitdiff
path: root/agent/mibgroup/ucd-snmp/pass.c
diff options
context:
space:
mode:
Diffstat (limited to 'agent/mibgroup/ucd-snmp/pass.c')
-rw-r--r--agent/mibgroup/ucd-snmp/pass.c325
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);
+}