All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [NEW EXTENSION] Condition Match
@ 2002-11-01  1:51 Stephane Ouellette
  2002-11-02  0:41 ` allen
  0 siblings, 1 reply; 11+ messages in thread
From: Stephane Ouellette @ 2002-11-01  1:51 UTC (permalink / raw)
  To: netfilter-devel

--- Harald Welte <laforge@gnumonks.org> wrote:

>> On Tue, Oct 29, 2002 at 10:43:07PM -0600, allen wrote:
>  
>
>>> > 
>>> > 
>>> > On Tuesday 29 October 2002 12:54 pm, Stephane Ouellette wrote:
>>    
>>
>>>> > >    I developped last week a new extension to Netfilter in order to
>>>> > > enable or disable a set of rules using /proc files.
>>>      
>>>
>>> > 
>>> > 
>>> > Yeah, as others have said, the idea is definitely cool.
>>    
>>
>> 
>> Though the idea is cool, I think we are solving a problem the wrong way.  Why
>> add complexity to the kernel for a problem which can be solved without
>> any problem from userspace?
>> 
>> Where is the problem in having a couple of different rulesets (e.g. created
>> with iptables-save) which are then loaded using an iptables-restore
>> commandline or a script at the shell of the firewall?
>

Harald,

   I have already tried the solution you propose on a production 
environment and it proved difficult to deal with.  Using the condition 
match, it is far faster to enable/disable rule sets than it is with a 
set of scripts.  It is also less error-prone on a management point of 
view as the firewall rules never change.

I would suggest that the condition match makes it to P-O-M, and let the 
users try it.

Regards,

Stephane Ouellette.

^ permalink raw reply	[flat|nested] 11+ messages in thread
* [NEW EXTENSION] Condition Match
@ 2002-10-29 18:54 Stephane Ouellette
  2002-10-29 23:00 ` Brad Chapman
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Stephane Ouellette @ 2002-10-29 18:54 UTC (permalink / raw)
  To: netfilter-devel

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

Folks,

   I developped last week a new extension to Netfilter in order to 
enable or disable a set of rules using /proc files.

   As an example, I like to play Quake III Aerna with a few friends of 
mine but I don't want to keep the firewall rules that make them able to 
connect to my computer active at all times.  Adding and removing these 
specific rules is annoying...

    So my solution is illustrated by the following rules:

iptables -t nat -A PREROUTING -p udp -m condition -i $INTERNET --dport 
27960 --condition quake -j DNAT --to-destination $MYCOMPUTER
iptables -t filter -A FORWARD -p udp -m condition -i $INTERNET -o $LAN 
--dport 27960 --condition quake -j ACCEPT
iptables -t filter -A FORWARD -p udp -m condition -i $LAN -o $INTERNET 
--dport 27960 --condition quake -j ACCEPT


To enable the rules, issue:        echo 1 > /proc/net/ipt_condition/quake
To disable the rules, issue:       echo 0> /proc/net/ipt_condition/quake


The /proc files are created automagically when a new condition is 
defined and destroyed when no rule points to them anymore.

As of this writing, the condition match module supports only one 
condition per rule.  I think I will add in a near future the possibility 
to match on many conditions at the same time, using the syntax:     
--condition file1,file2,file3. . .

- It was tested under kernel 2.4.20-pre10-ac2
- So far so good, the condition match module seems stable !

Any comments, bug reports or suggestions would be greatly appreciated.

Enjoy !

Stephane.


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

diff -aruN linux-2.4.20-pre10-ac1-machiavel/include/linux/netfilter_ipv4/ipt_condition.h linux-2.4.20-pre10-ac1-machiavel-new/include/linux/netfilter_ipv4/ipt_condition.h
--- linux-2.4.20-pre10-ac1-machiavel/include/linux/netfilter_ipv4/ipt_condition.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.4.20-pre10-ac1-machiavel-new/include/linux/netfilter_ipv4/ipt_condition.h	2002-10-25 21:26:09.000000000 -0400
@@ -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
diff -aruN linux-2.4.20-pre10-ac1-machiavel/net/ipv4/netfilter/ipt_condition.c linux-2.4.20-pre10-ac1-machiavel-new/net/ipv4/netfilter/ipt_condition.c
--- linux-2.4.20-pre10-ac1-machiavel/net/ipv4/netfilter/ipt_condition.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-2.4.20-pre10-ac1-machiavel-new/net/ipv4/netfilter/ipt_condition.c	2002-10-25 23:30:15.000000000 -0400
@@ -0,0 +1,227 @@
+/*-------------------------------------------*\
+|          Netfilter Condition Module         |
+|                                             |
+|  Description: This module allows firewall   |
+|    rules to match using condition variables |
+|    stored in /proc files.                   |
+|                                             |
+|  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>
+
+
+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(const char *tablename, const struct ipt_ip *ip,
+void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+  struct condition_info *info = (struct condition_info*)matchinfo;
+  struct condition_variable *var, *previous;
+
+  if(matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+    return 0;
+
+  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 void destroy(void *matchinfo, unsigned int matchsize)
+{
+  struct condition_info *info = (struct condition_info*)matchinfo;
+  struct condition_variable *var, *previous;
+
+  if(matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+    return;
+
+  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 struct ipt_match condition_match =
+{ { NULL, NULL }, "condition", &match, &checkentry, &destroy, THIS_MODULE };
+
+
+static int __init init(void)
+{
+  int  errorcode;
+  proc_net_condition = proc_mkdir("ipt_condition", proc_net);
+
+  if(proc_net_condition)
+  {
+    if((errorcode = ipt_register_match(&condition_match)) != 0)
+      remove_proc_entry("ipt_condition", proc_net);
+  }
+  else errorcode = -EACCES;
+
+  return(errorcode);
+}
+
+
+static void __exit fini(void)
+{
+  ipt_unregister_match(&condition_match);
+  remove_proc_entry("ipt_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
+

[-- Attachment #3: condition.patch.config.in --]
[-- Type: text/plain, Size: 178 bytes --]

  dep_tristate '  TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
  dep_tristate '  condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES

[-- Attachment #4: condition.patch.configure.help --]
[-- Type: text/plain, Size: 290 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 /proc files.

  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: 217 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 /proc files.


[-- Attachment #6: condition.patch.makefile --]
[-- Type: text/plain, Size: 100 bytes --]

obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o

obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o


[-- Attachment #7: libipt_condition.c --]
[-- Type: text/plain, Size: 2099 bytes --]

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

#include<linux/netfilter_ipv4/ip_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 ipt_entry_match *m, unsigned int *nfcache)
{
  *nfcache |= NFC_UNKNOWN;
}

static int parse(int c, char **argv, int invert, unsigned int *flags,
		const struct ipt_entry *entry, unsigned int *nfcache,
		struct ipt_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 ipt_ip *ip,
		const struct ipt_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 ipt_ip *ip, const struct ipt_entry_match *match)
{
  const struct condition_info *info = (const struct condition_info*)match->data;

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


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


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


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

end of thread, other threads:[~2002-11-02 14:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-11-01  1:51 [NEW EXTENSION] Condition Match Stephane Ouellette
2002-11-02  0:41 ` allen
  -- strict thread matches above, loose matches on Subject: below --
2002-10-29 18:54 Stephane Ouellette
2002-10-29 23:00 ` Brad Chapman
2002-10-30  2:52 ` Robin Johnson
2002-10-30  4:43 ` allen
2002-10-30  9:04   ` Harald Welte
2002-10-30 10:34     ` Peter Surda
2002-10-30 11:59     ` Brad Chapman
2002-11-01  1:34   ` Stephane Ouellette
2002-11-02 14:47 ` 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.