summaryrefslogtreecommitdiffstats
path: root/contrib/bsnmp/snmp_target/target_snmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bsnmp/snmp_target/target_snmp.c')
-rwxr-xr-xcontrib/bsnmp/snmp_target/target_snmp.c837
1 files changed, 837 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_target/target_snmp.c b/contrib/bsnmp/snmp_target/target_snmp.c
new file mode 100755
index 0000000..c6f05de
--- /dev/null
+++ b/contrib/bsnmp/snmp_target/target_snmp.c
@@ -0,0 +1,837 @@
+/*-
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Shteryana Sotirova Shopova under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <syslog.h>
+
+#include "asn1.h"
+#include "snmp.h"
+#include "snmpmod.h"
+
+#include "target_tree.h"
+#include "target_oid.h"
+
+static struct lmodule *target_module;
+/* For the registration. */
+static const struct asn_oid oid_target = OIDX_snmpTargetMIB;
+static const struct asn_oid oid_notification = OIDX_snmpNotificationMIB;
+
+static uint reg_target;
+static uint reg_notification;
+
+static int32_t target_lock;
+
+static const struct asn_oid oid_udp_domain = OIDX_snmpUDPDomain;
+
+/*
+ * Internal datastructures and forward declarations.
+ */
+static void target_append_index(struct asn_oid *, uint,
+ const char *);
+static int target_decode_index(const struct asn_oid *, uint,
+ char *);
+static struct target_address *target_get_address(const struct asn_oid *,
+ uint);
+static struct target_address *target_get_next_address(const struct asn_oid *,
+ uint);
+static struct target_param *target_get_param(const struct asn_oid *,
+ uint);
+static struct target_param *target_get_next_param(const struct asn_oid *,
+ uint);
+static struct target_notify *target_get_notify(const struct asn_oid *,
+ uint);
+static struct target_notify *target_get_next_notify(const struct asn_oid *,
+ uint);
+
+int
+op_snmp_target(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ struct snmpd_target_stats *ctx_stats;
+
+ if (val->var.subs[sub - 1] == LEAF_snmpTargetSpinLock) {
+ switch (op) {
+ case SNMP_OP_GET:
+ if (++target_lock == INT32_MAX)
+ target_lock = 0;
+ val->v.integer = target_lock;
+ break;
+ case SNMP_OP_GETNEXT:
+ abort();
+ case SNMP_OP_SET:
+ if (val->v.integer != target_lock)
+ return (SNMP_ERR_INCONS_VALUE);
+ break;
+ case SNMP_OP_ROLLBACK:
+ /* FALLTHROUGH */
+ case SNMP_OP_COMMIT:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+ } else if (op == SNMP_OP_SET)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ if ((ctx_stats = bsnmpd_get_target_stats()) == NULL)
+ return (SNMP_ERR_GENERR);
+
+ if (op == SNMP_OP_GET) {
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpUnavailableContexts:
+ val->v.uint32 = ctx_stats->unavail_contexts;
+ break;
+ case LEAF_snmpUnknownContexts:
+ val->v.uint32 = ctx_stats->unknown_contexts;
+ break;
+ default:
+ return (SNMP_ERR_NOSUCHNAME);
+ }
+ return (SNMP_ERR_NOERROR);
+ }
+ abort();
+}
+
+int
+op_snmp_target_addrs(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ char aname[SNMP_ADM_STR32_SIZ];
+ struct target_address *addrs;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((addrs = target_get_address(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((addrs = target_get_next_address(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ target_append_index(&val->var, sub, addrs->name);
+ break;
+
+ case SNMP_OP_SET:
+ if ((addrs = target_get_address(&val->var, sub)) == NULL &&
+ (val->var.subs[sub - 1] != LEAF_snmpTargetAddrRowStatus ||
+ val->v.integer != RowStatus_createAndWait))
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (addrs != NULL) {
+ if (community != COMM_INITIALIZE &&
+ addrs->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ if (addrs->status == RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetAddrTDomain:
+ return (SNMP_ERR_INCONS_VALUE);
+ case LEAF_snmpTargetAddrTAddress:
+ if (val->v.octetstring.len != SNMP_UDP_ADDR_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->ptr1 = malloc(SNMP_UDP_ADDR_SIZ);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ memcpy(ctx->scratch->ptr1, addrs->address,
+ SNMP_UDP_ADDR_SIZ);
+ memcpy(addrs->address, val->v.octetstring.octets,
+ SNMP_UDP_ADDR_SIZ);
+ break;
+
+ case LEAF_snmpTargetAddrTagList:
+ if (val->v.octetstring.len >= SNMP_TAG_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = strlen(addrs->taglist) + 1;
+ ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ strlcpy(ctx->scratch->ptr1, addrs->taglist,
+ ctx->scratch->int1);
+ memcpy(addrs->taglist, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ addrs->taglist[val->v.octetstring.len] = '\0';
+ break;
+
+ case LEAF_snmpTargetAddrParams:
+ if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = strlen(addrs->paramname) + 1;
+ ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ strlcpy(ctx->scratch->ptr1, addrs->paramname,
+ ctx->scratch->int1);
+ memcpy(addrs->paramname, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ addrs->paramname[val->v.octetstring.len] = '\0';
+ break;
+
+ case LEAF_snmpTargetAddrRetryCount:
+ ctx->scratch->int1 = addrs->retry;
+ addrs->retry = val->v.integer;
+ break;
+
+ case LEAF_snmpTargetAddrTimeout:
+ ctx->scratch->int1 = addrs->timeout;
+ addrs->timeout = val->v.integer / 10;
+ break;
+
+ case LEAF_snmpTargetAddrStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_snmpTargetAddrRowStatus:
+ if (addrs != NULL) {
+ if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ if (val->v.integer == RowStatus_active &&
+ (addrs->address[0] == 0 ||
+ strlen(addrs->taglist) == 0 ||
+ strlen(addrs->paramname) == 0))
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = addrs->status;
+ addrs->status = val->v.integer;
+ return (SNMP_ERR_NOERROR);
+ }
+ if (val->v.integer != RowStatus_createAndWait ||
+ target_decode_index(&val->var, sub, aname) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((addrs = target_new_address(aname)) == NULL)
+ return (SNMP_ERR_GENERR);
+ addrs->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ addrs->type = StorageType_volatile;
+ else
+ addrs->type = StorageType_readOnly;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetAddrTAddress:
+ case LEAF_snmpTargetAddrTagList:
+ case LEAF_snmpTargetAddrParams:
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_snmpTargetAddrRowStatus:
+ if ((addrs = target_get_address(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ if (val->v.integer == RowStatus_destroy)
+ return (target_delete_address(addrs));
+ else if (val->v.integer == RowStatus_active)
+ return (target_activate_address(addrs));
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((addrs = target_get_address(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetAddrTAddress:
+ memcpy(addrs->address, ctx->scratch->ptr1,
+ SNMP_UDP_ADDR_SIZ);
+ free(ctx->scratch->ptr1);
+ break;
+
+ case LEAF_snmpTargetAddrTagList:
+ strlcpy(addrs->taglist, ctx->scratch->ptr1,
+ ctx->scratch->int1);
+ free(ctx->scratch->ptr1);
+ break;
+
+ case LEAF_snmpTargetAddrParams:
+ strlcpy(addrs->paramname, ctx->scratch->ptr1,
+ ctx->scratch->int1);
+ free(ctx->scratch->ptr1);
+ break;
+
+ case LEAF_snmpTargetAddrRetryCount:
+ addrs->retry = ctx->scratch->int1;
+ break;
+
+ case LEAF_snmpTargetAddrTimeout:
+ addrs->timeout = ctx->scratch->int1;
+ break;
+
+ case LEAF_snmpTargetAddrRowStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (target_delete_address(addrs));
+ break;
+ default:
+ break;
+ }
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetAddrTDomain:
+ return (oid_get(val, &oid_udp_domain));
+ case LEAF_snmpTargetAddrTAddress:
+ return (string_get(val, addrs->address, SNMP_UDP_ADDR_SIZ));
+ case LEAF_snmpTargetAddrTimeout:
+ val->v.integer = addrs->timeout;
+ break;
+ case LEAF_snmpTargetAddrRetryCount:
+ val->v.integer = addrs->retry;
+ break;
+ case LEAF_snmpTargetAddrTagList:
+ return (string_get(val, addrs->taglist, -1));
+ case LEAF_snmpTargetAddrParams:
+ return (string_get(val, addrs->paramname, -1));
+ case LEAF_snmpTargetAddrStorageType:
+ val->v.integer = addrs->type;
+ break;
+ case LEAF_snmpTargetAddrRowStatus:
+ val->v.integer = addrs->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_snmp_target_params(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ char pname[SNMP_ADM_STR32_SIZ];
+ struct target_param *param;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((param = target_get_param(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((param = target_get_next_param(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ target_append_index(&val->var, sub, param->name);
+ break;
+
+ case SNMP_OP_SET:
+ if ((param = target_get_param(&val->var, sub)) == NULL &&
+ (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
+ val->v.integer != RowStatus_createAndWait))
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (param != NULL) {
+ if (community != COMM_INITIALIZE &&
+ param->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ if (param->status == RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetParamsMPModel:
+ if (val->v.integer != SNMP_MPM_SNMP_V1 &&
+ val->v.integer != SNMP_MPM_SNMP_V2c &&
+ val->v.integer != SNMP_MPM_SNMP_V3)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = param->mpmodel;
+ param->mpmodel = val->v.integer;
+ break;
+
+ case LEAF_snmpTargetParamsSecurityModel:
+ if (val->v.integer != SNMP_SECMODEL_SNMPv1 &&
+ val->v.integer != SNMP_SECMODEL_SNMPv2c &&
+ val->v.integer != SNMP_SECMODEL_USM)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = param->sec_model;
+ param->sec_model = val->v.integer;
+ break;
+
+ case LEAF_snmpTargetParamsSecurityName:
+ if (val->v.octetstring.len >= SNMP_ADM_STR32_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = strlen(param->secname) + 1;
+ ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ strlcpy(ctx->scratch->ptr1, param->secname,
+ ctx->scratch->int1);
+ memcpy(param->secname, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ param->secname[val->v.octetstring.len] = '\0';
+ break;
+
+ case LEAF_snmpTargetParamsSecurityLevel:
+ if (val->v.integer != SNMP_noAuthNoPriv &&
+ val->v.integer != SNMP_authNoPriv &&
+ val->v.integer != SNMP_authPriv)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = param->sec_level;
+ param->sec_level = val->v.integer;
+ break;
+
+ case LEAF_snmpTargetParamsStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_snmpTargetParamsRowStatus:
+ if (param != NULL) {
+ if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ if (val->v.integer == RowStatus_active &&
+ (param->sec_model == 0 ||
+ param->sec_level == 0 ||
+ strlen(param->secname) == 0))
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = param->status;
+ param->status = val->v.integer;
+ return (SNMP_ERR_NOERROR);
+ }
+ if (val->v.integer != RowStatus_createAndWait ||
+ target_decode_index(&val->var, sub, pname) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((param = target_new_param(pname)) == NULL)
+ return (SNMP_ERR_GENERR);
+ param->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ param->type = StorageType_volatile;
+ else
+ param->type = StorageType_readOnly;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetParamsSecurityName:
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_snmpTargetParamsRowStatus:
+ if ((param = target_get_param(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ if (val->v.integer == RowStatus_destroy)
+ return (target_delete_param(param));
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((param = target_get_param(&val->var, sub)) == NULL &&
+ (val->var.subs[sub - 1] != LEAF_snmpTargetParamsRowStatus ||
+ val->v.integer != RowStatus_createAndWait))
+ return (SNMP_ERR_GENERR);
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetParamsMPModel:
+ param->mpmodel = ctx->scratch->int1;
+ break;
+ case LEAF_snmpTargetParamsSecurityModel:
+ param->sec_model = ctx->scratch->int1;
+ break;
+ case LEAF_snmpTargetParamsSecurityName:
+ strlcpy(param->secname, ctx->scratch->ptr1,
+ sizeof(param->secname));
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_snmpTargetParamsSecurityLevel:
+ param->sec_level = ctx->scratch->int1;
+ break;
+ case LEAF_snmpTargetParamsRowStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (target_delete_param(param));
+ break;
+ default:
+ break;
+ }
+
+ return (SNMP_ERR_NOERROR);
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpTargetParamsMPModel:
+ val->v.integer = param->mpmodel;
+ break;
+ case LEAF_snmpTargetParamsSecurityModel:
+ val->v.integer = param->sec_model;
+ break;
+ case LEAF_snmpTargetParamsSecurityName:
+ return (string_get(val, param->secname, -1));
+ case LEAF_snmpTargetParamsSecurityLevel:
+ val->v.integer = param->sec_level;
+ break;
+ case LEAF_snmpTargetParamsStorageType:
+ val->v.integer = param->type;
+ break;
+ case LEAF_snmpTargetParamsRowStatus:
+ val->v.integer = param->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_snmp_notify(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ char nname[SNMP_ADM_STR32_SIZ];
+ struct target_notify *notify;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((notify = target_get_notify(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((notify = target_get_next_notify(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ target_append_index(&val->var, sub, notify->name);
+ break;
+
+ case SNMP_OP_SET:
+ if ((notify = target_get_notify(&val->var, sub)) == NULL &&
+ (val->var.subs[sub - 1] != LEAF_snmpNotifyRowStatus ||
+ val->v.integer != RowStatus_createAndGo))
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (notify != NULL) {
+ if (community != COMM_INITIALIZE &&
+ notify->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpNotifyTag:
+ if (val->v.octetstring.len >= SNMP_TAG_SIZ)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = strlen(notify->taglist) + 1;
+ ctx->scratch->ptr1 = malloc(ctx->scratch->int1);
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ strlcpy(ctx->scratch->ptr1, notify->taglist,
+ ctx->scratch->int1);
+ memcpy(notify->taglist, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ notify->taglist[val->v.octetstring.len] = '\0';
+ break;
+
+ case LEAF_snmpNotifyType:
+ /* FALLTHROUGH */
+ case LEAF_snmpNotifyStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+ case LEAF_snmpNotifyRowStatus:
+ if (notify != NULL) {
+ if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = notify->status;
+ notify->status = val->v.integer;
+ return (SNMP_ERR_NOERROR);
+ }
+ if (val->v.integer != RowStatus_createAndGo ||
+ target_decode_index(&val->var, sub, nname) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((notify = target_new_notify(nname)) == NULL)
+ return (SNMP_ERR_GENERR);
+ notify->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ notify->type = StorageType_volatile;
+ else
+ notify->type = StorageType_readOnly;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpNotifyTag:
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_snmpNotifyRowStatus:
+ notify = target_get_notify(&val->var, sub);
+ if (notify == NULL)
+ return (SNMP_ERR_GENERR);
+ if (val->v.integer == RowStatus_destroy)
+ return (target_delete_notify(notify));
+ else
+ notify->status = RowStatus_active;
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((notify = target_get_notify(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpNotifyTag:
+ strlcpy(notify->taglist, ctx->scratch->ptr1,
+ ctx->scratch->int1);
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_snmpNotifyRowStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (target_delete_notify(notify));
+ break;
+ default:
+ break;
+ }
+
+ default:
+ abort();
+ }
+
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_snmpNotifyTag:
+ return (string_get(val, notify->taglist, -1));
+ case LEAF_snmpNotifyType:
+ val->v.integer = snmpNotifyType_trap;
+ break;
+ case LEAF_snmpNotifyStorageType:
+ val->v.integer = notify->type;
+ break;
+ case LEAF_snmpNotifyRowStatus:
+ val->v.integer = notify->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+static void
+target_append_index(struct asn_oid *oid, uint sub, const char *name)
+{
+ uint32_t i;
+
+ oid->len = sub + strlen(name);
+ for (i = 0; i < strlen(name); i++)
+ oid->subs[sub + i] = name[i];
+}
+
+static int
+target_decode_index(const struct asn_oid *oid, uint sub, char *name)
+{
+ uint32_t i, len;
+
+ if ((len = oid->len - sub) >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < len; i++)
+ name[i] = oid->subs[sub + i];
+ name[i] = '\0';
+
+ return (0);
+}
+
+static struct target_address *
+target_get_address(const struct asn_oid *oid, uint sub)
+{
+ char aname[SNMP_ADM_STR32_SIZ];
+ struct target_address *addrs;
+
+ if (target_decode_index(oid, sub, aname) < 0)
+ return (NULL);
+
+ for (addrs = target_first_address(); addrs != NULL;
+ addrs = target_next_address(addrs))
+ if (strcmp(aname, addrs->name) == 0)
+ return (addrs);
+
+ return (NULL);
+}
+
+static struct target_address *
+target_get_next_address(const struct asn_oid * oid, uint sub)
+{
+ char aname[SNMP_ADM_STR32_SIZ];
+ struct target_address *addrs;
+
+ if (oid->len - sub == 0)
+ return (target_first_address());
+
+ if (target_decode_index(oid, sub, aname) < 0)
+ return (NULL);
+
+ for (addrs = target_first_address(); addrs != NULL;
+ addrs = target_next_address(addrs))
+ if (strcmp(aname, addrs->name) == 0)
+ return (target_next_address(addrs));
+
+ return (NULL);
+}
+
+static struct target_param *
+target_get_param(const struct asn_oid *oid, uint sub)
+{
+ char pname[SNMP_ADM_STR32_SIZ];
+ struct target_param *param;
+
+ if (target_decode_index(oid, sub, pname) < 0)
+ return (NULL);
+
+ for (param = target_first_param(); param != NULL;
+ param = target_next_param(param))
+ if (strcmp(pname, param->name) == 0)
+ return (param);
+
+ return (NULL);
+}
+
+static struct target_param *
+target_get_next_param(const struct asn_oid *oid, uint sub)
+{
+ char pname[SNMP_ADM_STR32_SIZ];
+ struct target_param *param;
+
+ if (oid->len - sub == 0)
+ return (target_first_param());
+
+ if (target_decode_index(oid, sub, pname) < 0)
+ return (NULL);
+
+ for (param = target_first_param(); param != NULL;
+ param = target_next_param(param))
+ if (strcmp(pname, param->name) == 0)
+ return (target_next_param(param));
+
+ return (NULL);
+}
+
+static struct target_notify *
+target_get_notify(const struct asn_oid *oid, uint sub)
+{
+ char nname[SNMP_ADM_STR32_SIZ];
+ struct target_notify *notify;
+
+ if (target_decode_index(oid, sub, nname) < 0)
+ return (NULL);
+
+ for (notify = target_first_notify(); notify != NULL;
+ notify = target_next_notify(notify))
+ if (strcmp(nname, notify->name) == 0)
+ return (notify);
+
+ return (NULL);
+}
+
+static struct target_notify *
+target_get_next_notify(const struct asn_oid *oid, uint sub)
+{
+ char nname[SNMP_ADM_STR32_SIZ];
+ struct target_notify *notify;
+
+ if (oid->len - sub == 0)
+ return (target_first_notify());
+
+ if (target_decode_index(oid, sub, nname) < 0)
+ return (NULL);
+
+ for (notify = target_first_notify(); notify != NULL;
+ notify = target_next_notify(notify))
+ if (strcmp(nname, notify->name) == 0)
+ return (target_next_notify(notify));
+
+ return (NULL);
+}
+
+static int
+target_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
+{
+ target_module = mod;
+ target_lock = random();
+
+ return (0);
+}
+
+
+static int
+target_fini(void)
+{
+ target_flush_all();
+ or_unregister(reg_target);
+ or_unregister(reg_notification);
+
+ return (0);
+}
+
+static void
+target_start(void)
+{
+ reg_target = or_register(&oid_target,
+ "The MIB module for managing SNMP Management Targets.",
+ target_module);
+ reg_notification = or_register(&oid_notification,
+ "The MIB module for configuring generation of SNMP notifications.",
+ target_module);
+}
+
+static void
+target_dump(void)
+{
+ /* XXX: dump the module stats & list of mgmt targets */
+}
+
+const char target_comment[] = \
+"This module implements SNMP Management Target MIB Module defined in RFC 3413.";
+
+const struct snmp_module config = {
+ .comment = target_comment,
+ .init = target_init,
+ .fini = target_fini,
+ .start = target_start,
+ .tree = target_ctree,
+ .dump = target_dump,
+ .tree_size = target_CTREE_SIZE,
+};
OpenPOWER on IntegriCloud