netfilter: nf_nat: support mangling a single TCP packet multiple times
nf_nat_mangle_tcp_packet() can currently only handle a single mangling per window because it only maintains two sequence adjustment positions: the one before the last adjustment and the one after. This patch makes sequence number adjustment tracking in nf_nat_mangle_tcp_packet() optional and allows a helper to manually update the offsets after the packet has been fully handled. Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
f5b321bd37
commit
010c0b9f34
2 changed files with 48 additions and 23 deletions
|
@ -7,13 +7,27 @@
|
|||
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_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, bool adjust);
|
||||
|
||||
static inline 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)
|
||||
{
|
||||
return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
match_offset, match_len,
|
||||
rep_buffer, rep_len, true);
|
||||
}
|
||||
|
||||
extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
|
@ -21,6 +35,10 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
|||
unsigned int match_len,
|
||||
const char *rep_buffer,
|
||||
unsigned int rep_len);
|
||||
|
||||
extern void nf_nat_set_seq_adjust(struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
__be32 seq, s16 off);
|
||||
extern int nf_nat_seq_adjust(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
|
|
|
@ -141,6 +141,17 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||
__be32 seq, s16 off)
|
||||
{
|
||||
if (!off)
|
||||
return;
|
||||
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
||||
adjust_tcp_sequence(ntohl(seq), off, ct, ctinfo);
|
||||
nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust);
|
||||
|
||||
/* Generic function for mangling variable-length address changes inside
|
||||
* NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
|
||||
* command in FTP).
|
||||
|
@ -149,14 +160,13 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
|
|||
* skb enlargement, ...
|
||||
*
|
||||
* */
|
||||
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)
|
||||
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, bool adjust)
|
||||
{
|
||||
struct rtable *rt = skb_rtable(skb);
|
||||
struct iphdr *iph;
|
||||
|
@ -202,16 +212,13 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
|||
inet_proto_csum_replace2(&tcph->check, skb,
|
||||
htons(oldlen), htons(datalen), 1);
|
||||
|
||||
if (rep_len != match_len) {
|
||||
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
||||
adjust_tcp_sequence(ntohl(tcph->seq),
|
||||
(int)rep_len - (int)match_len,
|
||||
ct, ctinfo);
|
||||
nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
|
||||
}
|
||||
if (adjust && rep_len != match_len)
|
||||
nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,
|
||||
(int)rep_len - (int)match_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(nf_nat_mangle_tcp_packet);
|
||||
EXPORT_SYMBOL(__nf_nat_mangle_tcp_packet);
|
||||
|
||||
/* Generic function for mangling variable-length address changes inside
|
||||
* NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
|
||||
|
|
Loading…
Reference in a new issue