All of lore.kernel.org
 help / color / mirror / Atom feed
* [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

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.