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


Reply via email to