f9dd09c7f7
Vitezslav Samel discovered that since 2.6.30.4+ active FTP can not work
over NAT. The "cause" of the problem was a fix of unacknowledged data
detection with NAT (commit a3a9f79e36
).
However, actually, that fix uncovered a long standing bug in TCP conntrack:
when NAT was enabled, we simply updated the max of the right edge of
the segments we have seen (td_end), by the offset NAT produced with
changing IP/port in the data. However, we did not update the other parameter
(td_maxend) which is affected by the NAT offset. Thus that could drift
away from the correct value and thus resulted breaking active FTP.
The patch below fixes the issue by *not* updating the conntrack parameters
from NAT, but instead taking into account the NAT offsets in conntrack in a
consistent way. (Updating from NAT would be more harder and expensive because
it'd need to re-calculate parameters we already calculated in conntrack.)
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
40 lines
1.2 KiB
C
40 lines
1.2 KiB
C
#ifndef _NF_NAT_HELPER_H
|
|
#define _NF_NAT_HELPER_H
|
|
/* NAT protocol helper routines. */
|
|
|
|
#include <net/netfilter/nf_conntrack.h>
|
|
|
|
struct sk_buff;
|
|
|
|
/* These return true or false. */
|
|
extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
|
struct nf_conn *ct,
|
|
enum ip_conntrack_info ctinfo,
|
|
unsigned int match_offset,
|
|
unsigned int match_len,
|
|
const char *rep_buffer,
|
|
unsigned int rep_len);
|
|
extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
|
struct nf_conn *ct,
|
|
enum ip_conntrack_info ctinfo,
|
|
unsigned int match_offset,
|
|
unsigned int match_len,
|
|
const char *rep_buffer,
|
|
unsigned int rep_len);
|
|
extern int nf_nat_seq_adjust(struct sk_buff *skb,
|
|
struct nf_conn *ct,
|
|
enum ip_conntrack_info ctinfo);
|
|
extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
|
|
struct nf_conn *ct,
|
|
enum ip_conntrack_info ctinfo);
|
|
|
|
/* Setup NAT on this expected conntrack so it follows master, but goes
|
|
* to port ct->master->saved_proto. */
|
|
extern void nf_nat_follow_master(struct nf_conn *ct,
|
|
struct nf_conntrack_expect *this);
|
|
|
|
extern s16 nf_nat_get_offset(const struct nf_conn *ct,
|
|
enum ip_conntrack_dir dir,
|
|
u32 seq);
|
|
#endif
|