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
This commit is contained in:
parent
1352a3a26c
commit
8a41a5d140
3 changed files with 58 additions and 0 deletions
4
clatd.c
4
clatd.c
|
|
@ -275,10 +275,12 @@ int update_clat_ipv6_address(const struct tun_data *tunnel, const char *interfac
|
|||
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 @@ int main(int argc, char **argv) {
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
51
setif.c
51
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 @@ cleanup:
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
3
setif.h
3
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue