diff options
author | Florian Westphal <fw@strlen.de> | 2013-04-19 00:58:23 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-04-29 14:09:04 -0400 |
commit | 4bd60443cc44c93ff37d483d69674647a0c48e4e (patch) | |
tree | 7ee64d74419db0e8f160a3638df0a8d9389e87d1 /net | |
parent | 6e01781d1c80e2e8263471252a631e86165b15c5 (diff) |
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) | |||
66 | module_put(entry->elem->owner); | 66 | module_put(entry->elem->owner); |
67 | } | 67 | } |
68 | 68 | ||
69 | /* Bump dev refs so they don't vanish while packet is out */ | ||
70 | static bool nf_queue_entry_get_refs(struct nf_queue_entry *entry) | ||
71 | { | ||
72 | if (!try_module_get(entry->elem->owner)) | ||
73 | return false; | ||
74 | |||
75 | if (entry->indev) | ||
76 | dev_hold(entry->indev); | ||
77 | if (entry->outdev) | ||
78 | dev_hold(entry->outdev); | ||
79 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
80 | if (entry->skb->nf_bridge) { | ||
81 | struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; | ||
82 | struct net_device *physdev; | ||
83 | |||
84 | physdev = nf_bridge->physindev; | ||
85 | if (physdev) | ||
86 | dev_hold(physdev); | ||
87 | physdev = nf_bridge->physoutdev; | ||
88 | if (physdev) | ||
89 | dev_hold(physdev); | ||
90 | } | ||
91 | #endif | ||
92 | |||
93 | return true; | ||
94 | } | ||
95 | |||
69 | /* | 96 | /* |
70 | * Any packet that leaves via this function must come back | 97 | * Any packet that leaves via this function must come back |
71 | * through nf_reinject(). | 98 | * through nf_reinject(). |
@@ -80,10 +107,6 @@ static int __nf_queue(struct sk_buff *skb, | |||
80 | { | 107 | { |
81 | int status = -ENOENT; | 108 | int status = -ENOENT; |
82 | struct nf_queue_entry *entry = NULL; | 109 | struct nf_queue_entry *entry = NULL; |
83 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
84 | struct net_device *physindev; | ||
85 | struct net_device *physoutdev; | ||
86 | #endif | ||
87 | const struct nf_afinfo *afinfo; | 110 | const struct nf_afinfo *afinfo; |
88 | const struct nf_queue_handler *qh; | 111 | const struct nf_queue_handler *qh; |
89 | 112 | ||
@@ -116,26 +139,10 @@ static int __nf_queue(struct sk_buff *skb, | |||
116 | .okfn = okfn, | 139 | .okfn = okfn, |
117 | }; | 140 | }; |
118 | 141 | ||
119 | /* If it's going away, ignore hook. */ | 142 | if (!nf_queue_entry_get_refs(entry)) { |
120 | if (!try_module_get(entry->elem->owner)) { | ||
121 | status = -ECANCELED; | 143 | status = -ECANCELED; |
122 | goto err_unlock; | 144 | goto err_unlock; |
123 | } | 145 | } |
124 | /* Bump dev refs so they don't vanish while packet is out */ | ||
125 | if (indev) | ||
126 | dev_hold(indev); | ||
127 | if (outdev) | ||
128 | dev_hold(outdev); | ||
129 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
130 | if (skb->nf_bridge) { | ||
131 | physindev = skb->nf_bridge->physindev; | ||
132 | if (physindev) | ||
133 | dev_hold(physindev); | ||
134 | physoutdev = skb->nf_bridge->physoutdev; | ||
135 | if (physoutdev) | ||
136 | dev_hold(physoutdev); | ||
137 | } | ||
138 | #endif | ||
139 | skb_dst_force(skb); | 146 | skb_dst_force(skb); |
140 | afinfo->saveroute(skb, entry); | 147 | afinfo->saveroute(skb, entry); |
141 | status = qh->outfn(entry, queuenum); | 148 | status = qh->outfn(entry, queuenum); |