initial import (Boeing r1752, NRL r878)
This commit is contained in:
commit
f8f46d28be
394 changed files with 99738 additions and 0 deletions
62
kernel/core-kernel-2.6.38/Makefile
Normal file
62
kernel/core-kernel-2.6.38/Makefile
Normal file
|
@ -0,0 +1,62 @@
|
|||
VERSION := 2.6.38
|
||||
TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2
|
||||
|
||||
SUBVERSION := -core
|
||||
REVISION := 1.0
|
||||
|
||||
PATCHDIR := patches
|
||||
PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch))
|
||||
|
||||
CONFIG := config.core
|
||||
|
||||
DEPDEBS := linux-source kernel-package po-debconf gettext
|
||||
|
||||
CONCURRENCY_LEVEL := 2
|
||||
|
||||
MAINTAINER ?= Tom Goff
|
||||
EMAIL ?= thomas.goff@boeing.com
|
||||
|
||||
MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \
|
||||
--append-to-version $(SUBVERSION) --revision $(REVISION)
|
||||
|
||||
.PHONY: build
|
||||
build: debcheck defaultconfig patch
|
||||
export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \
|
||||
KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && \
|
||||
if [ -f ../$(CONFIG) ]; then \
|
||||
cat ../$(CONFIG) >> .config; \
|
||||
fi && \
|
||||
fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch
|
||||
|
||||
.PHONY: debcheck
|
||||
debcheck:
|
||||
for d in $(DEPDEBS); do \
|
||||
if ! dpkg-query -s $$d > /dev/null 2>&1; then \
|
||||
echo ERROR: build dependency not installed: $$d >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.PHONY: defaultconfig
|
||||
defaultconfig: linux-source-$(VERSION)
|
||||
export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure
|
||||
|
||||
.PHONY: patch
|
||||
patch: linux-source-$(VERSION) patch-stamp
|
||||
patch-stamp: $(PATCHES)
|
||||
for p in $^; do \
|
||||
if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \
|
||||
echo ERROR: applying patch failed: $$p >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
linux-source-$(VERSION): $(TARBALL)
|
||||
tar -xjf $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf linux-source-$(VERSION) patch-stamp
|
9
kernel/core-kernel-2.6.38/README.txt
Normal file
9
kernel/core-kernel-2.6.38/README.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
Author: Tom Goff <thomas.goff@boeing.com>
|
||||
|
||||
The Makefile is basically a wrapper around the make-kpkg command that
|
||||
simplifies building kernel packages. Running make will do some basic
|
||||
dependency checks then build architecture appropriate kernel packages that
|
||||
include changes from the patches directory. The nfnetlink patch is what
|
||||
virtualizes the netfilter queue mechanism; the flow-cache patch allows using
|
||||
IPsec between network namespaces; the ifindex patch virtualizes network
|
||||
interface index numbers.
|
1
kernel/core-kernel-2.6.38/config.core
Normal file
1
kernel/core-kernel-2.6.38/config.core
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_XFRM_STATISTICS=y
|
|
@ -0,0 +1,31 @@
|
|||
Only use the flow cache for the initial network namespace.
|
||||
|
||||
The flow cache is not per netns and its entries do not include what
|
||||
namespace they are valid for. This causes problems when transformed
|
||||
traffic is sent between namespaces.
|
||||
---
|
||||
net/core/flow.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/net/core/flow.c b/net/core/flow.c
|
||||
index 127c8a7..890510f 100644
|
||||
--- a/net/core/flow.c
|
||||
+++ b/net/core/flow.c
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <net/flow.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/security.h>
|
||||
+#include <net/net_namespace.h>
|
||||
|
||||
struct flow_cache_entry {
|
||||
union {
|
||||
@@ -227,6 +228,9 @@ flow_cache_lookup(struct net *net, struct flowi *key, u16 family, u8 dir,
|
||||
if (!fcp->hash_table)
|
||||
goto nocache;
|
||||
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ goto nocache;
|
||||
+
|
||||
if (fcp->hash_rnd_recalc)
|
||||
flow_new_hash_rnd(fc, fcp);
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
Make network device ifindex sequential per network namespace.
|
||||
|
||||
---
|
||||
include/net/net_namespace.h | 2 ++
|
||||
net/core/dev.c | 13 ++++++-------
|
||||
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 1bf812b..6ee0db4 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -57,6 +57,8 @@ struct net {
|
||||
struct sock *rtnl; /* rtnetlink socket */
|
||||
struct sock *genl_sock;
|
||||
|
||||
+ int ifindex;
|
||||
+
|
||||
struct list_head dev_base_head;
|
||||
struct hlist_head *dev_name_head;
|
||||
struct hlist_head *dev_index_head;
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index 6561021..764a190 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4975,12 +4975,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
*/
|
||||
static int dev_new_index(struct net *net)
|
||||
{
|
||||
- static int ifindex;
|
||||
for (;;) {
|
||||
- if (++ifindex <= 0)
|
||||
- ifindex = 1;
|
||||
- if (!__dev_get_by_index(net, ifindex))
|
||||
- return ifindex;
|
||||
+ if (++net->ifindex <= 0)
|
||||
+ net->ifindex = 1;
|
||||
+ if (!__dev_get_by_index(net, net->ifindex))
|
||||
+ return net->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5918,8 +5917,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
- /* If there is an ifindex conflict assign a new one */
|
||||
- if (__dev_get_by_index(net, dev->ifindex)) {
|
||||
+ /* Assign a new ifindex */
|
||||
+ {
|
||||
int iflink = (dev->iflink == dev->ifindex);
|
||||
dev->ifindex = dev_new_index(net);
|
||||
if (iflink)
|
1662
kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch
Normal file
1662
kernel/core-kernel-2.6.38/patches/00-linux-2.6.38.nfnetlink.patch
Normal file
File diff suppressed because it is too large
Load diff
62
kernel/core-kernel-3.0/Makefile
Normal file
62
kernel/core-kernel-3.0/Makefile
Normal file
|
@ -0,0 +1,62 @@
|
|||
VERSION := 3.0.0
|
||||
TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2
|
||||
|
||||
SUBVERSION := -core
|
||||
REVISION := 1.0
|
||||
|
||||
PATCHDIR := patches
|
||||
PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch))
|
||||
|
||||
CONFIG := config.core
|
||||
|
||||
DEPDEBS := linux-source kernel-package po-debconf gettext
|
||||
|
||||
CONCURRENCY_LEVEL := 8
|
||||
|
||||
MAINTAINER ?= Tom Goff
|
||||
EMAIL ?= thomas.goff@boeing.com
|
||||
|
||||
MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \
|
||||
--append-to-version $(SUBVERSION) --revision $(REVISION)
|
||||
|
||||
.PHONY: build
|
||||
build: debcheck defaultconfig patch
|
||||
export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \
|
||||
KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && \
|
||||
if [ -f ../$(CONFIG) ]; then \
|
||||
cat ../$(CONFIG) >> .config; \
|
||||
fi && \
|
||||
fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch
|
||||
|
||||
.PHONY: debcheck
|
||||
debcheck:
|
||||
for d in $(DEPDEBS); do \
|
||||
if ! dpkg-query -s $$d > /dev/null 2>&1; then \
|
||||
echo ERROR: build dependency not installed: $$d >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.PHONY: defaultconfig
|
||||
defaultconfig: linux-source-$(VERSION)
|
||||
export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure
|
||||
|
||||
.PHONY: patch
|
||||
patch: linux-source-$(VERSION) patch-stamp
|
||||
patch-stamp: $(PATCHES)
|
||||
for p in $^; do \
|
||||
if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \
|
||||
echo ERROR: applying patch failed: $$p >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
linux-source-$(VERSION): $(TARBALL)
|
||||
tar -xjf $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf linux-source-$(VERSION) patch-stamp
|
9
kernel/core-kernel-3.0/README.txt
Normal file
9
kernel/core-kernel-3.0/README.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
Author: Tom Goff <thomas.goff@boeing.com>
|
||||
|
||||
The Makefile is basically a wrapper around the make-kpkg command that
|
||||
simplifies building kernel packages. Running make will do some basic
|
||||
dependency checks then build architecture appropriate kernel packages that
|
||||
include changes from the patches directory. The nfnetlink patch is what
|
||||
virtualizes the netfilter queue mechanism; the flow-cache patch allows using
|
||||
IPsec between network namespaces; the ifindex patch virtualizes network
|
||||
interface index numbers.
|
1
kernel/core-kernel-3.0/config.core
Normal file
1
kernel/core-kernel-3.0/config.core
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_XFRM_STATISTICS=y
|
49
kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch
Normal file
49
kernel/core-kernel-3.0/patches/00-linux-3.0.flow-cache.patch
Normal file
|
@ -0,0 +1,49 @@
|
|||
commit 0542b69e2c57fc9668ce6a03155bea6e1f557901
|
||||
Author: dpward <david.ward@ll.mit.edu>
|
||||
Date: Wed Aug 31 06:05:27 2011 +0000
|
||||
|
||||
net: Make flow cache namespace-aware
|
||||
|
||||
flow_cache_lookup will return a cached object (or null pointer) that the
|
||||
resolver (i.e. xfrm_policy_lookup) previously found for another namespace
|
||||
using the same key/family/dir. Instead, make the namespace part of what
|
||||
identifies entries in the cache.
|
||||
|
||||
As before, flow_entry_valid will return 0 for entries where the namespace
|
||||
has been deleted, and they will be removed from the cache the next time
|
||||
flow_cache_gc_task is run.
|
||||
|
||||
Reported-by: Andrew Dickinson <whydna@whydna.net>
|
||||
Signed-off-by: David Ward <david.ward@ll.mit.edu>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
diff --git a/net/core/flow.c b/net/core/flow.c
|
||||
index bf32c33..47b6d26 100644
|
||||
--- a/net/core/flow.c
|
||||
+++ b/net/core/flow.c
|
||||
@@ -30,6 +30,7 @@ struct flow_cache_entry {
|
||||
struct hlist_node hlist;
|
||||
struct list_head gc_list;
|
||||
} u;
|
||||
+ struct net *net;
|
||||
u16 family;
|
||||
u8 dir;
|
||||
u32 genid;
|
||||
@@ -232,7 +233,8 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
|
||||
|
||||
hash = flow_hash_code(fc, fcp, key);
|
||||
hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) {
|
||||
- if (tfle->family == family &&
|
||||
+ if (tfle->net == net &&
|
||||
+ tfle->family == family &&
|
||||
tfle->dir == dir &&
|
||||
flow_key_compare(key, &tfle->key) == 0) {
|
||||
fle = tfle;
|
||||
@@ -246,6 +248,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
|
||||
|
||||
fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
|
||||
if (fle) {
|
||||
+ fle->net = net;
|
||||
fle->family = family;
|
||||
fle->dir = dir;
|
||||
memcpy(&fle->key, key, sizeof(*key));
|
51
kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch
Normal file
51
kernel/core-kernel-3.0/patches/00-linux-3.0.ifindex.patch
Normal file
|
@ -0,0 +1,51 @@
|
|||
commit 7da7dfcb787d77929c15d5b7127c816ee16f1ede
|
||||
Author: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Fri Dec 16 17:39:00 2011 -0800
|
||||
|
||||
Make network device ifindex sequential per network namespace.
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 3bb6fa0..2fd53da 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -62,6 +62,8 @@ struct net {
|
||||
struct sock *rtnl; /* rtnetlink socket */
|
||||
struct sock *genl_sock;
|
||||
|
||||
+ int ifindex;
|
||||
+
|
||||
struct list_head dev_base_head;
|
||||
struct hlist_head *dev_name_head;
|
||||
struct hlist_head *dev_index_head;
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index 6ba50a1..ba95aa5 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -5260,12 +5260,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
*/
|
||||
static int dev_new_index(struct net *net)
|
||||
{
|
||||
- static int ifindex;
|
||||
for (;;) {
|
||||
- if (++ifindex <= 0)
|
||||
- ifindex = 1;
|
||||
- if (!__dev_get_by_index(net, ifindex))
|
||||
- return ifindex;
|
||||
+ if (++net->ifindex <= 0)
|
||||
+ net->ifindex = 1;
|
||||
+ if (!__dev_get_by_index(net, net->ifindex))
|
||||
+ return net->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6277,8 +6276,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
- /* If there is an ifindex conflict assign a new one */
|
||||
- if (__dev_get_by_index(net, dev->ifindex)) {
|
||||
+ /* Assign a new ifindex */
|
||||
+ {
|
||||
int iflink = (dev->iflink == dev->ifindex);
|
||||
dev->ifindex = dev_new_index(net);
|
||||
if (iflink)
|
|
@ -0,0 +1,351 @@
|
|||
From 4b819adab7892f61a96bab1e36e5d9a74018432b Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Tue, 3 Jan 2012 14:39:04 -0800
|
||||
Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per
|
||||
netns.
|
||||
|
||||
This allows subsystems to create per-netns entries.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/linux/netfilter.h | 5 ----
|
||||
include/net/net_namespace.h | 3 ++
|
||||
net/netfilter/core.c | 35 +++++++++++++++++++++++-------
|
||||
net/netfilter/nf_log.c | 33 +++++++++++++++++++++++++---
|
||||
net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++---
|
||||
net/netfilter/nfnetlink_log.c | 44 ++++++++++++++++++++++++++-----------
|
||||
net/netfilter/nfnetlink_queue.c | 45 ++++++++++++++++++++++++++------------
|
||||
7 files changed, 148 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
|
||||
index 857f502..b4e02fb 100644
|
||||
--- a/include/linux/netfilter.h
|
||||
+++ b/include/linux/netfilter.h
|
||||
@@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
#endif
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-#include <linux/proc_fs.h>
|
||||
-extern struct proc_dir_entry *proc_net_netfilter;
|
||||
-#endif
|
||||
-
|
||||
#else /* !CONFIG_NETFILTER */
|
||||
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 3bb6fa0..cf126ef 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -84,6 +84,9 @@ struct net {
|
||||
struct netns_dccp dccp;
|
||||
#endif
|
||||
#ifdef CONFIG_NETFILTER
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ struct proc_dir_entry *proc_net_netfilter;
|
||||
+#endif
|
||||
struct netns_xt xt;
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
struct netns_ct ct;
|
||||
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
|
||||
index afca6c7..9d9b103 100644
|
||||
--- a/net/netfilter/core.c
|
||||
+++ b/net/netfilter/core.c
|
||||
@@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
||||
EXPORT_SYMBOL(nf_conntrack_destroy);
|
||||
#endif /* CONFIG_NF_CONNTRACK */
|
||||
|
||||
+static int __net_init netfilter_net_init(struct net *net)
|
||||
+{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
-struct proc_dir_entry *proc_net_netfilter;
|
||||
-EXPORT_SYMBOL(proc_net_netfilter);
|
||||
+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter",
|
||||
+ net->proc_net);
|
||||
+ if (!net->proc_net_netfilter) {
|
||||
+ pr_err("%s: cannot create netfilter proc entry\n", __func__);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
#endif
|
||||
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ proc_net_remove(net, "netfilter");
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_net_ops = {
|
||||
+ .init = netfilter_net_init,
|
||||
+ .exit = netfilter_net_exit,
|
||||
+};
|
||||
+
|
||||
void __init netfilter_init(void)
|
||||
{
|
||||
int i, h;
|
||||
+
|
||||
+ if (register_pernet_subsys(&netfilter_net_ops))
|
||||
+ panic("%s: failed to register per netns operations", __func__);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
|
||||
for (h = 0; h < NF_MAX_HOOKS; h++)
|
||||
INIT_LIST_HEAD(&nf_hooks[i][h]);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
|
||||
- if (!proc_net_netfilter)
|
||||
- panic("cannot create netfilter proc entry");
|
||||
-#endif
|
||||
-
|
||||
if (netfilter_queue_init() < 0)
|
||||
panic("cannot initialize nf_queue");
|
||||
if (netfilter_log_init() < 0)
|
||||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
|
||||
index ce0c406..ccc15d6 100644
|
||||
--- a/net/netfilter/nf_log.c
|
||||
+++ b/net/netfilter/nf_log.c
|
||||
@@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
-int __init netfilter_log_init(void)
|
||||
+static int __net_init netfilter_log_net_init(struct net *net)
|
||||
{
|
||||
- int i, r;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_log", S_IRUGO,
|
||||
- proc_net_netfilter, &nflog_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nflog_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_log", net->proc_net_netfilter);
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_log_net_ops = {
|
||||
+ .init = netfilter_log_net_init,
|
||||
+ .exit = netfilter_log_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_log_init(void)
|
||||
+{
|
||||
+ int i, r;
|
||||
+
|
||||
+ r = register_pernet_subsys(&netfilter_log_net_ops);
|
||||
+ if (r) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
/* Errors will trigger panic, unroll on error is unnecessary. */
|
||||
r = netfilter_log_sysctl_init();
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index 99ffd28..ecb84a3 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = {
|
||||
};
|
||||
#endif /* PROC_FS */
|
||||
|
||||
-
|
||||
-int __init netfilter_queue_init(void)
|
||||
+static int __net_init netfilter_queue_net_init(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_queue", S_IRUGO,
|
||||
- proc_net_netfilter, &nfqueue_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nfqueue_file_ops))
|
||||
+ return -ENOMEM;
|
||||
#endif
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void __net_exit netfilter_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_queue_net_ops = {
|
||||
+ .init = netfilter_queue_net_init,
|
||||
+ .exit = netfilter_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_queue_init(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = register_pernet_subsys(&netfilter_queue_net_ops);
|
||||
+ if (err)
|
||||
+ pr_err("%s: cannot initialize per netns operations\n",
|
||||
+ __func__);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
|
||||
index 66b2c54..e4c3c1e 100644
|
||||
--- a/net/netfilter/nfnetlink_log.c
|
||||
+++ b/net/netfilter/nfnetlink_log.c
|
||||
@@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_log_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_log", 0440,
|
||||
+ net->proc_net_netfilter, &nful_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_log_net_ops = {
|
||||
+ .init = nfnetlink_log_net_init,
|
||||
+ .exit = nfnetlink_log_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_log_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_log_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void)
|
||||
goto cleanup_subsys;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_log", 0440,
|
||||
- proc_net_netfilter, &nful_file_ops))
|
||||
- goto cleanup_logger;
|
||||
-#endif
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_logger:
|
||||
- nf_log_unregister(&nfulnl_logger);
|
||||
-#endif
|
||||
cleanup_subsys:
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
cleanup_netlink_notifier:
|
||||
@@ -996,9 +1017,6 @@ cleanup_netlink_notifier:
|
||||
static void __exit nfnetlink_log_fini(void)
|
||||
{
|
||||
nf_log_unregister(&nfulnl_logger);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
||||
}
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index a80b0cb..b615da5 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_queue", 0440,
|
||||
+ net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
+ .init = nfnetlink_queue_net_init,
|
||||
+ .exit = nfnetlink_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void)
|
||||
goto cleanup_netlink_notifier;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_queue", 0440,
|
||||
- proc_net_netfilter, &nfqnl_file_ops))
|
||||
- goto cleanup_subsys;
|
||||
-#endif
|
||||
-
|
||||
register_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_subsys:
|
||||
- nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
-#endif
|
||||
cleanup_netlink_notifier:
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
return status;
|
||||
@@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void)
|
||||
{
|
||||
nf_unregister_queue_handlers(&nfqh);
|
||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
|
||||
--
|
||||
1.7.5.4
|
||||
|
|
@ -0,0 +1,516 @@
|
|||
From dd504f32d24e9f239d429204c43a5c500c9853c6 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Tue, 3 Jan 2012 15:52:32 -0800
|
||||
Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support.
|
||||
|
||||
Make nfnetlink_queue network namespace aware including a per-netns
|
||||
/proc/net/netfilter/nfnetlink_queue file.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 6 ++
|
||||
include/net/netfilter/nf_queue.h | 3 +-
|
||||
include/net/netns/nfqnl.h | 14 ++++
|
||||
net/ipv4/netfilter/ip_queue.c | 6 ++-
|
||||
net/ipv6/netfilter/ip6_queue.c | 6 ++-
|
||||
net/netfilter/nf_queue.c | 12 +++-
|
||||
net/netfilter/nfnetlink_queue.c | 138 +++++++++++++++++++-------------------
|
||||
7 files changed, 112 insertions(+), 73 deletions(-)
|
||||
create mode 100644 include/net/netns/nfqnl.h
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index cf126ef..4b6f04a 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <net/netns/conntrack.h>
|
||||
#endif
|
||||
#include <net/netns/xfrm.h>
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+#include <net/netns/nfqnl.h>
|
||||
+#endif
|
||||
|
||||
struct proc_dir_entry;
|
||||
struct net_device;
|
||||
@@ -93,6 +96,9 @@ struct net {
|
||||
#endif
|
||||
struct sock *nfnl;
|
||||
struct sock *nfnl_stash;
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+ struct netns_nfqnl nfqnl;
|
||||
+#endif
|
||||
#endif
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
|
||||
index 252fd10..3e5bde8 100644
|
||||
--- a/include/net/netfilter/nf_queue.h
|
||||
+++ b/include/net/netfilter/nf_queue.h
|
||||
@@ -19,7 +19,8 @@ struct nf_queue_entry {
|
||||
|
||||
/* Packet queuing */
|
||||
struct nf_queue_handler {
|
||||
- int (*outfn)(struct nf_queue_entry *entry,
|
||||
+ int (*outfn)(struct net *net,
|
||||
+ struct nf_queue_entry *entry,
|
||||
unsigned int queuenum);
|
||||
char *name;
|
||||
};
|
||||
diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h
|
||||
new file mode 100644
|
||||
index 0000000..0fe7fbe
|
||||
--- /dev/null
|
||||
+++ b/include/net/netns/nfqnl.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+#ifndef __NETNS_NFQNL_H
|
||||
+#define __NETNS_NFQNL_H
|
||||
+
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/list.h>
|
||||
+
|
||||
+#define NFQNL_INSTANCE_BUCKETS 16
|
||||
+
|
||||
+struct netns_nfqnl {
|
||||
+ spinlock_t instances_lock;
|
||||
+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS];
|
||||
+};
|
||||
+
|
||||
+#endif /* __NETNS_NFQNL_H */
|
||||
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
|
||||
index e59aabd..f3c43e5 100644
|
||||
--- a/net/ipv4/netfilter/ip_queue.c
|
||||
+++ b/net/ipv4/netfilter/ip_queue.c
|
||||
@@ -225,7 +225,8 @@ nlmsg_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
struct sk_buff *nskb;
|
||||
@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ goto err_out_free_nskb;
|
||||
+
|
||||
if (!peer_pid)
|
||||
goto err_out_free_nskb;
|
||||
|
||||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
|
||||
index e63c397..322c511 100644
|
||||
--- a/net/ipv6/netfilter/ip6_queue.c
|
||||
+++ b/net/ipv6/netfilter/ip6_queue.c
|
||||
@@ -225,7 +225,8 @@ nlmsg_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
struct sk_buff *nskb;
|
||||
@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ goto err_out_free_nskb;
|
||||
+
|
||||
if (!peer_pid)
|
||||
goto err_out_free_nskb;
|
||||
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index ecb84a3..9490bd5 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
const struct nf_afinfo *afinfo;
|
||||
const struct nf_queue_handler *qh;
|
||||
+ struct net *net;
|
||||
+
|
||||
+ if (indev)
|
||||
+ net = dev_net(indev);
|
||||
+ else if (skb->sk)
|
||||
+ net = sock_net(skb->sk);
|
||||
+ else if (outdev)
|
||||
+ net = dev_net(outdev);
|
||||
+ else
|
||||
+ return status;
|
||||
|
||||
/* QUEUE == DROP if no one is waiting, to be safe. */
|
||||
rcu_read_lock();
|
||||
@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
skb_dst_force(skb);
|
||||
afinfo->saveroute(skb, entry);
|
||||
- status = qh->outfn(entry, queuenum);
|
||||
+ status = qh->outfn(net, entry, queuenum);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index b615da5..48ea6f4 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -64,24 +64,19 @@ struct nfqnl_instance {
|
||||
|
||||
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
|
||||
|
||||
-static DEFINE_SPINLOCK(instances_lock);
|
||||
-
|
||||
-#define INSTANCE_BUCKETS 16
|
||||
-static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
|
||||
-
|
||||
static inline u_int8_t instance_hashfn(u_int16_t queue_num)
|
||||
{
|
||||
- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
|
||||
+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS;
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_lookup(u_int16_t queue_num)
|
||||
+instance_lookup(struct net *net, u_int16_t queue_num)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *pos;
|
||||
struct nfqnl_instance *inst;
|
||||
|
||||
- head = &instance_table[instance_hashfn(queue_num)];
|
||||
+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)];
|
||||
hlist_for_each_entry_rcu(inst, pos, head, hlist) {
|
||||
if (inst->queue_num == queue_num)
|
||||
return inst;
|
||||
@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num)
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_create(u_int16_t queue_num, int pid)
|
||||
+instance_create(struct net *net, u_int16_t queue_num, int pid)
|
||||
{
|
||||
struct nfqnl_instance *inst;
|
||||
unsigned int h;
|
||||
int err;
|
||||
|
||||
- spin_lock(&instances_lock);
|
||||
- if (instance_lookup(queue_num)) {
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ if (instance_lookup(net, queue_num)) {
|
||||
err = -EEXIST;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid)
|
||||
}
|
||||
|
||||
h = instance_hashfn(queue_num);
|
||||
- hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
|
||||
+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]);
|
||||
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
|
||||
return inst;
|
||||
|
||||
out_free:
|
||||
kfree(inst);
|
||||
out_unlock:
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst)
|
||||
}
|
||||
|
||||
static void
|
||||
-instance_destroy(struct nfqnl_instance *inst)
|
||||
+instance_destroy(struct net *net, struct nfqnl_instance *inst)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
__instance_destroy(inst);
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -390,7 +385,8 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
struct nfqnl_instance *queue;
|
||||
@@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
__be32 *packet_id_ptr;
|
||||
|
||||
/* rcu_read_lock()ed by nf_hook_slow() */
|
||||
- queue = instance_lookup(queuenum);
|
||||
+ queue = instance_lookup(net, queuenum);
|
||||
if (!queue) {
|
||||
err = -ESRCH;
|
||||
goto err_out;
|
||||
@@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
*packet_id_ptr = htonl(entry->id);
|
||||
|
||||
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
||||
- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
|
||||
+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT);
|
||||
if (err < 0) {
|
||||
queue->queue_user_dropped++;
|
||||
goto err_out_unlock;
|
||||
@@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
|
||||
/* drop all packets with either indev or outdev == ifindex from all queue
|
||||
* instances */
|
||||
static void
|
||||
-nfqnl_dev_drop(int ifindex)
|
||||
+nfqnl_dev_drop(struct net *net, int ifindex)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head = &net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_rcu(inst, tmp, head, hlist)
|
||||
nfqnl_flush(inst, dev_cmp, ifindex);
|
||||
@@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
- if (!net_eq(dev_net(dev), &init_net))
|
||||
- return NOTIFY_DONE;
|
||||
-
|
||||
/* Drop any packets associated with the downed device */
|
||||
if (event == NETDEV_DOWN)
|
||||
- nfqnl_dev_drop(dev->ifindex);
|
||||
+ nfqnl_dev_drop(dev_net(dev), dev->ifindex);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
|
||||
int i;
|
||||
|
||||
/* destroy all instances for this pid */
|
||||
- spin_lock(&instances_lock);
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ spin_lock(&n->net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp, *t2;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head =
|
||||
+ &n->net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
|
||||
- if ((n->net == &init_net) &&
|
||||
- (n->pid == inst->peer_pid))
|
||||
+ if (n->pid == inst->peer_pid)
|
||||
__instance_destroy(inst);
|
||||
}
|
||||
}
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&n->net->nfqnl.instances_lock);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -715,9 +710,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
|
||||
unsigned int verdict;
|
||||
struct nf_queue_entry *entry;
|
||||
int err;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
rcu_read_lock();
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue) {
|
||||
err = -ENODEV;
|
||||
goto err_out_unlock;
|
||||
@@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
struct nfqnl_msg_config_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
if (nfqa[NFQA_CFG_CMD]) {
|
||||
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
|
||||
@@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (queue && queue->peer_pid != NETLINK_CB(skb).pid) {
|
||||
ret = -EPERM;
|
||||
goto err_out_unlock;
|
||||
@@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -EBUSY;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- queue = instance_create(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = instance_create(net, queue_num,
|
||||
+ NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue)) {
|
||||
ret = PTR_ERR(queue);
|
||||
goto err_out_unlock;
|
||||
@@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -ENODEV;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- instance_destroy(queue);
|
||||
+ instance_destroy(net, queue);
|
||||
break;
|
||||
case NFQNL_CFG_CMD_PF_BIND:
|
||||
case NFQNL_CFG_CMD_PF_UNBIND:
|
||||
@@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = {
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct iter_state {
|
||||
+ struct seq_net_private p;
|
||||
unsigned int bucket;
|
||||
};
|
||||
|
||||
-static struct hlist_node *get_first(struct seq_file *seq)
|
||||
+static struct hlist_node *get_first(struct net *net, struct iter_state *st)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
||||
- if (!hlist_empty(&instance_table[st->bucket]))
|
||||
- return instance_table[st->bucket].first;
|
||||
+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) {
|
||||
+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket]))
|
||||
+ return net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
|
||||
+static struct hlist_node *get_next(struct net *net, struct iter_state *st,
|
||||
+ struct hlist_node *h)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
h = h->next;
|
||||
while (!h) {
|
||||
- if (++st->bucket >= INSTANCE_BUCKETS)
|
||||
+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS)
|
||||
return NULL;
|
||||
|
||||
- h = instance_table[st->bucket].first;
|
||||
+ h = net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
|
||||
+static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
|
||||
+ loff_t pos)
|
||||
{
|
||||
struct hlist_node *head;
|
||||
- head = get_first(seq);
|
||||
+ head = get_first(net, st);
|
||||
|
||||
if (head)
|
||||
- while (pos && (head = get_next(seq, head)))
|
||||
+ while (pos && (head = get_next(net, st, head)))
|
||||
pos--;
|
||||
return pos ? NULL : head;
|
||||
}
|
||||
|
||||
static void *seq_start(struct seq_file *seq, loff_t *pos)
|
||||
- __acquires(instances_lock)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
- return get_idx(seq, *pos);
|
||||
+ struct net *net = seq_file_net(seq);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ return get_idx(net, seq->private, *pos);
|
||||
}
|
||||
|
||||
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
(*pos)++;
|
||||
- return get_next(s, v);
|
||||
+ return get_next(seq_file_net(s), s->private, v);
|
||||
}
|
||||
|
||||
static void seq_stop(struct seq_file *s, void *v)
|
||||
- __releases(instances_lock)
|
||||
{
|
||||
- spin_unlock(&instances_lock);
|
||||
+ struct net *net = seq_file_net(s);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static int seq_show(struct seq_file *s, void *v)
|
||||
@@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = {
|
||||
|
||||
static int nfqnl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- return seq_open_private(file, &nfqnl_seq_ops,
|
||||
- sizeof(struct iter_state));
|
||||
+ return seq_open_net(inode, file, &nfqnl_seq_ops,
|
||||
+ sizeof(struct iter_state));
|
||||
}
|
||||
|
||||
static const struct file_operations nfqnl_file_ops = {
|
||||
@@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
.open = nfqnl_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
- .release = seq_release_private,
|
||||
+ .release = seq_release_net,
|
||||
};
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock_init(&net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++)
|
||||
+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]);
|
||||
+
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nfnetlink_queue", 0440,
|
||||
net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
@@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status;
|
||||
+ int status;
|
||||
|
||||
status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
if (status) {
|
||||
@@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
- INIT_HLIST_HEAD(&instance_table[i]);
|
||||
-
|
||||
netlink_register_notifier(&nfqnl_rtnl_notifier);
|
||||
status = nfnetlink_subsys_register(&nfqnl_subsys);
|
||||
if (status < 0) {
|
||||
--
|
||||
1.7.5.4
|
||||
|
62
kernel/core-kernel-3.2/Makefile
Normal file
62
kernel/core-kernel-3.2/Makefile
Normal file
|
@ -0,0 +1,62 @@
|
|||
VERSION := 3.2.0
|
||||
TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2
|
||||
|
||||
SUBVERSION := -core
|
||||
REVISION := 1.0
|
||||
|
||||
PATCHDIR := patches
|
||||
PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch))
|
||||
|
||||
CONFIG := config.core
|
||||
|
||||
DEPDEBS := linux-source kernel-package po-debconf gettext
|
||||
|
||||
CONCURRENCY_LEVEL := 8
|
||||
|
||||
MAINTAINER ?= Tom Goff
|
||||
EMAIL ?= thomas.goff@boeing.com
|
||||
|
||||
MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \
|
||||
--append-to-version $(SUBVERSION) --revision $(REVISION)
|
||||
|
||||
.PHONY: build
|
||||
build: debcheck defaultconfig patch
|
||||
export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \
|
||||
KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && \
|
||||
if [ -f ../$(CONFIG) ]; then \
|
||||
cat ../$(CONFIG) >> .config; \
|
||||
fi && \
|
||||
fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch
|
||||
|
||||
.PHONY: debcheck
|
||||
debcheck:
|
||||
for d in $(DEPDEBS); do \
|
||||
if ! dpkg-query -s $$d > /dev/null 2>&1; then \
|
||||
echo ERROR: build dependency not installed: $$d >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.PHONY: defaultconfig
|
||||
defaultconfig: linux-source-$(VERSION)
|
||||
export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure
|
||||
|
||||
.PHONY: patch
|
||||
patch: linux-source-$(VERSION) patch-stamp
|
||||
patch-stamp: $(PATCHES)
|
||||
for p in $^; do \
|
||||
if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \
|
||||
echo ERROR: applying patch failed: $$p >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
linux-source-$(VERSION): $(TARBALL)
|
||||
tar -xjf $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf linux-source-$(VERSION) patch-stamp
|
8
kernel/core-kernel-3.2/README.txt
Normal file
8
kernel/core-kernel-3.2/README.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Author: Tom Goff <thomas.goff@boeing.com>
|
||||
|
||||
The Makefile is basically a wrapper around the make-kpkg command that
|
||||
simplifies building kernel packages. Running make will do some basic
|
||||
dependency checks then build architecture appropriate kernel packages that
|
||||
include changes from the patches directory. The nfnetlink patch is what
|
||||
virtualizes the netfilter queue mechanism;
|
||||
the ifindex patch virtualizes network interface index numbers.
|
1
kernel/core-kernel-3.2/config.core
Normal file
1
kernel/core-kernel-3.2/config.core
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_XFRM_STATISTICS=y
|
60
kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch
Normal file
60
kernel/core-kernel-3.2/patches/00-linux-3.2.ifindex.patch
Normal file
|
@ -0,0 +1,60 @@
|
|||
From 918e253ebaa3d28c54ff64b596a0afc8779d106a Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Fri, 27 Jul 2012 00:02:50 -0700
|
||||
Subject: [PATCH] Make network device ifindex sequential per network
|
||||
namespace.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 2 ++
|
||||
net/core/dev.c | 13 ++++++-------
|
||||
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 4b6f04a..266e747 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -65,6 +65,8 @@ struct net {
|
||||
struct sock *rtnl; /* rtnetlink socket */
|
||||
struct sock *genl_sock;
|
||||
|
||||
+ int ifindex;
|
||||
+
|
||||
struct list_head dev_base_head;
|
||||
struct hlist_head *dev_name_head;
|
||||
struct hlist_head *dev_index_head;
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index 1cbddc9..d7f5711 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -5236,12 +5236,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
*/
|
||||
static int dev_new_index(struct net *net)
|
||||
{
|
||||
- static int ifindex;
|
||||
for (;;) {
|
||||
- if (++ifindex <= 0)
|
||||
- ifindex = 1;
|
||||
- if (!__dev_get_by_index(net, ifindex))
|
||||
- return ifindex;
|
||||
+ if (++net->ifindex <= 0)
|
||||
+ net->ifindex = 1;
|
||||
+ if (!__dev_get_by_index(net, net->ifindex))
|
||||
+ return net->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6253,8 +6252,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
- /* If there is an ifindex conflict assign a new one */
|
||||
- if (__dev_get_by_index(net, dev->ifindex)) {
|
||||
+ /* Assign a new ifindex */
|
||||
+ {
|
||||
int iflink = (dev->iflink == dev->ifindex);
|
||||
dev->ifindex = dev_new_index(net);
|
||||
if (iflink)
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,351 @@
|
|||
From 67765faf27ec646bcc008bd34d12e48a7466dcdd Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Thu, 26 Jul 2012 23:57:06 -0700
|
||||
Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per
|
||||
netns.
|
||||
|
||||
This allows subsystems to create per-netns entries.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/linux/netfilter.h | 5 -----
|
||||
include/net/net_namespace.h | 3 +++
|
||||
net/netfilter/core.c | 35 +++++++++++++++++++++++-------
|
||||
net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++----
|
||||
net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++----
|
||||
net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++-----------
|
||||
net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------
|
||||
7 files changed, 148 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
|
||||
index 857f502..b4e02fb 100644
|
||||
--- a/include/linux/netfilter.h
|
||||
+++ b/include/linux/netfilter.h
|
||||
@@ -340,11 +340,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
#endif
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-#include <linux/proc_fs.h>
|
||||
-extern struct proc_dir_entry *proc_net_netfilter;
|
||||
-#endif
|
||||
-
|
||||
#else /* !CONFIG_NETFILTER */
|
||||
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 3bb6fa0..cf126ef 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -84,6 +84,9 @@ struct net {
|
||||
struct netns_dccp dccp;
|
||||
#endif
|
||||
#ifdef CONFIG_NETFILTER
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ struct proc_dir_entry *proc_net_netfilter;
|
||||
+#endif
|
||||
struct netns_xt xt;
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
struct netns_ct ct;
|
||||
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
|
||||
index afca6c7..9d9b103 100644
|
||||
--- a/net/netfilter/core.c
|
||||
+++ b/net/netfilter/core.c
|
||||
@@ -255,25 +255,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
||||
EXPORT_SYMBOL(nf_conntrack_destroy);
|
||||
#endif /* CONFIG_NF_CONNTRACK */
|
||||
|
||||
+static int __net_init netfilter_net_init(struct net *net)
|
||||
+{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
-struct proc_dir_entry *proc_net_netfilter;
|
||||
-EXPORT_SYMBOL(proc_net_netfilter);
|
||||
+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter",
|
||||
+ net->proc_net);
|
||||
+ if (!net->proc_net_netfilter) {
|
||||
+ pr_err("%s: cannot create netfilter proc entry\n", __func__);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
#endif
|
||||
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ proc_net_remove(net, "netfilter");
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_net_ops = {
|
||||
+ .init = netfilter_net_init,
|
||||
+ .exit = netfilter_net_exit,
|
||||
+};
|
||||
+
|
||||
void __init netfilter_init(void)
|
||||
{
|
||||
int i, h;
|
||||
+
|
||||
+ if (register_pernet_subsys(&netfilter_net_ops))
|
||||
+ panic("%s: failed to register per netns operations", __func__);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
|
||||
for (h = 0; h < NF_MAX_HOOKS; h++)
|
||||
INIT_LIST_HEAD(&nf_hooks[i][h]);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
|
||||
- if (!proc_net_netfilter)
|
||||
- panic("cannot create netfilter proc entry");
|
||||
-#endif
|
||||
-
|
||||
if (netfilter_queue_init() < 0)
|
||||
panic("cannot initialize nf_queue");
|
||||
if (netfilter_log_init() < 0)
|
||||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
|
||||
index 957374a..c546ad7 100644
|
||||
--- a/net/netfilter/nf_log.c
|
||||
+++ b/net/netfilter/nf_log.c
|
||||
@@ -297,14 +297,39 @@ static __init int netfilter_log_sysctl_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
-int __init netfilter_log_init(void)
|
||||
+static int __net_init netfilter_log_net_init(struct net *net)
|
||||
{
|
||||
- int i, r;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_log", S_IRUGO,
|
||||
- proc_net_netfilter, &nflog_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nflog_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_log", net->proc_net_netfilter);
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_log_net_ops = {
|
||||
+ .init = netfilter_log_net_init,
|
||||
+ .exit = netfilter_log_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_log_init(void)
|
||||
+{
|
||||
+ int i, r;
|
||||
+
|
||||
+ r = register_pernet_subsys(&netfilter_log_net_ops);
|
||||
+ if (r) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
/* Errors will trigger panic, unroll on error is unnecessary. */
|
||||
r = netfilter_log_sysctl_init();
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index b3a7db6..470ec3a 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -383,14 +383,37 @@ static const struct file_operations nfqueue_file_ops = {
|
||||
};
|
||||
#endif /* PROC_FS */
|
||||
|
||||
-
|
||||
-int __init netfilter_queue_init(void)
|
||||
+static int __net_init netfilter_queue_net_init(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_queue", S_IRUGO,
|
||||
- proc_net_netfilter, &nfqueue_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nfqueue_file_ops))
|
||||
+ return -ENOMEM;
|
||||
#endif
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void __net_exit netfilter_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_queue_net_ops = {
|
||||
+ .init = netfilter_queue_net_init,
|
||||
+ .exit = netfilter_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_queue_init(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = register_pernet_subsys(&netfilter_queue_net_ops);
|
||||
+ if (err)
|
||||
+ pr_err("%s: cannot initialize per netns operations\n",
|
||||
+ __func__);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
|
||||
index 66b2c54..e4c3c1e 100644
|
||||
--- a/net/netfilter/nfnetlink_log.c
|
||||
+++ b/net/netfilter/nfnetlink_log.c
|
||||
@@ -950,9 +950,39 @@ static const struct file_operations nful_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_log_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_log", 0440,
|
||||
+ net->proc_net_netfilter, &nful_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_log_net_ops = {
|
||||
+ .init = nfnetlink_log_net_init,
|
||||
+ .exit = nfnetlink_log_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_log_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_log_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -975,17 +1005,8 @@ static int __init nfnetlink_log_init(void)
|
||||
goto cleanup_subsys;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_log", 0440,
|
||||
- proc_net_netfilter, &nful_file_ops))
|
||||
- goto cleanup_logger;
|
||||
-#endif
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_logger:
|
||||
- nf_log_unregister(&nfulnl_logger);
|
||||
-#endif
|
||||
cleanup_subsys:
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
cleanup_netlink_notifier:
|
||||
@@ -996,9 +1017,6 @@ cleanup_netlink_notifier:
|
||||
static void __exit nfnetlink_log_fini(void)
|
||||
{
|
||||
nf_log_unregister(&nfulnl_logger);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
||||
}
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index a80b0cb..b615da5 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -974,9 +974,39 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_queue", 0440,
|
||||
+ net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
+ .init = nfnetlink_queue_net_init,
|
||||
+ .exit = nfnetlink_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -988,19 +1018,9 @@ static int __init nfnetlink_queue_init(void)
|
||||
goto cleanup_netlink_notifier;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_queue", 0440,
|
||||
- proc_net_netfilter, &nfqnl_file_ops))
|
||||
- goto cleanup_subsys;
|
||||
-#endif
|
||||
-
|
||||
register_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_subsys:
|
||||
- nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
-#endif
|
||||
cleanup_netlink_notifier:
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
return status;
|
||||
@@ -1010,9 +1030,6 @@ static void __exit nfnetlink_queue_fini(void)
|
||||
{
|
||||
nf_unregister_queue_handlers(&nfqh);
|
||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -0,0 +1,544 @@
|
|||
From f8179877a37f37631d831de6381f22fd643b4ea0 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Thu, 26 Jul 2012 23:58:38 -0700
|
||||
Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support.
|
||||
|
||||
Make nfnetlink_queue network namespace aware including a per-netns
|
||||
/proc/net/netfilter/nfnetlink_queue file.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 6 ++
|
||||
include/net/netfilter/nf_queue.h | 3 +-
|
||||
include/net/netns/nfqnl.h | 14 ++++
|
||||
net/ipv4/netfilter/ip_queue.c | 6 +-
|
||||
net/ipv6/netfilter/ip6_queue.c | 6 +-
|
||||
net/netfilter/nf_queue.c | 12 +++-
|
||||
net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++-------------------
|
||||
7 files changed, 111 insertions(+), 72 deletions(-)
|
||||
create mode 100644 include/net/netns/nfqnl.h
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index cf126ef..4b6f04a 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <net/netns/conntrack.h>
|
||||
#endif
|
||||
#include <net/netns/xfrm.h>
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+#include <net/netns/nfqnl.h>
|
||||
+#endif
|
||||
|
||||
struct proc_dir_entry;
|
||||
struct net_device;
|
||||
@@ -93,6 +96,9 @@ struct net {
|
||||
#endif
|
||||
struct sock *nfnl;
|
||||
struct sock *nfnl_stash;
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+ struct netns_nfqnl nfqnl;
|
||||
+#endif
|
||||
#endif
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
|
||||
index 252fd10..3e5bde8 100644
|
||||
--- a/include/net/netfilter/nf_queue.h
|
||||
+++ b/include/net/netfilter/nf_queue.h
|
||||
@@ -19,7 +19,8 @@ struct nf_queue_entry {
|
||||
|
||||
/* Packet queuing */
|
||||
struct nf_queue_handler {
|
||||
- int (*outfn)(struct nf_queue_entry *entry,
|
||||
+ int (*outfn)(struct net *net,
|
||||
+ struct nf_queue_entry *entry,
|
||||
unsigned int queuenum);
|
||||
char *name;
|
||||
};
|
||||
diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h
|
||||
new file mode 100644
|
||||
index 0000000..0fe7fbe
|
||||
--- /dev/null
|
||||
+++ b/include/net/netns/nfqnl.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+#ifndef __NETNS_NFQNL_H
|
||||
+#define __NETNS_NFQNL_H
|
||||
+
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/list.h>
|
||||
+
|
||||
+#define NFQNL_INSTANCE_BUCKETS 16
|
||||
+
|
||||
+struct netns_nfqnl {
|
||||
+ spinlock_t instances_lock;
|
||||
+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS];
|
||||
+};
|
||||
+
|
||||
+#endif /* __NETNS_NFQNL_H */
|
||||
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
|
||||
index e59aabd..f3c43e5 100644
|
||||
--- a/net/ipv4/netfilter/ip_queue.c
|
||||
+++ b/net/ipv4/netfilter/ip_queue.c
|
||||
@@ -225,7 +225,8 @@ nlmsg_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
struct sk_buff *nskb;
|
||||
@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ goto err_out_free_nskb;
|
||||
+
|
||||
if (!peer_pid)
|
||||
goto err_out_free_nskb;
|
||||
|
||||
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
|
||||
index e63c397..322c511 100644
|
||||
--- a/net/ipv6/netfilter/ip6_queue.c
|
||||
+++ b/net/ipv6/netfilter/ip6_queue.c
|
||||
@@ -225,7 +225,8 @@ nlmsg_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+ipq_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
int status = -EINVAL;
|
||||
struct sk_buff *nskb;
|
||||
@@ -239,6 +240,9 @@ ipq_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
||||
+ if (!net_eq(net, &init_net))
|
||||
+ goto err_out_free_nskb;
|
||||
+
|
||||
if (!peer_pid)
|
||||
goto err_out_free_nskb;
|
||||
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index 470ec3a..6894ecc 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
const struct nf_afinfo *afinfo;
|
||||
const struct nf_queue_handler *qh;
|
||||
+ struct net *net;
|
||||
+
|
||||
+ if (indev)
|
||||
+ net = dev_net(indev);
|
||||
+ else if (skb->sk)
|
||||
+ net = sock_net(skb->sk);
|
||||
+ else if (outdev)
|
||||
+ net = dev_net(outdev);
|
||||
+ else
|
||||
+ return status;
|
||||
|
||||
/* QUEUE == DROP if no one is waiting, to be safe. */
|
||||
rcu_read_lock();
|
||||
@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
skb_dst_force(skb);
|
||||
afinfo->saveroute(skb, entry);
|
||||
- status = qh->outfn(entry, queuenum);
|
||||
+ status = qh->outfn(net, entry, queuenum);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index b615da5..11725a0 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -64,24 +64,19 @@ struct nfqnl_instance {
|
||||
|
||||
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
|
||||
|
||||
-static DEFINE_SPINLOCK(instances_lock);
|
||||
-
|
||||
-#define INSTANCE_BUCKETS 16
|
||||
-static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
|
||||
-
|
||||
static inline u_int8_t instance_hashfn(u_int16_t queue_num)
|
||||
{
|
||||
- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
|
||||
+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS;
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_lookup(u_int16_t queue_num)
|
||||
+instance_lookup(struct net *net, u_int16_t queue_num)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *pos;
|
||||
struct nfqnl_instance *inst;
|
||||
|
||||
- head = &instance_table[instance_hashfn(queue_num)];
|
||||
+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)];
|
||||
hlist_for_each_entry_rcu(inst, pos, head, hlist) {
|
||||
if (inst->queue_num == queue_num)
|
||||
return inst;
|
||||
@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num)
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_create(u_int16_t queue_num, int pid)
|
||||
+instance_create(struct net *net, u_int16_t queue_num, int pid)
|
||||
{
|
||||
struct nfqnl_instance *inst;
|
||||
unsigned int h;
|
||||
int err;
|
||||
|
||||
- spin_lock(&instances_lock);
|
||||
- if (instance_lookup(queue_num)) {
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ if (instance_lookup(net, queue_num)) {
|
||||
err = -EEXIST;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid)
|
||||
}
|
||||
|
||||
h = instance_hashfn(queue_num);
|
||||
- hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
|
||||
+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]);
|
||||
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
|
||||
return inst;
|
||||
|
||||
out_free:
|
||||
kfree(inst);
|
||||
out_unlock:
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst)
|
||||
}
|
||||
|
||||
static void
|
||||
-instance_destroy(struct nfqnl_instance *inst)
|
||||
+instance_destroy(struct net *net, struct nfqnl_instance *inst)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
__instance_destroy(inst);
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -390,7 +385,8 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
struct nfqnl_instance *queue;
|
||||
@@ -398,7 +394,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
__be32 *packet_id_ptr;
|
||||
|
||||
/* rcu_read_lock()ed by nf_hook_slow() */
|
||||
- queue = instance_lookup(queuenum);
|
||||
+ queue = instance_lookup(net, queuenum);
|
||||
if (!queue) {
|
||||
err = -ESRCH;
|
||||
goto err_out;
|
||||
@@ -432,7 +428,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
*packet_id_ptr = htonl(entry->id);
|
||||
|
||||
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
||||
- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
|
||||
+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT);
|
||||
if (err < 0) {
|
||||
queue->queue_user_dropped++;
|
||||
goto err_out_unlock;
|
||||
@@ -541,16 +537,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
|
||||
/* drop all packets with either indev or outdev == ifindex from all queue
|
||||
* instances */
|
||||
static void
|
||||
-nfqnl_dev_drop(int ifindex)
|
||||
+nfqnl_dev_drop(struct net *net, int ifindex)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head = &net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_rcu(inst, tmp, head, hlist)
|
||||
nfqnl_flush(inst, dev_cmp, ifindex);
|
||||
@@ -567,12 +563,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
- if (!net_eq(dev_net(dev), &init_net))
|
||||
- return NOTIFY_DONE;
|
||||
-
|
||||
/* Drop any packets associated with the downed device */
|
||||
if (event == NETDEV_DOWN)
|
||||
- nfqnl_dev_drop(dev->ifindex);
|
||||
+ nfqnl_dev_drop(dev_net(dev), dev->ifindex);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -590,19 +583,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
|
||||
int i;
|
||||
|
||||
/* destroy all instances for this pid */
|
||||
- spin_lock(&instances_lock);
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ spin_lock(&n->net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp, *t2;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head =
|
||||
+ &n->net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
|
||||
- if ((n->net == &init_net) &&
|
||||
- (n->pid == inst->peer_pid))
|
||||
+ if (n->pid == inst->peer_pid)
|
||||
__instance_destroy(inst);
|
||||
}
|
||||
}
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&n->net->nfqnl.instances_lock);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -622,11 +615,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
|
||||
[NFQA_MARK] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
-static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
|
||||
+static struct nfqnl_instance *verdict_instance_lookup(struct net *net,
|
||||
+ u16 queue_num, int nlpid)
|
||||
{
|
||||
struct nfqnl_instance *queue;
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -670,7 +664,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
|
||||
LIST_HEAD(batch_list);
|
||||
u16 queue_num = ntohs(nfmsg->res_id);
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num,
|
||||
+ NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -715,11 +710,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
unsigned int verdict;
|
||||
struct nf_queue_entry *entry;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -774,6 +770,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
struct nfqnl_msg_config_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
if (nfqa[NFQA_CFG_CMD]) {
|
||||
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
|
||||
@@ -790,7 +787,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (queue && queue->peer_pid != NETLINK_CB(skb).pid) {
|
||||
ret = -EPERM;
|
||||
goto err_out_unlock;
|
||||
@@ -803,7 +800,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -EBUSY;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- queue = instance_create(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = instance_create(net, queue_num,
|
||||
+ NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue)) {
|
||||
ret = PTR_ERR(queue);
|
||||
goto err_out_unlock;
|
||||
@@ -814,7 +812,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -ENODEV;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- instance_destroy(queue);
|
||||
+ instance_destroy(net, queue);
|
||||
break;
|
||||
case NFQNL_CFG_CMD_PF_BIND:
|
||||
case NFQNL_CFG_CMD_PF_UNBIND:
|
||||
@@ -878,65 +876,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = {
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct iter_state {
|
||||
+ struct seq_net_private p;
|
||||
unsigned int bucket;
|
||||
};
|
||||
|
||||
-static struct hlist_node *get_first(struct seq_file *seq)
|
||||
+static struct hlist_node *get_first(struct net *net, struct iter_state *st)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
||||
- if (!hlist_empty(&instance_table[st->bucket]))
|
||||
- return instance_table[st->bucket].first;
|
||||
+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) {
|
||||
+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket]))
|
||||
+ return net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
|
||||
+static struct hlist_node *get_next(struct net *net, struct iter_state *st,
|
||||
+ struct hlist_node *h)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
h = h->next;
|
||||
while (!h) {
|
||||
- if (++st->bucket >= INSTANCE_BUCKETS)
|
||||
+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS)
|
||||
return NULL;
|
||||
|
||||
- h = instance_table[st->bucket].first;
|
||||
+ h = net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
|
||||
+static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
|
||||
+ loff_t pos)
|
||||
{
|
||||
struct hlist_node *head;
|
||||
- head = get_first(seq);
|
||||
+ head = get_first(net, st);
|
||||
|
||||
if (head)
|
||||
- while (pos && (head = get_next(seq, head)))
|
||||
+ while (pos && (head = get_next(net, st, head)))
|
||||
pos--;
|
||||
return pos ? NULL : head;
|
||||
}
|
||||
|
||||
static void *seq_start(struct seq_file *seq, loff_t *pos)
|
||||
- __acquires(instances_lock)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
- return get_idx(seq, *pos);
|
||||
+ struct net *net = seq_file_net(seq);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ return get_idx(net, seq->private, *pos);
|
||||
}
|
||||
|
||||
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
(*pos)++;
|
||||
- return get_next(s, v);
|
||||
+ return get_next(seq_file_net(s), s->private, v);
|
||||
}
|
||||
|
||||
static void seq_stop(struct seq_file *s, void *v)
|
||||
- __releases(instances_lock)
|
||||
{
|
||||
- spin_unlock(&instances_lock);
|
||||
+ struct net *net = seq_file_net(s);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static int seq_show(struct seq_file *s, void *v)
|
||||
@@ -960,8 +957,8 @@ static const struct seq_operations nfqnl_seq_ops = {
|
||||
|
||||
static int nfqnl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- return seq_open_private(file, &nfqnl_seq_ops,
|
||||
- sizeof(struct iter_state));
|
||||
+ return seq_open_net(inode, file, &nfqnl_seq_ops,
|
||||
+ sizeof(struct iter_state));
|
||||
}
|
||||
|
||||
static const struct file_operations nfqnl_file_ops = {
|
||||
@@ -969,13 +966,19 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
.open = nfqnl_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
- .release = seq_release_private,
|
||||
+ .release = seq_release_net,
|
||||
};
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock_init(&net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++)
|
||||
+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]);
|
||||
+
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nfnetlink_queue", 0440,
|
||||
net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
@@ -999,7 +1002,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status;
|
||||
+ int status;
|
||||
|
||||
status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
if (status) {
|
||||
@@ -1008,9 +1011,6 @@ static int __init nfnetlink_queue_init(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
- INIT_HLIST_HEAD(&instance_table[i]);
|
||||
-
|
||||
netlink_register_notifier(&nfqnl_rtnl_notifier);
|
||||
status = nfnetlink_subsys_register(&nfqnl_subsys);
|
||||
if (status < 0) {
|
||||
--
|
||||
1.7.9.5
|
||||
|
70
kernel/core-kernel-3.5/Makefile
Normal file
70
kernel/core-kernel-3.5/Makefile
Normal file
|
@ -0,0 +1,70 @@
|
|||
VERSION := $(shell dpkg -l linux-source 2> /dev/null | \
|
||||
awk '/^i/ {print gensub("([0-9]+[.][0-9]+[.][0-9]+)[.0-9]*", "\\1", "1", $$3)}')
|
||||
TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2
|
||||
|
||||
SUBVERSION := -core
|
||||
REVISION := 1.0
|
||||
|
||||
PATCHDIR := patches
|
||||
PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch))
|
||||
|
||||
CONFIG := config.core
|
||||
|
||||
DEPDEBS := linux-source kernel-package po-debconf gettext
|
||||
|
||||
CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \
|
||||
awk '/^CPU\(s\)/ {print $$2}')
|
||||
ifeq ($(strip $(CONCURRENCY_LEVEL)),)
|
||||
CONCURRENCY_LEVEL := 1
|
||||
endif
|
||||
|
||||
MAINTAINER ?= $(shell id -nu)
|
||||
EMAIL ?= $(MAINTAINER)@$(shell hostname -f)
|
||||
|
||||
MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \
|
||||
--append-to-version $(SUBVERSION) --revision $(REVISION)
|
||||
|
||||
.PHONY: build
|
||||
build: debcheck defaultconfig patch
|
||||
export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \
|
||||
KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && \
|
||||
if [ -f ../$(CONFIG) ]; then \
|
||||
cat ../$(CONFIG) >> .config; \
|
||||
fi && \
|
||||
fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch
|
||||
|
||||
.PHONY: debcheck
|
||||
debcheck:
|
||||
for d in $(DEPDEBS); do \
|
||||
if ! dpkg-query -s $$d > /dev/null 2>&1; then \
|
||||
echo ERROR: build dependency not installed: $$d >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.PHONY: defaultconfig
|
||||
defaultconfig: linux-source-$(VERSION)
|
||||
export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure
|
||||
|
||||
.PHONY: patch
|
||||
patch: linux-source-$(VERSION) patch-stamp
|
||||
patch-stamp: $(PATCHES)
|
||||
for p in $^; do \
|
||||
if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \
|
||||
echo ERROR: applying patch failed: $$p >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
.PHONY: source
|
||||
source: linux-source-$(VERSION)
|
||||
|
||||
linux-source-$(VERSION): $(TARBALL)
|
||||
tar -xjf $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf linux-source-$(VERSION) patch-stamp
|
1
kernel/core-kernel-3.5/config.core
Normal file
1
kernel/core-kernel-3.5/config.core
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_XFRM_STATISTICS=y
|
60
kernel/core-kernel-3.5/patches/00-ifindex.patch
Normal file
60
kernel/core-kernel-3.5/patches/00-ifindex.patch
Normal file
|
@ -0,0 +1,60 @@
|
|||
From e98f08306dd0dc854d93339730a8603638173e23 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Fri, 27 Jul 2012 00:02:50 -0700
|
||||
Subject: [PATCH] Make network device ifindex sequential per network
|
||||
namespace.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 2 ++
|
||||
net/core/dev.c | 13 ++++++-------
|
||||
2 files changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index ac9195e..1b9c99a 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -62,6 +62,8 @@ struct net {
|
||||
struct sock *rtnl; /* rtnetlink socket */
|
||||
struct sock *genl_sock;
|
||||
|
||||
+ int ifindex;
|
||||
+
|
||||
struct list_head dev_base_head;
|
||||
struct hlist_head *dev_name_head;
|
||||
struct hlist_head *dev_index_head;
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index 3ad746b..7bec156 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -5168,12 +5168,11 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
|
||||
*/
|
||||
static int dev_new_index(struct net *net)
|
||||
{
|
||||
- static int ifindex;
|
||||
for (;;) {
|
||||
- if (++ifindex <= 0)
|
||||
- ifindex = 1;
|
||||
- if (!__dev_get_by_index(net, ifindex))
|
||||
- return ifindex;
|
||||
+ if (++net->ifindex <= 0)
|
||||
+ net->ifindex = 1;
|
||||
+ if (!__dev_get_by_index(net, net->ifindex))
|
||||
+ return net->ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6182,8 +6181,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
- /* If there is an ifindex conflict assign a new one */
|
||||
- if (__dev_get_by_index(net, dev->ifindex)) {
|
||||
+ /* Assign a new ifindex */
|
||||
+ {
|
||||
int iflink = (dev->iflink == dev->ifindex);
|
||||
dev->ifindex = dev_new_index(net);
|
||||
if (iflink)
|
||||
--
|
||||
1.7.10.4
|
||||
|
351
kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch
Normal file
351
kernel/core-kernel-3.5/patches/00-nfnetlink_queue.patch
Normal file
|
@ -0,0 +1,351 @@
|
|||
From 5af499895ded68e1d42510df30be2004b4b778bf Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Thu, 26 Jul 2012 23:57:06 -0700
|
||||
Subject: [PATCH 1/2] netfilter: Make the /proc/net/netfilter directory per
|
||||
netns.
|
||||
|
||||
This allows subsystems to create per-netns entries.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/linux/netfilter.h | 5 -----
|
||||
include/net/net_namespace.h | 3 +++
|
||||
net/netfilter/core.c | 35 +++++++++++++++++++++++-------
|
||||
net/netfilter/nf_log.c | 33 ++++++++++++++++++++++++----
|
||||
net/netfilter/nf_queue.c | 31 +++++++++++++++++++++++----
|
||||
net/netfilter/nfnetlink_log.c | 44 +++++++++++++++++++++++++++-----------
|
||||
net/netfilter/nfnetlink_queue.c | 45 +++++++++++++++++++++++++++------------
|
||||
7 files changed, 148 insertions(+), 48 deletions(-)
|
||||
|
||||
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
|
||||
index ff9c84c..e28a566 100644
|
||||
--- a/include/linux/netfilter.h
|
||||
+++ b/include/linux/netfilter.h
|
||||
@@ -350,11 +350,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
#endif
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-#include <linux/proc_fs.h>
|
||||
-extern struct proc_dir_entry *proc_net_netfilter;
|
||||
-#endif
|
||||
-
|
||||
#else /* !CONFIG_NETFILTER */
|
||||
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 1b9c99a..449fc8e 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -86,6 +86,9 @@ struct net {
|
||||
struct netns_dccp dccp;
|
||||
#endif
|
||||
#ifdef CONFIG_NETFILTER
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ struct proc_dir_entry *proc_net_netfilter;
|
||||
+#endif
|
||||
struct netns_xt xt;
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
struct netns_ct ct;
|
||||
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
|
||||
index e19f365..c7c9f39 100644
|
||||
--- a/net/netfilter/core.c
|
||||
+++ b/net/netfilter/core.c
|
||||
@@ -266,25 +266,44 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
|
||||
EXPORT_SYMBOL(nf_conntrack_destroy);
|
||||
#endif /* CONFIG_NF_CONNTRACK */
|
||||
|
||||
+static int __net_init netfilter_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter",
|
||||
+ net->proc_net);
|
||||
+ if (!net->proc_net_netfilter) {
|
||||
+ pr_err("%s: cannot create netfilter proc entry\n", __func__);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_net_exit(struct net *net)
|
||||
+{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
-struct proc_dir_entry *proc_net_netfilter;
|
||||
-EXPORT_SYMBOL(proc_net_netfilter);
|
||||
+ proc_net_remove(net, "netfilter");
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_net_ops = {
|
||||
+ .init = netfilter_net_init,
|
||||
+ .exit = netfilter_net_exit,
|
||||
+};
|
||||
|
||||
void __init netfilter_init(void)
|
||||
{
|
||||
int i, h;
|
||||
+
|
||||
+ if (register_pernet_subsys(&netfilter_net_ops))
|
||||
+ panic("%s: failed to register per netns operations", __func__);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
|
||||
for (h = 0; h < NF_MAX_HOOKS; h++)
|
||||
INIT_LIST_HEAD(&nf_hooks[i][h]);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
|
||||
- if (!proc_net_netfilter)
|
||||
- panic("cannot create netfilter proc entry");
|
||||
-#endif
|
||||
-
|
||||
if (netfilter_queue_init() < 0)
|
||||
panic("cannot initialize nf_queue");
|
||||
if (netfilter_log_init() < 0)
|
||||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
|
||||
index 703fb26..4507932 100644
|
||||
--- a/net/netfilter/nf_log.c
|
||||
+++ b/net/netfilter/nf_log.c
|
||||
@@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
-int __init netfilter_log_init(void)
|
||||
+static int __net_init netfilter_log_net_init(struct net *net)
|
||||
{
|
||||
- int i, r;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_log", S_IRUGO,
|
||||
- proc_net_netfilter, &nflog_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nflog_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_log", net->proc_net_netfilter);
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_log_net_ops = {
|
||||
+ .init = netfilter_log_net_init,
|
||||
+ .exit = netfilter_log_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_log_init(void)
|
||||
+{
|
||||
+ int i, r;
|
||||
+
|
||||
+ r = register_pernet_subsys(&netfilter_log_net_ops);
|
||||
+ if (r) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
/* Errors will trigger panic, unroll on error is unnecessary. */
|
||||
r = netfilter_log_sysctl_init();
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index ce60cf0..288c6f5 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -407,14 +407,37 @@ static const struct file_operations nfqueue_file_ops = {
|
||||
};
|
||||
#endif /* PROC_FS */
|
||||
|
||||
-
|
||||
-int __init netfilter_queue_init(void)
|
||||
+static int __net_init netfilter_queue_net_init(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_queue", S_IRUGO,
|
||||
- proc_net_netfilter, &nfqueue_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nfqueue_file_ops))
|
||||
+ return -ENOMEM;
|
||||
#endif
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void __net_exit netfilter_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_queue_net_ops = {
|
||||
+ .init = netfilter_queue_net_init,
|
||||
+ .exit = netfilter_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_queue_init(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = register_pernet_subsys(&netfilter_queue_net_ops);
|
||||
+ if (err)
|
||||
+ pr_err("%s: cannot initialize per netns operations\n",
|
||||
+ __func__);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
|
||||
index bbc1d91..e5c1731 100644
|
||||
--- a/net/netfilter/nfnetlink_log.c
|
||||
+++ b/net/netfilter/nfnetlink_log.c
|
||||
@@ -966,9 +966,39 @@ static const struct file_operations nful_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_log_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_log", 0440,
|
||||
+ net->proc_net_netfilter, &nful_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_log_net_ops = {
|
||||
+ .init = nfnetlink_log_net_init,
|
||||
+ .exit = nfnetlink_log_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_log_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_log_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -991,17 +1021,8 @@ static int __init nfnetlink_log_init(void)
|
||||
goto cleanup_subsys;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_log", 0440,
|
||||
- proc_net_netfilter, &nful_file_ops))
|
||||
- goto cleanup_logger;
|
||||
-#endif
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_logger:
|
||||
- nf_log_unregister(&nfulnl_logger);
|
||||
-#endif
|
||||
cleanup_subsys:
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
cleanup_netlink_notifier:
|
||||
@@ -1012,9 +1033,6 @@ cleanup_netlink_notifier:
|
||||
static void __exit nfnetlink_log_fini(void)
|
||||
{
|
||||
nf_log_unregister(&nfulnl_logger);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
||||
}
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index 4162437..add33dc 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -982,9 +982,39 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_queue", 0440,
|
||||
+ net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
+ .init = nfnetlink_queue_net_init,
|
||||
+ .exit = nfnetlink_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -996,19 +1026,9 @@ static int __init nfnetlink_queue_init(void)
|
||||
goto cleanup_netlink_notifier;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_queue", 0440,
|
||||
- proc_net_netfilter, &nfqnl_file_ops))
|
||||
- goto cleanup_subsys;
|
||||
-#endif
|
||||
-
|
||||
register_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_subsys:
|
||||
- nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
-#endif
|
||||
cleanup_netlink_notifier:
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
return status;
|
||||
@@ -1018,9 +1038,6 @@ static void __exit nfnetlink_queue_fini(void)
|
||||
{
|
||||
nf_unregister_queue_handlers(&nfqh);
|
||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
|
||||
--
|
||||
1.7.10.4
|
||||
|
494
kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch
Normal file
494
kernel/core-kernel-3.5/patches/01-nfnetlink_queue.patch
Normal file
|
@ -0,0 +1,494 @@
|
|||
From 1ede1963c84e15359d4b5bf7fb01587d90bcf1d4 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Thu, 26 Jul 2012 23:58:38 -0700
|
||||
Subject: [PATCH 2/2] netfilter: nfnetlink_queue: Add netns support.
|
||||
|
||||
Make nfnetlink_queue network namespace aware including a per-netns
|
||||
/proc/net/netfilter/nfnetlink_queue file.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 6 ++
|
||||
include/net/netfilter/nf_queue.h | 3 +-
|
||||
include/net/netns/nfqnl.h | 14 ++++
|
||||
net/netfilter/nf_queue.c | 12 +++-
|
||||
net/netfilter/nfnetlink_queue.c | 136 +++++++++++++++++++-------------------
|
||||
5 files changed, 101 insertions(+), 70 deletions(-)
|
||||
create mode 100644 include/net/netns/nfqnl.h
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 449fc8e..c4229f1 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -21,6 +21,9 @@
|
||||
#include <net/netns/conntrack.h>
|
||||
#endif
|
||||
#include <net/netns/xfrm.h>
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+#include <net/netns/nfqnl.h>
|
||||
+#endif
|
||||
|
||||
struct proc_dir_entry;
|
||||
struct net_device;
|
||||
@@ -95,6 +98,9 @@ struct net {
|
||||
#endif
|
||||
struct sock *nfnl;
|
||||
struct sock *nfnl_stash;
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+ struct netns_nfqnl nfqnl;
|
||||
+#endif
|
||||
#endif
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
|
||||
index 252fd10..3e5bde8 100644
|
||||
--- a/include/net/netfilter/nf_queue.h
|
||||
+++ b/include/net/netfilter/nf_queue.h
|
||||
@@ -19,7 +19,8 @@ struct nf_queue_entry {
|
||||
|
||||
/* Packet queuing */
|
||||
struct nf_queue_handler {
|
||||
- int (*outfn)(struct nf_queue_entry *entry,
|
||||
+ int (*outfn)(struct net *net,
|
||||
+ struct nf_queue_entry *entry,
|
||||
unsigned int queuenum);
|
||||
char *name;
|
||||
};
|
||||
diff --git a/include/net/netns/nfqnl.h b/include/net/netns/nfqnl.h
|
||||
new file mode 100644
|
||||
index 0000000..0fe7fbe
|
||||
--- /dev/null
|
||||
+++ b/include/net/netns/nfqnl.h
|
||||
@@ -0,0 +1,14 @@
|
||||
+#ifndef __NETNS_NFQNL_H
|
||||
+#define __NETNS_NFQNL_H
|
||||
+
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/list.h>
|
||||
+
|
||||
+#define NFQNL_INSTANCE_BUCKETS 16
|
||||
+
|
||||
+struct netns_nfqnl {
|
||||
+ spinlock_t instances_lock;
|
||||
+ struct hlist_head instance_table[NFQNL_INSTANCE_BUCKETS];
|
||||
+};
|
||||
+
|
||||
+#endif /* __NETNS_NFQNL_H */
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index 288c6f5..3cb8733 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -133,6 +133,16 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
const struct nf_afinfo *afinfo;
|
||||
const struct nf_queue_handler *qh;
|
||||
+ struct net *net;
|
||||
+
|
||||
+ if (indev)
|
||||
+ net = dev_net(indev);
|
||||
+ else if (skb->sk)
|
||||
+ net = sock_net(skb->sk);
|
||||
+ else if (outdev)
|
||||
+ net = dev_net(outdev);
|
||||
+ else
|
||||
+ return status;
|
||||
|
||||
/* QUEUE == DROP if no one is waiting, to be safe. */
|
||||
rcu_read_lock();
|
||||
@@ -185,7 +195,7 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
skb_dst_force(skb);
|
||||
afinfo->saveroute(skb, entry);
|
||||
- status = qh->outfn(entry, queuenum);
|
||||
+ status = qh->outfn(net, entry, queuenum);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
|
||||
index add33dc..43c50bb 100644
|
||||
--- a/net/netfilter/nfnetlink_queue.c
|
||||
+++ b/net/netfilter/nfnetlink_queue.c
|
||||
@@ -64,24 +64,19 @@ struct nfqnl_instance {
|
||||
|
||||
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
|
||||
|
||||
-static DEFINE_SPINLOCK(instances_lock);
|
||||
-
|
||||
-#define INSTANCE_BUCKETS 16
|
||||
-static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
|
||||
-
|
||||
static inline u_int8_t instance_hashfn(u_int16_t queue_num)
|
||||
{
|
||||
- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
|
||||
+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS;
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_lookup(u_int16_t queue_num)
|
||||
+instance_lookup(struct net *net, u_int16_t queue_num)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *pos;
|
||||
struct nfqnl_instance *inst;
|
||||
|
||||
- head = &instance_table[instance_hashfn(queue_num)];
|
||||
+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)];
|
||||
hlist_for_each_entry_rcu(inst, pos, head, hlist) {
|
||||
if (inst->queue_num == queue_num)
|
||||
return inst;
|
||||
@@ -90,14 +85,14 @@ instance_lookup(u_int16_t queue_num)
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_create(u_int16_t queue_num, int pid)
|
||||
+instance_create(struct net *net, u_int16_t queue_num, int pid)
|
||||
{
|
||||
struct nfqnl_instance *inst;
|
||||
unsigned int h;
|
||||
int err;
|
||||
|
||||
- spin_lock(&instances_lock);
|
||||
- if (instance_lookup(queue_num)) {
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ if (instance_lookup(net, queue_num)) {
|
||||
err = -EEXIST;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -122,16 +117,16 @@ instance_create(u_int16_t queue_num, int pid)
|
||||
}
|
||||
|
||||
h = instance_hashfn(queue_num);
|
||||
- hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
|
||||
+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]);
|
||||
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
|
||||
return inst;
|
||||
|
||||
out_free:
|
||||
kfree(inst);
|
||||
out_unlock:
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -157,11 +152,11 @@ __instance_destroy(struct nfqnl_instance *inst)
|
||||
}
|
||||
|
||||
static void
|
||||
-instance_destroy(struct nfqnl_instance *inst)
|
||||
+instance_destroy(struct net *net, struct nfqnl_instance *inst)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
__instance_destroy(inst);
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -400,7 +395,8 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
struct nfqnl_instance *queue;
|
||||
@@ -408,7 +404,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
__be32 *packet_id_ptr;
|
||||
|
||||
/* rcu_read_lock()ed by nf_hook_slow() */
|
||||
- queue = instance_lookup(queuenum);
|
||||
+ queue = instance_lookup(net, queuenum);
|
||||
if (!queue) {
|
||||
err = -ESRCH;
|
||||
goto err_out;
|
||||
@@ -440,7 +436,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
*packet_id_ptr = htonl(entry->id);
|
||||
|
||||
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
||||
- err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
|
||||
+ err = nfnetlink_unicast(nskb, net, queue->peer_pid, MSG_DONTWAIT);
|
||||
if (err < 0) {
|
||||
queue->queue_user_dropped++;
|
||||
goto err_out_unlock;
|
||||
@@ -549,16 +545,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
|
||||
/* drop all packets with either indev or outdev == ifindex from all queue
|
||||
* instances */
|
||||
static void
|
||||
-nfqnl_dev_drop(int ifindex)
|
||||
+nfqnl_dev_drop(struct net *net, int ifindex)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head = &net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_rcu(inst, tmp, head, hlist)
|
||||
nfqnl_flush(inst, dev_cmp, ifindex);
|
||||
@@ -575,12 +571,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
- if (!net_eq(dev_net(dev), &init_net))
|
||||
- return NOTIFY_DONE;
|
||||
-
|
||||
/* Drop any packets associated with the downed device */
|
||||
if (event == NETDEV_DOWN)
|
||||
- nfqnl_dev_drop(dev->ifindex);
|
||||
+ nfqnl_dev_drop(dev_net(dev), dev->ifindex);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -598,19 +591,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
|
||||
int i;
|
||||
|
||||
/* destroy all instances for this pid */
|
||||
- spin_lock(&instances_lock);
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ spin_lock(&n->net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp, *t2;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head =
|
||||
+ &n->net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
|
||||
- if ((n->net == &init_net) &&
|
||||
- (n->pid == inst->peer_pid))
|
||||
+ if (n->pid == inst->peer_pid)
|
||||
__instance_destroy(inst);
|
||||
}
|
||||
}
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&n->net->nfqnl.instances_lock);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -630,11 +623,12 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
|
||||
[NFQA_MARK] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
-static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
|
||||
+static struct nfqnl_instance *verdict_instance_lookup(struct net *net,
|
||||
+ u16 queue_num, int nlpid)
|
||||
{
|
||||
struct nfqnl_instance *queue;
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -678,7 +672,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
|
||||
LIST_HEAD(batch_list);
|
||||
u16 queue_num = ntohs(nfmsg->res_id);
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num,
|
||||
+ NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -723,11 +718,12 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
unsigned int verdict;
|
||||
struct nf_queue_entry *entry;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -782,6 +778,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
struct nfqnl_msg_config_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
if (nfqa[NFQA_CFG_CMD]) {
|
||||
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
|
||||
@@ -798,7 +795,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (queue && queue->peer_pid != NETLINK_CB(skb).pid) {
|
||||
ret = -EPERM;
|
||||
goto err_out_unlock;
|
||||
@@ -811,7 +808,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -EBUSY;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- queue = instance_create(queue_num, NETLINK_CB(skb).pid);
|
||||
+ queue = instance_create(net, queue_num,
|
||||
+ NETLINK_CB(skb).pid);
|
||||
if (IS_ERR(queue)) {
|
||||
ret = PTR_ERR(queue);
|
||||
goto err_out_unlock;
|
||||
@@ -822,7 +820,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -ENODEV;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- instance_destroy(queue);
|
||||
+ instance_destroy(net, queue);
|
||||
break;
|
||||
case NFQNL_CFG_CMD_PF_BIND:
|
||||
case NFQNL_CFG_CMD_PF_UNBIND:
|
||||
@@ -886,65 +884,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = {
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct iter_state {
|
||||
+ struct seq_net_private p;
|
||||
unsigned int bucket;
|
||||
};
|
||||
|
||||
-static struct hlist_node *get_first(struct seq_file *seq)
|
||||
+static struct hlist_node *get_first(struct net *net, struct iter_state *st)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
||||
- if (!hlist_empty(&instance_table[st->bucket]))
|
||||
- return instance_table[st->bucket].first;
|
||||
+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) {
|
||||
+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket]))
|
||||
+ return net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
|
||||
+static struct hlist_node *get_next(struct net *net, struct iter_state *st,
|
||||
+ struct hlist_node *h)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
h = h->next;
|
||||
while (!h) {
|
||||
- if (++st->bucket >= INSTANCE_BUCKETS)
|
||||
+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS)
|
||||
return NULL;
|
||||
|
||||
- h = instance_table[st->bucket].first;
|
||||
+ h = net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
|
||||
+static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
|
||||
+ loff_t pos)
|
||||
{
|
||||
struct hlist_node *head;
|
||||
- head = get_first(seq);
|
||||
+ head = get_first(net, st);
|
||||
|
||||
if (head)
|
||||
- while (pos && (head = get_next(seq, head)))
|
||||
+ while (pos && (head = get_next(net, st, head)))
|
||||
pos--;
|
||||
return pos ? NULL : head;
|
||||
}
|
||||
|
||||
static void *seq_start(struct seq_file *seq, loff_t *pos)
|
||||
- __acquires(instances_lock)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
- return get_idx(seq, *pos);
|
||||
+ struct net *net = seq_file_net(seq);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ return get_idx(net, seq->private, *pos);
|
||||
}
|
||||
|
||||
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
(*pos)++;
|
||||
- return get_next(s, v);
|
||||
+ return get_next(seq_file_net(s), s->private, v);
|
||||
}
|
||||
|
||||
static void seq_stop(struct seq_file *s, void *v)
|
||||
- __releases(instances_lock)
|
||||
{
|
||||
- spin_unlock(&instances_lock);
|
||||
+ struct net *net = seq_file_net(s);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static int seq_show(struct seq_file *s, void *v)
|
||||
@@ -968,8 +965,8 @@ static const struct seq_operations nfqnl_seq_ops = {
|
||||
|
||||
static int nfqnl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- return seq_open_private(file, &nfqnl_seq_ops,
|
||||
- sizeof(struct iter_state));
|
||||
+ return seq_open_net(inode, file, &nfqnl_seq_ops,
|
||||
+ sizeof(struct iter_state));
|
||||
}
|
||||
|
||||
static const struct file_operations nfqnl_file_ops = {
|
||||
@@ -977,13 +974,19 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
.open = nfqnl_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
- .release = seq_release_private,
|
||||
+ .release = seq_release_net,
|
||||
};
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock_init(&net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++)
|
||||
+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]);
|
||||
+
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nfnetlink_queue", 0440,
|
||||
net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
@@ -1007,7 +1010,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status;
|
||||
+ int status;
|
||||
|
||||
status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
if (status) {
|
||||
@@ -1016,9 +1019,6 @@ static int __init nfnetlink_queue_init(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
- INIT_HLIST_HEAD(&instance_table[i]);
|
||||
-
|
||||
netlink_register_notifier(&nfqnl_rtnl_notifier);
|
||||
status = nfnetlink_subsys_register(&nfqnl_subsys);
|
||||
if (status < 0) {
|
||||
--
|
||||
1.7.10.4
|
||||
|
70
kernel/core-kernel-3.8/Makefile
Normal file
70
kernel/core-kernel-3.8/Makefile
Normal file
|
@ -0,0 +1,70 @@
|
|||
VERSION := $(shell dpkg -l linux-source 2> /dev/null | \
|
||||
awk '/^i/ {print gensub("([0-9]+[.][0-9]+[.][0-9]+)[.0-9]*", "\\1", "1", $$3)}')
|
||||
TARBALL := /usr/src/linux-source-$(VERSION).tar.bz2
|
||||
|
||||
SUBVERSION := -core
|
||||
REVISION := 1.0
|
||||
|
||||
PATCHDIR := patches
|
||||
PATCHES := $(sort $(wildcard $(PATCHDIR)/*.patch))
|
||||
|
||||
CONFIG := config.core
|
||||
|
||||
DEPDEBS := linux-source kernel-package po-debconf gettext
|
||||
|
||||
CONCURRENCY_LEVEL := $(shell lscpu 2> /dev/null | \
|
||||
awk '/^CPU\(s\)/ {print $$2}')
|
||||
ifeq ($(strip $(CONCURRENCY_LEVEL)),)
|
||||
CONCURRENCY_LEVEL := 1
|
||||
endif
|
||||
|
||||
MAINTAINER ?= $(shell id -nu)
|
||||
EMAIL ?= $(MAINTAINER)@$(shell hostname -f)
|
||||
|
||||
MAKEKPKGFLAGS := --initrd --rootcmd fakeroot --us --uc \
|
||||
--append-to-version $(SUBVERSION) --revision $(REVISION)
|
||||
|
||||
.PHONY: build
|
||||
build: debcheck defaultconfig patch
|
||||
export CONCURRENCY_LEVEL="$(CONCURRENCY_LEVEL)" \
|
||||
KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && \
|
||||
if [ -f ../$(CONFIG) ]; then \
|
||||
cat ../$(CONFIG) >> .config; \
|
||||
fi && \
|
||||
fakeroot make-kpkg $(MAKEKPKGFLAGS) binary-arch
|
||||
|
||||
.PHONY: debcheck
|
||||
debcheck:
|
||||
for d in $(DEPDEBS); do \
|
||||
if ! dpkg-query -s $$d > /dev/null 2>&1; then \
|
||||
echo ERROR: build dependency not installed: $$d >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
.PHONY: defaultconfig
|
||||
defaultconfig: linux-source-$(VERSION)
|
||||
export KPKG_MAINTAINER="$(MAINTAINER)" KPKG_EMAIL="$(EMAIL)"; \
|
||||
cd linux-source-$(VERSION) && make-kpkg $(MAKEKPKGFLAGS) configure
|
||||
|
||||
.PHONY: patch
|
||||
patch: linux-source-$(VERSION) patch-stamp
|
||||
patch-stamp: $(PATCHES)
|
||||
for p in $^; do \
|
||||
if ! patch -d linux-source-$(VERSION) -p1 < $$p; then \
|
||||
echo ERROR: applying patch failed: $$p >&2; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
touch patch-stamp
|
||||
|
||||
.PHONY: source
|
||||
source: linux-source-$(VERSION)
|
||||
|
||||
linux-source-$(VERSION): $(TARBALL)
|
||||
tar -xjf $^
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf linux-source-$(VERSION) patch-stamp
|
1
kernel/core-kernel-3.8/config.core
Normal file
1
kernel/core-kernel-3.8/config.core
Normal file
|
@ -0,0 +1 @@
|
|||
CONFIG_XFRM_STATISTICS=y
|
29
kernel/core-kernel-3.8/patches/00-ifindex.patch
Normal file
29
kernel/core-kernel-3.8/patches/00-ifindex.patch
Normal file
|
@ -0,0 +1,29 @@
|
|||
From 1d992600b0f1962d0478df2083b76b1ceba50517 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Mon, 3 Jun 2013 18:29:42 -0700
|
||||
Subject: [PATCH 1/3] Make network device ifindex sequential per network
|
||||
namespace.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
net/core/dev.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index d592214..4b8da6e 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -6455,8 +6455,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
|
||||
/* Actually switch the network namespace */
|
||||
dev_net_set(dev, net);
|
||||
|
||||
- /* If there is an ifindex conflict assign a new one */
|
||||
- if (__dev_get_by_index(net, dev->ifindex)) {
|
||||
+ /* Assign a new ifindex */
|
||||
+ {
|
||||
int iflink = (dev->iflink == dev->ifindex);
|
||||
dev->ifindex = dev_new_index(net);
|
||||
if (iflink)
|
||||
--
|
||||
1.8.1.2
|
||||
|
307
kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch
Normal file
307
kernel/core-kernel-3.8/patches/00-nfnetlink_queue.patch
Normal file
|
@ -0,0 +1,307 @@
|
|||
From 433bc9e01b6a50db276c0b0d9dcd8bfcc2bc42f8 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Mon, 3 Jun 2013 18:30:31 -0700
|
||||
Subject: [PATCH 2/3] netfilter: Make the /proc/net/netfilter directory per
|
||||
netns.
|
||||
|
||||
This allows subsystems to create per-netns entries.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/linux/netfilter.h | 5 ----
|
||||
include/net/net_namespace.h | 3 +++
|
||||
net/netfilter/core.c | 35 ++++++++++++++++++++-------
|
||||
net/netfilter/nf_log.c | 33 ++++++++++++++++++++++----
|
||||
net/netfilter/nfnetlink_log.c | 46 ++++++++++++++++++++++++------------
|
||||
net/netfilter/nfnetlink_queue_core.c | 45 ++++++++++++++++++++++++-----------
|
||||
6 files changed, 121 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
|
||||
index ee14284..0060fde 100644
|
||||
--- a/include/linux/netfilter.h
|
||||
+++ b/include/linux/netfilter.h
|
||||
@@ -289,11 +289,6 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
#endif
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-#include <linux/proc_fs.h>
|
||||
-extern struct proc_dir_entry *proc_net_netfilter;
|
||||
-#endif
|
||||
-
|
||||
#else /* !CONFIG_NETFILTER */
|
||||
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
|
||||
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index de644bc..96b2242 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -94,6 +94,9 @@ struct net {
|
||||
struct netns_dccp dccp;
|
||||
#endif
|
||||
#ifdef CONFIG_NETFILTER
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ struct proc_dir_entry *proc_net_netfilter;
|
||||
+#endif
|
||||
struct netns_xt xt;
|
||||
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
|
||||
struct netns_ct ct;
|
||||
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
|
||||
index a9c488b..00e356d 100644
|
||||
--- a/net/netfilter/core.c
|
||||
+++ b/net/netfilter/core.c
|
||||
@@ -276,25 +276,44 @@ void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
|
||||
EXPORT_SYMBOL(nf_nat_decode_session_hook);
|
||||
#endif
|
||||
|
||||
+static int __net_init netfilter_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ net->proc_net_netfilter = proc_net_mkdir(net, "netfilter",
|
||||
+ net->proc_net);
|
||||
+ if (!net->proc_net_netfilter) {
|
||||
+ pr_err("%s: cannot create netfilter proc entry\n", __func__);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_net_exit(struct net *net)
|
||||
+{
|
||||
#ifdef CONFIG_PROC_FS
|
||||
-struct proc_dir_entry *proc_net_netfilter;
|
||||
-EXPORT_SYMBOL(proc_net_netfilter);
|
||||
+ proc_net_remove(net, "netfilter");
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_net_ops = {
|
||||
+ .init = netfilter_net_init,
|
||||
+ .exit = netfilter_net_exit,
|
||||
+};
|
||||
|
||||
void __init netfilter_init(void)
|
||||
{
|
||||
int i, h;
|
||||
+
|
||||
+ if (register_pernet_subsys(&netfilter_net_ops))
|
||||
+ panic("%s: failed to register per netns operations", __func__);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
|
||||
for (h = 0; h < NF_MAX_HOOKS; h++)
|
||||
INIT_LIST_HEAD(&nf_hooks[i][h]);
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- proc_net_netfilter = proc_mkdir("netfilter", init_net.proc_net);
|
||||
- if (!proc_net_netfilter)
|
||||
- panic("cannot create netfilter proc entry");
|
||||
-#endif
|
||||
-
|
||||
if (netfilter_log_init() < 0)
|
||||
panic("cannot initialize nf_log");
|
||||
}
|
||||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
|
||||
index 9e31269..5f33072 100644
|
||||
--- a/net/netfilter/nf_log.c
|
||||
+++ b/net/netfilter/nf_log.c
|
||||
@@ -290,14 +290,39 @@ static __init int netfilter_log_sysctl_init(void)
|
||||
}
|
||||
#endif /* CONFIG_SYSCTL */
|
||||
|
||||
-int __init netfilter_log_init(void)
|
||||
+static int __net_init netfilter_log_net_init(struct net *net)
|
||||
{
|
||||
- int i, r;
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nf_log", S_IRUGO,
|
||||
- proc_net_netfilter, &nflog_file_ops))
|
||||
- return -1;
|
||||
+ net->proc_net_netfilter, &nflog_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit netfilter_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nf_log", net->proc_net_netfilter);
|
||||
#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations netfilter_log_net_ops = {
|
||||
+ .init = netfilter_log_net_init,
|
||||
+ .exit = netfilter_log_net_exit,
|
||||
+};
|
||||
+
|
||||
+int __init netfilter_log_init(void)
|
||||
+{
|
||||
+ int i, r;
|
||||
+
|
||||
+ r = register_pernet_subsys(&netfilter_log_net_ops);
|
||||
+ if (r) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return r;
|
||||
+ }
|
||||
|
||||
/* Errors will trigger panic, unroll on error is unnecessary. */
|
||||
r = netfilter_log_sysctl_init();
|
||||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
|
||||
index 92fd8ec..9571c43 100644
|
||||
--- a/net/netfilter/nfnetlink_log.c
|
||||
+++ b/net/netfilter/nfnetlink_log.c
|
||||
@@ -986,9 +986,39 @@ static const struct file_operations nful_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_log_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_log", 0440,
|
||||
+ net->proc_net_netfilter, &nful_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_log_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_log", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_log_net_ops = {
|
||||
+ .init = nfnetlink_log_net_init,
|
||||
+ .exit = nfnetlink_log_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_log_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_log_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -1011,19 +1041,8 @@ static int __init nfnetlink_log_init(void)
|
||||
goto cleanup_subsys;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_log", 0440,
|
||||
- proc_net_netfilter, &nful_file_ops)) {
|
||||
- status = -ENOMEM;
|
||||
- goto cleanup_logger;
|
||||
- }
|
||||
-#endif
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_logger:
|
||||
- nf_log_unregister(&nfulnl_logger);
|
||||
-#endif
|
||||
cleanup_subsys:
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
cleanup_netlink_notifier:
|
||||
@@ -1034,9 +1053,6 @@ cleanup_netlink_notifier:
|
||||
static void __exit nfnetlink_log_fini(void)
|
||||
{
|
||||
nf_log_unregister(&nfulnl_logger);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_log", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfulnl_subsys);
|
||||
netlink_unregister_notifier(&nfulnl_rtnl_notifier);
|
||||
}
|
||||
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
|
||||
index 3158d87..8f2d9bb 100644
|
||||
--- a/net/netfilter/nfnetlink_queue_core.c
|
||||
+++ b/net/netfilter/nfnetlink_queue_core.c
|
||||
@@ -1048,9 +1048,39 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
+static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ if (!proc_create("nfnetlink_queue", 0440,
|
||||
+ net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
+ return -ENOMEM;
|
||||
+#endif
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void __net_exit nfnetlink_queue_net_exit(struct net *net)
|
||||
+{
|
||||
+#ifdef CONFIG_PROC_FS
|
||||
+ remove_proc_entry("nfnetlink_queue", net->proc_net_netfilter);
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
+ .init = nfnetlink_queue_net_init,
|
||||
+ .exit = nfnetlink_queue_net_exit,
|
||||
+};
|
||||
+
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status = -ENOMEM;
|
||||
+ int i, status;
|
||||
+
|
||||
+ status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
+ if (status) {
|
||||
+ pr_err("%s: failed to register per netns operations\n",
|
||||
+ __func__);
|
||||
+ return status;
|
||||
+ }
|
||||
|
||||
for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
INIT_HLIST_HEAD(&instance_table[i]);
|
||||
@@ -1062,20 +1092,10 @@ static int __init nfnetlink_queue_init(void)
|
||||
goto cleanup_netlink_notifier;
|
||||
}
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- if (!proc_create("nfnetlink_queue", 0440,
|
||||
- proc_net_netfilter, &nfqnl_file_ops))
|
||||
- goto cleanup_subsys;
|
||||
-#endif
|
||||
-
|
||||
register_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
nf_register_queue_handler(&nfqh);
|
||||
return status;
|
||||
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
-cleanup_subsys:
|
||||
- nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
-#endif
|
||||
cleanup_netlink_notifier:
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
return status;
|
||||
@@ -1085,9 +1105,6 @@ static void __exit nfnetlink_queue_fini(void)
|
||||
{
|
||||
nf_unregister_queue_handler();
|
||||
unregister_netdevice_notifier(&nfqnl_dev_notifier);
|
||||
-#ifdef CONFIG_PROC_FS
|
||||
- remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
|
||||
-#endif
|
||||
nfnetlink_subsys_unregister(&nfqnl_subsys);
|
||||
netlink_unregister_notifier(&nfqnl_rtnl_notifier);
|
||||
|
||||
--
|
||||
1.8.1.2
|
||||
|
475
kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch
Normal file
475
kernel/core-kernel-3.8/patches/01-nfnetlink_queue.patch
Normal file
|
@ -0,0 +1,475 @@
|
|||
From 3d1c0bfef9d6ca43050e7a9077b46e0139ee1e1f Mon Sep 17 00:00:00 2001
|
||||
From: Tom Goff <thomas.goff@boeing.com>
|
||||
Date: Mon, 3 Jun 2013 18:31:29 -0700
|
||||
Subject: [PATCH 3/3] netfilter: nfnetlink_queue: Add netns support.
|
||||
|
||||
Make nfnetlink_queue network namespace aware including a per-netns
|
||||
/proc/net/netfilter/nfnetlink_queue file.
|
||||
|
||||
Signed-off-by: Tom Goff <thomas.goff@boeing.com>
|
||||
---
|
||||
include/net/net_namespace.h | 6 ++
|
||||
include/net/netfilter/nf_queue.h | 3 +-
|
||||
net/netfilter/nf_queue.c | 12 ++-
|
||||
net/netfilter/nfnetlink_queue_core.c | 137 ++++++++++++++++++-----------------
|
||||
4 files changed, 88 insertions(+), 70 deletions(-)
|
||||
|
||||
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
|
||||
index 96b2242..1af155b 100644
|
||||
--- a/include/net/net_namespace.h
|
||||
+++ b/include/net/net_namespace.h
|
||||
@@ -22,6 +22,9 @@
|
||||
#include <net/netns/conntrack.h>
|
||||
#endif
|
||||
#include <net/netns/xfrm.h>
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+#include <net/netns/nfqnl.h>
|
||||
+#endif
|
||||
|
||||
struct user_namespace;
|
||||
struct proc_dir_entry;
|
||||
@@ -106,6 +109,9 @@ struct net {
|
||||
#endif
|
||||
struct sock *nfnl;
|
||||
struct sock *nfnl_stash;
|
||||
+#if defined(CONFIG_NETFILTER_NETLINK_QUEUE) || defined(CONFIG_NETFILTER_NETLINK_QUEUE_MODULE)
|
||||
+ struct netns_nfqnl nfqnl;
|
||||
+#endif
|
||||
#endif
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
|
||||
index fb1c0be..484453d 100644
|
||||
--- a/include/net/netfilter/nf_queue.h
|
||||
+++ b/include/net/netfilter/nf_queue.h
|
||||
@@ -19,7 +19,8 @@ struct nf_queue_entry {
|
||||
|
||||
/* Packet queuing */
|
||||
struct nf_queue_handler {
|
||||
- int (*outfn)(struct nf_queue_entry *entry,
|
||||
+ int (*outfn)(struct net *net,
|
||||
+ struct nf_queue_entry *entry,
|
||||
unsigned int queuenum);
|
||||
};
|
||||
|
||||
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
|
||||
index d812c12..0d69be9 100644
|
||||
--- a/net/netfilter/nf_queue.c
|
||||
+++ b/net/netfilter/nf_queue.c
|
||||
@@ -81,6 +81,16 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
const struct nf_afinfo *afinfo;
|
||||
const struct nf_queue_handler *qh;
|
||||
+ struct net *net;
|
||||
+
|
||||
+ if (indev)
|
||||
+ net = dev_net(indev);
|
||||
+ else if (skb->sk)
|
||||
+ net = sock_net(skb->sk);
|
||||
+ else if (outdev)
|
||||
+ net = dev_net(outdev);
|
||||
+ else
|
||||
+ return status;
|
||||
|
||||
/* QUEUE == DROP if no one is waiting, to be safe. */
|
||||
rcu_read_lock();
|
||||
@@ -133,7 +143,7 @@ static int __nf_queue(struct sk_buff *skb,
|
||||
#endif
|
||||
skb_dst_force(skb);
|
||||
afinfo->saveroute(skb, entry);
|
||||
- status = qh->outfn(entry, queuenum);
|
||||
+ status = qh->outfn(net, entry, queuenum);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
|
||||
index 8f2d9bb..1e0a830 100644
|
||||
--- a/net/netfilter/nfnetlink_queue_core.c
|
||||
+++ b/net/netfilter/nfnetlink_queue_core.c
|
||||
@@ -66,24 +66,19 @@ struct nfqnl_instance {
|
||||
|
||||
typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
|
||||
|
||||
-static DEFINE_SPINLOCK(instances_lock);
|
||||
-
|
||||
-#define INSTANCE_BUCKETS 16
|
||||
-static struct hlist_head instance_table[INSTANCE_BUCKETS] __read_mostly;
|
||||
-
|
||||
static inline u_int8_t instance_hashfn(u_int16_t queue_num)
|
||||
{
|
||||
- return ((queue_num >> 8) | queue_num) % INSTANCE_BUCKETS;
|
||||
+ return ((queue_num >> 8) | queue_num) % NFQNL_INSTANCE_BUCKETS;
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_lookup(u_int16_t queue_num)
|
||||
+instance_lookup(struct net *net, u_int16_t queue_num)
|
||||
{
|
||||
struct hlist_head *head;
|
||||
struct hlist_node *pos;
|
||||
struct nfqnl_instance *inst;
|
||||
|
||||
- head = &instance_table[instance_hashfn(queue_num)];
|
||||
+ head = &net->nfqnl.instance_table[instance_hashfn(queue_num)];
|
||||
hlist_for_each_entry_rcu(inst, pos, head, hlist) {
|
||||
if (inst->queue_num == queue_num)
|
||||
return inst;
|
||||
@@ -92,14 +87,14 @@ instance_lookup(u_int16_t queue_num)
|
||||
}
|
||||
|
||||
static struct nfqnl_instance *
|
||||
-instance_create(u_int16_t queue_num, int portid)
|
||||
+instance_create(struct net *net, u_int16_t queue_num, int portid)
|
||||
{
|
||||
struct nfqnl_instance *inst;
|
||||
unsigned int h;
|
||||
int err;
|
||||
|
||||
- spin_lock(&instances_lock);
|
||||
- if (instance_lookup(queue_num)) {
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ if (instance_lookup(net, queue_num)) {
|
||||
err = -EEXIST;
|
||||
goto out_unlock;
|
||||
}
|
||||
@@ -124,16 +119,16 @@ instance_create(u_int16_t queue_num, int portid)
|
||||
}
|
||||
|
||||
h = instance_hashfn(queue_num);
|
||||
- hlist_add_head_rcu(&inst->hlist, &instance_table[h]);
|
||||
+ hlist_add_head_rcu(&inst->hlist, &net->nfqnl.instance_table[h]);
|
||||
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
|
||||
return inst;
|
||||
|
||||
out_free:
|
||||
kfree(inst);
|
||||
out_unlock:
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
@@ -159,11 +154,11 @@ __instance_destroy(struct nfqnl_instance *inst)
|
||||
}
|
||||
|
||||
static void
|
||||
-instance_destroy(struct nfqnl_instance *inst)
|
||||
+instance_destroy(struct net *net, struct nfqnl_instance *inst)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
__instance_destroy(inst);
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -417,7 +412,8 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static int
|
||||
-nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
+nfqnl_enqueue_packet(struct net *net, struct nf_queue_entry *entry,
|
||||
+ unsigned int queuenum)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
struct nfqnl_instance *queue;
|
||||
@@ -426,7 +422,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
int failopen = 0;
|
||||
|
||||
/* rcu_read_lock()ed by nf_hook_slow() */
|
||||
- queue = instance_lookup(queuenum);
|
||||
+ queue = instance_lookup(net, queuenum);
|
||||
if (!queue) {
|
||||
err = -ESRCH;
|
||||
goto err_out;
|
||||
@@ -463,7 +459,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
*packet_id_ptr = htonl(entry->id);
|
||||
|
||||
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
||||
- err = nfnetlink_unicast(nskb, &init_net, queue->peer_portid, MSG_DONTWAIT);
|
||||
+ err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT);
|
||||
if (err < 0) {
|
||||
queue->queue_user_dropped++;
|
||||
goto err_out_unlock;
|
||||
@@ -576,16 +572,16 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
|
||||
/* drop all packets with either indev or outdev == ifindex from all queue
|
||||
* instances */
|
||||
static void
|
||||
-nfqnl_dev_drop(int ifindex)
|
||||
+nfqnl_dev_drop(struct net *net, int ifindex)
|
||||
{
|
||||
int i;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head = &net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_rcu(inst, tmp, head, hlist)
|
||||
nfqnl_flush(inst, dev_cmp, ifindex);
|
||||
@@ -602,12 +598,9 @@ nfqnl_rcv_dev_event(struct notifier_block *this,
|
||||
{
|
||||
struct net_device *dev = ptr;
|
||||
|
||||
- if (!net_eq(dev_net(dev), &init_net))
|
||||
- return NOTIFY_DONE;
|
||||
-
|
||||
/* Drop any packets associated with the downed device */
|
||||
if (event == NETDEV_DOWN)
|
||||
- nfqnl_dev_drop(dev->ifindex);
|
||||
+ nfqnl_dev_drop(dev_net(dev), dev->ifindex);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
@@ -625,19 +618,19 @@ nfqnl_rcv_nl_event(struct notifier_block *this,
|
||||
int i;
|
||||
|
||||
/* destroy all instances for this portid */
|
||||
- spin_lock(&instances_lock);
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++) {
|
||||
+ spin_lock(&n->net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++) {
|
||||
struct hlist_node *tmp, *t2;
|
||||
struct nfqnl_instance *inst;
|
||||
- struct hlist_head *head = &instance_table[i];
|
||||
+ struct hlist_head *head =
|
||||
+ &n->net->nfqnl.instance_table[i];
|
||||
|
||||
hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
|
||||
- if ((n->net == &init_net) &&
|
||||
- (n->portid == inst->peer_portid))
|
||||
+ if (n->portid == inst->peer_portid)
|
||||
__instance_destroy(inst);
|
||||
}
|
||||
}
|
||||
- spin_unlock(&instances_lock);
|
||||
+ spin_unlock(&n->net->nfqnl.instances_lock);
|
||||
}
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
@@ -658,11 +651,13 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
|
||||
[NFQA_MARK] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
-static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlportid)
|
||||
+static struct nfqnl_instance *verdict_instance_lookup(struct net *net,
|
||||
+ u16 queue_num,
|
||||
+ int nlportid)
|
||||
{
|
||||
struct nfqnl_instance *queue;
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@@ -706,7 +701,8 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
|
||||
LIST_HEAD(batch_list);
|
||||
u16 queue_num = ntohs(nfmsg->res_id);
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid);
|
||||
+ queue = verdict_instance_lookup(sock_net(ctnl), queue_num,
|
||||
+ NETLINK_CB(skb).portid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -751,13 +747,14 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
unsigned int verdict;
|
||||
struct nf_queue_entry *entry;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
enum ip_conntrack_info uninitialized_var(ctinfo);
|
||||
struct nf_conn *ct = NULL;
|
||||
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (!queue)
|
||||
|
||||
- queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid);
|
||||
+ queue = verdict_instance_lookup(net, queue_num, NETLINK_CB(skb).portid);
|
||||
if (IS_ERR(queue))
|
||||
return PTR_ERR(queue);
|
||||
|
||||
@@ -822,6 +819,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
struct nfqnl_instance *queue;
|
||||
struct nfqnl_msg_config_cmd *cmd = NULL;
|
||||
int ret = 0;
|
||||
+ struct net *net = sock_net(ctnl);
|
||||
|
||||
if (nfqa[NFQA_CFG_CMD]) {
|
||||
cmd = nla_data(nfqa[NFQA_CFG_CMD]);
|
||||
@@ -834,7 +832,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
- queue = instance_lookup(queue_num);
|
||||
+ queue = instance_lookup(net, queue_num);
|
||||
if (queue && queue->peer_portid != NETLINK_CB(skb).portid) {
|
||||
ret = -EPERM;
|
||||
goto err_out_unlock;
|
||||
@@ -847,7 +845,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -EBUSY;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- queue = instance_create(queue_num, NETLINK_CB(skb).portid);
|
||||
+ queue = instance_create(net, queue_num,
|
||||
+ NETLINK_CB(skb).portid);
|
||||
if (IS_ERR(queue)) {
|
||||
ret = PTR_ERR(queue);
|
||||
goto err_out_unlock;
|
||||
@@ -858,7 +857,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
|
||||
ret = -ENODEV;
|
||||
goto err_out_unlock;
|
||||
}
|
||||
- instance_destroy(queue);
|
||||
+ instance_destroy(net, queue);
|
||||
break;
|
||||
case NFQNL_CFG_CMD_PF_BIND:
|
||||
case NFQNL_CFG_CMD_PF_UNBIND:
|
||||
@@ -952,65 +951,64 @@ static const struct nfnetlink_subsystem nfqnl_subsys = {
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct iter_state {
|
||||
+ struct seq_net_private p;
|
||||
unsigned int bucket;
|
||||
};
|
||||
|
||||
-static struct hlist_node *get_first(struct seq_file *seq)
|
||||
+static struct hlist_node *get_first(struct net *net, struct iter_state *st)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
if (!st)
|
||||
return NULL;
|
||||
|
||||
- for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
|
||||
- if (!hlist_empty(&instance_table[st->bucket]))
|
||||
- return instance_table[st->bucket].first;
|
||||
+ for (st->bucket = 0; st->bucket < NFQNL_INSTANCE_BUCKETS; st->bucket++) {
|
||||
+ if (!hlist_empty(&net->nfqnl.instance_table[st->bucket]))
|
||||
+ return net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_next(struct seq_file *seq, struct hlist_node *h)
|
||||
+static struct hlist_node *get_next(struct net *net, struct iter_state *st,
|
||||
+ struct hlist_node *h)
|
||||
{
|
||||
- struct iter_state *st = seq->private;
|
||||
-
|
||||
h = h->next;
|
||||
while (!h) {
|
||||
- if (++st->bucket >= INSTANCE_BUCKETS)
|
||||
+ if (++st->bucket >= NFQNL_INSTANCE_BUCKETS)
|
||||
return NULL;
|
||||
|
||||
- h = instance_table[st->bucket].first;
|
||||
+ h = net->nfqnl.instance_table[st->bucket].first;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
-static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos)
|
||||
+static struct hlist_node *get_idx(struct net *net, struct iter_state *st,
|
||||
+ loff_t pos)
|
||||
{
|
||||
struct hlist_node *head;
|
||||
- head = get_first(seq);
|
||||
+ head = get_first(net, st);
|
||||
|
||||
if (head)
|
||||
- while (pos && (head = get_next(seq, head)))
|
||||
+ while (pos && (head = get_next(net, st, head)))
|
||||
pos--;
|
||||
return pos ? NULL : head;
|
||||
}
|
||||
|
||||
static void *seq_start(struct seq_file *seq, loff_t *pos)
|
||||
- __acquires(instances_lock)
|
||||
{
|
||||
- spin_lock(&instances_lock);
|
||||
- return get_idx(seq, *pos);
|
||||
+ struct net *net = seq_file_net(seq);
|
||||
+ spin_lock(&net->nfqnl.instances_lock);
|
||||
+ return get_idx(net, seq->private, *pos);
|
||||
}
|
||||
|
||||
static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
(*pos)++;
|
||||
- return get_next(s, v);
|
||||
+ return get_next(seq_file_net(s), s->private, v);
|
||||
}
|
||||
|
||||
static void seq_stop(struct seq_file *s, void *v)
|
||||
- __releases(instances_lock)
|
||||
{
|
||||
- spin_unlock(&instances_lock);
|
||||
+ struct net *net = seq_file_net(s);
|
||||
+ spin_unlock(&net->nfqnl.instances_lock);
|
||||
}
|
||||
|
||||
static int seq_show(struct seq_file *s, void *v)
|
||||
@@ -1034,8 +1032,8 @@ static const struct seq_operations nfqnl_seq_ops = {
|
||||
|
||||
static int nfqnl_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
- return seq_open_private(file, &nfqnl_seq_ops,
|
||||
- sizeof(struct iter_state));
|
||||
+ return seq_open_net(inode, file, &nfqnl_seq_ops,
|
||||
+ sizeof(struct iter_state));
|
||||
}
|
||||
|
||||
static const struct file_operations nfqnl_file_ops = {
|
||||
@@ -1043,13 +1041,19 @@ static const struct file_operations nfqnl_file_ops = {
|
||||
.open = nfqnl_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
- .release = seq_release_private,
|
||||
+ .release = seq_release_net,
|
||||
};
|
||||
|
||||
#endif /* PROC_FS */
|
||||
|
||||
static int __net_init nfnetlink_queue_net_init(struct net *net)
|
||||
{
|
||||
+ int i;
|
||||
+
|
||||
+ spin_lock_init(&net->nfqnl.instances_lock);
|
||||
+ for (i = 0; i < NFQNL_INSTANCE_BUCKETS; i++)
|
||||
+ INIT_HLIST_HEAD(&net->nfqnl.instance_table[i]);
|
||||
+
|
||||
#ifdef CONFIG_PROC_FS
|
||||
if (!proc_create("nfnetlink_queue", 0440,
|
||||
net->proc_net_netfilter, &nfqnl_file_ops))
|
||||
@@ -1073,7 +1077,7 @@ static struct pernet_operations nfnetlink_queue_net_ops = {
|
||||
|
||||
static int __init nfnetlink_queue_init(void)
|
||||
{
|
||||
- int i, status;
|
||||
+ int status;
|
||||
|
||||
status = register_pernet_subsys(&nfnetlink_queue_net_ops);
|
||||
if (status) {
|
||||
@@ -1082,9 +1086,6 @@ static int __init nfnetlink_queue_init(void)
|
||||
return status;
|
||||
}
|
||||
|
||||
- for (i = 0; i < INSTANCE_BUCKETS; i++)
|
||||
- INIT_HLIST_HEAD(&instance_table[i]);
|
||||
-
|
||||
netlink_register_notifier(&nfqnl_rtnl_notifier);
|
||||
status = nfnetlink_subsys_register(&nfqnl_subsys);
|
||||
if (status < 0) {
|
||||
--
|
||||
1.8.1.2
|
||||
|
7150
kernel/freebsd/4.11-R-CORE.diff
Normal file
7150
kernel/freebsd/4.11-R-CORE.diff
Normal file
File diff suppressed because it is too large
Load diff
24
kernel/freebsd/README.txt
Normal file
24
kernel/freebsd/README.txt
Normal file
|
@ -0,0 +1,24 @@
|
|||
CORE kernel patches
|
||||
|
||||
For information on the kernel modules ng_pipe and ng_wlan, see the README files in their respective directories. You should run the make && make install from
|
||||
the module directories for CORE to work properly.
|
||||
|
||||
FreeBSD 8.x requires the small patches to allow per-node directories.
|
||||
|
||||
The FreeBSD 7.x version of CORE does not require the patch included here.
|
||||
Instead you should download the latest vimage_7 kernel from:
|
||||
http://imunes.net/virtnet/
|
||||
|
||||
The FreeBSD 4.11 version of CORE requires the included patch to work. See the
|
||||
CORE manual for patching details.
|
||||
|
||||
ng_pipe module you should install with FreeBSD 4.11 or 7.x
|
||||
ng_wlan module you should install with FreeBSD 4.11 or 7.x
|
||||
4.11-R-CORE.diff patch you should use with FreeBSD 4.11
|
||||
freebsd7-config-CORE config that you may use with vimage_7 kernels
|
||||
freebsd7-config-COREDEBUG debugging config for use with vimage_7 kernels
|
||||
vimage_7-CORE.diff patch to add multicast routing to vimage_7_20081015
|
||||
imunes-8.0-RELEASE.diff per-node directories, persistent hub/switch, and
|
||||
traffic snopping for wireshark for FreeBSD 8.0
|
||||
symlinks-8.1-RELEASE.diff per-node directories for FreeBSD 8.1
|
||||
|
20
kernel/freebsd/freebsd7-config-CORE
Normal file
20
kernel/freebsd/freebsd7-config-CORE
Normal file
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# VIMAGE - sample kernel configuration file with a virtualized network stack
|
||||
# configure.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
include GENERIC
|
||||
ident CORE
|
||||
|
||||
options IPSEC
|
||||
device crypto
|
||||
options VIMAGE
|
||||
options IPFIREWALL
|
||||
options IPFIREWALL_DEFAULT_TO_ACCEPT #allow everything by default
|
||||
|
||||
#
|
||||
# Some kernel subsystems and functions don't yet compile with VIMAGE. Remove
|
||||
# from the configuration for now.
|
||||
#
|
||||
nooptions SCTP
|
22
kernel/freebsd/freebsd7-config-COREDEBUG
Normal file
22
kernel/freebsd/freebsd7-config-COREDEBUG
Normal file
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# VIMAGE - sample kernel configuration file with a virtualized network stack
|
||||
# configure.
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
include GENERIC
|
||||
ident COREDEBUG
|
||||
|
||||
device crypto
|
||||
options IPSEC
|
||||
options VIMAGE
|
||||
options DDB
|
||||
options GDB
|
||||
options KDB
|
||||
options KDB_TRACE
|
||||
|
||||
#
|
||||
# Some kernel subsystems and functions don't yet compile with VIMAGE. Remove
|
||||
# from the configuration for now.
|
||||
#
|
||||
nooptions SCTP
|
11
kernel/freebsd/freebsd8-config-CORE
Normal file
11
kernel/freebsd/freebsd8-config-CORE
Normal file
|
@ -0,0 +1,11 @@
|
|||
# this is the FreeBSD 8.x kernel configuration file for CORE
|
||||
include GENERIC
|
||||
ident CORE
|
||||
|
||||
options VIMAGE
|
||||
nooptions SCTP
|
||||
options IPSEC
|
||||
device crypto
|
||||
|
||||
options IPFIREWALL
|
||||
options IPFIREWALL_DEFAULT_TO_ACCEPT
|
372
kernel/freebsd/imunes-8.0-RELEASE.diff
Normal file
372
kernel/freebsd/imunes-8.0-RELEASE.diff
Normal file
|
@ -0,0 +1,372 @@
|
|||
# This patch is from http://imunes.net/imunes-8.0-RC3.diff
|
||||
#
|
||||
# This patch enables per-node directories, persistent hub/switch nodes, traffic
|
||||
# snooping for wireshark, and disallows vlan interfaces within a jail.
|
||||
diff -drup src-org/sys/kern/vfs_lookup.c src/sys/kern/vfs_lookup.c
|
||||
--- src-org/sys/kern/vfs_lookup.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/kern/vfs_lookup.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -59,6 +59,8 @@ __FBSDID("$FreeBSD: src/sys/kern/vfs_loo
|
||||
#include <sys/ktrace.h>
|
||||
#endif
|
||||
|
||||
+#include <net/vnet.h>
|
||||
+
|
||||
#include <security/audit/audit.h>
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
@@ -72,6 +74,19 @@ SDT_PROBE_DEFINE3(vfs, namei, lookup, en
|
||||
"unsigned long");
|
||||
SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
|
||||
|
||||
+#ifdef VIMAGE
|
||||
+#define IMUNES_SYMLINK_HACK
|
||||
+#endif
|
||||
+
|
||||
+#ifdef IMUNES_SYMLINK_HACK
|
||||
+static VNET_DEFINE(int, morphing_symlinks);
|
||||
+#define V_morphing_symlinks VNET(morphing_symlinks)
|
||||
+
|
||||
+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW,
|
||||
+ &VNET_NAME(morphing_symlinks), 0,
|
||||
+ "Resolve @ to vimage name in symlinks");
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Allocation zone for namei
|
||||
*/
|
||||
@@ -333,6 +348,44 @@ namei(struct nameidata *ndp)
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
+#ifdef IMUNES_SYMLINK_HACK
|
||||
+ /*
|
||||
+ * If the symbolic link includes a special character '@',
|
||||
+ * and V_morphing_symlinks is set, substitute the first
|
||||
+ * occurence of '@' with full path to jail / vimage name.
|
||||
+ * If the full path includes subhierarchies, s/./\// when
|
||||
+ * expanding '@' to jail / vimage name.
|
||||
+ *
|
||||
+ * XXX revisit buffer length checking.
|
||||
+ */
|
||||
+ CURVNET_SET_QUIET(TD_TO_VNET(curthread));
|
||||
+ if (V_morphing_symlinks) {
|
||||
+ char *sp = strchr(cp, '@');
|
||||
+
|
||||
+ if (sp) {
|
||||
+ char *vname = td->td_ucred->cr_prison->pr_name;
|
||||
+ int vnamelen = strlen(vname);
|
||||
+ int i;
|
||||
+
|
||||
+ if (vnamelen >= auio.uio_resid) {
|
||||
+ if (ndp->ni_pathlen > 1)
|
||||
+ uma_zfree(namei_zone, cp);
|
||||
+ error = ENAMETOOLONG;
|
||||
+ CURVNET_RESTORE();
|
||||
+ break;
|
||||
+ }
|
||||
+ bcopy(sp + 1, sp + vnamelen,
|
||||
+ linklen - (sp - cp));
|
||||
+ bcopy(td->td_ucred->cr_prison->pr_name,
|
||||
+ sp, vnamelen);
|
||||
+ linklen += (vnamelen - 1);
|
||||
+ for (i = 0; i < vnamelen; i++)
|
||||
+ if (sp[i] == '.')
|
||||
+ sp[i] = '/';
|
||||
+ }
|
||||
+ }
|
||||
+ CURVNET_RESTORE();
|
||||
+#endif
|
||||
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
|
||||
if (ndp->ni_pathlen > 1)
|
||||
uma_zfree(namei_zone, cp);
|
||||
diff -drup src-org/sys/net/bpf.c src/sys/net/bpf.c
|
||||
--- src-org/sys/net/bpf.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/net/bpf.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/net/bpf.c,v
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/conf.h>
|
||||
+#include <sys/ctype.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/malloc.h>
|
||||
@@ -1435,9 +1436,34 @@ bpf_setif(struct bpf_d *d, struct ifreq
|
||||
struct bpf_if *bp;
|
||||
struct ifnet *theywant;
|
||||
|
||||
+#define XVNET_BPF_SNOOPING
|
||||
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
|
||||
+ struct vnet *target_vnet = curvnet;
|
||||
+ char *c;
|
||||
+
|
||||
+ /* Attempt to attach to an ifnet in a foreign vnet, specified as @ */
|
||||
+ c = rindex(ifr->ifr_name, '@');
|
||||
+ if ( c != NULL ) {
|
||||
+ struct prison *target_pr;
|
||||
+
|
||||
+ *c++ = 0;
|
||||
+ if (!isascii(*c) && !isdigit(*c))
|
||||
+ return ENXIO;
|
||||
+ target_pr = prison_find_name(curthread->td_ucred->cr_prison, c);
|
||||
+ if (target_pr == NULL)
|
||||
+ return ENXIO;
|
||||
+ target_vnet = target_pr->pr_vnet;
|
||||
+ }
|
||||
+ CURVNET_SET_QUIET(target_vnet);
|
||||
+#endif
|
||||
+
|
||||
theywant = ifunit(ifr->ifr_name);
|
||||
- if (theywant == NULL || theywant->if_bpf == NULL)
|
||||
+ if (theywant == NULL || theywant->if_bpf == NULL) {
|
||||
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
|
||||
+ CURVNET_RESTORE();
|
||||
+#endif
|
||||
return (ENXIO);
|
||||
+ }
|
||||
|
||||
bp = theywant->if_bpf;
|
||||
|
||||
@@ -1477,6 +1503,9 @@ bpf_setif(struct bpf_d *d, struct ifreq
|
||||
BPFD_LOCK(d);
|
||||
reset_d(d);
|
||||
BPFD_UNLOCK(d);
|
||||
+#if defined(VIMAGE) && defined(XVNET_BPF_SNOOPING)
|
||||
+ CURVNET_RESTORE();
|
||||
+#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
diff -drup src-org/sys/net/if.c src/sys/net/if.c
|
||||
--- src-org/sys/net/if.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/net/if.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -813,6 +813,14 @@ if_detach_internal(struct ifnet *ifp, in
|
||||
struct ifnet *iter;
|
||||
int found = 0;
|
||||
|
||||
+ /*
|
||||
+ * Detach from any vlan, bridge or lagg ifnets linked to us.
|
||||
+ * A small though unlikely window for a race from here to ifp
|
||||
+ * unlinking from ifnet list is possible, hence we repeat the
|
||||
+ * procedure once again further bellow. XXX.
|
||||
+ */
|
||||
+ EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
|
||||
+
|
||||
IFNET_WLOCK();
|
||||
TAILQ_FOREACH(iter, &V_ifnet, if_link)
|
||||
if (iter == ifp) {
|
||||
diff -drup src-org/sys/net/if_llatbl.c src/sys/net/if_llatbl.c
|
||||
--- src-org/sys/net/if_llatbl.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/net/if_llatbl.c 2009-11-11 12:53:49.000000000 +0000
|
||||
@@ -57,11 +57,14 @@ __FBSDID("$FreeBSD: src/sys/net/if_llatb
|
||||
|
||||
MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
|
||||
|
||||
-static SLIST_HEAD(, lltable) lltables = SLIST_HEAD_INITIALIZER(lltables);
|
||||
+static VNET_DEFINE(SLIST_HEAD(, lltable), lltables);
|
||||
+#define V_lltables VNET(lltables)
|
||||
|
||||
extern void arprequest(struct ifnet *, struct in_addr *, struct in_addr *,
|
||||
u_char *);
|
||||
|
||||
+static void vnet_lltable_init(void);
|
||||
+
|
||||
struct rwlock lltable_rwlock;
|
||||
RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
|
||||
|
||||
@@ -75,7 +78,7 @@ lltable_sysctl_dumparp(int af, struct sy
|
||||
int error = 0;
|
||||
|
||||
LLTABLE_RLOCK();
|
||||
- SLIST_FOREACH(llt, &lltables, llt_link) {
|
||||
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
|
||||
if (llt->llt_af == af) {
|
||||
error = llt->llt_dump(llt, wr);
|
||||
if (error != 0)
|
||||
@@ -157,7 +160,7 @@ lltable_free(struct lltable *llt)
|
||||
KASSERT(llt != NULL, ("%s: llt is NULL", __func__));
|
||||
|
||||
LLTABLE_WLOCK();
|
||||
- SLIST_REMOVE(&lltables, llt, lltable, llt_link);
|
||||
+ SLIST_REMOVE(&V_lltables, llt, lltable, llt_link);
|
||||
LLTABLE_WUNLOCK();
|
||||
|
||||
for (i=0; i < LLTBL_HASHTBL_SIZE; i++) {
|
||||
@@ -180,7 +183,7 @@ lltable_drain(int af)
|
||||
register int i;
|
||||
|
||||
LLTABLE_RLOCK();
|
||||
- SLIST_FOREACH(llt, &lltables, llt_link) {
|
||||
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
|
||||
if (llt->llt_af != af)
|
||||
continue;
|
||||
|
||||
@@ -202,7 +205,7 @@ lltable_prefix_free(int af, struct socka
|
||||
struct lltable *llt;
|
||||
|
||||
LLTABLE_RLOCK();
|
||||
- SLIST_FOREACH(llt, &lltables, llt_link) {
|
||||
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
|
||||
if (llt->llt_af != af)
|
||||
continue;
|
||||
|
||||
@@ -232,7 +235,7 @@ lltable_init(struct ifnet *ifp, int af)
|
||||
LIST_INIT(&llt->lle_head[i]);
|
||||
|
||||
LLTABLE_WLOCK();
|
||||
- SLIST_INSERT_HEAD(&lltables, llt, llt_link);
|
||||
+ SLIST_INSERT_HEAD(&V_lltables, llt, llt_link);
|
||||
LLTABLE_WUNLOCK();
|
||||
|
||||
return (llt);
|
||||
@@ -302,7 +305,7 @@ lla_rt_output(struct rt_msghdr *rtm, str
|
||||
|
||||
/* XXX linked list may be too expensive */
|
||||
LLTABLE_RLOCK();
|
||||
- SLIST_FOREACH(llt, &lltables, llt_link) {
|
||||
+ SLIST_FOREACH(llt, &V_lltables, llt_link) {
|
||||
if (llt->llt_af == dst->sa_family &&
|
||||
llt->llt_ifp == ifp)
|
||||
break;
|
||||
@@ -367,3 +370,12 @@ lla_rt_output(struct rt_msghdr *rtm, str
|
||||
|
||||
return (error);
|
||||
}
|
||||
+
|
||||
+static void
|
||||
+vnet_lltable_init()
|
||||
+{
|
||||
+
|
||||
+ SLIST_INIT(&V_lltables);
|
||||
+}
|
||||
+VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST, vnet_lltable_init, NULL);
|
||||
+
|
||||
diff -drup src-org/sys/net/if_vlan.c src/sys/net/if_vlan.c
|
||||
--- src-org/sys/net/if_vlan.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/net/if_vlan.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -1359,6 +1359,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd
|
||||
error = copyin(ifr->ifr_data, &vlr, sizeof(vlr));
|
||||
if (error)
|
||||
break;
|
||||
+#ifdef VIMAGE
|
||||
+ if (ifp->if_home_vnet != ifp->if_vnet) {
|
||||
+ error = EPERM;
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
if (vlr.vlr_parent[0] == '\0') {
|
||||
vlan_unconfig(ifp);
|
||||
break;
|
||||
@@ -1386,6 +1392,12 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd
|
||||
|
||||
case SIOCGETVLAN:
|
||||
bzero(&vlr, sizeof(vlr));
|
||||
+#ifdef VIMAGE
|
||||
+ if (ifp->if_home_vnet != ifp->if_vnet) {
|
||||
+ error = EPERM;
|
||||
+ break;
|
||||
+ }
|
||||
+#endif
|
||||
VLAN_LOCK();
|
||||
if (TRUNK(ifv) != NULL) {
|
||||
strlcpy(vlr.vlr_parent, PARENT(ifv)->if_xname,
|
||||
diff -drup src-org/sys/netgraph/ng_bridge.c src/sys/netgraph/ng_bridge.c
|
||||
--- src-org/sys/netgraph/ng_bridge.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/netgraph/ng_bridge.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -105,6 +105,7 @@ struct ng_bridge_private {
|
||||
u_int numBuckets; /* num buckets in table */
|
||||
u_int hashMask; /* numBuckets - 1 */
|
||||
int numLinks; /* num connected links */
|
||||
+ int persistent; /* can exist w/o any hooks */
|
||||
struct callout timer; /* one second periodic timer */
|
||||
};
|
||||
typedef struct ng_bridge_private *priv_p;
|
||||
@@ -345,13 +346,13 @@ static int
|
||||
ng_bridge_newhook(node_p node, hook_p hook, const char *name)
|
||||
{
|
||||
const priv_p priv = NG_NODE_PRIVATE(node);
|
||||
+ int linkNum = -1;
|
||||
|
||||
/* Check for a link hook */
|
||||
if (strncmp(name, NG_BRIDGE_HOOK_LINK_PREFIX,
|
||||
strlen(NG_BRIDGE_HOOK_LINK_PREFIX)) == 0) {
|
||||
const char *cp;
|
||||
char *eptr;
|
||||
- u_long linkNum;
|
||||
|
||||
cp = name + strlen(NG_BRIDGE_HOOK_LINK_PREFIX);
|
||||
if (!isdigit(*cp) || (cp[0] == '0' && cp[1] != '\0'))
|
||||
@@ -359,6 +360,12 @@ ng_bridge_newhook(node_p node, hook_p ho
|
||||
linkNum = strtoul(cp, &eptr, 10);
|
||||
if (*eptr != '\0' || linkNum >= NG_BRIDGE_MAX_LINKS)
|
||||
return (EINVAL);
|
||||
+ } else if (strcmp(name, "anchor") == 0) {
|
||||
+ linkNum = 0;
|
||||
+ priv->persistent = 1;
|
||||
+ }
|
||||
+
|
||||
+ if (linkNum >= 0 ) {
|
||||
if (priv->links[linkNum] != NULL)
|
||||
return (EISCONN);
|
||||
priv->links[linkNum] = malloc(sizeof(*priv->links[linkNum]),
|
||||
@@ -366,7 +373,7 @@ ng_bridge_newhook(node_p node, hook_p ho
|
||||
if (priv->links[linkNum] == NULL)
|
||||
return (ENOMEM);
|
||||
priv->links[linkNum]->hook = hook;
|
||||
- NG_HOOK_SET_PRIVATE(hook, (void *)linkNum);
|
||||
+ NG_HOOK_SET_PRIVATE(hook, (void *)(intptr_t)linkNum);
|
||||
priv->numLinks++;
|
||||
return (0);
|
||||
}
|
||||
@@ -799,7 +806,8 @@ ng_bridge_disconnect(hook_p hook)
|
||||
|
||||
/* If no more hooks, go away */
|
||||
if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
|
||||
- && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) {
|
||||
+ && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
|
||||
+ && !priv->persistent) {
|
||||
ng_rmnode_self(NG_HOOK_NODE(hook));
|
||||
}
|
||||
return (0);
|
||||
diff -drup src-org/sys/netgraph/ng_hub.c src/sys/netgraph/ng_hub.c
|
||||
--- src-org/sys/netgraph/ng_hub.c 2009-10-25 01:10:29.000000000 +0000
|
||||
+++ src/sys/netgraph/ng_hub.c 2009-11-11 12:46:02.000000000 +0000
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <netgraph/netgraph.h>
|
||||
|
||||
static ng_constructor_t ng_hub_constructor;
|
||||
+static ng_newhook_t ng_hub_newhook;
|
||||
static ng_rcvdata_t ng_hub_rcvdata;
|
||||
static ng_disconnect_t ng_hub_disconnect;
|
||||
|
||||
@@ -44,6 +45,7 @@ static struct ng_type ng_hub_typestruct
|
||||
.version = NG_ABI_VERSION,
|
||||
.name = NG_HUB_NODE_TYPE,
|
||||
.constructor = ng_hub_constructor,
|
||||
+ .newhook = ng_hub_newhook,
|
||||
.rcvdata = ng_hub_rcvdata,
|
||||
.disconnect = ng_hub_disconnect,
|
||||
};
|
||||
@@ -57,6 +59,14 @@ ng_hub_constructor(node_p node)
|
||||
return (0);
|
||||
}
|
||||
|
||||
+static int
|
||||
+ng_hub_newhook(node_p node, hook_p hook, const char *name)
|
||||
+{
|
||||
+ if (strcmp(name, "anchor") == 0)
|
||||
+ node->nd_private = (void *) 1;
|
||||
+ return (0);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
ng_hub_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
@@ -94,7 +104,7 @@ ng_hub_disconnect(hook_p hook)
|
||||
{
|
||||
|
||||
if (NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0 &&
|
||||
- NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))
|
||||
+ NG_NODE_IS_VALID(NG_HOOK_NODE(hook)) && !hook->hk_node->nd_private)
|
||||
ng_rmnode_self(NG_HOOK_NODE(hook));
|
||||
return (0);
|
||||
}
|
27
kernel/freebsd/ng_pipe/Makefile
Normal file
27
kernel/freebsd/ng_pipe/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# (c)2008 the Boeing Company
|
||||
#
|
||||
# modified ng_pipe node
|
||||
#
|
||||
.if !defined(PLATFORM)
|
||||
#PLATFORM=i386
|
||||
PLATFORM=amd64
|
||||
.endif
|
||||
|
||||
CFLAGS=-DBOEING_WLAN -I/usr/src/sys/${PLATFORM}/compile/CORE
|
||||
|
||||
KMOD= ng_pipe
|
||||
|
||||
SRCS= ng_pipe.c
|
||||
|
||||
#MAN= ng_pipe.4
|
||||
|
||||
# FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0"
|
||||
#.if defined(OSTYPE)
|
||||
#.if (${OSTYPE} == "FreeBSD")
|
||||
#CFLAGS+=-DFREEBSD411
|
||||
#SRCS= ng_pipe_freebsd4.c
|
||||
#.endif
|
||||
#.endif
|
||||
|
||||
.include <bsd.kmod.mk>
|
21
kernel/freebsd/ng_pipe/README
Normal file
21
kernel/freebsd/ng_pipe/README
Normal file
|
@ -0,0 +1,21 @@
|
|||
|
||||
ng_pipe FreeBSD kernel module
|
||||
|
||||
See the copyright statement at the top of the source file.
|
||||
Copyright (c) 2004, 2005, 2007 University of Zagreb
|
||||
Copyright (c) 2007 FreeBSD Foundation
|
||||
(c) 2008 the Boeing Company
|
||||
modifications: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
|
||||
More complete documentation is available in the ng_pipe(4) man page.
|
||||
|
||||
This version of ng_pipe has been modified as follows:
|
||||
- added burst rate (or burstiness) which is the probability that the next packet
|
||||
will be dropped given an error with the current packet, 0 to 100
|
||||
- added jitter effect, which randomizes the delay an additional amount from
|
||||
0 to jitter microseconds
|
||||
- ng_wlan support added, to remove and read mbuf tags containing wlan link
|
||||
effect information
|
||||
- bugfix: random number generation improved from defective modulo algorithm
|
||||
- bugfix: fixed mbuf dangling pointer reference when ng_pipe has both duplicates
|
||||
and errors configured
|
1170
kernel/freebsd/ng_pipe/ng_pipe.c
Normal file
1170
kernel/freebsd/ng_pipe/ng_pipe.c
Normal file
File diff suppressed because it is too large
Load diff
171
kernel/freebsd/ng_pipe/ng_pipe.h
Normal file
171
kernel/freebsd/ng_pipe/ng_pipe.h
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2004, 2007 University of Zagreb
|
||||
* Copyright (c) 2007 FreeBSD Foundation
|
||||
*
|
||||
* This software was developed by the University of Zagreb and the
|
||||
* FreeBSD Foundation under sponsorship by the Stichting NLnet and the
|
||||
* FreeBSD Foundation.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NETGRAPH_PIPE_H_
|
||||
#define _NETGRAPH_PIPE_H_
|
||||
|
||||
/* Node type name and magic cookie */
|
||||
#define NG_PIPE_NODE_TYPE "pipe"
|
||||
#define NGM_PIPE_COOKIE 200708191
|
||||
|
||||
/* Hook names */
|
||||
#define NG_PIPE_HOOK_UPPER "upper"
|
||||
#define NG_PIPE_HOOK_LOWER "lower"
|
||||
|
||||
#define MAX_FSIZE 16384 /* Largest supported frame size, in bytes, for BER */
|
||||
#define MAX_OHSIZE 256 /* Largest supported dummy-framing size, in bytes */
|
||||
|
||||
/* Statistics structure for one hook */
|
||||
struct ng_pipe_hookstat {
|
||||
u_int64_t fwd_octets;
|
||||
u_int64_t fwd_frames;
|
||||
u_int64_t in_disc_octets;
|
||||
u_int64_t in_disc_frames;
|
||||
u_int64_t out_disc_octets;
|
||||
u_int64_t out_disc_frames;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_HOOKSTAT_INFO { \
|
||||
{ "FwdOctets", &ng_parse_uint64_type }, \
|
||||
{ "FwdFrames", &ng_parse_uint64_type }, \
|
||||
{ "queueDropOctets", &ng_parse_uint64_type }, \
|
||||
{ "queueDropFrames", &ng_parse_uint64_type }, \
|
||||
{ "delayDropOctets", &ng_parse_uint64_type }, \
|
||||
{ "delayDropFrames", &ng_parse_uint64_type }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Statistics structure returned by NGM_PIPE_GET_STATS */
|
||||
struct ng_pipe_stats {
|
||||
struct ng_pipe_hookstat downstream;
|
||||
struct ng_pipe_hookstat upstream;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_STATS_INFO(hstype) { \
|
||||
{ "downstream", (hstype) }, \
|
||||
{ "upstream", (hstype) }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Runtime structure for one hook */
|
||||
struct ng_pipe_hookrun {
|
||||
u_int32_t fifo_queues;
|
||||
u_int32_t qin_octets;
|
||||
u_int32_t qin_frames;
|
||||
u_int32_t qout_octets;
|
||||
u_int32_t qout_frames;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_HOOKRUN_INFO { \
|
||||
{ "queues", &ng_parse_uint32_type }, \
|
||||
{ "queuedOctets", &ng_parse_uint32_type }, \
|
||||
{ "queuedFrames", &ng_parse_uint32_type }, \
|
||||
{ "delayedOctets", &ng_parse_uint32_type }, \
|
||||
{ "delayedFrames", &ng_parse_uint32_type }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Runtime structure returned by NGM_PIPE_GET_RUN */
|
||||
struct ng_pipe_run {
|
||||
struct ng_pipe_hookrun downstream;
|
||||
struct ng_pipe_hookrun upstream;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_RUN_INFO(hstype) { \
|
||||
{ "downstream", (hstype) }, \
|
||||
{ "upstream", (hstype) }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Config structure for one hook */
|
||||
struct ng_pipe_hookcfg {
|
||||
u_int64_t bandwidth;
|
||||
u_int64_t ber;
|
||||
u_int32_t qin_size_limit;
|
||||
u_int32_t qout_size_limit;
|
||||
u_int32_t duplicate;
|
||||
u_int32_t fifo;
|
||||
u_int32_t drr;
|
||||
u_int32_t wfq;
|
||||
u_int32_t droptail;
|
||||
u_int32_t drophead;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_HOOKCFG_INFO { \
|
||||
{ "bandwidth", &ng_parse_uint64_type }, \
|
||||
{ "BER", &ng_parse_uint64_type }, \
|
||||
{ "queuelen", &ng_parse_uint32_type }, \
|
||||
{ "delaylen", &ng_parse_uint32_type }, \
|
||||
{ "duplicate", &ng_parse_uint32_type }, \
|
||||
{ "fifo", &ng_parse_uint32_type }, \
|
||||
{ "drr", &ng_parse_uint32_type }, \
|
||||
{ "wfq", &ng_parse_uint32_type }, \
|
||||
{ "droptail", &ng_parse_uint32_type }, \
|
||||
{ "drophead", &ng_parse_uint32_type }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Config structure returned by NGM_PIPE_GET_CFG */
|
||||
struct ng_pipe_cfg {
|
||||
u_int64_t bandwidth;
|
||||
u_int64_t delay;
|
||||
u_int32_t header_offset;
|
||||
u_int32_t overhead;
|
||||
struct ng_pipe_hookcfg downstream;
|
||||
struct ng_pipe_hookcfg upstream;
|
||||
};
|
||||
|
||||
/* Keep this in sync with the above structure definition */
|
||||
#define NG_PIPE_CFG_INFO(hstype) { \
|
||||
{ "bandwidth", &ng_parse_uint64_type }, \
|
||||
{ "delay", &ng_parse_uint64_type }, \
|
||||
{ "header_offset", &ng_parse_uint32_type }, \
|
||||
{ "overhead", &ng_parse_uint32_type }, \
|
||||
{ "downstream", (hstype) }, \
|
||||
{ "upstream", (hstype) }, \
|
||||
{ NULL }, \
|
||||
}
|
||||
|
||||
/* Netgraph commands */
|
||||
enum {
|
||||
NGM_PIPE_GET_STATS=1, /* get stats */
|
||||
NGM_PIPE_CLR_STATS, /* clear stats */
|
||||
NGM_PIPE_GETCLR_STATS, /* atomically get and clear stats */
|
||||
NGM_PIPE_GET_RUN, /* get current runtime status */
|
||||
NGM_PIPE_GET_CFG, /* get configurable parameters */
|
||||
NGM_PIPE_SET_CFG, /* set configurable parameters */
|
||||
};
|
||||
|
||||
#endif /* _NETGRAPH_PIPE_H_ */
|
1277
kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c
Normal file
1277
kernel/freebsd/ng_pipe/ng_pipe_freebsd4.c
Normal file
File diff suppressed because it is too large
Load diff
27
kernel/freebsd/ng_wlan/Makefile
Normal file
27
kernel/freebsd/ng_wlan/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# (c)2006-2011 the Boeing Company
|
||||
#
|
||||
# ng_wlan
|
||||
#
|
||||
.if !defined(PLATFORM)
|
||||
#PLATFORM=i386
|
||||
PLATFORM=amd64
|
||||
.endif
|
||||
|
||||
CFLAGS+=-I/usr/src/sys/${PLATFORM}/compile/CORE -DMULTICAST_LOOKUPS
|
||||
# FreeBSD 4.11 is "FreeBSD" and 7.0 is "freebsd7.0"
|
||||
|
||||
#.if defined(OSTYPE)
|
||||
#.if (${OSTYPE} == "FreeBSD")
|
||||
#CFLAGS+=-DFREEBSD411
|
||||
#.endif
|
||||
#.endif
|
||||
|
||||
KMOD= ng_wlan
|
||||
|
||||
SRCS= ng_wlan.c
|
||||
|
||||
#MAN= ng_wlan.4
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
50
kernel/freebsd/ng_wlan/README
Normal file
50
kernel/freebsd/ng_wlan/README
Normal file
|
@ -0,0 +1,50 @@
|
|||
|
||||
ng_wlan FreeBSD kernel module
|
||||
|
||||
(c) 2006-2011 the Boeing Company
|
||||
author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
|
||||
|
||||
The ng_wlan modules implements a netgraph node that models wireless
|
||||
LAN connectivity. ng_wlan extends the ng_hub node, only instead of sending
|
||||
packets to each connected peer, maintains a hash table of node connectivity,
|
||||
and sends packets between two nodes only when they are linked. By default all
|
||||
nodes are unlinked. Nodes can be linked and unlinked using "link" and
|
||||
"unlink" messages:
|
||||
ngctl msg e0_n2: link { node1=0x23 node2=0x0c }
|
||||
|
||||
The node IDs of the two nodes are the parameters, as depicted above.
|
||||
|
||||
Link effects between can also be specified for each node pair. If two nodes
|
||||
are linked and parameters are specified, an mbuf tag will be added to each data
|
||||
packet mbuf that specifies the effects. For FreeBSD 4.11, the metadata parameter
|
||||
is used instead of mbuf tags. Delay (microseconds), bandwidth
|
||||
(bits per second), PER (% packet errors), duplicates (%), jitter
|
||||
(microseconds), and burst (% burst errors) are supported. This tag is then
|
||||
removed by the ng_pipe node and the appropriate effects are applied. Link
|
||||
effects are specified with "set" and "unset" messages:
|
||||
ngctl msg e0_n2: set { node1=0x23 node2=0x0c delay=50000 bandwidth=54000000 per=0 duplicate=0 jitter=5000 burst=30 }
|
||||
ngctl msg e0_n2: unset { node1=0x23 node2=0x0c }
|
||||
|
||||
Note that a special ng_pipe module is needed (the default one does not support
|
||||
the mbuf tags and some effects.)
|
||||
|
||||
A separate error rate and burst rate affecting all multicast packets may be
|
||||
defined. Use the "mer" message:
|
||||
ngctl msg e0_n2: mer { mer=20 mburst=35 }
|
||||
The above example sets the multicast error rate to drop 20% of all multicast
|
||||
packets, with 35% burst errors.
|
||||
|
||||
When MULTICAST_LOOKUPS is defined, a second lookup table is defined for each
|
||||
WLAN where multicast group, source, and node pair tuples can be linked or
|
||||
unlinked. This causes different forwarding behavior for multicast packets,
|
||||
where non-local groups are only forwarded if the node pair has been linked
|
||||
together for that group (and the normal node pair has been linked).
|
||||
Usage:
|
||||
ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0x0a000002 }
|
||||
ngctl msg e0_n2: mcastset { node1=0x23 node2=0x0c group=0xEF020364 source=0}
|
||||
ngctl msg e0_n2: mcastunset { node1=0x23 node2=0x0c group=0xEF020364 source=0 }
|
||||
Once the first mcastset/mcastunset message is received, that ng_wlan will drop
|
||||
all non-local multicast packets that do not have a matching source, group,
|
||||
node pair entry. The source address of zero matches any IP source.
|
||||
|
1315
kernel/freebsd/ng_wlan/ng_wlan.c
Normal file
1315
kernel/freebsd/ng_wlan/ng_wlan.c
Normal file
File diff suppressed because it is too large
Load diff
109
kernel/freebsd/ng_wlan/ng_wlan.h
Normal file
109
kernel/freebsd/ng_wlan/ng_wlan.h
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2011 the Boeing Company
|
||||
* ng_wlan is based on ng_hub, which is:
|
||||
* Copyright (c) 2004 Ruslan Ermilov
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NETGRAPH_NG_WLAN_H_
|
||||
#define _NETGRAPH_NG_WLAN_H_
|
||||
|
||||
/* Node type name and magic cookie. */
|
||||
#define NG_WLAN_NODE_TYPE "wlan"
|
||||
#define NGM_WLAN_COOKIE 1146673193
|
||||
|
||||
/* Control message parse info */
|
||||
struct ng_wlan_config {
|
||||
u_int32_t node1;
|
||||
u_int32_t node2;
|
||||
};
|
||||
#define NG_WLAN_CONFIG_TYPE_INFO { \
|
||||
{ "node1", &ng_parse_uint32_type }, \
|
||||
{ "node2", &ng_parse_uint32_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
struct ng_wlan_set_data {
|
||||
u_int32_t node1;
|
||||
u_int32_t node2;
|
||||
u_int64_t delay; /* keep these aligned with struct ng_wlan_tag */
|
||||
u_int64_t bandwidth;
|
||||
u_int16_t per;
|
||||
u_int16_t duplicate;
|
||||
u_int32_t jitter;
|
||||
u_int16_t burst;
|
||||
};
|
||||
#define NG_WLAN_SET_DATA_TYPE_INFO { \
|
||||
{ "node1", &ng_parse_uint32_type }, \
|
||||
{ "node2", &ng_parse_uint32_type }, \
|
||||
{ "delay", &ng_parse_uint64_type }, \
|
||||
{ "bandwidth", &ng_parse_uint64_type }, \
|
||||
{ "per", &ng_parse_uint16_type }, \
|
||||
{ "duplicate", &ng_parse_uint16_type }, \
|
||||
{ "jitter", &ng_parse_uint32_type }, \
|
||||
{ "burst", &ng_parse_uint16_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
struct ng_wlan_mer {
|
||||
uint16_t mer;
|
||||
uint16_t mburst;
|
||||
};
|
||||
#define NG_WLAN_MER_TYPE_INFO { \
|
||||
{ "mer", &ng_parse_uint16_type }, \
|
||||
{ "mburst", &ng_parse_uint16_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
|
||||
#ifdef MULTICAST_LOOKUPS
|
||||
struct ng_wlan_multicast_set_data {
|
||||
u_int32_t node1;
|
||||
u_int32_t node2;
|
||||
u_int32_t group;
|
||||
u_int32_t source;
|
||||
};
|
||||
#define NG_WLAN_MULTICAST_SET_DATA_TYPE_INFO { \
|
||||
{ "node1", &ng_parse_uint32_type }, \
|
||||
{ "node2", &ng_parse_uint32_type }, \
|
||||
{ "group", &ng_parse_uint32_type }, \
|
||||
{ "source", &ng_parse_uint32_type }, \
|
||||
{ NULL } \
|
||||
}
|
||||
#endif /* MULTICAST_LOOKUPS */
|
||||
|
||||
/* List of supported Netgraph control messages */
|
||||
enum {
|
||||
NGM_WLAN_LINK_NODES = 1,
|
||||
NGM_WLAN_UNLINK_NODES,
|
||||
NGM_WLAN_NODES_SET,
|
||||
NGM_WLAN_NODES_UNSET,
|
||||
NGM_WLAN_NODES_GET,
|
||||
NGM_WLAN_MER, /* MULTICAST_ERR */
|
||||
NGM_WLAN_MULTICAST_SET, /* MULTICAST_LOOKUPS */
|
||||
NGM_WLAN_MULTICAST_UNSET, /* MULTICAST_LOOKUPS */
|
||||
NGM_WLAN_MULTICAST_GET, /* MULTICAST_LOOKUPS */
|
||||
};
|
||||
|
||||
#endif /* _NETGRAPH_NG_WLAN_H_ */
|
60
kernel/freebsd/ng_wlan/ng_wlan_tag.h
Normal file
60
kernel/freebsd/ng_wlan/ng_wlan_tag.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2011 the Boeing Company
|
||||
* All rights reserved.
|
||||
*
|
||||
* author: Jeff Ahrenholz <jeffrey.m.ahrenholz@boeing.com>
|
||||
*/
|
||||
|
||||
|
||||
#define NG_TAG_WLAN 0x01
|
||||
#ifdef FREEBSD411
|
||||
#define WLAN_META_SIZE (sizeof(struct ng_meta))+(sizeof(struct ng_wlan_tag))
|
||||
#define WLAN_META_PRIORITY 0x01
|
||||
#define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct meta_field_header))
|
||||
#else
|
||||
#define TAGSIZE (sizeof(struct ng_wlan_tag) - sizeof(struct m_tag))
|
||||
#endif
|
||||
|
||||
#define NG_WLAN_MAX_DELAY 2000000 /* 2,000,000us = 2s */
|
||||
#define NG_WLAN_MAX_BW 1000000000 /* 1,000,000,000bps = 1000M */
|
||||
#define NG_WLAN_MAX_PER 100 /* 100% */
|
||||
#define NG_WLAN_MAX_DUP 50 /* 50% */
|
||||
#define NG_WLAN_MAX_JITTER NG_WLAN_MAX_DELAY
|
||||
#define NG_WLAN_MAX_BURST NG_WLAN_MAX_PER
|
||||
|
||||
/* Tag data that is prepended to packets passing through the WLAN node.
|
||||
*/
|
||||
struct ng_wlan_tag {
|
||||
#ifdef FREEBSD411
|
||||
struct meta_field_header meta_hdr;
|
||||
#else
|
||||
struct m_tag tag;
|
||||
#endif
|
||||
u_int64_t delay;
|
||||
u_int64_t bandwidth;
|
||||
u_int16_t per;
|
||||
u_int16_t duplicate;
|
||||
u_int32_t jitter;
|
||||
u_int16_t burst;
|
||||
};
|
||||
|
||||
#define TAG_HAS_DATA(t) (t->delay || t->bandwidth || t->per || t->duplicate \
|
||||
|| t->jitter || t->burst )
|
||||
|
||||
#define WLAN_TAG_ZERO(t) do { \
|
||||
t->delay = 0; \
|
||||
t->bandwidth = 0; \
|
||||
t->per = 0; \
|
||||
t->duplicate = 0; \
|
||||
t->jitter = 0; \
|
||||
t->burst = 0; \
|
||||
} while(0);
|
||||
|
||||
#define WLAN_TAG_COPY(a, b) do { \
|
||||
a->delay = ((struct ng_wlan_tag*)b)->delay; \
|
||||
a->bandwidth = ((struct ng_wlan_tag*)b)->bandwidth; \
|
||||
a->per = ((struct ng_wlan_tag*)b)->per; \
|
||||
a->duplicate = ((struct ng_wlan_tag*)b)->duplicate; \
|
||||
a->jitter = ((struct ng_wlan_tag*)b)->jitter; \
|
||||
a->burst = ((struct ng_wlan_tag*)b)->burst; \
|
||||
} while(0);
|
78
kernel/freebsd/symlinks-8.1-RELEASE.diff
Normal file
78
kernel/freebsd/symlinks-8.1-RELEASE.diff
Normal file
|
@ -0,0 +1,78 @@
|
|||
Index: sys/kern/vfs_lookup.c
|
||||
===========================================================================
|
||||
--- sys/kern/vfs_lookup.c 2010/06/17 19:18:00 #3
|
||||
+++ sys/kern/vfs_lookup.c 2010/06/17 19:18:00
|
||||
@@ -59,6 +59,8 @@
|
||||
#include <sys/ktrace.h>
|
||||
#endif
|
||||
|
||||
+#include <net/vnet.h>
|
||||
+
|
||||
#include <security/audit/audit.h>
|
||||
#include <security/mac/mac_framework.h>
|
||||
|
||||
@@ -72,6 +74,19 @@
|
||||
"unsigned long");
|
||||
SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
|
||||
|
||||
+#ifdef VIMAGE
|
||||
+#define IMUNES_SYMLINK_HACK
|
||||
+#endif
|
||||
+
|
||||
+#ifdef IMUNES_SYMLINK_HACK
|
||||
+static VNET_DEFINE(int, morphing_symlinks);
|
||||
+#define V_morphing_symlinks VNET(morphing_symlinks)
|
||||
+
|
||||
+SYSCTL_VNET_INT(_vfs, OID_AUTO, morphing_symlinks, CTLFLAG_RW,
|
||||
+ &VNET_NAME(morphing_symlinks), 0,
|
||||
+ "Resolve @ to vimage name in symlinks");
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Allocation zone for namei
|
||||
*/
|
||||
@@ -333,6 +348,44 @@
|
||||
error = ENOENT;
|
||||
break;
|
||||
}
|
||||
+#ifdef IMUNES_SYMLINK_HACK
|
||||
+ /*
|
||||
+ * If the symbolic link includes a special character '@',
|
||||
+ * and V_morphing_symlinks is set, substitute the first
|
||||
+ * occurence of '@' with full path to jail / vimage name.
|
||||
+ * If the full path includes subhierarchies, s/./\// when
|
||||
+ * expanding '@' to jail / vimage name.
|
||||
+ *
|
||||
+ * XXX revisit buffer length checking.
|
||||
+ */
|
||||
+ CURVNET_SET_QUIET(TD_TO_VNET(curthread));
|
||||
+ if (V_morphing_symlinks) {
|
||||
+ char *sp = strchr(cp, '@');
|
||||
+
|
||||
+ if (sp) {
|
||||
+ char *vname = td->td_ucred->cr_prison->pr_name;
|
||||
+ int vnamelen = strlen(vname);
|
||||
+ int i;
|
||||
+
|
||||
+ if (vnamelen >= auio.uio_resid) {
|
||||
+ if (ndp->ni_pathlen > 1)
|
||||
+ uma_zfree(namei_zone, cp);
|
||||
+ error = ENAMETOOLONG;
|
||||
+ CURVNET_RESTORE();
|
||||
+ break;
|
||||
+ }
|
||||
+ bcopy(sp + 1, sp + vnamelen,
|
||||
+ linklen - (sp - cp));
|
||||
+ bcopy(td->td_ucred->cr_prison->pr_name,
|
||||
+ sp, vnamelen);
|
||||
+ linklen += (vnamelen - 1);
|
||||
+ for (i = 0; i < vnamelen; i++)
|
||||
+ if (sp[i] == '.')
|
||||
+ sp[i] = '/';
|
||||
+ }
|
||||
+ }
|
||||
+ CURVNET_RESTORE();
|
||||
+#endif
|
||||
if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
|
||||
if (ndp->ni_pathlen > 1)
|
||||
uma_zfree(namei_zone, cp);
|
14
kernel/freebsd/vimage/Makefile
Normal file
14
kernel/freebsd/vimage/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
# $FreeBSD$
|
||||
|
||||
PROG= vimage
|
||||
LDADD= -ljail
|
||||
DPADD= ${LIBJAIL}
|
||||
|
||||
WARNS?= 2
|
||||
CFLAGS+= -I../../../sys
|
||||
|
||||
MAN= vimage.8
|
||||
|
||||
BINDIR?= /usr/sbin
|
||||
|
||||
.include <bsd.prog.mk>
|
195
kernel/freebsd/vimage/vimage.8
Normal file
195
kernel/freebsd/vimage/vimage.8
Normal file
|
@ -0,0 +1,195 @@
|
|||
.\" Copyright (c) 2002, 2003 Marko Zec <zec@fer.hr>
|
||||
.\" Copyright (c) 2009 University of Zagreb
|
||||
.\" Copyright (c) 2009 FreeBSD Foundation
|
||||
.\"
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 25, 2009
|
||||
.Dt VIMAGE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm vimage
|
||||
.Nd manage virtual network stacks
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl c | m
|
||||
.Ar vname
|
||||
.Op Ar param=value ...
|
||||
.Nm
|
||||
.Fl d
|
||||
.Ar vname
|
||||
.Nm
|
||||
.Fl l
|
||||
.Op Fl rvj
|
||||
.Op Ar vname
|
||||
.Nm
|
||||
.Fl i
|
||||
.Ar vname ifname
|
||||
.Op Ar newifname
|
||||
.Nm
|
||||
.Ar vi_name
|
||||
.Op command ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility is an alternative user interface for controlling virtual network
|
||||
stacks in FreeBSD, aimed primarily at supporting legacy applications
|
||||
which are not yet converted to using
|
||||
.Xr jail 8 ,
|
||||
.Xr jexec 8 ,
|
||||
and
|
||||
.Xr jls 8 .
|
||||
.
|
||||
.Ss Overview
|
||||
A virtual image or vimage is a jail with its own independent network
|
||||
stack instance. Every process, socket and network interface present
|
||||
in the system is always attached to one, and only one, virtual network
|
||||
stack instance (vnet).
|
||||
During system bootup sequence a default vnet
|
||||
is created to which all the configured interfaces and user processes
|
||||
are initially attached.
|
||||
Assuming that enough system resources are
|
||||
are available, a user with sufficient privileges can create and manage
|
||||
a hierarchy of subordinated virtual images.
|
||||
The
|
||||
.Nm
|
||||
command allows for creation, deletion and monitoring of virtual images,
|
||||
as well as for execution of arbitrary processes in a targeted virtual
|
||||
image.
|
||||
.Ss Invocation
|
||||
If invoked with no modifiers, the
|
||||
.Nm
|
||||
command spawns a new interactive shell in virtual image
|
||||
.Ar vname .
|
||||
If optional additional arguments following
|
||||
.Ar vname
|
||||
are provided, the first of those will be executed in place of the
|
||||
interactive shell, and the rest of the arguments will be passed as
|
||||
arguments to the executed command.
|
||||
.Pp
|
||||
The following modifiers are available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c
|
||||
Create a new virtual image named
|
||||
.Ar vname .
|
||||
Additional arguments, if provided, may be used to specify operating
|
||||
parameters different from defaults, in format
|
||||
.Ar param=value .
|
||||
See
|
||||
.Xr jail 8
|
||||
for an extensive list of available parameters.
|
||||
.It Fl m
|
||||
Modify the parameters of a virtual image named
|
||||
.Ar vname ,
|
||||
using the same syntax as with the -c form of the command.
|
||||
.It Fl d
|
||||
Delete the virtual image
|
||||
.Ar vname .
|
||||
No processes and/or sockets should exist in the target virtual image
|
||||
in order for the delete request to succeed. Non-loopback interfaces
|
||||
residing in the target virtual image will be reassigned to the virtual
|
||||
image's parent.
|
||||
.It Fl l
|
||||
List the properties and statistics for virtual images one level
|
||||
below the current one in the hierarchy. If an optional argument
|
||||
.Ar vname
|
||||
is provided, only the information regarding the target virtual image
|
||||
.Ar vname
|
||||
is displayed.
|
||||
With the optional
|
||||
.Op Ar -r
|
||||
switch enabled the list will include all virtual images below the
|
||||
current level in the vimage hierarchy.
|
||||
Enabling the optional
|
||||
.Op Ar -v
|
||||
or
|
||||
.Op Ar -j
|
||||
switches results in a more detailed output.
|
||||
.It Fl i
|
||||
Move interface
|
||||
.Ar ifname
|
||||
to the target virtual image
|
||||
.Ar vname .
|
||||
Interfaces will be automatically renamed to
|
||||
.So
|
||||
ethXX
|
||||
.Sc ,
|
||||
unless an optional argument specifying the desired interface name
|
||||
.Op Ar newifname
|
||||
is provided.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Create a new virtual image named
|
||||
.So v1
|
||||
.Sc ,
|
||||
which is allowed to create and manage an own subhierarchy of vimages:
|
||||
.Pp
|
||||
.Dl vimage -c v1 children.max=100
|
||||
.Pp
|
||||
Execute the
|
||||
.So ifconfig
|
||||
.Sc command in the virtual image
|
||||
.So v1
|
||||
.Sc :
|
||||
.Pp
|
||||
.Dl vimage v1 ifconfig
|
||||
.Pp
|
||||
Move the interface
|
||||
.So vlan0
|
||||
.Sc to the virtual image
|
||||
.So v1
|
||||
.Sc while renaming the interface as
|
||||
.So
|
||||
ve0
|
||||
.Sc :
|
||||
.Pp
|
||||
.Dl vimage -i v1 vlan0 ve0
|
||||
.Pp
|
||||
Show the status information for virtual image
|
||||
.So v1
|
||||
.Sc :
|
||||
.Pp
|
||||
.Dl vimage -lv v1
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Nm
|
||||
command exits 0 on success, and >0 if an error occurs.
|
||||
.Sh SEE ALSO
|
||||
.Xr jail 8
|
||||
.Xr jexec 8
|
||||
.Xr jls 8
|
||||
.Sh HISTORY
|
||||
Network stack virtualization framework first appeared as a patchset
|
||||
against the FreeBSD 4.7 kernel in 2002, and was maintained outside
|
||||
of the main FreeBSD tree.
|
||||
As a result of a project sponsored by the FreeBSD Foundation and
|
||||
Stiching NLNet, integrated virtualized network stack first appeared
|
||||
in FreeBSD 8.0.
|
||||
.Sh BUGS
|
||||
Deletion of vimages / vnets is known to leak kernel memory and fail at
|
||||
stopping various timers, hence may lead to system crashes.
|
||||
.Sh AUTHOR
|
||||
.An "Marko Zec" Aq zec@fer.hr
|
390
kernel/freebsd/vimage/vimage.c
Normal file
390
kernel/freebsd/vimage/vimage.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2004 Marko Zec <zec@fer.hr>
|
||||
* Copyright (c) 2009 University of Zagreb
|
||||
* Copyright (c) 2009 FreeBSD Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/jail.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <jail.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef enum {
|
||||
VI_SWITCHTO,
|
||||
VI_CREATE,
|
||||
VI_MODIFY,
|
||||
VI_DESTROY,
|
||||
VI_IFMOVE,
|
||||
VI_GET
|
||||
} vi_cmd_t;
|
||||
|
||||
typedef struct vimage_status {
|
||||
char name[MAXPATHLEN]; /* Must be first field for strcmp(). */
|
||||
char path[MAXPATHLEN];
|
||||
char hostname[MAXPATHLEN];
|
||||
char domainname[MAXPATHLEN];
|
||||
int jid;
|
||||
int parentjid;
|
||||
int vnet;
|
||||
int childcnt;
|
||||
int childmax;
|
||||
int cpuset;
|
||||
int rawsock;
|
||||
int socket_af;
|
||||
int mount;
|
||||
} vstat_t;
|
||||
|
||||
#define VST_SIZE_STEP 1024
|
||||
#define MAXPARAMS 32
|
||||
|
||||
static int getjail(vstat_t *, int, int);
|
||||
|
||||
static char *invocname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr,
|
||||
"usage: %s [-c | -m] vname [param=value ...]\n"
|
||||
" %s -d vname\n"
|
||||
" %s -l[rvj] [vname]\n"
|
||||
" %s -i vname ifname [newifname]\n"
|
||||
" %s vname [command ...]\n",
|
||||
invocname, invocname, invocname, invocname, invocname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct jailparam params[MAXPARAMS];
|
||||
char ifname[IFNAMSIZ];
|
||||
struct ifreq ifreq;
|
||||
vi_cmd_t newcmd, cmd;
|
||||
int recurse = 0;
|
||||
int verbose = 0;
|
||||
int jid, i, s, namelen;
|
||||
int vst_size, vst_last;
|
||||
vstat_t *vst;
|
||||
char *str;
|
||||
char ch;
|
||||
|
||||
invocname = argv[0];
|
||||
|
||||
newcmd = cmd = VI_SWITCHTO; /* Default if no modifiers specified. */
|
||||
while ((ch = getopt(argc, argv, "cdijlmrv")) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
newcmd = VI_CREATE;
|
||||
break;
|
||||
case 'm':
|
||||
newcmd = VI_MODIFY;
|
||||
break;
|
||||
case 'd':
|
||||
newcmd = VI_DESTROY;
|
||||
break;
|
||||
case 'l':
|
||||
newcmd = VI_GET;
|
||||
break;
|
||||
case 'i':
|
||||
newcmd = VI_IFMOVE;
|
||||
break;
|
||||
case 'r':
|
||||
recurse = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'j':
|
||||
verbose = 2;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
if (cmd == VI_SWITCHTO || cmd == newcmd)
|
||||
cmd = newcmd;
|
||||
else
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if ((cmd != VI_GET && (argc == 0 || recurse != 0 || verbose != 0)) ||
|
||||
(cmd == VI_IFMOVE && (argc < 2 || argc > 3)) ||
|
||||
(cmd == VI_MODIFY && argc < 2) || argc >= MAXPARAMS)
|
||||
usage();
|
||||
|
||||
switch (cmd) {
|
||||
case VI_GET:
|
||||
vst_last = 0;
|
||||
vst_size = VST_SIZE_STEP;
|
||||
if ((vst = malloc(vst_size * sizeof(*vst))) == NULL)
|
||||
break;
|
||||
if (argc == 1)
|
||||
namelen = strlen(argv[0]);
|
||||
else
|
||||
namelen = 0;
|
||||
jid = 0;
|
||||
while ((jid = getjail(&vst[vst_last], jid, verbose)) > 0) {
|
||||
/* Skip jails which do not own vnets. */
|
||||
if (vst[vst_last].vnet != 1)
|
||||
continue;
|
||||
/* Skip non-matching vnames / hierarchies. */
|
||||
if (namelen &&
|
||||
((strlen(vst[vst_last].name) < namelen ||
|
||||
strncmp(vst[vst_last].name, argv[0], namelen) != 0)
|
||||
|| (strlen(vst[vst_last].name) > namelen &&
|
||||
vst[vst_last].name[namelen] != '.')))
|
||||
continue;
|
||||
/* Skip any sub-trees if -r not requested. */
|
||||
if (!recurse &&
|
||||
(strlen(vst[vst_last].name) < namelen ||
|
||||
strchr(&vst[vst_last].name[namelen], '.') != NULL))
|
||||
continue;
|
||||
/* Grow vst table if necessary. */
|
||||
if (++vst_last == vst_size) {
|
||||
vst_size += VST_SIZE_STEP;
|
||||
vst = realloc(vst, vst_size * sizeof(*vst));
|
||||
if (vst == NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vst == NULL)
|
||||
break;
|
||||
/* Sort: the key is the 1st field in *vst, i.e. vimage name. */
|
||||
qsort(vst, vst_last, sizeof(*vst), (void *) strcmp);
|
||||
for (i = 0; i < vst_last; i++) {
|
||||
if (!verbose) {
|
||||
printf("%s\n", vst[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("%s:\n", vst[i].name);
|
||||
printf(" Path: %s\n", vst[i].path);
|
||||
printf(" Hostname: %s\n", vst[i].hostname);
|
||||
printf(" Domainname: %s\n", vst[i].domainname);
|
||||
printf(" Children: %d\n", vst[i].childcnt);
|
||||
|
||||
if (verbose < 2)
|
||||
continue;
|
||||
|
||||
printf(" Children limit: %d\n", vst[i].childmax);
|
||||
printf(" CPUsetID: %d\n", vst[i].cpuset);
|
||||
printf(" JID: %d\n", vst[i].jid);
|
||||
printf(" PJID: %d\n", vst[i].parentjid);
|
||||
printf(" Raw sockets allowed: %d\n", vst[i].rawsock);
|
||||
printf(" All AF allowed: %d\n", vst[i].socket_af);
|
||||
printf(" Mount allowed: %d\n", vst[i].mount);
|
||||
}
|
||||
free(vst);
|
||||
exit(0);
|
||||
|
||||
case VI_IFMOVE:
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
break;
|
||||
if ((jid = jail_getid(argv[0])) < 0)
|
||||
break;
|
||||
ifreq.ifr_jid = jid;
|
||||
strncpy(ifreq.ifr_name, argv[1], sizeof(ifreq.ifr_name));
|
||||
if (ioctl(s, SIOCSIFVNET, (caddr_t)&ifreq) < 0)
|
||||
break;
|
||||
close(s);
|
||||
if (argc == 3)
|
||||
snprintf(ifname, sizeof(ifname), "%s", argv[2]);
|
||||
else
|
||||
snprintf(ifname, sizeof(ifname), "eth0");
|
||||
ifreq.ifr_data = ifname;
|
||||
/* Do we need to rename the ifnet? */
|
||||
if (strcmp(ifreq.ifr_name, ifname) != 0) {
|
||||
/* Switch to the context of the target vimage. */
|
||||
if (jail_attach(jid) < 0)
|
||||
break;
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
break;
|
||||
for (namelen = 0; isalpha(ifname[namelen]); namelen++);
|
||||
i = 0;
|
||||
/* Search for a free ifunit in target vnet. Unsafe. */
|
||||
while (ioctl(s, SIOCSIFNAME, (caddr_t)&ifreq) < 0) {
|
||||
snprintf(&ifname[namelen],
|
||||
sizeof(ifname) - namelen, "%d", i);
|
||||
/* Emergency brake. */
|
||||
if (i++ == IF_MAXUNIT)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < IF_MAXUNIT)
|
||||
printf("%s@%s\n", ifname, argv[0]);
|
||||
else
|
||||
printf("%s@%s\n", ifreq.ifr_name, argv[0]);
|
||||
exit(0);
|
||||
|
||||
case VI_CREATE:
|
||||
if (jail_setv(JAIL_CREATE,
|
||||
"name", argv[0],
|
||||
"vnet", NULL,
|
||||
"host", NULL,
|
||||
"persist", NULL,
|
||||
"allow.raw_sockets", "true",
|
||||
"allow.socket_af", "true",
|
||||
"allow.mount", "true",
|
||||
NULL) < 0)
|
||||
break;
|
||||
if (argc == 1)
|
||||
exit(0);
|
||||
/* Not done yet, proceed to apply non-default parameters. */
|
||||
|
||||
case VI_MODIFY:
|
||||
jailparam_init(¶ms[0], "name");
|
||||
jailparam_import(¶ms[0], argv[0]);
|
||||
for (i = 1; i < argc; i++) {
|
||||
for (str = argv[i]; *str != '=' && *str != 0; str++) {
|
||||
/* Do nothing - search for '=' delimeter. */
|
||||
}
|
||||
if (*str == 0)
|
||||
break;
|
||||
*str++ = 0;
|
||||
if (*str == 0)
|
||||
break;
|
||||
jailparam_init(¶ms[i], argv[i]);
|
||||
jailparam_import(¶ms[i], str);
|
||||
}
|
||||
if (i != argc)
|
||||
break;
|
||||
if (jailparam_set(params, i, JAIL_UPDATE) < 0)
|
||||
break;
|
||||
exit(0);
|
||||
|
||||
case VI_DESTROY:
|
||||
if ((jid = jail_getid(argv[0])) < 0)
|
||||
break;
|
||||
if (jail_remove(jid) < 0)
|
||||
break;
|
||||
exit(0);
|
||||
|
||||
case VI_SWITCHTO:
|
||||
if ((jid = jail_getid(argv[0])) < 0)
|
||||
break;
|
||||
if (jail_attach(jid) < 0)
|
||||
break;
|
||||
if (argc == 1) {
|
||||
printf("Switched to vimage %s\n", argv[0]);
|
||||
if ((str = getenv("SHELL")) == NULL)
|
||||
execlp("/bin/sh", invocname, NULL);
|
||||
else
|
||||
execlp(str, invocname, NULL);
|
||||
} else
|
||||
execvp(argv[1], &argv[1]);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Should be unreachable. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (jail_errmsg[0])
|
||||
fprintf(stderr, "Error: %s\n", jail_errmsg);
|
||||
else
|
||||
perror("Error");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
getjail(vstat_t *vs, int lastjid, int verbose)
|
||||
{
|
||||
struct jailparam params[32]; /* Must be > max(psize). */
|
||||
int psize = 0;
|
||||
|
||||
bzero(params, sizeof(params));
|
||||
bzero(vs, sizeof(*vs));
|
||||
|
||||
jailparam_init(¶ms[psize], "lastjid");
|
||||
jailparam_import_raw(¶ms[psize++], &lastjid, sizeof lastjid);
|
||||
|
||||
jailparam_init(¶ms[psize], "vnet");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->vnet, sizeof(vs->vnet));
|
||||
|
||||
jailparam_init(¶ms[psize], "name");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->name, sizeof(vs->name));
|
||||
|
||||
if (verbose == 0)
|
||||
goto done;
|
||||
|
||||
jailparam_init(¶ms[psize], "path");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->path, sizeof(vs->path));
|
||||
|
||||
jailparam_init(¶ms[psize], "host.hostname");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->hostname,
|
||||
sizeof(vs->hostname));
|
||||
|
||||
jailparam_init(¶ms[psize], "host.domainname");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->domainname,
|
||||
sizeof(vs->domainname));
|
||||
|
||||
jailparam_init(¶ms[psize], "children.cur");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->childcnt,
|
||||
sizeof(vs->childcnt));
|
||||
|
||||
if (verbose == 1)
|
||||
goto done;
|
||||
|
||||
jailparam_init(¶ms[psize], "children.max");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->childmax,
|
||||
sizeof(vs->childmax));
|
||||
|
||||
jailparam_init(¶ms[psize], "cpuset.id");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->cpuset,
|
||||
sizeof(vs->cpuset));
|
||||
|
||||
jailparam_init(¶ms[psize], "parent");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->parentjid,
|
||||
sizeof(vs->parentjid));
|
||||
|
||||
jailparam_init(¶ms[psize], "allow.raw_sockets");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->rawsock,
|
||||
sizeof(vs->rawsock));
|
||||
|
||||
jailparam_init(¶ms[psize], "allow.socket_af");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->socket_af,
|
||||
sizeof(vs->socket_af));
|
||||
|
||||
jailparam_init(¶ms[psize], "allow.mount");
|
||||
jailparam_import_raw(¶ms[psize++], &vs->mount, sizeof(vs->mount));
|
||||
|
||||
done:
|
||||
vs->jid = jailparam_get(params, psize, 0);
|
||||
jailparam_free(params, psize);
|
||||
return (vs->jid);
|
||||
}
|
3077
kernel/freebsd/vimage_7-CORE.diff
Normal file
3077
kernel/freebsd/vimage_7-CORE.diff
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue