aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-10-05 21:32:37 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-05 21:32:37 -0400
commit61b37d2f54961b336a47a501e797a05df20c3b30 (patch)
treed2b629be3e30ba71ba86573a72a4036b777e106f /net
parentad9eef52085c5c6047e44705806a1b5b14b7f476 (diff)
parent8da4cc1b10c1aeba090d1d862b17174e4dbd50a4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter/IPVS updates for net-next The following patchset contains another batch with Netfilter/IPVS updates for net-next, they are: 1) Add abstracted ICMP codes to the nf_tables reject expression. We introduce four reasons to reject using ICMP that overlap in IPv4 and IPv6 from the semantic point of view. This should simplify the maintainance of dual stack rule-sets through the inet table. 2) Move nf_send_reset() functions from header files to per-family nf_reject modules, suggested by Patrick McHardy. 3) We have to use IS_ENABLED(CONFIG_BRIDGE_NETFILTER) everywhere in the code now that br_netfilter can be modularized. Convert remaining spots in the network stack code. 4) Use rcu_barrier() in the nf_tables module removal path to ensure that we don't leave object that are still pending to be released via call_rcu (that may likely result in a crash). 5) Remove incomplete arch 32/64 compat from nft_compat. The original (bad) idea was to probe the word size based on the xtables match/target info size, but this assumption is wrong when you have to dump the information back to userspace. 6) Allow to filter from prerouting and postrouting in the nf_tables bridge. In order to emulate the ebtables NAT chains (which are actually simple filter chains with no special semantics), we have support filtering from this hooks too. 7) Add explicit module dependency between xt_physdev and br_netfilter. This provides a way to detect if the user needs br_netfilter from the configuration path. This should reduce the breakage of the br_netfilter modularization. 8) Cleanup coding style in ip_vs.h, from Simon Horman. 9) Fix crash in the recently added nf_tables masq expression. We have to register/unregister the notifiers to clean up the conntrack table entries from the module init/exit path, not from the rule addition / deletion path. From Arturo Borrero. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_netfilter.c5
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c2
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c95
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/ipv4/ip_output.c2
-rw-r--r--net/ipv4/netfilter/Kconfig6
-rw-r--r--net/ipv4/netfilter/Makefile3
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c2
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nf_reject_ipv4.c127
-rw-r--r--net/ipv4/netfilter/nft_masq_ipv4.c34
-rw-r--r--net/ipv4/netfilter/nft_reject_ipv4.c1
-rw-r--r--net/ipv6/netfilter/Kconfig6
-rw-r--r--net/ipv6/netfilter/Makefile3
-rw-r--r--net/ipv6/netfilter/nf_defrag_ipv6_hooks.c2
-rw-r--r--net/ipv6/netfilter/nf_reject_ipv6.c163
-rw-r--r--net/ipv6/netfilter/nft_masq_ipv6.c34
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c4
-rw-r--r--net/netfilter/nf_log_common.c2
-rw-r--r--net/netfilter/nf_queue.c4
-rw-r--r--net/netfilter/nf_tables_api.c1
-rw-r--r--net/netfilter/nfnetlink_log.c8
-rw-r--r--net/netfilter/nfnetlink_queue_core.c12
-rw-r--r--net/netfilter/nft_compat.c116
-rw-r--r--net/netfilter/nft_reject.c37
-rw-r--r--net/netfilter/nft_reject_inet.c94
-rw-r--r--net/netfilter/xt_physdev.c3
27 files changed, 593 insertions, 177 deletions
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 97e43937aaca..fa1270cc5086 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -856,6 +856,11 @@ static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops,
856 return NF_ACCEPT; 856 return NF_ACCEPT;
857} 857}
858 858
859void br_netfilter_enable(void)
860{
861}
862EXPORT_SYMBOL_GPL(br_netfilter_enable);
863
859/* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because 864/* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
860 * br_dev_queue_push_xmit is called afterwards */ 865 * br_dev_queue_push_xmit is called afterwards */
861static struct nf_hook_ops br_nf_ops[] __read_mostly = { 866static struct nf_hook_ops br_nf_ops[] __read_mostly = {
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index 5bcc0d8b31f2..da17a5eab8b4 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -34,9 +34,11 @@ static struct nft_af_info nft_af_bridge __read_mostly = {
34 .owner = THIS_MODULE, 34 .owner = THIS_MODULE,
35 .nops = 1, 35 .nops = 1,
36 .hooks = { 36 .hooks = {
37 [NF_BR_PRE_ROUTING] = nft_do_chain_bridge,
37 [NF_BR_LOCAL_IN] = nft_do_chain_bridge, 38 [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
38 [NF_BR_FORWARD] = nft_do_chain_bridge, 39 [NF_BR_FORWARD] = nft_do_chain_bridge,
39 [NF_BR_LOCAL_OUT] = nft_do_chain_bridge, 40 [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
41 [NF_BR_POST_ROUTING] = nft_do_chain_bridge,
40 }, 42 },
41}; 43};
42 44
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index ee3ffe93e14e..a76479535df2 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -14,21 +14,106 @@
14#include <linux/netfilter/nf_tables.h> 14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nft_reject.h> 16#include <net/netfilter/nft_reject.h>
17#include <net/netfilter/ipv4/nf_reject.h>
18#include <net/netfilter/ipv6/nf_reject.h>
17 19
18static void nft_reject_bridge_eval(const struct nft_expr *expr, 20static void nft_reject_bridge_eval(const struct nft_expr *expr,
19 struct nft_data data[NFT_REG_MAX + 1], 21 struct nft_data data[NFT_REG_MAX + 1],
20 const struct nft_pktinfo *pkt) 22 const struct nft_pktinfo *pkt)
21{ 23{
24 struct nft_reject *priv = nft_expr_priv(expr);
25 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
26
22 switch (eth_hdr(pkt->skb)->h_proto) { 27 switch (eth_hdr(pkt->skb)->h_proto) {
23 case htons(ETH_P_IP): 28 case htons(ETH_P_IP):
24 return nft_reject_ipv4_eval(expr, data, pkt); 29 switch (priv->type) {
30 case NFT_REJECT_ICMP_UNREACH:
31 nf_send_unreach(pkt->skb, priv->icmp_code);
32 break;
33 case NFT_REJECT_TCP_RST:
34 nf_send_reset(pkt->skb, pkt->ops->hooknum);
35 break;
36 case NFT_REJECT_ICMPX_UNREACH:
37 nf_send_unreach(pkt->skb,
38 nft_reject_icmp_code(priv->icmp_code));
39 break;
40 }
41 break;
25 case htons(ETH_P_IPV6): 42 case htons(ETH_P_IPV6):
26 return nft_reject_ipv6_eval(expr, data, pkt); 43 switch (priv->type) {
44 case NFT_REJECT_ICMP_UNREACH:
45 nf_send_unreach6(net, pkt->skb, priv->icmp_code,
46 pkt->ops->hooknum);
47 break;
48 case NFT_REJECT_TCP_RST:
49 nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
50 break;
51 case NFT_REJECT_ICMPX_UNREACH:
52 nf_send_unreach6(net, pkt->skb,
53 nft_reject_icmpv6_code(priv->icmp_code),
54 pkt->ops->hooknum);
55 break;
56 }
57 break;
27 default: 58 default:
28 /* No explicit way to reject this protocol, drop it. */ 59 /* No explicit way to reject this protocol, drop it. */
29 data[NFT_REG_VERDICT].verdict = NF_DROP;
30 break; 60 break;
31 } 61 }
62 data[NFT_REG_VERDICT].verdict = NF_DROP;
63}
64
65static int nft_reject_bridge_init(const struct nft_ctx *ctx,
66 const struct nft_expr *expr,
67 const struct nlattr * const tb[])
68{
69 struct nft_reject *priv = nft_expr_priv(expr);
70 int icmp_code;
71
72 if (tb[NFTA_REJECT_TYPE] == NULL)
73 return -EINVAL;
74
75 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
76 switch (priv->type) {
77 case NFT_REJECT_ICMP_UNREACH:
78 case NFT_REJECT_ICMPX_UNREACH:
79 if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
80 return -EINVAL;
81
82 icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
83 if (priv->type == NFT_REJECT_ICMPX_UNREACH &&
84 icmp_code > NFT_REJECT_ICMPX_MAX)
85 return -EINVAL;
86
87 priv->icmp_code = icmp_code;
88 break;
89 case NFT_REJECT_TCP_RST:
90 break;
91 default:
92 return -EINVAL;
93 }
94 return 0;
95}
96
97static int nft_reject_bridge_dump(struct sk_buff *skb,
98 const struct nft_expr *expr)
99{
100 const struct nft_reject *priv = nft_expr_priv(expr);
101
102 if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
103 goto nla_put_failure;
104
105 switch (priv->type) {
106 case NFT_REJECT_ICMP_UNREACH:
107 case NFT_REJECT_ICMPX_UNREACH:
108 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
109 goto nla_put_failure;
110 break;
111 }
112
113 return 0;
114
115nla_put_failure:
116 return -1;
32} 117}
33 118
34static struct nft_expr_type nft_reject_bridge_type; 119static struct nft_expr_type nft_reject_bridge_type;
@@ -36,8 +121,8 @@ static const struct nft_expr_ops nft_reject_bridge_ops = {
36 .type = &nft_reject_bridge_type, 121 .type = &nft_reject_bridge_type,
37 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), 122 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
38 .eval = nft_reject_bridge_eval, 123 .eval = nft_reject_bridge_eval,
39 .init = nft_reject_init, 124 .init = nft_reject_bridge_init,
40 .dump = nft_reject_dump, 125 .dump = nft_reject_bridge_dump,
41}; 126};
42 127
43static struct nft_expr_type nft_reject_bridge_type __read_mostly = { 128static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 28916e47f959..9a423e2c5766 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -572,7 +572,7 @@ static void skb_release_head_state(struct sk_buff *skb)
572#if IS_ENABLED(CONFIG_NF_CONNTRACK) 572#if IS_ENABLED(CONFIG_NF_CONNTRACK)
573 nf_conntrack_put(skb->nfct); 573 nf_conntrack_put(skb->nfct);
574#endif 574#endif
575#ifdef CONFIG_BRIDGE_NETFILTER 575#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
576 nf_bridge_put(skb->nf_bridge); 576 nf_bridge_put(skb->nf_bridge);
577#endif 577#endif
578/* XXX: IS this still necessary? - JHS */ 578/* XXX: IS this still necessary? - JHS */
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index c8fa62476461..e35b71289156 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -516,7 +516,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
516 516
517 hlen = iph->ihl * 4; 517 hlen = iph->ihl * 4;
518 mtu = mtu - hlen; /* Size of data space */ 518 mtu = mtu - hlen; /* Size of data space */
519#ifdef CONFIG_BRIDGE_NETFILTER 519#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
520 if (skb->nf_bridge) 520 if (skb->nf_bridge)
521 mtu -= nf_bridge_mtu_reduction(skb); 521 mtu -= nf_bridge_mtu_reduction(skb);
522#endif 522#endif
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 345242a79db6..4c019d5c3f57 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -61,8 +61,13 @@ config NFT_CHAIN_ROUTE_IPV4
61 fields such as the source, destination, type of service and 61 fields such as the source, destination, type of service and
62 the packet mark. 62 the packet mark.
63 63
64config NF_REJECT_IPV4
65 tristate "IPv4 packet rejection"
66 default m if NETFILTER_ADVANCED=n
67
64config NFT_REJECT_IPV4 68config NFT_REJECT_IPV4
65 depends on NF_TABLES_IPV4 69 depends on NF_TABLES_IPV4
70 select NF_REJECT_IPV4
66 default NFT_REJECT 71 default NFT_REJECT
67 tristate 72 tristate
68 73
@@ -208,6 +213,7 @@ config IP_NF_FILTER
208config IP_NF_TARGET_REJECT 213config IP_NF_TARGET_REJECT
209 tristate "REJECT target support" 214 tristate "REJECT target support"
210 depends on IP_NF_FILTER 215 depends on IP_NF_FILTER
216 select NF_REJECT_IPV4
211 default m if NETFILTER_ADVANCED=n 217 default m if NETFILTER_ADVANCED=n
212 help 218 help
213 The REJECT target allows a filtering rule to specify that an ICMP 219 The REJECT target allows a filtering rule to specify that an ICMP
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 14488cc5fd2c..f4cef5af0969 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -23,6 +23,9 @@ obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
23obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o 23obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o
24obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o 24obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o
25 25
26# reject
27obj-$(CONFIG_NF_REJECT_IPV4) += nf_reject_ipv4.o
28
26# NAT helpers (nf_conntrack) 29# NAT helpers (nf_conntrack)
27obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o 30obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
28obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 31obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 5b6e0df4ccff..8f48f5517e33 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -20,7 +20,7 @@
20#include <linux/netfilter/x_tables.h> 20#include <linux/netfilter/x_tables.h>
21#include <linux/netfilter_ipv4/ip_tables.h> 21#include <linux/netfilter_ipv4/ip_tables.h>
22#include <linux/netfilter_ipv4/ipt_REJECT.h> 22#include <linux/netfilter_ipv4/ipt_REJECT.h>
23#ifdef CONFIG_BRIDGE_NETFILTER 23#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
24#include <linux/netfilter_bridge.h> 24#include <linux/netfilter_bridge.h>
25#endif 25#endif
26 26
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 76bd1aef257f..7e5ca6f2d0cd 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -50,7 +50,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
50 zone = nf_ct_zone((struct nf_conn *)skb->nfct); 50 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
51#endif 51#endif
52 52
53#ifdef CONFIG_BRIDGE_NETFILTER 53#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
54 if (skb->nf_bridge && 54 if (skb->nf_bridge &&
55 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) 55 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
56 return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone; 56 return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
new file mode 100644
index 000000000000..b023b4eb1a96
--- /dev/null
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -0,0 +1,127 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <net/ip.h>
10#include <net/tcp.h>
11#include <net/route.h>
12#include <net/dst.h>
13#include <linux/netfilter_ipv4.h>
14
15/* Send RST reply */
16void nf_send_reset(struct sk_buff *oldskb, int hook)
17{
18 struct sk_buff *nskb;
19 const struct iphdr *oiph;
20 struct iphdr *niph;
21 const struct tcphdr *oth;
22 struct tcphdr _otcph, *tcph;
23
24 /* IP header checks: fragment. */
25 if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
26 return;
27
28 oth = skb_header_pointer(oldskb, ip_hdrlen(oldskb),
29 sizeof(_otcph), &_otcph);
30 if (oth == NULL)
31 return;
32
33 /* No RST for RST. */
34 if (oth->rst)
35 return;
36
37 if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
38 return;
39
40 /* Check checksum */
41 if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
42 return;
43 oiph = ip_hdr(oldskb);
44
45 nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
46 LL_MAX_HEADER, GFP_ATOMIC);
47 if (!nskb)
48 return;
49
50 skb_reserve(nskb, LL_MAX_HEADER);
51
52 skb_reset_network_header(nskb);
53 niph = (struct iphdr *)skb_put(nskb, sizeof(struct iphdr));
54 niph->version = 4;
55 niph->ihl = sizeof(struct iphdr) / 4;
56 niph->tos = 0;
57 niph->id = 0;
58 niph->frag_off = htons(IP_DF);
59 niph->protocol = IPPROTO_TCP;
60 niph->check = 0;
61 niph->saddr = oiph->daddr;
62 niph->daddr = oiph->saddr;
63
64 skb_reset_transport_header(nskb);
65 tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
66 memset(tcph, 0, sizeof(*tcph));
67 tcph->source = oth->dest;
68 tcph->dest = oth->source;
69 tcph->doff = sizeof(struct tcphdr) / 4;
70
71 if (oth->ack)
72 tcph->seq = oth->ack_seq;
73 else {
74 tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin +
75 oldskb->len - ip_hdrlen(oldskb) -
76 (oth->doff << 2));
77 tcph->ack = 1;
78 }
79
80 tcph->rst = 1;
81 tcph->check = ~tcp_v4_check(sizeof(struct tcphdr), niph->saddr,
82 niph->daddr, 0);
83 nskb->ip_summed = CHECKSUM_PARTIAL;
84 nskb->csum_start = (unsigned char *)tcph - nskb->head;
85 nskb->csum_offset = offsetof(struct tcphdr, check);
86
87 /* ip_route_me_harder expects skb->dst to be set */
88 skb_dst_set_noref(nskb, skb_dst(oldskb));
89
90 nskb->protocol = htons(ETH_P_IP);
91 if (ip_route_me_harder(nskb, RTN_UNSPEC))
92 goto free_nskb;
93
94 niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
95
96 /* "Never happens" */
97 if (nskb->len > dst_mtu(skb_dst(nskb)))
98 goto free_nskb;
99
100 nf_ct_attach(nskb, oldskb);
101
102#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
103 /* If we use ip_local_out for bridged traffic, the MAC source on
104 * the RST will be ours, instead of the destination's. This confuses
105 * some routers/firewalls, and they drop the packet. So we need to
106 * build the eth header using the original destination's MAC as the
107 * source, and send the RST packet directly.
108 */
109 if (oldskb->nf_bridge) {
110 struct ethhdr *oeth = eth_hdr(oldskb);
111 nskb->dev = oldskb->nf_bridge->physindev;
112 niph->tot_len = htons(nskb->len);
113 ip_send_check(niph);
114 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
115 oeth->h_source, oeth->h_dest, nskb->len) < 0)
116 goto free_nskb;
117 dev_queue_xmit(nskb);
118 } else
119#endif
120 ip_local_out(nskb);
121
122 return;
123
124 free_nskb:
125 kfree_skb(nskb);
126}
127EXPORT_SYMBOL_GPL(nf_send_reset);
diff --git a/net/ipv4/netfilter/nft_masq_ipv4.c b/net/ipv4/netfilter/nft_masq_ipv4.c
index 6ea1d207b6a5..1c636d6b5b50 100644
--- a/net/ipv4/netfilter/nft_masq_ipv4.c
+++ b/net/ipv4/netfilter/nft_masq_ipv4.c
@@ -32,33 +32,12 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
32 data[NFT_REG_VERDICT].verdict = verdict; 32 data[NFT_REG_VERDICT].verdict = verdict;
33} 33}
34 34
35static int nft_masq_ipv4_init(const struct nft_ctx *ctx,
36 const struct nft_expr *expr,
37 const struct nlattr * const tb[])
38{
39 int err;
40
41 err = nft_masq_init(ctx, expr, tb);
42 if (err < 0)
43 return err;
44
45 nf_nat_masquerade_ipv4_register_notifier();
46 return 0;
47}
48
49static void nft_masq_ipv4_destroy(const struct nft_ctx *ctx,
50 const struct nft_expr *expr)
51{
52 nf_nat_masquerade_ipv4_unregister_notifier();
53}
54
55static struct nft_expr_type nft_masq_ipv4_type; 35static struct nft_expr_type nft_masq_ipv4_type;
56static const struct nft_expr_ops nft_masq_ipv4_ops = { 36static const struct nft_expr_ops nft_masq_ipv4_ops = {
57 .type = &nft_masq_ipv4_type, 37 .type = &nft_masq_ipv4_type,
58 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 38 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
59 .eval = nft_masq_ipv4_eval, 39 .eval = nft_masq_ipv4_eval,
60 .init = nft_masq_ipv4_init, 40 .init = nft_masq_init,
61 .destroy = nft_masq_ipv4_destroy,
62 .dump = nft_masq_dump, 41 .dump = nft_masq_dump,
63}; 42};
64 43
@@ -73,12 +52,21 @@ static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
73 52
74static int __init nft_masq_ipv4_module_init(void) 53static int __init nft_masq_ipv4_module_init(void)
75{ 54{
76 return nft_register_expr(&nft_masq_ipv4_type); 55 int ret;
56
57 ret = nft_register_expr(&nft_masq_ipv4_type);
58 if (ret < 0)
59 return ret;
60
61 nf_nat_masquerade_ipv4_register_notifier();
62
63 return ret;
77} 64}
78 65
79static void __exit nft_masq_ipv4_module_exit(void) 66static void __exit nft_masq_ipv4_module_exit(void)
80{ 67{
81 nft_unregister_expr(&nft_masq_ipv4_type); 68 nft_unregister_expr(&nft_masq_ipv4_type);
69 nf_nat_masquerade_ipv4_unregister_notifier();
82} 70}
83 71
84module_init(nft_masq_ipv4_module_init); 72module_init(nft_masq_ipv4_module_init);
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
index e79718a382f2..ed33299c56d1 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -16,7 +16,6 @@
16#include <linux/netfilter.h> 16#include <linux/netfilter.h>
17#include <linux/netfilter/nf_tables.h> 17#include <linux/netfilter/nf_tables.h>
18#include <net/netfilter/nf_tables.h> 18#include <net/netfilter/nf_tables.h>
19#include <net/icmp.h>
20#include <net/netfilter/ipv4/nf_reject.h> 19#include <net/netfilter/ipv4/nf_reject.h>
21#include <net/netfilter/nft_reject.h> 20#include <net/netfilter/nft_reject.h>
22 21
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index bb1a40db7be1..6af874fc187f 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,8 +40,13 @@ config NFT_CHAIN_ROUTE_IPV6
40 fields such as the source, destination, flowlabel, hop-limit and 40 fields such as the source, destination, flowlabel, hop-limit and
41 the packet mark. 41 the packet mark.
42 42
43config NF_REJECT_IPV6
44 tristate "IPv6 packet rejection"
45 default m if NETFILTER_ADVANCED=n
46
43config NFT_REJECT_IPV6 47config NFT_REJECT_IPV6
44 depends on NF_TABLES_IPV6 48 depends on NF_TABLES_IPV6
49 select NF_REJECT_IPV6
45 default NFT_REJECT 50 default NFT_REJECT
46 tristate 51 tristate
47 52
@@ -208,6 +213,7 @@ config IP6_NF_FILTER
208config IP6_NF_TARGET_REJECT 213config IP6_NF_TARGET_REJECT
209 tristate "REJECT target support" 214 tristate "REJECT target support"
210 depends on IP6_NF_FILTER 215 depends on IP6_NF_FILTER
216 select NF_REJECT_IPV6
211 default m if NETFILTER_ADVANCED=n 217 default m if NETFILTER_ADVANCED=n
212 help 218 help
213 The REJECT target allows a filtering rule to specify that an ICMPv6 219 The REJECT target allows a filtering rule to specify that an ICMPv6
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index 0f7e5b3f328d..fbb25f01143c 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -27,6 +27,9 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
27# logging 27# logging
28obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o 28obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o
29 29
30# reject
31obj-$(CONFIG_NF_REJECT_IPV6) += nf_reject_ipv6.o
32
30# nf_tables 33# nf_tables
31obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o 34obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
32obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o 35obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
index 7b9a748c6bac..e70382e4dfb5 100644
--- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
+++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
@@ -40,7 +40,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
40 zone = nf_ct_zone((struct nf_conn *)skb->nfct); 40 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
41#endif 41#endif
42 42
43#ifdef CONFIG_BRIDGE_NETFILTER 43#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
44 if (skb->nf_bridge && 44 if (skb->nf_bridge &&
45 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) 45 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
46 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone; 46 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
new file mode 100644
index 000000000000..5f5f0438d74d
--- /dev/null
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -0,0 +1,163 @@
1/* (C) 1999-2001 Paul `Rusty' Russell
2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <net/ipv6.h>
9#include <net/ip6_route.h>
10#include <net/ip6_fib.h>
11#include <net/ip6_checksum.h>
12#include <linux/netfilter_ipv6.h>
13
14void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
15{
16 struct sk_buff *nskb;
17 struct tcphdr otcph, *tcph;
18 unsigned int otcplen, hh_len;
19 int tcphoff, needs_ack;
20 const struct ipv6hdr *oip6h = ipv6_hdr(oldskb);
21 struct ipv6hdr *ip6h;
22#define DEFAULT_TOS_VALUE 0x0U
23 const __u8 tclass = DEFAULT_TOS_VALUE;
24 struct dst_entry *dst = NULL;
25 u8 proto;
26 __be16 frag_off;
27 struct flowi6 fl6;
28
29 if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) ||
30 (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) {
31 pr_debug("addr is not unicast.\n");
32 return;
33 }
34
35 proto = oip6h->nexthdr;
36 tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off);
37
38 if ((tcphoff < 0) || (tcphoff > oldskb->len)) {
39 pr_debug("Cannot get TCP header.\n");
40 return;
41 }
42
43 otcplen = oldskb->len - tcphoff;
44
45 /* IP header checks: fragment, too short. */
46 if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) {
47 pr_debug("proto(%d) != IPPROTO_TCP, "
48 "or too short. otcplen = %d\n",
49 proto, otcplen);
50 return;
51 }
52
53 if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr)))
54 BUG();
55
56 /* No RST for RST. */
57 if (otcph.rst) {
58 pr_debug("RST is set\n");
59 return;
60 }
61
62 /* Check checksum. */
63 if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
64 pr_debug("TCP checksum is invalid\n");
65 return;
66 }
67
68 memset(&fl6, 0, sizeof(fl6));
69 fl6.flowi6_proto = IPPROTO_TCP;
70 fl6.saddr = oip6h->daddr;
71 fl6.daddr = oip6h->saddr;
72 fl6.fl6_sport = otcph.dest;
73 fl6.fl6_dport = otcph.source;
74 security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
75 dst = ip6_route_output(net, NULL, &fl6);
76 if (dst == NULL || dst->error) {
77 dst_release(dst);
78 return;
79 }
80 dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0);
81 if (IS_ERR(dst))
82 return;
83
84 hh_len = (dst->dev->hard_header_len + 15)&~15;
85 nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr)
86 + sizeof(struct tcphdr) + dst->trailer_len,
87 GFP_ATOMIC);
88
89 if (!nskb) {
90 net_dbg_ratelimited("cannot alloc skb\n");
91 dst_release(dst);
92 return;
93 }
94
95 skb_dst_set(nskb, dst);
96
97 skb_reserve(nskb, hh_len + dst->header_len);
98
99 skb_put(nskb, sizeof(struct ipv6hdr));
100 skb_reset_network_header(nskb);
101 ip6h = ipv6_hdr(nskb);
102 ip6_flow_hdr(ip6h, tclass, 0);
103 ip6h->hop_limit = ip6_dst_hoplimit(dst);
104 ip6h->nexthdr = IPPROTO_TCP;
105 ip6h->saddr = oip6h->daddr;
106 ip6h->daddr = oip6h->saddr;
107
108 skb_reset_transport_header(nskb);
109 tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr));
110 /* Truncate to length (no data) */
111 tcph->doff = sizeof(struct tcphdr)/4;
112 tcph->source = otcph.dest;
113 tcph->dest = otcph.source;
114
115 if (otcph.ack) {
116 needs_ack = 0;
117 tcph->seq = otcph.ack_seq;
118 tcph->ack_seq = 0;
119 } else {
120 needs_ack = 1;
121 tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin
122 + otcplen - (otcph.doff<<2));
123 tcph->seq = 0;
124 }
125
126 /* Reset flags */
127 ((u_int8_t *)tcph)[13] = 0;
128 tcph->rst = 1;
129 tcph->ack = needs_ack;
130 tcph->window = 0;
131 tcph->urg_ptr = 0;
132 tcph->check = 0;
133
134 /* Adjust TCP checksum */
135 tcph->check = csum_ipv6_magic(&ipv6_hdr(nskb)->saddr,
136 &ipv6_hdr(nskb)->daddr,
137 sizeof(struct tcphdr), IPPROTO_TCP,
138 csum_partial(tcph,
139 sizeof(struct tcphdr), 0));
140
141 nf_ct_attach(nskb, oldskb);
142
143#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
144 /* If we use ip6_local_out for bridged traffic, the MAC source on
145 * the RST will be ours, instead of the destination's. This confuses
146 * some routers/firewalls, and they drop the packet. So we need to
147 * build the eth header using the original destination's MAC as the
148 * source, and send the RST packet directly.
149 */
150 if (oldskb->nf_bridge) {
151 struct ethhdr *oeth = eth_hdr(oldskb);
152 nskb->dev = oldskb->nf_bridge->physindev;
153 nskb->protocol = htons(ETH_P_IPV6);
154 ip6h->payload_len = htons(sizeof(struct tcphdr));
155 if (dev_hard_header(nskb, nskb->dev, ntohs(nskb->protocol),
156 oeth->h_source, oeth->h_dest, nskb->len) < 0)
157 return;
158 dev_queue_xmit(nskb);
159 } else
160#endif
161 ip6_local_out(nskb);
162}
163EXPORT_SYMBOL_GPL(nf_send_reset6);
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c
index 4e51334ef6b7..556262f40761 100644
--- a/net/ipv6/netfilter/nft_masq_ipv6.c
+++ b/net/ipv6/netfilter/nft_masq_ipv6.c
@@ -32,33 +32,12 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr,
32 data[NFT_REG_VERDICT].verdict = verdict; 32 data[NFT_REG_VERDICT].verdict = verdict;
33} 33}
34 34
35static int nft_masq_ipv6_init(const struct nft_ctx *ctx,
36 const struct nft_expr *expr,
37 const struct nlattr * const tb[])
38{
39 int err;
40
41 err = nft_masq_init(ctx, expr, tb);
42 if (err < 0)
43 return err;
44
45 nf_nat_masquerade_ipv6_register_notifier();
46 return 0;
47}
48
49static void nft_masq_ipv6_destroy(const struct nft_ctx *ctx,
50 const struct nft_expr *expr)
51{
52 nf_nat_masquerade_ipv6_unregister_notifier();
53}
54
55static struct nft_expr_type nft_masq_ipv6_type; 35static struct nft_expr_type nft_masq_ipv6_type;
56static const struct nft_expr_ops nft_masq_ipv6_ops = { 36static const struct nft_expr_ops nft_masq_ipv6_ops = {
57 .type = &nft_masq_ipv6_type, 37 .type = &nft_masq_ipv6_type,
58 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)), 38 .size = NFT_EXPR_SIZE(sizeof(struct nft_masq)),
59 .eval = nft_masq_ipv6_eval, 39 .eval = nft_masq_ipv6_eval,
60 .init = nft_masq_ipv6_init, 40 .init = nft_masq_init,
61 .destroy = nft_masq_ipv6_destroy,
62 .dump = nft_masq_dump, 41 .dump = nft_masq_dump,
63}; 42};
64 43
@@ -73,12 +52,21 @@ static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
73 52
74static int __init nft_masq_ipv6_module_init(void) 53static int __init nft_masq_ipv6_module_init(void)
75{ 54{
76 return nft_register_expr(&nft_masq_ipv6_type); 55 int ret;
56
57 ret = nft_register_expr(&nft_masq_ipv6_type);
58 if (ret < 0)
59 return ret;
60
61 nf_nat_masquerade_ipv6_register_notifier();
62
63 return ret;
77} 64}
78 65
79static void __exit nft_masq_ipv6_module_exit(void) 66static void __exit nft_masq_ipv6_module_exit(void)
80{ 67{
81 nft_unregister_expr(&nft_masq_ipv6_type); 68 nft_unregister_expr(&nft_masq_ipv6_type);
69 nf_nat_masquerade_ipv6_unregister_notifier();
82} 70}
83 71
84module_init(nft_masq_ipv6_module_init); 72module_init(nft_masq_ipv6_module_init);
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 03cdb69ac9bf..35dd35873442 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -237,7 +237,7 @@ hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
237#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC) 237#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
238 238
239 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 239 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
240#ifdef CONFIG_BRIDGE_NETFILTER 240#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
241 const struct nf_bridge_info *nf_bridge = skb->nf_bridge; 241 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
242 242
243 if (!nf_bridge) 243 if (!nf_bridge)
@@ -474,7 +474,7 @@ hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
474 ip6_netmask(&e.ip, e.cidr); 474 ip6_netmask(&e.ip, e.cidr);
475 475
476 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) { 476 if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
477#ifdef CONFIG_BRIDGE_NETFILTER 477#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
478 const struct nf_bridge_info *nf_bridge = skb->nf_bridge; 478 const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
479 479
480 if (!nf_bridge) 480 if (!nf_bridge)
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c
index eeb8ef4ff1a3..a2233e77cf39 100644
--- a/net/netfilter/nf_log_common.c
+++ b/net/netfilter/nf_log_common.c
@@ -158,7 +158,7 @@ nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
158 '0' + loginfo->u.log.level, prefix, 158 '0' + loginfo->u.log.level, prefix,
159 in ? in->name : "", 159 in ? in->name : "",
160 out ? out->name : ""); 160 out ? out->name : "");
161#ifdef CONFIG_BRIDGE_NETFILTER 161#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
162 if (skb->nf_bridge) { 162 if (skb->nf_bridge) {
163 const struct net_device *physindev; 163 const struct net_device *physindev;
164 const struct net_device *physoutdev; 164 const struct net_device *physoutdev;
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 5d24b1fdb593..4c8b68e5fa16 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -52,7 +52,7 @@ void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
52 dev_put(entry->indev); 52 dev_put(entry->indev);
53 if (entry->outdev) 53 if (entry->outdev)
54 dev_put(entry->outdev); 54 dev_put(entry->outdev);
55#ifdef CONFIG_BRIDGE_NETFILTER 55#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
56 if (entry->skb->nf_bridge) { 56 if (entry->skb->nf_bridge) {
57 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; 57 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
58 58
@@ -77,7 +77,7 @@ bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
77 dev_hold(entry->indev); 77 dev_hold(entry->indev);
78 if (entry->outdev) 78 if (entry->outdev)
79 dev_hold(entry->outdev); 79 dev_hold(entry->outdev);
80#ifdef CONFIG_BRIDGE_NETFILTER 80#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
81 if (entry->skb->nf_bridge) { 81 if (entry->skb->nf_bridge) {
82 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge; 82 struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
83 struct net_device *physdev; 83 struct net_device *physdev;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 19e79f0d9ad2..556a0dfa4abc 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -4163,6 +4163,7 @@ static void __exit nf_tables_module_exit(void)
4163{ 4163{
4164 unregister_pernet_subsys(&nf_tables_net_ops); 4164 unregister_pernet_subsys(&nf_tables_net_ops);
4165 nfnetlink_subsys_unregister(&nf_tables_subsys); 4165 nfnetlink_subsys_unregister(&nf_tables_subsys);
4166 rcu_barrier();
4166 nf_tables_core_module_exit(); 4167 nf_tables_core_module_exit();
4167 kfree(info); 4168 kfree(info);
4168} 4169}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index a11c5ff2f720..b1e3a0579416 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -36,7 +36,7 @@
36 36
37#include <linux/atomic.h> 37#include <linux/atomic.h>
38 38
39#ifdef CONFIG_BRIDGE_NETFILTER 39#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
40#include "../bridge/br_private.h" 40#include "../bridge/br_private.h"
41#endif 41#endif
42 42
@@ -429,7 +429,7 @@ __build_packet_message(struct nfnl_log_net *log,
429 goto nla_put_failure; 429 goto nla_put_failure;
430 430
431 if (indev) { 431 if (indev) {
432#ifndef CONFIG_BRIDGE_NETFILTER 432#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
433 if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, 433 if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
434 htonl(indev->ifindex))) 434 htonl(indev->ifindex)))
435 goto nla_put_failure; 435 goto nla_put_failure;
@@ -460,7 +460,7 @@ __build_packet_message(struct nfnl_log_net *log,
460 } 460 }
461 461
462 if (outdev) { 462 if (outdev) {
463#ifndef CONFIG_BRIDGE_NETFILTER 463#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
464 if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, 464 if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
465 htonl(outdev->ifindex))) 465 htonl(outdev->ifindex)))
466 goto nla_put_failure; 466 goto nla_put_failure;
@@ -640,7 +640,7 @@ nfulnl_log_packet(struct net *net,
640 + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) 640 + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
641 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 641 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
642 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 642 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
643#ifdef CONFIG_BRIDGE_NETFILTER 643#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
644 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 644 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
645 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 645 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
646#endif 646#endif
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 108120f216b1..a82077d9f59b 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -36,7 +36,7 @@
36 36
37#include <linux/atomic.h> 37#include <linux/atomic.h>
38 38
39#ifdef CONFIG_BRIDGE_NETFILTER 39#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
40#include "../bridge/br_private.h" 40#include "../bridge/br_private.h"
41#endif 41#endif
42 42
@@ -302,7 +302,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
302 + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) 302 + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
303 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 303 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
304 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 304 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
305#ifdef CONFIG_BRIDGE_NETFILTER 305#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
306 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 306 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
307 + nla_total_size(sizeof(u_int32_t)) /* ifindex */ 307 + nla_total_size(sizeof(u_int32_t)) /* ifindex */
308#endif 308#endif
@@ -380,7 +380,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
380 380
381 indev = entry->indev; 381 indev = entry->indev;
382 if (indev) { 382 if (indev) {
383#ifndef CONFIG_BRIDGE_NETFILTER 383#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
384 if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex))) 384 if (nla_put_be32(skb, NFQA_IFINDEX_INDEV, htonl(indev->ifindex)))
385 goto nla_put_failure; 385 goto nla_put_failure;
386#else 386#else
@@ -410,7 +410,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
410 } 410 }
411 411
412 if (outdev) { 412 if (outdev) {
413#ifndef CONFIG_BRIDGE_NETFILTER 413#if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
414 if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) 414 if (nla_put_be32(skb, NFQA_IFINDEX_OUTDEV, htonl(outdev->ifindex)))
415 goto nla_put_failure; 415 goto nla_put_failure;
416#else 416#else
@@ -569,7 +569,7 @@ nf_queue_entry_dup(struct nf_queue_entry *e)
569 return NULL; 569 return NULL;
570} 570}
571 571
572#ifdef CONFIG_BRIDGE_NETFILTER 572#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
573/* When called from bridge netfilter, skb->data must point to MAC header 573/* When called from bridge netfilter, skb->data must point to MAC header
574 * before calling skb_gso_segment(). Else, original MAC header is lost 574 * before calling skb_gso_segment(). Else, original MAC header is lost
575 * and segmented skbs will be sent to wrong destination. 575 * and segmented skbs will be sent to wrong destination.
@@ -763,7 +763,7 @@ dev_cmp(struct nf_queue_entry *entry, unsigned long ifindex)
763 if (entry->outdev) 763 if (entry->outdev)
764 if (entry->outdev->ifindex == ifindex) 764 if (entry->outdev->ifindex == ifindex)
765 return 1; 765 return 1;
766#ifdef CONFIG_BRIDGE_NETFILTER 766#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
767 if (entry->skb->nf_bridge) { 767 if (entry->skb->nf_bridge) {
768 if (entry->skb->nf_bridge->physindev && 768 if (entry->skb->nf_bridge->physindev &&
769 entry->skb->nf_bridge->physindev->ifindex == ifindex) 769 entry->skb->nf_bridge->physindev->ifindex == ifindex)
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 1840989092ed..7e2683c8a44a 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -101,26 +101,12 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
101 101
102static void target_compat_from_user(struct xt_target *t, void *in, void *out) 102static void target_compat_from_user(struct xt_target *t, void *in, void *out)
103{ 103{
104#ifdef CONFIG_COMPAT 104 int pad;
105 if (t->compat_from_user) {
106 int pad;
107
108 t->compat_from_user(out, in);
109 pad = XT_ALIGN(t->targetsize) - t->targetsize;
110 if (pad > 0)
111 memset(out + t->targetsize, 0, pad);
112 } else
113#endif
114 memcpy(out, in, XT_ALIGN(t->targetsize));
115}
116 105
117static inline int nft_compat_target_offset(struct xt_target *target) 106 memcpy(out, in, t->targetsize);
118{ 107 pad = XT_ALIGN(t->targetsize) - t->targetsize;
119#ifdef CONFIG_COMPAT 108 if (pad > 0)
120 return xt_compat_target_offset(target); 109 memset(out + t->targetsize, 0, pad);
121#else
122 return 0;
123#endif
124} 110}
125 111
126static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = { 112static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = {
@@ -208,34 +194,6 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
208 module_put(target->me); 194 module_put(target->me);
209} 195}
210 196
211static int
212target_dump_info(struct sk_buff *skb, const struct xt_target *t, const void *in)
213{
214 int ret;
215
216#ifdef CONFIG_COMPAT
217 if (t->compat_to_user) {
218 mm_segment_t old_fs;
219 void *out;
220
221 out = kmalloc(XT_ALIGN(t->targetsize), GFP_ATOMIC);
222 if (out == NULL)
223 return -ENOMEM;
224
225 /* We want to reuse existing compat_to_user */
226 old_fs = get_fs();
227 set_fs(KERNEL_DS);
228 t->compat_to_user(out, in);
229 set_fs(old_fs);
230 ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), out);
231 kfree(out);
232 } else
233#endif
234 ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), in);
235
236 return ret;
237}
238
239static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr) 197static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
240{ 198{
241 const struct xt_target *target = expr->ops->data; 199 const struct xt_target *target = expr->ops->data;
@@ -243,7 +201,7 @@ static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
243 201
244 if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) || 202 if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) ||
245 nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) || 203 nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) ||
246 target_dump_info(skb, target, info)) 204 nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info))
247 goto nla_put_failure; 205 goto nla_put_failure;
248 206
249 return 0; 207 return 0;
@@ -341,17 +299,12 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
341 299
342static void match_compat_from_user(struct xt_match *m, void *in, void *out) 300static void match_compat_from_user(struct xt_match *m, void *in, void *out)
343{ 301{
344#ifdef CONFIG_COMPAT 302 int pad;
345 if (m->compat_from_user) { 303
346 int pad; 304 memcpy(out, in, m->matchsize);
347 305 pad = XT_ALIGN(m->matchsize) - m->matchsize;
348 m->compat_from_user(out, in); 306 if (pad > 0)
349 pad = XT_ALIGN(m->matchsize) - m->matchsize; 307 memset(out + m->matchsize, 0, pad);
350 if (pad > 0)
351 memset(out + m->matchsize, 0, pad);
352 } else
353#endif
354 memcpy(out, in, XT_ALIGN(m->matchsize));
355} 308}
356 309
357static int 310static int
@@ -404,43 +357,6 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
404 module_put(match->me); 357 module_put(match->me);
405} 358}
406 359
407static int
408match_dump_info(struct sk_buff *skb, const struct xt_match *m, const void *in)
409{
410 int ret;
411
412#ifdef CONFIG_COMPAT
413 if (m->compat_to_user) {
414 mm_segment_t old_fs;
415 void *out;
416
417 out = kmalloc(XT_ALIGN(m->matchsize), GFP_ATOMIC);
418 if (out == NULL)
419 return -ENOMEM;
420
421 /* We want to reuse existing compat_to_user */
422 old_fs = get_fs();
423 set_fs(KERNEL_DS);
424 m->compat_to_user(out, in);
425 set_fs(old_fs);
426 ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), out);
427 kfree(out);
428 } else
429#endif
430 ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), in);
431
432 return ret;
433}
434
435static inline int nft_compat_match_offset(struct xt_match *match)
436{
437#ifdef CONFIG_COMPAT
438 return xt_compat_match_offset(match);
439#else
440 return 0;
441#endif
442}
443
444static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr) 360static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
445{ 361{
446 void *info = nft_expr_priv(expr); 362 void *info = nft_expr_priv(expr);
@@ -448,7 +364,7 @@ static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
448 364
449 if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) || 365 if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
450 nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) || 366 nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) ||
451 match_dump_info(skb, match, info)) 367 nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info))
452 goto nla_put_failure; 368 goto nla_put_failure;
453 369
454 return 0; 370 return 0;
@@ -643,8 +559,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
643 return ERR_PTR(-ENOMEM); 559 return ERR_PTR(-ENOMEM);
644 560
645 nft_match->ops.type = &nft_match_type; 561 nft_match->ops.type = &nft_match_type;
646 nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize) + 562 nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
647 nft_compat_match_offset(match));
648 nft_match->ops.eval = nft_match_eval; 563 nft_match->ops.eval = nft_match_eval;
649 nft_match->ops.init = nft_match_init; 564 nft_match->ops.init = nft_match_init;
650 nft_match->ops.destroy = nft_match_destroy; 565 nft_match->ops.destroy = nft_match_destroy;
@@ -714,8 +629,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
714 return ERR_PTR(-ENOMEM); 629 return ERR_PTR(-ENOMEM);
715 630
716 nft_target->ops.type = &nft_target_type; 631 nft_target->ops.type = &nft_target_type;
717 nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize) + 632 nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
718 nft_compat_target_offset(target));
719 nft_target->ops.eval = nft_target_eval; 633 nft_target->ops.eval = nft_target_eval;
720 nft_target->ops.init = nft_target_init; 634 nft_target->ops.init = nft_target_init;
721 nft_target->ops.destroy = nft_target_destroy; 635 nft_target->ops.destroy = nft_target_destroy;
diff --git a/net/netfilter/nft_reject.c b/net/netfilter/nft_reject.c
index f3448c296446..ec8a456092a7 100644
--- a/net/netfilter/nft_reject.c
+++ b/net/netfilter/nft_reject.c
@@ -17,6 +17,8 @@
17#include <linux/netfilter/nf_tables.h> 17#include <linux/netfilter/nf_tables.h>
18#include <net/netfilter/nf_tables.h> 18#include <net/netfilter/nf_tables.h>
19#include <net/netfilter/nft_reject.h> 19#include <net/netfilter/nft_reject.h>
20#include <linux/icmp.h>
21#include <linux/icmpv6.h>
20 22
21const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = { 23const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
22 [NFTA_REJECT_TYPE] = { .type = NLA_U32 }, 24 [NFTA_REJECT_TYPE] = { .type = NLA_U32 },
@@ -70,5 +72,40 @@ nla_put_failure:
70} 72}
71EXPORT_SYMBOL_GPL(nft_reject_dump); 73EXPORT_SYMBOL_GPL(nft_reject_dump);
72 74
75static u8 icmp_code_v4[NFT_REJECT_ICMPX_MAX] = {
76 [NFT_REJECT_ICMPX_NO_ROUTE] = ICMP_NET_UNREACH,
77 [NFT_REJECT_ICMPX_PORT_UNREACH] = ICMP_PORT_UNREACH,
78 [NFT_REJECT_ICMPX_HOST_UNREACH] = ICMP_HOST_UNREACH,
79 [NFT_REJECT_ICMPX_ADMIN_PROHIBITED] = ICMP_PKT_FILTERED,
80};
81
82int nft_reject_icmp_code(u8 code)
83{
84 if (code > NFT_REJECT_ICMPX_MAX)
85 return -EINVAL;
86
87 return icmp_code_v4[code];
88}
89
90EXPORT_SYMBOL_GPL(nft_reject_icmp_code);
91
92
93static u8 icmp_code_v6[NFT_REJECT_ICMPX_MAX] = {
94 [NFT_REJECT_ICMPX_NO_ROUTE] = ICMPV6_NOROUTE,
95 [NFT_REJECT_ICMPX_PORT_UNREACH] = ICMPV6_PORT_UNREACH,
96 [NFT_REJECT_ICMPX_HOST_UNREACH] = ICMPV6_ADDR_UNREACH,
97 [NFT_REJECT_ICMPX_ADMIN_PROHIBITED] = ICMPV6_ADM_PROHIBITED,
98};
99
100int nft_reject_icmpv6_code(u8 code)
101{
102 if (code > NFT_REJECT_ICMPX_MAX)
103 return -EINVAL;
104
105 return icmp_code_v6[code];
106}
107
108EXPORT_SYMBOL_GPL(nft_reject_icmpv6_code);
109
73MODULE_LICENSE("GPL"); 110MODULE_LICENSE("GPL");
74MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 111MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/netfilter/nft_reject_inet.c b/net/netfilter/nft_reject_inet.c
index b718a52a4654..7b5f9d58680a 100644
--- a/net/netfilter/nft_reject_inet.c
+++ b/net/netfilter/nft_reject_inet.c
@@ -14,17 +14,103 @@
14#include <linux/netfilter/nf_tables.h> 14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nft_reject.h> 16#include <net/netfilter/nft_reject.h>
17#include <net/netfilter/ipv4/nf_reject.h>
18#include <net/netfilter/ipv6/nf_reject.h>
17 19
18static void nft_reject_inet_eval(const struct nft_expr *expr, 20static void nft_reject_inet_eval(const struct nft_expr *expr,
19 struct nft_data data[NFT_REG_MAX + 1], 21 struct nft_data data[NFT_REG_MAX + 1],
20 const struct nft_pktinfo *pkt) 22 const struct nft_pktinfo *pkt)
21{ 23{
24 struct nft_reject *priv = nft_expr_priv(expr);
25 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
26
22 switch (pkt->ops->pf) { 27 switch (pkt->ops->pf) {
23 case NFPROTO_IPV4: 28 case NFPROTO_IPV4:
24 return nft_reject_ipv4_eval(expr, data, pkt); 29 switch (priv->type) {
30 case NFT_REJECT_ICMP_UNREACH:
31 nf_send_unreach(pkt->skb, priv->icmp_code);
32 break;
33 case NFT_REJECT_TCP_RST:
34 nf_send_reset(pkt->skb, pkt->ops->hooknum);
35 break;
36 case NFT_REJECT_ICMPX_UNREACH:
37 nf_send_unreach(pkt->skb,
38 nft_reject_icmp_code(priv->icmp_code));
39 break;
40 }
41 break;
25 case NFPROTO_IPV6: 42 case NFPROTO_IPV6:
26 return nft_reject_ipv6_eval(expr, data, pkt); 43 switch (priv->type) {
44 case NFT_REJECT_ICMP_UNREACH:
45 nf_send_unreach6(net, pkt->skb, priv->icmp_code,
46 pkt->ops->hooknum);
47 break;
48 case NFT_REJECT_TCP_RST:
49 nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
50 break;
51 case NFT_REJECT_ICMPX_UNREACH:
52 nf_send_unreach6(net, pkt->skb,
53 nft_reject_icmpv6_code(priv->icmp_code),
54 pkt->ops->hooknum);
55 break;
56 }
57 break;
58 }
59 data[NFT_REG_VERDICT].verdict = NF_DROP;
60}
61
62static int nft_reject_inet_init(const struct nft_ctx *ctx,
63 const struct nft_expr *expr,
64 const struct nlattr * const tb[])
65{
66 struct nft_reject *priv = nft_expr_priv(expr);
67 int icmp_code;
68
69 if (tb[NFTA_REJECT_TYPE] == NULL)
70 return -EINVAL;
71
72 priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
73 switch (priv->type) {
74 case NFT_REJECT_ICMP_UNREACH:
75 case NFT_REJECT_ICMPX_UNREACH:
76 if (tb[NFTA_REJECT_ICMP_CODE] == NULL)
77 return -EINVAL;
78
79 icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]);
80 if (priv->type == NFT_REJECT_ICMPX_UNREACH &&
81 icmp_code > NFT_REJECT_ICMPX_MAX)
82 return -EINVAL;
83
84 priv->icmp_code = icmp_code;
85 break;
86 case NFT_REJECT_TCP_RST:
87 break;
88 default:
89 return -EINVAL;
27 } 90 }
91 return 0;
92}
93
94static int nft_reject_inet_dump(struct sk_buff *skb,
95 const struct nft_expr *expr)
96{
97 const struct nft_reject *priv = nft_expr_priv(expr);
98
99 if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type)))
100 goto nla_put_failure;
101
102 switch (priv->type) {
103 case NFT_REJECT_ICMP_UNREACH:
104 case NFT_REJECT_ICMPX_UNREACH:
105 if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code))
106 goto nla_put_failure;
107 break;
108 }
109
110 return 0;
111
112nla_put_failure:
113 return -1;
28} 114}
29 115
30static struct nft_expr_type nft_reject_inet_type; 116static struct nft_expr_type nft_reject_inet_type;
@@ -32,8 +118,8 @@ static const struct nft_expr_ops nft_reject_inet_ops = {
32 .type = &nft_reject_inet_type, 118 .type = &nft_reject_inet_type,
33 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), 119 .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
34 .eval = nft_reject_inet_eval, 120 .eval = nft_reject_inet_eval,
35 .init = nft_reject_init, 121 .init = nft_reject_inet_init,
36 .dump = nft_reject_dump, 122 .dump = nft_reject_inet_dump,
37}; 123};
38 124
39static struct nft_expr_type nft_reject_inet_type __read_mostly = { 125static struct nft_expr_type nft_reject_inet_type __read_mostly = {
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index d7ca16b8b8df..f440f57a452f 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -13,6 +13,7 @@
13#include <linux/netfilter_bridge.h> 13#include <linux/netfilter_bridge.h>
14#include <linux/netfilter/xt_physdev.h> 14#include <linux/netfilter/xt_physdev.h>
15#include <linux/netfilter/x_tables.h> 15#include <linux/netfilter/x_tables.h>
16#include <net/netfilter/br_netfilter.h>
16 17
17MODULE_LICENSE("GPL"); 18MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 19MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
@@ -87,6 +88,8 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
87{ 88{
88 const struct xt_physdev_info *info = par->matchinfo; 89 const struct xt_physdev_info *info = par->matchinfo;
89 90
91 br_netfilter_enable();
92
90 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || 93 if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
91 info->bitmask & ~XT_PHYSDEV_OP_MASK) 94 info->bitmask & ~XT_PHYSDEV_OP_MASK)
92 return -EINVAL; 95 return -EINVAL;