Commit 0379e92f authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Patrick McHardy

[NETFILTER]: Make conntrack timeouts become sysctls.

This patch introduces the /proc/sys/net/ipv4/netfilter/ directory for=20
the tuneable parameters of the conntrack engine of netfilter.

The parameters which can currently be fine-tuned (if required at all)=20
are the ip_conntrack_max, and the conntrack timeout parameters in seconds.

The default timeout value for the TCP CLOSE_WAIT state is raised to 3
days, which should cause less problems with long-lived half-closed TCP
sessions.

For the sake of compatibility with 2.4,=20
/proc/sys/net/ipv4/netfilter/ip_conntrack_max is duplicated as=20
/proc/sys/net/ipv4/ip_conntrack_max as well.
parent 7b32a04c
...@@ -59,7 +59,7 @@ LIST_HEAD(ip_conntrack_expect_list); ...@@ -59,7 +59,7 @@ LIST_HEAD(ip_conntrack_expect_list);
LIST_HEAD(protocol_list); LIST_HEAD(protocol_list);
static LIST_HEAD(helpers); static LIST_HEAD(helpers);
unsigned int ip_conntrack_htable_size = 0; unsigned int ip_conntrack_htable_size = 0;
static int ip_conntrack_max; int ip_conntrack_max;
static atomic_t ip_conntrack_count = ATOMIC_INIT(0); static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
struct list_head *ip_conntrack_hash; struct list_head *ip_conntrack_hash;
static kmem_cache_t *ip_conntrack_cachep; static kmem_cache_t *ip_conntrack_cachep;
...@@ -1328,45 +1328,6 @@ static struct nf_sockopt_ops so_getorigdst = { ...@@ -1328,45 +1328,6 @@ static struct nf_sockopt_ops so_getorigdst = {
.get = &getorigdst, .get = &getorigdst,
}; };
#define NET_IP_CONNTRACK_MAX 2089
#define NET_IP_CONNTRACK_MAX_NAME "ip_conntrack_max"
#ifdef CONFIG_SYSCTL
static struct ctl_table_header *ip_conntrack_sysctl_header;
static ctl_table ip_conntrack_table[] = {
{
.ctl_name = NET_IP_CONNTRACK_MAX,
.procname = NET_IP_CONNTRACK_MAX_NAME,
.data = &ip_conntrack_max,
.maxlen = sizeof(ip_conntrack_max),
.mode = 0644,
.proc_handler = proc_dointvec
},
{ .ctl_name = 0 }
};
static ctl_table ip_conntrack_dir_table[] = {
{
.ctl_name = NET_IPV4,
.procname = "ipv4",
.mode = 0555,
.child = ip_conntrack_table
},
{ .ctl_name = 0 }
};
static ctl_table ip_conntrack_root_table[] = {
{
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = ip_conntrack_dir_table
},
{ .ctl_name = 0 }
};
#endif /*CONFIG_SYSCTL*/
static int kill_all(const struct ip_conntrack *i, void *data) static int kill_all(const struct ip_conntrack *i, void *data)
{ {
return 1; return 1;
...@@ -1376,9 +1337,6 @@ static int kill_all(const struct ip_conntrack *i, void *data) ...@@ -1376,9 +1337,6 @@ static int kill_all(const struct ip_conntrack *i, void *data)
supposed to kill the mall. */ supposed to kill the mall. */
void ip_conntrack_cleanup(void) void ip_conntrack_cleanup(void)
{ {
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(ip_conntrack_sysctl_header);
#endif
ip_ct_attach = NULL; ip_ct_attach = NULL;
/* This makes sure all current packets have passed through /* This makes sure all current packets have passed through
netfilter framework. Roll on, two-stage module netfilter framework. Roll on, two-stage module
...@@ -1456,25 +1414,10 @@ int __init ip_conntrack_init(void) ...@@ -1456,25 +1414,10 @@ int __init ip_conntrack_init(void)
for (i = 0; i < ip_conntrack_htable_size; i++) for (i = 0; i < ip_conntrack_htable_size; i++)
INIT_LIST_HEAD(&ip_conntrack_hash[i]); INIT_LIST_HEAD(&ip_conntrack_hash[i]);
/* This is fucking braindead. There is NO WAY of doing this without
the CONFIG_SYSCTL unless you don't want to detect errors.
Grrr... --RR */
#ifdef CONFIG_SYSCTL
ip_conntrack_sysctl_header
= register_sysctl_table(ip_conntrack_root_table, 0);
if (ip_conntrack_sysctl_header == NULL) {
goto err_free_ct_cachep;
}
#endif /*CONFIG_SYSCTL*/
/* For use by ipt_REJECT */ /* For use by ipt_REJECT */
ip_ct_attach = ip_conntrack_attach; ip_ct_attach = ip_conntrack_attach;
return ret; return ret;
#ifdef CONFIG_SYSCTL
err_free_ct_cachep:
kmem_cache_destroy(ip_conntrack_cachep);
#endif /*CONFIG_SYSCTL*/
err_free_hash: err_free_hash:
vfree(ip_conntrack_hash); vfree(ip_conntrack_hash);
err_unreg_sockopt: err_unreg_sockopt:
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#define GENERIC_TIMEOUT (600*HZ) unsigned long ip_ct_generic_timeout = 600*HZ;
static int generic_pkt_to_tuple(const struct sk_buff *skb, static int generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
...@@ -44,7 +44,7 @@ static int packet(struct ip_conntrack *conntrack, ...@@ -44,7 +44,7 @@ static int packet(struct ip_conntrack *conntrack,
const struct sk_buff *skb, const struct sk_buff *skb,
enum ip_conntrack_info conntrackinfo) enum ip_conntrack_info conntrackinfo)
{ {
ip_ct_refresh(conntrack, GENERIC_TIMEOUT); ip_ct_refresh(conntrack, ip_ct_generic_timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#include <linux/icmp.h> #include <linux/icmp.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#define ICMP_TIMEOUT (30*HZ) unsigned long ip_ct_icmp_timeout = 30*HZ;
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
...@@ -86,7 +86,7 @@ static int icmp_packet(struct ip_conntrack *ct, ...@@ -86,7 +86,7 @@ static int icmp_packet(struct ip_conntrack *ct,
ct->timeout.function((unsigned long)ct); ct->timeout.function((unsigned long)ct);
} else { } else {
atomic_inc(&ct->proto.icmp.count); atomic_inc(&ct->proto.icmp.count);
ip_ct_refresh(ct, ICMP_TIMEOUT); ip_ct_refresh(ct, ip_ct_icmp_timeout);
} }
return NF_ACCEPT; return NF_ACCEPT;
......
...@@ -49,20 +49,28 @@ static const char *tcp_conntrack_names[] = { ...@@ -49,20 +49,28 @@ static const char *tcp_conntrack_names[] = {
#define HOURS * 60 MINS #define HOURS * 60 MINS
#define DAYS * 24 HOURS #define DAYS * 24 HOURS
unsigned long ip_ct_tcp_timeout_syn_sent = 2 MINS;
static unsigned long tcp_timeouts[] unsigned long ip_ct_tcp_timeout_syn_recv = 60 SECS;
= { 30 MINS, /* TCP_CONNTRACK_NONE, */ unsigned long ip_ct_tcp_timeout_established = 5 DAYS;
5 DAYS, /* TCP_CONNTRACK_ESTABLISHED, */ unsigned long ip_ct_tcp_timeout_fin_wait = 2 MINS;
2 MINS, /* TCP_CONNTRACK_SYN_SENT, */ unsigned long ip_ct_tcp_timeout_close_wait = 3 DAYS;
60 SECS, /* TCP_CONNTRACK_SYN_RECV, */ unsigned long ip_ct_tcp_timeout_last_ack = 30 SECS;
2 MINS, /* TCP_CONNTRACK_FIN_WAIT, */ unsigned long ip_ct_tcp_timeout_time_wait = 2 MINS;
2 MINS, /* TCP_CONNTRACK_TIME_WAIT, */ unsigned long ip_ct_tcp_timeout_close = 10 SECS;
10 SECS, /* TCP_CONNTRACK_CLOSE, */
60 SECS, /* TCP_CONNTRACK_CLOSE_WAIT, */ static unsigned long * tcp_timeouts[]
30 SECS, /* TCP_CONNTRACK_LAST_ACK, */ = { 0, /* TCP_CONNTRACK_NONE */
2 MINS, /* TCP_CONNTRACK_LISTEN, */ &ip_ct_tcp_timeout_established, /* TCP_CONNTRACK_ESTABLISHED, */
}; &ip_ct_tcp_timeout_syn_sent, /* TCP_CONNTRACK_SYN_SENT, */
&ip_ct_tcp_timeout_syn_recv, /* TCP_CONNTRACK_SYN_RECV, */
&ip_ct_tcp_timeout_fin_wait, /* TCP_CONNTRACK_FIN_WAIT, */
&ip_ct_tcp_timeout_time_wait, /* TCP_CONNTRACK_TIME_WAIT, */
&ip_ct_tcp_timeout_close, /* TCP_CONNTRACK_CLOSE, */
&ip_ct_tcp_timeout_close_wait, /* TCP_CONNTRACK_CLOSE_WAIT, */
&ip_ct_tcp_timeout_last_ack, /* TCP_CONNTRACK_LAST_ACK, */
0, /* TCP_CONNTRACK_LISTEN */
};
#define sNO TCP_CONNTRACK_NONE #define sNO TCP_CONNTRACK_NONE
#define sES TCP_CONNTRACK_ESTABLISHED #define sES TCP_CONNTRACK_ESTABLISHED
#define sSS TCP_CONNTRACK_SYN_SENT #define sSS TCP_CONNTRACK_SYN_SENT
...@@ -204,7 +212,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -204,7 +212,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
set_bit(IPS_ASSURED_BIT, &conntrack->status); set_bit(IPS_ASSURED_BIT, &conntrack->status);
WRITE_UNLOCK(&tcp_lock); WRITE_UNLOCK(&tcp_lock);
ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]); ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
} }
return NF_ACCEPT; return NF_ACCEPT;
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
#include <linux/udp.h> #include <linux/udp.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h> #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#define UDP_TIMEOUT (30*HZ) unsigned long ip_ct_udp_timeout = 30*HZ;
#define UDP_STREAM_TIMEOUT (180*HZ) unsigned long ip_ct_udp_timeout_stream = 180*HZ;
static int udp_pkt_to_tuple(const struct sk_buff *skb, static int udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
...@@ -57,11 +57,11 @@ static int udp_packet(struct ip_conntrack *conntrack, ...@@ -57,11 +57,11 @@ static int udp_packet(struct ip_conntrack *conntrack,
/* If we've seen traffic both ways, this is some kind of UDP /* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */ stream. Extend timeout. */
if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT); ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
/* Also, more likely to be important, and not a probe */ /* Also, more likely to be important, and not a probe */
set_bit(IPS_ASSURED_BIT, &conntrack->status); set_bit(IPS_ASSURED_BIT, &conntrack->status);
} else } else
ip_ct_refresh(conntrack, UDP_TIMEOUT); ip_ct_refresh(conntrack, ip_ct_udp_timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
/* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
Public Licence. */ Public Licence. */
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
...@@ -14,6 +15,9 @@ ...@@ -14,6 +15,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
#include <net/checksum.h> #include <net/checksum.h>
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
...@@ -256,6 +260,98 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = { ...@@ -256,6 +260,98 @@ static struct nf_hook_ops ip_conntrack_local_in_ops = {
.priority = NF_IP_PRI_LAST-1, .priority = NF_IP_PRI_LAST-1,
}; };
/* Sysctl support */
#ifdef CONFIG_SYSCTL
/* From ip_conntrack_core.c */
extern int ip_conntrack_max;
/* From ip_conntrack_proto_tcp.c */
extern unsigned long ip_ct_tcp_timeout_syn_sent;
extern unsigned long ip_ct_tcp_timeout_syn_recv;
extern unsigned long ip_ct_tcp_timeout_established;
extern unsigned long ip_ct_tcp_timeout_fin_wait;
extern unsigned long ip_ct_tcp_timeout_close_wait;
extern unsigned long ip_ct_tcp_timeout_last_ack;
extern unsigned long ip_ct_tcp_timeout_time_wait;
extern unsigned long ip_ct_tcp_timeout_close;
/* From ip_conntrack_proto_udp.c */
extern unsigned long ip_ct_udp_timeout;
extern unsigned long ip_ct_udp_timeout_stream;
/* From ip_conntrack_proto_icmp.c */
extern unsigned long ip_ct_icmp_timeout;
/* From ip_conntrack_proto_icmp.c */
extern unsigned long ip_ct_generic_timeout;
static struct ctl_table_header *ip_ct_sysctl_header;
static ctl_table ip_ct_sysctl_table[] = {
{NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
&ip_conntrack_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
&ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
&ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
&ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
&ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
&ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
&ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
&ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
&ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
&ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
&ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
&ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
&ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
&proc_dointvec_jiffies},
{0}
};
#define NET_IP_CONNTRACK_MAX 2089
static ctl_table ip_ct_netfilter_table[] = {
{NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
{NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
&ip_conntrack_max, sizeof(int), 0644, NULL,
&proc_dointvec},
{0}
};
static ctl_table ip_ct_ipv4_table[] = {
{NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
{0}
};
static ctl_table ip_ct_net_table[] = {
{CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
{0}
};
#endif
static int init_or_cleanup(int init) static int init_or_cleanup(int init)
{ {
struct proc_dir_entry *proc; struct proc_dir_entry *proc;
...@@ -291,10 +387,20 @@ static int init_or_cleanup(int init) ...@@ -291,10 +387,20 @@ static int init_or_cleanup(int init)
printk("ip_conntrack: can't register local in hook.\n"); printk("ip_conntrack: can't register local in hook.\n");
goto cleanup_inoutandlocalops; goto cleanup_inoutandlocalops;
} }
#ifdef CONFIG_SYSCTL
ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
if (ip_ct_sysctl_header == NULL) {
printk("ip_conntrack: can't register to sysctl.\n");
goto cleanup;
}
#endif
return ret; return ret;
cleanup: cleanup:
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(ip_ct_sysctl_header);
#endif
nf_unregister_hook(&ip_conntrack_local_in_ops); nf_unregister_hook(&ip_conntrack_local_in_ops);
cleanup_inoutandlocalops: cleanup_inoutandlocalops:
nf_unregister_hook(&ip_conntrack_out_ops); nf_unregister_hook(&ip_conntrack_out_ops);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment