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
634aad1093SAlexey Dobriyan ebt_in_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
641da177e4SLinus Torvalds    const struct net_device *out, int (*okfn)(struct sk_buff *))
651da177e4SLinus Torvalds {
664aad1093SAlexey Dobriyan 	return ebt_do_table(hook, skb, in, out, dev_net(in)->xt.frame_filter);
674aad1093SAlexey Dobriyan }
684aad1093SAlexey Dobriyan 
694aad1093SAlexey Dobriyan static unsigned int
704aad1093SAlexey Dobriyan ebt_out_hook(unsigned int hook, struct sk_buff *skb, const struct net_device *in,
714aad1093SAlexey Dobriyan    const struct net_device *out, int (*okfn)(struct sk_buff *))
724aad1093SAlexey Dobriyan {
734aad1093SAlexey Dobriyan 	return ebt_do_table(hook, skb, in, out, dev_net(out)->xt.frame_filter);
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds 
761999414aSPatrick McHardy static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
771da177e4SLinus Torvalds 	{
784aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
791da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8024c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
811da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_IN,
821da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
831da177e4SLinus Torvalds 	},
841da177e4SLinus Torvalds 	{
854aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
861da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8724c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
881da177e4SLinus Torvalds 		.hooknum	= NF_BR_FORWARD,
891da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
901da177e4SLinus Torvalds 	},
911da177e4SLinus Torvalds 	{
924aad1093SAlexey Dobriyan 		.hook		= ebt_out_hook,
931da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
9424c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
951da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_OUT,
961da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_OTHER,
971da177e4SLinus Torvalds 	},
981da177e4SLinus Torvalds };
991da177e4SLinus Torvalds 
1004aad1093SAlexey Dobriyan static int __net_init frame_filter_net_init(struct net *net)
1014aad1093SAlexey Dobriyan {
1024aad1093SAlexey Dobriyan 	net->xt.frame_filter = ebt_register_table(net, &frame_filter);
1038c6ffba0SRusty Russell 	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
1044aad1093SAlexey Dobriyan }
1054aad1093SAlexey Dobriyan 
1064aad1093SAlexey Dobriyan static void __net_exit frame_filter_net_exit(struct net *net)
1074aad1093SAlexey Dobriyan {
108f54e9367SAlexey Dobriyan 	ebt_unregister_table(net, net->xt.frame_filter);
1094aad1093SAlexey Dobriyan }
1104aad1093SAlexey Dobriyan 
1114aad1093SAlexey Dobriyan static struct pernet_operations frame_filter_net_ops = {
1124aad1093SAlexey Dobriyan 	.init = frame_filter_net_init,
1134aad1093SAlexey Dobriyan 	.exit = frame_filter_net_exit,
1144aad1093SAlexey Dobriyan };
1154aad1093SAlexey Dobriyan 
11665b4b4e8SAndrew Morton static int __init ebtable_filter_init(void)
1171da177e4SLinus Torvalds {
118e40f51a3SAlexey Dobriyan 	int ret;
1191da177e4SLinus Torvalds 
1204aad1093SAlexey Dobriyan 	ret = register_pernet_subsys(&frame_filter_net_ops);
1214aad1093SAlexey Dobriyan 	if (ret < 0)
1224aad1093SAlexey Dobriyan 		return ret;
123e40f51a3SAlexey Dobriyan 	ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
124e40f51a3SAlexey Dobriyan 	if (ret < 0)
1254aad1093SAlexey Dobriyan 		unregister_pernet_subsys(&frame_filter_net_ops);
1261da177e4SLinus Torvalds 	return ret;
1271da177e4SLinus Torvalds }
1281da177e4SLinus Torvalds 
12965b4b4e8SAndrew Morton static void __exit ebtable_filter_fini(void)
1301da177e4SLinus Torvalds {
131e40f51a3SAlexey Dobriyan 	nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
1324aad1093SAlexey Dobriyan 	unregister_pernet_subsys(&frame_filter_net_ops);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
13565b4b4e8SAndrew Morton module_init(ebtable_filter_init);
13665b4b4e8SAndrew Morton module_exit(ebtable_filter_fini);
1371da177e4SLinus Torvalds MODULE_LICENSE("GPL");
138