diff options
author | David S. Miller <davem@davemloft.net> | 2011-12-25 02:21:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-12-25 02:21:45 -0500 |
commit | c5e1fd8ccae09f574d6f978c90c2b968ee29030c (patch) | |
tree | e4485dc086ce76c4ff2ff551246255f5de0a250b | |
parent | 60b778ce519625102d3f72a2071ea72a05e990ce (diff) | |
parent | ceb98d03eac5704820f2ac1f370c9ff385e3a9f5 (diff) |
Merge branch 'nf-next' of git://1984.lsi.us.es/net-next
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 | |||
5 | header-y += nf_conntrack_sctp.h | 5 | header-y += nf_conntrack_sctp.h |
6 | header-y += nf_conntrack_tcp.h | 6 | header-y += nf_conntrack_tcp.h |
7 | header-y += nf_conntrack_tuple_common.h | 7 | header-y += nf_conntrack_tuple_common.h |
8 | header-y += nf_nat.h | ||
8 | header-y += nfnetlink.h | 9 | header-y += nfnetlink.h |
10 | header-y += nfnetlink_acct.h | ||
9 | header-y += nfnetlink_compat.h | 11 | header-y += nfnetlink_compat.h |
10 | header-y += nfnetlink_conntrack.h | 12 | header-y += nfnetlink_conntrack.h |
11 | header-y += nfnetlink_log.h | 13 | header-y += nfnetlink_log.h |
@@ -21,6 +23,7 @@ header-y += xt_DSCP.h | |||
21 | header-y += xt_IDLETIMER.h | 23 | header-y += xt_IDLETIMER.h |
22 | header-y += xt_LED.h | 24 | header-y += xt_LED.h |
23 | header-y += xt_MARK.h | 25 | header-y += xt_MARK.h |
26 | header-y += xt_nfacct.h | ||
24 | header-y += xt_NFLOG.h | 27 | header-y += xt_NFLOG.h |
25 | header-y += xt_NFQUEUE.h | 28 | header-y += xt_NFQUEUE.h |
26 | header-y += xt_RATEEST.h | 29 | header-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 | */ | ||
13 | union 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 | |||
12 | struct 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 | |||
20 | struct 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 | |||
8 | enum 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 | |||
16 | enum 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 | |||
28 | struct nf_acct; | ||
29 | |||
30 | extern struct nf_acct *nfnl_acct_find_get(const char *filter_name); | ||
31 | extern void nfnl_acct_put(struct nf_acct *acct); | ||
32 | extern 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 | ||
8 | struct xt_ct_target_info { | 9 | struct 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 | |||
6 | struct nf_acct; | ||
7 | |||
8 | struct 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 | |||
6 | enum { | ||
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 | |||
19 | struct 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 | |||
12 | header-y += ipt_ecn.h | 12 | header-y += ipt_ecn.h |
13 | header-y += ipt_realm.h | 13 | header-y += ipt_realm.h |
14 | header-y += ipt_ttl.h | 14 | header-y += ipt_ttl.h |
15 | header-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. */ | ||
12 | union 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. */ | ||
37 | struct 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. */ | ||
49 | struct 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); | |||
70 | extern struct dst_entry * ip6_route_output(struct net *net, | 70 | extern 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); |
73 | extern struct dst_entry * ip6_route_lookup(struct net *net, | ||
74 | struct flowi6 *fl6, int flags); | ||
73 | 75 | ||
74 | extern int ip6_route_init(void); | 76 | extern int ip6_route_init(void); |
75 | extern void ip6_route_cleanup(void); | 77 | extern 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 | ||
17 | struct nf_conn_counter { | 17 | struct 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 | ||
22 | static inline | 22 | static 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 | ||
92 | void nf_ct_remove_expectations(struct nf_conn *ct); | 92 | void nf_ct_remove_expectations(struct nf_conn *ct); |
93 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); | 93 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); |
94 | void 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 | |||
9 | enum nf_nat_manip_type { | 7 | enum 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. */ |
54 | extern unsigned int nf_nat_setup_info(struct nf_conn *ct, | 52 | extern 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, | |||
20 | static inline int nf_nat_initialized(struct nf_conn *ct, | 20 | static 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 | ||
7 | struct nf_nat_range; | 7 | struct nf_nat_ipv4_range; |
8 | 8 | ||
9 | struct nf_nat_protocol { | 9 | struct 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 | ||
63 | extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | 58 | extern 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 | ||
69 | extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb, | ||
70 | const struct nf_nat_range *range); | ||
71 | extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], | 64 | extern 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 | } |
70 | EXPORT_SYMBOL_GPL(fib_lookup); | ||
70 | 71 | ||
71 | static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, | 72 | static 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 | } |
1610 | EXPORT_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 | ||
85 | config 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 | |||
85 | config IP_NF_MATCH_TTL | 95 | config 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 |
51 | obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o | 51 | obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o |
52 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o | 52 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o |
53 | obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o | ||
53 | 54 | ||
54 | # targets | 55 | # targets |
55 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 56 | obj-$(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 */ |
31 | static int masquerade_tg_check(const struct xt_tgchk_param *par) | 31 | static 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 | ||
91 | static int | 91 | static 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 | ||
25 | static int netmap_tg_check(const struct xt_tgchk_param *par) | 25 | static 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 */ |
29 | static int redirect_tg_check(const struct xt_tgchk_param *par) | 29 | static 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 | ||
88 | static struct xt_target redirect_tg_reg __read_mostly = { | 88 | static 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 | |||
22 | MODULE_LICENSE("GPL"); | ||
23 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
24 | MODULE_DESCRIPTION("iptables: ipv4 reverse path filter match"); | ||
25 | |||
26 | /* don't try to find route from mcast/bcast/zeronet */ | ||
27 | static __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 | |||
35 | static 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 | |||
69 | static 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 | |||
101 | static 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 | |||
120 | static 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 | |||
130 | static int __init rpfilter_mt_init(void) | ||
131 | { | ||
132 | return xt_register_match(&rpfilter_mt_reg); | ||
133 | } | ||
134 | |||
135 | static void __exit rpfilter_mt_exit(void) | ||
136 | { | ||
137 | xt_unregister_match(&rpfilter_mt_reg); | ||
138 | } | ||
139 | |||
140 | module_init(rpfilter_mt_init); | ||
141 | module_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 | ||
36 | static DEFINE_SPINLOCK(nf_nat_lock); | 35 | static 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. */ |
83 | static int | 82 | static int |
84 | in_range(const struct nf_conntrack_tuple *tuple, | 83 | in_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 | |||
123 | find_appropriate_src(struct net *net, u16 zone, | 122 | find_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 | */ |
158 | static void | 157 | static void |
159 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | 158 | find_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, | |||
204 | static void | 203 | static void |
205 | get_unique_tuple(struct nf_conntrack_tuple *tuple, | 204 | get_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 | ||
268 | unsigned int | 267 | unsigned int |
269 | nf_nat_setup_info(struct nf_conn *ct, | 268 | nf_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 | ||
578 | static const struct nf_nat_protocol * | ||
579 | nf_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 | |||
592 | static void | ||
593 | nf_nat_proto_put(const struct nf_nat_protocol *p) | ||
594 | { | ||
595 | module_put(p->me); | ||
596 | } | ||
597 | |||
598 | static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { | 566 | static 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 | ||
603 | static int nfnetlink_parse_nat_proto(struct nlattr *attr, | 571 | static 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 | ||
622 | static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { | 591 | static 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 | ||
627 | static int | 597 | static int |
628 | nfnetlink_parse_nat(const struct nlattr *nat, | 598 | nfnetlink_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, | |||
398 | static void ip_nat_q931_expect(struct nf_conn *new, | 398 | static 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, | |||
496 | static void ip_nat_callforwarding_expect(struct nf_conn *new, | 496 | static 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, | |||
430 | void nf_nat_follow_master(struct nf_conn *ct, | 424 | void 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 | } |
451 | EXPORT_SYMBOL(nf_nat_follow_master); | 445 | EXPORT_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, | |||
37 | EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); | 37 | EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); |
38 | 38 | ||
39 | void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | 39 | void 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, | |||
96 | EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple); | 96 | EXPORT_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) |
99 | int 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 | |||
106 | nla_put_failure: | ||
107 | return -1; | ||
108 | } | ||
109 | EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range); | ||
110 | |||
111 | int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], | 99 | int 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 | } |
125 | EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr); | 113 | EXPORT_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 | ||
25 | static void | 25 | static void |
26 | dccp_unique_tuple(struct nf_conntrack_tuple *tuple, | 26 | dccp_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 | ||
81 | static const struct nf_nat_protocol nf_nat_protocol_dccp = { | 81 | static 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 ... */ |
40 | static void | 40 | static void |
41 | gre_unique_tuple(struct nf_conntrack_tuple *tuple, | 41 | gre_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 | ||
120 | static const struct nf_nat_protocol gre = { | 120 | static 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 | ||
31 | static void | 31 | static void |
32 | icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | 32 | icmp_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 | ||
75 | const struct nf_nat_protocol nf_nat_protocol_icmp = { | 75 | const 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 | ||
20 | static void | 20 | static void |
21 | sctp_unique_tuple(struct nf_conntrack_tuple *tuple, | 21 | sctp_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 | ||
71 | static const struct nf_nat_protocol nf_nat_protocol_sctp = { | 71 | static 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 | ||
24 | static void | 24 | static void |
25 | tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | 25 | tcp_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 | ||
83 | const struct nf_nat_protocol nf_nat_protocol_tcp = { | 83 | const 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 | ||
23 | static void | 23 | static void |
24 | udp_unique_tuple(struct nf_conntrack_tuple *tuple, | 24 | udp_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 | ||
74 | const struct nf_nat_protocol nf_nat_protocol_udp = { | 74 | const 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 | ||
22 | static void | 22 | static void |
23 | udplite_unique_tuple(struct nf_conntrack_tuple *tuple, | 23 | udplite_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 | ||
73 | static const struct nf_nat_protocol nf_nat_protocol_udplite = { | 73 | static 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 | ||
29 | static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple, | 29 | static 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 | ||
48 | const struct nf_nat_protocol nf_nat_unknown_protocol = { | 48 | const 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 | ||
62 | static unsigned int | 62 | static 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 | ||
80 | static int ipt_snat_checkentry(const struct xt_tgchk_param *par) | 80 | static 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 | ||
92 | static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) | 92 | static 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 | |||
105 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | 105 | alloc_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, | |||
140 | static struct xt_target ipt_snat_reg __read_mostly = { | 140 | static 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 = { | |||
150 | static struct xt_target ipt_dnat_reg __read_mostly = { | 150 | static 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) | |||
249 | static void ip_nat_sip_expected(struct nf_conn *ct, | 249 | static 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 | ||
128 | config 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 | |||
128 | config IP6_NF_MATCH_RT | 138 | config 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 | |||
27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o |
29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o | 29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o |
30 | obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | ||
30 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 31 | obj-$(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 | |||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
21 | MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match"); | ||
22 | |||
23 | static 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 | |||
29 | static 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 | |||
74 | static 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 | |||
92 | static 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 | |||
112 | static 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 | |||
122 | static int __init rpfilter_mt_init(void) | ||
123 | { | ||
124 | return xt_register_match(&rpfilter_mt_reg); | ||
125 | } | ||
126 | |||
127 | static void __exit rpfilter_mt_exit(void) | ||
128 | { | ||
129 | xt_unregister_match(&rpfilter_mt_reg); | ||
130 | } | ||
131 | |||
132 | module_init(rpfilter_mt_init); | ||
133 | module_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 | ||
661 | struct 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 | } | ||
666 | EXPORT_SYMBOL_GPL(ip6_route_lookup); | ||
667 | |||
661 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 668 | struct 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" | |||
4 | config NETFILTER_NETLINK | 4 | config NETFILTER_NETLINK |
5 | tristate | 5 | tristate |
6 | 6 | ||
7 | config NETFILTER_NETLINK_ACCT | ||
8 | tristate "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 | |||
7 | config NETFILTER_NETLINK_QUEUE | 15 | config 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 | ||
890 | config 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 | |||
882 | config NETFILTER_XT_MATCH_OSF | 900 | config 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 | |||
7 | obj-$(CONFIG_NETFILTER) = netfilter.o | 7 | obj-$(CONFIG_NETFILTER) = netfilter.o |
8 | 8 | ||
9 | obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o | 9 | obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o |
10 | obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o | ||
10 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o | 11 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o |
11 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o | 12 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o |
12 | 13 | ||
@@ -90,6 +91,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | |||
90 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | 91 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o |
91 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | 92 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o |
92 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o | 93 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o |
94 | obj-$(CONFIG_NETFILTER_XT_MATCH_NFACCT) += xt_nfacct.o | ||
93 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o | 95 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o |
94 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o | 96 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o |
95 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o | 97 | obj-$(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 | ||
235 | comment 'IPVS SH scheduler' | ||
236 | |||
237 | config 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 | |||
235 | comment 'IPVS application helper' | 250 | comment 'IPVS application helper' |
236 | 251 | ||
237 | config IP_VS_FTP | 252 | config 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 | }; |
52 | EXPORT_SYMBOL_GPL(seq_print_acct); | 52 | EXPORT_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); | |||
67 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); | 67 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); |
68 | 68 | ||
69 | unsigned int nf_conntrack_hash_rnd __read_mostly; | 69 | unsigned int nf_conntrack_hash_rnd __read_mostly; |
70 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_rnd); | ||
70 | 71 | ||
71 | static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone) | 72 | static 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 | ||
39 | static struct kmem_cache *nf_ct_expect_cachep __read_mostly; | 39 | static struct kmem_cache *nf_ct_expect_cachep __read_mostly; |
40 | 40 | ||
41 | static HLIST_HEAD(nf_ct_userspace_expect_list); | ||
42 | |||
43 | /* nf_conntrack_expect helper functions */ | 41 | /* nf_conntrack_expect helper functions */ |
44 | void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, | 42 | void 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 | } |
315 | EXPORT_SYMBOL_GPL(nf_ct_expect_put); | 313 | EXPORT_SYMBOL_GPL(nf_ct_expect_put); |
316 | 314 | ||
317 | static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) | 315 | static 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 | } |
462 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); | 456 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); |
463 | 457 | ||
464 | void 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 | } | ||
477 | EXPORT_SYMBOL_GPL(nf_ct_remove_userspace_expectations); | ||
478 | |||
479 | #ifdef CONFIG_PROC_FS | 458 | #ifdef CONFIG_PROC_FS |
480 | struct ct_expect_iter_state { | 459 | struct 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 | ||
205 | static int | 205 | static int |
206 | ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, | 206 | dump_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 | ||
234 | static int | 227 | static int |
228 | ctnetlink_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 | |||
248 | static int | ||
235 | ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) | 249 | ctnetlink_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 | ||
395 | static int | 409 | static int |
396 | ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | 410 | ctnetlink_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 | |||
26 | MODULE_LICENSE("GPL"); | ||
27 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
28 | MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure"); | ||
29 | |||
30 | static LIST_HEAD(nfnl_acct_list); | ||
31 | |||
32 | struct 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 | |||
41 | static int | ||
42 | nfnl_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 | |||
93 | static int | ||
94 | nfnl_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 | |||
128 | nlmsg_failure: | ||
129 | nla_put_failure: | ||
130 | nlmsg_cancel(skb, nlh); | ||
131 | return -1; | ||
132 | } | ||
133 | |||
134 | static int | ||
135 | nfnl_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 | |||
165 | static int | ||
166 | nfnl_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. */ | ||
205 | static 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 | |||
222 | static int | ||
223 | nfnl_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 | |||
251 | static 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 | |||
257 | static 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 | |||
272 | static 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 | |||
279 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT); | ||
280 | |||
281 | struct 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 | } | ||
301 | err: | ||
302 | rcu_read_unlock(); | ||
303 | return acct; | ||
304 | } | ||
305 | EXPORT_SYMBOL_GPL(nfnl_acct_find_get); | ||
306 | |||
307 | void nfnl_acct_put(struct nf_acct *acct) | ||
308 | { | ||
309 | atomic_dec(&acct->refcnt); | ||
310 | module_put(THIS_MODULE); | ||
311 | } | ||
312 | EXPORT_SYMBOL_GPL(nfnl_acct_put); | ||
313 | |||
314 | void 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 | } | ||
319 | EXPORT_SYMBOL_GPL(nfnl_acct_update); | ||
320 | |||
321 | static 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; | ||
332 | err_out: | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | static 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 | |||
351 | module_init(nfnl_acct_init); | ||
352 | module_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 | |||
16 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
17 | MODULE_DESCRIPTION("Xtables: match for the extended accounting infrastructure"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_ALIAS("ipt_nfacct"); | ||
20 | MODULE_ALIAS("ip6t_nfacct"); | ||
21 | |||
22 | static 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 | |||
31 | static int | ||
32 | nfacct_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 | |||
47 | static void | ||
48 | nfacct_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 | |||
55 | static 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 | |||
65 | static int __init nfacct_mt_init(void) | ||
66 | { | ||
67 | return xt_register_match(&nfacct_mt_reg); | ||
68 | } | ||
69 | |||
70 | static void __exit nfacct_mt_exit(void) | ||
71 | { | ||
72 | xt_unregister_match(&nfacct_mt_reg); | ||
73 | } | ||
74 | |||
75 | module_init(nfacct_mt_init); | ||
76 | module_exit(nfacct_mt_exit); | ||