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{
  28        .name           = "broute",
  29        .valid_hooks    = 1 << NF_BR_BROUTING,
  30        .entries_size   = sizeof(struct ebt_entries),
  31        .hook_entry     = {
  32                [NF_BR_BROUTING]        = &initial_chain,
  33        },
  34        .entries        = (char *)&initial_chain,
  35};
  36
  37static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
  38{
  39        if (valid_hooks & ~(1 << NF_BR_BROUTING))
  40                return -EINVAL;
  41        return 0;
  42}
  43
  44static const struct ebt_table broute_table =
  45{
  46        .name           = "broute",
  47        .table          = &initial_table,
  48        .valid_hooks    = 1 << NF_BR_BROUTING,
  49        .check          = check,
  50        .me             = THIS_MODULE,
  51};
  52
  53static int ebt_broute(struct sk_buff *skb)
  54{
  55        int ret;
  56
  57        ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
  58                           dev_net(skb->dev)->xt.broute_table);
  59        if (ret == NF_DROP)
  60                return 1; /* route it */
  61        return 0; /* bridge it */
  62}
  63
  64static int __net_init broute_net_init(struct net *net)
  65{
  66        net->xt.broute_table = ebt_register_table(net, &broute_table);
  67        if (IS_ERR(net->xt.broute_table))
  68                return PTR_ERR(net->xt.broute_table);
  69        return 0;
  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