summaryrefslogtreecommitdiffstats
path: root/contrib/bsnmp/snmpd
diff options
context:
space:
mode:
authorsyrinx <syrinx@FreeBSD.org>2010-12-20 17:13:14 +0000
committersyrinx <syrinx@FreeBSD.org>2010-12-20 17:13:14 +0000
commitcdf73327e5ede68524c23f9fb281bbbd7c771b07 (patch)
tree5b7dd1db00389b1d0504f34a299b48339c9b9aac /contrib/bsnmp/snmpd
parent0f810ef0a25b4d64ffe05b47b5dfd30d73167b71 (diff)
downloadFreeBSD-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/snmpd')
-rw-r--r--contrib/bsnmp/snmpd/main.c14
-rw-r--r--contrib/bsnmp/snmpd/snmpmod.3163
-rw-r--r--contrib/bsnmp/snmpd/snmpmod.h75
-rw-r--r--contrib/bsnmp/snmpd/trap.c513
-rw-r--r--contrib/bsnmp/snmpd/tree.def3
5 files changed, 731 insertions, 37 deletions
diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c
index e008bf7..c25fff2 100644
--- a/contrib/bsnmp/snmpd/main.c
+++ b/contrib/bsnmp/snmpd/main.c
@@ -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;
diff --git a/contrib/bsnmp/snmpd/snmpmod.3 b/contrib/bsnmp/snmpd/snmpmod.3
index a142069..38b3cf1 100644
--- a/contrib/bsnmp/snmpd/snmpmod.3
+++ b/contrib/bsnmp/snmpd/snmpmod.3
@@ -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.
diff --git a/contrib/bsnmp/snmpd/snmpmod.h b/contrib/bsnmp/snmpd/snmpmod.h
index 379070c..9025366 100644
--- a/contrib/bsnmp/snmpd/snmpmod.h
+++ b/contrib/bsnmp/snmpd/snmpmod.h
@@ -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:
@@ -455,6 +461,74 @@ 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
*/
extern const struct asn_oid oid_zeroDotZero;
@@ -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 *, ...);
diff --git a/contrib/bsnmp/snmpd/trap.c b/contrib/bsnmp/snmpd/trap.c
index 18164cf..d13f902 100644
--- a/contrib/bsnmp/snmpd/trap.c
+++ b/contrib/bsnmp/snmpd/trap.c
@@ -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);
}
diff --git a/contrib/bsnmp/snmpd/tree.def b/contrib/bsnmp/snmpd/tree.def
index 00672eb..f4d8579 100644
--- a/contrib/bsnmp/snmpd/tree.def
+++ b/contrib/bsnmp/snmpd/tree.def
@@ -30,6 +30,9 @@
#
# System group and private Begemot SNMPd MIB.
#
+
+include "tc.def"
+
(1 internet
(2 mgmt
(1 mibII
OpenPOWER on IntegriCloud