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.
4090 lines
109 KiB
C
4090 lines
109 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 - 2024 pedro
|
|
*
|
|
*/
|
|
|
|
|
|
#include "rc.h"
|
|
|
|
#include <arpa/inet.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <wlutils.h>
|
|
|
|
#include <sys/mount.h>
|
|
#include <mntent.h>
|
|
#include <dirent.h>
|
|
#include <linux/version.h>
|
|
|
|
#define ADBLOCK_EXE "/usr/sbin/adblock"
|
|
#define DNSMASQ_CONF "/etc/dnsmasq.conf"
|
|
#define RESOLV_CONF "/etc/resolv.conf"
|
|
#define IGMP_CONF "/etc/igmp.conf"
|
|
#define UPNP_DIR "/etc/upnp"
|
|
#define UPNP_CONFIG UPNP_DIR"/config"
|
|
#ifdef TCONFIG_ZEBRA
|
|
#define ZEBRA_CONF "/etc/zebra.conf"
|
|
#define RIPD_CONF "/etc/ripd.conf"
|
|
#endif
|
|
#ifdef TCONFIG_MDNS
|
|
#define AVAHI_CONFIG_PATH "/etc/avahi"
|
|
#define AVAHI_SERVICES_PATH "/etc/avahi/services"
|
|
#define AVAHI_CONFIG_FN "avahi-daemon.conf"
|
|
#endif /* TCONFIG_MDNS */
|
|
|
|
/* needed by logmsg() */
|
|
#define LOGMSG_DISABLE DISABLE_SYSLOG_OSM
|
|
#define LOGMSG_NVDEBUG "services_debug"
|
|
|
|
#ifdef TCONFIG_BCMARM
|
|
extern struct nvram_tuple rstats_defaults[];
|
|
#endif /* TCONFIG_BCMARM */
|
|
#ifdef TCONFIG_BCMARM
|
|
extern struct nvram_tuple cstats_defaults[];
|
|
#endif /* TCONFIG_BCMARM */
|
|
#if defined(TCONFIG_FTP) && defined(TCONFIG_BCMARM)
|
|
extern struct nvram_tuple ftp_defaults[];
|
|
#endif /* TCONFIG_FTP && TCONFIG_BCMARM */
|
|
#if defined(TCONFIG_SNMP) && defined(TCONFIG_BCMARM)
|
|
extern struct nvram_tuple snmp_defaults[];
|
|
#endif /* TCONFIG_SNMP && TCONFIG_BCMARM */
|
|
#ifdef TCONFIG_BCMARM
|
|
extern struct nvram_tuple upnp_defaults[];
|
|
#endif /* TCONFIG_BCMARM */
|
|
#ifdef TCONFIG_BCMBSD
|
|
extern struct nvram_tuple bsd_defaults[];
|
|
#endif /* TCONFIG_BCMBSD */
|
|
|
|
/* Pop an alarm to recheck pids in 500 msec */
|
|
static const struct itimerval pop_tv = { {0, 0}, {0, 500 * 1000} };
|
|
/* Pop an alarm to reap zombies */
|
|
static const struct itimerval zombie_tv = { {0, 0}, {307, 0} };
|
|
static const char dmhosts[] = "/etc/hosts.dnsmasq";
|
|
static const char dmresolv[] = "/etc/resolv.dnsmasq";
|
|
//static pid_t pid_dnsmasq = -1;
|
|
static pid_t pid_crond = -1;
|
|
static pid_t pid_hotplug2 = -1;
|
|
static pid_t pid_igmp = -1;
|
|
static pid_t pid_ntpd = -1;
|
|
#ifdef TCONFIG_FANCTRL
|
|
static pid_t pid_phy_tempsense = -1;
|
|
#endif
|
|
|
|
void add_rstats_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = rstats_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "rstats_defaults", "--add");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void del_rstats_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
if (nvram_match("rstats_enable", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = rstats_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "rstats_defaults", "--del");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void add_cstats_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = cstats_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "cstats_defaults", "--add");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void del_cstats_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
if (nvram_match("cstats_enable", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = cstats_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "cstats_defaults", "--del");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
#ifdef TCONFIG_FTP
|
|
void add_ftp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = ftp_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "ftp_defaults", "--add");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void del_ftp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
if (nvram_match("ftp_enable", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = ftp_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "ftp_defaults", "--del");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
#endif /* TCONFIG_FTP */
|
|
|
|
#ifdef TCONFIG_SNMP
|
|
void add_snmp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = snmp_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "snmp_defaults", "--add");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void del_snmp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
if (nvram_match("snmp_enable", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = snmp_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "snmp_defaults", "--del");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
#endif /* TCONFIG_SNMP */
|
|
|
|
void add_upnp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = upnp_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "upnp_defaults", "--add");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
void del_upnp_defaults(void)
|
|
{
|
|
#ifdef TCONFIG_BCMARM
|
|
if (nvram_match("upnp_enable", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = upnp_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
#else
|
|
eval("nvram", "upnp_defaults", "--del");
|
|
#endif /* TCONFIG_BCMARM */
|
|
}
|
|
|
|
#ifdef TCONFIG_BCMBSD
|
|
void add_bsd_defaults(void)
|
|
{
|
|
struct nvram_tuple *t;
|
|
|
|
/* Restore defaults if necessary */
|
|
for (t = bsd_defaults; t->name; t++) {
|
|
if (!nvram_get(t->name)) { /* check existence */
|
|
nvram_set(t->name, t->value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void del_bsd_defaults(void)
|
|
{
|
|
if (nvram_match("smart_connect_x", "0")) {
|
|
struct nvram_tuple *t;
|
|
|
|
/* remove defaults if NOT necessary (only keep "xyz_enable" nv var.) */
|
|
for (t = bsd_defaults; t->name; t++) {
|
|
nvram_unset(t->name);
|
|
}
|
|
}
|
|
}
|
|
#endif /* TCONFIG_BCMBSD */
|
|
|
|
void start_dnsmasq_wet()
|
|
{
|
|
FILE *f;
|
|
const char *nv;
|
|
char br;
|
|
char lanN_ifname[] = "lanXX_ifname";
|
|
|
|
if ((f = fopen(DNSMASQ_CONF, "w")) == NULL) {
|
|
logerr(__FUNCTION__, __LINE__, DNSMASQ_CONF);
|
|
return;
|
|
}
|
|
|
|
fprintf(f, "pid-file=/var/run/dnsmasq.pid\n"
|
|
"resolv-file=%s\n" /* the real stuff is here */
|
|
"min-port=%u\n" /* min port used for random src port */
|
|
"no-negcache\n" /* disable negative caching */
|
|
"bind-dynamic\n",
|
|
dmresolv,
|
|
4096);
|
|
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
snprintf(lanN_ifname, sizeof(lanN_ifname), "lan%s_ifname", bridge);
|
|
nv = nvram_safe_get(lanN_ifname);
|
|
|
|
if (strncmp(nv, "br", 2) == 0) {
|
|
fprintf(f, "interface=%s\n", nv);
|
|
fprintf(f, "no-dhcp-interface=%s\n", nv);
|
|
}
|
|
}
|
|
|
|
if (nvram_get_int("dnsmasq_debug"))
|
|
fprintf(f, "log-queries\n");
|
|
|
|
if ((nvram_get_int("adblock_enable")) && (f_exists("/etc/dnsmasq.adblock")))
|
|
fprintf(f, "conf-file=/etc/dnsmasq.adblock\n");
|
|
|
|
if (!nvram_get_int("dnsmasq_safe")) {
|
|
fprintf(f, "%s\n", nvram_safe_get("dnsmasq_custom"));
|
|
fappend(f, "/etc/dnsmasq.custom");
|
|
}
|
|
else
|
|
logmsg(LOG_WARNING, "Warning! Dnsmasq Custom configuration contains a disruptive syntax error. The Custom configuration is now excluded to allow dnsmasq to operate");
|
|
|
|
fappend(f, "/etc/dnsmasq.ipset");
|
|
|
|
fclose(f);
|
|
|
|
unlink(RESOLV_CONF);
|
|
symlink("/rom/etc/resolv.conf", RESOLV_CONF); /* nameserver 127.0.0.1 */
|
|
|
|
eval("dnsmasq", "-c", "4096", "--log-async");
|
|
}
|
|
|
|
void start_dnsmasq()
|
|
{
|
|
FILE *f, *hf;
|
|
const char *nv;
|
|
const char *router_ip;
|
|
char sdhcp_lease[32];
|
|
char buf[512], lan[24], tmp[128];
|
|
char *e, *p;
|
|
struct in_addr in4;
|
|
char *mac, *ip, *name, *bind;
|
|
char *nve, *nvp;
|
|
unsigned char ea[ETHER_ADDR_LEN];
|
|
int i, n;
|
|
int dhcp_lease;
|
|
int do_dhcpd, do_dns, do_dhcpd_hosts = 0;
|
|
#ifdef TCONFIG_IPV6
|
|
int ipv6_lease; /* DHCP IPv6 lease time */
|
|
int service;
|
|
#endif
|
|
int wan_unit, mwan_num;
|
|
const dns_list_t *dns;
|
|
char br;
|
|
char wan_prefix[] = "wanXX";
|
|
char lanN_proto[] = "lanXX_proto";
|
|
char lanN_ifname[] = "lanXX_ifname";
|
|
char lanN_ipaddr[] = "lanXX_ipaddr";
|
|
char lanN_netmask[] = "lanXX_netmask";
|
|
char dhcpdN_startip[] = "dhcpdXX_startip";
|
|
char dhcpdN_endip[] = "dhcpdXX_endip";
|
|
char dhcpN_lease[] = "dhcpXX_lease";
|
|
unsigned int start_ip = 2;
|
|
unsigned int end_ip = 50;
|
|
|
|
if (serialize_restart("dnsmasq", 1))
|
|
return;
|
|
|
|
/* check wireless ethernet bridge (wet) after stop_dnsmasq() */
|
|
if (foreach_wif(1, NULL, is_wet)) {
|
|
logmsg(LOG_INFO, "Starting dnsmasq for wireless ethernet bridge mode");
|
|
start_dnsmasq_wet();
|
|
return;
|
|
}
|
|
|
|
#ifdef TCONFIG_BCMWL6
|
|
/* check media bridge (psta) after stop_dnsmasq() */
|
|
if (foreach_wif(1, NULL, is_psta)) {
|
|
logmsg(LOG_INFO, "Starting dnsmasq for media bridge mode");
|
|
start_dnsmasq_wet();
|
|
return;
|
|
}
|
|
#endif /* TCONFIG_BCMWL6 */
|
|
|
|
if ((f = fopen(DNSMASQ_CONF, "w")) == NULL) {
|
|
logerr(__FUNCTION__, __LINE__, DNSMASQ_CONF);
|
|
return;
|
|
}
|
|
|
|
if (((nv = nvram_get("wan_domain")) != NULL) || ((nv = nvram_get("wan_get_domain")) != NULL)) {
|
|
if (*nv)
|
|
fprintf(f, "domain=%s\n", nv);
|
|
}
|
|
|
|
if ((nv = nvram_safe_get("dns_minport")) && (*nv))
|
|
n = atoi(nv);
|
|
else
|
|
n = 4096;
|
|
|
|
fprintf(f, "pid-file=/var/run/dnsmasq.pid\n"
|
|
"resolv-file=%s\n" /* the real stuff is here */
|
|
"expand-hosts\n" /* expand hostnames in hosts file */
|
|
"min-port=%u\n" /* min port used for random src port */
|
|
"no-negcache\n" /* disable negative caching */
|
|
"dhcp-name-match=set:wpad-ignore,wpad\n" /* protect against VU#598349 */
|
|
"dhcp-ignore-names=tag:wpad-ignore\n",
|
|
dmresolv, n);
|
|
|
|
/* DNS rebinding protection, will discard upstream RFC1918 responses */
|
|
if (nvram_get_int("dns_norebind"))
|
|
fprintf(f, "stop-dns-rebind\n"
|
|
"rebind-localhost-ok\n");
|
|
|
|
/* instruct clients like Firefox to not auto-enable DoH */
|
|
if (nvram_get_int("dns_priv_override")) {
|
|
fprintf(f, "address=/use-application-dns.net/mask.icloud.com/mask-h2.icloud.com/\n"
|
|
"address=/_dns.resolver.arpa/\n");
|
|
}
|
|
|
|
/* forward local domain queries to upstream DNS */
|
|
if (nvram_get_int("dns_fwd_local") != 1)
|
|
fprintf(f, "bogus-priv\n" /* don't forward private reverse lookups upstream */
|
|
"domain-needed\n"); /* don't forward plain name queries upstream */
|
|
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
if (nvram_get_int("dnscrypt_proxy"))
|
|
fprintf(f, "server=127.0.0.1#%s\n", nvram_safe_get("dnscrypt_port"));
|
|
#endif
|
|
#ifdef TCONFIG_STUBBY
|
|
if (nvram_get_int("stubby_proxy"))
|
|
fprintf(f, "server=127.0.0.1#%s\n", nvram_safe_get("stubby_port"));
|
|
#endif
|
|
#ifdef TCONFIG_TOR
|
|
if ((nvram_get_int("tor_enable")) && (nvram_get_int("dnsmasq_onion_support"))) {
|
|
char *t_ip = nvram_safe_get("lan_ipaddr");
|
|
|
|
for (i = 1; i < BRIDGE_COUNT; i++ ) {
|
|
snprintf(buf, sizeof(buf), "br%d", i);
|
|
if (nvram_match("tor_iface", buf)) {
|
|
snprintf(buf, sizeof(buf), "lan%d_ipaddr", i);
|
|
t_ip = nvram_safe_get(buf);
|
|
break;
|
|
}
|
|
}
|
|
fprintf(f, "server=/onion/%s#%s\n", t_ip, nvram_safe_get("tor_dnsport"));
|
|
}
|
|
#endif
|
|
|
|
mwan_num = nvram_get_int("mwan_num");
|
|
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
|
|
mwan_num = 1;
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
|
|
/* allow RFC1918 responses for server domain (fix connect PPTP/L2TP WANs) */
|
|
switch (get_wanx_proto(wan_prefix)) {
|
|
case WP_PPTP:
|
|
nv = nvram_safe_get(strlcat_r(wan_prefix, "_pptp_server_ip", tmp, sizeof(tmp)));
|
|
break;
|
|
case WP_L2TP:
|
|
nv = nvram_safe_get(strlcat_r(wan_prefix, "_l2tp_server_ip", tmp, sizeof(tmp)));
|
|
break;
|
|
default:
|
|
nv = NULL;
|
|
break;
|
|
}
|
|
if (nv && *nv)
|
|
fprintf(f, "rebind-domain-ok=%s\n", nv);
|
|
|
|
dns = get_dns(wan_prefix); /* this always points to a static buffer */
|
|
|
|
/* check dns entries only for active connections */
|
|
if ((check_wanup(wan_prefix) == 0) && (dns->count == 0))
|
|
continue;
|
|
|
|
/* dns list with non-standart ports */
|
|
for (n = 0 ; n < dns->count; ++n) {
|
|
if (dns->dns[n].port != 53)
|
|
fprintf(f, "server=%s#%u\n", inet_ntoa(dns->dns[n].addr), dns->dns[n].port);
|
|
}
|
|
}
|
|
|
|
/* ignore DHCP requests from unknown devices for given LAN */
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
snprintf(buf, sizeof(buf), (i == 0 ? "dhcpd_ostatic" : "dhcpd%d_ostatic"), i);
|
|
if (nvram_get_int(buf))
|
|
fprintf(f, "dhcp-ignore=tag:br%d,tag:!known\n", i);
|
|
}
|
|
|
|
if ((n = nvram_get_int("dnsmasq_q"))) { /* process quiet flags */
|
|
if (n & 1)
|
|
fprintf(f, "quiet-dhcp\n");
|
|
#ifdef TCONFIG_IPV6
|
|
if (n & 2)
|
|
fprintf(f, "quiet-dhcp6\n");
|
|
if (n & 4)
|
|
fprintf(f, "quiet-ra\n");
|
|
#endif
|
|
}
|
|
|
|
/* dhcp */
|
|
do_dns = nvram_get_int("dhcpd_dmdns");
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
snprintf(lanN_proto, sizeof(lanN_proto), "lan%s_proto", bridge);
|
|
snprintf(lanN_ifname, sizeof(lanN_ifname), "lan%s_ifname", bridge);
|
|
snprintf(lanN_ipaddr, sizeof(lanN_ipaddr), "lan%s_ipaddr", bridge);
|
|
do_dhcpd = nvram_match(lanN_proto, "dhcp");
|
|
if (do_dhcpd) {
|
|
do_dhcpd_hosts++;
|
|
|
|
router_ip = nvram_safe_get(lanN_ipaddr);
|
|
strlcpy(lan, router_ip, sizeof(lan));
|
|
if ((p = strrchr(lan, '.')) != NULL)
|
|
*(p + 1) = 0;
|
|
|
|
fprintf(f, "interface=%s\n", nvram_safe_get(lanN_ifname));
|
|
|
|
snprintf(dhcpN_lease, sizeof(dhcpN_lease), "dhcp%s_lease", bridge);
|
|
dhcp_lease = nvram_get_int(dhcpN_lease);
|
|
|
|
if (dhcp_lease <= 0)
|
|
dhcp_lease = 1440;
|
|
|
|
if (((e = nvram_get("dhcpd_slt")) != NULL) && (*e))
|
|
n = atoi(e);
|
|
else
|
|
n = 0;
|
|
|
|
memset(sdhcp_lease, 0, sizeof(sdhcp_lease));
|
|
if (n < 0)
|
|
strlcpy(sdhcp_lease, "infinite", sizeof(sdhcp_lease));
|
|
else
|
|
snprintf(sdhcp_lease, sizeof(sdhcp_lease), "%dm", ((n > 0) ? n : dhcp_lease));
|
|
|
|
if (!do_dns) { /* if not using dnsmasq for dns */
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
/* skip inactive WAN connections
|
|
* TBD: need to check if there is no WANs active do we need skip here also?!?
|
|
*/
|
|
if (check_wanup(wan_prefix) == 0)
|
|
continue;
|
|
|
|
dns = get_dns(wan_prefix); /* static buffer */
|
|
|
|
if ((dns->count == 0) && (nvram_get_int("dhcpd_llndns"))) {
|
|
/* no DNS might be temporary. use a low lease time to force clients to update. */
|
|
dhcp_lease = 2;
|
|
strlcpy(sdhcp_lease, "2m", sizeof(sdhcp_lease));
|
|
do_dns = 1;
|
|
}
|
|
else {
|
|
/* pass the dns directly */
|
|
buf[0] = 0;
|
|
for (n = 0 ; n < dns->count; ++n) {
|
|
if (dns->dns[n].port == 53) /* check: option 6 doesn't seem to support other ports */
|
|
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), ",%s", inet_ntoa(dns->dns[n].addr));
|
|
}
|
|
fprintf(f, "dhcp-option=tag:%s,6%s\n", nvram_safe_get(lanN_ifname), buf); /* dns-server */
|
|
}
|
|
}
|
|
}
|
|
|
|
snprintf(dhcpdN_startip, sizeof(dhcpdN_startip), "dhcpd%s_startip", bridge);
|
|
snprintf(dhcpdN_endip, sizeof(dhcpdN_endip), "dhcpd%s_endip", bridge);
|
|
snprintf(lanN_netmask, sizeof(lanN_netmask), "lan%s_netmask", bridge);
|
|
|
|
if ((p = nvram_safe_get(dhcpdN_startip)) && (*p) && (e = nvram_safe_get(dhcpdN_endip)) && (*e))
|
|
fprintf(f, "dhcp-range=tag:%s,%s,%s,%s,%dm\n", nvram_safe_get(lanN_ifname), p, e, nvram_safe_get(lanN_netmask), dhcp_lease);
|
|
else
|
|
/* defaults if not present in nvram */
|
|
fprintf(f, "dhcp-range=tag:%s,%s%d,%s%d,%s,%dm\n", nvram_safe_get(lanN_ifname), lan, start_ip, lan, end_ip, nvram_safe_get(lanN_netmask), dhcp_lease);
|
|
|
|
nv = nvram_safe_get(lanN_ipaddr);
|
|
if ((nvram_get_int("dhcpd_gwmode") == 1) && (get_wan_proto() == WP_DISABLED)) {
|
|
p = nvram_safe_get("lan_gateway");
|
|
if ((*p) && (strcmp(p, "0.0.0.0") != 0))
|
|
nv = p;
|
|
}
|
|
fprintf(f, "dhcp-option=tag:%s,3,%s\n", nvram_safe_get(lanN_ifname), nv); /* gateway */
|
|
|
|
nv = nvram_safe_get("wan_wins");
|
|
if ((*nv) && (strcmp(nv, "0.0.0.0") != 0))
|
|
fprintf(f, "dhcp-option=tag:%s,44,%s\n", nvram_safe_get(lanN_ifname), nv); /* netbios-ns */
|
|
#ifdef TCONFIG_SAMBASRV
|
|
else if ((nvram_get_int("smbd_enable") || (pidof("smbd") > 0)) && nvram_invmatch("lan_hostname", "") && nvram_get_int("smbd_wins")) {
|
|
if ((!*nv) || (strcmp(nv, "0.0.0.0") == 0))
|
|
/* Samba will serve as a WINS server */
|
|
fprintf(f, "dhcp-option=tag:%s,44,%s\n", nvram_safe_get(lanN_ifname), nvram_safe_get(lanN_ipaddr)); /* netbios-ns */
|
|
}
|
|
#endif
|
|
}
|
|
else {
|
|
if (strcmp(nvram_safe_get(lanN_ifname), "") != 0)
|
|
fprintf(f, "interface=%s\n", nvram_safe_get(lanN_ifname));
|
|
}
|
|
}
|
|
|
|
/* write static lease entries & create hosts file */
|
|
router_ip = nvram_safe_get("lan_ipaddr"); /* use the main one, not the last one from the loop! */
|
|
|
|
if ((hf = fopen(dmhosts, "w")) != NULL) {
|
|
if ((nv = nvram_safe_get("wan_hostname")) && (*nv))
|
|
fprintf(hf, "%s %s\n", router_ip, nv);
|
|
#ifdef TCONFIG_SAMBASRV
|
|
else if ((nv = nvram_safe_get("lan_hostname")) && (*nv)) /* FIXME: it has to be implemented (lan_hostname is always empty) */
|
|
fprintf(hf, "%s %s\n", router_ip, nv);
|
|
#endif
|
|
p = (char *)get_wanip("wan");
|
|
if ((!*p) || strcmp(p, "0.0.0.0") == 0)
|
|
p = "127.0.0.1";
|
|
fprintf(hf, "%s wan1-ip\n", p);
|
|
|
|
p = (char *)get_wanip("wan2");
|
|
if ((!*p) || strcmp(p, "0.0.0.0") == 0)
|
|
p = "127.0.0.1";
|
|
fprintf(hf, "%s wan2-ip\n", p);
|
|
#ifdef TCONFIG_MULTIWAN
|
|
p = (char *)get_wanip("wan3");
|
|
if ((!*p) || strcmp(p, "0.0.0.0") == 0)
|
|
p = "127.0.0.1";
|
|
fprintf(hf, "%s wan3-ip\n", p);
|
|
|
|
p = (char *)get_wanip("wan4");
|
|
if ((!*p) || strcmp(p, "0.0.0.0") == 0)
|
|
p = "127.0.0.1";
|
|
fprintf(hf, "%s wan4-ip\n", p);
|
|
#endif
|
|
}
|
|
|
|
/* add dhcp reservations
|
|
*
|
|
* FORMAT (static ARP binding after hostname):
|
|
* 00:aa:bb:cc:dd:ee<123.123.123.123<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xyz<a>
|
|
* 00:aa:bb:cc:dd:ee,00:aa:bb:cc:dd:ee<123.123.123.123<xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xyz<a>
|
|
*/
|
|
nve = nvp = strdup(nvram_safe_get("dhcpd_static"));
|
|
while (nvp && (p = strsep(&nvp, ">")) != NULL) {
|
|
name = NULL;
|
|
|
|
if ((vstrsep(p, "<", &mac, &ip, &name, &bind)) < 4)
|
|
continue;
|
|
|
|
if (*ip != '\0' && (inet_pton(AF_INET, ip, &in4) <= 0 || in4.s_addr == INADDR_ANY || in4.s_addr == INADDR_LOOPBACK || in4.s_addr == INADDR_BROADCAST)) /* invalid IP (if any) */
|
|
continue;
|
|
|
|
if ((hf) && (*ip) && (*name))
|
|
fprintf(hf, "%s %s\n", ip, name);
|
|
|
|
if (do_dhcpd_hosts > 0 && ether_atoe(mac, ea)) {
|
|
if (*ip)
|
|
fprintf(f, "dhcp-host=%s,%s", mac, ip);
|
|
else if (*name)
|
|
fprintf(f, "dhcp-host=%s,%s", mac, name);
|
|
|
|
if (((*ip) || (*name)) && (nvram_get_int("dhcpd_slt") != 0))
|
|
fprintf(f, ",%s", sdhcp_lease);
|
|
|
|
fprintf(f, "\n");
|
|
}
|
|
}
|
|
if (nve)
|
|
free(nve);
|
|
|
|
if (hf) {
|
|
/* add directory with additional hosts files */
|
|
fprintf(f, "addn-hosts=%s\n", dmhosts);
|
|
fclose(hf);
|
|
}
|
|
|
|
n = nvram_get_int("dhcpd_lmax");
|
|
fprintf(f, "dhcp-lease-max=%d\n", ((n > 0) ? n : 255));
|
|
|
|
if (nvram_get_int("dhcpd_auth") >= 0)
|
|
fprintf(f, "dhcp-option=252,\"\\n\"\n"
|
|
"dhcp-authoritative\n");
|
|
|
|
/* NTP server */
|
|
if (nvram_get_int("ntpd_enable"))
|
|
fprintf(f, "dhcp-option-force=42,%s\n", "0.0.0.0");
|
|
|
|
if (nvram_get_int("dnsmasq_debug"))
|
|
fprintf(f, "log-queries\n");
|
|
|
|
/* generate a name for DHCP clients which do not otherwise have one */
|
|
if (nvram_get_int("dnsmasq_gen_names"))
|
|
fprintf(f, "dhcp-generate-names\n");
|
|
|
|
if ((nvram_get_int("adblock_enable")) && (f_exists("/etc/dnsmasq.adblock")))
|
|
fprintf(f, "conf-file=/etc/dnsmasq.adblock\n");
|
|
|
|
#if defined(TCONFIG_DNSSEC) || defined(TCONFIG_STUBBY)
|
|
if (nvram_get_int("dnssec_enable")) {
|
|
#ifdef TCONFIG_STUBBY
|
|
if ((!nvram_get_int("stubby_proxy")) || (nvram_match("dnssec_method", "0"))) {
|
|
#endif
|
|
#ifdef TCONFIG_DNSSEC
|
|
fprintf(f, "conf-file=/etc/trust-anchors.conf\n"
|
|
"dnssec\n");
|
|
|
|
/* if NTP isn't set yet, wait until rc's ntp signals us to start validating time */
|
|
if (!nvram_get_int("ntp_ready"))
|
|
fprintf(f, "dnssec-no-timecheck\n");
|
|
#endif
|
|
#ifdef TCONFIG_STUBBY
|
|
}
|
|
else /* use stubby dnssec or server only */
|
|
fprintf(f, "proxy-dnssec\n");
|
|
#endif
|
|
}
|
|
#endif /* TCONFIG_DNSSEC || TCONFIG_STUBBY */
|
|
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
if (nvram_get_int("dnscrypt_proxy")) {
|
|
if (nvram_match("dnscrypt_priority", "1"))
|
|
fprintf(f, "strict-order\n");
|
|
|
|
if (nvram_match("dnscrypt_priority", "2"))
|
|
fprintf(f, "no-resolv\n");
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_STUBBY
|
|
if (nvram_get_int("stubby_proxy")) {
|
|
if (nvram_match("stubby_priority", "1"))
|
|
fprintf(f, "strict-order\n");
|
|
|
|
if (nvram_match("stubby_priority", "2"))
|
|
fprintf(f, "no-resolv\n");
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_OPENVPN
|
|
write_ovpn_dnsmasq_config(f);
|
|
#endif
|
|
|
|
#ifdef TCONFIG_PPTPD
|
|
write_pptpd_dnsmasq_config(f);
|
|
#endif
|
|
|
|
#ifdef TCONFIG_WIREGUARD
|
|
write_wg_dnsmasq_config(f);
|
|
#endif
|
|
|
|
#ifdef TCONFIG_IPV6
|
|
if (ipv6_enabled()) {
|
|
|
|
service = get_ipv6_service();
|
|
memset(tmp, 0, sizeof(tmp)); /* reset */
|
|
|
|
/* get mtu for IPv6 --> only for "wan" (no multiwan support) */
|
|
switch (service) {
|
|
case IPV6_ANYCAST_6TO4: /* use tun mtu (visible at basic-ipv6.asp) */
|
|
case IPV6_6IN4:
|
|
snprintf(tmp, sizeof(tmp), "%d", (nvram_get_int("ipv6_tun_mtu") > 0) ? nvram_get_int("ipv6_tun_mtu") : 1280);
|
|
break;
|
|
case IPV6_6RD: /* use wan mtu and calculate it */
|
|
case IPV6_6RD_DHCP:
|
|
snprintf(tmp, sizeof(tmp), "%d", (nvram_get_int("wan_mtu") > 0) ? (nvram_get_int("wan_mtu") - 20) : 1280);
|
|
break;
|
|
default:
|
|
snprintf(tmp, sizeof(tmp), "%d", (nvram_get_int("wan_mtu") > 0) ? nvram_get_int("wan_mtu") : 1280);
|
|
break;
|
|
}
|
|
|
|
/* enable-ra should be enabled in both cases (SLAAC and/or DHCPv6) */
|
|
if ((nvram_get_int("ipv6_radvd")) || (nvram_get_int("ipv6_dhcpd"))) {
|
|
fprintf(f, "enable-ra\n");
|
|
if (nvram_get_int("ipv6_fast_ra"))
|
|
fprintf(f, "ra-param=br*, mtu:%s, 15, 600\n", tmp); /* interface = br*, mtu = XYZ, ra-interval = 15 sec, router-lifetime = 600 sec (10 min) */
|
|
else /* default case */
|
|
fprintf(f, "ra-param=br*, mtu:%s, 60, 1200\n", tmp); /* interface = br*, mtu = XYZ, ra-interval = 60 sec, router-lifetime = 1200 sec (20 min) */
|
|
}
|
|
|
|
/* Check for DHCPv6 PD (and use IPv6 preferred lifetime in that case) */
|
|
if (service == IPV6_NATIVE_DHCP) {
|
|
ipv6_lease = nvram_get_int("ipv6_pd_pltime"); /* get IPv6 preferred lifetime (seconds) */
|
|
if ((ipv6_lease < IPV6_MIN_LIFETIME) || (ipv6_lease > ONEMONTH_LIFETIME)) /* check lease time and limit the range (120 sec up to one month) */
|
|
ipv6_lease = IPV6_MIN_LIFETIME;
|
|
|
|
/* only SLAAC and NO DHCPv6 */
|
|
if ((nvram_get_int("ipv6_radvd")) && (!nvram_get_int("ipv6_dhcpd")))
|
|
fprintf(f, "dhcp-range=::, constructor:br*, ra-names, ra-stateless, 64, %ds\n", ipv6_lease);
|
|
|
|
/* only DHCPv6 and NO SLAAC */
|
|
if ((nvram_get_int("ipv6_dhcpd")) && (!nvram_get_int("ipv6_radvd")))
|
|
fprintf(f, "dhcp-range=::2, ::FFFF:FFFF, constructor:br*, 64, %ds\n", ipv6_lease);
|
|
|
|
/* SLAAC and DHCPv6 (2 IPv6 IPs) */
|
|
if ((nvram_get_int("ipv6_radvd")) && (nvram_get_int("ipv6_dhcpd")))
|
|
fprintf(f, "dhcp-range=::2, ::FFFF:FFFF, constructor:br*, ra-names, 64, %ds\n", ipv6_lease);
|
|
}
|
|
else {
|
|
ipv6_lease = nvram_get_int("ipv6_lease_time"); /* get DHCP IPv6 lease time via GUI */
|
|
if ((ipv6_lease < 1) || (ipv6_lease > 720)) /* check lease time and limit the range (1...720 hours, 30 days should be enough) */
|
|
ipv6_lease = 12;
|
|
|
|
/* only SLAAC and NO DHCPv6 */
|
|
if ((nvram_get_int("ipv6_radvd")) && (!nvram_get_int("ipv6_dhcpd")))
|
|
fprintf(f, "dhcp-range=::, constructor:br*, ra-names, ra-stateless, 64, %dh\n", ipv6_lease);
|
|
|
|
/* only DHCPv6 and NO SLAAC */
|
|
if ((nvram_get_int("ipv6_dhcpd")) && (!nvram_get_int("ipv6_radvd")))
|
|
fprintf(f, "dhcp-range=::2, ::FFFF:FFFF, constructor:br*, 64, %dh\n", ipv6_lease);
|
|
|
|
/* SLAAC and DHCPv6 (2 IPv6 IPs) */
|
|
if ((nvram_get_int("ipv6_radvd")) && (nvram_get_int("ipv6_dhcpd")))
|
|
fprintf(f, "dhcp-range=::2, ::FFFF:FFFF, constructor:br*, ra-names, 64, %dh\n", ipv6_lease);
|
|
}
|
|
|
|
/* check for SLAAC and/or DHCPv6 */
|
|
if ((nvram_get_int("ipv6_radvd")) || (nvram_get_int("ipv6_dhcpd"))) {
|
|
char dns6[MAX_DNS6_SERVER_LAN][INET6_ADDRSTRLEN] = {{0}, {0}};
|
|
char word[INET6_ADDRSTRLEN], *next;
|
|
struct in6_addr addr;
|
|
int cntdns = 0;
|
|
|
|
/* first check DNS servers (DNS1 + DNS2) via GUI (advanced-dhcpdns.asp)
|
|
* and verify that this is a valid IPv6 address
|
|
*/
|
|
foreach (word, nvram_safe_get("ipv6_dns_lan"), next) {
|
|
if ((cntdns < MAX_DNS6_SERVER_LAN) && (inet_pton(AF_INET6, word, &addr) == 1)) {
|
|
strlcpy(dns6[cntdns], ipv6_address(word), INET6_ADDRSTRLEN);
|
|
cntdns++;
|
|
}
|
|
}
|
|
|
|
if (cntdns == 2) {
|
|
fprintf(f, "dhcp-option=option6:dns-server,[%s],[%s]\n", dns6[0], dns6[1]); /* take FT user DNS1 + DNS2 address */
|
|
}
|
|
else if (cntdns == 1) {
|
|
fprintf(f, "dhcp-option=option6:dns-server,[%s]\n", dns6[0]); /* take FT user DNS1 address */
|
|
}
|
|
/* Default - No DNS server via GUI (advanced-dhcpdns.asp) */
|
|
else {
|
|
fprintf(f, "dhcp-option=option6:dns-server,%s\n", "[::]"); /* use global address */
|
|
}
|
|
}
|
|
|
|
/* SNTP & NTP server */
|
|
if (nvram_get_int("ntpd_enable")) {
|
|
fprintf(f, "dhcp-option=option6:31,%s\n", "[::]");
|
|
fprintf(f, "dhcp-option=option6:56,%s\n", "[::]");
|
|
}
|
|
}
|
|
#endif /* TCONFIG_IPV6 */
|
|
|
|
fprintf(f, "edns-packet-max=%d\n", nvram_get_int("dnsmasq_edns_size"));
|
|
|
|
#ifdef TCONFIG_USB_EXTRAS
|
|
if (nvram_get_int("dnsmasq_tftp")) {
|
|
fprintf(f, "enable-tftp\n"
|
|
"tftp-no-fail\n"
|
|
"tftp-root=%s\n",
|
|
nvram_safe_get("dnsmasq_tftp_path"));
|
|
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
snprintf(buf, sizeof(buf), "dnsmasq_pxelan%d", i);
|
|
snprintf(tmp, sizeof(tmp), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
if (nvram_get_int(buf) && strlen(nvram_safe_get(tmp)) > 0) {
|
|
snprintf(tmp, sizeof(tmp), (i == 0 ? "lan_ipaddr" : "lan%d_ipaddr"), i);
|
|
fprintf(f, "dhcp-boot=pxelinux.0,,%s\n", nvram_safe_get(tmp));
|
|
}
|
|
}
|
|
}
|
|
#endif /* TCONFIG_USB_EXTRAS */
|
|
|
|
if (!nvram_get_int("dnsmasq_safe")) {
|
|
fprintf(f, "%s\n", nvram_safe_get("dnsmasq_custom"));
|
|
fappend(f, "/etc/dnsmasq.custom");
|
|
}
|
|
else
|
|
logmsg(LOG_WARNING, "Warning! Dnsmasq Custom configuration contains a disruptive syntax error. The Custom configuration is now excluded to allow dnsmasq to operate");
|
|
|
|
fappend(f, "/etc/dnsmasq.ipset");
|
|
|
|
fclose(f);
|
|
|
|
if (do_dns) {
|
|
unlink(RESOLV_CONF);
|
|
symlink("/rom/etc/resolv.conf", RESOLV_CONF); /* nameserver 127.0.0.1 */
|
|
}
|
|
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
stop_dnscrypt();
|
|
start_dnscrypt();
|
|
#endif
|
|
#ifdef TCONFIG_STUBBY
|
|
stop_stubby();
|
|
start_stubby();
|
|
#endif
|
|
|
|
/* default to some values we like, but allow the user to override them */
|
|
eval("dnsmasq", "-c", "4096", "--log-async");
|
|
|
|
// if (!nvram_contains_word("debug_norestart", "dnsmasq"))
|
|
// pid_dnsmasq = -2;
|
|
}
|
|
|
|
void stop_dnsmasq(void)
|
|
{
|
|
if (serialize_restart("dnsmasq", 0))
|
|
return;
|
|
|
|
// pid_dnsmasq = -1;
|
|
|
|
unlink(RESOLV_CONF);
|
|
symlink(dmresolv, RESOLV_CONF);
|
|
|
|
killall_tk_period_wait("dnsmasq", 50);
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
stop_dnscrypt();
|
|
#endif
|
|
#ifdef TCONFIG_STUBBY
|
|
stop_stubby();
|
|
#endif
|
|
}
|
|
|
|
void reload_dnsmasq(void)
|
|
{
|
|
/* notify dnsmasq */
|
|
killall("dnsmasq", SIGINT);
|
|
}
|
|
|
|
void clear_resolv(void)
|
|
{
|
|
logmsg(LOG_DEBUG, "*** %s: clear all DNS entries", __FUNCTION__);
|
|
f_write(dmresolv, NULL, 0, 0, 0); /* blank */
|
|
}
|
|
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
void start_dnscrypt(void)
|
|
{
|
|
const static char *dnscrypt_resolv = "/etc/dnscrypt-resolvers.csv";
|
|
const static char *dnscrypt_resolv_alt = "/etc/dnscrypt-resolvers-alt.csv";
|
|
char dnscrypt_local[30];
|
|
char *dnscrypt_ekeys;
|
|
char *edns1, *edns2;
|
|
|
|
if (!nvram_get_int("dnscrypt_proxy"))
|
|
return;
|
|
|
|
if (serialize_restart("dnscrypt-proxy", 1))
|
|
return;
|
|
|
|
memset(dnscrypt_local, 0, sizeof(dnscrypt_local));
|
|
snprintf(dnscrypt_local, sizeof(dnscrypt_local), "127.0.0.1:%s", nvram_safe_get("dnscrypt_port"));
|
|
|
|
dnscrypt_ekeys = nvram_get_int("dnscrypt_ephemeral_keys") ? "-E" : "";
|
|
edns1 = nvram_get_int("dnsmasq_edns_size") < 1252 ? "-e" : ""; /* in case of EDNS packet size is set lower than 1252 in dnsmasq, set it also for dnscrypt-proxy */
|
|
edns2 = nvram_get_int("dnsmasq_edns_size") < 1252 ? nvram_safe_get("dnsmasq_edns_size") : "";
|
|
|
|
if (nvram_get_int("dnscrypt_manual"))
|
|
eval("dnscrypt-proxy", "-d", dnscrypt_ekeys,
|
|
"-a", dnscrypt_local,
|
|
"-m", nvram_safe_get("dnscrypt_log"),
|
|
"-N", nvram_safe_get("dnscrypt_provider_name"),
|
|
"-k", nvram_safe_get("dnscrypt_provider_key"),
|
|
"-r", nvram_safe_get("dnscrypt_resolver_address"),
|
|
edns1, edns2);
|
|
else
|
|
eval("dnscrypt-proxy", "-d", dnscrypt_ekeys,
|
|
"-a", dnscrypt_local,
|
|
"-m", nvram_safe_get("dnscrypt_log"),
|
|
"-R", nvram_safe_get("dnscrypt_resolver"),
|
|
edns1, edns2,
|
|
"-L", f_exists(dnscrypt_resolv_alt) ? (char *) dnscrypt_resolv_alt : (char *) dnscrypt_resolv);
|
|
#ifdef TCONFIG_IPV6
|
|
if (get_ipv6_service()) { /* when ipv6 enabled */
|
|
memset(dnscrypt_local, 0, sizeof(dnscrypt_local));
|
|
snprintf(dnscrypt_local, sizeof(dnscrypt_local), "::1:%s", nvram_safe_get("dnscrypt_port"));
|
|
|
|
if (nvram_get_int("dnscrypt_manual"))
|
|
eval("dnscrypt-proxy", "-d", dnscrypt_ekeys,
|
|
"-a", dnscrypt_local,
|
|
"-m", nvram_safe_get("dnscrypt_log"),
|
|
"-N", nvram_safe_get("dnscrypt_provider_name"),
|
|
"-k", nvram_safe_get("dnscrypt_provider_key"),
|
|
"-r", nvram_safe_get("dnscrypt_resolver_address"),
|
|
edns1, edns2);
|
|
else
|
|
eval("dnscrypt-proxy", "-d", dnscrypt_ekeys,
|
|
"-a", dnscrypt_local,
|
|
"-m", nvram_safe_get("dnscrypt_log"),
|
|
"-R", nvram_safe_get("dnscrypt_resolver"),
|
|
edns1, edns2,
|
|
"-L", f_exists(dnscrypt_resolv_alt) ? (char *) dnscrypt_resolv_alt : (char *) dnscrypt_resolv);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void stop_dnscrypt(void)
|
|
{
|
|
if (serialize_restart("dnscrypt-proxy", 0))
|
|
return;
|
|
|
|
killall_tk_period_wait("dnscrypt-proxy", 50);
|
|
}
|
|
#endif /* TCONFIG_DNSCRYPT */
|
|
|
|
#ifdef TCONFIG_STUBBY
|
|
void start_stubby(void)
|
|
{
|
|
const static char *stubby_config = "/etc/stubby/stubby.yml";
|
|
FILE *fp;
|
|
char *nv, *nvp, *b;
|
|
char *server, *tlsport, *hostname, *spkipin, *digest;
|
|
int ntp_ready, port, dnssec, ret;
|
|
union {
|
|
struct in_addr addr4;
|
|
#ifdef TCONFIG_IPV6
|
|
struct in6_addr addr6;
|
|
#endif
|
|
} addr;
|
|
|
|
if (!nvram_get_int("stubby_proxy"))
|
|
return;
|
|
|
|
if (serialize_restart("stubby", 1))
|
|
return;
|
|
|
|
mkdir_if_none("/etc/stubby");
|
|
|
|
/* alternative (user) configuration file */
|
|
if (f_exists("/etc/stubby/stubby_alt.yml")) {
|
|
eval("stubby", "-g", "-C", "/etc/stubby/stubby_alt.yml");
|
|
return;
|
|
}
|
|
|
|
if ((fp = fopen(stubby_config, "w")) == NULL) {
|
|
logerr(__FUNCTION__, __LINE__, stubby_config);
|
|
return;
|
|
}
|
|
|
|
ntp_ready = nvram_get_int("ntp_ready");
|
|
dnssec = (nvram_get_int("dnssec_enable") && nvram_match("dnssec_method", "1"));
|
|
|
|
/* basic & privacy settings */
|
|
fprintf(fp, "appdata_dir: \"/var/lib/misc\"\n"
|
|
"resolution_type: GETDNS_RESOLUTION_STUB\n"
|
|
"dns_transport_list:\n"
|
|
"%s"
|
|
"tls_authentication: %s\n"
|
|
"tls_query_padding_blocksize: 128\n"
|
|
"edns_client_subnet_private: 1\n"
|
|
"%s"
|
|
/* connection settings */
|
|
"idle_timeout: 5000\n"
|
|
"tls_connection_retries: 5\n"
|
|
"tls_backoff_time: 900\n"
|
|
"timeout: 2000\n"
|
|
"round_robin_upstreams: 1\n"
|
|
"tls_min_version: %s\n"
|
|
/* listen address */
|
|
"listen_addresses:\n"
|
|
" - 127.0.0.1@%s\n",
|
|
ntp_ready ? " - GETDNS_TRANSPORT_TLS\n" : " - GETDNS_TRANSPORT_UDP\n - GETDNS_TRANSPORT_TCP\n",
|
|
ntp_ready ? "GETDNS_AUTHENTICATION_REQUIRED" : "GETDNS_AUTHENTICATION_NONE",
|
|
(ntp_ready && dnssec) ? "dnssec: GETDNS_EXTENSION_TRUE\n" : "",
|
|
nvram_get_int("stubby_force_tls13") ? "GETDNS_TLS1_3" : "GETDNS_TLS1_2",
|
|
nvram_safe_get("stubby_port"));
|
|
#ifdef TCONFIG_IPV6
|
|
if (get_ipv6_service()) /* when ipv6 enabled */
|
|
fprintf(fp, " - 0::1@%s\n", nvram_safe_get("stubby_port"));
|
|
#endif
|
|
/* upstreams */
|
|
fprintf(fp, "upstream_recursive_servers:\n");
|
|
|
|
nv = nvp = strdup(nvram_safe_get("stubby_resolvers"));
|
|
while (nvp && (b = strsep(&nvp, "<")) != NULL) {
|
|
server = tlsport = hostname = spkipin = NULL;
|
|
|
|
/* <server>port>hostname>[digest:]spkipin */
|
|
if ((vstrsep(b, ">", &server, &tlsport, &hostname, &spkipin)) < 4)
|
|
continue;
|
|
|
|
/* check server, can be IPv4/IPv6 address */
|
|
if (*server == '\0')
|
|
continue;
|
|
else if (inet_pton(AF_INET, server, &addr) <= 0
|
|
#ifdef TCONFIG_IPV6
|
|
&& ((inet_pton(AF_INET6, server, &addr) <= 0) || (!ipv6_enabled()))
|
|
#endif
|
|
)
|
|
continue;
|
|
|
|
/* check port, if specified */
|
|
port = (*tlsport ? atoi(tlsport) : 0);
|
|
if ((port < 0) || (port > 65535))
|
|
continue;
|
|
|
|
/* add server */
|
|
fprintf(fp, " - address_data: %s\n", server);
|
|
if (port)
|
|
fprintf(fp, " tls_port: %d\n", port);
|
|
if (*hostname)
|
|
fprintf(fp, " tls_auth_name: \"%s\"\n", hostname);
|
|
if (*spkipin) {
|
|
digest = strchr(spkipin, ':') ? strsep(&spkipin, ":") : "sha256";
|
|
fprintf(fp, " tls_pubkey_pinset:\n"
|
|
" - digest: \"%s\"\n"
|
|
" value: %s\n", digest, spkipin);
|
|
}
|
|
}
|
|
if (nv)
|
|
free(nv);
|
|
|
|
fclose(fp);
|
|
|
|
if (dnssec) {
|
|
if (ntp_ready)
|
|
logmsg(LOG_INFO, "stubby: DNSSEC enabled");
|
|
else
|
|
logmsg(LOG_INFO, "stubby: DNSSEC pending ntp sync");
|
|
}
|
|
|
|
ret = eval("stubby", "-g", "-v", nvram_safe_get("stubby_log"), "-C", (char *)stubby_config);
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting stubby failed ...");
|
|
}
|
|
|
|
void stop_stubby(void)
|
|
{
|
|
if (serialize_restart("stubby", 0))
|
|
return;
|
|
|
|
killall_tk_period_wait("stubby", 70);
|
|
eval("rm", "-f", "/var/run/stubby.pid");
|
|
}
|
|
#endif /* TCONFIG_STUBBY */
|
|
|
|
#ifdef TCONFIG_MDNS
|
|
void generate_mdns_config(void)
|
|
{
|
|
FILE *fp;
|
|
char avahi_config[80];
|
|
|
|
snprintf(avahi_config, sizeof(avahi_config), "%s/%s", AVAHI_CONFIG_PATH, AVAHI_CONFIG_FN);
|
|
|
|
/* generate avahi configuration file */
|
|
if (!(fp = fopen(avahi_config, "w"))) {
|
|
logerr(__FUNCTION__, __LINE__, avahi_config);
|
|
return;
|
|
}
|
|
|
|
/* set [server] configuration */
|
|
fprintf(fp, "[Server]\n"
|
|
"use-ipv4=yes\n"
|
|
"use-ipv6=%s\n"
|
|
"deny-interfaces=%s",
|
|
ipv6_enabled() ? "yes" : "no",
|
|
get_wanface("wan"));
|
|
|
|
if (check_wanup("wan2"))
|
|
fprintf(fp, ",%s", get_wanface("wan2"));
|
|
#ifdef TCONFIG_MULTIWAN
|
|
if (check_wanup("wan3"))
|
|
fprintf(fp, ",%s", get_wanface("wan3"));
|
|
if (check_wanup("wan4"))
|
|
fprintf(fp, ",%s", get_wanface("wan4"));
|
|
#endif
|
|
|
|
fprintf(fp, "\n"
|
|
"ratelimit-interval-usec=1000000\n"
|
|
"ratelimit-burst=1000\n");
|
|
|
|
/* set [publish] configuration */
|
|
fprintf(fp, "\n[publish]\n"
|
|
"publish-hinfo=yes\n"
|
|
"publish-a-on-ipv6=no\n"
|
|
"publish-aaaa-on-ipv4=%s\n",
|
|
ipv6_enabled() ? "yes" : "no");
|
|
|
|
/* set [reflector] configuration */
|
|
fprintf(fp, "\n[reflector]\n");
|
|
if (nvram_get_int("mdns_reflector"))
|
|
fprintf(fp, "enable-reflector=yes\n");
|
|
|
|
/* set [rlimits] configuration */
|
|
fprintf(fp, "\n[rlimits]\n"
|
|
"rlimit-core=0\n"
|
|
"rlimit-data=4194304\n"
|
|
"rlimit-fsize=0\n"
|
|
"rlimit-nofile=256\n"
|
|
"rlimit-stack=4194304\n"
|
|
"rlimit-nproc=3\n");
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
void start_mdns(void)
|
|
{
|
|
if (nvram_get_int("g_upgrade") || nvram_get_int("g_reboot"))
|
|
return;
|
|
|
|
if (!nvram_get_int("mdns_enable"))
|
|
return;
|
|
|
|
if (serialize_restart("avahi-daemon", 1))
|
|
return;
|
|
|
|
mkdir_if_none(AVAHI_CONFIG_PATH);
|
|
mkdir_if_none(AVAHI_SERVICES_PATH);
|
|
|
|
/* alternative (user) configuration file */
|
|
if (f_exists(AVAHI_CONFIG_PATH"/avahi-daemon_alt.conf"))
|
|
eval("avahi-daemon", "-D", "-f", AVAHI_CONFIG_PATH"/avahi-daemon_alt.conf", (nvram_get_int("mdns_debug") ? "--debug" : NULL));
|
|
else {
|
|
generate_mdns_config();
|
|
eval("avahi-daemon", "-D", (nvram_get_int("mdns_debug") ? "--debug" : NULL));
|
|
}
|
|
}
|
|
|
|
void stop_mdns(void)
|
|
{
|
|
if (serialize_restart("avahi-daemon", 0))
|
|
return;
|
|
|
|
killall_tk_period_wait("avahi-daemon", 50);
|
|
}
|
|
#endif /* TCONFIG_MDNS */
|
|
|
|
#ifdef TCONFIG_IRQBALANCE
|
|
void stop_irqbalance(void)
|
|
{
|
|
if (serialize_restart("irqbalance", 0))
|
|
return;
|
|
|
|
if (pidof("irqbalance") > 0) {
|
|
killall_tk_period_wait("irqbalance", 50);
|
|
logmsg(LOG_INFO, "irqbalance is stopped");
|
|
}
|
|
}
|
|
|
|
void start_irqbalance(void)
|
|
{
|
|
int ret;
|
|
|
|
if (serialize_restart("irqbalance", 1))
|
|
return;
|
|
|
|
ret = eval("irqbalance", "-t", "10", "-s", "/var/run/irqbalance.pid");
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting irqbalance failed ...");
|
|
else
|
|
logmsg(LOG_INFO, "irqbalance is started");
|
|
}
|
|
#endif /* TCONFIG_IRQBALANCE */
|
|
|
|
#ifdef TCONFIG_FANCTRL
|
|
void start_phy_tempsense()
|
|
{
|
|
stop_phy_tempsense();
|
|
/* renice to high priority (10) - avoid revs fluctuations on high CPU load */
|
|
char *phy_tempsense_argv[] = { "nice", "-n", "-10", "phy_tempsense", NULL };
|
|
_eval(phy_tempsense_argv, NULL, 0, &pid_phy_tempsense);
|
|
}
|
|
|
|
void stop_phy_tempsense()
|
|
{
|
|
pid_phy_tempsense = -1;
|
|
killall_tk_period_wait("phy_tempsense", 50);
|
|
}
|
|
#endif /* TCONFIG_FANCTRL */
|
|
|
|
void start_adblock(int update)
|
|
{
|
|
if (nvram_get_int("g_upgrade") || nvram_get_int("g_reboot"))
|
|
return;
|
|
|
|
if (!nvram_get_int("adblock_enable"))
|
|
return;
|
|
|
|
killall("adblock", SIGTERM);
|
|
sleep(1);
|
|
if (update)
|
|
xstart(ADBLOCK_EXE, "update");
|
|
else
|
|
xstart(ADBLOCK_EXE);
|
|
}
|
|
|
|
void stop_adblock()
|
|
{
|
|
xstart(ADBLOCK_EXE, "stop");
|
|
}
|
|
|
|
#ifdef TCONFIG_IPV6
|
|
static int write_ipv6_dns_servers(FILE *f, const char *prefix, char *dns, const char *suffix, int once)
|
|
{
|
|
char p[INET6_ADDRSTRLEN + 1], *next = NULL;
|
|
struct in6_addr addr;
|
|
int cnt = 0;
|
|
|
|
foreach(p, dns, next) {
|
|
/* verify that this is a valid IPv6 address */
|
|
if (inet_pton(AF_INET6, p, &addr) == 1) {
|
|
fprintf(f, "%s%s%s", (once && cnt) ? "" : prefix, p, suffix);
|
|
++cnt;
|
|
}
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
#endif
|
|
|
|
void dns_to_resolv(void)
|
|
{
|
|
FILE *f;
|
|
const dns_list_t *dns;
|
|
char *trig_ip;
|
|
int i;
|
|
mode_t m;
|
|
char wan_prefix[] = "wanXX";
|
|
int wan_unit, mwan_num;
|
|
int append = 0;
|
|
int exclusive = 0;
|
|
char tmp[64];
|
|
|
|
mwan_num = nvram_get_int("mwan_num");
|
|
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
|
|
mwan_num = 1;
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
|
|
/* skip inactive WAN connections */
|
|
if ((check_wanup(wan_prefix) == 0) &&
|
|
get_wanx_proto(wan_prefix) != WP_DISABLED &&
|
|
get_wanx_proto(wan_prefix) != WP_PPTP &&
|
|
get_wanx_proto(wan_prefix) != WP_L2TP &&
|
|
!nvram_get_int(strlcat_r(wan_prefix, "_ppp_demand", tmp, sizeof(tmp))))
|
|
{
|
|
logmsg(LOG_DEBUG, "*** %s: %s (proto:%d) is not UP, not P-t-P or On Demand, SKIP ADD", __FUNCTION__, wan_prefix, get_wanx_proto(wan_prefix));
|
|
continue;
|
|
}
|
|
else {
|
|
logmsg(LOG_DEBUG, "*** %s: %s (proto:%d) is OK to ADD", __FUNCTION__, wan_prefix, get_wanx_proto(wan_prefix));
|
|
append++;
|
|
}
|
|
m = umask(022); /* 077 from pppoecd */
|
|
if ((f = fopen(dmresolv, (append == 1) ? "w" : "a")) != NULL) { /* write / append */
|
|
if (append == 1)
|
|
/* check for VPN DNS entries */
|
|
exclusive = (write_pptp_client_resolv(f)
|
|
#ifdef TCONFIG_OPENVPN
|
|
|| write_ovpn_resolv(f)
|
|
#endif
|
|
);
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: exclusive: %d", __FUNCTION__, exclusive);
|
|
if (!exclusive) { /* exclusive check */
|
|
#ifdef TCONFIG_IPV6
|
|
if ((write_ipv6_dns_servers(f, "nameserver ", nvram_safe_get("ipv6_dns"), "\n", 0) == 0) || (nvram_get_int("wan_addget"))) /* addget only for the first WAN */
|
|
if (append == 1) /* only once */
|
|
write_ipv6_dns_servers(f, "nameserver ", nvram_safe_get("ipv6_get_dns"), "\n", 0);
|
|
#endif
|
|
dns = get_dns(wan_prefix); /* static buffer */
|
|
if (dns->count == 0) {
|
|
/* put a pseudo DNS IP to trigger Connect On Demand */
|
|
if (nvram_match(strlcat_r(wan_prefix, "_ppp_demand", tmp, sizeof(tmp)), "1")) {
|
|
switch (get_wanx_proto(wan_prefix)) {
|
|
case WP_PPPOE:
|
|
case WP_PPP3G:
|
|
case WP_PPTP:
|
|
case WP_L2TP:
|
|
/* The nameserver IP specified below used to be 1.1.1.1, however this became an legit IP address of a public recursive DNS server,
|
|
* defeating the purpose of specifying a bogus DNS server in order to trigger Connect On Demand.
|
|
* An IP address from TEST-NET-2 block was chosen here, as RFC 5737 explicitly states this address block
|
|
* should be non-routable over the public internet. In effect since January 2010.
|
|
* Further info: http://linksysinfo.org/index.php?threads/tomato-using-1-1-1-1-for-pppoe-connect-on-demand.74102
|
|
* Also add possibility to change that IP (198.51.100.1) in GUI by the user
|
|
*/
|
|
trig_ip = nvram_safe_get(strlcat_r(wan_prefix, "_ppp_demand_dnsip", tmp, sizeof(tmp)));
|
|
logmsg(LOG_DEBUG, "*** %s: no servers for %s: put a pseudo DNS (non-routable on public internet) IP %s to trigger Connect On Demand", __FUNCTION__, wan_prefix, trig_ip);
|
|
fprintf(f, "nameserver %s\n", trig_ip);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fprintf(f, "# dns for %s:\n", wan_prefix);
|
|
for (i = 0; i < dns->count; i++) {
|
|
if (dns->dns[i].port == 53) { /* resolv.conf doesn't allow for an alternate port */
|
|
fprintf(f, "nameserver %s\n", inet_ntoa(dns->dns[i].addr));
|
|
logmsg(LOG_DEBUG, "*** %s: %s DNS %s to %s [%s]", ((append == 1) ? "write" : "append"), __FUNCTION__, inet_ntoa(dns->dns[i].addr), dmresolv, wan_prefix);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fclose(f);
|
|
}
|
|
else {
|
|
logerr(__FUNCTION__, __LINE__, dmresolv);
|
|
return;
|
|
}
|
|
umask(m);
|
|
|
|
} /* end for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) */
|
|
}
|
|
|
|
void start_httpd(void)
|
|
{
|
|
int ret;
|
|
|
|
if (serialize_restart("httpd", 1))
|
|
return;
|
|
|
|
if (nvram_match("web_css", "online"))
|
|
xstart("/usr/sbin/ttb");
|
|
|
|
/* set www dir */
|
|
if (nvram_match("web_dir", "jffs"))
|
|
chdir("/jffs/www");
|
|
else if (nvram_match("web_dir", "opt"))
|
|
chdir("/opt/www");
|
|
else if (nvram_match("web_dir", "tmp"))
|
|
chdir("/tmp/www");
|
|
else
|
|
chdir("/www");
|
|
|
|
sleep(1);
|
|
ret = eval("httpd", (nvram_get_int("http_nocache") ? "-N" : ""));
|
|
chdir("/");
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting httpd failed ...");
|
|
else
|
|
logmsg(LOG_INFO, "httpd is started");
|
|
}
|
|
|
|
void stop_httpd(void)
|
|
{
|
|
if (serialize_restart("httpd", 0))
|
|
return;
|
|
|
|
if (pidof("httpd") > 0) {
|
|
killall_tk_period_wait("httpd", 50);
|
|
logmsg(LOG_INFO, "httpd is stopped");
|
|
}
|
|
}
|
|
|
|
#ifdef TCONFIG_IPV6
|
|
static void add_ip6_lanaddr(void)
|
|
{
|
|
char ip[INET6_ADDRSTRLEN + 4];
|
|
const char *p;
|
|
|
|
p = ipv6_router_address(NULL);
|
|
if (*p) {
|
|
snprintf(ip, sizeof(ip), "%s/%d", p, nvram_get_int("ipv6_prefix_length") ? : 64);
|
|
|
|
eval("ip", "-6", "addr", "add", ip, "dev", nvram_safe_get("lan_ifname"));
|
|
}
|
|
}
|
|
|
|
void start_ipv6_tunnel(void)
|
|
{
|
|
char ip[INET6_ADDRSTRLEN + 4];
|
|
char ip_tmp[INET6_ADDRSTRLEN + 4];
|
|
struct in_addr addr4;
|
|
struct in6_addr addr;
|
|
char *wanip, *mtu, *tun_dev;
|
|
int service;
|
|
char wan_prefix[] = "wanXX";
|
|
int wan_unit, mwan_num;
|
|
|
|
mwan_num = nvram_get_int("mwan_num");
|
|
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
|
|
mwan_num = 1;
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
if (check_wanup(wan_prefix))
|
|
break;
|
|
}
|
|
|
|
service = get_ipv6_service();
|
|
tun_dev = (char *)get_wan6face();
|
|
wanip = (char *)get_wanip(wan_prefix);
|
|
|
|
mtu = (nvram_get_int("ipv6_tun_mtu") > 0) ? nvram_safe_get("ipv6_tun_mtu") : "1480";
|
|
|
|
modprobe("sit");
|
|
|
|
eval("ip", "tunnel", "add", tun_dev, "mode", "sit", "remote", (service == IPV6_ANYCAST_6TO4) ? "any" : nvram_safe_get("ipv6_tun_v4end"), "local", wanip, "ttl", nvram_safe_get("ipv6_tun_ttl"));
|
|
eval("ip", "link", "set", tun_dev, "mtu", mtu, "up");
|
|
|
|
nvram_set("ipv6_ifname", tun_dev);
|
|
|
|
if (service == IPV6_ANYCAST_6TO4) {
|
|
int prefixlen = 16;
|
|
int mask4size = 0;
|
|
|
|
addr4.s_addr = 0;
|
|
memset(&addr, 0, sizeof(addr));
|
|
inet_aton(wanip, &addr4);
|
|
addr.s6_addr16[0] = htons(0x2002);
|
|
ipv6_mapaddr4(&addr, prefixlen, &addr4, mask4size);
|
|
addr.s6_addr16[7] = htons(0x0001);
|
|
inet_ntop(AF_INET6, &addr, ip_tmp, sizeof(ip_tmp));
|
|
snprintf(ip, sizeof(ip), "%s/%d", ip_tmp, prefixlen);
|
|
add_ip6_lanaddr();
|
|
}
|
|
/* static tunnel 6to4 */
|
|
else
|
|
snprintf(ip, sizeof(ip), "%s/%d", nvram_safe_get("ipv6_tun_addr"), nvram_get_int("ipv6_tun_addrlen") ? : 64);
|
|
|
|
eval("ip", "-6", "addr", "add", ip, "dev", tun_dev);
|
|
|
|
if (service == IPV6_ANYCAST_6TO4) {
|
|
snprintf(ip, sizeof(ip), "::192.88.99.%d", nvram_get_int("ipv6_relay"));
|
|
eval("ip", "-6", "route", "add", "2000::/3", "via", ip, "dev", tun_dev, "metric", "1");
|
|
}
|
|
else
|
|
eval("ip", "-6", "route", "add", "::/0", "dev", tun_dev, "metric", "1");
|
|
|
|
/* (re)start dnsmasq */
|
|
if (service == IPV6_ANYCAST_6TO4) {
|
|
stop_dnsmasq();
|
|
start_dnsmasq();
|
|
}
|
|
}
|
|
|
|
void stop_ipv6_tunnel(void)
|
|
{
|
|
eval("ip", "tunnel", "del", (char *)get_wan6face());
|
|
|
|
if (get_ipv6_service() == IPV6_ANYCAST_6TO4)
|
|
/* get rid of old IPv6 address from lan iface */
|
|
eval("ip", "-6", "addr", "flush", "dev", nvram_safe_get("lan_ifname"), "scope", "global");
|
|
|
|
modprobe_r("sit");
|
|
}
|
|
|
|
void start_6rd_tunnel(void)
|
|
{
|
|
const char *tun_dev, *wanip;
|
|
int service, mask_len, prefix_len, local_prefix_len;
|
|
char mtu[10], prefix[INET6_ADDRSTRLEN], relay[INET_ADDRSTRLEN];
|
|
struct in_addr netmask_addr, relay_addr, relay_prefix_addr, wanip_addr;
|
|
struct in6_addr prefix_addr, local_prefix_addr;
|
|
char local_prefix[INET6_ADDRSTRLEN];
|
|
char tmp_ipv6[INET6_ADDRSTRLEN + 4], tmp_ipv4[INET_ADDRSTRLEN + 4];
|
|
char tmp[256];
|
|
FILE *f;
|
|
char wan_prefix[] = "wanXX";
|
|
int wan_unit, mwan_num;
|
|
|
|
mwan_num = nvram_get_int("mwan_num");
|
|
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
|
|
mwan_num = 1;
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
if (check_wanup(wan_prefix))
|
|
break;
|
|
}
|
|
|
|
service = get_ipv6_service();
|
|
wanip = get_wanip(wan_prefix);
|
|
tun_dev = get_wan6face();
|
|
memset(mtu, 0, sizeof(mtu));
|
|
snprintf(mtu, sizeof(mtu), "%d", (nvram_get_int("wan_mtu") > 0) ? (nvram_get_int("wan_mtu") - 20) : 1280);
|
|
|
|
/* maybe we can merge the ipv6_6rd_* variables into a single ipv_6rd_string (ala wan_6rd) to save nvram space? */
|
|
if (service == IPV6_6RD) {
|
|
logmsg(LOG_DEBUG, "*** %s: starting 6rd tunnel using manual settings", __FUNCTION__);
|
|
mask_len = nvram_get_int("ipv6_6rd_ipv4masklen");
|
|
prefix_len = nvram_get_int("ipv6_6rd_prefix_length");
|
|
strlcpy(prefix, nvram_safe_get("ipv6_6rd_prefix"), sizeof(prefix));
|
|
strlcpy(relay, nvram_safe_get("ipv6_6rd_borderrelay"), sizeof(relay));
|
|
}
|
|
else {
|
|
logmsg(LOG_DEBUG, "*** %s: starting 6rd tunnel using automatic settings", __FUNCTION__);
|
|
char *wan_6rd = nvram_safe_get("wan_6rd");
|
|
if (sscanf(wan_6rd, "%d %d %s %s", &mask_len, &prefix_len, prefix, relay) < 4) {
|
|
logmsg(LOG_DEBUG, "*** %s: wan_6rd string is missing or invalid (%s)", __FUNCTION__, wan_6rd);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* validate values that were passed */
|
|
if ((mask_len < 0) || (mask_len > 32)) {
|
|
logmsg(LOG_DEBUG, "*** %s: invalid mask_len value (%d)", __FUNCTION__, mask_len);
|
|
return;
|
|
}
|
|
if ((prefix_len < 0) || (prefix_len > 128)) {
|
|
logmsg(LOG_DEBUG, "*** %s: invalid prefix_len value (%d)", __FUNCTION__, prefix_len);
|
|
return;
|
|
}
|
|
if (((32 - mask_len) + prefix_len) > 128) {
|
|
logmsg(LOG_DEBUG, "*** %s: invalid combination of mask_len and prefix_len!", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
memset(tmp, 0, sizeof(tmp));
|
|
snprintf(tmp, sizeof(tmp), "ping -q -c 2 %s | grep packet", relay);
|
|
if ((f = popen(tmp, "r")) == NULL) {
|
|
logmsg(LOG_DEBUG, "*** %s: error obtaining data", __FUNCTION__);
|
|
return;
|
|
}
|
|
fgets(tmp, sizeof(tmp), f);
|
|
pclose(f);
|
|
|
|
if (strstr(tmp, " 0% packet loss") == NULL) {
|
|
logmsg(LOG_DEBUG, "*** %s: failed to ping border relay", __FUNCTION__);
|
|
return;
|
|
}
|
|
|
|
/* get relay prefix from border relay address and mask */
|
|
netmask_addr.s_addr = htonl(0xffffffff << (32 - mask_len));
|
|
inet_aton(relay, &relay_addr);
|
|
relay_prefix_addr.s_addr = relay_addr.s_addr & netmask_addr.s_addr;
|
|
|
|
/* calculate the local prefix */
|
|
inet_pton(AF_INET6, prefix, &prefix_addr);
|
|
inet_pton(AF_INET, wanip, &wanip_addr);
|
|
if (calc_6rd_local_prefix(&prefix_addr, prefix_len, mask_len, &wanip_addr, &local_prefix_addr, &local_prefix_len) == 0) {
|
|
logmsg(LOG_DEBUG, "*** %s: error calculating local prefix", __FUNCTION__);
|
|
return;
|
|
}
|
|
inet_ntop(AF_INET6, &local_prefix_addr, local_prefix, sizeof(local_prefix));
|
|
|
|
snprintf(tmp_ipv6, sizeof(tmp_ipv6), "%s1", local_prefix);
|
|
nvram_set("ipv6_rtr_addr", tmp_ipv6);
|
|
nvram_set("ipv6_prefix", local_prefix);
|
|
|
|
/* load sit module needed for the 6rd tunnel */
|
|
modprobe("sit");
|
|
|
|
/* create the 6rd tunnel */
|
|
eval("ip", "tunnel", "add", (char *)tun_dev, "mode", "sit", "local", (char *)wanip, "ttl", nvram_safe_get("ipv6_tun_ttl"));
|
|
|
|
snprintf(tmp_ipv6, sizeof(tmp_ipv6), "%s/%d", prefix, prefix_len);
|
|
snprintf(tmp_ipv4, sizeof(tmp_ipv4), "%s/%d", inet_ntoa(relay_prefix_addr), mask_len);
|
|
eval("ip", "tunnel" "6rd", "dev", (char *)tun_dev, "6rd-prefix", tmp_ipv6, "6rd-relay_prefix", tmp_ipv4);
|
|
|
|
/* bring up the link */
|
|
eval("ip", "link", "set", "dev", (char *)tun_dev, "mtu", (char *)mtu, "up");
|
|
|
|
/* set the WAN address Note: IPv6 WAN CIDR should be: ((32 - ip6rd_ipv4masklen) + ip6rd_prefixlen) */
|
|
snprintf(tmp_ipv6, sizeof(tmp_ipv6), "%s1/%d", local_prefix, local_prefix_len);
|
|
eval("ip", "-6", "addr", "add", tmp_ipv6, "dev", (char *)tun_dev);
|
|
|
|
/* set the LAN address Note: IPv6 LAN CIDR should be 64 */
|
|
snprintf(tmp_ipv6, sizeof(tmp_ipv6), "%s1/%d", local_prefix, nvram_get_int("ipv6_prefix_length") ? : 64);
|
|
eval("ip", "-6", "addr", "add", tmp_ipv6, "dev", nvram_safe_get("lan_ifname"));
|
|
|
|
/* add default route via the border relay */
|
|
snprintf(tmp_ipv6, sizeof(tmp_ipv6), "::%s", relay);
|
|
eval("ip", "-6", "route", "add", "::/0", "via", tmp_ipv6, "dev", (char *)tun_dev);
|
|
|
|
nvram_set("ipv6_ifname", (char *)tun_dev);
|
|
|
|
/* (re)start dnsmasq */
|
|
stop_dnsmasq();
|
|
start_dnsmasq();
|
|
}
|
|
|
|
void stop_6rd_tunnel(void)
|
|
{
|
|
eval("ip", "tunnel", "del", (char *)get_wan6face());
|
|
eval("ip", "-6", "addr", "flush", "dev", nvram_safe_get("lan_ifname"), "scope", "global");
|
|
|
|
modprobe_r("sit");
|
|
}
|
|
|
|
void start_ipv6(void)
|
|
{
|
|
int service, i;
|
|
char buffer[16];
|
|
|
|
service = get_ipv6_service();
|
|
|
|
/* check if turned on */
|
|
if (service != IPV6_DISABLED) {
|
|
|
|
ipv6_forward("default", 1); /* enable it for default */
|
|
ipv6_forward("all", 1); /* enable it for all */
|
|
ndp_proxy("default", 1);
|
|
ndp_proxy("all", 1);
|
|
|
|
/* check if "ipv6_accept_ra" (bit 1) for lan is enabled (via GUI, basic-ipv6.asp) and "ipv6_radvd" AND "ipv6_dhcpd" (SLAAC and/or DHCP with dnsmasq) is disabled (via GUI, advanced-dhcpdns.asp) */
|
|
/* HINT: "ipv6_accept_ra" bit 0 ==> used for wan, "ipv6_accept_ra" bit 1 ==> used for lan interfaces (br0...br3) */
|
|
/* check lanX / brX if available */
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
memset(buffer, 0, sizeof(buffer));
|
|
snprintf(buffer, sizeof(buffer), (i == 0 ? "lan_ipaddr" : "lan%d_ipaddr"), i);
|
|
if (strcmp(nvram_safe_get(buffer), "") != 0) {
|
|
memset(buffer, 0, sizeof(buffer));
|
|
snprintf(buffer, sizeof(buffer), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
if (((nvram_get_int("ipv6_accept_ra") & 0x02) != 0) && !nvram_get_int("ipv6_radvd") && !nvram_get_int("ipv6_dhcpd"))
|
|
/* accept_ra for brX */
|
|
accept_ra(nvram_safe_get(buffer));
|
|
else
|
|
/* accept_ra default value for brX */
|
|
accept_ra_reset(nvram_safe_get(buffer));
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (service) {
|
|
case IPV6_NATIVE:
|
|
case IPV6_6IN4:
|
|
case IPV6_MANUAL:
|
|
add_ip6_lanaddr();
|
|
break;
|
|
case IPV6_NATIVE_DHCP:
|
|
case IPV6_ANYCAST_6TO4:
|
|
nvram_set("ipv6_rtr_addr", "");
|
|
nvram_set("ipv6_prefix", "");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stop_ipv6(void)
|
|
{
|
|
stop_ipv6_tunnel();
|
|
stop_dhcp6c();
|
|
|
|
ipv6_forward("default", 0); /* disable it for default */
|
|
ipv6_forward("all", 0); /* disable it for all */
|
|
ndp_proxy("default", 0);
|
|
ndp_proxy("all", 0);
|
|
|
|
eval("ip", "-6", "addr", "flush", "scope", "global");
|
|
eval("ip", "-6", "route", "flush", "scope", "global");
|
|
}
|
|
#endif /* TCONFIG_IPV6 */
|
|
|
|
void start_upnp(void)
|
|
{
|
|
FILE *f;
|
|
int enable, upnp_port, https;
|
|
int ports[4];
|
|
char uuid[45];
|
|
char lanN_ipaddr[] = "lanXX_ipaddr";
|
|
char lanN_netmask[] = "lanXX_netmask";
|
|
char lanN_ifname[] = "lanXX_ifname";
|
|
char upnp_lanN[] = "upnp_lanXX";
|
|
char *lanip, *lanmask, *lanifname;
|
|
char br;
|
|
|
|
enable = nvram_get_int("upnp_enable");
|
|
|
|
/* only if enabled and proto not disabled */
|
|
if ((enable == 0) || (get_wan_proto() == WP_DISABLED))
|
|
return;
|
|
|
|
if (serialize_restart("miniupnpd", 1))
|
|
return;
|
|
|
|
add_upnp_defaults(); /* backup: check nvram! */
|
|
|
|
mkdir(UPNP_DIR, 0777);
|
|
|
|
/* alternative configuration file */
|
|
if (f_exists(UPNP_DIR"/config.alt")) {
|
|
xstart("miniupnpd", "-f", UPNP_DIR"/config.alt");
|
|
return;
|
|
}
|
|
|
|
if ((f = fopen(UPNP_CONFIG, "w")) == NULL) {
|
|
logerr(__FUNCTION__, __LINE__, UPNP_CONFIG);
|
|
return;
|
|
}
|
|
|
|
/* GUI configuration */
|
|
|
|
/* not implemented in GUI */
|
|
upnp_port = nvram_get_int("upnp_port");
|
|
if ((upnp_port < 0) || (upnp_port >= 0xFFFF))
|
|
upnp_port = 0;
|
|
|
|
if (check_wanup("wan2"))
|
|
fprintf(f, "ext_ifname=%s\n", get_wanface("wan2"));
|
|
#ifdef TCONFIG_MULTIWAN
|
|
if (check_wanup("wan3"))
|
|
fprintf(f, "ext_ifname=%s\n", get_wanface("wan3"));
|
|
|
|
if (check_wanup("wan4"))
|
|
fprintf(f, "ext_ifname=%s\n", get_wanface("wan4"));
|
|
#endif
|
|
|
|
fprintf(f, "ext_ifname=%s\n"
|
|
"port=%d\n"
|
|
"enable_upnp=%s\n"
|
|
"enable_pcp_pmp=%s\n"
|
|
"force_igd_desc_v1=yes\n"
|
|
"secure_mode=%s\n"
|
|
"pcp_allow_thirdparty=%s\n"
|
|
"upnp_forward_chain=upnp\n"
|
|
"upnp_nat_chain=upnp\n"
|
|
"upnp_nat_postrouting_chain=pupnp\n"
|
|
"notify_interval=%d\n"
|
|
"system_uptime=yes\n"
|
|
"friendly_name=FreshTomato UPnP IGD & PCP\n"
|
|
"model_name=%s\n"
|
|
"model_url=https://freshtomato.org/\n"
|
|
"manufacturer_name=FreshTomato Firmware\n"
|
|
"manufacturer_url=https://freshtomato.org/\n"
|
|
/* Empty strings so that 1 and 00000000 are not reported */
|
|
"model_number=\n"
|
|
"serial=\n"
|
|
"\n",
|
|
get_wanface("wan"),
|
|
upnp_port,
|
|
(enable & 1) ? "yes" : "no", /* upnp enable */
|
|
(enable & 2) ? "yes" : "no", /* pcp_pmp enable */
|
|
nvram_get_int("upnp_secure") ? "yes" : "no", /* secure_mode (only forward to self) */
|
|
nvram_get_int("upnp_secure") ? "no" : "yes", /* allow third party */
|
|
nvram_get_int("upnp_ssdp_interval"),
|
|
nvram_safe_get("t_model_name"));
|
|
|
|
https = nvram_get_int("https_enable");
|
|
fprintf(f, "presentation_url=http%s://%s:%s/forward-upnp.asp\n", (https ? "s" : ""), nvram_safe_get("lan_ipaddr"), nvram_safe_get(https ? "https_lanport" : "http_lanport"));
|
|
|
|
f_read_string("/proc/sys/kernel/random/uuid", uuid, sizeof(uuid));
|
|
fprintf(f, "uuid=%s\n", uuid);
|
|
|
|
/* move custom configuration before "allow" statements */
|
|
/* discussion: http://www.linksysinfo.org/index.php?threads/miniupnpd-custom-config-syntax.70863/#post-256291 */
|
|
fappend(f, UPNP_DIR"/config.custom");
|
|
fprintf(f, "%s\n", nvram_safe_get("upnp_custom"));
|
|
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
snprintf(lanN_ipaddr, sizeof(lanN_ipaddr), "lan%s_ipaddr", bridge);
|
|
snprintf(lanN_netmask, sizeof(lanN_netmask), "lan%s_netmask", bridge);
|
|
snprintf(lanN_ifname, sizeof(lanN_ifname), "lan%s_ifname", bridge);
|
|
snprintf(upnp_lanN, sizeof(upnp_lanN), "upnp_lan%s", bridge);
|
|
|
|
lanip = nvram_safe_get(lanN_ipaddr);
|
|
lanmask = nvram_safe_get(lanN_netmask);
|
|
lanifname = nvram_safe_get(lanN_ifname);
|
|
|
|
if ((strcmp(nvram_safe_get(upnp_lanN), "1") == 0) && (strcmp(lanifname, "") != 0)) {
|
|
fprintf(f, "listening_ip=%s\n", lanifname);
|
|
|
|
/* not implemented in GUI */
|
|
if ((ports[0] = nvram_get_int("upnp_min_port_ext")) > 0 &&
|
|
(ports[1] = nvram_get_int("upnp_max_port_ext")) > 0 &&
|
|
(ports[2] = nvram_get_int("upnp_min_port_int")) > 0 &&
|
|
(ports[3] = nvram_get_int("upnp_max_port_int")) > 0)
|
|
fprintf(f, "allow %d-%d %s/%s %d-%d\n", ports[0], ports[1], lanip, lanmask, ports[2], ports[3]);
|
|
else
|
|
/* by default allow only redirection of ports above 1024 */
|
|
fprintf(f, "allow 1024-65535 %s/%s 1024-65535\n", lanip, lanmask);
|
|
}
|
|
}
|
|
fprintf(f, "\ndeny 0-65535 0.0.0.0/0 0-65535\n");
|
|
|
|
fclose(f);
|
|
|
|
xstart("miniupnpd", "-f", UPNP_CONFIG);
|
|
}
|
|
|
|
void stop_upnp(void)
|
|
{
|
|
if (serialize_restart("miniupnpd", 0))
|
|
return;
|
|
|
|
killall_tk_period_wait("miniupnpd", 50);
|
|
|
|
/* clean-up */
|
|
eval("rm", "-f", UPNP_CONFIG);
|
|
}
|
|
|
|
void start_cron(void)
|
|
{
|
|
stop_cron();
|
|
|
|
eval("crond", (nvram_contains_word("log_events", "crond") ? NULL : "-l"), "9");
|
|
|
|
if (!nvram_contains_word("debug_norestart", "crond"))
|
|
pid_crond = -2;
|
|
}
|
|
|
|
void stop_cron(void)
|
|
{
|
|
pid_crond = -1;
|
|
killall_tk_period_wait("crond", 50);
|
|
}
|
|
|
|
void start_hotplug2(void)
|
|
{
|
|
stop_hotplug2();
|
|
|
|
f_write_string("/proc/sys/kernel/hotplug", "", FW_NEWLINE, 0);
|
|
xstart("hotplug2", "--persistent", "--no-coldplug");
|
|
|
|
/* FIXME: Don't remember exactly why I put "sleep" here - but it was not for a race with check_services()... */
|
|
sleep(1);
|
|
|
|
if (!nvram_contains_word("debug_norestart", "hotplug2"))
|
|
pid_hotplug2 = -2;
|
|
}
|
|
|
|
void stop_hotplug2(void)
|
|
{
|
|
pid_hotplug2 = -1;
|
|
killall_tk_period_wait("hotplug2", 50);
|
|
}
|
|
|
|
#ifdef TCONFIG_ZEBRA
|
|
void start_zebra(void)
|
|
{
|
|
FILE *fp;
|
|
|
|
char *lan_tx = nvram_safe_get("dr_lan_tx");
|
|
char *lan_rx = nvram_safe_get("dr_lan_rx");
|
|
char *lan1_tx = nvram_safe_get("dr_lan1_tx");
|
|
char *lan1_rx = nvram_safe_get("dr_lan1_rx");
|
|
char *lan2_tx = nvram_safe_get("dr_lan2_tx");
|
|
char *lan2_rx = nvram_safe_get("dr_lan2_rx");
|
|
char *lan3_tx = nvram_safe_get("dr_lan3_tx");
|
|
char *lan3_rx = nvram_safe_get("dr_lan3_rx");
|
|
char *wan_tx = nvram_safe_get("dr_wan_tx");
|
|
char *wan_rx = nvram_safe_get("dr_wan_rx");
|
|
|
|
if (serialize_restart("zebra", 1))
|
|
return;
|
|
|
|
if ((*lan_tx == '0') && (*lan_rx == '0') &&
|
|
(*lan1_tx == '0') && (*lan1_rx == '0') &&
|
|
(*lan2_tx == '0') && (*lan2_rx == '0') &&
|
|
(*lan3_tx == '0') && (*lan3_rx == '0') &&
|
|
(*wan_tx == '0') && (*wan_rx == '0')) {
|
|
return;
|
|
}
|
|
|
|
f_write(ZEBRA_CONF, NULL, 0, 0, 0); /* blank */
|
|
|
|
if ((fp = fopen(RIPD_CONF, "w")) == NULL) {
|
|
logerr(__FUNCTION__, __LINE__, RIPD_CONF);
|
|
return;
|
|
}
|
|
|
|
char *lan_ifname = nvram_safe_get("lan_ifname");
|
|
char *lan1_ifname = nvram_safe_get("lan1_ifname");
|
|
char *lan2_ifname = nvram_safe_get("lan2_ifname");
|
|
char *lan3_ifname = nvram_safe_get("lan3_ifname");
|
|
char *wan_ifname = nvram_safe_get("wan_ifname");
|
|
|
|
fprintf(fp, "router rip\n");
|
|
|
|
if (strcmp(lan_ifname, "") != 0)
|
|
fprintf(fp, "network %s\n", lan_ifname);
|
|
if (strcmp(lan1_ifname, "") != 0)
|
|
fprintf(fp, "network %s\n", lan1_ifname);
|
|
if (strcmp(lan2_ifname, "") != 0)
|
|
fprintf(fp, "network %s\n", lan2_ifname);
|
|
if (strcmp(lan3_ifname, "") != 0)
|
|
fprintf(fp, "network %s\n", lan3_ifname);
|
|
|
|
fprintf(fp, "network %s\n", wan_ifname);
|
|
fprintf(fp, "redistribute connected\n");
|
|
|
|
if (strcmp(lan_ifname, "") != 0) {
|
|
fprintf(fp, "interface %s\n", lan_ifname);
|
|
if (*lan_tx != '0')
|
|
fprintf(fp, "ip rip send version %s\n", lan_tx);
|
|
if (*lan_rx != '0')
|
|
fprintf(fp, "ip rip receive version %s\n", lan_rx);
|
|
}
|
|
if (strcmp(lan1_ifname, "") != 0) {
|
|
fprintf(fp, "interface %s\n", lan1_ifname);
|
|
if (*lan1_tx != '0')
|
|
fprintf(fp, "ip rip send version %s\n", lan1_tx);
|
|
if (*lan1_rx != '0')
|
|
fprintf(fp, "ip rip receive version %s\n", lan1_rx);
|
|
}
|
|
if (strcmp(lan2_ifname, "") != 0) {
|
|
fprintf(fp, "interface %s\n", lan2_ifname);
|
|
if (*lan2_tx != '0')
|
|
fprintf(fp, "ip rip send version %s\n", lan2_tx);
|
|
if (*lan2_rx != '0')
|
|
fprintf(fp, "ip rip receive version %s\n", lan2_rx);
|
|
}
|
|
if (strcmp(lan3_ifname, "") != 0) {
|
|
fprintf(fp, "interface %s\n", lan3_ifname);
|
|
if (*lan3_tx != '0')
|
|
fprintf(fp, "ip rip send version %s\n", lan3_tx);
|
|
if (*lan3_rx != '0')
|
|
fprintf(fp, "ip rip receive version %s\n", lan3_rx);
|
|
}
|
|
|
|
fprintf(fp, "interface %s\n", wan_ifname);
|
|
|
|
if (*wan_tx != '0')
|
|
fprintf(fp, "ip rip send version %s\n", wan_tx);
|
|
if (*wan_rx != '0')
|
|
fprintf(fp, "ip rip receive version %s\n", wan_rx);
|
|
|
|
fprintf(fp, "router rip\n");
|
|
|
|
if (strcmp(lan_ifname, "") != 0) {
|
|
if (*lan_tx == '0')
|
|
fprintf(fp, "distribute-list private out %s\n", lan_ifname);
|
|
if (*lan_rx == '0')
|
|
fprintf(fp, "distribute-list private in %s\n", lan_ifname);
|
|
}
|
|
if (strcmp(lan1_ifname, "") != 0) {
|
|
if (*lan1_tx == '0')
|
|
fprintf(fp, "distribute-list private out %s\n", lan1_ifname);
|
|
if (*lan1_rx == '0')
|
|
fprintf(fp, "distribute-list private in %s\n", lan1_ifname);
|
|
}
|
|
if (strcmp(lan2_ifname, "") != 0) {
|
|
if (*lan2_tx == '0')
|
|
fprintf(fp, "distribute-list private out %s\n", lan2_ifname);
|
|
if (*lan2_rx == '0')
|
|
fprintf(fp, "distribute-list private in %s\n", lan2_ifname);
|
|
}
|
|
if (strcmp(lan3_ifname, "") != 0) {
|
|
if (*lan3_tx == '0')
|
|
fprintf(fp, "distribute-list private out %s\n", lan3_ifname);
|
|
if (*lan3_rx == '0')
|
|
fprintf(fp, "distribute-list private in %s\n", lan3_ifname);
|
|
}
|
|
if (*wan_tx == '0')
|
|
fprintf(fp, "distribute-list private out %s\n", wan_ifname);
|
|
if (*wan_rx == '0')
|
|
fprintf(fp, "distribute-list private in %s\n", wan_ifname);
|
|
|
|
fprintf(fp, "access-list private deny any\n");
|
|
|
|
//fprintf(fp, "debug rip events\n");
|
|
//fprintf(fp, "log file /etc/ripd.log\n");
|
|
fclose(fp);
|
|
|
|
xstart("zebra", "-d");
|
|
xstart("ripd", "-d");
|
|
}
|
|
|
|
void stop_zebra(void)
|
|
{
|
|
if (serialize_restart("zebra", 0))
|
|
return;
|
|
|
|
killall("zebra", SIGTERM);
|
|
killall("ripd", SIGTERM);
|
|
|
|
unlink(ZEBRA_CONF);
|
|
unlink(RIPD_CONF);
|
|
}
|
|
#endif /* #ifdef TCONFIG_ZEBRA */
|
|
|
|
void start_syslog(void)
|
|
{
|
|
char *argv[20];
|
|
int argc;
|
|
char *nv;
|
|
char *b_opt = "";
|
|
char rem[256];
|
|
int n;
|
|
char s[64];
|
|
char cfg[256];
|
|
char *rot_siz = "50";
|
|
char *rot_keep = "1";
|
|
char *log_file_path;
|
|
char log_default[] = "/var/log/messages";
|
|
char *log_min_level;
|
|
|
|
argv[0] = "syslogd";
|
|
argc = 1;
|
|
|
|
if (nvram_get_int("log_dropdups"))
|
|
argv[argc++] = "-D";
|
|
|
|
if (nvram_get_int("log_remote")) {
|
|
nv = nvram_safe_get("log_remoteip");
|
|
if (*nv) {
|
|
snprintf(rem, sizeof(rem), "%s:%s", nv, nvram_safe_get("log_remoteport"));
|
|
argv[argc++] = "-R";
|
|
argv[argc++] = rem;
|
|
}
|
|
}
|
|
|
|
if (nvram_get_int("log_file")) {
|
|
argv[argc++] = "-L";
|
|
|
|
if (strcmp(nvram_safe_get("log_file_size"), "") != 0)
|
|
rot_siz = nvram_safe_get("log_file_size");
|
|
|
|
if (nvram_get_int("log_file_size") > 0)
|
|
rot_keep = nvram_safe_get("log_file_keep");
|
|
|
|
/* log to custom path */
|
|
if (nvram_get_int("log_file_custom")) {
|
|
log_file_path = nvram_safe_get("log_file_path");
|
|
argv[argc++] = "-s";
|
|
argv[argc++] = rot_siz;
|
|
argv[argc++] = "-O";
|
|
argv[argc++] = log_file_path;
|
|
if (strcmp(nvram_safe_get("log_file_path"), log_default) != 0) {
|
|
remove(log_default);
|
|
symlink(log_file_path, log_default);
|
|
}
|
|
}
|
|
else {
|
|
/* Read options: rotate_size(kb) num_backups logfilename.
|
|
* Ignore these settings and use defaults if the logfile cannot be written to.
|
|
*/
|
|
if (f_read_string("/etc/syslogd.cfg", cfg, sizeof(cfg)) > 0) {
|
|
if ((nv = strchr(cfg, '\n')))
|
|
*nv = 0;
|
|
|
|
if ((nv = strtok(cfg, " \t"))) {
|
|
if (isdigit(*nv))
|
|
rot_siz = nv;
|
|
}
|
|
|
|
if ((nv = strtok(NULL, " \t")))
|
|
b_opt = nv;
|
|
|
|
if ((nv = strtok(NULL, " \t")) && *nv == '/') {
|
|
if (f_write(nv, cfg, 0, FW_APPEND, 0) >= 0) {
|
|
argv[argc++] = "-O";
|
|
argv[argc++] = nv;
|
|
}
|
|
else {
|
|
rot_siz = "50";
|
|
b_opt = "";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!(nvram_get_int("log_file_custom"))) {
|
|
argv[argc++] = "-s";
|
|
argv[argc++] = rot_siz;
|
|
struct stat sb;
|
|
if (lstat(log_default, &sb) != -1)
|
|
if (S_ISLNK(sb.st_mode))
|
|
remove(log_default);
|
|
}
|
|
|
|
if (isdigit(*b_opt)) {
|
|
argv[argc++] = "-b";
|
|
argv[argc++] = b_opt;
|
|
}
|
|
else if (nvram_get_int("log_file_size") > 0) {
|
|
argv[argc++] = "-b";
|
|
argv[argc++] = rot_keep;
|
|
}
|
|
|
|
log_min_level = nvram_safe_get("log_min_level");
|
|
argv[argc++] = "-l";
|
|
argv[argc++] = log_min_level;
|
|
}
|
|
|
|
if (argc > 1) {
|
|
argv[argc] = NULL;
|
|
_eval(argv, NULL, 0, NULL);
|
|
|
|
argv[0] = "klogd";
|
|
argv[1] = NULL;
|
|
_eval(argv, NULL, 0, NULL);
|
|
|
|
/* used to be available in syslogd -m */
|
|
n = nvram_get_int("log_mark");
|
|
if (n > 0) {
|
|
memset(rem, 0, sizeof(rem));
|
|
/* n is in minutes */
|
|
if (n < 60)
|
|
snprintf(rem, sizeof(rem), "*/%d * * * *", n);
|
|
else if (n < 60 * 24)
|
|
snprintf(rem, sizeof(rem), "0 */%d * * *", n / 60);
|
|
else
|
|
snprintf(rem, sizeof(rem), "0 0 */%d * *", n / (60 * 24));
|
|
|
|
memset(s, 0, sizeof(s));
|
|
snprintf(s, sizeof(s), "%s logger -p syslog.info -- -- MARK --", rem);
|
|
eval("cru", "a", "syslogdmark", s);
|
|
}
|
|
else {
|
|
eval("cru", "d", "syslogdmark");
|
|
}
|
|
}
|
|
}
|
|
|
|
void stop_syslog(void)
|
|
{
|
|
killall("klogd", SIGTERM);
|
|
killall("syslogd", SIGTERM);
|
|
}
|
|
|
|
void start_igmp_proxy(void)
|
|
{
|
|
FILE *fp;
|
|
const char *nv;
|
|
char igmp_buffer[32];
|
|
char wan_prefix[] = "wanXX";
|
|
int wan_unit, mwan_num, count = 0;
|
|
int ret = 1;
|
|
int i, enabled_interface;
|
|
|
|
mwan_num = nvram_get_int("mwan_num");
|
|
if ((mwan_num < 1) || (mwan_num > MWAN_MAX))
|
|
mwan_num = 1;
|
|
|
|
/* only if enabled */
|
|
if (!nvram_get_int("multicast_pass"))
|
|
return;
|
|
|
|
/* custom configuration file */
|
|
if (f_exists("/etc/igmp.alt"))
|
|
ret = eval("igmpproxy", "/etc/igmp.alt");
|
|
/* GUI configuration */
|
|
else if ((fp = fopen(IGMP_CONF, "w")) != NULL) {
|
|
fprintf(fp, "user nobody\n"); /* drop privileges */
|
|
|
|
/* check that lan, lan1, lan2 and lan3 are not selected and use custom config */
|
|
/* The configuration file must define one (or more) upstream interface(s) and one or more downstream interfaces,
|
|
* see https://github.com/pali/igmpproxy/commit/b55e0125c79fc9dbc95c6d6ab1121570f0c6f80f and
|
|
* see https://github.com/pali/igmpproxy/blob/master/igmpproxy.conf
|
|
*/
|
|
enabled_interface=0;
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
snprintf(igmp_buffer, sizeof(igmp_buffer), (i == 0 ? "multicast_lan" : "multicast_lan%d"), i);
|
|
enabled_interface += nvram_get_int(igmp_buffer);
|
|
}
|
|
if (!enabled_interface) {
|
|
fprintf(fp, "%s\n", nvram_safe_get("multicast_custom"));
|
|
fclose(fp);
|
|
ret = eval("igmpproxy", IGMP_CONF);
|
|
}
|
|
/* create default config for upstream/downstream interface(s) */
|
|
else {
|
|
if (nvram_get_int("multicast_quickleave"))
|
|
fprintf(fp, "quickleave\n");
|
|
|
|
for (wan_unit = 1; wan_unit <= mwan_num; ++wan_unit) {
|
|
get_wan_prefix(wan_unit, wan_prefix);
|
|
if ((check_wanup(wan_prefix)) && (get_wanx_proto(wan_prefix) != WP_DISABLED)) {
|
|
count++;
|
|
/*
|
|
* Configuration for Upstream Interface
|
|
* Example:
|
|
* phyint ppp0 upstream ratelimit 0 threshold 1
|
|
* altnet 193.158.35.0/24
|
|
*/
|
|
fprintf(fp, "phyint %s upstream ratelimit 0 threshold 1\n", get_wanface(wan_prefix));
|
|
/* check for allowed remote network address, see note at GUI advanced-firewall.asp */
|
|
if ((nvram_get("multicast_altnet_1") != NULL) || (nvram_get("multicast_altnet_2") != NULL) || (nvram_get("multicast_altnet_3") != NULL)) {
|
|
if (((nv = nvram_get("multicast_altnet_1")) != NULL) && (*nv)) {
|
|
memset(igmp_buffer, 0, sizeof(igmp_buffer)); /* reset */
|
|
snprintf(igmp_buffer, sizeof(igmp_buffer),"%s", nv); /* copy to buffer */
|
|
fprintf(fp, "\taltnet %s\n", igmp_buffer); /* with the following format: a.b.c.d/n - Example: altnet 10.0.0.0/16 */
|
|
logmsg(LOG_INFO, "igmpproxy: multicast_altnet_1 = %s", igmp_buffer);
|
|
}
|
|
|
|
if (((nv = nvram_get("multicast_altnet_2")) != NULL) && (*nv)) {
|
|
memset(igmp_buffer, 0, sizeof(igmp_buffer)); /* reset */
|
|
snprintf(igmp_buffer, sizeof(igmp_buffer),"%s", nv); /* copy to buffer */
|
|
fprintf(fp, "\taltnet %s\n", igmp_buffer); /* with the following format: a.b.c.d/n - Example: altnet 10.0.0.0/16 */
|
|
logmsg(LOG_INFO, "igmpproxy: multicast_altnet_2 = %s", igmp_buffer);
|
|
}
|
|
|
|
if (((nv = nvram_get("multicast_altnet_3")) != NULL) && (*nv)) {
|
|
memset(igmp_buffer, 0, sizeof(igmp_buffer)); /* reset */
|
|
snprintf(igmp_buffer, sizeof(igmp_buffer),"%s", nv); /* copy to buffer */
|
|
fprintf(fp, "\taltnet %s\n", igmp_buffer); /* with the following format: a.b.c.d/n - Example: altnet 10.0.0.0/16 */
|
|
logmsg(LOG_INFO, "igmpproxy: multicast_altnet_3 = %s", igmp_buffer);
|
|
}
|
|
}
|
|
else
|
|
fprintf(fp, "\taltnet 0.0.0.0/0\n"); /* default, allow all! */
|
|
}
|
|
}
|
|
if (!count) {
|
|
fclose(fp);
|
|
unlink(IGMP_CONF);
|
|
return;
|
|
}
|
|
|
|
char lanN_ifname[] = "lanXX_ifname";
|
|
char multicast_lanN[] = "multicast_lanXX";
|
|
char br;
|
|
|
|
for (br = 0; br < BRIDGE_COUNT; br++) {
|
|
char bridge[2] = "0";
|
|
if (br != 0)
|
|
bridge[0] += br;
|
|
else
|
|
memset(bridge, 0, sizeof(bridge));
|
|
|
|
snprintf(lanN_ifname, sizeof(lanN_ifname), "lan%s_ifname", bridge);
|
|
snprintf(multicast_lanN, sizeof(multicast_lanN), "multicast_lan%s", bridge);
|
|
|
|
if ((strcmp(nvram_safe_get(multicast_lanN), "1") == 0) && (strcmp(nvram_safe_get(lanN_ifname), "") != 0)) {
|
|
/*
|
|
* Configuration for Downstream Interface
|
|
* Example:
|
|
* phyint br0 downstream ratelimit 0 threshold 1
|
|
*/
|
|
fprintf(fp, "phyint %s downstream ratelimit 0 threshold 1\n", nvram_safe_get(lanN_ifname));
|
|
}
|
|
}
|
|
fclose(fp);
|
|
ret = eval("igmpproxy", IGMP_CONF);
|
|
}
|
|
}
|
|
else {
|
|
logerr(__FUNCTION__, __LINE__, IGMP_CONF);
|
|
return;
|
|
}
|
|
|
|
if (!nvram_contains_word("debug_norestart", "igmprt"))
|
|
pid_igmp = -2;
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting igmpproxy failed ...");
|
|
else
|
|
logmsg(LOG_INFO, "igmpproxy is started");
|
|
|
|
}
|
|
|
|
void stop_igmp_proxy(void)
|
|
{
|
|
pid_igmp = -1;
|
|
if (pidof("igmpproxy") > 0) {
|
|
killall_tk_period_wait("igmpproxy", 50);
|
|
logmsg(LOG_INFO, "igmpproxy is stopped");
|
|
}
|
|
|
|
/* clean-up */
|
|
unlink(IGMP_CONF);
|
|
}
|
|
|
|
void start_udpxy(void)
|
|
{
|
|
char wan_prefix[] = "wan"; /* not yet mwan ready, use wan for now */
|
|
char buffer[32], buffer2[16];
|
|
int i, bind_lan = 0;
|
|
|
|
/* only if enabled */
|
|
if (!nvram_get_int("udpxy_enable"))
|
|
return;
|
|
|
|
if ((check_wanup(wan_prefix)) && (get_wanx_proto(wan_prefix) != WP_DISABLED)) {
|
|
memset(buffer, 0, sizeof(buffer)); /* reset */
|
|
if (strlen(nvram_safe_get("udpxy_wanface")) > 0)
|
|
snprintf(buffer, sizeof(buffer), "%s", nvram_safe_get("udpxy_wanface")); /* user entered upstream interface */
|
|
else
|
|
snprintf(buffer, sizeof(buffer), "%s", get_wanface(wan_prefix)); /* copy wanface to buffer */
|
|
|
|
/* check interface to listen on */
|
|
/* check udpxy enabled/selected for br0 - br3 */
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
int ret1 = 0, ret2 = 0;
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), (i == 0 ? "udpxy_lan" : "udpxy_lan%d"), i);
|
|
ret1 = nvram_match(buffer2, "1");
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), (i == 0 ? "lan_ipaddr" : "lan%d_ipaddr"), i);
|
|
ret2 = strcmp(nvram_safe_get(buffer2), "") != 0;
|
|
if (ret1 && ret2) {
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
eval("udpxy", (nvram_get_int("udpxy_stats") ? "-S" : ""), "-p", nvram_safe_get("udpxy_port"), "-c", nvram_safe_get("udpxy_clients"), "-a", nvram_safe_get(buffer2), "-m", buffer);
|
|
bind_lan = 1;
|
|
break; /* start udpxy only once and only for one lanX */
|
|
}
|
|
}
|
|
/* address/interface to listen on: default = 0.0.0.0 */
|
|
if (!bind_lan)
|
|
eval("udpxy", (nvram_get_int("udpxy_stats") ? "-S" : ""), "-p", nvram_safe_get("udpxy_port"), "-c", nvram_safe_get("udpxy_clients"), "-m", buffer);
|
|
}
|
|
}
|
|
|
|
void stop_udpxy(void)
|
|
{
|
|
killall_tk_period_wait("udpxy", 50);
|
|
}
|
|
|
|
void set_tz(void)
|
|
{
|
|
f_write_string("/etc/TZ", nvram_safe_get("tm_tz"), (FW_CREATE | FW_NEWLINE), 0644);
|
|
}
|
|
|
|
void start_ntpd(void)
|
|
{
|
|
FILE *f;
|
|
char *servers, *ptr;
|
|
int servers_len = 0, ntp_updates_int = 0, index = 2, ret;
|
|
char *ntpd_argv[] = { "/usr/sbin/ntpd", "-t", NULL, NULL, NULL, NULL, NULL, NULL }; /* -ddddddd -q -S /sbin/ntpd_synced -l */
|
|
pid_t pid;
|
|
|
|
if (serialize_restart("ntpd", 1))
|
|
return;
|
|
|
|
set_tz();
|
|
|
|
if ((nvram_get_int("dnscrypt_proxy")) || (nvram_get_int("stubby_proxy")))
|
|
eval("ntp2ip");
|
|
|
|
/* this is the nvram var defining how the server should be run / how often to sync */
|
|
ntp_updates_int = nvram_get_int("ntp_updates");
|
|
|
|
/* the Tomato GUI allows the user to select an NTP Server region, and then string concats 1. 2. and 3. as prefix
|
|
* therefore, the nvram variable contains a string of 3 NTP servers - This code separates them and passes them to
|
|
* ntpd as separate parameters. this code should continue to work if GUI is changed to only store 1 value in the NVRAM var
|
|
*/
|
|
if (ntp_updates_int >= 0) { /* -1 = never */
|
|
servers_len = strlen(nvram_safe_get("ntp_server"));
|
|
|
|
/* allocating memory dynamically both so we don't waste memory, and in case of unanticipatedly long server name in nvram */
|
|
if ((servers = malloc(servers_len + 1)) == NULL) {
|
|
logmsg(LOG_ERR, "ntpd: failed allocating memory, exiting");
|
|
return; /* just get out if we couldn't allocate memory */
|
|
}
|
|
memset(servers, 0, servers_len + 1);
|
|
|
|
/* get the space separated list of ntp servers */
|
|
strlcpy(servers, nvram_safe_get("ntp_server"), servers_len + 1);
|
|
|
|
/* put the servers into the ntp config file */
|
|
if ((f = fopen("/etc/ntp.conf", "w")) != NULL) {
|
|
ptr = strtok(servers, " ");
|
|
while(ptr) {
|
|
fprintf(f, "server %s\n", ptr);
|
|
ptr = strtok(NULL, " ");
|
|
}
|
|
fclose(f);
|
|
}
|
|
else {
|
|
logerr(__FUNCTION__, __LINE__, "/etc/ntp.conf");
|
|
return;
|
|
}
|
|
|
|
free(servers);
|
|
|
|
if (nvram_contains_word("log_events", "ntp")) /* add verbose (doesn't work right now) */
|
|
ntpd_argv[index++] = "-ddddddd";
|
|
|
|
if (ntp_updates_int == 0) /* only at startup, then quit */
|
|
ntpd_argv[index++] = "-q";
|
|
else if (ntp_updates_int >= 1) { /* auto adjusted timing by ntpd since it doesn't currently implement minpoll and maxpoll */
|
|
ntpd_argv[index++] = "-S";
|
|
ntpd_argv[index++] = "/sbin/ntpd_synced";
|
|
|
|
if (nvram_get_int("ntpd_enable")) /* enable local NTP server */
|
|
ntpd_argv[index++] = "-l";
|
|
}
|
|
|
|
ret = _eval(ntpd_argv, NULL, 0, &pid);
|
|
|
|
if (!nvram_contains_word("debug_norestart", "ntpd"))
|
|
pid_ntpd = -2;
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting ntpd failed ...");
|
|
else
|
|
logmsg(LOG_INFO, "ntpd is started");
|
|
}
|
|
}
|
|
|
|
void stop_ntpd(void)
|
|
{
|
|
if (serialize_restart("ntpd", 0))
|
|
return;
|
|
|
|
pid_ntpd = -1;
|
|
if (pidof("ntpd") > 0) {
|
|
killall_tk_period_wait("ntpd", 50);
|
|
logmsg(LOG_INFO, "ntpd is stopped");
|
|
}
|
|
}
|
|
|
|
int ntpd_synced_main(int argc, char *argv[])
|
|
{
|
|
if (!nvram_match("ntp_ready", "1") && (argc == 2 && !strcmp(argv[1], "step"))) {
|
|
nvram_set("ntp_ready", "1");
|
|
logmsg(LOG_INFO, "initial clock set");
|
|
|
|
stop_httpd();
|
|
start_httpd();
|
|
start_sched();
|
|
stop_ddns();
|
|
start_ddns();
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
stop_dnscrypt();
|
|
start_dnscrypt();
|
|
#endif
|
|
#ifdef TCONFIG_STUBBY
|
|
stop_stubby();
|
|
start_stubby();
|
|
#endif
|
|
#ifdef TCONFIG_DNSSEC
|
|
if (nvram_get_int("dnssec_enable"))
|
|
reload_dnsmasq();
|
|
#endif
|
|
#ifdef TCONFIG_OPENVPN
|
|
start_ovpn_eas();
|
|
#endif
|
|
#ifdef TCONFIG_WIREGUARD
|
|
start_wg_eas();
|
|
#endif
|
|
#ifdef TCONFIG_MDNS
|
|
stop_mdns();
|
|
start_mdns();
|
|
#endif
|
|
}
|
|
|
|
FILE *file;
|
|
char message[300];
|
|
char *stratum = safe_getenv("stratum");
|
|
char *offset = safe_getenv("offset");
|
|
char *freq_drift_ppm = safe_getenv("freq_drift_ppm");
|
|
char *poll_interval = safe_getenv("poll_interval");
|
|
char *server_hostname = safe_getenv("server_hostname");
|
|
char *server_ip = safe_getenv("server_ip");
|
|
char *discipline_jitter = safe_getenv("discipline_jitter");
|
|
|
|
snprintf(message, sizeof(message), "Server: %s (%s)\n"
|
|
"Poll Interval: %ss\n"
|
|
"Stratum: %s\n"
|
|
"Offset: %ss\n"
|
|
"Jitter: %ss\n"
|
|
"Frequency: %sppm\n",
|
|
server_ip, server_hostname,
|
|
poll_interval,
|
|
stratum,
|
|
offset,
|
|
discipline_jitter,
|
|
freq_drift_ppm);
|
|
|
|
if (!(file = fopen("/tmp/ntpd", "w"))) {
|
|
return 1;
|
|
}
|
|
|
|
fprintf(file,"%s", message);
|
|
fclose(file);
|
|
return 0;
|
|
}
|
|
|
|
static void stop_rstats(void)
|
|
{
|
|
int n, m;
|
|
pid_t pid, pidz, ppidz;
|
|
int w = 0;
|
|
|
|
n = 60;
|
|
m = 15;
|
|
while ((n-- > 0) && ((pid = pidof("rstats")) > 0)) {
|
|
w = 1;
|
|
pidz = pidof("gzip");
|
|
if (pidz < 0)
|
|
pidz = pidof("cp");
|
|
|
|
ppidz = ppid(ppid(pidz));
|
|
if ((m > 0) && (pidz > 0) && (pid == ppidz)) {
|
|
logmsg(LOG_DEBUG, "*** %s: (PID %d) shutting down, waiting for helper process to complete (PID %d, PPID %d)", __FUNCTION__, pid, pidz, ppidz);
|
|
--m;
|
|
}
|
|
else
|
|
kill(pid, SIGTERM);
|
|
|
|
sleep(1);
|
|
}
|
|
if ((w == 1) && (n > 0))
|
|
logmsg(LOG_INFO, "rstats stopped");
|
|
}
|
|
|
|
static void start_rstats(int new)
|
|
{
|
|
if (nvram_get_int("rstats_enable")) {
|
|
add_rstats_defaults(); /* backup: check nvram! */
|
|
stop_rstats();
|
|
if (new)
|
|
xstart("rstats", "--new");
|
|
else
|
|
xstart("rstats");
|
|
|
|
logmsg(LOG_INFO, "starting rstats%s", (new ? " (new datafile)" : ""));
|
|
}
|
|
}
|
|
|
|
static void stop_cstats(void)
|
|
{
|
|
int n, m;
|
|
pid_t pid, pidz, ppidz;
|
|
int w = 0;
|
|
|
|
n = 60;
|
|
m = 15;
|
|
while ((n-- > 0) && ((pid = pidof("cstats")) > 0)) {
|
|
w = 1;
|
|
pidz = pidof("gzip");
|
|
if (pidz < 0)
|
|
pidz = pidof("cp");
|
|
|
|
ppidz = ppid(ppid(pidz));
|
|
if ((m > 0) && (pidz > 0) && (pid == ppidz)) {
|
|
logmsg(LOG_DEBUG, "*** %s: (PID %d) shutting down, waiting for helper process to complete (PID %d, PPID %d)", __FUNCTION__, pid, pidz, ppidz);
|
|
--m;
|
|
}
|
|
else
|
|
kill(pid, SIGTERM);
|
|
|
|
sleep(1);
|
|
}
|
|
if ((w == 1) && (n > 0))
|
|
logmsg(LOG_INFO, "cstats stopped");
|
|
}
|
|
|
|
static void start_cstats(int new)
|
|
{
|
|
if (nvram_get_int("cstats_enable")) {
|
|
add_cstats_defaults(); /* backup: check nvram! */
|
|
stop_cstats();
|
|
if (new)
|
|
xstart("cstats", "--new");
|
|
else
|
|
xstart("cstats");
|
|
|
|
logmsg(LOG_INFO, "starting cstats%s", (new ? " (new datafile)" : ""));
|
|
}
|
|
}
|
|
|
|
#ifdef TCONFIG_MEDIA_SERVER
|
|
static void start_media_server(int force)
|
|
{
|
|
FILE *f;
|
|
int port, https;
|
|
pid_t pid;
|
|
char *dbdir;
|
|
char *argv[] = { "minidlna", "-f", "/etc/minidlna.conf", "-r", "-P", "/var/run/minidlna.pid", NULL, NULL };
|
|
static int once = 1;
|
|
int ret, index = 4, i;
|
|
char *msi;
|
|
unsigned char ea[ETHER_ADDR_LEN];
|
|
char serial[18], uuident[37];
|
|
char buffer[32], buffer2[8], buffer3[32];
|
|
char *buf, *p, *q;
|
|
char *path, *restricted;
|
|
|
|
/* only if enabled or forced */
|
|
if (!nvram_get_int("ms_enable") && force == 0)
|
|
return;
|
|
|
|
if (serialize_restart("minidlna", 1))
|
|
return;
|
|
|
|
if (!nvram_get_int("ms_sas")) { /* scan media at startup? */
|
|
once = 0;
|
|
argv[index - 1] = NULL;
|
|
}
|
|
else if (!once) /* already scanned */
|
|
argv[index - 1] = NULL;
|
|
|
|
if (nvram_get_int("ms_rescan")) { /* rescan on the next run? */
|
|
argv[index - 1] = "-R";
|
|
nvram_unset("ms_rescan");
|
|
}
|
|
|
|
if (f_exists("/etc/minidlna.alt"))
|
|
argv[2] = "/etc/minidlna.alt";
|
|
else {
|
|
if ((f = fopen(argv[2], "w")) != NULL) {
|
|
port = nvram_get_int("ms_port");
|
|
https = nvram_get_int("https_enable");
|
|
msi = nvram_safe_get("ms_ifname");
|
|
dbdir = nvram_safe_get("ms_dbdir");
|
|
if (!(*dbdir))
|
|
dbdir = NULL;
|
|
|
|
mkdir_if_none(dbdir ? : "/var/lib/minidlna");
|
|
|
|
/* persistent ident (router's mac as serial) */
|
|
if (!ether_atoe(nvram_safe_get("lan_hwaddr"), ea))
|
|
f_read("/dev/urandom", ea, sizeof(ea));
|
|
|
|
snprintf(serial, sizeof(serial), "%02x:%02x:%02x:%02x:%02x:%02x", ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
|
|
snprintf(uuident, sizeof(uuident), "4d696e69-444c-164e-9d41-%02x%02x%02x%02x%02x%02x", ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]);
|
|
|
|
if (strlen(msi)) {
|
|
memset(buffer3, 0, sizeof(buffer3)); /* reset */
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
memset(buffer, 0, sizeof(buffer)); /* reset */
|
|
snprintf(buffer, sizeof(buffer), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
memset(buffer2, 0, sizeof(buffer2)); /* reset */
|
|
snprintf(buffer2, sizeof(buffer2), "br%d", i);
|
|
if ((strlen(nvram_safe_get(buffer)) > 0) && (strstr(msi, buffer2) != NULL)) { /* bridge is up & present in 'ms_ifname' */
|
|
if (strlen(buffer3) > 0)
|
|
strlcat(buffer3, ",", sizeof(buffer3));
|
|
|
|
strlcat(buffer3, buffer2, sizeof(buffer3));
|
|
}
|
|
}
|
|
msi = buffer3;
|
|
}
|
|
|
|
fprintf(f, "network_interface=%s\n"
|
|
"port=%d\n"
|
|
"friendly_name=FreshTomato DLNA Server\n"
|
|
"db_dir=%s/.db\n"
|
|
"enable_tivo=%s\n"
|
|
"strict_dlna=%s\n"
|
|
"presentation_url=http%s://%s:%s/nas-media.asp\n"
|
|
"inotify=%s\n"
|
|
"notify_interval=600\n"
|
|
"album_art_names=Cover.jpg/cover.jpg/AlbumArtSmall.jpg/albumartsmall.jpg/AlbumArt.jpg/albumart.jpg/Album.jpg/album.jpg/Folder.jpg/folder.jpg/Thumb.jpg/thumb.jpg\n"
|
|
"log_dir=/var/log\n"
|
|
"log_level=general,artwork,database,inotify,scanner,metadata,http,ssdp,tivo=warn\n"
|
|
"serial=%s\n"
|
|
"uuid=%s\n"
|
|
"model_name=Windows Media Connect compatible (MiniDLNA)\n"
|
|
"model_number=%s\n\n"
|
|
"# Custom config\n"
|
|
"%s\n",
|
|
strlen(msi) ? msi : nvram_safe_get("lan_ifname"),
|
|
(port < 0) || (port >= 0xffff) ? 0 : port, /* 0 - means random port (feature applied as minidlna patch) */
|
|
dbdir ? : "/var/lib/minidlna",
|
|
nvram_get_int("ms_tivo") ? "yes" : "no",
|
|
nvram_get_int("ms_stdlna") ? "yes" : "no",
|
|
https ? "s" : "", nvram_safe_get("lan_ipaddr"), nvram_safe_get(https ? "https_lanport" : "http_lanport"),
|
|
nvram_get_int("ms_autoscan") ? "yes" : "no",
|
|
serial,
|
|
uuident,
|
|
tomato_version,
|
|
nvram_safe_get("ms_custom"));
|
|
|
|
/* media directories */
|
|
if ((buf = strdup(nvram_safe_get("ms_dirs"))) && (*buf)) {
|
|
/* path<restricted[A|V|P|] */
|
|
p = buf;
|
|
while ((q = strsep(&p, ">")) != NULL) {
|
|
if ((vstrsep(q, "<", &path, &restricted) < 1) || (!path) || (!*path))
|
|
continue;
|
|
|
|
fprintf(f, "media_dir=%s%s%s\n",
|
|
restricted ? : "", (restricted && *restricted) ? "," : "", path);
|
|
}
|
|
free(buf);
|
|
}
|
|
fclose(f);
|
|
}
|
|
else {
|
|
logerr(__FUNCTION__, __LINE__, argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (nvram_get_int("ms_debug"))
|
|
argv[index++] = "-v";
|
|
|
|
ret = _eval(argv, NULL, 0, &pid);
|
|
sleep(1);
|
|
|
|
if ((pidof("minidlna") > 0) && !ret)
|
|
once = 0;
|
|
else
|
|
logmsg(LOG_ERR, "starting minidlna failed ...");
|
|
}
|
|
|
|
static void stop_media_server(void)
|
|
{
|
|
if (serialize_restart("minidlna", 0))
|
|
return;
|
|
|
|
if (pidof("minidlna") > 0)
|
|
killall_tk_period_wait("minidlna", 50);
|
|
|
|
/* clean-up */
|
|
eval("rm", "-rf", "/var/run/minidlna");
|
|
}
|
|
#endif /* TCONFIG_MEDIA_SERVER */
|
|
|
|
#ifdef TCONFIG_HAVEGED
|
|
void start_haveged(void)
|
|
{
|
|
pid_t pid;
|
|
|
|
if (serialize_restart("haveged", 1))
|
|
return;
|
|
|
|
char *cmd_argv[] = { "haveged",
|
|
"-r", "0", /* 0 = run as daemon */
|
|
"-w", "1024", /* write_wakeup_threshold [bits] */
|
|
#ifdef TCONFIG_BCMARM /* it has to be checkd for all MIPS routers */
|
|
"-d", "32", /* data cache size [KB] - fallback to 16 */
|
|
"-i", "32", /* instruction cache size [KB] - fallback to 16 */
|
|
#endif
|
|
NULL };
|
|
|
|
_eval(cmd_argv, NULL, 0, &pid);
|
|
}
|
|
|
|
void stop_haveged(void)
|
|
{
|
|
if (serialize_restart("haveged", 0))
|
|
return;
|
|
|
|
if (pidof("haveged") > 0)
|
|
killall_tk_period_wait("haveged", 50);
|
|
}
|
|
#endif /* TCONFIG_HAVEGED */
|
|
|
|
#ifdef TCONFIG_USB
|
|
static void start_nas_services(void)
|
|
{
|
|
if (nvram_get_int("g_upgrade") || nvram_get_int("g_reboot"))
|
|
return;
|
|
|
|
if (getpid() != 1) {
|
|
start_service("usbapps");
|
|
return;
|
|
}
|
|
|
|
#ifdef TCONFIG_SAMBASRV
|
|
start_samba(0);
|
|
#endif
|
|
#ifdef TCONFIG_FTP
|
|
start_ftpd(0);
|
|
#endif
|
|
#ifdef TCONFIG_MEDIA_SERVER
|
|
start_media_server(0);
|
|
#endif
|
|
}
|
|
|
|
static void stop_nas_services(void)
|
|
{
|
|
if (getpid() != 1) {
|
|
stop_service("usbapps");
|
|
return;
|
|
}
|
|
|
|
#ifdef TCONFIG_MEDIA_SERVER
|
|
stop_media_server();
|
|
#endif
|
|
#ifdef TCONFIG_FTP
|
|
stop_ftpd();
|
|
#endif
|
|
#ifdef TCONFIG_SAMBASRV
|
|
stop_samba();
|
|
#endif
|
|
}
|
|
|
|
void restart_nas_services(int stop, int start)
|
|
{
|
|
int fd = file_lock("usb");
|
|
/* restart all NAS applications */
|
|
if (stop)
|
|
stop_nas_services();
|
|
if (start)
|
|
start_nas_services();
|
|
|
|
file_unlock(fd);
|
|
}
|
|
#endif /* TCONFIG_USB */
|
|
|
|
/* -1 = Don't check for this program, it is not expected to be running.
|
|
* Other = This program has been started and should be kept running. If no
|
|
* process with the name is running, call func to restart it.
|
|
* Note: At startup, dnsmasq forks a short-lived child which forks a
|
|
* long-lived (grand)child. The parents terminate.
|
|
* Many daemons use this technique.
|
|
*/
|
|
static void _check(pid_t pid, const char *name, void (*func)(void))
|
|
{
|
|
if (pid == -1)
|
|
return;
|
|
|
|
if (pidof(name) > 0)
|
|
return;
|
|
|
|
logmsg(LOG_ERR, "%s terminated unexpectedly, restarting", name);
|
|
func();
|
|
|
|
/* force recheck in 500 msec */
|
|
setitimer(ITIMER_REAL, &pop_tv, NULL);
|
|
}
|
|
|
|
void check_services(void)
|
|
{
|
|
/* periodically reap any zombies */
|
|
setitimer(ITIMER_REAL, &zombie_tv, NULL);
|
|
|
|
/* do not restart if upgrading/rebooting */
|
|
if (!nvram_get_int("g_upgrade") && !nvram_get_int("g_reboot")) {
|
|
_check(pid_hotplug2, "hotplug2", start_hotplug2);
|
|
// _check(pid_dnsmasq, "dnsmasq", start_dnsmasq);
|
|
_check(pid_crond, "crond", start_cron);
|
|
_check(pid_igmp, "igmpproxy", start_igmp_proxy);
|
|
if (nvram_get_int("ntp_updates") >= 1)
|
|
_check(pid_ntpd, "ntpd", start_ntpd);
|
|
}
|
|
}
|
|
|
|
void start_services(void)
|
|
{
|
|
static int once = 1;
|
|
|
|
#ifdef TCONFIG_HAVEGED
|
|
start_haveged();
|
|
#endif
|
|
if (once) {
|
|
once = 0;
|
|
|
|
if (nvram_get_int("telnetd_eas"))
|
|
start_telnetd();
|
|
if (nvram_get_int("sshd_eas"))
|
|
start_sshd();
|
|
}
|
|
start_dhcpc_lan(); /* start very early */
|
|
start_nas();
|
|
#ifdef TCONFIG_ZEBRA
|
|
start_zebra();
|
|
#endif
|
|
#ifdef TCONFIG_SDHC
|
|
start_mmc();
|
|
#endif
|
|
start_dnsmasq();
|
|
#ifdef TCONFIG_MDNS
|
|
start_mdns();
|
|
#endif
|
|
start_cifs();
|
|
start_httpd();
|
|
#ifdef TCONFIG_NGINX
|
|
start_nginx(0);
|
|
start_mysql(0);
|
|
#endif
|
|
start_cron();
|
|
#ifdef TCONFIG_PPTPD
|
|
start_pptpd(0);
|
|
#endif
|
|
#ifdef TCONFIG_USB
|
|
restart_nas_services(1, 1); /* Samba, FTP and Media Server */
|
|
notice_set("nas", "" );
|
|
#endif
|
|
#ifdef TCONFIG_SNMP
|
|
start_snmp();
|
|
#endif
|
|
start_tomatoanon();
|
|
#ifdef TCONFIG_TOR
|
|
start_tor(0);
|
|
#endif
|
|
#ifdef TCONFIG_BT
|
|
start_bittorrent(0);
|
|
#endif
|
|
#ifdef TCONFIG_NOCAT
|
|
start_nocat();
|
|
#endif
|
|
#ifdef TCONFIG_NFS
|
|
start_nfs();
|
|
#endif
|
|
#ifdef TCONFIG_BCMARM
|
|
/* do LED setup for Router */
|
|
led_setup();
|
|
#endif
|
|
start_rstats(0);
|
|
start_cstats(0);
|
|
#ifdef TCONFIG_FANCTRL
|
|
start_phy_tempsense();
|
|
#endif
|
|
#if 0 /* see load_wl() for dhd_msg_level */
|
|
#ifdef TCONFIG_BCM7
|
|
if (!nvram_get_int("debug_wireless")) { /* suppress dhd debug messages (default 0x01) */
|
|
system("/usr/sbin/dhd -i eth1 msglevel 0x00");
|
|
system("/usr/sbin/dhd -i eth2 msglevel 0x00");
|
|
system("/usr/sbin/dhd -i eth3 msglevel 0x00");
|
|
}
|
|
#endif
|
|
#endif
|
|
#ifdef TCONFIG_BCMBSD
|
|
start_bsd();
|
|
#endif
|
|
#ifdef TCONFIG_ROAM
|
|
start_roamast();
|
|
#endif
|
|
#ifdef TCONFIG_IRQBALANCE
|
|
start_irqbalance();
|
|
#endif
|
|
}
|
|
|
|
void stop_services(void)
|
|
{
|
|
stop_dhcpc_lan(); /* stop very early */
|
|
clear_resolv();
|
|
stop_rstats();
|
|
stop_cstats();
|
|
#ifdef TCONFIG_FANCTRL
|
|
stop_phy_tempsense();
|
|
#endif
|
|
#ifdef TCONFIG_BT
|
|
stop_bittorrent();
|
|
#endif
|
|
#ifdef TCONFIG_NOCAT
|
|
stop_nocat();
|
|
#endif
|
|
#ifdef TCONFIG_SNMP
|
|
stop_snmp();
|
|
#endif
|
|
#ifdef TCONFIG_TOR
|
|
stop_tor();
|
|
#endif
|
|
stop_tomatoanon();
|
|
#ifdef TCONFIG_NFS
|
|
stop_nfs();
|
|
#endif
|
|
#ifdef TCONFIG_MDNS
|
|
stop_mdns();
|
|
#endif
|
|
#ifdef TCONFIG_USB
|
|
restart_nas_services(1, 0); /* Samba, FTP and Media Server */
|
|
#endif
|
|
#ifdef TCONFIG_PPTPD
|
|
stop_pptpd();
|
|
#endif
|
|
stop_sched();
|
|
stop_cron();
|
|
#ifdef TCONFIG_NGINX
|
|
stop_mysql();
|
|
stop_nginx();
|
|
#endif
|
|
#ifdef TCONFIG_SDHC
|
|
stop_mmc();
|
|
#endif
|
|
stop_cifs();
|
|
stop_httpd();
|
|
stop_dnsmasq();
|
|
#ifdef TCONFIG_ZEBRA
|
|
stop_zebra();
|
|
#endif
|
|
stop_nas();
|
|
#ifdef TCONFIG_BCMBSD
|
|
stop_bsd();
|
|
#endif
|
|
#ifdef TCONFIG_ROAM
|
|
stop_roamast();
|
|
#endif
|
|
#ifdef TCONFIG_IRQBALANCE
|
|
stop_irqbalance();
|
|
#endif
|
|
#ifdef TCONFIG_HAVEGED
|
|
stop_haveged();
|
|
#endif
|
|
}
|
|
|
|
/* nvram "action_service" is: "service-action[-modifier]"
|
|
* action is something like "stop" or "start" or "restart"
|
|
* optional modifier is "c" for the "service" command-line command
|
|
*/
|
|
void exec_service(void)
|
|
{
|
|
const int A_START = 1;
|
|
const int A_STOP = 2;
|
|
const int A_RESTART = 1|2;
|
|
char buffer[128], buffer2[16], buffer3[16];
|
|
char *service;
|
|
char *act;
|
|
char *next;
|
|
char *modifier;
|
|
int action, user;
|
|
int i;
|
|
int act_start, act_stop;
|
|
|
|
strlcpy(buffer, nvram_safe_get("action_service"), sizeof(buffer));
|
|
next = buffer;
|
|
|
|
TOP:
|
|
act = strsep(&next, ",");
|
|
service = strsep(&act, "-");
|
|
if (act == NULL) {
|
|
next = NULL;
|
|
goto CLEAR;
|
|
}
|
|
modifier = act;
|
|
action = 0;
|
|
strsep(&modifier, "-");
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: service=%s action=%s modifier=%s", __FUNCTION__, service, act, modifier ? : "");
|
|
|
|
if (strcmp(act, "start") == 0)
|
|
action = A_START;
|
|
if (strcmp(act, "stop") == 0)
|
|
action = A_STOP;
|
|
if (strcmp(act, "restart") == 0)
|
|
action = A_RESTART;
|
|
|
|
act_start = action & A_START;
|
|
act_stop = action & A_STOP;
|
|
|
|
user = (modifier != NULL && *modifier == 'c');
|
|
|
|
if (strcmp(service, "rstats_nvram") == 0) {
|
|
if (act_stop) del_rstats_defaults();
|
|
if (act_start) add_rstats_defaults();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "cstats_nvram") == 0) {
|
|
if (act_stop) del_cstats_defaults();
|
|
if (act_start) add_cstats_defaults();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_FTP
|
|
if (strcmp(service, "ftp_nvram") == 0) {
|
|
if (act_stop) del_ftp_defaults();
|
|
if (act_start) add_ftp_defaults();
|
|
goto CLEAR;
|
|
}
|
|
#endif /* TCONFIG_FTP */
|
|
|
|
#ifdef TCONFIG_SNMP
|
|
if (strcmp(service, "snmp_nvram") == 0) {
|
|
if (act_stop) del_snmp_defaults();
|
|
if (act_start) add_snmp_defaults();
|
|
goto CLEAR;
|
|
}
|
|
#endif /* TCONFIG_SNMP */
|
|
|
|
if (strcmp(service, "upnp_nvram") == 0) {
|
|
if (act_stop) del_upnp_defaults();
|
|
if (act_start) add_upnp_defaults();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_BCMBSD
|
|
if (strcmp(service, "bsd_nvram") == 0) {
|
|
if (act_stop) del_bsd_defaults();
|
|
if (act_start) add_bsd_defaults();
|
|
goto CLEAR;
|
|
}
|
|
#endif /* TCONFIG_BCMBSD */
|
|
|
|
if (strcmp(service, "dhcpc_wan") == 0) {
|
|
if (act_stop) stop_dhcpc("wan");
|
|
if (act_start) start_dhcpc("wan");
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "dhcpc_wan2") == 0) {
|
|
if (act_stop) stop_dhcpc("wan2");
|
|
if (act_start) start_dhcpc("wan2");
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_MULTIWAN
|
|
if (strcmp(service, "dhcpc_wan3") == 0) {
|
|
if (act_stop) stop_dhcpc("wan3");
|
|
if (act_start) start_dhcpc("wan3");
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "dhcpc_wan4") == 0) {
|
|
if (act_stop) stop_dhcpc("wan4");
|
|
if (act_start) start_dhcpc("wan4");
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strcmp(service, "dnsmasq") == 0) {
|
|
if (act_stop) stop_dnsmasq();
|
|
if (act_start && !nvram_get_int("g_upgrade")) {
|
|
dns_to_resolv();
|
|
start_dnsmasq();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "dns") == 0) {
|
|
if (act_start) reload_dnsmasq();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_DNSCRYPT
|
|
if ((strcmp(service, "dnscrypt") == 0) || (strcmp(service, "dnscrypt_proxy") == 0)) {
|
|
if (act_stop) stop_dnscrypt();
|
|
if (act_start) start_dnscrypt();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_STUBBY
|
|
if (strcmp(service, "stubby") == 0) {
|
|
if (act_stop) stop_stubby();
|
|
if (act_start) start_stubby();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_MDNS
|
|
if ((strcmp(service, "mdns") == 0) || (strcmp(service, "avahi_daemon") == 0)) {
|
|
if (act_stop) stop_mdns();
|
|
if (act_start) start_mdns();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_IRQBALANCE
|
|
if (strcmp(service, "irqbalance") == 0) {
|
|
if (act_stop) stop_irqbalance();
|
|
if (act_start) start_irqbalance();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_HAVEGED
|
|
if (strcmp(service, "haveged") == 0) {
|
|
if (act_stop) stop_haveged();
|
|
if (act_start) start_haveged();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strcmp(service, "adblock") == 0) {
|
|
if (act_stop) stop_adblock();
|
|
if (act_start) start_adblock(1); /* update lists immediately */
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "firewall") == 0) {
|
|
if (act_stop) {
|
|
stop_firewall();
|
|
stop_igmp_proxy();
|
|
stop_udpxy();
|
|
}
|
|
if (act_start) {
|
|
start_firewall();
|
|
start_igmp_proxy();
|
|
start_udpxy();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "restrict") == 0) {
|
|
if (act_stop)
|
|
stop_firewall();
|
|
|
|
if (act_start) {
|
|
i = nvram_get_int("rrules_radio"); /* -1 = not used, 0 = enabled by rule, 1 = disabled by rule */
|
|
|
|
start_firewall();
|
|
|
|
/* if radio was disabled by access restriction, but no rule is handling it now, enable it */
|
|
if (i == 1) {
|
|
if (nvram_get_int("rrules_radio") < 0)
|
|
eval("radio", "on");
|
|
}
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "arpbind") == 0) {
|
|
if (act_stop) stop_arpbind();
|
|
if (act_start) start_arpbind();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "bwlimit") == 0) {
|
|
if (act_stop) {
|
|
stop_bwlimit();
|
|
#ifdef TCONFIG_NOCAT
|
|
stop_nocat();
|
|
#endif
|
|
}
|
|
stop_firewall();
|
|
start_firewall(); /* always restarted */
|
|
if (act_start) {
|
|
start_bwlimit();
|
|
#ifdef TCONFIG_NOCAT
|
|
start_nocat();
|
|
#endif
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "qos") == 0) {
|
|
if (act_stop) {
|
|
stop_qos("wan");
|
|
stop_qos("wan2");
|
|
#ifdef TCONFIG_MULTIWAN
|
|
stop_qos("wan3");
|
|
stop_qos("wan4");
|
|
#endif
|
|
}
|
|
stop_firewall();
|
|
start_firewall(); /* always restarted */
|
|
if (act_start) {
|
|
start_qos("wan");
|
|
if (check_wanup("wan2"))
|
|
start_qos("wan2");
|
|
#ifdef TCONFIG_MULTIWAN
|
|
if (check_wanup("wan3"))
|
|
start_qos("wan3");
|
|
if (check_wanup("wan4"))
|
|
start_qos("wan4");
|
|
#endif
|
|
if (nvram_get_int("qos_reset"))
|
|
f_write_string("/proc/net/clear_marks", "1", 0, 0);
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if ((strcmp(service, "upnp") == 0) || (strcmp(service, "miniupnpd") == 0)) {
|
|
if (act_stop) stop_upnp();
|
|
stop_firewall();
|
|
start_firewall(); /* always restarted */
|
|
if (act_start) start_upnp();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "telnetd") == 0) {
|
|
if (act_stop) stop_telnetd();
|
|
if (act_start) start_telnetd();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "sshd") == 0 || strcmp(service, "dropbear") == 0) {
|
|
if (act_stop) stop_sshd();
|
|
if (act_start) start_sshd();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "httpd") == 0) {
|
|
if (act_stop) stop_httpd();
|
|
if (act_start) start_httpd();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_IPV6
|
|
if (strcmp(service, "dhcp6") == 0) {
|
|
if (act_stop) stop_dhcp6c();
|
|
if (act_start) start_dhcp6c();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strncmp(service, "admin", 5) == 0) {
|
|
if (act_stop) {
|
|
if (!(strcmp(service, "adminnosshd") == 0))
|
|
stop_sshd();
|
|
stop_telnetd();
|
|
stop_httpd();
|
|
}
|
|
stop_firewall();
|
|
start_firewall(); /* always restarted */
|
|
if (act_start) {
|
|
stop_httpd();
|
|
start_httpd();
|
|
if (!(strcmp(service, "adminnosshd") == 0))
|
|
create_passwd();
|
|
if (nvram_get_int("telnetd_eas"))
|
|
start_telnetd();
|
|
if (nvram_get_int("sshd_eas") && (!(strcmp(service, "adminnosshd") == 0)))
|
|
start_sshd();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "ddns") == 0) {
|
|
if (act_stop) stop_ddns();
|
|
if (act_start) start_ddns();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "ntpd") == 0) {
|
|
if (act_stop) stop_ntpd();
|
|
if (act_start) start_ntpd();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "logging") == 0) {
|
|
if (act_stop) stop_syslog();
|
|
if (act_start) start_syslog();
|
|
if (!user) {
|
|
/* always restarted except from "service" command */
|
|
stop_cron();
|
|
start_cron();
|
|
stop_firewall();
|
|
start_firewall();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "crond") == 0) {
|
|
if (act_stop) stop_cron();
|
|
if (act_start) start_cron();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "hotplug") == 0) {
|
|
if (act_stop) stop_hotplug2();
|
|
if (act_start) start_hotplug2();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "upgrade") == 0) {
|
|
if (act_start) {
|
|
nvram_set("g_upgrade", "1");
|
|
|
|
if (nvram_get_int("webmon_bkp"))
|
|
xstart("/usr/sbin/webmon_bkp", "hourly"); /* make a copy before upgrade */
|
|
|
|
stop_sched();
|
|
stop_cron();
|
|
#ifdef TCONFIG_NGINX
|
|
stop_mysql();
|
|
stop_nginx();
|
|
#endif
|
|
#ifdef TCONFIG_NFS
|
|
stop_nfs();
|
|
#endif
|
|
#ifdef TCONFIG_USB
|
|
restart_nas_services(1, 0); /* Samba, FTP and Media Server */
|
|
#endif
|
|
#ifdef TCONFIG_BT
|
|
stop_bittorrent();
|
|
#endif
|
|
#ifdef TCONFIG_NOCAT
|
|
stop_nocat();
|
|
#endif
|
|
#ifdef TCONFIG_TOR
|
|
stop_tor();
|
|
#endif
|
|
killall("rstats", SIGTERM);
|
|
killall("cstats", SIGTERM);
|
|
killall("buttons", SIGTERM);
|
|
stop_upnp();
|
|
if (!nvram_get_int("remote_upgrade")) {
|
|
killall("xl2tpd", SIGTERM);
|
|
killall("pppd", SIGTERM);
|
|
stop_dnsmasq();
|
|
killall("udhcpc", SIGTERM);
|
|
stop_wan();
|
|
} else
|
|
stop_adblock();
|
|
|
|
stop_tomatoanon();
|
|
remove_conntrack();
|
|
#ifdef TCONFIG_ZEBRA
|
|
stop_zebra();
|
|
#endif
|
|
#ifdef TCONFIG_IRQBALANCE
|
|
stop_irqbalance();
|
|
#endif
|
|
#ifdef TCONFIG_MDNS
|
|
stop_mdns();
|
|
#endif
|
|
#ifdef TCONFIG_HAVEGED
|
|
stop_haveged();
|
|
#endif
|
|
stop_jffs2();
|
|
stop_syslog();
|
|
sleep(1);
|
|
#ifdef TCONFIG_USB
|
|
#ifdef TCONFIG_USBAP
|
|
stop_wireless();
|
|
sleep(1);
|
|
#endif
|
|
remove_storage_main(1);
|
|
stop_usb();
|
|
#endif /* TCONFIG_USB */
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_CIFS
|
|
if (strcmp(service, "cifs") == 0) {
|
|
if (act_stop) stop_cifs();
|
|
if (act_start) start_cifs();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_JFFS2
|
|
if (strncmp(service, "jffs", 4) == 0) { /* could be jffs/jffs2 */
|
|
if (act_stop) stop_jffs2();
|
|
if (act_start) start_jffs2();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_ZEBRA
|
|
if (strcmp(service, "zebra") == 0) {
|
|
if (act_stop) stop_zebra();
|
|
if (act_start) start_zebra();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_SDHC
|
|
if (strcmp(service, "mmc") == 0) {
|
|
if (act_stop) stop_mmc();
|
|
if (act_start) start_mmc();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strcmp(service, "routing") == 0) {
|
|
if (act_stop) {
|
|
#ifdef TCONFIG_ZEBRA
|
|
stop_zebra();
|
|
#endif
|
|
do_static_routes(0); /* remove old '_saved' */
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
if ((i == 0) || (strcmp(nvram_safe_get(buffer2), "") != 0))
|
|
eval("brctl", "stp", nvram_safe_get(buffer2), "0");
|
|
}
|
|
}
|
|
stop_firewall();
|
|
start_firewall();
|
|
if (act_start) {
|
|
do_static_routes(1); /* add new */
|
|
#ifdef TCONFIG_ZEBRA
|
|
start_zebra();
|
|
#endif
|
|
for (i = 0; i < BRIDGE_COUNT; i++) {
|
|
memset(buffer2, 0, sizeof(buffer2));
|
|
snprintf(buffer2, sizeof(buffer2), (i == 0 ? "lan_ifname" : "lan%d_ifname"), i);
|
|
if ((i == 0) || (strcmp(nvram_safe_get(buffer2), "") != 0)) {
|
|
memset(buffer3, 0, sizeof(buffer3));
|
|
snprintf(buffer3, sizeof(buffer3), (i == 0 ? "lan_stp" : "lan%d_stp"), i);
|
|
eval("brctl", "stp", nvram_safe_get(buffer2), nvram_safe_get(buffer3));
|
|
}
|
|
}
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "ctnf") == 0) {
|
|
if (act_start) {
|
|
setup_conntrack();
|
|
stop_firewall();
|
|
start_firewall();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "wan") == 0) {
|
|
if (act_stop) stop_wan();
|
|
if (act_start) {
|
|
rename("/tmp/ppp/wan_log", "/tmp/ppp/wan_log.~");
|
|
start_wan();
|
|
sleep(5);
|
|
force_to_dial("wan");
|
|
sleep(5);
|
|
force_to_dial("wan2");
|
|
#ifdef TCONFIG_MULTIWAN
|
|
sleep(5);
|
|
force_to_dial("wan3");
|
|
sleep(5);
|
|
force_to_dial("wan4");
|
|
#endif
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "wan1") == 0) {
|
|
if (act_stop) stop_wan_if("wan");
|
|
if (act_start) {
|
|
start_wan_if("wan");
|
|
sleep(5);
|
|
force_to_dial("wan");
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "wan2") == 0) {
|
|
if (act_stop) stop_wan_if("wan2");
|
|
if (act_start) {
|
|
start_wan_if("wan2");
|
|
sleep(5);
|
|
force_to_dial("wan2");
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_MULTIWAN
|
|
if (strcmp(service, "wan3") == 0) {
|
|
if (act_stop) stop_wan_if("wan3");
|
|
if (act_start) {
|
|
start_wan_if("wan3");
|
|
sleep(5);
|
|
force_to_dial("wan3");
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "wan4") == 0) {
|
|
if (act_stop) stop_wan_if("wan4");
|
|
if (act_start) {
|
|
start_wan_if("wan4");
|
|
sleep(5);
|
|
force_to_dial("wan4");
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strcmp(service, "net") == 0) {
|
|
if (act_stop) {
|
|
#ifdef TCONFIG_USB
|
|
stop_nas_services();
|
|
#endif
|
|
#ifdef TCONFIG_PPPRELAY
|
|
stop_pppoerelay();
|
|
#endif
|
|
stop_httpd();
|
|
#ifdef TCONFIG_MDNS
|
|
stop_mdns();
|
|
#endif
|
|
stop_dnsmasq();
|
|
stop_nas();
|
|
stop_wan();
|
|
stop_arpbind();
|
|
stop_lan();
|
|
stop_vlan();
|
|
}
|
|
if (act_start) {
|
|
start_vlan();
|
|
start_lan();
|
|
start_arpbind();
|
|
start_nas();
|
|
start_dnsmasq();
|
|
#ifdef TCONFIG_MDNS
|
|
start_mdns();
|
|
#endif
|
|
start_httpd();
|
|
start_wl();
|
|
#ifdef TCONFIG_USB
|
|
start_nas_services();
|
|
#endif
|
|
/* last one as ssh telnet httpd samba etc can fail to load until start_wan_done */
|
|
start_wan();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if ((strcmp(service, "wireless") == 0) || (strcmp(service, "wl") == 0)) { /* for tomato user --> 'service wl start' will restart wl allways (failsafe, even if wl was not stopped!) */
|
|
if (act_stop) stop_wireless();
|
|
if (act_start) restart_wireless();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "wlgui") == 0) { /* for GUI to restart wireless (only stop wl once!) */
|
|
if (act_stop) stop_wireless();
|
|
if (act_start) start_wireless();
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "nas") == 0) {
|
|
if (act_stop) stop_nas();
|
|
if (act_start) {
|
|
start_nas();
|
|
start_wl();
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_BCMBSD
|
|
if (strcmp(service, "bsd") == 0) {
|
|
if (act_stop) stop_bsd();
|
|
if (act_start) start_bsd();
|
|
goto CLEAR;
|
|
}
|
|
#endif /* TCONFIG_BCMBSD */
|
|
|
|
#ifdef TCONFIG_ROAM
|
|
if ((strcmp(service, "roamast") == 0) || (strcmp(service, "rssi") == 0)) {
|
|
if (act_stop) stop_roamast();
|
|
if (act_start) start_roamast();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strncmp(service, "rstats", 6) == 0) {
|
|
if (act_stop) stop_rstats();
|
|
if (act_start) {
|
|
if (strcmp(service, "rstatsnew") == 0)
|
|
start_rstats(1);
|
|
else
|
|
start_rstats(0);
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strncmp(service, "cstats", 6) == 0) {
|
|
if (act_stop) stop_cstats();
|
|
if (act_start) {
|
|
if (strcmp(service, "cstatsnew") == 0)
|
|
start_cstats(1);
|
|
else
|
|
start_cstats(0);
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "sched") == 0) {
|
|
if (act_stop) stop_sched();
|
|
if (act_start) start_sched();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_BT
|
|
if ((strcmp(service, "bittorrent") == 0) || (strcmp(service, "transmission") == 0) || (strcmp(service, "transmission_da") == 0)) {
|
|
if (act_stop) stop_bittorrent();
|
|
if (act_start) start_bittorrent(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_NFS
|
|
if ((strcmp(service, "nfs") == 0) || (strcmp(service, "nfsd") == 0)) {
|
|
if (act_stop) stop_nfs();
|
|
if (act_start) start_nfs();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_SNMP
|
|
if (strcmp(service, "snmp") == 0) {
|
|
if (act_stop) stop_snmp();
|
|
if (act_start) start_snmp();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_TOR
|
|
if (strcmp(service, "tor") == 0) {
|
|
if (act_stop) stop_tor();
|
|
stop_firewall();
|
|
start_firewall(); /* always restarted */
|
|
if (act_start) start_tor(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_UPS
|
|
if (strcmp(service, "ups") == 0) {
|
|
if (act_stop) stop_ups();
|
|
if (act_start) start_ups();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
if (strcmp(service, "tomatoanon") == 0) {
|
|
if (act_stop) stop_tomatoanon();
|
|
if (act_start) start_tomatoanon();
|
|
goto CLEAR;
|
|
}
|
|
|
|
#ifdef TCONFIG_USB
|
|
if (strcmp(service, "usb") == 0) {
|
|
if (act_stop) stop_usb();
|
|
if (act_start) {
|
|
start_usb();
|
|
/* restart Samba and ftp since they may be killed by stop_usb() */
|
|
restart_nas_services(1, 1);
|
|
/* remount all partitions by simulating hotplug event */
|
|
add_remove_usbhost("-1", 1);
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "usbapps") == 0) {
|
|
if (act_stop) stop_nas_services();
|
|
if (act_start) start_nas_services();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_FTP
|
|
if ((strcmp(service, "ftpd") == 0) || (strcmp(service, "vsftpd") == 0)) {
|
|
if (act_stop) stop_ftpd();
|
|
setup_conntrack();
|
|
if (act_start) start_ftpd(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_MEDIA_SERVER
|
|
if ((strcmp(service, "media") == 0) || (strcmp(service, "minidlna") == 0)) {
|
|
if (act_stop) stop_media_server();
|
|
if (act_start) start_media_server(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_SAMBASRV
|
|
if ((strcmp(service, "samba") == 0) || (strcmp(service, "smbd") == 0)) {
|
|
if (act_stop) stop_samba();
|
|
if (act_start) {
|
|
create_passwd();
|
|
stop_dnsmasq();
|
|
start_dnsmasq();
|
|
start_samba(1); /* force (re)start */
|
|
}
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_OPENVPN
|
|
if (strncmp(service, "vpnclient", 9) == 0) {
|
|
if (act_stop) stop_ovpn_client(atoi(&service[9]));
|
|
if (act_start) start_ovpn_client(atoi(&service[9]));
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strncmp(service, "vpnserver", 9) == 0) {
|
|
if (act_stop) stop_ovpn_server(atoi(&service[9]));
|
|
if (act_start) start_ovpn_server(atoi(&service[9]));
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_WIREGUARD
|
|
if (strncmp(service, "wireguard", 9) == 0) {
|
|
if (act_stop) stop_wireguard(atoi(&service[9]));
|
|
if (act_start) start_wireguard(atoi(&service[9]));
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_TINC
|
|
if ((strcmp(service, "tinc") == 0) || (strcmp(service, "tincd") == 0)) {
|
|
if (act_stop) stop_tinc();
|
|
if (act_start) start_tinc(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_FANCTRL
|
|
if (strcmp(service, "fanctrl") == 0) {
|
|
if (act_stop) stop_phy_tempsense();
|
|
if (act_start) start_phy_tempsense();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_NOCAT
|
|
if (strcmp(service, "splashd") == 0) {
|
|
if (act_stop) stop_nocat();
|
|
if (act_start) start_nocat();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_NGINX
|
|
if (strcmp(service, "nginx") == 0) {
|
|
if (act_stop) stop_nginx();
|
|
if (act_start) start_nginx(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
if ((strcmp(service, "mysql") == 0) || (strcmp(service, "mysqld") == 0)) {
|
|
if (act_stop) stop_mysql();
|
|
if (act_start) start_mysql(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
#ifdef TCONFIG_PPTPD
|
|
if (strcmp(service, "pptpd") == 0) {
|
|
if (act_stop) stop_pptpd();
|
|
if (act_start) start_pptpd(1); /* force (re)start */
|
|
goto CLEAR;
|
|
}
|
|
|
|
if (strcmp(service, "pptpclient") == 0) {
|
|
if (act_stop) stop_pptp_client();
|
|
if (act_start) start_pptp_client();
|
|
goto CLEAR;
|
|
}
|
|
#endif
|
|
|
|
logmsg(LOG_WARNING, "no such service: %s", service);
|
|
|
|
CLEAR:
|
|
if (next)
|
|
goto TOP;
|
|
|
|
/* some functions check action_service and must be cleared at end */
|
|
nvram_set("action_service", "");
|
|
|
|
/* force recheck in 500 msec */
|
|
setitimer(ITIMER_REAL, &pop_tv, NULL);
|
|
}
|
|
|
|
static void do_service(const char *name, const char *action, int user)
|
|
{
|
|
int n;
|
|
char s[64], t[64];
|
|
|
|
snprintf(t, sizeof(t), "%s", nvram_safe_get("action_service"));
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: IN name: %s action: %s user: %d", __FUNCTION__, name, action, user);
|
|
|
|
n = 200;
|
|
while (!nvram_match("action_service", "")) { /* wait until nvram 'action_service' is empty (max 20 seconds when not user, user can wait indefinitely [??]) */
|
|
if (user) {
|
|
putchar('*');
|
|
fflush(stdout);
|
|
}
|
|
else if (--n < 0)
|
|
break;
|
|
|
|
usleep(100 * 1000); /* microseconds => 0,1s */
|
|
}
|
|
|
|
snprintf(s, sizeof(s), "%s-%s%s", name, action, (user ? "-c" : ""));
|
|
nvram_set("action_service", s); /* set new service to execute (for exec_service) */
|
|
|
|
if (n < 190) /* log only above 1 sec */
|
|
logmsg(LOG_DEBUG, "*** %s: waited %d second(s) for 'action_service' to be empty [%s] - [%s]", __FUNCTION__, ((200 - n) / 10), t, s);
|
|
|
|
logmsg(LOG_DEBUG, "*** %s: setting new 'action_service': [%s]", __FUNCTION__, s);
|
|
|
|
if (nvram_get_int("debug_rc_svc")) {
|
|
nvram_unset("debug_rc_svc");
|
|
exec_service();
|
|
}
|
|
else
|
|
kill(1, SIGUSR1);
|
|
|
|
n = 200;
|
|
while (nvram_match("action_service", s)) { /* wait until nvram 'action_service' is not equal 'name' (max 20 seconds when not user, user can wait indefinitely[??]) */
|
|
if (user) {
|
|
putchar('.');
|
|
fflush(stdout);
|
|
}
|
|
else if (--n < 0)
|
|
break;
|
|
|
|
usleep(100 * 1000); /* microseconds => 0,1s */
|
|
}
|
|
|
|
if (n < 190) /* log only above 1 sec */
|
|
logmsg(LOG_DEBUG, "*** %s: OUT waited %d second(s) for execution of 'action_service': [%s]", __FUNCTION__, ((200 - n) / 10), s);
|
|
}
|
|
|
|
int service_main(int argc, char *argv[])
|
|
{
|
|
if (argc != 3)
|
|
usage_exit(argv[0], "<service> <action>");
|
|
|
|
do_service(argv[1], argv[2], 1);
|
|
printf("\nDone.\n");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void start_service(const char *name)
|
|
{
|
|
do_service(name, "start", 0);
|
|
}
|
|
|
|
void stop_service(const char *name)
|
|
{
|
|
do_service(name, "stop", 0);
|
|
}
|
|
|
|
#ifdef TCONFIG_BCMBSD
|
|
int start_bsd(void)
|
|
{
|
|
int ret;
|
|
int bsd_enable = nvram_get_int("smart_connect_x");
|
|
|
|
/* only if enabled */
|
|
if (bsd_enable) {
|
|
add_bsd_defaults(); /* add bsd nvram values only if feature is enabled! */
|
|
|
|
/* band steering settings corrections, because 5 GHz module is the first one */
|
|
switch (get_model()) {
|
|
case MODEL_EA6350v1: /* EA6200 */
|
|
if (nvram_match("boardnum", "20140309")) {
|
|
/* nothing to do for EA6350v1 */
|
|
break;
|
|
}
|
|
/* fall through */
|
|
case MODEL_F9K1113v2:
|
|
case MODEL_F9K1113v2_20X0: /* version 2000 and 2010 */
|
|
case MODEL_R1D:
|
|
nvram_set("wl1_bsd_steering_policy", "0 5 3 -52 0 110 0x22");
|
|
nvram_set("wl0_bsd_steering_policy", "80 5 3 -82 0 0 0x20");
|
|
nvram_set("wl1_bsd_sta_select_policy", "10 -52 0 110 0 1 1 0 0 0 0x122");
|
|
nvram_set("wl0_bsd_sta_select_policy", "10 -82 0 0 0 1 1 0 0 0 0x20");
|
|
nvram_set("wl1_bsd_if_select_policy", "eth1");
|
|
nvram_set("wl0_bsd_if_select_policy", "eth2");
|
|
nvram_set("wl1_bsd_if_qualify_policy", "0 0x0");
|
|
nvram_set("wl0_bsd_if_qualify_policy", "60 0x0");
|
|
break;
|
|
default:
|
|
/* nothing to do right now */
|
|
break;
|
|
}
|
|
}
|
|
|
|
stop_bsd();
|
|
|
|
/* 0 = off, 1 = on (all-band), 2 = 5 GHz only! (no support, maybe later) */
|
|
if (!bsd_enable) {
|
|
ret = -1;
|
|
logmsg(LOG_INFO, "wireless band steering disabled");
|
|
return ret;
|
|
}
|
|
else
|
|
ret = eval("/usr/sbin/bsd");
|
|
|
|
if (ret)
|
|
logmsg(LOG_ERR, "starting wireless band steering failed ...");
|
|
else
|
|
logmsg(LOG_INFO, "wireless band steering is started");
|
|
|
|
return ret;
|
|
}
|
|
|
|
void stop_bsd(void)
|
|
{
|
|
killall_tk_period_wait("bsd", 50);
|
|
|
|
logmsg(LOG_INFO, "wireless band steering is stopped");
|
|
}
|
|
#endif /* TCONFIG_BCMBSD */
|
|
|
|
#ifdef TCONFIG_ROAM
|
|
#define TOMATO_WLIF_MAX 4
|
|
|
|
void stop_roamast(void)
|
|
{
|
|
killall_tk_period_wait("roamast", 50);
|
|
|
|
logmsg(LOG_INFO, "wireless roaming assistant is stopped");
|
|
}
|
|
|
|
void start_roamast(void)
|
|
{
|
|
char *cmd[] = {"roamast", NULL};
|
|
char prefix[] = "wl_XXXX";
|
|
char tmp[32];
|
|
pid_t pid;
|
|
int i;
|
|
|
|
stop_roamast();
|
|
|
|
for (i = 0; i < TOMATO_WLIF_MAX; i++) {
|
|
snprintf(prefix, sizeof(prefix), "wl%d_", i);
|
|
if (nvram_get_int(strlcat_r(prefix, "user_rssi", tmp, sizeof(tmp))) != 0) {
|
|
_eval(cmd, NULL, 0, &pid);
|
|
logmsg(LOG_INFO, "wireless roaming assistant is started");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* TCONFIG_ROAM */
|