#!/usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2021 Tim Wilkinson
Original Perl Copyright (C) 2020 - Darryl Quinn
See Contributors file for additional contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
aredn.@lqm[0].enable",
default = "1",
postcallback = "lqm_defaults()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].margin_snr",
type = "string",
desc = "SNR Margin in dB above Min SNR a signal must reach to be re-activated
aredn.@lqm[0].margin_snr",
default = "1",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].min_distance",
type = "string",
desc = "Min Distance in meters beyond which a neighbor RF link is allowed
aredn.@lqm[0].min_distance",
default = "0",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].auto_distance",
type = "string",
desc = "Default Distance in meters to use when actual distance cannot be calculated
aredn.@lqm[0].auto_distance",
default = "0",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].margin_quality",
type = "string",
desc = "Quality Margin percentage increase before neighbor can be re-activated
aredn.@lqm[0].margin_quality",
default = "1",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].ping_penalty",
type = "string",
desc = "Ping Penalty quality percentage to add when neighbor cannot be pinged
aredn.@lqm[0].ping_penalty",
default = "5",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].rts_threshold",
type = "string",
desc = "RTS Threshold in bytes before using RTS/CTS when hidden nodes are detected
aredn.@lqm[0].rts_threshold",
default = "1",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].mtu",
type = "string",
desc = "Maximum packet size in bytes sent over WiFi (256 to 1500)
aredn.@lqm[0].mtu",
default = "1500"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].user_blocks",
type = "string",
desc = "User Blocked comma-separated list of blocked MACs
aredn.@lqm[0].user_blocks",
default = "",
condition = "lqm_enabled()"
},
{
category = "Link Quality Settings",
key = "aredn.@lqm[0].user_allows",
type = "string",
desc = "User Allowed comma-separated list of always allowed MACs
aredn.@lqm[0].user_allows",
default = "",
condition = "lqm_enabled()"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].olsrd_gw",
type = "boolean",
desc = "Allow other MESH nodes to use my WAN - not recommended and OFF by default
aredn.@wan[0].olsrd_gw",
default = "0"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].lan_dhcp_route",
type = "boolean",
desc = "Allow my LAN devices to access my WAN - ON by default
aredn.@wan[0].lan_dhcp_route",
default = "1"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].lan_dhcp_defaultroute",
type = "boolean",
desc = "Provide default route to LAN devices even when WAN access is disabled
aredn.@wan[0].lan_dhcp_defaultroute",
default = "0"
},
{
category = "WAN Settings",
key = "aredn.wan.vlanid",
type = "string",
desc = "WAN VLAN Number - must be an integer in the range [1,4094]
aredn.wan.vlanid",
default = "",
condition = "supportsVLANChange()",
current = "currentWANVLAN()",
postcallback = "changeWANVLAN()"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].web_access",
type = "boolean",
desc = "Enable web access to the node from the WAN interface
aredn.@wan[0].web_access",
default = "1"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].ssh_access",
type = "boolean",
desc = "Enable SSH access to the node from the WAN interface
aredn.@wan[0].ssh_access",
default = "1"
},
{
category = "WAN Settings",
key = "aredn.@wan[0].telnet_access",
type = "boolean",
desc = "Enable TELNET access to the node from the WAN interface
aredn.@wan[0].telnet_access",
default = "1"
},
{
category = "Power Options",
key = "aredn.@poe[0].passthrough",
type = "boolean",
desc = "PoE Passthrough specifies whether PoE power should be enabled (Not all devices have PoE passthrough ports)
aredn.@poe[0].passthrough",
default = "0",
condition = "hasPOE()",
postcallback = "setPOEOutput()"
},
{
category = "Power Options",
key = "aredn.@usb[0].passthrough",
type = "boolean",
desc = "USB Power Passthrough specifies whether USB power should be enabled (Not all devices have USB powered ports)
aredn.@usb[0].passthrough",
default = "1",
postcallback = "setUSBOutput()",
condition = "hasUSB()"
},
{
category = "Tunnel Options",
key = "aredn.@tunnel[0].weight",
type = "string",
desc = "Tunnel Weight specifies the cost of using a tunnel. The higher the number, the less likely a tunnel is used.
aredn.@tunnel[0].weight",
default = "1",
condition = "not isSupernode()"
},
{
category = "Tunnel Options",
key = "aredn.@tunnel[0].wanonly",
type = "boolean",
desc = "WAN-Only Tunnel prevents tunnel traffic from being routed over the Mesh network itself
aredn.@tunnel[0].wanonly",
default = "1"
},
{
category = "Watchdog",
key = "aredn.@watchdog[0].enable",
type = "boolean",
desc = "The Watchdog will reboot the node if it stops operating correctly
aredn.@watchdog[0].enable",
default = "0"
},
{
category = "Watchdog",
key = "aredn.@watchdog[0].ping_addresses",
type = "string",
desc = "Watchdog IP addresses is a whitespace seperated list of IP addresses, one of which should always be pingable
aredn.@watchdog[0].ping_addresses",
default = ""
},
{
category = "Watchdog",
key = "aredn.@watchdog[0].daily",
type = "string",
desc = "Daily Watchdog hour is the hour every day (0-23) to automatically reboot the node
aredn.@watchdog[0].daily",
default = ""
},
{
category = "Memory Settings",
key = "aredn.@meshstatus[0].lowmem",
type = "string",
desc = "Low Memory Threshold in KB when the Mesh Status page will be truncated
aredn.@meshstatus[0].lowmem",
default = "10000"
},
{
category = "Memory Settings",
key = "aredn.@meshstatus[0].lowroutes",
type = "string",
desc = "Low Memory Max Routes is the maximum number of routes shown on the Mesh Status page when low memory is detected
aredn.@meshstatus[0].lowroutes",
default = "1000"
},
{
category = "Supernode Settings",
key = "aredn.@supernode[0].support",
type = "boolean",
desc = "Use any Supernodes found on the mesh
aredn.@supernode[0].support",
default = "1"
},
{
category = "Network Tools",
key = "aredn.olsr.restart",
type = "none",
desc = "OLSR Restart will restart OLSR when executed; wait up to 2 or 3 minutes to receive response
aredn.olsr.restart",
default = "0",
postcallback = "olsr_restart()"
},
{
category = "Network Tools",
key = "aredn.@iperf[0].enable",
type = "boolean",
desc = "IPERF Enable allows the included iperf3 client/server
aredn.@iperf[0].enable",
default = "1"
},
{
category = "Remote Logging",
key = "aredn.@remotelog[0].url",
type = "string",
desc = "Remote logging URL for the remote syslog machine. Must be formatted as protocol://ipaddress:port
aredn.@remotelog[0].url",
default = "",
precallback = "validate_rsyslog()"
},
{
category = "Map Paths",
key = "aredn.@map[0].maptiles",
type = "string",
desc = "Map Tiles URL
aredn.@map[0].maptiles",
default = "http://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.jpg"
},
{
category = "Map Paths",
key = "aredn.@map[0].leafletcss",
type = "string",
desc = "Leaflet.css URL
aredn.@map[0].leafletcss",
default = "http://unpkg.com/leaflet@0.7.7/dist/leaflet.css"
},
{
category = "Map Paths",
key = "aredn.@map[0].leafletjs",
type = "string",
desc = "Leaflet.js URL
aredn.@map[0].leafletjs",
default = "http://unpkg.com/leaflet@0.7.7/dist/leaflet.js"
},
{
category = "Firmware",
key = "aredn.@downloads[0].firmwarepath",
type = "string",
desc = "Firmware Download URL
aredn.@downloads[0].firmwarepath",
default = "http://downloads.arednmesh.org/firmware"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_core",
type = "string",
desc = "Core Packages Download URL
aredn.@downloads[0].pkgs_core",
default = defaultPackageRepos('aredn_core'),
postcallback = "writePackageRepo('core')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_base",
type = "string",
desc = "Base Packages URL
aredn.@downloads[0].pkgs_base",
default = defaultPackageRepos('base'),
postcallback = "writePackageRepo('base')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_arednpackages",
type = "string",
desc = "AREDN Packages URL
aredn.@downloads[0].pkgs_arednpackages",
default = defaultPackageRepos('arednpackages'),
postcallback = "writePackageRepo('arednpackages')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_luci",
type = "string",
desc = "Luci Packages URL
aredn.@downloads[0].pkgs_luci",
default = defaultPackageRepos('luci'),
postcallback = "writePackageRepo('luci')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_packages",
type = "string",
desc = "Package Download URL for packages not included in the other sections
aredn.@downloads[0].pkgs_packages",
default = defaultPackageRepos('packages'),
postcallback = "writePackageRepo('packages')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_routing",
type = "string",
desc = "Routing Packages URL
aredn.@downloads[0].pkgs_routing",
default = defaultPackageRepos('routing'),
postcallback = "writePackageRepo('routing')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_telephony",
type = "string",
desc = "Telephony Packages URL
aredn.@downloads[0].pkgs_telephony",
default = defaultPackageRepos('telephony'),
postcallback = "writePackageRepo('telephony')"
},
{
category = "Firmware",
key = "aredn.@downloads[0].pkgs_freifunk",
type = "string",
desc = "Freifunk Packages URL
aredn.@downloads[0].pkgs_freifunk",
default = defaultPackageRepos('freifunk'),
postcallback = "writePackageRepo('freifunk')"
},
{
category = "Firmware",
key = "aredn.firmware.dangerous_upgrade",
type = "boolean",
desc = "Dangerous Upgrade Disables all safety checks usually applied when upgrading firmware
aredn.firmware.dangerous_upgrade",
default = "0",
current = "current_force_upgrade()",
postcallback = "update_force_upgrade()"
},
{
category = "AREDN Alert Settings",
key = "aredn.aam.refresh",
type = "none",
desc = "Alert Message Refresh - Execute to pull any AREDN Alert messages
aredn.aam.refresh",
default = "0",
postcallback = "aam_refresh()"
},
{
category = "AREDN Alert Settings",
key = "aredn.@alerts[0].localpath",
type = "string",
desc = "Alert Message Local URL - location from which local AREDN Alerts can be downloaded
aredn.@alerts[0].localpath",
default = ""
},
{
category = "AREDN Alert Settings",
key = "aredn.@alerts[0].groups",
type = "string",
desc = "Alert Message Groups - comma seperated list of group names to check for alert messages
aredn.@alerts[0].groups",
default = ""
},
{
category = "AREDN Alert Settings",
key = "aredn.@alerts[0].pollrate",
type = "string",
desc = "Alert Message Pollrate - how many hours to wait between polling for new AREDN Alerts
aredn.@alerts[0].pollrate",
default = "1"
},
{
category = "AREDN Alert Settings",
key = "aredn.aam.purge",
type = "none",
desc = "Alert Message Purge - execute to immediately delete all alerts from this node
aredn.aam.purge",
default = "",
postcallback = "alert_purge()"
}
}
local msgs = {}
--
-- helpers
--
function msg(m)
msgs[#msgs + 1] = m
end
-- uci cursor
local cursor = uci.cursor("/etc/config.mesh")
function cursor_set(a, b, c, d)
if not cursor:get(a, b) and b:match("@(.+)%[0%]") then
cursor:add(a, b:match("@(.+)%[0%]"))
end
cursor:set(a, b, c, d)
cursor:commit(a)
end
function cursor_get(a, b, c)
return cursor:get(a, b, c)
end
function reboot()
local c = uci.cursor()
local node = aredn.info.get_nvram("node")
if node == "" then
node = "Node"
end
local lanip, _, lanmask = aredn.hardware.get_interface_ip4(aredn.hardware.get_iface_name("lan"))
local browser = os.getenv("REMOTE_ADDR")
local browser6 = browser:match("::ffff:([%d%.]+)")
if browser6 then
browser = browser6
end
local fromlan = false
local subnet_change = false
if lanip then
fromlan = validate_same_subnet(browser, lanip, lanmask)
if fromlan then
lanmask = ip_to_decimal(lanmask)
local cfgip = c:get("network", "lan", "ipaddr")
local cfgmask = ip_to_decimal(c:get("network", "lan", "netmask"))
if lanmask ~= cfgmask or nixio.bit.band(ip_to_decimal(lanip), lanmask) ~= nixio.bit.band(ip_to_decimal(cfgip), cfgmask) then
subnet_change = true
end
end
end
http_header()
if fromlan and subnet_change then
html.header(node .. " rebooting", true)
html.print("