From e8f32983048d6aa4a908b6a92da55fa71c859623 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 29 Feb 2012 13:48:36 +0100 Subject: libxt_CT: add --timeout option This patch adds the --timeout option to allow to attach timeout policy objects to flows, eg. iptables -I PREROUTING -t raw -s 1.1.1.1 -p tcp \ -j CT --timeout custom-tcp-policy You need the nfct(8) tool which is available at: http://git.netfilter.org/cgi-bin/gitweb.cgi?p=nfct.git To define the cttimeout policies. Example of usage: nfct timeout add custom-tcp-policy inet tcp established 1000 The new nfct tool also requires libnetfilter_cttimeout: http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_cttimeout.git Signed-off-by: Pablo Neira Ayuso --- extensions/libxt_CT.c | 134 ++++++++++++++++++++++++++++++++++++---- extensions/libxt_CT.man | 5 ++ include/linux/netfilter/xt_CT.h | 12 ++++ 3 files changed, 139 insertions(+), 12 deletions(-) diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 7b93bfaf..27a20e2e 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -16,9 +16,23 @@ static void ct_help(void) ); } +static void ct_help_v1(void) +{ + printf( +"CT target options:\n" +" --notrack Don't track connection\n" +" --helper name Use conntrack helper 'name' for connection\n" +" --timeout name Use timeout policy 'name' for connection\n" +" --ctevents event[,event...] Generate specified conntrack events for connection\n" +" --expevents event[,event...] Generate specified expectation events for connection\n" +" --zone ID Assign/Lookup connection in zone ID\n" + ); +} + enum { O_NOTRACK = 0, O_HELPER, + O_TIMEOUT, O_CTEVENTS, O_EXPEVENTS, O_ZONE, @@ -37,6 +51,21 @@ static const struct xt_option_entry ct_opts[] = { }; #undef s +#define s struct xt_ct_target_info_v1 +static const struct xt_option_entry ct_opts_v1[] = { + {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE}, + {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)}, + {.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING, + .flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)}, + {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING}, + {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING}, + {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16, + .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)}, + XTOPT_TABLEEND, +}; +#undef s + struct event_tbl { const char *name; unsigned int event; @@ -114,6 +143,28 @@ static void ct_parse(struct xt_option_call *cb) } } +static void ct_parse_v1(struct xt_option_call *cb) +{ + struct xt_ct_target_info_v1 *info = cb->data; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_NOTRACK: + info->flags |= XT_CT_NOTRACK; + break; + case O_CTEVENTS: + info->ct_events = ct_parse_events(ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), + cb->arg); + break; + case O_EXPEVENTS: + info->exp_events = ct_parse_events(exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), + cb->arg); + break; + } +} + static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) { const struct xt_ct_target_info *info = @@ -134,6 +185,29 @@ static void ct_print(const void *ip, const struct xt_entry_target *target, int n printf("zone %u ", info->zone); } +static void +ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric) +{ + const struct xt_ct_target_info_v1 *info = + (const struct xt_ct_target_info_v1 *)target->data; + + printf(" CT"); + if (info->flags & XT_CT_NOTRACK) + printf(" notrack"); + if (info->helper[0]) + printf(" helper %s", info->helper); + if (info->timeout[0]) + printf(" timeout %s", info->timeout); + if (info->ct_events) + ct_print_events("ctevents", ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), info->ct_events); + if (info->exp_events) + ct_print_events("expevents", exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), info->exp_events); + if (info->zone) + printf("zone %u ", info->zone); +} + static void ct_save(const void *ip, const struct xt_entry_target *target) { const struct xt_ct_target_info *info = @@ -153,20 +227,56 @@ static void ct_save(const void *ip, const struct xt_entry_target *target) printf(" --zone %u", info->zone); } -static struct xtables_target ct_target = { - .family = NFPROTO_UNSPEC, - .name = "CT", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), - .userspacesize = offsetof(struct xt_ct_target_info, ct), - .help = ct_help, - .print = ct_print, - .save = ct_save, - .x6_parse = ct_parse, - .x6_options = ct_opts, +static void ct_save_v1(const void *ip, const struct xt_entry_target *target) +{ + const struct xt_ct_target_info_v1 *info = + (const struct xt_ct_target_info_v1 *)target->data; + + if (info->flags & XT_CT_NOTRACK) + printf(" --notrack"); + if (info->helper[0]) + printf(" --helper %s", info->helper); + if (info->timeout[0]) + printf(" --timeout %s", info->timeout); + if (info->ct_events) + ct_print_events("--ctevents", ct_event_tbl, + ARRAY_SIZE(ct_event_tbl), info->ct_events); + if (info->exp_events) + ct_print_events("--expevents", exp_event_tbl, + ARRAY_SIZE(exp_event_tbl), info->exp_events); + if (info->zone) + printf(" --zone %u", info->zone); +} + +static struct xtables_target ct_target_reg[] = { + { + .family = NFPROTO_UNSPEC, + .name = "CT", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), + .userspacesize = offsetof(struct xt_ct_target_info, ct), + .help = ct_help, + .print = ct_print, + .save = ct_save, + .x6_parse = ct_parse, + .x6_options = ct_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "CT", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .help = ct_help_v1, + .print = ct_print_v1, + .save = ct_save_v1, + .x6_parse = ct_parse_v1, + .x6_options = ct_opts_v1, + }, }; void _init(void) { - xtables_register_target(&ct_target); + xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg)); } diff --git a/extensions/libxt_CT.man b/extensions/libxt_CT.man index ff258b79..a93eb149 100644 --- a/extensions/libxt_CT.man +++ b/extensions/libxt_CT.man @@ -23,3 +23,8 @@ Possible event types are: \fBnew\fP. \fB\-\-zone\fP \fIid\fP Assign this packet to zone \fIid\fP and only have lookups done in that zone. By default, packets have zone 0. +.TP +\fB\-\-timeout\fP \fIname\fP +Use the timeout policy identified by \fIname\fP for the connection. This is +provides more flexible timeout policy definition than global timeout values +available at /proc/sys/net/netfilter/nf_conntrack_*_timeout_*. diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index b56e7681..a064b8af 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h @@ -16,4 +16,16 @@ struct xt_ct_target_info { struct nf_conn *ct __attribute__((aligned(8))); }; +struct xt_ct_target_info_v1 { + __u16 flags; + __u16 zone; + __u32 ct_events; + __u32 exp_events; + char helper[16]; + char timeout[32]; + + /* Used internally by the kernel */ + struct nf_conn *ct __attribute__((aligned(8))); +}; + #endif /* _XT_CT_H */ -- cgit v1.2.3