aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-04-11 10:36:41 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2019-04-11 19:47:39 -0400
commit971502d77faa50a37c89bc6d172450294ad9a5fd (patch)
tree432504faa8b09801a8b004ffb298c4ce7827a799
parentf12064d1b402c60c5db9c4b63d5ed6d7facb33f6 (diff)
bridge: netfilter: unroll NF_HOOK helper in bridge input path
Replace NF_HOOK() based invocation of the netfilter hooks with a private copy of nf_hook_slow(). This copy has one difference: it can return the rx handler value expected by the stack, i.e. RX_HANDLER_CONSUMED or RX_HANDLER_PASS. This is needed by the next patch to invoke the ebtables "broute" table via the standard netfilter hooks rather than the custom "br_should_route_hook" indirection that is used now. When the skb is to be "brouted", we must return RX_HANDLER_PASS from the bridge rx input handler, but there is no way to indicate this via NF_HOOK(), unless perhaps by some hack such as exposing bridge_cb in the netfilter core or a percpu flag. text data bss dec filename 3369 56 0 3425 net/bridge/br_input.o.before 3458 40 0 3498 net/bridge/br_input.o.after This allows removal of the "br_should_route_hook" in the next patch. Signed-off-by: Florian Westphal <fw@strlen.de> Acked-by: David S. Miller <davem@davemloft.net> Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/net/netfilter/nf_queue.h3
-rw-r--r--net/bridge/br_input.c55
-rw-r--r--net/netfilter/core.c1
-rw-r--r--net/netfilter/nf_internals.h3
-rw-r--r--net/netfilter/nf_queue.c1
5 files changed, 56 insertions, 7 deletions
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index a50a69f5334c..7239105d9d2e 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -119,4 +119,7 @@ nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
119 return queue; 119 return queue;
120} 120}
121 121
122int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
123 const struct nf_hook_entries *entries, unsigned int index,
124 unsigned int verdict);
122#endif /* _NF_QUEUE_H */ 125#endif /* _NF_QUEUE_H */
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index e2f93e5c72da..4ac34fb5f943 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -16,6 +16,7 @@
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <linux/etherdevice.h> 17#include <linux/etherdevice.h>
18#include <linux/netfilter_bridge.h> 18#include <linux/netfilter_bridge.h>
19#include <net/netfilter/nf_queue.h>
19#include <linux/neighbour.h> 20#include <linux/neighbour.h>
20#include <net/arp.h> 21#include <net/arp.h>
21#include <linux/export.h> 22#include <linux/export.h>
@@ -206,6 +207,55 @@ static int br_handle_local_finish(struct net *net, struct sock *sk, struct sk_bu
206 return 0; 207 return 0;
207} 208}
208 209
210static int nf_hook_bridge_pre(struct sk_buff *skb, struct sk_buff **pskb)
211{
212#ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
213 struct nf_hook_entries *e = NULL;
214 struct nf_hook_state state;
215 unsigned int verdict, i;
216 struct net *net;
217 int ret;
218
219 net = dev_net(skb->dev);
220#ifdef HAVE_JUMP_LABEL
221 if (!static_key_false(&nf_hooks_needed[NFPROTO_BRIDGE][NF_BR_PRE_ROUTING]))
222 goto frame_finish;
223#endif
224
225 e = rcu_dereference(net->nf.hooks_bridge[NF_BR_PRE_ROUTING]);
226 if (!e)
227 goto frame_finish;
228
229 nf_hook_state_init(&state, NF_BR_PRE_ROUTING,
230 NFPROTO_BRIDGE, skb->dev, NULL, NULL,
231 net, br_handle_frame_finish);
232
233 for (i = 0; i < e->num_hook_entries; i++) {
234 verdict = nf_hook_entry_hookfn(&e->hooks[i], skb, &state);
235 switch (verdict & NF_VERDICT_MASK) {
236 case NF_ACCEPT:
237 break;
238 case NF_DROP:
239 kfree_skb(skb);
240 return RX_HANDLER_CONSUMED;
241 case NF_QUEUE:
242 ret = nf_queue(skb, &state, e, i, verdict);
243 if (ret == 1)
244 continue;
245 return RX_HANDLER_CONSUMED;
246 default: /* STOLEN */
247 return RX_HANDLER_CONSUMED;
248 }
249 }
250frame_finish:
251 net = dev_net(skb->dev);
252 br_handle_frame_finish(net, NULL, skb);
253#else
254 br_handle_frame_finish(dev_net(skb->dev), NULL, skb);
255#endif
256 return RX_HANDLER_CONSUMED;
257}
258
209/* 259/*
210 * Return NULL if skb is handled 260 * Return NULL if skb is handled
211 * note: already called with rcu_read_lock 261 * note: already called with rcu_read_lock
@@ -304,10 +354,7 @@ forward:
304 if (ether_addr_equal(p->br->dev->dev_addr, dest)) 354 if (ether_addr_equal(p->br->dev->dev_addr, dest))
305 skb->pkt_type = PACKET_HOST; 355 skb->pkt_type = PACKET_HOST;
306 356
307 NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, 357 return nf_hook_bridge_pre(skb, pskb);
308 dev_net(skb->dev), NULL, skb, skb->dev, NULL,
309 br_handle_frame_finish);
310 break;
311 default: 358 default:
312drop: 359drop:
313 kfree_skb(skb); 360 kfree_skb(skb);
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 93aaec3a54ec..71f06900473e 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -23,6 +23,7 @@
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/rcupdate.h> 24#include <linux/rcupdate.h>
25#include <net/net_namespace.h> 25#include <net/net_namespace.h>
26#include <net/netfilter/nf_queue.h>
26#include <net/sock.h> 27#include <net/sock.h>
27 28
28#include "nf_internals.h" 29#include "nf_internals.h"
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h
index e15779fd58e3..d6c43902ebd7 100644
--- a/net/netfilter/nf_internals.h
+++ b/net/netfilter/nf_internals.h
@@ -7,9 +7,6 @@
7#include <linux/netdevice.h> 7#include <linux/netdevice.h>
8 8
9/* nf_queue.c */ 9/* nf_queue.c */
10int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
11 const struct nf_hook_entries *entries, unsigned int index,
12 unsigned int verdict);
13void nf_queue_nf_hook_drop(struct net *net); 10void nf_queue_nf_hook_drop(struct net *net);
14 11
15/* nf_log.c */ 12/* nf_log.c */
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index a36a77bae1d6..9dc1d6e04946 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -240,6 +240,7 @@ int nf_queue(struct sk_buff *skb, struct nf_hook_state *state,
240 240
241 return 0; 241 return 0;
242} 242}
243EXPORT_SYMBOL_GPL(nf_queue);
243 244
244static unsigned int nf_iterate(struct sk_buff *skb, 245static unsigned int nf_iterate(struct sk_buff *skb,
245 struct nf_hook_state *state, 246 struct nf_hook_state *state,