From 3cd88a6d9c66360dad983578259ab92ba083fca8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 Jul 2012 02:22:58 +0200 Subject: conntrackd: implement selective flushing for `-t' and `-F' commands This patch changes the current behaviour of `-t' and `-F' commands, that results in flushing the kernel conntrack table. With this patch, the entries that match the Filter clauses in conntrackd.conf are ignored. This fixes the situation in which some local ssh connection to the firewall is lost during the failover (since `-t' is invoked from the primary-backup.sh script). Note that the Filter clause tells what entries have to be ignored, ie. the entries that do not need to be replicated. It makes sense not to flush entries that are not replicated (usually traffic to the local firewall). Reported-by: Gaurav Sinha Signed-off-by: Pablo Neira Ayuso --- src/internal_bypass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/internal_bypass.c') diff --git a/src/internal_bypass.c b/src/internal_bypass.c index 5c83c21..1194339 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -67,7 +67,7 @@ static void internal_bypass_ct_dump(int fd, int type) static void internal_bypass_ct_flush(void) { - nl_flush_conntrack_table(STATE(flush)); + nl_flush_conntrack_table_selective(); } struct { -- cgit v1.2.3 From 586382d9a8389ee553db019fd9be14a8a7c0b8ec Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 11 Jul 2013 00:43:20 +0200 Subject: conntrackd: simplify expectation filtering This patch simplifies the expectation filtering by looking up for the master conntrack. If it does not exists, then we assume that we don't want this expectation either. This simplification also fixes the current broken expectation filtering, since the master conntrack from expectations has neither reply tuple nor state, however, the filtering code assumes the opposite. This partially reverts (479a37a conntrackd: fix crash with IPv6 expectation in the filtering code) since it was incorrectly setting the reply tuple of the master conntrack. Thanks to Bill Fink for providing feedback to resolve this issue. Signed-off-by: Pablo Neira Ayuso --- include/filter.h | 1 + include/internal.h | 1 + src/cache-ct.c | 11 +++++++++-- src/ctnl.c | 37 +++++++++---------------------------- src/filter.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/internal_bypass.c | 6 ++++++ src/internal_cache.c | 11 +++++++++++ 7 files changed, 82 insertions(+), 30 deletions(-) (limited to 'src/internal_bypass.c') diff --git a/include/filter.h b/include/filter.h index 3c7c8cc..d0acd96 100644 --- a/include/filter.h +++ b/include/filter.h @@ -51,6 +51,7 @@ void ct_filter_set_logic(struct ct_filter *f, enum ct_filter_type type, enum ct_filter_logic logic); int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace); +int ct_filter_master(const struct nf_conntrack *master); struct exp_filter; struct nf_expect; diff --git a/include/internal.h b/include/internal.h index 2ba9714..1a796a7 100644 --- a/include/internal.h +++ b/include/internal.h @@ -40,6 +40,7 @@ struct internal_handler { void (*new)(struct nf_expect *exp, int origin_type); void (*upd)(struct nf_expect *exp, int origin_type); int (*del)(struct nf_expect *exp, int origin_type); + int (*find)(const struct nf_conntrack *master); void (*dump)(int fd, int type); void (*populate)(struct nf_expect *exp); diff --git a/src/cache-ct.c b/src/cache-ct.c index a538215..f86d143 100644 --- a/src/cache-ct.c +++ b/src/cache-ct.c @@ -88,14 +88,21 @@ cache_ct_hash(const void *data, const struct hashtable *table) return ret; } +/* master conntrack of expectations have no ID */ +static inline int +cache_ct_cmp_id(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2) +{ + return nfct_attr_is_set(ct2, ATTR_ID) ? + nfct_get_attr_u32(ct1, ATTR_ID) == nfct_get_attr_u32(ct2, ATTR_ID) : 1; +} + static int cache_ct_cmp(const void *data1, const void *data2) { const struct cache_object *obj = data1; const struct nf_conntrack *ct = data2; return nfct_cmp(obj->ptr, ct, NFCT_CMP_ORIG) && - nfct_get_attr_u32(obj->ptr, ATTR_ID) == - nfct_get_attr_u32(ct, ATTR_ID); + cache_ct_cmp_id(obj->ptr, ct); } static void *cache_ct_alloc(void) diff --git a/src/ctnl.c b/src/ctnl.c index 9e1cfa1..10b5f4c 100644 --- a/src/ctnl.c +++ b/src/ctnl.c @@ -211,35 +211,14 @@ out: return NFCT_CB_CONTINUE; } -static const struct nf_conntrack *exp_get_master_ct(struct nf_expect *exp) -{ - struct nf_conntrack *master = - (struct nf_conntrack *)nfexp_get_attr(exp, ATTR_EXP_MASTER); - - /* The function ct_filter_conntrack needs the source address of the - * reply tuple, emulate it. - */ - switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) { - case AF_INET: - nfct_set_attr_u32(master, ATTR_REPL_IPV4_SRC, - nfct_get_attr_u32(master, ATTR_IPV4_DST)); - break; - case AF_INET6: - nfct_set_attr(master, ATTR_REPL_IPV6_SRC, - nfct_get_attr(master, ATTR_IPV6_DST)); - break; - } - - return master; -} - static int exp_event_handler(const struct nlmsghdr *nlh, enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data) { int origin_type; - const struct nf_conntrack *master = exp_get_master_ct(exp); + const struct nf_conntrack *master = + nfexp_get_attr(exp, ATTR_EXP_MASTER); STATE(stats).nl_events_received++; @@ -247,7 +226,7 @@ static int exp_event_handler(const struct nlmsghdr *nlh, STATE(stats).nl_events_filtered++; goto out; } - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; origin_type = origin_find(nlh); @@ -296,12 +275,13 @@ static int dump_handler(enum nf_conntrack_msg_type type, static int exp_dump_handler(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data) { - const struct nf_conntrack *master = exp_get_master_ct(exp); + const struct nf_conntrack *master = + nfexp_get_attr(exp, ATTR_EXP_MASTER); if (!exp_filter_find(STATE(exp_filter), exp)) return NFCT_CB_CONTINUE; - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; switch(type) { @@ -329,12 +309,13 @@ static int get_handler(enum nf_conntrack_msg_type type, static int exp_get_handler(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data) { - const struct nf_conntrack *master = exp_get_master_ct(exp); + const struct nf_conntrack *master = + nfexp_get_attr(exp, ATTR_EXP_MASTER); if (!exp_filter_find(STATE(exp_filter), exp)) return NFCT_CB_CONTINUE; - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; STATE(get_retval) = 1; diff --git a/src/filter.c b/src/filter.c index e21cfde..8fac71b 100644 --- a/src/filter.c +++ b/src/filter.c @@ -407,6 +407,51 @@ int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace) return 0; } +static inline int +ct_filter_master_sanity_check(const struct nf_conntrack *master) +{ + if (master == NULL) { + dlog(LOG_ERR, "no master tuple in expectation"); + return 0; + } + + if (!nfct_attr_is_set(master, ATTR_L3PROTO)) { + dlog(LOG_ERR, "missing layer 3 protocol"); + return 0; + } + + switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) { + case AF_INET: + if (!nfct_attr_is_set(master, ATTR_IPV4_SRC) || + !nfct_attr_is_set(master, ATTR_IPV4_DST)) { + dlog(LOG_ERR, "missing IPv4 address. " + "You forgot to load nf_conntrack_ipv4?"); + return 0; + } + break; + case AF_INET6: + if (!nfct_attr_is_set(master, ATTR_IPV6_SRC) || + !nfct_attr_is_set(master, ATTR_IPV6_DST)) { + dlog(LOG_ERR, "missing IPv6 address. " + "You forgot to load nf_conntrack_ipv6?"); + return 0; + } + break; + } + return 1; +} + +int ct_filter_master(const struct nf_conntrack *master) +{ + if (!ct_filter_master_sanity_check(master)) + return 1; + + /* Check if we've got a master conntrack for this expectation in our + * caches. If there is not, we don't want this expectation either. + */ + return STATE(mode)->internal->exp.find(master) ? 0 : 1; +} + struct exp_filter { struct list_head list; }; diff --git a/src/internal_bypass.c b/src/internal_bypass.c index 1194339..ce2ae46 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -283,6 +283,11 @@ static int internal_bypass_exp_event_del(struct nf_expect *exp, int origin) return 1; } +static int internal_bypass_exp_master_find(const struct nf_conntrack *master) +{ + return nl_get_conntrack(STATE(get), master) == 0; +} + struct internal_handler internal_bypass = { .init = internal_bypass_init, .close = internal_bypass_close, @@ -309,5 +314,6 @@ struct internal_handler internal_bypass = { .new = internal_bypass_exp_event_new, .upd = internal_bypass_exp_event_upd, .del = internal_bypass_exp_event_del, + .find = internal_bypass_exp_master_find, }, }; diff --git a/src/internal_cache.c b/src/internal_cache.c index ba2d74b..bad31f3 100644 --- a/src/internal_cache.c +++ b/src/internal_cache.c @@ -364,6 +364,16 @@ static int internal_cache_exp_event_del(struct nf_expect *exp, int origin) return 1; } +static int internal_cache_exp_master_find(const struct nf_conntrack *master) +{ + struct cache_object *obj; + int id; + + obj = cache_find(STATE(mode)->internal->ct.data, + (struct nf_conntrack *)master, &id); + return obj ? 1 : 0; +} + struct internal_handler internal_cache = { .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, .init = internal_cache_init, @@ -391,5 +401,6 @@ struct internal_handler internal_cache = { .new = internal_cache_exp_event_new, .upd = internal_cache_exp_event_upd, .del = internal_cache_exp_event_del, + .find = internal_cache_exp_master_find, }, }; -- cgit v1.2.3 From 1c637fe7ea8a70a77273366d24e221b0d3d64702 Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 11:38:53 +0200 Subject: src: Use stdint types Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- extensions/libct_proto_dccp.c | 2 +- extensions/libct_proto_gre.c | 2 +- extensions/libct_proto_icmp.c | 4 ++-- extensions/libct_proto_icmpv6.c | 4 ++-- extensions/libct_proto_sctp.c | 4 ++-- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- extensions/libct_proto_udplite.c | 2 +- include/bitops.h | 14 +++++++------- include/helper.h | 2 +- src/filter.c | 4 ++-- src/helpers/amanda.c | 4 ++-- src/helpers/ftp.c | 2 +- src/helpers/ssdp.c | 2 +- src/internal_bypass.c | 4 ++-- src/sync-notrack.c | 2 +- 16 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src/internal_bypass.c') diff --git a/extensions/libct_proto_dccp.c b/extensions/libct_proto_dccp.c index f37ef68..f6258ad 100644 --- a/extensions/libct_proto_dccp.c +++ b/extensions/libct_proto_dccp.c @@ -118,7 +118,7 @@ static int parse_options(char c, unsigned int *flags) { int i; - u_int16_t port; + uint16_t port; switch(c) { case 1: diff --git a/extensions/libct_proto_gre.c b/extensions/libct_proto_gre.c index 0274a37..2dc63d1 100644 --- a/extensions/libct_proto_gre.c +++ b/extensions/libct_proto_gre.c @@ -91,7 +91,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index d04397f..2ce1c65 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -72,8 +72,8 @@ static int parse(char c, unsigned int *flags) { switch(c) { - u_int8_t tmp; - u_int16_t id; + uint8_t tmp; + uint16_t id; case '1': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); diff --git a/extensions/libct_proto_icmpv6.c b/extensions/libct_proto_icmpv6.c index f8c2c68..18dd3e5 100644 --- a/extensions/libct_proto_icmpv6.c +++ b/extensions/libct_proto_icmpv6.c @@ -75,8 +75,8 @@ static int parse(char c, unsigned int *flags) { switch(c) { - u_int8_t tmp; - u_int16_t id; + uint8_t tmp; + uint16_t id; case '1': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index 97042c3..04828bf 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -120,8 +120,8 @@ parse_options(char c, struct nf_conntrack *ct, unsigned int *flags) { int i; - u_int16_t port; - u_int32_t vtag; + uint16_t port; + uint32_t vtag; switch(c) { case 1: diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 65acd5a..8a37a55 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -106,7 +106,7 @@ static int parse_options(char c, unsigned int *flags) { int i; - u_int16_t port; + uint16_t port; switch(c) { case '1': diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 768304b..e30637c 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -87,7 +87,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(atoi(optarg)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/extensions/libct_proto_udplite.c b/extensions/libct_proto_udplite.c index 9b67bef..f46cef0 100644 --- a/extensions/libct_proto_udplite.c +++ b/extensions/libct_proto_udplite.c @@ -95,7 +95,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(atoi(optarg)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/include/bitops.h b/include/bitops.h index 51f4289..27fe58d 100644 --- a/include/bitops.h +++ b/include/bitops.h @@ -1,34 +1,34 @@ #ifndef _BITOPS_H_ #define _BITOPS_H_ -#include +#include -static inline void set_bit_u32(int nr, u_int32_t *addr) +static inline void set_bit_u32(int nr, uint32_t *addr) { addr[nr >> 5] |= (1UL << (nr & 31)); } -static inline void unset_bit_u32(int nr, u_int32_t *addr) +static inline void unset_bit_u32(int nr, uint32_t *addr) { addr[nr >> 5] &= ~(1UL << (nr & 31)); } -static inline int test_bit_u32(int nr, const u_int32_t *addr) +static inline int test_bit_u32(int nr, const uint32_t *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; } -static inline void set_bit_u16(int nr, u_int16_t *addr) +static inline void set_bit_u16(int nr, uint16_t *addr) { addr[nr >> 4] |= (1UL << (nr & 15)); } -static inline void unset_bit_u16(int nr, u_int16_t *addr) +static inline void unset_bit_u16(int nr, uint16_t *addr) { addr[nr >> 4] &= ~(1UL << (nr & 15)); } -static inline int test_bit_u16(int nr, const u_int16_t *addr) +static inline int test_bit_u16(int nr, const uint16_t *addr) { return ((1UL << (nr & 15)) & (addr[nr >> 4])) != 0; } diff --git a/include/helper.h b/include/helper.h index bd69af6..f412e55 100644 --- a/include/helper.h +++ b/include/helper.h @@ -25,7 +25,7 @@ struct ctd_helper { int (*cb)(struct pkt_buff *pkt, uint32_t protoff, struct myct *ct, - u_int32_t ctinfo); + uint32_t ctinfo); struct ctd_helper_policy policy[CTD_HELPER_POLICY_MAX]; diff --git a/src/filter.c b/src/filter.c index 8fac71b..1ae2cc5 100644 --- a/src/filter.c +++ b/src/filter.c @@ -33,8 +33,8 @@ struct ct_filter { int logic[CT_FILTER_MAX]; - u_int32_t l4protomap[IPPROTO_MAX/32]; - u_int16_t statemap[IPPROTO_MAX]; + uint32_t l4protomap[IPPROTO_MAX/32]; + uint16_t statemap[IPPROTO_MAX]; struct hashtable *h; struct hashtable *h6; struct vector *v; diff --git a/src/helpers/amanda.c b/src/helpers/amanda.c index c0cf701..9e6c4e7 100644 --- a/src/helpers/amanda.c +++ b/src/helpers/amanda.c @@ -34,7 +34,7 @@ static int nat_amanda(struct pkt_buff *pkt, uint32_t ctinfo, struct nf_expect *exp) { char buffer[sizeof("65535")]; - u_int16_t port, initial_port; + uint16_t port, initial_port; unsigned int ret; const struct nf_conntrack *expected; struct nf_conntrack *nat_tuple; @@ -111,7 +111,7 @@ amanda_helper_cb(struct pkt_buff *pkt, uint32_t protoff, struct nf_expect *exp; char *data, *data_limit, *tmp; unsigned int dataoff, i; - u_int16_t port, len; + uint16_t port, len; int ret = NF_ACCEPT; struct iphdr *iph; union nfct_attr_grp_addr saddr, daddr; diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c index 2c8dcd6..e7fe7f7 100644 --- a/src/helpers/ftp.c +++ b/src/helpers/ftp.c @@ -58,7 +58,7 @@ enum nf_ct_ftp_type { }; static int -get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term) +get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, uint8_t term) { const char *end; int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), diff --git a/src/helpers/ssdp.c b/src/helpers/ssdp.c index 2713f23..bc41087 100644 --- a/src/helpers/ssdp.c +++ b/src/helpers/ssdp.c @@ -44,7 +44,7 @@ static int ssdp_helper_cb(struct pkt_buff *pkt, uint32_t protoff, struct iphdr *net_hdr = (struct iphdr *)pktb_network_header(pkt); int good_packet = 0; struct nf_expect *exp; - u_int16_t port; + uint16_t port; unsigned int dataoff; void *sb_ptr; diff --git a/src/internal_bypass.c b/src/internal_bypass.c index ce2ae46..61988c7 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -49,7 +49,7 @@ internal_bypass_ct_dump_cb(enum nf_conntrack_msg_type type, static void internal_bypass_ct_dump(int fd, int type) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); @@ -180,7 +180,7 @@ internal_bypass_exp_dump_cb(enum nf_conntrack_msg_type type, static void internal_bypass_exp_dump(int fd, int type) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); diff --git a/src/sync-notrack.c b/src/sync-notrack.c index a7df4e7..c810bbb 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -99,7 +99,7 @@ static int kernel_resync_cb(enum nf_conntrack_msg_type type, static void kernel_resync(void) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); -- cgit v1.2.3