@@ -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'"
@@ -144,7 +151,7 @@ struct nfnl_subsys_handle {
uint32_t subscriptions;
uint8_t subsys_id;
uint8_t cb_count;
- struct nfnl_callback *cb; /* array of callbacks */
+ struct nfnl_callback2 *cb; /* array of callbacks with struct nlattr* */
};
struct nfnl_handle {
@@ -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;
@@ -259,7 +273,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);
@@ -484,7 +498,7 @@ struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
static struct nfq_handle *__nfq_open_nfnl(struct nfnl_handle *nfnlh,
struct nfq_handle *qh)
{
- struct nfnl_callback pkt_cb = {
+ struct nfnl_callback2 pkt_cb = {
.call = __nfq_rcv_pkt,
.attr_count = NFQA_MAX,
};
@@ -657,6 +671,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
* @{
@@ -768,7 +801,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);
}
/**
@@ -937,7 +971,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));
@@ -958,15 +992,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);
@@ -1130,8 +1166,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]);
}
/**
@@ -1143,6 +1181,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));
}
@@ -1159,11 +1201,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);
@@ -1184,7 +1227,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]));
}
/**
@@ -1198,7 +1244,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]));
}
/**
@@ -1212,7 +1261,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]));
}
/**
@@ -1228,7 +1280,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]));
}
/**
@@ -1363,8 +1418,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]);
}
/**
@@ -1412,10 +1469,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;
}
@@ -1433,10 +1490,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;
}
@@ -1454,14 +1511,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;
}
@@ -1480,10 +1536,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;
}
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 instead 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@optusnet.com.au> --- Changes in v3: - rebased - Don't include a kernel header (don't need it anyway) Changes in v2: - Fix spelling error in commit message - Fix checkpatch warning re space before __nfq_handle_msg declaration - rebase to account for updated patches doxygen/doxygen.cfg.in | 1 + src/libnetfilter_queue.c | 124 ++++++++++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 33 deletions(-)