|
Packit |
c43939 |
/* libnetfilter_queue.c: generic library for access to nf_queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* (C) 2005 by Harald Welte <laforge@gnumonks.org>
|
|
Packit |
c43939 |
* (C) 2005, 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
c43939 |
* it under the terms of the GNU General Public License version 2
|
|
Packit |
c43939 |
* as published by the Free Software Foundation (or any later at your option)
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
c43939 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
c43939 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
c43939 |
* GNU General Public License for more details.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
c43939 |
* along with this program; if not, write to the Free Software
|
|
Packit |
c43939 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* 2006-01-23 Andreas Florath <andreas@florath.net>
|
|
Packit |
c43939 |
* Fix __set_verdict() that it can now handle payload.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
#include <stdio.h>
|
|
Packit |
c43939 |
#include <stdlib.h>
|
|
Packit |
c43939 |
#include <unistd.h>
|
|
Packit |
c43939 |
#include <string.h>
|
|
Packit |
c43939 |
#include <ctype.h>
|
|
Packit |
c43939 |
#include <time.h>
|
|
Packit |
c43939 |
#include <errno.h>
|
|
Packit |
c43939 |
#include <netinet/in.h>
|
|
Packit |
c43939 |
#include <sys/socket.h>
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
#include <libnfnetlink/libnfnetlink.h>
|
|
Packit |
c43939 |
#include <libnetfilter_queue/libnetfilter_queue.h>
|
|
Packit |
c43939 |
#include "internal.h"
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \mainpage
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* libnetfilter_queue is a userspace library providing an API to packets that
|
|
Packit |
c43939 |
* have been queued by the kernel packet filter. It is is part of a system that
|
|
Packit |
c43939 |
* replaces the old ip_queue / libipq mechanism (withdrawn in kernel 3.5).
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* libnetfilter_queue homepage is:
|
|
Packit |
c43939 |
* https://netfilter.org/projects/libnetfilter_queue/
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section deps Dependencies
|
|
Packit |
c43939 |
* libnetfilter_queue requires libmnl, libnfnetlink and a kernel that includes
|
|
Packit |
c43939 |
* the Netfilter NFQUEUE over NFNETLINK interface (i.e. 2.6.14 or later).
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section features Main Features
|
|
Packit |
c43939 |
* - receiving queued packets from the kernel nfnetlink_queue subsystem
|
|
Packit |
c43939 |
* - issuing verdicts and possibly reinjecting altered packets to the kernel
|
|
Packit |
c43939 |
* nfnetlink_queue subsystem
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The cinematic is the following: When an nft rule with action **queue**
|
|
Packit |
c43939 |
* matches, the kernel terminates the current nft chain and enqueues the packet
|
|
Packit |
c43939 |
* in a chained list. It then formats and sends an nfnetlink message containing
|
|
Packit |
c43939 |
* the packet id and whatever information the userspace program configured to
|
|
Packit |
c43939 |
* receive (packet data and/or metadata) via a socket to the userspace program.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The userspace program must issue a verdict advising the kernel to **accept**
|
|
Packit |
c43939 |
* or **drop** the packet. Either verdict takes the packet off the queue:
|
|
Packit |
c43939 |
* **drop** discards the packet while
|
|
Packit |
c43939 |
* **accept** passes it on to the next chain.
|
|
Packit |
c43939 |
* Userspace can also alter packet contents or metadata (e.g. packet mark,
|
|
Packit |
c43939 |
* contrack mark). Verdict can be done in asynchronous manner, as the only
|
|
Packit |
c43939 |
* needed information is the packet id.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* When a queue is full, packets that should have been enqueued are dropped by
|
|
Packit |
c43939 |
* kernel instead of being enqueued.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section git Git Tree
|
|
Packit |
c43939 |
* The current development version of libnetfilter_queue can be accessed at
|
|
Packit |
c43939 |
* https://git.netfilter.org/libnetfilter_queue.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section privs Privileges
|
|
Packit |
c43939 |
* You need the CAP_NET_ADMIN capability in order to allow your application
|
|
Packit |
c43939 |
* to receive from and to send packets to kernel-space.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section using Using libnetfilter_queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* To write your own program using libnetfilter_queue, you should start by
|
|
Packit |
c43939 |
* reading (or, if feasible, compiling and stepping through with *gdb*)
|
|
Packit |
c43939 |
* nf-queue.c source file.
|
|
Packit |
c43939 |
* Simple compile line:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
gcc -g3 -ggdb -Wall -lmnl -lnetfilter_queue -o nf-queue nf-queue.c
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* The doxygen documentation \link LibrarySetup \endlink is Deprecated and
|
|
Packit |
c43939 |
* incompatible with non-deprecated functions. It is hoped to produce a
|
|
Packit |
c43939 |
* corresponding non-deprecated (*Current*) topic soon.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Somewhat outdated but possibly providing some insight into
|
|
Packit |
c43939 |
* libnetfilter_queue usage is the following
|
|
Packit |
c43939 |
* article:
|
|
Packit |
c43939 |
* https://home.regit.org/netfilter-en/using-nfqueue-and-libnetfilter_queue/
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section errors ENOBUFS errors in recv()
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* recv() may return -1 and errno is set to ENOBUFS in case that your
|
|
Packit |
c43939 |
* application is not fast enough to retrieve the packets from the kernel.
|
|
Packit |
c43939 |
* In that case, you can increase the socket buffer size by means of
|
|
Packit |
c43939 |
* nfnl_rcvbufsiz(). Although this delays the appearance of ENOBUFS errors,
|
|
Packit |
c43939 |
* you may hit it again sooner or later. The next section provides some hints
|
|
Packit |
c43939 |
* on how to obtain the best performance for your application.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \section perf Performance
|
|
Packit |
c43939 |
* To improve your libnetfilter_queue application in terms of performance,
|
|
Packit |
c43939 |
* you may consider the following tweaks:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - increase the default socket buffer size by means of nfnl_rcvbufsiz().
|
|
Packit |
c43939 |
* - set nice value of your process to -20 (maximum priority).
|
|
Packit |
c43939 |
* - set the CPU affinity of your process to a spare core that is not used
|
|
Packit |
c43939 |
* to handle NIC interruptions.
|
|
Packit |
c43939 |
* - set NETLINK_NO_ENOBUFS socket option to avoid receiving ENOBUFS errors
|
|
Packit |
c43939 |
* (requires Linux kernel >= 2.6.30).
|
|
Packit |
c43939 |
* - see --queue-balance option in NFQUEUE target for multi-threaded apps
|
|
Packit |
c43939 |
* (it requires Linux kernel >= 2.6.31).
|
|
Packit |
c43939 |
* - consider using fail-open option see nfq_set_queue_flags() (it requires
|
|
Packit |
c43939 |
* Linux kernel >= 3.6)
|
|
Packit |
c43939 |
* - increase queue max length with nfq_set_queue_maxlen() to resist to packets
|
|
Packit |
c43939 |
* burst
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
struct nfq_handle
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfnl_handle *nfnlh;
|
|
Packit |
c43939 |
struct nfnl_subsys_handle *nfnlssh;
|
|
Packit |
c43939 |
struct nfq_q_handle *qh_list;
|
|
Packit |
c43939 |
};
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
struct nfq_q_handle
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfq_q_handle *next;
|
|
Packit |
c43939 |
struct nfq_handle *h;
|
|
Packit |
c43939 |
uint16_t id;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfq_callback *cb;
|
|
Packit |
c43939 |
void *data;
|
|
Packit |
c43939 |
};
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
struct nfq_data {
|
|
Packit |
c43939 |
struct nfattr **data;
|
|
Packit |
c43939 |
};
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
EXPORT_SYMBOL int nfq_errno;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/***********************************************************************
|
|
Packit |
c43939 |
* low level stuff
|
|
Packit |
c43939 |
***********************************************************************/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static void del_qh(struct nfq_q_handle *qh)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfq_q_handle *cur_qh, *prev_qh = NULL;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) {
|
|
Packit |
c43939 |
if (cur_qh == qh) {
|
|
Packit |
c43939 |
if (prev_qh)
|
|
Packit |
c43939 |
prev_qh->next = qh->next;
|
|
Packit |
c43939 |
else
|
|
Packit |
c43939 |
qh->h->qh_list = qh->next;
|
|
Packit |
c43939 |
return;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
prev_qh = cur_qh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static void add_qh(struct nfq_q_handle *qh)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
qh->next = qh->h->qh_list;
|
|
Packit |
c43939 |
qh->h->qh_list = qh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static struct nfq_q_handle *find_qh(struct nfq_handle *h, uint16_t id)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfq_q_handle *qh;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
for (qh = h->qh_list; qh; qh = qh->next) {
|
|
Packit |
c43939 |
if (qh->id == id)
|
|
Packit |
c43939 |
return qh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* build a NFQNL_MSG_CONFIG message */
|
|
Packit |
c43939 |
static int
|
|
Packit |
c43939 |
__build_send_cfg_msg(struct nfq_handle *h, uint8_t command,
|
|
Packit |
c43939 |
uint16_t queuenum, uint16_t pf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
union {
|
|
Packit |
c43939 |
char buf[NFNL_HEADER_LEN
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
|
|
Packit |
c43939 |
struct nlmsghdr nmh;
|
|
Packit |
c43939 |
} u;
|
|
Packit |
c43939 |
struct nfqnl_msg_config_cmd cmd;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_fill_hdr(h->nfnlssh, &u.nmh, 0, AF_UNSPEC, queuenum,
|
|
Packit |
c43939 |
NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
cmd._pad = 0;
|
|
Packit |
c43939 |
cmd.command = command;
|
|
Packit |
c43939 |
cmd.pf = htons(pf);
|
|
Packit |
c43939 |
nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_CMD, &cmd, sizeof(cmd));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return nfnl_query(h->nfnlh, &u.nmh);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static int __nfq_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
|
|
Packit |
c43939 |
void *data)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
|
|
Packit |
c43939 |
struct nfq_handle *h = data;
|
|
Packit |
c43939 |
uint16_t queue_num = ntohs(nfmsg->res_id);
|
|
Packit |
c43939 |
struct nfq_q_handle *qh = find_qh(h, queue_num);
|
|
Packit |
c43939 |
struct nfq_data nfqa;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (!qh)
|
|
Packit |
c43939 |
return -ENODEV;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (!qh->cb)
|
|
Packit |
c43939 |
return -ENODEV;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfqa.data = nfa;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return qh->cb(qh, nfmsg, &nfqa, qh->data);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* public interface */
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfnl_handle *nfq_nfnlh(struct nfq_handle *h)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return h->nfnlh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \defgroup Queue Queue handling [DEPRECATED]
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Once libnetfilter_queue library has been initialised (See
|
|
Packit |
c43939 |
* \link LibrarySetup \endlink), it is possible to bind the program to a
|
|
Packit |
c43939 |
* specific queue. This can be done by using nfq_create_queue().
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The queue can then be tuned via nfq_set_mode() or nfq_set_queue_maxlen().
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Here's a little code snippet that create queue numbered 0:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
printf("binding this socket to queue '0'\n");
|
|
Packit |
c43939 |
qh = nfq_create_queue(h, 0, &cb, NULL);
|
|
Packit |
c43939 |
if (!qh) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_create_queue()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("setting copy_packet mode\n");
|
|
Packit |
c43939 |
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "can't set packet_copy mode\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Next step is the handling of incoming packets which can be done via a loop:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
fd = nfq_fd(h);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
while ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
|
|
Packit |
c43939 |
printf("pkt received\n");
|
|
Packit |
c43939 |
nfq_handle_packet(h, buf, rv);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* When the decision on a packet has been choosed, the verdict has to be given
|
|
Packit |
c43939 |
* by calling nfq_set_verdict() or nfq_set_verdict2(). The verdict
|
|
Packit |
c43939 |
* determines the destiny of the packet as follows:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NF_DROP discarded the packet
|
|
Packit |
c43939 |
* - NF_ACCEPT the packet passes, continue iterations
|
|
Packit |
c43939 |
* - NF_QUEUE inject the packet into a different queue
|
|
Packit |
c43939 |
* (the target queue number is in the high 16 bits of the verdict)
|
|
Packit |
c43939 |
* - NF_REPEAT iterate the same cycle once more
|
|
Packit |
c43939 |
* - NF_STOP accept, but don't continue iterations
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The verdict NF_STOLEN must not be used, as it has special meaning in the
|
|
Packit |
c43939 |
* kernel.
|
|
Packit |
c43939 |
* When using NF_REPEAT, one way to prevent re-queueing of the same packet
|
|
Packit |
c43939 |
* is to also set an nfmark using nfq_set_verdict2, and set up the nefilter
|
|
Packit |
c43939 |
* rules to only queue a packet when the mark is not (yet) set.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Data and information about the packet can be fetch by using message parsing
|
|
Packit |
c43939 |
* functions (See \link Parsing \endlink).
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_fd - get the file descriptor associated with the nfqueue handler
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return a file descriptor for the netlink connection associated with the
|
|
Packit |
c43939 |
* given queue connection handle. The file descriptor can then be used for
|
|
Packit |
c43939 |
* receiving the queued packets for processing.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function returns a file descriptor that can be used for communication
|
|
Packit |
c43939 |
* over the netlink connection associated with the given queue connection
|
|
Packit |
c43939 |
* handle.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_fd(struct nfq_handle *h)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return nfnl_fd(nfq_nfnlh(h));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \defgroup LibrarySetup Library setup [DEPRECATED]
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Library initialisation is made in two steps.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* First step is to call nfq_open() to open a NFQUEUE handler.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Second step is to tell the kernel that userspace queueing is handle by
|
|
Packit |
c43939 |
* NFQUEUE for the selected protocol. This is made by calling nfq_unbind_pf()
|
|
Packit |
c43939 |
* and nfq_bind_pf() with protocol information. The idea behind this is to
|
|
Packit |
c43939 |
* enable simultaneously loaded modules to be used for queuing.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Here's a little code snippet that bind with AF_INET:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
h = nfq_open();
|
|
Packit |
c43939 |
if (!h) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_open()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
|
|
Packit |
c43939 |
if (nfq_unbind_pf(h, AF_INET) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_unbind_pf()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
|
|
Packit |
c43939 |
if (nfq_bind_pf(h, AF_INET) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_bind_pf()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* Once this is done, you can setup and use a \link Queue \endlink.
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_open - open a nfqueue handler
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function obtains a netfilter queue connection handle. When you are
|
|
Packit |
c43939 |
* finished with the handle returned by this function, you should destroy
|
|
Packit |
c43939 |
* it by calling nfq_close(). A new netlink connection is obtained internally
|
|
Packit |
c43939 |
* and associated with the queue connection handle returned.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return a pointer to a new queue handle or NULL on failure.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfq_handle *nfq_open(void)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfnl_handle *nfnlh = nfnl_open();
|
|
Packit |
c43939 |
struct nfq_handle *qh;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (!nfnlh)
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* unset netlink sequence tracking by default */
|
|
Packit |
c43939 |
nfnl_unset_sequence_tracking(nfnlh);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
qh = nfq_open_nfnl(nfnlh);
|
|
Packit |
c43939 |
if (!qh)
|
|
Packit |
c43939 |
nfnl_close(nfnlh);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return qh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_open_nfnl - open a nfqueue handler from a existing nfnetlink handler
|
|
Packit |
c43939 |
* \param nfnlh Netfilter netlink connection handle obtained by calling nfnl_open()
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function obtains a netfilter queue connection handle using an existing
|
|
Packit |
c43939 |
* netlink connection. This function is used internally to implement
|
|
Packit |
c43939 |
* nfq_open(), and should typically not be called directly.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return a pointer to a new queue handle or NULL on failure.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfq_handle *nfq_open_nfnl(struct nfnl_handle *nfnlh)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfnl_callback pkt_cb = {
|
|
Packit |
c43939 |
.call = __nfq_rcv_pkt,
|
|
Packit |
c43939 |
.attr_count = NFQA_MAX,
|
|
Packit |
c43939 |
};
|
|
Packit |
c43939 |
struct nfq_handle *h;
|
|
Packit |
c43939 |
int err;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
h = malloc(sizeof(*h));
|
|
Packit |
c43939 |
if (!h)
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
memset(h, 0, sizeof(*h));
|
|
Packit |
c43939 |
h->nfnlh = nfnlh;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
h->nfnlssh = nfnl_subsys_open(h->nfnlh, NFNL_SUBSYS_QUEUE,
|
|
Packit |
c43939 |
NFQNL_MSG_MAX, 0);
|
|
Packit |
c43939 |
if (!h->nfnlssh) {
|
|
Packit |
c43939 |
/* FIXME: nfq_errno */
|
|
Packit |
c43939 |
goto out_free;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
pkt_cb.data = h;
|
|
Packit |
c43939 |
err = nfnl_callback_register(h->nfnlssh, NFQNL_MSG_PACKET, &pkt_cb);
|
|
Packit |
c43939 |
if (err < 0) {
|
|
Packit |
c43939 |
nfq_errno = err;
|
|
Packit |
c43939 |
goto out_close;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return h;
|
|
Packit |
c43939 |
out_close:
|
|
Packit |
c43939 |
nfnl_subsys_close(h->nfnlssh);
|
|
Packit |
c43939 |
out_free:
|
|
Packit |
c43939 |
free(h);
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \addtogroup LibrarySetup
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* When the program has finished with libnetfilter_queue, it has to call
|
|
Packit |
c43939 |
* the nfq_close() function to free all associated resources.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_close - close a nfqueue handler
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function closes the nfqueue handler and free associated resources.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return 0 on success, non-zero on failure.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_close(struct nfq_handle *h)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
int ret;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ret = nfnl_close(h->nfnlh);
|
|
Packit |
c43939 |
if (ret == 0)
|
|
Packit |
c43939 |
free(h);
|
|
Packit |
c43939 |
return ret;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_bind_pf - bind a nfqueue handler to a given protocol family
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
* \param pf protocol family to bind to nfqueue handler obtained from nfq_open()
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Binds the given queue connection handle to process packets belonging to
|
|
Packit |
c43939 |
* the given protocol family (ie. PF_INET, PF_INET6, etc).
|
|
Packit |
c43939 |
* This call is obsolete, Linux kernels from 3.8 onwards ignore it.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return integer inferior to 0 in case of failure
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_bind_pf(struct nfq_handle *h, uint16_t pf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_unbind_pf - unbind nfqueue handler from a protocol family
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
* \param pf protocol family to unbind family from
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Unbinds the given queue connection handle from processing packets belonging
|
|
Packit |
c43939 |
* to the given protocol family.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This call is obsolete, Linux kernels from 3.8 onwards ignore it.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_unbind_pf(struct nfq_handle *h, uint16_t pf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \addtogroup Queue
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_create_queue - create a new queue handle and return it.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
* \param num the number of the queue to bind to
|
|
Packit |
c43939 |
* \param cb callback function to call for each queued packet
|
|
Packit |
c43939 |
* \param data custom data to pass to the callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return a nfq_q_handle pointing to the newly created queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Creates a new queue handle, and returns it. The new queue is identified by
|
|
Packit |
c43939 |
* \b num, and the callback specified by \b cb will be called for each enqueued
|
|
Packit |
c43939 |
* packet. The \b data argument will be passed unchanged to the callback. If
|
|
Packit |
c43939 |
* a queue entry with id \b num already exists,
|
|
Packit |
c43939 |
* this function will return failure and the existing entry is unchanged.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The nfq_callback type is defined in libnetfilter_queue.h as:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
typedef int nfq_callback(struct nfq_q_handle *qh,
|
|
Packit |
c43939 |
struct nfgenmsg *nfmsg,
|
|
Packit |
c43939 |
struct nfq_data *nfad, void *data);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Parameters:
|
|
Packit |
c43939 |
* - qh The queue handle returned by nfq_create_queue
|
|
Packit |
c43939 |
* - nfmsg message objetc that contains the packet
|
|
Packit |
c43939 |
* - nfad Netlink packet data handle
|
|
Packit |
c43939 |
* - data the value passed to the data parameter of nfq_create_queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The callback should return < 0 to stop processing.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfq_q_handle *nfq_create_queue(struct nfq_handle *h, uint16_t num,
|
|
Packit |
c43939 |
nfq_callback *cb, void *data)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
int ret;
|
|
Packit |
c43939 |
struct nfq_q_handle *qh;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (find_qh(h, num))
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
qh = malloc(sizeof(*qh));
|
|
Packit |
c43939 |
if (!qh)
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
memset(qh, 0, sizeof(*qh));
|
|
Packit |
c43939 |
qh->h = h;
|
|
Packit |
c43939 |
qh->id = num;
|
|
Packit |
c43939 |
qh->cb = cb;
|
|
Packit |
c43939 |
qh->data = data;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
|
|
Packit |
c43939 |
if (ret < 0) {
|
|
Packit |
c43939 |
nfq_errno = ret;
|
|
Packit |
c43939 |
free(qh);
|
|
Packit |
c43939 |
return NULL;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
add_qh(qh);
|
|
Packit |
c43939 |
return qh;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \addtogroup Queue
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_destroy_queue - destroy a queue handle
|
|
Packit |
c43939 |
* \param qh queue handle that we want to destroy created via nfq_create_queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Removes the binding for the specified queue handle. This call also unbind
|
|
Packit |
c43939 |
* from the nfqueue handler, so you don't have to call nfq_unbind_pf.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_destroy_queue(struct nfq_q_handle *qh)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
|
|
Packit |
c43939 |
if (ret == 0) {
|
|
Packit |
c43939 |
del_qh(qh);
|
|
Packit |
c43939 |
free(qh);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return ret;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_handle_packet - handle a packet received from the nfqueue subsystem
|
|
Packit |
c43939 |
* \param h Netfilter queue connection handle obtained via call to nfq_open()
|
|
Packit |
c43939 |
* \param buf data to pass to the callback
|
|
Packit |
c43939 |
* \param len length of packet data in buffer
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Triggers an associated callback for the given packet received from the
|
|
Packit |
c43939 |
* queue. Packets can be read from the queue using nfq_fd() and recv(). See
|
|
Packit |
c43939 |
* example code for nfq_fd().
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return 0 on success, non-zero on failure.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_handle_packet(struct nfq_handle *h, char *buf, int len)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return nfnl_handle_packet(h->nfnlh, buf, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_mode - set the amount of packet data that nfqueue copies to userspace
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param mode the part of the packet that we are interested in
|
|
Packit |
c43939 |
* \param range size of the packet that we want to get
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Sets the amount of data to be copied to userspace for each packet queued
|
|
Packit |
c43939 |
* to the given queue.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQNL_COPY_NONE - noop, do not use it
|
|
Packit |
c43939 |
* - NFQNL_COPY_META - copy only packet metadata
|
|
Packit |
c43939 |
* - NFQNL_COPY_PACKET - copy entire packet
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error; >=0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_mode(struct nfq_q_handle *qh, uint8_t mode, uint32_t range)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
union {
|
|
Packit |
c43939 |
char buf[NFNL_HEADER_LEN
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
|
|
Packit |
c43939 |
struct nlmsghdr nmh;
|
|
Packit |
c43939 |
} u;
|
|
Packit |
c43939 |
struct nfqnl_msg_config_params params;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
|
|
Packit |
c43939 |
NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
params.copy_range = htonl(range);
|
|
Packit |
c43939 |
params.copy_mode = mode;
|
|
Packit |
c43939 |
nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_PARAMS, ¶ms,
|
|
Packit |
c43939 |
sizeof(params));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return nfnl_query(qh->h->nfnlh, &u.nmh);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_queue_flags - set flags (options) for the kernel queue
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param mask specifies which flag bits to modify
|
|
Packit |
c43939 |
* \param flags bitmask of flags
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Existing flags, that you may want to combine, are:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQA_CFG_F_FAIL_OPEN (requires Linux kernel >= 3.6): the kernel will
|
|
Packit |
c43939 |
* accept the packets if the kernel queue gets full. If this flag is not
|
|
Packit |
c43939 |
* set, the default action in this case is to drop packets.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQA_CFG_F_CONNTRACK (requires Linux kernel >= 3.6): the kernel will
|
|
Packit |
c43939 |
* include the Connection Tracking system information.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQA_CFG_F_GSO (requires Linux kernel >= 3.10): the kernel will
|
|
Packit |
c43939 |
* not normalize offload packets, i.e. your application will need to
|
|
Packit |
c43939 |
* be able to handle packets larger than the mtu.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Normalization is expensive, so this flag should always be set.
|
|
Packit |
c43939 |
* Because attributes in netlink messages are limited to 65531 bytes,
|
|
Packit |
c43939 |
* you also need to check the NFQA_CAP_LEN attribute, it contains the
|
|
Packit |
c43939 |
* original size of the captured packet on the kernel side.
|
|
Packit |
c43939 |
* If it is set and differs from the payload length, the packet was
|
|
Packit |
c43939 |
* truncated. This also happens when limiting capture size
|
|
Packit |
c43939 |
* with the NFQNL_COPY_PACKET setting, or when e.g. a local user
|
|
Packit |
c43939 |
* sends a very large packet.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* If your application validates checksums (e.g., tcp checksum),
|
|
Packit |
c43939 |
* then you must also check if the NFQA_SKB_INFO attribute is present.
|
|
Packit |
c43939 |
* If it is, you need to test the NFQA_SKB_CSUMNOTREADY bit:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
if (attr[NFQA_SKB_INFO]) {
|
|
Packit |
c43939 |
uint32_t info = ntohl(mnl_attr_get_u32(attr[NFQA_SKB_INFO]));
|
|
Packit |
c43939 |
if (info & NFQA_SKB_CSUMNOTREADY)
|
|
Packit |
c43939 |
validate_checksums = false;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* if this bit is set, the layer 3/4 checksums of the packet appear incorrect,
|
|
Packit |
c43939 |
* but are not (because they will be corrected later by the kernel).
|
|
Packit |
c43939 |
* Please see example/nf-queue.c in the libnetfilter_queue source for more
|
|
Packit |
c43939 |
* details.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQA_CFG_F_UID_GID: the kernel will dump UID and GID of the socket to
|
|
Packit |
c43939 |
* which each packet belongs.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Here's a little code snippet to show how to use this API:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
uint32_t flags = NFQA_CFG_F_FAIL_OPEN;
|
|
Packit |
c43939 |
uint32_t mask = NFQA_CFG_F_FAIL_OPEN;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("Enabling fail-open on this q\n");
|
|
Packit |
c43939 |
err = nfq_set_queue_flags(qh, mask, flags);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("Disabling fail-open on this q\n");
|
|
Packit |
c43939 |
flags &= ~NFQA_CFG_F_FAIL_OPEN;
|
|
Packit |
c43939 |
err = nfq_set_queue_flags(qh, mask, flags);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* - NFQA_CFG_F_SECCTX: the kernel will dump security context of the socket to
|
|
Packit |
c43939 |
* which each packet belongs.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \warning
|
|
Packit |
c43939 |
* When fragmentation occurs and NFQA_CFG_F_GSO is NOT set then the kernel
|
|
Packit |
c43939 |
* dumps UID/GID and security context fields only for one fragment. To deal
|
|
Packit |
c43939 |
* with this limitation always set NFQA_CFG_F_GSO.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error with errno set appropriately; =0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_queue_flags(struct nfq_q_handle *qh, uint32_t mask, uint32_t flags)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
union {
|
|
Packit |
c43939 |
char buf[NFNL_HEADER_LEN
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(mask)
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(flags)))];
|
|
Packit |
c43939 |
struct nlmsghdr nmh;
|
|
Packit |
c43939 |
} u;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
mask = htonl(mask);
|
|
Packit |
c43939 |
flags = htonl(flags);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
|
|
Packit |
c43939 |
NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_FLAGS, flags);
|
|
Packit |
c43939 |
nfnl_addattr32(&u.nmh, sizeof(u), NFQA_CFG_MASK, mask);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return nfnl_query(qh->h->nfnlh, &u.nmh);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_queue_maxlen - Set kernel queue maximum length parameter
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param queuelen the length of the queue
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Sets the size of the queue in kernel. This fixes the maximum number
|
|
Packit |
c43939 |
* of packets the kernel will store before internally before dropping
|
|
Packit |
c43939 |
* upcoming packets.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error; >=0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_queue_maxlen(struct nfq_q_handle *qh, uint32_t queuelen)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
union {
|
|
Packit |
c43939 |
char buf[NFNL_HEADER_LEN
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
|
|
Packit |
c43939 |
struct nlmsghdr nmh;
|
|
Packit |
c43939 |
} u;
|
|
Packit |
c43939 |
uint32_t queue_maxlen = htonl(queuelen);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
|
|
Packit |
c43939 |
NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_CFG_QUEUE_MAXLEN, &queue_maxlen,
|
|
Packit |
c43939 |
sizeof(queue_maxlen));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return nfnl_query(qh->h->nfnlh, &u.nmh);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static int __set_verdict(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict, uint32_t mark, int set_mark,
|
|
Packit |
c43939 |
uint32_t data_len, const unsigned char *data,
|
|
Packit |
c43939 |
enum nfqnl_msg_types type)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfqnl_msg_verdict_hdr vh;
|
|
Packit |
c43939 |
union {
|
|
Packit |
c43939 |
char buf[NFNL_HEADER_LEN
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(mark))
|
|
Packit |
c43939 |
+NFA_LENGTH(sizeof(vh))];
|
|
Packit |
c43939 |
struct nlmsghdr nmh;
|
|
Packit |
c43939 |
} u;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
struct iovec iov[3];
|
|
Packit |
c43939 |
int nvecs;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* This must be declared here (and not inside the data
|
|
Packit |
c43939 |
* handling block) because the iovec points to this. */
|
|
Packit |
c43939 |
struct nfattr data_attr;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
memset(iov, 0, sizeof(iov));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
vh.verdict = htonl(verdict);
|
|
Packit |
c43939 |
vh.id = htonl(id);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
nfnl_fill_hdr(qh->h->nfnlssh, &u.nmh, 0, AF_UNSPEC, qh->id,
|
|
Packit |
c43939 |
type, NLM_F_REQUEST);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* add verdict header */
|
|
Packit |
c43939 |
nfnl_addattr_l(&u.nmh, sizeof(u), NFQA_VERDICT_HDR, &vh, sizeof(vh));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (set_mark)
|
|
Packit |
c43939 |
nfnl_addattr32(&u.nmh, sizeof(u), NFQA_MARK, mark);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
iov[0].iov_base = &u.nmh;
|
|
Packit |
c43939 |
iov[0].iov_len = NLMSG_TAIL(&u.nmh) - (void *)&u.nmh;
|
|
Packit |
c43939 |
nvecs = 1;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (data_len) {
|
|
Packit |
c43939 |
/* The typecast here is to cast away data's const-ness: */
|
|
Packit |
c43939 |
nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD,
|
|
Packit |
c43939 |
data_len, (unsigned char *) data);
|
|
Packit |
c43939 |
nvecs += 2;
|
|
Packit |
c43939 |
/* Add the length of the appended data to the message
|
|
Packit |
c43939 |
* header. The size of the attribute is given in the
|
|
Packit |
c43939 |
* nfa_len field and is set in the nfnl_build_nfa_iovec()
|
|
Packit |
c43939 |
* function. */
|
|
Packit |
c43939 |
u.nmh.nlmsg_len += data_attr.nfa_len;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return nfnl_sendiov(qh->h->nfnlh, iov, nvecs, 0);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \addtogroup Queue
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_verdict - issue a verdict on a packet
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param id ID assigned to packet by netfilter.
|
|
Packit |
c43939 |
* \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP)
|
|
Packit |
c43939 |
* \param data_len number of bytes of data pointed to by \b buf
|
|
Packit |
c43939 |
* \param buf the buffer that contains the packet data
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Can be obtained by:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
int id;
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(tb);
|
|
Packit |
c43939 |
if (ph)
|
|
Packit |
c43939 |
id = ntohl(ph->packet_id);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Notifies netfilter of the userspace verdict for the given packet. Every
|
|
Packit |
c43939 |
* queued packet _must_ have a verdict specified by userspace, either by
|
|
Packit |
c43939 |
* calling this function, the nfq_set_verdict2() function, or the _batch
|
|
Packit |
c43939 |
* versions of these functions.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error; >= 0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_verdict(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict, uint32_t data_len,
|
|
Packit |
c43939 |
const unsigned char *buf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __set_verdict(qh, id, verdict, 0, 0, data_len, buf,
|
|
Packit |
c43939 |
NFQNL_MSG_VERDICT);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_verdict2 - like nfq_set_verdict, but you can set the mark.
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param id ID assigned to packet by netfilter.
|
|
Packit |
c43939 |
* \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP)
|
|
Packit |
c43939 |
* \param mark mark to put on packet
|
|
Packit |
c43939 |
* \param data_len number of bytes of data pointed to by \b buf
|
|
Packit |
c43939 |
* \param buf the buffer that contains the packet data
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_verdict2(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict, uint32_t mark,
|
|
Packit |
c43939 |
uint32_t data_len, const unsigned char *buf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __set_verdict(qh, id, verdict, htonl(mark), 1, data_len,
|
|
Packit |
c43939 |
buf, NFQNL_MSG_VERDICT);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_verdict_batch - issue verdicts on several packets at once
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param id maximum ID of the packets that the verdict should be applied to.
|
|
Packit |
c43939 |
* \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP)
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Unlike nfq_set_verdict, the verdict is applied to all queued packets
|
|
Packit |
c43939 |
* whose packet id is smaller or equal to \b id.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* batch support was added in Linux 3.1.
|
|
Packit |
c43939 |
* These functions will fail silently on older kernels.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_verdict_batch(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __set_verdict(qh, id, verdict, 0, 0, 0, NULL,
|
|
Packit |
c43939 |
NFQNL_MSG_VERDICT_BATCH);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_verdict_batch2 - like nfq_set_verdict_batch, but you can set a mark.
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param id maximum ID of the packets that the verdict should be applied to.
|
|
Packit |
c43939 |
* \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP)
|
|
Packit |
c43939 |
* \param mark mark to put on packet
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_verdict_batch2(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict, uint32_t mark)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __set_verdict(qh, id, verdict, htonl(mark), 1, 0,
|
|
Packit |
c43939 |
NULL, NFQNL_MSG_VERDICT_BATCH);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_set_verdict_mark - like nfq_set_verdict, but you can set the mark.
|
|
Packit |
c43939 |
* \param qh Netfilter queue handle obtained by call to nfq_create_queue().
|
|
Packit |
c43939 |
* \param id ID assigned to packet by netfilter.
|
|
Packit |
c43939 |
* \param verdict verdict to return to netfilter (NF_ACCEPT, NF_DROP)
|
|
Packit |
c43939 |
* \param mark the mark to put on the packet, in network byte order.
|
|
Packit |
c43939 |
* \param data_len number of bytes of data pointed to by \b buf
|
|
Packit |
c43939 |
* \param buf the buffer that contains the packet data
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error; >= 0 otherwise.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function is deprecated since it is broken, its use is highly
|
|
Packit |
c43939 |
* discouraged. Please, use nfq_set_verdict2 instead.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_set_verdict_mark(struct nfq_q_handle *qh, uint32_t id,
|
|
Packit |
c43939 |
uint32_t verdict, uint32_t mark,
|
|
Packit |
c43939 |
uint32_t data_len, const unsigned char *buf)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return __set_verdict(qh, id, verdict, mark, 1, data_len, buf,
|
|
Packit |
c43939 |
NFQNL_MSG_VERDICT);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/*************************************************************
|
|
Packit |
c43939 |
* Message parsing functions
|
|
Packit |
c43939 |
*************************************************************/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \defgroup Parsing Message parsing functions [DEPRECATED]
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfqnl_msg_packet_hdr - return the metaheader that wraps the packet
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return the netfilter queue netlink packet header for the given
|
|
Packit |
c43939 |
* nfq_data argument. Typically, the nfq_data value is passed as the 3rd
|
|
Packit |
c43939 |
* parameter to the callback function set by a call to nfq_create_queue().
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The nfqnl_msg_packet_hdr structure is defined in libnetfilter_queue.h as:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr {
|
|
Packit |
c43939 |
uint32_t packet_id; // unique ID of packet in queue
|
|
Packit |
c43939 |
uint16_t hw_protocol; // hw protocol (network order)
|
|
Packit |
c43939 |
uint8_t hook; // netfilter hook
|
|
Packit |
c43939 |
} __attribute__ ((packed));
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr *nfq_get_msg_packet_hdr(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return nfnl_get_pointer_to_data(nfad->data, NFQA_PACKET_HDR,
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_nfmark - get the packet mark
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return the netfilter mark currently assigned to the given queued packet.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_nfmark(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_MARK, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_timestamp - get the packet timestamp
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param tv structure to fill with timestamp info
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Retrieves the received timestamp when the given queued packet.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return 0 on success, non-zero on failure.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_timestamp(struct nfq_data *nfad, struct timeval *tv)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_timestamp *qpt;
|
|
Packit |
c43939 |
qpt = nfnl_get_pointer_to_data(nfad->data, NFQA_TIMESTAMP,
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_timestamp);
|
|
Packit |
c43939 |
if (!qpt)
|
|
Packit |
c43939 |
return -1;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
tv->tv_sec = __be64_to_cpu(qpt->sec);
|
|
Packit |
c43939 |
tv->tv_usec = __be64_to_cpu(qpt->usec);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return 0;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_indev - get the interface that the packet was received through
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return The index of the device the queued packet was received via. If the
|
|
Packit |
c43939 |
* returned index is 0, the packet was locally generated or the input
|
|
Packit |
c43939 |
* interface is not known (ie. POSTROUTING?).
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \warning all nfq_get_dev() functions return 0 if not set, since linux
|
|
Packit |
c43939 |
* only allows ifindex >= 1, see net/core/dev.c:2600 (in 2.6.13.1)
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_indev(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_INDEV, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_physindev - get the physical interface that the packet was received
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return The index of the physical device the queued packet was received via.
|
|
Packit |
c43939 |
* If the returned index is 0, the packet was locally generated or the
|
|
Packit |
c43939 |
* physical input interface is no longer known (ie. POSTROUTING?).
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_physindev(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSINDEV, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_outdev - gets the interface that the packet will be routed out
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return The index of the device the queued packet will be sent out. If the
|
|
Packit |
c43939 |
* returned index is 0, the packet is destined for localhost or the output
|
|
Packit |
c43939 |
* interface is not yet known (ie. PREROUTING?).
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_outdev(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_OUTDEV, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_physoutdev - get the physical interface that the packet output
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The index of the physical device the queued packet will be sent out.
|
|
Packit |
c43939 |
* If the returned index is 0, the packet is destined for localhost or the
|
|
Packit |
c43939 |
* physical output interface is not yet known (ie. PREROUTING?).
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return The index of physical interface that the packet output will be routed out.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_physoutdev(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_IFINDEX_PHYSOUTDEV, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_indev_name - get the name of the interface the packet
|
|
Packit |
c43939 |
* was received through
|
|
Packit |
c43939 |
* \param nlif_handle pointer to a nlif interface resolving handle
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param name pointer to the buffer to receive the interface name;
|
|
Packit |
c43939 |
* not more than \c IFNAMSIZ bytes will be copied to it.
|
|
Packit |
c43939 |
* \return -1 in case of error, >0 if it succeed.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* To use a nlif_handle, You need first to call nlif_open() and to open
|
|
Packit |
c43939 |
* an handler. Don't forget to store the result as it will be used
|
|
Packit |
c43939 |
* during all your program life:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
h = nlif_open();
|
|
Packit |
c43939 |
if (h == NULL) {
|
|
Packit |
c43939 |
perror("nlif_open");
|
|
Packit |
c43939 |
exit(EXIT_FAILURE);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* Once the handler is open, you need to fetch the interface table at a
|
|
Packit |
c43939 |
* whole via a call to nlif_query.
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
nlif_query(h);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* libnfnetlink is able to update the interface mapping when a new interface
|
|
Packit |
c43939 |
* appears. To do so, you need to call nlif_catch() on the handler after each
|
|
Packit |
c43939 |
* interface related event. The simplest way to get and treat event is to run
|
|
Packit |
c43939 |
* a select() or poll() against the nlif file descriptor. To get this file
|
|
Packit |
c43939 |
* descriptor, you need to use nlif_fd:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
if_fd = nlif_fd(h);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
* Don't forget to close the handler when you don't need the feature anymore:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
nlif_close(h);
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_indev_name(struct nlif_handle *nlif_handle,
|
|
Packit |
c43939 |
struct nfq_data *nfad, char *name)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
uint32_t ifindex = nfq_get_indev(nfad);
|
|
Packit |
c43939 |
return nlif_index2name(nlif_handle, ifindex, name);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_physindev_name - get the name of the physical interface the
|
|
Packit |
c43939 |
* packet was received through
|
|
Packit |
c43939 |
* \param nlif_handle pointer to a nlif interface resolving handle
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param name pointer to the buffer to receive the interface name;
|
|
Packit |
c43939 |
* not more than \c IFNAMSIZ bytes will be copied to it.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* See nfq_get_indev_name() documentation for nlif_handle usage.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 in case of error, > 0 if it succeed.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_physindev_name(struct nlif_handle *nlif_handle,
|
|
Packit |
c43939 |
struct nfq_data *nfad, char *name)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
uint32_t ifindex = nfq_get_physindev(nfad);
|
|
Packit |
c43939 |
return nlif_index2name(nlif_handle, ifindex, name);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_outdev_name - get the name of the physical interface the
|
|
Packit |
c43939 |
* packet will be sent to
|
|
Packit |
c43939 |
* \param nlif_handle pointer to a nlif interface resolving handle
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param name pointer to the buffer to receive the interface name;
|
|
Packit |
c43939 |
* not more than \c IFNAMSIZ bytes will be copied to it.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* See nfq_get_indev_name() documentation for nlif_handle usage.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 in case of error, > 0 if it succeed.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_outdev_name(struct nlif_handle *nlif_handle,
|
|
Packit |
c43939 |
struct nfq_data *nfad, char *name)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
uint32_t ifindex = nfq_get_outdev(nfad);
|
|
Packit |
c43939 |
return nlif_index2name(nlif_handle, ifindex, name);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_physoutdev_name - get the name of the interface the
|
|
Packit |
c43939 |
* packet will be sent to
|
|
Packit |
c43939 |
* \param nlif_handle pointer to a nlif interface resolving handle
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param name pointer to the buffer to receive the interface name;
|
|
Packit |
c43939 |
* not more than \c IFNAMSIZ bytes will be copied to it.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* See nfq_get_indev_name() documentation for nlif_handle usage.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 in case of error, > 0 if it succeed.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_physoutdev_name(struct nlif_handle *nlif_handle,
|
|
Packit |
c43939 |
struct nfq_data *nfad, char *name)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
uint32_t ifindex = nfq_get_physoutdev(nfad);
|
|
Packit |
c43939 |
return nlif_index2name(nlif_handle, ifindex, name);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_packet_hw
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* get hardware address
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Retrieves the hardware address associated with the given queued packet.
|
|
Packit |
c43939 |
* For ethernet packets, the hardware address returned (if any) will be the
|
|
Packit |
c43939 |
* MAC address of the packet source host. The destination MAC address is not
|
|
Packit |
c43939 |
* known until after POSTROUTING and a successful ARP request, so cannot
|
|
Packit |
c43939 |
* currently be retrieved.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* The nfqnl_msg_packet_hw structure is defined in libnetfilter_queue.h as:
|
|
Packit |
c43939 |
* \verbatim
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hw {
|
|
Packit |
c43939 |
uint16_t hw_addrlen;
|
|
Packit |
c43939 |
uint16_t _pad;
|
|
Packit |
c43939 |
uint8_t hw_addr[8];
|
|
Packit |
c43939 |
} __attribute__ ((packed));
|
|
Packit |
c43939 |
\endverbatim
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hw *nfq_get_packet_hw(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
return nfnl_get_pointer_to_data(nfad->data, NFQA_HWADDR,
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hw);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_skbinfo - return the NFQA_SKB_INFO meta information
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This can be used to obtain extra information about a packet by testing
|
|
Packit |
c43939 |
* the returned integer for any of the following bit flags:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQA_SKB_CSUMNOTREADY
|
|
Packit |
c43939 |
* packet header checksums will be computed by hardware later on, i.e.
|
|
Packit |
c43939 |
* tcp/ip checksums in the packet must not be validated, application
|
|
Packit |
c43939 |
* should pretend they are correct.
|
|
Packit |
c43939 |
* - NFQA_SKB_GSO
|
|
Packit |
c43939 |
* packet is an aggregated super-packet. It exceeds device mtu and will
|
|
Packit |
c43939 |
* be (re-)split on transmit by hardware.
|
|
Packit |
c43939 |
* - NFQA_SKB_CSUM_NOTVERIFIED
|
|
Packit |
c43939 |
* packet checksum was not yet verified by the kernel/hardware, for
|
|
Packit |
c43939 |
* example because this is an incoming packet and the NIC does not
|
|
Packit |
c43939 |
* perform checksum validation at hardware level.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return the skbinfo value
|
|
Packit |
c43939 |
* \sa __nfq_set_queue_flags__(3)
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
uint32_t nfq_get_skbinfo(struct nfq_data *nfad)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
if (!nfnl_attr_present(nfad->data, NFQA_SKB_INFO))
|
|
Packit |
c43939 |
return 0;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return ntohl(nfnl_get_data(nfad->data, NFQA_SKB_INFO, uint32_t));
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_uid - get the UID of the user the packet belongs to
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param uid Set to UID on return
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets
|
|
Packit |
c43939 |
* may be pushed into the queue. In this case, only one fragment will have the
|
|
Packit |
c43939 |
* UID field set. To deal with this issue always set NFQA_CFG_F_GSO.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return 1 if there is a UID available, 0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_uid(struct nfq_data *nfad, uint32_t *uid)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
if (!nfnl_attr_present(nfad->data, NFQA_UID))
|
|
Packit |
c43939 |
return 0;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
*uid = ntohl(nfnl_get_data(nfad->data, NFQA_UID, uint32_t));
|
|
Packit |
c43939 |
return 1;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_gid - get the GID of the user the packet belongs to
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param gid Set to GID on return
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets
|
|
Packit |
c43939 |
* may be pushed into the queue. In this case, only one fragment will have the
|
|
Packit |
c43939 |
* GID field set. To deal with this issue always set NFQA_CFG_F_GSO.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return 1 if there is a GID available, 0 otherwise.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_gid(struct nfq_data *nfad, uint32_t *gid)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
if (!nfnl_attr_present(nfad->data, NFQA_GID))
|
|
Packit |
c43939 |
return 0;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
*gid = ntohl(nfnl_get_data(nfad->data, NFQA_GID, uint32_t));
|
|
Packit |
c43939 |
return 1;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_secctx - get the security context for this packet
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param secdata data to write the security context to
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \warning If the NFQA_CFG_F_GSO flag is not set, then fragmented packets
|
|
Packit |
c43939 |
* may be pushed into the queue. In this case, only one fragment will have the
|
|
Packit |
c43939 |
* SECCTX field set. To deal with this issue always set NFQA_CFG_F_GSO.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error, otherwise > 0
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_secctx(struct nfq_data *nfad, unsigned char **secdata)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
if (!nfnl_attr_present(nfad->data, NFQA_SECCTX))
|
|
Packit |
c43939 |
return -1;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
*secdata = (unsigned char *)nfnl_get_pointer_to_data(nfad->data,
|
|
Packit |
c43939 |
NFQA_SECCTX, char);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (*secdata)
|
|
Packit |
c43939 |
return NFA_PAYLOAD(nfad->data[NFQA_SECCTX-1]);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return 0;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_get_payload - get payload
|
|
Packit |
c43939 |
* \param nfad Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param data Pointer of pointer that will be pointed to the payload
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* Retrieve the payload for a queued packet. The actual amount and type of
|
|
Packit |
c43939 |
* data retrieved by this function will depend on the mode set with the
|
|
Packit |
c43939 |
* nfq_set_mode() function.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 on error, otherwise > 0.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_get_payload(struct nfq_data *nfad, unsigned char **data)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
*data = (unsigned char *)
|
|
Packit |
c43939 |
nfnl_get_pointer_to_data(nfad->data, NFQA_PAYLOAD, char);
|
|
Packit |
c43939 |
if (*data)
|
|
Packit |
c43939 |
return NFA_PAYLOAD(nfad->data[NFQA_PAYLOAD-1]);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return -1;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
#define SNPRINTF_FAILURE(ret, rem, offset, len) \
|
|
Packit |
c43939 |
do { \
|
|
Packit |
c43939 |
if (ret < 0) \
|
|
Packit |
c43939 |
return ret; \
|
|
Packit |
c43939 |
len += ret; \
|
|
Packit |
c43939 |
if (ret > rem) \
|
|
Packit |
c43939 |
ret = rem; \
|
|
Packit |
c43939 |
offset += ret; \
|
|
Packit |
c43939 |
rem -= ret; \
|
|
Packit |
c43939 |
} while (0)
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* \defgroup Printing Printing [DEPRECATED]
|
|
Packit |
c43939 |
* @{
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* nfq_snprintf_xml - print the enqueued packet in XML format into a buffer
|
|
Packit |
c43939 |
* \param buf The buffer that you want to use to print the logged packet
|
|
Packit |
c43939 |
* \param rem The size of the buffer that you have passed
|
|
Packit |
c43939 |
* \param tb Netlink packet data handle passed to callback function
|
|
Packit |
c43939 |
* \param flags The flag that tell what to print into the buffer
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* This function supports the following flags:
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* - NFQ_XML_HW: include the hardware link layer address
|
|
Packit |
c43939 |
* - NFQ_XML_MARK: include the packet mark
|
|
Packit |
c43939 |
* - NFQ_XML_DEV: include the device information
|
|
Packit |
c43939 |
* - NFQ_XML_PHYSDEV: include the physical device information
|
|
Packit |
c43939 |
* - NFQ_XML_PAYLOAD: include the payload (in hexadecimal)
|
|
Packit |
c43939 |
* - NFQ_XML_TIME: include the timestamp
|
|
Packit |
c43939 |
* - NFQ_XML_ALL: include all the logging information (all flags set)
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* You can combine this flags with an binary OR.
|
|
Packit |
c43939 |
*
|
|
Packit |
c43939 |
* \return -1 in case of failure, otherwise the length of the string that
|
|
Packit |
c43939 |
* would have been printed into the buffer (in case that there is enough
|
|
Packit |
c43939 |
* room in it). See snprintf() return value for more information.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
EXPORT_SYMBOL
|
|
Packit |
c43939 |
int nfq_snprintf_xml(char *buf, size_t rem, struct nfq_data *tb, int flags)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr *ph;
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hw *hwph;
|
|
Packit |
c43939 |
uint32_t mark, ifi;
|
|
Packit |
c43939 |
uint32_t uid, gid;
|
|
Packit |
c43939 |
int size, offset = 0, len = 0, ret;
|
|
Packit |
c43939 |
unsigned char *data;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<pkt>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (flags & NFQ_XML_TIME) {
|
|
Packit |
c43939 |
time_t t;
|
|
Packit |
c43939 |
struct tm tm;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
t = time(NULL);
|
|
Packit |
c43939 |
if (localtime_r(&t, &tm) == NULL)
|
|
Packit |
c43939 |
return -1;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<when>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem,
|
|
Packit |
c43939 |
"<hour>%d</hour>", tm.tm_hour);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset,
|
|
Packit |
c43939 |
rem, "<min>%02d</min>", tm.tm_min);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset,
|
|
Packit |
c43939 |
rem, "<sec>%02d</sec>", tm.tm_sec);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<wday>%d</wday>",
|
|
Packit |
c43939 |
tm.tm_wday + 1);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<day>%d</day>", tm.tm_mday);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<month>%d</month>",
|
|
Packit |
c43939 |
tm.tm_mon + 1);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<year>%d</year>",
|
|
Packit |
c43939 |
1900 + tm.tm_year);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "</when>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ph = nfq_get_msg_packet_hdr(tb);
|
|
Packit |
c43939 |
if (ph) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem,
|
|
Packit |
c43939 |
"<hook>%u</hook><id>%u</id>",
|
|
Packit |
c43939 |
ph->hook, ntohl(ph->packet_id));
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
hwph = nfq_get_packet_hw(tb);
|
|
Packit |
c43939 |
if (hwph && (flags & NFQ_XML_HW)) {
|
|
Packit |
c43939 |
int i, hlen = ntohs(hwph->hw_addrlen);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<hw><proto>%04x"
|
|
Packit |
c43939 |
"</proto>",
|
|
Packit |
c43939 |
ntohs(ph->hw_protocol));
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<src>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
for (i=0; i
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "%02x",
|
|
Packit |
c43939 |
hwph->hw_addr[i]);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "</src></hw>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
} else if (flags & NFQ_XML_HW) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<hw><proto>%04x"
|
|
Packit |
c43939 |
"</proto></hw>",
|
|
Packit |
c43939 |
ntohs(ph->hw_protocol));
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
mark = nfq_get_nfmark(tb);
|
|
Packit |
c43939 |
if (mark && (flags & NFQ_XML_MARK)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<mark>%u</mark>", mark);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_indev(tb);
|
|
Packit |
c43939 |
if (ifi && (flags & NFQ_XML_DEV)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<indev>%u</indev>", ifi);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_outdev(tb);
|
|
Packit |
c43939 |
if (ifi && (flags & NFQ_XML_DEV)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<outdev>%u</outdev>", ifi);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_physindev(tb);
|
|
Packit |
c43939 |
if (ifi && (flags & NFQ_XML_PHYSDEV)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem,
|
|
Packit |
c43939 |
"<physindev>%u</physindev>", ifi);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_physoutdev(tb);
|
|
Packit |
c43939 |
if (ifi && (flags & NFQ_XML_PHYSDEV)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem,
|
|
Packit |
c43939 |
"<physoutdev>%u</physoutdev>", ifi);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (nfq_get_uid(tb, &uid) && (flags & NFQ_XML_UID)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<uid>%u</uid>", uid);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (nfq_get_gid(tb, &gid) && (flags & NFQ_XML_GID)) {
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<gid>%u</gid>", gid);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ret = nfq_get_payload(tb, &data);
|
|
Packit |
c43939 |
if (ret >= 0 && (flags & NFQ_XML_PAYLOAD)) {
|
|
Packit |
c43939 |
int i;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "<payload>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
for (i=0; i
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "%02x",
|
|
Packit |
c43939 |
data[i] & 0xff);
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "</payload>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
size = snprintf(buf + offset, rem, "</pkt>");
|
|
Packit |
c43939 |
SNPRINTF_FAILURE(size, rem, offset, len);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return len;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/**
|
|
Packit |
c43939 |
* @}
|
|
Packit |
c43939 |
*/
|