Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2008 Patrick McHardy <kaber@trash.net> |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 3 | * Copyright (c) 2013 Pablo Neira Ayuso <pablo@netfilter.org> |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License version 2 as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * Development of this code funded by Astaro AG (http://www.astaro.com/) |
| 10 | */ |
| 11 | |
| 12 | #include <linux/init.h> |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/netfilter_bridge.h> |
| 15 | #include <net/netfilter/nf_tables.h> |
Alvaro Neira | 68b0faa | 2014-11-26 10:21:36 +0100 | [diff] [blame] | 16 | #include <linux/ip.h> |
| 17 | #include <linux/ipv6.h> |
Alvaro Neira | 1b63d4b | 2014-11-26 10:21:37 +0100 | [diff] [blame] | 18 | #include <net/netfilter/nf_tables_ipv4.h> |
| 19 | #include <net/netfilter/nf_tables_ipv6.h> |
Alvaro Neira | 68b0faa | 2014-11-26 10:21:36 +0100 | [diff] [blame] | 20 | |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 21 | static unsigned int |
Eric W. Biederman | 06198b3 | 2015-09-18 14:33:06 -0500 | [diff] [blame] | 22 | nft_do_chain_bridge(void *priv, |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 23 | struct sk_buff *skb, |
David S. Miller | 238e54c | 2015-04-03 20:32:56 -0400 | [diff] [blame] | 24 | const struct nf_hook_state *state) |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 25 | { |
| 26 | struct nft_pktinfo pkt; |
| 27 | |
Alvaro Neira | 1b63d4b | 2014-11-26 10:21:37 +0100 | [diff] [blame] | 28 | switch (eth_hdr(skb)->h_proto) { |
| 29 | case htons(ETH_P_IP): |
Pablo Neira Ayuso | 10151d7 | 2016-09-09 12:42:52 +0200 | [diff] [blame] | 30 | nft_set_pktinfo_ipv4_validate(&pkt, skb, state); |
Alvaro Neira | 1b63d4b | 2014-11-26 10:21:37 +0100 | [diff] [blame] | 31 | break; |
| 32 | case htons(ETH_P_IPV6): |
Pablo Neira Ayuso | 10151d7 | 2016-09-09 12:42:52 +0200 | [diff] [blame] | 33 | nft_set_pktinfo_ipv6_validate(&pkt, skb, state); |
Alvaro Neira | 1b63d4b | 2014-11-26 10:21:37 +0100 | [diff] [blame] | 34 | break; |
| 35 | default: |
Pablo Neira Ayuso | beac5af | 2016-09-09 12:42:49 +0200 | [diff] [blame] | 36 | nft_set_pktinfo_unspec(&pkt, skb, state); |
Alvaro Neira | 1b63d4b | 2014-11-26 10:21:37 +0100 | [diff] [blame] | 37 | break; |
| 38 | } |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 39 | |
Eric W. Biederman | 06198b3 | 2015-09-18 14:33:06 -0500 | [diff] [blame] | 40 | return nft_do_chain(&pkt, priv); |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 41 | } |
| 42 | |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 43 | static struct nft_af_info nft_af_bridge __read_mostly = { |
| 44 | .family = NFPROTO_BRIDGE, |
| 45 | .nhooks = NF_BR_NUMHOOKS, |
| 46 | .owner = THIS_MODULE, |
Patrick McHardy | 115a60b | 2014-01-03 12:16:15 +0000 | [diff] [blame] | 47 | .nops = 1, |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 48 | .hooks = { |
Pablo Neira Ayuso | 36d2af5 | 2014-10-01 20:34:37 +0200 | [diff] [blame] | 49 | [NF_BR_PRE_ROUTING] = nft_do_chain_bridge, |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 50 | [NF_BR_LOCAL_IN] = nft_do_chain_bridge, |
| 51 | [NF_BR_FORWARD] = nft_do_chain_bridge, |
| 52 | [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, |
Pablo Neira Ayuso | 36d2af5 | 2014-10-01 20:34:37 +0200 | [diff] [blame] | 53 | [NF_BR_POST_ROUTING] = nft_do_chain_bridge, |
Patrick McHardy | 3b088c4 | 2014-01-03 12:16:13 +0000 | [diff] [blame] | 54 | }, |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 55 | }; |
| 56 | |
Pablo Neira Ayuso | 99633ab | 2013-10-10 23:28:33 +0200 | [diff] [blame] | 57 | static int nf_tables_bridge_init_net(struct net *net) |
| 58 | { |
| 59 | net->nft.bridge = kmalloc(sizeof(struct nft_af_info), GFP_KERNEL); |
| 60 | if (net->nft.bridge == NULL) |
| 61 | return -ENOMEM; |
| 62 | |
| 63 | memcpy(net->nft.bridge, &nft_af_bridge, sizeof(nft_af_bridge)); |
| 64 | |
| 65 | if (nft_register_afinfo(net, net->nft.bridge) < 0) |
| 66 | goto err; |
| 67 | |
| 68 | return 0; |
| 69 | err: |
| 70 | kfree(net->nft.bridge); |
| 71 | return -ENOMEM; |
| 72 | } |
| 73 | |
| 74 | static void nf_tables_bridge_exit_net(struct net *net) |
| 75 | { |
Pablo Neira Ayuso | df05ef8 | 2015-12-15 19:39:32 +0100 | [diff] [blame] | 76 | nft_unregister_afinfo(net, net->nft.bridge); |
Pablo Neira Ayuso | 99633ab | 2013-10-10 23:28:33 +0200 | [diff] [blame] | 77 | kfree(net->nft.bridge); |
| 78 | } |
| 79 | |
| 80 | static struct pernet_operations nf_tables_bridge_net_ops = { |
| 81 | .init = nf_tables_bridge_init_net, |
| 82 | .exit = nf_tables_bridge_exit_net, |
| 83 | }; |
| 84 | |
Patrick McHardy | 2a37d75 | 2014-01-09 18:42:37 +0000 | [diff] [blame] | 85 | static const struct nf_chain_type filter_bridge = { |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 86 | .name = "filter", |
| 87 | .type = NFT_CHAIN_T_DEFAULT, |
Patrick McHardy | fa2c1de | 2014-01-09 18:42:38 +0000 | [diff] [blame] | 88 | .family = NFPROTO_BRIDGE, |
| 89 | .owner = THIS_MODULE, |
Pablo Neira Ayuso | 4d87716 | 2014-10-25 12:25:06 +0200 | [diff] [blame] | 90 | .hook_mask = (1 << NF_BR_PRE_ROUTING) | |
| 91 | (1 << NF_BR_LOCAL_IN) | |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 92 | (1 << NF_BR_FORWARD) | |
Pablo Neira Ayuso | 4d87716 | 2014-10-25 12:25:06 +0200 | [diff] [blame] | 93 | (1 << NF_BR_LOCAL_OUT) | |
| 94 | (1 << NF_BR_POST_ROUTING), |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 95 | }; |
| 96 | |
Stephane Bryant | ac28634 | 2016-03-26 08:42:10 +0100 | [diff] [blame] | 97 | static void nf_br_saveroute(const struct sk_buff *skb, |
| 98 | struct nf_queue_entry *entry) |
| 99 | { |
| 100 | } |
| 101 | |
| 102 | static int nf_br_reroute(struct net *net, struct sk_buff *skb, |
| 103 | const struct nf_queue_entry *entry) |
| 104 | { |
| 105 | return 0; |
| 106 | } |
| 107 | |
| 108 | static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook, |
| 109 | unsigned int dataoff, u_int8_t protocol) |
| 110 | { |
| 111 | return 0; |
| 112 | } |
| 113 | |
| 114 | static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook, |
| 115 | unsigned int dataoff, unsigned int len, |
| 116 | u_int8_t protocol) |
| 117 | { |
| 118 | return 0; |
| 119 | } |
| 120 | |
| 121 | static int nf_br_route(struct net *net, struct dst_entry **dst, |
| 122 | struct flowi *fl, bool strict __always_unused) |
| 123 | { |
| 124 | return 0; |
| 125 | } |
| 126 | |
| 127 | static const struct nf_afinfo nf_br_afinfo = { |
| 128 | .family = AF_BRIDGE, |
| 129 | .checksum = nf_br_checksum, |
| 130 | .checksum_partial = nf_br_checksum_partial, |
| 131 | .route = nf_br_route, |
| 132 | .saveroute = nf_br_saveroute, |
| 133 | .reroute = nf_br_reroute, |
| 134 | .route_key_size = 0, |
| 135 | }; |
| 136 | |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 137 | static int __init nf_tables_bridge_init(void) |
| 138 | { |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 139 | int ret; |
| 140 | |
Stephane Bryant | ac28634 | 2016-03-26 08:42:10 +0100 | [diff] [blame] | 141 | nf_register_afinfo(&nf_br_afinfo); |
Gao Feng | 23d0750 | 2016-09-10 10:04:30 +0800 | [diff] [blame] | 142 | ret = nft_register_chain_type(&filter_bridge); |
| 143 | if (ret < 0) |
| 144 | goto err1; |
| 145 | |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 146 | ret = register_pernet_subsys(&nf_tables_bridge_net_ops); |
Gao Feng | 23d0750 | 2016-09-10 10:04:30 +0800 | [diff] [blame] | 147 | if (ret < 0) |
| 148 | goto err2; |
| 149 | |
| 150 | return ret; |
| 151 | |
| 152 | err2: |
| 153 | nft_unregister_chain_type(&filter_bridge); |
| 154 | err1: |
| 155 | nf_unregister_afinfo(&nf_br_afinfo); |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 156 | return ret; |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | static void __exit nf_tables_bridge_exit(void) |
| 160 | { |
Pablo Neira Ayuso | 4641382 | 2013-10-28 17:58:07 +0100 | [diff] [blame] | 161 | unregister_pernet_subsys(&nf_tables_bridge_net_ops); |
| 162 | nft_unregister_chain_type(&filter_bridge); |
Stephane Bryant | ac28634 | 2016-03-26 08:42:10 +0100 | [diff] [blame] | 163 | nf_unregister_afinfo(&nf_br_afinfo); |
Patrick McHardy | 9651851 | 2013-10-14 11:00:02 +0200 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | module_init(nf_tables_bridge_init); |
| 167 | module_exit(nf_tables_bridge_exit); |
| 168 | |
| 169 | MODULE_LICENSE("GPL"); |
| 170 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
| 171 | MODULE_ALIAS_NFT_FAMILY(AF_BRIDGE); |