1 /*
2  *  ebtable_filter
3  *
4  *	Authors:
5  *	Bart De Schuymer <bdschuym@pandora.be>
6  *
7  *  April, 2002
8  *
9  */
10 
11 #include <linux/netfilter_bridge/ebtables.h>
12 #include <linux/module.h>
13 
14 #define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
15 			    (1 << NF_BR_LOCAL_OUT))
16 
17 static struct ebt_entries initial_chains[] = {
18 	{
19 		.name	= "INPUT",
20 		.policy	= EBT_ACCEPT,
21 	},
22 	{
23 		.name	= "FORWARD",
24 		.policy	= EBT_ACCEPT,
25 	},
26 	{
27 		.name	= "OUTPUT",
28 		.policy	= EBT_ACCEPT,
29 	},
30 };
31 
32 static struct ebt_replace_kernel initial_table = {
33 	.name		= "filter",
34 	.valid_hooks	= FILTER_VALID_HOOKS,
35 	.entries_size	= 3 * sizeof(struct ebt_entries),
36 	.hook_entry	= {
37 		[NF_BR_LOCAL_IN]	= &initial_chains[0],
38 		[NF_BR_FORWARD]		= &initial_chains[1],
39 		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
40 	},
41 	.entries	= (char *)initial_chains,
42 };
43 
44 static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
45 {
46 	if (valid_hooks & ~FILTER_VALID_HOOKS)
47 		return -EINVAL;
48 	return 0;
49 }
50 
51 static const struct ebt_table frame_filter = {
52 	.name		= "filter",
53 	.table		= &initial_table,
54 	.valid_hooks	= FILTER_VALID_HOOKS,
55 	.check		= check,
56 	.me		= THIS_MODULE,
57 };
58 
59 static unsigned int
60 ebt_in_hook(void *priv, struct sk_buff *skb,
61 	    const struct nf_hook_state *state)
62 {
63 	return ebt_do_table(skb, state, state->net->xt.frame_filter);
64 }
65 
66 static unsigned int
67 ebt_out_hook(void *priv, struct sk_buff *skb,
68 	     const struct nf_hook_state *state)
69 {
70 	return ebt_do_table(skb, state, state->net->xt.frame_filter);
71 }
72 
73 static const struct nf_hook_ops ebt_ops_filter[] = {
74 	{
75 		.hook		= ebt_in_hook,
76 		.pf		= NFPROTO_BRIDGE,
77 		.hooknum	= NF_BR_LOCAL_IN,
78 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
79 	},
80 	{
81 		.hook		= ebt_in_hook,
82 		.pf		= NFPROTO_BRIDGE,
83 		.hooknum	= NF_BR_FORWARD,
84 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
85 	},
86 	{
87 		.hook		= ebt_out_hook,
88 		.pf		= NFPROTO_BRIDGE,
89 		.hooknum	= NF_BR_LOCAL_OUT,
90 		.priority	= NF_BR_PRI_FILTER_OTHER,
91 	},
92 };
93 
94 static int __net_init frame_filter_net_init(struct net *net)
95 {
96 	net->xt.frame_filter = ebt_register_table(net, &frame_filter, ebt_ops_filter);
97 	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
98 }
99 
100 static void __net_exit frame_filter_net_exit(struct net *net)
101 {
102 	ebt_unregister_table(net, net->xt.frame_filter, ebt_ops_filter);
103 }
104 
105 static struct pernet_operations frame_filter_net_ops = {
106 	.init = frame_filter_net_init,
107 	.exit = frame_filter_net_exit,
108 };
109 
110 static int __init ebtable_filter_init(void)
111 {
112 	return register_pernet_subsys(&frame_filter_net_ops);
113 }
114 
115 static void __exit ebtable_filter_fini(void)
116 {
117 	unregister_pernet_subsys(&frame_filter_net_ops);
118 }
119 
120 module_init(ebtable_filter_init);
121 module_exit(ebtable_filter_fini);
122 MODULE_LICENSE("GPL");
123