Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |
tanxiaojun | 97ad8b5 | 2013-12-19 13:28:14 +0800 | [diff] [blame] | 26 | static struct ebt_replace_kernel initial_table = { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 | |
tanxiaojun | 97ad8b5 | 2013-12-19 13:28:14 +0800 | [diff] [blame] | 43 | static const struct ebt_table broute_table = { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | .name = "broute", |
| 45 | .table = &initial_table, |
| 46 | .valid_hooks = 1 << NF_BR_BROUTING, |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 47 | .check = check, |
| 48 | .me = THIS_MODULE, |
| 49 | }; |
| 50 | |
Herbert Xu | 3db05fe | 2007-10-15 00:53:15 -0700 | [diff] [blame] | 51 | static int ebt_broute(struct sk_buff *skb) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 52 | { |
Eric W. Biederman | 97b59c3 | 2015-09-18 14:32:54 -0500 | [diff] [blame] | 53 | struct nf_hook_state state; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 | int ret; |
| 55 | |
Eric W. Biederman | 97b59c3 | 2015-09-18 14:32:54 -0500 | [diff] [blame] | 56 | nf_hook_state_init(&state, NULL, NF_BR_BROUTING, INT_MIN, |
| 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); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 61 | if (ret == NF_DROP) |
| 62 | return 1; /* route it */ |
| 63 | return 0; /* bridge it */ |
| 64 | } |
| 65 | |
Alexey Dobriyan | 8157e6d | 2008-11-04 14:29:03 +0100 | [diff] [blame] | 66 | static int __net_init broute_net_init(struct net *net) |
| 67 | { |
| 68 | net->xt.broute_table = ebt_register_table(net, &broute_table); |
Rusty Russell | 8c6ffba | 2013-07-15 11:20:32 +0930 | [diff] [blame] | 69 | return PTR_ERR_OR_ZERO(net->xt.broute_table); |
Alexey Dobriyan | 8157e6d | 2008-11-04 14:29:03 +0100 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | static void __net_exit broute_net_exit(struct net *net) |
| 73 | { |
Alexey Dobriyan | f54e936 | 2010-01-18 08:25:47 +0100 | [diff] [blame] | 74 | ebt_unregister_table(net, net->xt.broute_table); |
Alexey Dobriyan | 8157e6d | 2008-11-04 14:29:03 +0100 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | static struct pernet_operations broute_net_ops = { |
| 78 | .init = broute_net_init, |
| 79 | .exit = broute_net_exit, |
| 80 | }; |
| 81 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 82 | static int __init ebtable_broute_init(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | { |
Alexey Dobriyan | 8157e6d | 2008-11-04 14:29:03 +0100 | [diff] [blame] | 84 | int ret; |
| 85 | |
| 86 | ret = register_pernet_subsys(&broute_net_ops); |
| 87 | if (ret < 0) |
| 88 | return ret; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 89 | /* see br_input.c */ |
Stephen Hemminger | a9b3cd7 | 2011-08-01 16:19:00 +0000 | [diff] [blame] | 90 | RCU_INIT_POINTER(br_should_route_hook, |
Eric Dumazet | a386f99 | 2010-11-15 06:38:11 +0000 | [diff] [blame] | 91 | (br_should_route_hook_t *)ebt_broute); |
Alexey Dobriyan | 6beceee | 2008-11-04 14:27:15 +0100 | [diff] [blame] | 92 | return 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 93 | } |
| 94 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 95 | static void __exit ebtable_broute_fini(void) |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 96 | { |
Stephen Hemminger | a9b3cd7 | 2011-08-01 16:19:00 +0000 | [diff] [blame] | 97 | RCU_INIT_POINTER(br_should_route_hook, NULL); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | synchronize_net(); |
Alexey Dobriyan | 8157e6d | 2008-11-04 14:29:03 +0100 | [diff] [blame] | 99 | unregister_pernet_subsys(&broute_net_ops); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | } |
| 101 | |
Andrew Morton | 65b4b4e | 2006-03-28 16:37:06 -0800 | [diff] [blame] | 102 | module_init(ebtable_broute_init); |
| 103 | module_exit(ebtable_broute_fini); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 104 | MODULE_LICENSE("GPL"); |