diff --git a/sys/netlink/netlink_snl.h b/sys/netlink/netlink_snl.h --- a/sys/netlink/netlink_snl.h +++ b/sys/netlink/netlink_snl.h @@ -106,6 +106,27 @@ return (data); } +static inline bool +lb_extendz(struct linear_buffer *lb, void *old, int old_len, int new_len) +{ + int delta; + + /* Is the old buffer the last allocated region in the lb? */ + old_len = roundup2(old_len, alignof(__max_align_t)); + if ((char *)old + old_len != lb->base + lb->offset) + return (false); + + /* Is there room to grow the end of the lb? */ + new_len = roundup2(new_len, alignof(__max_align_t)); + delta = new_len - old_len; + if (lb->offset + delta > lb->size) + return (false); + + lb->offset += delta; + memset((char *)old + old_len, 0, delta); + return (true); +} + static inline void lb_clear(struct linear_buffer *lb) { @@ -221,6 +242,12 @@ return (data); } +static inline bool +snl_extendz(struct snl_state *ss, void *old, int old_len, int new_len) +{ + return (lb_extendz(ss->lb, old, old_len, new_len)); +} + static inline void snl_clear_lb(struct snl_state *ss) { @@ -1091,6 +1118,11 @@ if (nw->error) return (false); + if (snl_extendz(nw->ss, nw->base, nw->size, new_size)) { + nw->size = new_size; + return (true); + } + new_base = snl_allocz(nw->ss, new_size); if (new_base == NULL) { nw->error = true;