aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netfilter/ipv4/nf_nat_redirect.h9
-rw-r--r--include/net/netfilter/ipv6/nf_nat_redirect.h8
-rw-r--r--include/net/netfilter/nft_redir.h21
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h18
-rw-r--r--net/bridge/br_netfilter.c1
-rw-r--r--net/ipv4/netfilter/Kconfig15
-rw-r--r--net/ipv4/netfilter/Makefile2
-rw-r--r--net/ipv4/netfilter/nf_log_arp.c24
-rw-r--r--net/ipv4/netfilter/nf_log_ipv4.c12
-rw-r--r--net/ipv4/netfilter/nf_nat_redirect_ipv4.c82
-rw-r--r--net/ipv4/netfilter/nf_reject_ipv4.c1
-rw-r--r--net/ipv4/netfilter/nft_redir_ipv4.c77
-rw-r--r--net/ipv4/netfilter/nft_reject_ipv4.c7
-rw-r--r--net/ipv6/netfilter/Kconfig15
-rw-r--r--net/ipv6/netfilter/Makefile2
-rw-r--r--net/ipv6/netfilter/nf_log_ipv6.c12
-rw-r--r--net/ipv6/netfilter/nf_nat_redirect_ipv6.c75
-rw-r--r--net/ipv6/netfilter/nf_reject_ipv6.c1
-rw-r--r--net/ipv6/netfilter/nft_redir_ipv6.c77
-rw-r--r--net/ipv6/netfilter/nft_reject_ipv6.c7
-rw-r--r--net/netfilter/Kconfig11
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/core.c1
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_pe.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_sched.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c1
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c14
-rw-r--r--net/netfilter/nf_conntrack_helper.c2
-rw-r--r--net/netfilter/nf_log.c40
-rw-r--r--net/netfilter/nf_tables_api.c5
-rw-r--r--net/netfilter/nfnetlink_log.c18
-rw-r--r--net/netfilter/nft_meta.c7
-rw-r--r--net/netfilter/nft_redir.c99
-rw-r--r--net/netfilter/xt_DSCP.c6
-rw-r--r--net/netfilter/xt_REDIRECT.c84
-rw-r--r--net/netfilter/xt_connlimit.c25
38 files changed, 636 insertions, 156 deletions
diff --git a/include/net/netfilter/ipv4/nf_nat_redirect.h b/include/net/netfilter/ipv4/nf_nat_redirect.h
new file mode 100644
index 000000000000..19e1df3a0a4d
--- /dev/null
+++ b/include/net/netfilter/ipv4/nf_nat_redirect.h
@@ -0,0 +1,9 @@
1#ifndef _NF_NAT_REDIRECT_IPV4_H_
2#define _NF_NAT_REDIRECT_IPV4_H_
3
4unsigned int
5nf_nat_redirect_ipv4(struct sk_buff *skb,
6 const struct nf_nat_ipv4_multi_range_compat *mr,
7 unsigned int hooknum);
8
9#endif /* _NF_NAT_REDIRECT_IPV4_H_ */
diff --git a/include/net/netfilter/ipv6/nf_nat_redirect.h b/include/net/netfilter/ipv6/nf_nat_redirect.h
new file mode 100644
index 000000000000..1ebdffc461cc
--- /dev/null
+++ b/include/net/netfilter/ipv6/nf_nat_redirect.h
@@ -0,0 +1,8 @@
1#ifndef _NF_NAT_REDIRECT_IPV6_H_
2#define _NF_NAT_REDIRECT_IPV6_H_
3
4unsigned int
5nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
6 unsigned int hooknum);
7
8#endif /* _NF_NAT_REDIRECT_IPV6_H_ */
diff --git a/include/net/netfilter/nft_redir.h b/include/net/netfilter/nft_redir.h
new file mode 100644
index 000000000000..a2d67546afab
--- /dev/null
+++ b/include/net/netfilter/nft_redir.h
@@ -0,0 +1,21 @@
1#ifndef _NFT_REDIR_H_
2#define _NFT_REDIR_H_
3
4struct nft_redir {
5 enum nft_registers sreg_proto_min:8;
6 enum nft_registers sreg_proto_max:8;
7 u16 flags;
8};
9
10extern const struct nla_policy nft_redir_policy[];
11
12int nft_redir_init(const struct nft_ctx *ctx,
13 const struct nft_expr *expr,
14 const struct nlattr * const tb[]);
15
16int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr);
17
18int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
19 const struct nft_data **data);
20
21#endif /* _NFT_REDIR_H_ */
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index f31fe7b660a5..832bc46db78b 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -579,6 +579,7 @@ enum nft_exthdr_attributes {
579 * @NFT_META_CPU: cpu id through smp_processor_id() 579 * @NFT_META_CPU: cpu id through smp_processor_id()
580 * @NFT_META_IIFGROUP: packet input interface group 580 * @NFT_META_IIFGROUP: packet input interface group
581 * @NFT_META_OIFGROUP: packet output interface group 581 * @NFT_META_OIFGROUP: packet output interface group
582 * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid)
582 */ 583 */
583enum nft_meta_keys { 584enum nft_meta_keys {
584 NFT_META_LEN, 585 NFT_META_LEN,
@@ -604,6 +605,7 @@ enum nft_meta_keys {
604 NFT_META_CPU, 605 NFT_META_CPU,
605 NFT_META_IIFGROUP, 606 NFT_META_IIFGROUP,
606 NFT_META_OIFGROUP, 607 NFT_META_OIFGROUP,
608 NFT_META_CGROUP,
607}; 609};
608 610
609/** 611/**
@@ -838,6 +840,22 @@ enum nft_masq_attributes {
838#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1) 840#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
839 841
840/** 842/**
843 * enum nft_redir_attributes - nf_tables redirect expression netlink attributes
844 *
845 * @NFTA_REDIR_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
846 * @NFTA_REDIR_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
847 * @NFTA_REDIR_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
848 */
849enum nft_redir_attributes {
850 NFTA_REDIR_UNSPEC,
851 NFTA_REDIR_REG_PROTO_MIN,
852 NFTA_REDIR_REG_PROTO_MAX,
853 NFTA_REDIR_FLAGS,
854 __NFTA_REDIR_MAX
855};
856#define NFTA_REDIR_MAX (__NFTA_REDIR_MAX - 1)
857
858/**
841 * enum nft_gen_attributes - nf_tables ruleset generation attributes 859 * enum nft_gen_attributes - nf_tables ruleset generation attributes
842 * 860 *
843 * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32) 861 * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 1a4f32c09ad5..c190d22b6b3d 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -35,6 +35,7 @@
35#include <net/ip.h> 35#include <net/ip.h>
36#include <net/ipv6.h> 36#include <net/ipv6.h>
37#include <net/route.h> 37#include <net/route.h>
38#include <net/netfilter/br_netfilter.h>
38 39
39#include <asm/uaccess.h> 40#include <asm/uaccess.h>
40#include "br_private.h" 41#include "br_private.h"
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 4c019d5c3f57..8358b2da1549 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -104,6 +104,12 @@ config NF_NAT_MASQUERADE_IPV4
104 This is the kernel functionality to provide NAT in the masquerade 104 This is the kernel functionality to provide NAT in the masquerade
105 flavour (automatic source address selection). 105 flavour (automatic source address selection).
106 106
107config NF_NAT_REDIRECT_IPV4
108 tristate "IPv4 redirect support"
109 help
110 This is the kernel functionality to provide NAT in the redirect
111 flavour (redirect packets to local machine).
112
107config NFT_MASQ_IPV4 113config NFT_MASQ_IPV4
108 tristate "IPv4 masquerading support for nf_tables" 114 tristate "IPv4 masquerading support for nf_tables"
109 depends on NF_TABLES_IPV4 115 depends on NF_TABLES_IPV4
@@ -113,6 +119,15 @@ config NFT_MASQ_IPV4
113 This is the expression that provides IPv4 masquerading support for 119 This is the expression that provides IPv4 masquerading support for
114 nf_tables. 120 nf_tables.
115 121
122config NFT_REDIR_IPV4
123 tristate "IPv4 redirect support for nf_tables"
124 depends on NF_TABLES_IPV4
125 depends on NFT_REDIR
126 select NF_NAT_REDIRECT_IPV4
127 help
128 This is the expression that provides IPv4 redirect support for
129 nf_tables.
130
116config NF_NAT_SNMP_BASIC 131config NF_NAT_SNMP_BASIC
117 tristate "Basic SNMP-ALG support" 132 tristate "Basic SNMP-ALG support"
118 depends on NF_CONNTRACK_SNMP 133 depends on NF_CONNTRACK_SNMP
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index f4cef5af0969..902bcd1597bb 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
31obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o 31obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
32obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o 32obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
33obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o 33obj-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o
34obj-$(CONFIG_NF_NAT_REDIRECT_IPV4) += nf_nat_redirect_ipv4.o
34 35
35# NAT protocols (nf_nat) 36# NAT protocols (nf_nat)
36obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 37obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
@@ -40,6 +41,7 @@ obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
40obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o 41obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
41obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o 42obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
42obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o 43obj-$(CONFIG_NFT_MASQ_IPV4) += nft_masq_ipv4.o
44obj-$(CONFIG_NFT_REDIR_IPV4) += nft_redir_ipv4.o
43obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o 45obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
44 46
45# generic IP tables 47# generic IP tables
diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c
index ccfc78db12ee..d059182c1466 100644
--- a/net/ipv4/netfilter/nf_log_arp.c
+++ b/net/ipv4/netfilter/nf_log_arp.c
@@ -10,6 +10,7 @@
10 * it under the terms of the GNU General Public License version 2 as 10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation. 11 * published by the Free Software Foundation.
12 */ 12 */
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 14
14#include <linux/module.h> 15#include <linux/module.h>
15#include <linux/spinlock.h> 16#include <linux/spinlock.h>
@@ -74,12 +75,12 @@ static void dump_arp_packet(struct nf_log_buf *m,
74 ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst); 75 ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst);
75} 76}
76 77
77void nf_log_arp_packet(struct net *net, u_int8_t pf, 78static void nf_log_arp_packet(struct net *net, u_int8_t pf,
78 unsigned int hooknum, const struct sk_buff *skb, 79 unsigned int hooknum, const struct sk_buff *skb,
79 const struct net_device *in, 80 const struct net_device *in,
80 const struct net_device *out, 81 const struct net_device *out,
81 const struct nf_loginfo *loginfo, 82 const struct nf_loginfo *loginfo,
82 const char *prefix) 83 const char *prefix)
83{ 84{
84 struct nf_log_buf *m; 85 struct nf_log_buf *m;
85 86
@@ -130,8 +131,17 @@ static int __init nf_log_arp_init(void)
130 if (ret < 0) 131 if (ret < 0)
131 return ret; 132 return ret;
132 133
133 nf_log_register(NFPROTO_ARP, &nf_arp_logger); 134 ret = nf_log_register(NFPROTO_ARP, &nf_arp_logger);
135 if (ret < 0) {
136 pr_err("failed to register logger\n");
137 goto err1;
138 }
139
134 return 0; 140 return 0;
141
142err1:
143 unregister_pernet_subsys(&nf_log_arp_net_ops);
144 return ret;
135} 145}
136 146
137static void __exit nf_log_arp_exit(void) 147static void __exit nf_log_arp_exit(void)
diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c
index 078bdca1b607..75101980eeee 100644
--- a/net/ipv4/netfilter/nf_log_ipv4.c
+++ b/net/ipv4/netfilter/nf_log_ipv4.c
@@ -5,6 +5,7 @@
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 9
9#include <linux/module.h> 10#include <linux/module.h>
10#include <linux/spinlock.h> 11#include <linux/spinlock.h>
@@ -366,8 +367,17 @@ static int __init nf_log_ipv4_init(void)
366 if (ret < 0) 367 if (ret < 0)
367 return ret; 368 return ret;
368 369
369 nf_log_register(NFPROTO_IPV4, &nf_ip_logger); 370 ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
371 if (ret < 0) {
372 pr_err("failed to register logger\n");
373 goto err1;
374 }
375
370 return 0; 376 return 0;
377
378err1:
379 unregister_pernet_subsys(&nf_log_ipv4_net_ops);
380 return ret;
371} 381}
372 382
373static void __exit nf_log_ipv4_exit(void) 383static void __exit nf_log_ipv4_exit(void)
diff --git a/net/ipv4/netfilter/nf_nat_redirect_ipv4.c b/net/ipv4/netfilter/nf_nat_redirect_ipv4.c
new file mode 100644
index 000000000000..a220552fc532
--- /dev/null
+++ b/net/ipv4/netfilter/nf_nat_redirect_ipv4.c
@@ -0,0 +1,82 @@
1/*
2 * (C) 1999-2001 Paul `Rusty' Russell
3 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6
11 * NAT funded by Astaro.
12 */
13
14#include <linux/if.h>
15#include <linux/inetdevice.h>
16#include <linux/ip.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/netdevice.h>
20#include <linux/netfilter.h>
21#include <linux/types.h>
22#include <linux/netfilter_ipv4.h>
23#include <linux/netfilter/x_tables.h>
24#include <net/addrconf.h>
25#include <net/checksum.h>
26#include <net/protocol.h>
27#include <net/netfilter/nf_nat.h>
28#include <net/netfilter/ipv4/nf_nat_redirect.h>
29
30unsigned int
31nf_nat_redirect_ipv4(struct sk_buff *skb,
32 const struct nf_nat_ipv4_multi_range_compat *mr,
33 unsigned int hooknum)
34{
35 struct nf_conn *ct;
36 enum ip_conntrack_info ctinfo;
37 __be32 newdst;
38 struct nf_nat_range newrange;
39
40 NF_CT_ASSERT(hooknum == NF_INET_PRE_ROUTING ||
41 hooknum == NF_INET_LOCAL_OUT);
42
43 ct = nf_ct_get(skb, &ctinfo);
44 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
45
46 /* Local packets: make them go to loopback */
47 if (hooknum == NF_INET_LOCAL_OUT) {
48 newdst = htonl(0x7F000001);
49 } else {
50 struct in_device *indev;
51 struct in_ifaddr *ifa;
52
53 newdst = 0;
54
55 rcu_read_lock();
56 indev = __in_dev_get_rcu(skb->dev);
57 if (indev != NULL) {
58 ifa = indev->ifa_list;
59 newdst = ifa->ifa_local;
60 }
61 rcu_read_unlock();
62
63 if (!newdst)
64 return NF_DROP;
65 }
66
67 /* Transfer from original range. */
68 memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
69 memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
70 newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
71 newrange.min_addr.ip = newdst;
72 newrange.max_addr.ip = newdst;
73 newrange.min_proto = mr->range[0].min;
74 newrange.max_proto = mr->range[0].max;
75
76 /* Hand modified range to generic setup. */
77 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
78}
79EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv4);
80
81MODULE_LICENSE("GPL");
82MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c
index 1baaa83dfe5c..536da7bc598a 100644
--- a/net/ipv4/netfilter/nf_reject_ipv4.c
+++ b/net/ipv4/netfilter/nf_reject_ipv4.c
@@ -11,6 +11,7 @@
11#include <net/tcp.h> 11#include <net/tcp.h>
12#include <net/route.h> 12#include <net/route.h>
13#include <net/dst.h> 13#include <net/dst.h>
14#include <net/netfilter/ipv4/nf_reject.h>
14#include <linux/netfilter_ipv4.h> 15#include <linux/netfilter_ipv4.h>
15#include <net/netfilter/ipv4/nf_reject.h> 16#include <net/netfilter/ipv4/nf_reject.h>
16 17
diff --git a/net/ipv4/netfilter/nft_redir_ipv4.c b/net/ipv4/netfilter/nft_redir_ipv4.c
new file mode 100644
index 000000000000..643c5967aa27
--- /dev/null
+++ b/net/ipv4/netfilter/nft_redir_ipv4.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
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 <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/netlink.h>
13#include <linux/netfilter.h>
14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/ipv4/nf_nat_redirect.h>
18#include <net/netfilter/nft_redir.h>
19
20static void nft_redir_ipv4_eval(const struct nft_expr *expr,
21 struct nft_data data[NFT_REG_MAX + 1],
22 const struct nft_pktinfo *pkt)
23{
24 struct nft_redir *priv = nft_expr_priv(expr);
25 struct nf_nat_ipv4_multi_range_compat mr;
26 unsigned int verdict;
27
28 memset(&mr, 0, sizeof(mr));
29 if (priv->sreg_proto_min) {
30 mr.range[0].min.all = (__force __be16)
31 data[priv->sreg_proto_min].data[0];
32 mr.range[0].max.all = (__force __be16)
33 data[priv->sreg_proto_max].data[0];
34 mr.range[0].flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
35 }
36
37 mr.range[0].flags |= priv->flags;
38
39 verdict = nf_nat_redirect_ipv4(pkt->skb, &mr, pkt->ops->hooknum);
40 data[NFT_REG_VERDICT].verdict = verdict;
41}
42
43static struct nft_expr_type nft_redir_ipv4_type;
44static const struct nft_expr_ops nft_redir_ipv4_ops = {
45 .type = &nft_redir_ipv4_type,
46 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
47 .eval = nft_redir_ipv4_eval,
48 .init = nft_redir_init,
49 .dump = nft_redir_dump,
50 .validate = nft_redir_validate,
51};
52
53static struct nft_expr_type nft_redir_ipv4_type __read_mostly = {
54 .family = NFPROTO_IPV4,
55 .name = "redir",
56 .ops = &nft_redir_ipv4_ops,
57 .policy = nft_redir_policy,
58 .maxattr = NFTA_REDIR_MAX,
59 .owner = THIS_MODULE,
60};
61
62static int __init nft_redir_ipv4_module_init(void)
63{
64 return nft_register_expr(&nft_redir_ipv4_type);
65}
66
67static void __exit nft_redir_ipv4_module_exit(void)
68{
69 nft_unregister_expr(&nft_redir_ipv4_type);
70}
71
72module_init(nft_redir_ipv4_module_init);
73module_exit(nft_redir_ipv4_module_exit);
74
75MODULE_LICENSE("GPL");
76MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
77MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "redir");
diff --git a/net/ipv4/netfilter/nft_reject_ipv4.c b/net/ipv4/netfilter/nft_reject_ipv4.c
index ed33299c56d1..d729542bd1b7 100644
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -19,9 +19,9 @@
19#include <net/netfilter/ipv4/nf_reject.h> 19#include <net/netfilter/ipv4/nf_reject.h>
20#include <net/netfilter/nft_reject.h> 20#include <net/netfilter/nft_reject.h>
21 21
22void nft_reject_ipv4_eval(const struct nft_expr *expr, 22static void nft_reject_ipv4_eval(const struct nft_expr *expr,
23 struct nft_data data[NFT_REG_MAX + 1], 23 struct nft_data data[NFT_REG_MAX + 1],
24 const struct nft_pktinfo *pkt) 24 const struct nft_pktinfo *pkt)
25{ 25{
26 struct nft_reject *priv = nft_expr_priv(expr); 26 struct nft_reject *priv = nft_expr_priv(expr);
27 27
@@ -36,7 +36,6 @@ void nft_reject_ipv4_eval(const struct nft_expr *expr,
36 36
37 data[NFT_REG_VERDICT].verdict = NF_DROP; 37 data[NFT_REG_VERDICT].verdict = NF_DROP;
38} 38}
39EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval);
40 39
41static struct nft_expr_type nft_reject_ipv4_type; 40static struct nft_expr_type nft_reject_ipv4_type;
42static const struct nft_expr_ops nft_reject_ipv4_ops = { 41static const struct nft_expr_ops nft_reject_ipv4_ops = {
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 6af874fc187f..0dbe5c7953e5 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -82,6 +82,12 @@ config NF_NAT_MASQUERADE_IPV6
82 This is the kernel functionality to provide NAT in the masquerade 82 This is the kernel functionality to provide NAT in the masquerade
83 flavour (automatic source address selection) for IPv6. 83 flavour (automatic source address selection) for IPv6.
84 84
85config NF_NAT_REDIRECT_IPV6
86 tristate "IPv6 redirect support"
87 help
88 This is the kernel functionality to provide NAT in the redirect
89 flavour (redirect packet to local machine) for IPv6.
90
85config NFT_MASQ_IPV6 91config NFT_MASQ_IPV6
86 tristate "IPv6 masquerade support for nf_tables" 92 tristate "IPv6 masquerade support for nf_tables"
87 depends on NF_TABLES_IPV6 93 depends on NF_TABLES_IPV6
@@ -91,6 +97,15 @@ config NFT_MASQ_IPV6
91 This is the expression that provides IPv4 masquerading support for 97 This is the expression that provides IPv4 masquerading support for
92 nf_tables. 98 nf_tables.
93 99
100config NFT_REDIR_IPV6
101 tristate "IPv6 redirect support for nf_tables"
102 depends on NF_TABLES_IPV6
103 depends on NFT_REDIR
104 select NF_NAT_REDIRECT_IPV6
105 help
106 This is the expression that provides IPv4 redirect support for
107 nf_tables.
108
94endif # NF_NAT_IPV6 109endif # NF_NAT_IPV6
95 110
96config IP6_NF_IPTABLES 111config IP6_NF_IPTABLES
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index fbb25f01143c..d2ac9f5f212c 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
19nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o 19nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o
20obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o 20obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
21obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o 21obj-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o
22obj-$(CONFIG_NF_NAT_REDIRECT_IPV6) += nf_nat_redirect_ipv6.o
22 23
23# defrag 24# defrag
24nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o 25nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
@@ -36,6 +37,7 @@ obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
36obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o 37obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
37obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o 38obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
38obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o 39obj-$(CONFIG_NFT_MASQ_IPV6) += nft_masq_ipv6.o
40obj-$(CONFIG_NFT_REDIR_IPV6) += nft_redir_ipv6.o
39 41
40# matches 42# matches
41obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o 43obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c
index 7b17a0be93e7..7fc34d1681a1 100644
--- a/net/ipv6/netfilter/nf_log_ipv6.c
+++ b/net/ipv6/netfilter/nf_log_ipv6.c
@@ -5,6 +5,7 @@
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 9
9#include <linux/module.h> 10#include <linux/module.h>
10#include <linux/spinlock.h> 11#include <linux/spinlock.h>
@@ -398,8 +399,17 @@ static int __init nf_log_ipv6_init(void)
398 if (ret < 0) 399 if (ret < 0)
399 return ret; 400 return ret;
400 401
401 nf_log_register(NFPROTO_IPV6, &nf_ip6_logger); 402 ret = nf_log_register(NFPROTO_IPV6, &nf_ip6_logger);
403 if (ret < 0) {
404 pr_err("failed to register logger\n");
405 goto err1;
406 }
407
402 return 0; 408 return 0;
409
410err1:
411 unregister_pernet_subsys(&nf_log_ipv6_net_ops);
412 return ret;
403} 413}
404 414
405static void __exit nf_log_ipv6_exit(void) 415static void __exit nf_log_ipv6_exit(void)
diff --git a/net/ipv6/netfilter/nf_nat_redirect_ipv6.c b/net/ipv6/netfilter/nf_nat_redirect_ipv6.c
new file mode 100644
index 000000000000..ea1308aeb048
--- /dev/null
+++ b/net/ipv6/netfilter/nf_nat_redirect_ipv6.c
@@ -0,0 +1,75 @@
1/*
2 * (C) 1999-2001 Paul `Rusty' Russell
3 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4 * Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6
11 * NAT funded by Astaro.
12 */
13
14#include <linux/if.h>
15#include <linux/inetdevice.h>
16#include <linux/ip.h>
17#include <linux/kernel.h>
18#include <linux/module.h>
19#include <linux/netdevice.h>
20#include <linux/netfilter.h>
21#include <linux/types.h>
22#include <linux/netfilter_ipv6.h>
23#include <linux/netfilter/x_tables.h>
24#include <net/addrconf.h>
25#include <net/checksum.h>
26#include <net/protocol.h>
27#include <net/netfilter/nf_nat.h>
28#include <net/netfilter/ipv6/nf_nat_redirect.h>
29
30static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
31
32unsigned int
33nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
34 unsigned int hooknum)
35{
36 struct nf_nat_range newrange;
37 struct in6_addr newdst;
38 enum ip_conntrack_info ctinfo;
39 struct nf_conn *ct;
40
41 ct = nf_ct_get(skb, &ctinfo);
42 if (hooknum == NF_INET_LOCAL_OUT) {
43 newdst = loopback_addr;
44 } else {
45 struct inet6_dev *idev;
46 struct inet6_ifaddr *ifa;
47 bool addr = false;
48
49 rcu_read_lock();
50 idev = __in6_dev_get(skb->dev);
51 if (idev != NULL) {
52 list_for_each_entry(ifa, &idev->addr_list, if_list) {
53 newdst = ifa->addr;
54 addr = true;
55 break;
56 }
57 }
58 rcu_read_unlock();
59
60 if (!addr)
61 return NF_DROP;
62 }
63
64 newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
65 newrange.min_addr.in6 = newdst;
66 newrange.max_addr.in6 = newdst;
67 newrange.min_proto = range->min_proto;
68 newrange.max_proto = range->max_proto;
69
70 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
71}
72EXPORT_SYMBOL_GPL(nf_nat_redirect_ipv6);
73
74MODULE_LICENSE("GPL");
75MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c
index 015eb8a80766..d05b36440e8b 100644
--- a/net/ipv6/netfilter/nf_reject_ipv6.c
+++ b/net/ipv6/netfilter/nf_reject_ipv6.c
@@ -11,6 +11,7 @@
11#include <net/ip6_route.h> 11#include <net/ip6_route.h>
12#include <net/ip6_fib.h> 12#include <net/ip6_fib.h>
13#include <net/ip6_checksum.h> 13#include <net/ip6_checksum.h>
14#include <net/netfilter/ipv6/nf_reject.h>
14#include <linux/netfilter_ipv6.h> 15#include <linux/netfilter_ipv6.h>
15#include <net/netfilter/ipv6/nf_reject.h> 16#include <net/netfilter/ipv6/nf_reject.h>
16 17
diff --git a/net/ipv6/netfilter/nft_redir_ipv6.c b/net/ipv6/netfilter/nft_redir_ipv6.c
new file mode 100644
index 000000000000..83420eeaad1c
--- /dev/null
+++ b/net/ipv6/netfilter/nft_redir_ipv6.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
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 <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/netlink.h>
13#include <linux/netfilter.h>
14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_tables.h>
16#include <net/netfilter/nf_nat.h>
17#include <net/netfilter/nft_redir.h>
18#include <net/netfilter/ipv6/nf_nat_redirect.h>
19
20static void nft_redir_ipv6_eval(const struct nft_expr *expr,
21 struct nft_data data[NFT_REG_MAX + 1],
22 const struct nft_pktinfo *pkt)
23{
24 struct nft_redir *priv = nft_expr_priv(expr);
25 struct nf_nat_range range;
26 unsigned int verdict;
27
28 memset(&range, 0, sizeof(range));
29 if (priv->sreg_proto_min) {
30 range.min_proto.all = (__force __be16)
31 data[priv->sreg_proto_min].data[0];
32 range.max_proto.all = (__force __be16)
33 data[priv->sreg_proto_max].data[0];
34 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
35 }
36
37 range.flags |= priv->flags;
38
39 verdict = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->ops->hooknum);
40 data[NFT_REG_VERDICT].verdict = verdict;
41}
42
43static struct nft_expr_type nft_redir_ipv6_type;
44static const struct nft_expr_ops nft_redir_ipv6_ops = {
45 .type = &nft_redir_ipv6_type,
46 .size = NFT_EXPR_SIZE(sizeof(struct nft_redir)),
47 .eval = nft_redir_ipv6_eval,
48 .init = nft_redir_init,
49 .dump = nft_redir_dump,
50 .validate = nft_redir_validate,
51};
52
53static struct nft_expr_type nft_redir_ipv6_type __read_mostly = {
54 .family = NFPROTO_IPV6,
55 .name = "redir",
56 .ops = &nft_redir_ipv6_ops,
57 .policy = nft_redir_policy,
58 .maxattr = NFTA_REDIR_MAX,
59 .owner = THIS_MODULE,
60};
61
62static int __init nft_redir_ipv6_module_init(void)
63{
64 return nft_register_expr(&nft_redir_ipv6_type);
65}
66
67static void __exit nft_redir_ipv6_module_exit(void)
68{
69 nft_unregister_expr(&nft_redir_ipv6_type);
70}
71
72module_init(nft_redir_ipv6_module_init);
73module_exit(nft_redir_ipv6_module_exit);
74
75MODULE_LICENSE("GPL");
76MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
77MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "redir");
diff --git a/net/ipv6/netfilter/nft_reject_ipv6.c b/net/ipv6/netfilter/nft_reject_ipv6.c
index 0bc19fa87821..f73285924144 100644
--- a/net/ipv6/netfilter/nft_reject_ipv6.c
+++ b/net/ipv6/netfilter/nft_reject_ipv6.c
@@ -19,9 +19,9 @@
19#include <net/netfilter/nft_reject.h> 19#include <net/netfilter/nft_reject.h>
20#include <net/netfilter/ipv6/nf_reject.h> 20#include <net/netfilter/ipv6/nf_reject.h>
21 21
22void nft_reject_ipv6_eval(const struct nft_expr *expr, 22static void nft_reject_ipv6_eval(const struct nft_expr *expr,
23 struct nft_data data[NFT_REG_MAX + 1], 23 struct nft_data data[NFT_REG_MAX + 1],
24 const struct nft_pktinfo *pkt) 24 const struct nft_pktinfo *pkt)
25{ 25{
26 struct nft_reject *priv = nft_expr_priv(expr); 26 struct nft_reject *priv = nft_expr_priv(expr);
27 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); 27 struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
@@ -38,7 +38,6 @@ void nft_reject_ipv6_eval(const struct nft_expr *expr,
38 38
39 data[NFT_REG_VERDICT].verdict = NF_DROP; 39 data[NFT_REG_VERDICT].verdict = NF_DROP;
40} 40}
41EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval);
42 41
43static struct nft_expr_type nft_reject_ipv6_type; 42static struct nft_expr_type nft_reject_ipv6_type;
44static const struct nft_expr_ops nft_reject_ipv6_ops = { 43static const struct nft_expr_ops nft_reject_ipv6_ops = {
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index ae5096ab65eb..57f15a9aa481 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -505,6 +505,15 @@ config NFT_MASQ
505 This option adds the "masquerade" expression that you can use 505 This option adds the "masquerade" expression that you can use
506 to perform NAT in the masquerade flavour. 506 to perform NAT in the masquerade flavour.
507 507
508config NFT_REDIR
509 depends on NF_TABLES
510 depends on NF_CONNTRACK
511 depends on NF_NAT
512 tristate "Netfilter nf_tables redirect support"
513 help
514 This options adds the "redirect" expression that you can use
515 to perform NAT in the redirect flavour.
516
508config NFT_NAT 517config NFT_NAT
509 depends on NF_TABLES 518 depends on NF_TABLES
510 depends on NF_CONNTRACK 519 depends on NF_CONNTRACK
@@ -835,6 +844,8 @@ config NETFILTER_XT_TARGET_RATEEST
835config NETFILTER_XT_TARGET_REDIRECT 844config NETFILTER_XT_TARGET_REDIRECT
836 tristate "REDIRECT target support" 845 tristate "REDIRECT target support"
837 depends on NF_NAT 846 depends on NF_NAT
847 select NF_NAT_REDIRECT_IPV4 if NF_NAT_IPV4
848 select NF_NAT_REDIRECT_IPV6 if NF_NAT_IPV6
838 ---help--- 849 ---help---
839 REDIRECT is a special case of NAT: all incoming connections are 850 REDIRECT is a special case of NAT: all incoming connections are
840 mapped onto the incoming interface's address, causing the packets to 851 mapped onto the incoming interface's address, causing the packets to
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index a9571be3f791..f3eb4680f2ec 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_NFT_HASH) += nft_hash.o
88obj-$(CONFIG_NFT_COUNTER) += nft_counter.o 88obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
89obj-$(CONFIG_NFT_LOG) += nft_log.o 89obj-$(CONFIG_NFT_LOG) += nft_log.o
90obj-$(CONFIG_NFT_MASQ) += nft_masq.o 90obj-$(CONFIG_NFT_MASQ) += nft_masq.o
91obj-$(CONFIG_NFT_REDIR) += nft_redir.o
91 92
92# generic X tables 93# generic X tables
93obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o 94obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 024a2e25c8a4..fea9ef566427 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -17,6 +17,7 @@
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/if.h> 18#include <linux/if.h>
19#include <linux/netdevice.h> 19#include <linux/netdevice.h>
20#include <linux/netfilter_ipv6.h>
20#include <linux/inetdevice.h> 21#include <linux/inetdevice.h>
21#include <linux/proc_fs.h> 22#include <linux/proc_fs.h>
22#include <linux/mutex.h> 23#include <linux/mutex.h>
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index ac7ba689efe7..b8295a430a56 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -465,8 +465,7 @@ __ip_vs_bind_svc(struct ip_vs_dest *dest, struct ip_vs_service *svc)
465 465
466static void ip_vs_service_free(struct ip_vs_service *svc) 466static void ip_vs_service_free(struct ip_vs_service *svc)
467{ 467{
468 if (svc->stats.cpustats) 468 free_percpu(svc->stats.cpustats);
469 free_percpu(svc->stats.cpustats);
470 kfree(svc); 469 kfree(svc);
471} 470}
472 471
diff --git a/net/netfilter/ipvs/ip_vs_pe.c b/net/netfilter/ipvs/ip_vs_pe.c
index 1a82b29ce8ea..0df17caa8af6 100644
--- a/net/netfilter/ipvs/ip_vs_pe.c
+++ b/net/netfilter/ipvs/ip_vs_pe.c
@@ -37,8 +37,7 @@ struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name)
37 rcu_read_unlock(); 37 rcu_read_unlock();
38 return pe; 38 return pe;
39 } 39 }
40 if (pe->module) 40 module_put(pe->module);
41 module_put(pe->module);
42 } 41 }
43 rcu_read_unlock(); 42 rcu_read_unlock();
44 43
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index 4dbcda6258bc..199760c71f39 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -104,8 +104,7 @@ static struct ip_vs_scheduler *ip_vs_sched_getbyname(const char *sched_name)
104 mutex_unlock(&ip_vs_sched_mutex); 104 mutex_unlock(&ip_vs_sched_mutex);
105 return sched; 105 return sched;
106 } 106 }
107 if (sched->module) 107 module_put(sched->module);
108 module_put(sched->module);
109 } 108 }
110 109
111 mutex_unlock(&ip_vs_sched_mutex); 110 mutex_unlock(&ip_vs_sched_mutex);
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 7162c86fd50d..c47ffd7a0a70 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -820,8 +820,7 @@ ip_vs_conn_fill_param_sync(struct net *net, int af, union ip_vs_sync_conn *sc,
820 820
821 p->pe_data = kmemdup(pe_data, pe_data_len, GFP_ATOMIC); 821 p->pe_data = kmemdup(pe_data, pe_data_len, GFP_ATOMIC);
822 if (!p->pe_data) { 822 if (!p->pe_data) {
823 if (p->pe->module) 823 module_put(p->pe->module);
824 module_put(p->pe->module);
825 return -ENOMEM; 824 return -ENOMEM;
826 } 825 }
827 p->pe_data_len = pe_data_len; 826 p->pe_data_len = pe_data_len;
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index bd90bf8107da..1f933136155a 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -293,7 +293,6 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
293 &dest->addr.ip, &dest_dst->dst_saddr.ip, 293 &dest->addr.ip, &dest_dst->dst_saddr.ip,
294 atomic_read(&rt->dst.__refcnt)); 294 atomic_read(&rt->dst.__refcnt));
295 } 295 }
296 daddr = dest->addr.ip;
297 if (ret_saddr) 296 if (ret_saddr)
298 *ret_saddr = dest_dst->dst_saddr.ip; 297 *ret_saddr = dest_dst->dst_saddr.ip;
299 } else { 298 } else {
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 3a3a60b126e0..1d69f5b9748f 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -728,7 +728,8 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
728 728
729/* If the calling party is on the same side of the forward-to party, 729/* If the calling party is on the same side of the forward-to party,
730 * we don't need to track the second call */ 730 * we don't need to track the second call */
731static int callforward_do_filter(const union nf_inet_addr *src, 731static int callforward_do_filter(struct net *net,
732 const union nf_inet_addr *src,
732 const union nf_inet_addr *dst, 733 const union nf_inet_addr *dst,
733 u_int8_t family) 734 u_int8_t family)
734{ 735{
@@ -750,9 +751,9 @@ static int callforward_do_filter(const union nf_inet_addr *src,
750 751
751 memset(&fl2, 0, sizeof(fl2)); 752 memset(&fl2, 0, sizeof(fl2));
752 fl2.daddr = dst->ip; 753 fl2.daddr = dst->ip;
753 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, 754 if (!afinfo->route(net, (struct dst_entry **)&rt1,
754 flowi4_to_flowi(&fl1), false)) { 755 flowi4_to_flowi(&fl1), false)) {
755 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, 756 if (!afinfo->route(net, (struct dst_entry **)&rt2,
756 flowi4_to_flowi(&fl2), false)) { 757 flowi4_to_flowi(&fl2), false)) {
757 if (rt_nexthop(rt1, fl1.daddr) == 758 if (rt_nexthop(rt1, fl1.daddr) ==
758 rt_nexthop(rt2, fl2.daddr) && 759 rt_nexthop(rt2, fl2.daddr) &&
@@ -774,9 +775,9 @@ static int callforward_do_filter(const union nf_inet_addr *src,
774 775
775 memset(&fl2, 0, sizeof(fl2)); 776 memset(&fl2, 0, sizeof(fl2));
776 fl2.daddr = dst->in6; 777 fl2.daddr = dst->in6;
777 if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, 778 if (!afinfo->route(net, (struct dst_entry **)&rt1,
778 flowi6_to_flowi(&fl1), false)) { 779 flowi6_to_flowi(&fl1), false)) {
779 if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, 780 if (!afinfo->route(net, (struct dst_entry **)&rt2,
780 flowi6_to_flowi(&fl2), false)) { 781 flowi6_to_flowi(&fl2), false)) {
781 if (ipv6_addr_equal(rt6_nexthop(rt1), 782 if (ipv6_addr_equal(rt6_nexthop(rt1),
782 rt6_nexthop(rt2)) && 783 rt6_nexthop(rt2)) &&
@@ -807,6 +808,7 @@ static int expect_callforwarding(struct sk_buff *skb,
807 __be16 port; 808 __be16 port;
808 union nf_inet_addr addr; 809 union nf_inet_addr addr;
809 struct nf_conntrack_expect *exp; 810 struct nf_conntrack_expect *exp;
811 struct net *net = nf_ct_net(ct);
810 typeof(nat_callforwarding_hook) nat_callforwarding; 812 typeof(nat_callforwarding_hook) nat_callforwarding;
811 813
812 /* Read alternativeAddress */ 814 /* Read alternativeAddress */
@@ -816,7 +818,7 @@ static int expect_callforwarding(struct sk_buff *skb,
816 /* If the calling party is on the same side of the forward-to party, 818 /* If the calling party is on the same side of the forward-to party,
817 * we don't need to track the second call */ 819 * we don't need to track the second call */
818 if (callforward_filter && 820 if (callforward_filter &&
819 callforward_do_filter(&addr, &ct->tuplehash[!dir].tuple.src.u3, 821 callforward_do_filter(net, &addr, &ct->tuplehash[!dir].tuple.src.u3,
820 nf_ct_l3num(ct))) { 822 nf_ct_l3num(ct))) {
821 pr_debug("nf_ct_q931: Call Forwarding not tracked\n"); 823 pr_debug("nf_ct_q931: Call Forwarding not tracked\n");
822 return 0; 824 return 0;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 5b3eae7d4c9a..bd9d31537905 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -250,7 +250,7 @@ out:
250} 250}
251EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); 251EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper);
252 252
253/* appropiate ct lock protecting must be taken by caller */ 253/* appropriate ct lock protecting must be taken by caller */
254static inline int unhelp(struct nf_conntrack_tuple_hash *i, 254static inline int unhelp(struct nf_conntrack_tuple_hash *i,
255 const struct nf_conntrack_helper *me) 255 const struct nf_conntrack_helper *me)
256{ 256{
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index d7197649dba6..49a64174f3f1 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -19,6 +19,9 @@
19static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly; 19static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
20static DEFINE_MUTEX(nf_log_mutex); 20static DEFINE_MUTEX(nf_log_mutex);
21 21
22#define nft_log_dereference(logger) \
23 rcu_dereference_protected(logger, lockdep_is_held(&nf_log_mutex))
24
22static struct nf_logger *__find_logger(int pf, const char *str_logger) 25static struct nf_logger *__find_logger(int pf, const char *str_logger)
23{ 26{
24 struct nf_logger *log; 27 struct nf_logger *log;
@@ -28,8 +31,7 @@ static struct nf_logger *__find_logger(int pf, const char *str_logger)
28 if (loggers[pf][i] == NULL) 31 if (loggers[pf][i] == NULL)
29 continue; 32 continue;
30 33
31 log = rcu_dereference_protected(loggers[pf][i], 34 log = nft_log_dereference(loggers[pf][i]);
32 lockdep_is_held(&nf_log_mutex));
33 if (!strncasecmp(str_logger, log->name, strlen(log->name))) 35 if (!strncasecmp(str_logger, log->name, strlen(log->name)))
34 return log; 36 return log;
35 } 37 }
@@ -45,8 +47,7 @@ void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger)
45 return; 47 return;
46 48
47 mutex_lock(&nf_log_mutex); 49 mutex_lock(&nf_log_mutex);
48 log = rcu_dereference_protected(net->nf.nf_loggers[pf], 50 log = nft_log_dereference(net->nf.nf_loggers[pf]);
49 lockdep_is_held(&nf_log_mutex));
50 if (log == NULL) 51 if (log == NULL)
51 rcu_assign_pointer(net->nf.nf_loggers[pf], logger); 52 rcu_assign_pointer(net->nf.nf_loggers[pf], logger);
52 53
@@ -61,8 +62,7 @@ void nf_log_unset(struct net *net, const struct nf_logger *logger)
61 62
62 mutex_lock(&nf_log_mutex); 63 mutex_lock(&nf_log_mutex);
63 for (i = 0; i < NFPROTO_NUMPROTO; i++) { 64 for (i = 0; i < NFPROTO_NUMPROTO; i++) {
64 log = rcu_dereference_protected(net->nf.nf_loggers[i], 65 log = nft_log_dereference(net->nf.nf_loggers[i]);
65 lockdep_is_held(&nf_log_mutex));
66 if (log == logger) 66 if (log == logger)
67 RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); 67 RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL);
68 } 68 }
@@ -75,6 +75,7 @@ EXPORT_SYMBOL(nf_log_unset);
75int nf_log_register(u_int8_t pf, struct nf_logger *logger) 75int nf_log_register(u_int8_t pf, struct nf_logger *logger)
76{ 76{
77 int i; 77 int i;
78 int ret = 0;
78 79
79 if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) 80 if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers))
80 return -EINVAL; 81 return -EINVAL;
@@ -82,16 +83,25 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger)
82 mutex_lock(&nf_log_mutex); 83 mutex_lock(&nf_log_mutex);
83 84
84 if (pf == NFPROTO_UNSPEC) { 85 if (pf == NFPROTO_UNSPEC) {
86 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
87 if (rcu_access_pointer(loggers[i][logger->type])) {
88 ret = -EEXIST;
89 goto unlock;
90 }
91 }
85 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) 92 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
86 rcu_assign_pointer(loggers[i][logger->type], logger); 93 rcu_assign_pointer(loggers[i][logger->type], logger);
87 } else { 94 } else {
88 /* register at end of list to honor first register win */ 95 if (rcu_access_pointer(loggers[pf][logger->type])) {
96 ret = -EEXIST;
97 goto unlock;
98 }
89 rcu_assign_pointer(loggers[pf][logger->type], logger); 99 rcu_assign_pointer(loggers[pf][logger->type], logger);
90 } 100 }
91 101
102unlock:
92 mutex_unlock(&nf_log_mutex); 103 mutex_unlock(&nf_log_mutex);
93 104 return ret;
94 return 0;
95} 105}
96EXPORT_SYMBOL(nf_log_register); 106EXPORT_SYMBOL(nf_log_register);
97 107
@@ -144,8 +154,7 @@ int nf_logger_find_get(int pf, enum nf_log_type type)
144 struct nf_logger *logger; 154 struct nf_logger *logger;
145 int ret = -ENOENT; 155 int ret = -ENOENT;
146 156
147 logger = loggers[pf][type]; 157 if (rcu_access_pointer(loggers[pf][type]) == NULL)
148 if (logger == NULL)
149 request_module("nf-logger-%u-%u", pf, type); 158 request_module("nf-logger-%u-%u", pf, type);
150 159
151 rcu_read_lock(); 160 rcu_read_lock();
@@ -297,8 +306,7 @@ static int seq_show(struct seq_file *s, void *v)
297 int i, ret; 306 int i, ret;
298 struct net *net = seq_file_net(s); 307 struct net *net = seq_file_net(s);
299 308
300 logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], 309 logger = nft_log_dereference(net->nf.nf_loggers[*pos]);
301 lockdep_is_held(&nf_log_mutex));
302 310
303 if (!logger) 311 if (!logger)
304 ret = seq_printf(s, "%2lld NONE (", *pos); 312 ret = seq_printf(s, "%2lld NONE (", *pos);
@@ -312,8 +320,7 @@ static int seq_show(struct seq_file *s, void *v)
312 if (loggers[*pos][i] == NULL) 320 if (loggers[*pos][i] == NULL)
313 continue; 321 continue;
314 322
315 logger = rcu_dereference_protected(loggers[*pos][i], 323 logger = nft_log_dereference(loggers[*pos][i]);
316 lockdep_is_held(&nf_log_mutex));
317 ret = seq_printf(s, "%s", logger->name); 324 ret = seq_printf(s, "%s", logger->name);
318 if (ret < 0) 325 if (ret < 0)
319 return ret; 326 return ret;
@@ -385,8 +392,7 @@ static int nf_log_proc_dostring(struct ctl_table *table, int write,
385 mutex_unlock(&nf_log_mutex); 392 mutex_unlock(&nf_log_mutex);
386 } else { 393 } else {
387 mutex_lock(&nf_log_mutex); 394 mutex_lock(&nf_log_mutex);
388 logger = rcu_dereference_protected(net->nf.nf_loggers[tindex], 395 logger = nft_log_dereference(net->nf.nf_loggers[tindex]);
389 lockdep_is_held(&nf_log_mutex));
390 if (!logger) 396 if (!logger)
391 table->data = "NONE"; 397 table->data = "NONE";
392 else 398 else
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 66e8425dbfe7..129a8daa4abf 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2477,7 +2477,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2477 const struct nfgenmsg *nfmsg = nlmsg_data(nlh); 2477 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
2478 int err; 2478 int err;
2479 2479
2480 /* Verify existance before starting dump */ 2480 /* Verify existence before starting dump */
2481 err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla); 2481 err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
2482 if (err < 0) 2482 if (err < 0)
2483 return err; 2483 return err;
@@ -3665,8 +3665,7 @@ static int nf_tables_abort(struct sk_buff *skb)
3665 break; 3665 break;
3666 case NFT_MSG_NEWCHAIN: 3666 case NFT_MSG_NEWCHAIN:
3667 if (nft_trans_chain_update(trans)) { 3667 if (nft_trans_chain_update(trans)) {
3668 if (nft_trans_chain_stats(trans)) 3668 free_percpu(nft_trans_chain_stats(trans));
3669 free_percpu(nft_trans_chain_stats(trans));
3670 3669
3671 nft_trans_destroy(trans); 3670 nft_trans_destroy(trans);
3672 } else { 3671 } else {
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 5f1be5ba3559..11d85b3813f2 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -12,6 +12,9 @@
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation. 13 * published by the Free Software Foundation.
14 */ 14 */
15
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
15#include <linux/module.h> 18#include <linux/module.h>
16#include <linux/skbuff.h> 19#include <linux/skbuff.h>
17#include <linux/if_arp.h> 20#include <linux/if_arp.h>
@@ -337,9 +340,6 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
337 340
338 skb = nfnetlink_alloc_skb(net, pkt_size, 341 skb = nfnetlink_alloc_skb(net, pkt_size,
339 peer_portid, GFP_ATOMIC); 342 peer_portid, GFP_ATOMIC);
340 if (!skb)
341 pr_err("nfnetlink_log: can't even alloc %u bytes\n",
342 pkt_size);
343 } 343 }
344 } 344 }
345 345
@@ -570,10 +570,8 @@ __build_packet_message(struct nfnl_log_net *log,
570 struct nlattr *nla; 570 struct nlattr *nla;
571 int size = nla_attr_size(data_len); 571 int size = nla_attr_size(data_len);
572 572
573 if (skb_tailroom(inst->skb) < nla_total_size(data_len)) { 573 if (skb_tailroom(inst->skb) < nla_total_size(data_len))
574 printk(KERN_WARNING "nfnetlink_log: no tailroom!\n"); 574 goto nla_put_failure;
575 return -1;
576 }
577 575
578 nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len)); 576 nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len));
579 nla->nla_type = NFULA_PAYLOAD; 577 nla->nla_type = NFULA_PAYLOAD;
@@ -1069,19 +1067,19 @@ static int __init nfnetlink_log_init(void)
1069 netlink_register_notifier(&nfulnl_rtnl_notifier); 1067 netlink_register_notifier(&nfulnl_rtnl_notifier);
1070 status = nfnetlink_subsys_register(&nfulnl_subsys); 1068 status = nfnetlink_subsys_register(&nfulnl_subsys);
1071 if (status < 0) { 1069 if (status < 0) {
1072 pr_err("log: failed to create netlink socket\n"); 1070 pr_err("failed to create netlink socket\n");
1073 goto cleanup_netlink_notifier; 1071 goto cleanup_netlink_notifier;
1074 } 1072 }
1075 1073
1076 status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger); 1074 status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
1077 if (status < 0) { 1075 if (status < 0) {
1078 pr_err("log: failed to register logger\n"); 1076 pr_err("failed to register logger\n");
1079 goto cleanup_subsys; 1077 goto cleanup_subsys;
1080 } 1078 }
1081 1079
1082 status = register_pernet_subsys(&nfnl_log_net_ops); 1080 status = register_pernet_subsys(&nfnl_log_net_ops);
1083 if (status < 0) { 1081 if (status < 0) {
1084 pr_err("log: failed to register pernet ops\n"); 1082 pr_err("failed to register pernet ops\n");
1085 goto cleanup_logger; 1083 goto cleanup_logger;
1086 } 1084 }
1087 return status; 1085 return status;
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 1e7c076ca63a..e99911eda915 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -165,6 +165,12 @@ void nft_meta_get_eval(const struct nft_expr *expr,
165 goto err; 165 goto err;
166 dest->data[0] = out->group; 166 dest->data[0] = out->group;
167 break; 167 break;
168 case NFT_META_CGROUP:
169 if (skb->sk == NULL)
170 break;
171
172 dest->data[0] = skb->sk->sk_classid;
173 break;
168 default: 174 default:
169 WARN_ON(1); 175 WARN_ON(1);
170 goto err; 176 goto err;
@@ -240,6 +246,7 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
240 case NFT_META_CPU: 246 case NFT_META_CPU:
241 case NFT_META_IIFGROUP: 247 case NFT_META_IIFGROUP:
242 case NFT_META_OIFGROUP: 248 case NFT_META_OIFGROUP:
249 case NFT_META_CGROUP:
243 break; 250 break;
244 default: 251 default:
245 return -EOPNOTSUPP; 252 return -EOPNOTSUPP;
diff --git a/net/netfilter/nft_redir.c b/net/netfilter/nft_redir.c
new file mode 100644
index 000000000000..9e8093f28311
--- /dev/null
+++ b/net/netfilter/nft_redir.c
@@ -0,0 +1,99 @@
1/*
2 * Copyright (c) 2014 Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
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 <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/netlink.h>
13#include <linux/netfilter.h>
14#include <linux/netfilter/nf_tables.h>
15#include <net/netfilter/nf_nat.h>
16#include <net/netfilter/nf_tables.h>
17#include <net/netfilter/nft_redir.h>
18
19const struct nla_policy nft_redir_policy[NFTA_REDIR_MAX + 1] = {
20 [NFTA_REDIR_REG_PROTO_MIN] = { .type = NLA_U32 },
21 [NFTA_REDIR_REG_PROTO_MAX] = { .type = NLA_U32 },
22 [NFTA_REDIR_FLAGS] = { .type = NLA_U32 },
23};
24EXPORT_SYMBOL_GPL(nft_redir_policy);
25
26int nft_redir_init(const struct nft_ctx *ctx,
27 const struct nft_expr *expr,
28 const struct nlattr * const tb[])
29{
30 struct nft_redir *priv = nft_expr_priv(expr);
31 int err;
32
33 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
34 if (err < 0)
35 return err;
36
37 if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
38 priv->sreg_proto_min =
39 ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MIN]));
40
41 err = nft_validate_input_register(priv->sreg_proto_min);
42 if (err < 0)
43 return err;
44
45 if (tb[NFTA_REDIR_REG_PROTO_MAX]) {
46 priv->sreg_proto_max =
47 ntohl(nla_get_be32(tb[NFTA_REDIR_REG_PROTO_MAX]));
48
49 err = nft_validate_input_register(priv->sreg_proto_max);
50 if (err < 0)
51 return err;
52 } else {
53 priv->sreg_proto_max = priv->sreg_proto_min;
54 }
55 }
56
57 if (tb[NFTA_REDIR_FLAGS]) {
58 priv->flags = ntohl(nla_get_be32(tb[NFTA_REDIR_FLAGS]));
59 if (priv->flags & ~NF_NAT_RANGE_MASK)
60 return -EINVAL;
61 }
62
63 return 0;
64}
65EXPORT_SYMBOL_GPL(nft_redir_init);
66
67int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr)
68{
69 const struct nft_redir *priv = nft_expr_priv(expr);
70
71 if (priv->sreg_proto_min) {
72 if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MIN,
73 htonl(priv->sreg_proto_min)))
74 goto nla_put_failure;
75 if (nla_put_be32(skb, NFTA_REDIR_REG_PROTO_MAX,
76 htonl(priv->sreg_proto_max)))
77 goto nla_put_failure;
78 }
79
80 if (priv->flags != 0 &&
81 nla_put_be32(skb, NFTA_REDIR_FLAGS, htonl(priv->flags)))
82 goto nla_put_failure;
83
84 return 0;
85
86nla_put_failure:
87 return -1;
88}
89EXPORT_SYMBOL_GPL(nft_redir_dump);
90
91int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
92 const struct nft_data **data)
93{
94 return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
95}
96EXPORT_SYMBOL_GPL(nft_redir_validate);
97
98MODULE_LICENSE("GPL");
99MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index ae8271652efa..3f83d38c4e5b 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -37,7 +37,8 @@ dscp_tg(struct sk_buff *skb, const struct xt_action_param *par)
37 if (!skb_make_writable(skb, sizeof(struct iphdr))) 37 if (!skb_make_writable(skb, sizeof(struct iphdr)))
38 return NF_DROP; 38 return NF_DROP;
39 39
40 ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), 40 ipv4_change_dsfield(ip_hdr(skb),
41 (__force __u8)(~XT_DSCP_MASK),
41 dinfo->dscp << XT_DSCP_SHIFT); 42 dinfo->dscp << XT_DSCP_SHIFT);
42 43
43 } 44 }
@@ -54,7 +55,8 @@ dscp_tg6(struct sk_buff *skb, const struct xt_action_param *par)
54 if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) 55 if (!skb_make_writable(skb, sizeof(struct ipv6hdr)))
55 return NF_DROP; 56 return NF_DROP;
56 57
57 ipv6_change_dsfield(ipv6_hdr(skb), (__u8)(~XT_DSCP_MASK), 58 ipv6_change_dsfield(ipv6_hdr(skb),
59 (__force __u8)(~XT_DSCP_MASK),
58 dinfo->dscp << XT_DSCP_SHIFT); 60 dinfo->dscp << XT_DSCP_SHIFT);
59 } 61 }
60 return XT_CONTINUE; 62 return XT_CONTINUE;
diff --git a/net/netfilter/xt_REDIRECT.c b/net/netfilter/xt_REDIRECT.c
index 22a10309297c..b6ec67efd900 100644
--- a/net/netfilter/xt_REDIRECT.c
+++ b/net/netfilter/xt_REDIRECT.c
@@ -26,48 +26,13 @@
26#include <net/checksum.h> 26#include <net/checksum.h>
27#include <net/protocol.h> 27#include <net/protocol.h>
28#include <net/netfilter/nf_nat.h> 28#include <net/netfilter/nf_nat.h>
29 29#include <net/netfilter/ipv4/nf_nat_redirect.h>
30static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; 30#include <net/netfilter/ipv6/nf_nat_redirect.h>
31 31
32static unsigned int 32static unsigned int
33redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) 33redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
34{ 34{
35 const struct nf_nat_range *range = par->targinfo; 35 return nf_nat_redirect_ipv6(skb, par->targinfo, par->hooknum);
36 struct nf_nat_range newrange;
37 struct in6_addr newdst;
38 enum ip_conntrack_info ctinfo;
39 struct nf_conn *ct;
40
41 ct = nf_ct_get(skb, &ctinfo);
42 if (par->hooknum == NF_INET_LOCAL_OUT)
43 newdst = loopback_addr;
44 else {
45 struct inet6_dev *idev;
46 struct inet6_ifaddr *ifa;
47 bool addr = false;
48
49 rcu_read_lock();
50 idev = __in6_dev_get(skb->dev);
51 if (idev != NULL) {
52 list_for_each_entry(ifa, &idev->addr_list, if_list) {
53 newdst = ifa->addr;
54 addr = true;
55 break;
56 }
57 }
58 rcu_read_unlock();
59
60 if (!addr)
61 return NF_DROP;
62 }
63
64 newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
65 newrange.min_addr.in6 = newdst;
66 newrange.max_addr.in6 = newdst;
67 newrange.min_proto = range->min_proto;
68 newrange.max_proto = range->max_proto;
69
70 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
71} 36}
72 37
73static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) 38static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
@@ -98,48 +63,7 @@ static int redirect_tg4_check(const struct xt_tgchk_param *par)
98static unsigned int 63static unsigned int
99redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par) 64redirect_tg4(struct sk_buff *skb, const struct xt_action_param *par)
100{ 65{
101 struct nf_conn *ct; 66 return nf_nat_redirect_ipv4(skb, par->targinfo, par->hooknum);
102 enum ip_conntrack_info ctinfo;
103 __be32 newdst;
104 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
105 struct nf_nat_range newrange;
106
107 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
108 par->hooknum == NF_INET_LOCAL_OUT);
109
110 ct = nf_ct_get(skb, &ctinfo);
111 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
112
113 /* Local packets: make them go to loopback */
114 if (par->hooknum == NF_INET_LOCAL_OUT)
115 newdst = htonl(0x7F000001);
116 else {
117 struct in_device *indev;
118 struct in_ifaddr *ifa;
119
120 newdst = 0;
121
122 rcu_read_lock();
123 indev = __in_dev_get_rcu(skb->dev);
124 if (indev && (ifa = indev->ifa_list))
125 newdst = ifa->ifa_local;
126 rcu_read_unlock();
127
128 if (!newdst)
129 return NF_DROP;
130 }
131
132 /* Transfer from original range. */
133 memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
134 memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
135 newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
136 newrange.min_addr.ip = newdst;
137 newrange.max_addr.ip = newdst;
138 newrange.min_proto = mr->range[0].min;
139 newrange.max_proto = mr->range[0].max;
140
141 /* Hand modified range to generic setup. */
142 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
143} 67}
144 68
145static struct xt_target redirect_tg_reg[] __read_mostly = { 69static struct xt_target redirect_tg_reg[] __read_mostly = {
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index fbc66bb250d5..29ba6218a820 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -134,6 +134,7 @@ static bool add_hlist(struct hlist_head *head,
134static unsigned int check_hlist(struct net *net, 134static unsigned int check_hlist(struct net *net,
135 struct hlist_head *head, 135 struct hlist_head *head,
136 const struct nf_conntrack_tuple *tuple, 136 const struct nf_conntrack_tuple *tuple,
137 u16 zone,
137 bool *addit) 138 bool *addit)
138{ 139{
139 const struct nf_conntrack_tuple_hash *found; 140 const struct nf_conntrack_tuple_hash *found;
@@ -147,8 +148,7 @@ static unsigned int check_hlist(struct net *net,
147 148
148 /* check the saved connections */ 149 /* check the saved connections */
149 hlist_for_each_entry_safe(conn, n, head, node) { 150 hlist_for_each_entry_safe(conn, n, head, node) {
150 found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, 151 found = nf_conntrack_find_get(net, zone, &conn->tuple);
151 &conn->tuple);
152 if (found == NULL) { 152 if (found == NULL) {
153 hlist_del(&conn->node); 153 hlist_del(&conn->node);
154 kmem_cache_free(connlimit_conn_cachep, conn); 154 kmem_cache_free(connlimit_conn_cachep, conn);
@@ -201,7 +201,7 @@ static unsigned int
201count_tree(struct net *net, struct rb_root *root, 201count_tree(struct net *net, struct rb_root *root,
202 const struct nf_conntrack_tuple *tuple, 202 const struct nf_conntrack_tuple *tuple,
203 const union nf_inet_addr *addr, const union nf_inet_addr *mask, 203 const union nf_inet_addr *addr, const union nf_inet_addr *mask,
204 u8 family) 204 u8 family, u16 zone)
205{ 205{
206 struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES]; 206 struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES];
207 struct rb_node **rbnode, *parent; 207 struct rb_node **rbnode, *parent;
@@ -229,7 +229,7 @@ count_tree(struct net *net, struct rb_root *root,
229 } else { 229 } else {
230 /* same source network -> be counted! */ 230 /* same source network -> be counted! */
231 unsigned int count; 231 unsigned int count;
232 count = check_hlist(net, &rbconn->hhead, tuple, &addit); 232 count = check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
233 233
234 tree_nodes_free(root, gc_nodes, gc_count); 234 tree_nodes_free(root, gc_nodes, gc_count);
235 if (!addit) 235 if (!addit)
@@ -245,7 +245,7 @@ count_tree(struct net *net, struct rb_root *root,
245 continue; 245 continue;
246 246
247 /* only used for GC on hhead, retval and 'addit' ignored */ 247 /* only used for GC on hhead, retval and 'addit' ignored */
248 check_hlist(net, &rbconn->hhead, tuple, &addit); 248 check_hlist(net, &rbconn->hhead, tuple, zone, &addit);
249 if (hlist_empty(&rbconn->hhead)) 249 if (hlist_empty(&rbconn->hhead))
250 gc_nodes[gc_count++] = rbconn; 250 gc_nodes[gc_count++] = rbconn;
251 } 251 }
@@ -290,7 +290,7 @@ static int count_them(struct net *net,
290 const struct nf_conntrack_tuple *tuple, 290 const struct nf_conntrack_tuple *tuple,
291 const union nf_inet_addr *addr, 291 const union nf_inet_addr *addr,
292 const union nf_inet_addr *mask, 292 const union nf_inet_addr *mask,
293 u_int8_t family) 293 u_int8_t family, u16 zone)
294{ 294{
295 struct rb_root *root; 295 struct rb_root *root;
296 int count; 296 int count;
@@ -306,7 +306,7 @@ static int count_them(struct net *net,
306 306
307 spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); 307 spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
308 308
309 count = count_tree(net, root, tuple, addr, mask, family); 309 count = count_tree(net, root, tuple, addr, mask, family, zone);
310 310
311 spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); 311 spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]);
312 312
@@ -324,13 +324,16 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
324 enum ip_conntrack_info ctinfo; 324 enum ip_conntrack_info ctinfo;
325 const struct nf_conn *ct; 325 const struct nf_conn *ct;
326 unsigned int connections; 326 unsigned int connections;
327 u16 zone = NF_CT_DEFAULT_ZONE;
327 328
328 ct = nf_ct_get(skb, &ctinfo); 329 ct = nf_ct_get(skb, &ctinfo);
329 if (ct != NULL) 330 if (ct != NULL) {
330 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 331 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
331 else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb), 332 zone = nf_ct_zone(ct);
332 par->family, &tuple)) 333 } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
334 par->family, &tuple)) {
333 goto hotdrop; 335 goto hotdrop;
336 }
334 337
335 if (par->family == NFPROTO_IPV6) { 338 if (par->family == NFPROTO_IPV6) {
336 const struct ipv6hdr *iph = ipv6_hdr(skb); 339 const struct ipv6hdr *iph = ipv6_hdr(skb);
@@ -343,7 +346,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
343 } 346 }
344 347
345 connections = count_them(net, info->data, tuple_ptr, &addr, 348 connections = count_them(net, info->data, tuple_ptr, &addr,
346 &info->mask, par->family); 349 &info->mask, par->family, zone);
347 if (connections == 0) 350 if (connections == 0)
348 /* kmalloc failed, drop it entirely */ 351 /* kmalloc failed, drop it entirely */
349 goto hotdrop; 352 goto hotdrop;