1/* 2 * ebtable_broute 3 * 4 * Authors: 5 * Bart De Schuymer <bdschuym@pandora.be> 6 * 7 * April, 2002 8 * 9 * This table lets you choose between routing and bridging for frames 10 * entering on a bridge enslaved nic. This table is traversed before any 11 * other ebtables table. See net/bridge/br_input.c. 12 */ 13 14#include <linux/netfilter_bridge/ebtables.h> 15#include <linux/module.h> 16#include <linux/if_bridge.h> 17 18/* EBT_ACCEPT means the frame will be bridged 19 * EBT_DROP means the frame will be routed 20 */ 21static struct ebt_entries initial_chain = { 22 .name = "BROUTING", 23 .policy = EBT_ACCEPT, 24}; 25 26static struct ebt_replace_kernel initial_table = { 27 .name = "broute", 28 .valid_hooks = 1 << NF_BR_BROUTING, 29 .entries_size = sizeof(struct ebt_entries), 30 .hook_entry = { 31 [NF_BR_BROUTING] = &initial_chain, 32 }, 33 .entries = (char *)&initial_chain, 34}; 35 36static int check(const struct ebt_table_info *info, unsigned int valid_hooks) 37{ 38 if (valid_hooks & ~(1 << NF_BR_BROUTING)) 39 return -EINVAL; 40 return 0; 41} 42 43static const struct ebt_table broute_table = { 44 .name = "broute", 45 .table = &initial_table, 46 .valid_hooks = 1 << NF_BR_BROUTING, 47 .check = check, 48 .me = THIS_MODULE, 49}; 50 51static int ebt_broute(struct sk_buff *skb) 52{ 53 int ret; 54 55 ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL, 56 dev_net(skb->dev)->xt.broute_table); 57 if (ret == NF_DROP) 58 return 1; /* route it */ 59 return 0; /* bridge it */ 60} 61 62static int __net_init broute_net_init(struct net *net) 63{ 64 net->xt.broute_table = ebt_register_table(net, &broute_table); 65 return PTR_ERR_OR_ZERO(net->xt.broute_table); 66} 67 68static void __net_exit broute_net_exit(struct net *net) 69{ 70 ebt_unregister_table(net, net->xt.broute_table); 71} 72 73static struct pernet_operations broute_net_ops = { 74 .init = broute_net_init, 75 .exit = broute_net_exit, 76}; 77 78static int __init ebtable_broute_init(void) 79{ 80 int ret; 81 82 ret = register_pernet_subsys(&broute_net_ops); 83 if (ret < 0) 84 return ret; 85 /* see br_input.c */ 86 RCU_INIT_POINTER(br_should_route_hook, 87 (br_should_route_hook_t *)ebt_broute); 88 return 0; 89} 90 91static void __exit ebtable_broute_fini(void) 92{ 93 RCU_INIT_POINTER(br_should_route_hook, NULL); 94 synchronize_net(); 95 unregister_pernet_subsys(&broute_net_ops); 96} 97 98module_init(ebtable_broute_init); 99module_exit(ebtable_broute_fini); 100MODULE_LICENSE("GPL"); 101