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
diff --git a/Android.bp b/Android.bp
index 2603472..7f28a3c 100644
--- a/Android.bp
+++ b/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 @@
         "-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 @@
 // 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 @@
 // Microbenchmark.
 cc_test {
     name: "clatd_microbenchmark",
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wunused-parameter",
-    ],
+    defaults: ["clatd_defaults"],
     srcs: [
         "clatd_microbenchmark.c",
         "checksum.c",
diff --git a/clatd.c b/clatd.c
index 18d7562..2ef10a5 100644
--- a/clatd.c
+++ b/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 @@
   }
 }
 
-/* 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 @@
   *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;
-}
diff --git a/clatd.h b/clatd.h
index 327a948..32f8cd5 100644
--- a/clatd.h
+++ b/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__ */
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..e9551ee
--- /dev/null
+++ b/common.h
@@ -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__ */
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..e717498
--- /dev/null
+++ b/main.c
@@ -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;
+}
diff --git a/translate.c b/translate.c
index 58a7e9d..df3d020 100644
--- a/translate.c
+++ b/translate.c
@@ -19,6 +19,7 @@
 
 #include "checksum.h"
 #include "clatd.h"
+#include "common.h"
 #include "config.h"
 #include "debug.h"
 #include "icmp.h"
diff --git a/translate.h b/translate.h
index 692affc..0e520f7 100644
--- a/translate.h
+++ b/translate.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.
 
diff --git a/tun.c b/tun.c
index 1120bae..406fc2f 100644
--- a/tun.c
+++ b/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
diff --git a/tun.h b/tun.h
index bcdd10e..f0449b9 100644
--- a/tun.h
+++ b/tun.h
@@ -20,7 +20,7 @@
 
 #include <linux/if.h>
 
-#include "clatd.h"
+#include "common.h"
 #include "ring.h"
 
 struct tun_data {