196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy/*
296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
346413825a7e697109028738eede2191900ec848fPablo Neira Ayuso * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org>
496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy *
596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * This program is free software; you can redistribute it and/or modify
696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * it under the terms of the GNU General Public License version 2 as
796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * published by the Free Software Foundation.
896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy *
996518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy * Development of this code funded by Astaro AG (http://www.astaro.com/)
1096518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy */
1196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
1296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/init.h>
1396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/module.h>
1496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <linux/netfilter_bridge.h>
1596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy#include <net/netfilter/nf_tables.h>
1696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
173b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardystatic unsigned int
183b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardynft_do_chain_bridge(const struct nf_hook_ops *ops,
193b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		    struct sk_buff *skb,
203b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		    const struct net_device *in,
213b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		    const struct net_device *out,
223b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		    int (*okfn)(struct sk_buff *))
233b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy{
243b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy	struct nft_pktinfo pkt;
253b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy
263b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy	nft_set_pktinfo(&pkt, ops, skb, in, out);
273b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy
283876d22dba62ebf6582f33e1ef2160eeb95e1129Patrick McHardy	return nft_do_chain(&pkt, ops);
293b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy}
303b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy
3196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic struct nft_af_info nft_af_bridge __read_mostly = {
3296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.family		= NFPROTO_BRIDGE,
3396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.nhooks		= NF_BR_NUMHOOKS,
3496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy	.owner		= THIS_MODULE,
35115a60b173af0170e0db26b9a3fd6a911fba70a3Patrick McHardy	.nops		= 1,
363b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy	.hooks		= {
3736d2af5998258344993dd43729997a7a3baa9d99Pablo Neira Ayuso		[NF_BR_PRE_ROUTING]	= nft_do_chain_bridge,
383b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		[NF_BR_LOCAL_IN]	= nft_do_chain_bridge,
393b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		[NF_BR_FORWARD]		= nft_do_chain_bridge,
403b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy		[NF_BR_LOCAL_OUT]	= nft_do_chain_bridge,
4136d2af5998258344993dd43729997a7a3baa9d99Pablo Neira Ayuso		[NF_BR_POST_ROUTING]	= nft_do_chain_bridge,
423b088c4bc0035da662faa81818ba217e34c4bba4Patrick McHardy	},
4396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy};
4496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
4599633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayusostatic int nf_tables_bridge_init_net(struct net *net)
4699633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso{
4799633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL);
4899633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	if (net->nft.bridge == NULL)
4999633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso		return -ENOMEM;
5099633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
5199633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge));
5299633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
5399633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	if (nft_register_afinfo(net, net->nft.bridge) < 0)
5499633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso		goto err;
5599633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
5699633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	return 0;
5799633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayusoerr:
5899633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	kfree(net->nft.bridge);
5999633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	return -ENOMEM;
6099633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso}
6199633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
6299633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayusostatic void nf_tables_bridge_exit_net(struct net *net)
6399633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso{
6499633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	nft_unregister_afinfo(net->nft.bridge);
6599633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	kfree(net->nft.bridge);
6699633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso}
6799633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
6899633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayusostatic struct pernet_operations nf_tables_bridge_net_ops = {
6999633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	.init	= nf_tables_bridge_init_net,
7099633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso	.exit	= nf_tables_bridge_exit_net,
7199633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso};
7299633ab29b2131b68089a6c7f60458390860e044Pablo Neira Ayuso
732a37d755b885995443f11cdcaf1f9d4b5f246eabPatrick McHardystatic const struct nf_chain_type filter_bridge = {
7446413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	.name		= "filter",
7546413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	.type		= NFT_CHAIN_T_DEFAULT,
76fa2c1de0bbd98985f7f930205de97ae0d3e86c16Patrick McHardy	.family		= NFPROTO_BRIDGE,
77fa2c1de0bbd98985f7f930205de97ae0d3e86c16Patrick McHardy	.owner		= THIS_MODULE,
784d87716cd057bde3f90e304289c1fec88d45a1ccPablo Neira Ayuso	.hook_mask	= (1 << NF_BR_PRE_ROUTING) |
794d87716cd057bde3f90e304289c1fec88d45a1ccPablo Neira Ayuso			  (1 << NF_BR_LOCAL_IN) |
8046413825a7e697109028738eede2191900ec848fPablo Neira Ayuso			  (1 << NF_BR_FORWARD) |
814d87716cd057bde3f90e304289c1fec88d45a1ccPablo Neira Ayuso			  (1 << NF_BR_LOCAL_OUT) |
824d87716cd057bde3f90e304289c1fec88d45a1ccPablo Neira Ayuso			  (1 << NF_BR_POST_ROUTING),
8346413825a7e697109028738eede2191900ec848fPablo Neira Ayuso};
8446413825a7e697109028738eede2191900ec848fPablo Neira Ayuso
8596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic int __init nf_tables_bridge_init(void)
8696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
8746413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	int ret;
8846413825a7e697109028738eede2191900ec848fPablo Neira Ayuso
8946413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	nft_register_chain_type(&filter_bridge);
9046413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	ret = register_pernet_subsys(&nf_tables_bridge_net_ops);
9146413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	if (ret < 0)
9246413825a7e697109028738eede2191900ec848fPablo Neira Ayuso		nft_unregister_chain_type(&filter_bridge);
9346413825a7e697109028738eede2191900ec848fPablo Neira Ayuso
9446413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	return ret;
9596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
9696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
9796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardystatic void __exit nf_tables_bridge_exit(void)
9896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy{
9946413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	unregister_pernet_subsys(&nf_tables_bridge_net_ops);
10046413825a7e697109028738eede2191900ec848fPablo Neira Ayuso	nft_unregister_chain_type(&filter_bridge);
10196518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy}
10296518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
10396518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardymodule_init(nf_tables_bridge_init);
10496518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardymodule_exit(nf_tables_bridge_exit);
10596518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardy
10696518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_LICENSE("GPL");
10796518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
10896518518cc417bb0a8c80b9fb736202e28acdf96Patrick McHardyMODULE_ALIAS_NFT_FAMILY(AF_BRIDGE);
109