summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2019-01-04 12:27:27 +0900
committerLorenzo Colitti <lorenzo@google.com>2019-01-06 11:22:16 +0900
commit66deecd38f88e4e7944ed5841e10051ef5f0b7d6 (patch)
treeab6193bf151756a59faa9b69819753e1f1770833
parent72f770c4ad644ad49371531ac030196eff32076b (diff)
downloadplatform_external_android-clat-66deecd38f88e4e7944ed5841e10051ef5f0b7d6.tar.gz
platform_external_android-clat-66deecd38f88e4e7944ed5841e10051ef5f0b7d6.tar.bz2
platform_external_android-clat-66deecd38f88e4e7944ed5841e10051ef5f0b7d6.zip
Drop support for updating IPv6 addresses in clatd.
Currently, when clatd detects that the IPv6 address on its interface has changed, it updates its configuration accordingly. This complicates the code, and it prevents us from determining the IPv6 address in netd instead of clatd. Stop doing this, and simply exit instead. The framework will notice that the interface is gone and restart clatd, which will then have the correct configuration (and, unlike current code, the correct NAT64 prefix, if that has changed as well). This change also allows us to drop CAP_NET_ADMIN and run clatd as an unprivileged user with no capabilities. Test: atest clatd_test Test: changing IPv6 address on interface causes clatd to exit Test: "adb shell cat /proc/$(adb shell pidof clatd)/status | grep Cap" Change-Id: I296dcb185f603f685223b24ffefdf7a5c22b66e6
-rw-r--r--clatd.c57
-rw-r--r--clatd.h2
-rw-r--r--clatd_test.cpp37
-rw-r--r--main.c3
4 files changed, 71 insertions, 28 deletions
diff --git a/clatd.c b/clatd.c
index 2ef10a5..bcbd9c5 100644
--- a/clatd.c
+++ b/clatd.c
@@ -228,13 +228,36 @@ void open_sockets(struct tun_data *tunnel, uint32_t mark) {
}
}
-/* function: update_clat_ipv6_address
+int ipv6_address_changed(const char *interface) {
+ union anyip *interface_ip;
+
+ interface_ip = getinterface_ip(interface, AF_INET6);
+ if (!interface_ip) {
+ logmsg(ANDROID_LOG_ERROR, "Unable to find an IPv6 address on interface %s", interface);
+ return 1;
+ }
+
+ if (!ipv6_prefix_equal(&interface_ip->ip6, &Global_Clatd_Config.ipv6_local_subnet)) {
+ char oldstr[INET6_ADDRSTRLEN];
+ char newstr[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, oldstr, sizeof(oldstr));
+ inet_ntop(AF_INET6, &interface_ip->ip6, newstr, sizeof(newstr));
+ logmsg(ANDROID_LOG_INFO, "IPv6 prefix on %s changed: %s -> %s", interface, oldstr, newstr);
+ free(interface_ip);
+ return 1;
+ } else {
+ free(interface_ip);
+ return 0;
+ }
+}
+
+/* function: configure_clat_ipv6_address
* picks the clat IPv6 address and configures packet translation to use it.
* tunnel - tun device data
* interface - uplink interface name
* returns: 1 on success, 0 on failure
*/
-int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interface) {
+int configure_clat_ipv6_address(const struct tun_data *tunnel, const char *interface) {
union anyip *interface_ip;
char addrstr[INET6_ADDRSTRLEN];
@@ -245,27 +268,10 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
return 0;
}
- // If our prefix hasn't changed, do nothing. (If this is the first time we configure an IPv6
- // address, Global_Clatd_Config.ipv6_local_subnet will be ::, which won't match our new prefix.)
- if (ipv6_prefix_equal(&interface_ip->ip6, &Global_Clatd_Config.ipv6_local_subnet)) {
- free(interface_ip);
- return 1;
- }
-
// Generate an interface ID.
config_generate_local_ipv6_subnet(&interface_ip->ip6);
inet_ntop(AF_INET6, &interface_ip->ip6, addrstr, sizeof(addrstr));
-
- if (IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet)) {
- // Startup.
- logmsg(ANDROID_LOG_INFO, "Using IPv6 address %s on %s", addrstr, interface);
- } else {
- // Prefix change.
- char from_addr[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, from_addr, sizeof(from_addr));
- logmsg(ANDROID_LOG_INFO, "clat IPv6 address changed from %s to %s", from_addr, addrstr);
- del_anycast_address(tunnel->write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
- }
+ logmsg(ANDROID_LOG_INFO, "Using IPv6 address %s on %s", addrstr, interface);
// Start translating packets to the new prefix.
Global_Clatd_Config.ipv6_local_subnet = interface_ip->ip6;
@@ -276,7 +282,7 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
if (!configure_packet_socket(tunnel->read_fd6)) {
// Things aren't going to work. Bail out and hope we have better luck next time.
// We don't log an error here because configure_packet_socket has already done so.
- exit(1);
+ return 0;
}
return 1;
@@ -330,6 +336,10 @@ void configure_interface(const char *uplink_interface, const char *plat_prefix,
}
configure_tun_ip(tunnel);
+
+ if (!configure_clat_ipv6_address(tunnel, uplink_interface)) {
+ exit(1);
+ }
}
/* function: read_packet
@@ -418,8 +428,9 @@ void event_loop(struct tun_data *tunnel) {
time_t now = time(NULL);
if (last_interface_poll < (now - INTERFACE_POLL_FREQUENCY)) {
- update_clat_ipv6_address(tunnel, Global_Clatd_Config.default_pdp_interface);
- last_interface_poll = now;
+ if (ipv6_address_changed(Global_Clatd_Config.default_pdp_interface)) {
+ break;
+ }
}
}
}
diff --git a/clatd.h b/clatd.h
index 32f8cd5..67ba990 100644
--- a/clatd.h
+++ b/clatd.h
@@ -39,7 +39,7 @@ void set_capability(uint64_t target_cap);
void drop_root_but_keep_caps();
void open_sockets(struct tun_data *tunnel, uint32_t mark);
int ipv6_address_changed(const char *interface);
-int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interface);
+int configure_clat_ipv6_address(const struct tun_data *tunnel, const char *interface);
void configure_interface(const char *uplink_interface, const char *plat_prefix,
struct tun_data *tunnel, unsigned net_id);
void event_loop(struct tun_data *tunnel);
diff --git a/clatd_test.cpp b/clatd_test.cpp
index 4f998ea..81af41d 100644
--- a/clatd_test.cpp
+++ b/clatd_test.cpp
@@ -24,6 +24,8 @@
#include <sys/uio.h>
#include <gtest/gtest.h>
+
+#include "netutils/ifc.h"
#include "tun_interface.h"
extern "C" {
@@ -963,16 +965,16 @@ TEST_F(ClatdTest, GetInterfaceIp) {
expect_ipv6_addr_equal(&expected, &actual);
}
-TEST_F(ClatdTest, UpdateIpv6Address) {
+TEST_F(ClatdTest, ConfigureIpv6Address) {
// Create some fake but realistic-looking sockets so update_clat_ipv6_address doesn't balk.
struct tun_data tunnel = {
.write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
.read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
};
- // Run update_clat_ipv6_address with no local IID yet picked.
+ // Run configure_clat_ipv6_address.
ASSERT_TRUE(IN6_IS_ADDR_UNSPECIFIED(&Global_Clatd_Config.ipv6_local_subnet));
- ASSERT_EQ(1, update_clat_ipv6_address(&tunnel, sTun.name().c_str()));
+ ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, sTun.name().c_str()));
// Check that it generated an IID in the same prefix as the address assigned to the interface,
// and that the IID is not the default IID.
@@ -990,3 +992,32 @@ TEST_F(ClatdTest, UpdateIpv6Address) {
EXPECT_EQ(htons(ETH_P_IPV6), sll.sll_protocol);
EXPECT_EQ(sll.sll_ifindex, sTun.ifindex());
}
+
+TEST_F(ClatdTest, Ipv6AddressChanged) {
+ // Configure the clat IPv6 address.
+ struct tun_data tunnel = {
+ .write_fd6 = socket(AF_INET6, SOCK_RAW | SOCK_NONBLOCK, IPPROTO_RAW),
+ .read_fd6 = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)),
+ };
+ const char *ifname = sTun.name().c_str();
+ ASSERT_EQ(1, configure_clat_ipv6_address(&tunnel, ifname));
+ EXPECT_EQ(0, ipv6_address_changed(ifname));
+ EXPECT_EQ(0, ipv6_address_changed(ifname));
+
+ // Change the IP address on the tun interface to a new prefix.
+ char srcaddr[INET6_ADDRSTRLEN];
+ char dstaddr[INET6_ADDRSTRLEN];
+ ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.srcAddr(), srcaddr, sizeof(srcaddr)));
+ ASSERT_NE(nullptr, inet_ntop(AF_INET6, &sTun.dstAddr(), dstaddr, sizeof(dstaddr)));
+ EXPECT_EQ(0, ifc_del_address(ifname, srcaddr, 64));
+ EXPECT_EQ(0, ifc_del_address(ifname, dstaddr, 64));
+
+ // Check that we can tell that the address has changed.
+ EXPECT_EQ(0, ifc_add_address(ifname, "2001:db8::1:2", 64));
+ EXPECT_EQ(1, ipv6_address_changed(ifname));
+ EXPECT_EQ(1, ipv6_address_changed(ifname));
+
+ // Restore the tun interface configuration.
+ sTun.destroy();
+ ASSERT_EQ(0, sTun.init());
+}
diff --git a/main.c b/main.c
index e717498..11c51a5 100644
--- a/main.c
+++ b/main.c
@@ -127,7 +127,8 @@ int main(int argc, char **argv) {
configure_interface(uplink_interface, plat_prefix, &tunnel, net_id);
- update_clat_ipv6_address(&tunnel, uplink_interface);
+ // Drop all remaining capabilities.
+ set_capability(0);
// Loop until someone sends us a signal or brings down the tun interface.
if (signal(SIGTERM, stop_loop) == SIG_ERR) {