freebsd-dev/contrib/bsnmp/snmp_target/target_snmp.c
Shteryana Shopova ac89bc4f84 Fix a bug in decoding string indexes in snmp_target(3), thus causing
bsnmpd(1) to not send v3 notifications properly; while here add two
missing return statements which could lead to abort() in case of a
rollback
2014-10-10 00:26:28 +00:00

841 lines
23 KiB
C

/*-
* 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;
}
return (SNMP_ERR_NOERROR);
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;
}
return (SNMP_ERR_NOERROR);
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;
if (oid->len - sub != oid->subs[sub] + 1 || oid->subs[sub] >=
SNMP_ADM_STR32_SIZ)
return (-1);
for (i = 0; i < oid->subs[sub]; i++)
name[i] = oid->subs[sub + i + 1];
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,
};