diff options
author | syrinx <syrinx@FreeBSD.org> | 2010-12-20 17:13:14 +0000 |
---|---|---|
committer | syrinx <syrinx@FreeBSD.org> | 2010-12-20 17:13:14 +0000 |
commit | cdf73327e5ede68524c23f9fb281bbbd7c771b07 (patch) | |
tree | 5b7dd1db00389b1d0504f34a299b48339c9b9aac /contrib/bsnmp/snmp_target | |
parent | 0f810ef0a25b4d64ffe05b47b5dfd30d73167b71 (diff) | |
download | FreeBSD-src-cdf73327e5ede68524c23f9fb281bbbd7c771b07.zip FreeBSD-src-cdf73327e5ede68524c23f9fb281bbbd7c771b07.tar.gz |
Bring in a SNMP module that allows configuration of SNMPv3 Notification targets.
Sponsored by: The FreeBSD Foundation
Reviewed by: philip
Approved by: philip
Diffstat (limited to 'contrib/bsnmp/snmp_target')
-rwxr-xr-x | contrib/bsnmp/snmp_target/snmp_target.3 | 204 | ||||
-rwxr-xr-x | contrib/bsnmp/snmp_target/target_snmp.c | 837 | ||||
-rwxr-xr-x | contrib/bsnmp/snmp_target/target_tree.def | 95 |
3 files changed, 1136 insertions, 0 deletions
diff --git a/contrib/bsnmp/snmp_target/snmp_target.3 b/contrib/bsnmp/snmp_target/snmp_target.3 new file mode 100755 index 0000000..03071b5 --- /dev/null +++ b/contrib/bsnmp/snmp_target/snmp_target.3 @@ -0,0 +1,204 @@ +.\"- +.\" 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 December 16, 2010 +.Dt SNMP_TARGET 3 +.Os +.Sh NAME +.Nm snmp_target +.Nd "Target addresses and notifications module for +.Xr bsnmpd 1 +.Sh LIBRARY +.Pq begemotSnmpdModulePath."target" = "/usr/lib/snmp_target.so" +.Sh DESCRIPTION +The +.Nm snmp_target +module implements SNMPv3 Management Target MIB and basic functionality from +Notification MIB as defined in RFC 3413. The module is used to manage the +internal list of SNMPv3 notification target addresses in +.Nm bsnmpd +and their associated transport and encapsulation parameters. +The module must be loaded for +.Nm bsnmpd +to send SNMPv3 Trap-PDUs to the configured notification target addresses. +.Sh IMPLEMENTATION NOTES +A short description of the objects implemented in the module follows. +.Bl -tag -width "XXXXXXXXX" +.It Va snmpTargetSpinLock +An advisory lock used to coordinate several Command Generator Applications when +altering the SNMP Target addresses and their associated parameters. +.It Va snmpTargetAddrTable +The table contains the transport addresses to be used in generation of SNMP +messages. +The table contains the following objects +.Bl -tag -width ".It Va snmpTargetAddrName" +.It Va snmpTargetAddrName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpTargetAddrTDomain +The transport domain of the target address. Currently only UDP over IPv4 is +supported and any attempt to SET the value of this object will return an +"inconsistentValue" error. Additional transport domains will be supported +in future via the object definitions in TRANSPORT-ADDRESS-MIB (RFC 3419). +.It Va snmpTargetAddrTAddress +The transport address of this entry interpreted within the context of the value +of +.Va snmpTargetAddrTDomain . +For UDP over IPv4, this is a 6-byte long octetstring, with the first 4 bytes +representing the IPv4 address and the last 2 bytes the UDP port number in +network-byte order. +.It Va snmpTargetAddrTimeout +The value of this object is only relevant when the receiver of the SNMP +message is to send an acknowledgment that the message was received, i.e +for SNMP notifications it is relevant if the notification is SNMP Inform +rather than SNMP Trap. Currently +.Nm bsnmpd +supports only SNMP Trap notifications, so the value of this object is +meaningless. +.It Va snmpTargetAddrRetryCount +As with +.Va snmpTargetAddrTimeout +the value of this object currently is meaningless. +.It Va snmpTargetAddrTagList +A list of human-readable tag values used to select target addresses for a +particular operation. Recognized ASCII delimiting characters between tags are +space (0x20), tab (0x20), carriage return (0xOD) and line feed (0x0A). +.It Va snmpTargetAddrParams +The value of this object contains the value of a key in snmpTargetParamsTable +containing SNMP parameters used when generating messages to this transport +address. +.It Va snmpTargetAddrStorageType +This column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5) and +it is not possible to modify those entries. Entries created by Command Generator +Applications always have this column set to volatile(2) and such entries are +lost when the module is restarted. A SET operation on this column is not +allowed. +.It Va snmpTargetAddrRowStatus +This column is used to create new target address entries or delete existing ones +from the table. +.El +.It Va snmpTargetParamsTable +The table contains the target information to be used in generation of SNMP +messages. +The table contains the following objects +.Bl -tag -width ".It Va snmpTargetParamsName" +.It Va snmpTargetParamsName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpTargetParamsMPModel +The Message Processing Model to be used when generating SNMP PDUs using this +entry. Supported values are 0 for SNMPv1, 1 for SNMPv2c and 3 for SNMPv3. +.It Va snmpTargetParamsSecurityModel +The Security Model to be used when generating SNMP PDUs using this entry. +Supported values are 1 for SNMPv1, 2 for SNMPv2c and 3 for SNMPv3 User-Based +Security Model. +.It Va snmpTargetParamsSecurityName +The securityName which identifies the Principal on whose behalf SNMP PDUs +will be generated using this entry. For SNMPv1 and SNMPv2c this is the +name of a community configured in +.Nm bsnmpd , +and for SNMPv3 USM, this is the name of an existing user configured via the +.Nm snmp_usm +module. +.It Va snmpTargetParamsSecurityLevel +The Security Level to be used when generating SNMP PDUs using this entry. +Supported values are noAuthNoPriv(1) for plain-text PDUs with no authentication, +authNoPriv(2) for authenticated plain-text PDUs and authPriv(3) for encrypted +PDUs. +.It Va snmpTargetParamsStorageType +As with +.Va snmpTargetAddrStorageType +this column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5), while entries +created by Command Generator Applications always have this column set to +volatile(2). A SET operation on this column is not allowed. +.It Va snmpTargetParamsRowStatus +This column is used to create new target address parameters entries or delete +existing ones from the table. +.El +.It Va snmpNotifyTable +The table is used to select the management targets which should receive SNMP +notifications. +The table contains the following objects +.Bl -tag -width ".It Va snmpNotifyName" +.It Va snmpNotifyName +A unique local identifier used as entry key. Not accessible for GET or SET +operations. +.It Va snmpNotifyTag +This object contains a single tag value used to select target addresses from +the +.Va snmpTargetAddrTable +to which the notifications will be send. +.It Va snmpNotifyType +The type of SNMP notifications that will be send to the target addresses +matching the corresponding +.Va snmpNotifyTag . +Possible values are Trap (1) or Inform (2). Currently only SNMP Traps are +supported and any attempt to SET the value of this object will return an +"inconsistentValue" error. +.It Va snmpNotifyStorageType +Again this column always has either of two values. Entries created via +.Nm bsnmpd's +configuration file always have this column set to readOnly (5), while entries +created by Command Generator Applications always have this column set to +volatile(2). A SET operation on this column is not allowed. +.It Va snmpNotifyRowStatus +This column is used to create new notification target entries or delete existing +ones from the table. +.El +.El +.Pp +The +.Va snmpNotifyFilterProfileTable +and +.Va snmpNotifyFilterTable +tables from the SNMP-NOTIFICATION-MIB are not supported by the module. +Notification filtering is supported via the +.Xr snmp_vacm 3 +module instead. +.Sh FILES +.Bl -tag -width "XXXXXXXXX" +.It Pa /usr/share/snmp/defs/target_tree.def +The description of the MIB tree implemented by +.Nm . +.El +.Sh SEE ALSO +.Xr bsnmpd 1 , +.Xr gensnmptree 1 , +.Xr snmpmod 3 , +.Xr snmp_usm 3 , +.Xr snmp_vacm 3 +.Sh STANDARDS +IETF RFC 3413 +.Sh AUTHORS +.An Shteryana Shopova Aq syrinx@FreeBSD.org 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, +}; diff --git a/contrib/bsnmp/snmp_target/target_tree.def b/contrib/bsnmp/snmp_target/target_tree.def new file mode 100755 index 0000000..6c77b3f --- /dev/null +++ b/contrib/bsnmp/snmp_target/target_tree.def @@ -0,0 +1,95 @@ +#- +# 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$ +# + +include "tc.def" + +typedef StorageType ENUM ( + 1 other + 2 volatile + 3 nonVolatile + 4 permanent + 5 readOnly +) + +(1 internet + (6 snmpV2 + (1 snmpDomains + (1 snmpUDPDomain + ) + ) + (3 snmpModules + (12 snmpTargetMIB + (1 snmpTargetObjects + (1 snmpTargetSpinLock INTEGER op_snmp_target GET SET) + (2 snmpTargetAddrTable + (1 snmpTargetAddrEntry : OCTETSTRING op_snmp_target_addrs + (1 snmpTargetAddrName OCTETSTRING) + (2 snmpTargetAddrTDomain OID GET SET) + (3 snmpTargetAddrTAddress OCTETSTRING | TAddress GET SET) + (4 snmpTargetAddrTimeout INTEGER GET SET) + (5 snmpTargetAddrRetryCount INTEGER GET SET) + (6 snmpTargetAddrTagList OCTETSTRING | SnmpTagList GET SET) + (7 snmpTargetAddrParams OCTETSTRING GET SET) + (8 snmpTargetAddrStorageType StorageType GET SET) + (9 snmpTargetAddrRowStatus RowStatus GET SET) + ) + ) + (3 snmpTargetParamsTable + (1 snmpTargetParamsEntry : OCTETSTRING op_snmp_target_params + (1 snmpTargetParamsName OCTETSTRING) + (2 snmpTargetParamsMPModel INTEGER GET SET) + (3 snmpTargetParamsSecurityModel INTEGER GET SET) + (4 snmpTargetParamsSecurityName OCTETSTRING | SnmpAdminString GET SET) + (5 snmpTargetParamsSecurityLevel ENUM ( 1 noAuthNoPriv 2 authNoPriv 3 authPriv ) GET SET) + (6 snmpTargetParamsStorageType StorageType GET SET) + (7 snmpTargetParamsRowStatus RowStatus GET SET) + ) + ) + (4 snmpUnavailableContexts COUNTER op_snmp_target GET) + (5 snmpUnknownContexts COUNTER op_snmp_target GET) + ) + ) + (13 snmpNotificationMIB + (1 snmpNotifyObjects + (1 snmpNotifyTable + (1 snmpNotifyEntry : OCTETSTRING op_snmp_notify + (1 snmpNotifyName OCTETSTRING) + (2 snmpNotifyTag OCTETSTRING | SnmpTagValue GET SET) + (3 snmpNotifyType ENUM ( 1 trap 2 inform ) GET SET) + (4 snmpNotifyStorageType StorageType GET SET) + (5 snmpNotifyRowStatus RowStatus GET SET) + ) + ) + ) + ) + ) + ) +) |