void reload_lan_addr6(void) { char *lan_addr6; clear_if_addr6(IFNAME_BR); lan_addr6 = nvram_safe_get("lan_addr6"); if (*lan_addr6) doSystem("ip -6 addr add %s dev %s", lan_addr6, IFNAME_BR); }
void wan6_up(char *wan_ifname) { int ipv6_type, start_radvd_now; char *wan_addr6, *wan_gate6, *wan_addr4; ipv6_type = get_ipv6_type(); if (ipv6_type == IPV6_DISABLED) return; stop_dhcp6c(); build_dns6_var(); control_if_ipv6_dad(IFNAME_BR, 1); start_radvd_now = 1; if (ipv6_type == IPV6_6IN4 || ipv6_type == IPV6_6TO4 || ipv6_type == IPV6_6RD) { wan_addr4 = nvram_safe_get("wan0_ipaddr"); wan_addr6 = nvram_safe_get("wan0_addr6"); start_sit_tunnel(ipv6_type, wan_addr4, wan_addr6); } else { control_if_ipv6_dad(wan_ifname, 1); if (ipv6_type == IPV6_NATIVE_STATIC) { wan_addr6 = nvram_safe_get("wan0_addr6"); wan_gate6 = nvram_safe_get("wan0_gate6"); control_if_ipv6_radv(wan_ifname, 0); clear_if_addr6(wan_ifname); if (*wan_addr6) doSystem("ip -6 addr add %s dev %s", wan_addr6, wan_ifname); if (*wan_gate6) { doSystem("ip -6 route add %s dev %s", wan_gate6, wan_ifname); doSystem("ip -6 route add default via %s metric %d", wan_gate6, 1); } } else { doSystem("ip -6 route add default dev %s metric %d", wan_ifname, 2048); control_if_ipv6_autoconf(wan_ifname, nvram_invmatch("ip6_wan_dhcp", "1")); control_if_ipv6_radv(wan_ifname, 1); /* wait for interface ready */ sleep(2); start_dhcp6c(wan_ifname); if (nvram_match("ip6_lan_auto", "1")) start_radvd_now = 0; } } if (start_radvd_now) reload_radvd(); }
void wan6_down(char *wan_ifname) { int ipv6_type; char *wan6_ifname; ipv6_type = get_ipv6_type(); if (ipv6_type == IPV6_DISABLED) return; stop_radvd(); stop_dhcp6c(); control_if_ipv6_radv(wan_ifname, 0); control_if_ipv6_autoconf(wan_ifname, 0); if (ipv6_type == IPV6_6IN4 || ipv6_type == IPV6_6TO4 || ipv6_type == IPV6_6RD) { wan6_ifname = IFNAME_SIT; if (is_interface_exist(IFNAME_SIT)) doSystem("ip link set dev %s down", IFNAME_SIT); } else { wan6_ifname = wan_ifname; } // clear WAN routes6 clear_if_route6(wan6_ifname); // clear WAN addr6 clear_if_addr6(wan6_ifname); // delete SIT tunnel stop_sit_tunnel(); // clear DNS6 for resolv.conf nvram_set("wan0_dns6", ""); }
void clear_lan_addr6(void) { clear_if_addr6(IFNAME_BR); }
void start_sit_tunnel(int ipv6_type, char *wan_addr4, char *wan_addr6) { int sit_ttl, sit_mtu, size4, size6; char *sit_remote, *sit_relay, *wan_gate6; char addr6s[INET6_ADDRSTRLEN]; struct in_addr addr4; struct in6_addr addr6; size4 = 0; addr4.s_addr = inet_addr_(wan_addr4); if (addr4.s_addr == INADDR_ANY) return; // cannot start SIT tunnel w/o IPv4 WAN addr sit_mtu = nvram_get_int("ip6_sit_mtu"); sit_ttl = nvram_get_int("ip6_sit_ttl"); if (sit_mtu < 1280) sit_mtu = 1280; if (sit_ttl < 1) sit_ttl = 1; if (sit_ttl > 255) sit_ttl = 255; memset(&addr6, 0, sizeof(addr6)); size6 = ipv6_from_string(wan_addr6, &addr6); if (size6 < 0) size6 = 0; sit_relay = ""; sit_remote = "any"; if (ipv6_type == IPV6_6IN4) sit_remote = nvram_safe_get("ip6_6in4_remote"); if (is_interface_exist(IFNAME_SIT)) doSystem("ip tunnel del %s", IFNAME_SIT); doSystem("ip tunnel %s %s mode sit remote %s local %s ttl %d", "add", IFNAME_SIT, sit_remote, wan_addr4, sit_ttl); if (ipv6_type == IPV6_6TO4) { size6 = 16; memset(&addr6, 0, sizeof(addr6)); addr6.s6_addr16[0] = htons(0x2002); ipv6_to_ipv4_map(&addr6, size6, &addr4, 0); addr6.s6_addr16[7] = htons(0x0001); sit_relay = nvram_safe_get("ip6_6to4_relay"); } else if (ipv6_type == IPV6_6RD) { struct in_addr net4; struct in6_addr net6; char sit_6rd_prefix[INET6_ADDRSTRLEN], sit_6rd_relay_prefix[32]; memcpy(&net6, &addr6, sizeof(addr6)); ipv6_to_net(&net6, size6); inet_ntop(AF_INET6, &net6, sit_6rd_prefix, INET6_ADDRSTRLEN); sprintf(sit_6rd_prefix, "%s/%d", sit_6rd_prefix, size6); strcpy(sit_6rd_relay_prefix, "0.0.0.0/0"); size4 = nvram_get_int("wan0_6rd_size"); if (size4 > 0 && size4 <= 32) { net4.s_addr = addr4.s_addr & htonl(0xffffffffUL << (32 - size4)); sprintf(sit_6rd_relay_prefix, "%s/%d", inet_ntoa(net4), size4); } doSystem("ip tunnel 6rd dev %s 6rd-prefix %s 6rd-relay_prefix %s", IFNAME_SIT, sit_6rd_prefix, sit_6rd_relay_prefix); ipv6_to_ipv4_map(&addr6, size6, &addr4, size4); addr6.s6_addr16[7] = htons(0x0001); sit_relay = nvram_safe_get("wan0_6rd_relay"); } // WAN IPv6 address inet_ntop(AF_INET6, &addr6, addr6s, INET6_ADDRSTRLEN); if (size6 > 0) sprintf(addr6s, "%s/%d", addr6s, size6); control_if_ipv6_radv(IFNAME_SIT, 0); doSystem("ip link set mtu %d dev %s up", sit_mtu, IFNAME_SIT); control_if_ipv6(IFNAME_SIT, 1); clear_if_addr6(IFNAME_SIT); doSystem("ip -6 addr add %s dev %s", addr6s, IFNAME_SIT); /* WAN IPv6 gateway (auto-generate for 6to4/6rd) */ if (ipv6_type == IPV6_6TO4 || ipv6_type == IPV6_6RD) { sprintf(addr6s, "::%s", sit_relay); wan_gate6 = addr6s; /* add direct default gateway for workaround "No route to host" on new kernel */ doSystem("ip -6 route add default dev %s metric %d", IFNAME_SIT, 2048); } else { wan_gate6 = nvram_safe_get("wan0_gate6"); } if (*wan_gate6) doSystem("ip -6 route add default via %s dev %s metric %d", wan_gate6, IFNAME_SIT, 1); /* LAN IPv6 address (auto-generate for 6to4/6rd) */ if (ipv6_type == IPV6_6TO4 || ipv6_type == IPV6_6RD) { memset(&addr6, 0, sizeof(addr6)); if (ipv6_type == IPV6_6TO4) { addr6.s6_addr16[0] = htons(0x2002); ipv6_to_ipv4_map(&addr6, 16, &addr4, 0); addr6.s6_addr16[3] = htons(0x0001); addr6.s6_addr16[7] = htons(0x0001); } else { ipv6_from_string(wan_addr6, &addr6); ipv6_to_ipv4_map(&addr6, size6, &addr4, size4); addr6.s6_addr16[7] = htons(0x0001); } inet_ntop(AF_INET6, &addr6, addr6s, INET6_ADDRSTRLEN); sprintf(addr6s, "%s/%d", addr6s, 64); clear_if_addr6(IFNAME_BR); doSystem("ip -6 addr add %s dev %s", addr6s, IFNAME_BR); store_lan_addr6(addr6s); } }