diff options
Diffstat (limited to 'snmplib/snmp_service.c')
-rw-r--r-- | snmplib/snmp_service.c | 432 |
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"); +} |