Support 464xlat on broadcast interfaces such as wifi.

This works by generating a random IID and then using the
IPV6_JOIN_ANYCAST socket option on the write-only raw socket to
configure an address on the interface.

Change-Id: Ieb885b7c54454988e2e4254a14b4213cba3bd791
diff --git a/clatd.c b/clatd.c
index 78ccccc..41e961e 100644
--- a/clatd.c
+++ b/clatd.c
@@ -275,10 +275,12 @@
     char from_addr[INET6_ADDRSTRLEN];
     inet_ntop(AF_INET6, &Global_Clatd_Config.ipv6_local_subnet, from_addr, sizeof(from_addr));
     logmsg(ANDROID_LOG_INFO, "clat IPv6 address changed from %s to %s", from_addr, addrstr);
+    del_anycast_address(tunnel->write_fd6, &Global_Clatd_Config.ipv6_local_subnet);
   }
 
   // Start translating packets to the new prefix.
   Global_Clatd_Config.ipv6_local_subnet = interface_ip->ip6;
+  add_anycast_address(tunnel->write_fd6, &Global_Clatd_Config.ipv6_local_subnet, interface);
   free(interface_ip);
 
   // Update our packet socket filter to reflect the new 464xlat IP address.
@@ -534,9 +536,11 @@
     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/setif.c b/setif.c
index 5ee00bc..359ed24 100644
--- a/setif.c
+++ b/setif.c
@@ -23,8 +23,11 @@
 #include <netlink/handlers.h>
 #include <netlink/msg.h>
 
+#include "logging.h"
 #include "netlink_msg.h"
 
+#define DEBUG_OPTNAME(a) case (a): { optname = #a; break; }
+
 /* function: add_address
  * adds an IP address to/from an interface, returns 0 on success and <0 on failure
  * ifname    - name of interface to change
@@ -127,3 +130,51 @@
 
   return retval;
 }
+
+static int do_anycast_setsockopt(int sock, int what, struct in6_addr *addr, int ifindex) {
+  struct ipv6_mreq mreq = { *addr, ifindex };
+  char *optname;
+  int ret;
+
+  switch (what) {
+    DEBUG_OPTNAME(IPV6_JOIN_ANYCAST)
+    DEBUG_OPTNAME(IPV6_LEAVE_ANYCAST)
+    default:
+      optname = "???";
+      break;
+  }
+
+  ret = setsockopt(sock, SOL_IPV6, what, &mreq, sizeof(mreq));
+  if (ret) {
+    logmsg(ANDROID_LOG_ERROR, "%s: setsockopt(%s): %s", __func__, optname, strerror(errno));
+  }
+
+  return ret;
+}
+
+/* function: add_anycast_address
+ * adds an anycast IPv6 address to an interface, returns 0 on success and <0 on failure
+ * sock      - the socket to add the address to
+ * addr      - the IP address to add
+ * ifname    - name of interface to add the address to
+ */
+int add_anycast_address(int sock, struct in6_addr *addr, const char *ifname) {
+  int ifindex, s, ret;
+
+  ifindex = if_nametoindex(ifname);
+  if (!ifindex) {
+    logmsg(ANDROID_LOG_ERROR, "%s: unknown ifindex for interface %s", __func__, ifname);
+    return -ENODEV;
+  }
+
+  return do_anycast_setsockopt(sock, IPV6_JOIN_ANYCAST, addr, ifindex);
+}
+
+/* function: del_anycast_address
+ * removes an anycast IPv6 address from the system, returns 0 on success and <0 on failure
+ * sock      - the socket to remove from, must have had the address added via add_anycast_address
+ * addr      - the IP address to remove
+ */
+int del_anycast_address(int sock, struct in6_addr *addr) {
+  return do_anycast_setsockopt(sock, IPV6_LEAVE_ANYCAST, addr, 0);
+}
diff --git a/setif.h b/setif.h
index 7f83f73..d31eed5 100644
--- a/setif.h
+++ b/setif.h
@@ -21,4 +21,7 @@
 int add_address(const char *ifname, int family, const void *address, int cidr, const void *broadcast);
 int if_up(const char *ifname, int mtu);
 
+int add_anycast_address(int sock, const struct in6_addr *addr, const char *interface);
+int del_anycast_address(int sock, const struct in6_addr *addr);
+
 #endif