* [RFC] new API for libnetfilter_conntrack
@ 2006-10-30 2:25 Pablo Neira Ayuso
2006-10-31 18:57 ` Pablo Neira Ayuso
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2006-10-30 2:25 UTC (permalink / raw)
To: Netfilter Development Mailinglist
Cc: Harald Welte, Patrick McHardy, Eric Leblond
[-- Attachment #1: Type: text/plain, Size: 1776 bytes --]
Hi,
Attached a patch, yet incomplete, that introduces the new API for
libnetfilter_conntrack. Basically the idea consists of providing
"conntrack" objects constructor/destructor functions and an interface to
get and set object attributes. The conntrack object structure is
encapsulated therefore we can add new attributes without breaking binary
backward compatibility. There is an example of the new API use in the
patch (see test.c file)
See that conntrack object attributes are different from the netlink
attributes therefore they provide a high level interface that abstract
from netlink details. The idea is to let the programmer make the choice
to work with high level (objects) or low level (netlink) and provide the
gateways to switch from high to low level and vice-versa by means of
functions to build/parse netlink messages from/to conntrack objects.
The reason why I posted this patch is because I'm thinking about
generalizing this a bit more and provide a complete high level API that
would be the same for all the netfilter subsystems. This will result in
a single library to rules them all with a subdirectory that contains the
details of every specific subsystem.
nfh = nf_open(); /* encapsulate nfnl_open() */
ssh = nf_setup_subsys(nfnlh, CONNTRACK); /* encapsulate
nfnl_subsys_open() */
...
ct = nf_new_object(NF_CONNTRACK_OBJECT);
nf_set_attr_u8(ct, ATTR_XXX, value);
nf_set_attr_u16(ct, ATTR_XXX, value);
...
nf_query_object(ssh, NF_CT_CREATE, ct);
nf_free_object(ct);
nf_close(nfh);
I'd like to hear from you before going ahead, always appreciate your
feedback guys. Comments welcome.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
[-- Attachment #2: api.patch --]
[-- Type: text/plain, Size: 46215 bytes --]
Index: libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h
===================================================================
--- libnetfilter_conntrack.orig/include/libnetfilter_conntrack/libnetfilter_conntrack.h 2006-10-30 02:11:10.000000000 +0100
+++ libnetfilter_conntrack/include/libnetfilter_conntrack/libnetfilter_conntrack.h 2006-10-30 02:11:18.000000000 +0100
@@ -238,6 +238,9 @@ extern int nfct_close(struct nfct_handle
extern int nfct_fd(struct nfct_handle *cth);
+extern struct nfnl_handle *nfct_get_nfnl(struct nfct_handle *h);
+extern struct nfnl_subsys_handle *nfct_get_nfnlssh_ct(struct nfct_handle *h);
+
/*
* [Register|unregister] callbacks
*/
@@ -332,6 +335,113 @@ extern int nfct_sprintf_expect_id(char *
extern void nfct_build_tuple(struct nfnlhdr *req, int size,
struct nfct_tuple *t, int type);
+/*
+ * New libnetfilter_conntrack API
+ */
+
+/* high level API */
+
+#include <sys/types.h>
+
+/* conntrack object */
+struct nf_conntrack;
+
+/* conntrack attributes */
+enum nf_conntrack_attr {
+ ATTR_ORIG_IPV4_SRC = 0,
+ ATTR_ORIG_IPV4_DST,
+ ATTR_REPL_IPV4_SRC,
+ ATTR_REPL_IPV4_DST,
+ ATTR_ORIG_IPV6_SRC,
+ ATTR_ORIG_IPV6_DST,
+ ATTR_REPL_IPV6_SRC,
+ ATTR_REPL_IPV6_DST,
+ ATTR_ORIG_PORT_SRC,
+ ATTR_ORIG_PORT_DST,
+ ATTR_REPL_PORT_SRC,
+ ATTR_REPL_PORT_DST,
+ ATTR_ICMP_TYPE,
+ ATTR_ICMP_CODE,
+ ATTR_ICMP_ID,
+ ATTR_ORIG_L3PROTO,
+ ATTR_REPL_L3PROTO,
+ ATTR_ORIG_L4PROTO,
+ ATTR_REPL_L4PROTO,
+ ATTR_TCP_STATE,
+ ATTR_SNAT_IPV4,
+ ATTR_DNAT_IPV4,
+ ATTR_SNAT_PORT,
+ ATTR_DNAT_PORT,
+ ATTR_TIMEOUT,
+ ATTR_MARK,
+ ATTR_ORIG_COUNTER_PACKETS,
+ ATTR_REPL_COUNTER_PACKETS,
+ ATTR_ORIG_COUNTER_BYTES,
+ ATTR_REPL_COUNTER_BYTES,
+ ATTR_USE,
+ ATTR_ID,
+ ATTR_ASSURED,
+ ATTR_SEEN_REPLY,
+ ATTR_MAX
+};
+
+/* constructor / destructor */
+extern struct nf_conntrack *nfct_new(void);
+extern void nfct_destroy(struct nf_conntrack *ct);
+
+/* setter */
+extern void nfct_set_attr(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ void *value);
+
+extern void nfct_set_attr_u8(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int8_t value);
+
+extern void nfct_set_attr_u16(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int16_t value);
+
+extern void nfct_set_attr_u32(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int32_t value);
+
+/* getter */
+extern void * nfct_get_attr(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type);
+
+extern u_int8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type);
+
+extern u_int16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type);
+
+extern u_int32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type);
+
+/* query */
+enum nf_conntrack_query {
+ NFCT_Q_CREATE,
+ NFCT_Q_UPDATE,
+ NFCT_Q_DESTROY
+};
+
+extern int nfct_query(const struct nfct_handle *h,
+ const enum nf_conntrack_query query,
+ const struct nf_conntrack *ct);
+
+extern int nfct_sprintf(char *buf, const struct nf_conntrack *ct);
+
+/* low level API: netlink functions */
+
+extern int nfct_nl_build_conntrack(struct nfnl_subsys_handle *ssh,
+ struct nfnlhdr *req,
+ size_t size,
+ u_int16_t type,
+ u_int16_t flags,
+ const struct nf_conntrack *ct);
+extern int nfct_nl_parse_conntrack(const struct nlmsghdr *nlh,
+ struct nf_conntrack *ct);
#endif /* _LIBNETFILTER_CONNTRACK_H_ */
Index: libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
===================================================================
--- libnetfilter_conntrack.orig/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h 2006-10-30 02:11:10.000000000 +0100
+++ libnetfilter_conntrack/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h 2006-10-30 02:11:18.000000000 +0100
@@ -27,13 +27,15 @@ enum ctattr_type {
CTA_STATUS,
CTA_PROTOINFO,
CTA_HELP,
- CTA_NAT,
+ CTA_NAT_SRC,
+#define CTA_NAT CTA_NAT_SRC /* backwards compatibility */
CTA_TIMEOUT,
CTA_MARK,
CTA_COUNTERS_ORIG,
CTA_COUNTERS_REPLY,
CTA_USE,
CTA_ID,
+ CTA_NAT_DST,
__CTA_MAX
};
#define CTA_MAX (__CTA_MAX - 1)
Index: libnetfilter_conntrack/src/Makefile.am
===================================================================
--- libnetfilter_conntrack.orig/src/Makefile.am 2006-10-30 02:11:15.000000000 +0100
+++ libnetfilter_conntrack/src/Makefile.am 2006-10-30 02:11:18.000000000 +0100
@@ -11,4 +11,6 @@ lib_LTLIBRARIES = libnetfilter_conntrack
libnetfilter_conntrack_la_LDFLAGS = -Wc,-nostartfiles -lnfnetlink -ldl \
-version-info $(LIBVERSION)
-libnetfilter_conntrack_la_SOURCES = libnetfilter_conntrack.c
+libnetfilter_conntrack_la_SOURCES = libnetfilter_conntrack.c \
+ api.c build.c parse.c sprint.c \
+ setter.c getter.c
Index: libnetfilter_conntrack/src/libnetfilter_conntrack.c
===================================================================
--- libnetfilter_conntrack.orig/src/libnetfilter_conntrack.c 2006-10-30 02:11:15.000000000 +0100
+++ libnetfilter_conntrack/src/libnetfilter_conntrack.c 2006-10-30 02:11:18.000000000 +0100
@@ -37,6 +37,16 @@ struct nfct_handle {
nfct_handler handler; /* netlink handler */
};
+struct nfnl_subsys_handle *nfct_get_nfnlssh_ct(struct nfct_handle *h)
+{
+ return h->nfnlssh_ct;
+}
+
+extern struct nfnl_handle *nfct_get_nfnl(struct nfct_handle *h)
+{
+ return h->nfnlh;
+}
+
static char *lib_dir = LIBNETFILTER_CONNTRACK_DIR;
static LIST_HEAD(proto_list);
static LIST_HEAD(l3proto_list);
Index: libnetfilter_conntrack/src/api.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/api.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,344 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include <stdlib.h>
+#include <string.h> /* for memset */
+#include <errno.h>
+#include <assert.h>
+
+#include "internal.h"
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+/**
+ * nfct_conntrack_new - allocate a new conntrack
+ *
+ * In case of success, this function returns a valid pointer to a memory blob,
+ * otherwise NULL is returned and errno is set appropiately.
+ */
+struct nf_conntrack *nfct_new()
+{
+ struct nf_conntrack *ct;
+
+ ct = malloc(sizeof(struct nf_conntrack));
+ if (!ct)
+ return NULL;
+
+ memset(ct, 0, sizeof(struct nf_conntrack));
+
+ /* always work with confirmed conntracks */
+ ct->status |= IPS_CONFIRMED;
+
+ return ct;
+}
+
+/**
+ * nf_conntrack_destroy - release a conntrack object
+ * @ct: pointer to the conntrack object
+ */
+void nfct_destroy(struct nf_conntrack *ct)
+{
+ assert(ct != NULL);
+ free(ct);
+ ct = NULL; /* bugtrap for bad programmers: assertions ;) */
+}
+
+/**
+ * nfct_set_attr - set the value of a certain conntrack attribute
+ * @ct: pointer to a valid conntrack
+ * @type: attribute type
+ * @value: pointer to the attribute value
+ */
+void nfct_set_attr(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ void *value)
+{
+ assert(ct != NULL);
+ assert(value != NULL);
+
+ if (type > ATTR_MAX)
+ return;
+
+ set_attr_array[type](ct, value);
+ set_bit(type, ct->set);
+}
+
+/**
+ * nfct_set_attr_u8 - set the value of a certain conntrack attribute
+ * @ct: pointer to a valid conntrack
+ * @type: attribute type
+ * @value: unsigned 8 bits attribute value
+ */
+void nfct_set_attr_u8(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int8_t value)
+{
+ nfct_set_attr(ct, type, &value);
+}
+
+/**
+ * nfct_set_attr_u16 - set the value of a certain conntrack attribute
+ * @ct: pointer to a valid conntrack
+ * @type: attribute type
+ * @value: unsigned 16 bits attribute value
+ */
+void nfct_set_attr_u16(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int16_t value)
+{
+ nfct_set_attr(ct, type, &value);
+}
+
+/**
+ * nfct_set_attr_u32 - set the value of a certain conntrack attribute
+ * @ct: pointer to a valid conntrack
+ * @type: attribute type
+ * @value: unsigned 32 bits attribute value
+ */
+void nfct_set_attr_u32(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type,
+ u_int32_t value)
+{
+ nfct_set_attr(ct, type, &value);
+}
+
+/**
+ * nfct_get_attr - get a conntrack attribute
+ * @ct: pointer to a valid conntrack
+ * @type: attribute type
+ */
+void *nfct_get_attr(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type)
+{
+ assert(ct != NULL);
+
+ if (type > ATTR_MAX)
+ return NULL;
+
+ if (test_bit(type, ct->set))
+ return NULL;
+
+ return get_attr_array[type](ct);
+}
+
+u_int8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type)
+{
+ return *((u_int8_t *) nfct_get_attr(ct, type));
+}
+
+u_int16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type)
+{
+ return *((u_int16_t *) nfct_get_attr(ct, type));
+}
+
+u_int32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr type)
+{
+ return *((u_int32_t *) nfct_get_attr(ct, type));
+}
+
+int nfct_nl_build_conntrack(struct nfnl_subsys_handle *ssh,
+ struct nfnlhdr *req,
+ size_t size,
+ u_int16_t type,
+ u_int16_t flags,
+ const struct nf_conntrack *ct)
+{
+ u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum;
+
+ assert(ssh != NULL);
+ assert(req != NULL);
+ assert(ct != NULL);
+
+ if (!test_bit(ATTR_ORIG_L3PROTO, ct->set)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(req, 0, size);
+
+ nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags);
+
+ __build_tuple(req, size, &ct->tuple[__DIR_ORIG], CTA_TUPLE_ORIG);
+ __build_tuple(req, size, &ct->tuple[__DIR_REPL], CTA_TUPLE_REPLY);
+
+ /* always build IPS_CONFIRMED */
+ __build_status(req, size, ct);
+
+ if (test_bit(ATTR_TIMEOUT, ct->set))
+ __build_timeout(req, size, ct);
+
+ if (test_bit(ATTR_MARK, ct->set))
+ __build_mark(req, size, ct);
+
+ if (test_bit(ATTR_TCP_STATE, ct->set))
+ __build_protoinfo(req, size, ct);
+
+ if (test_bit(ATTR_SNAT_IPV4, ct->set) &&
+ test_bit(ATTR_SNAT_PORT, ct->set))
+ __build_snat(req, size, ct);
+
+ if (test_bit(ATTR_SNAT_IPV4, ct->set))
+ __build_snat_ipv4(req, size, ct);
+
+ if (test_bit(ATTR_SNAT_PORT, ct->set))
+ __build_snat_port(req, size, ct);
+
+ if (test_bit(ATTR_DNAT_IPV4, ct->set) &&
+ test_bit(ATTR_DNAT_PORT, ct->set))
+ __build_dnat(req, size, ct);
+
+ if (test_bit(ATTR_DNAT_IPV4, ct->set))
+ __build_dnat_ipv4(req, size, ct);
+
+ if (test_bit(ATTR_DNAT_PORT, ct->set))
+ __build_dnat_port(req, size, ct);
+
+ return 0;
+}
+
+int nfct_nl_parse_conntrack(const struct nlmsghdr *nlh, struct nf_conntrack *ct)
+{
+ int ret;
+ struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
+ int len = nlh->nlmsg_len;
+ struct nfattr *cda[CTA_MAX];
+
+ len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ if (len < 0)
+ return -EINVAL;
+
+ ret = __msgtype2enum(nlh);
+
+ memset(ct, 0, sizeof(struct nfct_conntrack));
+
+ ct->tuple[NFCT_DIR_ORIGINAL].l3protonum = nfhdr->nfgen_family;
+ ct->tuple[__DIR_REPL].l3protonum = nfhdr->nfgen_family;
+
+ nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
+
+ if (cda[CTA_TUPLE_ORIG-1])
+ __parse_tuple(cda[CTA_TUPLE_ORIG-1],
+ &ct->tuple[NFCT_DIR_ORIGINAL], ct->set);
+
+ if (cda[CTA_TUPLE_REPLY-1])
+ __parse_tuple(cda[CTA_TUPLE_REPLY-1],
+ &ct->tuple[__DIR_REPL], ct->set);
+
+ if (cda[CTA_STATUS-1]) {
+ ct->status = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_STATUS-1]));
+ if (ct->status & IPS_ASSURED)
+ set_bit(ATTR_ASSURED, ct->set);
+ if (ct->status & IPS_SEEN_REPLY)
+ set_bit(ATTR_SEEN_REPLY, ct->set);
+ }
+
+ if (cda[CTA_PROTOINFO-1])
+ __parse_protoinfo(cda[CTA_PROTOINFO-1], ct);
+
+ if (cda[CTA_TIMEOUT-1]) {
+ ct->timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1]));
+ set_bit(ATTR_TIMEOUT, ct->set);
+ }
+
+ if (cda[CTA_MARK-1]) {
+ ct->mark = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_MARK-1]));
+ set_bit(ATTR_MARK, ct->set);
+ }
+
+ if (cda[CTA_COUNTERS_ORIG-1])
+ __parse_counters(cda[CTA_COUNTERS_ORIG-1], ct,
+ NFA_TYPE(cda[CTA_COUNTERS_ORIG-1])-1);
+
+ if (cda[CTA_COUNTERS_REPLY-1])
+ __parse_counters(cda[CTA_COUNTERS_REPLY-1], ct,
+ NFA_TYPE(cda[CTA_COUNTERS_REPLY-1])-1);
+
+ if (cda[CTA_USE-1]) {
+ ct->use = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_USE-1]));
+ set_bit(ATTR_USE, ct->set);
+ }
+
+ if (cda[CTA_ID-1]) {
+ ct->id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
+ set_bit(ATTR_ID, ct->set);
+ }
+
+ return 0;
+}
+
+int nfct_query(const struct nfct_handle *h,
+ const enum nf_conntrack_query query,
+ const struct nf_conntrack *ct)
+{
+ size_t size = 4096;
+ char buffer[size];
+ struct nfnlhdr *req = buffer;
+
+ memset(req, 0, size);
+
+ switch(query) {
+ case NFCT_Q_CREATE:
+ nfct_nl_build_conntrack(nfct_get_nfnlssh_ct(h), req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, ct);
+ break;
+ case NFCT_Q_UPDATE:
+ nfct_nl_build_conntrack(nfct_get_nfnlssh_ct(h), req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, ct);
+ break;
+ case NFCT_Q_DESTROY:
+ nfct_nl_build_conntrack(nfct_get_nfnlssh_ct(h), req, size, IPCTNL_MSG_CT_DELETE, NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK, ct);
+ break;
+ default:
+ return -1;
+ }
+
+ return nfnl_talk(nfct_get_nfnl(h), &req->nlh, 0, 0, NULL, NULL, NULL);
+}
+
+int nfct_sprintf(char *buf, const struct nf_conntrack *ct)
+{
+ int size = 0;
+
+ size += __sprintf_protocol(buf, ct);
+
+ if (test_bit(ATTR_TIMEOUT, ct->set))
+ size += __sprintf_timeout(buf+size, ct);
+
+ if (test_bit(ATTR_TCP_STATE, ct->set))
+ size += __sprintf_protoinfo(buf+size, ct);
+
+ size += __sprintf_address(buf+size, &ct->tuple[__DIR_ORIG]);
+ size += __sprintf_proto(buf+size, &ct->tuple[__DIR_ORIG]);
+
+ if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->set) &&
+ test_bit(ATTR_ORIG_COUNTER_BYTES, ct->set))
+ size += __sprintf_counters(buf+size, ct, __DIR_ORIG);
+
+ if (test_bit(ATTR_SEEN_REPLY, ct->set))
+ size += __sprintf_status_seen_reply(buf+size, ct);
+
+ size += __sprintf_address(buf+size, &ct->tuple[__DIR_REPL]);
+ size += __sprintf_proto(buf+size, &ct->tuple[__DIR_REPL]);
+
+ if (test_bit(ATTR_REPL_COUNTER_PACKETS, ct->set) &&
+ test_bit(ATTR_REPL_COUNTER_BYTES, ct->set))
+ size += __sprintf_counters(buf+size, ct, __DIR_REPL);
+
+ if (test_bit(ATTR_ASSURED, ct->set))
+ size += __sprintf_status_assured(buf+size, ct);
+
+ if (test_bit(ATTR_MARK, ct->set))
+ size += __sprintf_mark(buf+size, ct);
+
+ if (test_bit(ATTR_USE, ct->set))
+ size += __sprintf_use(buf+size, ct);
+
+ /* Delete the last blank space */
+ size--;
+
+ return size;
+}
Index: libnetfilter_conntrack/src/build.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/build.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,240 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+void __build_tuple_ip(struct nfnlhdr *req,
+ size_t size,
+ const struct __nfct_tuple *t)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_IP);
+
+ switch(t->l3protonum) {
+ case AF_INET:
+ nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_SRC, &t->src.v4,
+ sizeof(u_int32_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_IP_V4_DST, &t->dst.v4,
+ sizeof(u_int32_t));
+ break;
+ case AF_INET6:
+ nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_SRC, &t->src.v6,
+ sizeof(struct in6_addr));
+ nfnl_addattr_l(&req->nlh, size, CTA_IP_V6_DST, &t->dst.v6,
+ sizeof(struct in6_addr));
+ break;
+ default:
+ break;
+ }
+
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_tuple_proto(struct nfnlhdr *req,
+ size_t size,
+ const struct __nfct_tuple *t)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_TUPLE_PROTO);
+
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_NUM, &t->protonum,
+ sizeof(u_int8_t));
+
+ switch(t->protonum) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT,
+ &t->l4src.tcp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_DST_PORT,
+ &t->l4dst.tcp.port, sizeof(u_int16_t));
+ break;
+ case IPPROTO_ICMP:
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_CODE,
+ &t->l4dst.icmp.code, sizeof(u_int8_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_TYPE,
+ &t->l4dst.icmp.type, sizeof(u_int8_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTO_ICMP_ID,
+ &t->l4src.icmp.id, sizeof(u_int16_t));
+ break;
+ default:
+ break;
+ }
+
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_tuple(struct nfnlhdr *req,
+ size_t size,
+ const struct __nfct_tuple *t,
+ const int type)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, type);
+
+ __build_tuple_ip(req, size, t);
+ __build_tuple_proto(req, size, t);
+
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_protoinfo(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest, *nest_proto;
+ struct nfct_proto *h;
+
+ switch(ct->tuple[__DIR_ORIG].protonum) {
+ case IPPROTO_TCP:
+ nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO);
+ nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP);
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTOINFO_TCP_STATE,
+ &ct->protoinfo.tcp.state, sizeof(u_int8_t));
+ nfnl_nest_end(&req->nlh, nest_proto);
+ nfnl_nest_end(&req->nlh, nest);
+ break;
+ default:
+ break;
+ }
+}
+
+void __build_protonat(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct,
+ struct __nfct_nat *nat)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_PROTO);
+
+ switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
+#if 0
+ case IPPROTO_TCP:
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MIN,
+ &ct->nat.l4min.tcp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_TCP_MAX,
+ &ct->nat.l4max.tcp.port, sizeof(u_int16_t));
+ break;
+ case IPPROTO_UDP:
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MIN,
+ &ct->nat.l4min.udp.port, sizeof(u_int16_t));
+ nfnl_addattr_l(&req->nlh, size, CTA_PROTONAT_UDP_MAX,
+ &ct->nat.l4max.udp.port, sizeof(u_int16_t));
+ break;
+#endif
+ }
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_nat(struct nfnlhdr *req,
+ size_t size,
+ const struct __nfct_nat *nat)
+{
+ nfnl_addattr_l(&req->nlh, size, CTA_NAT_MINIP,
+ &nat->min_ip, sizeof(u_int32_t));
+}
+
+void __build_snat(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_nat(req, size, &ct->snat);
+ __build_protonat(req, size, ct, &ct->snat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_snat_ipv4(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_nat(req, size, &ct->snat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_snat_port(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_protonat(req, size, ct, &ct->snat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_nat(req, size, &ct->dnat);
+ __build_protonat(req, size, ct, &ct->dnat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat_ipv4(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_nat(req, size, &ct->dnat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_dnat_port(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ struct nfattr *nest;
+
+ nest = nfnl_nest(&req->nlh, size, CTA_NAT_SRC);
+ __build_protonat(req, size, ct, &ct->dnat);
+ nfnl_nest_end(&req->nlh, nest);
+}
+
+void __build_status(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ nfnl_addattr32(&req->nlh, size, CTA_STATUS,
+ htonl(ct->status | IPS_CONFIRMED));
+}
+
+void __build_timeout(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ nfnl_addattr32(&req->nlh, size, CTA_TIMEOUT, htonl(ct->timeout));
+}
+
+void __build_mark(struct nfnlhdr *req,
+ size_t size,
+ const struct nf_conntrack *ct)
+{
+ nfnl_addattr32(&req->nlh, size, CTA_MARK, htonl(ct->mark));
+}
+
+void __build_id(struct nfnlhdr *req,
+ size_t size,
+ const const struct nf_conntrack *ct)
+{
+ nfnl_addattr32(&req->nlh, size, CTA_ID, htonl(ct->id));
+}
Index: libnetfilter_conntrack/src/getter.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/getter.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,179 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.net>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+static const void *get_attr_orig_ipv4_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].src.v4;
+}
+
+static const void *get_attr_orig_ipv4_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].dst.v4;
+}
+
+static const void *get_attr_repl_ipv4_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].src.v4;
+}
+
+static const void *get_attr_repl_ipv4_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].dst.v4;
+}
+
+static const void *get_attr_orig_ipv6_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].src.v6;
+}
+
+static const void *get_attr_orig_ipv6_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].dst.v6;
+}
+
+static const void *get_attr_repl_ipv6_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].src.v6;
+}
+
+static const void *get_attr_repl_ipv6_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].dst.v6;
+}
+
+static const void *get_attr_orig_port_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l4src.all;
+}
+
+static const void *get_attr_orig_port_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l4dst.all;
+}
+
+static const void *get_attr_repl_port_src(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].l4src.all;
+}
+
+static const void *get_attr_repl_port_dst(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].l4dst.all;
+}
+
+static const void *get_attr_icmp_type(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l4dst.icmp.type;
+}
+
+static const void *get_attr_icmp_code(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l4dst.icmp.code;
+}
+
+static const void *get_attr_icmp_id(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l4src.icmp.id;
+}
+
+static const void *get_attr_orig_l3proto(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].l3protonum;
+}
+
+static const void *get_attr_repl_l3proto(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].l3protonum;
+}
+
+static const void *get_attr_orig_l4proto(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_ORIG].protonum;
+}
+
+static const void *get_attr_repl_l4proto(const struct nf_conntrack *ct)
+{
+ return &ct->tuple[__DIR_REPL].protonum;
+}
+
+static const void *get_attr_tcp_state(const struct nf_conntrack *ct)
+{
+ return &ct->protoinfo.tcp.state;
+}
+
+static const void *get_attr_snat_ipv4(const struct nf_conntrack *ct)
+{
+ return &ct->snat.min_ip;
+}
+
+static const void *get_attr_dnat_ipv4(const struct nf_conntrack *ct)
+{
+ return &ct->dnat.min_ip;
+}
+
+static const void *get_attr_snat_port(const struct nf_conntrack *ct)
+{
+ return &ct->snat.l4min.all;
+}
+
+static const void *get_attr_dnat_port(const struct nf_conntrack *ct)
+{
+ return &ct->dnat.l4min.all;
+}
+
+static const void *get_attr_timeout(const struct nf_conntrack *ct)
+{
+ return &ct->timeout;
+}
+
+static const void *get_attr_mark(const struct nf_conntrack *ct)
+{
+ return &ct->mark;
+}
+
+static const void *get_attr_assured(const struct nf_conntrack *ct)
+{
+ return &ct->status;
+}
+
+static const void *get_attr_seen_reply(const struct nf_conntrack *ct)
+{
+ return &ct->status;
+}
+
+get_attr get_attr_array[] = {
+ [ATTR_ORIG_IPV4_SRC] = get_attr_orig_ipv4_src,
+ [ATTR_ORIG_IPV4_DST] = get_attr_orig_ipv4_dst,
+ [ATTR_REPL_IPV4_SRC] = get_attr_repl_ipv4_src,
+ [ATTR_REPL_IPV4_DST] = get_attr_repl_ipv4_dst,
+ [ATTR_ORIG_IPV6_SRC] = get_attr_orig_ipv6_src,
+ [ATTR_ORIG_IPV6_DST] = get_attr_orig_ipv6_dst,
+ [ATTR_REPL_IPV6_SRC] = get_attr_repl_ipv6_src,
+ [ATTR_REPL_IPV6_DST] = get_attr_repl_ipv6_dst,
+ [ATTR_ORIG_PORT_SRC] = get_attr_orig_port_src,
+ [ATTR_ORIG_PORT_DST] = get_attr_orig_port_dst,
+ [ATTR_REPL_PORT_SRC] = get_attr_repl_port_src,
+ [ATTR_REPL_PORT_DST] = get_attr_repl_port_dst,
+ [ATTR_ICMP_TYPE] = get_attr_icmp_type,
+ [ATTR_ICMP_CODE] = get_attr_icmp_code,
+ [ATTR_ICMP_ID] = get_attr_icmp_id,
+ [ATTR_ORIG_L3PROTO] = get_attr_orig_l3proto,
+ [ATTR_REPL_L3PROTO] = get_attr_repl_l3proto,
+ [ATTR_ORIG_L4PROTO] = get_attr_orig_l4proto,
+ [ATTR_REPL_L4PROTO] = get_attr_repl_l4proto,
+ [ATTR_TCP_STATE] = get_attr_tcp_state,
+ [ATTR_SNAT_IPV4] = get_attr_snat_ipv4,
+ [ATTR_DNAT_IPV4] = get_attr_dnat_ipv4,
+ [ATTR_SNAT_PORT] = get_attr_snat_port,
+ [ATTR_DNAT_PORT] = get_attr_dnat_port,
+ [ATTR_TIMEOUT] = get_attr_timeout,
+ [ATTR_MARK] = get_attr_mark,
+ [ATTR_ASSURED] = get_attr_assured,
+ [ATTR_SEEN_REPLY] = get_attr_seen_reply,
+};
Index: libnetfilter_conntrack/src/setter.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/setter.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,179 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.net>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+static void set_attr_orig_ipv4_src(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].src.v4 = *((u_int32_t *) value);
+}
+
+static void set_attr_orig_ipv4_dst(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].dst.v4 = *((u_int32_t *) value);
+}
+
+static void set_attr_repl_ipv4_src(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].src.v4 = *((u_int32_t *) value);
+}
+
+static void set_attr_repl_ipv4_dst(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].dst.v4 = *((u_int32_t *) value);
+}
+
+static void set_attr_orig_ipv6_src(struct nf_conntrack *ct, const void *value)
+{
+ memcpy(&ct->tuple[__DIR_ORIG].src.v6, value, sizeof(u_int32_t)*4);
+}
+
+static void set_attr_orig_ipv6_dst(struct nf_conntrack *ct, const void *value)
+{
+ memcpy(&ct->tuple[__DIR_ORIG].dst.v6, value, sizeof(u_int32_t)*4);
+}
+
+static void set_attr_repl_ipv6_src(struct nf_conntrack *ct, const void *value)
+{
+ memcpy(&ct->tuple[__DIR_REPL].src.v6, value, sizeof(u_int32_t)*4);
+}
+
+static void set_attr_repl_ipv6_dst(struct nf_conntrack *ct, const void *value)
+{
+ memcpy(&ct->tuple[__DIR_REPL].dst.v6, value, sizeof(u_int32_t)*4);
+}
+
+static void set_attr_orig_port_src(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l4src.all = *((u_int16_t *) value);
+}
+
+static void set_attr_orig_port_dst(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l4dst.all = *((u_int16_t *) value);
+}
+
+static void set_attr_repl_port_src(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].l4src.all = *((u_int16_t *) value);
+}
+
+static void set_attr_repl_port_dst(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].l4dst.all = *((u_int16_t *) value);
+}
+
+static void set_attr_icmp_type(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l4dst.icmp.type = *((u_int8_t *) value);
+}
+
+static void set_attr_icmp_code(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l4dst.icmp.code = *((u_int8_t *) value);
+}
+
+static void set_attr_icmp_id(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l4src.icmp.id = *((u_int8_t *) value);
+}
+
+static void set_attr_orig_l3proto(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].l3protonum = *((u_int8_t *) value);
+}
+
+static void set_attr_repl_l3proto(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].l3protonum = *((u_int8_t *) value);
+}
+
+static void set_attr_orig_l4proto(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_ORIG].protonum = *((u_int8_t *) value);
+}
+
+static void set_attr_repl_l4proto(struct nf_conntrack *ct, const void *value)
+{
+ ct->tuple[__DIR_REPL].protonum = *((u_int8_t *) value);
+}
+
+static void set_attr_tcp_state(struct nf_conntrack *ct, const void *value)
+{
+ ct->protoinfo.tcp.state = *((u_int8_t *) value);
+}
+
+static void set_attr_snat_ipv4(struct nf_conntrack *ct, const void *value)
+{
+ ct->snat.min_ip = ct->snat.max_ip = *((u_int32_t *) value);
+}
+
+static void set_attr_dnat_ipv4(struct nf_conntrack *ct, const void *value)
+{
+ ct->dnat.min_ip = ct->snat.max_ip = *((u_int32_t *) value);
+}
+
+static void set_attr_snat_port(struct nf_conntrack *ct, const void *value)
+{
+ ct->snat.l4min.all = ct->snat.l4max.all = *((u_int16_t *) value);
+}
+
+static void set_attr_dnat_port(struct nf_conntrack *ct, const void *value)
+{
+ ct->dnat.l4min.all = ct->dnat.l4max.all = *((u_int16_t *) value);
+}
+
+static void set_attr_timeout(struct nf_conntrack *ct, const void *value)
+{
+ ct->timeout = *((u_int32_t *) value);
+}
+
+static void set_attr_mark(struct nf_conntrack *ct, const void *value)
+{
+ ct->mark = *((u_int32_t *) value);
+}
+
+static void set_attr_assured(struct nf_conntrack *ct, const void *value)
+{
+ ct->status |= IPS_ASSURED;
+}
+
+static void set_attr_seen_reply(struct nf_conntrack *ct, const void *value)
+{
+ ct->status |= IPS_SEEN_REPLY;
+}
+
+set_attr set_attr_array[] = {
+ [ATTR_ORIG_IPV4_SRC] = set_attr_orig_ipv4_src,
+ [ATTR_ORIG_IPV4_DST] = set_attr_orig_ipv4_dst,
+ [ATTR_REPL_IPV4_SRC] = set_attr_repl_ipv4_src,
+ [ATTR_REPL_IPV4_DST] = set_attr_repl_ipv4_dst,
+ [ATTR_ORIG_IPV6_SRC] = set_attr_orig_ipv6_src,
+ [ATTR_ORIG_IPV6_DST] = set_attr_orig_ipv6_dst,
+ [ATTR_REPL_IPV6_SRC] = set_attr_repl_ipv6_src,
+ [ATTR_REPL_IPV6_DST] = set_attr_repl_ipv6_dst,
+ [ATTR_ORIG_PORT_SRC] = set_attr_orig_port_src,
+ [ATTR_ORIG_PORT_DST] = set_attr_orig_port_dst,
+ [ATTR_REPL_PORT_SRC] = set_attr_repl_port_src,
+ [ATTR_REPL_PORT_DST] = set_attr_repl_port_dst,
+ [ATTR_ICMP_TYPE] = set_attr_icmp_type,
+ [ATTR_ICMP_CODE] = set_attr_icmp_code,
+ [ATTR_ICMP_ID] = set_attr_icmp_id,
+ [ATTR_ORIG_L3PROTO] = set_attr_orig_l3proto,
+ [ATTR_REPL_L3PROTO] = set_attr_repl_l3proto,
+ [ATTR_ORIG_L4PROTO] = set_attr_orig_l4proto,
+ [ATTR_REPL_L4PROTO] = set_attr_repl_l4proto,
+ [ATTR_TCP_STATE] = set_attr_tcp_state,
+ [ATTR_SNAT_IPV4] = set_attr_snat_ipv4,
+ [ATTR_DNAT_IPV4] = set_attr_dnat_ipv4,
+ [ATTR_SNAT_PORT] = set_attr_snat_port,
+ [ATTR_DNAT_PORT] = set_attr_dnat_port,
+ [ATTR_TIMEOUT] = set_attr_timeout,
+ [ATTR_MARK] = set_attr_mark,
+ [ATTR_ASSURED] = set_attr_assured,
+ [ATTR_SEEN_REPLY] = set_attr_seen_reply,
+};
Index: libnetfilter_conntrack/src/internal.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/internal.h 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,133 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.net>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * WARNING: Do *NOT* ever include this file, only for internal use!
+ * Use the set/get API in order to set/get the conntrack attributes
+ */
+
+#ifndef __LIBNETFILTER_CONNTRACK_INTERNAL__
+#define __LIBNETFILTER_CONNTRACK_INTERNAL__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+struct nfct_handle;
+
+typedef void (*set_attr)(struct nf_conntrack *ct, const void *value);
+typedef const void *(*get_attr)(const struct nf_conntrack *ct);
+
+extern set_attr set_attr_array[];
+extern get_attr get_attr_array[];
+
+union __nfct_l4 {
+ /* Add other protocols here. */
+ u_int16_t all;
+ struct {
+ u_int16_t port;
+ } tcp;
+ struct {
+ u_int16_t port;
+ } udp;
+ struct {
+ u_int8_t type, code;
+ u_int16_t id;
+ } icmp;
+ struct {
+ u_int16_t port;
+ } sctp;
+};
+
+union __nfct_address {
+ u_int32_t v4;
+ struct in6_addr v6;
+};
+
+struct __nfct_tuple {
+ union __nfct_address src;
+ union __nfct_address dst;
+
+ u_int8_t l3protonum;
+ u_int8_t protonum;
+ union __nfct_l4 l4src;
+ union __nfct_l4 l4dst;
+};
+
+union __nfct_protoinfo {
+ struct {
+ u_int8_t state;
+ } tcp;
+};
+
+struct __nfct_counters {
+ u_int64_t packets;
+ u_int64_t bytes;
+};
+
+struct __nfct_nat {
+ u_int32_t min_ip, max_ip;
+ union __nfct_l4 l4min, l4max;
+};
+
+#define __DIR_ORIG 0
+#define __DIR_REPL 1
+#define __DIR_MAX __DIR_REPL+1
+
+struct nf_conntrack {
+ struct __nfct_tuple tuple[__DIR_MAX];
+
+ u_int32_t timeout;
+ u_int32_t mark;
+ u_int32_t status;
+ u_int32_t use;
+ u_int32_t id;
+
+ union __nfct_protoinfo protoinfo;
+ struct __nfct_counters counters[__DIR_MAX];
+ struct __nfct_nat snat;
+ struct __nfct_nat dnat;
+
+ u_int32_t set[2];
+};
+
+static inline void set_bit(int nr, u_int32_t *addr)
+{
+ addr[nr >> 5] |= (1UL << (nr & 31));
+}
+
+static inline int test_bit(int nr, const u_int32_t *addr)
+{
+ return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
+}
+
+static char *proto2str[IPPROTO_MAX] = {
+ [IPPROTO_TCP] = "tcp",
+ [IPPROTO_UDP] = "udp",
+ [IPPROTO_ICMP] = "icmp",
+ [IPPROTO_SCTP] = "sctp"
+};
+static char *l3proto2str[AF_MAX] = {
+ [AF_INET] = "ipv4",
+ [AF_INET6] = "ipv6"
+};
+
+static const char *states[] = {
+ "NONE",
+ "SYN_SENT",
+ "SYN_RECV",
+ "ESTABLISHED",
+ "FIN_WAIT",
+ "CLOSE_WAIT",
+ "LAST_ACK",
+ "TIME_WAIT",
+ "CLOSE",
+ "LISTEN"
+};
+
+#endif
Index: libnetfilter_conntrack/src/parse.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/parse.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,231 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+void __parse_ip(const struct nfattr *attr,
+ struct __nfct_tuple *tuple,
+ const int dir,
+ u_int32_t *set)
+{
+ struct nfattr *tb[CTA_IP_MAX];
+
+ nfnl_parse_nested(tb, CTA_IP_MAX, attr);
+
+ if (tb[CTA_IP_V4_SRC-1]) {
+ tuple->src.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_IPV4_SRC, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_IPV4_SRC, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_IP_V4_DST-1]) {
+ tuple->dst.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_IPV4_DST, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_IPV4_DST, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_IP_V6_SRC-1]) {
+ memcpy(&tuple->src.v6, NFA_DATA(tb[CTA_IP_V6_SRC-1]),
+ sizeof(struct in6_addr));
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_IPV6_SRC, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_IPV6_SRC, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_IP_V6_DST-1]) {
+ memcpy(&tuple->dst.v6, NFA_DATA(tb[CTA_IP_V6_DST-1]),
+ sizeof(struct in6_addr));
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_IPV6_DST, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_IPV6_DST, set);
+ break;
+ }
+ }
+}
+
+void __parse_proto(const struct nfattr *attr,
+ struct __nfct_tuple *tuple,
+ const int dir,
+ u_int32_t *set)
+{
+ struct nfattr *tb[CTA_PROTO_MAX];
+
+ nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
+
+ if (tb[CTA_PROTO_NUM-1]) {
+ tuple->protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_L4PROTO, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_L4PROTO, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_PROTO_SRC_PORT-1]) {
+ tuple->l4src.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_SRC_PORT-1]);
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_PORT_SRC, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_PORT_SRC, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_PROTO_DST_PORT-1]) {
+ tuple->l4dst.tcp.port =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_DST_PORT-1]);
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_PORT_DST, set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_PORT_DST, set);
+ break;
+ }
+ }
+
+ if (tb[CTA_PROTO_ICMP_TYPE-1]) {
+ tuple->l4dst.icmp.type =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
+ set_bit(ATTR_ICMP_TYPE, set);
+ }
+
+ if (tb[CTA_PROTO_ICMP_CODE-1]) {
+ tuple->l4dst.icmp.code =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
+ set_bit(ATTR_ICMP_CODE, set);
+ }
+
+ if (tb[CTA_PROTO_ICMP_ID-1]) {
+ tuple->l4src.icmp.id =
+ *(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+ set_bit(ATTR_ICMP_ID, set);
+ }
+}
+
+void __parse_tuple(const struct nfattr *attr,
+ struct __nfct_tuple *tuple,
+ int dir,
+ u_int32_t *set)
+{
+ struct nfattr *tb[CTA_TUPLE_MAX];
+
+ nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
+
+ if (tb[CTA_TUPLE_IP-1])
+ __parse_ip(tb[CTA_TUPLE_IP-1], tuple, dir, set);
+ if (tb[CTA_TUPLE_PROTO-1])
+ __parse_proto(tb[CTA_TUPLE_PROTO-1], tuple, dir, set);
+}
+
+void __parse_mask(const struct nfattr *attr,
+ struct __nfct_tuple *tuple,
+ const u_int8_t l3protonum,
+ const u_int16_t protonum,
+ u_int32_t *set)
+{
+ __parse_tuple(attr, tuple, __DIR_ORIG, set);
+}
+
+void __parse_protoinfo(const struct nfattr *attr, struct nf_conntrack *ct)
+{
+ struct nfattr *tb[CTA_PROTOINFO_MAX];
+
+ nfnl_parse_nested(tb, CTA_PROTOINFO_MAX, attr);
+
+ if (!tb[CTA_PROTOINFO_TCP-1])
+ return 0;
+
+ nfnl_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, tb[CTA_PROTOINFO_TCP-1]);
+
+ if (tb[CTA_PROTOINFO_TCP_STATE-1]) {
+ ct->protoinfo.tcp.state =
+ *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
+ set_bit(ATTR_TCP_STATE, ct->set);
+ }
+}
+
+void __parse_counters(const struct nfattr *attr,
+ struct nf_conntrack *ct,
+ enum ctattr_type parent)
+{
+ struct nfattr *tb[CTA_COUNTERS_MAX];
+ int dir = (parent == CTA_COUNTERS_ORIG ? __DIR_REPL
+ : __DIR_ORIG);
+
+ nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
+ if (tb[CTA_COUNTERS_PACKETS-1]) {
+ ct->counters[dir].packets
+ = __be64_to_cpu(*(u_int64_t *)
+ NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]));
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_COUNTER_PACKETS, ct->set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_COUNTER_PACKETS, ct->set);
+ break;
+ }
+ }
+ if (tb[CTA_COUNTERS_BYTES-1]) {
+ ct->counters[dir].bytes
+ = __be64_to_cpu(*(u_int64_t *)
+ NFA_DATA(tb[CTA_COUNTERS_BYTES-1]));
+ switch(dir) {
+ case __DIR_ORIG:
+ set_bit(ATTR_ORIG_COUNTER_BYTES, ct->set);
+ break;
+ case __DIR_REPL:
+ set_bit(ATTR_REPL_COUNTER_BYTES, ct->set);
+ break;
+ }
+ }
+}
+
+int __msgtype2enum(struct nlmsghdr *nlh)
+{
+ u_int16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
+ u_int16_t flags = nlh->nlmsg_flags;
+ int ret = NFCT_MSG_UNKNOWN;
+
+ if (type == IPCTNL_MSG_CT_NEW) {
+ if (flags & (NLM_F_CREATE|NLM_F_EXCL))
+ ret = NFCT_MSG_NEW;
+ else
+ ret = NFCT_MSG_UPDATE;
+ } else if (type == IPCTNL_MSG_CT_DELETE)
+ ret = NFCT_MSG_DESTROY;
+
+ return ret;
+}
+
Index: libnetfilter_conntrack/src/sprint.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/src/sprint.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,137 @@
+/*
+ * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
+
+#include "internal.h"
+
+int __sprintf_protocol(char *buf, struct nf_conntrack *ct)
+{
+ return (sprintf(buf, "%-8s %u ",
+ proto2str[ct->tuple[__DIR_ORIG].protonum] == NULL ?
+ "unknown" : proto2str[ct->tuple[__DIR_ORIG].protonum],
+ ct->tuple[__DIR_ORIG].protonum));
+}
+
+int __sprintf_timeout(char *buf, struct nf_conntrack *ct)
+{
+ return sprintf(buf, "%u ", ct->timeout);
+}
+
+int __sprintf_protoinfo(char *buf, struct nf_conntrack *ct)
+{
+ int size = 0;
+
+ if (test_bit(ATTR_TCP_STATE, ct->set))
+ size = sprintf(buf, "%s ", states[ct->protoinfo.tcp.state]);
+
+ return size;
+}
+
+int __sprintf_address(char *buf, struct nfct_tuple *tuple)
+{
+ int size = 0;
+
+ switch (tuple->l3protonum) {
+ case AF_INET:
+ {
+ struct in_addr src = { .s_addr = tuple->src.v4 };
+ struct in_addr dst = { .s_addr = tuple->dst.v4 };
+
+ size = sprintf(buf, "src=%s ", inet_ntoa(src));
+ size += sprintf(buf+size, "dst=%s ", inet_ntoa(dst));
+ }
+ break;
+ case AF_INET6:
+ {
+ struct in6_addr src;
+ struct in6_addr dst;
+ char tmp[INET6_ADDRSTRLEN];
+
+ memcpy(&src.in6_u, tuple->src.v6, sizeof(struct in6_addr));
+ memcpy(&dst.in6_u, tuple->dst.v6, sizeof(struct in6_addr));
+
+ if (!inet_ntop(AF_INET6, &src, tmp, sizeof(tmp)))
+ return 0;
+
+ size = sprintf(buf, "src=%s ", tmp);
+
+ if (!inet_ntop(AF_INET6, &dst, tmp, sizeof(tmp)))
+ return 0;
+
+ size += sprintf(buf + size, "dst=%s ", tmp);
+ }
+ break;
+ }
+
+ return size;
+}
+
+int __sprintf_proto(char *buf, struct nfct_tuple *tuple)
+{
+ int size = 0;
+
+ switch(tuple->protonum) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_SCTP:
+ sprintf(buf, "sport=%u dport=%u ",
+ htons(tuple->l4src.tcp.port),
+ htons(tuple->l4dst.tcp.port));
+ break;
+ case IPPROTO_ICMP:
+ /* The ID only makes sense some ICMP messages but we want to
+ * display the same output that /proc/net/ip_conntrack does */
+ return (sprintf(buf, "type=%d code=%d id=%d ",
+ tuple->l4dst.icmp.type,
+ tuple->l4dst.icmp.code,
+ ntohs(tuple->l4src.icmp.id)));
+ break;
+ }
+
+ return size;
+}
+
+int __sprintf_status_assured(char *buf, struct nf_conntrack *ct)
+{
+ int size = 0;
+
+ if (ct->status & IPS_ASSURED)
+ size = sprintf(buf, "[ASSURED] ");
+
+ return size;
+}
+
+int __sprintf_status_seen_reply(char *buf, struct nf_conntrack *ct)
+{
+ int size = 0;
+
+ if (!(ct->status & IPS_SEEN_REPLY))
+ size = sprintf(buf, "[UNREPLIED] ");
+
+ return size;
+}
+
+int __sprintf_counters(char *buf, struct nf_conntrack *ct, int dir)
+{
+ return (sprintf(buf, "packets=%llu bytes=%llu ",
+ (unsigned long long) ct->counters[dir].packets,
+ (unsigned long long) ct->counters[dir].bytes));
+}
+
+int __sprintf_mark(char *buf, struct nf_conntrack *ct)
+{
+ return (sprintf(buf, "mark=%u ", ct->mark));
+}
+
+int __sprintf_use(char *buf, struct nf_conntrack *ct)
+{
+ return (sprintf(buf, "use=%u ", ct->use));
+}
+
+int __sprintf_id(char *buf, u_int32_t id)
+{
+ return (sprintf(buf, "id=%u ", id));
+}
Index: libnetfilter_conntrack/utils/test.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ libnetfilter_conntrack/utils/test.c 2006-10-30 02:11:18.000000000 +0100
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+int main()
+{
+ int ret;
+ struct nfct_handle *h;
+ struct nf_conntrack *ct;
+ char buf[1024];
+
+ ct = nfct_new();
+ if (!ct) {
+ perror("nfct_new");
+ return 0;
+ }
+
+ nfct_set_attr_u8(ct, ATTR_ORIG_L3PROTO, AF_INET);
+ nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_SRC, inet_addr("1.1.1.1"));
+ nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_DST, inet_addr("2.2.2.2"));
+
+ nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_TCP);
+ nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, ntohs(20));
+ nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, ntohs(10));
+
+ nfct_set_attr_u8(ct, ATTR_REPL_L3PROTO, AF_INET);
+ nfct_set_attr_u32(ct, ATTR_REPL_IPV4_SRC, inet_addr("2.2.2.2"));
+ nfct_set_attr_u32(ct, ATTR_REPL_IPV4_DST, inet_addr("1.1.1.1"));
+
+ nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_TCP);
+ nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, ntohs(10));
+ nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, ntohs(20));
+
+ nfct_set_attr_u8(ct, ATTR_TCP_STATE, 1);
+ nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100);
+
+ nfct_sprintf(buf, ct);
+ printf("Test conntrack: %s\n", buf);
+
+ h = nfct_open(CONNTRACK, 0);
+ if (!h) {
+ fprintf(stderr, "Can't open handler\n");
+ return -1;
+ }
+
+ ret = nfct_query(h, NFCT_Q_CREATE, ct);
+
+ printf("create ret = %d\n", ret);
+
+ ret = nfct_query(h, NFCT_Q_UPDATE, ct);
+
+ printf("update ret = %d\n", ret);
+
+ ret = nfct_query(h, NFCT_Q_DESTROY, ct);
+
+ printf("destroy ret = %d\n", ret);
+
+ nfct_close(h);
+}
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
2006-10-30 2:25 [RFC] new API for libnetfilter_conntrack Pablo Neira Ayuso
@ 2006-10-31 18:57 ` Pablo Neira Ayuso
2006-11-03 10:03 ` Patrick McHardy
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2006-10-31 18:57 UTC (permalink / raw)
To: Netfilter Development Mailinglist
Cc: Harald Welte, Patrick McHardy, Eric Leblond
Pablo Neira Ayuso wrote:
> Hi,
>
> Attached a patch, yet incomplete, that introduces the new API for
> libnetfilter_conntrack. Basically the idea consists of providing
> "conntrack" objects constructor/destructor functions and an interface to
> get and set object attributes. The conntrack object structure is
> encapsulated therefore we can add new attributes without breaking binary
> backward compatibility. There is an example of the new API use in the
> patch (see test.c file)
JFYI: I'm going to finish the patch and then get back to the list for
discussion, perhaps I was too fast to request feedback. If someone is
interested in the evolution of the proposed new API, I'll be updating
the patch on my people netfilter place.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
2006-10-30 2:25 [RFC] new API for libnetfilter_conntrack Pablo Neira Ayuso
2006-10-31 18:57 ` Pablo Neira Ayuso
@ 2006-11-03 10:03 ` Patrick McHardy
2006-11-05 14:32 ` Pablo Neira Ayuso
2006-11-07 19:24 ` Harald Welte
[not found] ` <20061107192458.GJ4423@(none)>
3 siblings, 1 reply; 8+ messages in thread
From: Patrick McHardy @ 2006-11-03 10:03 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Harald Welte, Netfilter Development Mailinglist, Eric Leblond
Pablo Neira Ayuso wrote:
> Hi,
>
> Attached a patch, yet incomplete, that introduces the new API for
> libnetfilter_conntrack. Basically the idea consists of providing
> "conntrack" objects constructor/destructor functions and an interface to
> get and set object attributes. The conntrack object structure is
> encapsulated therefore we can add new attributes without breaking binary
> backward compatibility. There is an example of the new API use in the
> patch (see test.c file)
>
> See that conntrack object attributes are different from the netlink
> attributes therefore they provide a high level interface that abstract
> from netlink details. The idea is to let the programmer make the choice
> to work with high level (objects) or low level (netlink) and provide the
> gateways to switch from high to low level and vice-versa by means of
> functions to build/parse netlink messages from/to conntrack objects.
>
> The reason why I posted this patch is because I'm thinking about
> generalizing this a bit more and provide a complete high level API that
> would be the same for all the netfilter subsystems. This will result in
> a single library to rules them all with a subdirectory that contains the
> details of every specific subsystem.
>
> nfh = nf_open(); /* encapsulate nfnl_open() */
> ssh = nf_setup_subsys(nfnlh, CONNTRACK); /* encapsulate
> nfnl_subsys_open() */
> ...
> ct = nf_new_object(NF_CONNTRACK_OBJECT);
> nf_set_attr_u8(ct, ATTR_XXX, value);
> nf_set_attr_u16(ct, ATTR_XXX, value);
> ...
> nf_query_object(ssh, NF_CT_CREATE, ct);
> nf_free_object(ct);
> nf_close(nfh);
>
> I'd like to hear from you before going ahead, always appreciate your
> feedback guys. Comments welcome.
I like that approach. Its getting pretty close to the libnl API,
have you considered integrating this in libnl?
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
2006-11-03 10:03 ` Patrick McHardy
@ 2006-11-05 14:32 ` Pablo Neira Ayuso
2006-11-05 16:45 ` Patrick McHardy
0 siblings, 1 reply; 8+ messages in thread
From: Pablo Neira Ayuso @ 2006-11-05 14:32 UTC (permalink / raw)
To: Patrick McHardy
Cc: Harald Welte, Netfilter Development Mailinglist, Eric Leblond
Patrick McHardy wrote:
> Pablo Neira Ayuso wrote:
>> Hi,
>>
>> Attached a patch, yet incomplete, that introduces the new API for
>> libnetfilter_conntrack. Basically the idea consists of providing
>> "conntrack" objects constructor/destructor functions and an interface to
>> get and set object attributes. The conntrack object structure is
>> encapsulated therefore we can add new attributes without breaking binary
>> backward compatibility. There is an example of the new API use in the
>> patch (see test.c file)
>>
>> See that conntrack object attributes are different from the netlink
>> attributes therefore they provide a high level interface that abstract
>> from netlink details. The idea is to let the programmer make the choice
>> to work with high level (objects) or low level (netlink) and provide the
>> gateways to switch from high to low level and vice-versa by means of
>> functions to build/parse netlink messages from/to conntrack objects.
>>
>> [...]
>
> I like that approach. Its getting pretty close to the libnl API,
> have you considered integrating this in libnl?
I'm going to, I'm not too familiar with libnl (just spend some hours
yesterday and today) but I agree that the new API is getting close. At
first sight, my impression is that most of the code of my current patch
could be adapted to introduce ctnetlink support in libnl, and I don't
mind about doing so in the close future.
Perhaps we can introduce some kind of dependency between libnl and
libnetfilter_* (of course, providing an homogeneous API) but I'm unsure
that Thomas would like that.
I agree that people could choose between different libraries depending
on their preferences but at the moment I'm unsure that this would imply
dropping support for our libraries.
Back to libnl, I think that the cache thing provided by the library is
nice to implement quick applications without too much effort but I'm
unsure that this is the place to put this, I think that the data
structure used to store the entries of, say the neighbour cache, must be
up to the programmer (array, hash table, tree...), although nothing
prevents the programmer of not using the cache thing.
Anyway, I'm going to post the patches for libnfnetlink and
libnetfilter_conntrack soon, please let me make peace and apply them
since I do need them in mainline as well as many other people, we can go
back to this discussion later once I get more familiarized with libnl.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
2006-11-05 14:32 ` Pablo Neira Ayuso
@ 2006-11-05 16:45 ` Patrick McHardy
0 siblings, 0 replies; 8+ messages in thread
From: Patrick McHardy @ 2006-11-05 16:45 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Harald Welte, Netfilter Development Mailinglist, Eric Leblond
Pablo Neira Ayuso wrote:
> Patrick McHardy wrote:
>
>>I like that approach. Its getting pretty close to the libnl API,
>>have you considered integrating this in libnl?
>
>
> I'm going to, I'm not too familiar with libnl (just spend some hours
> yesterday and today) but I agree that the new API is getting close. At
> first sight, my impression is that most of the code of my current patch
> could be adapted to introduce ctnetlink support in libnl, and I don't
> mind about doing so in the close future.
>
> Perhaps we can introduce some kind of dependency between libnl and
> libnetfilter_* (of course, providing an homogeneous API) but I'm unsure
> that Thomas would like that.
I don't think thats necessary, libnl includes all the infrastrucure
needed to handle nfnetlink.
> I agree that people could choose between different libraries depending
> on their preferences but at the moment I'm unsure that this would imply
> dropping support for our libraries.
>
> Back to libnl, I think that the cache thing provided by the library is
> nice to implement quick applications without too much effort but I'm
> unsure that this is the place to put this, I think that the data
> structure used to store the entries of, say the neighbour cache, must be
> up to the programmer (array, hash table, tree...), although nothing
> prevents the programmer of not using the cache thing.
Agreed. I have a patch that replaces the linked list caches by hashes,
but it has some drawbacks since not all objects are suitable for
hashing without making expectations about their use. It shouldn't
be hard to use your own scheme, I think the only thing that
prevents it right now is that the structure is hidden from API
users.
> Anyway, I'm going to post the patches for libnfnetlink and
> libnetfilter_conntrack soon, please let me make peace and apply them
> since I do need them in mainline as well as many other people, we can go
> back to this discussion later once I get more familiarized with libnl.
Sure. Harald is renewing your keys, so you can simply apply it yourself.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
2006-10-30 2:25 [RFC] new API for libnetfilter_conntrack Pablo Neira Ayuso
2006-10-31 18:57 ` Pablo Neira Ayuso
2006-11-03 10:03 ` Patrick McHardy
@ 2006-11-07 19:24 ` Harald Welte
[not found] ` <20061107192458.GJ4423@(none)>
3 siblings, 0 replies; 8+ messages in thread
From: Harald Welte @ 2006-11-07 19:24 UTC (permalink / raw)
To: Pablo Neira Ayuso
Cc: Netfilter Development Mailinglist, Patrick McHardy, Eric Leblond
[-- Attachment #1: Type: text/plain, Size: 2001 bytes --]
On Mon, Oct 30, 2006 at 03:25:09AM +0100, Pablo Neira Ayuso wrote:
> Hi,
>
> Attached a patch, yet incomplete, that introduces the new API for
> libnetfilter_conntrack. Basically the idea consists of providing
> "conntrack" objects constructor/destructor functions and an interface to
> get and set object attributes. The conntrack object structure is
> encapsulated therefore we can add new attributes without breaking binary
> backward compatibility. There is an example of the new API use in the
> patch (see test.c file)
I like that API and I think it's the right way to go.
> The reason why I posted this patch is because I'm thinking about
> generalizing this a bit more and provide a complete high level API that
> would be the same for all the netfilter subsystems.
Makes sense.
> This will result in a single library to rules them all with a
> subdirectory that contains the details of every specific subsystem.
I disagree with that proposition. I don't really understand why
completely independent netfilter subsystems should share a high-level
userspace library. Every time some obscure bug in libnetfilter_log
happens, libnetfilter_conntrack will be affected, too.
This is especially difficult if meanwhile you have commited
not-yet-completely-stable code for one subsystem, and then need to make
a bugfix releease of the other (svn branching is an option, but it all
sounds a bit too complex for my taste).
One option would be implement the subsystem specific parts as plugins
and to dlopen() them at runtime, providing a way of updating only
individual subystem-plugins
--
- Harald Welte <laforge@netfilter.org> http://netfilter.org/
============================================================================
"Fragmentation is like classful addressing -- an interesting early
architectural error that shows how much experimentation was going
on while IP was being designed." -- Paul Vixie
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
[not found] ` <20061107192458.GJ4423@(none)>
@ 2006-11-08 19:44 ` Pablo Neira Ayuso
2006-11-10 19:07 ` Pablo Neira Ayuso
1 sibling, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2006-11-08 19:44 UTC (permalink / raw)
To: Harald Welte, Pablo Neira Ayuso,
Netfilter Development Mailinglist, Patrick McHardy, Eric Leblond
Harald Welte wrote:
> One option would be implement the subsystem specific parts as plugins
> and to dlopen() them at runtime, providing a way of updating only
> individual subystem-plugins
I like this option
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC] new API for libnetfilter_conntrack
[not found] ` <20061107192458.GJ4423@(none)>
2006-11-08 19:44 ` Pablo Neira Ayuso
@ 2006-11-10 19:07 ` Pablo Neira Ayuso
1 sibling, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2006-11-10 19:07 UTC (permalink / raw)
To: Harald Welte, Pablo Neira Ayuso,
Netfilter Development Mailinglist, Patrick McHardy, Eric Leblond
Harald Welte wrote:
>> This will result in a single library to rules them all with a
>> subdirectory that contains the details of every specific subsystem.
>
> I disagree with that proposition. I don't really understand why
> completely independent netfilter subsystems should share a high-level
> userspace library. Every time some obscure bug in libnetfilter_log
> happens, libnetfilter_conntrack will be affected, too.
>
> This is especially difficult if meanwhile you have commited
> not-yet-completely-stable code for one subsystem, and then need to make
> a bugfix releease of the other (svn branching is an option, but it all
> sounds a bit too complex for my taste).
Yes, this is a tricky issue, although the libraries are relatively small
in terms of code and the impact of such problem could be reduced if we
do frequent releases.
> One option would be implement the subsystem specific parts as plugins
> and to dlopen() them at runtime, providing a way of updating only
> individual subystem-plugins
As I posted days ago, this is an alternative that I like, such dlopen()
would require a versioning mechanism, the only concerned here is about
getting people confused with this modular view.
--
The dawn of the fourth age of Linux firewalling is coming; a time of
great struggle and heroic deeds -- J.Kadlecsik got inspired by J.Morris
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2006-11-10 19:07 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-30 2:25 [RFC] new API for libnetfilter_conntrack Pablo Neira Ayuso
2006-10-31 18:57 ` Pablo Neira Ayuso
2006-11-03 10:03 ` Patrick McHardy
2006-11-05 14:32 ` Pablo Neira Ayuso
2006-11-05 16:45 ` Patrick McHardy
2006-11-07 19:24 ` Harald Welte
[not found] ` <20061107192458.GJ4423@(none)>
2006-11-08 19:44 ` Pablo Neira Ayuso
2006-11-10 19:07 ` Pablo Neira Ayuso
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.