linux/net/bridge/netfilter/ebtable_broute.c
<<
>>
Prefs
   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        struct nf_hook_state state;
  54        int ret;
  55
  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);
  61        if (ret == NF_DROP)
  62                return 1; /* route it */
  63        return 0; /* bridge it */
  64}
  65
  66static int __net_init broute_net_init(struct net *net)
  67{
  68        net->xt.broute_table = ebt_register_table(net, &broute_table);
  69        return PTR_ERR_OR_ZERO(net->xt.broute_table);
  70}
  71
  72static void __net_exit broute_net_exit(struct net *net)
  73{
  74        ebt_unregister_table(net, net->xt.broute_table);
  75}
  76
  77static struct pernet_operations broute_net_ops = {
  78        .init = broute_net_init,
  79        .exit = broute_net_exit,
  80};
  81
  82static 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
  95static 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
 102module_init(ebtable_broute_init);
 103module_exit(ebtable_broute_fini);
 104MODULE_LICENSE("GPL");
 105