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

* Re: [PATCH]  ip6tables support for the CONDITION MATCH
  2002-11-16 21:36 [PATCH] ip6tables support for the CONDITION MATCH Stephane Ouellette
@ 2002-12-05 20:30 ` Harald Welte
  0 siblings, 0 replies; 2+ messages in thread
From: Harald Welte @ 2002-12-05 20:30 UTC (permalink / raw)
  To: Stephane Ouellette; +Cc: netfilter-devel

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

On Sat, Nov 16, 2002 at 04:36:34PM -0500, Stephane Ouellette wrote:
> Harald,
> 
>   here is a patch to the condition match to support ip6tables.  IPv6 
> support will be compiled only if selected in the kernel configuration.

sorry, but although this is the most efficient way to implement it
(implement ipv4 and ipv6 part in one module), it confuses users (and
iptables itself).

imagine autoloading.  we always try to load ip6t_condition.o, but in
your case everything is in ipt_condition.o :((

I think you can understand that I cannot accept it this way :((

> Regards,
> Stephane Ouellette


-- 
Live long and prosper
- Harald Welte / laforge@gnumonks.org               http://www.gnumonks.org/
============================================================================
GCS/E/IT d- s-: a-- C+++ UL++++$ P+++ L++++$ E--- W- N++ o? K- w--- O- M- 
V-- PS+ PE-- Y+ PGP++ t++ 5-- !X !R tv-- b+++ DI? !D G+ e* h+ r% y+(*)

[-- Attachment #2: Type: application/pgp-signature, Size: 232 bytes --]

^ 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.