summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2013-04-08 18:02:24 +0900
committerLorenzo Colitti <lorenzo@google.com>2013-04-09 17:14:40 +0900
commit0278627f576832860af2d84e04e383ecaa92d74f (patch)
tree32e195850b333b077be9f7e998d445feeb4b39ec
parent41e758e33e6c3b43f363591d4113dea54a4330d9 (diff)
downloadandroid_external_android-clat-0278627f576832860af2d84e04e383ecaa92d74f.tar.gz
android_external_android-clat-0278627f576832860af2d84e04e383ecaa92d74f.tar.bz2
android_external_android-clat-0278627f576832860af2d84e04e383ecaa92d74f.zip
Pass in the length to pseudo checksum functions
Currently, the pseudo-header checksum calculation functions get the transport layer length from the IP header. This requires that the length be known at IP header construction time, which does not allow transport layer translation functions to change the length of the packet later. Have the transport functions pass in the size directly. Bug: 8276725 Change-Id: I76a93f5e66181bec21d68f779c68c54090a77c33
-rw-r--r--checksum.c44
-rw-r--r--checksum.h6
-rw-r--r--dump.c8
-rw-r--r--translate.c10
4 files changed, 35 insertions, 33 deletions
diff --git a/checksum.c b/checksum.c
index 14b7113..a4dc9b8 100644
--- a/checksum.c
+++ b/checksum.c
@@ -28,12 +28,12 @@
/* function: ip_checksum_add
* adds data to a checksum
- * current_sum - the current checksum (or 0 to start a new checksum)
+ * current - the current checksum (or 0 to start a new checksum)
* data - the data to add to the checksum
* len - length of data
*/
-uint32_t ip_checksum_add(uint32_t current_sum, const void *data, int len) {
- uint32_t checksum = current_sum;
+uint32_t ip_checksum_add(uint32_t current, const void *data, int len) {
+ uint32_t checksum = current;
int left = len;
const uint16_t *data_16 = data;
@@ -76,38 +76,40 @@ uint16_t ip_checksum(const void *data, int len) {
/* function: ipv6_pseudo_header_checksum
* calculate the pseudo header checksum for use in tcp/udp/icmp headers
- * current_sum - the current checksum or 0 to start a new checksum
- * ip6 - the ipv6 header
+ * current - the current checksum or 0 to start a new checksum
+ * ip6 - the ipv6 header
+ * len - the transport length (transport header + payload)
*/
-uint32_t ipv6_pseudo_header_checksum(uint32_t current_sum, const struct ip6_hdr *ip6) {
+uint32_t ipv6_pseudo_header_checksum(uint32_t current, const struct ip6_hdr *ip6, uint16_t len) {
uint32_t checksum_len, checksum_next;
- checksum_len = htonl(ntohs(ip6->ip6_plen));
+ checksum_len = htonl((uint32_t) len);
checksum_next = htonl(ip6->ip6_nxt);
- current_sum = ip_checksum_add(current_sum,&(ip6->ip6_src),sizeof(struct in6_addr));
- current_sum = ip_checksum_add(current_sum,&(ip6->ip6_dst),sizeof(struct in6_addr));
- current_sum = ip_checksum_add(current_sum,&checksum_len,sizeof(checksum_len));
- current_sum = ip_checksum_add(current_sum,&checksum_next,sizeof(checksum_next));
+ current = ip_checksum_add(current, &(ip6->ip6_src), sizeof(struct in6_addr));
+ current = ip_checksum_add(current, &(ip6->ip6_dst), sizeof(struct in6_addr));
+ current = ip_checksum_add(current, &checksum_len, sizeof(checksum_len));
+ current = ip_checksum_add(current, &checksum_next, sizeof(checksum_next));
- return current_sum;
+ return current;
}
/* function: ipv4_pseudo_header_checksum
* calculate the pseudo header checksum for use in tcp/udp headers
- * current_sum - the current checksum or 0 to start a new checksum
- * ip - the ipv4 header
+ * current - the current checksum or 0 to start a new checksum
+ * ip - the ipv4 header
+ * len - the transport length (transport header + payload)
*/
-uint32_t ipv4_pseudo_header_checksum(uint32_t current_sum, const struct iphdr *ip) {
+uint32_t ipv4_pseudo_header_checksum(uint32_t current, const struct iphdr *ip, uint16_t len) {
uint16_t temp_protocol, temp_length;
temp_protocol = htons(ip->protocol);
- temp_length = htons(ntohs(ip->tot_len) - ip->ihl*4);
+ temp_length = htons(len);
- current_sum = ip_checksum_add(current_sum, &(ip->saddr), sizeof(uint32_t));
- current_sum = ip_checksum_add(current_sum, &(ip->daddr), sizeof(uint32_t));
- current_sum = ip_checksum_add(current_sum, &temp_protocol, sizeof(uint16_t));
- current_sum = ip_checksum_add(current_sum, &temp_length, sizeof(uint16_t));
+ current = ip_checksum_add(current, &(ip->saddr), sizeof(uint32_t));
+ current = ip_checksum_add(current, &(ip->daddr), sizeof(uint32_t));
+ current = ip_checksum_add(current, &temp_protocol, sizeof(uint16_t));
+ current = ip_checksum_add(current, &temp_length, sizeof(uint16_t));
- return current_sum;
+ return current;
}
diff --git a/checksum.h b/checksum.h
index c8346a0..473f5f5 100644
--- a/checksum.h
+++ b/checksum.h
@@ -18,11 +18,11 @@
#ifndef __CHECKSUM_H__
#define __CHECKSUM_H__
-uint32_t ip_checksum_add(uint32_t current_sum, const void *data, int len);
+uint32_t ip_checksum_add(uint32_t current, const void *data, int len);
uint16_t ip_checksum_finish(uint32_t temp_sum);
uint16_t ip_checksum(const void *data, int len);
-uint32_t ipv6_pseudo_header_checksum(uint32_t current_sum, const struct ip6_hdr *ip6);
-uint32_t ipv4_pseudo_header_checksum(uint32_t current_sum, const struct iphdr *ip);
+uint32_t ipv6_pseudo_header_checksum(uint32_t current, const struct ip6_hdr *ip6, uint16_t len);
+uint32_t ipv4_pseudo_header_checksum(uint32_t current, const struct iphdr *ip, uint16_t len);
#endif /* __CHECKSUM_H__ */
diff --git a/dump.c b/dump.c
index e538f3e..fe9721a 100644
--- a/dump.c
+++ b/dump.c
@@ -146,14 +146,14 @@ void dump_udp_generic(const struct udphdr *udp, uint32_t temp_checksum, const ch
/* print ipv4/udp header */
void dump_udp(const struct udphdr *udp, const struct iphdr *ip, const char *payload, size_t payload_size) {
uint32_t temp_checksum;
- temp_checksum = ipv4_pseudo_header_checksum(0, ip);
+ temp_checksum = ipv4_pseudo_header_checksum(0, ip, sizeof(*udp) + payload_size);
dump_udp_generic(udp, temp_checksum, payload, payload_size);
}
/* print ipv6/udp header */
void dump_udp6(const struct udphdr *udp, const struct ip6_hdr *ip6, const char *payload, size_t payload_size) {
uint32_t temp_checksum;
- temp_checksum = ipv6_pseudo_header_checksum(0, ip6);
+ temp_checksum = ipv6_pseudo_header_checksum(0, ip6, sizeof(*udp) + payload_size);
dump_udp_generic(udp, temp_checksum, payload, payload_size);
}
@@ -202,7 +202,7 @@ void dump_tcp_generic(const struct tcphdr *tcp, const char *options, size_t opti
void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip, const char *payload, size_t payload_size, const char *options, size_t options_size) {
uint32_t temp_checksum;
- temp_checksum = ipv4_pseudo_header_checksum(0, ip);
+ temp_checksum = ipv4_pseudo_header_checksum(0, ip, sizeof(*tcp) + options_size + payload_size);
dump_tcp_generic(tcp, options, options_size, temp_checksum, payload, payload_size);
}
@@ -210,7 +210,7 @@ void dump_tcp(const struct tcphdr *tcp, const struct iphdr *ip, const char *payl
void dump_tcp6(const struct tcphdr *tcp, const struct ip6_hdr *ip6, const char *payload, size_t payload_size, const char *options, size_t options_size) {
uint32_t temp_checksum;
- temp_checksum = ipv6_pseudo_header_checksum(0, ip6);
+ temp_checksum = ipv6_pseudo_header_checksum(0, ip6, sizeof(*tcp) + options_size + payload_size);
dump_tcp_generic(tcp, options, options_size, temp_checksum, payload, payload_size);
}
diff --git a/translate.c b/translate.c
index cdaca14..89a7e7b 100644
--- a/translate.c
+++ b/translate.c
@@ -142,7 +142,7 @@ void icmp_to_icmp6(int fd, const struct iphdr *ip, const struct icmphdr *icmp, c
icmp6_targ.icmp6_id = icmp->un.echo.id;
icmp6_targ.icmp6_seq = icmp->un.echo.sequence;
- checksum_temp = ipv6_pseudo_header_checksum(0,&ip6_targ);
+ checksum_temp = ipv6_pseudo_header_checksum(0, &ip6_targ, sizeof(icmp6_targ) + payload_size);
checksum_temp = ip_checksum_add(checksum_temp, &icmp6_targ, sizeof(icmp6_targ));
checksum_temp = ip_checksum_add(checksum_temp, payload, payload_size);
icmp6_targ.icmp6_cksum = ip_checksum_finish(checksum_temp);
@@ -255,7 +255,7 @@ void udp_to_udp6(int fd, const struct iphdr *ip, const struct udphdr *udp, const
fill_ip6_header(&ip6_targ,payload_size + sizeof(struct udphdr),IPPROTO_UDP,ip);
- checksum = ipv6_pseudo_header_checksum(0, &ip6_targ);
+ checksum = ipv6_pseudo_header_checksum(0, &ip6_targ, sizeof(*udp) + payload_size);
io_targ[0].iov_base = &tun_header;
io_targ[0].iov_len = sizeof(tun_header);
@@ -283,7 +283,7 @@ void udp6_to_udp(int fd, const struct ip6_hdr *ip6, const struct udphdr *udp, co
fill_ip_header(&ip_targ,payload_size + sizeof(struct udphdr),IPPROTO_UDP,ip6);
- checksum = ipv4_pseudo_header_checksum(0, &ip_targ);
+ checksum = ipv4_pseudo_header_checksum(0, &ip_targ, sizeof(*udp) + payload_size);
io_targ[0].iov_base = &tun_header;
io_targ[0].iov_len = sizeof(tun_header);
@@ -363,7 +363,7 @@ void tcp_to_tcp6(int fd,const struct iphdr *ip, const struct tcphdr *tcp, const
fill_ip6_header(&ip6_targ,payload_size+options_size+sizeof(struct tcphdr),IPPROTO_TCP,ip);
- checksum = ipv6_pseudo_header_checksum(0, &ip6_targ);
+ checksum = ipv6_pseudo_header_checksum(0, &ip6_targ, sizeof(*tcp) + options_size + payload_size);
io_targ[0].iov_base = &tun_header;
io_targ[0].iov_len = sizeof(tun_header);
@@ -393,7 +393,7 @@ void tcp6_to_tcp(int fd,const struct ip6_hdr *ip6, const struct tcphdr *tcp, con
fill_ip_header(&ip_targ,payload_size+options_size+sizeof(struct tcphdr),IPPROTO_TCP,ip6);
- checksum = ipv4_pseudo_header_checksum(0, &ip_targ);
+ checksum = ipv4_pseudo_header_checksum(0, &ip_targ, sizeof(*tcp) + payload_size + options_size);
io_targ[0].iov_base = &tun_header;
io_targ[0].iov_len = sizeof(tun_header);