[RFCLAT#4] Move clat ipv6 address setup from clatd to netd
This is a preparation for reducing the clatd required capability.
Function change:
- configure_clat_ipv6_address(), configure_interface(),
configure_packet_socket() are moved to netd/ClatdController
- move the follows to main() because previous functions are removed.
setup Global_Clatd_Config.native_ipv6_interface
setup Global_Clatd_Config.plat_subnet
setup Global_Clatd_Config.ipv6_local_subnet
Bug: 212345928
Test: manual test
1. Connect to ipv6-only wifi.
2. Try IPv4 traffic.
$ ping 8.8.8.8
Change-Id: I8457b7752a799756549a72296aae572ad73ff653
diff --git a/clatd.c b/clatd.c
index 865a568..bc6b652 100644
--- a/clatd.c
+++ b/clatd.c
@@ -57,53 +57,6 @@
volatile sig_atomic_t running = 1;
-/* function: configure_packet_socket
- * Binds the packet socket and attaches the receive filter to it.
- * sock - the socket to configure
- */
-int configure_packet_socket(int sock) {
- uint32_t *ipv6 = Global_Clatd_Config.ipv6_local_subnet.s6_addr32;
-
- // clang-format off
- struct sock_filter filter_code[] = {
- // Load the first four bytes of the IPv6 destination address (starts 24 bytes in).
- // Compare it against the first four bytes of our IPv6 address, in host byte order (BPF loads
- // are always in host byte order). If it matches, continue with next instruction (JMP 0). If it
- // doesn't match, jump ahead to statement that returns 0 (ignore packet). Repeat for the other
- // three words of the IPv6 address, and if they all match, return PACKETLEN (accept packet).
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 24),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[0]), 0, 7),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 28),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[1]), 0, 5),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 32),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[2]), 0, 3),
- BPF_STMT(BPF_LD | BPF_W | BPF_ABS, 36),
- BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, htonl(ipv6[3]), 0, 1),
- BPF_STMT(BPF_RET | BPF_K, PACKETLEN),
- BPF_STMT(BPF_RET | BPF_K, 0),
- };
- // clang-format on
- struct sock_fprog filter = { sizeof(filter_code) / sizeof(filter_code[0]), filter_code };
-
- if (setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &filter, sizeof(filter))) {
- logmsg(ANDROID_LOG_FATAL, "attach packet filter failed: %s", strerror(errno));
- return 0;
- }
-
- struct sockaddr_ll sll = {
- .sll_family = AF_PACKET,
- .sll_protocol = htons(ETH_P_IPV6),
- .sll_ifindex = if_nametoindex(Global_Clatd_Config.native_ipv6_interface),
- .sll_pkttype = PACKET_OTHERHOST, // The 464xlat IPv6 address is not assigned to the kernel.
- };
- if (bind(sock, (struct sockaddr *)&sll, sizeof(sll))) {
- logmsg(ANDROID_LOG_FATAL, "binding packet socket: %s", strerror(errno));
- return 0;
- }
-
- return 1;
-}
-
/* function: set_capability
* set the permitted, effective and inheritable capabilities of the current
* thread
@@ -169,56 +122,6 @@
}
}
-/* 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 configure_clat_ipv6_address(const struct tun_data *tunnel, const char *interface,
- const char *v6_addr) {
- if (!v6_addr || !inet_pton(AF_INET6, v6_addr, &Global_Clatd_Config.ipv6_local_subnet)) {
- logmsg(ANDROID_LOG_FATAL, "Invalid source address %s", v6_addr);
- return 0;
- }
-
- char addrstr[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, addrstr, sizeof(addrstr));
- logmsg(ANDROID_LOG_INFO, "Using IPv6 address %s on %s", addrstr, interface);
-
- // Start translating packets to the new prefix.
- add_anycast_address(tunnel->write_fd6, &Global_Clatd_Config.ipv6_local_subnet, interface);
-
- // Update our packet socket filter to reflect the new 464xlat IP address.
- 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.
- return 0;
- }
-
- return 1;
-}
-
-/* function: configure_interface
- * reads the configuration and applies it to the interface
- * uplink_interface - network interface to use to reach the ipv6 internet
- * plat_prefix - PLAT prefix to use
- * v6_addr - the v6 address to use on the native interface
- * tunnel - tun device data
- */
-void configure_interface(const char *uplink_interface, const char *plat_prefix, const char *v6_addr,
- struct tun_data *tunnel) {
- Global_Clatd_Config.native_ipv6_interface = uplink_interface;
- if (!plat_prefix || inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
- logmsg(ANDROID_LOG_FATAL, "invalid IPv6 address specified for plat prefix: %s", plat_prefix);
- exit(1);
- }
-
- if (!configure_clat_ipv6_address(tunnel, uplink_interface, v6_addr)) {
- exit(1);
- }
-}
-
/* function: read_packet
* reads a packet from the tunnel fd and translates it
* read_fd - file descriptor to read original packet from
diff --git a/clatd.h b/clatd.h
index a42768c..be3c9c1 100644
--- a/clatd.h
+++ b/clatd.h
@@ -41,10 +41,6 @@
void set_capability(uint64_t target_cap);
void drop_root_and_caps();
int ipv6_address_changed(const char *interface);
-int configure_clat_ipv6_address(const struct tun_data *tunnel, const char *interface,
- const char *src_addr);
-void configure_interface(const char *uplink_interface, const char *plat_prefix, const char *v6,
- struct tun_data *tunnel);
void event_loop(struct tun_data *tunnel);
/* function: parse_int
diff --git a/main.c b/main.c
index fe88dfd..ef5e3ab 100644
--- a/main.c
+++ b/main.c
@@ -145,18 +145,27 @@
exit(1);
}
+ Global_Clatd_Config.native_ipv6_interface = uplink_interface;
+ if (!plat_prefix || inet_pton(AF_INET6, plat_prefix, &Global_Clatd_Config.plat_subnet) <= 0) {
+ logmsg(ANDROID_LOG_FATAL, "invalid IPv6 address specified for plat prefix: %s", plat_prefix);
+ exit(1);
+ }
+
if (!v4_addr || !inet_pton(AF_INET, v4_addr, &Global_Clatd_Config.ipv4_local_subnet.s_addr)) {
logmsg(ANDROID_LOG_FATAL, "Invalid IPv4 address %s", v4_addr);
exit(1);
}
+ if (!v6_addr || !inet_pton(AF_INET6, v6_addr, &Global_Clatd_Config.ipv6_local_subnet)) {
+ logmsg(ANDROID_LOG_FATAL, "Invalid source address %s", v6_addr);
+ exit(1);
+ }
+
logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s mark=%s plat=%s v4=%s v6=%s",
CLATD_VERSION, uplink_interface, mark_str ? mark_str : "(none)",
plat_prefix ? plat_prefix : "(none)", v4_addr ? v4_addr : "(none)",
v6_addr ? v6_addr : "(none)");
- configure_interface(uplink_interface, plat_prefix, v6_addr, &tunnel);
-
// run under a regular user with no capabilities
drop_root_and_caps();