I'm currently working on adding SNMPv3 support to traps in snmpd(8).
For sending traps we loop over sc_trapreceivers and can send each trap
to 0 or more receivers.
I want to high-jack snmpe_response() to do the heavy lifting for doing
the snmp/usm encoding, but this interface frees the varbindlist in
snmp_msgfree(), which means I need to rebuild the varbindlist for every
iteration. To keep this simple I suggest adding ober_dup, which
duplicates a full ber_element chain.
Sending this prior to any of my snmpd(8) work, since it requires a
library version bump.
OK?
Any additional coordination needed for this diff?
martijn@
Index: Symbols.map
===================================================================
RCS file: /cvs/src/lib/libutil/Symbols.map,v
retrieving revision 1.3
diff -u -p -r1.3 Symbols.map
--- Symbols.map 24 Oct 2019 12:39:26 -0000 1.3
+++ Symbols.map 22 Jul 2021 20:18:35 -0000
@@ -65,6 +65,7 @@
ober_add_set;
ober_add_string;
ober_calc_len;
+ ober_dup;
ober_free;
ober_free_element;
ober_free_elements;
Index: ber.c
===================================================================
RCS file: /cvs/src/lib/libutil/ber.c,v
retrieving revision 1.21
diff -u -p -r1.21 ber.c
--- ber.c 22 Feb 2021 17:15:02 -0000 1.21
+++ ber.c 22 Jul 2021 20:18:35 -0000
@@ -926,6 +926,43 @@ ober_getpos(struct ber_element *elm)
return elm->be_offs;
}
+struct ber_element *
+ober_dup(struct ber_element *orig)
+{
+ struct ber_element *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL)
+ return NULL;
+ memcpy(new, orig, sizeof(*new));
+ new->be_next = NULL;
+ new->be_sub = NULL;
+
+ if (orig->be_next != NULL) {
+ if ((new->be_next = ober_dup(orig->be_next)) == NULL)
+ goto fail;
+ }
+ if (orig->be_encoding == BER_TYPE_SEQUENCE ||
+ orig->be_encoding == BER_TYPE_SET) {
+ if (orig->be_sub != NULL) {
+ if ((new->be_sub = ober_dup(orig->be_sub)) == NULL)
+ goto fail;
+ }
+ } else if (orig->be_encoding == BER_TYPE_OCTETSTRING ||
+ orig->be_encoding == BER_TYPE_BITSTRING ||
+ orig->be_encoding == BER_TYPE_OBJECT) {
+ if (orig->be_val != NULL) {
+ if ((new->be_val = malloc(orig->be_len)) == NULL)
+ goto fail;
+ memcpy(new->be_val, orig->be_val, orig->be_len);
+ }
+ } else
+ new->be_numeric = orig->be_numeric;
+ return new;
+ fail:
+ ober_free_elements(new);
+ return NULL;
+}
+
void
ober_free_element(struct ber_element *root)
{
Index: ber.h
===================================================================
RCS file: /cvs/src/lib/libutil/ber.h,v
retrieving revision 1.3
diff -u -p -r1.3 ber.h
--- ber.h 31 Dec 2019 10:34:14 -0000 1.3
+++ ber.h 22 Jul 2021 20:18:35 -0000
@@ -137,6 +137,7 @@ ssize_t ober_write_elements(struct be
void ober_set_readbuf(struct ber *, void *, size_t);
struct ber_element *ober_read_elements(struct ber *, struct ber_element *);
off_t ober_getpos(struct ber_element *);
+struct ber_element *ober_dup(struct ber_element *);
void ober_free_element(struct ber_element *);
void ober_free_elements(struct ber_element *);
size_t ober_calc_len(struct ber_element *);
Index: ober_set_header.3
===================================================================
RCS file: /cvs/src/lib/libutil/ober_set_header.3,v
retrieving revision 1.2
diff -u -p -r1.2 ober_set_header.3
--- ober_set_header.3 12 Mar 2021 05:18:01 -0000 1.2
+++ ober_set_header.3 22 Jul 2021 20:18:35 -0000
@@ -23,6 +23,7 @@
.Nm ober_set_writecallback ,
.Nm ober_link_elements ,
.Nm ober_replace_elements ,
+.Nm ober_dup ,
.Nm ober_unlink_elements ,
.Nm ober_free_element ,
.Nm ober_free_elements
@@ -45,6 +46,8 @@
.Ft "void"
.Fn "ober_replace_elements" "struct ber_element *prev" "struct ber_element
*elm"
.Ft "struct ber_element *"
+.Ft "struct ber_element *"
+.Fn "ober_dup" "struct ber_element *orig"
.Fn "ober_unlink_elements" "struct ber_element *prev"
.Ft "void"
.Fn "ober_free_element" "struct ber_element *root"
@@ -101,6 +104,9 @@ with
and frees any dynamically allocated storage associated with
.Fa prev .
.Pp
+.Fn ober_dup
+duplicates an element and all linked elements.
+.Pp
.Fn ober_unlink_elements
unlinks
.Fa prev .
@@ -116,6 +122,11 @@ returns the total length of a fully popu
.Fa root
containing one or more
.Vt ber_element .
+.Pp
+.Fn ober_dup
+returns a pointer to the duplicated element or
+.Dv NULL
+on error.
.Pp
.Fn ober_unlink_elements
returns a pointer to
Index: shlib_version
===================================================================
RCS file: /cvs/src/lib/libutil/shlib_version,v
retrieving revision 1.32
diff -u -p -r1.32 shlib_version
--- shlib_version 31 Dec 2019 10:34:14 -0000 1.32
+++ shlib_version 22 Jul 2021 20:18:35 -0000
@@ -1,2 +1,2 @@
major=15
-minor=0
+minor=1