On Wed, Nov 15, 2023 at 10:30:11PM +1100, Duncan Roe wrote: > Enable mnl programs to check whether a config request was accepted. > (nfnl programs do this already). > > v3: force on NLM_F_REQUEST > > v2: take flags as an arg (Pablo request) > Signed-off-by: Duncan Roe <duncan_roe@xxxxxxxxxxxxxxx> > --- > .../libnetfilter_queue/libnetfilter_queue.h | 1 + > src/nlmsg.c | 55 ++++++++++++++++++- > 2 files changed, 55 insertions(+), 1 deletion(-) > > diff --git a/include/libnetfilter_queue/libnetfilter_queue.h b/include/libnetfilter_queue/libnetfilter_queue.h > index 3d8e444..f254984 100644 > --- a/include/libnetfilter_queue/libnetfilter_queue.h > +++ b/include/libnetfilter_queue/libnetfilter_queue.h > @@ -151,6 +151,7 @@ void nfq_nlmsg_verdict_put_pkt(struct nlmsghdr *nlh, const void *pkt, uint32_t p > > int nfq_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr); > struct nlmsghdr *nfq_nlmsg_put(char *buf, int type, uint32_t queue_num); > +struct nlmsghdr *nfq_nlmsg_put2(char *buf, int type, uint32_t queue_num, uint16_t flags); > > #ifdef __cplusplus > } /* extern "C" */ > diff --git a/src/nlmsg.c b/src/nlmsg.c > index 5400dd7..999ccfe 100644 > --- a/src/nlmsg.c > +++ b/src/nlmsg.c > @@ -309,10 +309,63 @@ int nfq_nlmsg_parse(const struct nlmsghdr *nlh, struct nlattr **attr) > */ > EXPORT_SYMBOL > struct nlmsghdr *nfq_nlmsg_put(char *buf, int type, uint32_t queue_num) > +{ > + return nfq_nlmsg_put2(buf, type, queue_num, 0); > +} > + > +/** > + * nfq_nlmsg_put2 - Convert memory buffer into a Netlink buffer with > + * user-specified flags This is setting up a netlink header in the memory buffer. > + * \param *buf Pointer to memory buffer > + * \param type Either NFQNL_MSG_CONFIG or NFQNL_MSG_VERDICT > + * \param queue_num Queue number > + * \param flags additional (to NLM_F_REQUEST) flags to put in message header, > + * commonly NLM_F_ACK remove NLM_F_REQUEST here. > + * \returns Pointer to netlink message Pointer to netlink header > + * > + * Use NLM_F_ACK before performing an action that might fail, e.g. Failures are always reported. if you set NLM_F_ACK, then you always get an acknowledgment from the kernel, either 0 to report success or negative to report failure. if you do not set NLM_F_ACK, then only failures are reported by the kernel. > + * attempt to configure NFQA_CFG_F_SECCTX on a system not runnine SELinux. > + * \n > + * NLM_F_ACK instructs the kernel to send a message in response > + * to a successful command. As I said above, this is not accurate. > + * The kernel always sends a message in response to a failed command. > + * \n > + * This code snippet demonstrates reading these responses: > + * \verbatim > + nlh = nfq_nlmsg_put2(nltxbuf, NFQNL_MSG_CONFIG, queue_num, NLM_F_ACK); > + mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, NFQA_CFG_F_SECCTX); > + mnl_attr_put_u32(nlh, NFQA_CFG_MASK, NFQA_CFG_F_SECCTX); > + > + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { > + perror("mnl_socket_send"); > + exit(EXIT_FAILURE); > + } > + > + ret = mnl_socket_recvfrom(nl, nlrxbuf, sizeof nlrxbuf); > + if (ret == -1) { > + perror("mnl_socket_recvfrom"); > + exit(EXIT_FAILURE); > + } > + > + ret = mnl_cb_run(nlrxbuf, ret, 0, portid, NULL, NULL); > + if (ret == -1) > + perror("configure NFQA_CFG_F_SECCTX"); > +\endverbatim > + * > + * \note > + * The program above can continue after the error because NFQA_CFG_F_SECCTX > + * was the only item in the preceding **mnl_socket_sendto**. > + * If there had been other items, they would not have been actioned and it would > + * not now be safe to proceed. > + */ > + > +EXPORT_SYMBOL > +struct nlmsghdr *nfq_nlmsg_put2(char *buf, int type, uint32_t queue_num, > + uint16_t flags) > { > struct nlmsghdr *nlh = mnl_nlmsg_put_header(buf); > nlh->nlmsg_type = (NFNL_SUBSYS_QUEUE << 8) | type; > - nlh->nlmsg_flags = NLM_F_REQUEST; > + nlh->nlmsg_flags = NLM_F_REQUEST | flags; > > struct nfgenmsg *nfg = mnl_nlmsg_put_extra_header(nlh, sizeof(*nfg)); > nfg->nfgen_family = AF_UNSPEC; > -- > 2.35.8 >