From: Massimiliano Hofer <max@nucleus.it>
To: netfilter-devel@lists.netfilter.org
Subject: condition for 2.6.16
Date: Thu, 20 Apr 2006 19:19:12 +0200 [thread overview]
Message-ID: <200604201919.19246.max@nucleus.it> (raw)
[-- Attachment #1: Type: text/plain, Size: 665 bytes --]
Hi,
I wrote here some time ago about condition and Krzysztof told me it wasn't
supposed to work.
I tested it and it seemed to work, but reading the code I agree that it
shouldn't have. :)
I find this extension very useful, so I did a complete porting to 2.6.16
complete with XT. I fixed various things (mostly fossils of the 2.4 era) in
the process and it works in my test environment.
I am about to test it in a few high load machines, but I'd appreciate if
someone else could have a look at it.
What are the next steps in order to have it included in the core extension and
finally merged in the kernel?
--
Saluti,
Massimiliano Hofer
Nucleus
[-- Attachment #2: condition.patch --]
[-- Type: text/x-diff, Size: 13594 bytes --]
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/help patch-o-matic-ng-20060419.new/patchlets/condition/help
--- patch-o-matic-ng-20060419/patchlets/condition/help 2003-12-20 17:19:17.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/help 2006-04-20 18:36:22.000000000 +0200
@@ -7,8 +7,10 @@
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
+echo 1 > /proc/net/nf_condition/web_ok
To disable this rule:
-echo 0 > /proc/net/ipt_condition/web_ok
+echo 0 > /proc/net/nf_condition/web_ok
+
+NB: it was /proc/net/ipt_condition on 2.4.
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/info patch-o-matic-ng-20060419.new/patchlets/condition/info
--- patch-o-matic-ng-20060419/patchlets/condition/info 2004-02-20 00:25:33.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/info 2006-04-20 18:52:56.000000000 +0200
@@ -1,4 +1,4 @@
-Author: Stephane Ouellette <ouellettes@videotron.ca>
+Author: Stephane Ouellette <ouellettes@videotron.ca> and Massimiliano Hofer <max@nucleus.it>
Status: ItWorksForMe(tm)
+Requires: linux == 2.4 || linux >= 2.6.16
Repository: extra
-Requires: linux < 2.6.0
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/Documentation/Configure.help.ladd patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/Documentation/Configure.help.ladd
--- patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/Documentation/Configure.help.ladd 1970-01-01 01:00:00.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/Documentation/Configure.help.ladd 2006-04-20 17:24:15.000000000 +0200
@@ -0,0 +1,6 @@
+NETFILTER_XT_MATCH_CONDITION
+ This option allows you to match firewall rules against condition
+ variables stored in the /proc/net/nf_condition directory.
+
+ If you want to compile it as a module, say M here and read
+ Documentation/modules.txt. If unsure, say `N'.
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/include/linux/netfilter/xt_condition.h patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/include/linux/netfilter/xt_condition.h
--- patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/include/linux/netfilter/xt_condition.h 1970-01-01 01:00:00.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/include/linux/netfilter/xt_condition.h 2006-04-20 17:18:11.000000000 +0200
@@ -0,0 +1,11 @@
+#ifndef _XT_CONDITION_H
+#define _XT_CONDITION_H
+
+#define CONDITION_NAME_LEN 32
+
+struct condition_info {
+ char name[CONDITION_NAME_LEN];
+ int invert;
+};
+
+#endif /* _XT_CONDITION_H */
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/Kconfig.ladd patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/Kconfig.ladd
--- patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/Kconfig.ladd 1970-01-01 01:00:00.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/Kconfig.ladd 2006-04-20 17:22:13.000000000 +0200
@@ -0,0 +1,9 @@
+config NETFILTER_XT_MATCH_CONDITION
+ tristate '"condition" match support'
+ depends on NETFILTER_XTABLES
+ help
+ 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'.
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/Makefile.ladd patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/Makefile.ladd
--- patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/Makefile.ladd 1970-01-01 01:00:00.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/Makefile.ladd 2006-04-20 18:34:08.000000000 +0200
@@ -0,0 +1,2 @@
+obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
+obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_condition.o
diff -Nru patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/xt_condition.c patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/xt_condition.c
--- patch-o-matic-ng-20060419/patchlets/condition/linux-2.6.16/net/netfilter/xt_condition.c 1970-01-01 01:00:00.000000000 +0100
+++ patch-o-matic-ng-20060419.new/patchlets/condition/linux-2.6.16/net/netfilter/xt_condition.c 2006-04-20 17:21:07.000000000 +0200
@@ -0,0 +1,318 @@
+/*-------------------------------------------*\
+| 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> |
+| Massimiliano Hofer 2006-05-15 |
+| <max@nucleus.it> |
+| |
+| History: |
+| 2003-02-10 Second version with improved |
+| locking and simplified code. |
+| 2006-05-15 2.6.16 adaptations. |
+| Locking overhaul. |
+| Various bug fixes. |
+| |
+| This software is distributed under the |
+| terms of the GNU GPL. |
+\*-------------------------------------------*/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <asm/semaphore.h>
+#include <linux/string.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <linux/netfilter/x_tables.h>
+#include <linux/netfilter/xt_condition.h>
+
+#ifndef CONFIG_PROC_FS
+#error "Proc file system support is required for this module"
+#endif
+
+/* Defaults, these can be overridden on the module command-line. */
+static unsigned int condition_list_perms = 0644;
+
+MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca> and Massimiliano Hofer <max@nucleus.it>");
+MODULE_DESCRIPTION("Allows rules to match against condition variables");
+MODULE_LICENSE("GPL");
+module_param(condition_list_perms, uint, 0400);
+MODULE_PARM_DESC(condition_list_perms,"permissions on /proc/net/nf_condition/* files");
+MODULE_ALIAS("ipt_condition");
+MODULE_ALIAS("ip6t_condition");
+
+struct condition_variable {
+ struct condition_variable *next;
+ struct proc_dir_entry *status_proc;
+ atomic_t refcount;
+ int enabled; /* TRUE == 1, FALSE == 0 */
+};
+
+/* list_lock is a spin lock used to synchronize user and bottom half contexts. */
+/* It is used only for short period requiring reads from BH or */
+/* read/write from user. */
+/* proc_lock is a user context only semaphor used for more extensive operations */
+/* during insertion and deletion of rules. It must never be acquired by */
+/* by someone already having a list_lock, but you can obtain a list_lock */
+/* while having a proc_lock. */
+static DEFINE_SPINLOCK(list_lock);
+static DECLARE_MUTEX(proc_lock);
+
+static struct condition_variable *head = NULL;
+static struct proc_dir_entry *proc_net_condition = NULL;
+
+
+static int
+xt_condition_read_info(char __user *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+
+ buffer[0] = (var->enabled) ? '1' : '0';
+ buffer[1] = '\n';
+ if (length>=2)
+ *eof = 1;
+
+ return 2;
+}
+
+
+static int
+xt_condition_write_info(struct file *file, const char __user *buffer,
+ unsigned long length, void *data)
+{
+ struct condition_variable *var =
+ (struct condition_variable *) data;
+ char newval;
+
+ if (length>0) {
+ if (get_user(newval, buffer))
+ return -EFAULT;
+ /* Match only on the first character */
+ switch (newval) {
+ case '0':
+ var->enabled = 0;
+ break;
+ case '1':
+ var->enabled = 1;
+ break;
+ }
+ }
+
+ 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,
+ unsigned int protoff, int *hotdrop)
+{
+ const struct condition_info *info =
+ (const struct condition_info *) matchinfo;
+ struct condition_variable *var;
+ int condition_status = 0;
+
+ spin_lock_bh(&list_lock);
+
+ for (var = head; var != NULL; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ condition_status = var->enabled;
+ break;
+ }
+ }
+
+ spin_unlock_bh(&list_lock);
+
+ return condition_status ^ info->invert;
+}
+
+
+
+static int
+checkentry(const char *tablename, const void *ip,
+ void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
+{
+ static const char * const forbidden_names[]={ "", ".", ".." };
+ struct condition_info *info = (struct condition_info *) matchinfo;
+ struct condition_variable *var, *newvar;
+
+ int i;
+
+ if (matchsize != XT_ALIGN(sizeof(struct condition_info)))
+ return 0;
+
+ /* We don't want a '/' in a proc file name. */
+ for(i=0; i < CONDITION_NAME_LEN && info->name[i] != '\0'; i++)
+ if(info->name[i] == '/')
+ return 0;
+ /* We can't handle file names longer than CONDITION_NAME_LEN and */
+ /* we want a NULL terminated string. */
+ if(i == CONDITION_NAME_LEN)
+ return 0;
+
+ /* We don't want certain reserved names. */
+ for(i=0; i < sizeof(forbidden_names)/sizeof(char *); i++)
+ if(strcmp(info->name, forbidden_names[i])==0)
+ return 0;
+
+ /* The first step is to check if the condition variable already exists. */
+ /* This lock is to prevent other processes performing the same check and */
+ /* modify code and from altering proc entries. */
+ down(&proc_lock);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ up(&proc_lock);
+ return 1;
+ }
+ }
+
+ /* At this point, we need to allocate a new condition variable */
+ newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
+
+ if (!newvar) {
+ up(&proc_lock);
+ return -ENOMEM;
+ }
+
+ /* Create the condition variable's proc file entry */
+ newvar->status_proc = create_proc_entry(info->name, condition_list_perms, proc_net_condition);
+
+ if (!newvar->status_proc) {
+ /*
+ * There are two possibilities:
+ * 1- Another condition variable with the same name has been created, which is valid.
+ * 2- There was a memory allocation error.
+ */
+ kfree(newvar);
+
+ for (var = head; var; var = var->next) {
+ if (strcmp(info->name, var->status_proc->name) == 0) {
+ atomic_inc(&var->refcount);
+ up(&proc_lock);
+ return 1;
+ }
+ }
+
+ up(&proc_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 = xt_condition_read_info;
+ newvar->status_proc->write_proc = xt_condition_write_info;
+
+ /* There used to be a lock here, but a memory barrier should be good enough. */
+ newvar->next = head;
+ wmb();
+ head = newvar;
+
+ up(&proc_lock);
+
+ return 1;
+}
+
+
+static void
+destroy(void *matchinfo, unsigned int matchsize)
+{
+ struct condition_info *info = (struct condition_info *) matchinfo;
+ struct condition_variable *var, *prev;
+
+ if (matchsize != XT_ALIGN(sizeof(struct condition_info)))
+ return;
+
+ down(&proc_lock);
+
+ for (prev = NULL, var = head; var && strcmp(info->name, var->status_proc->name);
+ prev = var, var = var->next);
+
+ if (var && atomic_dec_and_test(&var->refcount)) {
+ /* This lock is to prevent clashing with netfilter matching. */
+ spin_lock_bh(&list_lock);
+ if (prev)
+ prev->next = var->next;
+ else
+ head = var->next;
+ spin_unlock_bh(&list_lock);
+
+ remove_proc_entry(var->status_proc->name, proc_net_condition);
+ kfree(var);
+ }
+
+ up(&proc_lock);
+}
+
+
+static struct xt_match condition_match = {
+ .name = "condition",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+static struct xt_match condition6_match = {
+ .name = "condition",
+ .match = &match,
+ .checkentry = &checkentry,
+ .destroy = &destroy,
+ .me = THIS_MODULE
+};
+
+static int __init
+init(void)
+{
+ int errorcode;
+
+ spin_lock_init(&list_lock);
+
+ proc_net_condition = proc_mkdir("nf_condition", proc_net);
+ if (!proc_net_condition) {
+ errorcode = -EACCES;
+ goto remove_proc;
+ }
+
+ errorcode = xt_register_match(AF_INET, &condition_match);
+ if (errorcode)
+ goto remove_inet;
+
+ errorcode = xt_register_match(AF_INET6, &condition6_match);
+ if (errorcode)
+ goto remove_inet6;
+ return 0;
+
+remove_inet6:
+ xt_unregister_match(AF_INET6, &condition6_match);
+remove_inet:
+ xt_unregister_match(AF_INET, &condition_match);
+remove_proc:
+ remove_proc_entry("nf_condition", proc_net);
+
+ return errorcode;
+}
+
+
+static void __exit
+fini(void)
+{
+ xt_unregister_match(AF_INET6, &condition6_match);
+ xt_unregister_match(AF_INET, &condition_match);
+ remove_proc_entry("nf_condition", proc_net);
+}
+
+module_init(init);
+module_exit(fini);
next reply other threads:[~2006-04-20 17:19 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-04-20 17:19 Massimiliano Hofer [this message]
2006-04-20 18:49 ` condition for 2.6.16 Patrick McHardy
2006-04-20 19:39 ` Massimiliano Hofer
2006-04-20 19:44 ` Martijn Lievaart
2006-04-20 22:47 ` Patrick McHardy
2006-04-20 23:26 ` Massimiliano Hofer
2006-04-21 0:41 ` Gerd v. Egidy
2006-04-21 0:48 ` Gerd v. Egidy
2006-04-21 9:29 ` Amin Azez
2006-04-23 13:47 ` Simon Lodal
2006-04-28 7:12 ` Patrick McHardy
2006-04-28 10:46 ` Massimiliano Hofer
2006-04-28 11:06 ` Patrick McHardy
2006-04-28 12:44 ` Massimiliano Hofer
2006-04-28 12:58 ` Jozsef Kadlecsik
2006-04-28 13:07 ` Patrick McHardy
2006-04-28 15:18 ` KOVACS Krisztian
2006-04-28 15:34 ` Patrick McHardy
2006-04-29 0:53 ` Massimiliano Hofer
2006-04-29 2:56 ` Patrick McHardy
2006-04-29 15:36 ` Massimiliano Hofer
2006-04-28 13:18 ` Massimiliano Hofer
2006-04-28 13:09 ` Patrick McHardy
2006-04-28 13:26 ` Massimiliano Hofer
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=200604201919.19246.max@nucleus.it \
--to=max@nucleus.it \
--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.