From 2993c1b4e70c201fd6cbcccf424c536bbb7f5eaf Mon Sep 17 00:00:00 2001 From: martijn Date: Mon, 6 Nov 2023 11:00:46 +0000 Subject: [PATCH] Allow agent capabilities to be stored on a per appl_context basis. This is needed for AgentX's {add,remove}agentcaps, and the sysORTable. OK tb@ --- usr.sbin/snmpd/application.c | 123 ++++++++++++++++++++++++++++++++++- usr.sbin/snmpd/application.h | 6 +- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/usr.sbin/snmpd/application.c b/usr.sbin/snmpd/application.c index 2663c9ed55e..e91c630a8c4 100644 --- a/usr.sbin/snmpd/application.c +++ b/usr.sbin/snmpd/application.c @@ -1,4 +1,4 @@ -/* $OpenBSD: application.c,v 1.28 2023/11/04 09:22:52 martijn Exp $ */ +/* $OpenBSD: application.c,v 1.29 2023/11/06 11:00:46 martijn Exp $ */ /* * Copyright (c) 2021 Martijn van Duren @@ -36,10 +36,24 @@ TAILQ_HEAD(, appl_context) contexts = TAILQ_HEAD_INITIALIZER(contexts); +struct appl_agentcap { + struct appl_backend *aa_backend; + struct appl_context *aa_context; + uint32_t aa_index; + struct ber_oid aa_oid; + char aa_descr[256]; + int aa_uptime; + + TAILQ_ENTRY(appl_agentcap) aa_entry; +}; + struct appl_context { char ac_name[APPL_CONTEXTNAME_MAX + 1]; RB_HEAD(appl_regions, appl_region) ac_regions; + TAILQ_HEAD(, appl_agentcap) ac_agentcaps; + int ac_agentcap_lastid; + int ac_agentcap_lastchange; TAILQ_ENTRY(appl_context) ac_entries; }; @@ -113,6 +127,7 @@ struct snmp_target_mib { uint32_t snmp_unknowncontexts; } snmp_target_mib; +void appl_agentcap_free(struct appl_agentcap *); enum appl_error appl_region(struct appl_context *, uint32_t, uint8_t, struct ber_oid *, int, int, struct appl_backend *); void appl_region_free(struct appl_context *, struct appl_region *); @@ -176,6 +191,7 @@ appl_shutdown(void) TAILQ_FOREACH_SAFE(ctx, &contexts, ac_entries, tctx) { assert(RB_EMPTY(&(ctx->ac_regions))); + assert(TAILQ_EMPTY(&(ctx->ac_agentcaps))); TAILQ_REMOVE(&contexts, ctx, ac_entries); free(ctx); } @@ -210,11 +226,111 @@ appl_context(const char *name, int create) strlcpy(ctx->ac_name, name, sizeof(ctx->ac_name)); RB_INIT(&(ctx->ac_regions)); + TAILQ_INIT(&(ctx->ac_agentcaps)); + ctx->ac_agentcap_lastid = 0; + ctx->ac_agentcap_lastchange = 0; TAILQ_INSERT_TAIL(&contexts, ctx, ac_entries); return ctx; } +/* Name from RFC 2741 section 6.2.14 */ +enum appl_error +appl_addagentcaps(const char *ctxname, struct ber_oid *oid, const char *descr, + struct appl_backend *backend) +{ + struct appl_context *ctx; + struct appl_agentcap *cap; + char oidbuf[1024]; + + if (ctxname == NULL) + ctxname = ""; + + (void)smi_oid2string(oid, oidbuf, sizeof(oidbuf), 0); + log_info("%s: Adding agent capabilities %s context(%s)", + backend->ab_name, oidbuf, ctxname); + + if ((ctx = appl_context(ctxname, 0)) == NULL) { + log_info("%s: Can't add agent capabilities %s: " + "Unsupported context \"%s\"", backend->ab_name, oidbuf, + ctxname); + return APPL_ERROR_UNSUPPORTEDCONTEXT; + } + + if ((cap = malloc(sizeof(*ctx))) == NULL) { + log_warn("%s: Can't add agent capabilities %s", + backend->ab_name, oidbuf); + return APPL_ERROR_PROCESSINGERROR; + } + + cap->aa_backend = backend; + cap->aa_context = ctx; + cap->aa_index = ++ctx->ac_agentcap_lastid; + cap->aa_oid = *oid; + cap->aa_uptime = smi_getticks(); + if (strlcpy(cap->aa_descr, descr, + sizeof(cap->aa_descr)) >= sizeof(cap->aa_descr)) { + log_info("%s: Can't add agent capabilities %s: " + "Invalid description", backend->ab_name, oidbuf); + free(cap); + return APPL_ERROR_PARSEERROR; + } + + TAILQ_INSERT_TAIL(&(ctx->ac_agentcaps), cap, aa_entry); + ctx->ac_agentcap_lastchange = cap->aa_uptime; + + return APPL_ERROR_NOERROR; +} + +/* Name from RFC2741 section 6.2.15 */ +enum appl_error +appl_removeagentcaps(const char *ctxname, struct ber_oid *oid, + struct appl_backend *backend) +{ + struct appl_context *ctx; + struct appl_agentcap *cap, *tmp; + char oidbuf[1024]; + int found = 0; + + if (ctxname == NULL) + ctxname = ""; + + (void)smi_oid2string(oid, oidbuf, sizeof(oidbuf), 0); + log_info("%s: Removing agent capabilities %s context(%s)", + backend->ab_name, oidbuf, ctxname); + + if ((ctx = appl_context(ctxname, 0)) == NULL) { + log_info("%s: Can't remove agent capabilities %s: " + "Unsupported context \"%s\"", backend->ab_name, oidbuf, + ctxname); + return APPL_ERROR_UNSUPPORTEDCONTEXT; + } + + TAILQ_FOREACH_SAFE(cap, &(ctx->ac_agentcaps), aa_entry, tmp) { + /* No duplicate oid check, just continue */ + if (cap->aa_backend != backend || + ober_oid_cmp(oid, &(cap->aa_oid)) != 0) + continue; + found = 1; + appl_agentcap_free(cap); + } + + if (found) + return APPL_ERROR_NOERROR; + + log_info("%s: Can't remove agent capabilities %s: not found", + backend->ab_name, oidbuf); + return APPL_ERROR_UNKNOWNAGENTCAPS; +} + +void +appl_agentcap_free(struct appl_agentcap *cap) +{ + TAILQ_REMOVE(&(cap->aa_context->ac_agentcaps), cap, aa_entry); + cap->aa_context->ac_agentcap_lastchange = smi_getticks(); + free(cap); +} + enum appl_error appl_region(struct appl_context *ctx, uint32_t timeout, uint8_t priority, struct ber_oid *oid, int instance, int subtree, @@ -534,10 +650,15 @@ void appl_close(struct appl_backend *backend) { struct appl_context *ctx; + struct appl_agentcap *cap, *tcap; struct appl_region *region, *tregion, *nregion; struct appl_request_downstream *request, *trequest; TAILQ_FOREACH(ctx, &contexts, ac_entries) { + TAILQ_FOREACH_SAFE(cap, &(ctx->ac_agentcaps), aa_entry, tcap) { + if (cap->aa_backend == backend) + appl_agentcap_free(cap); + } RB_FOREACH_SAFE(region, appl_regions, &(ctx->ac_regions), tregion) { while (region != NULL) { diff --git a/usr.sbin/snmpd/application.h b/usr.sbin/snmpd/application.h index 6e638e2c988..e873599cf9c 100644 --- a/usr.sbin/snmpd/application.h +++ b/usr.sbin/snmpd/application.h @@ -1,4 +1,4 @@ -/* $OpenBSD: application.h,v 1.7 2023/11/04 09:22:52 martijn Exp $ */ +/* $OpenBSD: application.h,v 1.8 2023/11/06 11:00:46 martijn Exp $ */ /* * Copyright (c) 2021 Martijn van Duren @@ -123,6 +123,10 @@ void appl(void); void appl_init(void); void appl_shutdown(void); struct appl_context *appl_context(const char *, int); +enum appl_error appl_addagentcaps(const char *, struct ber_oid *, const char *, + struct appl_backend *); +enum appl_error appl_removeagentcaps(const char *, struct ber_oid *, + struct appl_backend *); enum appl_error appl_register(const char *, uint32_t, uint8_t, struct ber_oid *, int, int, uint8_t, uint32_t, struct appl_backend *); enum appl_error appl_unregister(const char *, uint8_t, struct ber_oid *, -- 2.20.1