From 0a0a6669a49b5253344a33f2fc9116ed67424887 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=laforge/emailAddress=laforge@netfilter.org" Date: Tue, 26 Jul 2005 06:56:22 +0000 Subject: add new queue userspace library --- libnfnetlink_queue.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 libnfnetlink_queue.c (limited to 'libnfnetlink_queue.c') diff --git a/libnfnetlink_queue.c b/libnfnetlink_queue.c new file mode 100644 index 0000000..a3c58b7 --- /dev/null +++ b/libnfnetlink_queue.c @@ -0,0 +1,182 @@ +/* libnfqnetlink.c: generic library for access to nf_queue + * + * (C) 2005 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libnfqnetlink.h" + +/*********************************************************************** + * low level stuff + ***********************************************************************/ + +int nfqnl_open(struct nfqnl_handle *h) +{ + int err; + + memset(h, 0, sizeof(*h)); + + err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, subscriptions); + if (err < 0) + return err; + + return 0; +} + +int nfqnl_close(struct nfqnl_handle *h) +{ + return nfnl_close(&h->nfnlh); +} + +/* build a NFQNL_MSG_CONFIG message */ +static int +__build_send_cfg_msg(const struct nfqnl_handle *h, u_int8_t command, + u_int16_t queuenum, u_int16_t pf) +{ + char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) + +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + +NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))]; + struct nfqnl_msg_config_cmd cmd; + struct nlmsghdr *nmh = (struct nlmsghdr *) buf; + + nfnl_fill_hdr(&h->nfnlh, nmh, 0, AF_UNSPEC, queuenum, + NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); + + cmd.command = command; + cmd.pf = htons(pf); + nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd)); + + return nfnl_send(&h->nfnlh, nmh); +} + +/* bind nf_queue from a specific protocol family */ +int nfqnl_bind_pf(const struct nfqnl_handle *h, u_int16_t pf) +{ + return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_BIND, 0, pf); +} + +/* unbind nf_queue from a specific protocol family */ +int nfqnl_unbind_pf(const struct nfqnl_handle *h, u_int16_t pf) +{ + return __build_send_cfg_msg(h, NFQNL_CFG_CMD_PF_UNBIND, 0, pf); +} + +/* bind this socket to a specific queue number */ +int nfqnl_create_queue(const struct nfqnl_handle *h, + struct nfqnl_q_handle *qh, u_int16_t num) +{ + qh->queue = h; + qh->id = qh; + + return __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0); +} + +/* unbind this socket from a specific queue number */ +int nfqnl_destroy_queue(struct nfqnl_q_handle *qh) +{ + int ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_UNBIND, num, 0); + if (ret == 0) + qh->h = NULL; + + return ret; +} + +int nfqnl_set_mode(const struct nfqnl_q_handle *qh + u_int8_t mode, u_int32_t range) +{ + char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) + +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + +NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))]; + struct nfqnl_msg_config_params params; + struct nlmsghdr *nmh = (struct nlmsghdr *) buf; + + nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, queuenum, + NFQNL_MSG_CONFIG, NLM_F_REQUEST|NLM_F_ACK); + + params.copy_range = htonl(range); + params.copy_mode = mode; + nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, ¶ms, + sizeof(params)); + + return nfnl_send(&qh->h->nfnlh, nmh); +} + +static int __set_verdict(const struct nfqnl_q_handle *qh, u_int32_t id, + u_int32_t verdict, u_int32_t mark, int set_mark, + u_int32_t data_len, unsigned char *buf) +{ + struct nfqnl_msg_verdict_hdr vh; + char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr)) + +NLMSG_LENGTH(sizeof(struct nfgenmsg)) + +NFA_LENGTH(sizeof(mark)) + +NFA_LENGTH(sizeof(vh))]; + struct nlmsghdr *nmh = (struct nlmsghdr *) buf; + + struct iovec iov[3]; + struct msghdr msg; + int nvecs; + + vh.verdict = htonl(verdict); + vh.id = htonl(id); + + nfnl_fill_hdr(&qh->h->nfnlh, nmh, 0, AF_UNSPEC, queuenum, + NFQNL_MSG_VERDICT, NLM_F_REQUEST); + + /* add verdict header */ + nfnl_addattr_l(nmh, sizeof(buf), NFQA_VERDICT_HDR, &vh, sizeof(vh)); + + if (set_mark) + nfnl_addattr32(nmh, sizeof(buf), NFQA_MARK, mark); + + iov[0].iov_base = nmh; + iov[0].iov_len = FIXME; + nvecs = 1; + + if (data_len) { + struct nfattr data_attr; + + nfnl_build_nfa_iovec(&iov[1], &data_attr, NFQA_PAYLOAD, + data_len, buf); + nvecs += 2; + } + + return nfnl_sendiov(&qh->h->nfnlh, &iov, nvecs, 0); +} + +int nfqnl_set_verdict(const struct nfqnl_q_handle *qh, u_int32_t id, + u_int32_t verdict, u_int32_t data_len, + unsigned char *buf) +{ + return __set_verdict(qh, id, verdict, 0, 0, datalen, buf); +} + +int nfqnl_set_verdict_mark(const struct nfqnl_q_handle *qh, u_int32_t id, + u_int32_t verdict, u_int32_t mark, + u_int32_t datalen, unsigned char *buf) +{ + return __set_verdict(qh, id, verdict, mark, 1, datalen, buf); +} -- cgit v1.2.3