summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej Żenczykowski <maze@google.com>2023-03-15 17:40:45 +0000
committerMaciej Żenczykowski <maze@google.com>2023-03-16 09:36:10 +0000
commitca9466c76809f6bec044669dc2ffb35552e6b404 (patch)
treea66cfc3456323e74a8b05266e9339fb85d92c40d
parenta4df1010f69d1cff2a38e4f7aafb45dfc438cd37 (diff)
downloadandroid-clat-ca9466c76809f6bec044669dc2ffb35552e6b404.tar.gz
clatd: remove ipv6 address monitoring
This code/logic is spurious, because the majority of packets are translated by eBPF, so whether the daemon runs or not, usually just doesn't matter - bpf will handle them anyway. As such what we actually care about is that the daemon is terminated at the same time as the bpf map configuration is removed. This is done by jni native code stopClatdProcess() which is called from ClatCoordinator java code immediately after maybeStopBpf(). Additionally on ipv6 address change we don't even terminate the daemon - we simply stop the event loop, but still block in main() until we receive SIGTERM/SIGKILL. (This was done a while ago to fix a bunch of issues with daemon dieing and being killed racing with each other) Test: TreeHugger Signed-off-by: Maciej Żenczykowski <maze@google.com> Change-Id: I86d203a244838166ed1fbec1bc48a680e433f9fa
-rw-r--r--Android.bp1
-rw-r--r--clatd.c38
-rw-r--r--clatd.h7
-rw-r--r--clatd_test.cpp53
-rw-r--r--getaddr.c169
-rw-r--r--getaddr.h30
6 files changed, 1 insertions, 297 deletions
diff --git a/Android.bp b/Android.bp
index 982e656..983ee00 100644
--- a/Android.bp
+++ b/Android.bp
@@ -40,7 +40,6 @@ filegroup {
srcs: [
"clatd.c",
"dump.c",
- "getaddr.c",
"icmp.c",
"ipv4.c",
"ipv6.c",
diff --git a/clatd.c b/clatd.c
index d1bfa5e..7cee4e8 100644
--- a/clatd.c
+++ b/clatd.c
@@ -44,7 +44,6 @@
#include "checksum.h"
#include "config.h"
#include "dump.h"
-#include "getaddr.h"
#include "logging.h"
#include "translate.h"
@@ -55,29 +54,6 @@ struct clat_config Global_Clatd_Config;
volatile sig_atomic_t running = 1;
-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;
- }
-}
-
// reads IPv6 packet from AF_PACKET socket, translates to IPv4, writes to tun
void process_packet_6_to_4(struct tun_data *tunnel) {
// ethernet header is 14 bytes, plus 4 for a normal VLAN tag or 8 for Q-in-Q
@@ -300,17 +276,13 @@ void event_loop(struct tun_data *tunnel) {
// TODO: actually perform true DAD
send_dad(tunnel->write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
- time_t last_interface_poll;
struct pollfd wait_fd[] = {
{ tunnel->read_fd6, POLLIN, 0 },
{ tunnel->fd4, POLLIN, 0 },
};
- // start the poll timer
- last_interface_poll = time(NULL);
-
while (running) {
- if (poll(wait_fd, ARRAY_SIZE(wait_fd), NO_TRAFFIC_INTERFACE_POLL_FREQUENCY * 1000) == -1) {
+ if (poll(wait_fd, ARRAY_SIZE(wait_fd), -1) == -1) {
if (errno != EINTR) {
logmsg(ANDROID_LOG_WARN, "event_loop/poll returned an error: %s", strerror(errno));
}
@@ -323,13 +295,5 @@ void event_loop(struct tun_data *tunnel) {
if (wait_fd[0].revents) process_packet_6_to_4(tunnel);
if (wait_fd[1].revents) process_packet_4_to_6(tunnel);
}
-
- time_t now = time(NULL);
- if (now >= (last_interface_poll + INTERFACE_POLL_FREQUENCY)) {
- last_interface_poll = now;
- if (ipv6_address_changed(Global_Clatd_Config.native_ipv6_interface)) {
- break;
- }
- }
}
}
diff --git a/clatd.h b/clatd.h
index 59f78ab..85e2c49 100644
--- a/clatd.h
+++ b/clatd.h
@@ -52,15 +52,8 @@ struct tun_data;
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-// how frequently (in seconds) to poll for an address change while traffic is passing
-#define INTERFACE_POLL_FREQUENCY 30
-
-// how frequently (in seconds) to poll for an address change while there is no traffic
-#define NO_TRAFFIC_INTERFACE_POLL_FREQUENCY 90
-
extern volatile sig_atomic_t running;
-int ipv6_address_changed(const char *interface);
void event_loop(struct tun_data *tunnel);
/* function: parse_int
diff --git a/clatd_test.cpp b/clatd_test.cpp
index 8eef738..94ae0b5 100644
--- a/clatd_test.cpp
+++ b/clatd_test.cpp
@@ -33,7 +33,6 @@ extern "C" {
#include "checksum.h"
#include "clatd.h"
#include "config.h"
-#include "getaddr.h"
#include "translate.h"
}
@@ -836,55 +835,3 @@ TEST_F(ClatdTest, TranslateChecksumNeutral) {
check_translate_checksum_neutral(udp_ipv4, sizeof(udp_ipv4), sizeof(udp_ipv4) + 20,
"UDP/IPv4 -> UDP/IPv6 checksum neutral");
}
-
-TEST_F(ClatdTest, GetInterfaceIpV4) {
- TunInterface v4Iface;
- ASSERT_EQ(0, v4Iface.init());
- EXPECT_EQ(0, v4Iface.addAddress("192.0.2.1", 32));
-
- union anyip *ip = getinterface_ip(v4Iface.name().c_str(), AF_INET);
- ASSERT_NE(nullptr, ip);
- EXPECT_EQ(inet_addr("192.0.2.1"), ip->ip4.s_addr);
- free(ip);
-
- v4Iface.destroy();
-}
-
-TEST_F(ClatdTest, GetInterfaceIpV6) {
- union anyip *ip = getinterface_ip(sTun.name().c_str(), AF_INET6);
- ASSERT_NE(nullptr, ip);
- in6_addr expected = sTun.srcAddr();
- in6_addr actual = ip->ip6;
- expect_ipv6_addr_equal(&expected, &actual);
-}
-
-TEST_F(ClatdTest, Ipv6AddressChanged) {
- // Configure the clat IPv6 address.
- const char *ifname = sTun.name().c_str();
-
- in6_addr myaddr = sTun.srcAddr();
- gen_random_iid(&myaddr, &Global_Clatd_Config.ipv4_local_subnet, &Global_Clatd_Config.plat_subnet);
- char addrstr[INET6_ADDRSTRLEN];
- ASSERT_NE(nullptr, inet_ntop(AF_INET6, &myaddr, addrstr, sizeof(addrstr)));
-
- Global_Clatd_Config.ipv6_local_subnet = myaddr;
- 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/getaddr.c b/getaddr.c
deleted file mode 100644
index ba8052d..0000000
--- a/getaddr.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2012 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.
- *
- * getaddr.c - get a locally configured address
- */
-#include "getaddr.h"
-
-#include <errno.h>
-#include <linux/if_addr.h>
-#include <linux/rtnetlink.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-
-#include "logging.h"
-
-// Kernel suggests that keep the packet under 8KiB (NLMSG_GOODSIZE) in include/linux/netlink.h.
-#define NLMSG_SIZE 8192
-
-// shared state between getinterface_ip and parse_ifaddrmsg
-// TODO: refactor the communication between getinterface_ip and parse_ifaddrmsg because there
-// is no netlink callback anymore.
-struct target {
- int family;
- unsigned int ifindex;
- union anyip ip;
- int foundip;
-};
-
-/* function: parse_ifaddrmsg
- * parse ifaddrmsg for getinterface_ip
- * nh - netlink message header
- * targ_p - (struct target) info for which address we're looking for
- * and the parsed result if any.
- */
-static void parse_ifaddrmsg(struct nlmsghdr *nh, struct target *targ_p) {
- struct ifaddrmsg *ifa_p;
- struct rtattr *rta_p;
- int rta_len;
-
- ifa_p = (struct ifaddrmsg *)NLMSG_DATA(nh);
- rta_p = (struct rtattr *)IFA_RTA(ifa_p);
-
- if (ifa_p->ifa_index != targ_p->ifindex) return;
-
- if (ifa_p->ifa_scope != RT_SCOPE_UNIVERSE) return;
-
- rta_len = IFA_PAYLOAD(nh);
- for (; RTA_OK(rta_p, rta_len); rta_p = RTA_NEXT(rta_p, rta_len)) {
- switch (rta_p->rta_type) {
- case IFA_ADDRESS:
- if ((targ_p->family == AF_INET6) && !(ifa_p->ifa_flags & IFA_F_SECONDARY)) {
- memcpy(&targ_p->ip.ip6, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
- targ_p->foundip = 1;
- return;
- }
- break;
- case IFA_LOCAL:
- if (targ_p->family == AF_INET) {
- memcpy(&targ_p->ip.ip4, RTA_DATA(rta_p), rta_p->rta_len - sizeof(struct rtattr));
- targ_p->foundip = 1;
- return;
- }
- break;
- }
- }
-}
-
-void sendrecv_ifaddrmsg(struct target *targ_p) {
- int s = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
- if (s < 0) {
- logmsg(ANDROID_LOG_ERROR, "open NETLINK_ROUTE socket failed %s", strerror(errno));
- return;
- }
-
- // Fill in netlink structures.
- struct {
- struct nlmsghdr n;
- struct ifaddrmsg r;
- } req = {
- // Netlink message header.
- .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
- .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT,
- .n.nlmsg_type = RTM_GETADDR,
-
- // Interface address message header.
- .r.ifa_family = targ_p->family,
- };
-
- // Send interface address message.
- if ((send(s, &req, req.n.nlmsg_len, 0)) < 0) {
- logmsg(ANDROID_LOG_ERROR, "send netlink socket failed %s", strerror(errno));
- close(s);
- return;
- }
-
- // Read interface address message and parse the result if any.
- ssize_t bytes_read;
- char buf[NLMSG_SIZE];
- while ((bytes_read = recv(s, buf, sizeof(buf), 0)) > 0) {
- struct nlmsghdr *nh = (struct nlmsghdr *)buf;
- for (; NLMSG_OK(nh, bytes_read); nh = NLMSG_NEXT(nh, bytes_read)) {
- if (nh->nlmsg_type == NLMSG_DONE) {
- close(s);
- return;
- }
- if (nh->nlmsg_type == NLMSG_ERROR) {
- logmsg(ANDROID_LOG_ERROR, "netlink message error");
- close(s);
- return;
- }
- if (nh->nlmsg_type == RTM_NEWADDR) {
- // Walk through the all messages and update struct target variable as the deleted
- // callback behavior of getaddr_cb() which always returns NL_OK.
- // TODO: review if this can early return once address has been found.
- parse_ifaddrmsg(nh, targ_p);
- }
- }
- }
- close(s);
-}
-
-/* function: getinterface_ip
- * finds the first global non-privacy IP of the given family for the given interface, or returns
- * NULL. caller frees pointer
- * interface - interface to look for
- * family - family
- */
-union anyip *getinterface_ip(const char *interface, int family) {
- union anyip *retval = NULL;
- struct target targ = {
- .family = family,
- .foundip = 0,
- .ifindex = if_nametoindex(interface),
- };
-
- if (targ.ifindex == 0) {
- return NULL; // interface not found
- }
-
- // sends message and receives the response.
- sendrecv_ifaddrmsg(&targ);
-
- if (targ.foundip) {
- retval = malloc(sizeof(union anyip));
- if (!retval) {
- logmsg(ANDROID_LOG_FATAL, "getinterface_ip/out of memory");
- return NULL;
- }
- memcpy(retval, &targ.ip, sizeof(union anyip));
- }
-
- return retval;
-}
diff --git a/getaddr.h b/getaddr.h
deleted file mode 100644
index 482ac13..0000000
--- a/getaddr.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.
- *
- * getaddr.h - get a locally configured address
- */
-#ifndef __GETADDR_H__
-#define __GETADDR_H__
-
-#include <netinet/in.h>
-
-union anyip {
- struct in6_addr ip6;
- struct in_addr ip4;
-};
-
-union anyip *getinterface_ip(const char *interface, int family);
-
-#endif