All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephane Ouellette <ouellettes@videotron.ca>
To: netfilter-devel@lists.netfilter.org
Subject: [RELEASE]  Condition variable match module
Date: Tue, 11 Feb 2003 17:56:31 -0500	[thread overview]
Message-ID: <3E497F9F.5000608@videotron.ca> (raw)

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

Folks,

    here's the second version of the condition variable match module. 
 There are two separate sets of patches in order to support ip6tables.

Regards,

Stephane Ouellette.


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

diff -aruN linux-2.4.21-pre4-ac3-orig/include/linux/netfilter_ipv4/ipt_condition.h linux-2.4.21-pre4-ac3/include/linux/netfilter_ipv4/ipt_condition.h
--- linux-2.4.21-pre4-ac3-orig/include/linux/netfilter_ipv4/ipt_condition.h	Wed Dec 31 19:00:00 1969
+++ linux-2.4.21-pre4-ac3/include/linux/netfilter_ipv4/ipt_condition.h	Mon Feb 10 22:39:19 2003
@@ -0,0 +1,11 @@
+#ifndef __IPT_CONDITION_MATCH__
+#define __IPT_CONDITION_MATCH__
+
+#define CONDITION_NAME_LEN  32
+
+struct condition_info {
+  char	name[CONDITION_NAME_LEN];
+  int   invert;
+};
+
+#endif
diff -aruN linux-2.4.21-pre4-ac3-orig/net/ipv4/netfilter/ipt_condition.c linux-2.4.21-pre4-ac3/net/ipv4/netfilter/ipt_condition.c
--- linux-2.4.21-pre4-ac3-orig/net/ipv4/netfilter/ipt_condition.c	Wed Dec 31 19:00:00 1969
+++ linux-2.4.21-pre4-ac3/net/ipv4/netfilter/ipt_condition.c	Mon Feb 10 22:39:35 2003
@@ -0,0 +1,247 @@
+/*-------------------------------------------*\
+|          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>          |
+|                                             |
+|  History:                                   |
+|    2003-02-10  Second version with improved |
+|                locking and simplified code. |
+\*-------------------------------------------*/
+
+#include<linux/module.h>
+#include<linux/proc_fs.h>
+#include<linux/spinlock.h>
+#include<linux/string.h>
+#include<asm/atomic.h>
+#include<linux/netfilter_ipv4/ip_tables.h>
+#include<linux/netfilter_ipv4/ipt_condition.h>
+
+
+#ifndef CONFIG_PROC_FS
+#error  "Proc file system support is required for this module"
+#endif
+
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+
+
+struct condition_variable {
+  int       enabled;      // TRUE == 1, FALSE == 0
+  atomic_t  refcount; 
+  struct condition_variable *next;
+  struct proc_dir_entry *status_proc;
+};
+
+
+static rwlock_t list_lock;
+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)
+{
+  struct condition_variable *var = (struct condition_variable*)data;
+
+  if(offset == 0)
+  {
+    *start = buffer;
+    buffer[0] = (var->enabled) ? '1' : '0';
+    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)
+{
+  struct condition_variable *var = (struct condition_variable*)data;
+
+  if(length)
+  {
+    // Match only on the first character
+    switch(buffer[0])
+    {
+    case '0': var->enabled = 0; break;
+    case '1': var->enabled = 1;
+    }
+  }
+
+  return((int)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;
+  int    condition_status = 0;
+
+  read_lock(&list_lock);
+
+  for(var = head; var; var = var->next)
+  {
+    if(strcmp(info->name, var->status_proc->name) == 0)
+    {
+      condition_status = var->enabled;
+      break;
+    }
+  }
+
+  read_unlock(&list_lock);
+
+  return(condition_status ^ info->invert);
+}
+
+
+
+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, *newvar;
+
+  if(matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+    return(0);
+
+  // The first step is to check if the condition variable already exists.
+  read_lock(&list_lock);   // Here, a read lock is sufficient because we won't change the list
+
+  for(var = head; var; var = var->next)
+  {
+    if(strcmp(info->name, var->status_proc->name) == 0)
+    {
+      // The condition variable already exists, increment the reference count and exit
+      atomic_inc(&var->refcount);
+      read_unlock(&list_lock);
+      return(1);
+    }
+  }
+
+  read_unlock(&list_lock);
+
+  // At this point, we need to allocate a new condition variable
+  if((newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL)) == NULL)
+    return(-ENOMEM);
+
+  // Create the condition variable's proc file entry
+  if((newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition)) == NULL)
+  {
+    // There are two possibilities:
+    // 1- Another process has just created a condition variable with the same name, which is valid.
+    // 2- There was a memory allocation error.
+    kfree(newvar);
+    read_lock(&list_lock);   // Here, a read lock is sufficient because we won't change the list
+
+    for(var = head; var; var = var->next)
+    {
+      if(strcmp(info->name, var->status_proc->name) == 0)
+      {
+	// The condition variable already exists, increment the reference count and exit
+	atomic_inc(&var->refcount);
+	read_unlock(&list_lock);
+	return(1);
+      }
+    }
+
+    read_unlock(&list_lock);
+    return(-ENOMEM);
+  }
+
+  atomic_set(&newvar->refcount, 1);
+  newvar->enabled = 0;
+  newvar->status_proc->owner = THIS_MODULE;
+  newvar->status_proc->data = newvar;
+  wmb();
+  newvar->status_proc->read_proc = ipt_condition_read_info;
+  newvar->status_proc->write_proc = ipt_condition_write_info;
+
+  // It's time to insert the new element at the beginning of the list
+  write_lock(&list_lock);
+
+  newvar->next = head;
+  head = newvar;
+
+  write_unlock(&list_lock);
+
+  return(1);
+}
+
+
+static void destroy(void *matchinfo, unsigned int matchsize)
+{
+  struct condition_info *info = (struct condition_info*)matchinfo;
+  struct condition_variable *var, *prev = NULL;
+
+  if(matchsize != IPT_ALIGN(sizeof(struct condition_info)))
+    return;
+
+  write_lock(&list_lock);
+
+  for(var = head; var && strcmp(info->name, var->status_proc->name); prev = var, var = var->next);
+
+  if(var && atomic_dec_and_test(&var->refcount))
+  {
+    if(prev)
+      prev->next = var->next;
+    else
+      head = var->next;
+
+    write_unlock(&list_lock);
+    remove_proc_entry(var->status_proc->name, proc_net_condition);
+    kfree(var);
+  }
+  else
+    write_unlock(&list_lock);
+}
+
+
+static struct ipt_match condition_match = {
+  .list = { .next = NULL, .prev = NULL },
+  .name = "condition",
+  .match = &match,
+  .checkentry = &checkentry,
+  .destroy = &destroy,
+  .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+  int  errorcode;
+
+  rwlock_init(&list_lock);
+  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: 325 bytes --]

CONFIG_IP_NF_MATCH_TOS
Condition variable 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.

  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: 522 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. Multiple rules can match on a single
condition variable.

Example:
iptables -A INPUT -p tcp -m condition --condition web_ok --dport 80 -j ACCEPT

To allow this rule to match:
echo 1 > /proc/net/ipt_condition/web_ok

To disable this rule: 
echo 0 > /proc/net/ipt_condition/web_ok


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

obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o

[-- Attachment #7: condition6.patch.ipv6 --]
[-- Type: text/plain, Size: 7340 bytes --]

diff -aruN linux-2.4.21-pre4-ac3-orig/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.4.21-pre4-ac3/include/linux/netfilter_ipv6/ip6t_condition.h
--- linux-2.4.21-pre4-ac3-orig/include/linux/netfilter_ipv6/ip6t_condition.h	Wed Dec 31 19:00:00 1969
+++ linux-2.4.21-pre4-ac3/include/linux/netfilter_ipv6/ip6t_condition.h	Mon Feb 10 22:43:22 2003
@@ -0,0 +1,11 @@
+#ifndef __IP6T_CONDITION_MATCH__
+#define __IP6T_CONDITION_MATCH__
+
+#define CONDITION6_NAME_LEN  32
+
+struct condition6_info {
+  char	name[CONDITION6_NAME_LEN];
+  int   invert;
+};
+
+#endif
diff -aruN linux-2.4.21-pre4-ac3-orig/net/ipv6/netfilter/ip6t_condition.c linux-2.4.21-pre4-ac3/net/ipv6/netfilter/ip6t_condition.c
--- linux-2.4.21-pre4-ac3-orig/net/ipv6/netfilter/ip6t_condition.c	Wed Dec 31 19:00:00 1969
+++ linux-2.4.21-pre4-ac3/net/ipv6/netfilter/ip6t_condition.c	Mon Feb 10 22:43:46 2003
@@ -0,0 +1,243 @@
+/*-------------------------------------------*\
+|    Netfilter Condition Module for IPv6      |
+|                                             |
+|  Description: This module allows firewall   |
+|    rules to match using condition variables |
+|    stored in /proc files.                   |
+|                                             |
+|  Author: Stephane Ouellette     2003-02-10  |
+|          <ouellettes@videotron.ca>          |
+\*-------------------------------------------*/
+
+#include<linux/module.h>
+#include<linux/proc_fs.h>
+#include<linux/spinlock.h>
+#include<linux/string.h>
+#include<asm/atomic.h>
+#include<linux/netfilter_ipv6/ip6_tables.h>
+#include<linux/netfilter_ipv6/ip6t_condition.h>
+
+
+#ifndef CONFIG_PROC_FS
+#error  "Proc file system support is required for this module"
+#endif
+
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+
+
+struct condition_variable {
+  int       enabled;      // TRUE == 1, FALSE == 0
+  atomic_t  refcount; 
+  struct condition_variable *next;
+  struct proc_dir_entry *status_proc;
+};
+
+
+static rwlock_t list_lock;
+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)
+{
+  struct condition_variable *var = (struct condition_variable*)data;
+
+  if(offset == 0)
+  {
+    *start = buffer;
+    buffer[0] = (var->enabled) ? '1' : '0';
+    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)
+{
+  struct condition_variable *var = (struct condition_variable*)data;
+
+  if(length)
+  {
+    // Match only on the first character
+    switch(buffer[0])
+    {
+    case '0': var->enabled = 0; break;
+    case '1': var->enabled = 1;
+    }
+  }
+
+  return((int)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 condition6_info *info = (const struct condition6_info*)matchinfo;
+  struct condition_variable *var;
+  int    condition_status = 0;
+
+  read_lock(&list_lock);
+
+  for(var = head; var; var = var->next)
+  {
+    if(strcmp(info->name, var->status_proc->name) == 0)
+    {
+      condition_status = var->enabled;
+      break;
+    }
+  }
+
+  read_unlock(&list_lock);
+
+  return(condition_status ^ info->invert);
+}
+
+
+
+static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
+void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+  struct condition6_info *info = (struct condition6_info*)matchinfo;
+  struct condition_variable *var, *newvar;
+
+  if(matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
+    return(0);
+
+  // The first step is to check if the condition variable already exists.
+  read_lock(&list_lock);   // Here, a read lock is sufficient because we won't change the list
+
+  for(var = head; var; var = var->next)
+  {
+    if(strcmp(info->name, var->status_proc->name) == 0)
+    {
+      // The condition variable already exists, increment the reference count and exit
+      atomic_inc(&var->refcount);
+      read_unlock(&list_lock);
+      return(1);
+    }
+  }
+
+  read_unlock(&list_lock);
+
+  // At this point, we need to allocate a new condition variable
+  if((newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL)) == NULL)
+    return(-ENOMEM);
+
+  // Create the condition variable's proc file entry
+  if((newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition)) == NULL)
+  {
+    // There are two possibilities:
+    // 1- Another process has just created a condition variable with the same name, which is valid.
+    // 2- There was a memory allocation error.
+    kfree(newvar);
+    read_lock(&list_lock);   // Here, a read lock is sufficient because we won't change the list
+
+    for(var = head; var; var = var->next)
+    {
+      if(strcmp(info->name, var->status_proc->name) == 0)
+      {
+	// The condition variable already exists, increment the reference count and exit
+	atomic_inc(&var->refcount);
+	read_unlock(&list_lock);
+	return(1);
+      }
+    }
+
+    read_unlock(&list_lock);
+    return(-ENOMEM);
+  }
+
+  atomic_set(&newvar->refcount, 1);
+  newvar->enabled = 0;
+  newvar->status_proc->owner = THIS_MODULE;
+  newvar->status_proc->data = newvar;
+  wmb();
+  newvar->status_proc->read_proc = ipt_condition_read_info;
+  newvar->status_proc->write_proc = ipt_condition_write_info;
+
+  // It's time to insert the new element at the beginning of the list
+  write_lock(&list_lock);
+
+  newvar->next = head;
+  head = newvar;
+
+  write_unlock(&list_lock);
+
+  return(1);
+}
+
+
+static void destroy(void *matchinfo, unsigned int matchsize)
+{
+  struct condition6_info *info = (struct condition6_info*)matchinfo;
+  struct condition_variable *var, *prev = NULL;
+
+  if(matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
+    return;
+
+  write_lock(&list_lock);
+
+  for(var = head; var && strcmp(info->name, var->status_proc->name); prev = var, var = var->next);
+
+  if(var && atomic_dec_and_test(&var->refcount))
+  {
+    if(prev)
+      prev->next = var->next;
+    else
+      head = var->next;
+
+    write_unlock(&list_lock);
+    remove_proc_entry(var->status_proc->name, proc_net_condition);
+    kfree(var);
+  }
+  else
+    write_unlock(&list_lock);
+}
+
+
+static struct ip6t_match condition_match = {
+  .list = { .next = NULL, .prev = NULL },
+  .name = "condition",
+  .match = &match,
+  .checkentry = &checkentry,
+  .destroy = &destroy,
+  .me = THIS_MODULE
+};
+
+
+static int __init init(void)
+{
+  int  errorcode;
+
+  rwlock_init(&list_lock);
+  proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
+
+  if(proc_net_condition)
+  {
+    if((errorcode = ipt_register_match(&condition_match)) != 0)
+      remove_proc_entry("ip6t_condition", proc_net);
+  }
+  else errorcode = -EACCES;
+
+  return(errorcode);
+}
+
+
+static void __exit fini(void)
+{
+  ipt_unregister_match(&condition_match);
+  remove_proc_entry("ip6t_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);

[-- Attachment #8: condition6.patch.ipv6.config.in --]
[-- Type: text/plain, Size: 199 bytes --]

  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
  dep_tristate '  Condition variable match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES

[-- Attachment #9: condition6.patch.ipv6.configure.help --]
[-- Type: text/plain, Size: 328 bytes --]

CONFIG_IP6_NF_MATCH_MARK
Condition variable match support
CONFIG_IP6_NF_MATCH_CONDITION
  This option allows you to match firewall rules against condition
  variables stored in the /proc/net/ipt_condition directory.

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

[-- Attachment #10: condition6.patch.ipv6.help --]
[-- Type: text/plain, Size: 527 bytes --]

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

This patch adds CONFIG_IP6_NF_MATCH_CONDITION which allows you to
match firewall rules against condition variables stored in the
/proc/net/ip6t_condition directory. Multiple rules can match on a single
condition variable.

Example:
ip6tables -A INPUT -p tcp -m condition --condition web_ok --dport 80 -j ACCEPT

To allow this rule to match:
echo 1 > /proc/net/ip6t_condition/web_ok

To disable this rule: 
echo 0 > /proc/net/ip6t_condition/web_ok


[-- Attachment #11: condition6.patch.ipv6.makefile --]
[-- Type: text/plain, Size: 104 bytes --]

obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o

[-- Attachment #12: libip6t_condition.c --]
[-- Type: text/plain, Size: 2376 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_ipv6/ip6t_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[] = {
  { .name = "condition", .has_arg = 1, .flag = 0, .val = 'X' },
  { .name = 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 condition6_info *info = (struct condition6_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]) < CONDITION6_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 condition6_info *info = (const struct condition6_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 condition6_info *info = (const struct condition6_info*)match->data;

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


static struct ip6tables_match condition = {
  .next          = NULL,
  .name          = "condition",
  .version       = IPTABLES_VERSION,
  .size          = IP6T_ALIGN(sizeof(struct condition6_info)),
  .userspacesize = IP6T_ALIGN(sizeof(struct condition6_info)),
  .help          = &help,
  .init          = &init,
  .parse         = &parse,
  .final_check   = &final_check,
  .print         = &print,
  .save          = &save,
  .extra_opts    = opts
};


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


[-- Attachment #13: libipt_condition.c --]
[-- Type: text/plain, Size: 2352 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[] = {
  { .name = "condition", .has_arg = 1, .flag = 0, .val = 'X' },
  { .name = 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]) < CONDITION_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 = {
  .next          = NULL,
  .name          = "condition",
  .version       = IPTABLES_VERSION,
  .size          = IPT_ALIGN(sizeof(struct condition_info)),
  .userspacesize = IPT_ALIGN(sizeof(struct condition_info)),
  .help          = &help,
  .init          = &init,
  .parse         = &parse,
  .final_check   = &final_check,
  .print         = &print,
  .save          = &save,
  .extra_opts    = opts
};


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

[-- Attachment #14: .condition-test --]
[-- Type: text/plain, Size: 124 bytes --]

#!/bin/sh
# True if condition is applied.
[ -f $KERNEL_DIR/include/linux/netfilter_ipv4/ipt_condition.h ] && echo condition

[-- Attachment #15: .condition-test6 --]
[-- Type: text/plain, Size: 126 bytes --]

#!/bin/sh
# True if condition6 is applied.
[ -f $KERNEL_DIR/include/linux/netfilter_ipv6/ip6t_condition.h ] && echo condition

             reply	other threads:[~2003-02-11 22:56 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-02-11 22:56 Stephane Ouellette [this message]
2003-02-13  9:53 ` [RELEASE] Condition variable match module Harald Welte

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3E497F9F.5000608@videotron.ca \
    --to=ouellettes@videotron.ca \
    --cc=netfilter-devel@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.