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