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 struct ebt_table broute_table =
45{
46	.name		= "broute",
47	.table		= &initial_table,
48	.valid_hooks	= 1 << NF_BR_BROUTING,
49	.lock		= RW_LOCK_UNLOCKED,
50	.check		= check,
51	.me		= THIS_MODULE,
52};
53
54static int ebt_broute(struct sk_buff **pskb)
55{
56	int ret;
57
58	ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL,
59	   &broute_table);
60	if (ret == NF_DROP)
61		return 1; /* route it */
62	return 0; /* bridge it */
63}
64
65static int __init ebtable_broute_init(void)
66{
67	int ret;
68
69	ret = ebt_register_table(&broute_table);
70	if (ret < 0)
71		return ret;
72	/* see br_input.c */
73	br_should_route_hook = ebt_broute;
74	return ret;
75}
76
77static void __exit ebtable_broute_fini(void)
78{
79	br_should_route_hook = NULL;
80	synchronize_net();
81	ebt_unregister_table(&broute_table);
82}
83
84module_init(ebtable_broute_init);
85module_exit(ebtable_broute_fini);
86MODULE_LICENSE("GPL");
87