resolved conflicts for merge of fbef82d1 to klp-dev-plus-aosp
Change-Id: I7ec85f26fc1f94324fbb57c031d760098d2f76cb
diff --git a/Android.mk b/Android.mk
index 635f2f6..e732c72 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,7 +3,6 @@
LOCAL_SRC_FILES:=clatd.c dump.c checksum.c translate.c icmp.c ipv4.c ipv6.c config.c dns64.c logging.c getaddr.c getroute.c netlink_callbacks.c netlink_msg.c setif.c setroute.c mtu.c
-LOCAL_CFLAGS := -Wall -Werror
LOCAL_C_INCLUDES := external/libnl/include
LOCAL_STATIC_LIBRARIES := libnl
LOCAL_SHARED_LIBRARIES := libcutils liblog
diff --git a/checksum.c b/checksum.c
index 099be6a..a4dc9b8 100644
--- a/checksum.c
+++ b/checksum.c
@@ -49,25 +49,17 @@
return checksum;
}
-/* function: ip_checksum_fold
- * folds a 32-bit partial checksum into 16 bits
+/* function: ip_checksum_finish
+ * close the checksum
* temp_sum - sum from ip_checksum_add
- * returns: the folded checksum in network byte order
*/
-uint16_t ip_checksum_fold(uint32_t temp_sum) {
+uint16_t ip_checksum_finish(uint32_t temp_sum) {
while(temp_sum > 0xffff)
temp_sum = (temp_sum >> 16) + (temp_sum & 0xFFFF);
- return temp_sum;
-}
+ temp_sum = (~temp_sum) & 0xffff;
-/* function: ip_checksum_finish
- * folds and closes the checksum
- * temp_sum - sum from ip_checksum_add
- * returns: a header checksum value in network byte order
- */
-uint16_t ip_checksum_finish(uint32_t temp_sum) {
- return ~ip_checksum_fold(temp_sum);
+ return temp_sum;
}
/* function: ip_checksum
@@ -121,23 +113,3 @@
return current;
}
-
-/* function: ip_checksum_adjust
- * calculates a new checksum given a previous checksum and the old and new pseudo-header checksums
- * checksum - the header checksum in the original packet in network byte order
- * old_hdr_sum - the pseudo-header checksum of the original packet
- * new_hdr_sum - the pseudo-header checksum of the translated packet
- * returns: the new header checksum in network byte order
- */
-uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum) {
- // Algorithm suggested in RFC 1624.
- // http://tools.ietf.org/html/rfc1624#section-3
- checksum = ~checksum;
- uint16_t folded_sum = ip_checksum_fold(checksum + new_hdr_sum);
- uint16_t folded_old = ip_checksum_fold(old_hdr_sum);
- if (folded_sum > folded_old) {
- return ~(folded_sum - folded_old);
- } else {
- return ~(folded_sum - folded_old - 1); // end-around borrow
- }
-}
diff --git a/checksum.h b/checksum.h
index 44921f0..473f5f5 100644
--- a/checksum.h
+++ b/checksum.h
@@ -25,6 +25,4 @@
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);
-uint16_t ip_checksum_adjust(uint16_t checksum, uint32_t old_hdr_sum, uint32_t new_hdr_sum);
-
#endif /* __CHECKSUM_H__ */
diff --git a/clatd.c b/clatd.c
index 3ab2371..26ecb57 100644
--- a/clatd.c
+++ b/clatd.c
@@ -29,6 +29,15 @@
#include <arpa/inet.h>
#include <fcntl.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <linux/icmp.h>
+
#include <sys/capability.h>
#include <sys/uio.h>
#include <linux/prctl.h>
@@ -38,6 +47,8 @@
#include <private/android_filesystem_config.h>
+#include "ipv4.h"
+#include "ipv6.h"
#include "translate.h"
#include "clatd.h"
#include "config.h"
@@ -54,6 +65,11 @@
int forwarding_fd = -1;
volatile sig_atomic_t running = 1;
+struct tun_data {
+ char device6[IFNAMSIZ], device4[IFNAMSIZ];
+ int fd6, fd4;
+};
+
/* function: set_forwarding
* enables/disables ipv6 forwarding
*/
@@ -68,7 +84,7 @@
/* function: stop_loop
* signal handler: stop the event loop
*/
-void stop_loop() {
+void stop_loop(int signal) {
running = 0;
}
@@ -130,6 +146,7 @@
* tunnel - tun device data
*/
void configure_tun_ipv6(const struct tun_data *tunnel) {
+ struct in6_addr local_nat64_prefix_6;
int status;
status = if_route(tunnel->device6, AF_INET6, &Global_Clatd_Config.ipv6_local_subnet,
@@ -291,6 +308,56 @@
configure_tun_ip(tunnel);
}
+/* function: packet_handler
+ * takes a tun header and a packet and sends it down the stack
+ * tunnel - tun device data
+ * tun_header - tun header
+ * packet - packet
+ * packetsize - size of packet
+ */
+void packet_handler(const struct tun_data *tunnel, struct tun_pi *tun_header, const char *packet,
+ size_t packetsize) {
+ int fd;
+ int iov_len = 0;
+
+ // Allocate buffers for all packet headers.
+ struct tun_pi tun_targ;
+ char iphdr[sizeof(struct ip6_hdr)];
+ char transporthdr[MAX_TCP_HDR];
+ char icmp_iphdr[sizeof(struct ip6_hdr)];
+ char icmp_transporthdr[MAX_TCP_HDR];
+
+ // iovec of the packets we'll send. This gets passed down to the translation functions.
+ clat_packet out = {
+ { &tun_targ, sizeof(tun_targ) }, // Tunnel header.
+ { iphdr, 0 }, // IP header.
+ { transporthdr, 0 }, // Transport layer header.
+ { icmp_iphdr, 0 }, // ICMP error inner IP header.
+ { icmp_transporthdr, 0 }, // ICMP error transport layer header.
+ { NULL, 0 }, // Payload. No buffer, it's a pointer to the original payload.
+ };
+
+ if(tun_header->flags != 0) {
+ logmsg(ANDROID_LOG_WARN,"packet_handler: unexpected flags = %d", tun_header->flags);
+ }
+
+ if(ntohs(tun_header->proto) == ETH_P_IP) {
+ fd = tunnel->fd6;
+ fill_tun_header(&tun_targ, ETH_P_IPV6);
+ iov_len = ipv4_packet(out, CLAT_POS_IPHDR, packet, packetsize);
+ } else if(ntohs(tun_header->proto) == ETH_P_IPV6) {
+ fd = tunnel->fd4;
+ fill_tun_header(&tun_targ, ETH_P_IP);
+ iov_len = ipv6_packet(out, CLAT_POS_IPHDR, packet, packetsize);
+ } else {
+ logmsg(ANDROID_LOG_WARN,"packet_handler: unknown packet type = %x",tun_header->proto);
+ }
+
+ if (iov_len > 0) {
+ writev(fd, out, iov_len);
+ }
+}
+
/* function: read_packet
* reads a packet from the tunnel fd and passes it down the stack
* active_fd - tun file descriptor marked ready for reading
@@ -312,6 +379,7 @@
logmsg(ANDROID_LOG_WARN,"read_packet/tun interface removed");
running = 0;
} else {
+ struct tun_pi tun_header;
ssize_t header_size = sizeof(struct tun_pi);
if(readlen < header_size) {
@@ -319,7 +387,7 @@
return;
}
- translate_packet(tunnel, (struct tun_pi *) packet, packet + header_size, readlen - header_size);
+ packet_handler(tunnel, (struct tun_pi *) packet, packet + header_size, readlen - header_size);
}
}
diff --git a/clatd.h b/clatd.h
index 44a655e..3459b09 100644
--- a/clatd.h
+++ b/clatd.h
@@ -18,7 +18,6 @@
#ifndef __CLATD_H__
#define __CLATD_H__
-#include <linux/if.h>
#include <linux/if_tun.h>
#define MAXMTU 1500
@@ -31,9 +30,4 @@
// how frequently (in seconds) to poll for an address change while there is no traffic
#define NO_TRAFFIC_INTERFACE_POLL_FREQUENCY 90
-struct tun_data {
- char device6[IFNAMSIZ], device4[IFNAMSIZ];
- int fd6, fd4;
-};
-
#endif /* __CLATD_H__ */
diff --git a/config.c b/config.c
index b82ac6c..61a4ebb 100644
--- a/config.c
+++ b/config.c
@@ -154,7 +154,7 @@
* does dns lookups to set the plat subnet or exits on failure, waits forever for a dns response with a query backoff timer
*/
void dns64_detection() {
- int backoff_sleep, status;
+ int i, backoff_sleep, status;
struct in6_addr tmp_ptr;
backoff_sleep = 1;
diff --git a/icmp.c b/icmp.c
index 75a4a4d..af96b83 100644
--- a/icmp.c
+++ b/icmp.c
@@ -139,7 +139,7 @@
}
// We don't understand this ICMP type. Return parameter problem so the caller will bail out.
- logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_type: unhandled ICMP type/code %d/%d", type, code);
+ logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_type: unhandled ICMP type %d", type);
return ICMP_PARAMETERPROB;
}
diff --git a/ipv4.c b/ipv4.c
index c828ffa..89e47e4 100644
--- a/ipv4.c
+++ b/ipv4.c
@@ -17,8 +17,18 @@
*/
#include <string.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <linux/icmp.h>
+
#include "translate.h"
#include "checksum.h"
+#include "ipv4.h"
#include "logging.h"
#include "debug.h"
#include "dump.h"
@@ -61,7 +71,7 @@
uint8_t nxthdr;
const char *next_header;
size_t len_left;
- uint32_t old_sum, new_sum;
+ uint32_t checksum;
int iov_len;
if(len < sizeof(struct iphdr)) {
@@ -112,19 +122,14 @@
out[pos].iov_len = sizeof(struct ip6_hdr);
// Calculate the pseudo-header checksum.
- old_sum = ipv4_pseudo_header_checksum(0, header, len_left);
- new_sum = ipv6_pseudo_header_checksum(0, ip6_targ, len_left);
+ checksum = ipv6_pseudo_header_checksum(0, ip6_targ, len_left);
- if (nxthdr == IPPROTO_ICMPV6) {
- iov_len = icmp_packet(out, pos + 1, (const struct icmphdr *) next_header, new_sum, len_left);
- } else if (nxthdr == IPPROTO_TCP) {
- iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, old_sum, new_sum,
- len_left);
- } else if (nxthdr == IPPROTO_UDP) {
- iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, old_sum, new_sum,
- len_left);
- } else if (nxthdr == IPPROTO_GRE) {
- iov_len = generic_packet(out, pos + 1, next_header, len_left);
+ if(nxthdr == IPPROTO_ICMPV6) {
+ iov_len = icmp_packet(out, pos + 1, (const struct icmphdr *) next_header, checksum, len_left);
+ } else if(nxthdr == IPPROTO_TCP) {
+ iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum, len_left);
+ } else if(nxthdr == IPPROTO_UDP) {
+ iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum, len_left);
} else {
#if CLAT_DEBUG
logmsg_dbg(ANDROID_LOG_ERROR, "ip_packet/unknown protocol: %x",header->protocol);
diff --git a/ipv4.h b/ipv4.h
new file mode 100644
index 0000000..00befd2
--- /dev/null
+++ b/ipv4.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Daniel Drown
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ipv4.h - takes an ipv4 packet and hands it off to the proper translate function
+ */
+#ifndef __IPV4_H__
+#define __IPV4_H__
+
+#include "translate.h"
+
+int ipv4_packet(clat_packet out, int pos, const char *packet, size_t len);
+
+#endif /* __IPV4_H__ */
diff --git a/ipv6.c b/ipv6.c
index 371d9e1..ef1e62f 100644
--- a/ipv6.c
+++ b/ipv6.c
@@ -17,10 +17,19 @@
*/
#include <string.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <linux/icmp.h>
#include <arpa/inet.h>
#include "translate.h"
#include "checksum.h"
+#include "ipv6.h"
#include "logging.h"
#include "dump.h"
#include "config.h"
@@ -34,7 +43,8 @@
* len - size of ip payload
* returns: the highest position in the output clat_packet that's filled in
*/
-int icmp6_packet(clat_packet out, int pos, const struct icmp6_hdr *icmp6, size_t len) {
+int icmp6_packet(clat_packet out, int pos, const struct icmp6_hdr *icmp6, uint32_t checksum,
+ size_t len) {
const char *payload;
size_t payload_size;
@@ -46,7 +56,7 @@
payload = (const char *) (icmp6 + 1);
payload_size = len - sizeof(struct icmp6_hdr);
- return icmp6_to_icmp(out, pos, icmp6, payload, payload_size);
+ return icmp6_to_icmp(out, pos, icmp6, checksum, payload, payload_size);
}
/* function: log_bad_address
@@ -54,18 +64,16 @@
* fmt - printf-style format, use %s to place the address
* badaddr - the bad address in question
*/
-#if CLAT_DEBUG
void log_bad_address(const char *fmt, const struct in6_addr *src, const struct in6_addr *dst) {
+#if CLAT_DEBUG
char srcstr[INET6_ADDRSTRLEN];
char dststr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, src, srcstr, sizeof(srcstr));
inet_ntop(AF_INET6, dst, dststr, sizeof(dststr));
logmsg_dbg(ANDROID_LOG_ERROR, fmt, srcstr, dststr);
-}
-#else
-#define log_bad_address(fmt, src, dst)
#endif
+}
/* function: ipv6_packet
* takes an ipv6 packet and hands it off to the layer 4 protocol function
@@ -80,8 +88,9 @@
uint8_t protocol;
const char *next_header;
size_t len_left;
- uint32_t old_sum, new_sum;
+ uint32_t checksum;
int iov_len;
+ int i;
if(len < sizeof(struct ip6_hdr)) {
logmsg_dbg(ANDROID_LOG_ERROR, "ipv6_packet/too short for an ip6 header: %d", len);
@@ -125,20 +134,18 @@
out[pos].iov_len = sizeof(struct iphdr);
// Calculate the pseudo-header checksum.
- old_sum = ipv6_pseudo_header_checksum(0, ip6, len_left);
- new_sum = ipv4_pseudo_header_checksum(0, ip_targ, len_left);
+ checksum = 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, old_sum, new_sum,
+ if(protocol == IPPROTO_ICMP) {
+ iov_len = icmp6_packet(out, pos + 1, (const struct icmp6_hdr *) next_header, checksum,
+ len_left);
+ } else if(ip6->ip6_nxt == IPPROTO_TCP) {
+ iov_len = tcp_packet(out, pos + 1, (const struct tcphdr *) next_header, checksum,
len_left);
- } else if (ip6->ip6_nxt == IPPROTO_UDP) {
- iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, old_sum, new_sum,
+ } else if(ip6->ip6_nxt == IPPROTO_UDP) {
+ iov_len = udp_packet(out, pos + 1, (const struct udphdr *) next_header, checksum,
len_left);
- } else if (ip6->ip6_nxt == IPPROTO_GRE) {
- iov_len = generic_packet(out, pos + 1, next_header, len_left);
} else {
#if CLAT_DEBUG
logmsg(ANDROID_LOG_ERROR, "ipv6_packet/unknown next header type: %x", ip6->ip6_nxt);
diff --git a/ipv6.h b/ipv6.h
new file mode 100644
index 0000000..019de17
--- /dev/null
+++ b/ipv6.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 Daniel Drown
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ipv6.h - takes an ipv6 packet and hands it off to the proper translate function
+ */
+#ifndef __IPV6_H__
+#define __IPV6_H__
+
+#include "translate.h"
+
+int ipv6_packet(clat_packet out, int pos, const char *packet, size_t len);
+
+#endif /* __IPV6_H__ */
diff --git a/translate.c b/translate.c
index f7f09cb..fc70f3d 100644
--- a/translate.c
+++ b/translate.c
@@ -16,7 +16,15 @@
* translate.c - CLAT functions / partial implementation of rfc6145
*/
#include <string.h>
-#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <linux/icmp.h>
#include "icmp.h"
#include "translate.h"
@@ -141,7 +149,7 @@
// Third-party ICMPv6 message. This may have been originated by an native IPv6 address.
// In that case, the source IPv6 address can't be translated and we need to make up an IPv4
// source address. For now, use 255.0.0.<ttl>, which at least looks useful in traceroute.
- if ((uint32_t) ip->saddr == INADDR_NONE) {
+ if (ip->saddr == (uint32_t) INADDR_NONE) {
ttl_guess = icmp_guess_ttl(old_header->ip6_hlim);
ip->saddr = htonl((0xff << 24) + ttl_guess);
}
@@ -167,7 +175,6 @@
ip6->ip6_dst = ipv4_addr_to_ipv6_addr(old_header->daddr);
}
-
/* function: icmp_to_icmp6
* translate ipv4 icmp to ipv6 icmp
* out - output packet
@@ -201,10 +208,12 @@
// The pseudo-header checksum was calculated on the transport length of the original IPv4
// packet that we were asked to translate. This transport length is 20 bytes smaller than it
// needs to be, because the ICMP error contains an IPv4 header, which we will be translating to
- // an IPv6 header, which is 20 bytes longer. Fix it up here.
+ // an IPv6 header, which is 20 bytes longer. Fix it up here. This is simpler than the
+ // alternative, which is to always update the pseudo-header checksum in all UDP/TCP/ICMP
+ // translation functions (rather than pre-calculating it when translating the IPv4 header).
// We only need to do this for ICMP->ICMPv6, not ICMPv6->ICMP, because ICMP does not use the
// pseudo-header when calculating its checksum (as the IPv4 header has its own checksum).
- checksum = checksum + htons(20);
+ checksum = htonl(ntohl(checksum) + 20);
} else if (icmp6_type == ICMP6_ECHO_REQUEST || icmp6_type == ICMP6_ECHO_REPLY) {
// Ping packet.
icmp6_targ->icmp6_id = icmp->un.echo.id;
@@ -227,14 +236,16 @@
* translate ipv6 icmp to ipv4 icmp
* out - output packet
* icmp6 - source packet icmp6 header
+ * checksum - pseudo-header checksum (unused)
* payload - icmp6 payload
* payload_size - size of payload
* returns: the highest position in the output clat_packet that's filled in
*/
-int icmp6_to_icmp(clat_packet out, int pos, const struct icmp6_hdr *icmp6,
+int icmp6_to_icmp(clat_packet out, int pos, const struct icmp6_hdr *icmp6, uint32_t checksum,
const char *payload, size_t payload_size) {
struct icmphdr *icmp_targ = out[pos].iov_base;
uint8_t icmp_type;
+ int ttl;
int clat_packet_len;
memset(icmp_targ, 0, sizeof(struct icmphdr));
@@ -269,32 +280,14 @@
return clat_packet_len;
}
-/* function: generic_packet
- * takes a generic IP packet and sets it up for translation
- * out - output packet
- * pos - position in the output packet of the transport header
- * payload - pointer to IP payload
- * len - size of ip payload
- * returns: the highest position in the output clat_packet that's filled in
- */
-int generic_packet(clat_packet out, int pos, const char *payload, size_t len) {
- out[pos].iov_len = 0;
- out[CLAT_POS_PAYLOAD].iov_base = (char *) payload;
- out[CLAT_POS_PAYLOAD].iov_len = len;
-
- return CLAT_POS_PAYLOAD + 1;
-}
-
/* function: udp_packet
* takes a udp packet and sets it up for translation
* out - output packet
* udp - pointer to udp header in packet
- * old_sum - pseudo-header checksum of old header
- * new_sum - pseudo-header checksum of new header
+ * checksum - pseudo-header checksum
* len - size of ip payload
*/
-int udp_packet(clat_packet out, int pos, const struct udphdr *udp,
- uint32_t old_sum, uint32_t new_sum, size_t len) {
+int udp_packet(clat_packet out, int pos, const struct udphdr *udp, uint32_t checksum, size_t len) {
const char *payload;
size_t payload_size;
@@ -306,7 +299,7 @@
payload = (const char *) (udp + 1);
payload_size = len - sizeof(struct udphdr);
- return udp_translate(out, pos, udp, old_sum, new_sum, payload, payload_size);
+ return udp_translate(out, pos, udp, checksum, payload, payload_size);
}
/* function: tcp_packet
@@ -317,8 +310,7 @@
* len - size of ip payload
* returns: the highest position in the output clat_packet that's filled in
*/
-int tcp_packet(clat_packet out, int pos, const struct tcphdr *tcp,
- uint32_t old_sum, uint32_t new_sum, size_t len) {
+int tcp_packet(clat_packet out, int pos, const struct tcphdr *tcp, uint32_t checksum, size_t len) {
const char *payload;
size_t payload_size, header_size;
@@ -341,21 +333,20 @@
payload = ((const char *) tcp) + header_size;
payload_size = len - header_size;
- return tcp_translate(out, pos, tcp, header_size, old_sum, new_sum, payload, payload_size);
+ return tcp_translate(out, pos, tcp, header_size, checksum, payload, payload_size);
}
/* function: udp_translate
* common between ipv4/ipv6 - setup checksum and send udp packet
* out - output packet
* udp - udp header
- * old_sum - pseudo-header checksum of old header
- * new_sum - pseudo-header checksum of new header
+ * checksum - pseudo-header checksum
* payload - tcp payload
* payload_size - size of payload
* returns: the highest position in the output clat_packet that's filled in
*/
-int udp_translate(clat_packet out, int pos, const struct udphdr *udp, uint32_t old_sum,
- uint32_t new_sum, const char *payload, size_t payload_size) {
+int udp_translate(clat_packet out, int pos, const struct udphdr *udp, uint32_t checksum,
+ const char *payload, size_t payload_size) {
struct udphdr *udp_targ = out[pos].iov_base;
memcpy(udp_targ, udp, sizeof(struct udphdr));
@@ -364,22 +355,8 @@
out[CLAT_POS_PAYLOAD].iov_base = (char *) payload;
out[CLAT_POS_PAYLOAD].iov_len = payload_size;
- if (udp_targ->check) {
- udp_targ->check = ip_checksum_adjust(udp->check, old_sum, new_sum);
- } else {
- // Zero checksums are special. RFC 768 says, "An all zero transmitted checksum value means that
- // the transmitter generated no checksum (for debugging or for higher level protocols that
- // don't care)." However, in IPv6 zero UDP checksums were only permitted by RFC 6935 (2013). So
- // for safety we recompute it.
- udp_targ->check = 0; // Checksum field must be 0 when calculating checksum.
- udp_targ->check = packet_checksum(new_sum, out, pos);
- }
-
- // RFC 768: "If the computed checksum is zero, it is transmitted as all ones (the equivalent
- // in one's complement arithmetic)."
- if (!udp_targ->check) {
- udp_targ->check = 0xffff;
- }
+ udp_targ->check = 0; // Checksum field must be 0 when calculating checksum.
+ udp_targ->check = packet_checksum(checksum, out, pos);
return CLAT_POS_PAYLOAD + 1;
}
@@ -398,7 +375,7 @@
* TODO: hosts without pmtu discovery - non DF packets will rely on fragmentation (unimplemented)
*/
int tcp_translate(clat_packet out, int pos, const struct tcphdr *tcp, size_t header_size,
- uint32_t old_sum, uint32_t new_sum, const char *payload, size_t payload_size) {
+ uint32_t checksum, const char *payload, size_t payload_size) {
struct tcphdr *tcp_targ = out[pos].iov_base;
out[pos].iov_len = header_size;
@@ -415,57 +392,8 @@
out[CLAT_POS_PAYLOAD].iov_base = (char *)payload;
out[CLAT_POS_PAYLOAD].iov_len = payload_size;
- tcp_targ->check = ip_checksum_adjust(tcp->check, old_sum, new_sum);
+ tcp_targ->check = 0; // Checksum field must be 0 when calculating checksum.
+ tcp_targ->check = packet_checksum(checksum, out, pos);
return CLAT_POS_PAYLOAD + 1;
}
-
-/* function: translate_packet
- * takes a tun header and a packet and sends it down the stack
- * tunnel - tun device data
- * tun_header - tun header
- * packet - packet
- * packetsize - size of packet
- */
-void translate_packet(const struct tun_data *tunnel, struct tun_pi *tun_header, const char *packet,
- size_t packetsize) {
- int fd;
- int iov_len = 0;
-
- // Allocate buffers for all packet headers.
- struct tun_pi tun_targ;
- char iphdr[sizeof(struct ip6_hdr)];
- char transporthdr[MAX_TCP_HDR];
- char icmp_iphdr[sizeof(struct ip6_hdr)];
- char icmp_transporthdr[MAX_TCP_HDR];
-
- // iovec of the packets we'll send. This gets passed down to the translation functions.
- clat_packet out = {
- { &tun_targ, sizeof(tun_targ) }, // Tunnel header.
- { iphdr, 0 }, // IP header.
- { transporthdr, 0 }, // Transport layer header.
- { icmp_iphdr, 0 }, // ICMP error inner IP header.
- { icmp_transporthdr, 0 }, // ICMP error transport layer header.
- { NULL, 0 }, // Payload. No buffer, it's a pointer to the original payload.
- };
-
- if(tun_header->flags != 0) {
- logmsg(ANDROID_LOG_WARN, "translate_packet: unexpected flags = %d", tun_header->flags);
- }
-
- if(ntohs(tun_header->proto) == ETH_P_IP) {
- fd = tunnel->fd6;
- fill_tun_header(&tun_targ, ETH_P_IPV6);
- iov_len = ipv4_packet(out, CLAT_POS_IPHDR, packet, packetsize);
- } else if(ntohs(tun_header->proto) == ETH_P_IPV6) {
- fd = tunnel->fd4;
- fill_tun_header(&tun_targ, ETH_P_IP);
- iov_len = ipv6_packet(out, CLAT_POS_IPHDR, packet, packetsize);
- } else {
- logmsg(ANDROID_LOG_WARN, "translate_packet: unknown packet type = %x",tun_header->proto);
- }
-
- if (iov_len > 0) {
- writev(fd, out, iov_len);
- }
-}
diff --git a/translate.h b/translate.h
index 3378254..fded251 100644
--- a/translate.h
+++ b/translate.h
@@ -18,18 +18,8 @@
#ifndef __TRANSLATE_H__
#define __TRANSLATE_H__
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <linux/icmp.h>
#include <linux/if_tun.h>
-#include "clatd.h"
-
#define MAX_TCP_HDR (15 * 4) // Data offset field is 4 bits and counts in 32-bit words.
// A clat_packet is an array of iovec structures representing a packet that we are translating.
@@ -57,32 +47,19 @@
void fill_ip6_header(struct ip6_hdr *ip6, uint16_t payload_len, uint8_t protocol,
const struct iphdr *old_header);
-// Translate and send packets.
-void translate_packet(const struct tun_data *tunnel, struct tun_pi *tun_header, const char *packet,
- size_t packetsize);
-
-// Translate IPv4 and IPv6 packets.
-int ipv4_packet(clat_packet out, int pos, const char *packet, size_t len);
-int ipv6_packet(clat_packet out, int pos, const char *packet, size_t len);
-
// Translate ICMP packets.
int icmp_to_icmp6(clat_packet out, int pos, const struct icmphdr *icmp, uint32_t checksum,
const char *payload, size_t payload_size);
-int icmp6_to_icmp(clat_packet out, int pos, const struct icmp6_hdr *icmp6,
+int icmp6_to_icmp(clat_packet out, int pos, const struct icmp6_hdr *icmp6, uint32_t checksum,
const char *payload, size_t payload_size);
-// Translate generic IP packets.
-int generic_packet(clat_packet out, int pos, const char *payload, size_t len);
-
// Translate TCP and UDP packets.
-int tcp_packet(clat_packet out, int pos, const struct tcphdr *tcp,
- uint32_t old_sum, uint32_t new_sum, size_t len);
-int udp_packet(clat_packet out, int pos, const struct udphdr *udp,
- uint32_t old_sum, uint32_t new_sum, size_t len);
+int tcp_packet(clat_packet out, int pos, const struct tcphdr *tcp, uint32_t checksum, size_t len);
+int udp_packet(clat_packet out, int pos, const struct udphdr *udp, uint32_t checksum, size_t len);
int tcp_translate(clat_packet out, int pos, const struct tcphdr *tcp, size_t header_size,
- uint32_t old_sum, uint32_t new_sum, const char *payload, size_t payload_size);
-int udp_translate(clat_packet out, int pos, const struct udphdr *udp,
- uint32_t old_sum, uint32_t new_sum, const char *payload, size_t payload_size);
+ uint32_t checksum, const char *payload, size_t payload_size);
+int udp_translate(clat_packet out, int pos, const struct udphdr *udp, uint32_t checksum,
+ const char *payload, size_t payload_size);
#endif /* __TRANSLATE_H__ */