Bring in a SNMP module that allows configuration of SNMPv3 Notification targets.

Sponsored by:	The FreeBSD Foundation
Reviewed by:	philip
Approved by:	philip
This commit is contained in:
Shteryana Shopova 2010-12-20 17:13:14 +00:00
parent 81bd5041a2
commit 72cd7a520d
24 changed files with 1998 additions and 100 deletions

View File

@ -37,7 +37,7 @@
.\"
.\" $Begemot: bsnmp/lib/bsnmplib.3,v 1.9 2005/10/04 08:46:51 brandt_h Exp $
.\"
.Dd September 9, 2010
.Dd December 19, 2010
.Dt BSNMPLIB 3
.Os
.Sh NAME
@ -50,6 +50,7 @@
.Nm snmp_pdu_decode_header ,
.Nm snmp_pdu_decode_scoped ,
.Nm snmp_pdu_decode_secmode ,
.Nm snmp_pdu_init_secparams ,
.Nm snmp_pdu_dump ,
.Nm snmp_passwd_to_keys ,
.Nm snmp_get_local_keys ,
@ -83,6 +84,8 @@ Begemot SNMP library
.Ft enum snmp_code
.Fn snmp_pdu_decode_secmode "struct asn_buf *buf" "struct snmp_pdu *pdu"
.Ft void
.Fn snmp_pdu_init_secparams "struct snmp_pdu *pdu"
.Ft void
.Fn snmp_pdu_dump "const struct snmp_pdu *pdu"
.Ft enum snmp_code
.Fn snmp_passwd_to_keys "struct snmp_user *user" "char *passwd"
@ -175,12 +178,18 @@ This structure represents an SNMP engine as specified by the SNMP Management
Architecture described in RFC 3411.
.Pp
.Bd -literal -offset indent
#define SNMP_USM_NAME_SIZ (32 + 1)
#define SNMP_ADM_STR32_SIZ (32 + 1)
#define SNMP_AUTH_KEY_SIZ 40
#define SNMP_PRIV_KEY_SIZ 32
enum snmp_usm_level {
SNMP_noAuthNoPriv = 1,
SNMP_authNoPriv = 2,
SNMP_authPriv = 3
};
struct snmp_user {
char sec_name[SNMP_USM_NAME_SIZ];
char sec_name[SNMP_ADM_STR32_SIZ];
enum snmp_authentication auth_proto;
enum snmp_privacy priv_proto;
uint8_t auth_key[SNMP_AUTH_KEY_SIZ];
@ -230,7 +239,9 @@ contain the authentication and privacy keys for the user.
#define SNMP_MSG_PRIV_FLAG 0x2
#define SNMP_MSG_REPORT_FLAG 0x4
#define SNMP_SECMODEL_USM 3
#define SNMP_MPM_SNMP_V1 0
#define SNMP_MPM_SNMP_V2c 1
#define SNMP_MPM_SNMP_V3 3
struct snmp_pdu {
char community[SNMP_COMMUNITY_MAXLEN + 1];
@ -296,7 +307,17 @@ and
is the type of the PDU.
.Fa security_model
is the security model used for SNMPv3 PDUs. The only supported
value currently is 3 (User-based Security Model).
value currently is 3 (User-based Security Model). Additional values for any,
unknown, SNMPv1 and SNMPv2c security models are also enumerated
.Bd -literal -offset indent
enum snmp_secmodel {
SNMP_SECMODEL_ANY = 0,
SNMP_SECMODEL_SNMPv1 = 1,
SNMP_SECMODEL_SNMPv2c = 2,
SNMP_SECMODEL_USM = 3,
SNMP_SECMODEL_UNKNOWN
};
.Ed
.Pp
The function
.Fn snmp_value_free
@ -366,6 +387,13 @@ if the PDU is encrypted, decrypts the PDU contents pointed to by
If successfull, a plain text scoped PDU is stored in the buffer.
.Pp
The function
.Fn snmp_pdu_init_secparams
calculates the initialization vector for the privacy protocol in use before
the PDU pointed to by
.Fa pdu
may be encrypted or decrypted.
.Pp
The function
.Fn snmp_pdu_dump
dumps the PDU in a human readable form by calling
.Fn snmp_printf .

View File

@ -764,6 +764,7 @@ snmp_pdu_encode_header(struct asn_buf *b, struct snmp_pdu *pdu)
if (pdu->type != SNMP_PDU_RESPONSE &&
pdu->type != SNMP_PDU_TRAP &&
pdu->type != SNMP_PDU_TRAP2 &&
pdu->type != SNMP_PDU_REPORT)
pdu->flags |= SNMP_MSG_REPORT_FLAG;
@ -1176,23 +1177,19 @@ snmp_value_copy(struct snmp_value *to, const struct snmp_value *from)
}
void
snmp_pdu_init_secparams(struct snmp_pdu *pdu, struct snmp_engine *eng,
struct snmp_user *user)
snmp_pdu_init_secparams(struct snmp_pdu *pdu)
{
int32_t rval;
memcpy(&pdu->engine, eng, sizeof(pdu->engine));
memcpy(&pdu->user, user, sizeof(pdu->user));
if (user->auth_proto != SNMP_AUTH_NOAUTH)
if (pdu->user.auth_proto != SNMP_AUTH_NOAUTH)
pdu->flags |= SNMP_MSG_AUTH_FLAG;
switch (user->priv_proto) {
switch (pdu->user.priv_proto) {
case SNMP_PRIV_DES:
memcpy(pdu->msg_salt, &eng->engine_boots,
sizeof(eng->engine_boots));
memcpy(pdu->msg_salt, &pdu->engine.engine_boots,
sizeof(pdu->engine.engine_boots));
rval = random();
memcpy(pdu->msg_salt + sizeof(eng->engine_boots), &rval,
memcpy(pdu->msg_salt + sizeof(pdu->engine.engine_boots), &rval,
sizeof(int32_t));
pdu->flags |= SNMP_MSG_PRIV_FLAG;
break;

View File

@ -89,6 +89,10 @@ enum snmp_version {
SNMP_V3,
};
#define SNMP_MPM_SNMP_V1 0
#define SNMP_MPM_SNMP_V2c 1
#define SNMP_MPM_SNMP_V3 3
#define SNMP_ADM_STR32_SIZ (32 + 1)
#define SNMP_AUTH_KEY_SIZ 40
#define SNMP_PRIV_KEY_SIZ 32
@ -255,6 +259,7 @@ int snmp_value_parse(const char *, enum snmp_syntax, union snmp_values *);
int snmp_value_copy(struct snmp_value *, const struct snmp_value *);
void snmp_pdu_free(struct snmp_pdu *);
void snmp_pdu_init_secparams(struct snmp_pdu *);
enum snmp_code snmp_pdu_decode(struct asn_buf *b, struct snmp_pdu *pdu, int32_t *);
enum snmp_code snmp_pdu_decode_header(struct asn_buf *, struct snmp_pdu *);
enum snmp_code snmp_pdu_decode_scoped(struct asn_buf *, struct snmp_pdu *, int32_t *);

View File

@ -178,7 +178,9 @@ snmp_pdu_create_response(struct snmp_pdu *pdu, struct snmp_pdu *resp)
if (resp->version != SNMP_V3)
return;
snmp_pdu_init_secparams(resp, &pdu->engine, &pdu->user);
memcpy(&resp->engine, &pdu->engine, sizeof(pdu->engine));
memcpy(&resp->user, &pdu->user, sizeof(pdu->user));
snmp_pdu_init_secparams(resp);
resp->identifier = pdu->identifier;
resp->security_model = pdu->security_model;
resp->context_engine_len = pdu->context_engine_len;

View File

@ -1160,10 +1160,11 @@ snmp_pdu_create(struct snmp_pdu *pdu, u_int op)
pdu->flags = 0;
pdu->security_model = snmp_client.security_model;
if (snmp_client.security_model == SNMP_SECMODEL_USM)
snmp_pdu_init_secparams(pdu, &snmp_client.engine,
&snmp_client.user);
else
if (snmp_client.security_model == SNMP_SECMODEL_USM) {
memcpy(&pdu->engine, &snmp_client.engine, sizeof(pdu->engine));
memcpy(&pdu->user, &snmp_client.user, sizeof(pdu->user));
snmp_pdu_init_secparams(pdu);
} else
seterr(&snmp_client, "unknown security model");
if (snmp_client.clen > 0) {
@ -1440,9 +1441,11 @@ snmp_receive_packet(struct snmp_pdu *pdu, struct timeval *tv)
abuf.asn_len = ret;
memset(pdu, 0, sizeof(*pdu));
if (snmp_client.security_model == SNMP_SECMODEL_USM)
snmp_pdu_init_secparams(pdu, &snmp_client.engine,
&snmp_client.user);
if (snmp_client.security_model == SNMP_SECMODEL_USM) {
memcpy(&pdu->engine, &snmp_client.engine, sizeof(pdu->engine));
memcpy(&pdu->user, &snmp_client.user, sizeof(pdu->user));
snmp_pdu_init_secparams(pdu);
}
if (SNMP_CODE_OK != (ret = snmp_pdu_decode(&abuf, pdu, &ip))) {
seterr(&snmp_client, "snmp_decode_pdu: failed %d", ret);

View File

@ -38,9 +38,6 @@ enum snmp_code snmp_fix_encoding(struct asn_buf *, struct snmp_pdu *);
enum asn_err snmp_parse_pdus_hdr(struct asn_buf *b, struct snmp_pdu *pdu,
asn_len_t *lenp);
void snmp_pdu_init_secparams(struct snmp_pdu *, struct snmp_engine *,
struct snmp_user *);
enum snmp_code snmp_pdu_calc_digest(const struct snmp_pdu *, uint8_t *);
enum snmp_code snmp_pdu_encrypt(const struct snmp_pdu *);
enum snmp_code snmp_pdu_decrypt(const struct snmp_pdu *);

40
contrib/bsnmp/lib/tc.def Executable file
View File

@ -0,0 +1,40 @@
#-
# 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 RowStatus ENUM (
1 active
2 notInService
3 notReady
4 createAndGo
5 createAndWait
6 destroy
)

View File

@ -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

View File

@ -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,
};

View File

@ -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)
)
)
)
)
)
)
)

View File

@ -112,7 +112,7 @@ 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 usmUserStatus
This column is used to create new USM user entries or delete exsiting ones from
This column is used to create new USM user entries or delete existing ones from
the table.
.El
.EL

View File

@ -29,6 +29,8 @@
# $FreeBSD$
#
include "tc.def"
typedef StorageType ENUM (
1 other
2 volatile
@ -37,15 +39,6 @@ typedef StorageType ENUM (
5 readOnly
)
typedef RowStatus ENUM (
1 active
2 notInService
3 notReady
4 createAndGo
5 createAndWait
6 destroy
)
(1 internet
(6 snmpV2
(3 snmpModules

View File

@ -29,6 +29,8 @@
# $FreeBSD$
#
include "tc.def"
typedef StorageType ENUM (
1 other
2 volatile
@ -37,15 +39,6 @@ typedef StorageType ENUM (
5 readOnly
)
typedef RowStatus ENUM (
1 active
2 notInService
3 notReady
4 createAndGo
5 createAndWait
6 destroy
)
(1 internet
(6 snmpV2
(3 snmpModules

View File

@ -5,6 +5,12 @@
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were 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:
@ -98,6 +104,8 @@ struct snmp_engine snmpd_engine;
/* snmpSerialNo */
int32_t snmp_serial_no;
struct snmpd_target_stats snmpd_target_stats;
/* search path for config files */
const char *syspath = PATH_SYSCONFIG;
@ -361,7 +369,7 @@ snmp_pdu_auth_user(struct snmp_pdu *pdu)
* Check whether access to each of var bindings in the PDU is allowed based
* on the user credentials against the configured User groups & VACM views.
*/
static enum snmp_code
enum snmp_code
snmp_pdu_auth_access(struct snmp_pdu *pdu, int32_t *ip)
{
const char *uname;
@ -1838,14 +1846,14 @@ main(int argc, char *argv[])
exit(1);
}
snmp_send_trap(&oid_coldStart, (struct snmp_value *)NULL);
while ((m = TAILQ_FIRST(&modules_start)) != NULL) {
m->flags &= ~LM_ONSTARTLIST;
TAILQ_REMOVE(&modules_start, m, start);
lm_start(m);
}
snmp_send_trap(&oid_coldStart, (struct snmp_value *)NULL);
for (;;) {
#ifndef USE_LIBBEGEMOT
evEvent event;

View File

@ -31,7 +31,7 @@
.\"
.\" $Begemot: bsnmp/snmpd/snmpmod.3,v 1.14 2005/10/04 13:30:35 brandt_h Exp $
.\"
.Dd September 9, 2010
.Dd December 19, 2010
.Dt SNMPMOD 3
.Os
.Sh NAME
@ -83,6 +83,7 @@
.Nm snmp_output ,
.Nm snmp_send_port ,
.Nm snmp_send_trap ,
.Nm snmp_pdu_auth_access
.Nm string_save ,
.Nm string_commit ,
.Nm string_rollback ,
@ -102,6 +103,7 @@
.Nm index_compare_off ,
.Nm index_append ,
.Nm index_append_off,
.Nm snmpd_usmstats,
.Nm bsnmpd_get_usm_stats,
.Nm bsnmpd_reset_usm_stats,
.Nm usm_first_user,
@ -111,6 +113,25 @@
.Nm usm_delete_user,
.Nm usm_flush_users,
.Nm usm_user
.Nm snmpd_target_stat
.Nm bsnmpd_get_target_stats
.Nm target_first_address
.Nm target_next_address
.Nm target_new_address
.Nm target_activate_address
.Nm target_delete_address
.Nm target_first_param
.Nm target_next_param
.Nm target_new_param
.Nm target_delete_param
.Nm target_first_notify
.Nm target_next_notify
.Nm target_new_notify
.Nm target_delete_notify
.Nm target_flush_all
.Nm target_address
.Nm target_param
.Nm target_notify
.Nd "SNMP daemon loadable module interface"
.Sh LIBRARY
Begemot SNMP library
@ -201,6 +222,8 @@ Begemot SNMP library
.Fc
.Ft void
.Fn snmp_send_trap "const struct asn_oid *oid" "..."
.Ft enum snmp_code
.Fn snmp_pdu_auth_access "struct snmp_pdu *pdu" "int32_t *ip"
.Ft int
.Fn string_save "struct snmp_value *val" "struct snmp_context *ctx" "ssize_t req_size" "u_char **strp"
.Ft void
@ -239,6 +262,7 @@ Begemot SNMP library
.Fn index_append "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src"
.Ft void
.Fn index_append_off "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" "u_int off"
.Vt extern struct snmpd_usmstat snmpd_usmstats ;
.Ft struct snmpd_usmstat *
.Fn bsnmpd_get_usm_stats "void"
.Ft void
@ -256,6 +280,36 @@ Begemot SNMP library
.Ft void
.Fn usm_flush_users "void"
.Vt extern struct usm_user *usm_user;
.Ft struct snmpd_target_stats *
.Fn bsnmpd_get_target_stats "void"
.Ft struct target_address *
.Fn target_first_address "void"
.Ft struct target_address *
.Fn target_next_address "struct target_address *"
.Ft struct target_address *
.Fn target_new_address "char *"
.Ft int
.Fn target_activate_address "struct target_address *"
.Ft int
.Fn target_delete_address "struct target_address *"
.Ft struct target_param *
.Fn target_first_param "void"
.Ft struct target_param *
.Fn target_next_param "struct target_param *"
.Ft struct target_param *
.Fn target_new_param "char *"
.Ft int
.Fn target_delete_param "struct target_param *"
.Ft struct target_notify *
.Fn target_first_notify "void"
.Ft struct target_notify *
.Fn target_next_notify "struct target_notify *"
.Ft struct target_notify *
.Fn target_new_notify "char *"
.Ft int
.Fn target_delete_notify "struct target_notify *"
.Ft void
.Fn target_flush_all "void"
.Vt extern const struct asn_oid oid_usmUnknownEngineIDs;
.Vt extern const struct asn_oid oid_usmNotInTimeWindows;
.Sh DESCRIPTION
@ -603,7 +657,7 @@ struct usm_user {
struct snmp_user suser;
uint8_t user_engine_id[SNMP_ENGINE_ID_SIZ];
uint32_t user_engine_len;
char user_public[SNMP_USM_NAME_SIZ];
char user_public[SNMP_ADM_STR32_SIZ];
uint32_t user_public_len;
int32_t status;
int32_t type;
@ -640,6 +694,103 @@ and
or
.Li NULL
if an user with the specified name and engine id is not present in the list.
.Ss THE MANAGEMENT TARGET GROUP
The Management Target group holds target address information used when sending
SNMPv3 notifications.
.Pp
The scalar statistics of the Management Target group are held in the global
variable
.Va snmpd_target_stats :
.Bd -literal -offset indent
struct snmpd_target_stats {
uint32_t unavail_contexts;
uint32_t unknown_contexts;
};
.Ed
.Fn bsnmpd_get_target_stats
returns a pointer to the global structure containing the statistics.
.Pp
Three global lists of configured management target addresses, parameters and
notifications respectively are maintained by the daemon.
.Bd -literal -offset indent
struct target_address {
char name[SNMP_ADM_STR32_SIZ];
uint8_t address[SNMP_UDP_ADDR_SIZ];
int32_t timeout;
int32_t retry;
char taglist[SNMP_TAG_SIZ];
char paramname[SNMP_ADM_STR32_SIZ];
int32_t type;
int32_t socket;
int32_t status;
SLIST_ENTRY(target_address) ta;
};
.Ed
This structure represents a SNMPv3 Management Target address. Each time a SNMP
TRAP is send the daemon will send the Trap to all active Management Target
addresses in its global list.
.Bd -literal -offset indent
struct target_param {
char name[SNMP_ADM_STR32_SIZ];
int32_t mpmodel;
int32_t sec_model;
char secname[SNMP_ADM_STR32_SIZ];
enum snmp_usm_level sec_level;
int32_t type;
int32_t status;
SLIST_ENTRY(target_param) tp;
};
.Ed
This structure represents the information used to generate SNMP messages to the
associated SNMPv3 Management Target addresses.
.Bd -literal -offset indent
struct target_notify {
char name[SNMP_ADM_STR32_SIZ];
char taglist[SNMP_TAG_SIZ];
int32_t notify_type;
int32_t type;
int32_t status;
SLIST_ENTRY(target_notify) tn;
};
.Ed
This structure represents Notification Tag entries - SNMP notifications are sent
to the Target address for each entry in the Management Target Address list that
has a tag matching the specified tag in this structure.
.Pp
The daemon does not create or remove entries in the Management Target group
lists, it gives an interface to external loadable module(s) to manage the lists.
.Fn target_new_address
adds a target address entry, and
.Fn target_delete_address
deletes an existing entry from the target address list.
.Fn target_activate_address
creates a socket associated with the target address entry so that SNMP
notifications may actually be send to that target address.
.Fn target_first_address
will return a pointer to the first target address entry in the list, while
.Fn target_next_address
will return a pointer to the next target address of a given entry if one exists.
.Fn target_new_param
adds a target parameters' entry, and
.Fn target_delete_param
deletes an existing entry from the target parameters list.
.Fn target_first_param
will return a pointer to the first target parameters' entry in the list, while
.Fn target_next_param
will return a pointer to the next target parameters of a given entry if one
exists.
.Fn target_new_notify
adds a notification target entry, and
.Fn target_delete_notify
deletes an existing entry from the notification target list.
.Fn target_first_notify
will return a pointer to the first notification target entry in the list, while
.Fn target_next_notify
will return a pointer to the next notification target of a given entry if one
exists.
.Fn target_flush_all
is used to remove all configured data from the three global Management Target
Group lists.
.Ss WELL KNOWN OIDS
The global variable
.Va oid_zeroDotZero
@ -840,6 +991,14 @@ The arguments are the
identifying the trap and a NULL-terminated list of
.Vt struct snmp_value
pointers that are to be inserted into the trap binding list.
.Fn snmp_pdu_auth_access
verifies whether access to the object IDs contained in the
.Fa pdu
should be granted or denied, according to the configured View-Based Access
rules.
.Fa ip
contains the index of the first varbinding to which access was denied, or 0 if
access to all varbindings in the PDU is granted.
.Ss SIMPLE ACTION SUPPORT
For simple scalar variables that need no dependencies a number of support
functions is available to handle the set, commit, rollback and get.

View File

@ -5,6 +5,12 @@
*
* Author: Harti Brandt <harti@freebsd.org>
*
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were 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:
@ -454,6 +460,74 @@ struct vacm_context *vacm_next_context(struct vacm_context *);
struct vacm_context *vacm_add_context(char *, int32_t);
void vacm_flush_contexts(int32_t);
/*
* RFC 3413 SNMP Management Target & Notification MIB
*/
struct snmpd_target_stats {
uint32_t unavail_contexts;
uint32_t unknown_contexts;
};
#define SNMP_UDP_ADDR_SIZ 6
#define SNMP_TAG_SIZ (255 + 1)
struct target_address {
char name[SNMP_ADM_STR32_SIZ];
uint8_t address[SNMP_UDP_ADDR_SIZ];
int32_t timeout;
int32_t retry;
char taglist[SNMP_TAG_SIZ];
char paramname[SNMP_ADM_STR32_SIZ];
int32_t type;
int32_t socket;
int32_t status;
SLIST_ENTRY(target_address) ta;
};
SLIST_HEAD(target_addresslist, target_address);
struct target_param {
char name[SNMP_ADM_STR32_SIZ];
int32_t mpmodel;
int32_t sec_model;
char secname[SNMP_ADM_STR32_SIZ];
enum snmp_usm_level sec_level;
int32_t type;
int32_t status;
SLIST_ENTRY(target_param) tp;
};
SLIST_HEAD(target_paramlist, target_param);
struct target_notify {
char name[SNMP_ADM_STR32_SIZ];
char taglist[SNMP_TAG_SIZ];
int32_t notify_type;
int32_t type;
int32_t status;
SLIST_ENTRY(target_notify) tn;
};
SLIST_HEAD(target_notifylist, target_notify);
extern struct snmpd_target_stats snmpd_target_stats;
struct snmpd_target_stats *bsnmpd_get_target_stats(void);
struct target_address *target_first_address(void);
struct target_address *target_next_address(struct target_address *);
struct target_address *target_new_address(char *);
int target_activate_address(struct target_address *);
int target_delete_address(struct target_address *);
struct target_param *target_first_param(void);
struct target_param *target_next_param(struct target_param *);
struct target_param *target_new_param(char *);
int target_delete_param(struct target_param *);
struct target_notify *target_first_notify(void);
struct target_notify *target_next_notify(struct target_notify *);
struct target_notify *target_new_notify(char *);
int target_delete_notify (struct target_notify *);
void target_flush_all(void);
/*
* Well known OIDs
*/
@ -515,6 +589,7 @@ enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *,
void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *);
void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *,
const struct sockaddr *, socklen_t);
enum snmp_code snmp_pdu_auth_access(struct snmp_pdu *, int32_t *);
/* sending traps */
void snmp_send_trap(const struct asn_oid *, ...);

View File

@ -4,7 +4,13 @@
* All rights reserved.
*
* Author: Harti Brandt <harti@freebsd.org>
*
*
* Copyright (c) 2010 The FreeBSD Foundation
* All rights reserved.
*
* Portions of this software were 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:
@ -34,6 +40,7 @@
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/un.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
@ -52,6 +59,18 @@
struct trapsink_list trapsink_list = TAILQ_HEAD_INITIALIZER(trapsink_list);
/* List of target addresses */
struct target_addresslist target_addresslist =
SLIST_HEAD_INITIALIZER(target_addresslist);
/* List of target parameters */
struct target_paramlist target_paramlist =
SLIST_HEAD_INITIALIZER(target_paramlist);
/* List of notification targets */
struct target_notifylist target_notifylist =
SLIST_HEAD_INITIALIZER(target_notifylist);
static const struct asn_oid oid_begemotTrapSinkTable =
OIDX_begemotTrapSinkTable;
static const struct asn_oid oid_sysUpTime = OIDX_sysUpTime;
@ -398,57 +417,152 @@ op_trapsink(struct snmp_context *ctx, struct snmp_value *value,
return (SNMP_ERR_NOERROR);
}
static void
snmp_create_v1_trap(struct snmp_pdu *pdu, char *com,
const struct asn_oid *trap_oid)
{
memset(pdu, 0, sizeof(*pdu));
strcpy(pdu->community, com);
pdu->version = SNMP_V1;
pdu->type = SNMP_PDU_TRAP;
pdu->enterprise = systemg.object_id;
memcpy(pdu->agent_addr, snmpd.trap1addr, 4);
pdu->generic_trap = trap_oid->subs[trap_oid->len - 1] - 1;
pdu->specific_trap = 0;
pdu->time_stamp = get_ticks() - start_tick;
pdu->nbindings = 0;
}
static void
snmp_create_v2_trap(struct snmp_pdu *pdu, char *com,
const struct asn_oid *trap_oid)
{
memset(pdu, 0, sizeof(*pdu));
strcpy(pdu->community, com);
pdu->version = SNMP_V2c;
pdu->type = SNMP_PDU_TRAP2;
pdu->request_id = reqid_next(trap_reqid);
pdu->error_index = 0;
pdu->error_status = SNMP_ERR_NOERROR;
pdu->bindings[0].var = oid_sysUpTime;
pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0;
pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
pdu->bindings[0].v.uint32 = get_ticks() - start_tick;
pdu->bindings[1].var = oid_snmpTrapOID;
pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0;
pdu->bindings[1].syntax = SNMP_SYNTAX_OID;
pdu->bindings[1].v.oid = *trap_oid;
pdu->nbindings = 2;
}
static void
snmp_create_v3_trap(struct snmp_pdu *pdu, struct target_param *target,
const struct asn_oid *trap_oid)
{
uint64_t etime;
struct usm_user *usmuser;
memset(pdu, 0, sizeof(*pdu));
pdu->version = SNMP_V3;
pdu->type = SNMP_PDU_TRAP2;
pdu->request_id = reqid_next(trap_reqid);
pdu->error_index = 0;
pdu->error_status = SNMP_ERR_NOERROR;
pdu->bindings[0].var = oid_sysUpTime;
pdu->bindings[0].var.subs[pdu->bindings[0].var.len++] = 0;
pdu->bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
pdu->bindings[0].v.uint32 = get_ticks() - start_tick;
pdu->bindings[1].var = oid_snmpTrapOID;
pdu->bindings[1].var.subs[pdu->bindings[1].var.len++] = 0;
pdu->bindings[1].syntax = SNMP_SYNTAX_OID;
pdu->bindings[1].v.oid = *trap_oid;
pdu->nbindings = 2;
etime = (get_ticks() - start_tick) / 100ULL;
if (etime < INT32_MAX)
snmpd_engine.engine_time = etime;
else {
start_tick = get_ticks();
set_snmpd_engine();
snmpd_engine.engine_time = start_tick;
}
memcpy(pdu->engine.engine_id, snmpd_engine.engine_id,
snmpd_engine.engine_len);
pdu->engine.engine_len = snmpd_engine.engine_len;
pdu->engine.engine_boots = snmpd_engine.engine_boots;
pdu->engine.engine_time = snmpd_engine.engine_time;
pdu->engine.max_msg_size = snmpd_engine.max_msg_size;
strlcpy(pdu->user.sec_name, target->secname,
sizeof(pdu->user.sec_name));
pdu->security_model = target->sec_model;
pdu->context_engine_len = snmpd_engine.engine_len;
memcpy(pdu->context_engine, snmpd_engine.engine_id,
snmpd_engine.engine_len);
if (target->sec_model == SNMP_SECMODEL_USM &&
target->sec_level != SNMP_noAuthNoPriv) {
usmuser = usm_find_user(pdu->engine.engine_id,
pdu->engine.engine_len, pdu->user.sec_name);
if (usmuser != NULL) {
pdu->user.auth_proto = usmuser->suser.auth_proto;
pdu->user.priv_proto = usmuser->suser.priv_proto;
memcpy(pdu->user.auth_key, usmuser->suser.auth_key,
sizeof(pdu->user.auth_key));
memcpy(pdu->user.priv_key, usmuser->suser.priv_key,
sizeof(pdu->user.priv_key));
}
snmp_pdu_init_secparams(pdu);
}
}
void
snmp_send_trap(const struct asn_oid *trap_oid, ...)
{
struct snmp_pdu pdu;
struct trapsink *t;
const struct snmp_value *v;
struct target_notify *n;
struct target_address *ta;
struct target_param *tp;
va_list ap;
u_char *sndbuf;
char *tag;
size_t sndlen;
ssize_t len;
int32_t ip;
TAILQ_FOREACH(t, &trapsink_list, link) {
if (t->status != TRAPSINK_ACTIVE)
continue;
memset(&pdu, 0, sizeof(pdu));
strcpy(pdu.community, t->comm);
if (t->version == TRAPSINK_V1) {
pdu.version = SNMP_V1;
pdu.type = SNMP_PDU_TRAP;
pdu.enterprise = systemg.object_id;
memcpy(pdu.agent_addr, snmpd.trap1addr, 4);
pdu.generic_trap = trap_oid->subs[trap_oid->len - 1] - 1;
pdu.specific_trap = 0;
pdu.time_stamp = get_ticks() - start_tick;
pdu.nbindings = 0;
} else {
pdu.version = SNMP_V2c;
pdu.type = SNMP_PDU_TRAP2;
pdu.request_id = reqid_next(trap_reqid);
pdu.error_index = 0;
pdu.error_status = SNMP_ERR_NOERROR;
pdu.bindings[0].var = oid_sysUpTime;
pdu.bindings[0].var.subs[pdu.bindings[0].var.len++] = 0;
pdu.bindings[0].syntax = SNMP_SYNTAX_TIMETICKS;
pdu.bindings[0].v.uint32 = get_ticks() - start_tick;
pdu.bindings[1].var = oid_snmpTrapOID;
pdu.bindings[1].var.subs[pdu.bindings[1].var.len++] = 0;
pdu.bindings[1].syntax = SNMP_SYNTAX_OID;
pdu.bindings[1].v.oid = *trap_oid;
pdu.nbindings = 2;
}
if (t->version == TRAPSINK_V1)
snmp_create_v1_trap(&pdu, t->comm, trap_oid);
else
snmp_create_v2_trap(&pdu, t->comm, trap_oid);
va_start(ap, trap_oid);
while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
pdu.bindings[pdu.nbindings++] = *v;
va_end(ap);
if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) {
syslog(LOG_DEBUG, "send trap to %s failed: no access",
t->comm);
continue;
}
if ((sndbuf = buf_alloc(1)) == NULL) {
syslog(LOG_ERR, "trap send buffer: %m");
return;
@ -464,4 +578,339 @@ snmp_send_trap(const struct asn_oid *trap_oid, ...)
free(sndbuf);
}
SLIST_FOREACH(n, &target_notifylist, tn) {
if (n->status != RowStatus_active || n->taglist[0] == '\0')
continue;
SLIST_FOREACH(ta, &target_addresslist, ta)
if ((tag = strstr(ta->taglist, n->taglist)) != NULL &&
(tag[strlen(n->taglist)] == ' ' ||
tag[strlen(n->taglist)] == '\0' ||
tag[strlen(n->taglist)] == '\t' ||
tag[strlen(n->taglist)] == '\r' ||
tag[strlen(n->taglist)] == '\n') &&
ta->status == RowStatus_active)
break;
if (ta == NULL)
continue;
SLIST_FOREACH(tp, &target_paramlist, tp)
if (strcmp(tp->name, ta->paramname) == 0 &&
tp->status == 1)
break;
if (tp == NULL)
continue;
switch (tp->mpmodel) {
case SNMP_MPM_SNMP_V1:
snmp_create_v1_trap(&pdu, tp->secname, trap_oid);
break;
case SNMP_MPM_SNMP_V2c:
snmp_create_v2_trap(&pdu, tp->secname, trap_oid);
break;
case SNMP_MPM_SNMP_V3:
snmp_create_v3_trap(&pdu, tp, trap_oid);
break;
default:
continue;
}
va_start(ap, trap_oid);
while ((v = va_arg(ap, const struct snmp_value *)) != NULL)
pdu.bindings[pdu.nbindings++] = *v;
va_end(ap);
if (snmp_pdu_auth_access(&pdu, &ip) != SNMP_CODE_OK) {
syslog(LOG_DEBUG, "send trap to %s failed: no access",
t->comm);
continue;
}
if ((sndbuf = buf_alloc(1)) == NULL) {
syslog(LOG_ERR, "trap send buffer: %m");
return;
}
snmp_output(&pdu, sndbuf, &sndlen, "TRAP");
if ((len = send(ta->socket, sndbuf, sndlen, 0)) == -1)
syslog(LOG_ERR, "send: %m");
else if ((size_t)len != sndlen)
syslog(LOG_ERR, "send: short write %zu/%zu",
sndlen, (size_t)len);
free(sndbuf);
}
}
/*
* RFC 3413 SNMP Management Target MIB
*/
struct snmpd_target_stats *
bsnmpd_get_target_stats(void)
{
return (&snmpd_target_stats);
}
struct target_address *
target_first_address(void)
{
return (SLIST_FIRST(&target_addresslist));
}
struct target_address *
target_next_address(struct target_address *addrs)
{
if (addrs == NULL)
return (NULL);
return (SLIST_NEXT(addrs, ta));
}
struct target_address *
target_new_address(char *aname)
{
int cmp;
struct target_address *addrs, *temp, *prev;
SLIST_FOREACH(addrs, &target_addresslist, ta)
if (strcmp(aname, addrs->name) == 0)
return (NULL);
if ((addrs = (struct target_address *)malloc(sizeof(*addrs))) == NULL)
return (NULL);
memset(addrs, 0, sizeof(*addrs));
strlcpy(addrs->name, aname, sizeof(addrs->name));
addrs->timeout = 150;
addrs->retry = 3; /* XXX */
if ((prev = SLIST_FIRST(&target_addresslist)) == NULL ||
strcmp(aname, prev->name) < 0) {
SLIST_INSERT_HEAD(&target_addresslist, addrs, ta);
return (addrs);
}
SLIST_FOREACH(temp, &target_addresslist, ta) {
if ((cmp = strcmp(aname, temp->name)) <= 0)
break;
prev = temp;
}
if (temp == NULL || cmp < 0)
SLIST_INSERT_AFTER(prev, addrs, ta);
else if (cmp > 0)
SLIST_INSERT_AFTER(temp, addrs, ta);
else {
syslog(LOG_ERR, "Target address %s exists", addrs->name);
free(addrs);
return (NULL);
}
return (addrs);
}
int
target_activate_address(struct target_address *addrs)
{
struct sockaddr_in sa;
if ((addrs->socket = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
syslog(LOG_ERR, "socket(UDP): %m");
return (SNMP_ERR_RES_UNAVAIL);
}
(void)shutdown(addrs->socket, SHUT_RD);
sa.sin_len = sizeof(sa);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl((addrs->address[0] << 24) |
(addrs->address[1] << 16) | (addrs->address[2] << 8) |
(addrs->address[3] << 0));
sa.sin_port = htons(addrs->address[4]) << 8 |
htons(addrs->address[5]) << 0;
if (connect(addrs->socket, (struct sockaddr *)&sa, sa.sin_len) == -1) {
syslog(LOG_ERR, "connect(%s,%u): %m",
inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
(void)close(addrs->socket);
return (SNMP_ERR_GENERR);
}
addrs->status = RowStatus_active;
return (SNMP_ERR_NOERROR);
}
int
target_delete_address(struct target_address *addrs)
{
SLIST_REMOVE(&target_addresslist, addrs, target_address, ta);
if (addrs->status == RowStatus_active)
close(addrs->socket);
free(addrs);
return (0);
}
struct target_param *
target_first_param(void)
{
return (SLIST_FIRST(&target_paramlist));
}
struct target_param *
target_next_param(struct target_param *param)
{
if (param == NULL)
return (NULL);
return (SLIST_NEXT(param, tp));
}
struct target_param *
target_new_param(char *pname)
{
int cmp;
struct target_param *param, *temp, *prev;
SLIST_FOREACH(param, &target_paramlist, tp)
if (strcmp(pname, param->name) == 0)
return (NULL);
if ((param = (struct target_param *)malloc(sizeof(*param))) == NULL)
return (NULL);
memset(param, 0, sizeof(*param));
strlcpy(param->name, pname, sizeof(param->name));
if ((prev = SLIST_FIRST(&target_paramlist)) == NULL ||
strcmp(pname, prev->name) < 0) {
SLIST_INSERT_HEAD(&target_paramlist, param, tp);
return (param);
}
SLIST_FOREACH(temp, &target_paramlist, tp) {
if ((cmp = strcmp(pname, temp->name)) <= 0)
break;
prev = temp;
}
if (temp == NULL || cmp < 0)
SLIST_INSERT_AFTER(prev, param, tp);
else if (cmp > 0)
SLIST_INSERT_AFTER(temp, param, tp);
else {
syslog(LOG_ERR, "Target parameter %s exists", param->name);
free(param);
return (NULL);
}
return (param);
}
int
target_delete_param(struct target_param *param)
{
SLIST_REMOVE(&target_paramlist, param, target_param, tp);
free(param);
return (0);
}
struct target_notify *
target_first_notify(void)
{
return (SLIST_FIRST(&target_notifylist));
}
struct target_notify *
target_next_notify(struct target_notify *notify)
{
if (notify == NULL)
return (NULL);
return (SLIST_NEXT(notify, tn));
}
struct target_notify *
target_new_notify(char *nname)
{
int cmp;
struct target_notify *notify, *temp, *prev;
SLIST_FOREACH(notify, &target_notifylist, tn)
if (strcmp(nname, notify->name) == 0)
return (NULL);
if ((notify = (struct target_notify *)malloc(sizeof(*notify))) == NULL)
return (NULL);
memset(notify, 0, sizeof(*notify));
strlcpy(notify->name, nname, sizeof(notify->name));
if ((prev = SLIST_FIRST(&target_notifylist)) == NULL ||
strcmp(nname, prev->name) < 0) {
SLIST_INSERT_HEAD(&target_notifylist, notify, tn);
return (notify);
}
SLIST_FOREACH(temp, &target_notifylist, tn) {
if ((cmp = strcmp(nname, temp->name)) <= 0)
break;
prev = temp;
}
if (temp == NULL || cmp < 0)
SLIST_INSERT_AFTER(prev, notify, tn);
else if (cmp > 0)
SLIST_INSERT_AFTER(temp, notify, tn);
else {
syslog(LOG_ERR, "Notification target %s exists", notify->name);
free(notify);
return (NULL);
}
return (notify);
}
int
target_delete_notify(struct target_notify *notify)
{
SLIST_REMOVE(&target_notifylist, notify, target_notify, tn);
free(notify);
return (0);
}
void
target_flush_all(void)
{
struct target_address *addrs;
struct target_param *param;
struct target_notify *notify;
while ((addrs = SLIST_FIRST(&target_addresslist)) != NULL) {
SLIST_REMOVE_HEAD(&target_addresslist, ta);
if (addrs->status == RowStatus_active)
close(addrs->socket);
free(addrs);
}
SLIST_INIT(&target_addresslist);
while ((param = SLIST_FIRST(&target_paramlist)) != NULL) {
SLIST_REMOVE_HEAD(&target_paramlist, tp);
free(param);
}
SLIST_INIT(&target_paramlist);
while ((notify = SLIST_FIRST(&target_notifylist)) != NULL) {
SLIST_REMOVE_HEAD(&target_notifylist, tn);
free(notify);
}
SLIST_INIT(&target_notifylist);
}

View File

@ -30,6 +30,9 @@
#
# System group and private Begemot SNMPd MIB.
#
include "tc.def"
(1 internet
(2 mgmt
(1 mibII

View File

@ -10,6 +10,10 @@ CONTRIB= ${.CURDIR}/../../../contrib/bsnmp/lib
LIB= bsnmp
SHLIBDIR?= /lib
FILESGROUPS+= DEFS
DEFSDIR?= ${SHAREDIR}/snmp/defs
DEFS= tc.def
CFLAGS+= -I${CONTRIB} -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY
CFLAGS+= -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DQUADFMT='"llu"' -DQUADXFMT='"llx"'

View File

@ -25,6 +25,7 @@ BMIBSDIR= ${SHAREDIR}/snmp/mibs
DEFS= tree.def
DEFSDIR= ${SHAREDIR}/snmp/defs
CFLAGS+= -DSNMPTREE_TYPES
CFLAGS+= -I${CONTRIB}/lib -I${CONTRIB}/snmpd -I. -DUSE_LIBBEGEMOT
CFLAGS+= -DUSE_TCPWRAPPERS -DQUADFMT='"llu"' -DQUADXFMT='"llx"'
CFLAGS+= -DHAVE_STDINT_H -DHAVE_INTTYPES_H -DHAVE_ERR_H -DHAVE_STRLCPY

View File

@ -13,6 +13,7 @@ SUBDIR= ${_snmp_atm} \
snmp_hostres \
snmp_mibII \
snmp_pf \
snmp_target \
snmp_usm \
snmp_vacm \
snmp_wlan

View File

@ -26,22 +26,13 @@
# $FreeBSD$
#
#include "tc.def"
include "tc.def"
typedef TruthValue ENUM (
1 true
2 false
)
typedef RowStatus ENUM (
1 active
2 notInService
3 notReady
4 createAndGo
5 createAndWait
6 destroy
)
typedef StpPortState ENUM (
1 disabled
2 blocking

View File

@ -0,0 +1,20 @@
# $FreeBSD$
#
# Author: Shteryana Shopova <syrinx@freebsd.org>
CONTRIB= ${.CURDIR}/../../../../contrib/bsnmp
.PATH: ${CONTRIB}/snmp_target
MOD= target
SRCS= target_snmp.c
XSYM= snmpTargetMIB snmpNotificationMIB snmpUDPDomain
MAN= snmp_target.3
CFLAGS+= -I${CONTRIB}/lib -I${CONTRIB}/snmpd -DSNMPTREE_TYPES
CFLAGS+= -DHAVE_ERR_H -DHAVE_GETADDRINFO -DHAVE_STRLCPY -DHAVE_SYS_TREE_H
DEFS= ${MOD}_tree.def
BMIBS=
.include <bsd.snmpmod.mk>

View File

@ -29,14 +29,7 @@
# $FreeBSD$
#
typedef RowStatus ENUM (
1 active
2 notInService
3 notReady
4 createAndGo
5 createAndWait
6 destroy
)
include "tc.def"
typedef TruthValue ENUM (
1 true