From 7dd5289076160ee2844978bfd1640ca7aa34f4da Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 30 Oct 2008 20:44:25 +0100 Subject: groups: add attribute group API This new API allows you to set and get some logical set of attributes. This is not intended to replace the existing per-attribute get/set API but to provide more efficient way to get/set certain attributes. This change includes an example file (conntrack_grp_create.c) of the use of the attribute group API. See ATTR_GRP_* for more information on the existing groups. Signed-off-by: Pablo Neira Ayuso --- src/conntrack/Makefile.am | 3 +- src/conntrack/api.c | 93 +++++++++++++++++++++++++++ src/conntrack/grp.c | 69 ++++++++++++++++++++ src/conntrack/grp_getter.c | 108 +++++++++++++++++++++++++++++++ src/conntrack/grp_setter.c | 156 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 src/conntrack/grp.c create mode 100644 src/conntrack/grp_getter.c create mode 100644 src/conntrack/grp_setter.c (limited to 'src/conntrack') 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 @@ -384,6 +384,99 @@ int nfct_attr_unset(struct nf_conntrack *ct, return 0; } +/** + * 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 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 + * + * 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 + * + * 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 + * + * 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 +#include + +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, +}; -- cgit v1.2.3