In order to get trap support back into relayd libagentx needs to get
notify support. Here's my interpretation on the matter. Relayd itself
still needs a proper NOTIFICATION-TYPE definition before that can be
implemented, but that shouldn't stop this diff.
I already have an OK rob@, but additional feedback welcome.
Since this has an additional manpage and library bump: any good/bad
timeframe for committing this?
martijn@
Index: Makefile
===================================================================
RCS file: /cvs/src/lib/libagentx/Makefile,v
retrieving revision 1.4
diff -u -p -r1.4 Makefile
--- Makefile 26 Oct 2020 15:57:03 -0000 1.4
+++ Makefile 4 Jan 2021 17:34:01 -0000
@@ -4,7 +4,7 @@ LIB= agentx
SRCS= ax.c agentx.c agentx_log.c
HDRS= agentx.h
-MAN= agentx.3
+MAN= agentx.3 agentx_notify.3
CFLAGS+= -Wall
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
Index: Symbols.list
===================================================================
RCS file: /cvs/src/lib/libagentx/Symbols.list,v
retrieving revision 1.3
diff -u -p -r1.3 Symbols.list
--- Symbols.list 27 Oct 2020 18:24:01 -0000 1.3
+++ Symbols.list 4 Jan 2021 17:34:01 -0000
@@ -29,6 +29,23 @@ agentx_index_oid_dynamic
agentx_index_noid_dynamic
agentx_index_ipaddress_dynamic
agentx_index_free
+agentx_notify
+agentx_notify_counter32
+agentx_notify_counter64
+agentx_notify_gauge32
+agentx_notify_index
+agentx_notify_integer
+agentx_notify_ipaddress
+agentx_notify_nstring
+agentx_notify_null
+agentx_notify_object
+agentx_notify_oid
+agentx_notify_opaque
+agentx_notify_printf
+agentx_notify_send
+agentx_notify_string
+agentx_notify_timeticks
+agentx_notify_unsigned32
agentx_object
agentx_object_free
agentx_varbind_integer
Index: agentx.3
===================================================================
RCS file: /cvs/src/lib/libagentx/agentx.3,v
retrieving revision 1.5
diff -u -p -r1.5 agentx.3
--- agentx.3 3 Dec 2020 22:47:21 -0000 1.5
+++ agentx.3 4 Jan 2021 17:34:01 -0000
@@ -621,6 +621,7 @@ in timeticks.
.El
.Sh SEE ALSO
.Xr snmp 1 ,
+.Xr agentx_notify 3 ,
.Xr snmpd 8
.Sh STANDARDS
.Rs
Index: agentx.c
===================================================================
RCS file: /cvs/src/lib/libagentx/agentx.c,v
retrieving revision 1.8
diff -u -p -r1.8 agentx.c
--- agentx.c 27 Oct 2020 18:24:01 -0000 1.8
+++ agentx.c 4 Jan 2021 17:34:01 -0000
@@ -87,6 +87,18 @@ struct agentx_object {
TAILQ_ENTRY(agentx_object) axo_axr_objects;
};
+struct agentx_notify {
+ struct agentx_context *axn_axc;
+ struct ax_varbind *axn_vb;
+ struct ax_oid axn_trapoid;
+ uint32_t axn_uptime;
+ int axn_sent;
+ size_t axn_nvb;
+ size_t axn_vbsize;
+ int axn_fail;
+ TAILQ_ENTRY(agentx_notify) axn_axc_notifications;
+};
+
struct agentx_varbind {
struct agentx_get *axv_axg;
struct agentx_object *axv_axo;
@@ -160,6 +172,9 @@ static void agentx_object_free_finalize(
static void agentx_object_reset(struct agentx_object *);
static int agentx_object_cmp(struct agentx_object *,
struct agentx_object *);
+static int agentx_notify_add(struct agentx_notify *, const uint32_t [],
size_t);
+static int agentx_notify_finalize(struct ax_pdu *, void *);
+static void agentx_notify_free(struct agentx_notify *);
static void agentx_get_start(struct agentx_context *,
struct ax_pdu *);
static void agentx_get_finalize(struct agentx_get *);
@@ -596,6 +611,7 @@ agentx_context(struct agentx_session *ax
axc->axc_dstate = AX_DSTATE_OPEN;
TAILQ_INIT(&(axc->axc_agentcaps));
TAILQ_INIT(&(axc->axc_regions));
+ TAILQ_INIT(&(axc->axc_notifications));
TAILQ_INSERT_HEAD(&(axs->axs_contexts), axc, axc_axs_contexts);
@@ -690,6 +706,7 @@ agentx_context_free(struct agentx_contex
{
struct agentx_agentcaps *axa, *tsaa;
struct agentx_region *axr, *tsar;
+ struct agentx_notify *axn, *taxn;
if (axc == NULL)
return;
@@ -700,6 +717,14 @@ agentx_context_free(struct agentx_contex
#endif
axc->axc_dstate = AX_DSTATE_CLOSE;
+ TAILQ_FOREACH_SAFE(axn, &(axc->axc_notifications),
+ axn_axc_notifications, taxn) {
+ axn->axn_axc = NULL;
+ TAILQ_REMOVE(&(axc->axc_notifications), axn,
+ axn_axc_notifications);
+ if (axn->axn_sent)
+ agentx_notify_free(axn);
+ }
TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps,
tsaa) {
if (axa->axa_dstate != AX_DSTATE_CLOSE)
@@ -720,6 +745,9 @@ agentx_context_free_finalize(struct agen
if (axc->axc_dstate != AX_DSTATE_CLOSE)
agentx_log_axc_fatalx(axc, "%s: unexpected context free",
__func__);
+ if (!TAILQ_EMPTY(&(axc->axc_notifications)))
+ agentx_log_axc_fatalx(axc, "%s: notifications not empty",
+ __func__);
#endif
if (!TAILQ_EMPTY(&(axc->axc_regions)) ||
!TAILQ_EMPTY(&(axc->axc_agentcaps)))
@@ -734,11 +762,20 @@ agentx_context_reset(struct agentx_conte
{
struct agentx_agentcaps *axa, *tsaa;
struct agentx_region *axr, *tsar;
+ struct agentx_notify *axn, *taxn;
axc->axc_cstate = AX_CSTATE_CLOSE;
axc->axc_sysuptimespec.tv_sec = 0;
axc->axc_sysuptimespec.tv_nsec = 0;
+ TAILQ_FOREACH_SAFE(axn, &(axc->axc_notifications),
+ axn_axc_notifications, taxn) {
+ axn->axn_axc = NULL;
+ TAILQ_REMOVE(&(axc->axc_notifications), axn,
+ axn_axc_notifications);
+ if (axn->axn_sent)
+ agentx_notify_free(axn);
+ }
TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, tsaa)
agentx_agentcaps_reset(axa);
TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, tsar)
@@ -2473,6 +2510,379 @@ agentx_object_implied(struct agentx_obje
__func__);
#endif
return 0;
+}
+
+struct agentx_notify *
+agentx_notify(struct agentx_context *axc, const uint32_t oid[], size_t oidlen)
+{
+ struct agentx_notify *axn;
+ size_t i;
+
+ if (axc->axc_dstate == AX_DSTATE_CLOSE)
+ agentx_log_axc_fatalx(axc, "%s: use after free", __func__);
+
+ if ((axn = calloc(1, sizeof(*axn))) == NULL)
+ return NULL;
+ axn->axn_axc = axc;
+ TAILQ_INSERT_TAIL(&(axc->axc_notifications), axn,
+ axn_axc_notifications);
+
+ for (i = 0; i < oidlen; i++)
+ axn->axn_trapoid.aoi_id[i] = oid[i];
+ axn->axn_trapoid.aoi_idlen = oidlen;
+ if ((axn->axn_uptime = agentx_context_uptime(axc)) == 0) {
+ agentx_notify_free(axn);
+ errno = ENOTCONN;
+ return NULL;
+ }
+
+ agentx_notify_timeticks(axn, AGENTX_OID(AGENTX_SYSUPTIME, 0),
+ axn->axn_uptime);
+ agentx_notify_oid(axn, AGENTX_OID(AGENTX_SNMPTRAPOID, 0), oid, oidlen);
+
+ if (axn->axn_fail) {
+ agentx_notify_free(axn);
+ return NULL;
+ }
+ return axn;
+}
+
+void
+agentx_notify_integer(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, int32_t value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_INTEGER;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_int32 = value;
+}
+
+void
+agentx_notify_string(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const char *value)
+{
+ agentx_notify_nstring(axn, oid, oidlen, value, strlen(value));
+}
+
+void
+agentx_notify_nstring(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const char *value, size_t slen)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ if ((axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string =
+ malloc(slen)) == NULL) {
+ agentx_log_axc_warnx(axn->axn_axc, "Failed to bind string to "
+ "notify");
+ axn->axn_fail = 1;
+ return;
+ }
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_OCTETSTRING;
+ memcpy(axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string, value,
+ slen);
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_ostring.aos_slen = slen;
+}
+
+void
+agentx_notify_printf(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const char *fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ va_start(ap, fmt);
+ r = vasprintf((char **)
+ &(axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string),
+ fmt, ap);
+ va_end(ap);
+
+ if (r == -1) {
+ agentx_log_axc_warn(axn->axn_axc, "Failed to bind string to "
+ "notify");
+ axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string =
+ NULL;
+ axn->axn_fail = 1;
+ return;
+ }
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_OCTETSTRING;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_ostring.aos_slen = r;
+}
+
+void
+agentx_notify_null(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb++].avb_type = AX_DATA_TYPE_NULL;
+}
+
+void
+agentx_notify_oid(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const uint32_t value[], size_t vlen)
+{
+ size_t i;
+
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_OID;
+ for (i = 0; i < vlen; i++)
+ axn->axn_vb[axn->axn_nvb].avb_data.avb_oid.aoi_id[i] = value[i];
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_oid.aoi_idlen = vlen;
+}
+
+void
+agentx_notify_object(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, struct agentx_object *axo)
+{
+ agentx_notify_oid(axn, oid, oidlen, axo->axo_oid.aoi_id,
+ axo->axo_oid.aoi_idlen);
+}
+
+void
+agentx_notify_index(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, struct agentx_index *axi)
+{
+ agentx_notify_oid(axn, oid, oidlen, axi->axi_vb.avb_oid.aoi_id,
+ axi->axi_vb.avb_oid.aoi_idlen);
+}
+
+void
+agentx_notify_ipaddress(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const struct in_addr *value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ if ((axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string =
+ malloc(4)) == NULL) {
+ agentx_log_axc_warn(axn->axn_axc, "Couldn't bind ipaddress to"
+ "notify");
+ axn->axn_fail = 1;
+ return;
+ }
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_IPADDRESS;
+ memcpy(axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string,
+ value, 4);
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_ostring.aos_slen = 4;
+}
+
+void
+agentx_notify_counter32(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, uint32_t value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_COUNTER32;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_uint32 = value;
+}
+
+void
+agentx_notify_gauge32(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, uint32_t value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_GAUGE32;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_uint32 = value;
+}
+
+void
+agentx_notify_unsigned32(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, uint32_t value)
+{
+ agentx_notify_gauge32(axn, oid, oidlen, value);
+}
+
+void
+agentx_notify_timeticks(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, uint32_t value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_TIMETICKS;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_uint32 = value;
+}
+
+void
+agentx_notify_opaque(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, const char *value, size_t slen)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ if ((axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string =
+ malloc(slen)) == NULL) {
+ agentx_log_axc_warn(axn->axn_axc, "Failed to bind opaque to "
+ "notify");
+ axn->axn_fail = 1;
+ return;
+ }
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_OPAQUE;
+ memcpy(axn->axn_vb[axn->axn_nvb].avb_data.avb_ostring.aos_string, value,
+ slen);
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_ostring.aos_slen = slen;
+}
+
+void
+agentx_notify_counter64(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen, uint64_t value)
+{
+ if (agentx_notify_add(axn, oid, oidlen) == -1)
+ return;
+
+ axn->axn_vb[axn->axn_nvb].avb_type = AX_DATA_TYPE_COUNTER64;
+ axn->axn_vb[axn->axn_nvb++].avb_data.avb_uint64 = value;
+}
+
+void
+agentx_notify_send(struct agentx_notify *axn)
+{
+ struct agentx_context *axc = axn->axn_axc;
+ struct agentx_session *axs;
+ struct agentx *ax;
+ uint32_t packetid;
+ char *logmsg = NULL;
+ size_t i;
+ int fail = 0;
+
+ if (axn->axn_fail || axc == NULL) {
+ agentx_log_axc_warn(axc, "Failed to send notify: %s: %s",
+ ax_oid2string(&(axn->axn_trapoid)),
+ axn->axn_fail ? "Prior error" : "Connection reset");
+ agentx_notify_free(axn);
+ return;
+ }
+ axs = axc->axc_axs;
+ ax = axs->axs_ax;
+
+ if ((packetid = ax_notify(ax->ax_ax, axs->axs_id,
+ AGENTX_CONTEXT_CTX(axc), axn->axn_vb, axn->axn_nvb)) == 0) {
+ agentx_log_axc_warn(axc, "Couldn't generate %s: %s",
+ ax_oid2string(&(axn->axn_trapoid)),
+ ax_pdutype2string(AX_PDU_TYPE_NOTIFY));
+ agentx_notify_free(axn);
+ return;
+ }
+
+ for (i = 2; i < axn->axn_nvb; i++) {
+ if (i == 2)
+ fail |= agentx_strcat(&logmsg, " {");
+ else
+ fail |= agentx_strcat(&logmsg, ",{");
+ fail |= agentx_strcat(&logmsg,
+ ax_varbind2string(&(axn->axn_vb[i])));
+ fail |= agentx_strcat(&logmsg, "}");
+ if (fail)
+ break;
+ }
+ if (fail)
+ agentx_log_axc_warn(axc, "Failed to generate notify log");
+ else {
+ agentx_log_axc_debug(axc, "Notify %s(%u):%s",
+ ax_oid2string(&(axn->axn_trapoid)), axn->axn_uptime,
+ logmsg);
+ }
+ free(logmsg);
+ agentx_log_axc_info(axc, "Notify %s(%u): sent",
+ ax_oid2string(&(axn->axn_trapoid)), axn->axn_uptime);
+ axn->axn_sent = 1;
+ if (agentx_request(ax, packetid, agentx_notify_finalize, axn) == -1)
+ agentx_notify_free(axn);
+}
+
+static int
+agentx_notify_add(struct agentx_notify *axn, const uint32_t oid[],
+ size_t oidlen)
+{
+ struct ax_varbind *vb;
+ size_t i;
+
+ if (oidlen < 1) {
+#ifdef AX_DEBUG
+ agentx_log_axc_fatalx(axn->axn_axc, "%s: oidlen == 0",
+ __func__);
+#else
+ agentx_log_axc_warnx(axn->axn_axc, "%s: oidlen == 0", __func__);
+ axn->axn_fail = 1;
+ return -1;
+#endif
+ }
+ if (oidlen > AGENTX_OID_MAX_LEN) {
+#ifdef AX_DEBUG
+ agentx_log_axc_fatalx(axn->axn_axc, "%s: oidlen > %d", __func__,
+ AGENTX_OID_MAX_LEN);
+#else
+ agentx_log_axc_warnx(axn->axn_axc, "%s: oidlen > %d", __func__,
+ AGENTX_OID_MAX_LEN);
+ axn->axn_fail = 1;
+ return -1;
+#endif
+ }
+
+ if (axn->axn_fail)
+ return -1;
+
+ if (axn->axn_nvb == axn->axn_vbsize) {
+ if ((vb = recallocarray(axn->axn_vb, axn->axn_vbsize,
+ axn->axn_vbsize + 5, sizeof (*vb))) == NULL) {
+ agentx_log_axc_warnx(axn->axn_axc, "Failed to add "
+ "varbind to notify");
+ axn->axn_fail = 1;
+ return -1;
+ }
+ axn->axn_vb = vb;
+ axn->axn_vbsize += 5;
+ }
+
+ for (i = 0; i < oidlen; i++)
+ axn->axn_vb[axn->axn_nvb].avb_oid.aoi_id[i] = oid[i];
+ axn->axn_vb[axn->axn_nvb].avb_oid.aoi_idlen = oidlen;
+
+ return 0;
+}
+
+static int
+agentx_notify_finalize(struct ax_pdu *pdu, void *cookie)
+{
+ struct agentx_notify *axn = cookie;
+ struct agentx_context *axc = axn->axn_axc;
+
+ if (pdu->ap_payload.ap_response.ap_error != AX_PDU_ERROR_NOERROR)
+ agentx_log_axc_warnx(axc, "Failed to send notify %s(%u): %s",
+ ax_oid2string(&(axn->axn_trapoid)), axn->axn_uptime,
+ ax_error2string(pdu->ap_payload.ap_response.ap_error));
+ else
+ agentx_log_axc_info(axc, "notify sent %s(%u)",
+ ax_oid2string(&(axn->axn_trapoid)), axn->axn_uptime);
+
+ agentx_notify_free(axn);
+ return 0;
+}
+
+static void
+agentx_notify_free(struct agentx_notify *axn)
+{
+ size_t i;
+
+ for (i = 0; i < axn->axn_nvb; i++)
+ ax_varbind_free(&(axn->axn_vb[i]));
+ free(axn->axn_vb);
+ if (axn->axn_axc != NULL)
+ TAILQ_REMOVE(&(axn->axn_axc->axc_notifications), axn,
+ axn_axc_notifications);
+ free(axn);
}
static void
Index: agentx.h
===================================================================
RCS file: /cvs/src/lib/libagentx/agentx.h,v
retrieving revision 1.5
diff -u -p -r1.5 agentx.h
--- agentx.h 27 Oct 2020 18:24:01 -0000 1.5
+++ agentx.h 4 Jan 2021 17:34:01 -0000
@@ -27,6 +27,7 @@ struct agentx_agentcaps;
struct agentx_region;
struct agentx_index;
struct agentx_object;
+struct agentx_notify;
struct agentx_varbind;
enum agentx_request_type {
@@ -40,6 +41,8 @@ enum agentx_request_type {
#define AGENTX_OID_INDEX_MAX_LEN 10
#define AGENTX_MIB2 1, 3, 6, 1, 2, 1
#define AGENTX_ENTERPRISES 1, 3, 6, 1, 4, 1
+#define AGENTX_SYSUPTIME AGENTX_MIB2, 1, 3
+#define AGENTX_SNMPTRAPOID 1, 3, 6, 1, 6, 3, 1, 1, 4, 1
#define AGENTX_OID(...) (uint32_t []) { __VA_ARGS__ }, \
(sizeof((uint32_t []) { __VA_ARGS__ }) / sizeof(uint32_t))
@@ -147,3 +150,36 @@ void agentx_varbind_set_index_object(str
struct agentx_index *, struct agentx_object *);
void agentx_varbind_set_index_ipaddress(struct agentx_varbind *,
struct agentx_index *, const struct in_addr *);
+
+struct agentx_notify *agentx_notify(struct agentx_context *, const uint32_t[],
+ size_t);
+void agentx_notify_integer(struct agentx_notify *, const uint32_t[], size_t,
+ int32_t);
+void agentx_notify_string(struct agentx_notify *, const uint32_t[], size_t,
+ const char *);
+void agentx_notify_nstring(struct agentx_notify *, const uint32_t[], size_t,
+ const char *, size_t);
+void agentx_notify_printf(struct agentx_notify *, const uint32_t[], size_t,
+ const char *, ...) __attribute__((__format__ (printf, 4, 5)));
+void agentx_notify_null(struct agentx_notify *, const uint32_t[], size_t);
+void agentx_notify_oid(struct agentx_notify *, const uint32_t[], size_t,
+ const uint32_t[], size_t);
+void agentx_notify_object(struct agentx_notify *, const uint32_t[], size_t,
+ struct agentx_object *);
+void agentx_notify_index(struct agentx_notify *, const uint32_t[], size_t,
+ struct agentx_index *);
+void agentx_notify_ipaddress(struct agentx_notify *, const uint32_t[], size_t,
+ const struct in_addr *);
+void agentx_notify_counter32(struct agentx_notify *, const uint32_t[], size_t,
+ uint32_t);
+void agentx_notify_gauge32(struct agentx_notify *, const uint32_t[], size_t,
+ uint32_t);
+void agentx_notify_unsigned32(struct agentx_notify *, const uint32_t[], size_t,
+ uint32_t);
+void agentx_notify_timeticks(struct agentx_notify *, const uint32_t[], size_t,
+ uint32_t);
+void agentx_notify_opaque(struct agentx_notify *, const uint32_t[], size_t,
+ const char *, size_t);
+void agentx_notify_counter64(struct agentx_notify *, const uint32_t[], size_t,
+ uint64_t);
+void agentx_notify_send(struct agentx_notify *);
Index: agentx_internal.h
===================================================================
RCS file: /cvs/src/lib/libagentx/agentx_internal.h,v
retrieving revision 1.2
diff -u -p -r1.2 agentx_internal.h
--- agentx_internal.h 26 Oct 2020 16:02:16 -0000 1.2
+++ agentx_internal.h 4 Jan 2021 17:34:01 -0000
@@ -67,6 +67,7 @@ struct agentx_context {
enum agentx_dstate axc_dstate;
TAILQ_HEAD(, agentx_agentcaps) axc_agentcaps;
TAILQ_HEAD(, agentx_region) axc_regions;
+ TAILQ_HEAD(, agentx_notify) axc_notifications;
RB_HEAD(axc_objects, agentx_object) axc_objects;
TAILQ_ENTRY(agentx_context) axc_axs_contexts;
};
Index: agentx_notify.3
===================================================================
RCS file: agentx_notify.3
diff -N agentx_notify.3
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ agentx_notify.3 4 Jan 2021 17:34:01 -0000
@@ -0,0 +1,177 @@
+.\" $OpenBSD: agentx.3,v 1.5 2020/12/03 22:47:21 jmc Exp $
+.\"
+.\" Copyright (c) 2020 Martijn van Duren <[email protected]>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: December 3 2020 $
+.Dt AGENTX_NOTIFY 3
+.Os
+.Sh NAME
+.Nm agentx_notify
+.Nm agentx_notify_integer
+.Nm agentx_notify_string
+.Nm agentx_notify_nstring
+.Nm agentx_notify_printf
+.Nm agentx_notify_null
+.Nm agentx_notify_oid
+.Nm agentx_notify_object
+.Nm agentx_notify_index
+.Nm agentx_notify_ipaddress
+.Nm agentx_notify_counter32
+.Nm agentx_notify_gauge32
+.Nm agentx_notify_unsigned32
+.Nm agentx_notify_timeticks
+.Nm agentx_notify_opaque
+.Nm agentx_notify_counter64
+.Nm agentx_notify_send
+.Sh SYNOPSIS
+.In agentx.h
+.Ft struct agentx_notify *
+.Fo agentx_notify
+.Fa "struct agentx_context *axc" "const uint32_t trapoid[]" "size_t oidlen"
+.Fc
+.Ft void
+.Fo agentx_notify_integer
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "int32_t value"
+.Fc
+.Ft void
+.Fo agentx_notify_string
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const char *string"
+.Fc
+.Ft void
+.Fo agentx_notify_nstring
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const char *string" "size_t slen"
+.Fc
+.Ft void
+.Fo agentx_notify_printf
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const char *fmt" ...
+.Fc
+.Ft void
+.Fo agentx_notify_null
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fc
+.Ft void
+.Fo agentx_notify_oid
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const uint32_t oidvalue[]" "size_t oidvlen"
+.Fc
+.Ft void
+.Fo agentx_notify_object
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "struct agentx_object *axo"
+.Fc
+.Ft void
+.Fo agentx_notify_index
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "struct agentx_index *axi"
+.Fc
+.Ft void
+.Fo agentx_notify_ipaddress
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const struct in_addr *addr"
+.Fc
+.Ft void
+.Fo agentx_notify_counter32
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "uint32_t value"
+.Fc
+.Ft void
+.Fo agentx_notify_gauge32
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "uint32_t value"
+.Fc
+.Ft void
+.Fo agentx_notify_unsigned32
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "uint32_t value"
+.Fc
+.Ft void
+.Fo agentx_notify_timeticks
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "uint32_t value"
+.Fc
+.Ft void
+.Fo agentx_notify_opaque
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "const char *string" "size_t slen"
+.Fc
+.Ft void
+.Fo agentx_notify_counter64
+.Fa "struct agentx_notify *axn" "const uint32_t oid[]" "size_t oidlen"
+.Fa "uint64_t value"
+.Fc
+.Ft void
+.Fn agentx_notify_send "struct agentx_notify *axn"
+.Sh DESCRIPTION
+The
+.Nm agentx_notify
+interface allows to send notify messages or
+.Dq SNMP trap
+messages to the agentx master.
+To send a message a notify context needs to be set up on an context initiated
+with
+.Xr agentx_context 3 .
+The
+.Fa trapoid
+and
+.Fa oidlen
+combination identifies the trap to be sent.
+The sysuptime parameter is set internally.
+.Pp
+Additional objects can be added to the notify by calling agentx_notify_<type>.
+These functions must be called in the order specified by the MIB and work
+similar to the agentx_varbind_<type> functions.
+.Pp
+Once the notify is complete it can be send out by
+.Fn agentx_notify_send .
+This function also frees all allocated memory related to this notify.
+.Sh RETURN VALUES
+Upon succesful completion,
+.Fn agentx_notify
+returns a
+.Vt "struct agentx_notify"
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ENOTCONN
+The
+.Vt "struct agentx"
+pointer to which
+.Fa axc
+belongs is not connected.
+.El
+.Pp
+.Fn agentx_notify
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr agentx 3
+.Sh HISTORY
+The
+.Nm agentx_notify
+API first appeared in
+.Ox 6.9 .
+.Sh AUTHORS
+.An Martijn van Duren Aq Mt [email protected]
Index: ax.c
===================================================================
RCS file: /cvs/src/lib/libagentx/ax.c,v
retrieving revision 1.7
diff -u -p -r1.7 ax.c
--- ax.c 2 Jan 2021 01:06:31 -0000 1.7
+++ ax.c 4 Jan 2021 17:34:01 -0000
@@ -551,6 +551,19 @@ ax_unregister(struct ax *ax, uint32_t se
return ax_pdu_queue(ax);
}
+uint32_t
+ax_notify(struct ax *ax, uint32_t sessionid, struct ax_ostring *context,
+ struct ax_varbind *vblist, size_t nvb)
+{
+ if (ax_pdu_header(ax, AX_PDU_TYPE_NOTIFY, 0, sessionid, 0, 0,
+ context) == -1)
+ return 0;
+
+ if (ax_pdu_add_varbindlist(ax, vblist, nvb) == -1)
+ return 0;
+ return ax_pdu_queue(ax);
+}
+
int
ax_response(struct ax *ax, uint32_t sessionid, uint32_t transactionid,
uint32_t packetid, struct ax_ostring *context, uint32_t sysuptime,
Index: ax.h
===================================================================
RCS file: /cvs/src/lib/libagentx/ax.h,v
retrieving revision 1.4
diff -u -p -r1.4 ax.h
--- ax.h 2 Jan 2021 01:06:31 -0000 1.4
+++ ax.h 4 Jan 2021 17:34:01 -0000
@@ -219,6 +219,8 @@ uint32_t ax_register(struct ax *, uint8_
uint32_t);
uint32_t ax_unregister(struct ax *, uint32_t, struct ax_ostring *,
uint8_t, uint8_t, struct ax_oid *, uint32_t);
+uint32_t ax_notify(struct ax *, uint32_t, struct ax_ostring *,
+ struct ax_varbind *, size_t);
int ax_response(struct ax *, uint32_t, uint32_t, uint32_t,
struct ax_ostring *, uint32_t, uint16_t, uint16_t,
struct ax_varbind *, size_t);
Index: shlib_version
===================================================================
RCS file: /cvs/src/lib/libagentx/shlib_version,v
retrieving revision 1.2
diff -u -p -r1.2 shlib_version
--- shlib_version 26 Oct 2020 15:45:56 -0000 1.2
+++ shlib_version 4 Jan 2021 17:34:01 -0000
@@ -1,2 +1,2 @@
major=1
-minor=0
+minor=1