4 Copyright (C) 2006 Jonathan Zarate
6 Licensed under GNU GPL v2.
9 #include <linux/module.h>
10 #include <linux/skbuff.h>
11 #include <linux/version.h>
12 #include <linux/proc_fs.h>
14 #include <linux/netfilter_ipv4/ip_tables.h>
15 #include <net/netfilter/nf_conntrack.h>
16 #include <net/netfilter/nf_conntrack_core.h>
17 #include <net/netfilter/nf_conntrack_helper.h>
19 // #define TEST_HASHDIST
23 static int hashdist_read(char *buffer
, char **start
, off_t offset
, int length
, int *eof
, void *data
)
25 struct nf_conntrack_tuple_hash
*h
;
32 // do this the easy way...
33 max
= nf_conntrack_htable_size
* sizeof("12345\t12345\n");
34 buf
= kmalloc(max
+ 1, GFP_KERNEL
);
35 if (buf
== NULL
) return 0;
38 max
-= sizeof("12345\t12345\n");
40 read_lock_bh(&nf_conntrack_lock
);
42 for (i
= 0; i
< nf_conntrack_htable_size
; ++i
) {
44 list_for_each_entry(h
, &nf_conntrack_hash
[i
], list
) {
47 n
+= sprintf(buf
+ n
, "%d\t%d\n", i
, count
);
49 printk("hashdist: %d > %d\n", n
, max
);
54 read_unlock_bh(&nf_conntrack_lock
);
65 memcpy(buffer
, buf
+ offset
, n
);
79 static void iterate_all(void (*func
)(struct nf_conn
*, unsigned long), unsigned long data
)
82 struct nf_conntrack_tuple_hash
*h
;
84 write_lock_bh(&nf_conntrack_lock
);
85 for (i
= 0; i
< nf_conntrack_htable_size
; ++i
) {
86 list_for_each_entry(h
, &nf_conntrack_hash
[i
], list
) {
87 func(nf_ct_tuplehash_to_ctrack(h
), data
);
90 write_unlock_bh(&nf_conntrack_lock
);
93 static void expireearly(struct nf_conn
*ct
, unsigned long data
)
95 if (ct
->timeout
.expires
> data
) {
96 if (del_timer(&ct
->timeout
)) {
97 ct
->timeout
.expires
= data
;
98 add_timer(&ct
->timeout
);
103 static int expireearly_write(struct file
*file
, const char *buffer
, unsigned long length
, void *data
)
108 if ((length
> 0) && (length
< 6)) {
109 memcpy(s
, buffer
, length
);
111 n
= simple_strtoul(s
, NULL
, 10);
113 else if (n
> 86400) n
= 86400;
115 iterate_all(expireearly
, jiffies
+ (n
* HZ
));
119 if ((length > 0) && (buffer[0] == '1')) {
120 iterate_all(expireearly, jiffies + (20 * HZ));
128 static void clearmarks(struct nf_conn
*ct
, unsigned long data
)
133 static int clearmarks_write(struct file
*file
, const char *buffer
, unsigned long length
, void *data
)
135 if ((length
> 0) && (buffer
[0] == '1')) {
136 iterate_all(clearmarks
, 0);
141 static int conntrack_clear_write(struct file
*file
, const char *buffer
, unsigned long length
, void *data
)
143 if ((length
> 0) && (buffer
[0] == '1')) {
145 nf_conntrack_flush();
146 if (atomic_read(&nf_conntrack_count
) != 0) {
148 goto i_see_dead_people
;
154 static int __init
init(void)
156 #ifdef CONFIG_PROC_FS
157 struct proc_dir_entry
*p
;
159 printk(__FILE__
" [" __DATE__
" " __TIME__
"]\n");
162 p
= create_proc_entry("hash_dist", 0400, proc_net
);
164 p
->owner
= THIS_MODULE
;
165 p
->read_proc
= hashdist_read
;
169 p
= create_proc_entry("expire_early", 0200, proc_net
);
171 p
->owner
= THIS_MODULE
;
172 p
->write_proc
= expireearly_write
;
175 p
= create_proc_entry("clear_marks", 0200, proc_net
);
177 p
->owner
= THIS_MODULE
;
178 p
->write_proc
= clearmarks_write
;
181 p
= create_proc_entry("conntrack_clear", 0200, proc_net
);
183 p
->owner
= THIS_MODULE
;
184 p
->write_proc
= conntrack_clear_write
;
186 #endif /* CONFIG_PROC_FS */
191 static void __exit
fini(void)
193 #ifdef CONFIG_PROC_FS
195 remove_proc_entry("hash_dist", proc_net
);
197 remove_proc_entry("expire_early", proc_net
);
198 remove_proc_entry("clear_marks", proc_net
);
199 remove_proc_entry("conntrack_clear", proc_net
);
200 #endif /* CONFIG_PROC_FS */
206 MODULE_LICENSE("GPL");