summaryrefslogtreecommitdiff
path: root/snmplib/snmp_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'snmplib/snmp_service.c')
-rw-r--r--snmplib/snmp_service.c432
1 files changed, 432 insertions, 0 deletions
diff --git a/snmplib/snmp_service.c b/snmplib/snmp_service.c
new file mode 100644
index 0000000..54cb4ac
--- /dev/null
+++ b/snmplib/snmp_service.c
@@ -0,0 +1,432 @@
+#include <net-snmp/net-snmp-config.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/library/snmp_transport.h>
+
+static char**
+create_word_array_helper(const char* cptr, size_t idx, char* tmp, size_t tmplen)
+{
+ char* item;
+ char** res;
+ cptr = copy_nword_const(cptr, tmp, tmplen);
+ item = strdup(tmp);
+ if (cptr)
+ res = create_word_array_helper(cptr, idx + 1, tmp, tmplen);
+ else {
+ res = (char**)malloc(sizeof(char*) * (idx + 2));
+ res[idx + 1] = NULL;
+ }
+ res[idx] = item;
+ return res;
+}
+
+static char**
+create_word_array(const char* cptr)
+{
+ size_t tmplen = strlen(cptr);
+ char* tmp = (char*)malloc(tmplen + 1);
+ char** res = create_word_array_helper(cptr, 0, tmp, tmplen + 1);
+ free(tmp);
+ return res;
+}
+
+static void
+destroy_word_array(char** arr)
+{
+ if (arr) {
+ char** run = arr;
+ while(*run) {
+ free(*run);
+ ++run;
+ }
+ free(arr);
+ }
+}
+
+struct netsnmp_lookup_domain {
+ char* application;
+ char** userDomain;
+ char** domain;
+ struct netsnmp_lookup_domain* next;
+};
+
+static struct netsnmp_lookup_domain* domains = NULL;
+
+int
+netsnmp_register_default_domain(const char* application, const char* domain)
+{
+ struct netsnmp_lookup_domain *run = domains, *prev = NULL;
+ int res = 0;
+
+ while (run != NULL && strcmp(run->application, application) < 0) {
+ prev = run;
+ run = run->next;
+ }
+ if (run && strcmp(run->application, application) == 0) {
+ if (run->domain != NULL) {
+ destroy_word_array(run->domain);
+ run->domain = NULL;
+ res = 1;
+ }
+ } else {
+ run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
+ run->application = strdup(application);
+ run->userDomain = NULL;
+ if (prev) {
+ run->next = prev->next;
+ prev->next = run;
+ } else {
+ run->next = domains;
+ domains = run;
+ }
+ }
+ if (domain) {
+ run->domain = create_word_array(domain);
+ } else if (run->userDomain == NULL) {
+ if (prev)
+ prev->next = run->next;
+ else
+ domains = run->next;
+ free(run->application);
+ free(run);
+ }
+ return res;
+}
+
+void
+netsnmp_clear_default_domain(void)
+{
+ while (domains) {
+ struct netsnmp_lookup_domain *tmp = domains;
+ domains = domains->next;
+ free(tmp->application);
+ destroy_word_array(tmp->userDomain);
+ destroy_word_array(tmp->domain);
+ free(tmp);
+ }
+}
+
+static void
+netsnmp_register_user_domain(const char* token, char* cptr)
+{
+ struct netsnmp_lookup_domain *run = domains, *prev = NULL;
+ size_t len = strlen(cptr) + 1;
+ char* application = (char*)malloc(len);
+ char** domain;
+
+ {
+ char* cp = copy_nword(cptr, application, len);
+ if (cp == NULL) {
+ netsnmp_config_error("No domain(s) in registration of "
+ "defDomain \"%s\"", application);
+ free(application);
+ return;
+ }
+ domain = create_word_array(cp);
+ }
+
+ while (run != NULL && strcmp(run->application, application) < 0) {
+ prev = run;
+ run = run->next;
+ }
+ if (run && strcmp(run->application, application) == 0) {
+ if (run->userDomain != NULL) {
+ config_perror("Default transport already registered for this "
+ "application");
+ destroy_word_array(domain);
+ free(application);
+ return;
+ }
+ } else {
+ run = SNMP_MALLOC_STRUCT(netsnmp_lookup_domain);
+ run->application = strdup(application);
+ run->domain = NULL;
+ if (prev) {
+ run->next = prev->next;
+ prev->next = run;
+ } else {
+ run->next = domains;
+ domains = run;
+ }
+ }
+ run->userDomain = domain;
+ free(application);
+}
+
+static void
+netsnmp_clear_user_domain(void)
+{
+ struct netsnmp_lookup_domain *run = domains, *prev = NULL;
+
+ while (run) {
+ if (run->userDomain != NULL) {
+ destroy_word_array(run->userDomain);
+ run->userDomain = NULL;
+ }
+ if (run->domain == NULL) {
+ struct netsnmp_lookup_domain *tmp = run;
+ if (prev)
+ run = prev->next = run->next;
+ else
+ run = domains = run->next;
+ free(tmp->application);
+ free(tmp);
+ } else {
+ prev = run;
+ run = run->next;
+ }
+ }
+}
+
+const char* const *
+netsnmp_lookup_default_domains(const char* application)
+{
+ const char * const * res;
+
+ if (application == NULL)
+ res = NULL;
+ else {
+ struct netsnmp_lookup_domain *run = domains;
+
+ while (run && strcmp(run->application, application) < 0)
+ run = run->next;
+ if (run && strcmp(run->application, application) == 0)
+ if (run->userDomain)
+ res = (const char * const *)run->userDomain;
+ else
+ res = (const char * const *)run->domain;
+ else
+ res = NULL;
+ }
+ DEBUGMSGTL(("defaults",
+ "netsnmp_lookup_default_domain(\"%s\") ->",
+ application ? application : "[NIL]"));
+ if (res) {
+ const char * const * r = res;
+ while(*r) {
+ DEBUGMSG(("defaults", " \"%s\"", *r));
+ ++r;
+ }
+ DEBUGMSG(("defaults", "\n"));
+ } else
+ DEBUGMSG(("defaults", " \"[NIL]\"\n"));
+ return res;
+}
+
+const char*
+netsnmp_lookup_default_domain(const char* application)
+{
+ const char * const * res = netsnmp_lookup_default_domains(application);
+ return (res ? *res : NULL);
+}
+
+struct netsnmp_lookup_target {
+ char* application;
+ char* domain;
+ char* userTarget;
+ char* target;
+ struct netsnmp_lookup_target* next;
+};
+
+static struct netsnmp_lookup_target* targets = NULL;
+
+/**
+ * Add an (application, domain, target) triplet to the targets list if target
+ * != NULL. Remove an entry if target == NULL and the userTarget pointer for
+ * the entry found is also NULL. Keep at most one target per (application,
+ * domain) pair.
+ *
+ * @return 1 if an entry for (application, domain) was already present in the
+ * targets list or 0 if such an entry was not yet present in the targets list.
+ */
+int
+netsnmp_register_default_target(const char* application, const char* domain,
+ const char* target)
+{
+ struct netsnmp_lookup_target *run = targets, *prev = NULL;
+ int i = 0, res = 0;
+ while (run && ((i = strcmp(run->application, application)) < 0 ||
+ (i == 0 && strcmp(run->domain, domain) < 0))) {
+ prev = run;
+ run = run->next;
+ }
+ if (run && i == 0 && strcmp(run->domain, domain) == 0) {
+ if (run->target != NULL) {
+ free(run->target);
+ run->target = NULL;
+ res = 1;
+ }
+ } else {
+ run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
+ run->application = strdup(application);
+ run->domain = strdup(domain);
+ run->userTarget = NULL;
+ if (prev) {
+ run->next = prev->next;
+ prev->next = run;
+ } else {
+ run->next = targets;
+ targets = run;
+ }
+ }
+ if (target) {
+ run->target = strdup(target);
+ } else if (run->userTarget == NULL) {
+ if (prev)
+ prev->next = run->next;
+ else
+ targets = run->next;
+ free(run->domain);
+ free(run->application);
+ free(run);
+ }
+ return res;
+}
+
+/**
+ * Clear the targets list.
+ */
+void
+netsnmp_clear_default_target(void)
+{
+ while (targets) {
+ struct netsnmp_lookup_target *tmp = targets;
+ targets = targets->next;
+ free(tmp->application);
+ free(tmp->domain);
+ free(tmp->userTarget);
+ free(tmp->target);
+ free(tmp);
+ }
+}
+
+static void
+netsnmp_register_user_target(const char* token, char* cptr)
+{
+ struct netsnmp_lookup_target *run = targets, *prev = NULL;
+ size_t len = strlen(cptr) + 1;
+ char* application = (char*)malloc(len);
+ char* domain = (char*)malloc(len);
+ char* target = (char*)malloc(len);
+ int i = 0;
+
+ {
+ char* cp = copy_nword(cptr, application, len);
+ if (cp == NULL) {
+ netsnmp_config_error("No domain and target in registration of "
+ "defTarget \"%s\"", application);
+ goto done;
+ }
+ cp = copy_nword(cp, domain, len);
+ if (cp == NULL) {
+ netsnmp_config_error("No target in registration of "
+ "defTarget \"%s\" \"%s\"",
+ application, domain);
+ goto done;
+ }
+ cp = copy_nword(cp, target, len);
+ if (cp)
+ config_pwarn("Trailing junk found");
+ }
+
+ while (run && ((i = strcmp(run->application, application)) < 0 ||
+ (i == 0 && strcmp(run->domain, domain) < 0))) {
+ prev = run;
+ run = run->next;
+ }
+ if (run && i == 0 && strcmp(run->domain, domain) == 0) {
+ if (run->userTarget != NULL) {
+ config_perror("Default target already registered for this "
+ "application-domain combination");
+ goto done;
+ }
+ } else {
+ run = SNMP_MALLOC_STRUCT(netsnmp_lookup_target);
+ run->application = strdup(application);
+ run->domain = strdup(domain);
+ run->target = NULL;
+ if (prev) {
+ run->next = prev->next;
+ prev->next = run;
+ } else {
+ run->next = targets;
+ targets = run;
+ }
+ }
+ run->userTarget = strdup(target);
+ done:
+ free(target);
+ free(domain);
+ free(application);
+}
+
+static void
+netsnmp_clear_user_target(void)
+{
+ struct netsnmp_lookup_target *run = targets, *prev = NULL;
+
+ while (run) {
+ if (run->userTarget != NULL) {
+ free(run->userTarget);
+ run->userTarget = NULL;
+ }
+ if (run->target == NULL) {
+ struct netsnmp_lookup_target *tmp = run;
+ if (prev)
+ run = prev->next = run->next;
+ else
+ run = targets = run->next;
+ free(tmp->application);
+ free(tmp->domain);
+ free(tmp);
+ } else {
+ prev = run;
+ run = run->next;
+ }
+ }
+}
+
+const char*
+netsnmp_lookup_default_target(const char* application, const char* domain)
+{
+ int i = 0;
+ struct netsnmp_lookup_target *run = targets;
+ const char *res;
+
+ if (application == NULL || domain == NULL)
+ res = NULL;
+ else {
+ while (run && ((i = strcmp(run->application, application)) < 0 ||
+ (i == 0 && strcmp(run->domain, domain) < 0)))
+ run = run->next;
+ if (run && i == 0 && strcmp(run->domain, domain) == 0)
+ if (run->userTarget != NULL)
+ res = run->userTarget;
+ else
+ res = run->target;
+ else
+ res = NULL;
+ }
+ DEBUGMSGTL(("defaults",
+ "netsnmp_lookup_default_target(\"%s\", \"%s\") -> \"%s\"\n",
+ application ? application : "[NIL]",
+ domain ? domain : "[NIL]",
+ res ? res : "[NIL]"));
+ return res;
+}
+
+void
+netsnmp_register_service_handlers(void)
+{
+ register_config_handler("snmp:", "defDomain",
+ netsnmp_register_user_domain,
+ netsnmp_clear_user_domain,
+ "application domain");
+ register_config_handler("snmp:", "defTarget",
+ netsnmp_register_user_target,
+ netsnmp_clear_user_target,
+ "application domain target");
+}