|
@@ -165,7 +165,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|
{
|
|
{
|
|
struct iphdr *iph;
|
|
struct iphdr *iph;
|
|
struct tcphdr *tcph;
|
|
struct tcphdr *tcph;
|
|
- int datalen;
|
|
|
|
|
|
+ int oldlen, datalen;
|
|
|
|
|
|
if (!skb_make_writable(pskb, (*pskb)->len))
|
|
if (!skb_make_writable(pskb, (*pskb)->len))
|
|
return 0;
|
|
return 0;
|
|
@@ -180,13 +180,22 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
|
|
iph = (*pskb)->nh.iph;
|
|
iph = (*pskb)->nh.iph;
|
|
tcph = (void *)iph + iph->ihl*4;
|
|
tcph = (void *)iph + iph->ihl*4;
|
|
|
|
|
|
|
|
+ oldlen = (*pskb)->len - iph->ihl*4;
|
|
mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
|
|
mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4,
|
|
match_offset, match_len, rep_buffer, rep_len);
|
|
match_offset, match_len, rep_buffer, rep_len);
|
|
|
|
|
|
datalen = (*pskb)->len - iph->ihl*4;
|
|
datalen = (*pskb)->len - iph->ihl*4;
|
|
- tcph->check = 0;
|
|
|
|
- tcph->check = tcp_v4_check(tcph, datalen, iph->saddr, iph->daddr,
|
|
|
|
- csum_partial((char *)tcph, datalen, 0));
|
|
|
|
|
|
+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
|
|
|
+ tcph->check = 0;
|
|
|
|
+ tcph->check = tcp_v4_check(tcph, datalen,
|
|
|
|
+ iph->saddr, iph->daddr,
|
|
|
|
+ csum_partial((char *)tcph,
|
|
|
|
+ datalen, 0));
|
|
|
|
+ } else
|
|
|
|
+ tcph->check = nf_proto_csum_update(*pskb,
|
|
|
|
+ htons(oldlen) ^ 0xFFFF,
|
|
|
|
+ htons(datalen),
|
|
|
|
+ tcph->check, 1);
|
|
|
|
|
|
if (rep_len != match_len) {
|
|
if (rep_len != match_len) {
|
|
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
|
set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
|
|
@@ -221,6 +230,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|
{
|
|
{
|
|
struct iphdr *iph;
|
|
struct iphdr *iph;
|
|
struct udphdr *udph;
|
|
struct udphdr *udph;
|
|
|
|
+ int datalen, oldlen;
|
|
|
|
|
|
/* UDP helpers might accidentally mangle the wrong packet */
|
|
/* UDP helpers might accidentally mangle the wrong packet */
|
|
iph = (*pskb)->nh.iph;
|
|
iph = (*pskb)->nh.iph;
|
|
@@ -238,22 +248,32 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,
|
|
|
|
|
|
iph = (*pskb)->nh.iph;
|
|
iph = (*pskb)->nh.iph;
|
|
udph = (void *)iph + iph->ihl*4;
|
|
udph = (void *)iph + iph->ihl*4;
|
|
|
|
+
|
|
|
|
+ oldlen = (*pskb)->len - iph->ihl*4;
|
|
mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
|
|
mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph),
|
|
match_offset, match_len, rep_buffer, rep_len);
|
|
match_offset, match_len, rep_buffer, rep_len);
|
|
|
|
|
|
/* update the length of the UDP packet */
|
|
/* update the length of the UDP packet */
|
|
- udph->len = htons((*pskb)->len - iph->ihl*4);
|
|
|
|
|
|
+ datalen = (*pskb)->len - iph->ihl*4;
|
|
|
|
+ udph->len = htons(datalen);
|
|
|
|
|
|
/* fix udp checksum if udp checksum was previously calculated */
|
|
/* fix udp checksum if udp checksum was previously calculated */
|
|
- if (udph->check) {
|
|
|
|
- int datalen = (*pskb)->len - iph->ihl * 4;
|
|
|
|
|
|
+ if (!udph->check && (*pskb)->ip_summed != CHECKSUM_PARTIAL)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ if ((*pskb)->ip_summed != CHECKSUM_PARTIAL) {
|
|
udph->check = 0;
|
|
udph->check = 0;
|
|
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
|
|
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
|
|
datalen, IPPROTO_UDP,
|
|
datalen, IPPROTO_UDP,
|
|
csum_partial((char *)udph,
|
|
csum_partial((char *)udph,
|
|
datalen, 0));
|
|
datalen, 0));
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ if (!udph->check)
|
|
|
|
+ udph->check = -1;
|
|
|
|
+ } else
|
|
|
|
+ udph->check = nf_proto_csum_update(*pskb,
|
|
|
|
+ htons(oldlen) ^ 0xFFFF,
|
|
|
|
+ htons(datalen),
|
|
|
|
+ udph->check, 1);
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
|
|
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
|
|
@@ -293,11 +313,14 @@ sack_adjust(struct sk_buff *skb,
|
|
ntohl(sack->start_seq), new_start_seq,
|
|
ntohl(sack->start_seq), new_start_seq,
|
|
ntohl(sack->end_seq), new_end_seq);
|
|
ntohl(sack->end_seq), new_end_seq);
|
|
|
|
|
|
- tcph->check =
|
|
|
|
- ip_nat_cheat_check(~sack->start_seq, new_start_seq,
|
|
|
|
- ip_nat_cheat_check(~sack->end_seq,
|
|
|
|
- new_end_seq,
|
|
|
|
- tcph->check));
|
|
|
|
|
|
+ tcph->check = nf_proto_csum_update(skb,
|
|
|
|
+ ~sack->start_seq,
|
|
|
|
+ new_start_seq,
|
|
|
|
+ tcph->check, 0);
|
|
|
|
+ tcph->check = nf_proto_csum_update(skb,
|
|
|
|
+ ~sack->end_seq,
|
|
|
|
+ new_end_seq,
|
|
|
|
+ tcph->check, 0);
|
|
sack->start_seq = new_start_seq;
|
|
sack->start_seq = new_start_seq;
|
|
sack->end_seq = new_end_seq;
|
|
sack->end_seq = new_end_seq;
|
|
sackoff += sizeof(*sack);
|
|
sackoff += sizeof(*sack);
|
|
@@ -381,10 +404,10 @@ ip_nat_seq_adjust(struct sk_buff **pskb,
|
|
newack = ntohl(tcph->ack_seq) - other_way->offset_before;
|
|
newack = ntohl(tcph->ack_seq) - other_way->offset_before;
|
|
newack = htonl(newack);
|
|
newack = htonl(newack);
|
|
|
|
|
|
- tcph->check = ip_nat_cheat_check(~tcph->seq, newseq,
|
|
|
|
- ip_nat_cheat_check(~tcph->ack_seq,
|
|
|
|
- newack,
|
|
|
|
- tcph->check));
|
|
|
|
|
|
+ tcph->check = nf_proto_csum_update(*pskb, ~tcph->seq, newseq,
|
|
|
|
+ tcph->check, 0);
|
|
|
|
+ tcph->check = nf_proto_csum_update(*pskb, ~tcph->ack_seq, newack,
|
|
|
|
+ tcph->check, 0);
|
|
|
|
|
|
DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
|
|
DEBUGP("Adjusting sequence number from %u->%u, ack from %u->%u\n",
|
|
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
|
|
ntohl(tcph->seq), ntohl(newseq), ntohl(tcph->ack_seq),
|