From ea0469ea8f507eed0496c2cedbe1c5894169dd1c Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Wed, 14 May 2008 17:40:59 +0000 Subject: improve nfct_copy --- src/conntrack/api.c | 94 +++++++++-- src/conntrack/copy.c | 429 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 474 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/conntrack/api.c b/src/conntrack/api.c index 4d5abb7..45b03c0 100644 --- a/src/conntrack/api.c +++ b/src/conntrack/api.c @@ -737,21 +737,97 @@ int nfct_cmp(const struct nf_conntrack *ct1, * 1) You have to pass an already allocated space for the target object * 2) You can copy only a part of the source object to the target * - * The current supported flags are NFCT_CP_ORIG and NFCT_CP_REPL that - * can be used to copy the information that identifies a flow in the - * original and the reply direction. This information is usually composed - * of: source and destination IP address; source and destination ports; - * layer 3 and 4 protocol number. + * The current supported flags are: + * - NFCT_CP_ALL that copies the object entirely. + * - NFCT_CP_ORIG and NFCT_CP_REPL that can be used to copy the + * information that identifies a flow in the original and the reply + * direction. This information is usually composed of: source and + * destination IP address; source and destination ports; layer 3 + * and 4 protocol number. + * - NFCT_CP_META that copies the metainformation + * (all the attributes >= ATTR_TCP_STATE) */ void nfct_copy(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags) { + int i; + assert(ct1 != NULL); assert(ct2 != NULL); - if (flags & NFCT_CP_ORIG) - __copy_tuple(ct1, ct2, __DIR_ORIG); - if (flags & NFCT_CP_REPL) - __copy_tuple(ct1, ct2, __DIR_REPL); + if (flags == NFCT_CP_ALL) { + for (i=0; iset)) { + copy_attr_array[i](ct1, ct2); + set_bit(i, ct1->set); + } + } + return; + } + + static int cp_orig_mask[] = { + ATTR_ORIG_IPV6_SRC, /* this also copies IPv4 */ + ATTR_ORIG_IPV6_DST, + ATTR_ORIG_PORT_SRC, /* this also copies ICMP */ + ATTR_ORIG_PORT_DST, + ATTR_ORIG_L3PROTO, + ATTR_ORIG_L4PROTO, + }; + #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int) + + if (flags & NFCT_CP_ORIG) { + for (i=0; i<__CP_ORIG_MAX; i++) { + if (test_bit(i, ct2->set)) { + copy_attr_array[cp_orig_mask[i]](ct1, ct2); + set_bit(i, ct1->set); + } + } + } + + static int cp_repl_mask[] = { + ATTR_REPL_IPV6_SRC, /* this also copies IPv4 */ + ATTR_REPL_IPV6_DST, + ATTR_REPL_PORT_SRC, /* this also copies ICMP */ + ATTR_REPL_PORT_DST, + ATTR_REPL_L3PROTO, + ATTR_REPL_L4PROTO, + }; + #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int) + + if (flags & NFCT_CP_REPL) { + for (i=0; i<__CP_REPL_MAX; i++) { + if (test_bit(i, ct2->set)) { + copy_attr_array[cp_repl_mask[i]](ct1, ct2); + set_bit(i, ct1->set); + } + } + } + + if (flags & NFCT_CP_META) { + for (i=ATTR_TCP_STATE; iset)) { + copy_attr_array[i](ct1, ct2); + set_bit(i, ct1->set); + } + } + } +} + +/** + * nfct_copy_attr - copy an attribute of one source object to another + * @ct1: destination object + * @ct2: source object + * @flags: flags + * + * This function copies one attribute (if present) to another object. + */ +void nfct_copy_attr(struct nf_conntrack *ct1, + const struct nf_conntrack *ct2, + const enum nf_conntrack_attr type) +{ + if (test_bit(type, ct2->set)) { + copy_attr_array[type](ct1, ct2); + set_bit(type, ct1->set); + } } diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c index e03abc8..142f868 100644 --- a/src/conntrack/copy.c +++ b/src/conntrack/copy.c @@ -7,51 +7,400 @@ #include "internal.h" -#define TS_ORIG \ -({ \ - ((1 << ATTR_ORIG_IPV4_SRC) | (1 << ATTR_ORIG_IPV4_DST) | \ - (1 << ATTR_ORIG_IPV6_SRC) | (1 << ATTR_ORIG_IPV6_DST) | \ - (1 << ATTR_ORIG_PORT_SRC) | (1 << ATTR_ORIG_PORT_DST) | \ - (1 << ATTR_ORIG_L3PROTO) | (1 << ATTR_ORIG_L4PROTO) | \ - (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ - (1 << ATTR_ICMP_ID)); \ -}) - -#define TS_REPL \ -({ \ - ((1 << ATTR_REPL_IPV4_SRC) | (1 << ATTR_REPL_IPV4_DST) | \ - (1 << ATTR_REPL_IPV6_SRC) | (1 << ATTR_REPL_IPV6_DST) | \ - (1 << ATTR_REPL_PORT_SRC) | (1 << ATTR_REPL_PORT_DST) | \ - (1 << ATTR_REPL_L3PROTO) | (1 << ATTR_REPL_L4PROTO) | \ - (1 << ATTR_ICMP_TYPE) | (1 << ATTR_ICMP_CODE) | \ - (1 << ATTR_ICMP_ID)); \ -}) - -#define TUPLE_SET(dir) (dir == __DIR_ORIG ? TS_ORIG : TS_REPL) - -void __copy_tuple(struct nf_conntrack *ct2, - const struct nf_conntrack *ct1, - int dir) -{ - memcpy(&ct2->tuple[dir].src, - &ct1->tuple[dir].src, +static void copy_attr_orig_ipv4_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].src.v4 = orig->tuple[__DIR_ORIG].src.v4; +} + +static void copy_attr_orig_ipv4_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].dst.v4 = orig->tuple[__DIR_ORIG].dst.v4; +} + +static void copy_attr_repl_ipv4_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].src.v4 = orig->tuple[__DIR_REPL].src.v4; +} + +static void copy_attr_repl_ipv4_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].dst.v4 = orig->tuple[__DIR_REPL].dst.v4; +} + +static void copy_attr_orig_ipv6_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_ORIG].src, + &orig->tuple[__DIR_ORIG].src, + sizeof(union __nfct_address)); +} + +static void copy_attr_orig_ipv6_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_ORIG].dst, + &orig->tuple[__DIR_ORIG].dst, + sizeof(union __nfct_address)); +} + +static void copy_attr_repl_ipv6_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_REPL].src, + &orig->tuple[__DIR_REPL].src, + sizeof(union __nfct_address)); +} + +static void copy_attr_repl_ipv6_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_REPL].dst, + &orig->tuple[__DIR_REPL].dst, + sizeof(union __nfct_address)); +} + +static void copy_attr_orig_port_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l4src.all = orig->tuple[__DIR_ORIG].l4src.all; +} + +static void copy_attr_orig_port_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l4dst.all = orig->tuple[__DIR_ORIG].l4dst.all; +} + +static void copy_attr_repl_port_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].l4src.all = orig->tuple[__DIR_REPL].l4src.all; +} + +static void copy_attr_repl_port_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].l4dst.all = orig->tuple[__DIR_REPL].l4dst.all; +} + +static void copy_attr_icmp_type(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l4dst.icmp.type = + orig->tuple[__DIR_ORIG].l4dst.icmp.type; + +} + +static void copy_attr_icmp_code(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l4dst.icmp.code = + orig->tuple[__DIR_ORIG].l4dst.icmp.code; + +} + +static void copy_attr_icmp_id(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l4src.icmp.id = + orig->tuple[__DIR_ORIG].l4src.icmp.id; +} + +static void copy_attr_orig_l3proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].l3protonum = orig->tuple[__DIR_ORIG].l3protonum; +} + +static void copy_attr_repl_l3proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].l3protonum = orig->tuple[__DIR_REPL].l3protonum; +} + +static void copy_attr_orig_l4proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].protonum = orig->tuple[__DIR_ORIG].protonum; +} + +static void copy_attr_repl_l4proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].protonum = orig->tuple[__DIR_REPL].protonum; +} + +static void copy_attr_master_ipv4_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].src.v4 = orig->tuple[__DIR_MASTER].src.v4; +} + +static void copy_attr_master_ipv4_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].dst.v4 = orig->tuple[__DIR_MASTER].dst.v4; +} + +static void copy_attr_master_ipv6_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_MASTER].src, + &orig->tuple[__DIR_MASTER].src, sizeof(union __nfct_address)); +} - memcpy(&ct2->tuple[dir].dst, - &ct1->tuple[dir].dst, +static void copy_attr_master_ipv6_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + memcpy(&dest->tuple[__DIR_MASTER].dst, + &orig->tuple[__DIR_MASTER].dst, sizeof(union __nfct_address)); +} + +static void copy_attr_master_port_src(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].l4src.all = + orig->tuple[__DIR_MASTER].l4src.all; +} + +static void copy_attr_master_port_dst(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].l4dst.all = + orig->tuple[__DIR_MASTER].l4dst.all; +} + +static void copy_attr_master_l3proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].l3protonum = + orig->tuple[__DIR_MASTER].l3protonum; +} + +static void copy_attr_master_l4proto(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_MASTER].protonum = + orig->tuple[__DIR_MASTER].protonum; +} + +static void copy_attr_tcp_state(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.tcp.state = orig->protoinfo.tcp.state; +} + +static void copy_attr_tcp_flags_orig(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.tcp.flags[__DIR_ORIG].value = + orig->protoinfo.tcp.flags[__DIR_ORIG].value; +} + +static void copy_attr_tcp_flags_repl(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.tcp.flags[__DIR_REPL].value = + orig->protoinfo.tcp.flags[__DIR_REPL].value; +} + +static void copy_attr_tcp_mask_orig(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.tcp.flags[__DIR_ORIG].mask = + orig->protoinfo.tcp.flags[__DIR_ORIG].mask; +} + +static void copy_attr_tcp_mask_repl(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.tcp.flags[__DIR_REPL].mask = + orig->protoinfo.tcp.flags[__DIR_REPL].mask; +} + +static void copy_attr_snat_ipv4(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->snat.min_ip = orig->snat.min_ip; +} + +static void copy_attr_dnat_ipv4(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->dnat.min_ip = orig->dnat.min_ip; +} + +static void copy_attr_snat_port(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->snat.l4min.all = orig->snat.l4min.all; +} + +static void copy_attr_dnat_port(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->dnat.l4min.all = orig->dnat.l4min.all; +} + +static void copy_attr_timeout(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->timeout = orig->timeout; +} + +static void copy_attr_mark(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->mark = orig->mark; +} + +static void copy_attr_secmark(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->secmark = orig->secmark; +} + +static void copy_attr_orig_counter_packets(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->counters[__DIR_ORIG].packets = orig->counters[__DIR_ORIG].packets; +} + +static void copy_attr_repl_counter_packets(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->counters[__DIR_REPL].packets = orig->counters[__DIR_REPL].packets; +} - ct2->tuple[dir].l3protonum = ct1->tuple[dir].l3protonum; - ct2->tuple[dir].protonum = ct1->tuple[dir].protonum; +static void copy_attr_orig_counter_bytes(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->counters[__DIR_ORIG].bytes = orig->counters[__DIR_ORIG].bytes; +} + +static void copy_attr_repl_counter_bytes(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->counters[__DIR_REPL].bytes = orig->counters[__DIR_REPL].bytes; +} - memcpy(&ct2->tuple[dir].l4src, - &ct1->tuple[dir].l4src, - sizeof(union __nfct_l4)); +static void copy_attr_status(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->status = orig->status; +} - memcpy(&ct2->tuple[dir].l4dst, - &ct1->tuple[dir].l4dst, - sizeof(union __nfct_l4)); +static void copy_attr_use(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->use = orig->use; +} - /* XXX: this is safe but better convert bitset to uint64_t */ - ct2->set[0] |= ct1->set[0] & TUPLE_SET(__DIR_ORIG); +static void copy_attr_id(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->id = orig->id; } + +static void copy_attr_orig_cor_pos(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].natseq.correction_pos = + orig->tuple[__DIR_ORIG].natseq.correction_pos; +} + +static void copy_attr_orig_off_bfr(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].natseq.offset_before = + orig->tuple[__DIR_ORIG].natseq.offset_before; +} + +static void copy_attr_orig_off_aft(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_ORIG].natseq.offset_after = + orig->tuple[__DIR_ORIG].natseq.offset_after; +} + +static void copy_attr_repl_cor_pos(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].natseq.correction_pos = + orig->tuple[__DIR_REPL].natseq.correction_pos; +} + +static void copy_attr_repl_off_bfr(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].natseq.offset_before = + orig->tuple[__DIR_REPL].natseq.offset_before; +} + +static void copy_attr_repl_off_aft(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->tuple[__DIR_REPL].natseq.offset_after = + orig->tuple[__DIR_REPL].natseq.offset_after; +} + +copy_attr copy_attr_array[] = { + [ATTR_ORIG_IPV4_SRC] = copy_attr_orig_ipv4_src, + [ATTR_ORIG_IPV4_DST] = copy_attr_orig_ipv4_dst, + [ATTR_REPL_IPV4_SRC] = copy_attr_repl_ipv4_src, + [ATTR_REPL_IPV4_DST] = copy_attr_repl_ipv4_dst, + [ATTR_ORIG_IPV6_SRC] = copy_attr_orig_ipv6_src, + [ATTR_ORIG_IPV6_DST] = copy_attr_orig_ipv6_dst, + [ATTR_REPL_IPV6_SRC] = copy_attr_repl_ipv6_src, + [ATTR_REPL_IPV6_DST] = copy_attr_repl_ipv6_dst, + [ATTR_ORIG_PORT_SRC] = copy_attr_orig_port_src, + [ATTR_ORIG_PORT_DST] = copy_attr_orig_port_dst, + [ATTR_REPL_PORT_SRC] = copy_attr_repl_port_src, + [ATTR_REPL_PORT_DST] = copy_attr_repl_port_dst, + [ATTR_ICMP_TYPE] = copy_attr_icmp_type, + [ATTR_ICMP_CODE] = copy_attr_icmp_code, + [ATTR_ICMP_ID] = copy_attr_icmp_id, + [ATTR_ORIG_L3PROTO] = copy_attr_orig_l3proto, + [ATTR_REPL_L3PROTO] = copy_attr_repl_l3proto, + [ATTR_ORIG_L4PROTO] = copy_attr_orig_l4proto, + [ATTR_REPL_L4PROTO] = copy_attr_repl_l4proto, + [ATTR_TCP_STATE] = copy_attr_tcp_state, + [ATTR_SNAT_IPV4] = copy_attr_snat_ipv4, + [ATTR_DNAT_IPV4] = copy_attr_dnat_ipv4, + [ATTR_SNAT_PORT] = copy_attr_snat_port, + [ATTR_DNAT_PORT] = copy_attr_dnat_port, + [ATTR_TIMEOUT] = copy_attr_timeout, + [ATTR_MARK] = copy_attr_mark, + [ATTR_ORIG_COUNTER_PACKETS] = copy_attr_orig_counter_packets, + [ATTR_ORIG_COUNTER_BYTES] = copy_attr_orig_counter_bytes, + [ATTR_REPL_COUNTER_PACKETS] = copy_attr_repl_counter_packets, + [ATTR_REPL_COUNTER_BYTES] = copy_attr_repl_counter_bytes, + [ATTR_USE] = copy_attr_use, + [ATTR_ID] = copy_attr_id, + [ATTR_STATUS] = copy_attr_status, + [ATTR_TCP_FLAGS_ORIG] = copy_attr_tcp_flags_orig, + [ATTR_TCP_FLAGS_REPL] = copy_attr_tcp_flags_repl, + [ATTR_TCP_MASK_ORIG] = copy_attr_tcp_mask_orig, + [ATTR_TCP_MASK_REPL] = copy_attr_tcp_mask_repl, + [ATTR_MASTER_IPV4_SRC] = copy_attr_master_ipv4_src, + [ATTR_MASTER_IPV4_DST] = copy_attr_master_ipv4_dst, + [ATTR_MASTER_IPV6_SRC] = copy_attr_master_ipv6_src, + [ATTR_MASTER_IPV6_DST] = copy_attr_master_ipv6_dst, + [ATTR_MASTER_PORT_SRC] = copy_attr_master_port_src, + [ATTR_MASTER_PORT_DST] = copy_attr_master_port_dst, + [ATTR_MASTER_L3PROTO] = copy_attr_master_l3proto, + [ATTR_MASTER_L4PROTO] = copy_attr_master_l4proto, + [ATTR_SECMARK] = copy_attr_secmark, + [ATTR_ORIG_NAT_SEQ_CORRECTION_POS] = copy_attr_orig_cor_pos, + [ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE] = copy_attr_orig_off_bfr, + [ATTR_ORIG_NAT_SEQ_OFFSET_AFTER] = copy_attr_orig_off_aft, + [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = copy_attr_repl_cor_pos, + [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = copy_attr_repl_off_bfr, + [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = copy_attr_repl_off_aft, +}; -- cgit v1.2.3