On Thu, Jul 22, 2021 at 10:19:59PM +0200, Martijn van Duren wrote: > 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?
ok jmatthew@ I don't think we need to worry about clashing with existing symbols in ports, since we renamed ber_* to ober_* because no one was using it. > > 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 > >