summaryrefslogtreecommitdiffstats
path: root/src/conntrack
diff options
context:
space:
mode:
Diffstat (limited to 'src/conntrack')
-rw-r--r--src/conntrack/Makefile.am3
-rw-r--r--src/conntrack/api.c93
-rw-r--r--src/conntrack/grp.c69
-rw-r--r--src/conntrack/grp_getter.c108
-rw-r--r--src/conntrack/grp_setter.c156
5 files changed, 428 insertions, 1 deletions
diff --git a/src/conntrack/Makefile.am b/src/conntrack/Makefile.am
index 94009ea..2d62177 100644
--- a/src/conntrack/Makefile.am
+++ b/src/conntrack/Makefile.am
@@ -13,4 +13,5 @@ libnfconntrack_la_SOURCES = api.c callback.c \
objopt.c \
compare.c \
copy.c \
- filter.c bsf.c
+ filter.c bsf.c \
+ grp.c grp_getter.c grp_setter.c
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 61d3237..efd298e 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -385,6 +385,99 @@ int nfct_attr_unset(struct nf_conntrack *ct,
}
/**
+ * nfct_set_attr_grp - set a group of attributes
+ * @ct: pointer to a valid conntrack object
+ * @type: attribute group (see ATTR_GRP_*)
+ * @data: pointer to struct (see struct nfct_attr_grp_*)
+ *
+ * Note that calling this function for ATTR_GRP_COUNTER_* does nothing since
+ * counters are unsettable.
+ */
+void nfct_set_attr_grp(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr_grp type,
+ const void *data)
+{
+ assert(ct != NULL);
+
+ if (unlikely(type >= ATTR_GRP_MAX))
+ return;
+
+ if (set_attr_grp_array[type]) {
+ set_attr_grp_array[type](ct, data);
+ set_bitmask_u32(ct->set, attr_grp_bitmask[type], __NFCT_BITSET);
+ }
+}
+
+/**
+ * nfct_get_attr_grp - get an attribute group
+ * @ct: pointer to a valid conntrack object
+ * @type: attribute group (see ATTR_GRP_*)
+ * @data: pointer to struct (see struct nfct_attr_grp_*)
+ *
+ * On error, it returns -1 and errno is appropriately set. On success, the
+ * data pointer contains the attribute group.
+ */
+int nfct_get_attr_grp(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr_grp type,
+ void *data)
+{
+ assert(ct != NULL);
+
+ if (unlikely(type >= ATTR_GRP_MAX)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (!test_bitmask_u32(ct->set, attr_grp_bitmask[type], __NFCT_BITSET)) {
+ errno = ENODATA;
+ return -1;
+ }
+ assert(get_attr_grp_array[type]);
+ get_attr_grp_array[type](ct, data);
+ return 0;
+}
+
+/**
+ * nfct_attr_grp_is_set - check if an attribute group is set
+ * @ct: pointer to a valid conntrack object
+ * @type: attribute group (see ATTR_GRP_*)
+ *
+ * If the attribute group is set, this function returns 1, otherwise 0.
+ */
+int nfct_attr_grp_is_set(const struct nf_conntrack *ct,
+ const enum nf_conntrack_attr_grp type)
+{
+ assert(ct != NULL);
+
+ if (unlikely(type >= ATTR_GRP_MAX)) {
+ errno = EINVAL;
+ return -1;
+ }
+ return test_bitmask_u32(ct->set, attr_grp_bitmask[type], __NFCT_BITSET);
+}
+
+/**
+ * nfct_attr_grp_unset - unset an attribute group
+ * @ct: pointer to a valid conntrack object
+ * @type: attribute group (see ATTR_GRP_*)
+ *
+ * On error, it returns -1 and errno is appropriately set. On success,
+ * this function returns 0.
+ */
+int nfct_attr_grp_unset(struct nf_conntrack *ct,
+ const enum nf_conntrack_attr_grp type)
+{
+ assert(ct != NULL);
+
+ if (unlikely(type >= ATTR_GRP_MAX)) {
+ errno = EINVAL;
+ return -1;
+ }
+ unset_bitmask_u32(ct->set, attr_grp_bitmask[type], __NFCT_BITSET);
+
+ return 0;
+}
+
+/**
* nfct_build_conntrack - build a netlink message from a conntrack object
* @ssh: nfnetlink subsystem handler
* @req: buffer used to build the netlink message
diff --git a/src/conntrack/grp.c b/src/conntrack/grp.c
new file mode 100644
index 0000000..739f8c6
--- /dev/null
+++ b/src/conntrack/grp.c
@@ -0,0 +1,69 @@
+/*
+ * (C) 2008 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/internal.h"
+
+uint32_t attr_grp_bitmask[ATTR_GRP_MAX][__NFCT_BITSET] = {
+ [ATTR_GRP_ORIG_IPV4] = {
+ [0] = (1 << ATTR_ORIG_IPV4_SRC) |
+ (1 << ATTR_ORIG_IPV4_DST) |
+ (1 << ATTR_ORIG_L3PROTO),
+ },
+ [ATTR_GRP_REPL_IPV4] = {
+ [0] = (1 << ATTR_REPL_IPV4_SRC) |
+ (1 << ATTR_REPL_IPV4_DST) |
+ (1 << ATTR_REPL_L3PROTO),
+ },
+ [ATTR_GRP_ORIG_IPV6] = {
+ [0] = (1 << ATTR_ORIG_IPV6_SRC) |
+ (1 << ATTR_ORIG_IPV6_DST) |
+ (1 << ATTR_ORIG_L3PROTO),
+ },
+ [ATTR_GRP_REPL_IPV6] = {
+ [0] = (1 << ATTR_REPL_IPV6_SRC) |
+ (1 << ATTR_REPL_IPV6_DST) |
+ (1 << ATTR_REPL_L3PROTO),
+ },
+ [ATTR_GRP_ORIG_PORT] = {
+ [0] = (1 << ATTR_ORIG_PORT_SRC) |
+ (1 << ATTR_ORIG_PORT_DST) |
+ (1 << ATTR_ORIG_L4PROTO),
+ },
+ [ATTR_GRP_REPL_PORT] = {
+ [0] = (1 << ATTR_REPL_PORT_SRC) |
+ (1 << ATTR_REPL_PORT_DST) |
+ (1 << ATTR_REPL_L4PROTO),
+ },
+ [ATTR_GRP_ICMP] = {
+ [0] = (1 << ATTR_ICMP_CODE) |
+ (1 << ATTR_ICMP_TYPE) |
+ (1 << ATTR_ICMP_ID),
+ },
+ [ATTR_GRP_MASTER_IPV4] = {
+ [1] = (1 << (ATTR_MASTER_IPV4_SRC - 32)) |
+ (1 << (ATTR_MASTER_IPV4_DST - 32)) |
+ (1 << (ATTR_MASTER_L3PROTO - 32)),
+ },
+ [ATTR_GRP_MASTER_IPV6] = {
+ [1] = (1 << (ATTR_MASTER_IPV6_SRC - 32)) |
+ (1 << (ATTR_MASTER_IPV6_DST - 32)) |
+ (1 << (ATTR_MASTER_L3PROTO - 32)),
+ },
+ [ATTR_GRP_MASTER_PORT] = {
+ [1] = (1 << (ATTR_MASTER_PORT_SRC - 32)) |
+ (1 << (ATTR_MASTER_PORT_DST - 32)) |
+ (1 << (ATTR_MASTER_L4PROTO - 32)),
+ },
+ [ATTR_GRP_ORIG_COUNTERS] = {
+ [0] = (1 << (ATTR_ORIG_COUNTER_PACKETS)) |
+ (1 << (ATTR_ORIG_COUNTER_BYTES)),
+ },
+ [ATTR_GRP_REPL_COUNTERS] = {
+ [0] = (1 << (ATTR_REPL_COUNTER_PACKETS)) |
+ (1 << (ATTR_REPL_COUNTER_BYTES)),
+ },
+};
diff --git a/src/conntrack/grp_getter.c b/src/conntrack/grp_getter.c
new file mode 100644
index 0000000..adfd903
--- /dev/null
+++ b/src/conntrack/grp_getter.c
@@ -0,0 +1,108 @@
+/*
+ * (C) 2008 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/internal.h"
+
+static void get_attr_grp_orig_ipv4(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv4 *this = data;
+ this->src = ct->tuple[__DIR_ORIG].src.v4;
+ this->dst = ct->tuple[__DIR_ORIG].dst.v4;
+}
+
+static void get_attr_grp_repl_ipv4(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv4 *this = data;
+ this->src = ct->tuple[__DIR_REPL].src.v4;
+ this->dst = ct->tuple[__DIR_REPL].dst.v4;
+}
+
+static void get_attr_grp_orig_ipv6(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv6 *this = data;
+ memcpy(this->src, &ct->tuple[__DIR_ORIG].src.v6, sizeof(u_int32_t)*4);
+ memcpy(this->dst, &ct->tuple[__DIR_ORIG].dst.v6, sizeof(u_int32_t)*4);
+}
+
+static void get_attr_grp_repl_ipv6(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv6 *this = data;
+ memcpy(this->src, &ct->tuple[__DIR_REPL].src.v6, sizeof(u_int32_t)*4);
+ memcpy(this->dst, &ct->tuple[__DIR_REPL].dst.v6, sizeof(u_int32_t)*4);
+}
+
+static void get_attr_grp_orig_port(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_port *this = data;
+ this->sport = ct->tuple[__DIR_ORIG].l4src.all;
+ this->dport = ct->tuple[__DIR_ORIG].l4dst.all;
+}
+
+static void get_attr_grp_repl_port(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_port *this = data;
+ this->sport = ct->tuple[__DIR_REPL].l4src.all;
+ this->dport = ct->tuple[__DIR_REPL].l4dst.all;
+}
+
+static void get_attr_grp_icmp(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_icmp *this = data;
+ this->type = ct->tuple[__DIR_ORIG].l4dst.icmp.type;
+ this->code = ct->tuple[__DIR_ORIG].l4dst.icmp.code;
+ this->id = ct->tuple[__DIR_ORIG].l4src.icmp.id;
+}
+
+static void get_attr_grp_master_ipv4(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv4 *this = data;
+ this->src = ct->tuple[__DIR_MASTER].src.v4;
+ this->dst = ct->tuple[__DIR_MASTER].dst.v4;
+}
+
+static void get_attr_grp_master_ipv6(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ipv6 *this = data;
+ memcpy(this->src, &ct->tuple[__DIR_MASTER].src.v6, sizeof(u_int32_t)*4);
+ memcpy(this->dst, &ct->tuple[__DIR_MASTER].dst.v6, sizeof(u_int32_t)*4);
+}
+
+static void get_attr_grp_master_port(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_port *this = data;
+ this->sport = ct->tuple[__DIR_MASTER].l4src.all;
+ this->dport = ct->tuple[__DIR_MASTER].l4dst.all;
+}
+
+static void get_attr_grp_orig_ctrs(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ctrs *this = data;
+ this->packets = ct->counters[__DIR_ORIG].packets;
+ this->bytes = ct->counters[__DIR_ORIG].bytes;
+}
+
+static void get_attr_grp_repl_ctrs(const struct nf_conntrack *ct, void *data)
+{
+ struct nfct_attr_grp_ctrs *this = data;
+ this->packets = ct->counters[__DIR_REPL].packets;
+ this->bytes = ct->counters[__DIR_REPL].bytes;
+}
+
+get_attr_grp get_attr_grp_array[] = {
+ [ATTR_GRP_ORIG_IPV4] = get_attr_grp_orig_ipv4,
+ [ATTR_GRP_REPL_IPV4] = get_attr_grp_repl_ipv4,
+ [ATTR_GRP_ORIG_IPV6] = get_attr_grp_orig_ipv6,
+ [ATTR_GRP_REPL_IPV6] = get_attr_grp_repl_ipv6,
+ [ATTR_GRP_ORIG_PORT] = get_attr_grp_orig_port,
+ [ATTR_GRP_REPL_PORT] = get_attr_grp_repl_port,
+ [ATTR_GRP_ICMP] = get_attr_grp_icmp,
+ [ATTR_GRP_MASTER_IPV4] = get_attr_grp_master_ipv4,
+ [ATTR_GRP_MASTER_IPV6] = get_attr_grp_master_ipv6,
+ [ATTR_GRP_MASTER_PORT] = get_attr_grp_master_port,
+ [ATTR_GRP_ORIG_COUNTERS] = get_attr_grp_orig_ctrs,
+ [ATTR_GRP_REPL_COUNTERS] = get_attr_grp_repl_ctrs
+};
diff --git a/src/conntrack/grp_setter.c b/src/conntrack/grp_setter.c
new file mode 100644
index 0000000..16f0a10
--- /dev/null
+++ b/src/conntrack/grp_setter.c
@@ -0,0 +1,156 @@
+/*
+ * (C) 2008 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/internal.h"
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+
+static const u_int8_t invmap_icmp[] = {
+ [ICMP_ECHO] = ICMP_ECHOREPLY + 1,
+ [ICMP_ECHOREPLY] = ICMP_ECHO + 1,
+ [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1,
+ [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1,
+ [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1,
+ [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1,
+ [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1,
+ [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
+};
+
+#ifndef ICMPV6_NI_QUERY
+#define ICMPV6_NI_QUERY 139
+#endif
+
+#ifndef ICMPV6_NI_REPLY
+#define ICMPV6_NI_REPLY 140
+#endif
+
+static u_int8_t invmap_icmpv6[] = {
+ [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
+ [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
+ [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
+ [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1
+};
+
+static void set_attr_grp_orig_ipv4(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv4 *this = value;
+ ct->tuple[__DIR_ORIG].src.v4 = this->src;
+ ct->tuple[__DIR_ORIG].dst.v4 = this->dst;
+ ct->tuple[__DIR_ORIG].l3protonum = AF_INET;
+}
+
+static void set_attr_grp_repl_ipv4(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv4 *this = value;
+ ct->tuple[__DIR_REPL].src.v4 = this->src;
+ ct->tuple[__DIR_REPL].dst.v4 = this->dst;
+ ct->tuple[__DIR_REPL].l3protonum = AF_INET;
+}
+
+static void set_attr_grp_orig_ipv6(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv6 *this = value;
+ memcpy(&ct->tuple[__DIR_ORIG].src.v6, this->src, sizeof(u_int32_t)*4);
+ memcpy(&ct->tuple[__DIR_ORIG].dst.v6, this->dst, sizeof(u_int32_t)*4);
+ ct->tuple[__DIR_ORIG].l3protonum = AF_INET6;
+}
+
+static void set_attr_grp_repl_ipv6(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv6 *this = value;
+ memcpy(&ct->tuple[__DIR_REPL].src.v6, this->src, sizeof(u_int32_t)*4);
+ memcpy(&ct->tuple[__DIR_REPL].dst.v6, this->dst, sizeof(u_int32_t)*4);
+ ct->tuple[__DIR_REPL].l3protonum = AF_INET6;
+}
+
+static void set_attr_grp_orig_port(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_port *this = value;
+ ct->tuple[__DIR_ORIG].l4src.all = this->sport;
+ ct->tuple[__DIR_ORIG].l4dst.all = this->dport;
+}
+
+static void set_attr_grp_repl_port(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_port *this = value;
+ ct->tuple[__DIR_REPL].l4src.all = this->sport;
+ ct->tuple[__DIR_REPL].l4dst.all = this->dport;
+}
+
+static void set_attr_grp_icmp(struct nf_conntrack *ct, const void *value)
+{
+ u_int8_t rtype;
+ const struct nfct_attr_grp_icmp *this = value;
+
+ ct->tuple[__DIR_ORIG].l4dst.icmp.type = this->type;
+
+ switch(ct->tuple[__DIR_ORIG].l3protonum) {
+ case AF_INET:
+ rtype = invmap_icmp[this->type];
+ break;
+
+ case AF_INET6:
+ rtype = invmap_icmpv6[this->type - 128];
+ break;
+
+ default:
+ rtype = 0; /* not found */
+ }
+
+ if (rtype)
+ ct->tuple[__DIR_REPL].l4dst.icmp.type = rtype - 1;
+ else
+ ct->tuple[__DIR_REPL].l4dst.icmp.type = 255; /* -EINVAL */
+
+ ct->tuple[__DIR_ORIG].l4dst.icmp.code = this->code;
+ ct->tuple[__DIR_REPL].l4dst.icmp.code = this->code;
+
+ ct->tuple[__DIR_ORIG].l4src.icmp.id = this->id;
+ ct->tuple[__DIR_REPL].l4src.icmp.id = this->id;
+}
+
+static void set_attr_grp_master_ipv4(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv4 *this = value;
+ ct->tuple[__DIR_MASTER].src.v4 = this->src;
+ ct->tuple[__DIR_MASTER].dst.v4 = this->dst;
+ ct->tuple[__DIR_MASTER].l3protonum = AF_INET;
+}
+
+static void set_attr_grp_master_ipv6(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_ipv6 *this = value;
+ memcpy(&ct->tuple[__DIR_MASTER].src.v6, this->src, sizeof(u_int32_t)*4);
+ memcpy(&ct->tuple[__DIR_MASTER].dst.v6, this->dst, sizeof(u_int32_t)*4);
+ ct->tuple[__DIR_MASTER].l3protonum = AF_INET6;
+}
+
+static void set_attr_grp_master_port(struct nf_conntrack *ct, const void *value)
+{
+ const struct nfct_attr_grp_port *this = value;
+ ct->tuple[__DIR_MASTER].l4src.all = this->sport;
+ ct->tuple[__DIR_MASTER].l4dst.all = this->dport;
+}
+
+static void set_attr_grp_do_nothing(struct nf_conntrack *ct, const void *value)
+{
+}
+
+set_attr_grp set_attr_grp_array[] = {
+ [ATTR_GRP_ORIG_IPV4] = set_attr_grp_orig_ipv4,
+ [ATTR_GRP_REPL_IPV4] = set_attr_grp_repl_ipv4,
+ [ATTR_GRP_ORIG_IPV6] = set_attr_grp_orig_ipv6,
+ [ATTR_GRP_REPL_IPV6] = set_attr_grp_repl_ipv6,
+ [ATTR_GRP_ORIG_PORT] = set_attr_grp_orig_port,
+ [ATTR_GRP_REPL_PORT] = set_attr_grp_repl_port,
+ [ATTR_GRP_ICMP] = set_attr_grp_icmp,
+ [ATTR_GRP_MASTER_IPV4] = set_attr_grp_master_ipv4,
+ [ATTR_GRP_MASTER_IPV6] = set_attr_grp_master_ipv6,
+ [ATTR_GRP_MASTER_PORT] = set_attr_grp_master_port,
+ [ATTR_GRP_ORIG_COUNTERS] = set_attr_grp_do_nothing,
+ [ATTR_GRP_REPL_COUNTERS] = set_attr_grp_do_nothing,
+};