summaryrefslogtreecommitdiffstats
path: root/clatd.c
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2014-10-31 21:54:33 +0900
committerLorenzo Colitti <lorenzo@google.com>2014-11-01 01:17:22 +0900
commit798f9934fca523dfb57136bd185cf6e9460323ad (patch)
tree2173d37b9a340b20d06a339375e9b27a7730b01c /clatd.c
parent8a41a5d140b3cf56a54bdeef234e89ee12cba0dc (diff)
downloadandroid_external_android-clat-798f9934fca523dfb57136bd185cf6e9460323ad.tar.gz
android_external_android-clat-798f9934fca523dfb57136bd185cf6e9460323ad.tar.bz2
android_external_android-clat-798f9934fca523dfb57136bd185cf6e9460323ad.zip
Use different IPv4 addresses on different clat interfaces.
Previously the code would use 192.0.0.4 on all clat interfaces. This works, but it has the problem when a clat interface goes down, we do not reset TCP connections on its IP address if there is another clat interface up. Fix this by assigning every clat interface its own IP address in 192.0.0.0/29. Bug: 12111730 Change-Id: I28c831acd93b0980efea8e90c1cdf8b607beac68
Diffstat (limited to 'clatd.c')
-rw-r--r--clatd.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/clatd.c b/clatd.c
index 41e961e..3f0af0b 100644
--- a/clatd.c
+++ b/clatd.c
@@ -157,6 +157,22 @@ int configure_packet_socket(int sock) {
void configure_tun_ip(const struct tun_data *tunnel) {
int status;
+ // Pick an IPv4 address to use by finding a free address in the configured prefix. Technically,
+ // there is a race here - if another clatd calls config_select_ipv4_address after we do, but
+ // before we call add_address, it can end up having the same IP address as we do. But the time
+ // window in which this can happen is extremely small, and even if we end up with a duplicate
+ // address, the only damage is that IPv4 TCP connections won't be reset until both interfaces go
+ // down.
+ in_addr_t localaddr = config_select_ipv4_address(&Global_Clatd_Config.ipv4_local_subnet,
+ Global_Clatd_Config.ipv4_local_prefixlen);
+ if (localaddr == INADDR_NONE) {
+ logmsg(ANDROID_LOG_FATAL,"No free IPv4 address in %s/%d",
+ inet_ntoa(Global_Clatd_Config.ipv4_local_subnet),
+ Global_Clatd_Config.ipv4_local_prefixlen);
+ exit(1);
+ }
+ Global_Clatd_Config.ipv4_local_subnet.s_addr = localaddr;
+
// Configure the interface before bringing it up. As soon as we bring the interface up, the
// framework will be notified and will assume the interface's configuration has been finalized.
status = add_address(tunnel->device4, AF_INET, &Global_Clatd_Config.ipv4_local_subnet,
@@ -166,6 +182,10 @@ void configure_tun_ip(const struct tun_data *tunnel) {
exit(1);
}
+ char addrstr[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &Global_Clatd_Config.ipv4_local_subnet, addrstr, sizeof(addrstr));
+ logmsg(ANDROID_LOG_INFO, "Using IPv4 address %s on %s", addrstr, tunnel->device4);
+
if((status = if_up(tunnel->device4, Global_Clatd_Config.ipv4mtu)) < 0) {
logmsg(ANDROID_LOG_FATAL,"configure_tun_ip/if_up(4) failed: %s",strerror(-status));
exit(1);
@@ -269,7 +289,7 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
if (IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet)) {
// Startup.
- logmsg(ANDROID_LOG_INFO, "Using %s on %s", addrstr, interface);
+ logmsg(ANDROID_LOG_INFO, "Using IPv6 address %s on %s", addrstr, interface);
} else {
// Prefix change.
char from_addr[INET6_ADDRSTRLEN];