10 #include <linux/module.h>
12 #include <linux/types.h>
14 #include <linux/tcp.h>
15 #include <linux/udp.h>
28 #define DUMP_OFFSET(x) \
29 pr_debug("offset_before=%d, offset_after=%d, correction_pos=%u\n", \
30 x->offset_before, x->offset_after, x->correction_pos);
36 adjust_tcp_sequence(
u32 seq,
45 pr_debug(
"adjust_tcp_sequence: seq = %u, sizediff = %d\n",
48 pr_debug(
"adjust_tcp_sequence: Seq_offset before: ");
51 spin_lock_bh(&nf_nat_seqofs_lock);
63 spin_unlock_bh(&nf_nat_seqofs_lock);
65 pr_debug(
"adjust_tcp_sequence: Seq_offset after: ");
81 this_way = &nat->
seq[dir];
82 spin_lock_bh(&nf_nat_seqofs_lock);
85 spin_unlock_bh(&nf_nat_seqofs_lock);
91 static void mangle_contents(
struct sk_buff *
skb,
93 unsigned int match_offset,
94 unsigned int match_len,
95 const char *rep_buffer,
100 BUG_ON(skb_is_nonlinear(skb));
101 data = skb_network_header(skb) + dataoff;
104 memmove(data + match_offset + rep_len,
105 data + match_offset + match_len,
107 match_offset + match_len));
110 memcpy(data + match_offset, rep_buffer, rep_len);
113 if (rep_len > match_len) {
114 pr_debug(
"nf_nat_mangle_packet: Extending packet by "
115 "%u from %u bytes\n", rep_len - match_len, skb->
len);
116 skb_put(skb, rep_len - match_len);
118 pr_debug(
"nf_nat_mangle_packet: Shrinking packet from "
119 "%u from %u bytes\n", match_len - rep_len, skb->
len);
120 __skb_trim(skb, skb->
len + rep_len - match_len);
125 ip_hdr(skb)->tot_len =
htons(skb->
len);
128 ipv6_hdr(skb)->payload_len =
133 static int enlarge_skb(
struct sk_buff *skb,
unsigned int extra)
135 if (skb->
len + extra > 65535)
150 adjust_tcp_sequence(
ntohl(seq), off, ct, ctinfo);
163 th = (
struct tcphdr *)(skb_network_header(skb)+ ip_hdrlen(skb));
179 unsigned int protoff,
180 unsigned int match_offset,
181 unsigned int match_len,
182 const char *rep_buffer,
183 unsigned int rep_len,
bool adjust)
192 if (rep_len > match_len &&
193 rep_len - match_len > skb_tailroom(skb) &&
194 !enlarge_skb(skb, rep_len - match_len))
197 SKB_LINEAR_ASSERT(skb);
199 tcph = (
void *)skb->
data + protoff;
201 oldlen = skb->
len - protoff;
202 mangle_contents(skb, protoff + tcph->doff*4,
203 match_offset, match_len, rep_buffer, rep_len);
205 datalen = skb->
len - protoff;
211 if (adjust && rep_len != match_len)
213 (
int)rep_len - (
int)match_len);
233 unsigned int protoff,
234 unsigned int match_offset,
235 unsigned int match_len,
236 const char *rep_buffer,
237 unsigned int rep_len)
246 if (rep_len > match_len &&
247 rep_len - match_len > skb_tailroom(skb) &&
248 !enlarge_skb(skb, rep_len - match_len))
251 udph = (
void *)skb->
data + protoff;
253 oldlen = skb->
len - protoff;
254 mangle_contents(skb, protoff +
sizeof(*udph),
255 match_offset, match_len, rep_buffer, rep_len);
258 datalen = skb->
len - protoff;
275 sack_adjust(
struct sk_buff *skb,
277 unsigned int sackoff,
278 unsigned int sackend,
281 while (sackoff < sackend) {
283 __be32 new_start_seq, new_end_seq;
285 sack = (
void *)skb->
data + sackoff;
302 pr_debug(
"sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n",
309 sack->
end_seq, new_end_seq, 0);
312 sackoff +=
sizeof(*sack);
317 static inline unsigned int
318 nf_nat_sack_adjust(
struct sk_buff *skb,
319 unsigned int protoff,
324 unsigned int dir, optoff, optend;
327 optoff = protoff +
sizeof(
struct tcphdr);
328 optend = protoff + tcph->doff * 4;
335 while (optoff < optend) {
337 unsigned char *
op = skb->
data + optoff;
347 if (optoff + 1 == optend ||
348 optoff + op[1] > optend ||
354 sack_adjust(skb, tcph, optoff+2,
355 optoff+op[1], &nat->
seq[!dir]);
367 unsigned int protoff)
378 this_way = &nat->
seq[dir];
379 other_way = &nat->
seq[!dir];
384 tcph = (
void *)skb->
data + protoff;
402 pr_debug(
"Adjusting sequence number from %u->%u, ack from %u->%u\n",
409 return nf_nat_sack_adjust(skb, protoff, tcph, ct, ctinfo);
425 = ct->
master->tuplehash[!exp->dir].tuple.dst.u3;
432 = ct->
master->tuplehash[!exp->dir].tuple.src.u3;