* [PATCH] Conntrack proc interface for tuple removal
@ 2005-05-12 18:47 Ferry Huberts
2005-05-13 5:13 ` Pablo Neira
0 siblings, 1 reply; 6+ messages in thread
From: Ferry Huberts @ 2005-05-12 18:47 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 385 bytes --]
Hi list,
I badly needed to be able to remove conntrack tuple because of some very
dynamic application behaviour, so I wrote a patch.
Hope it lives up to your standards, I find it quite usefull :-)
The patch is based on work from Yutaka Kondo.
The patch is against 2.4.30 since that is the kernel I'm using, haven't
looked into applying it against 2.6.x.y
Cheers!
--
Ferry Huberts
[-- Attachment #2: kernel_remove_conntrack.diff --]
[-- Type: application/octet-stream, Size: 8923 bytes --]
# ==============================================================================
# $Id: kernel_remove_conntrack.diff,v 1.1 2005/05/12 18:26:59 titaan Exp $
# $Name: $
# ==============================================================================
#
# Check-in information: $Author: titaan $
# $Date: 2005/05/12 18:26:59 $
# $Revision: 1.1 $
#
# Locking information : $Locker: $
# $State: Exp $
# ==============================================================================
# History of check-in comments
# ==============================================================================
# $Log: kernel_remove_conntrack.diff,v $
# Revision 1.1 2005/05/12 18:26:59 titaan
# add conntrack removal kernel patch
#
# ==============================================================================
This patch allow for removal of selected conntrack records:
Usage:
echo "src=x.x.x.x" > /proc/net/ip_conntrack
echo "dst=x.x.x.x" > /proc/net/ip_conntrack
echo "all" > /proc/net/ip_conntrack
Modes:
src=x.x.x.x : all records that have x.x.x.x as the IP address in the src
field of the 'ORIGINAL' or 'REPLY' will be deleted from
the connection tracking table
dst=x.x.x.x : all records that have x.x.x.x as the IP address in the dst
field of the 'ORIGINAL' or 'REPLY' will be deleted from
the connection tracking table
all : all records will be deleted from the connection tracking table
--- linux/net/ipv4/netfilter/ip_conntrack_standalone.c.org 2005-05-12 15:29:26.000000000 +0200
+++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2005-05-12 20:17:47.000000000 +0200
@@ -6,9 +6,14 @@
/* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
Public Licence. */
+
+/* 2005-05-12 Ferry Huberts : added ip_conntrack_user_remove capability,
+ based heavily on work from Yutaka Kondo
+ (kondo@rdd.soliton.co.jp) */
#include <linux/config.h>
#include <linux/types.h>
+#include <asm/byteorder.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
@@ -39,6 +44,257 @@
MODULE_LICENSE("GPL");
+/*
+Returns 1 when the character is a digit, 0 otherwise
+*/
+static inline int conntrack_isdigit(unsigned char ch) {
+ if ((ch >= '0') && (ch <= '9')) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+/*
+convert string to (network endianess) integer
+safer version than the one in utils
+also more compliant to inet_aton function
+*/
+static unsigned int conntrack_aton(const char *str) {
+ unsigned long ipvalue;
+ unsigned int bytecount;
+ unsigned int bytevalue;
+ int i;
+
+ ipvalue = 0;
+ bytecount = 0;
+ for (i = 0; i < 4; i++) {
+ ipvalue <<= 8;
+ bytevalue = 0;
+ while ((*str != '\0') &&
+ (*str != '\n') &&
+ conntrack_isdigit((unsigned char)*str)) {
+ bytevalue *= 10;
+ bytevalue += (*str - '0');
+ str++;
+ }
+
+ /* clip the value */
+ if (bytevalue <= 0xff) {
+ ipvalue |= bytevalue;
+ }
+ else {
+ ipvalue |= 0xff;
+ }
+
+ /* we have processed another byte */
+ bytecount++;
+
+ if ((*str != '\0') && (*str != '\n')) {
+ /* not at the end of the string */
+
+ if ((bytecount == 4) || (*str != '.')) {
+ /* and not a dot: illegal value */
+ ipvalue = 0;
+ bytecount = 4;
+ break;
+ }
+ else {
+ /* and a dot: skip the dot */
+ str++;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+
+ unsigned long tmp;
+ switch (bytecount) {
+ case 1:
+ ipvalue <<= 24;
+ break;
+
+ case 2:
+ tmp = (ipvalue & 0x0000ff00);
+ ipvalue &= 0x000000ff;
+ ipvalue |= (tmp << 16);
+ break;
+
+ case 3:
+ tmp = (ipvalue & 0x00ff0000);
+ ipvalue &= 0x0000ffff;
+ ipvalue |= (tmp << 8);
+ break;
+
+ case 4:
+ break;
+
+ default:
+ ipvalue = 0;
+ break;
+ }
+
+ return (htonl(ipvalue));
+}
+
+
+/*
+Remove conntrack entry
+*/
+static inline void match_remove_all_conntrack(
+ __u32 in,
+ struct ip_conntrack *conntrack) {
+/* from the function death_by_timeout
+ del_timer(&conntrack->timeout);
+ clean_from_lists(conntrack);
+ ip_conntrack_put(conntrack);
+*/
+
+ del_timer(&conntrack->timeout);
+ conntrack->timeout.expires = jiffies;
+ conntrack->timeout.function((unsigned long)conntrack);
+}
+
+
+/*
+Remove conntrack entry, if src ip address matches in
+*/
+static inline void match_remove_srcip_conntrack(
+ __u32 in,
+ struct ip_conntrack *conntrack) {
+ if ((in == conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip) ||
+ (in == conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip)) {
+ match_remove_all_conntrack(in, conntrack);
+ }
+}
+
+
+/*
+Remove conntrack entry, if dst ip address matches in
+*/
+static inline void match_remove_dstip_conntrack(
+ __u32 in,
+ struct ip_conntrack *conntrack) {
+ if ((in == conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) ||
+ (in == conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip)) {
+ match_remove_all_conntrack(in, conntrack);
+ }
+}
+
+
+/*
+Called upon write to /proc/net/ip_conntrack
+
+Traverse conntrack list and forcibly remove matching entries
+*/
+static int ip_conntrack_user_remove(struct file * file,
+ const char * buffer,
+ unsigned long count,
+ void * data) {
+ unsigned int i;
+
+ const char * srcstr = "src=";
+ const int srclen = 4;
+ int checksrc = 0;
+
+ const char * dststr = "dst=";
+ const int dstlen = 4;
+ int checkdst = 0;
+
+ const char * allstr = "all";
+ const int alllen = 3;
+ int checkall = 0;
+
+ int validoption = 0;
+ __u32 ipvalue = 0;
+
+
+ /* DEBUG */
+ printk("count = %lu\n", count);
+
+ /* check for valid src option */
+ if ((count >= srclen) && (! memcmp(buffer, srcstr, srclen))) {
+ checksrc = 1;
+ validoption = 1;
+ ipvalue = conntrack_aton((const char *)(&buffer[srclen]));
+ /* DEBUG */
+ printk("Src address = %u.%u.%u.%u will be removed from conntrack\n",
+ NIPQUAD(ipvalue));
+ }
+
+ /* check for valid dst option */
+ else if ((count >= dstlen) && (! memcmp(buffer, dststr, dstlen))) {
+ checkdst = 1;
+ validoption = 1;
+ ipvalue = conntrack_aton((const char *)(&buffer[dstlen]));
+ /* DEBUG */
+ printk("Dst address = %u.%u.%u.%u will be removed from conntrack\n",
+ NIPQUAD(ipvalue));
+ }
+
+ /* check for valid all option */
+ else if ((count >= alllen) && (! memcmp(buffer, allstr, alllen))) {
+ checkall = 1;
+ validoption = 1;
+ /* DEBUG */
+ printk("All records will be removed from conntrack\n");
+ }
+
+
+ /* check if we found a valid option, if not: exit */
+ if (! validoption) {
+ printk("Conntrack user remove: no valid option detected\n");
+ goto endnounlock;
+ }
+
+ /* check if we found a valid ip address when we need it, if not: exit */
+ if ((checksrc || checkdst) && (! ipvalue)) {
+ printk("Conntrack user remove: no valid ip detected\n");
+ goto endnounlock;
+ }
+
+
+ READ_LOCK(&ip_conntrack_lock);
+
+ /* Traverse conntrack table */
+ for (i = 0; i < ip_conntrack_htable_size; i++) {
+ const struct list_head * head = &ip_conntrack_hash[i];
+ do {
+ head = head->next;
+ if (head == &ip_conntrack_hash[i]) {
+ head = NULL;
+ break;
+ }
+ if (head == NULL) {
+ break;
+ }
+ if (checksrc) {
+ match_remove_srcip_conntrack(
+ ipvalue,
+ ((struct ip_conntrack_tuple_hash *)head)->ctrack);
+ }
+ else if (checkdst) {
+ match_remove_dstip_conntrack(
+ ipvalue,
+ ((struct ip_conntrack_tuple_hash *)head)->ctrack);
+ }
+ else if (checkall) {
+ match_remove_all_conntrack(
+ ipvalue,
+ ((struct ip_conntrack_tuple_hash *)head)->ctrack);
+ }
+ } while (1);
+ }
+
+ READ_UNLOCK(&ip_conntrack_lock);
+
+endnounlock:
+ return count;
+}
+
static int kill_proto(struct ip_conntrack *i, void *data)
{
return (i->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum ==
@@ -352,6 +608,7 @@
proc = proc_net_create("ip_conntrack", 0440, list_conntracks);
if (!proc) goto cleanup_init;
proc->owner = THIS_MODULE;
+ proc->write_proc = ip_conntrack_user_remove;
ret = nf_register_hook(&ip_conntrack_in_ops);
if (ret < 0) {
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Conntrack proc interface for tuple removal
2005-05-12 18:47 [PATCH] Conntrack proc interface for tuple removal Ferry Huberts
@ 2005-05-13 5:13 ` Pablo Neira
2005-05-17 16:00 ` Amin Azez
2005-05-17 16:00 ` Amin Azez
0 siblings, 2 replies; 6+ messages in thread
From: Pablo Neira @ 2005-05-13 5:13 UTC (permalink / raw)
To: ferry; +Cc: netfilter-devel
Ferry Huberts wrote:
> I badly needed to be able to remove conntrack tuple because of some very
> dynamic application behaviour, so I wrote a patch.
> Hope it lives up to your standards, I find it quite usefull :-)
>
> The patch is based on work from Yutaka Kondo.
>
> The patch is against 2.4.30 since that is the kernel I'm using, haven't
> looked into applying it against 2.6.x.y
You should do this with ctnetlink. It actually provides a more flexible
interface to user space applications: I mean, more actions like
creation, update, deletion, whatever... instead of doing this via /proc.
Have a look at the conntrack tool in netfilter SVN.
BTW, some comments about your patch:
- READ_LOCK'ing while trying to delete a conntrack is racy, you must use
write_lock instead. Someone else could be reading the conntrack table
while you try to delete a conntrack.
- check the value returned by del_timer, currently racy as well.
- Deadlock on SMP: calling conntrack->timeout.function
(death_by_timeout) is illegal if you've got ip_conntrack_lock.
--
Pablo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Conntrack proc interface for tuple removal
2005-05-13 5:13 ` Pablo Neira
@ 2005-05-17 16:00 ` Amin Azez
2005-05-18 6:51 ` Jozsef Kadlecsik
2005-05-17 16:00 ` Amin Azez
1 sibling, 1 reply; 6+ messages in thread
From: Amin Azez @ 2005-05-17 16:00 UTC (permalink / raw)
To: Pablo Neira; +Cc: netfilter-devel
Pablo Neira wrote:
> - READ_LOCK'ing while trying to delete a conntrack is racy, you must use
> write_lock instead. Someone else could be reading the conntrack table
> while you try to delete a conntrack.
> - check the value returned by del_timer, currently racy as well.
> - Deadlock on SMP: calling conntrack->timeout.function
> (death_by_timeout) is illegal if you've got ip_conntrack_lock.
Where should one read to learn about the rules and intricacies of such
locking dependancies.
Amin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Conntrack proc interface for tuple removal
2005-05-17 16:00 ` Amin Azez
@ 2005-05-18 6:51 ` Jozsef Kadlecsik
2005-05-19 3:10 ` Pablo Neira
0 siblings, 1 reply; 6+ messages in thread
From: Jozsef Kadlecsik @ 2005-05-18 6:51 UTC (permalink / raw)
To: Amin Azez; +Cc: netfilter-devel
On Tue, 17 May 2005, Amin Azez wrote:
> Pablo Neira wrote:
> > - READ_LOCK'ing while trying to delete a conntrack is racy, you must use
> > write_lock instead. Someone else could be reading the conntrack table
> > while you try to delete a conntrack.
> > - check the value returned by del_timer, currently racy as well.
> > - Deadlock on SMP: calling conntrack->timeout.function
> > (death_by_timeout) is illegal if you've got ip_conntrack_lock.
>
> Where should one read to learn about the rules and intricacies of such
> locking dependancies.
Rusty's 'Unreliable Guide To Locking' is an excellent paper on the locking
issues in the Linux kernel.
Best regards,
Jozsef
-
E-mail : kadlec@blackhole.kfki.hu, kadlec@sunserv.kfki.hu
PGP key : http://www.kfki.hu/~kadlec/pgp_public_key.txt
Address : KFKI Research Institute for Particle and Nuclear Physics
H-1525 Budapest 114, POB. 49, Hungary
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] Conntrack proc interface for tuple removal
2005-05-18 6:51 ` Jozsef Kadlecsik
@ 2005-05-19 3:10 ` Pablo Neira
0 siblings, 0 replies; 6+ messages in thread
From: Pablo Neira @ 2005-05-19 3:10 UTC (permalink / raw)
To: Amin Azez; +Cc: netfilter-devel, Jozsef Kadlecsik
Jozsef Kadlecsik wrote:
> On Tue, 17 May 2005, Amin Azez wrote:
>
>
>>Pablo Neira wrote:
>>
>>>- READ_LOCK'ing while trying to delete a conntrack is racy, you must use
>>>write_lock instead. Someone else could be reading the conntrack table
>>>while you try to delete a conntrack.
>>>- check the value returned by del_timer, currently racy as well.
>>>- Deadlock on SMP: calling conntrack->timeout.function
>>>(death_by_timeout) is illegal if you've got ip_conntrack_lock.
>>
>>Where should one read to learn about the rules and intricacies of such
>>locking dependancies.
>
>
> Rusty's 'Unreliable Guide To Locking' is an excellent paper on the locking
> issues in the Linux kernel.
Robert Love has also written some stuff about this. Look for "Kernel
locking techniques". It could help you out together with Rusty's stuff.
--
Pablo
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Conntrack proc interface for tuple removal
2005-05-13 5:13 ` Pablo Neira
2005-05-17 16:00 ` Amin Azez
@ 2005-05-17 16:00 ` Amin Azez
1 sibling, 0 replies; 6+ messages in thread
From: Amin Azez @ 2005-05-17 16:00 UTC (permalink / raw)
To: Pablo Neira; +Cc: netfilter-devel
Pablo Neira wrote:
> - READ_LOCK'ing while trying to delete a conntrack is racy, you must use
> write_lock instead. Someone else could be reading the conntrack table
> while you try to delete a conntrack.
> - check the value returned by del_timer, currently racy as well.
> - Deadlock on SMP: calling conntrack->timeout.function
> (death_by_timeout) is illegal if you've got ip_conntrack_lock.
Where should one read to learn about the rules and intricacies of such
locking dependancies.
Amin
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2005-05-19 3:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-05-12 18:47 [PATCH] Conntrack proc interface for tuple removal Ferry Huberts
2005-05-13 5:13 ` Pablo Neira
2005-05-17 16:00 ` Amin Azez
2005-05-18 6:51 ` Jozsef Kadlecsik
2005-05-19 3:10 ` Pablo Neira
2005-05-17 16:00 ` Amin Azez
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.