diff options
Diffstat (limited to 'src/libnetfilter_queue.c')
-rw-r--r-- | src/libnetfilter_queue.c | 355 |
1 files changed, 229 insertions, 126 deletions
diff --git a/src/libnetfilter_queue.c b/src/libnetfilter_queue.c index 1702158..bf67a19 100644 --- a/src/libnetfilter_queue.c +++ b/src/libnetfilter_queue.c @@ -4,7 +4,7 @@ * (C) 2005, 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org> * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 + * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation (or any later at your option) * * This program is distributed in the hope that it will be useful, @@ -29,6 +29,7 @@ #include <errno.h> #include <netinet/in.h> #include <sys/socket.h> +#include <linux/netfilter/nfnetlink_queue.h> #include <libnfnetlink/libnfnetlink.h> #include <libnetfilter_queue/libnetfilter_queue.h> @@ -39,53 +40,71 @@ * * libnetfilter_queue is a userspace library providing an API to packets that * have been queued by the kernel packet filter. It is is part of a system that - * deprecates the old ip_queue / libipq mechanism. + * replaces the old ip_queue / libipq mechanism (withdrawn in kernel 3.5). * * libnetfilter_queue homepage is: - * http://netfilter.org/projects/libnetfilter_queue/ + * https://netfilter.org/projects/libnetfilter_queue/ * - * \section Dependencies - * libnetfilter_queue requires libnfnetlink and a kernel that includes the - * nfnetlink_queue subsystem (i.e. 2.6.14 or later). + <h1>Dependencies</h1> + * libnetfilter_queue requires libmnl, libnfnetlink and a kernel that includes + * the Netfilter NFQUEUE over NFNETLINK interface (i.e. 2.6.14 or later). * - * \section Main Features + * <h1>Main Features</h1> * - receiving queued packets from the kernel nfnetlink_queue subsystem - * - issuing verdicts and/or reinjecting altered packets to the kernel + * - issuing verdicts and possibly reinjecting altered packets to the kernel * nfnetlink_queue subsystem * - * The cinematic is the following: When an iptables rules with target NFQUEUE - * matches, the kernel en-queued the packet in a chained list. It then format - * a nfnetlink message and sends the information (packet data , packet id and - * metadata) via a socket to the software connected to the queue. The software - * can then read the message. + * The cinematic is the following: When an nft rule with action **queue** + * matches, the kernel terminates the current nft chain and enqueues the packet + * in a chained list. It then formats and sends an nfnetlink message containing + * the packet id and whatever information the userspace program configured to + * receive (packet data and/or metadata) via a socket to the userspace program. * - * To remove the packet from the queue, the userspace software must issue a - * verdict asking kernel to accept or drop the packet. Userspace can also alter - * the packet. Verdict can be done in asynchronous manner, as the only needed - * information is the packet id. + * The userspace program must issue a verdict advising the kernel to **accept** + * or **drop** the packet. Either verdict takes the packet off the queue: + * **drop** discards the packet while + * **accept** passes it on to the next chain. + * Userspace can also alter packet contents or metadata (e.g. packet mark, + * contrack mark). Verdict can be done in asynchronous manner, as the only + * needed information is the packet id. * - * When a queue is full, packets that should have been en-queued are dropped by - * kernel instead of being en-queued. + * When a queue is full, packets that should have been enqueued are dropped by + * kernel instead of being enqueued. * - * \section Git Tree - * The current development version of libnetfilter_queue can be accessed - * at https://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_queue.git;a=summary. + * <h1>Git Tree</h1> + * The current development version of libnetfilter_queue can be accessed at + * https://git.netfilter.org/libnetfilter_queue. * - * \section Privileges + * <h1>Privileges</h1> * You need the CAP_NET_ADMIN capability in order to allow your application * to receive from and to send packets to kernel-space. * - * \section Using libnetfilter_queue - * - * To write your own program using libnetfilter_queue, you should start by reading - * the doxygen documentation (start by \link LibrarySetup \endlink page) and - * nf-queue.c source file. + * <h1>Using libnetfilter_queue</h1> * - * Another source of information on libnetfilter_queue usage is the following + * To write your own program using libnetfilter_queue, you should start by + * reading (or, if feasible, compiling and stepping through with *gdb*) + * nf-queue.c source file. + * Simple compile line: + * \verbatim +gcc -g3 -ggdb -Wall -lmnl -lnetfilter_queue -o nf-queue nf-queue.c +\endverbatim + *The doxygen documentation + * \htmlonly +<a class="el" href="group__LibrarySetup.html">LibrarySetup </a> +\endhtmlonly + * \manonly +\fBLibrarySetup\fP\ +\endmanonly + * is Deprecated and + * incompatible with non-deprecated functions. It is hoped to produce a + * corresponding non-deprecated (*Current*) topic soon. + * + * Somewhat outdated but possibly providing some insight into + * libnetfilter_queue usage is the following * article: * https://home.regit.org/netfilter-en/using-nfqueue-and-libnetfilter_queue/ * - * \section errors ENOBUFS errors in recv() + * <h1>ENOBUFS errors in recv()</h1> * * recv() may return -1 and errno is set to ENOBUFS in case that your * application is not fast enough to retrieve the packets from the kernel. @@ -94,7 +113,7 @@ * you may hit it again sooner or later. The next section provides some hints * on how to obtain the best performance for your application. * - * \section perf Performance + * <h1>Performance</h1> * To improve your libnetfilter_queue application in terms of performance, * you may consider the following tweaks: * @@ -108,6 +127,9 @@ * (it requires Linux kernel >= 2.6.31). * - consider using fail-open option see nfq_set_queue_flags() (it requires * Linux kernel >= 3.6) + * - make your application offload aware to avoid costly normalization on kernel + * side. See NFQA_CFG_F_GSO flag to nfq_set_queue_flags(). + * Linux kernel >= 3.10. * - increase queue max length with nfq_set_queue_maxlen() to resist to packets * burst */ @@ -133,11 +155,10 @@ struct nfq_data { struct nfattr **data; }; -int nfq_errno; -EXPORT_SYMBOL(nfq_errno); +EXPORT_SYMBOL int nfq_errno; /*********************************************************************** - * low level stuff + * low level stuff ***********************************************************************/ static void del_qh(struct nfq_q_handle *qh) @@ -218,22 +239,22 @@ static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[], /* public interface */ +EXPORT_SYMBOL struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h) { return h->nfnlh; } -EXPORT_SYMBOL(nfq_nfnlh); /** * * \defgroup Queue Queue handling [DEPRECATED] * - * Once libnetfilter_queue library has been initialised (See + * Once libnetfilter_queue library has been initialised (See * \link LibrarySetup \endlink), it is possible to bind the program to a * specific queue. This can be done by using nfq_create_queue(). * * The queue can then be tuned via nfq_set_mode() or nfq_set_queue_maxlen(). - * + * * Here's a little code snippet that create queue numbered 0: * \verbatim printf("binding this socket to queue '0'\n"); @@ -260,7 +281,7 @@ EXPORT_SYMBOL(nfq_nfnlh); nfq_handle_packet(h, buf, rv); } \endverbatim - * When the decision on a packet has been choosed, the verdict has to be given + * When the decision on a packet has been chosen, the verdict has to be given * by calling nfq_set_verdict() or nfq_set_verdict2(). The verdict * determines the destiny of the packet as follows: * @@ -277,8 +298,18 @@ EXPORT_SYMBOL(nfq_nfnlh); * is to also set an nfmark using nfq_set_verdict2, and set up the nefilter * rules to only queue a packet when the mark is not (yet) set. * - * Data and information about the packet can be fetch by using message parsing + * Data and information about the packet can be fetched by using message parsing * functions (See \link Parsing \endlink). + * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <linux/netfilter.h> +#include <linux/netfilter/nfnetlink_queue.h> +#include <libnetfilter_queue/libnetfilter_queue.h> +\endmanonly + * * @{ */ @@ -294,11 +325,11 @@ EXPORT_SYMBOL(nfq_nfnlh); * over the netlink connection associated with the given queue connection * handle. */ +EXPORT_SYMBOL int nfq_fd(struct nfq_handle *h) { return nfnl_fd(nfq_nfnlh(h)); } -EXPORT_SYMBOL(nfq_fd); /** * @} */ @@ -308,7 +339,7 @@ EXPORT_SYMBOL(nfq_fd); * * Library initialisation is made in two steps. * - * First step is to call nfq_open() to open a NFQUEUE handler. + * First step is to call nfq_open() to open a NFQUEUE handler. * * Second step is to tell the kernel that userspace queueing is handle by * NFQUEUE for the selected protocol. This is made by calling nfq_unbind_pf() @@ -349,6 +380,7 @@ EXPORT_SYMBOL(nfq_fd); * * \return a pointer to a new queue handle or NULL on failure. */ +EXPORT_SYMBOL struct nfq_handle *nfq_open(void) { struct nfnl_handle *nfnlh = nfnl_open(); @@ -366,7 +398,6 @@ struct nfq_handle *nfq_open(void) return qh; } -EXPORT_SYMBOL(nfq_open); /** * @} @@ -377,11 +408,12 @@ EXPORT_SYMBOL(nfq_open); * \param nfnlh Netfilter netlink connection handle obtained by calling nfnl_open() * * This function obtains a netfilter queue connection handle using an existing - * netlink connection. This function is used internally to implement + * netlink connection. This function is used internally to implement * nfq_open(), and should typically not be called directly. * * \return a pointer to a new queue handle or NULL on failure. */ +EXPORT_SYMBOL struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh) { struct nfnl_callback pkt_cb = { @@ -398,7 +430,7 @@ struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh) memset(h, 0, sizeof(*h)); h->nfnlh = nfnlh; - h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE, + h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE, NFQNL_MSG_MAX, 0); if (!h->nfnlssh) { /* FIXME: nfq_errno */ @@ -419,7 +451,6 @@ out_free: free(h); return NULL; } -EXPORT_SYMBOL(nfq_open_nfnl); /** * \addtogroup LibrarySetup @@ -427,6 +458,14 @@ EXPORT_SYMBOL(nfq_open_nfnl); * When the program has finished with libnetfilter_queue, it has to call * the nfq_close() function to free all associated resources. * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <linux/netfilter/nfnetlink_queue.h> +#include <libnetfilter_queue/libnetfilter_queue.h> +\endmanonly + * * @{ */ @@ -436,18 +475,18 @@ EXPORT_SYMBOL(nfq_open_nfnl); * * This function closes the nfqueue handler and free associated resources. * - * \return 0 on success, non-zero on failure. + * \return 0 on success, non-zero on failure. */ +EXPORT_SYMBOL int nfq_close(struct nfq_handle *h) { int ret; - + ret = nfnl_close(h->nfnlh); if (ret == 0) free(h); return ret; } -EXPORT_SYMBOL(nfq_close); /** * nfq_bind_pf - bind a nfqueue handler to a given protocol family @@ -460,11 +499,11 @@ EXPORT_SYMBOL(nfq_close); * * \return integer inferior to 0 in case of failure */ +EXPORT_SYMBOL int nfq_bind_pf(struct nfq_handle *h, uint16_t pf) { return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf); } -EXPORT_SYMBOL(nfq_bind_pf); /** * nfq_unbind_pf - unbind nfqueue handler from a protocol family @@ -476,11 +515,11 @@ EXPORT_SYMBOL(nfq_bind_pf); * * This call is obsolete, Linux kernels from 3.8 onwards ignore it. */ +EXPORT_SYMBOL int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf) { return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf); } -EXPORT_SYMBOL(nfq_unbind_pf); /** @@ -503,15 +542,15 @@ EXPORT_SYMBOL(nfq_unbind_pf); * \return a nfq_q_handle pointing to the newly created queue * * Creates a new queue handle, and returns it. The new queue is identified by - * #num, and the callback specified by #cb will be called for each enqueued - * packet. The #data argument will be passed unchanged to the callback. If - * a queue entry with id #num already exists, this function will return failure - * and the existing entry is unchanged. + * \b num, and the callback specified by \b cb will be called for each enqueued + * packet. The \b data argument will be passed unchanged to the callback. If + * a queue entry with id \b num already exists, + * this function will return failure and the existing entry is unchanged. * * The nfq_callback type is defined in libnetfilter_queue.h as: * \verbatim typedef int nfq_callback(struct nfq_q_handle *qh, - struct nfgenmsg *nfmsg, + struct nfgenmsg *nfmsg, struct nfq_data *nfad, void *data); \endverbatim * @@ -524,10 +563,9 @@ typedef int nfq_callback(struct nfq_q_handle *qh, * The callback should return < 0 to stop processing. */ -struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, - uint16_t num, - nfq_callback *cb, - void *data) +EXPORT_SYMBOL +struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, uint16_t num, + nfq_callback *cb, void *data) { int ret; struct nfq_q_handle *qh; @@ -555,7 +593,6 @@ struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, add_qh(qh); return qh; } -EXPORT_SYMBOL(nfq_create_queue); /** * @} @@ -573,6 +610,7 @@ EXPORT_SYMBOL(nfq_create_queue); * Removes the binding for the specified queue handle. This call also unbind * from the nfqueue handler, so you don't have to call nfq_unbind_pf. */ +EXPORT_SYMBOL int nfq_destroy_queue(struct nfq_q_handle *qh) { int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0); @@ -583,7 +621,6 @@ int nfq_destroy_queue(struct nfq_q_handle *qh) return ret; } -EXPORT_SYMBOL(nfq_destroy_queue); /** * nfq_handle_packet - handle a packet received from the nfqueue subsystem @@ -597,11 +634,11 @@ EXPORT_SYMBOL(nfq_destroy_queue); * * \return 0 on success, non-zero on failure. */ +EXPORT_SYMBOL int nfq_handle_packet(struct nfq_handle *h, char *buf, int len) { return nfnl_handle_packet(h->nfnlh, buf, len); } -EXPORT_SYMBOL(nfq_handle_packet); /** * nfq_set_mode - set the amount of packet data that nfqueue copies to userspace @@ -618,8 +655,8 @@ EXPORT_SYMBOL(nfq_handle_packet); * * \return -1 on error; >=0 otherwise. */ -int nfq_set_mode(struct nfq_q_handle *qh, - uint8_t mode, uint32_t range) +EXPORT_SYMBOL +int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range) { union { char buf[NFNL_HEADER_LEN @@ -638,13 +675,12 @@ int nfq_set_mode(struct nfq_q_handle *qh, return nfnl_query(qh->h->nfnlh, &u.nmh); } -EXPORT_SYMBOL(nfq_set_mode); /** * nfq_set_queue_flags - set flags (options) for the kernel queue * \param qh Netfilter queue handle obtained by call to nfq_create_queue(). * \param mask specifies which flag bits to modify - * \param flag bitmask of flags + * \param flags bitmask of flags * * Existing flags, that you may want to combine, are: * @@ -698,11 +734,18 @@ EXPORT_SYMBOL(nfq_set_mode); flags &= ~NFQA_CFG_F_FAIL_OPEN; err = nfq_set_queue_flags(qh, mask, flags); \endverbatim + * - NFQA_CFG_F_SECCTX: the kernel will dump security context of the socket to + * which each packet belongs. + * + * \warning + * When fragmentation occurs and NFQA_CFG_F_GSO is NOT set then the kernel + * dumps UID/GID and security context fields only for one fragment. To deal + * with this limitation always set NFQA_CFG_F_GSO. * * \return -1 on error with errno set appropriately; =0 otherwise. */ -int nfq_set_queue_flags(struct nfq_q_handle *qh, - uint32_t mask, uint32_t flags) +EXPORT_SYMBOL +int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags) { union { char buf[NFNL_HEADER_LEN @@ -722,7 +765,6 @@ int nfq_set_queue_flags(struct nfq_q_handle *qh, return nfnl_query(qh->h->nfnlh, &u.nmh); } -EXPORT_SYMBOL(nfq_set_queue_flags); /** * nfq_set_queue_maxlen - Set kernel queue maximum length parameter @@ -735,8 +777,8 @@ EXPORT_SYMBOL(nfq_set_queue_flags); * * \return -1 on error; >=0 otherwise. */ -int nfq_set_queue_maxlen(struct nfq_q_handle *qh, - uint32_t queuelen) +EXPORT_SYMBOL +int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen) { union { char buf[NFNL_HEADER_LEN @@ -753,7 +795,6 @@ int nfq_set_queue_maxlen(struct nfq_q_handle *qh, return nfnl_query(qh->h->nfnlh, &u.nmh); } -EXPORT_SYMBOL(nfq_set_queue_maxlen); /** * @} @@ -818,19 +859,19 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id, */ /** - * nfq_set_verdict - issue a verdict on a packet + * nfq_set_verdict - issue a verdict on a packet * \param qh Netfilter queue handle obtained by call to nfq_create_queue(). * \param id ID assigned to packet by netfilter. * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) - * \param data_len number of bytes of data pointed to by #buf + * \param data_len number of bytes of data pointed to by \b buf * \param buf the buffer that contains the packet data * - * Can be obtained by: + * Can be obtained by: * \verbatim int id; struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(tb); if (ph) - id = ntohl(ph->packet_id); + id = ntohl(ph->packet_id); \endverbatim * * Notifies netfilter of the userspace verdict for the given packet. Every @@ -840,14 +881,14 @@ static int __set_verdict(struct nfq_q_handle *qh, uint32_t id, * * \return -1 on error; >= 0 otherwise. */ +EXPORT_SYMBOL int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id, - uint32_t verdict, uint32_t data_len, - const unsigned char *buf) + uint32_t verdict, uint32_t data_len, + const unsigned char *buf) { return __set_verdict(qh, id, verdict, 0, 0, data_len, buf, NFQNL_MSG_VERDICT); } -EXPORT_SYMBOL(nfq_set_verdict); /** * nfq_set_verdict2 - like nfq_set_verdict, but you can set the mark. @@ -855,9 +896,10 @@ EXPORT_SYMBOL(nfq_set_verdict); * \param id ID assigned to packet by netfilter. * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) * \param mark mark to put on packet - * \param data_len number of bytes of data pointed to by #buf + * \param data_len number of bytes of data pointed to by \b buf * \param buf the buffer that contains the packet data */ +EXPORT_SYMBOL int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id, uint32_t verdict, uint32_t mark, uint32_t data_len, const unsigned char *buf) @@ -865,7 +907,6 @@ int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id, return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len, buf, NFQNL_MSG_VERDICT); } -EXPORT_SYMBOL(nfq_set_verdict2); /** * nfq_set_verdict_batch - issue verdicts on several packets at once @@ -874,18 +915,18 @@ EXPORT_SYMBOL(nfq_set_verdict2); * \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. + * whose packet id is smaller or equal to \b id. * * batch support was added in Linux 3.1. * These functions will fail silently on older kernels. */ +EXPORT_SYMBOL int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id, - uint32_t verdict) + uint32_t verdict) { return __set_verdict(qh, id, verdict, 0, 0, 0, NULL, NFQNL_MSG_VERDICT_BATCH); } -EXPORT_SYMBOL(nfq_set_verdict_batch); /** * nfq_set_verdict_batch2 - like nfq_set_verdict_batch, but you can set a mark. @@ -894,13 +935,13 @@ EXPORT_SYMBOL(nfq_set_verdict_batch); * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) * \param mark mark to put on packet */ +EXPORT_SYMBOL int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id, - uint32_t verdict, uint32_t mark) + uint32_t verdict, uint32_t mark) { return __set_verdict(qh, id, verdict, htonl(mark), 1, 0, NULL, NFQNL_MSG_VERDICT_BATCH); } -EXPORT_SYMBOL(nfq_set_verdict_batch2); /** * nfq_set_verdict_mark - like nfq_set_verdict, but you can set the mark. @@ -908,7 +949,7 @@ EXPORT_SYMBOL(nfq_set_verdict_batch2); * \param id ID assigned to packet by netfilter. * \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP) * \param mark the mark to put on the packet, in network byte order. - * \param data_len number of bytes of data pointed to by #buf + * \param data_len number of bytes of data pointed to by \b buf * \param buf the buffer that contains the packet data * * \return -1 on error; >= 0 otherwise. @@ -916,14 +957,14 @@ EXPORT_SYMBOL(nfq_set_verdict_batch2); * This function is deprecated since it is broken, its use is highly * discouraged. Please, use nfq_set_verdict2 instead. */ +EXPORT_SYMBOL int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id, - uint32_t verdict, uint32_t mark, - uint32_t data_len, const unsigned char *buf) + uint32_t verdict, uint32_t mark, + uint32_t data_len, const unsigned char *buf) { return __set_verdict(qh, id, verdict, mark, 1, data_len, buf, NFQNL_MSG_VERDICT); } -EXPORT_SYMBOL(nfq_set_verdict_mark); /** * @} @@ -932,11 +973,20 @@ EXPORT_SYMBOL(nfq_set_verdict_mark); /************************************************************* - * Message parsing functions + * Message parsing functions *************************************************************/ /** * \defgroup Parsing Message parsing functions [DEPRECATED] + * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <linux/netfilter/nfnetlink_queue.h> +#include <libnetfilter_queue/libnetfilter_queue.h> +\endmanonly + * * @{ */ @@ -958,12 +1008,12 @@ EXPORT_SYMBOL(nfq_set_verdict_mark); } __attribute__ ((packed)); \endverbatim */ +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); } -EXPORT_SYMBOL(nfq_get_msg_packet_hdr); /** * nfq_get_nfmark - get the packet mark @@ -971,11 +1021,11 @@ EXPORT_SYMBOL(nfq_get_msg_packet_hdr); * * \return the netfilter mark currently assigned to the given queued packet. */ +EXPORT_SYMBOL uint32_t nfq_get_nfmark(struct nfq_data *nfad) { return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t)); } -EXPORT_SYMBOL(nfq_get_nfmark); /** * nfq_get_timestamp - get the packet timestamp @@ -986,6 +1036,7 @@ EXPORT_SYMBOL(nfq_get_nfmark); * * \return 0 on success, non-zero on failure. */ +EXPORT_SYMBOL int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv) { struct nfqnl_msg_packet_timestamp *qpt; @@ -999,7 +1050,6 @@ int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv) return 0; } -EXPORT_SYMBOL(nfq_get_timestamp); /** * nfq_get_indev - get the interface that the packet was received through @@ -1012,11 +1062,11 @@ EXPORT_SYMBOL(nfq_get_timestamp); * \warning all nfq_get_dev() functions return 0 if not set, since linux * only allows ifindex >= 1, see net/core/dev.c:2600 (in 2.6.13.1) */ +EXPORT_SYMBOL uint32_t nfq_get_indev(struct nfq_data *nfad) { return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t)); } -EXPORT_SYMBOL(nfq_get_indev); /** * nfq_get_physindev - get the physical interface that the packet was received @@ -1026,11 +1076,11 @@ EXPORT_SYMBOL(nfq_get_indev); * If the returned index is 0, the packet was locally generated or the * physical input interface is no longer known (ie. POSTROUTING?). */ +EXPORT_SYMBOL uint32_t nfq_get_physindev(struct nfq_data *nfad) { return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t)); } -EXPORT_SYMBOL(nfq_get_physindev); /** * nfq_get_outdev - gets the interface that the packet will be routed out @@ -1040,11 +1090,11 @@ EXPORT_SYMBOL(nfq_get_physindev); * returned index is 0, the packet is destined for localhost or the output * interface is not yet known (ie. PREROUTING?). */ +EXPORT_SYMBOL uint32_t nfq_get_outdev(struct nfq_data *nfad) { return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t)); } -EXPORT_SYMBOL(nfq_get_outdev); /** * nfq_get_physoutdev - get the physical interface that the packet output @@ -1053,14 +1103,14 @@ EXPORT_SYMBOL(nfq_get_outdev); * The index of the physical device the queued packet will be sent out. * If the returned index is 0, the packet is destined for localhost or the * physical output interface is not yet known (ie. PREROUTING?). - * + * * \return The index of physical interface that the packet output will be routed out. */ +EXPORT_SYMBOL uint32_t nfq_get_physoutdev(struct nfq_data *nfad) { return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t)); } -EXPORT_SYMBOL(nfq_get_physoutdev); /** * nfq_get_indev_name - get the name of the interface the packet @@ -1069,44 +1119,44 @@ EXPORT_SYMBOL(nfq_get_physoutdev); * \param nfad Netlink packet data handle passed to callback function * \param name pointer to the buffer to receive the interface name; * not more than \c IFNAMSIZ bytes will be copied to it. - * \return -1 in case of error, >0 if it succeed. + * \return -1 in case of error, >0 if it succeed. * * To use a nlif_handle, You need first to call nlif_open() and to open - * an handler. Don't forget to store the result as it will be used + * an handler. Don't forget to store the result as it will be used * during all your program life: * \verbatim h = nlif_open(); - if (h == NULL) { - perror("nlif_open"); - exit(EXIT_FAILURE); - } + if (h == NULL) { + perror("nlif_open"); + exit(EXIT_FAILURE); + } \endverbatim * Once the handler is open, you need to fetch the interface table at a * whole via a call to nlif_query. * \verbatim - nlif_query(h); + nlif_query(h); \endverbatim * libnfnetlink is able to update the interface mapping when a new interface * appears. To do so, you need to call nlif_catch() on the handler after each * interface related event. The simplest way to get and treat event is to run - * a select() or poll() against the nlif file descriptor. To get this file + * a select() or poll() against the nlif file descriptor. To get this file * descriptor, you need to use nlif_fd: * \verbatim - if_fd = nlif_fd(h); + if_fd = nlif_fd(h); \endverbatim * Don't forget to close the handler when you don't need the feature anymore: * \verbatim - nlif_close(h); + nlif_close(h); \endverbatim * */ +EXPORT_SYMBOL int nfq_get_indev_name(struct nlif_handle *nlif_handle, - struct nfq_data *nfad, char *name) + struct nfq_data *nfad, char *name) { uint32_t ifindex = nfq_get_indev(nfad); return nlif_index2name(nlif_handle, ifindex, name); } -EXPORT_SYMBOL(nfq_get_indev_name); /** * nfq_get_physindev_name - get the name of the physical interface the @@ -1118,15 +1168,15 @@ EXPORT_SYMBOL(nfq_get_indev_name); * * See nfq_get_indev_name() documentation for nlif_handle usage. * - * \return -1 in case of error, > 0 if it succeed. + * \return -1 in case of error, > 0 if it succeed. */ +EXPORT_SYMBOL int nfq_get_physindev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name) { uint32_t ifindex = nfq_get_physindev(nfad); return nlif_index2name(nlif_handle, ifindex, name); } -EXPORT_SYMBOL(nfq_get_physindev_name); /** * nfq_get_outdev_name - get the name of the physical interface the @@ -1138,15 +1188,15 @@ EXPORT_SYMBOL(nfq_get_physindev_name); * * See nfq_get_indev_name() documentation for nlif_handle usage. * - * \return -1 in case of error, > 0 if it succeed. + * \return -1 in case of error, > 0 if it succeed. */ +EXPORT_SYMBOL int nfq_get_outdev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name) { uint32_t ifindex = nfq_get_outdev(nfad); return nlif_index2name(nlif_handle, ifindex, name); } -EXPORT_SYMBOL(nfq_get_outdev_name); /** * nfq_get_physoutdev_name - get the name of the interface the @@ -1158,21 +1208,21 @@ EXPORT_SYMBOL(nfq_get_outdev_name); * * See nfq_get_indev_name() documentation for nlif_handle usage. * - * \return -1 in case of error, > 0 if it succeed. + * \return -1 in case of error, > 0 if it succeed. */ +EXPORT_SYMBOL int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle, struct nfq_data *nfad, char *name) { uint32_t ifindex = nfq_get_physoutdev(nfad); return nlif_index2name(nlif_handle, ifindex, name); } -EXPORT_SYMBOL(nfq_get_physoutdev_name); /** * nfq_get_packet_hw * - * get hardware address + * get hardware address * * \param nfad Netlink packet data handle passed to callback function * @@ -1191,19 +1241,56 @@ EXPORT_SYMBOL(nfq_get_physoutdev_name); } __attribute__ ((packed)); \endverbatim */ +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); } -EXPORT_SYMBOL(nfq_get_packet_hw); + +/** + * nfq_get_skbinfo - return the NFQA_SKB_INFO meta information + * \param nfad Netlink packet data handle passed to callback function + * + * This can be used to obtain extra information about a packet by testing + * the returned integer for any of the following bit flags: + * + * - NFQA_SKB_CSUMNOTREADY + * packet header checksums will be computed by hardware later on, i.e. + * tcp/ip checksums in the packet must not be validated, application + * should pretend they are correct. + * - NFQA_SKB_GSO + * packet is an aggregated super-packet. It exceeds device mtu and will + * be (re-)split on transmit by hardware. + * - NFQA_SKB_CSUM_NOTVERIFIED + * packet checksum was not yet verified by the kernel/hardware, for + * example because this is an incoming packet and the NIC does not + * perform checksum validation at hardware level. + * + * \return the skbinfo value + * \sa __nfq_set_queue_flags__(3) + */ +EXPORT_SYMBOL +uint32_t nfq_get_skbinfo(struct nfq_data *nfad) +{ + if (!nfnl_attr_present(nfad->data, NFQA_SKB_INFO)) + return 0; + + return ntohl(nfnl_get_data(nfad->data, NFQA_SKB_INFO, uint32_t)); +} /** * nfq_get_uid - get the UID of the user the packet belongs to * \param nfad Netlink packet data handle passed to callback function + * \param uid Set to UID on return + * + * \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets + * may be pushed into the queue. In this case, only one fragment will have the + * UID field set. To deal with this issue always set NFQA_CFG_F_GSO. * * \return 1 if there is a UID available, 0 otherwise. */ +EXPORT_SYMBOL int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid) { if (!nfnl_attr_present(nfad->data, NFQA_UID)) @@ -1212,14 +1299,19 @@ int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid) *uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t)); return 1; } -EXPORT_SYMBOL(nfq_get_uid); /** * nfq_get_gid - get the GID of the user the packet belongs to * \param nfad Netlink packet data handle passed to callback function + * \param gid Set to GID on return + * + * \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets + * may be pushed into the queue. In this case, only one fragment will have the + * GID field set. To deal with this issue always set NFQA_CFG_F_GSO. * * \return 1 if there is a GID available, 0 otherwise. */ +EXPORT_SYMBOL int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid) { if (!nfnl_attr_present(nfad->data, NFQA_GID)) @@ -1228,16 +1320,19 @@ int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid) *gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t)); return 1; } -EXPORT_SYMBOL(nfq_get_gid); - /** * nfq_get_secctx - get the security context for this packet * \param nfad Netlink packet data handle passed to callback function * \param secdata data to write the security context to * + * \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets + * may be pushed into the queue. In this case, only one fragment will have the + * SECCTX field set. To deal with this issue always set NFQA_CFG_F_GSO. + * * \return -1 on error, otherwise > 0 */ +EXPORT_SYMBOL int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata) { if (!nfnl_attr_present(nfad->data, NFQA_SECCTX)) @@ -1251,10 +1346,9 @@ int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata) return 0; } -EXPORT_SYMBOL(nfq_get_secctx); /** - * nfq_get_payload - get payload + * nfq_get_payload - get payload * \param nfad Netlink packet data handle passed to callback function * \param data Pointer of pointer that will be pointed to the payload * @@ -1264,6 +1358,7 @@ EXPORT_SYMBOL(nfq_get_secctx); * * \return -1 on error, otherwise > 0. */ +EXPORT_SYMBOL int nfq_get_payload(struct nfq_data *nfad, unsigned char **data) { *data = (unsigned char *) @@ -1273,7 +1368,6 @@ int nfq_get_payload(struct nfq_data *nfad, unsigned char **data) return -1; } -EXPORT_SYMBOL(nfq_get_payload); /** * @} @@ -1292,6 +1386,15 @@ do { \ /** * \defgroup Printing Printing [DEPRECATED] + * + * \manonly +.SH SYNOPSIS +.nf +\fB +#include <linux/netfilter/nfnetlink_queue.h> +#include <libnetfilter_queue/libnetfilter_queue.h> +\endmanonly + * * @{ */ @@ -1318,6 +1421,7 @@ do { \ * would have been printed into the buffer (in case that there is enough * room in it). See snprintf() return value for more information. */ +EXPORT_SYMBOL int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags) { struct nfqnl_msg_packet_hdr *ph; @@ -1471,7 +1575,6 @@ int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags) return len; } -EXPORT_SYMBOL(nfq_snprintf_xml); /** * @} |