11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  ebtable_filter
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *	Authors:
51da177e4SLinus Torvalds  *	Bart De Schuymer <bdschuym@pandora.be>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  April, 2002
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/netfilter_bridge/ebtables.h>
121da177e4SLinus Torvalds #include <linux/module.h>
131da177e4SLinus Torvalds 
141da177e4SLinus Torvalds #define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
151da177e4SLinus Torvalds    (1 << NF_BR_LOCAL_OUT))
161da177e4SLinus Torvalds 
171da177e4SLinus Torvalds static struct ebt_entries initial_chains[] =
181da177e4SLinus Torvalds {
191da177e4SLinus Torvalds 	{
201da177e4SLinus Torvalds 		.name	= "INPUT",
211da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
221da177e4SLinus Torvalds 	},
231da177e4SLinus Torvalds 	{
241da177e4SLinus Torvalds 		.name	= "FORWARD",
251da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
261da177e4SLinus Torvalds 	},
271da177e4SLinus Torvalds 	{
281da177e4SLinus Torvalds 		.name	= "OUTPUT",
291da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
301da177e4SLinus Torvalds 	},
311da177e4SLinus Torvalds };
321da177e4SLinus Torvalds 
331e419cd9SAl Viro static struct ebt_replace_kernel initial_table =
341da177e4SLinus Torvalds {
351da177e4SLinus Torvalds 	.name		= "filter",
361da177e4SLinus Torvalds 	.valid_hooks	= FILTER_VALID_HOOKS,
371da177e4SLinus Torvalds 	.entries_size	= 3 * sizeof(struct ebt_entries),
381da177e4SLinus Torvalds 	.hook_entry	= {
391da177e4SLinus Torvalds 		[NF_BR_LOCAL_IN]	= &initial_chains[0],
401da177e4SLinus Torvalds 		[NF_BR_FORWARD]		= &initial_chains[1],
411da177e4SLinus Torvalds 		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
421da177e4SLinus Torvalds 	},
431da177e4SLinus Torvalds 	.entries	= (char *)initial_chains,
441da177e4SLinus Torvalds };
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
471da177e4SLinus Torvalds {
481da177e4SLinus Torvalds 	if (valid_hooks & ~FILTER_VALID_HOOKS)
491da177e4SLinus Torvalds 		return -EINVAL;
501da177e4SLinus Torvalds 	return 0;
511da177e4SLinus Torvalds }
521da177e4SLinus Torvalds 
5335aad0ffSJan Engelhardt static const struct ebt_table frame_filter =
541da177e4SLinus Torvalds {
551da177e4SLinus Torvalds 	.name		= "filter",
561da177e4SLinus Torvalds 	.table		= &initial_table,
571da177e4SLinus Torvalds 	.valid_hooks	= FILTER_VALID_HOOKS,
581da177e4SLinus Torvalds 	.check		= check,
591da177e4SLinus Torvalds 	.me		= THIS_MODULE,
601da177e4SLinus Torvalds };
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds static unsigned int
63795aa6efSPatrick McHardy ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
64795aa6efSPatrick McHardy 	    const struct net_device *in, const struct net_device *out,
65795aa6efSPatrick McHardy 	    int (*okfn)(struct sk_buff *))
661da177e4SLinus Torvalds {
67795aa6efSPatrick McHardy 	return ebt_do_table(ops->hooknum, skb, in, out,
68795aa6efSPatrick McHardy 			    dev_net(in)->xt.frame_filter);
694aad1093SAlexey Dobriyan }
704aad1093SAlexey Dobriyan 
714aad1093SAlexey Dobriyan static unsigned int
72795aa6efSPatrick McHardy ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
73795aa6efSPatrick McHardy 	     const struct net_device *in, const struct net_device *out,
74795aa6efSPatrick McHardy 	     int (*okfn)(struct sk_buff *))
754aad1093SAlexey Dobriyan {
76795aa6efSPatrick McHardy 	return ebt_do_table(ops->hooknum, skb, in, out,
77795aa6efSPatrick McHardy 			    dev_net(out)->xt.frame_filter);
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds 
801999414aSPatrick McHardy static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
811da177e4SLinus Torvalds 	{
824aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
831da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8424c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
851da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_IN,
861da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
871da177e4SLinus Torvalds 	},
881da177e4SLinus Torvalds 	{
894aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
901da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
9124c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
921da177e4SLinus Torvalds 		.hooknum	= NF_BR_FORWARD,
931da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
941da177e4SLinus Torvalds 	},
951da177e4SLinus Torvalds 	{
964aad1093SAlexey Dobriyan 		.hook		= ebt_out_hook,
971da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
9824c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
991da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_OUT,
1001da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_OTHER,
1011da177e4SLinus Torvalds 	},
1021da177e4SLinus Torvalds };
1031da177e4SLinus Torvalds 
1044aad1093SAlexey Dobriyan static int __net_init frame_filter_net_init(struct net *net)
1054aad1093SAlexey Dobriyan {
1064aad1093SAlexey Dobriyan 	net->xt.frame_filter = ebt_register_table(net, &frame_filter);
1078c6ffba0SRusty Russell 	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
1084aad1093SAlexey Dobriyan }
1094aad1093SAlexey Dobriyan 
1104aad1093SAlexey Dobriyan static void __net_exit frame_filter_net_exit(struct net *net)
1114aad1093SAlexey Dobriyan {
112f54e9367SAlexey Dobriyan 	ebt_unregister_table(net, net->xt.frame_filter);
1134aad1093SAlexey Dobriyan }
1144aad1093SAlexey Dobriyan 
1154aad1093SAlexey Dobriyan static struct pernet_operations frame_filter_net_ops = {
1164aad1093SAlexey Dobriyan 	.init = frame_filter_net_init,
1174aad1093SAlexey Dobriyan 	.exit = frame_filter_net_exit,
1184aad1093SAlexey Dobriyan };
1194aad1093SAlexey Dobriyan 
12065b4b4e8SAndrew Morton static int __init ebtable_filter_init(void)
1211da177e4SLinus Torvalds {
122e40f51a3SAlexey Dobriyan 	int ret;
1231da177e4SLinus Torvalds 
1244aad1093SAlexey Dobriyan 	ret = register_pernet_subsys(&frame_filter_net_ops);
1254aad1093SAlexey Dobriyan 	if (ret < 0)
1264aad1093SAlexey Dobriyan 		return ret;
127e40f51a3SAlexey Dobriyan 	ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
128e40f51a3SAlexey Dobriyan 	if (ret < 0)
1294aad1093SAlexey Dobriyan 		unregister_pernet_subsys(&frame_filter_net_ops);
1301da177e4SLinus Torvalds 	return ret;
1311da177e4SLinus Torvalds }
1321da177e4SLinus Torvalds 
13365b4b4e8SAndrew Morton static void __exit ebtable_filter_fini(void)
1341da177e4SLinus Torvalds {
135e40f51a3SAlexey Dobriyan 	nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
1364aad1093SAlexey Dobriyan 	unregister_pernet_subsys(&frame_filter_net_ops);
1371da177e4SLinus Torvalds }
1381da177e4SLinus Torvalds 
13965b4b4e8SAndrew Morton module_init(ebtable_filter_init);
14065b4b4e8SAndrew Morton module_exit(ebtable_filter_fini);
1411da177e4SLinus Torvalds MODULE_LICENSE("GPL");
142