diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c --- a/sys/compat/linux/linux_netlink.c +++ b/sys/compat/linux/linux_netlink.c @@ -550,22 +550,15 @@ } } -static bool -nlmsgs_to_linux(struct nl_writer *nw, struct nlpcb *nlp) +static struct nl_buf * +nlmsgs_to_linux(struct nl_buf *orig, struct nlpcb *nlp) { - struct nl_buf *nb, *orig; - u_int offset, msglen, orig_messages; - - RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__, - nw->buf->datalen, nw->num_messages); + struct nl_writer nw; + u_int offset, msglen; - orig = nw->buf; - nb = nl_buf_alloc(orig->datalen + SCRATCH_BUFFER_SIZE, M_NOWAIT); - if (__predict_false(nb == NULL)) - return (false); - nw->buf = nb; - orig_messages = nw->num_messages; - nw->num_messages = 0; + if (__predict_false(!nl_writer_unicast(&nw, + orig->datalen + SCRATCH_BUFFER_SIZE, nlp, false))) + return (NULL); /* Assume correct headers. Buffer IS mutable */ for (offset = 0; @@ -574,22 +567,18 @@ struct nlmsghdr *hdr = (struct nlmsghdr *)&orig->data[offset]; msglen = NLMSG_ALIGN(hdr->nlmsg_len); - if (!nlmsg_to_linux(hdr, nlp, nw)) { + if (!nlmsg_to_linux(hdr, nlp, &nw)) { RT_LOG(LOG_DEBUG, "failed to process msg type %d", hdr->nlmsg_type); - nl_buf_free(nb); - nw->buf = orig; - nw->num_messages = orig_messages; - return (false); + nl_buf_free(nw.buf); + return (NULL); } } - MPASS(nw->num_messages == orig_messages); - MPASS(nw->buf == nb); - nl_buf_free(orig); - RT_LOG(LOG_DEBUG3, "%p: out %u bytes", __func__, offset); + RT_LOG(LOG_DEBUG3, "%p: in %u bytes %u messages", __func__, + nw.buf->datalen, nw.num_messages); - return (true); + return (nw.buf); } static struct linux_netlink_provider linux_netlink_v1 = { diff --git a/sys/netlink/netlink_io.c b/sys/netlink/netlink_io.c --- a/sys/netlink/netlink_io.c +++ b/sys/netlink/netlink_io.c @@ -216,16 +216,17 @@ hdr->nlmsg_len); } - if (nlp->nl_linux && linux_netlink_p != NULL && - __predict_false(!linux_netlink_p->msgs_to_linux(nw, nlp))) { + if (nlp->nl_linux && linux_netlink_p != NULL) { + nb = linux_netlink_p->msgs_to_linux(nw->buf, nlp); nl_buf_free(nw->buf); nw->buf = NULL; - return (false); + if (nb == NULL) + return (false); + } else { + nb = nw->buf; + nw->buf = NULL; } - nb = nw->buf; - nw->buf = NULL; - SOCK_RECVBUF_LOCK(so); if (!nw->ignore_limit && __predict_false(sb->sb_hiwat <= sb->sb_ccc)) { SOCK_RECVBUF_UNLOCK(so); diff --git a/sys/netlink/netlink_linux.h b/sys/netlink/netlink_linux.h --- a/sys/netlink/netlink_linux.h +++ b/sys/netlink/netlink_linux.h @@ -37,7 +37,7 @@ struct nl_pstate; struct nl_writer; -typedef bool msgs_to_linux_cb_t(struct nl_writer *nw, struct nlpcb *nlp); +typedef struct nl_buf * msgs_to_linux_cb_t(struct nl_buf *, struct nlpcb *); typedef int msg_from_linux_cb_t(int netlink_family, struct nlmsghdr **hdr, struct nl_pstate *npt);