diff options
author | Florian Westphal <fw@strlen.de> | 2013-04-19 08:58:23 +0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-29 22:09:04 +0400 |
commit | 4bd60443cc44c93ff37d483d69674647a0c48e4e (patch) | |
tree | 7ee64d74419db0e8f160a3638df0a8d9389e87d1 /net | |
parent | 6e01781d1c80e2e8263471252a631e86165b15c5 (diff) | |
download | linux-4bd60443cc44c93ff37d483d69674647a0c48e4e.tar.xz |
netfilter: nf_queue: move device refcount bump to extra function
required by future patch that will need to duplicate the
nf_queue_entry, bumping refcounts of the copy.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nf_queue.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5ccf01e35390..1d91e77ba4c2 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -66,6 +66,33 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) module_put(entry->elem->owner); } +/* Bump dev refs so they don't vanish while packet is out */ +static bool nf_queue_entry_get_refs(struct nf_queue_entry *entry) +{ + if (!try_module_get(entry->elem->owner)) + return false; + + if (entry->indev) + dev_hold(entry->indev); + if (entry->outdev) + dev_hold(entry->outdev); +#ifdef CONFIG_BRIDGE_NETFILTER + if (entry->skb->nf_bridge) { + struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; + struct net_device *physdev; + + physdev = nf_bridge->physindev; + if (physdev) + dev_hold(physdev); + physdev = nf_bridge->physoutdev; + if (physdev) + dev_hold(physdev); + } +#endif + + return true; +} + /* * Any packet that leaves via this function must come back * through nf_reinject(). @@ -80,10 +107,6 @@ static int __nf_queue(struct sk_buff *skb, { int status = -ENOENT; struct nf_queue_entry *entry = NULL; -#ifdef CONFIG_BRIDGE_NETFILTER - struct net_device *physindev; - struct net_device *physoutdev; -#endif const struct nf_afinfo *afinfo; const struct nf_queue_handler *qh; @@ -116,26 +139,10 @@ static int __nf_queue(struct sk_buff *skb, .okfn = okfn, }; - /* If it's going away, ignore hook. */ - if (!try_module_get(entry->elem->owner)) { + if (!nf_queue_entry_get_refs(entry)) { status = -ECANCELED; goto err_unlock; } - /* Bump dev refs so they don't vanish while packet is out */ - if (indev) - dev_hold(indev); - if (outdev) - dev_hold(outdev); -#ifdef CONFIG_BRIDGE_NETFILTER - if (skb->nf_bridge) { - physindev = skb->nf_bridge->physindev; - if (physindev) - dev_hold(physindev); - physoutdev = skb->nf_bridge->physoutdev; - if (physoutdev) - dev_hold(physoutdev); - } -#endif skb_dst_force(skb); afinfo->saveroute(skb, entry); status = qh->outfn(entry, queuenum); |