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 */ 21 static struct ebt_entries initial_chain = { 22 .name = "BROUTING", 23 .policy = EBT_ACCEPT, 24 }; 25 26 static 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 36 static 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 43 static 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 51 static int ebt_broute(struct sk_buff *skb) 52 { 53 struct nf_hook_state state; 54 int ret; 55 56 nf_hook_state_init(&state, NF_BR_BROUTING, 57 NFPROTO_BRIDGE, skb->dev, NULL, NULL, 58 dev_net(skb->dev), NULL); 59 60 ret = ebt_do_table(skb, &state, state.net->xt.broute_table); 61 if (ret == NF_DROP) 62 return 1; /* route it */ 63 return 0; /* bridge it */ 64 } 65 66 static int __net_init broute_net_init(struct net *net) 67 { 68 net->xt.broute_table = ebt_register_table(net, &broute_table, NULL); 69 return PTR_ERR_OR_ZERO(net->xt.broute_table); 70 } 71 72 static void __net_exit broute_net_exit(struct net *net) 73 { 74 ebt_unregister_table(net, net->xt.broute_table, NULL); 75 } 76 77 static struct pernet_operations broute_net_ops = { 78 .init = broute_net_init, 79 .exit = broute_net_exit, 80 }; 81 82 static int __init ebtable_broute_init(void) 83 { 84 int ret; 85 86 ret = register_pernet_subsys(&broute_net_ops); 87 if (ret < 0) 88 return ret; 89 /* see br_input.c */ 90 RCU_INIT_POINTER(br_should_route_hook, 91 (br_should_route_hook_t *)ebt_broute); 92 return 0; 93 } 94 95 static void __exit ebtable_broute_fini(void) 96 { 97 RCU_INIT_POINTER(br_should_route_hook, NULL); 98 synchronize_net(); 99 unregister_pernet_subsys(&broute_net_ops); 100 } 101 102 module_init(ebtable_broute_init); 103 module_exit(ebtable_broute_fini); 104 MODULE_LICENSE("GPL"); 105