diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-10-30 20:44:25 +0100 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2008-10-30 20:44:25 +0100 |
commit | 7dd5289076160ee2844978bfd1640ca7aa34f4da (patch) | |
tree | a91a1c1dcea8238bf01f933352f41526f6581ba0 | |
parent | 215d42fef86577ad74151cda553a20b1bdb58a30 (diff) |
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 <pablo@netfilter.org>
-rw-r--r-- | include/internal/bitops.h | 31 | ||||
-rw-r--r-- | include/internal/extern.h | 4 | ||||
-rw-r--r-- | include/internal/object.h | 3 | ||||
-rw-r--r-- | include/internal/types.h | 2 | ||||
-rw-r--r-- | include/libnetfilter_conntrack/libnetfilter_conntrack.h | 56 | ||||
-rw-r--r-- | src/conntrack/Makefile.am | 3 | ||||
-rw-r--r-- | src/conntrack/api.c | 93 | ||||
-rw-r--r-- | src/conntrack/grp.c | 69 | ||||
-rw-r--r-- | src/conntrack/grp_getter.c | 108 | ||||
-rw-r--r-- | src/conntrack/grp_setter.c | 156 | ||||
-rw-r--r-- | utils/Makefile.am | 7 | ||||
-rw-r--r-- | utils/conntrack_grp_create.c | 53 |
12 files changed, 582 insertions, 3 deletions
diff --git a/include/internal/bitops.h b/include/internal/bitops.h index b1bd848..0c1fde8 100644 --- a/include/internal/bitops.h +++ b/include/internal/bitops.h @@ -24,9 +24,40 @@ static inline void unset_bit_u16(int nr, u_int16_t *addr) addr[nr >> 4] &= ~(1UL << (nr & 15)); } +static inline void +set_bitmask_u32(u_int32_t *buf1, const u_int32_t *buf2, int len) +{ + int i; + + for (i=0; i<len; i++) + buf1[i] |= buf2[i]; +} + +static inline void +unset_bitmask_u32(u_int32_t *buf1, const u_int32_t *buf2, int len) +{ + int i; + + for (i=0; i<len; i++) + buf1[i] &= ~buf2[i]; +} + static inline int test_bit(int nr, const u_int32_t *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; } +static inline int +test_bitmask_u32(const uint32_t *buf1, const uint32_t *buf2, int len) +{ + int i; + + for (i=0; i<len; i++) { + if ((buf1[i] & buf2[i]) != buf2[i]) { + return 0; + } + } + return 1; +} + #endif diff --git a/include/internal/extern.h b/include/internal/extern.h index a43cde7..d0b079f 100644 --- a/include/internal/extern.h +++ b/include/internal/extern.h @@ -5,8 +5,12 @@ extern set_attr set_attr_array[]; extern get_attr get_attr_array[]; extern copy_attr copy_attr_array[]; extern filter_attr filter_attr_array[]; +extern set_attr_grp set_attr_grp_array[]; +extern get_attr_grp get_attr_grp_array[]; extern set_exp_attr set_exp_attr_array[]; extern get_exp_attr get_exp_attr_array[]; +extern uint32_t attr_grp_bitmask[ATTR_GRP_MAX][__NFCT_BITSET]; + #endif diff --git a/include/internal/object.h b/include/internal/object.h index f68d340..8213f4a 100644 --- a/include/internal/object.h +++ b/include/internal/object.h @@ -146,7 +146,8 @@ struct nf_conntrack { struct __nfct_nat snat; struct __nfct_nat dnat; - u_int32_t set[2]; +#define __NFCT_BITSET 2 + u_int32_t set[__NFCT_BITSET]; }; /* diff --git a/include/internal/types.h b/include/internal/types.h index 790bf7a..433de5b 100644 --- a/include/internal/types.h +++ b/include/internal/types.h @@ -13,6 +13,8 @@ typedef void (*copy_attr)(struct nf_conntrack *d, const struct nf_conntrack *o); typedef void (*filter_attr)(struct nfct_filter *filter, const void *value); typedef int (*getobjopt)(const struct nf_conntrack *ct); typedef void (*setobjopt)(struct nf_conntrack *ct); +typedef void (*set_attr_grp)(struct nf_conntrack *ct, const void *value); +typedef void (*get_attr_grp)(const struct nf_conntrack *ct, void *data); /* * expectation types diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index e66f0f8..2fde9a8 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -124,6 +124,45 @@ enum nf_conntrack_attr { ATTR_MAX }; +/* conntrack attribute groups */ +enum nf_conntrack_attr_grp { + ATTR_GRP_ORIG_IPV4 = 0, /* struct nfct_attr_grp_ipv4 */ + ATTR_GRP_REPL_IPV4, /* struct nfct_attr_grp_ipv4 */ + ATTR_GRP_ORIG_IPV6, /* struct nfct_attr_grp_ipv6 */ + ATTR_GRP_REPL_IPV6, /* struct nfct_attr_grp_ipv6 */ + ATTR_GRP_ORIG_PORT = 4, /* struct nfct_attr_grp_port */ + ATTR_GRP_REPL_PORT, /* struct nfct_attr_grp_port */ + ATTR_GRP_ICMP, /* struct nfct_attr_grp_icmp */ + ATTR_GRP_MASTER_IPV4, /* struct nfct_attr_grp_ipv4 */ + ATTR_GRP_MASTER_IPV6 = 8, /* struct nfct_attr_grp_ipv6 */ + ATTR_GRP_MASTER_PORT, /* struct nfct_attr_grp_port */ + ATTR_GRP_ORIG_COUNTERS, /* struct nfct_attr_grp_ctrs */ + ATTR_GRP_REPL_COUNTERS, /* struct nfct_attr_grp_ctrs */ + ATTR_GRP_MAX +}; + +struct nfct_attr_grp_ipv4 { + u_int32_t src, dst; +}; + +struct nfct_attr_grp_ipv6 { + u_int32_t src[4], dst[4]; +}; + +struct nfct_attr_grp_port { + u_int16_t sport, dport; +}; + +struct nfct_attr_grp_icmp { + u_int16_t id; + u_int8_t code, type; +}; + +struct nfct_attr_grp_ctrs { + u_int64_t packets; + u_int64_t bytes; +}; + /* message type */ enum nf_conntrack_msg_type { NFCT_T_UNKNOWN = 0, @@ -238,6 +277,23 @@ extern int nfct_attr_is_set(const struct nf_conntrack *ct, extern int nfct_attr_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr type); +/* group setter */ +extern void nfct_set_attr_grp(struct nf_conntrack *ct, + const enum nf_conntrack_attr_grp type, + const void *value); +/* group getter */ +extern int nfct_get_attr_grp(const struct nf_conntrack *ct, + const enum nf_conntrack_attr_grp type, + void *data); + +/* group checker */ +extern int nfct_attr_grp_is_set(const struct nf_conntrack *ct, + const enum nf_conntrack_attr_grp type); + +/* unsetter */ +extern int nfct_attr_grp_unset(struct nf_conntrack *ct, + const enum nf_conntrack_attr_grp type); + /* print */ /* output type */ 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, +}; diff --git a/utils/Makefile.am b/utils/Makefile.am index b0797ae..26cbdc4 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -5,7 +5,12 @@ check_PROGRAMS = expect_dump expect_create expect_get expect_delete \ conntrack_create conntrack_dump conntrack_update \ conntrack_delete conntrack_flush conntrack_create_nat \ conntrack_get conntrack_events \ - conntrack_master conntrack_filter + conntrack_master conntrack_filter \ + conntrack_grp_create + +conntrack_grp_create_SOURCES = conntrack_grp_create.c +conntrack_grp_create_LDADD = ../src/libnetfilter_conntrack.la +conntrack_grp_create_LDFLAGS = -dynamic -ldl conntrack_create_SOURCES = conntrack_create.c conntrack_create_LDADD = ../src/libnetfilter_conntrack.la diff --git a/utils/conntrack_grp_create.c b/utils/conntrack_grp_create.c new file mode 100644 index 0000000..a0bb0d7 --- /dev/null +++ b/utils/conntrack_grp_create.c @@ -0,0 +1,53 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +#include <libnetfilter_conntrack/libnetfilter_conntrack.h> +#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h> + +int main() +{ + int ret; + struct nfct_handle *h; + struct nf_conntrack *ct; + + ct = nfct_new(); + if (!ct) { + perror("nfct_new"); + return 0; + } + + struct nfct_attr_grp_ipv4 grp_ipv4 = { + .src = inet_addr("1.1.1.1"), + .dst = inet_addr("2.2.2.2") + }; + nfct_set_attr_grp(ct, ATTR_GRP_ORIG_IPV4, &grp_ipv4); + + struct nfct_attr_grp_port grp_port = { + .sport = htons(20), + .dport = htons(10) + }; + nfct_set_attr_grp(ct, ATTR_GRP_ORIG_PORT, &grp_port); + nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); + + nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY); + + nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN); + nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100); + nfct_set_attr(ct, ATTR_HELPER_NAME, "ftp"); + + h = nfct_open(CONNTRACK, 0); + if (!h) { + perror("nfct_open"); + return -1; + } + + ret = nfct_query(h, NFCT_Q_CREATE, ct); + + printf("TEST: create conntrack (%d)(%s)\n", ret, strerror(errno)); + + if (ret == -1) + exit(EXIT_FAILURE); + + nfct_close(h); +} |