aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-12-25 02:21:45 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-25 02:21:45 -0500
commitc5e1fd8ccae09f574d6f978c90c2b968ee29030c (patch)
treee4485dc086ce76c4ff2ff551246255f5de0a250b
parent60b778ce519625102d3f72a2071ea72a05e990ce (diff)
parentceb98d03eac5704820f2ac1f370c9ff385e3a9f5 (diff)
Merge branch 'nf-next' of git://1984.lsi.us.es/net-next
-rw-r--r--include/linux/netfilter/Kbuild3
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h4
-rw-r--r--include/linux/netfilter/nf_conntrack_tuple_common.h27
-rw-r--r--include/linux/netfilter/nf_nat.h25
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/nfnetlink_acct.h36
-rw-r--r--include/linux/netfilter/xt_CT.h3
-rw-r--r--include/linux/netfilter/xt_nfacct.h13
-rw-r--r--include/linux/netfilter/xt_rpfilter.h23
-rw-r--r--include/linux/netfilter_ipv4/Kbuild1
-rw-r--r--include/linux/netfilter_ipv4/nf_nat.h58
-rw-r--r--include/net/ip6_route.h2
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h4
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h1
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h1
-rw-r--r--include/net/netfilter/nf_nat.h10
-rw-r--r--include/net/netfilter/nf_nat_core.h2
-rw-r--r--include/net/netfilter/nf_nat_protocol.h17
-rw-r--r--net/ipv4/fib_rules.c1
-rw-r--r--net/ipv4/fib_trie.c1
-rw-r--r--net/ipv4/netfilter/Kconfig10
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c16
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c14
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c16
-rw-r--r--net/ipv4/netfilter/ipt_rpfilter.c141
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c96
-rw-r--r--net/ipv4/netfilter/nf_nat_h323.c20
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c16
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c14
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_common.c36
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_dccp.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c10
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_sctp.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udplite.c6
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_unknown.c3
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c22
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c10
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c2
-rw-r--r--net/ipv6/netfilter/Kconfig10
-rw-r--r--net/ipv6/netfilter/Makefile1
-rw-r--r--net/ipv6/netfilter/ip6t_rpfilter.c133
-rw-r--r--net/ipv6/route.c7
-rw-r--r--net/netfilter/Kconfig18
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/ipvs/Kconfig15
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c18
-rw-r--r--net/netfilter/nf_conntrack_acct.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c15
-rw-r--r--net/netfilter/nf_conntrack_expect.c63
-rw-r--r--net/netfilter/nf_conntrack_helper.c12
-rw-r--r--net/netfilter/nf_conntrack_netlink.c82
-rw-r--r--net/netfilter/nfnetlink_acct.c352
-rw-r--r--net/netfilter/xt_CT.c8
-rw-r--r--net/netfilter/xt_connbytes.c32
-rw-r--r--net/netfilter/xt_nfacct.c76
59 files changed, 1168 insertions, 378 deletions
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
index a1b410c76fc3..e630a2ed4f18 100644
--- a/include/linux/netfilter/Kbuild
+++ b/include/linux/netfilter/Kbuild
@@ -5,7 +5,9 @@ header-y += nf_conntrack_ftp.h
5header-y += nf_conntrack_sctp.h 5header-y += nf_conntrack_sctp.h
6header-y += nf_conntrack_tcp.h 6header-y += nf_conntrack_tcp.h
7header-y += nf_conntrack_tuple_common.h 7header-y += nf_conntrack_tuple_common.h
8header-y += nf_nat.h
8header-y += nfnetlink.h 9header-y += nfnetlink.h
10header-y += nfnetlink_acct.h
9header-y += nfnetlink_compat.h 11header-y += nfnetlink_compat.h
10header-y += nfnetlink_conntrack.h 12header-y += nfnetlink_conntrack.h
11header-y += nfnetlink_log.h 13header-y += nfnetlink_log.h
@@ -21,6 +23,7 @@ header-y += xt_DSCP.h
21header-y += xt_IDLETIMER.h 23header-y += xt_IDLETIMER.h
22header-y += xt_LED.h 24header-y += xt_LED.h
23header-y += xt_MARK.h 25header-y += xt_MARK.h
26header-y += xt_nfacct.h
24header-y += xt_NFLOG.h 27header-y += xt_NFLOG.h
25header-y += xt_NFQUEUE.h 28header-y += xt_NFQUEUE.h
26header-y += xt_RATEEST.h 29header-y += xt_RATEEST.h
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
index 0d3dd66322ec..9e3a2838291b 100644
--- a/include/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -83,6 +83,10 @@ enum ip_conntrack_status {
83 /* Conntrack is a fake untracked entry */ 83 /* Conntrack is a fake untracked entry */
84 IPS_UNTRACKED_BIT = 12, 84 IPS_UNTRACKED_BIT = 12,
85 IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), 85 IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
86
87 /* Conntrack has a userspace helper. */
88 IPS_USERSPACE_HELPER_BIT = 13,
89 IPS_USERSPACE_HELPER = (1 << IPS_USERSPACE_HELPER_BIT),
86}; 90};
87 91
88/* Connection tracking event types */ 92/* Connection tracking event types */
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h
index 2ea22b018a87..2f6bbc5b8125 100644
--- a/include/linux/netfilter/nf_conntrack_tuple_common.h
+++ b/include/linux/netfilter/nf_conntrack_tuple_common.h
@@ -7,6 +7,33 @@ enum ip_conntrack_dir {
7 IP_CT_DIR_MAX 7 IP_CT_DIR_MAX
8}; 8};
9 9
10/* The protocol-specific manipulable parts of the tuple: always in
11 * network order
12 */
13union nf_conntrack_man_proto {
14 /* Add other protocols here. */
15 __be16 all;
16
17 struct {
18 __be16 port;
19 } tcp;
20 struct {
21 __be16 port;
22 } udp;
23 struct {
24 __be16 id;
25 } icmp;
26 struct {
27 __be16 port;
28 } dccp;
29 struct {
30 __be16 port;
31 } sctp;
32 struct {
33 __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
34 } gre;
35};
36
10#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) 37#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
11 38
12#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */ 39#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h
new file mode 100644
index 000000000000..8df2d13730b2
--- /dev/null
+++ b/include/linux/netfilter/nf_nat.h
@@ -0,0 +1,25 @@
1#ifndef _NETFILTER_NF_NAT_H
2#define _NETFILTER_NF_NAT_H
3
4#include <linux/netfilter.h>
5#include <linux/netfilter/nf_conntrack_tuple_common.h>
6
7#define NF_NAT_RANGE_MAP_IPS 1
8#define NF_NAT_RANGE_PROTO_SPECIFIED 2
9#define NF_NAT_RANGE_PROTO_RANDOM 4
10#define NF_NAT_RANGE_PERSISTENT 8
11
12struct nf_nat_ipv4_range {
13 unsigned int flags;
14 __be32 min_ip;
15 __be32 max_ip;
16 union nf_conntrack_man_proto min;
17 union nf_conntrack_man_proto max;
18};
19
20struct nf_nat_ipv4_multi_range_compat {
21 unsigned int rangesize;
22 struct nf_nat_ipv4_range range[1];
23};
24
25#endif /* _NETFILTER_NF_NAT_H */
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 74d33861473c..b64454c2f79f 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -48,7 +48,8 @@ struct nfgenmsg {
48#define NFNL_SUBSYS_ULOG 4 48#define NFNL_SUBSYS_ULOG 4
49#define NFNL_SUBSYS_OSF 5 49#define NFNL_SUBSYS_OSF 5
50#define NFNL_SUBSYS_IPSET 6 50#define NFNL_SUBSYS_IPSET 6
51#define NFNL_SUBSYS_COUNT 7 51#define NFNL_SUBSYS_ACCT 7
52#define NFNL_SUBSYS_COUNT 8
52 53
53#ifdef __KERNEL__ 54#ifdef __KERNEL__
54 55
diff --git a/include/linux/netfilter/nfnetlink_acct.h b/include/linux/netfilter/nfnetlink_acct.h
new file mode 100644
index 000000000000..7c4279b4ae7a
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_acct.h
@@ -0,0 +1,36 @@
1#ifndef _NFNL_ACCT_H_
2#define _NFNL_ACCT_H_
3
4#ifndef NFACCT_NAME_MAX
5#define NFACCT_NAME_MAX 32
6#endif
7
8enum nfnl_acct_msg_types {
9 NFNL_MSG_ACCT_NEW,
10 NFNL_MSG_ACCT_GET,
11 NFNL_MSG_ACCT_GET_CTRZERO,
12 NFNL_MSG_ACCT_DEL,
13 NFNL_MSG_ACCT_MAX
14};
15
16enum nfnl_acct_type {
17 NFACCT_UNSPEC,
18 NFACCT_NAME,
19 NFACCT_PKTS,
20 NFACCT_BYTES,
21 NFACCT_USE,
22 __NFACCT_MAX
23};
24#define NFACCT_MAX (__NFACCT_MAX - 1)
25
26#ifdef __KERNEL__
27
28struct nf_acct;
29
30extern struct nf_acct *nfnl_acct_find_get(const char *filter_name);
31extern void nfnl_acct_put(struct nf_acct *acct);
32extern void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct);
33
34#endif /* __KERNEL__ */
35
36#endif /* _NFNL_ACCT_H */
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h
index b56e76811c04..6390f0992f36 100644
--- a/include/linux/netfilter/xt_CT.h
+++ b/include/linux/netfilter/xt_CT.h
@@ -3,7 +3,8 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5 5
6#define XT_CT_NOTRACK 0x1 6#define XT_CT_NOTRACK 0x1
7#define XT_CT_USERSPACE_HELPER 0x2
7 8
8struct xt_ct_target_info { 9struct xt_ct_target_info {
9 __u16 flags; 10 __u16 flags;
diff --git a/include/linux/netfilter/xt_nfacct.h b/include/linux/netfilter/xt_nfacct.h
new file mode 100644
index 000000000000..3e19c8a86576
--- /dev/null
+++ b/include/linux/netfilter/xt_nfacct.h
@@ -0,0 +1,13 @@
1#ifndef _XT_NFACCT_MATCH_H
2#define _XT_NFACCT_MATCH_H
3
4#include <linux/netfilter/nfnetlink_acct.h>
5
6struct nf_acct;
7
8struct xt_nfacct_match_info {
9 char name[NFACCT_NAME_MAX];
10 struct nf_acct *nfacct;
11};
12
13#endif /* _XT_NFACCT_MATCH_H */
diff --git a/include/linux/netfilter/xt_rpfilter.h b/include/linux/netfilter/xt_rpfilter.h
new file mode 100644
index 000000000000..8358d4f71952
--- /dev/null
+++ b/include/linux/netfilter/xt_rpfilter.h
@@ -0,0 +1,23 @@
1#ifndef _XT_RPATH_H
2#define _XT_RPATH_H
3
4#include <linux/types.h>
5
6enum {
7 XT_RPFILTER_LOOSE = 1 << 0,
8 XT_RPFILTER_VALID_MARK = 1 << 1,
9 XT_RPFILTER_ACCEPT_LOCAL = 1 << 2,
10 XT_RPFILTER_INVERT = 1 << 3,
11#ifdef __KERNEL__
12 XT_RPFILTER_OPTION_MASK = XT_RPFILTER_LOOSE |
13 XT_RPFILTER_VALID_MARK |
14 XT_RPFILTER_ACCEPT_LOCAL |
15 XT_RPFILTER_INVERT,
16#endif
17};
18
19struct xt_rpfilter_info {
20 __u8 flags;
21};
22
23#endif
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
index c3b45480ecf7..f9930c87fff3 100644
--- a/include/linux/netfilter_ipv4/Kbuild
+++ b/include/linux/netfilter_ipv4/Kbuild
@@ -12,4 +12,3 @@ header-y += ipt_ah.h
12header-y += ipt_ecn.h 12header-y += ipt_ecn.h
13header-y += ipt_realm.h 13header-y += ipt_realm.h
14header-y += ipt_ttl.h 14header-y += ipt_ttl.h
15header-y += nf_nat.h
diff --git a/include/linux/netfilter_ipv4/nf_nat.h b/include/linux/netfilter_ipv4/nf_nat.h
deleted file mode 100644
index 7a861d09fc86..000000000000
--- a/include/linux/netfilter_ipv4/nf_nat.h
+++ /dev/null
@@ -1,58 +0,0 @@
1#ifndef _LINUX_NF_NAT_H
2#define _LINUX_NF_NAT_H
3
4#include <linux/types.h>
5
6#define IP_NAT_RANGE_MAP_IPS 1
7#define IP_NAT_RANGE_PROTO_SPECIFIED 2
8#define IP_NAT_RANGE_PROTO_RANDOM 4
9#define IP_NAT_RANGE_PERSISTENT 8
10
11/* The protocol-specific manipulable parts of the tuple. */
12union nf_conntrack_man_proto {
13 /* Add other protocols here. */
14 __be16 all;
15
16 struct {
17 __be16 port;
18 } tcp;
19 struct {
20 __be16 port;
21 } udp;
22 struct {
23 __be16 id;
24 } icmp;
25 struct {
26 __be16 port;
27 } dccp;
28 struct {
29 __be16 port;
30 } sctp;
31 struct {
32 __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
33 } gre;
34};
35
36/* Single range specification. */
37struct nf_nat_range {
38 /* Set to OR of flags above. */
39 unsigned int flags;
40
41 /* Inclusive: network order. */
42 __be32 min_ip, max_ip;
43
44 /* Inclusive: network order */
45 union nf_conntrack_man_proto min, max;
46};
47
48/* For backwards compat: don't use in modern code. */
49struct nf_nat_multi_range_compat {
50 unsigned int rangesize; /* Must be 1. */
51
52 /* hangs off end. */
53 struct nf_nat_range range[1];
54};
55
56#define nf_nat_multi_range nf_nat_multi_range_compat
57
58#endif
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 789d5f47d5e3..2ad92ca4e6f3 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -70,6 +70,8 @@ extern void ip6_route_input(struct sk_buff *skb);
70extern struct dst_entry * ip6_route_output(struct net *net, 70extern struct dst_entry * ip6_route_output(struct net *net,
71 const struct sock *sk, 71 const struct sock *sk,
72 struct flowi6 *fl6); 72 struct flowi6 *fl6);
73extern struct dst_entry * ip6_route_lookup(struct net *net,
74 struct flowi6 *fl6, int flags);
73 75
74extern int ip6_route_init(void); 76extern int ip6_route_init(void);
75extern void ip6_route_cleanup(void); 77extern void ip6_route_cleanup(void);
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
index 4e9c63a20db2..463ae8e16696 100644
--- a/include/net/netfilter/nf_conntrack_acct.h
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -15,8 +15,8 @@
15#include <net/netfilter/nf_conntrack_extend.h> 15#include <net/netfilter/nf_conntrack_extend.h>
16 16
17struct nf_conn_counter { 17struct nf_conn_counter {
18 u_int64_t packets; 18 atomic64_t packets;
19 u_int64_t bytes; 19 atomic64_t bytes;
20}; 20};
21 21
22static inline 22static inline
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 0f8a8c587532..4619caadd9d1 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -91,7 +91,6 @@ static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
91 91
92void nf_ct_remove_expectations(struct nf_conn *ct); 92void nf_ct_remove_expectations(struct nf_conn *ct);
93void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); 93void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
94void nf_ct_remove_userspace_expectations(void);
95 94
96/* Allocate space for an expectation: this is mandatory before calling 95/* Allocate space for an expectation: this is mandatory before calling
97 nf_ct_expect_related. You will have to call put afterwards. */ 96 nf_ct_expect_related. You will have to call put afterwards. */
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 2f8fb77bfdd1..aea3f8221be0 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -12,7 +12,6 @@
12 12
13#include <linux/netfilter/x_tables.h> 13#include <linux/netfilter/x_tables.h>
14#include <linux/netfilter/nf_conntrack_tuple_common.h> 14#include <linux/netfilter/nf_conntrack_tuple_common.h>
15#include <linux/netfilter_ipv4/nf_nat.h>
16#include <linux/list_nulls.h> 15#include <linux/list_nulls.h>
17 16
18/* A `tuple' is a structure containing the information to uniquely 17/* A `tuple' is a structure containing the information to uniquely
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index b8872df7285f..b4de990b55f1 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -1,14 +1,12 @@
1#ifndef _NF_NAT_H 1#ifndef _NF_NAT_H
2#define _NF_NAT_H 2#define _NF_NAT_H
3#include <linux/netfilter_ipv4.h> 3#include <linux/netfilter_ipv4.h>
4#include <linux/netfilter_ipv4/nf_nat.h> 4#include <linux/netfilter/nf_nat.h>
5#include <net/netfilter/nf_conntrack_tuple.h> 5#include <net/netfilter/nf_conntrack_tuple.h>
6 6
7#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
8
9enum nf_nat_manip_type { 7enum nf_nat_manip_type {
10 IP_NAT_MANIP_SRC, 8 NF_NAT_MANIP_SRC,
11 IP_NAT_MANIP_DST 9 NF_NAT_MANIP_DST
12}; 10};
13 11
14/* SRC manip occurs POST_ROUTING or LOCAL_IN */ 12/* SRC manip occurs POST_ROUTING or LOCAL_IN */
@@ -52,7 +50,7 @@ struct nf_conn_nat {
52 50
53/* Set up the info structure to map into this range. */ 51/* Set up the info structure to map into this range. */
54extern unsigned int nf_nat_setup_info(struct nf_conn *ct, 52extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
55 const struct nf_nat_range *range, 53 const struct nf_nat_ipv4_range *range,
56 enum nf_nat_manip_type maniptype); 54 enum nf_nat_manip_type maniptype);
57 55
58/* Is this tuple already taken? (not by us)*/ 56/* Is this tuple already taken? (not by us)*/
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 3dc7b98effeb..b13d8d18d595 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -20,7 +20,7 @@ extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
20static inline int nf_nat_initialized(struct nf_conn *ct, 20static inline int nf_nat_initialized(struct nf_conn *ct,
21 enum nf_nat_manip_type manip) 21 enum nf_nat_manip_type manip)
22{ 22{
23 if (manip == IP_NAT_MANIP_SRC) 23 if (manip == NF_NAT_MANIP_SRC)
24 return ct->status & IPS_SRC_NAT_DONE; 24 return ct->status & IPS_SRC_NAT_DONE;
25 else 25 else
26 return ct->status & IPS_DST_NAT_DONE; 26 return ct->status & IPS_DST_NAT_DONE;
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
index 93cc90d28e66..7b0b51165f70 100644
--- a/include/net/netfilter/nf_nat_protocol.h
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -4,14 +4,12 @@
4#include <net/netfilter/nf_nat.h> 4#include <net/netfilter/nf_nat.h>
5#include <linux/netfilter/nfnetlink_conntrack.h> 5#include <linux/netfilter/nfnetlink_conntrack.h>
6 6
7struct nf_nat_range; 7struct nf_nat_ipv4_range;
8 8
9struct nf_nat_protocol { 9struct nf_nat_protocol {
10 /* Protocol number. */ 10 /* Protocol number. */
11 unsigned int protonum; 11 unsigned int protonum;
12 12
13 struct module *me;
14
15 /* Translate a packet to the target according to manip type. 13 /* Translate a packet to the target according to manip type.
16 Return true if succeeded. */ 14 Return true if succeeded. */
17 bool (*manip_pkt)(struct sk_buff *skb, 15 bool (*manip_pkt)(struct sk_buff *skb,
@@ -30,15 +28,12 @@ struct nf_nat_protocol {
30 possible. Per-protocol part of tuple is initialized to the 28 possible. Per-protocol part of tuple is initialized to the
31 incoming packet. */ 29 incoming packet. */
32 void (*unique_tuple)(struct nf_conntrack_tuple *tuple, 30 void (*unique_tuple)(struct nf_conntrack_tuple *tuple,
33 const struct nf_nat_range *range, 31 const struct nf_nat_ipv4_range *range,
34 enum nf_nat_manip_type maniptype, 32 enum nf_nat_manip_type maniptype,
35 const struct nf_conn *ct); 33 const struct nf_conn *ct);
36 34
37 int (*range_to_nlattr)(struct sk_buff *skb,
38 const struct nf_nat_range *range);
39
40 int (*nlattr_to_range)(struct nlattr *tb[], 35 int (*nlattr_to_range)(struct nlattr *tb[],
41 struct nf_nat_range *range); 36 struct nf_nat_ipv4_range *range);
42}; 37};
43 38
44/* Protocol registration. */ 39/* Protocol registration. */
@@ -61,14 +56,12 @@ extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
61 const union nf_conntrack_man_proto *max); 56 const union nf_conntrack_man_proto *max);
62 57
63extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, 58extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
64 const struct nf_nat_range *range, 59 const struct nf_nat_ipv4_range *range,
65 enum nf_nat_manip_type maniptype, 60 enum nf_nat_manip_type maniptype,
66 const struct nf_conn *ct, 61 const struct nf_conn *ct,
67 u_int16_t *rover); 62 u_int16_t *rover);
68 63
69extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
70 const struct nf_nat_range *range);
71extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], 64extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
72 struct nf_nat_range *range); 65 struct nf_nat_ipv4_range *range);
73 66
74#endif /*_NF_NAT_PROTO_H*/ 67#endif /*_NF_NAT_PROTO_H*/
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 46339ba7a2d3..799fc790b3cf 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -67,6 +67,7 @@ int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res)
67 67
68 return err; 68 return err;
69} 69}
70EXPORT_SYMBOL_GPL(fib_lookup);
70 71
71static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, 72static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp,
72 int flags, struct fib_lookup_arg *arg) 73 int flags, struct fib_lookup_arg *arg)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 37b671185c81..d04b13ae18fe 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1607,6 +1607,7 @@ found:
1607 rcu_read_unlock(); 1607 rcu_read_unlock();
1608 return ret; 1608 return ret;
1609} 1609}
1610EXPORT_SYMBOL_GPL(fib_table_lookup);
1610 1611
1611/* 1612/*
1612 * Remove the leaf and return parent. 1613 * Remove the leaf and return parent.
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index f19f2182894c..7e1f5cdaf11e 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -82,6 +82,16 @@ config IP_NF_MATCH_ECN
82 82
83 To compile it as a module, choose M here. If unsure, say N. 83 To compile it as a module, choose M here. If unsure, say N.
84 84
85config IP_NF_MATCH_RPFILTER
86 tristate '"rpfilter" reverse path filter match support'
87 depends on NETFILTER_ADVANCED
88 ---help---
89 This option allows you to match packets whose replies would
90 go out via the interface the packet came in.
91
92 To compile it as a module, choose M here. If unsure, say N.
93 The module will be called ipt_rpfilter.
94
85config IP_NF_MATCH_TTL 95config IP_NF_MATCH_TTL
86 tristate '"ttl" match support' 96 tristate '"ttl" match support'
87 depends on NETFILTER_ADVANCED 97 depends on NETFILTER_ADVANCED
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index dca2082ec683..123dd88cea53 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
50# matches 50# matches
51obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o 51obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
52obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 52obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
53obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o
53 54
54# targets 55# targets
55obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 56obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 9931152a78b5..2f210c79dc87 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -30,9 +30,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT");
30/* FIXME: Multiple targets. --RR */ 30/* FIXME: Multiple targets. --RR */
31static int masquerade_tg_check(const struct xt_tgchk_param *par) 31static int masquerade_tg_check(const struct xt_tgchk_param *par)
32{ 32{
33 const struct nf_nat_multi_range_compat *mr = par->targinfo; 33 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
34 34
35 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 35 if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) {
36 pr_debug("bad MAP_IPS.\n"); 36 pr_debug("bad MAP_IPS.\n");
37 return -EINVAL; 37 return -EINVAL;
38 } 38 }
@@ -49,8 +49,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
49 struct nf_conn *ct; 49 struct nf_conn *ct;
50 struct nf_conn_nat *nat; 50 struct nf_conn_nat *nat;
51 enum ip_conntrack_info ctinfo; 51 enum ip_conntrack_info ctinfo;
52 struct nf_nat_range newrange; 52 struct nf_nat_ipv4_range newrange;
53 const struct nf_nat_multi_range_compat *mr; 53 const struct nf_nat_ipv4_multi_range_compat *mr;
54 const struct rtable *rt; 54 const struct rtable *rt;
55 __be32 newsrc; 55 __be32 newsrc;
56 56
@@ -79,13 +79,13 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
79 nat->masq_index = par->out->ifindex; 79 nat->masq_index = par->out->ifindex;
80 80
81 /* Transfer from original range. */ 81 /* Transfer from original range. */
82 newrange = ((struct nf_nat_range) 82 newrange = ((struct nf_nat_ipv4_range)
83 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 83 { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
84 newsrc, newsrc, 84 newsrc, newsrc,
85 mr->range[0].min, mr->range[0].max }); 85 mr->range[0].min, mr->range[0].max });
86 86
87 /* Hand modified range to generic setup. */ 87 /* Hand modified range to generic setup. */
88 return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_SRC); 88 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
89} 89}
90 90
91static int 91static int
@@ -139,7 +139,7 @@ static struct xt_target masquerade_tg_reg __read_mostly = {
139 .name = "MASQUERADE", 139 .name = "MASQUERADE",
140 .family = NFPROTO_IPV4, 140 .family = NFPROTO_IPV4,
141 .target = masquerade_tg, 141 .target = masquerade_tg,
142 .targetsize = sizeof(struct nf_nat_multi_range_compat), 142 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
143 .table = "nat", 143 .table = "nat",
144 .hooks = 1 << NF_INET_POST_ROUTING, 144 .hooks = 1 << NF_INET_POST_ROUTING,
145 .checkentry = masquerade_tg_check, 145 .checkentry = masquerade_tg_check,
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c
index 6cdb298f1035..b5bfbbabf70d 100644
--- a/net/ipv4/netfilter/ipt_NETMAP.c
+++ b/net/ipv4/netfilter/ipt_NETMAP.c
@@ -24,9 +24,9 @@ MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets");
24 24
25static int netmap_tg_check(const struct xt_tgchk_param *par) 25static int netmap_tg_check(const struct xt_tgchk_param *par)
26{ 26{
27 const struct nf_nat_multi_range_compat *mr = par->targinfo; 27 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
28 28
29 if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { 29 if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) {
30 pr_debug("bad MAP_IPS.\n"); 30 pr_debug("bad MAP_IPS.\n");
31 return -EINVAL; 31 return -EINVAL;
32 } 32 }
@@ -43,8 +43,8 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
43 struct nf_conn *ct; 43 struct nf_conn *ct;
44 enum ip_conntrack_info ctinfo; 44 enum ip_conntrack_info ctinfo;
45 __be32 new_ip, netmask; 45 __be32 new_ip, netmask;
46 const struct nf_nat_multi_range_compat *mr = par->targinfo; 46 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
47 struct nf_nat_range newrange; 47 struct nf_nat_ipv4_range newrange;
48 48
49 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || 49 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
50 par->hooknum == NF_INET_POST_ROUTING || 50 par->hooknum == NF_INET_POST_ROUTING ||
@@ -61,8 +61,8 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
61 new_ip = ip_hdr(skb)->saddr & ~netmask; 61 new_ip = ip_hdr(skb)->saddr & ~netmask;
62 new_ip |= mr->range[0].min_ip & netmask; 62 new_ip |= mr->range[0].min_ip & netmask;
63 63
64 newrange = ((struct nf_nat_range) 64 newrange = ((struct nf_nat_ipv4_range)
65 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 65 { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
66 new_ip, new_ip, 66 new_ip, new_ip,
67 mr->range[0].min, mr->range[0].max }); 67 mr->range[0].min, mr->range[0].max });
68 68
@@ -74,7 +74,7 @@ static struct xt_target netmap_tg_reg __read_mostly = {
74 .name = "NETMAP", 74 .name = "NETMAP",
75 .family = NFPROTO_IPV4, 75 .family = NFPROTO_IPV4,
76 .target = netmap_tg, 76 .target = netmap_tg,
77 .targetsize = sizeof(struct nf_nat_multi_range_compat), 77 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
78 .table = "nat", 78 .table = "nat",
79 .hooks = (1 << NF_INET_PRE_ROUTING) | 79 .hooks = (1 << NF_INET_PRE_ROUTING) |
80 (1 << NF_INET_POST_ROUTING) | 80 (1 << NF_INET_POST_ROUTING) |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c
index 18a0656505a0..7c0103a5203e 100644
--- a/net/ipv4/netfilter/ipt_REDIRECT.c
+++ b/net/ipv4/netfilter/ipt_REDIRECT.c
@@ -28,9 +28,9 @@ MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
28/* FIXME: Take multiple ranges --RR */ 28/* FIXME: Take multiple ranges --RR */
29static int redirect_tg_check(const struct xt_tgchk_param *par) 29static int redirect_tg_check(const struct xt_tgchk_param *par)
30{ 30{
31 const struct nf_nat_multi_range_compat *mr = par->targinfo; 31 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
32 32
33 if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { 33 if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) {
34 pr_debug("bad MAP_IPS.\n"); 34 pr_debug("bad MAP_IPS.\n");
35 return -EINVAL; 35 return -EINVAL;
36 } 36 }
@@ -47,8 +47,8 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
47 struct nf_conn *ct; 47 struct nf_conn *ct;
48 enum ip_conntrack_info ctinfo; 48 enum ip_conntrack_info ctinfo;
49 __be32 newdst; 49 __be32 newdst;
50 const struct nf_nat_multi_range_compat *mr = par->targinfo; 50 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
51 struct nf_nat_range newrange; 51 struct nf_nat_ipv4_range newrange;
52 52
53 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || 53 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
54 par->hooknum == NF_INET_LOCAL_OUT); 54 par->hooknum == NF_INET_LOCAL_OUT);
@@ -76,20 +76,20 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
76 } 76 }
77 77
78 /* Transfer from original range. */ 78 /* Transfer from original range. */
79 newrange = ((struct nf_nat_range) 79 newrange = ((struct nf_nat_ipv4_range)
80 { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, 80 { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
81 newdst, newdst, 81 newdst, newdst,
82 mr->range[0].min, mr->range[0].max }); 82 mr->range[0].min, mr->range[0].max });
83 83
84 /* Hand modified range to generic setup. */ 84 /* Hand modified range to generic setup. */
85 return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_DST); 85 return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
86} 86}
87 87
88static struct xt_target redirect_tg_reg __read_mostly = { 88static struct xt_target redirect_tg_reg __read_mostly = {
89 .name = "REDIRECT", 89 .name = "REDIRECT",
90 .family = NFPROTO_IPV4, 90 .family = NFPROTO_IPV4,
91 .target = redirect_tg, 91 .target = redirect_tg,
92 .targetsize = sizeof(struct nf_nat_multi_range_compat), 92 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
93 .table = "nat", 93 .table = "nat",
94 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), 94 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
95 .checkentry = redirect_tg_check, 95 .checkentry = redirect_tg_check,
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
new file mode 100644
index 000000000000..31371be8174b
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -0,0 +1,141 @@
1/*
2 * Copyright (c) 2011 Florian Westphal <fw@strlen.de>
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 * based on fib_frontend.c; Author: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9 */
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/netdevice.h>
14#include <linux/ip.h>
15#include <net/ip.h>
16#include <net/ip_fib.h>
17#include <net/route.h>
18
19#include <linux/netfilter/xt_rpfilter.h>
20#include <linux/netfilter/x_tables.h>
21
22MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
24MODULE_DESCRIPTION("iptables: ipv4 reverse path filter match");
25
26/* don't try to find route from mcast/bcast/zeronet */
27static __be32 rpfilter_get_saddr(__be32 addr)
28{
29 if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) ||
30 ipv4_is_zeronet(addr))
31 return 0;
32 return addr;
33}
34
35static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
36 const struct net_device *dev, u8 flags)
37{
38 struct fib_result res;
39 bool dev_match;
40 struct net *net = dev_net(dev);
41 int ret __maybe_unused;
42
43 if (fib_lookup(net, fl4, &res))
44 return false;
45
46 if (res.type != RTN_UNICAST) {
47 if (res.type != RTN_LOCAL || !(flags & XT_RPFILTER_ACCEPT_LOCAL))
48 return false;
49 }
50 dev_match = false;
51#ifdef CONFIG_IP_ROUTE_MULTIPATH
52 for (ret = 0; ret < res.fi->fib_nhs; ret++) {
53 struct fib_nh *nh = &res.fi->fib_nh[ret];
54
55 if (nh->nh_dev == dev) {
56 dev_match = true;
57 break;
58 }
59 }
60#else
61 if (FIB_RES_DEV(res) == dev)
62 dev_match = true;
63#endif
64 if (dev_match || flags & XT_RPFILTER_LOOSE)
65 return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;
66 return dev_match;
67}
68
69static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
70{
71 const struct xt_rpfilter_info *info;
72 const struct iphdr *iph;
73 struct flowi4 flow;
74 bool invert;
75
76 info = par->matchinfo;
77 invert = info->flags & XT_RPFILTER_INVERT;
78
79 if (par->in->flags & IFF_LOOPBACK)
80 return true ^ invert;
81
82 iph = ip_hdr(skb);
83 if (ipv4_is_multicast(iph->daddr)) {
84 if (ipv4_is_zeronet(iph->saddr))
85 return ipv4_is_local_multicast(iph->daddr) ^ invert;
86 flow.flowi4_iif = 0;
87 } else {
88 flow.flowi4_iif = dev_net(par->in)->loopback_dev->ifindex;
89 }
90
91 flow.daddr = iph->saddr;
92 flow.saddr = rpfilter_get_saddr(iph->daddr);
93 flow.flowi4_oif = 0;
94 flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
95 flow.flowi4_tos = RT_TOS(iph->tos);
96 flow.flowi4_scope = RT_SCOPE_UNIVERSE;
97
98 return rpfilter_lookup_reverse(&flow, par->in, info->flags) ^ invert;
99}
100
101static int rpfilter_check(const struct xt_mtchk_param *par)
102{
103 const struct xt_rpfilter_info *info = par->matchinfo;
104 unsigned int options = ~XT_RPFILTER_OPTION_MASK;
105 if (info->flags & options) {
106 pr_info("unknown options encountered");
107 return -EINVAL;
108 }
109
110 if (strcmp(par->table, "mangle") != 0 &&
111 strcmp(par->table, "raw") != 0) {
112 pr_info("match only valid in the \'raw\' "
113 "or \'mangle\' tables, not \'%s\'.\n", par->table);
114 return -EINVAL;
115 }
116
117 return 0;
118}
119
120static struct xt_match rpfilter_mt_reg __read_mostly = {
121 .name = "rpfilter",
122 .family = NFPROTO_IPV4,
123 .checkentry = rpfilter_check,
124 .match = rpfilter_mt,
125 .matchsize = sizeof(struct xt_rpfilter_info),
126 .hooks = (1 << NF_INET_PRE_ROUTING),
127 .me = THIS_MODULE
128};
129
130static int __init rpfilter_mt_init(void)
131{
132 return xt_register_match(&rpfilter_mt_reg);
133}
134
135static void __exit rpfilter_mt_exit(void)
136{
137 xt_unregister_match(&rpfilter_mt_reg);
138}
139
140module_init(rpfilter_mt_init);
141module_exit(rpfilter_mt_exit);
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 447bc5cfdc6c..acdd002bb540 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -30,7 +30,6 @@
30#include <net/netfilter/nf_nat_helper.h> 30#include <net/netfilter/nf_nat_helper.h>
31#include <net/netfilter/nf_conntrack_helper.h> 31#include <net/netfilter/nf_conntrack_helper.h>
32#include <net/netfilter/nf_conntrack_l3proto.h> 32#include <net/netfilter/nf_conntrack_l3proto.h>
33#include <net/netfilter/nf_conntrack_l4proto.h>
34#include <net/netfilter/nf_conntrack_zones.h> 33#include <net/netfilter/nf_conntrack_zones.h>
35 34
36static DEFINE_SPINLOCK(nf_nat_lock); 35static DEFINE_SPINLOCK(nf_nat_lock);
@@ -57,7 +56,7 @@ hash_by_src(const struct net *net, u16 zone,
57 /* Original src, to ensure we map it consistently if poss. */ 56 /* Original src, to ensure we map it consistently if poss. */
58 hash = jhash_3words((__force u32)tuple->src.u3.ip, 57 hash = jhash_3words((__force u32)tuple->src.u3.ip,
59 (__force u32)tuple->src.u.all ^ zone, 58 (__force u32)tuple->src.u.all ^ zone,
60 tuple->dst.protonum, 0); 59 tuple->dst.protonum, nf_conntrack_hash_rnd);
61 return ((u64)hash * net->ipv4.nat_htable_size) >> 32; 60 return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
62} 61}
63 62
@@ -82,14 +81,14 @@ EXPORT_SYMBOL(nf_nat_used_tuple);
82 * that meet the constraints of range. */ 81 * that meet the constraints of range. */
83static int 82static int
84in_range(const struct nf_conntrack_tuple *tuple, 83in_range(const struct nf_conntrack_tuple *tuple,
85 const struct nf_nat_range *range) 84 const struct nf_nat_ipv4_range *range)
86{ 85{
87 const struct nf_nat_protocol *proto; 86 const struct nf_nat_protocol *proto;
88 int ret = 0; 87 int ret = 0;
89 88
90 /* If we are supposed to map IPs, then we must be in the 89 /* If we are supposed to map IPs, then we must be in the
91 range specified, otherwise let this drag us onto a new src IP. */ 90 range specified, otherwise let this drag us onto a new src IP. */
92 if (range->flags & IP_NAT_RANGE_MAP_IPS) { 91 if (range->flags & NF_NAT_RANGE_MAP_IPS) {
93 if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) || 92 if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) ||
94 ntohl(tuple->src.u3.ip) > ntohl(range->max_ip)) 93 ntohl(tuple->src.u3.ip) > ntohl(range->max_ip))
95 return 0; 94 return 0;
@@ -97,8 +96,8 @@ in_range(const struct nf_conntrack_tuple *tuple,
97 96
98 rcu_read_lock(); 97 rcu_read_lock();
99 proto = __nf_nat_proto_find(tuple->dst.protonum); 98 proto = __nf_nat_proto_find(tuple->dst.protonum);
100 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || 99 if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) ||
101 proto->in_range(tuple, IP_NAT_MANIP_SRC, 100 proto->in_range(tuple, NF_NAT_MANIP_SRC,
102 &range->min, &range->max)) 101 &range->min, &range->max))
103 ret = 1; 102 ret = 1;
104 rcu_read_unlock(); 103 rcu_read_unlock();
@@ -123,7 +122,7 @@ static int
123find_appropriate_src(struct net *net, u16 zone, 122find_appropriate_src(struct net *net, u16 zone,
124 const struct nf_conntrack_tuple *tuple, 123 const struct nf_conntrack_tuple *tuple,
125 struct nf_conntrack_tuple *result, 124 struct nf_conntrack_tuple *result,
126 const struct nf_nat_range *range) 125 const struct nf_nat_ipv4_range *range)
127{ 126{
128 unsigned int h = hash_by_src(net, zone, tuple); 127 unsigned int h = hash_by_src(net, zone, tuple);
129 const struct nf_conn_nat *nat; 128 const struct nf_conn_nat *nat;
@@ -157,7 +156,7 @@ find_appropriate_src(struct net *net, u16 zone,
157*/ 156*/
158static void 157static void
159find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, 158find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
160 const struct nf_nat_range *range, 159 const struct nf_nat_ipv4_range *range,
161 const struct nf_conn *ct, 160 const struct nf_conn *ct,
162 enum nf_nat_manip_type maniptype) 161 enum nf_nat_manip_type maniptype)
163{ 162{
@@ -166,10 +165,10 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
166 u_int32_t minip, maxip, j; 165 u_int32_t minip, maxip, j;
167 166
168 /* No IP mapping? Do nothing. */ 167 /* No IP mapping? Do nothing. */
169 if (!(range->flags & IP_NAT_RANGE_MAP_IPS)) 168 if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
170 return; 169 return;
171 170
172 if (maniptype == IP_NAT_MANIP_SRC) 171 if (maniptype == NF_NAT_MANIP_SRC)
173 var_ipp = &tuple->src.u3.ip; 172 var_ipp = &tuple->src.u3.ip;
174 else 173 else
175 var_ipp = &tuple->dst.u3.ip; 174 var_ipp = &tuple->dst.u3.ip;
@@ -189,7 +188,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
189 minip = ntohl(range->min_ip); 188 minip = ntohl(range->min_ip);
190 maxip = ntohl(range->max_ip); 189 maxip = ntohl(range->max_ip);
191 j = jhash_2words((__force u32)tuple->src.u3.ip, 190 j = jhash_2words((__force u32)tuple->src.u3.ip,
192 range->flags & IP_NAT_RANGE_PERSISTENT ? 191 range->flags & NF_NAT_RANGE_PERSISTENT ?
193 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); 192 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0);
194 j = ((u64)j * (maxip - minip + 1)) >> 32; 193 j = ((u64)j * (maxip - minip + 1)) >> 32;
195 *var_ipp = htonl(minip + j); 194 *var_ipp = htonl(minip + j);
@@ -204,7 +203,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
204static void 203static void
205get_unique_tuple(struct nf_conntrack_tuple *tuple, 204get_unique_tuple(struct nf_conntrack_tuple *tuple,
206 const struct nf_conntrack_tuple *orig_tuple, 205 const struct nf_conntrack_tuple *orig_tuple,
207 const struct nf_nat_range *range, 206 const struct nf_nat_ipv4_range *range,
208 struct nf_conn *ct, 207 struct nf_conn *ct,
209 enum nf_nat_manip_type maniptype) 208 enum nf_nat_manip_type maniptype)
210{ 209{
@@ -219,8 +218,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
219 This is only required for source (ie. NAT/masq) mappings. 218 This is only required for source (ie. NAT/masq) mappings.
220 So far, we don't do local source mappings, so multiple 219 So far, we don't do local source mappings, so multiple
221 manips not an issue. */ 220 manips not an issue. */
222 if (maniptype == IP_NAT_MANIP_SRC && 221 if (maniptype == NF_NAT_MANIP_SRC &&
223 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { 222 !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
224 /* try the original tuple first */ 223 /* try the original tuple first */
225 if (in_range(orig_tuple, range)) { 224 if (in_range(orig_tuple, range)) {
226 if (!nf_nat_used_tuple(orig_tuple, ct)) { 225 if (!nf_nat_used_tuple(orig_tuple, ct)) {
@@ -247,8 +246,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
247 proto = __nf_nat_proto_find(orig_tuple->dst.protonum); 246 proto = __nf_nat_proto_find(orig_tuple->dst.protonum);
248 247
249 /* Only bother mapping if it's not already in range and unique */ 248 /* Only bother mapping if it's not already in range and unique */
250 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { 249 if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) {
251 if (range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { 250 if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) {
252 if (proto->in_range(tuple, maniptype, &range->min, 251 if (proto->in_range(tuple, maniptype, &range->min,
253 &range->max) && 252 &range->max) &&
254 (range->min.all == range->max.all || 253 (range->min.all == range->max.all ||
@@ -267,7 +266,7 @@ out:
267 266
268unsigned int 267unsigned int
269nf_nat_setup_info(struct nf_conn *ct, 268nf_nat_setup_info(struct nf_conn *ct,
270 const struct nf_nat_range *range, 269 const struct nf_nat_ipv4_range *range,
271 enum nf_nat_manip_type maniptype) 270 enum nf_nat_manip_type maniptype)
272{ 271{
273 struct net *net = nf_ct_net(ct); 272 struct net *net = nf_ct_net(ct);
@@ -284,8 +283,8 @@ nf_nat_setup_info(struct nf_conn *ct,
284 } 283 }
285 } 284 }
286 285
287 NF_CT_ASSERT(maniptype == IP_NAT_MANIP_SRC || 286 NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC ||
288 maniptype == IP_NAT_MANIP_DST); 287 maniptype == NF_NAT_MANIP_DST);
289 BUG_ON(nf_nat_initialized(ct, maniptype)); 288 BUG_ON(nf_nat_initialized(ct, maniptype));
290 289
291 /* What we've got will look like inverse of reply. Normally 290 /* What we've got will look like inverse of reply. Normally
@@ -306,13 +305,13 @@ nf_nat_setup_info(struct nf_conn *ct,
306 nf_conntrack_alter_reply(ct, &reply); 305 nf_conntrack_alter_reply(ct, &reply);
307 306
308 /* Non-atomic: we own this at the moment. */ 307 /* Non-atomic: we own this at the moment. */
309 if (maniptype == IP_NAT_MANIP_SRC) 308 if (maniptype == NF_NAT_MANIP_SRC)
310 ct->status |= IPS_SRC_NAT; 309 ct->status |= IPS_SRC_NAT;
311 else 310 else
312 ct->status |= IPS_DST_NAT; 311 ct->status |= IPS_DST_NAT;
313 } 312 }
314 313
315 if (maniptype == IP_NAT_MANIP_SRC) { 314 if (maniptype == NF_NAT_MANIP_SRC) {
316 unsigned int srchash; 315 unsigned int srchash;
317 316
318 srchash = hash_by_src(net, nf_ct_zone(ct), 317 srchash = hash_by_src(net, nf_ct_zone(ct),
@@ -327,7 +326,7 @@ nf_nat_setup_info(struct nf_conn *ct,
327 } 326 }
328 327
329 /* It's done. */ 328 /* It's done. */
330 if (maniptype == IP_NAT_MANIP_DST) 329 if (maniptype == NF_NAT_MANIP_DST)
331 ct->status |= IPS_DST_NAT_DONE; 330 ct->status |= IPS_DST_NAT_DONE;
332 else 331 else
333 ct->status |= IPS_SRC_NAT_DONE; 332 ct->status |= IPS_SRC_NAT_DONE;
@@ -361,7 +360,7 @@ manip_pkt(u_int16_t proto,
361 360
362 iph = (void *)skb->data + iphdroff; 361 iph = (void *)skb->data + iphdroff;
363 362
364 if (maniptype == IP_NAT_MANIP_SRC) { 363 if (maniptype == NF_NAT_MANIP_SRC) {
365 csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); 364 csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
366 iph->saddr = target->src.u3.ip; 365 iph->saddr = target->src.u3.ip;
367 } else { 366 } else {
@@ -381,7 +380,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct,
381 unsigned long statusbit; 380 unsigned long statusbit;
382 enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); 381 enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum);
383 382
384 if (mtype == IP_NAT_MANIP_SRC) 383 if (mtype == NF_NAT_MANIP_SRC)
385 statusbit = IPS_SRC_NAT; 384 statusbit = IPS_SRC_NAT;
386 else 385 else
387 statusbit = IPS_DST_NAT; 386 statusbit = IPS_DST_NAT;
@@ -414,8 +413,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
414 struct icmphdr icmp; 413 struct icmphdr icmp;
415 struct iphdr ip; 414 struct iphdr ip;
416 } *inside; 415 } *inside;
417 const struct nf_conntrack_l4proto *l4proto; 416 struct nf_conntrack_tuple target;
418 struct nf_conntrack_tuple inner, target;
419 int hdrlen = ip_hdrlen(skb); 417 int hdrlen = ip_hdrlen(skb);
420 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 418 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
421 unsigned long statusbit; 419 unsigned long statusbit;
@@ -447,7 +445,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
447 return 0; 445 return 0;
448 } 446 }
449 447
450 if (manip == IP_NAT_MANIP_SRC) 448 if (manip == NF_NAT_MANIP_SRC)
451 statusbit = IPS_SRC_NAT; 449 statusbit = IPS_SRC_NAT;
452 else 450 else
453 statusbit = IPS_DST_NAT; 451 statusbit = IPS_DST_NAT;
@@ -463,16 +461,6 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
463 "dir %s\n", skb, manip, 461 "dir %s\n", skb, manip,
464 dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); 462 dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");
465 463
466 /* rcu_read_lock()ed by nf_hook_slow */
467 l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol);
468
469 if (!nf_ct_get_tuple(skb, hdrlen + sizeof(struct icmphdr),
470 (hdrlen +
471 sizeof(struct icmphdr) + inside->ip.ihl * 4),
472 (u_int16_t)AF_INET, inside->ip.protocol,
473 &inner, l3proto, l4proto))
474 return 0;
475
476 /* Change inner back to look like incoming packet. We do the 464 /* Change inner back to look like incoming packet. We do the
477 opposite manip on this hook to normal, because it might not 465 opposite manip on this hook to normal, because it might not
478 pass all hooks (locally-generated ICMP). Consider incoming 466 pass all hooks (locally-generated ICMP). Consider incoming
@@ -575,26 +563,6 @@ static struct nf_ct_ext_type nat_extend __read_mostly = {
575#include <linux/netfilter/nfnetlink.h> 563#include <linux/netfilter/nfnetlink.h>
576#include <linux/netfilter/nfnetlink_conntrack.h> 564#include <linux/netfilter/nfnetlink_conntrack.h>
577 565
578static const struct nf_nat_protocol *
579nf_nat_proto_find_get(u_int8_t protonum)
580{
581 const struct nf_nat_protocol *p;
582
583 rcu_read_lock();
584 p = __nf_nat_proto_find(protonum);
585 if (!try_module_get(p->me))
586 p = &nf_nat_unknown_protocol;
587 rcu_read_unlock();
588
589 return p;
590}
591
592static void
593nf_nat_proto_put(const struct nf_nat_protocol *p)
594{
595 module_put(p->me);
596}
597
598static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { 566static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
599 [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 }, 567 [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 },
600 [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 }, 568 [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 },
@@ -602,7 +570,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = {
602 570
603static int nfnetlink_parse_nat_proto(struct nlattr *attr, 571static int nfnetlink_parse_nat_proto(struct nlattr *attr,
604 const struct nf_conn *ct, 572 const struct nf_conn *ct,
605 struct nf_nat_range *range) 573 struct nf_nat_ipv4_range *range)
606{ 574{
607 struct nlattr *tb[CTA_PROTONAT_MAX+1]; 575 struct nlattr *tb[CTA_PROTONAT_MAX+1];
608 const struct nf_nat_protocol *npt; 576 const struct nf_nat_protocol *npt;
@@ -612,21 +580,23 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
612 if (err < 0) 580 if (err < 0)
613 return err; 581 return err;
614 582
615 npt = nf_nat_proto_find_get(nf_ct_protonum(ct)); 583 rcu_read_lock();
584 npt = __nf_nat_proto_find(nf_ct_protonum(ct));
616 if (npt->nlattr_to_range) 585 if (npt->nlattr_to_range)
617 err = npt->nlattr_to_range(tb, range); 586 err = npt->nlattr_to_range(tb, range);
618 nf_nat_proto_put(npt); 587 rcu_read_unlock();
619 return err; 588 return err;
620} 589}
621 590
622static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { 591static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = {
623 [CTA_NAT_MINIP] = { .type = NLA_U32 }, 592 [CTA_NAT_MINIP] = { .type = NLA_U32 },
624 [CTA_NAT_MAXIP] = { .type = NLA_U32 }, 593 [CTA_NAT_MAXIP] = { .type = NLA_U32 },
594 [CTA_NAT_PROTO] = { .type = NLA_NESTED },
625}; 595};
626 596
627static int 597static int
628nfnetlink_parse_nat(const struct nlattr *nat, 598nfnetlink_parse_nat(const struct nlattr *nat,
629 const struct nf_conn *ct, struct nf_nat_range *range) 599 const struct nf_conn *ct, struct nf_nat_ipv4_range *range)
630{ 600{
631 struct nlattr *tb[CTA_NAT_MAX+1]; 601 struct nlattr *tb[CTA_NAT_MAX+1];
632 int err; 602 int err;
@@ -646,7 +616,7 @@ nfnetlink_parse_nat(const struct nlattr *nat,
646 range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); 616 range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]);
647 617
648 if (range->min_ip) 618 if (range->min_ip)
649 range->flags |= IP_NAT_RANGE_MAP_IPS; 619 range->flags |= NF_NAT_RANGE_MAP_IPS;
650 620
651 if (!tb[CTA_NAT_PROTO]) 621 if (!tb[CTA_NAT_PROTO])
652 return 0; 622 return 0;
@@ -663,7 +633,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct,
663 enum nf_nat_manip_type manip, 633 enum nf_nat_manip_type manip,
664 const struct nlattr *attr) 634 const struct nlattr *attr)
665{ 635{
666 struct nf_nat_range range; 636 struct nf_nat_ipv4_range range;
667 637
668 if (nfnetlink_parse_nat(attr, ct, &range) < 0) 638 if (nfnetlink_parse_nat(attr, ct, &range) < 0)
669 return -EINVAL; 639 return -EINVAL;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index b9a1136addbd..dc1dd912baf4 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -398,7 +398,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
398static void ip_nat_q931_expect(struct nf_conn *new, 398static void ip_nat_q931_expect(struct nf_conn *new,
399 struct nf_conntrack_expect *this) 399 struct nf_conntrack_expect *this)
400{ 400{
401 struct nf_nat_range range; 401 struct nf_nat_ipv4_range range;
402 402
403 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ 403 if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
404 nf_nat_follow_master(new, this); 404 nf_nat_follow_master(new, this);
@@ -409,16 +409,16 @@ static void ip_nat_q931_expect(struct nf_conn *new,
409 BUG_ON(new->status & IPS_NAT_DONE_MASK); 409 BUG_ON(new->status & IPS_NAT_DONE_MASK);
410 410
411 /* Change src to where master sends to */ 411 /* Change src to where master sends to */
412 range.flags = IP_NAT_RANGE_MAP_IPS; 412 range.flags = NF_NAT_RANGE_MAP_IPS;
413 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; 413 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
414 nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); 414 nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
415 415
416 /* For DST manip, map port here to where it's expected. */ 416 /* For DST manip, map port here to where it's expected. */
417 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 417 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
418 range.min = range.max = this->saved_proto; 418 range.min = range.max = this->saved_proto;
419 range.min_ip = range.max_ip = 419 range.min_ip = range.max_ip =
420 new->master->tuplehash[!this->dir].tuple.src.u3.ip; 420 new->master->tuplehash[!this->dir].tuple.src.u3.ip;
421 nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); 421 nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
422} 422}
423 423
424/****************************************************************************/ 424/****************************************************************************/
@@ -496,21 +496,21 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
496static void ip_nat_callforwarding_expect(struct nf_conn *new, 496static void ip_nat_callforwarding_expect(struct nf_conn *new,
497 struct nf_conntrack_expect *this) 497 struct nf_conntrack_expect *this)
498{ 498{
499 struct nf_nat_range range; 499 struct nf_nat_ipv4_range range;
500 500
501 /* This must be a fresh one. */ 501 /* This must be a fresh one. */
502 BUG_ON(new->status & IPS_NAT_DONE_MASK); 502 BUG_ON(new->status & IPS_NAT_DONE_MASK);
503 503
504 /* Change src to where master sends to */ 504 /* Change src to where master sends to */
505 range.flags = IP_NAT_RANGE_MAP_IPS; 505 range.flags = NF_NAT_RANGE_MAP_IPS;
506 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; 506 range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
507 nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); 507 nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
508 508
509 /* For DST manip, map port here to where it's expected. */ 509 /* For DST manip, map port here to where it's expected. */
510 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 510 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
511 range.min = range.max = this->saved_proto; 511 range.min = range.max = this->saved_proto;
512 range.min_ip = range.max_ip = this->saved_ip; 512 range.min_ip = range.max_ip = this->saved_ip;
513 nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); 513 nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
514} 514}
515 515
516/****************************************************************************/ 516/****************************************************************************/
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index ebc5f8894f99..af65958f6308 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -253,12 +253,6 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb,
253 struct udphdr *udph; 253 struct udphdr *udph;
254 int datalen, oldlen; 254 int datalen, oldlen;
255 255
256 /* UDP helpers might accidentally mangle the wrong packet */
257 iph = ip_hdr(skb);
258 if (skb->len < iph->ihl*4 + sizeof(*udph) +
259 match_offset + match_len)
260 return 0;
261
262 if (!skb_make_writable(skb, skb->len)) 256 if (!skb_make_writable(skb, skb->len))
263 return 0; 257 return 0;
264 258
@@ -430,22 +424,22 @@ nf_nat_seq_adjust(struct sk_buff *skb,
430void nf_nat_follow_master(struct nf_conn *ct, 424void nf_nat_follow_master(struct nf_conn *ct,
431 struct nf_conntrack_expect *exp) 425 struct nf_conntrack_expect *exp)
432{ 426{
433 struct nf_nat_range range; 427 struct nf_nat_ipv4_range range;
434 428
435 /* This must be a fresh one. */ 429 /* This must be a fresh one. */
436 BUG_ON(ct->status & IPS_NAT_DONE_MASK); 430 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
437 431
438 /* Change src to where master sends to */ 432 /* Change src to where master sends to */
439 range.flags = IP_NAT_RANGE_MAP_IPS; 433 range.flags = NF_NAT_RANGE_MAP_IPS;
440 range.min_ip = range.max_ip 434 range.min_ip = range.max_ip
441 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; 435 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
442 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); 436 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
443 437
444 /* For DST manip, map port here to where it's expected. */ 438 /* For DST manip, map port here to where it's expected. */
445 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 439 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
446 range.min = range.max = exp->saved_proto; 440 range.min = range.max = exp->saved_proto;
447 range.min_ip = range.max_ip 441 range.min_ip = range.max_ip
448 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; 442 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
449 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); 443 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
450} 444}
451EXPORT_SYMBOL(nf_nat_follow_master); 445EXPORT_SYMBOL(nf_nat_follow_master);
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 3e8284ba46b8..c273d58980ae 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -47,7 +47,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
47 struct nf_conntrack_tuple t; 47 struct nf_conntrack_tuple t;
48 const struct nf_ct_pptp_master *ct_pptp_info; 48 const struct nf_ct_pptp_master *ct_pptp_info;
49 const struct nf_nat_pptp *nat_pptp_info; 49 const struct nf_nat_pptp *nat_pptp_info;
50 struct nf_nat_range range; 50 struct nf_nat_ipv4_range range;
51 51
52 ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; 52 ct_pptp_info = &nfct_help(master)->help.ct_pptp_info;
53 nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; 53 nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
@@ -88,24 +88,24 @@ static void pptp_nat_expected(struct nf_conn *ct,
88 BUG_ON(ct->status & IPS_NAT_DONE_MASK); 88 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
89 89
90 /* Change src to where master sends to */ 90 /* Change src to where master sends to */
91 range.flags = IP_NAT_RANGE_MAP_IPS; 91 range.flags = NF_NAT_RANGE_MAP_IPS;
92 range.min_ip = range.max_ip 92 range.min_ip = range.max_ip
93 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; 93 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
94 if (exp->dir == IP_CT_DIR_ORIGINAL) { 94 if (exp->dir == IP_CT_DIR_ORIGINAL) {
95 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 95 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
96 range.min = range.max = exp->saved_proto; 96 range.min = range.max = exp->saved_proto;
97 } 97 }
98 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); 98 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
99 99
100 /* For DST manip, map port here to where it's expected. */ 100 /* For DST manip, map port here to where it's expected. */
101 range.flags = IP_NAT_RANGE_MAP_IPS; 101 range.flags = NF_NAT_RANGE_MAP_IPS;
102 range.min_ip = range.max_ip 102 range.min_ip = range.max_ip
103 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; 103 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
104 if (exp->dir == IP_CT_DIR_REPLY) { 104 if (exp->dir == IP_CT_DIR_REPLY) {
105 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 105 range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
106 range.min = range.max = exp->saved_proto; 106 range.min = range.max = exp->saved_proto;
107 } 107 }
108 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); 108 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
109} 109}
110 110
111/* outbound packets == from PNS to PAC */ 111/* outbound packets == from PNS to PAC */
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c
index a3d997618602..9993bc93e102 100644
--- a/net/ipv4/netfilter/nf_nat_proto_common.c
+++ b/net/ipv4/netfilter/nf_nat_proto_common.c
@@ -26,7 +26,7 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
26{ 26{
27 __be16 port; 27 __be16 port;
28 28
29 if (maniptype == IP_NAT_MANIP_SRC) 29 if (maniptype == NF_NAT_MANIP_SRC)
30 port = tuple->src.u.all; 30 port = tuple->src.u.all;
31 else 31 else
32 port = tuple->dst.u.all; 32 port = tuple->dst.u.all;
@@ -37,7 +37,7 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
37EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); 37EXPORT_SYMBOL_GPL(nf_nat_proto_in_range);
38 38
39void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, 39void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
40 const struct nf_nat_range *range, 40 const struct nf_nat_ipv4_range *range,
41 enum nf_nat_manip_type maniptype, 41 enum nf_nat_manip_type maniptype,
42 const struct nf_conn *ct, 42 const struct nf_conn *ct,
43 u_int16_t *rover) 43 u_int16_t *rover)
@@ -46,15 +46,15 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
46 __be16 *portptr; 46 __be16 *portptr;
47 u_int16_t off; 47 u_int16_t off;
48 48
49 if (maniptype == IP_NAT_MANIP_SRC) 49 if (maniptype == NF_NAT_MANIP_SRC)
50 portptr = &tuple->src.u.all; 50 portptr = &tuple->src.u.all;
51 else 51 else
52 portptr = &tuple->dst.u.all; 52 portptr = &tuple->dst.u.all;
53 53
54 /* If no range specified... */ 54 /* If no range specified... */
55 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { 55 if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) {
56 /* If it's dst rewrite, can't change port */ 56 /* If it's dst rewrite, can't change port */
57 if (maniptype == IP_NAT_MANIP_DST) 57 if (maniptype == NF_NAT_MANIP_DST)
58 return; 58 return;
59 59
60 if (ntohs(*portptr) < 1024) { 60 if (ntohs(*portptr) < 1024) {
@@ -75,9 +75,9 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
75 range_size = ntohs(range->max.all) - min + 1; 75 range_size = ntohs(range->max.all) - min + 1;
76 } 76 }
77 77
78 if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) 78 if (range->flags & NF_NAT_RANGE_PROTO_RANDOM)
79 off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, 79 off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip,
80 maniptype == IP_NAT_MANIP_SRC 80 maniptype == NF_NAT_MANIP_SRC
81 ? tuple->dst.u.all 81 ? tuple->dst.u.all
82 : tuple->src.u.all); 82 : tuple->src.u.all);
83 else 83 else
@@ -87,7 +87,7 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
87 *portptr = htons(min + off % range_size); 87 *portptr = htons(min + off % range_size);
88 if (++i != range_size && nf_nat_used_tuple(tuple, ct)) 88 if (++i != range_size && nf_nat_used_tuple(tuple, ct))
89 continue; 89 continue;
90 if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) 90 if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM))
91 *rover = off; 91 *rover = off;
92 return; 92 return;
93 } 93 }
@@ -96,31 +96,19 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
96EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple); 96EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple);
97 97
98#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 98#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
99int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
100 const struct nf_nat_range *range)
101{
102 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all);
103 NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all);
104 return 0;
105
106nla_put_failure:
107 return -1;
108}
109EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
110
111int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], 99int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
112 struct nf_nat_range *range) 100 struct nf_nat_ipv4_range *range)
113{ 101{
114 if (tb[CTA_PROTONAT_PORT_MIN]) { 102 if (tb[CTA_PROTONAT_PORT_MIN]) {
115 range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); 103 range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]);
116 range->max.all = range->min.tcp.port; 104 range->max.all = range->min.tcp.port;
117 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 105 range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
118 } 106 }
119 if (tb[CTA_PROTONAT_PORT_MAX]) { 107 if (tb[CTA_PROTONAT_PORT_MAX]) {
120 range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]); 108 range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]);
121 range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; 109 range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
122 } 110 }
123 return 0; 111 return 0;
124} 112}
125EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr); 113EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range);
126#endif 114#endif
diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c
index 570faf2667b2..3f67138d187c 100644
--- a/net/ipv4/netfilter/nf_nat_proto_dccp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c
@@ -24,7 +24,7 @@ static u_int16_t dccp_port_rover;
24 24
25static void 25static void
26dccp_unique_tuple(struct nf_conntrack_tuple *tuple, 26dccp_unique_tuple(struct nf_conntrack_tuple *tuple,
27 const struct nf_nat_range *range, 27 const struct nf_nat_ipv4_range *range,
28 enum nf_nat_manip_type maniptype, 28 enum nf_nat_manip_type maniptype,
29 const struct nf_conn *ct) 29 const struct nf_conn *ct)
30{ 30{
@@ -54,7 +54,7 @@ dccp_manip_pkt(struct sk_buff *skb,
54 iph = (struct iphdr *)(skb->data + iphdroff); 54 iph = (struct iphdr *)(skb->data + iphdroff);
55 hdr = (struct dccp_hdr *)(skb->data + hdroff); 55 hdr = (struct dccp_hdr *)(skb->data + hdroff);
56 56
57 if (maniptype == IP_NAT_MANIP_SRC) { 57 if (maniptype == NF_NAT_MANIP_SRC) {
58 oldip = iph->saddr; 58 oldip = iph->saddr;
59 newip = tuple->src.u3.ip; 59 newip = tuple->src.u3.ip;
60 newport = tuple->src.u.dccp.port; 60 newport = tuple->src.u.dccp.port;
@@ -80,12 +80,10 @@ dccp_manip_pkt(struct sk_buff *skb,
80 80
81static const struct nf_nat_protocol nf_nat_protocol_dccp = { 81static const struct nf_nat_protocol nf_nat_protocol_dccp = {
82 .protonum = IPPROTO_DCCP, 82 .protonum = IPPROTO_DCCP,
83 .me = THIS_MODULE,
84 .manip_pkt = dccp_manip_pkt, 83 .manip_pkt = dccp_manip_pkt,
85 .in_range = nf_nat_proto_in_range, 84 .in_range = nf_nat_proto_in_range,
86 .unique_tuple = dccp_unique_tuple, 85 .unique_tuple = dccp_unique_tuple,
87#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 86#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
88 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
89 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 87 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
90#endif 88#endif
91}; 89};
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index bc8d83a31c73..46ba0b9ab985 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -39,7 +39,7 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
39/* generate unique tuple ... */ 39/* generate unique tuple ... */
40static void 40static void
41gre_unique_tuple(struct nf_conntrack_tuple *tuple, 41gre_unique_tuple(struct nf_conntrack_tuple *tuple,
42 const struct nf_nat_range *range, 42 const struct nf_nat_ipv4_range *range,
43 enum nf_nat_manip_type maniptype, 43 enum nf_nat_manip_type maniptype,
44 const struct nf_conn *ct) 44 const struct nf_conn *ct)
45{ 45{
@@ -52,12 +52,12 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
52 if (!ct->master) 52 if (!ct->master)
53 return; 53 return;
54 54
55 if (maniptype == IP_NAT_MANIP_SRC) 55 if (maniptype == NF_NAT_MANIP_SRC)
56 keyptr = &tuple->src.u.gre.key; 56 keyptr = &tuple->src.u.gre.key;
57 else 57 else
58 keyptr = &tuple->dst.u.gre.key; 58 keyptr = &tuple->dst.u.gre.key;
59 59
60 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { 60 if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) {
61 pr_debug("%p: NATing GRE PPTP\n", ct); 61 pr_debug("%p: NATing GRE PPTP\n", ct);
62 min = 1; 62 min = 1;
63 range_size = 0xffff; 63 range_size = 0xffff;
@@ -99,7 +99,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
99 99
100 /* we only have destination manip of a packet, since 'source key' 100 /* we only have destination manip of a packet, since 'source key'
101 * is not present in the packet itself */ 101 * is not present in the packet itself */
102 if (maniptype != IP_NAT_MANIP_DST) 102 if (maniptype != NF_NAT_MANIP_DST)
103 return true; 103 return true;
104 switch (greh->version) { 104 switch (greh->version) {
105 case GRE_VERSION_1701: 105 case GRE_VERSION_1701:
@@ -119,12 +119,10 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
119 119
120static const struct nf_nat_protocol gre = { 120static const struct nf_nat_protocol gre = {
121 .protonum = IPPROTO_GRE, 121 .protonum = IPPROTO_GRE,
122 .me = THIS_MODULE,
123 .manip_pkt = gre_manip_pkt, 122 .manip_pkt = gre_manip_pkt,
124 .in_range = nf_nat_proto_in_range, 123 .in_range = nf_nat_proto_in_range,
125 .unique_tuple = gre_unique_tuple, 124 .unique_tuple = gre_unique_tuple,
126#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 125#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
127 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
128 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 126 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
129#endif 127#endif
130}; 128};
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index 9f4dc1235dc7..b35172851bae 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -30,7 +30,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
30 30
31static void 31static void
32icmp_unique_tuple(struct nf_conntrack_tuple *tuple, 32icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
33 const struct nf_nat_range *range, 33 const struct nf_nat_ipv4_range *range,
34 enum nf_nat_manip_type maniptype, 34 enum nf_nat_manip_type maniptype,
35 const struct nf_conn *ct) 35 const struct nf_conn *ct)
36{ 36{
@@ -40,7 +40,7 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
40 40
41 range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; 41 range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
42 /* If no range specified... */ 42 /* If no range specified... */
43 if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) 43 if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED))
44 range_size = 0xFFFF; 44 range_size = 0xFFFF;
45 45
46 for (i = 0; ; ++id) { 46 for (i = 0; ; ++id) {
@@ -74,12 +74,10 @@ icmp_manip_pkt(struct sk_buff *skb,
74 74
75const struct nf_nat_protocol nf_nat_protocol_icmp = { 75const struct nf_nat_protocol nf_nat_protocol_icmp = {
76 .protonum = IPPROTO_ICMP, 76 .protonum = IPPROTO_ICMP,
77 .me = THIS_MODULE,
78 .manip_pkt = icmp_manip_pkt, 77 .manip_pkt = icmp_manip_pkt,
79 .in_range = icmp_in_range, 78 .in_range = icmp_in_range,
80 .unique_tuple = icmp_unique_tuple, 79 .unique_tuple = icmp_unique_tuple,
81#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 80#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
82 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
83 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 81 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
84#endif 82#endif
85}; 83};
diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c
index bd5a80a62a5b..3cce9b6c1c29 100644
--- a/net/ipv4/netfilter/nf_nat_proto_sctp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c
@@ -19,7 +19,7 @@ static u_int16_t nf_sctp_port_rover;
19 19
20static void 20static void
21sctp_unique_tuple(struct nf_conntrack_tuple *tuple, 21sctp_unique_tuple(struct nf_conntrack_tuple *tuple,
22 const struct nf_nat_range *range, 22 const struct nf_nat_ipv4_range *range,
23 enum nf_nat_manip_type maniptype, 23 enum nf_nat_manip_type maniptype,
24 const struct nf_conn *ct) 24 const struct nf_conn *ct)
25{ 25{
@@ -46,7 +46,7 @@ sctp_manip_pkt(struct sk_buff *skb,
46 iph = (struct iphdr *)(skb->data + iphdroff); 46 iph = (struct iphdr *)(skb->data + iphdroff);
47 hdr = (struct sctphdr *)(skb->data + hdroff); 47 hdr = (struct sctphdr *)(skb->data + hdroff);
48 48
49 if (maniptype == IP_NAT_MANIP_SRC) { 49 if (maniptype == NF_NAT_MANIP_SRC) {
50 /* Get rid of src ip and src pt */ 50 /* Get rid of src ip and src pt */
51 oldip = iph->saddr; 51 oldip = iph->saddr;
52 newip = tuple->src.u3.ip; 52 newip = tuple->src.u3.ip;
@@ -70,12 +70,10 @@ sctp_manip_pkt(struct sk_buff *skb,
70 70
71static const struct nf_nat_protocol nf_nat_protocol_sctp = { 71static const struct nf_nat_protocol nf_nat_protocol_sctp = {
72 .protonum = IPPROTO_SCTP, 72 .protonum = IPPROTO_SCTP,
73 .me = THIS_MODULE,
74 .manip_pkt = sctp_manip_pkt, 73 .manip_pkt = sctp_manip_pkt,
75 .in_range = nf_nat_proto_in_range, 74 .in_range = nf_nat_proto_in_range,
76 .unique_tuple = sctp_unique_tuple, 75 .unique_tuple = sctp_unique_tuple,
77#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 76#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
78 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
79 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 77 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
80#endif 78#endif
81}; 79};
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index 0d67bb80130f..9fb4b4e72bbf 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -23,7 +23,7 @@ static u_int16_t tcp_port_rover;
23 23
24static void 24static void
25tcp_unique_tuple(struct nf_conntrack_tuple *tuple, 25tcp_unique_tuple(struct nf_conntrack_tuple *tuple,
26 const struct nf_nat_range *range, 26 const struct nf_nat_ipv4_range *range,
27 enum nf_nat_manip_type maniptype, 27 enum nf_nat_manip_type maniptype,
28 const struct nf_conn *ct) 28 const struct nf_conn *ct)
29{ 29{
@@ -55,7 +55,7 @@ tcp_manip_pkt(struct sk_buff *skb,
55 iph = (struct iphdr *)(skb->data + iphdroff); 55 iph = (struct iphdr *)(skb->data + iphdroff);
56 hdr = (struct tcphdr *)(skb->data + hdroff); 56 hdr = (struct tcphdr *)(skb->data + hdroff);
57 57
58 if (maniptype == IP_NAT_MANIP_SRC) { 58 if (maniptype == NF_NAT_MANIP_SRC) {
59 /* Get rid of src ip and src pt */ 59 /* Get rid of src ip and src pt */
60 oldip = iph->saddr; 60 oldip = iph->saddr;
61 newip = tuple->src.u3.ip; 61 newip = tuple->src.u3.ip;
@@ -82,12 +82,10 @@ tcp_manip_pkt(struct sk_buff *skb,
82 82
83const struct nf_nat_protocol nf_nat_protocol_tcp = { 83const struct nf_nat_protocol nf_nat_protocol_tcp = {
84 .protonum = IPPROTO_TCP, 84 .protonum = IPPROTO_TCP,
85 .me = THIS_MODULE,
86 .manip_pkt = tcp_manip_pkt, 85 .manip_pkt = tcp_manip_pkt,
87 .in_range = nf_nat_proto_in_range, 86 .in_range = nf_nat_proto_in_range,
88 .unique_tuple = tcp_unique_tuple, 87 .unique_tuple = tcp_unique_tuple,
89#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 88#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
90 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
91 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 89 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
92#endif 90#endif
93}; 91};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index 0b1b8601cba7..9883336e628f 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -22,7 +22,7 @@ static u_int16_t udp_port_rover;
22 22
23static void 23static void
24udp_unique_tuple(struct nf_conntrack_tuple *tuple, 24udp_unique_tuple(struct nf_conntrack_tuple *tuple,
25 const struct nf_nat_range *range, 25 const struct nf_nat_ipv4_range *range,
26 enum nf_nat_manip_type maniptype, 26 enum nf_nat_manip_type maniptype,
27 const struct nf_conn *ct) 27 const struct nf_conn *ct)
28{ 28{
@@ -47,7 +47,7 @@ udp_manip_pkt(struct sk_buff *skb,
47 iph = (struct iphdr *)(skb->data + iphdroff); 47 iph = (struct iphdr *)(skb->data + iphdroff);
48 hdr = (struct udphdr *)(skb->data + hdroff); 48 hdr = (struct udphdr *)(skb->data + hdroff);
49 49
50 if (maniptype == IP_NAT_MANIP_SRC) { 50 if (maniptype == NF_NAT_MANIP_SRC) {
51 /* Get rid of src ip and src pt */ 51 /* Get rid of src ip and src pt */
52 oldip = iph->saddr; 52 oldip = iph->saddr;
53 newip = tuple->src.u3.ip; 53 newip = tuple->src.u3.ip;
@@ -73,12 +73,10 @@ udp_manip_pkt(struct sk_buff *skb,
73 73
74const struct nf_nat_protocol nf_nat_protocol_udp = { 74const struct nf_nat_protocol nf_nat_protocol_udp = {
75 .protonum = IPPROTO_UDP, 75 .protonum = IPPROTO_UDP,
76 .me = THIS_MODULE,
77 .manip_pkt = udp_manip_pkt, 76 .manip_pkt = udp_manip_pkt,
78 .in_range = nf_nat_proto_in_range, 77 .in_range = nf_nat_proto_in_range,
79 .unique_tuple = udp_unique_tuple, 78 .unique_tuple = udp_unique_tuple,
80#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 79#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
81 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
82 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 80 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
83#endif 81#endif
84}; 82};
diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/ipv4/netfilter/nf_nat_proto_udplite.c
index f83ef23e2ab7..d24d10a7beb2 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udplite.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udplite.c
@@ -21,7 +21,7 @@ static u_int16_t udplite_port_rover;
21 21
22static void 22static void
23udplite_unique_tuple(struct nf_conntrack_tuple *tuple, 23udplite_unique_tuple(struct nf_conntrack_tuple *tuple,
24 const struct nf_nat_range *range, 24 const struct nf_nat_ipv4_range *range,
25 enum nf_nat_manip_type maniptype, 25 enum nf_nat_manip_type maniptype,
26 const struct nf_conn *ct) 26 const struct nf_conn *ct)
27{ 27{
@@ -47,7 +47,7 @@ udplite_manip_pkt(struct sk_buff *skb,
47 iph = (struct iphdr *)(skb->data + iphdroff); 47 iph = (struct iphdr *)(skb->data + iphdroff);
48 hdr = (struct udphdr *)(skb->data + hdroff); 48 hdr = (struct udphdr *)(skb->data + hdroff);
49 49
50 if (maniptype == IP_NAT_MANIP_SRC) { 50 if (maniptype == NF_NAT_MANIP_SRC) {
51 /* Get rid of src ip and src pt */ 51 /* Get rid of src ip and src pt */
52 oldip = iph->saddr; 52 oldip = iph->saddr;
53 newip = tuple->src.u3.ip; 53 newip = tuple->src.u3.ip;
@@ -72,12 +72,10 @@ udplite_manip_pkt(struct sk_buff *skb,
72 72
73static const struct nf_nat_protocol nf_nat_protocol_udplite = { 73static const struct nf_nat_protocol nf_nat_protocol_udplite = {
74 .protonum = IPPROTO_UDPLITE, 74 .protonum = IPPROTO_UDPLITE,
75 .me = THIS_MODULE,
76 .manip_pkt = udplite_manip_pkt, 75 .manip_pkt = udplite_manip_pkt,
77 .in_range = nf_nat_proto_in_range, 76 .in_range = nf_nat_proto_in_range,
78 .unique_tuple = udplite_unique_tuple, 77 .unique_tuple = udplite_unique_tuple,
79#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 78#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
80 .range_to_nlattr = nf_nat_proto_range_to_nlattr,
81 .nlattr_to_range = nf_nat_proto_nlattr_to_range, 79 .nlattr_to_range = nf_nat_proto_nlattr_to_range,
82#endif 80#endif
83}; 81};
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c
index a50f2bc1c732..e0afe8112b1c 100644
--- a/net/ipv4/netfilter/nf_nat_proto_unknown.c
+++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c
@@ -27,7 +27,7 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple,
27} 27}
28 28
29static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple, 29static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple,
30 const struct nf_nat_range *range, 30 const struct nf_nat_ipv4_range *range,
31 enum nf_nat_manip_type maniptype, 31 enum nf_nat_manip_type maniptype,
32 const struct nf_conn *ct) 32 const struct nf_conn *ct)
33{ 33{
@@ -46,7 +46,6 @@ unknown_manip_pkt(struct sk_buff *skb,
46} 46}
47 47
48const struct nf_nat_protocol nf_nat_unknown_protocol = { 48const struct nf_nat_protocol nf_nat_unknown_protocol = {
49 /* .me isn't set: getting a ref to this cannot fail. */
50 .manip_pkt = unknown_manip_pkt, 49 .manip_pkt = unknown_manip_pkt,
51 .in_range = unknown_in_range, 50 .in_range = unknown_in_range,
52 .unique_tuple = unknown_unique_tuple, 51 .unique_tuple = unknown_unique_tuple,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 733c9abc1cbd..d2a9dc314e0e 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -44,7 +44,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par)
44{ 44{
45 struct nf_conn *ct; 45 struct nf_conn *ct;
46 enum ip_conntrack_info ctinfo; 46 enum ip_conntrack_info ctinfo;
47 const struct nf_nat_multi_range_compat *mr = par->targinfo; 47 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
48 48
49 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING || 49 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING ||
50 par->hooknum == NF_INET_LOCAL_IN); 50 par->hooknum == NF_INET_LOCAL_IN);
@@ -56,7 +56,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par)
56 ctinfo == IP_CT_RELATED_REPLY)); 56 ctinfo == IP_CT_RELATED_REPLY));
57 NF_CT_ASSERT(par->out != NULL); 57 NF_CT_ASSERT(par->out != NULL);
58 58
59 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); 59 return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_SRC);
60} 60}
61 61
62static unsigned int 62static unsigned int
@@ -64,7 +64,7 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par)
64{ 64{
65 struct nf_conn *ct; 65 struct nf_conn *ct;
66 enum ip_conntrack_info ctinfo; 66 enum ip_conntrack_info ctinfo;
67 const struct nf_nat_multi_range_compat *mr = par->targinfo; 67 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
68 68
69 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || 69 NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
70 par->hooknum == NF_INET_LOCAL_OUT); 70 par->hooknum == NF_INET_LOCAL_OUT);
@@ -74,12 +74,12 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par)
74 /* Connection must be valid and new. */ 74 /* Connection must be valid and new. */
75 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); 75 NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
76 76
77 return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); 77 return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_DST);
78} 78}
79 79
80static int ipt_snat_checkentry(const struct xt_tgchk_param *par) 80static int ipt_snat_checkentry(const struct xt_tgchk_param *par)
81{ 81{
82 const struct nf_nat_multi_range_compat *mr = par->targinfo; 82 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
83 83
84 /* Must be a valid range */ 84 /* Must be a valid range */
85 if (mr->rangesize != 1) { 85 if (mr->rangesize != 1) {
@@ -91,7 +91,7 @@ static int ipt_snat_checkentry(const struct xt_tgchk_param *par)
91 91
92static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) 92static int ipt_dnat_checkentry(const struct xt_tgchk_param *par)
93{ 93{
94 const struct nf_nat_multi_range_compat *mr = par->targinfo; 94 const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
95 95
96 /* Must be a valid range */ 96 /* Must be a valid range */
97 if (mr->rangesize != 1) { 97 if (mr->rangesize != 1) {
@@ -105,13 +105,13 @@ static unsigned int
105alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) 105alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
106{ 106{
107 /* Force range to this IP; let proto decide mapping for 107 /* Force range to this IP; let proto decide mapping for
108 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). 108 per-proto parts (hence not NF_NAT_RANGE_PROTO_SPECIFIED).
109 */ 109 */
110 struct nf_nat_range range; 110 struct nf_nat_ipv4_range range;
111 111
112 range.flags = 0; 112 range.flags = 0;
113 pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, 113 pr_debug("Allocating NULL binding for %p (%pI4)\n", ct,
114 HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? 114 HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
115 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip : 115 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :
116 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); 116 &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
117 117
@@ -140,7 +140,7 @@ int nf_nat_rule_find(struct sk_buff *skb,
140static struct xt_target ipt_snat_reg __read_mostly = { 140static struct xt_target ipt_snat_reg __read_mostly = {
141 .name = "SNAT", 141 .name = "SNAT",
142 .target = ipt_snat_target, 142 .target = ipt_snat_target,
143 .targetsize = sizeof(struct nf_nat_multi_range_compat), 143 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
144 .table = "nat", 144 .table = "nat",
145 .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), 145 .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN),
146 .checkentry = ipt_snat_checkentry, 146 .checkentry = ipt_snat_checkentry,
@@ -150,7 +150,7 @@ static struct xt_target ipt_snat_reg __read_mostly = {
150static struct xt_target ipt_dnat_reg __read_mostly = { 150static struct xt_target ipt_dnat_reg __read_mostly = {
151 .name = "DNAT", 151 .name = "DNAT",
152 .target = ipt_dnat_target, 152 .target = ipt_dnat_target,
153 .targetsize = sizeof(struct nf_nat_multi_range_compat), 153 .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
154 .table = "nat", 154 .table = "nat",
155 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), 155 .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
156 .checkentry = ipt_dnat_checkentry, 156 .checkentry = ipt_dnat_checkentry,
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 78844d9208f1..d0319f96269f 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -249,25 +249,25 @@ static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off)
249static void ip_nat_sip_expected(struct nf_conn *ct, 249static void ip_nat_sip_expected(struct nf_conn *ct,
250 struct nf_conntrack_expect *exp) 250 struct nf_conntrack_expect *exp)
251{ 251{
252 struct nf_nat_range range; 252 struct nf_nat_ipv4_range range;
253 253
254 /* This must be a fresh one. */ 254 /* This must be a fresh one. */
255 BUG_ON(ct->status & IPS_NAT_DONE_MASK); 255 BUG_ON(ct->status & IPS_NAT_DONE_MASK);
256 256
257 /* For DST manip, map port here to where it's expected. */ 257 /* For DST manip, map port here to where it's expected. */
258 range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); 258 range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
259 range.min = range.max = exp->saved_proto; 259 range.min = range.max = exp->saved_proto;
260 range.min_ip = range.max_ip = exp->saved_ip; 260 range.min_ip = range.max_ip = exp->saved_ip;
261 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); 261 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
262 262
263 /* Change src to where master sends to, but only if the connection 263 /* Change src to where master sends to, but only if the connection
264 * actually came from the same source. */ 264 * actually came from the same source. */
265 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == 265 if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip ==
266 ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { 266 ct->master->tuplehash[exp->dir].tuple.src.u3.ip) {
267 range.flags = IP_NAT_RANGE_MAP_IPS; 267 range.flags = NF_NAT_RANGE_MAP_IPS;
268 range.min_ip = range.max_ip 268 range.min_ip = range.max_ip
269 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; 269 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
270 nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); 270 nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
271 } 271 }
272} 272}
273 273
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 92900482edea..3828a4229822 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -137,7 +137,7 @@ nf_nat_fn(unsigned int hooknum,
137 return ret; 137 return ret;
138 } else 138 } else
139 pr_debug("Already setup manip %s for ct %p\n", 139 pr_debug("Already setup manip %s for ct %p\n",
140 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", 140 maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
141 ct); 141 ct);
142 break; 142 break;
143 143
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index f792b34cbe9c..9a68fb5b9e77 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -125,6 +125,16 @@ config IP6_NF_MATCH_MH
125 125
126 To compile it as a module, choose M here. If unsure, say N. 126 To compile it as a module, choose M here. If unsure, say N.
127 127
128config IP6_NF_MATCH_RPFILTER
129 tristate '"rpfilter" reverse path filter match support'
130 depends on NETFILTER_ADVANCED
131 ---help---
132 This option allows you to match packets whose replies would
133 go out via the interface the packet came in.
134
135 To compile it as a module, choose M here. If unsure, say N.
136 The module will be called ip6t_rpfilter.
137
128config IP6_NF_MATCH_RT 138config IP6_NF_MATCH_RT
129 tristate '"rt" Routing header match support' 139 tristate '"rt" Routing header match support'
130 depends on NETFILTER_ADVANCED 140 depends on NETFILTER_ADVANCED
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index abfee91ce816..2eaed96db02c 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
27obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 27obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
28obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o 28obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
29obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o 29obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
30obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
30obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 31obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
31 32
32# targets 33# targets
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
new file mode 100644
index 000000000000..5d1d8b04d694
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (c) 2011 Florian Westphal <fw@strlen.de>
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#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <linux/netdevice.h>
12#include <linux/route.h>
13#include <net/ip6_fib.h>
14#include <net/ip6_route.h>
15
16#include <linux/netfilter/xt_rpfilter.h>
17#include <linux/netfilter/x_tables.h>
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
21MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match");
22
23static bool rpfilter_addr_unicast(const struct in6_addr *addr)
24{
25 int addr_type = ipv6_addr_type(addr);
26 return addr_type & IPV6_ADDR_UNICAST;
27}
28
29static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
30 const struct net_device *dev, u8 flags)
31{
32 struct rt6_info *rt;
33 struct ipv6hdr *iph = ipv6_hdr(skb);
34 bool ret = false;
35 struct flowi6 fl6 = {
36 .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,
37 .flowi6_proto = iph->nexthdr,
38 .daddr = iph->saddr,
39 };
40 int lookup_flags;
41
42 if (rpfilter_addr_unicast(&iph->daddr)) {
43 memcpy(&fl6.saddr, &iph->daddr, sizeof(struct in6_addr));
44 lookup_flags = RT6_LOOKUP_F_HAS_SADDR;
45 } else {
46 lookup_flags = 0;
47 }
48
49 fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
50 if ((flags & XT_RPFILTER_LOOSE) == 0) {
51 fl6.flowi6_oif = dev->ifindex;
52 lookup_flags |= RT6_LOOKUP_F_IFACE;
53 }
54
55 rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags);
56 if (rt->dst.error)
57 goto out;
58
59 if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST))
60 goto out;
61
62 if (rt->rt6i_flags & RTF_LOCAL) {
63 ret = flags & XT_RPFILTER_ACCEPT_LOCAL;
64 goto out;
65 }
66
67 if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
68 ret = true;
69 out:
70 dst_release(&rt->dst);
71 return ret;
72}
73
74static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
75{
76 const struct xt_rpfilter_info *info = par->matchinfo;
77 int saddrtype;
78 struct ipv6hdr *iph;
79 bool invert = info->flags & XT_RPFILTER_INVERT;
80
81 if (par->in->flags & IFF_LOOPBACK)
82 return true ^ invert;
83
84 iph = ipv6_hdr(skb);
85 saddrtype = ipv6_addr_type(&iph->saddr);
86 if (unlikely(saddrtype == IPV6_ADDR_ANY))
87 return true ^ invert; /* not routable: forward path will drop it */
88
89 return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert;
90}
91
92static int rpfilter_check(const struct xt_mtchk_param *par)
93{
94 const struct xt_rpfilter_info *info = par->matchinfo;
95 unsigned int options = ~XT_RPFILTER_OPTION_MASK;
96
97 if (info->flags & options) {
98 pr_info("unknown options encountered");
99 return -EINVAL;
100 }
101
102 if (strcmp(par->table, "mangle") != 0 &&
103 strcmp(par->table, "raw") != 0) {
104 pr_info("match only valid in the \'raw\' "
105 "or \'mangle\' tables, not \'%s\'.\n", par->table);
106 return -EINVAL;
107 }
108
109 return 0;
110}
111
112static struct xt_match rpfilter_mt_reg __read_mostly = {
113 .name = "rpfilter",
114 .family = NFPROTO_IPV6,
115 .checkentry = rpfilter_check,
116 .match = rpfilter_mt,
117 .matchsize = sizeof(struct xt_rpfilter_info),
118 .hooks = (1 << NF_INET_PRE_ROUTING),
119 .me = THIS_MODULE
120};
121
122static int __init rpfilter_mt_init(void)
123{
124 return xt_register_match(&rpfilter_mt_reg);
125}
126
127static void __exit rpfilter_mt_exit(void)
128{
129 xt_unregister_match(&rpfilter_mt_reg);
130}
131
132module_init(rpfilter_mt_init);
133module_exit(rpfilter_mt_exit);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index ad438546d915..5855e9ede3cb 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -658,6 +658,13 @@ out:
658 658
659} 659}
660 660
661struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6,
662 int flags)
663{
664 return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
665}
666EXPORT_SYMBOL_GPL(ip6_route_lookup);
667
661struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, 668struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
662 const struct in6_addr *saddr, int oif, int strict) 669 const struct in6_addr *saddr, int oif, int strict)
663{ 670{
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index d5597b759ba3..bac93ba60778 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -4,6 +4,14 @@ menu "Core Netfilter Configuration"
4config NETFILTER_NETLINK 4config NETFILTER_NETLINK
5 tristate 5 tristate
6 6
7config NETFILTER_NETLINK_ACCT
8tristate "Netfilter NFACCT over NFNETLINK interface"
9 depends on NETFILTER_ADVANCED
10 select NETFILTER_NETLINK
11 help
12 If this option is enabled, the kernel will include support
13 for extended accounting via NFNETLINK.
14
7config NETFILTER_NETLINK_QUEUE 15config NETFILTER_NETLINK_QUEUE
8 tristate "Netfilter NFQUEUE over NFNETLINK interface" 16 tristate "Netfilter NFQUEUE over NFNETLINK interface"
9 depends on NETFILTER_ADVANCED 17 depends on NETFILTER_ADVANCED
@@ -879,6 +887,16 @@ config NETFILTER_XT_MATCH_MULTIPORT
879 887
880 To compile it as a module, choose M here. If unsure, say N. 888 To compile it as a module, choose M here. If unsure, say N.
881 889
890config NETFILTER_XT_MATCH_NFACCT
891 tristate '"nfacct" match support'
892 default m if NETFILTER_ADVANCED=n
893 select NETFILTER_NETLINK_ACCT
894 help
895 This option allows you to use the extended accounting through
896 nfnetlink_acct.
897
898 To compile it as a module, choose M here. If unsure, say N.
899
882config NETFILTER_XT_MATCH_OSF 900config NETFILTER_XT_MATCH_OSF
883 tristate '"osf" Passive OS fingerprint match' 901 tristate '"osf" Passive OS fingerprint match'
884 depends on NETFILTER_ADVANCED && NETFILTER_NETLINK 902 depends on NETFILTER_ADVANCED && NETFILTER_NETLINK
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 1a02853df863..b2eee4df8168 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -7,6 +7,7 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
7obj-$(CONFIG_NETFILTER) = netfilter.o 7obj-$(CONFIG_NETFILTER) = netfilter.o
8 8
9obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o 9obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
10obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o
10obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 11obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
11obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 12obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
12 13
@@ -90,6 +91,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
90obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o 91obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
91obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o 92obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
92obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o 93obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o
94obj-$(CONFIG_NETFILTER_XT_MATCH_NFACCT) += xt_nfacct.o
93obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o 95obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o
94obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o 96obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o
95obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o 97obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index 70bd1d0774c6..af4c0b8c5275 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -232,6 +232,21 @@ config IP_VS_NQ
232 If you want to compile it in kernel, say Y. To compile it as a 232 If you want to compile it in kernel, say Y. To compile it as a
233 module, choose M here. If unsure, say N. 233 module, choose M here. If unsure, say N.
234 234
235comment 'IPVS SH scheduler'
236
237config IP_VS_SH_TAB_BITS
238 int "IPVS source hashing table size (the Nth power of 2)"
239 range 4 20
240 default 8
241 ---help---
242 The source hashing scheduler maps source IPs to destinations
243 stored in a hash table. This table is tiled by each destination
244 until all slots in the table are filled. When using weights to
245 allow destinations to receive more connections, the table is
246 tiled an amount proportional to the weights specified. The table
247 needs to be large enough to effectively fit all the destinations
248 multiplied by their respective weights.
249
235comment 'IPVS application helper' 250comment 'IPVS application helper'
236 251
237config IP_VS_FTP 252config IP_VS_FTP
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index 33815f4fb451..069e8d4d5c01 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -30,6 +30,11 @@
30 * server is dead or overloaded, the load balancer can bypass the cache 30 * server is dead or overloaded, the load balancer can bypass the cache
31 * server and send requests to the original server directly. 31 * server and send requests to the original server directly.
32 * 32 *
33 * The weight destination attribute can be used to control the
34 * distribution of connections to the destinations in servernode. The
35 * greater the weight, the more connections the destination
36 * will receive.
37 *
33 */ 38 */
34 39
35#define KMSG_COMPONENT "IPVS" 40#define KMSG_COMPONENT "IPVS"
@@ -99,9 +104,11 @@ ip_vs_sh_assign(struct ip_vs_sh_bucket *tbl, struct ip_vs_service *svc)
99 struct ip_vs_sh_bucket *b; 104 struct ip_vs_sh_bucket *b;
100 struct list_head *p; 105 struct list_head *p;
101 struct ip_vs_dest *dest; 106 struct ip_vs_dest *dest;
107 int d_count;
102 108
103 b = tbl; 109 b = tbl;
104 p = &svc->destinations; 110 p = &svc->destinations;
111 d_count = 0;
105 for (i=0; i<IP_VS_SH_TAB_SIZE; i++) { 112 for (i=0; i<IP_VS_SH_TAB_SIZE; i++) {
106 if (list_empty(p)) { 113 if (list_empty(p)) {
107 b->dest = NULL; 114 b->dest = NULL;
@@ -113,7 +120,16 @@ ip_vs_sh_assign(struct ip_vs_sh_bucket *tbl, struct ip_vs_service *svc)
113 atomic_inc(&dest->refcnt); 120 atomic_inc(&dest->refcnt);
114 b->dest = dest; 121 b->dest = dest;
115 122
116 p = p->next; 123 IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n",
124 i, IP_VS_DBG_ADDR(svc->af, &dest->addr),
125 atomic_read(&dest->weight));
126
127 /* Don't move to next dest until filling weight */
128 if (++d_count >= atomic_read(&dest->weight)) {
129 p = p->next;
130 d_count = 0;
131 }
132
117 } 133 }
118 b++; 134 b++;
119 } 135 }
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c
index bffa6b03bb79..f4f8cda05986 100644
--- a/net/netfilter/nf_conntrack_acct.c
+++ b/net/netfilter/nf_conntrack_acct.c
@@ -46,8 +46,8 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
46 return 0; 46 return 0;
47 47
48 return seq_printf(s, "packets=%llu bytes=%llu ", 48 return seq_printf(s, "packets=%llu bytes=%llu ",
49 (unsigned long long)acct[dir].packets, 49 (unsigned long long)atomic64_read(&acct[dir].packets),
50 (unsigned long long)acct[dir].bytes); 50 (unsigned long long)atomic64_read(&acct[dir].bytes));
51}; 51};
52EXPORT_SYMBOL_GPL(seq_print_acct); 52EXPORT_SYMBOL_GPL(seq_print_acct);
53 53
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index deeef74e775f..e875f8902db3 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -67,6 +67,7 @@ DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked);
67EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); 67EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked);
68 68
69unsigned int nf_conntrack_hash_rnd __read_mostly; 69unsigned int nf_conntrack_hash_rnd __read_mostly;
70EXPORT_SYMBOL_GPL(nf_conntrack_hash_rnd);
70 71
71static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone) 72static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone)
72{ 73{
@@ -1044,10 +1045,8 @@ acct:
1044 1045
1045 acct = nf_conn_acct_find(ct); 1046 acct = nf_conn_acct_find(ct);
1046 if (acct) { 1047 if (acct) {
1047 spin_lock_bh(&ct->lock); 1048 atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
1048 acct[CTINFO2DIR(ctinfo)].packets++; 1049 atomic64_add(skb->len, &acct[CTINFO2DIR(ctinfo)].bytes);
1049 acct[CTINFO2DIR(ctinfo)].bytes += skb->len;
1050 spin_unlock_bh(&ct->lock);
1051 } 1050 }
1052 } 1051 }
1053} 1052}
@@ -1063,11 +1062,9 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
1063 1062
1064 acct = nf_conn_acct_find(ct); 1063 acct = nf_conn_acct_find(ct);
1065 if (acct) { 1064 if (acct) {
1066 spin_lock_bh(&ct->lock); 1065 atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets);
1067 acct[CTINFO2DIR(ctinfo)].packets++; 1066 atomic64_add(skb->len - skb_network_offset(skb),
1068 acct[CTINFO2DIR(ctinfo)].bytes += 1067 &acct[CTINFO2DIR(ctinfo)].bytes);
1069 skb->len - skb_network_offset(skb);
1070 spin_unlock_bh(&ct->lock);
1071 } 1068 }
1072 } 1069 }
1073 1070
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 340c80d968d4..bebb1675e6ff 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -38,8 +38,6 @@ unsigned int nf_ct_expect_max __read_mostly;
38 38
39static struct kmem_cache *nf_ct_expect_cachep __read_mostly; 39static struct kmem_cache *nf_ct_expect_cachep __read_mostly;
40 40
41static HLIST_HEAD(nf_ct_userspace_expect_list);
42
43/* nf_conntrack_expect helper functions */ 41/* nf_conntrack_expect helper functions */
44void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, 42void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
45 u32 pid, int report) 43 u32 pid, int report)
@@ -47,14 +45,14 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
47 struct nf_conn_help *master_help = nfct_help(exp->master); 45 struct nf_conn_help *master_help = nfct_help(exp->master);
48 struct net *net = nf_ct_exp_net(exp); 46 struct net *net = nf_ct_exp_net(exp);
49 47
48 NF_CT_ASSERT(master_help);
50 NF_CT_ASSERT(!timer_pending(&exp->timeout)); 49 NF_CT_ASSERT(!timer_pending(&exp->timeout));
51 50
52 hlist_del_rcu(&exp->hnode); 51 hlist_del_rcu(&exp->hnode);
53 net->ct.expect_count--; 52 net->ct.expect_count--;
54 53
55 hlist_del(&exp->lnode); 54 hlist_del(&exp->lnode);
56 if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) 55 master_help->expecting[exp->class]--;
57 master_help->expecting[exp->class]--;
58 56
59 nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report); 57 nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report);
60 nf_ct_expect_put(exp); 58 nf_ct_expect_put(exp);
@@ -314,37 +312,34 @@ void nf_ct_expect_put(struct nf_conntrack_expect *exp)
314} 312}
315EXPORT_SYMBOL_GPL(nf_ct_expect_put); 313EXPORT_SYMBOL_GPL(nf_ct_expect_put);
316 314
317static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) 315static int nf_ct_expect_insert(struct nf_conntrack_expect *exp)
318{ 316{
319 struct nf_conn_help *master_help = nfct_help(exp->master); 317 struct nf_conn_help *master_help = nfct_help(exp->master);
318 struct nf_conntrack_helper *helper;
320 struct net *net = nf_ct_exp_net(exp); 319 struct net *net = nf_ct_exp_net(exp);
321 const struct nf_conntrack_expect_policy *p;
322 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); 320 unsigned int h = nf_ct_expect_dst_hash(&exp->tuple);
323 321
324 /* two references : one for hash insert, one for the timer */ 322 /* two references : one for hash insert, one for the timer */
325 atomic_add(2, &exp->use); 323 atomic_add(2, &exp->use);
326 324
327 if (master_help) { 325 hlist_add_head(&exp->lnode, &master_help->expectations);
328 hlist_add_head(&exp->lnode, &master_help->expectations); 326 master_help->expecting[exp->class]++;
329 master_help->expecting[exp->class]++;
330 } else if (exp->flags & NF_CT_EXPECT_USERSPACE)
331 hlist_add_head(&exp->lnode, &nf_ct_userspace_expect_list);
332 327
333 hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]); 328 hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]);
334 net->ct.expect_count++; 329 net->ct.expect_count++;
335 330
336 setup_timer(&exp->timeout, nf_ct_expectation_timed_out, 331 setup_timer(&exp->timeout, nf_ct_expectation_timed_out,
337 (unsigned long)exp); 332 (unsigned long)exp);
338 if (master_help) { 333 helper = rcu_dereference_protected(master_help->helper,
339 p = &rcu_dereference_protected( 334 lockdep_is_held(&nf_conntrack_lock));
340 master_help->helper, 335 if (helper) {
341 lockdep_is_held(&nf_conntrack_lock) 336 exp->timeout.expires = jiffies +
342 )->expect_policy[exp->class]; 337 helper->expect_policy[exp->class].timeout * HZ;
343 exp->timeout.expires = jiffies + p->timeout * HZ;
344 } 338 }
345 add_timer(&exp->timeout); 339 add_timer(&exp->timeout);
346 340
347 NF_CT_STAT_INC(net, expect_create); 341 NF_CT_STAT_INC(net, expect_create);
342 return 0;
348} 343}
349 344
350/* Race with expectations being used means we could have none to find; OK. */ 345/* Race with expectations being used means we could have none to find; OK. */
@@ -389,14 +384,13 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
389 struct nf_conntrack_expect *i; 384 struct nf_conntrack_expect *i;
390 struct nf_conn *master = expect->master; 385 struct nf_conn *master = expect->master;
391 struct nf_conn_help *master_help = nfct_help(master); 386 struct nf_conn_help *master_help = nfct_help(master);
387 struct nf_conntrack_helper *helper;
392 struct net *net = nf_ct_exp_net(expect); 388 struct net *net = nf_ct_exp_net(expect);
393 struct hlist_node *n; 389 struct hlist_node *n;
394 unsigned int h; 390 unsigned int h;
395 int ret = 1; 391 int ret = 1;
396 392
397 /* Don't allow expectations created from kernel-space with no helper */ 393 if (!master_help) {
398 if (!(expect->flags & NF_CT_EXPECT_USERSPACE) &&
399 (!master_help || (master_help && !master_help->helper))) {
400 ret = -ESHUTDOWN; 394 ret = -ESHUTDOWN;
401 goto out; 395 goto out;
402 } 396 }
@@ -414,11 +408,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect)
414 } 408 }
415 } 409 }
416 /* Will be over limit? */ 410 /* Will be over limit? */
417 if (master_help) { 411 helper = rcu_dereference_protected(master_help->helper,
418 p = &rcu_dereference_protected( 412 lockdep_is_held(&nf_conntrack_lock));
419 master_help->helper, 413 if (helper) {
420 lockdep_is_held(&nf_conntrack_lock) 414 p = &helper->expect_policy[expect->class];
421 )->expect_policy[expect->class];
422 if (p->max_expected && 415 if (p->max_expected &&
423 master_help->expecting[expect->class] >= p->max_expected) { 416 master_help->expecting[expect->class] >= p->max_expected) {
424 evict_oldest_expect(master, expect); 417 evict_oldest_expect(master, expect);
@@ -450,8 +443,9 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
450 if (ret <= 0) 443 if (ret <= 0)
451 goto out; 444 goto out;
452 445
453 ret = 0; 446 ret = nf_ct_expect_insert(expect);
454 nf_ct_expect_insert(expect); 447 if (ret < 0)
448 goto out;
455 spin_unlock_bh(&nf_conntrack_lock); 449 spin_unlock_bh(&nf_conntrack_lock);
456 nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report); 450 nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report);
457 return ret; 451 return ret;
@@ -461,21 +455,6 @@ out:
461} 455}
462EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); 456EXPORT_SYMBOL_GPL(nf_ct_expect_related_report);
463 457
464void nf_ct_remove_userspace_expectations(void)
465{
466 struct nf_conntrack_expect *exp;
467 struct hlist_node *n, *next;
468
469 hlist_for_each_entry_safe(exp, n, next,
470 &nf_ct_userspace_expect_list, lnode) {
471 if (del_timer(&exp->timeout)) {
472 nf_ct_unlink_expect(exp);
473 nf_ct_expect_put(exp);
474 }
475 }
476}
477EXPORT_SYMBOL_GPL(nf_ct_remove_userspace_expectations);
478
479#ifdef CONFIG_PROC_FS 458#ifdef CONFIG_PROC_FS
480struct ct_expect_iter_state { 459struct ct_expect_iter_state {
481 struct seq_net_private p; 460 struct seq_net_private p;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 93c4bdbfc1ae..c9e0de08aa87 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -121,6 +121,18 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
121 int ret = 0; 121 int ret = 0;
122 122
123 if (tmpl != NULL) { 123 if (tmpl != NULL) {
124 /* we've got a userspace helper. */
125 if (tmpl->status & IPS_USERSPACE_HELPER) {
126 help = nf_ct_helper_ext_add(ct, flags);
127 if (help == NULL) {
128 ret = -ENOMEM;
129 goto out;
130 }
131 rcu_assign_pointer(help->helper, NULL);
132 __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
133 ret = 0;
134 goto out;
135 }
124 help = nfct_help(tmpl); 136 help = nfct_help(tmpl);
125 if (help != NULL) 137 if (help != NULL)
126 helper = help->helper; 138 helper = help->helper;
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index ef21b221f036..85033344aed2 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -203,25 +203,18 @@ nla_put_failure:
203} 203}
204 204
205static int 205static int
206ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, 206dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes,
207 enum ip_conntrack_dir dir) 207 enum ip_conntrack_dir dir)
208{ 208{
209 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; 209 enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG;
210 struct nlattr *nest_count; 210 struct nlattr *nest_count;
211 const struct nf_conn_counter *acct;
212
213 acct = nf_conn_acct_find(ct);
214 if (!acct)
215 return 0;
216 211
217 nest_count = nla_nest_start(skb, type | NLA_F_NESTED); 212 nest_count = nla_nest_start(skb, type | NLA_F_NESTED);
218 if (!nest_count) 213 if (!nest_count)
219 goto nla_put_failure; 214 goto nla_put_failure;
220 215
221 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, 216 NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts));
222 cpu_to_be64(acct[dir].packets)); 217 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes));
223 NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES,
224 cpu_to_be64(acct[dir].bytes));
225 218
226 nla_nest_end(skb, nest_count); 219 nla_nest_end(skb, nest_count);
227 220
@@ -232,6 +225,27 @@ nla_put_failure:
232} 225}
233 226
234static int 227static int
228ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct,
229 enum ip_conntrack_dir dir, int type)
230{
231 struct nf_conn_counter *acct;
232 u64 pkts, bytes;
233
234 acct = nf_conn_acct_find(ct);
235 if (!acct)
236 return 0;
237
238 if (type == IPCTNL_MSG_CT_GET_CTRZERO) {
239 pkts = atomic64_xchg(&acct[dir].packets, 0);
240 bytes = atomic64_xchg(&acct[dir].bytes, 0);
241 } else {
242 pkts = atomic64_read(&acct[dir].packets);
243 bytes = atomic64_read(&acct[dir].bytes);
244 }
245 return dump_counters(skb, pkts, bytes, dir);
246}
247
248static int
235ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) 249ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct)
236{ 250{
237 struct nlattr *nest_count; 251 struct nlattr *nest_count;
@@ -393,15 +407,15 @@ nla_put_failure:
393} 407}
394 408
395static int 409static int
396ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, 410ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
397 int event, struct nf_conn *ct) 411 struct nf_conn *ct)
398{ 412{
399 struct nlmsghdr *nlh; 413 struct nlmsghdr *nlh;
400 struct nfgenmsg *nfmsg; 414 struct nfgenmsg *nfmsg;
401 struct nlattr *nest_parms; 415 struct nlattr *nest_parms;
402 unsigned int flags = pid ? NLM_F_MULTI : 0; 416 unsigned int flags = pid ? NLM_F_MULTI : 0, event;
403 417
404 event |= NFNL_SUBSYS_CTNETLINK << 8; 418 event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW);
405 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); 419 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
406 if (nlh == NULL) 420 if (nlh == NULL)
407 goto nlmsg_failure; 421 goto nlmsg_failure;
@@ -430,8 +444,8 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
430 444
431 if (ctnetlink_dump_status(skb, ct) < 0 || 445 if (ctnetlink_dump_status(skb, ct) < 0 ||
432 ctnetlink_dump_timeout(skb, ct) < 0 || 446 ctnetlink_dump_timeout(skb, ct) < 0 ||
433 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || 447 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 ||
434 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || 448 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 ||
435 ctnetlink_dump_timestamp(skb, ct) < 0 || 449 ctnetlink_dump_timestamp(skb, ct) < 0 ||
436 ctnetlink_dump_protoinfo(skb, ct) < 0 || 450 ctnetlink_dump_protoinfo(skb, ct) < 0 ||
437 ctnetlink_dump_helpinfo(skb, ct) < 0 || 451 ctnetlink_dump_helpinfo(skb, ct) < 0 ||
@@ -612,8 +626,10 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
612 goto nla_put_failure; 626 goto nla_put_failure;
613 627
614 if (events & (1 << IPCT_DESTROY)) { 628 if (events & (1 << IPCT_DESTROY)) {
615 if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || 629 if (ctnetlink_dump_counters(skb, ct,
616 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || 630 IP_CT_DIR_ORIGINAL, type) < 0 ||
631 ctnetlink_dump_counters(skb, ct,
632 IP_CT_DIR_REPLY, type) < 0 ||
617 ctnetlink_dump_timestamp(skb, ct) < 0) 633 ctnetlink_dump_timestamp(skb, ct) < 0)
618 goto nla_put_failure; 634 goto nla_put_failure;
619 } else { 635 } else {
@@ -709,20 +725,13 @@ restart:
709 } 725 }
710 if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, 726 if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
711 cb->nlh->nlmsg_seq, 727 cb->nlh->nlmsg_seq,
712 IPCTNL_MSG_CT_NEW, ct) < 0) { 728 NFNL_MSG_TYPE(
729 cb->nlh->nlmsg_type),
730 ct) < 0) {
713 nf_conntrack_get(&ct->ct_general); 731 nf_conntrack_get(&ct->ct_general);
714 cb->args[1] = (unsigned long)ct; 732 cb->args[1] = (unsigned long)ct;
715 goto out; 733 goto out;
716 } 734 }
717
718 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) ==
719 IPCTNL_MSG_CT_GET_CTRZERO) {
720 struct nf_conn_counter *acct;
721
722 acct = nf_conn_acct_find(ct);
723 if (acct)
724 memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX]));
725 }
726 } 735 }
727 if (cb->args[1]) { 736 if (cb->args[1]) {
728 cb->args[1] = 0; 737 cb->args[1] = 0;
@@ -1001,7 +1010,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
1001 1010
1002 rcu_read_lock(); 1011 rcu_read_lock();
1003 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 1012 err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq,
1004 IPCTNL_MSG_CT_NEW, ct); 1013 NFNL_MSG_TYPE(nlh->nlmsg_type), ct);
1005 rcu_read_unlock(); 1014 rcu_read_unlock();
1006 nf_ct_put(ct); 1015 nf_ct_put(ct);
1007 if (err <= 0) 1016 if (err <= 0)
@@ -1087,14 +1096,14 @@ ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[])
1087 1096
1088 if (cda[CTA_NAT_DST]) { 1097 if (cda[CTA_NAT_DST]) {
1089 ret = ctnetlink_parse_nat_setup(ct, 1098 ret = ctnetlink_parse_nat_setup(ct,
1090 IP_NAT_MANIP_DST, 1099 NF_NAT_MANIP_DST,
1091 cda[CTA_NAT_DST]); 1100 cda[CTA_NAT_DST]);
1092 if (ret < 0) 1101 if (ret < 0)
1093 return ret; 1102 return ret;
1094 } 1103 }
1095 if (cda[CTA_NAT_SRC]) { 1104 if (cda[CTA_NAT_SRC]) {
1096 ret = ctnetlink_parse_nat_setup(ct, 1105 ret = ctnetlink_parse_nat_setup(ct,
1097 IP_NAT_MANIP_SRC, 1106 NF_NAT_MANIP_SRC,
1098 cda[CTA_NAT_SRC]); 1107 cda[CTA_NAT_SRC]);
1099 if (ret < 0) 1108 if (ret < 0)
1100 return ret; 1109 return ret;
@@ -1847,7 +1856,9 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1847 if (err < 0) 1856 if (err < 0)
1848 return err; 1857 return err;
1849 1858
1850 if (cda[CTA_EXPECT_MASTER]) 1859 if (cda[CTA_EXPECT_TUPLE])
1860 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1861 else if (cda[CTA_EXPECT_MASTER])
1851 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3); 1862 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
1852 else 1863 else
1853 return -EINVAL; 1864 return -EINVAL;
@@ -2023,6 +2034,10 @@ ctnetlink_create_expect(struct net *net, u16 zone,
2023 } 2034 }
2024 help = nfct_help(ct); 2035 help = nfct_help(ct);
2025 if (!help) { 2036 if (!help) {
2037 err = -EOPNOTSUPP;
2038 goto out;
2039 }
2040 if (test_bit(IPS_USERSPACE_HELPER_BIT, &ct->status)) {
2026 if (!cda[CTA_EXPECT_TIMEOUT]) { 2041 if (!cda[CTA_EXPECT_TIMEOUT]) {
2027 err = -EINVAL; 2042 err = -EINVAL;
2028 goto out; 2043 goto out;
@@ -2247,7 +2262,6 @@ static void __exit ctnetlink_exit(void)
2247{ 2262{
2248 pr_info("ctnetlink: unregistering from nfnetlink.\n"); 2263 pr_info("ctnetlink: unregistering from nfnetlink.\n");
2249 2264
2250 nf_ct_remove_userspace_expectations();
2251 unregister_pernet_subsys(&ctnetlink_net_ops); 2265 unregister_pernet_subsys(&ctnetlink_net_ops);
2252 nfnetlink_subsys_unregister(&ctnl_exp_subsys); 2266 nfnetlink_subsys_unregister(&ctnl_exp_subsys);
2253 nfnetlink_subsys_unregister(&ctnl_subsys); 2267 nfnetlink_subsys_unregister(&ctnl_subsys);
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c
new file mode 100644
index 000000000000..362ab6ca3dc1
--- /dev/null
+++ b/net/netfilter/nfnetlink_acct.c
@@ -0,0 +1,352 @@
1/*
2 * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2011 Intra2net AG <http://www.intra2net.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation (or any later at your option).
8 */
9#include <linux/init.h>
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/skbuff.h>
13#include <linux/netlink.h>
14#include <linux/rculist.h>
15#include <linux/slab.h>
16#include <linux/types.h>
17#include <linux/errno.h>
18#include <net/netlink.h>
19#include <net/sock.h>
20#include <asm/atomic.h>
21
22#include <linux/netfilter.h>
23#include <linux/netfilter/nfnetlink.h>
24#include <linux/netfilter/nfnetlink_acct.h>
25
26MODULE_LICENSE("GPL");
27MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
28MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure");
29
30static LIST_HEAD(nfnl_acct_list);
31
32struct nf_acct {
33 atomic64_t pkts;
34 atomic64_t bytes;
35 struct list_head head;
36 atomic_t refcnt;
37 char name[NFACCT_NAME_MAX];
38 struct rcu_head rcu_head;
39};
40
41static int
42nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
43 const struct nlmsghdr *nlh, const struct nlattr * const tb[])
44{
45 struct nf_acct *nfacct, *matching = NULL;
46 char *acct_name;
47
48 if (!tb[NFACCT_NAME])
49 return -EINVAL;
50
51 acct_name = nla_data(tb[NFACCT_NAME]);
52
53 list_for_each_entry(nfacct, &nfnl_acct_list, head) {
54 if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
55 continue;
56
57 if (nlh->nlmsg_flags & NLM_F_EXCL)
58 return -EEXIST;
59
60 matching = nfacct;
61 break;
62 }
63
64 if (matching) {
65 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
66 /* reset counters if you request a replacement. */
67 atomic64_set(&matching->pkts, 0);
68 atomic64_set(&matching->bytes, 0);
69 return 0;
70 }
71 return -EBUSY;
72 }
73
74 nfacct = kzalloc(sizeof(struct nf_acct), GFP_KERNEL);
75 if (nfacct == NULL)
76 return -ENOMEM;
77
78 strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX);
79
80 if (tb[NFACCT_BYTES]) {
81 atomic64_set(&nfacct->bytes,
82 be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES])));
83 }
84 if (tb[NFACCT_PKTS]) {
85 atomic64_set(&nfacct->pkts,
86 be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS])));
87 }
88 atomic_set(&nfacct->refcnt, 1);
89 list_add_tail_rcu(&nfacct->head, &nfnl_acct_list);
90 return 0;
91}
92
93static int
94nfnl_acct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
95 int event, struct nf_acct *acct)
96{
97 struct nlmsghdr *nlh;
98 struct nfgenmsg *nfmsg;
99 unsigned int flags = pid ? NLM_F_MULTI : 0;
100 u64 pkts, bytes;
101
102 event |= NFNL_SUBSYS_ACCT << 8;
103 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
104 if (nlh == NULL)
105 goto nlmsg_failure;
106
107 nfmsg = nlmsg_data(nlh);
108 nfmsg->nfgen_family = AF_UNSPEC;
109 nfmsg->version = NFNETLINK_V0;
110 nfmsg->res_id = 0;
111
112 NLA_PUT_STRING(skb, NFACCT_NAME, acct->name);
113
114 if (type == NFNL_MSG_ACCT_GET_CTRZERO) {
115 pkts = atomic64_xchg(&acct->pkts, 0);
116 bytes = atomic64_xchg(&acct->bytes, 0);
117 } else {
118 pkts = atomic64_read(&acct->pkts);
119 bytes = atomic64_read(&acct->bytes);
120 }
121 NLA_PUT_BE64(skb, NFACCT_PKTS, cpu_to_be64(pkts));
122 NLA_PUT_BE64(skb, NFACCT_BYTES, cpu_to_be64(bytes));
123 NLA_PUT_BE32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt)));
124
125 nlmsg_end(skb, nlh);
126 return skb->len;
127
128nlmsg_failure:
129nla_put_failure:
130 nlmsg_cancel(skb, nlh);
131 return -1;
132}
133
134static int
135nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb)
136{
137 struct nf_acct *cur, *last;
138
139 if (cb->args[2])
140 return 0;
141
142 last = (struct nf_acct *)cb->args[1];
143 if (cb->args[1])
144 cb->args[1] = 0;
145
146 rcu_read_lock();
147 list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {
148 if (last && cur != last)
149 continue;
150
151 if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).pid,
152 cb->nlh->nlmsg_seq,
153 NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
154 NFNL_MSG_ACCT_NEW, cur) < 0) {
155 cb->args[1] = (unsigned long)cur;
156 break;
157 }
158 }
159 if (!cb->args[1])
160 cb->args[2] = 1;
161 rcu_read_unlock();
162 return skb->len;
163}
164
165static int
166nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb,
167 const struct nlmsghdr *nlh, const struct nlattr * const tb[])
168{
169 int ret = 0;
170 struct nf_acct *cur;
171 char *acct_name;
172
173 if (nlh->nlmsg_flags & NLM_F_DUMP) {
174 return netlink_dump_start(nfnl, skb, nlh, nfnl_acct_dump,
175 NULL, 0);
176 }
177
178 if (!tb[NFACCT_NAME])
179 return -EINVAL;
180 acct_name = nla_data(tb[NFACCT_NAME]);
181
182 list_for_each_entry(cur, &nfnl_acct_list, head) {
183 struct sk_buff *skb2;
184
185 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
186 continue;
187
188 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
189 if (skb2 == NULL)
190 break;
191
192 ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).pid,
193 nlh->nlmsg_seq,
194 NFNL_MSG_TYPE(nlh->nlmsg_type),
195 NFNL_MSG_ACCT_NEW, cur);
196 if (ret <= 0)
197 kfree_skb(skb2);
198
199 break;
200 }
201 return ret;
202}
203
204/* try to delete object, fail if it is still in use. */
205static int nfnl_acct_try_del(struct nf_acct *cur)
206{
207 int ret = 0;
208
209 /* we want to avoid races with nfnl_acct_find_get. */
210 if (atomic_dec_and_test(&cur->refcnt)) {
211 /* We are protected by nfnl mutex. */
212 list_del_rcu(&cur->head);
213 kfree_rcu(cur, rcu_head);
214 } else {
215 /* still in use, restore reference counter. */
216 atomic_inc(&cur->refcnt);
217 ret = -EBUSY;
218 }
219 return ret;
220}
221
222static int
223nfnl_acct_del(struct sock *nfnl, struct sk_buff *skb,
224 const struct nlmsghdr *nlh, const struct nlattr * const tb[])
225{
226 char *acct_name;
227 struct nf_acct *cur;
228 int ret = -ENOENT;
229
230 if (!tb[NFACCT_NAME]) {
231 list_for_each_entry(cur, &nfnl_acct_list, head)
232 nfnl_acct_try_del(cur);
233
234 return 0;
235 }
236 acct_name = nla_data(tb[NFACCT_NAME]);
237
238 list_for_each_entry(cur, &nfnl_acct_list, head) {
239 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0)
240 continue;
241
242 ret = nfnl_acct_try_del(cur);
243 if (ret < 0)
244 return ret;
245
246 break;
247 }
248 return ret;
249}
250
251static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = {
252 [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 },
253 [NFACCT_BYTES] = { .type = NLA_U64 },
254 [NFACCT_PKTS] = { .type = NLA_U64 },
255};
256
257static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = {
258 [NFNL_MSG_ACCT_NEW] = { .call = nfnl_acct_new,
259 .attr_count = NFACCT_MAX,
260 .policy = nfnl_acct_policy },
261 [NFNL_MSG_ACCT_GET] = { .call = nfnl_acct_get,
262 .attr_count = NFACCT_MAX,
263 .policy = nfnl_acct_policy },
264 [NFNL_MSG_ACCT_GET_CTRZERO] = { .call = nfnl_acct_get,
265 .attr_count = NFACCT_MAX,
266 .policy = nfnl_acct_policy },
267 [NFNL_MSG_ACCT_DEL] = { .call = nfnl_acct_del,
268 .attr_count = NFACCT_MAX,
269 .policy = nfnl_acct_policy },
270};
271
272static const struct nfnetlink_subsystem nfnl_acct_subsys = {
273 .name = "acct",
274 .subsys_id = NFNL_SUBSYS_ACCT,
275 .cb_count = NFNL_MSG_ACCT_MAX,
276 .cb = nfnl_acct_cb,
277};
278
279MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT);
280
281struct nf_acct *nfnl_acct_find_get(const char *acct_name)
282{
283 struct nf_acct *cur, *acct = NULL;
284
285 rcu_read_lock();
286 list_for_each_entry_rcu(cur, &nfnl_acct_list, head) {
287 if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0)
288 continue;
289
290 if (!try_module_get(THIS_MODULE))
291 goto err;
292
293 if (!atomic_inc_not_zero(&cur->refcnt)) {
294 module_put(THIS_MODULE);
295 goto err;
296 }
297
298 acct = cur;
299 break;
300 }
301err:
302 rcu_read_unlock();
303 return acct;
304}
305EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
306
307void nfnl_acct_put(struct nf_acct *acct)
308{
309 atomic_dec(&acct->refcnt);
310 module_put(THIS_MODULE);
311}
312EXPORT_SYMBOL_GPL(nfnl_acct_put);
313
314void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct)
315{
316 atomic64_inc(&nfacct->pkts);
317 atomic64_add(skb->len, &nfacct->bytes);
318}
319EXPORT_SYMBOL_GPL(nfnl_acct_update);
320
321static int __init nfnl_acct_init(void)
322{
323 int ret;
324
325 pr_info("nfnl_acct: registering with nfnetlink.\n");
326 ret = nfnetlink_subsys_register(&nfnl_acct_subsys);
327 if (ret < 0) {
328 pr_err("nfnl_acct_init: cannot register with nfnetlink.\n");
329 goto err_out;
330 }
331 return 0;
332err_out:
333 return ret;
334}
335
336static void __exit nfnl_acct_exit(void)
337{
338 struct nf_acct *cur, *tmp;
339
340 pr_info("nfnl_acct: unregistering from nfnetlink.\n");
341 nfnetlink_subsys_unregister(&nfnl_acct_subsys);
342
343 list_for_each_entry_safe(cur, tmp, &nfnl_acct_list, head) {
344 list_del_rcu(&cur->head);
345 /* We are sure that our objects have no clients at this point,
346 * it's safe to release them all without checking refcnt. */
347 kfree_rcu(cur, rcu_head);
348 }
349}
350
351module_init(nfnl_acct_init);
352module_exit(nfnl_acct_exit);
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 0221d10de75a..8e87123f1373 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -62,8 +62,8 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
62 int ret = 0; 62 int ret = 0;
63 u8 proto; 63 u8 proto;
64 64
65 if (info->flags & ~XT_CT_NOTRACK) 65 if (info->flags & ~(XT_CT_NOTRACK | XT_CT_USERSPACE_HELPER))
66 return -EINVAL; 66 return -EOPNOTSUPP;
67 67
68 if (info->flags & XT_CT_NOTRACK) { 68 if (info->flags & XT_CT_NOTRACK) {
69 ct = nf_ct_untracked_get(); 69 ct = nf_ct_untracked_get();
@@ -92,7 +92,9 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par)
92 GFP_KERNEL)) 92 GFP_KERNEL))
93 goto err3; 93 goto err3;
94 94
95 if (info->helper[0]) { 95 if (info->flags & XT_CT_USERSPACE_HELPER) {
96 __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status);
97 } else if (info->helper[0]) {
96 ret = -ENOENT; 98 ret = -ENOENT;
97 proto = xt_ct_find_proto(par); 99 proto = xt_ct_find_proto(par);
98 if (!proto) { 100 if (!proto) {
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c
index 9ddf1c3bfb39..e595e07a759b 100644
--- a/net/netfilter/xt_connbytes.c
+++ b/net/netfilter/xt_connbytes.c
@@ -40,46 +40,46 @@ connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
40 case XT_CONNBYTES_PKTS: 40 case XT_CONNBYTES_PKTS:
41 switch (sinfo->direction) { 41 switch (sinfo->direction) {
42 case XT_CONNBYTES_DIR_ORIGINAL: 42 case XT_CONNBYTES_DIR_ORIGINAL:
43 what = counters[IP_CT_DIR_ORIGINAL].packets; 43 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
44 break; 44 break;
45 case XT_CONNBYTES_DIR_REPLY: 45 case XT_CONNBYTES_DIR_REPLY:
46 what = counters[IP_CT_DIR_REPLY].packets; 46 what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
47 break; 47 break;
48 case XT_CONNBYTES_DIR_BOTH: 48 case XT_CONNBYTES_DIR_BOTH:
49 what = counters[IP_CT_DIR_ORIGINAL].packets; 49 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
50 what += counters[IP_CT_DIR_REPLY].packets; 50 what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
51 break; 51 break;
52 } 52 }
53 break; 53 break;
54 case XT_CONNBYTES_BYTES: 54 case XT_CONNBYTES_BYTES:
55 switch (sinfo->direction) { 55 switch (sinfo->direction) {
56 case XT_CONNBYTES_DIR_ORIGINAL: 56 case XT_CONNBYTES_DIR_ORIGINAL:
57 what = counters[IP_CT_DIR_ORIGINAL].bytes; 57 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
58 break; 58 break;
59 case XT_CONNBYTES_DIR_REPLY: 59 case XT_CONNBYTES_DIR_REPLY:
60 what = counters[IP_CT_DIR_REPLY].bytes; 60 what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
61 break; 61 break;
62 case XT_CONNBYTES_DIR_BOTH: 62 case XT_CONNBYTES_DIR_BOTH:
63 what = counters[IP_CT_DIR_ORIGINAL].bytes; 63 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
64 what += counters[IP_CT_DIR_REPLY].bytes; 64 what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
65 break; 65 break;
66 } 66 }
67 break; 67 break;
68 case XT_CONNBYTES_AVGPKT: 68 case XT_CONNBYTES_AVGPKT:
69 switch (sinfo->direction) { 69 switch (sinfo->direction) {
70 case XT_CONNBYTES_DIR_ORIGINAL: 70 case XT_CONNBYTES_DIR_ORIGINAL:
71 bytes = counters[IP_CT_DIR_ORIGINAL].bytes; 71 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
72 pkts = counters[IP_CT_DIR_ORIGINAL].packets; 72 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
73 break; 73 break;
74 case XT_CONNBYTES_DIR_REPLY: 74 case XT_CONNBYTES_DIR_REPLY:
75 bytes = counters[IP_CT_DIR_REPLY].bytes; 75 bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
76 pkts = counters[IP_CT_DIR_REPLY].packets; 76 pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
77 break; 77 break;
78 case XT_CONNBYTES_DIR_BOTH: 78 case XT_CONNBYTES_DIR_BOTH:
79 bytes = counters[IP_CT_DIR_ORIGINAL].bytes + 79 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +
80 counters[IP_CT_DIR_REPLY].bytes; 80 atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
81 pkts = counters[IP_CT_DIR_ORIGINAL].packets + 81 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +
82 counters[IP_CT_DIR_REPLY].packets; 82 atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
83 break; 83 break;
84 } 84 }
85 if (pkts != 0) 85 if (pkts != 0)
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c
new file mode 100644
index 000000000000..b3be0ef21f19
--- /dev/null
+++ b/net/netfilter/xt_nfacct.c
@@ -0,0 +1,76 @@
1/*
2 * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org>
3 * (C) 2011 Intra2net AG <http://www.intra2net.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 (or any
7 * later at your option) as published by the Free Software Foundation.
8 */
9#include <linux/module.h>
10#include <linux/skbuff.h>
11
12#include <linux/netfilter/x_tables.h>
13#include <linux/netfilter/nfnetlink_acct.h>
14#include <linux/netfilter/xt_nfacct.h>
15
16MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
17MODULE_DESCRIPTION("Xtables: match for the extended accounting infrastructure");
18MODULE_LICENSE("GPL");
19MODULE_ALIAS("ipt_nfacct");
20MODULE_ALIAS("ip6t_nfacct");
21
22static bool nfacct_mt(const struct sk_buff *skb, struct xt_action_param *par)
23{
24 const struct xt_nfacct_match_info *info = par->targinfo;
25
26 nfnl_acct_update(skb, info->nfacct);
27
28 return true;
29}
30
31static int
32nfacct_mt_checkentry(const struct xt_mtchk_param *par)
33{
34 struct xt_nfacct_match_info *info = par->matchinfo;
35 struct nf_acct *nfacct;
36
37 nfacct = nfnl_acct_find_get(info->name);
38 if (nfacct == NULL) {
39 pr_info("xt_nfacct: accounting object with name `%s' "
40 "does not exists\n", info->name);
41 return -ENOENT;
42 }
43 info->nfacct = nfacct;
44 return 0;
45}
46
47static void
48nfacct_mt_destroy(const struct xt_mtdtor_param *par)
49{
50 const struct xt_nfacct_match_info *info = par->matchinfo;
51
52 nfnl_acct_put(info->nfacct);
53}
54
55static struct xt_match nfacct_mt_reg __read_mostly = {
56 .name = "nfacct",
57 .family = NFPROTO_UNSPEC,
58 .checkentry = nfacct_mt_checkentry,
59 .match = nfacct_mt,
60 .destroy = nfacct_mt_destroy,
61 .matchsize = sizeof(struct xt_nfacct_match_info),
62 .me = THIS_MODULE,
63};
64
65static int __init nfacct_mt_init(void)
66{
67 return xt_register_match(&nfacct_mt_reg);
68}
69
70static void __exit nfacct_mt_exit(void)
71{
72 xt_unregister_match(&nfacct_mt_reg);
73}
74
75module_init(nfacct_mt_init);
76module_exit(nfacct_mt_exit);