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 
1797ad8b53Stanxiaojun static struct ebt_entries initial_chains[] = {
181da177e4SLinus Torvalds 	{
191da177e4SLinus Torvalds 		.name	= "INPUT",
201da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
211da177e4SLinus Torvalds 	},
221da177e4SLinus Torvalds 	{
231da177e4SLinus Torvalds 		.name	= "FORWARD",
241da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
251da177e4SLinus Torvalds 	},
261da177e4SLinus Torvalds 	{
271da177e4SLinus Torvalds 		.name	= "OUTPUT",
281da177e4SLinus Torvalds 		.policy	= EBT_ACCEPT,
291da177e4SLinus Torvalds 	},
301da177e4SLinus Torvalds };
311da177e4SLinus Torvalds 
3297ad8b53Stanxiaojun static struct ebt_replace_kernel initial_table = {
331da177e4SLinus Torvalds 	.name		= "filter",
341da177e4SLinus Torvalds 	.valid_hooks	= FILTER_VALID_HOOKS,
351da177e4SLinus Torvalds 	.entries_size	= 3 * sizeof(struct ebt_entries),
361da177e4SLinus Torvalds 	.hook_entry	= {
371da177e4SLinus Torvalds 		[NF_BR_LOCAL_IN]	= &initial_chains[0],
381da177e4SLinus Torvalds 		[NF_BR_FORWARD]		= &initial_chains[1],
391da177e4SLinus Torvalds 		[NF_BR_LOCAL_OUT]	= &initial_chains[2],
401da177e4SLinus Torvalds 	},
411da177e4SLinus Torvalds 	.entries	= (char *)initial_chains,
421da177e4SLinus Torvalds };
431da177e4SLinus Torvalds 
441da177e4SLinus Torvalds static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds 	if (valid_hooks & ~FILTER_VALID_HOOKS)
471da177e4SLinus Torvalds 		return -EINVAL;
481da177e4SLinus Torvalds 	return 0;
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
5197ad8b53Stanxiaojun static const struct ebt_table frame_filter = {
521da177e4SLinus Torvalds 	.name		= "filter",
531da177e4SLinus Torvalds 	.table		= &initial_table,
541da177e4SLinus Torvalds 	.valid_hooks	= FILTER_VALID_HOOKS,
551da177e4SLinus Torvalds 	.check		= check,
561da177e4SLinus Torvalds 	.me		= THIS_MODULE,
571da177e4SLinus Torvalds };
581da177e4SLinus Torvalds 
591da177e4SLinus Torvalds static unsigned int
60795aa6efSPatrick McHardy ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
61795aa6efSPatrick McHardy 	    const struct net_device *in, const struct net_device *out,
62795aa6efSPatrick McHardy 	    int (*okfn)(struct sk_buff *))
631da177e4SLinus Torvalds {
64795aa6efSPatrick McHardy 	return ebt_do_table(ops->hooknum, skb, in, out,
65795aa6efSPatrick McHardy 			    dev_net(in)->xt.frame_filter);
664aad1093SAlexey Dobriyan }
674aad1093SAlexey Dobriyan 
684aad1093SAlexey Dobriyan static unsigned int
69795aa6efSPatrick McHardy ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
70795aa6efSPatrick McHardy 	     const struct net_device *in, const struct net_device *out,
71795aa6efSPatrick McHardy 	     int (*okfn)(struct sk_buff *))
724aad1093SAlexey Dobriyan {
73795aa6efSPatrick McHardy 	return ebt_do_table(ops->hooknum, skb, in, out,
74795aa6efSPatrick McHardy 			    dev_net(out)->xt.frame_filter);
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds 
771999414aSPatrick McHardy static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
781da177e4SLinus Torvalds 	{
794aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
801da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8124c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
821da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_IN,
831da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
841da177e4SLinus Torvalds 	},
851da177e4SLinus Torvalds 	{
864aad1093SAlexey Dobriyan 		.hook		= ebt_in_hook,
871da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
8824c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
891da177e4SLinus Torvalds 		.hooknum	= NF_BR_FORWARD,
901da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_BRIDGED,
911da177e4SLinus Torvalds 	},
921da177e4SLinus Torvalds 	{
934aad1093SAlexey Dobriyan 		.hook		= ebt_out_hook,
941da177e4SLinus Torvalds 		.owner		= THIS_MODULE,
9524c232d8SJan Engelhardt 		.pf		= NFPROTO_BRIDGE,
961da177e4SLinus Torvalds 		.hooknum	= NF_BR_LOCAL_OUT,
971da177e4SLinus Torvalds 		.priority	= NF_BR_PRI_FILTER_OTHER,
981da177e4SLinus Torvalds 	},
991da177e4SLinus Torvalds };
1001da177e4SLinus Torvalds 
1014aad1093SAlexey Dobriyan static int __net_init frame_filter_net_init(struct net *net)
1024aad1093SAlexey Dobriyan {
1034aad1093SAlexey Dobriyan 	net->xt.frame_filter = ebt_register_table(net, &frame_filter);
1048c6ffba0SRusty Russell 	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
1054aad1093SAlexey Dobriyan }
1064aad1093SAlexey Dobriyan 
1074aad1093SAlexey Dobriyan static void __net_exit frame_filter_net_exit(struct net *net)
1084aad1093SAlexey Dobriyan {
109f54e9367SAlexey Dobriyan 	ebt_unregister_table(net, net->xt.frame_filter);
1104aad1093SAlexey Dobriyan }
1114aad1093SAlexey Dobriyan 
1124aad1093SAlexey Dobriyan static struct pernet_operations frame_filter_net_ops = {
1134aad1093SAlexey Dobriyan 	.init = frame_filter_net_init,
1144aad1093SAlexey Dobriyan 	.exit = frame_filter_net_exit,
1154aad1093SAlexey Dobriyan };
1164aad1093SAlexey Dobriyan 
11765b4b4e8SAndrew Morton static int __init ebtable_filter_init(void)
1181da177e4SLinus Torvalds {
119e40f51a3SAlexey Dobriyan 	int ret;
1201da177e4SLinus Torvalds 
1214aad1093SAlexey Dobriyan 	ret = register_pernet_subsys(&frame_filter_net_ops);
1224aad1093SAlexey Dobriyan 	if (ret < 0)
1234aad1093SAlexey Dobriyan 		return ret;
124e40f51a3SAlexey Dobriyan 	ret = nf_register_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
125e40f51a3SAlexey Dobriyan 	if (ret < 0)
1264aad1093SAlexey Dobriyan 		unregister_pernet_subsys(&frame_filter_net_ops);
1271da177e4SLinus Torvalds 	return ret;
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds 
13065b4b4e8SAndrew Morton static void __exit ebtable_filter_fini(void)
1311da177e4SLinus Torvalds {
132e40f51a3SAlexey Dobriyan 	nf_unregister_hooks(ebt_ops_filter, ARRAY_SIZE(ebt_ops_filter));
1334aad1093SAlexey Dobriyan 	unregister_pernet_subsys(&frame_filter_net_ops);
1341da177e4SLinus Torvalds }
1351da177e4SLinus Torvalds 
13665b4b4e8SAndrew Morton module_init(ebtable_filter_init);
13765b4b4e8SAndrew Morton module_exit(ebtable_filter_fini);
1381da177e4SLinus Torvalds MODULE_LICENSE("GPL");
139