Skip to content

Commit

Permalink
netfilter: nf_nat: support mangling a single TCP packet multiple times
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Patrick McHardy committed Feb 11, 2010
1 parent f5b321b commit 010c0b9
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 23 deletions.
32 changes: 25 additions & 7 deletions include/net/netfilter/nf_nat_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,38 @@
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,
unsigned int match_offset,
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);
Expand Down
39 changes: 23 additions & 16 deletions net/ipv4/netfilter/nf_nat_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 010c0b9

Please sign in to comment.