int ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length, struct in6_addr gw) { struct in6_rtmsg rtmsg; int result; int ifindex; memset(&rtmsg, 0, sizeof(rtmsg)); ifindex = if_nametoindex(ifname); if (ifindex == 0) { printerr("if_nametoindex() failed: interface %s\n", ifname); return -ENXIO; } rtmsg.rtmsg_ifindex = ifindex; rtmsg.rtmsg_dst = dst; rtmsg.rtmsg_dst_len = prefix_length; rtmsg.rtmsg_flags = RTF_UP; if (prefix_length == 128) { rtmsg.rtmsg_flags |= RTF_HOST; } if (memcmp(&gw, &in6addr_any, sizeof(in6addr_any))) { rtmsg.rtmsg_flags |= RTF_GATEWAY; rtmsg.rtmsg_gateway = gw; } ifc_init6(); if (ifc_ctl_sock6 < 0) { return -errno; } result = ioctl(ifc_ctl_sock6, action, &rtmsg); if (result < 0) { if (errno == EEXIST) { result = 0; } else { result = -errno; } } ifc_close6(); return result; }
int ifc_reset_connections(const char *ifname, const int reset_mask) { #ifdef HAVE_ANDROID_OS int result, success; in_addr_t myaddr = 0; struct ifreq ifr; struct in6_ifreq ifr6; if (reset_mask & RESET_IPV4_ADDRESSES) { /* IPv4. Clear connections on the IP address. */ ifc_init(); if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { ifc_get_info(ifname, &myaddr, NULL, NULL); } ifc_init_ifr(ifname, &ifr); init_sockaddr_in(&ifr.ifr_addr, myaddr); result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); ifc_close(); } else { result = 0; } if (reset_mask & RESET_IPV6_ADDRESSES) { /* * IPv6. On Linux, when an interface goes down it loses all its IPv6 * addresses, so we don't know which connections belonged to that interface * So we clear all unused IPv6 connections on the device by specifying an * empty IPv6 address. */ ifc_init6(); // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. memset(&ifr6, 0, sizeof(ifr6)); success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); if (result == 0) { result = success; } ifc_close6(); } return result; #else return 0; #endif }