All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH]  ip6tables support for the CONDITION MATCH
@ 2002-11-16 21:36 Stephane Ouellette
  2002-12-05 20:30 ` Harald Welte
  0 siblings, 1 reply; 2+ messages in thread
From: Stephane Ouellette @ 2002-11-16 21:36 UTC (permalink / raw)
  To: netfilter-devel

[-- Attachment #1: Type: text/plain, Size: 243 bytes --]

Harald,

   here is a patch to the condition match to support ip6tables.  IPv6 
support will be compiled only if selected in the kernel configuration.

   There is also a patch for userspace/extensions/Makefile.

Regards,

Stephane Ouellette


[-- Attachment #2: condition.patch --]
[-- Type: text/plain, Size: 7619 bytes --]

--- linux-orig/include/linux/netfilter_ipv4/ipt_condition.h	1969-12-31 19:00:00.000000000 -0500
+++ linux/include/linux/netfilter_ipv4/ipt_condition.h	2002-11-10 00:11:49.000000000 -0500
@@ -0,0 +1,11 @@
+#ifndef __IPT_CONDITION_MATCH__
+#define __IPT_CONDITION_MATCH__
+
+#define VARIABLE_NAME_LEN  32
+
+struct condition_info {
+  char	name[VARIABLE_NAME_LEN];
+  int   invert;
+};
+
+#endif
--- linux-orig/net/ipv4/netfilter/ipt_condition.c	1969-12-31 19:00:00.000000000 -0500
+++ linux/net/ipv4/netfilter/ipt_condition.c	2002-11-10 00:19:59.000000000 -0500
@@ -0,0 +1,275 @@
+/*-------------------------------------------*\
+|          Netfilter Condition Module         |
+|                                             |
+|  Description: This module allows firewall   |
+|    rules to match using condition variables |
+|    stored in /proc files.  It allows IPv4   |
+|    and IPv6 firewall rules to share their   |
+|    condition variables.                     |
+|                                             |
+|  Author: Stephane Ouellette     2002-10-22  |
+|          <ouellettes@videotron.ca>          |
+\*-------------------------------------------*/
+
+#include<linux/module.h>
+#include<linux/proc_fs.h>
+#include<linux/spinlock.h>
+#include<linux/interrupt.h>
+#include<asm/uaccess.h>
+#include<linux/ctype.h>
+#include<linux/vmalloc.h>
+
+#include<linux/netfilter_ipv4/ip_tables.h>
+#include<linux/netfilter_ipv4/ipt_condition.h>
+
+#ifdef CONFIG_IPV6
+#include<linux/netfilter_ipv6/ip6_tables.h>
+#endif
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+
+
+struct condition_variable {
+  char         name[VARIABLE_NAME_LEN];
+			   // Variable Name (NULL-terminated string)
+  u_int32_t    refcount;   // Number of references to this variable
+  u_int32_t    boolean;    // TRUE == 1, FALSE == 0
+  spinlock_t   variable_lock;
+  struct proc_dir_entry *status_proc;
+  struct condition_variable *next;
+};
+
+
+static spinlock_t list_lock = SPIN_LOCK_UNLOCKED;
+static struct condition_variable *head = NULL;
+static struct proc_dir_entry *proc_net_condition = NULL;
+
+
+static int ipt_condition_read_info(char *buffer, char **start, off_t offset,
+int length, int *eof, void *data)
+{
+  if(offset == 0)
+  {
+    *start = buffer;
+    buffer[0] = '0' + (char)((struct condition_variable*)data)->boolean;
+    buffer[1] = '\n';
+    return 2;
+  }
+ 
+  *eof = 1;
+  return 0;
+}
+
+
+static int ipt_condition_write_info(struct file *file, const char *buffer,
+unsigned long length, void *data)
+{
+  if(length)
+  {
+    // Match only on the first character
+    if(buffer[0] == '0')
+      ((struct condition_variable*)data)->boolean = 0;
+    else if(buffer[0] == '1') 
+      ((struct condition_variable*)data)->boolean = 1;
+  }
+
+  return length;
+}
+
+
+static int match(const struct sk_buff *skb, const struct net_device *in,
+const struct net_device *out, const void *matchinfo, int offset,
+const void *hdr, u_int16_t datalen, int *hotdrop)
+{
+  const struct condition_info *info = (const struct condition_info*)matchinfo;
+  struct condition_variable *var = head;
+  
+  while(var && strncmp(info->name, var->name, VARIABLE_NAME_LEN))
+    var = var->next;
+
+  return((var) ? var->boolean ^ info->invert : 0);
+}
+
+
+static int checkentry_common(struct condition_info *info)
+{
+  struct condition_variable *var = head, *previous = NULL;
+
+  spin_lock_bh(&list_lock);
+
+  // Search for the condition variable in the list
+  while(var && (strncmp(info->name, var->name, VARIABLE_NAME_LEN))) 
+  {
+    previous = var;
+    var = var->next;
+  }
+
+  if(var)
+  {
+    // The variable already exists, increment the reference count
+    spin_lock_bh(&var->variable_lock);
+    var->refcount++;    
+    spin_unlock_bh(&var->variable_lock);
+  }
+  else
+  {
+    // Create a new variable 
+    if((var = vmalloc(sizeof(struct condition_variable))) == NULL)
+    {
+      spin_unlock_bh(&list_lock);
+      return -ENOMEM;
+    }
+
+    strncpy(var->name, info->name, VARIABLE_NAME_LEN - 1);
+    var->name[VARIABLE_NAME_LEN - 1] = 0;
+    var->refcount = 1;
+    var->boolean = 0;
+    var->variable_lock = SPIN_LOCK_UNLOCKED;
+    var->next = NULL;
+    var->status_proc = create_proc_entry(var->name, 0644, proc_net_condition);
+
+    if(!var->status_proc)
+    {
+      vfree(var);
+      spin_unlock_bh(&list_lock);
+      return -ENOMEM;
+    }
+
+    var->status_proc->owner = THIS_MODULE;
+    var->status_proc->read_proc = ipt_condition_read_info;
+    var->status_proc->write_proc = ipt_condition_write_info;
+    var->status_proc->data = var;
+
+    if(previous)
+      previous->next = var;
+    else
+      head = var;
+  }
+
+  spin_unlock_bh(&list_lock);
+  return 1;
+}
+
+
+static int checkentry4(const char *tablename, const struct ipt_ip *ip,
+void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+  if(matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+    return 0;
+
+  return checkentry_common((struct condition_info*)matchinfo);
+}
+
+
+#ifdef CONFIG_IPV6
+static int checkentry6(const char *tablename, const struct ip6t_ip6 *ip,
+void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+  if(matchsize != IP6T_ALIGN(sizeof(struct condition_info)))
+    return 0;
+
+  return checkentry_common((struct condition_info*)matchinfo);
+}
+#endif
+
+
+static void destroy_common(struct condition_info *info)
+{
+  struct condition_variable *var = head, *previous = NULL;
+  
+  spin_lock_bh(&list_lock);
+
+  while(var && strncmp(info->name, var->name, VARIABLE_NAME_LEN))
+  {
+    previous = var;
+    var = var->next;
+  }
+
+  if(var)
+  {
+    spin_lock_bh(&var->variable_lock);
+
+    if(--var->refcount == 0)
+    {
+      if(previous)
+        previous->next = var->next;
+      else
+        head = var->next;
+
+      remove_proc_entry(var->name, proc_net_condition);
+      spin_unlock_bh(&var->variable_lock);
+      vfree(var);
+    }
+    else spin_unlock_bh(&var->variable_lock);
+  }
+
+  spin_unlock_bh(&list_lock);
+}
+
+
+static void destroy4(void *matchinfo, unsigned int matchsize)
+{
+  if(matchsize == IPT_ALIGN(sizeof(struct condition_info)))
+    destroy_common((struct condition_info*)matchinfo);
+}
+
+
+#ifdef CONFIG_IPV6
+static void destroy6(void *matchinfo, unsigned int matchsize)
+{
+  if(matchsize == IP6T_ALIGN(sizeof(struct condition_info)))
+    destroy_common((struct condition_info*)matchinfo);
+}
+#endif
+
+
+static struct ipt_match condition_match4 =
+{ { NULL, NULL }, "condition", &match, &checkentry4, &destroy4, THIS_MODULE };
+
+
+#ifdef CONFIG_IPV6
+static struct ip6t_match condition_match6 =
+{ { NULL, NULL }, "condition", &match, &checkentry6, &destroy6, THIS_MODULE };
+#endif
+
+
+static int __init init(void)
+{
+  int  errorcode;
+  proc_net_condition = proc_mkdir("ipt_condition", proc_net);
+
+  if(proc_net_condition)
+  {
+    errorcode = ipt_register_match(&condition_match4);
+
+#ifdef CONFIG_IPV6
+    if(errorcode == 0)
+    {
+      if((errorcode = ip6t_register_match(&condition_match6)) != 0)
+        ipt_unregister_match(&condition_match4);
+    }
+#endif
+
+    if(errorcode != 0)
+      remove_proc_entry("ipt_condition", proc_net);
+  }
+  else errorcode = -EACCES;
+
+  return(errorcode);
+}
+
+
+static void __exit fini(void)
+{
+#ifdef CONFIG_IPV6
+  ip6t_unregister_match(&condition_match6);
+#endif
+  ipt_unregister_match(&condition_match4);
+  remove_proc_entry("ipt_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
+

[-- Attachment #3: libip6t_condition.c --]
[-- Type: text/plain, Size: 2114 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <ip6tables.h>

#include<linux/netfilter_ipv6/ip6_tables.h>
#include<linux/netfilter_ipv4/ipt_condition.h>


static void help(void)
{
  printf("condition match v%s options:\n"
  "--condition [!] filename       Match on boolean value stored in /proc file"
  "\n", IPTABLES_VERSION);
}

static struct option opts[] = { { "condition", 1, 0, 'X' }, { 0 } };

static void init(struct ip6t_entry_match *m, unsigned int *nfcache)
{
  *nfcache |= NFC_UNKNOWN;
}

static int parse(int c, char **argv, int invert, unsigned int *flags,
		const struct ip6t_entry *entry, unsigned int *nfcache,
		struct ip6t_entry_match **match)
{
  struct condition_info *info = (struct condition_info*)(*match)->data;

  check_inverse(optarg, &invert, &optind, 0);

  if(*flags)
    exit_error(PARAMETER_PROBLEM, "Can't specify multiple conditions");

  if(c == 'X')
  {
    if(strlen(argv[optind-1]) < VARIABLE_NAME_LEN)
      strcpy(info->name, argv[optind-1]);
    else
      exit_error(PARAMETER_PROBLEM, "File name too long");

    info->invert = invert;
    *flags = 1;
    return 1;
  }

  return 0;
}


static void final_check(unsigned int flags)
{
  if(!flags)
    exit_error(PARAMETER_PROBLEM, "Condition match: must specify --condition");
}


static void print(const struct ip6t_ip6 *ip,
		const struct ip6t_entry_match *match, int numeric)
{
  const struct condition_info *info = (const struct condition_info*)match->data;

  printf("condition %s%s ", (info->invert) ? "!" : "", info->name);
}


static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
{
  const struct condition_info *info = (const struct condition_info*)match->data;

  printf("--condition %s%s ", (info->invert) ? "! " : "", info->name);
}


static struct ip6tables_match condition = {
  NULL,
  "condition",
  IPTABLES_VERSION,
  IP6T_ALIGN(sizeof(struct condition_info)),
  IP6T_ALIGN(sizeof(struct condition_info)),
  &help,
  &init,
  &parse,
  &final_check,
  &print,
  &save,
  opts
};


void _init(void)
{
  register_match6(&condition);
}


[-- Attachment #4: condition.patch.configure.help --]
[-- Type: text/plain, Size: 420 bytes --]

CONFIG_IP_NF_MATCH_TOS
condition match support
CONFIG_IP_NF_MATCH_CONDITION
  This option allows you to match firewall rules against condition
  variables stored in the /proc/net/ipt_condition directory.

  This module also supports IPv6. Condition variables can be shared
  by IPv4 and IPv6 firewall rules.

  If you want to compile it as a module, say M here and read
  Documentation/modules.txt.  If unsure, say `N'.

[-- Attachment #5: condition.patch.help --]
[-- Type: text/plain, Size: 342 bytes --]

Author: Stephane Ouellette <ouellettes@videotron.ca>
Status: ItWorksForMe(tm)

This patch adds CONFIG_IP_NF_MATCH_CONDITION which allows you to
match firewall rules against condition variables stored in the
/proc/net/ipt_condition directory.

This module now supports IPv6.  Condition variables can be shared
by IPv4 and IPv6 firewall rules.

[-- Attachment #6: Makefile.diff --]
[-- Type: text/plain, Size: 340 bytes --]

--- Makefile.old	2002-11-16 16:32:34.000000000 -0500
+++ Makefile	2002-11-16 16:33:15.000000000 -0500
@@ -4,6 +4,7 @@
 PF6_EXT_SLIB:=eui64 icmpv6 length limit mac mark multiport owner standard tcp udp LOG MARK
 
 # The following may not be present, but compile them anyway.
+PF6_EXT_SLIB+=condition
 PF_EXT_SLIB+=TTL iplimit
 
 # Optionals

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-12-05 20:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-16 21:36 [PATCH] ip6tables support for the CONDITION MATCH Stephane Ouellette
2002-12-05 20:30 ` Harald Welte

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.