You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
freshtomato-arm/release/src-rt-6.x.4708/router/rc/dhcp.c

667 lines
19 KiB
C

/*
Copyright 2003, CyberTAN Inc. All Rights Reserved
This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
the contents of this file may not be disclosed to third parties,
copied or duplicated in any form without the prior written
permission of CyberTAN Inc.
This software should be used as a reference only, and it not
intended for production use!
THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
*/
/*
Copyright 2005, Broadcom Corporation
All Rights Reserved.
THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
*/
/*
Modified for Tomato Firmware
Portions, Copyright (C) 2006-2009 Jonathan Zarate
*/
#include "rc.h"
#include <sys/sysinfo.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#define mwanlog(level,x...) if(nvram_get_int("mwan_debug")>=level) syslog(level, x)
static void expires(unsigned int seconds, char *prefix)
{
struct sysinfo info;
char s[32];
char expires_file[256];
sysinfo(&info);
sprintf(s, "%u", (unsigned int)info.uptime + seconds);
memset(expires_file, 0, 256);
sprintf(expires_file, "/var/lib/misc/dhcpc-%s.expires", prefix);
f_write_string(expires_file, s, 0, 0);
}
// copy env to nvram
// returns 1 if new/changed, 0 if not changed/no env
static int env2nv(char *env, char *nv)
{
char *value;
if ((value = getenv(env)) != NULL) {
if (!nvram_match(nv, value)) {
nvram_set(nv, value);
return 1;
}
}
return 0;
}
static int env2nv_gateway(const char *nv)
{
char *v, *g;
char *b;
int r;
r = 0;
if ((v = getenv("router")) != NULL) {
if ((b = strdup(v)) != NULL) {
if ((v = strchr(b, ' ')) != NULL) *v = 0; // truncate multiple entries
if (!nvram_match((char *)nv, b)) {
nvram_set(nv, b);
r = 1;
}
free(b);
}
}
else if ((v = getenv("staticroutes")) != NULL) {
if ((b = strdup(v)) == NULL) return 0;
v = b;
while ((g = strsep(&v, " ")) != NULL) {
if (strcmp(g, "0.0.0.0/0") == 0) {
if ((g = strsep(&v, " ")) && *g) {
if (!nvram_match((char *)nv, g)) {
nvram_set(nv, g);
r = 1;
}
break;
}
}
}
free(b);
}
return r;
}
//static const char renewing[] = "/var/lib/misc/dhcpc.renewing";
static int deconfig(char *ifname,char *prefix)
{
char tmp[100];
TRACE_PT("begin\n");
ifconfig(ifname, IFUP, "0.0.0.0", NULL);
if (using_dhcpc(prefix)) {
nvram_set(strcat_r(prefix, "_ipaddr", tmp), "0.0.0.0");
nvram_set(strcat_r(prefix, "_gateway", tmp), "0.0.0.0");
}
nvram_set(strcat_r(prefix, "_lease", tmp), "0");
nvram_set(strcat_r(prefix, "_routes1", tmp), "");
nvram_set(strcat_r(prefix, "_routes2", tmp), "");
expires(0, prefix);
if (get_wan_proto() == WP_DHCP || get_wan_proto() == WP_LTE) {
nvram_set(strcat_r(prefix, "_netmask", tmp), "0.0.0.0");
nvram_set(strcat_r(prefix, "_gateway_get", tmp), "0.0.0.0");
nvram_set(strcat_r(prefix, "_get_dns", tmp), "");
}
// route_del(ifname, 0, NULL, NULL, NULL);
#ifdef TCONFIG_IPV6
nvram_set("wan_6rd", "");
#endif
TRACE_PT("end\n");
return 0;
}
static int bound(char *ifname, int renew, char *prefix)
{
char tmp [100];
TRACE_PT("begin\n");
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
unlink(renew_file);
char *netmask, *dns;
int wan_proto = get_wanx_proto(prefix);
mwanlog(LOG_INFO, "dhcpc_bound, interface=%s, wan_prefix=%s, renew=%d, proto=%d", ifname, prefix, renew, wan_proto);
dns = nvram_safe_get(strcat_r(prefix, "_get_dns", tmp));
nvram_set(strcat_r(prefix, "_routes1", tmp), "");
nvram_set(strcat_r(prefix, "_routes2", tmp), "");
env2nv("ip", strcat_r(prefix, "_ipaddr", tmp));
env2nv_gateway(strcat_r(prefix, "_gateway", tmp));
env2nv("dns", strcat_r(prefix, "_get_dns", tmp));
env2nv("domain", strcat_r(prefix, "_get_domain", tmp));
env2nv("lease", strcat_r(prefix, "_lease", tmp));
netmask = getenv("subnet") ? : "255.255.255.255";
if (wan_proto == WP_DHCP || wan_proto == WP_LTE) {
nvram_set(strcat_r(prefix, "_netmask", tmp), netmask);
nvram_set(strcat_r(prefix, "_gateway_get", tmp), nvram_safe_get(strcat_r(prefix, "_gateway", tmp)));
}
/* RFC3442: If the DHCP server returns both a Classless Static Routes option
* and a Router option, the DHCP client MUST ignore the Router option.
* Similarly, if the DHCP server returns both a Classless Static Routes
* option and a Static Routes option, the DHCP client MUST ignore the
* Static Routes option.
* Ref: http://www.faqs.org/rfcs/rfc3442.html
*/
/* Classless Static Routes (option 121) */
if (!env2nv("staticroutes", strcat_r(prefix, "_routes1", tmp)))
/* or MS Classless Static Routes (option 249) */
env2nv("msstaticroutes", strcat_r(prefix, "_routes1", tmp));
/* Static Routes (option 33) */
env2nv("routes", strcat_r(prefix, "_routes2", tmp));
expires(atoi(safe_getenv("lease")), prefix);
#ifdef TCONFIG_IPV6
env2nv("ip6rd", "wan_6rd");
#endif
TRACE_PT(strcat_r(prefix, "_ipaddr=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_ipaddr", tmp)));
TRACE_PT(strcat_r(prefix, "_netmask=%s\n", tmp), netmask);
TRACE_PT(strcat_r(prefix, "_gateway=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_gateway", tmp)));
TRACE_PT(strcat_r(prefix, "_get_domain=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_get_domain", tmp)));
TRACE_PT(strcat_r(prefix, "_get_dns=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_get_dns", tmp)));
TRACE_PT(strcat_r(prefix, "_lease=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_lease", tmp)));
TRACE_PT(strcat_r(prefix, "_routes1=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_routes1", tmp)));
TRACE_PT(strcat_r(prefix, "_routes2=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_routes2", tmp)));
#ifdef TCONFIG_IPV6
TRACE_PT("wan_6rd=%s\n", nvram_safe_get("wan_6rd"));
#endif
mwanlog(LOG_DEBUG, "*** bound, %s_ipaddr=%s", prefix, nvram_safe_get(strcat_r(prefix, "_ipaddr", tmp)));
mwanlog(LOG_DEBUG, "*** bound, %s_netmask=%s", prefix, netmask);
mwanlog(LOG_DEBUG, "*** bound, %s_gateway=%s", prefix, nvram_safe_get(strcat_r(prefix, "_gateway", tmp)));
mwanlog(LOG_DEBUG, "*** bound, %s_get_dns=%s", prefix, nvram_safe_get(strcat_r(prefix, "_get_dns", tmp)));
mwanlog(LOG_DEBUG, "*** bound, %s_routes1=%s", prefix, nvram_safe_get(strcat_r(prefix, "_routes1", tmp)));
mwanlog(LOG_DEBUG, "*** bound, %s_routes2=%s", prefix, nvram_safe_get(strcat_r(prefix, "_routes2", tmp)));
mwanlog(LOG_DEBUG, "*** bound, do ifconfig ...");
ifconfig(ifname, IFUP, "0.0.0.0", NULL);
ifconfig(ifname, IFUP, nvram_safe_get(strcat_r(prefix, "_ipaddr", tmp)), netmask);
if (wan_proto != WP_DHCP && wan_proto != WP_LTE) {
char *gw = nvram_safe_get(strcat_r(prefix, "_gateway", tmp));
preset_wan(ifname, gw, netmask, prefix);
/* clear / set dns in the resolv.conf */
nvram_set(strcat_r(prefix, "_get_dns", tmp), renew ? dns : "");
mwanlog(LOG_DEBUG, "*** bound, clear dns from resolv.conf (if not renew)");
switch (wan_proto) {
case WP_PPTP:
start_pptp(BOOT,prefix);
break;
case WP_L2TP:
start_l2tp(prefix);
break;
}
}
else {
mwanlog(LOG_DEBUG,"OUT bound: to start_wan_done, ifname=%s prefix=%s", ifname, prefix);
start_wan_done(ifname,prefix);
}
TRACE_PT("end\n");
return 0;
}
static int renew(char *ifname, char *prefix)
{
char *a;
int changed = 0, routes_changed = 0;
int wan_proto = get_wanx_proto(prefix);
char tmp[100];
TRACE_PT("begin\n");
mwanlog(LOG_INFO, "dhcpc_renew, interface=%s, wan_prefix=%s", ifname, prefix);
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
unlink(renew_file);
if (env2nv("ip", strcat_r(prefix, "_ipaddr", tmp)) ||
env2nv_gateway(strcat_r(prefix, "_gateway", tmp)) ||
(wan_proto == WP_LTE && env2nv("subnet", strcat_r(prefix, "_netmask", tmp))) ||
(wan_proto == WP_DHCP && env2nv("subnet", strcat_r(prefix, "_netmask", tmp)))) {
/* WAN IP or gateway changed, restart/reconfigure everything */
TRACE_PT("end\n");
return bound(ifname, 1, prefix);
}
if (wan_proto == WP_DHCP || wan_proto == WP_LTE) {
changed |= env2nv("domain", strcat_r(prefix, "_get_domain", tmp));
changed |= env2nv("dns", strcat_r(prefix, "_get_dns", tmp));
}
nvram_set(strcat_r(prefix, "_routes1_save", tmp), nvram_safe_get(strcat_r(prefix, "_routes1", tmp)));
nvram_set(strcat_r(prefix, "_routes2_save", tmp), nvram_safe_get(strcat_r(prefix, "_routes2", tmp)));
/* Classless Static Routes (option 121) or MS Classless Static Routes (option 249) */
if (getenv("staticroutes"))
routes_changed |= env2nv("staticroutes", strcat_r(prefix, "_routes1_save", tmp));
else
routes_changed |= env2nv("msstaticroutes", strcat_r(prefix, "_routes1_save", tmp));
/* Static Routes (option 33) */
routes_changed |= env2nv("routes", strcat_r(prefix, "_routes2_save", tmp));
changed |= routes_changed;
if ((a = getenv("lease")) != NULL) {
nvram_set(strcat_r(prefix, "_lease", tmp), a);
expires(atoi(a), prefix);
}
if (changed) {
set_host_domain_name();
start_dnsmasq(); // (re)start
}
if (routes_changed) {
do_wan_routes(ifname, 0, 0, prefix);
nvram_set(strcat_r(prefix, "_routes1", tmp), nvram_safe_get(strcat_r(prefix, "_routes1_save", tmp)));
nvram_set(strcat_r(prefix, "_routes2", tmp), nvram_safe_get(strcat_r(prefix, "_routes2_save", tmp)));
do_wan_routes(ifname, 0, 1, prefix);
}
nvram_unset(strcat_r(prefix, "_routes1_save", tmp));
nvram_unset(strcat_r(prefix, "_routes2_save", tmp));
TRACE_PT(strcat_r(prefix, "_ipaddr=%s\n", tmp), nvram_safe_get(strcat_r(prefix, "_ipaddr", tmp)));
TRACE_PT(strcat_r(prefix, "_netmask=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_netmask", tmp)));
TRACE_PT(strcat_r(prefix, "_gateway=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_gateway", tmp)));
TRACE_PT(strcat_r(prefix, "_get_domain=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_get_domain", tmp)));
TRACE_PT(strcat_r(prefix, "_get_dns=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_get_dns", tmp)));
TRACE_PT(strcat_r(prefix, "_lease=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_lease", tmp)));
TRACE_PT(strcat_r(prefix, "_routes1=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_routes1", tmp)));
TRACE_PT(strcat_r(prefix, "_routes2=%s\n" tmp), nvram_safe_get(strcat_r(prefix, "_routes2", tmp)));
TRACE_PT("end\n");
return 0;
}
int dhcpc_event_main(int argc, char **argv)
{
char *ifname;
ifname = getenv("interface");
char prefix[] = "wanXXXXXXXXXX_";
if (nvram_match( "wan2_ifname", ifname )) strcpy(prefix, "wan2");
#ifdef TCONFIG_MULTIWAN
else if (nvram_match( "wan3_ifname", ifname )) strcpy(prefix, "wan3");
else if (nvram_match( "wan4_ifname", ifname )) strcpy(prefix, "wan4");
#endif
else strcpy(prefix, "wan");
if (!wait_action_idle(10)) return 1;
mwanlog(LOG_INFO, "dhcpc_event_main, interface=%s, wan_prefix=%s, argc=%d, argv=%s", ifname, prefix, argc, argv[1]);
if ((argc == 2) && (ifname = getenv("interface")) != NULL) {
TRACE_PT("event=%s\n", argv[1]);
if (strcmp(argv[1], "deconfig") == 0) return deconfig(ifname, prefix);
if (strcmp(argv[1], "bound") == 0) return bound(ifname, 0, prefix);
if ((strcmp(argv[1], "renew") == 0) || (strcmp(argv[1], "update") == 0)) return renew(ifname,prefix);
}
return 1;
}
// -----------------------------------------------------------------------------
int dhcpc_release_main(int argc, char **argv)
{
char prefix[] = "wanXXXXXXXXXX_";
if(argc > 1){
strcpy(prefix, argv[1]); }
else{
strcpy(prefix, "wan"); }
mwanlog(LOG_INFO, "dhcpc_release_main, argc=%d, wan_prefix=%s", argc, prefix);
TRACE_PT("begin\n");
#ifdef TCONFIG_MULTIWAN
mwan_table_del(prefix);
#endif
if (!using_dhcpc(prefix)) return 1;
char dhcpcpid_file[256];
memset(dhcpcpid_file, 0, 256);
sprintf(dhcpcpid_file, "/var/run/udhcpc-%s.pid", prefix);
if (kill_pidfile_s(dhcpcpid_file, SIGUSR2) == 0) {
sleep(2);
}
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
unlink(renew_file);
char wanconn_file[256];
memset(wanconn_file, 0, 256);
sprintf(wanconn_file, "/var/lib/misc/%s.connecting", prefix);
unlink(wanconn_file);
#ifdef TCONFIG_MULTIWAN
mwan_load_balance();
#endif
TRACE_PT("end\n");
return 0;
}
int dhcpc_renew_main(int argc, char **argv)
{
char prefix[] = "wanXXXXXXXXXX_";
if(argc > 0){
strcpy(prefix, argv[1]); }
else{
strcpy(prefix, "wan"); }
mwanlog(LOG_INFO, "dhcpc_renew_main, argc=%d, wan_prefix=%s", argc, prefix);
TRACE_PT("begin\n");
if (!using_dhcpc(prefix)) return 1;
char dhcpcpid_file[256];
memset(dhcpcpid_file, 0, 256);
sprintf(dhcpcpid_file, "/var/run/udhcpc-%s.pid", prefix);
if (kill_pidfile_s(dhcpcpid_file, SIGUSR1) == 0) {
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
f_write(renew_file, NULL, 0, 0, 0);
}
else {
stop_dhcpc(prefix);
start_dhcpc(prefix);
}
TRACE_PT("end\n");
return 0;
}
// -----------------------------------------------------------------------------
void start_dhcpc(char *prefix)
{
char cmd[256];
char *ifname;
char *p;
int proto;
char tmp[100];
TRACE_PT("begin\n");
nvram_set(strcat_r(prefix, "_get_dns", tmp), "");
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
f_write(renew_file, NULL, 0, 0, 0);
proto = get_wanx_proto(prefix);
if (proto == WP_LTE) {
ifname = nvram_safe_get("wan_4g");
} else {
ifname = nvram_safe_get(strcat_r(prefix, "_ifname", tmp));
}
if (proto == WP_DHCP || proto == WP_LTE) {
nvram_set(strcat_r(prefix, "_iface", tmp), ifname);
}
#if 1 // REMOVEME after 1/1/2012
// temporary code for compatibility with old nvram variables
int changed = 0;
strcpy(cmd, nvram_safe_get("dhcpc_custom"));
if (strstr(cmd, "-V ") == NULL) {
if ((p = nvram_get("dhcpc_vendorclass")) && (*p)) {
changed++;
strcat(cmd, " -V ");
strcat(cmd, p);
}
}
if (strstr(cmd, "-r ") == NULL) {
if ((p = nvram_get("dhcpc_requestip")) && (*p) && (strcmp(p, "0.0.0.0") != 0)) {
changed++;
strcat(cmd, " -r ");
strcat(cmd, p);
}
}
if (changed) {
nvram_set("dhcpc_custom", cmd);
}
#endif
char dhcpcpid_file[256];
memset(dhcpcpid_file, 0, 256);
sprintf(dhcpcpid_file, "/var/run/udhcpc-%s.pid", prefix);
snprintf(cmd, sizeof(cmd),
"udhcpc -i %s -b -s dhcpc-event %s %s %s %s %s %s %s -p %s",
ifname,
nvram_invmatch("wan_hostname", "") ? "-H" : "", nvram_safe_get("wan_hostname"),
// This params required to get static / classless routes from DHCP server
nvram_get_int("dhcp_routes") ? "-O 33 -O 121 -O 249" : "",
nvram_get_int("dhcpc_minpkt") ? "-m" : "",
nvram_contains_word("log_events", "dhcpc") ? "-S" : "",
nvram_safe_get("dhcpc_custom"),
#ifdef TCONFIG_IPV6
(get_ipv6_service() == IPV6_6RD_DHCP) ? "-O ip6rd" : ""
#else
""
#endif
,
dhcpcpid_file
);
mwanlog(LOG_DEBUG, "MultiWAN: start_dhcpc(%s), cmd = \"/bin/sh -c %s\"", prefix, cmd);
xstart("/bin/sh", "-c", cmd);
TRACE_PT("end\n");
}
void stop_dhcpc(char *prefix)
{
TRACE_PT("begin\n");
killall("dhcpc-event", SIGTERM);
char dhcpcpid_file[256];
memset(dhcpcpid_file, 0, 256);
sprintf(dhcpcpid_file, "/var/run/udhcpc-%s.pid", prefix);
if (kill_pidfile_s(dhcpcpid_file, SIGUSR2) == 0) { // release
sleep(2);
}
kill_pidfile_s(dhcpcpid_file, SIGTERM);
unlink(dhcpcpid_file);
char renew_file[256];
memset(renew_file, 0, 256);
sprintf(renew_file, "/var/lib/misc/%s_dhcpc.renewing", prefix);
unlink(renew_file);
TRACE_PT("end\n");
}
// -----------------------------------------------------------------------------
#ifdef TCONFIG_IPV6
int dhcp6c_state_main(int argc, char **argv)
{
char prefix[INET6_ADDRSTRLEN];
char *lanif;
struct in6_addr addr;
int i, r;
TRACE_PT("begin\n");
if (!wait_action_idle(10)) return 1;
lanif = getifaddr(nvram_safe_get("lan_ifname"), AF_INET6, 0);
if (!nvram_match("ipv6_rtr_addr", lanif)) {
nvram_set("ipv6_rtr_addr", lanif);
// extract prefix from configured IPv6 address
if (inet_pton(AF_INET6, nvram_safe_get("ipv6_rtr_addr"), &addr) > 0) {
r = nvram_get_int("ipv6_prefix_length") ? : 64;
for (r = 128 - r, i = 15; r > 0; r -= 8) {
if (r >= 8)
addr.s6_addr[i--] = 0;
else
addr.s6_addr[i--] &= (0xff << r);
}
inet_ntop(AF_INET6, &addr, prefix, sizeof(prefix));
nvram_set("ipv6_prefix", prefix);
}
// (re)start dnsmasq and httpd
set_host_domain_name();
start_dnsmasq();
start_httpd();
}
if (env2nv("new_domain_name_servers", "ipv6_get_dns")) {
dns_to_resolv();
}
TRACE_PT("ipv6_get_dns=%s\n", nvram_safe_get("ipv6_get_dns"));
TRACE_PT("end\n");
return 0;
}
void start_dhcp6c(void)
{
FILE *f;
int prefix_len;
char *wan6face;
char *argv[] = { "dhcp6c", "-T", "LL", NULL, NULL, NULL };
int argc;
int ipv6_vlan;
TRACE_PT("begin\n");
// Check if turned on
if (get_ipv6_service() != IPV6_NATIVE_DHCP) return;
prefix_len = 64 - (nvram_get_int("ipv6_prefix_length") ? : 64);
if (prefix_len < 0)
prefix_len = 0;
wan6face = nvram_safe_get("wan_iface");
ipv6_vlan = nvram_get_int("ipv6_vlan");
nvram_set("ipv6_get_dns", "");
nvram_set("ipv6_rtr_addr", "");
nvram_set("ipv6_prefix", "");
// Create dhcp6c.conf
unlink("/var/dhcp6c_duid");
if ((f = fopen("/etc/dhcp6c.conf", "w"))) {
fprintf(f,
"interface %s {\n", wan6face);
if (nvram_get_int("ipv6_pdonly") == 0) {
fprintf(f,
" send ia-na 0;\n");
};
fprintf(f,
" send ia-pd 0;\n"
" request domain-name-servers;\n"
" script \"/sbin/dhcp6c-state\";\n"
"};\n"
"id-assoc pd 0 {\n"
" prefix ::/%d infinity;\n"
" prefix-interface %s {\n"
" sla-id 0;\n"
" sla-len %d;\n"
" };\n",
nvram_get_int("ipv6_prefix_length"),
nvram_safe_get("lan_ifname"),
prefix_len);
if ((ipv6_vlan & 1) && (prefix_len >= 1)) { //2 ipv6 /64 networks
fprintf(f,
" prefix-interface %s {\n"
" sla-id 1;\n"
" sla-len %d;\n"
" };\n", nvram_safe_get("lan1_ifname"), prefix_len);
};
if ((ipv6_vlan & 2) && (prefix_len >= 2)) { //4 ipv6 /64 networks
fprintf(f,
" prefix-interface %s {\n"
" sla-id 2;\n"
" sla-len %d;\n"
" };\n", nvram_safe_get("lan2_ifname"), prefix_len);
};
if ((ipv6_vlan & 4) && (prefix_len >= 2)) {
fprintf(f,
" prefix-interface %s {\n"
" sla-id 3;\n"
" sla-len %d;\n"
" };\n", nvram_safe_get("lan3_ifname"), prefix_len);
};
fprintf(f,
"};\n"
"id-assoc na 0 { };\n");
fclose(f);
}
argc = 3;
if (nvram_get_int("debug_ipv6"))
argv[argc++] = "-D";
argv[argc++] = wan6face;
argv[argc] = NULL;
_eval(argv, NULL, 0, NULL);
TRACE_PT("end\n");
}
void stop_dhcp6c(void)
{
TRACE_PT("begin\n");
killall("dhcp6c-event", SIGTERM);
killall_tk("dhcp6c");
TRACE_PT("end\n");
}
#endif // TCONFIG_IPV6