The opaque struct nfq_data is now an array of struct nlattr instead of struct nfattr. Because of using mnl_attr_parse(), the first array element is for attribute 0 instaed of attribute 1 as previously. Because of this, all the nfq_get_ functions have to be converted for this commit. Functions now using libmnl exclusively: nfq_get_msg_packet_hdr(), nfq_get_nfmark(), nfq_get_timestamp(), nfq_get_indev(), nfq_get_physindev(), nfq_get_outdev(), nfq_get_physoutdev(), nfqnl_msg_packet_hw(), nfq_get_uid() & nfq_get_gid(). Signed-off-by: Duncan Roe <duncan_roe@xxxxxxxxxxxxxxx> --- doxygen/doxygen.cfg.in | 1 + src/libnetfilter_queue.c | 122 +++++++++++++++++++++++++++++---------- 2 files changed, 91 insertions(+), 32 deletions(-) diff --git a/doxygen/doxygen.cfg.in b/doxygen/doxygen.cfg.in index 6dd7017..fcfc045 100644 --- a/doxygen/doxygen.cfg.in +++ b/doxygen/doxygen.cfg.in @@ -16,6 +16,7 @@ EXCLUDE_SYMBOLS = EXPORT_SYMBOL \ nfnl_handle \ nfnl_subsys_handle \ mnl_socket \ + nfnl_callback2 \ tcp_flag_word EXAMPLE_PATTERNS = INPUT_FILTER = "sed 's/EXPORT_SYMBOL//g'" diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c index 28aa771..58875b1 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -32,6 +32,13 @@ #include <linux/netfilter/nfnetlink_queue.h> #include <libmnl/libmnl.h> + +/* Use the real header since libnfnetlink is going away. */ +/* nfq_pkt_parse_attr_cb only knows attribates up to NFQA_SECCTX */ +/* so won't try to validate higher-numbered attrs but will store them. */ +/* mnl API programs will then be able to access them. */ +#include <linux/netfilter/nfnetlink.h> + #include <libnfnetlink/libnfnetlink.h> #include <libnetfilter_queue/libnetfilter_queue.h> #include "internal.h" @@ -166,6 +173,13 @@ struct mnl_socket { struct sockaddr_nl addr; }; +/* Amended callback prototype */ +struct nfnl_callback2 { + int (*call)(struct nlmsghdr *nlh, struct nlattr *nfa[], void *data); + void *data; + uint16_t attr_count; +}; + struct nfq_handle { struct nfnl_handle *nfnlh; @@ -185,7 +199,7 @@ struct nfq_q_handle }; struct nfq_data { - struct nfattr **data; + struct nlattr **data; }; EXPORT_SYMBOL int nfq_errno; @@ -256,7 +270,7 @@ __build_send_cfg_msg(struct nfq_handle *h, uint8_t command, return nfq_query(h, nlh, buf, sizeof(buf)); } -static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], +static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nlattr *nfa[], void *data) { struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); @@ -411,7 +425,7 @@ int nfq_fd(struct nfq_handle *h) static bool fill_nfnl_subsys_handle(struct nfq_handle *h) { - struct nfnl_callback pkt_cb = { + struct nfnl_callback2 pkt_cb = { .call = __nfq_rcv_pkt, .attr_count = NFQA_MAX, }; @@ -610,6 +624,25 @@ int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf) * @} */ + static int __nfq_handle_msg(const struct nlmsghdr *nlh, void *data) +{ + struct nfq_handle *h = data; + struct nfq_q_handle *qh; + struct nlattr *nfa[NFQA_MAX + 1] = {}; + struct nfq_data nfad = {nfa}; + struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); + + if (nfq_nlmsg_parse(nlh, nfa) < 0) + return MNL_CB_ERROR; + + /* Find our queue handler (to get CB fn) */ + qh = find_qh(h, ntohs(nfmsg->res_id)); + if (!qh) + return MNL_CB_ERROR; + + return qh->cb(qh, nfmsg, &nfad, qh->data); +} + /** * \addtogroup Queue * @{ @@ -721,7 +754,8 @@ int nfq_destroy_queue(struct nfq_q_handle *qh) EXPORT_SYMBOL int nfq_handle_packet(struct nfq_handle *h, char *buf, int len) { - return nfnl_handle_packet(h->nfnlh, buf, len); + return mnl_cb_run(buf, len, 0, mnl_socket_get_portid(h->nl), + __nfq_handle_msg, h); } /** @@ -891,7 +925,7 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id, /* This must be declared here (and not inside the data * handling block) because the iovec points to this. */ - struct nfattr data_attr; + struct nlattr data_attr; memset(iov, 0, sizeof(iov)); @@ -912,15 +946,17 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id, nvecs = 1; if (data_len) { - /* The typecast here is to cast away data's const-ness: */ - nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD, - data_len, (unsigned char *) data); + /* Temporary cast until we get rid of nfnl_build_nfa_iovec() */ + nfnl_build_nfa_iovec(&iov[1], (struct nfattr *)&data_attr, + //nfnl_build_nfa_iovec(&iov[1], &data_attr, + NFQA_PAYLOAD, data_len, + (unsigned char *) data); nvecs += 2; /* Add the length of the appended data to the message * header. The size of the attribute is given in the - * nfa_len field and is set in the nfnl_build_nfa_iovec() + * nla_len field and is set in the nfnl_build_nfa_iovec() * function. */ - u.nmh.nlmsg_len += data_attr.nfa_len; + u.nmh.nlmsg_len += data_attr.nla_len; } return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0); @@ -1084,8 +1120,10 @@ int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id, EXPORT_SYMBOL struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad) { - return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR, - struct nfqnl_msg_packet_hdr); + if (!nfad->data[NFQA_PACKET_HDR]) + return NULL; + + return mnl_attr_get_payload(nfad->data[NFQA_PACKET_HDR]); } /** @@ -1097,6 +1135,10 @@ struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad) EXPORT_SYMBOL uint32_t nfq_get_nfmark(struct nfq_data *nfad) { + if (!nfad->data[NFQA_MARK]) + return 0; + + return ntohl(mnl_attr_get_u32(nfad->data[NFQA_MARK])); return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t)); } @@ -1113,11 +1155,12 @@ EXPORT_SYMBOL int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv) { struct nfqnl_msg_packet_timestamp *qpt; - qpt = nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP, - struct nfqnl_msg_packet_timestamp); - if (!qpt) + + if (!nfad->data[NFQA_TIMESTAMP]) return -1; + qpt = mnl_attr_get_payload(nfad->data[NFQA_TIMESTAMP]); + tv->tv_sec = __be64_to_cpu(qpt->sec); tv->tv_usec = __be64_to_cpu(qpt->usec); @@ -1138,7 +1181,10 @@ int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv) EXPORT_SYMBOL uint32_t nfq_get_indev(struct nfq_data *nfad) { - return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t)); + if (!nfad->data[NFQA_IFINDEX_INDEV]) + return 0; + + return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_INDEV])); } /** @@ -1152,7 +1198,10 @@ uint32_t nfq_get_indev(struct nfq_data *nfad) EXPORT_SYMBOL uint32_t nfq_get_physindev(struct nfq_data *nfad) { - return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t)); + if (!nfad->data[NFQA_IFINDEX_PHYSINDEV]) + return 0; + + return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_PHYSINDEV])); } /** @@ -1166,7 +1215,10 @@ uint32_t nfq_get_physindev(struct nfq_data *nfad) EXPORT_SYMBOL uint32_t nfq_get_outdev(struct nfq_data *nfad) { - return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t)); + if (!nfad->data[NFQA_IFINDEX_OUTDEV]) + return 0; + + return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_OUTDEV])); } /** @@ -1182,7 +1234,10 @@ uint32_t nfq_get_outdev(struct nfq_data *nfad) EXPORT_SYMBOL uint32_t nfq_get_physoutdev(struct nfq_data *nfad) { - return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t)); + if (!nfad->data[NFQA_IFINDEX_PHYSOUTDEV]) + return 0; + + return ntohl(mnl_attr_get_u32(nfad->data[NFQA_IFINDEX_PHYSOUTDEV])); } /** @@ -1317,8 +1372,10 @@ int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle, EXPORT_SYMBOL struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad) { - return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR, - struct nfqnl_msg_packet_hw); + if (!nfad->data[NFQA_HWADDR]) + return NULL; + + return mnl_attr_get_payload(nfad->data[NFQA_HWADDR]); } /** @@ -1366,10 +1423,10 @@ uint32_t nfq_get_skbinfo(struct nfq_data *nfad) EXPORT_SYMBOL int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid) { - if (!nfnl_attr_present(nfad->data, NFQA_UID)) + if (!nfad->data[NFQA_UID]) return 0; - *uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t)); + *uid = ntohl(mnl_attr_get_u32(nfad->data[NFQA_UID])); return 1; } @@ -1387,10 +1444,10 @@ int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid) EXPORT_SYMBOL int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid) { - if (!nfnl_attr_present(nfad->data, NFQA_GID)) + if (!nfad->data[NFQA_GID]) return 0; - *gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t)); + *gid = ntohl(mnl_attr_get_u32(nfad->data[NFQA_GID])); return 1; } @@ -1408,14 +1465,13 @@ int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid) EXPORT_SYMBOL int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata) { - if (!nfnl_attr_present(nfad->data, NFQA_SECCTX)) + if (!nfad->data[NFQA_SECCTX]) return -1; - *secdata = (unsigned char *)nfnl_get_pointer_to_data(nfad->data, - NFQA_SECCTX, char); + *secdata = mnl_attr_get_payload(nfad->data[NFQA_SECCTX]); if (*secdata) - return NFA_PAYLOAD(nfad->data[NFQA_SECCTX-1]); + return mnl_attr_get_payload_len(nfad->data[NFQA_SECCTX]); return 0; } @@ -1434,10 +1490,12 @@ int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata) EXPORT_SYMBOL int nfq_get_payload(struct nfq_data *nfad, unsigned char **data) { - *data = (unsigned char *) - nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char); + if (!nfad->data[NFQA_PAYLOAD]) + return -1; + + *data = mnl_attr_get_payload(nfad->data[NFQA_PAYLOAD]); if (*data) - return NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]); + return mnl_attr_get_payload_len(nfad->data[NFQA_PAYLOAD]); return -1; } -- 2.35.8