summaryrefslogtreecommitdiff
path: root/contrib/bsnmp/snmp_vacm
diff options
context:
space:
mode:
authorShteryana Shopova <syrinx@FreeBSD.org>2010-12-08 13:51:38 +0000
committerShteryana Shopova <syrinx@FreeBSD.org>2010-12-08 13:51:38 +0000
commit135f7de5ddb65ddb53a072113961b7d779a72f1b (patch)
tree30b62404bfa57932ef78fb729b57635b158c2a4a /contrib/bsnmp/snmp_vacm
parent055731ce60c309fbf0a56d364a3679ddb6b0d7ab (diff)
downloadsrc-test2-135f7de5ddb65ddb53a072113961b7d779a72f1b.tar.gz
src-test2-135f7de5ddb65ddb53a072113961b7d779a72f1b.zip
In bsnmpd(1) add support for SNMPv3 message processing model, including message authentication, packet encryption & view-based access control (RFC 3412, 3414, 3415).
Sponsored by: The FreeBSD Foundation Reviewed by: philip@ (mostly) Approved by: philip@
Notes
Notes: svn path=/head/; revision=216294
Diffstat (limited to 'contrib/bsnmp/snmp_vacm')
-rwxr-xr-xcontrib/bsnmp/snmp_vacm/snmp_vacm.394
-rwxr-xr-xcontrib/bsnmp/snmp_vacm/vacm_snmp.c1026
-rwxr-xr-xcontrib/bsnmp/snmp_vacm/vacm_tree.def104
3 files changed, 1224 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_vacm/snmp_vacm.3 b/contrib/bsnmp/snmp_vacm/snmp_vacm.3
new file mode 100755
index 000000000000..9ad25be6f8de
--- /dev/null
+++ b/contrib/bsnmp/snmp_vacm/snmp_vacm.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (C) 2010 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written 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 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 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$
+.\"
+.Dd October 7, 2010
+.Dt SNMP_VACM 3
+.Os
+.Sh NAME
+.Nm snmp_vacm
+.Nd "View-based Access Control module for
+.Xr bsnmpd 1
+.Sh LIBRARY
+.Pq begemotSnmpdModulePath."vacm" = "/usr/lib/snmp_vacm.so"
+.Sh DESCRIPTION
+The
+.Nm snmp_vacm
+module implements SNMPv3 View-based Access Control Model MIB as defined in
+RFC 3415. The module is used to manage the internal lists of SNMPv1, v2c and
+v3 user names and groups and their access rights to fetch or modify the values
+of the MIB objects maintained by
+.Nm bsnmpd
+and the modules loaded in the daemon.
+The module must be loaded for
+.Nm bsnmpd
+to implement proper view-based access control. If the module is not loaded,
+access is granted to all configured SNMPv1 & SNMPv2c communities and SNMPv3
+USM users.
+.Sh IMPLEMENTATION NOTES
+An entry in any table implemented by this MIB may be created by setting the
+relevant RowStatus column to createAndGo (4) - in fact, any other value for
+those columns in a SET operation will cause an error. When an entry is created,
+any of its columns that is not used as index, is set to the default value as
+specified in the SNMP-VIEW-BASED-ACM-MIB. All entries maintained by the module
+are persistent after reboot if created via
+.Nm bsnmpd 's
+config file, otherwise entries created via SNMP are lost after reboot.
+A short description of the objects in the MIB follows.
+.Bl -tag -width "XXXXXXXXX"
+.It Va vacmContextTable
+A read-only table that consists of a list of SNMP contexts available in
+.Nm bsnmpd .
+.It Va vacmSecurityToGroupTable
+The table contains a list of SNMPv1, v2c and v3 user names and the groups
+they belong to.
+.It Va vacmAccessTable
+The table contains a list of SNMP contexts to groups mappings and respectively
+the names of the SNMP views under those contexts, to which users in the group
+are granted read-only, read-write access or receive notifications for the
+objects under the subtree in the relevant view.
+.It Va vacmViewTreeFamilyTable
+The table contains a list of SNMP views, i.e. entries specifying the OID of a
+MIB subtree and whether access to the objects under this subtree is to be
+allowed or forbiden.
+.El
+.Sh FILES
+.Bl -tag -width "XXXXXXXXX"
+.It Pa /usr/share/snmp/defs/vacm_tree.def
+The description of the MIB tree implemented by
+.Nm .
+.El
+.Sh SEE ALSO
+.Xr bsnmpd 1 ,
+.Xr gensnmptree 1 ,
+.Xr snmpmod 3
+.Sh STANDARDS
+IETF RFC 3415
+.Sh AUTHORS
+.An Shteryana Shopova Aq syrinx@FreeBSD.org
diff --git a/contrib/bsnmp/snmp_vacm/vacm_snmp.c b/contrib/bsnmp/snmp_vacm/vacm_snmp.c
new file mode 100755
index 000000000000..cdec9f42b7fe
--- /dev/null
+++ b/contrib/bsnmp/snmp_vacm/vacm_snmp.c
@@ -0,0 +1,1026 @@
+/*-
+ * 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 "vacm_tree.h"
+#include "vacm_oid.h"
+
+static struct lmodule *vacm_module;
+/* For the registration. */
+static const struct asn_oid oid_vacm = OIDX_snmpVacmMIB;
+
+static uint reg_vacm;
+
+static int32_t vacm_lock;
+
+/*
+ * Internal datastructures and forward declarations.
+ */
+static void vacm_append_userindex(struct asn_oid *,
+ uint, const struct vacm_user *);
+static int vacm_user_index_decode(const struct asn_oid *,
+ uint, int32_t *, char *);
+static struct vacm_user *vacm_get_user(const struct asn_oid *,
+ uint);
+static struct vacm_user *vacm_get_next_user(const struct asn_oid *,
+ uint);
+static void vacm_append_access_rule_index(struct asn_oid *,
+ uint, const struct vacm_access *);
+static int vacm_access_rule_index_decode(const struct asn_oid *,
+ uint, char *, char *, int32_t *, int32_t *);
+static struct vacm_access * vacm_get_access_rule(const struct asn_oid *,
+ uint);
+static struct vacm_access * vacm_get_next_access_rule(const struct asn_oid *,
+ uint);
+static int vacm_view_index_decode(const struct asn_oid *, uint,
+ char *, struct asn_oid *);
+static void vacm_append_viewindex(struct asn_oid *, uint,
+ const struct vacm_view *);
+static struct vacm_view *vacm_get_view(const struct asn_oid *, uint);
+static struct vacm_view *vacm_get_next_view(const struct asn_oid *, uint);
+static struct vacm_view *vacm_get_view_by_name(u_char *, u_int);
+static struct vacm_context *vacm_get_context(const struct asn_oid *, uint);
+static struct vacm_context *vacm_get_next_context(const struct asn_oid *,
+ uint);
+static void vacm_append_ctxindex(struct asn_oid *, uint,
+ const struct vacm_context *);
+
+int
+op_vacm_context(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ char cname[SNMP_ADM_STR32_SIZ];
+ size_t cnamelen;
+ struct vacm_context *vacm_ctx;
+
+ if (val->var.subs[sub - 1] != LEAF_vacmContextName)
+ abort();
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((vacm_ctx = vacm_get_context(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((vacm_ctx = vacm_get_next_context(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ vacm_append_ctxindex(&val->var, sub, vacm_ctx);
+ break;
+
+ case SNMP_OP_SET:
+ if ((vacm_ctx = vacm_get_context(&val->var, sub)) != NULL)
+ return (SNMP_ERR_WRONG_VALUE);
+ if (community != COMM_INITIALIZE)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ if (val->var.subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (SNMP_ERR_WRONG_VALUE);
+ if (index_decode(&val->var, sub, iidx, &cname, &cnamelen))
+ return (SNMP_ERR_GENERR);
+ cname[cnamelen] = '\0';
+ if ((vacm_ctx = vacm_add_context(cname, reg_vacm)) == NULL)
+ return (SNMP_ERR_GENERR);
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ /* FALLTHROUGH*/
+ case SNMP_OP_ROLLBACK:
+ return (SNMP_ERR_NOERROR);
+ default:
+ abort();
+ }
+
+ return (string_get(val, vacm_ctx->ctxname, -1));
+}
+
+int
+op_vacm_security_to_group(struct snmp_context *ctx, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ int32_t smodel;
+ char uname[SNMP_ADM_STR32_SIZ];
+ struct vacm_user *user;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((user = vacm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((user = vacm_get_next_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ vacm_append_userindex(&val->var, sub, user);
+ break;
+
+ case SNMP_OP_SET:
+ if ((user = vacm_get_user(&val->var, sub)) == NULL &&
+ val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (user != NULL) {
+ if (community != COMM_INITIALIZE &&
+ user->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ if (user->status == RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmGroupName:
+ ctx->scratch->ptr1 = user->group->groupname;
+ ctx->scratch->int1 = strlen(user->group->groupname);
+ return (vacm_user_set_group(user,
+ val->v.octetstring.octets,val->v.octetstring.len));
+
+ case LEAF_vacmSecurityToGroupStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_vacmSecurityToGroupStatus:
+ if (user == NULL) {
+ if (val->v.integer != RowStatus_createAndGo ||
+ vacm_user_index_decode(&val->var, sub,
+ &smodel, uname) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ user = vacm_new_user(smodel, uname);
+ if (user == NULL)
+ return (SNMP_ERR_GENERR);
+ user->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ user->type = StorageType_volatile;
+ else
+ user->type = StorageType_readOnly;
+ } else if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = user->status;
+ user->status = val->v.integer;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ if (val->var.subs[sub - 1] != LEAF_vacmSecurityToGroupStatus)
+ return (SNMP_ERR_NOERROR);
+ if ((user = vacm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->v.integer) {
+ case RowStatus_destroy:
+ return (vacm_delete_user(user));
+
+ case RowStatus_createAndGo:
+ user->status = RowStatus_active;
+ break;
+
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((user = vacm_get_user(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmGroupName:
+ return (vacm_user_set_group(user, ctx->scratch->ptr1,
+ ctx->scratch->int1));
+
+ case LEAF_vacmSecurityToGroupStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (vacm_delete_user(user));
+ user->status = ctx->scratch->int1;
+ break;
+
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmGroupName:
+ return (string_get(val, user->group->groupname, -1));
+ case LEAF_vacmSecurityToGroupStorageType:
+ val->v.integer = user->type;
+ break;
+ case LEAF_vacmSecurityToGroupStatus:
+ val->v.integer = user->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_vacm_access(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
+ uint32_t iidx __unused, enum snmp_op op)
+{
+ int32_t smodel, slevel;
+ char gname[SNMP_ADM_STR32_SIZ], cprefix[SNMP_ADM_STR32_SIZ];
+ struct vacm_access *acl;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((acl = vacm_get_next_access_rule(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ vacm_append_access_rule_index(&val->var, sub, acl);
+ break;
+
+ case SNMP_OP_SET:
+ if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL &&
+ val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
+ return (SNMP_ERR_NOSUCHNAME);
+ if (acl != NULL && community != COMM_INITIALIZE &&
+ acl->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmAccessContextMatch:
+ ctx->scratch->int1 = acl->ctx_match;
+ if (val->v.integer == vacmAccessContextMatch_exact)
+ acl->ctx_match = 1;
+ else if (val->v.integer == vacmAccessContextMatch_prefix)
+ acl->ctx_match = 0;
+ else
+ return (SNMP_ERR_WRONG_VALUE);
+ break;
+
+ case LEAF_vacmAccessReadViewName:
+ ctx->scratch->ptr1 = acl->read_view;
+ acl->read_view = vacm_get_view_by_name(val->v.octetstring.octets, val->v.octetstring.len);
+ if (acl->read_view == NULL) {
+ acl->read_view = ctx->scratch->ptr1;
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case LEAF_vacmAccessWriteViewName:
+ ctx->scratch->ptr1 = acl->write_view;
+ if ((acl->write_view =
+ vacm_get_view_by_name(val->v.octetstring.octets,
+ val->v.octetstring.len)) == NULL) {
+ acl->write_view = ctx->scratch->ptr1;
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+ break;
+
+ case LEAF_vacmAccessNotifyViewName:
+ ctx->scratch->ptr1 = acl->notify_view;
+ if ((acl->notify_view =
+ vacm_get_view_by_name(val->v.octetstring.octets,
+ val->v.octetstring.len)) == NULL) {
+ acl->notify_view = ctx->scratch->ptr1;
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+ break;
+
+ case LEAF_vacmAccessStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_vacmAccessStatus:
+ if (acl == NULL) {
+ if (val->v.integer != RowStatus_createAndGo ||
+ vacm_access_rule_index_decode(&val->var,
+ sub, gname, cprefix, &smodel, &slevel) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((acl = vacm_new_access_rule(gname, cprefix,
+ smodel, slevel)) == NULL)
+ return (SNMP_ERR_GENERR);
+ acl->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ acl->type = StorageType_volatile;
+ else
+ acl->type = StorageType_readOnly;
+ } else if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = acl->status;
+ acl->status = val->v.integer;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ if (val->var.subs[sub - 1] != LEAF_vacmAccessStatus)
+ return (SNMP_ERR_NOERROR);
+ if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ if (val->v.integer == RowStatus_destroy)
+ return (vacm_delete_access_rule(acl));
+ else
+ acl->status = RowStatus_active;
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((acl = vacm_get_access_rule(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmAccessContextMatch:
+ acl->ctx_match = ctx->scratch->int1;
+ break;
+ case LEAF_vacmAccessReadViewName:
+ acl->read_view = ctx->scratch->ptr1;
+ break;
+ case LEAF_vacmAccessWriteViewName:
+ acl->write_view = ctx->scratch->ptr1;
+ break;
+ case LEAF_vacmAccessNotifyViewName:
+ acl->notify_view = ctx->scratch->ptr1;
+ break;
+ case LEAF_vacmAccessStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (vacm_delete_access_rule(acl));
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmAccessContextMatch:
+ return (string_get(val, acl->ctx_prefix, -1));
+ case LEAF_vacmAccessReadViewName:
+ if (acl->read_view != NULL)
+ return (string_get(val, acl->read_view->viewname, -1));
+ else
+ return (string_get(val, NULL, 0));
+ case LEAF_vacmAccessWriteViewName:
+ if (acl->write_view != NULL)
+ return (string_get(val, acl->write_view->viewname, -1));
+ else
+ return (string_get(val, NULL, 0));
+ case LEAF_vacmAccessNotifyViewName:
+ if (acl->notify_view != NULL)
+ return (string_get(val, acl->notify_view->viewname, -1));
+ else
+ return (string_get(val, NULL, 0));
+ case LEAF_vacmAccessStorageType:
+ val->v.integer = acl->type;
+ break;
+ case LEAF_vacmAccessStatus:
+ val->v.integer = acl->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_vacm_view_lock(struct snmp_context *ctx __unused, struct snmp_value *val,
+ uint32_t sub, uint32_t iidx __unused, enum snmp_op op)
+{
+ if (val->var.subs[sub - 1] != LEAF_vacmViewSpinLock)
+ return (SNMP_ERR_NOSUCHNAME);
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if (++vacm_lock == INT32_MAX)
+ vacm_lock = 0;
+ val->v.integer = vacm_lock;
+ break;
+
+ case SNMP_OP_GETNEXT:
+ abort();
+
+ case SNMP_OP_SET:
+ if (val->v.integer != vacm_lock)
+ return (SNMP_ERR_INCONS_VALUE);
+ break;
+
+ case SNMP_OP_ROLLBACK:
+ /* FALLTHROUGH */
+ case SNMP_OP_COMMIT:
+ break;
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+int
+op_vacm_view(struct snmp_context *ctx, struct snmp_value *val, uint32_t sub,
+ uint32_t iidx __unused, enum snmp_op op)
+{
+ char vname[SNMP_ADM_STR32_SIZ];
+ struct asn_oid oid;
+ struct vacm_view *view;
+
+ switch (op) {
+ case SNMP_OP_GET:
+ if ((view = vacm_get_view(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ break;
+
+ case SNMP_OP_GETNEXT:
+ if ((view = vacm_get_next_view(&val->var, sub)) == NULL)
+ return (SNMP_ERR_NOSUCHNAME);
+ vacm_append_viewindex(&val->var, sub, view);
+ break;
+
+ case SNMP_OP_SET:
+ if ((view = vacm_get_view(&val->var, sub)) == NULL &&
+ val->var.subs[sub - 1] != LEAF_vacmViewTreeFamilyStatus)
+ return (SNMP_ERR_NOSUCHNAME);
+
+ if (view != NULL) {
+ if (community != COMM_INITIALIZE &&
+ view->type == StorageType_readOnly)
+ return (SNMP_ERR_NOT_WRITEABLE);
+ if (view->status == RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmViewTreeFamilyMask:
+ if (val->v.octetstring.len > sizeof(view->mask))
+ ctx->scratch->ptr1 = malloc(sizeof(view->mask));
+ if (ctx->scratch->ptr1 == NULL)
+ return (SNMP_ERR_GENERR);
+ memset(ctx->scratch->ptr1, 0, sizeof(view->mask));
+ memcpy(ctx->scratch->ptr1, view->mask,
+ sizeof(view->mask));
+ memset(view->mask, 0, sizeof(view->mask));
+ memcpy(view->mask, val->v.octetstring.octets,
+ val->v.octetstring.len);
+ break;
+
+ case LEAF_vacmViewTreeFamilyType:
+ ctx->scratch->int1 = view->exclude;
+ if (val->v.integer == vacmViewTreeFamilyType_included)
+ view->exclude = 0;
+ else if (val->v.integer == vacmViewTreeFamilyType_excluded)
+ view->exclude = 1;
+ else
+ return (SNMP_ERR_WRONG_VALUE);
+ break;
+
+ case LEAF_vacmViewTreeFamilyStorageType:
+ return (SNMP_ERR_INCONS_VALUE);
+
+ case LEAF_vacmViewTreeFamilyStatus:
+ if (view == NULL) {
+ if (val->v.integer != RowStatus_createAndGo ||
+ vacm_view_index_decode(&val->var, sub, vname,
+ &oid) < 0)
+ return (SNMP_ERR_INCONS_VALUE);
+ if ((view = vacm_new_view(vname, &oid)) == NULL)
+ return (SNMP_ERR_GENERR);
+ view->status = RowStatus_destroy;
+ if (community != COMM_INITIALIZE)
+ view->type = StorageType_volatile;
+ else
+ view->type = StorageType_readOnly;
+ } else if (val->v.integer != RowStatus_active &&
+ val->v.integer != RowStatus_destroy)
+ return (SNMP_ERR_INCONS_VALUE);
+ ctx->scratch->int1 = view->status;
+ view->status = val->v.integer;
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_COMMIT:
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmViewTreeFamilyMask:
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_vacmViewTreeFamilyStatus:
+ if ((view = vacm_get_view(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->v.integer) {
+ case RowStatus_destroy:
+ return (vacm_delete_view(view));
+
+ case RowStatus_createAndGo:
+ view->status = RowStatus_active;
+ break;
+
+ default:
+ /* NOTREACHED*/
+ return (SNMP_ERR_GENERR);
+ }
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ case SNMP_OP_ROLLBACK:
+ if ((view = vacm_get_view(&val->var, sub)) == NULL)
+ return (SNMP_ERR_GENERR);
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmViewTreeFamilyMask:
+ memcpy(view->mask, ctx->scratch->ptr1,
+ sizeof(view->mask));
+ free(ctx->scratch->ptr1);
+ break;
+ case LEAF_vacmViewTreeFamilyType:
+ view->exclude = ctx->scratch->int1;
+ break;
+ case LEAF_vacmViewTreeFamilyStatus:
+ if (ctx->scratch->int1 == RowStatus_destroy)
+ return (vacm_delete_view(view));
+ break;
+ default:
+ break;
+ }
+ return (SNMP_ERR_NOERROR);
+
+ default:
+ abort();
+ }
+
+ switch (val->var.subs[sub - 1]) {
+ case LEAF_vacmViewTreeFamilyMask:
+ return (string_get(val, view->mask, sizeof(view->mask)));
+ case LEAF_vacmViewTreeFamilyType:
+ if (view->exclude)
+ val->v.integer = vacmViewTreeFamilyType_excluded;
+ else
+ val->v.integer = vacmViewTreeFamilyType_included;
+ break;
+ case LEAF_vacmViewTreeFamilyStorageType:
+ val->v.integer = view->type;
+ break;
+ case LEAF_vacmViewTreeFamilyStatus:
+ val->v.integer = view->status;
+ break;
+ default:
+ abort();
+ }
+
+ return (SNMP_ERR_NOERROR);
+}
+
+static void
+vacm_append_userindex(struct asn_oid *oid, uint sub,
+ const struct vacm_user *user)
+{
+ uint32_t i;
+
+ oid->len = sub + strlen(user->secname) + 2;
+ oid->subs[sub++] = user->sec_model;
+ oid->subs[sub] = strlen(user->secname);
+ for (i = 1; i <= strlen(user->secname); i++)
+ oid->subs[sub + i] = user->secname[i - 1];
+}
+
+static int
+vacm_user_index_decode(const struct asn_oid *oid, uint sub,
+ int32_t *smodel, char *uname)
+{
+ uint32_t i;
+
+ *smodel = oid->subs[sub++];
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < oid->subs[sub]; i++)
+ uname[i] = oid->subs[sub + i + 1];
+ uname[i] = '\0';
+
+ return (0);
+}
+
+static struct vacm_user *
+vacm_get_user(const struct asn_oid *oid, uint sub)
+{
+ int32_t smodel;
+ char uname[SNMP_ADM_STR32_SIZ];
+ struct vacm_user *user;
+
+ if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
+ return (NULL);
+
+ for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
+ if (strcmp(uname, user->secname) == 0 &&
+ user->sec_model == smodel)
+ return (user);
+
+ return (NULL);
+}
+
+static struct vacm_user *
+vacm_get_next_user(const struct asn_oid *oid, uint sub)
+{
+ int32_t smodel;
+ char uname[SNMP_ADM_STR32_SIZ];
+ struct vacm_user *user;
+
+ if (oid->len - sub == 0)
+ return (vacm_first_user());
+
+ if (vacm_user_index_decode(oid, sub, &smodel, uname) < 0)
+ return (NULL);
+
+ for (user = vacm_first_user(); user != NULL; user = vacm_next_user(user))
+ if (strcmp(uname, user->secname) == 0 &&
+ user->sec_model == smodel)
+ return (vacm_next_user(user));
+
+ return (NULL);
+}
+
+static void
+vacm_append_access_rule_index(struct asn_oid *oid, uint sub,
+ const struct vacm_access *acl)
+{
+ uint32_t i;
+
+ oid->len = sub + strlen(acl->group->groupname) +
+ strlen(acl->ctx_prefix) + 4;
+
+ oid->subs[sub] = strlen(acl->group->groupname);
+ for (i = 1; i <= strlen(acl->group->groupname); i++)
+ oid->subs[sub + i] = acl->group->groupname[i - 1];
+ sub += strlen(acl->group->groupname) + 1;
+
+ oid->subs[sub] = strlen(acl->ctx_prefix);
+ for (i = 1; i <= strlen(acl->ctx_prefix); i++)
+ oid->subs[sub + i] = acl->ctx_prefix[i - 1];
+ sub += strlen(acl->ctx_prefix) + 1;
+ oid->subs[sub++] = acl->sec_model;
+ oid->subs[sub] = acl->sec_level;
+}
+
+static int
+vacm_access_rule_index_decode(const struct asn_oid *oid, uint sub, char *gname,
+ char *cprefix, int32_t *smodel, int32_t *slevel)
+{
+ uint32_t i;
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < oid->subs[sub]; i++)
+ gname[i] = oid->subs[sub + i + 1];
+ gname[i] = '\0';
+ sub += strlen(gname) + 1;
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < oid->subs[sub]; i++)
+ cprefix[i] = oid->subs[sub + i + 1];
+ cprefix[i] = '\0';
+ sub += strlen(cprefix) + 1;
+
+ *smodel = oid->subs[sub++];
+ *slevel = oid->subs[sub];
+
+ return (0);
+}
+
+struct vacm_access *
+vacm_get_access_rule(const struct asn_oid *oid, uint sub)
+{
+ int32_t smodel, slevel;
+ char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
+ struct vacm_access *acl;
+
+ if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
+ &slevel) < 0)
+ return (NULL);
+
+ for (acl = vacm_first_access_rule(); acl != NULL;
+ acl = vacm_next_access_rule(acl))
+ if (strcmp(gname, acl->group->groupname) == 0 &&
+ strcmp(prefix, acl->ctx_prefix) == 0 &&
+ smodel == acl->sec_model && slevel == acl->sec_level)
+ return (acl);
+
+ return (NULL);
+}
+
+struct vacm_access *
+vacm_get_next_access_rule(const struct asn_oid *oid __unused, uint sub __unused)
+{
+ int32_t smodel, slevel;
+ char gname[SNMP_ADM_STR32_SIZ], prefix[SNMP_ADM_STR32_SIZ];
+ struct vacm_access *acl;
+
+ if (oid->len - sub == 0)
+ return (vacm_first_access_rule());
+
+ if (vacm_access_rule_index_decode(oid, sub, gname, prefix, &smodel,
+ &slevel) < 0)
+ return (NULL);
+
+ for (acl = vacm_first_access_rule(); acl != NULL;
+ acl = vacm_next_access_rule(acl))
+ if (strcmp(gname, acl->group->groupname) == 0 &&
+ strcmp(prefix, acl->ctx_prefix) == 0 &&
+ smodel == acl->sec_model && slevel == acl->sec_model)
+ return (vacm_next_access_rule(acl));
+
+ return (NULL);
+}
+
+static int
+vacm_view_index_decode(const struct asn_oid *oid, uint sub, char *vname,
+ struct asn_oid *view_oid)
+{
+ uint32_t i;
+ int viod_off;
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (-1);
+
+ for (i = 0; i < oid->subs[sub]; i++)
+ vname[i] = oid->subs[sub + i + 1];
+ vname[i] = '\0';
+
+ viod_off = sub + oid->subs[sub] + 1;
+ if ((view_oid->len = oid->subs[viod_off]) > ASN_MAXOIDLEN)
+ return (-1);
+
+ memcpy(&view_oid->subs[0], &oid->subs[viod_off + 1],
+ view_oid->len * sizeof(view_oid->subs[0]));
+
+ return (0);
+}
+
+static void
+vacm_append_viewindex(struct asn_oid *oid, uint sub, const struct vacm_view *view)
+{
+ uint32_t i;
+
+ oid->len = sub + strlen(view->viewname) + 1;
+ oid->subs[sub] = strlen(view->viewname);
+ for (i = 1; i <= strlen(view->viewname); i++)
+ oid->subs[sub + i] = view->viewname[i - 1];
+
+ sub += strlen(view->viewname) + 1;
+ oid->subs[sub] = view->subtree.len;
+ oid->len++;
+ asn_append_oid(oid, &view->subtree);
+}
+
+struct vacm_view *
+vacm_get_view(const struct asn_oid *oid, uint sub)
+{
+ char vname[SNMP_ADM_STR32_SIZ];
+ struct asn_oid subtree;
+ struct vacm_view *view;
+
+ if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
+ return (NULL);
+
+ for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
+ if (strcmp(vname, view->viewname) == 0 &&
+ asn_compare_oid(&subtree, &view->subtree)== 0)
+ return (view);
+
+ return (NULL);
+}
+
+struct vacm_view *
+vacm_get_next_view(const struct asn_oid *oid, uint sub)
+{
+ char vname[SNMP_ADM_STR32_SIZ];
+ struct asn_oid subtree;
+ struct vacm_view *view;
+
+ if (oid->len - sub == 0)
+ return (vacm_first_view());
+
+ if (vacm_view_index_decode(oid, sub, vname, &subtree) < 0)
+ return (NULL);
+
+ for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
+ if (strcmp(vname, view->viewname) == 0 &&
+ asn_compare_oid(&subtree, &view->subtree)== 0)
+ return (vacm_next_view(view));
+
+ return (NULL);
+}
+
+static struct vacm_view *
+vacm_get_view_by_name(u_char *octets, u_int len)
+{
+ struct vacm_view *view;
+
+ for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
+ if (strlen(view->viewname) == len &&
+ memcmp(octets, view->viewname, len) == 0)
+ return (view);
+
+ return (NULL);
+}
+
+static struct vacm_context *
+vacm_get_context(const struct asn_oid *oid, uint sub)
+{
+ char cname[SNMP_ADM_STR32_SIZ];
+ size_t cnamelen;
+ u_int index_count;
+ struct vacm_context *vacm_ctx;
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (NULL);
+
+ index_count = 0;
+ index_count = SNMP_INDEX(index_count, 1);
+ if (index_decode(oid, sub, index_count, &cname, &cnamelen))
+ return (NULL);
+
+ for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
+ vacm_ctx = vacm_next_context(vacm_ctx))
+ if (strcmp(cname, vacm_ctx->ctxname) == 0)
+ return (vacm_ctx);
+
+ return (NULL);
+}
+
+static struct vacm_context *
+vacm_get_next_context(const struct asn_oid *oid, uint sub)
+{
+ char cname[SNMP_ADM_STR32_SIZ];
+ size_t cnamelen;
+ u_int index_count;
+ struct vacm_context *vacm_ctx;
+
+ if (oid->len - sub == 0)
+ return (vacm_first_context());
+
+ if (oid->subs[sub] >= SNMP_ADM_STR32_SIZ)
+ return (NULL);
+
+ index_count = 0;
+ index_count = SNMP_INDEX(index_count, 1);
+ if (index_decode(oid, sub, index_count, &cname, &cnamelen))
+ return (NULL);
+
+ for (vacm_ctx = vacm_first_context(); vacm_ctx != NULL;
+ vacm_ctx = vacm_next_context(vacm_ctx))
+ if (strcmp(cname, vacm_ctx->ctxname) == 0)
+ return (vacm_next_context(vacm_ctx));
+
+ return (NULL);
+}
+
+static void
+vacm_append_ctxindex(struct asn_oid *oid, uint sub,
+ const struct vacm_context *ctx)
+{
+ uint32_t i;
+
+ oid->len = sub + strlen(ctx->ctxname) + 1;
+ oid->subs[sub] = strlen(ctx->ctxname);
+ for (i = 1; i <= strlen(ctx->ctxname); i++)
+ oid->subs[sub + i] = ctx->ctxname[i - 1];
+}
+
+/*
+ * VACM snmp module initialization hook.
+ * Returns 0 on success, < 0 on error.
+ */
+static int
+vacm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
+{
+ vacm_module = mod;
+ vacm_lock = random();
+ vacm_groups_init();
+
+ /* XXX: TODO - initialize structures */
+ return (0);
+}
+
+/*
+ * VACM snmp module finalization hook.
+ */
+static int
+vacm_fini(void)
+{
+ /* XXX: TODO - cleanup */
+ vacm_flush_contexts(reg_vacm);
+ or_unregister(reg_vacm);
+
+ return (0);
+}
+
+/*
+ * VACM snmp module start operation.
+ */
+static void
+vacm_start(void)
+{
+ static char dflt_ctx[] = "";
+
+ reg_vacm = or_register(&oid_vacm,
+ "The MIB module for managing SNMP View-based Access Control Model.",
+ vacm_module);
+
+ (void)vacm_add_context(dflt_ctx, reg_vacm);
+}
+
+static void
+vacm_dump(void)
+{
+ struct vacm_context *vacmctx;
+ struct vacm_user *vuser;
+ struct vacm_access *vacl;
+ struct vacm_view *view;
+ static char oidbuf[ASN_OIDSTRLEN];
+
+ syslog(LOG_ERR, "\n");
+ syslog(LOG_ERR, "Context list:");
+ for (vacmctx = vacm_first_context(); vacmctx != NULL;
+ vacmctx = vacm_next_context(vacmctx))
+ syslog(LOG_ERR, "Context \"%s\", module id %d",
+ vacmctx->ctxname, vacmctx->regid);
+
+ syslog(LOG_ERR, "VACM users:");
+ for (vuser = vacm_first_user(); vuser != NULL;
+ vuser = vacm_next_user(vuser))
+ syslog(LOG_ERR, "Uname %s, Group %s, model %d", vuser->secname,
+ vuser->group!= NULL?vuser->group->groupname:"Unknown",
+ vuser->sec_model);
+
+ syslog(LOG_ERR, "VACM Access rules:");
+ for (vacl = vacm_first_access_rule(); vacl != NULL;
+ vacl = vacm_next_access_rule(vacl))
+ syslog(LOG_ERR, "Group %s, CtxPrefix %s, Model %d, Level %d, "
+ "RV %s, WR %s, NV %s", vacl->group!=NULL?
+ vacl->group->groupname:"Unknown", vacl->ctx_prefix,
+ vacl->sec_model, vacl->sec_level, vacl->read_view!=NULL?
+ vacl->read_view->viewname:"None", vacl->write_view!=NULL?
+ vacl->write_view->viewname:"None", vacl->notify_view!=NULL?
+ vacl->notify_view->viewname:"None");
+
+ syslog(LOG_ERR, "VACM Views:");
+ for (view = vacm_first_view(); view != NULL; view = vacm_next_view(view))
+ syslog(LOG_ERR, "View %s, Tree %s - %s", view->viewname,
+ asn_oid2str_r(&view->subtree, oidbuf), view->exclude?
+ "excluded":"included");
+}
+
+const char vacm_comment[] = \
+"This module implements SNMP View-based Access Control Model defined in RFC 3415.";
+
+const struct snmp_module config = {
+ .comment = vacm_comment,
+ .init = vacm_init,
+ .fini = vacm_fini,
+ .start = vacm_start,
+ .tree = vacm_ctree,
+ .dump = vacm_dump,
+ .tree_size = vacm_CTREE_SIZE,
+};
diff --git a/contrib/bsnmp/snmp_vacm/vacm_tree.def b/contrib/bsnmp/snmp_vacm/vacm_tree.def
new file mode 100755
index 000000000000..db70f7de5b1a
--- /dev/null
+++ b/contrib/bsnmp/snmp_vacm/vacm_tree.def
@@ -0,0 +1,104 @@
+#-
+# 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 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 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$
+#
+
+typedef StorageType ENUM (
+ 1 other
+ 2 volatile
+ 3 nonVolatile
+ 4 permanent
+ 5 readOnly
+)
+
+typedef RowStatus ENUM (
+ 1 active
+ 2 notInService
+ 3 notReady
+ 4 createAndGo
+ 5 createAndWait
+ 6 destroy
+)
+
+(1 internet
+ (6 snmpV2
+ (3 snmpModules
+ (16 snmpVacmMIB
+ (1 vacmMIBObjects
+ (1 vacmContextTable
+ (1 vacmContextEntry : OCTETSTRING op_vacm_context
+ (1 vacmContextName OCTETSTRING GET)
+ )
+ )
+ (2 vacmSecurityToGroupTable
+ (1 vacmSecurityToGroupEntry : INTEGER OCTETSTRING op_vacm_security_to_group
+ (1 vacmSecurityModel INTEGER)
+ (2 vacmSecurityName OCTETSTRING)
+ (3 vacmGroupName OCTETSTRING GET SET)
+ (4 vacmSecurityToGroupStorageType StorageType GET SET)
+ (5 vacmSecurityToGroupStatus RowStatus GET SET)
+ )
+ )
+ (4 vacmAccessTable
+ (1 vacmAccessEntry : OCTETSTRING OCTETSTRING INTEGER ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) op_vacm_access
+ (1 vacmAccessContextPrefix OCTETSTRING)
+ (2 vacmAccessSecurityModel INTEGER)
+ (3 vacmAccessSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ))
+ (4 vacmAccessContextMatch ENUM ( 1 exact 2 prefix ) GET SET)
+ (5 vacmAccessReadViewName OCTETSTRING GET SET)
+ (6 vacmAccessWriteViewName OCTETSTRING GET SET)
+ (7 vacmAccessNotifyViewName OCTETSTRING GET SET)
+ (8 vacmAccessStorageType StorageType GET SET)
+ (9 vacmAccessStatus RowStatus GET SET)
+ )
+ )
+ (5 vacmMIBViews
+ (1 vacmViewSpinLock INTEGER op_vacm_view_lock GET SET)
+ (2 vacmViewTreeFamilyTable
+ (1 vacmViewTreeFamilyEntry : OCTETSTRING OID op_vacm_view
+ (1 vacmViewTreeFamilyViewName OCTETSTRING)
+ (2 vacmViewTreeFamilySubtree OID)
+ (3 vacmViewTreeFamilyMask OCTETSTRING GET SET)
+ (4 vacmViewTreeFamilyType ENUM ( 1 included 2 excluded ) GET SET)
+ (5 vacmViewTreeFamilyStorageType StorageType GET SET)
+ (6 vacmViewTreeFamilyStatus RowStatus GET SET)
+ )
+ )
+ )
+ )
+ (2 vacmMIBConformance
+ (1 vacmMIBCompliances
+ )
+ (2 vacmMIBGroups
+ )
+ )
+ )
+ )
+ )
+)