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/wan.c

1450 lines
44 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
* Fixes/updates (C) 2018 - 2023 pedro
*
*/
#include "rc.h"
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <sys/sysinfo.h>
#include <time.h>
#include <bcmdevs.h>
#include <linux/sockios.h>
#include <linux/if_vlan.h>
/* needed by logmsg() */
#define LOGMSG_DISABLE DISABLE_SYSLOG_OSM
#define LOGMSG_NVDEBUG "wan_debug"
static int config_pppd(int wan_proto, int num, char *prefix)
{
FILE *fp;
#ifdef TCONFIG_USB
FILE *cfp;
#endif
char *p;
int demand;
char tmp[100];
mkdir("/tmp/ppp", 0777);
symlink("/dev/null", "/tmp/ppp/connect-errors");
symlink("/sbin/rc", "/tmp/ppp/ip-up");
symlink("/sbin/rc", "/tmp/ppp/ip-down");
symlink("/sbin/rc", "/tmp/ppp/ip-pre-up");
#ifdef TCONFIG_IPV6
symlink("/sbin/rc", "/tmp/ppp/ipv6-up");
symlink("/sbin/rc", "/tmp/ppp/ipv6-down");
#endif
demand = nvram_get_int(strlcat_r(prefix, "_ppp_demand", tmp, sizeof(tmp)));
/* Generate options file */
char ppp_optfile[256];
memset(ppp_optfile, 0, sizeof(ppp_optfile));
snprintf(ppp_optfile, sizeof(ppp_optfile), "/tmp/ppp/%s_options", prefix);
if ((fp = fopen(ppp_optfile, "w")) == NULL) {
logerr(__FUNCTION__, __LINE__, ppp_optfile);
return -1;
}
#ifdef TCONFIG_USB
if (wan_proto != WP_PPP3G)
#endif
fprintf(fp, "user \"%s\"\n" /* Don't rely on pap/chap secrets (useless) */
"password \"%s\"\n" /* Don't rely on pap/chap secrets (useless) */
"lcp-echo-adaptive\n", /* Suppress LCP echo-requests if traffic was received */
nvram_safe_get(strlcat_r(prefix, "_ppp_username", tmp, sizeof(tmp))),
nvram_safe_get(strlcat_r(prefix, "_ppp_passwd", tmp, sizeof(tmp))));
fprintf(fp, "unit %d\n" /* unit as WAN NUM, let's try to have persistent names */
"linkname %s\n" /* link name for WAN ID */
"defaultroute\n" /* Add a default route to the system routing tables, using the peer as the gateway */
"usepeerdns\n" /* Ask the peer for up to 2 DNS server addresses */
"default-asyncmap\n" /* Disable asyncmap negotiation */
"novj\n" /* Disable Van Jacobson style TCP/IP header compression */
"nobsdcomp\n" /* Disable BSD-Compress compression */
"nodeflate\n" /* Disable Deflate compression */
"noauth\n" /* Do not authenticate peer */
"refuse-eap\n" /* Do not use eap */
"maxfail 0\n" /* Never give up */
"lcp-echo-interval %d\n" /* Interval between LCP echo-requests */
"lcp-echo-failure %d\n" /* Tolerance to unanswered echo-requests */
"%s", /* Debug */
num,
prefix,
nvram_get_int(strlcat_r(prefix, "_pppoe_lei", tmp, sizeof(tmp))) ? : 10,
nvram_get_int(strlcat_r(prefix, "_pppoe_lef", tmp, sizeof(tmp))) ? : 5,
nvram_get_int("debug_ppp") ? "debug\n" : "");
#ifdef TCONFIG_USB
if (wan_proto == WP_PPP3G && nvram_match(strlcat_r(prefix, "_modem_dev", tmp, sizeof(tmp)), "ttyACM0")) {
/* Don't write nopcomp and noaccomp options */
}
else
#endif
fprintf(fp, "nopcomp\n" /* Disable protocol field compression */
"noaccomp\n"); /* Disable Address/Control compression */
if (wan_proto != WP_L2TP)
fprintf(fp, "persist\n" /* Keep on reopening connection after close */
"holdoff %d\n", /* Set time in seconds before retrying connection */
demand ? 30 : (nvram_get_int(strlcat_r(prefix, "_ppp_redialperiod", tmp, sizeof(tmp))) ? : 30));
switch (wan_proto) {
case WP_PPTP:
fprintf(fp, "plugin pptp.so\n"
"pptp_server %s\n"
"nomppe-stateful\n" /* disallow MPPE stateful mode */
"require-mschap-v2\n" /* Require MS-CHAPv2 authentication from peer */
"noauth\n" /* No authenticate peer (i dunno why it doesn't apply from shared params) */
"mtu %d\n",
nvram_safe_get(strlcat_r(prefix, "_pptp_server_ip", tmp, sizeof(tmp))),
(nvram_get_int(strlcat_r(prefix, "_mtu_enable", tmp, sizeof(tmp))) ? nvram_get_int(strlcat_r(prefix, "_wan_mtu", tmp, sizeof(tmp))) : 1400));
break;
case WP_PPPOE:
fprintf(fp, "plugin rp-pppoe.so\n"
"nomppe\n" /* don't allow MPPE encryption */
"nic-%s\n"
"mru %d mtu %d\n",
nvram_safe_get(strlcat_r(prefix, "_ifname", tmp, sizeof(tmp))),
nvram_get_int(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp))),
nvram_get_int(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp))));
if ((p = nvram_safe_get(strlcat_r(prefix, "_ppp_service", tmp, sizeof(tmp)))) && (*p))
fprintf(fp, "rp_pppoe_service '%s'\n", p);
if ((p = nvram_safe_get(strlcat_r(prefix, "_ppp_ac", tmp, sizeof(tmp)))) && (*p))
fprintf(fp, "rp_pppoe_ac '%s'\n", p);
if (nvram_match(strlcat_r(prefix, "_ppp_mlppp", tmp, sizeof(tmp)), "1"))
fprintf(fp, "mp\n"); /* Enable multilink operation */
break;
#ifdef TCONFIG_USB
case WP_PPP3G: ;
/* Generate chat file */
char ppp3g_chatfile[256];
memset(ppp3g_chatfile, 0, sizeof(ppp3g_chatfile));
snprintf(ppp3g_chatfile, sizeof(ppp3g_chatfile), "/tmp/ppp/%s_connect.chat", prefix);
if ((cfp = fopen(ppp3g_chatfile, "w")) == NULL) {
logerr(__FUNCTION__, __LINE__, ppp3g_chatfile);
return -1;
}
fprintf(cfp, "ABORT \"NO CARRIER\"\n"
"ABORT \"NO DIALTONE\"\n"
"ABORT \"NO DIAL TONE\"\n"
"ABORT \"NO ERROR\"\n"
"ABORT \"NO ANSWER\"\n"
"ABORT \"BUSY\"\n"
"ABORT \"VOICE\"\n"
"ABORT \"DELAYED\"\n"
"REPORT CONNECT\n"
"TIMEOUT 10\n"
"\"\" \"AT\"\n"
"OK \"AT&FE0V1X1&D2&C1S0=0\"\n"
"OK \"AT\"\n"
"OK \"ATS0=0\"\n"
"OK \"AT\"\n"
"OK \"AT&FE0V1X1&D2&C1S0=0\"\n"
"OK \"AT\"\n");
/* Only send the AT+CGDCONT (define PDP context) command to set
* the APN if modem_apn is defined and non-empty. Some ISPs
* (ex. BSNL EVDO in India) don't need this (the modem returns
* ERROR if issued).
*/
if ((p = nvram_safe_get(strlcat_r(prefix, "_modem_apn", tmp, sizeof(tmp)))) && (*p))
fprintf(cfp, "OK 'AT+CGDCONT=1,\"IP\",\"%s\"'\n", p);
fprintf(cfp, "OK \"ATDT%s\"\n"
"TIMEOUT 30\n"
"CONNECT \\c\n",
nvram_safe_get(strlcat_r(prefix, "_modem_init", tmp, sizeof(tmp))));
fclose(cfp);
/* Add to options file */
fprintf(fp, "%s\n"
"460800\n"
"connect \"/usr/sbin/chat %s -t 30 -f %s\"\n"
"noipdefault\n" /* Don't use name for default IP adrs */
"lock\n" /* Lock the modem device, to avoid another process trying to use it */
"crtscts\n" /* Use hardware flow-control between the computer and the modem, to avoid data loss */
"modem\n" /* Use the modem control lines */
"ipcp-accept-local\n", /* Accept peer's address for us */
nvram_safe_get(strlcat_r(prefix, "_modem_dev", tmp, sizeof(tmp))),
nvram_get_int("debug_ppp") ? "-v" : "-V",
ppp3g_chatfile);
if (strlen(nvram_get(strlcat_r(prefix, "_ppp_username", tmp, sizeof(tmp)))) > 0)
fprintf(fp, "user \"%s\"\n", nvram_get(strlcat_r(prefix, "_ppp_username", tmp, sizeof(tmp))));
if (strlen(nvram_get(strlcat_r(prefix, "_ppp_passwd", tmp, sizeof(tmp)))) > 0)
fprintf(fp, "password \"%s\"\n", nvram_get(strlcat_r(prefix, "_ppp_passwd", tmp, sizeof(tmp))));
/* Clear old gateway */
if (strlen(nvram_safe_get(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)))) > 0)
nvram_set(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)), "");
/* Detect 3G Modem */
if (!nvram_get_int("g_upgrade") && !nvram_get_int("g_reboot"))
xstart("switch3g", prefix);
break;
#endif
case WP_L2TP:
fprintf(fp, "nomppe\n"); /* don't allow MPPE encryption */
if (nvram_get_int(strlcat_r(prefix, "_mtu_enable", tmp, sizeof(tmp))))
fprintf(fp, "mtu %d\n", nvram_get_int(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp))));
break;
}
if (demand) {
/* Demand mode */
if (wan_proto != WP_L2TP)
fprintf(fp, "demand\n" /* Dial on demand */
"idle %d\n", /* Disconnect if the link is idle for n seconds */
nvram_get_int(strlcat_r(prefix, "_ppp_idletime", tmp, sizeof(tmp))) * 60);
fprintf(fp, "ipcp-accept-remote\n" /* Force to accept the peer's idea of its (remote) IP address */
"ipcp-accept-local\n" /* Force to accept the peer's idea of local IP address */
"noipdefault\n" /* Disables the default behaviour when no local IP address is specified (request from peer) */
"ktune\n"); /* Set /proc/sys/net/ipv4/ip_dynaddr to 1 in demand mode if the local address changes */
}
#ifdef TCONFIG_IPV6
/* start/add IPv6 BUT only for "wan" (no multiwan support) */
if (strcmp(prefix, "wan") == 0) { /* check for "wan" prefix */
switch (get_ipv6_service()) {
case IPV6_NATIVE:
case IPV6_NATIVE_DHCP:
fprintf(fp, "+ipv6\n");
break;
}
}
#endif
/* User specific options */
fprintf(fp, "%s\n", nvram_safe_get(strlcat_r(prefix, "_ppp_custom", tmp, sizeof(tmp))));
fclose(fp);
return 0;
}
static void stop_ppp(char *prefix)
{
char buffer[64];
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "/tmp/ppp/%s_link", prefix);
unlink(buffer);
/* Fix switching wan type from UI error (stale options file) */
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "/tmp/ppp/%s_options", prefix);
unlink(buffer);
memset(buffer, 0, sizeof(buffer));
snprintf(buffer, sizeof(buffer), "pppd%s", prefix);
/* Race condition on start_pppoe in ip-up on boot, primary pp(poe/tp) wan will not reach start_wan_done on secondary ppp(oe/3g) start */
//killall_tk_period_wait("ip-up", 50);
//killall_tk_period_wait("ip-pre-up", 50);
//killall_tk_period_wait("ip-down", 50);
#ifdef TCONFIG_IPV6
//killall_tk_period_wait("ipv6-up", 50);
//killall_tk_period_wait("ipv6-down", 50);
#endif
/* FIXME: find a proper way to stop daemon */
if (get_wanx_proto("wan") != WP_L2TP
&& get_wanx_proto("wan2") != WP_L2TP
#ifdef TCONFIG_MULTIWAN
&& get_wanx_proto("wan3") != WP_L2TP
&& get_wanx_proto("wan4") != WP_L2TP
#endif
)
killall_tk_period_wait("xl2tpd", 50);
//kill(nvram_get_int(strlcat_r(prefix, "_pppd_pid", tmp, sizeof(tmp))),1);
killall_tk_period_wait((char *)buffer, 50);
/* Don't kill other wans listeners, only this wan one
* its PID can be found in /var/run/listen-wan%d.pid
*/
//killall_tk_period_wait("listen", 50);
/* WAN LED control */
wan_led_off(prefix); /* LED OFF? */
}
static void run_pppd(char *prefix)
{
char tmp[100];
char pppd_path[256];
char ppp_optfile[256];
memset(pppd_path, 0, sizeof(pppd_path));
snprintf(pppd_path, sizeof(pppd_path), "/tmp/ppp/pppd%s", prefix);
memset(ppp_optfile, 0, sizeof(ppp_optfile));
snprintf(ppp_optfile, sizeof(ppp_optfile), "/tmp/ppp/%s_options", prefix);
symlink("/usr/sbin/pppd", pppd_path);
eval(pppd_path, "file", ppp_optfile);
if (nvram_get_int(strlcat_r(prefix, "_ppp_demand", tmp, sizeof(tmp)))) { /* Demand mode */
/*
* Fixed issue id 7887(or 7787):
* When DUT is PPTP Connect on Demand mode, it couldn't be trigger from LAN.
*/
stop_dnsmasq();
dns_to_resolv();
start_dnsmasq();
/* Trigger Connect On Demand if user ping pptp server IP or WAN IP */
eval("listen", nvram_safe_get("lan_ifname"), prefix);
}
else { /* Keepalive mode */
start_redial(prefix);
}
}
inline void stop_pptp(char *prefix)
{
stop_ppp(prefix);
}
void start_pptp(char *prefix)
{
int num = 0; /* wan */
if (!strcmp(prefix,"wan2")) num = 1;
#ifdef TCONFIG_MULTIWAN
else if (!strcmp(prefix,"wan3")) num = 2;
else if (!strcmp(prefix,"wan4")) num = 3;
#endif
if (!using_dhcpc(prefix))
stop_dhcpc(prefix);
stop_pptp(prefix);
if (config_pppd(WP_PPTP, num, prefix) != 0)
return;
run_pppd(prefix);
}
/* Used by PPTP/L2TP mainly to setup host routes to DNS and access server */
void preset_wan(char *ifname, char *gw, char *netmask, char *prefix)
{
struct in_addr ipaddr;
char tmp[100];
char word[100], *next;
int i, ret;
int proto;
int mwan_num;
mwan_num = nvram_get_int("mwan_num");
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
mwan_num = 1;
if (mwan_num == 1) {
/* Delete default route */
route_del(ifname, 0, NULL, NULL, NULL);
/* Set default route to gateway if specified */
i = 5;
while ((ret = route_add(ifname, 1, "0.0.0.0", gw, "0.0.0.0") != 0) && (i--)) {
sleep(1);
}
}
/* Try adding a host route to gateway first */
route_add(ifname, 0, gw, NULL, "255.255.255.255");
/* Add routes to dns servers as well for demand ppp to work */
in_addr_t mask = inet_addr(netmask);
foreach(word, nvram_safe_get(strlcat_r(prefix, "_get_dns", tmp, sizeof(tmp))), next) {
if ((inet_addr(word) & mask) != (inet_addr(nvram_safe_get(strlcat_r(prefix, "_ipaddr", tmp, sizeof(tmp)))) & mask))
route_add(ifname, 0, word, gw, "255.255.255.255");
}
/* Add routes to PPTP/L2TP servers for load-balanced WAN setups will work.
* Without it, if there is other WAN active, xl2tpd / pptp tries to connect
* to l2tp/pptp server not via WAN's gateway, but setup route via existing
* Internet connection (other WAN gw or default) so never reached server.
* NB! l2/pptp_server_ip can be hostname also, so route will not be added
*/
proto = get_wanx_proto(prefix);
if (proto == WP_PPTP) {
if (inet_pton(AF_INET, nvram_safe_get(strlcat_r(prefix, "_pptp_server_ip", tmp, sizeof(tmp))), &(ipaddr.s_addr)))
route_add(ifname, 0, nvram_safe_get(strlcat_r(prefix, "_pptp_server_ip", tmp, sizeof(tmp))), gw, "255.255.255.255");
}
if (proto == WP_L2TP) {
if (inet_pton(AF_INET, nvram_safe_get(strlcat_r(prefix, "_l2tp_server_ip", tmp, sizeof(tmp))), &(ipaddr.s_addr)))
route_add(ifname, 0, nvram_safe_get(strlcat_r(prefix, "_l2tp_server_ip", tmp, sizeof(tmp))), gw, "255.255.255.255");
}
/* FIXME! why only on primary WAN?
* All PPTP / L2TP need working DNS
* to resolve access server IP
*/
//if (!strcmp(prefix, "wan")) {
stop_dnsmasq();
dns_to_resolv();
start_dnsmasq();
sleep(1);
/* issue with call from dhcp.c bound (it didn't do start_ppxxx on startup) on primary WAN! so disabled here */
//start_firewall();
//}
}
/* Get the IP, subnetmask, gaeway from WAN ppp interface in demand mode and set nvram */
static void start_tmp_ppp(int num, char *ifname, char *prefix)
{
struct ifreq ifr;
char tmp[100];
int timeout;
int s;
/* wtf? only on primary wan? */
//if (num != 0) return;
/* Wait for ppp0 to be created */
timeout = 15;
while ((ifconfig(ifname, IFUP, NULL, NULL) != 0) && (timeout-- > 0)) {
sleep(1);
}
if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
return;
strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
/* Set temporary IP address */
timeout = 3;
while (ioctl(s, SIOCGIFADDR, &ifr) && timeout--) {
sleep(1);
}
if (!using_dhcpc(prefix)) {
nvram_set(strlcat_r(prefix, "_ipaddr", tmp, sizeof(tmp)), inet_ntoa(sin_addr(&(ifr.ifr_addr))));
nvram_set(strlcat_r(prefix, "_netmask", tmp, sizeof(tmp)), "255.255.255.255");
}
else /* Don't overwrite netmask and set proper IP for PPP+DHCP wan */
nvram_set(strlcat_r(prefix, "_ppp_get_ip", tmp, sizeof(tmp)), inet_ntoa(sin_addr(&(ifr.ifr_addr))));
/* Get temporary P-t-P address */
timeout = 3;
while (ioctl(s, SIOCGIFDSTADDR, &ifr) && timeout--) {
sleep(1);
}
/* UI and listen / connect scripts se wan_gateway() which return gateway_get */
if (!using_dhcpc(prefix)) {
nvram_set(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)), inet_ntoa(sin_addr(&(ifr.ifr_dstaddr))));
nvram_set(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp)), inet_ntoa(sin_addr(&(ifr.ifr_dstaddr))));
}
else
nvram_set(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp)), inet_ntoa(sin_addr(&(ifr.ifr_dstaddr))));
close(s);
start_wan_done(ifname, prefix);
}
void start_pppoe(int num, char *prefix)
{
char pppname[8] = "";
char tmp[100];
if (num < 0 || num > 3)
return;
stop_pppoe(prefix);
#ifdef TCONFIG_USB
if (nvram_match(strlcat_r(prefix, "_proto", tmp, sizeof(tmp)), "ppp3g")) {
if (config_pppd(WP_PPP3G, num, prefix) != 0)
return;
}
else {
#endif
if (config_pppd(WP_PPPOE, num, prefix) != 0)
return;
#ifdef TCONFIG_USB
}
#endif
run_pppd(prefix);
snprintf(pppname, sizeof(pppname), "ppp%d", num); /* Control by "unit" ppp options param */
if (strcmp(pppname, "none") && strcmp(pppname, "")) { /* Got interface */
/* Run in demand mode only if interface exists and not for L2TP wan */
if (nvram_get_int(strlcat_r(prefix, "_ppp_demand", tmp, sizeof(tmp))) && !nvram_match(strlcat_r(prefix, "_proto", tmp, sizeof(tmp)), "l2tp"))
start_tmp_ppp(num, pppname, prefix);
else
ifconfig(pppname, IFUP, NULL, NULL);
}
}
void stop_pppoe(char *prefix)
{
stop_ppp(prefix);
}
static int config_l2tp(void) /* shared xl2tpd.conf for all WAN */
{
FILE *fp;
int i;
int demand;
char xl2tp_file[256];
char tmp[100];
const char *names[] = {
"wan",
"wan2",
#ifdef TCONFIG_MULTIWAN
"wan3",
"wan4",
#endif
NULL
};
/* Generate XL2TPD configuration file */
memset(xl2tp_file, 0, sizeof(xl2tp_file));
snprintf(xl2tp_file, sizeof(xl2tp_file), "/etc/xl2tpd.conf");
if ((fp = fopen(xl2tp_file, "w")) == NULL) {
logerr(__FUNCTION__, __LINE__, xl2tp_file);
return -1;
}
/* GLOBAL */
fprintf(fp, "[global]\n"
"access control = no\n"
"port = 1701\n"
"debug avp = no\n"
"debug network = no\n"
"debug packet = no\n"
"debug state = no\n"
"debug tunnel = no\n"
"\n");
/* LACS */
for (i = 0; names[i] != NULL; ++i) {
if (!strcmp(nvram_safe_get(strlcat_r(names[i], "_proto", tmp, sizeof(tmp))), "l2tp")) {
demand = nvram_get_int(strlcat_r(names[i], "_ppp_demand", tmp, sizeof(tmp)));
char ppp_optfile[256];
memset(ppp_optfile, 0, sizeof(ppp_optfile));
snprintf(ppp_optfile, sizeof(ppp_optfile), "/tmp/ppp/%s_options", names[i]);
fprintf(fp, "[lac %s]\n"
"lns = %s\n"
"bps = 1000000000\n" /* 1 gbit to both tx/rx */
"tunnel rws = 8\n"
"pppoptfile = %s\n"
"autodial = no\n"
"redial = %s\n"
"max redials = 32767\n"
"redial timeout = %d\n"
"ppp debug = %s\n"
"%s\n",
names[i], /* LAC name */
nvram_safe_get(strlcat_r(names[i], "_l2tp_server_ip", tmp, sizeof(tmp))),
ppp_optfile,
demand ? "no" : "yes",
nvram_get_int(strlcat_r(names[i], "_ppp_redialperiod", tmp, sizeof(tmp))) ? : 30,
nvram_get_int("debug_ppp") ? "yes" : "no",
nvram_safe_get(strlcat_r(names[i], "_xl2tpd_custom", tmp, sizeof(tmp))));
memset(xl2tp_file, 0, sizeof(xl2tp_file));
snprintf(xl2tp_file, sizeof(xl2tp_file), "/etc/%s_xl2tpd.custom", names[i]);
fappend(fp, xl2tp_file);
}
}
fclose(fp);
return 0;
}
inline void stop_l2tp(char *prefix)
{
char l2tp_file[64];
char dconnects[64];
memset(l2tp_file, 0, sizeof(l2tp_file));
snprintf(l2tp_file, sizeof(l2tp_file), "/var/run/l2tp-control");
memset(dconnects, 0, sizeof(dconnects));
snprintf(dconnects, sizeof(dconnects), "d %s", prefix);
f_write_string(l2tp_file, dconnects, 0, 0); /* Disconnect current session first */
sleep(1); /* Wait ip-down scripts to finish graceful */
stop_ppp(prefix); /* Unlink ppp files in /tmp/ppp (used by mwan.c) and stop daemon */
}
void start_l2tp(char *prefix)
{
char tmp[100];
int demand;
if (!using_dhcpc(prefix)) /* As for PPTP */
stop_dhcpc(prefix);
//stop_l2tp(prefix);
if (config_l2tp() != 0) /* Generate L2TP daemon config */
return;
int num = 0; /* wan */
if (!strcmp(prefix,"wan2")) num = 1;
#ifdef TCONFIG_MULTIWAN
else if (!strcmp(prefix,"wan3")) num = 2;
else if (!strcmp(prefix,"wan4")) num = 3;
#endif
if (config_pppd(WP_L2TP, num, prefix) != 0) /* ppp options */
return;
demand = nvram_get_int(strlcat_r(prefix, "_ppp_demand", tmp, sizeof(tmp)));
enable_ip_forward();
eval("xl2tpd", "-c", "/etc/xl2tpd.conf");
if (demand) /* Listen LAN for ping to l2tp server IP, see listen.c */
eval("listen", nvram_safe_get("lan_ifname"), prefix);
else
force_to_dial(prefix); /* Force connect via l2tp-control */
}
char *wan_gateway(char *prefix)
{
char tmp[100];
char *gw = nvram_safe_get(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp)));
if ((*gw == 0) || (strcmp(gw, "0.0.0.0") == 0))
gw = nvram_safe_get(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)));
return gw;
}
/* Trigger connect on demand */
void force_to_dial(char *prefix)
{
char l2tp_file[64];
char connects[64];
char dgw[64];
memset(dgw, 0, sizeof(dgw));
snprintf(dgw, sizeof(dgw), "10.112.112.%d", 111 + get_wan_unit(prefix)); /* 10.112.112.112-115 for ppp0-3 */
sleep(1);
switch (get_wanx_proto(prefix)) {
case WP_L2TP:
memset(l2tp_file, 0, sizeof(l2tp_file));
snprintf(l2tp_file, sizeof(l2tp_file), "/var/run/l2tp-control");
memset(connects, 0, sizeof(connects));
snprintf(connects, sizeof(connects), "c %s", prefix);
f_write_string(l2tp_file, connects, 0, 0);
break;
case WP_PPTP:
eval("ping", "-c", "2", dgw);
break;
case WP_DISABLED:
case WP_STATIC:
break;
default:
eval("ping", "-c", "2", (strcmp(wan_gateway(prefix),"") != 0 && strcmp(wan_gateway(prefix),"0.0.0.0") != 0) ? wan_gateway(prefix) : dgw);
break;
}
}
static void _do_wan_routes(char *ifname, char *nvname, int metric, int add)
{
char *routes, *tmp;
int bits;
struct in_addr mask;
char netmask[16];
/* IP[/MASK] ROUTER IP2[/MASK2] ROUTER2 ... */
tmp = routes = strdup(nvram_safe_get(nvname));
while (tmp && *tmp) {
char *ipaddr, *gateway, *nmask;
ipaddr = nmask = strsep(&tmp, " ");
memset(netmask, 0, sizeof(netmask));
strlcpy(netmask, "255.255.255.255", sizeof(netmask));
if (nmask) {
ipaddr = strsep(&nmask, "/");
if (nmask && *nmask) {
bits = strtol(nmask, &nmask, 10);
if (bits >= 1 && bits <= 32) {
mask.s_addr = htonl(0xffffffff << (32 - bits));
memset(netmask, 0, sizeof(netmask));
strlcpy(netmask, inet_ntoa(mask), sizeof(netmask));
}
}
}
gateway = strsep(&tmp, " ");
if (gateway && *gateway) {
if (add)
route_add(ifname, metric, ipaddr, gateway, netmask);
else
route_del(ifname, metric, ipaddr, gateway, netmask);
}
}
free(routes);
}
void do_wan_routes(char *ifname, int metric, int add, char *prefix)
{
char tmp[100];
if (nvram_get_int("dhcpc_121")) {
/* Classless Static Routes: IP/MASK ROUTER IP2/MASK2 ROUTER2 ... */
memset(tmp, 0, sizeof(tmp));
_do_wan_routes(ifname, strlcat_r(prefix, "_routes1", tmp, sizeof(tmp)), metric, add);
}
if (nvram_get_int("dhcpc_33")) {
/* Static Routes: IP ROUTER IP2 ROUTER2 ... */
memset(tmp, 0, sizeof(tmp));
_do_wan_routes(ifname, strlcat_r(prefix, "_routes2", tmp, sizeof(tmp)), metric, add);
}
}
void create_wanx_mac(char *prefix, int mac_plus)
{
char buffer[32] = { 0 };
char nvtmp[16];
snprintf(buffer, sizeof(buffer), "%s", nvram_safe_get("lan_hwaddr")); /* get LAN MAC address (usually et0) */
inc_mac(buffer, mac_plus, sizeof(buffer)); /* MAC + value for wanX */
nvram_set(strlcat_r(prefix, "_mac", nvtmp, sizeof(nvtmp)), buffer); /* save it to nvram */
logmsg(LOG_INFO, "Create and save wanX mac address - WAN: %s - Address: %s", prefix, buffer);
}
void store_wan_if_to_nvram(char *prefix)
{
char *p = NULL;
char *w = NULL;
char buf[64];
int wan_unit;
int vid;
int vid_map;
#if !defined(CONFIG_BCMWL6) && !defined(TCONFIG_BLINK) /* only mips RT branch */
int vlan0tag = nvram_get_int("vlan0tag");
#endif
char tmp[64];
char *nvvar = NULL;
wan_unit = get_wan_unit(prefix);
if (strcmp(nvram_safe_get(strlcat_r(prefix, "_sta", tmp, sizeof(tmp))), "") == 0) {
/* vlan ID mapping */
p = nvram_safe_get(strlcat_r(prefix, "_ifnameX", tmp, sizeof(tmp)));
if (sscanf(p, "vlan%d", &vid) == 1) {
snprintf(buf, sizeof(buf), "vlan%dvid", vid);
vid_map = nvram_get_int(buf);
if ((vid_map < 1) || (vid_map > 4094)) {
#if !defined(CONFIG_BCMWL6) && !defined(TCONFIG_BLINK) /* only mips RT branch */
vid_map = vlan0tag | vid;
#else
vid_map = vid;
#endif
}
snprintf(buf, sizeof(buf), "vlan%d", vid_map);
p = buf;
}
/* Set wan mac on vlan (but not for wireless client) */
nvvar = nvram_get(strlcat_r(prefix, "_mac", tmp, sizeof(tmp)));
/* check if we have a wanX mac? FT user could/can define one ... if not, create it (default);
* Increase mac address and keep distance to et0 mac --> We need it for working VLAN setups! (PPPoE);
* Set wanX macs after wl VIFs
* wan --> et0 mac +16
* wan2 --> et0 mac +17
* wan3 --> et0 mac +18
* wan4 --> et0 mac +19
* Info: sync GUI def-mac - see www/advanced-mac.asp
*/
if ((nvvar == NULL) ||
(nvvar && !strlen(nvvar))) {
create_wanx_mac(prefix, (wan_unit + 15));
}
set_mac(p, tmp, (wan_unit + 15));
}
else { /* Wireless client as wan */
w = nvram_safe_get(strlcat_r(prefix, "_sta", tmp, sizeof(tmp)));
p = nvram_safe_get(strlcat_r(w, "_ifname", tmp, sizeof(tmp)));
}
/* Store interface name to nvram */
nvram_set(strlcat_r(prefix, "_ifname", tmp, sizeof(tmp)), p);
nvram_set(strlcat_r(prefix, "_ifnames", tmp, sizeof(tmp)), p);
}
void start_wan_if(char *prefix)
{
int wan_proto;
char *wan_ifname;
char *nvp;
struct ifreq ifr;
int sd;
int max;
int mtu;
char buf[128];
char tmp[128], tmp2[32];
int jumbo_enable = 0;
struct vlan_ioctl_args ifv;
do_connect_file(1, prefix);
store_wan_if_to_nvram(prefix);
/* Setup WAN interface name */
wan_ifname = nvram_safe_get(strlcat_r(prefix, "_ifname", tmp, sizeof(tmp)));
if (wan_ifname[0] == 0) {
wan_ifname = "none";
nvram_set(strlcat_r(prefix, "_ifname", tmp, sizeof(tmp)), wan_ifname);
}
if (strcmp(wan_ifname, "none") == 0) {
nvram_set(strlcat_r(prefix, "_proto", tmp, sizeof(tmp)), "disabled");
logmsg(LOG_WARNING, "%s ifname is NONE, please check you vlan settings!", prefix);
}
/* Defined in shared.h, misc.c */
wan_proto = get_wanx_proto(prefix);
/* Set the default gateway for WAN interface */
nvram_set(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp)), nvram_safe_get(strlcat_r(prefix, "_gateway", tmp2, sizeof(tmp2)))); /* tmp2 needed --> code evaluation left to right! */
if (wan_proto == WP_DISABLED) {
start_wan_done(wan_ifname, prefix);
return;
}
if ((sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
logerr(__FUNCTION__, __LINE__, "socket");
return;
}
jumbo_enable = nvram_get_int("jumbo_frame_enable");
/* MTU */
switch (wan_proto) {
case WP_PPPOE:
case WP_PPP3G:
max = 1492;
break;
case WP_PPTP:
case WP_L2TP:
max = 1460;
break;
default:
max = 1500;
break;
}
if (nvram_match(strlcat_r(prefix, "_mtu_enable", tmp, sizeof(tmp)), "0"))
mtu = max;
else {
/* KDB If we've big fat frames enabled then we *CAN* break the
* max MTU on PPP link
*/
mtu = nvram_get_int(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp)));
if (!jumbo_enable && (mtu > max))
mtu = max;
else if (mtu < 576)
mtu = 576;
}
memset(buf, 0, sizeof(buf));
snprintf(buf, sizeof(buf), "%d", mtu);
nvram_set(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp)), buf);
nvram_set(strlcat_r(prefix, "_run_mtu", tmp, sizeof(tmp)), buf);
/* Don't set the MTU on the port for PPP connections, it will be set on the link instead */
if ((wan_proto == WP_PPTP) || (wan_proto == WP_L2TP) || (wan_proto == WP_PPPOE) || (wan_proto == WP_PPP3G))
mtu = 0;
/* Bring wan interface UP */
_ifconfig(wan_ifname, IFUP, NULL, NULL, NULL, mtu);
/* Try to increase WAN interface MTU to allow PPPoE MTU/MRU 1500 (default 1492, with 8 byte overhead) */
mtu = nvram_get_int(strlcat_r(prefix, "_mtu", tmp, sizeof(tmp))); /* get mtu again */
if ((jumbo_enable) && (mtu == 1500) && (wan_proto == WP_PPPOE)) {
logmsg(LOG_INFO, "Try to increase WAN MTU up to 1500 for ISPs that support RFC 4638");
/* set parent device --> should be "eth0" */
strlcpy(ifv.device1, wan_ifname, IFNAMSIZ);
ifv.cmd = GET_VLAN_REALDEV_NAME_CMD;
if (ioctl(sd, SIOCGIFVLAN, &ifv) >= 0) {
strlcpy(ifr.ifr_name, ifv.u.device2, IFNAMSIZ);
ifr.ifr_mtu = mtu + 8;
if (ioctl(sd, SIOCSIFMTU, &ifr)) {
logerr(__FUNCTION__, __LINE__, wan_ifname);
logmsg(LOG_INFO, "Error setting MTU on %s to %d", ifr.ifr_name, ifr.ifr_mtu);
}
else
logmsg(LOG_INFO, "Increase MTU on %s to %d", ifr.ifr_name, ifr.ifr_mtu);
}
/* set wan device --> for example "vlan7" */
strlcpy(ifr.ifr_name, wan_ifname, IFNAMSIZ);
ifr.ifr_mtu = mtu + 8;
if (ioctl(sd, SIOCSIFMTU, &ifr)) {
logerr(__FUNCTION__, __LINE__, wan_ifname);
logmsg(LOG_INFO, "Error setting MTU on %s to %d", ifr.ifr_name, ifr.ifr_mtu);
}
else
logmsg(LOG_INFO, "Increase MTU on %s to %d", ifr.ifr_name, ifr.ifr_mtu);
}
switch (wan_proto) {
case WP_PPPOE:
case WP_PPP3G:
if (wan_proto == WP_PPPOE && using_dhcpc(prefix)) { /* PPPoE with DHCP MAN */
stop_dhcpc(prefix);
start_dhcpc(prefix);
}
else if (!strcmp(prefix, "wan")) start_pppoe(PPPOEWAN, prefix);
else if (!strcmp(prefix, "wan2")) start_pppoe(PPPOEWAN2, prefix);
#ifdef TCONFIG_MULTIWAN
else if (!strcmp(prefix, "wan3")) start_pppoe(PPPOEWAN3, prefix);
else if (!strcmp(prefix, "wan4")) start_pppoe(PPPOEWAN4, prefix);
#endif
break;
case WP_DHCP:
case WP_LTE:
case WP_L2TP:
case WP_PPTP:
if (wan_proto == WP_LTE) {
/* Prepare LTE modem */
if (!nvram_get_int("g_upgrade") && !nvram_get_int("g_reboot"))
xstart("switch4g", prefix);
}
else if (using_dhcpc(prefix)) {
stop_dhcpc(prefix);
start_dhcpc(prefix);
}
else if (wan_proto != WP_DHCP && wan_proto != WP_LTE) {
/* Set wan interface IP/mask */
ifconfig(wan_ifname, IFUP, "0.0.0.0", NULL);
ifconfig(wan_ifname, IFUP, nvram_safe_get(strlcat_r(prefix, "_ipaddr", tmp, sizeof(tmp))), nvram_safe_get(strlcat_r(prefix, "_netmask", tmp, sizeof(tmp))));
nvp = nvram_safe_get(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)));
if ((strcmp(nvp, "0.0.0.0") != 0) && (*nvp))
preset_wan(wan_ifname, nvp, nvram_safe_get(strlcat_r(prefix, "_netmask", tmp, sizeof(tmp))), prefix);
switch (wan_proto) {
case WP_PPTP:
start_pptp(prefix);
break;
case WP_L2TP:
start_l2tp(prefix);
break;
}
}
break;
default: /* Static */
nvram_set(strlcat_r(prefix, "_iface", tmp, sizeof(tmp)), wan_ifname);
ifconfig(wan_ifname, IFUP, nvram_safe_get(strlcat_r(prefix, "_ipaddr", tmp, sizeof(tmp))), nvram_safe_get(strlcat_r(prefix, "_netmask", tmp, sizeof(tmp))));
int r = 10;
while ((!check_wanup(prefix)) && (r-- > 0)) {
sleep(1);
}
start_wan_done(wan_ifname, prefix);
break;
}
/* Get current WAN hardware address */
strlcpy(ifr.ifr_name, wan_ifname, IFNAMSIZ);
if (ioctl(sd, SIOCGIFHWADDR, &ifr) == 0)
nvram_set(strlcat_r(prefix, "_hwaddr", tmp, sizeof(tmp)), ether_etoa((const unsigned char *) ifr.ifr_hwaddr.sa_data, buf));
close(sd);
/* Set initial QoS mode again now that WAN port is ready. */
set_et_qos_mode();
}
void start_wan(void)
{
int mwan_num;
int wan_unit;
char prefix[] = "wanXX";
mwan_num = nvram_get_int("mwan_num");
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
mwan_num = 1;
logmsg(LOG_INFO, "MultiWAN: MWAN is %d (max %d)", mwan_num, MWAN_MAX);
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
get_wan_prefix(wan_unit, prefix);
start_wan_if(prefix);
logmsg(LOG_DEBUG, "*** MultiWAN: %s: (unit: %d), prefix = %s", __FUNCTION__, wan_unit, prefix);
}
start_firewall();
set_host_domain_name();
/* only start mwanroute if it's not already up! */
if (pidof("mwanroute") < 0) {
logmsg(LOG_DEBUG, "*** %s: mwanroute not found, launch process", __FUNCTION__);
xstart("mwanroute");
}
if (nvram_get_int("mwan_cktime") > 0) {
logmsg(LOG_DEBUG, "*** %s: adding mwwatchdog job", __FUNCTION__);
xstart("mwwatchdog", "add");
}
led(LED_DIAG, LED_OFF);
led(LED_DMZ, nvram_match("dmz_enable", "1"));
}
#ifdef TCONFIG_IPV6
void start_wan6(const char *wan_ifname)
{
struct in_addr addr4;
struct in6_addr addr;
static char addr6[INET6_ADDRSTRLEN];
int service = get_ipv6_service();
if (service != IPV6_DISABLED) {
/* Check if "ipv6_accept_ra" (bit 0) for wan is enabled (via GUI, basic-ipv6.asp) */
if ((nvram_get_int("ipv6_accept_ra") & 0x01) != 0)
accept_ra(wan_ifname);
else /* set default value */
accept_ra_reset(wan_ifname);
}
switch (service) {
case IPV6_NATIVE:
snprintf(addr6, sizeof(addr6), "%s/%d", nvram_safe_get("ipv6_wan_addr"), nvram_get_int("ipv6_prefix_len_wan"));
eval("ip", "-6", "addr", "add", addr6, "dev", (char *)wan_ifname);
eval("ip", "-6", "route", "del", "::/0");
eval("ip", "-6", "route", "add", nvram_safe_get("ipv6_isp_gw"), "dev", (char *)wan_ifname);
eval("ip", "-6", "route", "add", "::/0", "via", nvram_safe_get("ipv6_isp_gw"), "dev", (char *)wan_ifname);
break;
case IPV6_NATIVE_DHCP:
/* IPv6 RA (via WAN) will take care of adding the default route, so that ipv6_isp_opt should not be enabled/required!
BUT: some ISP's, Snap (NZ), Internode (AU) may need the default route / workaround --> Tomato User can decide
see also https://www.linksysinfo.org/index.php?threads/ipv6-and-comcast.38006/
*/
if (nvram_get_int("ipv6_isp_opt") == 1) {
eval("ip", "route", "add", "::/0", "dev", (char *)wan_ifname);
}
stop_dhcp6c();
start_dhcp6c();
break;
case IPV6_ANYCAST_6TO4:
case IPV6_6IN4:
stop_ipv6_tunnel();
if (service == IPV6_ANYCAST_6TO4) {
addr4.s_addr = 0;
memset(&addr, 0, sizeof(addr));
inet_aton(get_wanip("wan"), &addr4);
addr.s6_addr16[0] = htons(0x2002);
ipv6_mapaddr4(&addr, 16, &addr4, 0);
addr.s6_addr16[3] = htons(0x0001);
inet_ntop(AF_INET6, &addr, addr6, sizeof(addr6));
nvram_set("ipv6_prefix", addr6);
}
start_ipv6_tunnel();
/* FIXME: give it a few seconds for DAD completion */
sleep(2);
break;
case IPV6_6RD:
case IPV6_6RD_DHCP:
stop_6rd_tunnel();
start_6rd_tunnel();
/* FIXME2?: give it a few seconds for DAD completion */
sleep(2);
break;
}
}
void stop_wan6(void)
{
stop_ipv6_tunnel();
stop_dhcp6c();
nvram_set("ipv6_get_dns", ""); /* clear dns */
dns_to_resolv();
}
#endif /* #ifdef TCONFIG_IPV6 */
/* ppp_demand: 0=keep alive, 1=connect on demand (run 'listen')
* wan_ifname: vlan1
* wan_iface: ppp# (PPPOE, PPP3G, PPTP, L2TP), vlan1 (DHCP, HB, Static, LTE)
*/
void start_wan_done(char *wan_ifname, char *prefix)
{
int proto;
int n;
char *gw;
struct sysinfo si;
int wanup;
int mwan_num;
char tmp[100];
int is_primary;
char pw[] = "wanXX";
int first_ntp_sync = 0;
sysinfo(&si);
mwan_num = nvram_get_int("mwan_num");
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
mwan_num = 1;
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "/var/lib/misc/%s_time", prefix);
f_write(tmp, &si.uptime, sizeof(si.uptime), 0, 0);
proto = get_wanx_proto(prefix);
if (mwan_num == 1) {
/* Delete default interface route */
if (proto == WP_PPTP || proto == WP_L2TP || (proto == WP_PPPOE && using_dhcpc(prefix))) /* Delete MAN default route */
route_del(NULL, 0, NULL, NULL, NULL);
else
route_del(wan_ifname, 0, NULL, NULL, NULL);
}
if (proto != WP_DISABLED) {
/* Set default route to gateway if specified */
gw = wan_gateway(prefix);
if ((*gw != 0) && (strcmp(gw, "0.0.0.0") != 0)) {
if (proto == WP_DHCP || proto == WP_STATIC || proto == WP_LTE)
/* Possibly gateway is over the bridge, try adding a route to gateway first */
route_add(wan_ifname, 0, gw, NULL, "255.255.255.255");
if (mwan_num == 1) {
n = 5;
while ((route_add(wan_ifname, 0, "0.0.0.0", gw, "0.0.0.0") == 1) && (n--)) {
sleep(1);
}
}
/* hack: avoid routing cycles, when both peer and server have the same IP */
if (proto == WP_PPTP || proto == WP_L2TP)
/* Delete gateway route as it's no longer needed */
route_del(wan_ifname, 0, gw, "0.0.0.0", "255.255.255.255");
}
/* Change GW from peer IP to PPTP/L2TP IP */
if (proto == WP_PPTP || proto == WP_L2TP) {
route_del(nvram_safe_get(strlcat_r(prefix, "_iface", tmp, sizeof(tmp))), 0, nvram_safe_get(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp))), NULL, "255.255.255.255");
route_add(nvram_safe_get(strlcat_r(prefix, "_iface", tmp, sizeof(tmp))), 0, nvram_safe_get(strlcat_r(prefix, "_ppp_get_ip", tmp, sizeof(tmp))), NULL, "255.255.255.255");
}
}
stop_dnsmasq();
dns_to_resolv();
start_dnsmasq();
start_firewall();
start_qos(prefix);
do_static_routes(1);
/* And routes supplied via DHCP */
do_wan_routes((using_dhcpc(prefix) ? nvram_safe_get(strlcat_r(prefix, "_ifname", tmp, sizeof(tmp))) : wan_ifname), 0, 1, prefix);
#ifdef TCONFIG_IPV6
/* start IPv6 BUT only for "wan" (no multiwan support, no primary wan) */
if (strcmp(prefix, "wan") == 0) { /* check for "wan" prefix */
switch (get_ipv6_service()) {
case IPV6_NATIVE:
case IPV6_NATIVE_DHCP:
if (strncmp(wan_ifname, "ppp", 3) == 0) { /* check for pppx */
break;
}
/* fall through */
default:
start_wan6(get_wan6face());
break;
}
}
#endif
/*
* FIX boot with only secondary etc wan active (assume current wan is primary if previous is not up)
*/
get_wan_prefix(nvram_get_int("wan_primary"), pw); /* Get current primary wan name */
if (!check_wanup(pw)) { /* If primary wan offline, set current as primary */
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "%d", get_wan_unit(prefix));
nvram_set("wan_primary", tmp);
memset(pw, 0, sizeof(pw));
strlcpy(pw, prefix, sizeof(pw));
}
wanup = check_wanup(prefix); /* is wan up? */
is_primary = (strcmp(prefix, pw) == 0); /* is this primary wan? */
if (is_primary) {
#ifdef TCONFIG_ZEBRA
stop_zebra();
start_zebra();
#endif
if ((wanup || (proto == WP_DISABLED)) && (!nvram_get_int("ntp_ready"))) {
if ((proto == WP_DISABLED) && nvram_get_int("lan_dhcp")) { /* Case: AP / WET / MB Mode with DHCP client for Lan (br0) */
/* nothing to do here! and start ntpd (only) with bound event */
logmsg(LOG_DEBUG, "*** %s: start ntpd with bound event (DHCP client)", __FUNCTION__);
}
else { /* default */
first_ntp_sync = 1;
stop_ntpd();
start_ntpd();
}
}
if ((wanup) || (proto == WP_DISABLED)) {
stop_igmp_proxy();
stop_udpxy();
start_igmp_proxy();
start_udpxy();
}
if (nvram_get_int("ntp_ready") && !first_ntp_sync) {
stop_httpd();
start_httpd();
}
} /* is_primary */
if ((wanup) || (proto == WP_DISABLED)) {
if (nvram_get_int("ntp_ready") && !first_ntp_sync) {
stop_ddns();
start_ddns();
}
}
if (nvram_get_int("ntp_ready") && !first_ntp_sync) {
stop_sched();
start_sched();
}
if (wanup) {
char wan_unit_str[16];
memset(wan_unit_str, 0, sizeof(wan_unit_str));
snprintf(wan_unit_str, sizeof(wan_unit_str), "%d", get_wan_unit(prefix));
notice_set(prefix, "");
run_nvscript("script_mwanup", wan_unit_str, 0);
if (is_primary)
run_nvscript("script_wanup", NULL, 0);
}
if (is_primary) {
/* WAN LED control */
if (wanup)
wan_led(wanup); /* LED ON! */
#ifndef TCONFIG_BCMARM
/* We don't need STP after wireless led is lighted */
if (check_hw_type() == HW_BCM4702) {
eval("brctl", "stp", nvram_safe_get("lan_ifname"), "0");
if (nvram_match("lan_stp", "1"))
eval("brctl", "stp", nvram_safe_get("lan_ifname"), "1");
if (strcmp(nvram_safe_get("lan1_ifname"),"") != 0) {
eval("brctl", "stp", nvram_safe_get("lan1_ifname"), "0");
if (nvram_match("lan1_stp", "1"))
eval("brctl", "stp", nvram_safe_get("lan1_ifname"), "1");
}
if (strcmp(nvram_safe_get("lan2_ifname"),"") != 0) {
eval("brctl", "stp", nvram_safe_get("lan2_ifname"), "0");
if (nvram_match("lan2_stp", "1"))
eval("brctl", "stp", nvram_safe_get("lan2_ifname"), "1");
}
if (strcmp(nvram_safe_get("lan3_ifname"),"") != 0) {
eval("brctl", "stp", nvram_safe_get("lan3_ifname"), "0");
if (nvram_match("lan3_stp", "1"))
eval("brctl", "stp", nvram_safe_get("lan3_ifname"), "1");
}
}
#endif
if ((wanup) || (proto == WP_DISABLED)) {
#ifdef TCONFIG_OPENVPN
if (nvram_get_int("ntp_ready") && !first_ntp_sync)
start_ovpn_eas();
#endif
#ifdef TCONFIG_WIREGUARD
if (nvram_get_int("ntp_ready") && !first_ntp_sync)
start_wg_eas();
#endif
#ifdef TCONFIG_TINC
start_tinc(0);
#endif
start_pptp_client_eas();
start_adblock(0);
#ifdef TCONFIG_SAMBASRV
stop_samba();
start_samba(0);
#endif
}
stop_upnp();
start_upnp();
start_bwlimit();
} /* is_primary */
mwan_table_add(prefix);
mwan_load_balance();
do_connect_file(0, prefix);
}
void stop_wan_if(char *prefix)
{
char name[80];
char *next;
int wan_proto;
char tmp[100];
int mwan_num = nvram_get_int("mwan_num");
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
mwan_num = 1;
if ((strcmp(prefix, "wan") == 0) && (mwan_num == 1)) { /* check for "wan" prefix AND only 1x wan (single-wan) */
stop_upnp();
logmsg(LOG_DEBUG, "*** %s: stop miniupnp (Case: Single-WAN)", __FUNCTION__);
}
mwan_table_del(prefix);
stop_qos(prefix);
/* stop IPv6 BUT only for "wan" (no multiwan support, no primary wan) */
#ifdef TCONFIG_IPV6
if (strcmp(prefix, "wan") == 0) { /* check for "wan" prefix */
stop_wan6();
}
#endif
/* Kill any WAN client daemons or callbacks */
stop_redial(prefix);
stop_l2tp(prefix); /* Special case for xl2tpd */
stop_ppp(prefix); /* One for all */
stop_dhcpc(prefix);
wan_proto = get_wanx_proto(prefix);
if (wan_proto == WP_PPP3G)
killall_tk_period_wait("switch3g", 50); /* Kill switch3g script if running */
if (wan_proto == WP_LTE) {
killall_tk_period_wait("switch4g", 50); /* Kill switch4g script if running */
xstart("switch4g", prefix, "disconnect");
if (!nvram_get_int("g_upgrade"))
sleep(3); /* Wait a litle for disconnect */
}
/* Bring down WAN interfaces */
foreach(name, nvram_safe_get(strlcat_r(prefix, "_ifnames", tmp, sizeof(tmp))), next)
ifconfig(name, 0, "0.0.0.0", NULL);
memset(tmp, 0, sizeof(tmp));
snprintf(tmp, sizeof(tmp), "/var/notice/%s", prefix);
unlink(tmp);
do_connect_file(0, prefix);
mwan_load_balance();
/* Clear old IP params from nvram on if stop
* but only if WAN is not as STATIC - shibby
* TBD: check mwan compat on empty gw/ip etc
*/
if (wan_proto != WP_STATIC && using_dhcpc(prefix)) { /* Not STATIC or PPP wan with manual IP params */
nvram_set(strlcat_r(prefix, "_ipaddr", tmp, sizeof(tmp)), "0.0.0.0");
nvram_set(strlcat_r(prefix, "_netmask", tmp, sizeof(tmp)), "0.0.0.0");
nvram_set(strlcat_r(prefix, "_gateway", tmp, sizeof(tmp)), "0.0.0.0");
}
if (wan_proto == WP_DHCP || wan_proto == WP_LTE || using_dhcpc(prefix)) { /* DHCP/LTE/PPP+DHCP wan */
nvram_set(strlcat_r(prefix, "_gateway_get", tmp, sizeof(tmp)), "0.0.0.0");
nvram_set(strlcat_r(prefix, "_get_dns", tmp, sizeof(tmp)), "");
}
if (wan_proto == WP_PPTP || wan_proto == WP_L2TP || wan_proto == WP_PPPOE || wan_proto == WP_PPP3G) {
nvram_set(strlcat_r(prefix, "_ppp_get_ip", tmp, sizeof(tmp)), "0.0.0.0");
nvram_set(strlcat_r(prefix, "_get_dns", tmp, sizeof(tmp)), "");
/* For debug. Don't fool mwwatchdog / mwan scripts with old obsolete interface, it can be actually used on other wan (ex: ppp0) */
nvram_set(strlcat_r(prefix, "_iface", tmp, sizeof(tmp)), "none");
}
}
void stop_wan(void)
{
logmsg(LOG_DEBUG, "*** IN: %s", __FUNCTION__);
logmsg(LOG_DEBUG, "*** %s: removing mwwatchdog job", __FUNCTION__);
xstart("mwwatchdog", "del");
#ifdef TCONFIG_TINC
stop_tinc();
#endif
stop_bwlimit();
stop_upnp(); /* miniupnp - case: stop always (x wan(s)/restart) */
#ifdef TCONFIG_OPENVPN
stop_ovpn_all();
#endif
#ifdef TCONFIG_WIREGUARD
stop_wg_all();
#endif
stop_pptp_client_eas();
stop_igmp_proxy();
stop_udpxy();
#ifdef TCONFIG_IPV6
stop_ipv6_tunnel();
stop_dhcp6c();
nvram_set("ipv6_get_dns", "");
#endif
stop_firewall();
stop_adblock();
clear_resolv();
stop_wan_if("wan");
stop_wan_if("wan2");
#ifdef TCONFIG_MULTIWAN
stop_wan_if("wan3");
stop_wan_if("wan4");
#endif
logmsg(LOG_DEBUG, "*** OUT: %s", __FUNCTION__);
}