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
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 @@
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 @@
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());
+}