diff options
-rw-r--r-- | include/linux/netfilter.h | 9 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_extend.h | 2 | ||||
-rw-r--r-- | include/net/netfilter/nf_conntrack_seqadj.h | 49 | ||||
-rw-r--r-- | include/net/netfilter/nf_nat.h | 10 | ||||
-rw-r--r-- | include/net/netfilter/nf_nat_helper.h | 19 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nf_conntrack_common.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/netfilter/nfnetlink_conntrack.h | 15 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | 7 | ||||
-rw-r--r-- | net/netfilter/Makefile | 2 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_core.c | 16 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 115 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_proto_tcp.c | 18 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_seqadj.c | 218 | ||||
-rw-r--r-- | net/netfilter/nf_nat_core.c | 16 | ||||
-rw-r--r-- | net/netfilter/nf_nat_helper.c | 228 | ||||
-rw-r--r-- | net/netfilter/nf_nat_sip.c | 3 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_ct.c | 8 |
18 files changed, 369 insertions, 376 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index e2cf786be22f..708fe72ab913 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h | |||
@@ -319,6 +319,7 @@ extern void nf_ct_attach(struct sk_buff *, const struct sk_buff *); | |||
319 | extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu; | 319 | extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu; |
320 | 320 | ||
321 | struct nf_conn; | 321 | struct nf_conn; |
322 | enum ip_conntrack_info; | ||
322 | struct nlattr; | 323 | struct nlattr; |
323 | 324 | ||
324 | struct nfq_ct_hook { | 325 | struct nfq_ct_hook { |
@@ -327,14 +328,10 @@ struct nfq_ct_hook { | |||
327 | int (*parse)(const struct nlattr *attr, struct nf_conn *ct); | 328 | int (*parse)(const struct nlattr *attr, struct nf_conn *ct); |
328 | int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct, | 329 | int (*attach_expect)(const struct nlattr *attr, struct nf_conn *ct, |
329 | u32 portid, u32 report); | 330 | u32 portid, u32 report); |
330 | }; | ||
331 | extern struct nfq_ct_hook __rcu *nfq_ct_hook; | ||
332 | |||
333 | struct nfq_ct_nat_hook { | ||
334 | void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct, | 331 | void (*seq_adjust)(struct sk_buff *skb, struct nf_conn *ct, |
335 | u32 ctinfo, s32 off); | 332 | enum ip_conntrack_info ctinfo, s32 off); |
336 | }; | 333 | }; |
337 | extern struct nfq_ct_nat_hook __rcu *nfq_ct_nat_hook; | 334 | extern struct nfq_ct_hook __rcu *nfq_ct_hook; |
338 | #else | 335 | #else |
339 | static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} | 336 | static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} |
340 | #endif | 337 | #endif |
diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 977bc8a46444..2a22bcbfe6e4 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h | |||
@@ -9,6 +9,7 @@ enum nf_ct_ext_id { | |||
9 | NF_CT_EXT_HELPER, | 9 | NF_CT_EXT_HELPER, |
10 | #if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE) | 10 | #if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE) |
11 | NF_CT_EXT_NAT, | 11 | NF_CT_EXT_NAT, |
12 | NF_CT_EXT_SEQADJ, | ||
12 | #endif | 13 | #endif |
13 | NF_CT_EXT_ACCT, | 14 | NF_CT_EXT_ACCT, |
14 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 15 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
@@ -31,6 +32,7 @@ enum nf_ct_ext_id { | |||
31 | 32 | ||
32 | #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help | 33 | #define NF_CT_EXT_HELPER_TYPE struct nf_conn_help |
33 | #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat | 34 | #define NF_CT_EXT_NAT_TYPE struct nf_conn_nat |
35 | #define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj | ||
34 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter | 36 | #define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter |
35 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache | 37 | #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache |
36 | #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone | 38 | #define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone |
diff --git a/include/net/netfilter/nf_conntrack_seqadj.h b/include/net/netfilter/nf_conntrack_seqadj.h new file mode 100644 index 000000000000..30bfbbed9f47 --- /dev/null +++ b/include/net/netfilter/nf_conntrack_seqadj.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef _NF_CONNTRACK_SEQADJ_H | ||
2 | #define _NF_CONNTRACK_SEQADJ_H | ||
3 | |||
4 | #include <net/netfilter/nf_conntrack_extend.h> | ||
5 | |||
6 | /** | ||
7 | * struct nf_ct_seqadj - sequence number adjustment information | ||
8 | * | ||
9 | * @correction_pos: position of the last TCP sequence number modification | ||
10 | * @offset_before: sequence number offset before last modification | ||
11 | * @offset_after: sequence number offset after last modification | ||
12 | */ | ||
13 | struct nf_ct_seqadj { | ||
14 | u32 correction_pos; | ||
15 | s32 offset_before; | ||
16 | s32 offset_after; | ||
17 | }; | ||
18 | |||
19 | struct nf_conn_seqadj { | ||
20 | struct nf_ct_seqadj seq[IP_CT_DIR_MAX]; | ||
21 | }; | ||
22 | |||
23 | static inline struct nf_conn_seqadj *nfct_seqadj(const struct nf_conn *ct) | ||
24 | { | ||
25 | return nf_ct_ext_find(ct, NF_CT_EXT_SEQADJ); | ||
26 | } | ||
27 | |||
28 | static inline struct nf_conn_seqadj *nfct_seqadj_ext_add(struct nf_conn *ct) | ||
29 | { | ||
30 | return nf_ct_ext_add(ct, NF_CT_EXT_SEQADJ, GFP_ATOMIC); | ||
31 | } | ||
32 | |||
33 | extern int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
34 | __be32 seq, s32 off); | ||
35 | extern void nf_ct_tcp_seqadj_set(struct sk_buff *skb, | ||
36 | struct nf_conn *ct, | ||
37 | enum ip_conntrack_info ctinfo, | ||
38 | s32 off); | ||
39 | |||
40 | extern int nf_ct_seq_adjust(struct sk_buff *skb, | ||
41 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
42 | unsigned int protoff); | ||
43 | extern s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, | ||
44 | u32 seq); | ||
45 | |||
46 | extern int nf_conntrack_seqadj_init(void); | ||
47 | extern void nf_conntrack_seqadj_fini(void); | ||
48 | |||
49 | #endif /* _NF_CONNTRACK_SEQADJ_H */ | ||
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index e2441413675c..59a192420053 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h | |||
@@ -13,15 +13,6 @@ enum nf_nat_manip_type { | |||
13 | #define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \ | 13 | #define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \ |
14 | (hooknum) != NF_INET_LOCAL_IN) | 14 | (hooknum) != NF_INET_LOCAL_IN) |
15 | 15 | ||
16 | /* NAT sequence number modifications */ | ||
17 | struct nf_nat_seq { | ||
18 | /* position of the last TCP sequence number modification (if any) */ | ||
19 | u_int32_t correction_pos; | ||
20 | |||
21 | /* sequence number offset before and after last modification */ | ||
22 | int32_t offset_before, offset_after; | ||
23 | }; | ||
24 | |||
25 | #include <linux/list.h> | 16 | #include <linux/list.h> |
26 | #include <linux/netfilter/nf_conntrack_pptp.h> | 17 | #include <linux/netfilter/nf_conntrack_pptp.h> |
27 | #include <net/netfilter/nf_conntrack_extend.h> | 18 | #include <net/netfilter/nf_conntrack_extend.h> |
@@ -39,7 +30,6 @@ struct nf_conn; | |||
39 | /* The structure embedded in the conntrack structure. */ | 30 | /* The structure embedded in the conntrack structure. */ |
40 | struct nf_conn_nat { | 31 | struct nf_conn_nat { |
41 | struct hlist_node bysource; | 32 | struct hlist_node bysource; |
42 | struct nf_nat_seq seq[IP_CT_DIR_MAX]; | ||
43 | struct nf_conn *ct; | 33 | struct nf_conn *ct; |
44 | union nf_conntrack_nat_help help; | 34 | union nf_conntrack_nat_help help; |
45 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ | 35 | #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ |
diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index 194c34794923..404324d1d0c4 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h | |||
@@ -39,28 +39,9 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
39 | const char *rep_buffer, | 39 | const char *rep_buffer, |
40 | unsigned int rep_len); | 40 | unsigned int rep_len); |
41 | 41 | ||
42 | extern void nf_nat_set_seq_adjust(struct nf_conn *ct, | ||
43 | enum ip_conntrack_info ctinfo, | ||
44 | __be32 seq, s32 off); | ||
45 | extern int nf_nat_seq_adjust(struct sk_buff *skb, | ||
46 | struct nf_conn *ct, | ||
47 | enum ip_conntrack_info ctinfo, | ||
48 | unsigned int protoff); | ||
49 | extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, | ||
50 | struct nf_conn *ct, | ||
51 | enum ip_conntrack_info ctinfo, | ||
52 | unsigned int protoff); | ||
53 | |||
54 | /* Setup NAT on this expected conntrack so it follows master, but goes | 42 | /* Setup NAT on this expected conntrack so it follows master, but goes |
55 | * to port ct->master->saved_proto. */ | 43 | * to port ct->master->saved_proto. */ |
56 | extern void nf_nat_follow_master(struct nf_conn *ct, | 44 | extern void nf_nat_follow_master(struct nf_conn *ct, |
57 | struct nf_conntrack_expect *this); | 45 | struct nf_conntrack_expect *this); |
58 | 46 | ||
59 | extern s32 nf_nat_get_offset(const struct nf_conn *ct, | ||
60 | enum ip_conntrack_dir dir, | ||
61 | u32 seq); | ||
62 | |||
63 | extern void nf_nat_tcp_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | ||
64 | u32 dir, s32 off); | ||
65 | |||
66 | #endif | 47 | #endif |
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h index d69483fb3825..8dd803818ebe 100644 --- a/include/uapi/linux/netfilter/nf_conntrack_common.h +++ b/include/uapi/linux/netfilter/nf_conntrack_common.h | |||
@@ -99,7 +99,8 @@ enum ip_conntrack_events { | |||
99 | IPCT_PROTOINFO, /* protocol information has changed */ | 99 | IPCT_PROTOINFO, /* protocol information has changed */ |
100 | IPCT_HELPER, /* new helper has been set */ | 100 | IPCT_HELPER, /* new helper has been set */ |
101 | IPCT_MARK, /* new mark has been set */ | 101 | IPCT_MARK, /* new mark has been set */ |
102 | IPCT_NATSEQADJ, /* NAT is doing sequence adjustment */ | 102 | IPCT_SEQADJ, /* sequence adjustment has changed */ |
103 | IPCT_NATSEQADJ = IPCT_SEQADJ, | ||
103 | IPCT_SECMARK, /* new security mark has been set */ | 104 | IPCT_SECMARK, /* new security mark has been set */ |
104 | IPCT_LABEL, /* new connlabel has been set */ | 105 | IPCT_LABEL, /* new connlabel has been set */ |
105 | }; | 106 | }; |
diff --git a/include/uapi/linux/netfilter/nfnetlink_conntrack.h b/include/uapi/linux/netfilter/nfnetlink_conntrack.h index 08fabc6c93f3..acad6c52a652 100644 --- a/include/uapi/linux/netfilter/nfnetlink_conntrack.h +++ b/include/uapi/linux/netfilter/nfnetlink_conntrack.h | |||
@@ -42,8 +42,10 @@ enum ctattr_type { | |||
42 | CTA_ID, | 42 | CTA_ID, |
43 | CTA_NAT_DST, | 43 | CTA_NAT_DST, |
44 | CTA_TUPLE_MASTER, | 44 | CTA_TUPLE_MASTER, |
45 | CTA_NAT_SEQ_ADJ_ORIG, | 45 | CTA_SEQ_ADJ_ORIG, |
46 | CTA_NAT_SEQ_ADJ_REPLY, | 46 | CTA_NAT_SEQ_ADJ_ORIG = CTA_SEQ_ADJ_ORIG, |
47 | CTA_SEQ_ADJ_REPLY, | ||
48 | CTA_NAT_SEQ_ADJ_REPLY = CTA_SEQ_ADJ_REPLY, | ||
47 | CTA_SECMARK, /* obsolete */ | 49 | CTA_SECMARK, /* obsolete */ |
48 | CTA_ZONE, | 50 | CTA_ZONE, |
49 | CTA_SECCTX, | 51 | CTA_SECCTX, |
@@ -165,6 +167,15 @@ enum ctattr_protonat { | |||
165 | }; | 167 | }; |
166 | #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) | 168 | #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) |
167 | 169 | ||
170 | enum ctattr_seqadj { | ||
171 | CTA_SEQADJ_UNSPEC, | ||
172 | CTA_SEQADJ_CORRECTION_POS, | ||
173 | CTA_SEQADJ_OFFSET_BEFORE, | ||
174 | CTA_SEQADJ_OFFSET_AFTER, | ||
175 | __CTA_SEQADJ_MAX | ||
176 | }; | ||
177 | #define CTA_SEQADJ_MAX (__CTA_SEQADJ_MAX - 1) | ||
178 | |||
168 | enum ctattr_natseq { | 179 | enum ctattr_natseq { |
169 | CTA_NAT_SEQ_UNSPEC, | 180 | CTA_NAT_SEQ_UNSPEC, |
170 | CTA_NAT_SEQ_CORRECTION_POS, | 181 | CTA_NAT_SEQ_CORRECTION_POS, |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0a2e0e3e95ba..86f5b34a4ed1 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <net/netfilter/nf_conntrack_l3proto.h> | 25 | #include <net/netfilter/nf_conntrack_l3proto.h> |
26 | #include <net/netfilter/nf_conntrack_zones.h> | 26 | #include <net/netfilter/nf_conntrack_zones.h> |
27 | #include <net/netfilter/nf_conntrack_core.h> | 27 | #include <net/netfilter/nf_conntrack_core.h> |
28 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
28 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 29 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
29 | #include <net/netfilter/nf_nat_helper.h> | 30 | #include <net/netfilter/nf_nat_helper.h> |
30 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 31 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
@@ -136,11 +137,7 @@ static unsigned int ipv4_confirm(unsigned int hooknum, | |||
136 | /* adjust seqs for loopback traffic only in outgoing direction */ | 137 | /* adjust seqs for loopback traffic only in outgoing direction */ |
137 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && | 138 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && |
138 | !nf_is_loopback_packet(skb)) { | 139 | !nf_is_loopback_packet(skb)) { |
139 | typeof(nf_nat_seq_adjust_hook) seq_adjust; | 140 | if (!nf_ct_seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) { |
140 | |||
141 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); | ||
142 | if (!seq_adjust || | ||
143 | !seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) { | ||
144 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); | 141 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); |
145 | return NF_DROP; | 142 | return NF_DROP; |
146 | } | 143 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index c9b6a6e6a1e8..d6e4dd8b58df 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <net/netfilter/nf_conntrack_l3proto.h> | 28 | #include <net/netfilter/nf_conntrack_l3proto.h> |
29 | #include <net/netfilter/nf_conntrack_core.h> | 29 | #include <net/netfilter/nf_conntrack_core.h> |
30 | #include <net/netfilter/nf_conntrack_zones.h> | 30 | #include <net/netfilter/nf_conntrack_zones.h> |
31 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
31 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 32 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
32 | #include <net/netfilter/nf_nat_helper.h> | 33 | #include <net/netfilter/nf_nat_helper.h> |
33 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 34 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
@@ -158,11 +159,7 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
158 | /* adjust seqs for loopback traffic only in outgoing direction */ | 159 | /* adjust seqs for loopback traffic only in outgoing direction */ |
159 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && | 160 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && |
160 | !nf_is_loopback_packet(skb)) { | 161 | !nf_is_loopback_packet(skb)) { |
161 | typeof(nf_nat_seq_adjust_hook) seq_adjust; | 162 | if (!nf_ct_seq_adjust(skb, ct, ctinfo, protoff)) { |
162 | |||
163 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); | ||
164 | if (!seq_adjust || | ||
165 | !seq_adjust(skb, ct, ctinfo, protoff)) { | ||
166 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); | 163 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); |
167 | return NF_DROP; | 164 | return NF_DROP; |
168 | } | 165 | } |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index ebfa7dc747cd..89a9c1658f5e 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | 2 | ||
3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o | 3 | nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o |
4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o | 4 | nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o |
5 | nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o | 5 | nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o |
6 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o | 6 | nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index da6f1787a102..00a7a94d4132 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <net/netfilter/nf_conntrack_l4proto.h> | 39 | #include <net/netfilter/nf_conntrack_l4proto.h> |
40 | #include <net/netfilter/nf_conntrack_expect.h> | 40 | #include <net/netfilter/nf_conntrack_expect.h> |
41 | #include <net/netfilter/nf_conntrack_helper.h> | 41 | #include <net/netfilter/nf_conntrack_helper.h> |
42 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
42 | #include <net/netfilter/nf_conntrack_core.h> | 43 | #include <net/netfilter/nf_conntrack_core.h> |
43 | #include <net/netfilter/nf_conntrack_extend.h> | 44 | #include <net/netfilter/nf_conntrack_extend.h> |
44 | #include <net/netfilter/nf_conntrack_acct.h> | 45 | #include <net/netfilter/nf_conntrack_acct.h> |
@@ -1326,6 +1327,7 @@ void nf_conntrack_cleanup_end(void) | |||
1326 | nf_ct_extend_unregister(&nf_ct_zone_extend); | 1327 | nf_ct_extend_unregister(&nf_ct_zone_extend); |
1327 | #endif | 1328 | #endif |
1328 | nf_conntrack_proto_fini(); | 1329 | nf_conntrack_proto_fini(); |
1330 | nf_conntrack_seqadj_fini(); | ||
1329 | nf_conntrack_labels_fini(); | 1331 | nf_conntrack_labels_fini(); |
1330 | nf_conntrack_helper_fini(); | 1332 | nf_conntrack_helper_fini(); |
1331 | nf_conntrack_timeout_fini(); | 1333 | nf_conntrack_timeout_fini(); |
@@ -1531,6 +1533,10 @@ int nf_conntrack_init_start(void) | |||
1531 | if (ret < 0) | 1533 | if (ret < 0) |
1532 | goto err_labels; | 1534 | goto err_labels; |
1533 | 1535 | ||
1536 | ret = nf_conntrack_seqadj_init(); | ||
1537 | if (ret < 0) | ||
1538 | goto err_seqadj; | ||
1539 | |||
1534 | #ifdef CONFIG_NF_CONNTRACK_ZONES | 1540 | #ifdef CONFIG_NF_CONNTRACK_ZONES |
1535 | ret = nf_ct_extend_register(&nf_ct_zone_extend); | 1541 | ret = nf_ct_extend_register(&nf_ct_zone_extend); |
1536 | if (ret < 0) | 1542 | if (ret < 0) |
@@ -1555,6 +1561,8 @@ err_proto: | |||
1555 | nf_ct_extend_unregister(&nf_ct_zone_extend); | 1561 | nf_ct_extend_unregister(&nf_ct_zone_extend); |
1556 | err_extend: | 1562 | err_extend: |
1557 | #endif | 1563 | #endif |
1564 | nf_conntrack_seqadj_fini(); | ||
1565 | err_seqadj: | ||
1558 | nf_conntrack_labels_fini(); | 1566 | nf_conntrack_labels_fini(); |
1559 | err_labels: | 1567 | err_labels: |
1560 | nf_conntrack_helper_fini(); | 1568 | nf_conntrack_helper_fini(); |
@@ -1577,9 +1585,6 @@ void nf_conntrack_init_end(void) | |||
1577 | /* For use by REJECT target */ | 1585 | /* For use by REJECT target */ |
1578 | RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach); | 1586 | RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach); |
1579 | RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack); | 1587 | RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack); |
1580 | |||
1581 | /* Howto get NAT offsets */ | ||
1582 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); | ||
1583 | } | 1588 | } |
1584 | 1589 | ||
1585 | /* | 1590 | /* |
@@ -1666,8 +1671,3 @@ err_slabname: | |||
1666 | err_stat: | 1671 | err_stat: |
1667 | return ret; | 1672 | return ret; |
1668 | } | 1673 | } |
1669 | |||
1670 | s32 (*nf_ct_nat_offset)(const struct nf_conn *ct, | ||
1671 | enum ip_conntrack_dir dir, | ||
1672 | u32 seq); | ||
1673 | EXPORT_SYMBOL_GPL(nf_ct_nat_offset); | ||
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index fa61fea63234..7c55745ececf 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <net/netfilter/nf_conntrack_core.h> | 37 | #include <net/netfilter/nf_conntrack_core.h> |
38 | #include <net/netfilter/nf_conntrack_expect.h> | 38 | #include <net/netfilter/nf_conntrack_expect.h> |
39 | #include <net/netfilter/nf_conntrack_helper.h> | 39 | #include <net/netfilter/nf_conntrack_helper.h> |
40 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
40 | #include <net/netfilter/nf_conntrack_l3proto.h> | 41 | #include <net/netfilter/nf_conntrack_l3proto.h> |
41 | #include <net/netfilter/nf_conntrack_l4proto.h> | 42 | #include <net/netfilter/nf_conntrack_l4proto.h> |
42 | #include <net/netfilter/nf_conntrack_tuple.h> | 43 | #include <net/netfilter/nf_conntrack_tuple.h> |
@@ -381,9 +382,8 @@ nla_put_failure: | |||
381 | return -1; | 382 | return -1; |
382 | } | 383 | } |
383 | 384 | ||
384 | #ifdef CONFIG_NF_NAT_NEEDED | ||
385 | static int | 385 | static int |
386 | dump_nat_seq_adj(struct sk_buff *skb, const struct nf_nat_seq *natseq, int type) | 386 | dump_ct_seq_adj(struct sk_buff *skb, const struct nf_ct_seqadj *seq, int type) |
387 | { | 387 | { |
388 | struct nlattr *nest_parms; | 388 | struct nlattr *nest_parms; |
389 | 389 | ||
@@ -391,12 +391,12 @@ dump_nat_seq_adj(struct sk_buff *skb, const struct nf_nat_seq *natseq, int type) | |||
391 | if (!nest_parms) | 391 | if (!nest_parms) |
392 | goto nla_put_failure; | 392 | goto nla_put_failure; |
393 | 393 | ||
394 | if (nla_put_be32(skb, CTA_NAT_SEQ_CORRECTION_POS, | 394 | if (nla_put_be32(skb, CTA_SEQADJ_CORRECTION_POS, |
395 | htonl(natseq->correction_pos)) || | 395 | htonl(seq->correction_pos)) || |
396 | nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_BEFORE, | 396 | nla_put_be32(skb, CTA_SEQADJ_OFFSET_BEFORE, |
397 | htonl(natseq->offset_before)) || | 397 | htonl(seq->offset_before)) || |
398 | nla_put_be32(skb, CTA_NAT_SEQ_OFFSET_AFTER, | 398 | nla_put_be32(skb, CTA_SEQADJ_OFFSET_AFTER, |
399 | htonl(natseq->offset_after))) | 399 | htonl(seq->offset_after))) |
400 | goto nla_put_failure; | 400 | goto nla_put_failure; |
401 | 401 | ||
402 | nla_nest_end(skb, nest_parms); | 402 | nla_nest_end(skb, nest_parms); |
@@ -408,27 +408,24 @@ nla_put_failure: | |||
408 | } | 408 | } |
409 | 409 | ||
410 | static inline int | 410 | static inline int |
411 | ctnetlink_dump_nat_seq_adj(struct sk_buff *skb, const struct nf_conn *ct) | 411 | ctnetlink_dump_ct_seq_adj(struct sk_buff *skb, const struct nf_conn *ct) |
412 | { | 412 | { |
413 | struct nf_nat_seq *natseq; | 413 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); |
414 | struct nf_conn_nat *nat = nfct_nat(ct); | 414 | struct nf_ct_seqadj *seq; |
415 | 415 | ||
416 | if (!(ct->status & IPS_SEQ_ADJUST) || !nat) | 416 | if (!(ct->status & IPS_SEQ_ADJUST) || !seqadj) |
417 | return 0; | 417 | return 0; |
418 | 418 | ||
419 | natseq = &nat->seq[IP_CT_DIR_ORIGINAL]; | 419 | seq = &seqadj->seq[IP_CT_DIR_ORIGINAL]; |
420 | if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_ORIG) == -1) | 420 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_ORIG) == -1) |
421 | return -1; | 421 | return -1; |
422 | 422 | ||
423 | natseq = &nat->seq[IP_CT_DIR_REPLY]; | 423 | seq = &seqadj->seq[IP_CT_DIR_REPLY]; |
424 | if (dump_nat_seq_adj(skb, natseq, CTA_NAT_SEQ_ADJ_REPLY) == -1) | 424 | if (dump_ct_seq_adj(skb, seq, CTA_SEQ_ADJ_REPLY) == -1) |
425 | return -1; | 425 | return -1; |
426 | 426 | ||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | #else | ||
430 | #define ctnetlink_dump_nat_seq_adj(a, b) (0) | ||
431 | #endif | ||
432 | 429 | ||
433 | static inline int | 430 | static inline int |
434 | ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) | 431 | ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) |
@@ -502,7 +499,7 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, | |||
502 | ctnetlink_dump_id(skb, ct) < 0 || | 499 | ctnetlink_dump_id(skb, ct) < 0 || |
503 | ctnetlink_dump_use(skb, ct) < 0 || | 500 | ctnetlink_dump_use(skb, ct) < 0 || |
504 | ctnetlink_dump_master(skb, ct) < 0 || | 501 | ctnetlink_dump_master(skb, ct) < 0 || |
505 | ctnetlink_dump_nat_seq_adj(skb, ct) < 0) | 502 | ctnetlink_dump_ct_seq_adj(skb, ct) < 0) |
506 | goto nla_put_failure; | 503 | goto nla_put_failure; |
507 | 504 | ||
508 | nlmsg_end(skb, nlh); | 505 | nlmsg_end(skb, nlh); |
@@ -707,8 +704,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) | |||
707 | ctnetlink_dump_master(skb, ct) < 0) | 704 | ctnetlink_dump_master(skb, ct) < 0) |
708 | goto nla_put_failure; | 705 | goto nla_put_failure; |
709 | 706 | ||
710 | if (events & (1 << IPCT_NATSEQADJ) && | 707 | if (events & (1 << IPCT_SEQADJ) && |
711 | ctnetlink_dump_nat_seq_adj(skb, ct) < 0) | 708 | ctnetlink_dump_ct_seq_adj(skb, ct) < 0) |
712 | goto nla_put_failure; | 709 | goto nla_put_failure; |
713 | } | 710 | } |
714 | 711 | ||
@@ -1439,66 +1436,65 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[] | |||
1439 | return err; | 1436 | return err; |
1440 | } | 1437 | } |
1441 | 1438 | ||
1442 | #ifdef CONFIG_NF_NAT_NEEDED | 1439 | static const struct nla_policy seqadj_policy[CTA_SEQADJ_MAX+1] = { |
1443 | static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = { | 1440 | [CTA_SEQADJ_CORRECTION_POS] = { .type = NLA_U32 }, |
1444 | [CTA_NAT_SEQ_CORRECTION_POS] = { .type = NLA_U32 }, | 1441 | [CTA_SEQADJ_OFFSET_BEFORE] = { .type = NLA_U32 }, |
1445 | [CTA_NAT_SEQ_OFFSET_BEFORE] = { .type = NLA_U32 }, | 1442 | [CTA_SEQADJ_OFFSET_AFTER] = { .type = NLA_U32 }, |
1446 | [CTA_NAT_SEQ_OFFSET_AFTER] = { .type = NLA_U32 }, | ||
1447 | }; | 1443 | }; |
1448 | 1444 | ||
1449 | static inline int | 1445 | static inline int |
1450 | change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) | 1446 | change_seq_adj(struct nf_ct_seqadj *seq, const struct nlattr * const attr) |
1451 | { | 1447 | { |
1452 | int err; | 1448 | int err; |
1453 | struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; | 1449 | struct nlattr *cda[CTA_SEQADJ_MAX+1]; |
1454 | 1450 | ||
1455 | err = nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy); | 1451 | err = nla_parse_nested(cda, CTA_SEQADJ_MAX, attr, seqadj_policy); |
1456 | if (err < 0) | 1452 | if (err < 0) |
1457 | return err; | 1453 | return err; |
1458 | 1454 | ||
1459 | if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) | 1455 | if (!cda[CTA_SEQADJ_CORRECTION_POS]) |
1460 | return -EINVAL; | 1456 | return -EINVAL; |
1461 | 1457 | ||
1462 | natseq->correction_pos = | 1458 | seq->correction_pos = |
1463 | ntohl(nla_get_be32(cda[CTA_NAT_SEQ_CORRECTION_POS])); | 1459 | ntohl(nla_get_be32(cda[CTA_SEQADJ_CORRECTION_POS])); |
1464 | 1460 | ||
1465 | if (!cda[CTA_NAT_SEQ_OFFSET_BEFORE]) | 1461 | if (!cda[CTA_SEQADJ_OFFSET_BEFORE]) |
1466 | return -EINVAL; | 1462 | return -EINVAL; |
1467 | 1463 | ||
1468 | natseq->offset_before = | 1464 | seq->offset_before = |
1469 | ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_BEFORE])); | 1465 | ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_BEFORE])); |
1470 | 1466 | ||
1471 | if (!cda[CTA_NAT_SEQ_OFFSET_AFTER]) | 1467 | if (!cda[CTA_SEQADJ_OFFSET_AFTER]) |
1472 | return -EINVAL; | 1468 | return -EINVAL; |
1473 | 1469 | ||
1474 | natseq->offset_after = | 1470 | seq->offset_after = |
1475 | ntohl(nla_get_be32(cda[CTA_NAT_SEQ_OFFSET_AFTER])); | 1471 | ntohl(nla_get_be32(cda[CTA_SEQADJ_OFFSET_AFTER])); |
1476 | 1472 | ||
1477 | return 0; | 1473 | return 0; |
1478 | } | 1474 | } |
1479 | 1475 | ||
1480 | static int | 1476 | static int |
1481 | ctnetlink_change_nat_seq_adj(struct nf_conn *ct, | 1477 | ctnetlink_change_seq_adj(struct nf_conn *ct, |
1482 | const struct nlattr * const cda[]) | 1478 | const struct nlattr * const cda[]) |
1483 | { | 1479 | { |
1480 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | ||
1484 | int ret = 0; | 1481 | int ret = 0; |
1485 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
1486 | 1482 | ||
1487 | if (!nat) | 1483 | if (!seqadj) |
1488 | return 0; | 1484 | return 0; |
1489 | 1485 | ||
1490 | if (cda[CTA_NAT_SEQ_ADJ_ORIG]) { | 1486 | if (cda[CTA_SEQ_ADJ_ORIG]) { |
1491 | ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_ORIGINAL], | 1487 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_ORIGINAL], |
1492 | cda[CTA_NAT_SEQ_ADJ_ORIG]); | 1488 | cda[CTA_SEQ_ADJ_ORIG]); |
1493 | if (ret < 0) | 1489 | if (ret < 0) |
1494 | return ret; | 1490 | return ret; |
1495 | 1491 | ||
1496 | ct->status |= IPS_SEQ_ADJUST; | 1492 | ct->status |= IPS_SEQ_ADJUST; |
1497 | } | 1493 | } |
1498 | 1494 | ||
1499 | if (cda[CTA_NAT_SEQ_ADJ_REPLY]) { | 1495 | if (cda[CTA_SEQ_ADJ_REPLY]) { |
1500 | ret = change_nat_seq_adj(&nat->seq[IP_CT_DIR_REPLY], | 1496 | ret = change_seq_adj(&seqadj->seq[IP_CT_DIR_REPLY], |
1501 | cda[CTA_NAT_SEQ_ADJ_REPLY]); | 1497 | cda[CTA_SEQ_ADJ_REPLY]); |
1502 | if (ret < 0) | 1498 | if (ret < 0) |
1503 | return ret; | 1499 | return ret; |
1504 | 1500 | ||
@@ -1507,7 +1503,6 @@ ctnetlink_change_nat_seq_adj(struct nf_conn *ct, | |||
1507 | 1503 | ||
1508 | return 0; | 1504 | return 0; |
1509 | } | 1505 | } |
1510 | #endif | ||
1511 | 1506 | ||
1512 | static int | 1507 | static int |
1513 | ctnetlink_attach_labels(struct nf_conn *ct, const struct nlattr * const cda[]) | 1508 | ctnetlink_attach_labels(struct nf_conn *ct, const struct nlattr * const cda[]) |
@@ -1573,13 +1568,12 @@ ctnetlink_change_conntrack(struct nf_conn *ct, | |||
1573 | ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); | 1568 | ct->mark = ntohl(nla_get_be32(cda[CTA_MARK])); |
1574 | #endif | 1569 | #endif |
1575 | 1570 | ||
1576 | #ifdef CONFIG_NF_NAT_NEEDED | 1571 | if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) { |
1577 | if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { | 1572 | err = ctnetlink_change_seq_adj(ct, cda); |
1578 | err = ctnetlink_change_nat_seq_adj(ct, cda); | ||
1579 | if (err < 0) | 1573 | if (err < 0) |
1580 | return err; | 1574 | return err; |
1581 | } | 1575 | } |
1582 | #endif | 1576 | |
1583 | if (cda[CTA_LABELS]) { | 1577 | if (cda[CTA_LABELS]) { |
1584 | err = ctnetlink_attach_labels(ct, cda); | 1578 | err = ctnetlink_attach_labels(ct, cda); |
1585 | if (err < 0) | 1579 | if (err < 0) |
@@ -1684,13 +1678,11 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
1684 | goto err2; | 1678 | goto err2; |
1685 | } | 1679 | } |
1686 | 1680 | ||
1687 | #ifdef CONFIG_NF_NAT_NEEDED | 1681 | if (cda[CTA_SEQ_ADJ_ORIG] || cda[CTA_SEQ_ADJ_REPLY]) { |
1688 | if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { | 1682 | err = ctnetlink_change_seq_adj(ct, cda); |
1689 | err = ctnetlink_change_nat_seq_adj(ct, cda); | ||
1690 | if (err < 0) | 1683 | if (err < 0) |
1691 | goto err2; | 1684 | goto err2; |
1692 | } | 1685 | } |
1693 | #endif | ||
1694 | 1686 | ||
1695 | memset(&ct->proto, 0, sizeof(ct->proto)); | 1687 | memset(&ct->proto, 0, sizeof(ct->proto)); |
1696 | if (cda[CTA_PROTOINFO]) { | 1688 | if (cda[CTA_PROTOINFO]) { |
@@ -1804,7 +1796,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1804 | (1 << IPCT_ASSURED) | | 1796 | (1 << IPCT_ASSURED) | |
1805 | (1 << IPCT_HELPER) | | 1797 | (1 << IPCT_HELPER) | |
1806 | (1 << IPCT_PROTOINFO) | | 1798 | (1 << IPCT_PROTOINFO) | |
1807 | (1 << IPCT_NATSEQADJ) | | 1799 | (1 << IPCT_SEQADJ) | |
1808 | (1 << IPCT_MARK) | events, | 1800 | (1 << IPCT_MARK) | events, |
1809 | ct, NETLINK_CB(skb).portid, | 1801 | ct, NETLINK_CB(skb).portid, |
1810 | nlmsg_report(nlh)); | 1802 | nlmsg_report(nlh)); |
@@ -1827,7 +1819,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1827 | (1 << IPCT_HELPER) | | 1819 | (1 << IPCT_HELPER) | |
1828 | (1 << IPCT_LABEL) | | 1820 | (1 << IPCT_LABEL) | |
1829 | (1 << IPCT_PROTOINFO) | | 1821 | (1 << IPCT_PROTOINFO) | |
1830 | (1 << IPCT_NATSEQADJ) | | 1822 | (1 << IPCT_SEQADJ) | |
1831 | (1 << IPCT_MARK), | 1823 | (1 << IPCT_MARK), |
1832 | ct, NETLINK_CB(skb).portid, | 1824 | ct, NETLINK_CB(skb).portid, |
1833 | nlmsg_report(nlh)); | 1825 | nlmsg_report(nlh)); |
@@ -2082,7 +2074,7 @@ ctnetlink_nfqueue_build(struct sk_buff *skb, struct nf_conn *ct) | |||
2082 | goto nla_put_failure; | 2074 | goto nla_put_failure; |
2083 | 2075 | ||
2084 | if ((ct->status & IPS_SEQ_ADJUST) && | 2076 | if ((ct->status & IPS_SEQ_ADJUST) && |
2085 | ctnetlink_dump_nat_seq_adj(skb, ct) < 0) | 2077 | ctnetlink_dump_ct_seq_adj(skb, ct) < 0) |
2086 | goto nla_put_failure; | 2078 | goto nla_put_failure; |
2087 | 2079 | ||
2088 | #ifdef CONFIG_NF_CONNTRACK_MARK | 2080 | #ifdef CONFIG_NF_CONNTRACK_MARK |
@@ -2211,6 +2203,7 @@ static struct nfq_ct_hook ctnetlink_nfqueue_hook = { | |||
2211 | .build = ctnetlink_nfqueue_build, | 2203 | .build = ctnetlink_nfqueue_build, |
2212 | .parse = ctnetlink_nfqueue_parse, | 2204 | .parse = ctnetlink_nfqueue_parse, |
2213 | .attach_expect = ctnetlink_nfqueue_attach_expect, | 2205 | .attach_expect = ctnetlink_nfqueue_attach_expect, |
2206 | .seq_adjust = nf_ct_tcp_seqadj_set, | ||
2214 | }; | 2207 | }; |
2215 | #endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */ | 2208 | #endif /* CONFIG_NETFILTER_NETLINK_QUEUE_CT */ |
2216 | 2209 | ||
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index d224e001f14f..984a8d1a3359 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <net/netfilter/nf_conntrack.h> | 27 | #include <net/netfilter/nf_conntrack.h> |
28 | #include <net/netfilter/nf_conntrack_l4proto.h> | 28 | #include <net/netfilter/nf_conntrack_l4proto.h> |
29 | #include <net/netfilter/nf_conntrack_ecache.h> | 29 | #include <net/netfilter/nf_conntrack_ecache.h> |
30 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
30 | #include <net/netfilter/nf_log.h> | 31 | #include <net/netfilter/nf_log.h> |
31 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> | 32 | #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> |
32 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 33 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
@@ -495,21 +496,6 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, | |||
495 | } | 496 | } |
496 | } | 497 | } |
497 | 498 | ||
498 | #ifdef CONFIG_NF_NAT_NEEDED | ||
499 | static inline s32 nat_offset(const struct nf_conn *ct, | ||
500 | enum ip_conntrack_dir dir, | ||
501 | u32 seq) | ||
502 | { | ||
503 | typeof(nf_ct_nat_offset) get_offset = rcu_dereference(nf_ct_nat_offset); | ||
504 | |||
505 | return get_offset != NULL ? get_offset(ct, dir, seq) : 0; | ||
506 | } | ||
507 | #define NAT_OFFSET(ct, dir, seq) \ | ||
508 | (nat_offset(ct, dir, seq)) | ||
509 | #else | ||
510 | #define NAT_OFFSET(ct, dir, seq) 0 | ||
511 | #endif | ||
512 | |||
513 | static bool tcp_in_window(const struct nf_conn *ct, | 499 | static bool tcp_in_window(const struct nf_conn *ct, |
514 | struct ip_ct_tcp *state, | 500 | struct ip_ct_tcp *state, |
515 | enum ip_conntrack_dir dir, | 501 | enum ip_conntrack_dir dir, |
@@ -540,7 +526,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
540 | tcp_sack(skb, dataoff, tcph, &sack); | 526 | tcp_sack(skb, dataoff, tcph, &sack); |
541 | 527 | ||
542 | /* Take into account NAT sequence number mangling */ | 528 | /* Take into account NAT sequence number mangling */ |
543 | receiver_offset = NAT_OFFSET(ct, !dir, ack - 1); | 529 | receiver_offset = nf_ct_seq_offset(ct, !dir, ack - 1); |
544 | ack -= receiver_offset; | 530 | ack -= receiver_offset; |
545 | sack -= receiver_offset; | 531 | sack -= receiver_offset; |
546 | 532 | ||
diff --git a/net/netfilter/nf_conntrack_seqadj.c b/net/netfilter/nf_conntrack_seqadj.c new file mode 100644 index 000000000000..483eb9ce3216 --- /dev/null +++ b/net/netfilter/nf_conntrack_seqadj.c | |||
@@ -0,0 +1,218 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/netfilter.h> | ||
3 | #include <net/tcp.h> | ||
4 | |||
5 | #include <net/netfilter/nf_conntrack.h> | ||
6 | #include <net/netfilter/nf_conntrack_extend.h> | ||
7 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
8 | |||
9 | int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
10 | __be32 seq, s32 off) | ||
11 | { | ||
12 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | ||
13 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
14 | struct nf_ct_seqadj *this_way; | ||
15 | |||
16 | if (off == 0) | ||
17 | return 0; | ||
18 | |||
19 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); | ||
20 | |||
21 | spin_lock_bh(&ct->lock); | ||
22 | this_way = &seqadj->seq[dir]; | ||
23 | if (this_way->offset_before == this_way->offset_after || | ||
24 | before(this_way->correction_pos, seq)) { | ||
25 | this_way->correction_pos = seq; | ||
26 | this_way->offset_before = this_way->offset_after; | ||
27 | this_way->offset_after += off; | ||
28 | } | ||
29 | spin_unlock_bh(&ct->lock); | ||
30 | return 0; | ||
31 | } | ||
32 | EXPORT_SYMBOL_GPL(nf_ct_seqadj_set); | ||
33 | |||
34 | void nf_ct_tcp_seqadj_set(struct sk_buff *skb, | ||
35 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
36 | s32 off) | ||
37 | { | ||
38 | const struct tcphdr *th; | ||
39 | |||
40 | if (nf_ct_protonum(ct) != IPPROTO_TCP) | ||
41 | return; | ||
42 | |||
43 | th = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb)); | ||
44 | nf_ct_seqadj_set(ct, ctinfo, th->seq, off); | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(nf_ct_tcp_seqadj_set); | ||
47 | |||
48 | /* Adjust one found SACK option including checksum correction */ | ||
49 | static void nf_ct_sack_block_adjust(struct sk_buff *skb, | ||
50 | struct tcphdr *tcph, | ||
51 | unsigned int sackoff, | ||
52 | unsigned int sackend, | ||
53 | struct nf_ct_seqadj *seq) | ||
54 | { | ||
55 | while (sackoff < sackend) { | ||
56 | struct tcp_sack_block_wire *sack; | ||
57 | __be32 new_start_seq, new_end_seq; | ||
58 | |||
59 | sack = (void *)skb->data + sackoff; | ||
60 | if (after(ntohl(sack->start_seq) - seq->offset_before, | ||
61 | seq->correction_pos)) | ||
62 | new_start_seq = htonl(ntohl(sack->start_seq) - | ||
63 | seq->offset_after); | ||
64 | else | ||
65 | new_start_seq = htonl(ntohl(sack->start_seq) - | ||
66 | seq->offset_before); | ||
67 | |||
68 | if (after(ntohl(sack->end_seq) - seq->offset_before, | ||
69 | seq->correction_pos)) | ||
70 | new_end_seq = htonl(ntohl(sack->end_seq) - | ||
71 | seq->offset_after); | ||
72 | else | ||
73 | new_end_seq = htonl(ntohl(sack->end_seq) - | ||
74 | seq->offset_before); | ||
75 | |||
76 | pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", | ||
77 | ntohl(sack->start_seq), new_start_seq, | ||
78 | ntohl(sack->end_seq), new_end_seq); | ||
79 | |||
80 | inet_proto_csum_replace4(&tcph->check, skb, | ||
81 | sack->start_seq, new_start_seq, 0); | ||
82 | inet_proto_csum_replace4(&tcph->check, skb, | ||
83 | sack->end_seq, new_end_seq, 0); | ||
84 | sack->start_seq = new_start_seq; | ||
85 | sack->end_seq = new_end_seq; | ||
86 | sackoff += sizeof(*sack); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | /* TCP SACK sequence number adjustment */ | ||
91 | static unsigned int nf_ct_sack_adjust(struct sk_buff *skb, | ||
92 | unsigned int protoff, | ||
93 | struct tcphdr *tcph, | ||
94 | struct nf_conn *ct, | ||
95 | enum ip_conntrack_info ctinfo) | ||
96 | { | ||
97 | unsigned int dir, optoff, optend; | ||
98 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | ||
99 | |||
100 | optoff = protoff + sizeof(struct tcphdr); | ||
101 | optend = protoff + tcph->doff * 4; | ||
102 | |||
103 | if (!skb_make_writable(skb, optend)) | ||
104 | return 0; | ||
105 | |||
106 | dir = CTINFO2DIR(ctinfo); | ||
107 | |||
108 | while (optoff < optend) { | ||
109 | /* Usually: option, length. */ | ||
110 | unsigned char *op = skb->data + optoff; | ||
111 | |||
112 | switch (op[0]) { | ||
113 | case TCPOPT_EOL: | ||
114 | return 1; | ||
115 | case TCPOPT_NOP: | ||
116 | optoff++; | ||
117 | continue; | ||
118 | default: | ||
119 | /* no partial options */ | ||
120 | if (optoff + 1 == optend || | ||
121 | optoff + op[1] > optend || | ||
122 | op[1] < 2) | ||
123 | return 0; | ||
124 | if (op[0] == TCPOPT_SACK && | ||
125 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && | ||
126 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) | ||
127 | nf_ct_sack_block_adjust(skb, tcph, optoff + 2, | ||
128 | optoff+op[1], | ||
129 | &seqadj->seq[!dir]); | ||
130 | optoff += op[1]; | ||
131 | } | ||
132 | } | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ | ||
137 | int nf_ct_seq_adjust(struct sk_buff *skb, | ||
138 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
139 | unsigned int protoff) | ||
140 | { | ||
141 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
142 | struct tcphdr *tcph; | ||
143 | __be32 newseq, newack; | ||
144 | s32 seqoff, ackoff; | ||
145 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | ||
146 | struct nf_ct_seqadj *this_way, *other_way; | ||
147 | int res; | ||
148 | |||
149 | this_way = &seqadj->seq[dir]; | ||
150 | other_way = &seqadj->seq[!dir]; | ||
151 | |||
152 | if (!skb_make_writable(skb, protoff + sizeof(*tcph))) | ||
153 | return 0; | ||
154 | |||
155 | tcph = (void *)skb->data + protoff; | ||
156 | spin_lock_bh(&ct->lock); | ||
157 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | ||
158 | seqoff = this_way->offset_after; | ||
159 | else | ||
160 | seqoff = this_way->offset_before; | ||
161 | |||
162 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, | ||
163 | other_way->correction_pos)) | ||
164 | ackoff = other_way->offset_after; | ||
165 | else | ||
166 | ackoff = other_way->offset_before; | ||
167 | |||
168 | newseq = htonl(ntohl(tcph->seq) + seqoff); | ||
169 | newack = htonl(ntohl(tcph->ack_seq) - ackoff); | ||
170 | |||
171 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); | ||
172 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); | ||
173 | |||
174 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", | ||
175 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | ||
176 | ntohl(newack)); | ||
177 | |||
178 | tcph->seq = newseq; | ||
179 | tcph->ack_seq = newack; | ||
180 | |||
181 | res = nf_ct_sack_adjust(skb, protoff, tcph, ct, ctinfo); | ||
182 | spin_unlock_bh(&ct->lock); | ||
183 | |||
184 | return res; | ||
185 | } | ||
186 | EXPORT_SYMBOL_GPL(nf_ct_seq_adjust); | ||
187 | |||
188 | s32 nf_ct_seq_offset(const struct nf_conn *ct, | ||
189 | enum ip_conntrack_dir dir, | ||
190 | u32 seq) | ||
191 | { | ||
192 | struct nf_conn_seqadj *seqadj = nfct_seqadj(ct); | ||
193 | struct nf_ct_seqadj *this_way; | ||
194 | |||
195 | if (!seqadj) | ||
196 | return 0; | ||
197 | |||
198 | this_way = &seqadj->seq[dir]; | ||
199 | return after(seq, this_way->correction_pos) ? | ||
200 | this_way->offset_after : this_way->offset_before; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(nf_ct_seq_offset); | ||
203 | |||
204 | static struct nf_ct_ext_type nf_ct_seqadj_extend __read_mostly = { | ||
205 | .len = sizeof(struct nf_conn_seqadj), | ||
206 | .align = __alignof__(struct nf_conn_seqadj), | ||
207 | .id = NF_CT_EXT_SEQADJ, | ||
208 | }; | ||
209 | |||
210 | int nf_conntrack_seqadj_init(void) | ||
211 | { | ||
212 | return nf_ct_extend_register(&nf_ct_seqadj_extend); | ||
213 | } | ||
214 | |||
215 | void nf_conntrack_seqadj_fini(void) | ||
216 | { | ||
217 | nf_ct_extend_unregister(&nf_ct_seqadj_extend); | ||
218 | } | ||
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 6ff808375b5e..6f0f4f7f68a5 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <net/netfilter/nf_nat_core.h> | 25 | #include <net/netfilter/nf_nat_core.h> |
26 | #include <net/netfilter/nf_nat_helper.h> | 26 | #include <net/netfilter/nf_nat_helper.h> |
27 | #include <net/netfilter/nf_conntrack_helper.h> | 27 | #include <net/netfilter/nf_conntrack_helper.h> |
28 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
28 | #include <net/netfilter/nf_conntrack_l3proto.h> | 29 | #include <net/netfilter/nf_conntrack_l3proto.h> |
29 | #include <net/netfilter/nf_conntrack_zones.h> | 30 | #include <net/netfilter/nf_conntrack_zones.h> |
30 | #include <linux/netfilter/nf_nat.h> | 31 | #include <linux/netfilter/nf_nat.h> |
@@ -402,6 +403,9 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
402 | ct->status |= IPS_SRC_NAT; | 403 | ct->status |= IPS_SRC_NAT; |
403 | else | 404 | else |
404 | ct->status |= IPS_DST_NAT; | 405 | ct->status |= IPS_DST_NAT; |
406 | |||
407 | if (nfct_help(ct)) | ||
408 | nfct_seqadj_ext_add(ct); | ||
405 | } | 409 | } |
406 | 410 | ||
407 | if (maniptype == NF_NAT_MANIP_SRC) { | 411 | if (maniptype == NF_NAT_MANIP_SRC) { |
@@ -764,10 +768,6 @@ static struct nf_ct_helper_expectfn follow_master_nat = { | |||
764 | .expectfn = nf_nat_follow_master, | 768 | .expectfn = nf_nat_follow_master, |
765 | }; | 769 | }; |
766 | 770 | ||
767 | static struct nfq_ct_nat_hook nfq_ct_nat = { | ||
768 | .seq_adjust = nf_nat_tcp_seq_adjust, | ||
769 | }; | ||
770 | |||
771 | static int __init nf_nat_init(void) | 771 | static int __init nf_nat_init(void) |
772 | { | 772 | { |
773 | int ret; | 773 | int ret; |
@@ -787,14 +787,9 @@ static int __init nf_nat_init(void) | |||
787 | /* Initialize fake conntrack so that NAT will skip it */ | 787 | /* Initialize fake conntrack so that NAT will skip it */ |
788 | nf_ct_untracked_status_or(IPS_NAT_DONE_MASK); | 788 | nf_ct_untracked_status_or(IPS_NAT_DONE_MASK); |
789 | 789 | ||
790 | BUG_ON(nf_nat_seq_adjust_hook != NULL); | ||
791 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); | ||
792 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); | 790 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
793 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, | 791 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, |
794 | nfnetlink_parse_nat_setup); | 792 | nfnetlink_parse_nat_setup); |
795 | BUG_ON(nf_ct_nat_offset != NULL); | ||
796 | RCU_INIT_POINTER(nf_ct_nat_offset, nf_nat_get_offset); | ||
797 | RCU_INIT_POINTER(nfq_ct_nat_hook, &nfq_ct_nat); | ||
798 | #ifdef CONFIG_XFRM | 793 | #ifdef CONFIG_XFRM |
799 | BUG_ON(nf_nat_decode_session_hook != NULL); | 794 | BUG_ON(nf_nat_decode_session_hook != NULL); |
800 | RCU_INIT_POINTER(nf_nat_decode_session_hook, __nf_nat_decode_session); | 795 | RCU_INIT_POINTER(nf_nat_decode_session_hook, __nf_nat_decode_session); |
@@ -813,10 +808,7 @@ static void __exit nf_nat_cleanup(void) | |||
813 | unregister_pernet_subsys(&nf_nat_net_ops); | 808 | unregister_pernet_subsys(&nf_nat_net_ops); |
814 | nf_ct_extend_unregister(&nat_extend); | 809 | nf_ct_extend_unregister(&nat_extend); |
815 | nf_ct_helper_expectfn_unregister(&follow_master_nat); | 810 | nf_ct_helper_expectfn_unregister(&follow_master_nat); |
816 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); | ||
817 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); | 811 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); |
818 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); | ||
819 | RCU_INIT_POINTER(nfq_ct_nat_hook, NULL); | ||
820 | #ifdef CONFIG_XFRM | 812 | #ifdef CONFIG_XFRM |
821 | RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); | 813 | RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); |
822 | #endif | 814 | #endif |
diff --git a/net/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index 46b9baa845a6..2840abb5bb99 100644 --- a/net/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c | |||
@@ -20,67 +20,13 @@ | |||
20 | #include <net/netfilter/nf_conntrack_helper.h> | 20 | #include <net/netfilter/nf_conntrack_helper.h> |
21 | #include <net/netfilter/nf_conntrack_ecache.h> | 21 | #include <net/netfilter/nf_conntrack_ecache.h> |
22 | #include <net/netfilter/nf_conntrack_expect.h> | 22 | #include <net/netfilter/nf_conntrack_expect.h> |
23 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
23 | #include <net/netfilter/nf_nat.h> | 24 | #include <net/netfilter/nf_nat.h> |
24 | #include <net/netfilter/nf_nat_l3proto.h> | 25 | #include <net/netfilter/nf_nat_l3proto.h> |
25 | #include <net/netfilter/nf_nat_l4proto.h> | 26 | #include <net/netfilter/nf_nat_l4proto.h> |
26 | #include <net/netfilter/nf_nat_core.h> | 27 | #include <net/netfilter/nf_nat_core.h> |
27 | #include <net/netfilter/nf_nat_helper.h> | 28 | #include <net/netfilter/nf_nat_helper.h> |
28 | 29 | ||
29 | #define DUMP_OFFSET(x) \ | ||
30 | pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \ | ||
31 | x->offset_before, x->offset_after, x->correction_pos); | ||
32 | |||
33 | /* Setup TCP sequence correction given this change at this sequence */ | ||
34 | static inline void | ||
35 | adjust_tcp_sequence(u32 seq, | ||
36 | int sizediff, | ||
37 | struct nf_conn *ct, | ||
38 | enum ip_conntrack_info ctinfo) | ||
39 | { | ||
40 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
41 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
42 | struct nf_nat_seq *this_way = &nat->seq[dir]; | ||
43 | |||
44 | pr_debug("adjust_tcp_sequence: seq = %u, sizediff = %d\n", | ||
45 | seq, sizediff); | ||
46 | |||
47 | pr_debug("adjust_tcp_sequence: Seq_offset before: "); | ||
48 | DUMP_OFFSET(this_way); | ||
49 | |||
50 | spin_lock_bh(&ct->lock); | ||
51 | |||
52 | /* SYN adjust. If it's uninitialized, or this is after last | ||
53 | * correction, record it: we don't handle more than one | ||
54 | * adjustment in the window, but do deal with common case of a | ||
55 | * retransmit */ | ||
56 | if (this_way->offset_before == this_way->offset_after || | ||
57 | before(this_way->correction_pos, seq)) { | ||
58 | this_way->correction_pos = seq; | ||
59 | this_way->offset_before = this_way->offset_after; | ||
60 | this_way->offset_after += sizediff; | ||
61 | } | ||
62 | spin_unlock_bh(&ct->lock); | ||
63 | |||
64 | pr_debug("adjust_tcp_sequence: Seq_offset after: "); | ||
65 | DUMP_OFFSET(this_way); | ||
66 | } | ||
67 | |||
68 | /* Get the offset value, for conntrack. Caller must have the conntrack locked */ | ||
69 | s32 nf_nat_get_offset(const struct nf_conn *ct, | ||
70 | enum ip_conntrack_dir dir, | ||
71 | u32 seq) | ||
72 | { | ||
73 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
74 | struct nf_nat_seq *this_way; | ||
75 | |||
76 | if (!nat) | ||
77 | return 0; | ||
78 | |||
79 | this_way = &nat->seq[dir]; | ||
80 | return after(seq, this_way->correction_pos) | ||
81 | ? this_way->offset_after : this_way->offset_before; | ||
82 | } | ||
83 | |||
84 | /* Frobs data inside this packet, which is linear. */ | 30 | /* Frobs data inside this packet, which is linear. */ |
85 | static void mangle_contents(struct sk_buff *skb, | 31 | static void mangle_contents(struct sk_buff *skb, |
86 | unsigned int dataoff, | 32 | unsigned int dataoff, |
@@ -135,30 +81,6 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra) | |||
135 | return 1; | 81 | return 1; |
136 | } | 82 | } |
137 | 83 | ||
138 | void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, | ||
139 | __be32 seq, s32 off) | ||
140 | { | ||
141 | if (!off) | ||
142 | return; | ||
143 | set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); | ||
144 | adjust_tcp_sequence(ntohl(seq), off, ct, ctinfo); | ||
145 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); | ||
148 | |||
149 | void nf_nat_tcp_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | ||
150 | u32 ctinfo, int off) | ||
151 | { | ||
152 | const struct tcphdr *th; | ||
153 | |||
154 | if (nf_ct_protonum(ct) != IPPROTO_TCP) | ||
155 | return; | ||
156 | |||
157 | th = (struct tcphdr *)(skb_network_header(skb)+ ip_hdrlen(skb)); | ||
158 | nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off); | ||
159 | } | ||
160 | EXPORT_SYMBOL_GPL(nf_nat_tcp_seq_adjust); | ||
161 | |||
162 | /* Generic function for mangling variable-length address changes inside | 84 | /* Generic function for mangling variable-length address changes inside |
163 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX | 85 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX |
164 | * command in FTP). | 86 | * command in FTP). |
@@ -203,8 +125,8 @@ int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
203 | datalen, oldlen); | 125 | datalen, oldlen); |
204 | 126 | ||
205 | if (adjust && rep_len != match_len) | 127 | if (adjust && rep_len != match_len) |
206 | nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, | 128 | nf_ct_seqadj_set(ct, ctinfo, tcph->seq, |
207 | (int)rep_len - (int)match_len); | 129 | (int)rep_len - (int)match_len); |
208 | 130 | ||
209 | return 1; | 131 | return 1; |
210 | } | 132 | } |
@@ -264,150 +186,6 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
264 | } | 186 | } |
265 | EXPORT_SYMBOL(nf_nat_mangle_udp_packet); | 187 | EXPORT_SYMBOL(nf_nat_mangle_udp_packet); |
266 | 188 | ||
267 | /* Adjust one found SACK option including checksum correction */ | ||
268 | static void | ||
269 | sack_adjust(struct sk_buff *skb, | ||
270 | struct tcphdr *tcph, | ||
271 | unsigned int sackoff, | ||
272 | unsigned int sackend, | ||
273 | struct nf_nat_seq *natseq) | ||
274 | { | ||
275 | while (sackoff < sackend) { | ||
276 | struct tcp_sack_block_wire *sack; | ||
277 | __be32 new_start_seq, new_end_seq; | ||
278 | |||
279 | sack = (void *)skb->data + sackoff; | ||
280 | if (after(ntohl(sack->start_seq) - natseq->offset_before, | ||
281 | natseq->correction_pos)) | ||
282 | new_start_seq = htonl(ntohl(sack->start_seq) | ||
283 | - natseq->offset_after); | ||
284 | else | ||
285 | new_start_seq = htonl(ntohl(sack->start_seq) | ||
286 | - natseq->offset_before); | ||
287 | |||
288 | if (after(ntohl(sack->end_seq) - natseq->offset_before, | ||
289 | natseq->correction_pos)) | ||
290 | new_end_seq = htonl(ntohl(sack->end_seq) | ||
291 | - natseq->offset_after); | ||
292 | else | ||
293 | new_end_seq = htonl(ntohl(sack->end_seq) | ||
294 | - natseq->offset_before); | ||
295 | |||
296 | pr_debug("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", | ||
297 | ntohl(sack->start_seq), new_start_seq, | ||
298 | ntohl(sack->end_seq), new_end_seq); | ||
299 | |||
300 | inet_proto_csum_replace4(&tcph->check, skb, | ||
301 | sack->start_seq, new_start_seq, 0); | ||
302 | inet_proto_csum_replace4(&tcph->check, skb, | ||
303 | sack->end_seq, new_end_seq, 0); | ||
304 | sack->start_seq = new_start_seq; | ||
305 | sack->end_seq = new_end_seq; | ||
306 | sackoff += sizeof(*sack); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | /* TCP SACK sequence number adjustment */ | ||
311 | static inline unsigned int | ||
312 | nf_nat_sack_adjust(struct sk_buff *skb, | ||
313 | unsigned int protoff, | ||
314 | struct tcphdr *tcph, | ||
315 | struct nf_conn *ct, | ||
316 | enum ip_conntrack_info ctinfo) | ||
317 | { | ||
318 | unsigned int dir, optoff, optend; | ||
319 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
320 | |||
321 | optoff = protoff + sizeof(struct tcphdr); | ||
322 | optend = protoff + tcph->doff * 4; | ||
323 | |||
324 | if (!skb_make_writable(skb, optend)) | ||
325 | return 0; | ||
326 | |||
327 | dir = CTINFO2DIR(ctinfo); | ||
328 | |||
329 | while (optoff < optend) { | ||
330 | /* Usually: option, length. */ | ||
331 | unsigned char *op = skb->data + optoff; | ||
332 | |||
333 | switch (op[0]) { | ||
334 | case TCPOPT_EOL: | ||
335 | return 1; | ||
336 | case TCPOPT_NOP: | ||
337 | optoff++; | ||
338 | continue; | ||
339 | default: | ||
340 | /* no partial options */ | ||
341 | if (optoff + 1 == optend || | ||
342 | optoff + op[1] > optend || | ||
343 | op[1] < 2) | ||
344 | return 0; | ||
345 | if (op[0] == TCPOPT_SACK && | ||
346 | op[1] >= 2+TCPOLEN_SACK_PERBLOCK && | ||
347 | ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) | ||
348 | sack_adjust(skb, tcph, optoff+2, | ||
349 | optoff+op[1], &nat->seq[!dir]); | ||
350 | optoff += op[1]; | ||
351 | } | ||
352 | } | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | /* TCP sequence number adjustment. Returns 1 on success, 0 on failure */ | ||
357 | int | ||
358 | nf_nat_seq_adjust(struct sk_buff *skb, | ||
359 | struct nf_conn *ct, | ||
360 | enum ip_conntrack_info ctinfo, | ||
361 | unsigned int protoff) | ||
362 | { | ||
363 | struct tcphdr *tcph; | ||
364 | int dir; | ||
365 | __be32 newseq, newack; | ||
366 | s32 seqoff, ackoff; | ||
367 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
368 | struct nf_nat_seq *this_way, *other_way; | ||
369 | int res; | ||
370 | |||
371 | dir = CTINFO2DIR(ctinfo); | ||
372 | |||
373 | this_way = &nat->seq[dir]; | ||
374 | other_way = &nat->seq[!dir]; | ||
375 | |||
376 | if (!skb_make_writable(skb, protoff + sizeof(*tcph))) | ||
377 | return 0; | ||
378 | |||
379 | tcph = (void *)skb->data + protoff; | ||
380 | spin_lock_bh(&ct->lock); | ||
381 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | ||
382 | seqoff = this_way->offset_after; | ||
383 | else | ||
384 | seqoff = this_way->offset_before; | ||
385 | |||
386 | if (after(ntohl(tcph->ack_seq) - other_way->offset_before, | ||
387 | other_way->correction_pos)) | ||
388 | ackoff = other_way->offset_after; | ||
389 | else | ||
390 | ackoff = other_way->offset_before; | ||
391 | |||
392 | newseq = htonl(ntohl(tcph->seq) + seqoff); | ||
393 | newack = htonl(ntohl(tcph->ack_seq) - ackoff); | ||
394 | |||
395 | inet_proto_csum_replace4(&tcph->check, skb, tcph->seq, newseq, 0); | ||
396 | inet_proto_csum_replace4(&tcph->check, skb, tcph->ack_seq, newack, 0); | ||
397 | |||
398 | pr_debug("Adjusting sequence number from %u->%u, ack from %u->%u\n", | ||
399 | ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq), | ||
400 | ntohl(newack)); | ||
401 | |||
402 | tcph->seq = newseq; | ||
403 | tcph->ack_seq = newack; | ||
404 | |||
405 | res = nf_nat_sack_adjust(skb, protoff, tcph, ct, ctinfo); | ||
406 | spin_unlock_bh(&ct->lock); | ||
407 | |||
408 | return res; | ||
409 | } | ||
410 | |||
411 | /* Setup NAT on this expected conntrack so it follows master. */ | 189 | /* Setup NAT on this expected conntrack so it follows master. */ |
412 | /* If we fail to get a free NAT slot, we'll get dropped on confirm */ | 190 | /* If we fail to get a free NAT slot, we'll get dropped on confirm */ |
413 | void nf_nat_follow_master(struct nf_conn *ct, | 191 | void nf_nat_follow_master(struct nf_conn *ct, |
diff --git a/net/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c index dac11f73868e..f9790405b7ff 100644 --- a/net/netfilter/nf_nat_sip.c +++ b/net/netfilter/nf_nat_sip.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <net/netfilter/nf_nat_helper.h> | 20 | #include <net/netfilter/nf_nat_helper.h> |
21 | #include <net/netfilter/nf_conntrack_helper.h> | 21 | #include <net/netfilter/nf_conntrack_helper.h> |
22 | #include <net/netfilter/nf_conntrack_expect.h> | 22 | #include <net/netfilter/nf_conntrack_expect.h> |
23 | #include <net/netfilter/nf_conntrack_seqadj.h> | ||
23 | #include <linux/netfilter/nf_conntrack_sip.h> | 24 | #include <linux/netfilter/nf_conntrack_sip.h> |
24 | 25 | ||
25 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
@@ -308,7 +309,7 @@ static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff, | |||
308 | return; | 309 | return; |
309 | 310 | ||
310 | th = (struct tcphdr *)(skb->data + protoff); | 311 | th = (struct tcphdr *)(skb->data + protoff); |
311 | nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off); | 312 | nf_ct_seqadj_set(ct, ctinfo, th->seq, off); |
312 | } | 313 | } |
313 | 314 | ||
314 | /* Handles expected signalling connections and media streams */ | 315 | /* Handles expected signalling connections and media streams */ |
diff --git a/net/netfilter/nfnetlink_queue_ct.c b/net/netfilter/nfnetlink_queue_ct.c index be893039966d..96cac50e0d12 100644 --- a/net/netfilter/nfnetlink_queue_ct.c +++ b/net/netfilter/nfnetlink_queue_ct.c | |||
@@ -87,14 +87,14 @@ nla_put_failure: | |||
87 | void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | 87 | void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, |
88 | enum ip_conntrack_info ctinfo, int diff) | 88 | enum ip_conntrack_info ctinfo, int diff) |
89 | { | 89 | { |
90 | struct nfq_ct_nat_hook *nfq_nat_ct; | 90 | struct nfq_ct_hook *nfq_ct; |
91 | 91 | ||
92 | nfq_nat_ct = rcu_dereference(nfq_ct_nat_hook); | 92 | nfq_ct = rcu_dereference(nfq_ct_hook); |
93 | if (nfq_nat_ct == NULL) | 93 | if (nfq_ct == NULL) |
94 | return; | 94 | return; |
95 | 95 | ||
96 | if ((ct->status & IPS_NAT_MASK) && diff) | 96 | if ((ct->status & IPS_NAT_MASK) && diff) |
97 | nfq_nat_ct->seq_adjust(skb, ct, ctinfo, diff); | 97 | nfq_ct->seq_adjust(skb, ct, ctinfo, diff); |
98 | } | 98 | } |
99 | 99 | ||
100 | int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr, | 100 | int nfqnl_attach_expect(struct nf_conn *ct, const struct nlattr *attr, |