summaryrefslogtreecommitdiffstats
path: root/ipv6.c
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2014-02-10 09:20:05 +0900
committerLorenzo Colitti <lorenzo@google.com>2014-02-14 13:33:04 +0900
commit5a50c0283346a197cda7af19e68f611f14b8fe57 (patch)
tree1cccafeba5bbd41374daa0aed35379faa4c26a88 /ipv6.c
parenta33592bd08a20c6a521b8508975b7a74ecdf4f03 (diff)
downloadandroid_external_android-clat-5a50c0283346a197cda7af19e68f611f14b8fe57.tar.gz
android_external_android-clat-5a50c0283346a197cda7af19e68f611f14b8fe57.tar.bz2
android_external_android-clat-5a50c0283346a197cda7af19e68f611f14b8fe57.zip
Fix up checksums instead of recalculating them.
Currently the checksums of translated packets are calculated from scratch by checksumming the translated packet. This is slow and does not work in the case of fragments, because the whole packet is not available. Instead, calculate the checksum by adjusting the checksum of the original packet. Bug: 11542311 Bug: 12116252 Change-Id: I6b78a94ca5bd96b13ee2653b6200551193b3dcc1
Diffstat (limited to 'ipv6.c')
-rw-r--r--ipv6.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/ipv6.c b/ipv6.c
index 79303ec..e4a73fe 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -88,7 +88,7 @@ int ipv6_packet(clat_packet out, int pos, const char *packet, size_t len) {
uint8_t protocol;
const char *next_header;
size_t len_left;
- uint32_t checksum;
+ uint32_t old_sum, new_sum;
int iov_len;
if(len < sizeof(struct ip6_hdr)) {
@@ -133,16 +133,17 @@ int ipv6_packet(clat_packet out, int pos, const char *packet, size_t len) {
out[pos].iov_len = sizeof(struct iphdr);
// Calculate the pseudo-header checksum.
- checksum = ipv4_pseudo_header_checksum(0, ip_targ, len_left);
+ old_sum = ipv6_pseudo_header_checksum(0, ip6, len_left);
+ new_sum = ipv4_pseudo_header_checksum(0, ip_targ, len_left);
// does not support IPv6 extension headers, this will drop any packet with them
if (protocol == IPPROTO_ICMP) {
iov_len = icmp6_packet(out, pos + 1, (const struct icmp6_hdr *) next_header, len_left);
} else if (ip6->ip6_nxt == IPPROTO_TCP) {
- iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum,
+ iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, old_sum, new_sum,
len_left);
} else if (ip6->ip6_nxt == IPPROTO_UDP) {
- iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum,
+ iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, old_sum, new_sum,
len_left);
} else if (ip6->ip6_nxt == IPPROTO_GRE) {
iov_len = generic_packet(out, pos + 1, next_header, len_left);