Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 010c0b9f authored by Patrick McHardy's avatar Patrick McHardy
Browse files

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: default avatarPatrick McHardy <kaber@trash.net>
parent f5b321bd
Loading
Loading
Loading
Loading
+25 −7
Original line number Original line Diff line number Diff line
@@ -7,13 +7,27 @@
struct sk_buff;
struct sk_buff;


/* These return true or false. */
/* These return true or false. */
extern int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
				      struct nf_conn *ct,
				      struct nf_conn *ct,
				      enum ip_conntrack_info ctinfo,
				      enum ip_conntrack_info ctinfo,
				      unsigned int match_offset,
				      unsigned int match_offset,
				      unsigned int match_len,
				      unsigned int match_len,
				      const char *rep_buffer,
				      const char *rep_buffer,
				    unsigned int rep_len);
				      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,
extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
				    struct nf_conn *ct,
				    struct nf_conn *ct,
				    enum ip_conntrack_info ctinfo,
				    enum ip_conntrack_info ctinfo,
@@ -21,6 +35,10 @@ extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
				    unsigned int match_len,
				    unsigned int match_len,
				    const char *rep_buffer,
				    const char *rep_buffer,
				    unsigned int rep_len);
				    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,
extern int nf_nat_seq_adjust(struct sk_buff *skb,
			     struct nf_conn *ct,
			     struct nf_conn *ct,
			     enum ip_conntrack_info ctinfo);
			     enum ip_conntrack_info ctinfo);
+23 −16
Original line number Original line Diff line number Diff line
@@ -141,6 +141,17 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
	return 1;
	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
/* Generic function for mangling variable-length address changes inside
 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
 * command in FTP).
 * command in FTP).
@@ -149,14 +160,13 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
 * skb enlargement, ...
 * skb enlargement, ...
 *
 *
 * */
 * */
int
int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
nf_nat_mangle_tcp_packet(struct sk_buff *skb,
			       struct nf_conn *ct,
			       struct nf_conn *ct,
			       enum ip_conntrack_info ctinfo,
			       enum ip_conntrack_info ctinfo,
			       unsigned int match_offset,
			       unsigned int match_offset,
			       unsigned int match_len,
			       unsigned int match_len,
			       const char *rep_buffer,
			       const char *rep_buffer,
			 unsigned int rep_len)
			       unsigned int rep_len, bool adjust)
{
{
	struct rtable *rt = skb_rtable(skb);
	struct rtable *rt = skb_rtable(skb);
	struct iphdr *iph;
	struct iphdr *iph;
@@ -202,16 +212,13 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
		inet_proto_csum_replace2(&tcph->check, skb,
		inet_proto_csum_replace2(&tcph->check, skb,
					 htons(oldlen), htons(datalen), 1);
					 htons(oldlen), htons(datalen), 1);


	if (rep_len != match_len) {
	if (adjust && rep_len != match_len)
		set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
		nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,
		adjust_tcp_sequence(ntohl(tcph->seq),
				      (int)rep_len - (int)match_len);
				    (int)rep_len - (int)match_len,

				    ct, ctinfo);
		nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
	}
	return 1;
	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
/* Generic function for mangling variable-length address changes inside
 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX