Signed-off-by: Eric Leblond --- include/linux/netfilter/nfnetlink_conntrack.h | 3 ++ include/linux/netfilter_ipv4/ip_conntrack.h | 6 ++++ net/ipv4/netfilter/Kconfig | 12 +++++++++ net/ipv4/netfilter/ip_conntrack_core.c | 29 ++++++++++++++++----- net/ipv4/netfilter/ip_conntrack_netlink.c | 35 ++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 8 deletions(-) e55274cbfe9a0ae13e1c78da1308eb25cbe04517 diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index 668ec94..fefc11f 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h @@ -29,6 +29,9 @@ enum ctattr_type { CTA_HELP, CTA_NAT, CTA_TIMEOUT, +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + CTA_FIXED_TIMEOUT, +#endif CTA_MARK, CTA_COUNTERS_ORIG, CTA_COUNTERS_REPLY, diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index 215765f..9e2ad88 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h @@ -82,7 +82,11 @@ struct ip_conntrack /* Timer function; drops refcnt when it goes off. */ struct timer_list timeout; - +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + /* Is timeout fixed ? */ + uint32_t fixed_timeout; +#endif + #ifdef CONFIG_IP_NF_CT_ACCT /* Accounting Information (same cache line as other written members) */ struct ip_conntrack_counter counters[IP_CT_DIR_MAX]; diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index db78303..3ad3355 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -46,6 +46,18 @@ config IP_NF_CT_ACCT If unsure, say `N'. +config IP_NF_CT_FIXED_TIMEOUT + bool "Connection tracking fixed timeout" + depends on IP_NF_CONNTRACK + help + If this option is enabled, the connection tracking code will + be able to have connection that will expire automatically after + a given time. + + This feature can be used with libnetfilter_conntrack library. + + If unsure, say `N'. + config IP_NF_CONNTRACK_MARK bool 'Connection mark tracking support' depends on IP_NF_CONNTRACK diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 84c66db..95f086b 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -488,6 +488,8 @@ __ip_conntrack_confirm(struct sk_buff ** weird delay cases. */ ct->timeout.expires += jiffies; add_timer(&ct->timeout); + + atomic_inc(&ct->ct_general.use); set_bit(IPS_CONFIRMED_BIT, &ct->status); CONNTRACK_STAT_INC(insert); @@ -724,11 +726,20 @@ init_conntrack(struct ip_conntrack_tuple /* this is ugly, but there is no other place where to put it */ conntrack->nat.masq_index = exp->master->nat.masq_index; #endif + +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + /* fixed_timeout of related connection is the one of master */ + conntrack->fixed_timeout=exp->master->fixed_timeout; +#endif nf_conntrack_get(&conntrack->master->ct_general); CONNTRACK_STAT_INC(expect_new); } else { conntrack->helper = __ip_conntrack_helper_find(&repl_tuple); +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + /* init fixed_timeout to 0 (do not finish) */ + conntrack->fixed_timeout=0; +#endif CONNTRACK_STAT_INC(new); } @@ -1135,12 +1146,18 @@ void __ip_ct_refresh_acct(struct ip_conn ct->timeout.expires = extra_jiffies; event = IPCT_REFRESH; } else { - /* Need del_timer for race avoidance (may already be dying). */ - if (del_timer(&ct->timeout)) { - ct->timeout.expires = jiffies + extra_jiffies; - add_timer(&ct->timeout); - event = IPCT_REFRESH; - } + /* Need del_timer for race avoidance (may already be dying). */ + if (del_timer(&ct->timeout)) { + ct->timeout.expires = jiffies + extra_jiffies; +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + if ((ct->fixed_timeout) && + (ct->timeout.expires > jiffies+ ct->fixed_timeout *HZ)) { + ct->timeout.expires = jiffies + ct->fixed_timeout * HZ; + } +#endif + add_timer(&ct->timeout); + event = IPCT_REFRESH; + } } #ifdef CONFIG_IP_NF_CT_ACCT diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index c9ebbe0..10688cc 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -42,7 +42,7 @@ MODULE_LICENSE("GPL"); -static char __initdata version[] = "0.90"; +static char __initdata version[] = "0.91"; #if 0 #define DEBUGP printk @@ -942,6 +942,20 @@ ctnetlink_change_timeout(struct ip_connt } static inline int +ctnetlink_check_timeout(struct ip_conntrack *ct) +{ + if (ct->timeout.expires > jiffies+ ct->fixed_timeout *HZ) { + if (!del_timer(&ct->timeout)) + return -ETIME; + ct->timeout.expires = jiffies + ct->fixed_timeout * HZ; + add_timer(&ct->timeout); + } + return 0; +} + + + +static inline int ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) { struct nfattr *tb[CTA_PROTOINFO_MAX], *attr = cda[CTA_PROTOINFO-1]; @@ -979,6 +993,15 @@ ctnetlink_change_conntrack(struct ip_con return err; } +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + if (cda[CTA_FIXED_TIMEOUT-1]) { + ct->fixed_timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_FIXED_TIMEOUT-1])); + err = ctnetlink_check_timeout(ct); + if (err < 0) + return err; + } +#endif + if (cda[CTA_STATUS-1]) { err = ctnetlink_change_status(ct, cda); if (err < 0) @@ -1018,7 +1041,17 @@ ctnetlink_create_conntrack(struct nfattr goto err; ct->timeout.expires = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_TIMEOUT-1])); + /* we admit jiffies delay on timeout even if is fixed */ ct->timeout.expires = jiffies + ct->timeout.expires * HZ; + +#ifdef CONFIG_IP_NF_CT_FIXED_TIMEOUT + if (cda[CTA_FIXED_TIMEOUT-1]) { + ct->fixed_timeout = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_FIXED_TIMEOUT-1])); + } else { + ct->fixed_timeout = 0; + } +#endif + ct->status |= IPS_CONFIRMED; err = ctnetlink_change_status(ct, cda); -- 1.1.5