1 // SPDX-License-Identifier: GPL-2.0-only
6 * Bart De Schuymer <bdschuym@pandora.be>
10 * This table lets you choose between routing and bridging for frames
11 * entering on a bridge enslaved nic. This table is traversed before any
12 * other ebtables table. See net/bridge/br_input.c.
15 #include <linux/netfilter_bridge/ebtables.h>
16 #include <linux/module.h>
17 #include <linux/if_bridge.h>
19 #include "../br_private.h"
21 /* EBT_ACCEPT means the frame will be bridged
22 * EBT_DROP means the frame will be routed
24 static struct ebt_entries initial_chain
= {
29 static struct ebt_replace_kernel initial_table
= {
31 .valid_hooks
= 1 << NF_BR_BROUTING
,
32 .entries_size
= sizeof(struct ebt_entries
),
34 [NF_BR_BROUTING
] = &initial_chain
,
36 .entries
= (char *)&initial_chain
,
39 static const struct ebt_table broute_table
= {
41 .table
= &initial_table
,
42 .valid_hooks
= 1 << NF_BR_BROUTING
,
46 static unsigned int ebt_broute(void *priv
, struct sk_buff
*skb
,
47 const struct nf_hook_state
*s
)
49 struct net_bridge_port
*p
= br_port_get_rcu(skb
->dev
);
50 struct nf_hook_state state
;
54 if (!p
|| p
->state
!= BR_STATE_FORWARDING
)
57 nf_hook_state_init(&state
, NF_BR_BROUTING
,
58 NFPROTO_BRIDGE
, s
->in
, NULL
, NULL
,
61 ret
= ebt_do_table(priv
, skb
, &state
);
65 /* DROP in ebtables -t broute means that the
66 * skb should be routed, not bridged.
67 * This is awkward, but can't be changed for compatibility
70 * We map DROP to ACCEPT and set the ->br_netfilter_broute flag.
72 BR_INPUT_SKB_CB(skb
)->br_netfilter_broute
= 1;
74 /* undo PACKET_HOST mangling done in br_input in case the dst
75 * address matches the logical bridge but not the port.
77 dest
= eth_hdr(skb
)->h_dest
;
78 if (skb
->pkt_type
== PACKET_HOST
&&
79 !ether_addr_equal(skb
->dev
->dev_addr
, dest
) &&
80 ether_addr_equal(p
->br
->dev
->dev_addr
, dest
))
81 skb
->pkt_type
= PACKET_OTHERHOST
;
86 static const struct nf_hook_ops ebt_ops_broute
= {
89 .hooknum
= NF_BR_PRE_ROUTING
,
90 .priority
= NF_BR_PRI_FIRST
,
93 static int broute_table_init(struct net
*net
)
95 return ebt_register_table(net
, &broute_table
, &ebt_ops_broute
);
98 static void __net_exit
broute_net_pre_exit(struct net
*net
)
100 ebt_unregister_table_pre_exit(net
, "broute");
103 static void __net_exit
broute_net_exit(struct net
*net
)
105 ebt_unregister_table(net
, "broute");
108 static struct pernet_operations broute_net_ops
= {
109 .exit
= broute_net_exit
,
110 .pre_exit
= broute_net_pre_exit
,
113 static int __init
ebtable_broute_init(void)
115 int ret
= ebt_register_template(&broute_table
, broute_table_init
);
120 ret
= register_pernet_subsys(&broute_net_ops
);
122 ebt_unregister_template(&broute_table
);
129 static void __exit
ebtable_broute_fini(void)
131 unregister_pernet_subsys(&broute_net_ops
);
132 ebt_unregister_template(&broute_table
);
135 module_init(ebtable_broute_init
);
136 module_exit(ebtable_broute_fini
);
137 MODULE_LICENSE("GPL");
138 MODULE_DESCRIPTION("Force packets to be routed instead of bridged");