summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libnfnetlink_queue/libipq.h4
-rw-r--r--include/libnfnetlink_queue/libnfnetlink_queue.h53
-rw-r--r--src/libipq_compat.c27
-rw-r--r--src/libnfnetlink_queue.c181
4 files changed, 197 insertions, 68 deletions
diff --git a/include/libnfnetlink_queue/libipq.h b/include/libnfnetlink_queue/libipq.h
index 483a514..06c10c1 100644
--- a/include/libnfnetlink_queue/libipq.h
+++ b/include/libnfnetlink_queue/libipq.h
@@ -52,8 +52,8 @@ typedef unsigned long ipq_id_t;
struct ipq_handle
{
- struct nfqnl_handle nfqnlh;
- struct nfqnl_q_handle qh;
+ struct nfqnl_handle *nfqnlh;
+ struct nfqnl_q_handle *qh;
u_int8_t family;
u_int8_t blocking;
};
diff --git a/include/libnfnetlink_queue/libnfnetlink_queue.h b/include/libnfnetlink_queue/libnfnetlink_queue.h
index b3aad73..b4d6f81 100644
--- a/include/libnfnetlink_queue/libnfnetlink_queue.h
+++ b/include/libnfnetlink_queue/libnfnetlink_queue.h
@@ -13,39 +13,32 @@
#include <linux/netfilter/nfnetlink_queue.h>
#include <libnfnetlink/libnfnetlink.h>
+struct nfqnl_handle;
+struct nfqnl_q_handle;
-#define NFQN
-struct nfqnl_handle
-{
- struct nfnl_handle nfnlh;
-};
-
-struct nfqnl_q_handle
-{
- struct nfqnl_handle *h;
- u_int16_t id;
-};
-
-struct ctnl_msg_handler {
- int type;
- int (*handler)(struct sockaddr_nl *, struct nlmsghdr *, void *arg);
-};
-
-struct ctnl_handle {
- struct nfnl_handle nfnlh;
- struct ctnl_msg_handler *handler[NFQNL_MSG_MAX];
-};
-
-extern int nfqnl_open(struct nfqnl_handle *h);
+extern int nfqnl_errno;
+
+extern struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h);
+extern int nfqnl_fd(struct nfqnl_handle *h);
+
+typedef nfqnl_callback(struct nfqnl_q_handle *gh, struct nfgenmsg *nfmsg,
+ struct nfattr *nfa[], void *data);
+
+
+extern struct nfqnl_handle *nfqnl_open(void);
extern int nfqnl_close(struct nfqnl_handle *h);
extern int nfqnl_bind_pf(struct nfqnl_handle *h, u_int16_t pf);
extern int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf);
-extern int nfqnl_create_queue(struct nfqnl_handle *h,
- struct nfqnl_q_handle *qh, u_int16_t num);
+extern struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h,
+ u_int16_t num,
+ nfqnl_callback *cb,
+ void *data);
extern int nfqnl_destroy_queue(struct nfqnl_q_handle *qh);
+extern int nfqnl_handle_packet(struct nfqnl_handle *h, char *buf, int len);
+
extern int nfqnl_set_mode(struct nfqnl_q_handle *qh,
u_int8_t mode, unsigned int len);
@@ -54,8 +47,10 @@ extern int nfqnl_set_verdict(struct nfqnl_q_handle *qh,
u_int32_t verdict,
u_int32_t data_len,
unsigned char *buf);
-
-extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh, u_int32_t id,
- u_int32_t verdict, u_int32_t mark,
- u_int32_t datalen, unsigned char *buf);
+extern int nfqnl_set_verdict_mark(struct nfqnl_q_handle *qh,
+ u_int32_t id,
+ u_int32_t verdict,
+ u_int32_t mark,
+ u_int32_t datalen,
+ unsigned char *buf);
#endif /* __LIBNFQNETLINK_H */
diff --git a/src/libipq_compat.c b/src/libipq_compat.c
index 9e99674..d263aed 100644
--- a/src/libipq_compat.c
+++ b/src/libipq_compat.c
@@ -27,8 +27,8 @@
#include <sys/time.h>
#include <sys/types.h>
-#include "libnfnetlink_queue.h"
-#include "libipq.h"
+#include <libnfnetlink_queue/libnfnetlink_queue.h>
+#include <libnfnetlink_queue/libipq.h>
/****************************************************************************
*
@@ -216,16 +216,16 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol)
memset(h, 0, sizeof(struct ipq_handle));
- status = nfqnl_open(&h->nfqnlh);
- if (status < 0) {
+ h->nfqnlh = nfqnl_open();
+ if (!h->nfqnlh) {
ipq_errno = IPQ_ERR_SOCKET;
goto err_free;
}
if (protocol == PF_INET)
- status = nfqnl_bind_pf(&h->nfqnlh, PF_INET);
+ status = nfqnl_bind_pf(h->nfqnlh, PF_INET);
else if (protocol == PF_INET6)
- status = nfqnl_bind_pf(&h->nfqnlh, PF_INET6);
+ status = nfqnl_bind_pf(h->nfqnlh, PF_INET6);
else {
ipq_errno = IPQ_ERR_PROTOCOL;
goto err_close;
@@ -236,8 +236,8 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol)
goto err_close;
}
- status = nfqnl_create_queue(&h->nfqnlh, &h->qh, 0);
- if (status < 0) {
+ h->qh = nfqnl_create_queue(h->nfqnlh, 0, NULL, NULL);
+ if (!h->qh) {
ipq_errno = IPQ_ERR_BIND;
goto err_close;
}
@@ -245,7 +245,7 @@ struct ipq_handle *ipq_create_handle(u_int32_t flags, u_int32_t protocol)
return h;
err_close:
- nfqnl_close(&h->nfqnlh);
+ nfqnl_close(h->nfqnlh);
err_free:
free(h);
return NULL;
@@ -258,7 +258,7 @@ err_free:
int ipq_destroy_handle(struct ipq_handle *h)
{
if (h) {
- nfqnl_close(&h->nfqnlh);
+ nfqnl_close(h->nfqnlh);
free(h);
}
return 0;
@@ -267,7 +267,7 @@ int ipq_destroy_handle(struct ipq_handle *h)
int ipq_set_mode(const struct ipq_handle *h,
u_int8_t mode, size_t range)
{
- return nfqnl_set_mode(&h->qh, mode, range);
+ return nfqnl_set_mode(h->qh, mode, range);
}
/*
@@ -288,7 +288,7 @@ ssize_t ipq_read(const struct ipq_handle *h,
* in order to build a data structure that is compatible to
* the old ipq interface... */
- nfa = nfnl_parse_hdr(&h->nfqnlh.nfnlh, nlh, &msg);
+ nfa = nfnl_parse_hdr(nfqnl_nfnlh(h->nfqnlh), nlh, &msg);
if (!msg || !nfa)
return 0;
@@ -298,6 +298,7 @@ ssize_t ipq_read(const struct ipq_handle *h,
nfnl_parse_attr(tb, NFQA_MAX, nfa, 0xffff);
+ return 0;
}
int ipq_message_type(const unsigned char *buf)
@@ -323,7 +324,7 @@ int ipq_set_verdict(const struct ipq_handle *h,
size_t data_len,
unsigned char *buf)
{
- return nfqnl_set_verdict(&h->qh, id, verdict, data_len, buf);
+ return nfqnl_set_verdict(h->qh, id, verdict, data_len, buf);
}
/* Not implemented yet */
diff --git a/src/libnfnetlink_queue.c b/src/libnfnetlink_queue.c
index d65c2eb..62f914d 100644
--- a/src/libnfnetlink_queue.c
+++ b/src/libnfnetlink_queue.c
@@ -32,26 +32,60 @@
#include <libnfnetlink/libnfnetlink.h>
#include <libnfnetlink_queue/libnfnetlink_queue.h>
+struct nfqnl_handle
+{
+ struct nfnl_handle nfnlh;
+ struct nfqnl_q_handle *qh_list;
+};
+
+struct nfqnl_q_handle
+{
+ struct nfqnl_q_handle *next;
+ struct nfqnl_handle *h;
+ u_int16_t id;
+
+ nfqnl_callback *cb;
+ void *data;
+};
+
+
+int nfqnl_errno;
+
/***********************************************************************
* low level stuff
***********************************************************************/
-int nfqnl_open(struct nfqnl_handle *h)
+static void del_qh(struct nfqnl_q_handle *qh)
{
- int err;
-
- memset(h, 0, sizeof(*h));
-
- err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, 0);
- if (err < 0)
- return err;
+ struct nfqnl_q_handle *cur_qh, *prev_qh = NULL;
+
+ for (cur_qh = qh->h->qh_list; cur_qh; cur_qh = cur_qh->next) {
+ if (cur_qh == qh) {
+ if (prev_qh)
+ prev_qh->next = qh->next;
+ else
+ qh->h->qh_list = qh->next;
+ return;
+ }
+ prev_qh = cur_qh;
+ }
+}
- return 0;
+static void add_qh(struct nfqnl_q_handle *qh)
+{
+ qh->next = qh->h->qh_list;
+ qh->h->qh_list = qh;
}
-int nfqnl_close(struct nfqnl_handle *h)
+static struct nfqnl_q_handle *find_qh(struct nfqnl_handle *h, u_int16_t id)
{
- return nfnl_close(&h->nfnlh);
+ struct nfqnl_q_handle *qh;
+
+ for (qh = h->qh_list; qh; qh = qh->next) {
+ if (qh->id == id)
+ return qh;
+ }
+ return NULL;
}
/* build a NFQNL_MSG_CONFIG message */
@@ -59,8 +93,7 @@ static int
__build_send_cfg_msg(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))
+ char buf[NFNL_HEADER_LEN
+NFA_LENGTH(sizeof(struct nfqnl_msg_config_cmd))];
struct nfqnl_msg_config_cmd cmd;
struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
@@ -72,7 +105,81 @@ __build_send_cfg_msg(struct nfqnl_handle *h, u_int8_t command,
cmd.pf = htons(pf);
nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_CMD, &cmd, sizeof(cmd));
- return nfnl_send(&h->nfnlh, nmh);
+ return nfnl_talk(&h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
+}
+
+static int __nfqnl_rcv_pkt(struct nlmsghdr *nlh, struct nfattr *nfa[],
+ void *data)
+{
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ struct nfqnl_handle *h = data;
+ u_int16_t queue_num = ntohs(nfmsg->res_id);
+ struct nfqnl_q_handle *qh = find_qh(h, queue_num);
+
+ if (!qh)
+ return -ENODEV;
+
+ if (!qh->cb)
+ return -ENODEV;
+
+ return qh->cb(qh, nfmsg, nfa, qh->data);
+}
+
+static struct nfnl_callback pkt_cb = {
+ .call = &__nfqnl_rcv_pkt,
+ .attr_count = NFQA_MAX,
+};
+
+/* public interface */
+
+struct nfnl_handle *nfqnl_nfnlh(struct nfqnl_handle *h)
+{
+ return &h->nfnlh;
+}
+
+int nfqnl_fd(struct nfqnl_handle *h)
+{
+ return nfnl_fd(nfqnl_nfnlh(h));
+}
+
+struct nfqnl_handle *nfqnl_open(void)
+{
+ struct nfqnl_handle *h;
+ int err;
+
+ h = malloc(sizeof(*h));
+ if (!h)
+ return NULL;
+
+ memset(h, 0, sizeof(*h));
+
+ err = nfnl_open(&h->nfnlh, NFNL_SUBSYS_QUEUE, NFQNL_MSG_MAX, 0);
+ if (err < 0) {
+ nfqnl_errno = err;
+ goto out_free;
+ }
+
+ pkt_cb.data = h;
+ err = nfnl_callback_register(&h->nfnlh, NFQNL_MSG_PACKET, &pkt_cb);
+ if (err < 0) {
+ nfqnl_errno = err;
+ goto out_close;
+ }
+
+ return h;
+out_close:
+ nfnl_close(&h->nfnlh);
+out_free:
+ free(h);
+ return NULL;
+}
+
+int nfqnl_close(struct nfqnl_handle *h)
+{
+ int ret = nfnl_close(&h->nfnlh);
+ if (ret == 0)
+ free(h);
+ return ret;
}
/* bind nf_queue from a specific protocol family */
@@ -88,30 +195,57 @@ int nfqnl_unbind_pf(struct nfqnl_handle *h, u_int16_t pf)
}
/* bind this socket to a specific queue number */
-int nfqnl_create_queue(struct nfqnl_handle *h,
- struct nfqnl_q_handle *qh, u_int16_t num)
+struct nfqnl_q_handle *nfqnl_create_queue(struct nfqnl_handle *h,
+ u_int16_t num,
+ nfqnl_callback *cb,
+ void *data)
{
+ int ret;
+ struct nfqnl_q_handle *qh;
+
+ if (find_qh(h, num))
+ return NULL;
+
+ qh = malloc(sizeof(*qh));
+
+ memset(qh, 0, sizeof(*qh));
qh->h = h;
qh->id = num;
+ qh->cb = cb;
+ qh->data = data;
+
+ ret = __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
+ if (ret < 0) {
+ nfqnl_errno = ret;
+ free(qh);
+ return NULL;
+ }
- return __build_send_cfg_msg(h, NFQNL_CFG_CMD_BIND, num, 0);
+ add_qh(qh);
+ return qh;
}
/* unbind this socket from a specific queue number */
int nfqnl_destroy_queue(struct nfqnl_q_handle *qh)
{
int ret = __build_send_cfg_msg(qh->h, NFQNL_CFG_CMD_UNBIND, qh->id, 0);
- if (ret == 0)
- qh->h = NULL;
+ if (ret == 0) {
+ del_qh(qh);
+ free(qh);
+ }
return ret;
}
+int nfqnl_handle_packet(struct nfqnl_handle *h, char *buf, int len)
+{
+ return nfnl_handle_packet(&h->nfnlh, buf, len);
+}
+
int nfqnl_set_mode(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))
+ char buf[NFNL_HEADER_LEN
+NFA_LENGTH(sizeof(struct nfqnl_msg_config_params))];
struct nfqnl_msg_config_params params;
struct nlmsghdr *nmh = (struct nlmsghdr *) buf;
@@ -124,7 +258,7 @@ int nfqnl_set_mode(struct nfqnl_q_handle *qh,
nfnl_addattr_l(nmh, sizeof(buf), NFQA_CFG_PARAMS, &params,
sizeof(params));
- return nfnl_send(&qh->h->nfnlh, nmh);
+ return nfnl_talk(&qh->h->nfnlh, nmh, 0, 0, NULL, NULL, NULL);
}
static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
@@ -132,8 +266,7 @@ static int __set_verdict(struct nfqnl_q_handle *qh, u_int32_t id,
u_int32_t data_len, unsigned char *data)
{
struct nfqnl_msg_verdict_hdr vh;
- char buf[NLMSG_LENGTH(sizeof(struct nlmsghdr))
- +NLMSG_LENGTH(sizeof(struct nfgenmsg))
+ char buf[NFNL_HEADER_LEN
+NFA_LENGTH(sizeof(mark))
+NFA_LENGTH(sizeof(vh))];
struct nlmsghdr *nmh = (struct nlmsghdr *) buf;