diff options
author | Florian Westphal <fw@strlen.de> | 2011-09-06 13:47:43 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@gnumonks.org> | 2011-09-06 13:47:43 +0200 |
commit | 1154021c599257edf2c3dcb4d29f6b4dcb67643a (patch) | |
tree | d6a7150a34f8e1c9535f6f9accd62f4a05742bad | |
parent | ebdfa9a7631534071c6997b8210b8964db5e6957 (diff) | |
download | libnetfilter_queue-1154021c599257edf2c3dcb4d29f6b4dcb67643a.tar.gz |
src: add NFQNL_MSG_VERDICT_BATCH support
add nfq_set_verdict_batch() and nfq_set_verdict_batch2 (to also
set the nfmark of all packets).
verdicts sent by the _batch variant will affect all queued skbs
whose id is smaller or equal to the given id.
This facility is available from Linux 3.1 onwards.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@gnumonks.org>
-rw-r--r-- | include/libnetfilter_queue/libnetfilter_queue.h | 9 | ||||
-rw-r--r-- | include/libnetfilter_queue/linux_nfnetlink_queue.h | 1 | ||||
-rw-r--r-- | src/libnetfilter_queue.c | 50 |
3 files changed, 54 insertions, 6 deletions
diff --git a/include/libnetfilter_queue/libnetfilter_queue.h b/include/libnetfilter_queue/libnetfilter_queue.h index 295de66..28bf2b1 100644 --- a/include/libnetfilter_queue/libnetfilter_queue.h +++ b/include/libnetfilter_queue/libnetfilter_queue.h @@ -69,6 +69,15 @@ extern int nfq_set_verdict2(struct nfq_q_handle *qh, u_int32_t datalen, const unsigned char *buf); +extern int nfq_set_verdict_batch(struct nfq_q_handle *qh, + u_int32_t id, + u_int32_t verdict); + +extern int nfq_set_verdict_batch2(struct nfq_q_handle *qh, + u_int32_t id, + u_int32_t verdict, + u_int32_t mark); + extern __attribute__((deprecated)) int nfq_set_verdict_mark(struct nfq_q_handle *qh, u_int32_t id, diff --git a/include/libnetfilter_queue/linux_nfnetlink_queue.h b/include/libnetfilter_queue/linux_nfnetlink_queue.h index 191b094..6b4f86d 100644 --- a/include/libnetfilter_queue/linux_nfnetlink_queue.h +++ b/include/libnetfilter_queue/linux_nfnetlink_queue.h @@ -11,6 +11,7 @@ enum nfqnl_msg_types { NFQNL_MSG_PACKET, /* packet from kernel to userspace */ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */ NFQNL_MSG_CONFIG, /* connect to a particular queue */ + NFQNL_MSG_VERDICT_BATCH, /* batch verdict from userspace to kernel */ NFQNL_MSG_MAX }; diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c index 08c4039..358e9b1 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -632,7 +632,8 @@ int nfq_set_queue_maxlen(struct nfq_q_handle *qh, static int __set_verdict(struct nfq_q_handle *qh, u_int32_t id, u_int32_t verdict, u_int32_t mark, int set_mark, - u_int32_t data_len, const unsigned char *data) + u_int32_t data_len, const unsigned char *data, + enum nfqnl_msg_types type) { struct nfqnl_msg_verdict_hdr vh; union { @@ -655,7 +656,7 @@ static int __set_verdict(struct nfq_q_handle *qh, u_int32_t id, vh.id = htonl(id); nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id, - NFQNL_MSG_VERDICT, NLM_F_REQUEST); + type, NLM_F_REQUEST); /* add verdict header */ nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_VERDICT_HDR, &vh, sizeof(vh)); @@ -705,7 +706,8 @@ static int __set_verdict(struct nfq_q_handle *qh, u_int32_t id, * * Notifies netfilter of the userspace verdict for the given packet. Every * queued packet _must_ have a verdict specified by userspace, either by - * calling this function, or by calling the nfq_set_verdict2() function. + * calling this function, the nfq_set_verdict2() function, or the _batch + * versions of these functions. * * \return -1 on error; >= 0 otherwise. */ @@ -713,7 +715,8 @@ int nfq_set_verdict(struct nfq_q_handle *qh, u_int32_t id, u_int32_t verdict, u_int32_t data_len, const unsigned char *buf) { - return __set_verdict(qh, id, verdict, 0, 0, data_len, buf); + return __set_verdict(qh, id, verdict, 0, 0, data_len, buf, + NFQNL_MSG_VERDICT); } /** @@ -729,7 +732,41 @@ int nfq_set_verdict2(struct nfq_q_handle *qh, u_int32_t id, u_int32_t verdict, u_int32_t mark, u_int32_t data_len, const unsigned char *buf) { - return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len, buf); + return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len, + buf, NFQNL_MSG_VERDICT); +} + +/** + * nfq_set_verdict_batch - issue verdicts on several packets at once + * \param qh Netfilter queue handle obtained by call to nfq_create_queue(). + * \param id maximum ID of the packets that the verdict should be applied to. + * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) + * + * Unlike nfq_set_verdict, the verdict is applied to all queued packets + * whose packet id is smaller or equal to #id. + * + * batch support was added in Linux 3.1. + * These functions will fail silently on older kernels. + */ +int nfq_set_verdict_batch(struct nfq_q_handle *qh, u_int32_t id, + u_int32_t verdict) +{ + return __set_verdict(qh, id, verdict, 0, 0, 0, NULL, + NFQNL_MSG_VERDICT_BATCH); +} + +/** + * nfq_set_verdict_batch2 - like nfq_set_verdict_batch, but you can set a mark. + * \param qh Netfilter queue handle obtained by call to nfq_create_queue(). + * \param id maximum ID of the packets that the verdict should be applied to. + * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) + * \param mark mark to put on packet + */ +int nfq_set_verdict_batch2(struct nfq_q_handle *qh, u_int32_t id, + u_int32_t verdict, u_int32_t mark) +{ + return __set_verdict(qh, id, verdict, htonl(mark), 1, 0, + NULL, NFQNL_MSG_VERDICT_BATCH); } /** @@ -750,7 +787,8 @@ int nfq_set_verdict_mark(struct nfq_q_handle *qh, u_int32_t id, u_int32_t verdict, u_int32_t mark, u_int32_t data_len, const unsigned char *buf) { - return __set_verdict(qh, id, verdict, mark, 1, data_len, buf); + return __set_verdict(qh, id, verdict, mark, 1, data_len, buf, + NFQNL_MSG_VERDICT); } /** |