Move main() out of clatd.c.
This allows us to unit test methods that are in clatd.c. Also simplify the build file, adding a defaults stanza and grouping files in a filegroup so that both the code and the unit test have the same source files. Test: atest clatd_test Test: builds, boots, 464xlat works Change-Id: I544c3ee846abd3e38b80a2d9a4db5497fd9beb0c
This commit is contained in:
parent
b5e8f977bb
commit
eb92f48b1d
9 changed files with 247 additions and 175 deletions
98
Android.bp
98
Android.bp
|
|
@ -1,26 +1,5 @@
|
|||
// The clat daemon.
|
||||
cc_binary {
|
||||
name: "clatd",
|
||||
|
||||
srcs: [
|
||||
"clatd.c",
|
||||
"dump.c",
|
||||
"checksum.c",
|
||||
"translate.c",
|
||||
"icmp.c",
|
||||
"ipv4.c",
|
||||
"ipv6.c",
|
||||
"config.c",
|
||||
"dns64.c",
|
||||
"logging.c",
|
||||
"getaddr.c",
|
||||
"netlink_callbacks.c",
|
||||
"netlink_msg.c",
|
||||
"setif.c",
|
||||
"mtu.c",
|
||||
"tun.c",
|
||||
"ring.c",
|
||||
],
|
||||
cc_defaults {
|
||||
name: "clatd_defaults",
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
|
|
@ -31,15 +10,51 @@ cc_binary {
|
|||
"-Wno-address-of-packed-member",
|
||||
],
|
||||
|
||||
// For NETID_UNSET and MARK_UNSET.
|
||||
include_dirs: ["bionic/libc/dns/include"],
|
||||
|
||||
// For NETID_USE_LOCAL_NAMESERVERS.
|
||||
header_libs: ["libnetd_client_headers"],
|
||||
}
|
||||
|
||||
// Code used both by the daemon and by unit tests.
|
||||
filegroup {
|
||||
name: "clatd_common",
|
||||
srcs: [
|
||||
"checksum.c",
|
||||
"config.c",
|
||||
"clatd.c",
|
||||
"dns64.c",
|
||||
"dump.c",
|
||||
"getaddr.c",
|
||||
"icmp.c",
|
||||
"ipv4.c",
|
||||
"ipv6.c",
|
||||
"logging.c",
|
||||
"mtu.c",
|
||||
"netlink_callbacks.c",
|
||||
"netlink_msg.c",
|
||||
"ring.c",
|
||||
"setif.c",
|
||||
"tun.c",
|
||||
"translate.c",
|
||||
],
|
||||
}
|
||||
|
||||
// The clat daemon.
|
||||
cc_binary {
|
||||
name: "clatd",
|
||||
defaults: ["clatd_defaults"],
|
||||
srcs: [
|
||||
":clatd_common",
|
||||
"main.c"
|
||||
],
|
||||
static_libs: ["libnl"],
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libnetutils",
|
||||
],
|
||||
|
||||
}
|
||||
|
||||
// The configuration file.
|
||||
|
|
@ -51,28 +66,18 @@ prebuilt_etc {
|
|||
// Unit tests.
|
||||
cc_test {
|
||||
name: "clatd_test",
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wunused-parameter",
|
||||
|
||||
// Bug: http://b/33566695
|
||||
"-Wno-address-of-packed-member",
|
||||
],
|
||||
|
||||
defaults: ["clatd_defaults"],
|
||||
srcs: [
|
||||
"clatd_test.cpp",
|
||||
"checksum.c",
|
||||
"translate.c",
|
||||
"icmp.c",
|
||||
"ipv4.c",
|
||||
"ipv6.c",
|
||||
"logging.c",
|
||||
"config.c",
|
||||
"tun.c",
|
||||
":clatd_common",
|
||||
"clatd_test.cpp"
|
||||
],
|
||||
static_libs: [
|
||||
"libbase",
|
||||
"libnetd_test_tun_interface",
|
||||
"libnl",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libcutils",
|
||||
"liblog",
|
||||
"libnetutils",
|
||||
],
|
||||
|
|
@ -81,12 +86,7 @@ cc_test {
|
|||
// Microbenchmark.
|
||||
cc_test {
|
||||
name: "clatd_microbenchmark",
|
||||
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-Wunused-parameter",
|
||||
],
|
||||
defaults: ["clatd_defaults"],
|
||||
srcs: [
|
||||
"clatd_microbenchmark.c",
|
||||
"checksum.c",
|
||||
|
|
|
|||
110
clatd.c
110
clatd.c
|
|
@ -53,8 +53,6 @@
|
|||
#include "translate.h"
|
||||
#include "tun.h"
|
||||
|
||||
#define DEVICEPREFIX "v4-"
|
||||
|
||||
/* 40 bytes IPv6 header - 20 bytes IPv4 header + 8 bytes fragment header */
|
||||
#define MTU_DELTA 28
|
||||
|
||||
|
|
@ -426,17 +424,6 @@ void event_loop(struct tun_data *tunnel) {
|
|||
}
|
||||
}
|
||||
|
||||
/* function: print_help
|
||||
* in case the user is running this on the command line
|
||||
*/
|
||||
void print_help() {
|
||||
printf("android-clat arguments:\n");
|
||||
printf("-i [uplink interface]\n");
|
||||
printf("-p [plat prefix]\n");
|
||||
printf("-n [NetId]\n");
|
||||
printf("-m [socket mark]\n");
|
||||
}
|
||||
|
||||
/* function: parse_unsigned
|
||||
* parses a string as a decimal/hex/octal unsigned integer
|
||||
* str - the string to parse
|
||||
|
|
@ -447,100 +434,3 @@ int parse_unsigned(const char *str, unsigned *out) {
|
|||
*out = strtoul(str, &end_ptr, 0);
|
||||
return *str && !*end_ptr;
|
||||
}
|
||||
|
||||
/* function: main
|
||||
* allocate and setup the tun device, then run the event loop
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
struct tun_data tunnel;
|
||||
int opt;
|
||||
char *uplink_interface = NULL, *plat_prefix = NULL, *net_id_str = NULL, *mark_str = NULL;
|
||||
unsigned net_id = NETID_UNSET;
|
||||
uint32_t mark = MARK_UNSET;
|
||||
unsigned len;
|
||||
|
||||
while ((opt = getopt(argc, argv, "i:p:n:m:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
uplink_interface = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
plat_prefix = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
net_id_str = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
mark_str = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
default:
|
||||
logmsg(ANDROID_LOG_FATAL, "Unknown option -%c. Exiting.", (char)optopt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uplink_interface == NULL) {
|
||||
logmsg(ANDROID_LOG_FATAL, "clatd called without an interface");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (net_id_str != NULL && !parse_unsigned(net_id_str, &net_id)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid NetID %s", net_id_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mark_str != NULL && !parse_unsigned(mark_str, &mark)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid mark %s", mark_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = snprintf(tunnel.device4, sizeof(tunnel.device4), "%s%s", DEVICEPREFIX, uplink_interface);
|
||||
if (len >= sizeof(tunnel.device4)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "interface name too long '%s'", tunnel.device4);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s netid=%s mark=%s", CLATD_VERSION,
|
||||
uplink_interface, net_id_str ? net_id_str : "(none)", mark_str ? mark_str : "(none)");
|
||||
|
||||
// run under a regular user but keep needed capabilities
|
||||
drop_root_but_keep_caps();
|
||||
|
||||
// open our raw sockets before dropping privs
|
||||
open_sockets(&tunnel, mark);
|
||||
|
||||
// keeps only admin capability
|
||||
set_capability(1 << CAP_NET_ADMIN);
|
||||
|
||||
// we can create tun devices as non-root because we're in the VPN group.
|
||||
tunnel.fd4 = tun_open();
|
||||
if (tunnel.fd4 < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// When run from netd, the environment variable ANDROID_DNS_MODE is set to
|
||||
// "local", but that only works for the netd process itself. Removing the
|
||||
// following line causes XLAT failure in permissive mode.
|
||||
unsetenv("ANDROID_DNS_MODE");
|
||||
|
||||
configure_interface(uplink_interface, plat_prefix, &tunnel, net_id);
|
||||
|
||||
update_clat_ipv6_address(&tunnel, uplink_interface);
|
||||
|
||||
// Loop until someone sends us a signal or brings down the tun interface.
|
||||
if (signal(SIGTERM, stop_loop) == SIG_ERR) {
|
||||
logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_loop(&tunnel);
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Shutting down clat on %s", uplink_interface);
|
||||
del_anycast_address(tunnel.write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
30
clatd.h
30
clatd.h
|
|
@ -13,13 +13,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* clatd.h - main system definitions
|
||||
* clatd.h - main routines used by clatd
|
||||
*/
|
||||
#ifndef __CLATD_H__
|
||||
#define __CLATD_H__
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
struct tun_data;
|
||||
|
||||
#define MAXMTU 1500
|
||||
#define PACKETLEN (MAXMTU + sizeof(struct tun_pi))
|
||||
#define CLATD_VERSION "1.4"
|
||||
|
|
@ -32,21 +34,15 @@
|
|||
// how frequently (in seconds) to poll for an address change while there is no traffic
|
||||
#define NO_TRAFFIC_INTERFACE_POLL_FREQUENCY 90
|
||||
|
||||
// A clat_packet is an array of iovec structures representing a packet that we are translating.
|
||||
// The CLAT_POS_XXX constants represent the array indices within the clat_packet that contain
|
||||
// specific parts of the packet. The packet_* functions operate on all the packet segments past a
|
||||
// given position.
|
||||
typedef enum {
|
||||
CLAT_POS_TUNHDR,
|
||||
CLAT_POS_IPHDR,
|
||||
CLAT_POS_FRAGHDR,
|
||||
CLAT_POS_TRANSPORTHDR,
|
||||
CLAT_POS_ICMPERR_IPHDR,
|
||||
CLAT_POS_ICMPERR_FRAGHDR,
|
||||
CLAT_POS_ICMPERR_TRANSPORTHDR,
|
||||
CLAT_POS_PAYLOAD,
|
||||
CLAT_POS_MAX
|
||||
} clat_packet_index;
|
||||
typedef struct iovec clat_packet[CLAT_POS_MAX];
|
||||
void stop_loop();
|
||||
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);
|
||||
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);
|
||||
int parse_unsigned(const char *str, unsigned *out);
|
||||
|
||||
#endif /* __CLATD_H__ */
|
||||
|
|
|
|||
40
common.h
Normal file
40
common.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* common.h - common definitions
|
||||
*/
|
||||
#ifndef __CLATD_COMMON_H__
|
||||
#define __CLATD_COMMON_H__
|
||||
|
||||
#include <sys/uio.h>
|
||||
|
||||
// A clat_packet is an array of iovec structures representing a packet that we are translating.
|
||||
// The CLAT_POS_XXX constants represent the array indices within the clat_packet that contain
|
||||
// specific parts of the packet. The packet_* functions operate on all the packet segments past a
|
||||
// given position.
|
||||
typedef enum {
|
||||
CLAT_POS_TUNHDR,
|
||||
CLAT_POS_IPHDR,
|
||||
CLAT_POS_FRAGHDR,
|
||||
CLAT_POS_TRANSPORTHDR,
|
||||
CLAT_POS_ICMPERR_IPHDR,
|
||||
CLAT_POS_ICMPERR_FRAGHDR,
|
||||
CLAT_POS_ICMPERR_TRANSPORTHDR,
|
||||
CLAT_POS_PAYLOAD,
|
||||
CLAT_POS_MAX
|
||||
} clat_packet_index;
|
||||
typedef struct iovec clat_packet[CLAT_POS_MAX];
|
||||
|
||||
#endif /* __CLATD_COMMON_H__ */
|
||||
144
main.c
Normal file
144
main.c
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* main.c - main function
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/capability.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "resolv_netid.h"
|
||||
|
||||
#include "clatd.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
#include "setif.h"
|
||||
#include "tun.h"
|
||||
|
||||
#define DEVICEPREFIX "v4-"
|
||||
|
||||
/* function: print_help
|
||||
* in case the user is running this on the command line
|
||||
*/
|
||||
void print_help() {
|
||||
printf("android-clat arguments:\n");
|
||||
printf("-i [uplink interface]\n");
|
||||
printf("-p [plat prefix]\n");
|
||||
printf("-n [NetId]\n");
|
||||
printf("-m [socket mark]\n");
|
||||
}
|
||||
|
||||
/* function: main
|
||||
* allocate and setup the tun device, then run the event loop
|
||||
*/
|
||||
int main(int argc, char **argv) {
|
||||
struct tun_data tunnel;
|
||||
int opt;
|
||||
char *uplink_interface = NULL, *plat_prefix = NULL, *net_id_str = NULL, *mark_str = NULL;
|
||||
unsigned net_id = NETID_UNSET;
|
||||
uint32_t mark = MARK_UNSET;
|
||||
unsigned len;
|
||||
|
||||
while ((opt = getopt(argc, argv, "i:p:n:m:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 'i':
|
||||
uplink_interface = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
plat_prefix = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
net_id_str = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
mark_str = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(0);
|
||||
default:
|
||||
logmsg(ANDROID_LOG_FATAL, "Unknown option -%c. Exiting.", (char)optopt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uplink_interface == NULL) {
|
||||
logmsg(ANDROID_LOG_FATAL, "clatd called without an interface");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (net_id_str != NULL && !parse_unsigned(net_id_str, &net_id)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid NetID %s", net_id_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (mark_str != NULL && !parse_unsigned(mark_str, &mark)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "invalid mark %s", mark_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = snprintf(tunnel.device4, sizeof(tunnel.device4), "%s%s", DEVICEPREFIX, uplink_interface);
|
||||
if (len >= sizeof(tunnel.device4)) {
|
||||
logmsg(ANDROID_LOG_FATAL, "interface name too long '%s'", tunnel.device4);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Starting clat version %s on %s netid=%s mark=%s", CLATD_VERSION,
|
||||
uplink_interface, net_id_str ? net_id_str : "(none)", mark_str ? mark_str : "(none)");
|
||||
|
||||
// run under a regular user but keep needed capabilities
|
||||
drop_root_but_keep_caps();
|
||||
|
||||
// open our raw sockets before dropping privs
|
||||
open_sockets(&tunnel, mark);
|
||||
|
||||
// keeps only admin capability
|
||||
set_capability(1 << CAP_NET_ADMIN);
|
||||
|
||||
// we can create tun devices as non-root because we're in the VPN group.
|
||||
tunnel.fd4 = tun_open();
|
||||
if (tunnel.fd4 < 0) {
|
||||
logmsg(ANDROID_LOG_FATAL, "tun_open4 failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// When run from netd, the environment variable ANDROID_DNS_MODE is set to
|
||||
// "local", but that only works for the netd process itself. Removing the
|
||||
// following line causes XLAT failure in permissive mode.
|
||||
unsetenv("ANDROID_DNS_MODE");
|
||||
|
||||
configure_interface(uplink_interface, plat_prefix, &tunnel, net_id);
|
||||
|
||||
update_clat_ipv6_address(&tunnel, uplink_interface);
|
||||
|
||||
// Loop until someone sends us a signal or brings down the tun interface.
|
||||
if (signal(SIGTERM, stop_loop) == SIG_ERR) {
|
||||
logmsg(ANDROID_LOG_FATAL, "sigterm handler failed: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
event_loop(&tunnel);
|
||||
|
||||
logmsg(ANDROID_LOG_INFO, "Shutting down clat on %s", uplink_interface);
|
||||
del_anycast_address(tunnel.write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "checksum.h"
|
||||
#include "clatd.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
#include "icmp.h"
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <netinet/udp.h>
|
||||
|
||||
#include "clatd.h"
|
||||
#include "common.h"
|
||||
|
||||
#define MAX_TCP_HDR (15 * 4) // Data offset field is 4 bits and counts in 32-bit words.
|
||||
|
||||
|
|
|
|||
2
tun.c
2
tun.c
|
|
@ -24,7 +24,7 @@
|
|||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "clatd.h"
|
||||
#include "common.h"
|
||||
|
||||
/* function: tun_open
|
||||
* tries to open the tunnel device
|
||||
|
|
|
|||
2
tun.h
2
tun.h
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "clatd.h"
|
||||
#include "common.h"
|
||||
#include "ring.h"
|
||||
|
||||
struct tun_data {
|
||||
|
|
|
|||
Loading…
Reference in a new issue