summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2003-04-27 12:28:47 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-04-27 12:28:47 -0700
commitce0041ef255121563bab8b747c1440c1bbf93ddf (patch)
tree123967aebfb5f491257e5b638597c49563364049
parent90c1d5ebfecd53b5aac187777988d577b3f2e19c (diff)
[NETFILTER]: Add owner field to nf_hook_ops.
Adds an owner field to nf_hook_ops, and use it to hold the hook in place for queued packets.
-rw-r--r--include/linux/netfilter.h1
-rw-r--r--net/bridge/br_netfilter.c18
-rw-r--r--net/bridge/netfilter/ebtable_filter.c3
-rw-r--r--net/bridge/netfilter/ebtable_nat.c3
-rw-r--r--net/core/netfilter.c49
-rw-r--r--net/ipv4/netfilter/arptable_filter.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c3
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c5
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c3
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c5
-rw-r--r--net/sched/sch_ingress.c1
14 files changed, 75 insertions, 30 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index b1ae5446b0e2..3f3f29f11ad8 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -47,6 +47,7 @@ struct nf_hook_ops
/* User fills in from here down. */
nf_hookfn *hook;
+ struct module *owner;
int pf;
int hooknum;
/* Hooks are ordered in ascending priority. */
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index e0a61b6b9ac2..9cf424a9b0b0 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -574,15 +574,15 @@ static unsigned int ipv4_sabotage_out(unsigned int hook, struct sk_buff **pskb,
* ip_refrag() can return NF_STOLEN.
*/
static struct nf_hook_ops br_nf_ops[] = {
- { { NULL, NULL }, br_nf_pre_routing, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF },
- { { NULL, NULL }, br_nf_local_in, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF },
- { { NULL, NULL }, br_nf_forward, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF },
- { { NULL, NULL }, br_nf_local_out, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST },
- { { NULL, NULL }, br_nf_post_routing, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST },
- { { NULL, NULL }, ipv4_sabotage_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST },
- { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD },
- { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT },
- { { NULL, NULL }, ipv4_sabotage_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST }
+ { { NULL, NULL }, br_nf_pre_routing, THIS_MODULE, PF_BRIDGE, NF_BR_PRE_ROUTING, NF_BR_PRI_BRNF },
+ { { NULL, NULL }, br_nf_local_in, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_IN, NF_BR_PRI_BRNF },
+ { { NULL, NULL }, br_nf_forward, THIS_MODULE, PF_BRIDGE, NF_BR_FORWARD, NF_BR_PRI_BRNF },
+ { { NULL, NULL }, br_nf_local_out, THIS_MODULE, PF_BRIDGE, NF_BR_LOCAL_OUT, NF_BR_PRI_FIRST },
+ { { NULL, NULL }, br_nf_post_routing, THIS_MODULE, PF_BRIDGE, NF_BR_POST_ROUTING, NF_BR_PRI_LAST },
+ { { NULL, NULL }, ipv4_sabotage_in, THIS_MODULE, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FIRST },
+ { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_FORWARD, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD },
+ { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT },
+ { { NULL, NULL }, ipv4_sabotage_out, THIS_MODULE, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FIRST }
};
#define NUMHOOKS (sizeof(br_nf_ops)/sizeof(br_nf_ops[0]))
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index ce60c4ea527d..ee9394bb5e01 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -70,18 +70,21 @@ ebt_hook (unsigned int hook, struct sk_buff **pskb, const struct net_device *in,
static struct nf_hook_ops ebt_ops_filter[] = {
{
.hook = ebt_hook,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_LOCAL_IN,
.priority = NF_BR_PRI_FILTER_BRIDGED,
},
{
.hook = ebt_hook,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_FILTER_BRIDGED,
},
{
.hook = ebt_hook,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_LOCAL_OUT,
.priority = NF_BR_PRI_FILTER_OTHER,
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 8dcf54528612..ca39dac72f66 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -76,18 +76,21 @@ ebt_nat_src(unsigned int hook, struct sk_buff **pskb, const struct net_device *i
static struct nf_hook_ops ebt_ops_nat[] = {
{
.hook = ebt_nat_dst,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_LOCAL_OUT,
.priority = NF_BR_PRI_NAT_DST_OTHER,
},
{
.hook = ebt_nat_src,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_POST_ROUTING,
.priority = NF_BR_PRI_NAT_SRC,
},
{
.hook = ebt_nat_dst,
+ .owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_PRE_ROUTING,
.priority = NF_BR_PRI_NAT_DST_BRIDGED,
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 706f4ec6cceb..463490a7ea9a 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -350,6 +350,8 @@ static unsigned int nf_iterate(struct list_head *head,
if (hook_thresh > elem->priority)
continue;
+ /* Optimization: we don't need to hold module
+ reference here, since function can't sleep. --RR */
switch (elem->hook(hook, skb, indev, outdev, okfn)) {
case NF_QUEUE:
return NF_QUEUE;
@@ -408,12 +410,12 @@ int nf_unregister_queue_handler(int pf)
* Any packet that leaves via this function must come back
* through nf_reinject().
*/
-static void nf_queue(struct sk_buff *skb,
- struct list_head *elem,
- int pf, unsigned int hook,
- struct net_device *indev,
- struct net_device *outdev,
- int (*okfn)(struct sk_buff *))
+static int nf_queue(struct sk_buff *skb,
+ struct list_head *elem,
+ int pf, unsigned int hook,
+ struct net_device *indev,
+ struct net_device *outdev,
+ int (*okfn)(struct sk_buff *))
{
int status;
struct nf_info *info;
@@ -422,9 +424,10 @@ static void nf_queue(struct sk_buff *skb,
struct net_device *physoutdev = NULL;
#endif
+ /* QUEUE == DROP if noone is waiting, to be safe. */
if (!queue_handler[pf].outfn) {
kfree_skb(skb);
- return;
+ return 1;
}
info = kmalloc(sizeof(*info), GFP_ATOMIC);
@@ -433,12 +436,16 @@ static void nf_queue(struct sk_buff *skb,
printk(KERN_ERR "OOM queueing packet %p\n",
skb);
kfree_skb(skb);
- return;
+ return 1;
}
*info = (struct nf_info) {
(struct nf_hook_ops *)elem, pf, hook, indev, outdev, okfn };
+ /* If it's going away, ignore hook. */
+ if (!try_module_get(info->elem->owner))
+ return 0;
+
/* Bump dev refs so they don't vanish while packet is out */
if (indev) dev_hold(indev);
if (outdev) dev_hold(outdev);
@@ -461,10 +468,12 @@ static void nf_queue(struct sk_buff *skb,
if (physindev) dev_put(physindev);
if (physoutdev) dev_put(physoutdev);
#endif
+ module_put(info->elem->owner);
kfree(info);
kfree_skb(skb);
- return;
+ return 1;
}
+ return 1;
}
int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
@@ -497,11 +506,13 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
#endif
elem = &nf_hooks[pf][hook];
+ next_hook:
verdict = nf_iterate(&nf_hooks[pf][hook], &skb, hook, indev,
outdev, &elem, okfn, hook_thresh);
if (verdict == NF_QUEUE) {
NFDEBUG("nf_hook: Verdict = QUEUE.\n");
- nf_queue(skb, elem, pf, hook, indev, outdev, okfn);
+ if (!nf_queue(skb, elem, pf, hook, indev, outdev, okfn))
+ goto next_hook;
}
switch (verdict) {
@@ -527,15 +538,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
/* We don't have BR_NETPROTO_LOCK here */
br_read_lock_bh(BR_NETPROTO_LOCK);
- for (i = nf_hooks[info->pf][info->hook].next; i != elem; i = i->next) {
- if (i == &nf_hooks[info->pf][info->hook]) {
- /* The module which sent it to userspace is gone. */
- NFDEBUG("%s: module disappeared, dropping packet.\n",
- __FUNCTION__);
- verdict = NF_DROP;
- break;
- }
- }
+
+ /* Drop reference to owner of hook which queued us. */
+ module_put(info->elem->owner);
/* Continue traversal iff userspace said ok... */
if (verdict == NF_REPEAT) {
@@ -544,6 +549,7 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
}
if (verdict == NF_ACCEPT) {
+ next_hook:
verdict = nf_iterate(&nf_hooks[info->pf][info->hook],
&skb, info->hook,
info->indev, info->outdev, &elem,
@@ -556,8 +562,9 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
break;
case NF_QUEUE:
- nf_queue(skb, elem, info->pf, info->hook,
- info->indev, info->outdev, info->okfn);
+ if (!nf_queue(skb, elem, info->pf, info->hook,
+ info->indev, info->outdev, info->okfn))
+ goto next_hook;
break;
case NF_DROP:
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 0519b7930496..3387279f6908 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -133,11 +133,13 @@ static unsigned int arpt_hook(unsigned int hook,
static struct nf_hook_ops arpt_ops[] = {
{
.hook = arpt_hook,
+ .owner = THIS_MODULE,
.pf = NF_ARP,
.hooknum = NF_ARP_IN,
},
{
.hook = arpt_hook,
+ .owner = THIS_MODULE,
.pf = NF_ARP,
.hooknum = NF_ARP_OUT,
}
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index c939c329ecf1..d1704ed5723b 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -227,6 +227,7 @@ static unsigned int ip_conntrack_local(unsigned int hooknum,
make it the first hook. */
static struct nf_hook_ops ip_conntrack_in_ops = {
.hook = ip_conntrack_in,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_CONNTRACK,
@@ -234,6 +235,7 @@ static struct nf_hook_ops ip_conntrack_in_ops = {
static struct nf_hook_ops ip_conntrack_local_out_ops = {
.hook = ip_conntrack_local,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_CONNTRACK,
@@ -242,6 +244,7 @@ static struct nf_hook_ops ip_conntrack_local_out_ops = {
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops = {
.hook = ip_refrag,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_LAST,
@@ -249,6 +252,7 @@ static struct nf_hook_ops ip_conntrack_out_ops = {
static struct nf_hook_ops ip_conntrack_local_in_ops = {
.hook = ip_confirm,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_LAST-1,
diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
index bc08c07dbb2b..470784e138ab 100644
--- a/net/ipv4/netfilter/ip_fw_compat.c
+++ b/net/ipv4/netfilter/ip_fw_compat.c
@@ -226,6 +226,7 @@ static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len)
static struct nf_hook_ops preroute_ops = {
.hook = fw_in,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_FILTER,
@@ -233,6 +234,7 @@ static struct nf_hook_ops preroute_ops = {
static struct nf_hook_ops postroute_ops = {
.hook = fw_in,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_FILTER,
@@ -240,6 +242,7 @@ static struct nf_hook_ops postroute_ops = {
static struct nf_hook_ops forward_ops = {
.hook = fw_in,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = NF_IP_PRI_FILTER,
@@ -247,6 +250,7 @@ static struct nf_hook_ops forward_ops = {
static struct nf_hook_ops local_in_ops = {
.hook = fw_confirm,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_LAST - 1,
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 5d84a14e8e82..69cf5c6ae27a 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -238,6 +238,7 @@ ip_nat_local_fn(unsigned int hooknum,
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_in_ops = {
.hook = ip_nat_fn,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_NAT_DST,
@@ -246,6 +247,7 @@ static struct nf_hook_ops ip_nat_in_ops = {
/* After packet filtering, change source */
static struct nf_hook_ops ip_nat_out_ops = {
.hook = ip_nat_out,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC,
@@ -254,6 +256,7 @@ static struct nf_hook_ops ip_nat_out_ops = {
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops = {
.hook = ip_nat_local_fn,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST,
@@ -262,6 +265,7 @@ static struct nf_hook_ops ip_nat_local_out_ops = {
#ifdef CONFIG_IP_NF_NAT_LOCAL
static struct nf_hook_ops ip_nat_local_in_ops = {
.hook = ip_nat_fn,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC,
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 81f13ed42c5a..05e7798d2973 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -125,18 +125,21 @@ ipt_local_out_hook(unsigned int hook,
static struct nf_hook_ops ipt_ops[] = {
{
.hook = ipt_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_FILTER,
},
{
.hook = ipt_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = NF_IP_PRI_FILTER,
},
{
.hook = ipt_local_out_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_FILTER,
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 3c57d06e48fc..65232b030090 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -178,30 +178,35 @@ ipt_local_hook(unsigned int hook,
static struct nf_hook_ops ipt_ops[] = {
{
.hook = ipt_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_PRE_ROUTING,
.priority = NF_IP_PRI_MANGLE,
},
{
.hook = ipt_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = NF_IP_PRI_MANGLE,
},
{
.hook = ipt_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = NF_IP_PRI_MANGLE,
},
{
.hook = ipt_local_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_OUT,
.priority = NF_IP_PRI_MANGLE,
},
{
.hook = ipt_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_MANGLE,
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index e720778b3d32..dc034cb823f1 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -123,18 +123,21 @@ ip6t_local_out_hook(unsigned int hook,
static struct nf_hook_ops ip6t_ops[] = {
{
.hook = ip6t_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_IN,
.priority = NF_IP6_PRI_FILTER,
},
{
.hook = ip6t_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_FORWARD,
.priority = NF_IP6_PRI_FILTER,
},
{
.hook = ip6t_local_out_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_OUT,
.priority = NF_IP6_PRI_FILTER,
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index 848ce9c8b699..08b0c24b27a1 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -186,30 +186,35 @@ ip6t_local_hook(unsigned int hook,
static struct nf_hook_ops ip6t_ops[] = {
{
.hook = ip6t_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_PRE_ROUTING,
.priority = NF_IP6_PRI_MANGLE,
},
{
.hook = ip6t_local_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_IN,
.priority = NF_IP6_PRI_MANGLE,
},
{
.hook = ip6t_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_FORWARD,
.priority = NF_IP6_PRI_MANGLE,
},
{
.hook = ip6t_local_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_OUT,
.priority = NF_IP6_PRI_MANGLE,
},
{
.hook = ip6t_route_hook,
+ .owner = THIS_MODULE,
.pf = PF_INET6,
.hooknum = NF_IP6_POST_ROUTING,
.priority = NF_IP6_PRI_MANGLE,
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index c3457f94eca6..48a63bae0124 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -241,6 +241,7 @@ static struct nf_hook_ops ing_ops =
{
{ NULL, NULL},
ing_hook,
+ THIS_MODULE,
PF_INET,
NF_IP_PRE_ROUTING,
NF_IP_PRI_FILTER + 1