PKG_NAME:=luci-app-mwan3
PKG_VERSION:=1.3
-PKG_RELEASE:=4
+PKG_RELEASE:=5
PKG_MAINTAINER:=Aedan Renner <chipdankly@gmail.com>
PKG_LICENSE:=GPLv2
CATEGORY:=LuCI
SUBMENU:=3. Applications
TITLE:=LuCI support for the MWAN3 multiwan hotplug script
- DEPENDS:=+mwan3 +luci-mod-admin-full +luci-lib-nixio
+ DEPENDS:=+mwan3 +luci-mod-admin-full +luci-app-firewall +luci-lib-nixio
PKGARCH:=all
MAINTAINER:=Aedan Renner <chipdankly@gmail.com>
endef
+++ /dev/null
-#!/bin/sh
-
-# to enable this script uncomment the case loop at the bottom
-# to report mwan3 status on interface hotplug ifup/ifdown events modify the lines in the send_alert function
-
-send_alert()
-{
- # variable "$1" stores the mwan3 status information
- # insert your code here to send the contents of "$1"
- echo "$1"
-}
-
-gather_event_info()
-{
- # create event information message
- local EVENT_INFO="Interface [ "$INTERFACE" ($DEVICE) ] on router [ "$(uci get -p /var/state system.@system[0].hostname)" ] has triggered a hotplug [ "$ACTION" ] event on "$(date +"%a %b %d %Y %T %Z")""
-
- # get current interface, policy and rule status
- local CURRENT_STATUS="$(/usr/sbin/mwan3 status)"
-
- # get last 50 mwan3 systemlog messages
- local MWAN3_LOG="$(echo -e "Last 50 MWAN3 systemlog entries. Newest entries sorted at the top:\n$(logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x')")"
-
- # pass event info to send_alert function
- send_alert "$(echo -e "$EVENT_INFO\n\n$CURRENT_STATUS\n\n$MWAN3_LOG")"
-}
-
-#case "$ACTION" in
-# ifup)
-# gather_event_info
-# ;;
-#
-# ifdown)
-# gather_event_info
-# ;;
-#esac
-
-exit 0
--- /dev/null
+#!/bin/sh
+
+# to enable this script uncomment the case loop at the bottom
+# to report mwan status on interface hotplug ifup/ifdown events modify the lines in the send_alert function
+
+send_alert()
+{
+ # variable "$1" stores the MWAN status information
+ # insert your code here to send the contents of "$1"
+ echo "$1"
+}
+
+gather_event_info()
+{
+ # create event information message
+ local EVENT_INFO="Interface [ "$INTERFACE" ($DEVICE) ] on router [ "$(uci get -p /var/state system.@system[0].hostname)" ] has triggered a hotplug [ "$ACTION" ] event on "$(date +"%a %b %d %Y %T %Z")""
+
+ # get current interface, policy and rule status
+ local CURRENT_STATUS="$(/usr/sbin/mwan3 status)"
+
+ # get last 50 MWAN systemlog messages
+ local MWAN_LOG="$(echo -e "Last 50 MWAN systemlog entries. Newest entries sorted at the top:\n$(logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x')")"
+
+ # pass event info to send_alert function
+ send_alert "$(echo -e "$EVENT_INFO\n\n$CURRENT_STATUS\n\n$MWAN_LOG")"
+}
+
+#case "$ACTION" in
+# ifup)
+# gather_event_info
+# ;;
+#
+# ifdown)
+# gather_event_info
+# ;;
+#esac
+
+exit 0
--- /dev/null
+#!/bin/sh
+
+# replace existing mwan ucitrack entry
+uci -q batch <<-EOF >/dev/null
+ del ucitrack.@mwan3[-1]
+ add ucitrack mwan3
+ set ucitrack.@mwan3[-1].exec="/usr/sbin/mwan3 restart"
+ commit ucitrack
+EOF
+
+# remove LuCI cache
+rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
+
+exit 0
+++ /dev/null
-#!/bin/sh
-
-# replace existing mwan3-luci ucitrack entry
-uci -q batch <<-EOF >/dev/null
- del ucitrack.@mwan3[-1]
- add ucitrack mwan3
- set ucitrack.@mwan3[-1].exec="/usr/sbin/mwan3 restart"
- commit ucitrack
-EOF
-
-# remove LuCI cache
-rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
-
-exit 0
return
end
- entry({"admin", "network", "mwan3"},
- alias("admin", "network", "mwan3", "overview"),
+ entry({"admin", "network", "mwan"},
+ alias("admin", "network", "mwan", "overview"),
_("Load Balancing"), 600)
- entry({"admin", "network", "mwan3", "overview"},
- alias("admin", "network", "mwan3", "overview", "over_iface"),
+ entry({"admin", "network", "mwan", "overview"},
+ alias("admin", "network", "mwan", "overview", "overview_interface"),
_("Overview"), 10)
- entry({"admin", "network", "mwan3", "overview", "over_iface"},
- template("mwan3/mwan3_over_interface"))
- entry({"admin", "network", "mwan3", "overview", "iface_status"},
- call("mwan3_iface_status"))
- entry({"admin", "network", "mwan3", "overview", "over_detail"},
- template("mwan3/mwan3_over_detail"))
- entry({"admin", "network", "mwan3", "overview", "detail_status"},
- call("mwan3_detail_status"))
-
- entry({"admin", "network", "mwan3", "configuration"},
- alias("admin", "network", "mwan3", "configuration", "interface"),
+ entry({"admin", "network", "mwan", "overview", "overview_interface"},
+ template("mwan/overview_interface"))
+ entry({"admin", "network", "mwan", "overview", "interface_status"},
+ call("interfaceStatus"))
+ entry({"admin", "network", "mwan", "overview", "overview_detailed"},
+ template("mwan/overview_detailed"))
+ entry({"admin", "network", "mwan", "overview", "detailed_status"},
+ call("detailedStatus"))
+
+ entry({"admin", "network", "mwan", "configuration"},
+ alias("admin", "network", "mwan", "configuration", "interface"),
_("Configuration"), 20)
- entry({"admin", "network", "mwan3", "configuration", "interface"},
- arcombine(cbi("mwan3/mwan3_interface"), cbi("mwan3/mwan3_interfaceconfig")),
+ entry({"admin", "network", "mwan", "configuration", "interface"},
+ arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
_("Interfaces"), 10).leaf = true
- entry({"admin", "network", "mwan3", "configuration", "member"},
- arcombine(cbi("mwan3/mwan3_member"), cbi("mwan3/mwan3_memberconfig")),
+ entry({"admin", "network", "mwan", "configuration", "member"},
+ arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
_("Members"), 20).leaf = true
- entry({"admin", "network", "mwan3", "configuration", "policy"},
- arcombine(cbi("mwan3/mwan3_policy"), cbi("mwan3/mwan3_policyconfig")),
+ entry({"admin", "network", "mwan", "configuration", "policy"},
+ arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
_("Policies"), 30).leaf = true
- entry({"admin", "network", "mwan3", "configuration", "rule"},
- arcombine(cbi("mwan3/mwan3_rule"), cbi("mwan3/mwan3_ruleconfig")),
+ entry({"admin", "network", "mwan", "configuration", "rule"},
+ arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
_("Rules"), 40).leaf = true
- entry({"admin", "network", "mwan3", "advanced"},
- alias("admin", "network", "mwan3", "advanced", "hotplug"),
+ entry({"admin", "network", "mwan", "advanced"},
+ alias("admin", "network", "mwan", "advanced", "hotplugscript"),
_("Advanced"), 100)
- entry({"admin", "network", "mwan3", "advanced", "hotplug"},
- form("mwan3/mwan3_adv_hotplug"))
- entry({"admin", "network", "mwan3", "advanced", "mwan3"},
- form("mwan3/mwan3_adv_mwan3"))
- entry({"admin", "network", "mwan3", "advanced", "network"},
- form("mwan3/mwan3_adv_network"))
- entry({"admin", "network", "mwan3", "advanced", "diag"},
- template("mwan3/mwan3_adv_diagnostics"))
- entry({"admin", "network", "mwan3", "advanced", "diag_display"},
- call("mwan3_diag_data"), nil).leaf = true
- entry({"admin", "network", "mwan3", "advanced", "tshoot"},
- template("mwan3/mwan3_adv_troubleshoot"))
- entry({"admin", "network", "mwan3", "advanced", "tshoot_display"},
- call("mwan3_tshoot_data"))
+ entry({"admin", "network", "mwan", "advanced", "hotplugscript"},
+ form("mwan/advanced_hotplugscript"))
+ entry({"admin", "network", "mwan", "advanced", "mwanconfig"},
+ form("mwan/advanced_mwanconfig"))
+ entry({"admin", "network", "mwan", "advanced", "networkconfig"},
+ form("mwan/advanced_networkconfig"))
+ entry({"admin", "network", "mwan", "advanced", "diagnostics"},
+ template("mwan/advanced_diagnostics"))
+ entry({"admin", "network", "mwan", "advanced", "diagnostics_display"},
+ call("diagnosticsData"), nil).leaf = true
+ entry({"admin", "network", "mwan", "advanced", "troubleshooting"},
+ template("mwan/advanced_troubleshooting"))
+ entry({"admin", "network", "mwan", "advanced", "troubleshooting_display"},
+ call("troubleshootingData"))
end
-function mwan3_get_iface_status(rulenum, ifname)
- if ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".enabled")) == "1" then
- if ut.trim(sys.exec("ip route list table " .. rulenum)) ~= "" then
- if ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".track_ip")) ~= "" then
- return "on"
+function getInterfaceStatus(ruleNumber, interfaceName)
+ if ut.trim(sys.exec("uci get -p /var/state mwan3." .. interfaceName .. ".enabled")) == "1" then
+ if ut.trim(sys.exec("ip route list table " .. ruleNumber)) ~= "" then
+ if ut.trim(sys.exec("uci get -p /var/state mwan3." .. interfaceName .. ".track_ip")) ~= "" then
+ return "online"
else
- return "nm"
+ return "notMonitored"
end
else
- return "off"
+ return "offline"
end
else
- return "ne"
+ return "notEnabled"
end
end
-function mwan3_get_iface()
- local rulenum, str = 0, ""
+function getInterfaceName()
+ local ruleNumber, status = 0, ""
uci.cursor():foreach("mwan3", "interface",
function (section)
- rulenum = rulenum+1
- str = str .. section[".name"] .. "[" .. mwan3_get_iface_status(rulenum, section[".name"]) .. "]"
+ ruleNumber = ruleNumber+1
+ status = status .. section[".name"] .. "[" .. getInterfaceStatus(ruleNumber, section[".name"]) .. "]"
end
)
- return str
+ return status
end
-function mwan3_iface_status()
+function interfaceStatus()
local ntm = require "luci.model.network".init()
- local rv = { }
+ local mArray = {}
-- overview status
- local statstr = mwan3_get_iface()
- if statstr ~= "" then
- rv.wans = { }
+ local statusString = getInterfaceName()
+ if statusString ~= "" then
+ mArray.wans = {}
wansid = {}
- for wanname, ifstat in string.gfind(statstr, "([^%[]+)%[([^%]]+)%]") do
- local wanifname = ut.trim(sys.exec("uci get -p /var/state network." .. wanname .. ".ifname"))
- if wanifname == "" then
- wanifname = "X"
+ for wanName, interfaceState in string.gfind(statusString, "([^%[]+)%[([^%]]+)%]") do
+ local wanInterfaceName = ut.trim(sys.exec("uci get -p /var/state network." .. wanName .. ".ifname"))
+ if wanInterfaceName == "" then
+ wanInterfaceName = "X"
end
- local wanlink = ntm:get_interface(wanifname)
- wanlink = wanlink and wanlink:get_network()
- wanlink = wanlink and wanlink:adminlink() or "#"
- wansid[wanname] = #rv.wans + 1
- rv.wans[wansid[wanname]] = { name = wanname, link = wanlink, ifname = wanifname, status = ifstat }
+ local wanDeviceLink = ntm:get_interface(wanInterfaceName)
+ wanDeviceLink = wanDeviceLink and wanDeviceLink:get_network()
+ wanDeviceLink = wanDeviceLink and wanDeviceLink:adminlink() or "#"
+ wansid[wanName] = #mArray.wans + 1
+ mArray.wans[wansid[wanName]] = { name = wanName, link = wanDeviceLink, ifname = wanInterfaceName, status = interfaceState }
end
end
-- overview status log
- local mwlg = ut.trim(sys.exec("logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x'"))
- if mwlg ~= "" then
- rv.mwan3log = { }
- mwlog = {}
- mwlog[mwlg] = #rv.mwan3log + 1
- rv.mwan3log[mwlog[mwlg]] = { mwanlog = mwlg }
+ local mwanLog = ut.trim(sys.exec("logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x'"))
+ if mwanLog ~= "" then
+ mArray.mwanlog = { mwanLog }
end
luci.http.prepare_content("application/json")
- luci.http.write_json(rv)
+ luci.http.write_json(mArray)
end
-function mwan3_detail_status()
- local rv = { }
+function detailedStatus()
+ local mArray = {}
- -- detailed mwan3 status
- local dst = ut.trim(sys.exec("mwan3 status"))
- if dst ~= "" then
- rv.mwan3dst = { }
- dstat = {}
- dstat[dst] = #rv.mwan3dst + 1
- rv.mwan3dst[dstat[dst]] = { detailstat = dst }
+ -- detailed mwan status
+ local detailStatusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
+ if detailStatusInfo ~= "" then
+ mArray.mwandetail = { detailStatusInfo }
end
luci.http.prepare_content("application/json")
- luci.http.write_json(rv)
+ luci.http.write_json(mArray)
end
-function mwan3_diag_data(iface, tool, alt)
- function get_ifnum()
- local num = 0
+function diagnosticsData(interface, tool, task)
+ function getInterfaceNumber()
+ local number = 0
uci.cursor():foreach("mwan3", "interface",
function (section)
- num = num+1
- if section[".name"] == iface then
- ifnum = num
+ number = number+1
+ if section[".name"] == interface then
+ interfaceNumber = number
end
end
)
end
- local rv = { }
+ local mArray = {}
- local res = ""
+ local results = ""
if tool == "service" then
- os.execute("mwan3 " .. alt)
- if alt == "restart" then
- res = "MWAN3 restarted"
- elseif alt == "stop" then
- res = "MWAN3 stopped"
+ os.execute("/usr/sbin/mwan3 " .. task)
+ if task == "restart" then
+ results = "MWAN3 restarted"
+ elseif task == "stop" then
+ results = "MWAN3 stopped"
else
- res = "MWAN3 started"
+ results = "MWAN3 started"
end
else
- local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. iface .. ".ifname"))
- if ifdev ~= "" then
+ local interfaceDevice = ut.trim(sys.exec("uci get -p /var/state network." .. interface .. ".ifname"))
+ if interfaceDevice ~= "" then
if tool == "ping" then
- local gateway = ut.trim(sys.exec("route -n | awk '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $2 }'"))
+ local gateway = ut.trim(sys.exec("route -n | awk '{if ($8 == \"" .. interfaceDevice .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $2}'"))
if gateway ~= "" then
- if alt == "gateway" then
- local cmd = "ping -c 3 -W 2 -I " .. ifdev .. " " .. gateway
- res = cmd .. "\n\n" .. sys.exec(cmd)
+ if task == "gateway" then
+ local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. gateway
+ results = pingCommand .. "\n\n" .. sys.exec(pingCommand)
else
- local str = ut.trim(sys.exec("uci get -p /var/state mwan3." .. iface .. ".track_ip"))
- if str ~= "" then
- for z in str:gmatch("[^ ]+") do
- local cmd = "ping -c 3 -W 2 -I " .. ifdev .. " " .. z
- res = res .. cmd .. "\n\n" .. sys.exec(cmd) .. "\n\n"
+ local tracked = ut.trim(sys.exec("uci get -p /var/state mwan3." .. interface .. ".track_ip"))
+ if tracked ~= "" then
+ for z in tracked:gmatch("[^ ]+") do
+ local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. z
+ results = results .. pingCommand .. "\n\n" .. sys.exec(pingCommand) .. "\n\n"
end
else
- res = "No tracking IP addresses configured on " .. iface
+ results = "No tracking IP addresses configured on " .. interface
end
end
else
- res = "No default gateway for " .. iface .. " found. Default route does not exist or is configured incorrectly"
+ results = "No default gateway for " .. interface .. " found. Default route does not exist or is configured incorrectly"
end
elseif tool == "rulechk" then
- get_ifnum()
- local rule1 = sys.exec("ip rule | grep $(echo $((" .. ifnum .. " + 1000)))")
- local rule2 = sys.exec("ip rule | grep $(echo $((" .. ifnum .. " + 2000)))")
+ getInterfaceNumber()
+ local rule1 = sys.exec("ip rule | grep $(echo $((" .. interfaceNumber .. " + 1000)))")
+ local rule2 = sys.exec("ip rule | grep $(echo $((" .. interfaceNumber .. " + 2000)))")
if rule1 ~= "" and rule2 ~= "" then
- res = "All required interface IP rules found:\n\n" .. rule1 .. rule2
+ results = "All required interface IP rules found:\n\n" .. rule1 .. rule2
elseif rule1 ~= "" or rule2 ~= "" then
- res = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
+ results = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
else
- res = "Missing both of the required interface IP rules"
+ results = "Missing both of the required interface IP rules"
end
elseif tool == "routechk" then
- get_ifnum()
- local table = sys.exec("ip route list table " .. ifnum)
- if table ~= "" then
- res = "Interface routing table " .. ifnum .. " was found:\n\n" .. table
+ getInterfaceNumber()
+ local routeTable = sys.exec("ip route list table " .. interfaceNumber)
+ if routeTable ~= "" then
+ results = "Interface routing table " .. interfaceNumber .. " was found:\n\n" .. routeTable
else
- res = "Missing required interface routing table " .. ifnum
+ results = "Missing required interface routing table " .. interfaceNumber
end
elseif tool == "hotplug" then
- if alt == "ifup" then
- os.execute("mwan3 ifup " .. iface)
- res = "Hotplug ifup sent to interface " .. iface .. "..."
+ if task == "ifup" then
+ os.execute("/usr/sbin/mwan3 ifup " .. interface)
+ results = "Hotplug ifup sent to interface " .. interface .. "..."
else
- os.execute("mwan3 ifdown " .. iface)
- res = "Hotplug ifdown sent to interface " .. iface .. "..."
+ os.execute("/usr/sbin/mwan3 ifdown " .. interface)
+ results = "Hotplug ifdown sent to interface " .. interface .. "..."
end
end
else
- res = "Unable to perform diagnostic tests on " .. iface .. ". There is no physical or virtual device associated with this interface"
+ results = "Unable to perform diagnostic tests on " .. interface .. ". There is no physical or virtual device associated with this interface"
end
end
- if res ~= "" then
- res = ut.trim(res)
- rv.diagres = { }
- dres = {}
- dres[res] = #rv.diagres + 1
- rv.diagres[dres[res]] = { diagresult = res }
+ if results ~= "" then
+ results = ut.trim(results)
+ mArray.diagnostics = { results }
end
luci.http.prepare_content("application/json")
- luci.http.write_json(rv)
+ luci.http.write_json(mArray)
end
-function mwan3_tshoot_data()
- local rv = { }
+function troubleshootingData()
+ local mArray = {}
-- software versions
- local wrtrelease = ut.trim(luci.version.distversion)
- if wrtrelease ~= "" then
- wrtrelease = "OpenWrt - " .. wrtrelease
+ local wrtRelease = ut.trim(luci.version.distversion)
+ if wrtRelease ~= "" then
+ wrtRelease = "OpenWrt - " .. wrtRelease
else
- wrtrelease = "OpenWrt - unknown"
+ wrtRelease = "OpenWrt - unknown"
end
- local lucirelease = ut.trim(luci.version.luciversion)
- if lucirelease ~= "" then
- lucirelease = "\nLuCI - " .. lucirelease
+ local luciRelease = ut.trim(luci.version.luciversion)
+ if luciRelease ~= "" then
+ luciRelease = "\nLuCI - " .. luciRelease
else
- lucirelease = "\nLuCI - unknown"
+ luciRelease = "\nLuCI - unknown"
end
- local mwan3version = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{ print $2 }'"))
- if mwan3version ~= "" then
- mwan3version = "\n\nmwan3 - " .. mwan3version
+ local mwanVersion = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{print $2}'"))
+ if mwanVersion ~= "" then
+ mwanVersion = "\n\nmwan3 - " .. mwanVersion
else
- mwan3version = "\nmwan3 - unknown"
+ mwanVersion = "\n\nmwan3 - unknown"
end
- local mwan3lversion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{ print $2 }'"))
- if mwan3lversion ~= "" then
- mwan3lversion = "\nmwan3-luci - " .. mwan3lversion
+ local mwanLuciVersion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{print $2}'"))
+ if mwanLuciVersion ~= "" then
+ mwanLuciVersion = "\nmwan3-luci - " .. mwanLuciVersion
else
- mwan3lversion = "\nmwan3-luci - unknown"
+ mwanLuciVersion = "\nmwan3-luci - unknown"
end
- local softrev = wrtrelease .. lucirelease .. mwan3version .. mwan3lversion
- rv.mw3ver = { }
- mwv = {}
- mwv[softrev] = #rv.mw3ver + 1
- rv.mw3ver[mwv[softrev]] = { mwan3v = softrev }
-
- -- mwan3 config
- local mwcg = ut.trim(sys.exec("cat /etc/config/mwan3"))
- if mwcg == "" then
- mwcg = "No data found"
+ mArray.versions = { wrtRelease .. luciRelease .. mwanVersion .. mwanLuciVersion }
+
+ -- mwan config
+ local mwanConfig = ut.trim(sys.exec("cat /etc/config/mwan3"))
+ if mwanConfig == "" then
+ mwanConfig = "No data found"
end
- rv.mwan3config = { }
- mwan3cfg = {}
- mwan3cfg[mwcg] = #rv.mwan3config + 1
- rv.mwan3config[mwan3cfg[mwcg]] = { mwn3cfg = mwcg }
+ mArray.mwanconfig = { mwanConfig }
-- network config
- local netcg = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/'"))
- if netcg == "" then
- netcg = "No data found"
+ local networkConfig = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/'"))
+ if networkConfig == "" then
+ networkConfig = "No data found"
end
- rv.netconfig = { }
- ncfg = {}
- ncfg[netcg] = #rv.netconfig + 1
- rv.netconfig[ncfg[netcg]] = { netcfg = netcg }
+ mArray.netconfig = { networkConfig }
-- ifconfig
- local ifcg = ut.trim(sys.exec("ifconfig"))
- if ifcg == "" then
- ifcg = "No data found"
+ local ifconfig = ut.trim(sys.exec("ifconfig"))
+ if ifconfig == "" then
+ ifconfig = "No data found"
end
- rv.ifconfig = { }
- icfg = {}
- icfg[ifcg] = #rv.ifconfig + 1
- rv.ifconfig[icfg[ifcg]] = { ifcfg = ifcg }
+ mArray.ifconfig = { ifconfig }
-- route -n
- local routeshow = ut.trim(sys.exec("route -n"))
- if routeshow == "" then
- routeshow = "No data found"
+ local routeShow = ut.trim(sys.exec("route -n"))
+ if routeShow == "" then
+ routeShow = "No data found"
end
- rv.rtshow = { }
- rshw = {}
- rshw[routeshow] = #rv.rtshow + 1
- rv.rtshow[rshw[routeshow]] = { iprtshow = routeshow }
+ mArray.routeshow = { routeShow }
-- ip rule show
- local ipr = ut.trim(sys.exec("ip rule show"))
- if ipr == "" then
- ipr = "No data found"
+ local ipRuleShow = ut.trim(sys.exec("ip rule show"))
+ if ipRuleShow == "" then
+ ipRuleShow = "No data found"
end
- rv.iprule = { }
- ipruleid = {}
- ipruleid[ipr] = #rv.iprule + 1
- rv.iprule[ipruleid[ipr]] = { rule = ipr }
+ mArray.iprule = { ipRuleShow }
-- ip route list table 1-250
- local routelisting, rlstr = ut.trim(sys.exec("ip rule | sed 's/://g' | awk '$1>=2001 && $1<=2250' | awk '{ print $NF }'")), ""
- if routelisting ~= "" then
- for line in routelisting:gmatch("[^\r\n]+") do
- rlstr = rlstr .. line .. "\n" .. sys.exec("ip route list table " .. line)
+ local routeList, routeString = ut.trim(sys.exec("ip rule | sed 's/://g' | awk '$1>=2001 && $1<=2250' | awk '{print $NF}'")), ""
+ if routeList ~= "" then
+ for line in routeList:gmatch("[^\r\n]+") do
+ routeString = routeString .. line .. "\n" .. sys.exec("ip route list table " .. line)
end
- rlstr = ut.trim(rlstr)
+ routeString = ut.trim(routeString)
else
- rlstr = "No data found"
+ routeString = "No data found"
end
- rv.routelist = { }
- rtlist = {}
- rtlist[rlstr] = #rv.routelist + 1
- rv.routelist[rtlist[rlstr]] = { iprtlist = rlstr }
+ mArray.routelist = { routeString }
-- default firewall output policy
- local defout = ut.trim(sys.exec("uci get -p /var/state firewall.@defaults[0].output"))
- if defout == "" then
- defout = "No data found"
+ local firewallOut = ut.trim(sys.exec("uci get -p /var/state firewall.@defaults[0].output"))
+ if firewallOut == "" then
+ firewallOut = "No data found"
end
- rv.fidef = { }
- fwdf = {}
- fwdf[defout] = #rv.fidef + 1
- rv.fidef[fwdf[defout]] = { firedef = defout }
+ mArray.firewallout = { firewallOut }
-- iptables
- local iptbl = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
- if iptbl == "" then
- iptbl = "No data found"
+ local iptables = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
+ if iptables == "" then
+ iptables = "No data found"
end
- rv.iptables = { }
- tables = {}
- tables[iptbl] = #rv.iptables + 1
- rv.iptables[tables[iptbl]] = { iptbls = iptbl }
+ mArray.iptables = { iptables }
luci.http.prepare_content("application/json")
- luci.http.write_json(rv)
+ luci.http.write_json(mArray)
end
--- /dev/null
+-- ------ hotplug script configuration ------ --
+
+fs = require "nixio.fs"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+script = "/etc/hotplug.d/iface/16-mwancustom"
+scriptBackup = "/etc/hotplug.d/iface/16-mwancustombak"
+
+if luci.http.formvalue("cbid.luci.1._restorebak") then -- restore button has been clicked
+ luci.http.redirect(luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript") .. "?restore=yes")
+elseif luci.http.formvalue("restore") == "yes" then -- restore script from backup
+ os.execute("cp -f " .. scriptBackup .. " " .. script)
+end
+
+
+m5 = SimpleForm("luci", nil)
+ m5:append(Template("mwan/advanced_hotplugscript")) -- highlight current tab
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/hotplug.d/iface/16-mwancustom<br />" ..
+ "This is useful for running system commands and/or scripts based on interface ifup or ifdown hotplug events<br /><br />" ..
+ "Notes:<br />" ..
+ "The first line of the script must be "#!/bin/sh" without quotes<br />" ..
+ "Lines beginning with # are comments and are not executed<br /><br />" ..
+ "Available variables:<br />" ..
+ "$ACTION is the hotplug event (ifup, ifdown)<br />" ..
+ "$INTERFACE is the interface name (wan1, wan2, etc.)<br />" ..
+ "$DEVICE is the device name attached to the interface (eth0.1, eth1, etc.)"))
+
+
+restore = f:option(Button, "_restorebak", translate("Restore default hotplug script"))
+ restore.inputtitle = translate("Restore...")
+ restore.inputstyle = "apply"
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ local hps = fs.readfile(script)
+ if not hps or hps == "" then -- if script does not exist or is blank restore from backup
+ sys.call("cp -f " .. scriptBackup .. " " .. script)
+ return fs.readfile(script)
+ else
+ return hps
+ end
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return fs.writefile(script, ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+
+return m5
--- /dev/null
+-- ------ mwan configuration ------ --
+
+ut = require "luci.util"
+
+mwanConfig = "/etc/config/mwan3"
+
+
+m5 = SimpleForm("luci", nil)
+ m5:append(Template("mwan/advanced_mwanconfig")) -- highlight current tab
+
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/config/mwan3"))
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ return nixio.fs.readfile(mwanConfig) or ""
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return nixio.fs.writefile(mwanConfig, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function f.handle(self, state, data)
+ return true
+ end
+
+
+return m5
--- /dev/null
+-- ------ network configuration ------ --
+
+ut = require "luci.util"
+
+networkConfig = "/etc/config/network"
+
+
+m5 = SimpleForm("networkconf", nil)
+ m5:append(Template("mwan/advanced_networkconfig")) -- highlight current tab
+
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/config/network"))
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ return nixio.fs.readfile(networkConfig) or ""
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return nixio.fs.writefile(networkConfig, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function f.handle(self, state, data)
+ return true
+ end
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function interfaceCheck() -- find issues with too many interfaces, reliability and metric
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ local interfaceName = section[".name"]
+ interfaceNumber = interfaceNumber+1 -- count number of mwan interfaces configured
+ -- create list of metrics for none and duplicate checking
+ local metricValue = ut.trim(sys.exec("uci get -p /var/state network." .. interfaceName .. ".metric"))
+ if metricValue == "" then
+ errorFound = 1
+ errorNoMetricList = errorNoMetricList .. interfaceName .. " "
+ else
+ metricList = metricList .. interfaceName .. " " .. metricValue .. "\n"
+ end
+ -- check if any interfaces have a higher reliability requirement than tracking IPs configured
+ local trackingNumber = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. interfaceName .. ".track_ip) | wc -w")))
+ if trackingNumber > 0 then
+ local reliabilityNumber = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. interfaceName .. ".reliability")))
+ if reliabilityNumber and reliabilityNumber > trackingNumber then
+ errorFound = 1
+ errorReliabilityList = errorReliabilityList .. interfaceName .. " "
+ end
+ end
+ -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
+ if ut.trim(sys.exec("uci get -p /var/state network." .. interfaceName)) == "interface" then
+ local interfaceDevice = ut.trim(sys.exec("uci get -p /var/state network." .. interfaceName .. ".ifname"))
+ if interfaceDevice == "uci: Entry not found" or interfaceDevice == "" then
+ errorFound = 1
+ errorNetConfigList = errorNetConfigList .. interfaceName .. " "
+ errorRouteList = errorRouteList .. interfaceName .. " "
+ else
+ local routeCheck = ut.trim(sys.exec("route -n | awk '{if ($8 == \"" .. interfaceDevice .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $1}'"))
+ if routeCheck == "" then
+ errorFound = 1
+ errorRouteList = errorRouteList .. interfaceName .. " "
+ end
+ end
+ else
+ errorFound = 1
+ errorNetConfigList = errorNetConfigList .. interfaceName .. " "
+ errorRouteList = errorRouteList .. interfaceName .. " "
+ end
+ end
+ )
+ -- check if any interfaces have duplicate metrics
+ local metricDuplicateNumbers = sys.exec("echo '" .. metricList .. "' | awk '{print $2}' | uniq -d")
+ if metricDuplicateNumbers ~= "" then
+ errorFound = 1
+ local metricDuplicates = ""
+ for line in metricDuplicateNumbers:gmatch("[^\r\n]+") do
+ metricDuplicates = sys.exec("echo '" .. metricList .. "' | grep '" .. line .. "' | awk '{print $1}'")
+ errorDuplicateMetricList = errorDuplicateMetricList .. metricDuplicates
+ end
+ errorDuplicateMetricList = sys.exec("echo '" .. errorDuplicateMetricList .. "' | tr '\n' ' '")
+ end
+end
+
+function interfaceWarnings() -- display status and warning messages at the top of the page
+ local warnings = ""
+ if interfaceNumber <= 250 then
+ warnings = "<strong>There are currently " .. interfaceNumber .. " of 250 supported interfaces configured</strong>"
+ else
+ warnings = "<font color=\"ff0000\"><strong>WARNING: " .. interfaceNumber .. " interfaces are configured exceeding the maximum of 250!</strong></font>"
+ end
+ if errorReliabilityList ~= " " then
+ warnings = warnings .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have a higher reliability requirement than there are tracking IP addresses!</strong></font>"
+ end
+ if errorRouteList ~= " " then
+ warnings = warnings .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no default route in the main routing table!</strong></font>"
+ end
+ if errorNetConfigList ~= " " then
+ warnings = warnings .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces are configured incorrectly or not at all in /etc/config/network!</strong></font>"
+ end
+ if errorNoMetricList ~= " " then
+ warnings = warnings .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no metric configured in /etc/config/network!</strong></font>"
+ end
+ if errorDuplicateMetricList ~= " " then
+ warnings = warnings .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
+ end
+ return warnings
+end
+
+-- ------ interface configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+interfaceNumber = 0
+metricList = ""
+errorFound = 0
+errorDuplicateMetricList = " "
+errorNetConfigList = " "
+errorNoMetricList = " "
+errorReliabilityList = " "
+errorRouteList = " "
+interfaceCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Interface Configuration"),
+ translate(interfaceWarnings()))
+ m5:append(Template("mwan/config_css"))
+
+
+mwan_interface = m5:section(TypedSection, "interface", translate("Interfaces"),
+ translate("MWAN supports up to 250 physical and/or logical interfaces<br />" ..
+ "MWAN requires that all interfaces have a unique metric configured in /etc/config/network<br />" ..
+ "Names must match the interface name found in /etc/config/network (see advanced tab)<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Interfaces may not share the same name as configured members, policies or rules"))
+ mwan_interface.addremove = true
+ mwan_interface.dynamic = false
+ mwan_interface.sectionhead = "Interface"
+ mwan_interface.sortable = true
+ mwan_interface.template = "cbi/tblsection"
+ mwan_interface.extedit = dsp.build_url("admin", "network", "mwan", "configuration", "interface", "%s")
+ function mwan_interface.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(dsp.build_url("admin", "network", "mwan", "configuration", "interface", section))
+ end
+
+
+enabled = mwan_interface:option(DummyValue, "enabled", translate("Enabled"))
+ enabled.rawhtml = true
+ function enabled.cfgvalue(self, s)
+ if self.map:get(s, "enabled") == "1" then
+ return "Yes"
+ else
+ return "No"
+ end
+ end
+
+track_ip = mwan_interface:option(DummyValue, "track_ip", translate("Tracking IP"))
+ track_ip.rawhtml = true
+ function track_ip.cfgvalue(self, s)
+ tracked = self.map:get(s, "track_ip")
+ if tracked then
+ local ipList = ""
+ for k,v in pairs(tracked) do
+ ipList = ipList .. v .. "<br />"
+ end
+ return ipList
+ else
+ return "—"
+ end
+ end
+
+reliability = mwan_interface:option(DummyValue, "reliability", translate("Tracking reliability"))
+ reliability.rawhtml = true
+ function reliability.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "reliability") or "—"
+ else
+ return "—"
+ end
+ end
+
+count = mwan_interface:option(DummyValue, "count", translate("Ping count"))
+ count.rawhtml = true
+ function count.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "count") or "—"
+ else
+ return "—"
+ end
+ end
+
+timeout = mwan_interface:option(DummyValue, "timeout", translate("Ping timeout"))
+ timeout.rawhtml = true
+ function timeout.cfgvalue(self, s)
+ if tracked then
+ local timeoutValue = self.map:get(s, "timeout")
+ if timeoutValue then
+ return timeoutValue .. "s"
+ else
+ return "—"
+ end
+ else
+ return "—"
+ end
+ end
+
+interval = mwan_interface:option(DummyValue, "interval", translate("Ping interval"))
+ interval.rawhtml = true
+ function interval.cfgvalue(self, s)
+ if tracked then
+ local intervalValue = self.map:get(s, "interval")
+ if intervalValue then
+ return intervalValue .. "s"
+ else
+ return "—"
+ end
+ else
+ return "—"
+ end
+ end
+
+down = mwan_interface:option(DummyValue, "down", translate("Interface down"))
+ down.rawhtml = true
+ function down.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "down") or "—"
+ else
+ return "—"
+ end
+ end
+
+up = mwan_interface:option(DummyValue, "up", translate("Interface up"))
+ up.rawhtml = true
+ function up.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "up") or "—"
+ else
+ return "—"
+ end
+ end
+
+metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ local metricValue = sys.exec("uci get -p /var/state network." .. s .. ".metric")
+ if metricValue ~= "" then
+ return metricValue
+ else
+ return "—"
+ end
+ end
+
+errors = mwan_interface:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if errorFound == 1 then
+ local mouseOver, lineBreak = "", ""
+ if string.find(errorReliabilityList, " " .. s .. " ") then
+ mouseOver = "Higher reliability requirement than there are tracking IP addresses"
+ lineBreak = " "
+ end
+ if string.find(errorRouteList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "No default route in the main routing table"
+ lineBreak = " "
+ end
+ if string.find(errorNetConfigList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "Configured incorrectly or not at all in /etc/config/network"
+ lineBreak = " "
+ end
+ if string.find(errorNoMetricList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "No metric configured in /etc/config/network"
+ lineBreak = " "
+ end
+ if string.find(errorDuplicateMetricList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "Duplicate metric configured in /etc/config/network"
+ end
+ if mouseOver == "" then
+ return ""
+ else
+ return "<span title=\"" .. mouseOver .. "\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ else
+ return ""
+ end
+ end
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function interfaceCheck()
+ metricValue = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".metric"))
+ if metricValue == "" then -- no metric
+ errorNoMetric = 1
+ else -- if metric exists create list of interface metrics to compare against for duplicates
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ local metricValue = ut.trim(sys.exec("uci get -p /var/state network." .. section[".name"] .. ".metric"))
+ metricList = metricList .. section[".name"] .. " " .. metricValue .. "\n"
+ end
+ )
+ -- compare metric against list
+ local metricDuplicateNumbers, metricDuplicates = sys.exec("echo '" .. metricList .. "' | awk '{print $2}' | uniq -d"), ""
+ for line in metricDuplicateNumbers:gmatch("[^\r\n]+") do
+ metricDuplicates = sys.exec("echo '" .. metricList .. "' | grep '" .. line .. "' | awk '{print $1}'")
+ errorDuplicateMetricList = errorDuplicateMetricList .. metricDuplicates
+ end
+ if sys.exec("echo '" .. errorDuplicateMetricList .. "' | grep -w " .. arg[1]) ~= "" then
+ errorDuplicateMetric = 1
+ end
+ end
+ -- check if this interface has a higher reliability requirement than track IPs configured
+ local trackingNumber = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. arg[1] .. ".track_ip) | wc -w")))
+ if trackingNumber > 0 then
+ local reliabilityNumber = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".reliability")))
+ if reliabilityNumber and reliabilityNumber > trackingNumber then
+ errorReliability = 1
+ end
+ end
+ -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
+ if ut.trim(sys.exec("uci get -p /var/state network." .. arg[1])) == "interface" then
+ local interfaceDevice = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".ifname"))
+ if interfaceDevice == "uci: Entry not found" or interfaceDevice == "" then
+ errorNetConfig = 1
+ errorRoute = 1
+ else
+ local routeCheck = ut.trim(sys.exec("route -n | awk '{if ($8 == \"" .. interfaceDevice .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $1}'"))
+ if routeCheck == "" then
+ errorRoute = 1
+ end
+ end
+ else
+ errorNetConfig = 1
+ errorRoute = 1
+ end
+end
+
+function interfaceWarnings() -- display warning messages at the top of the page
+ local warns, lineBreak = "", ""
+ if errorReliability == 1 then
+ warns = "<font color=\"ff0000\"><strong>WARNING: this interface has a higher reliability requirement than there are tracking IP addresses!</strong></font>"
+ lineBreak = "<br /><br />"
+ end
+ if errorRoute == 1 then
+ warns = warns .. lineBreak .. "<font color=\"ff0000\"><strong>WARNING: this interface has no default route in the main routing table!</strong></font>"
+ lineBreak = "<br /><br />"
+ end
+ if errorNetConfig == 1 then
+ warns = warns .. lineBreak .. "<font color=\"ff0000\"><strong>WARNING: this interface is configured incorrectly or not at all in /etc/config/network!</strong></font>"
+ lineBreak = "<br /><br />"
+ end
+ if errorNoMetric == 1 then
+ warns = warns .. lineBreak .. "<font color=\"ff0000\"><strong>WARNING: this interface has no metric configured in /etc/config/network!</strong></font>"
+ elseif errorDuplicateMetric == 1 then
+ warns = warns .. lineBreak .. "<font color=\"ff0000\"><strong>WARNING: this and other interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
+ end
+ return warns
+end
+
+-- ------ interface configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+arg[1] = arg[1] or ""
+
+metricValue = ""
+metricList = ""
+errorDuplicateMetricList = ""
+errorNoMetric = 0
+errorDuplicateMetric = 0
+errorRoute = 0
+errorNetConfig = 0
+errorReliability = 0
+interfaceCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Interface Configuration - " .. arg[1]),
+ translate(interfaceWarnings()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan", "configuration", "interface")
+
+
+mwan_interface = m5:section(NamedSection, arg[1], "interface", "")
+ mwan_interface.addremove = false
+ mwan_interface.dynamic = false
+
+
+enabled = mwan_interface:option(ListValue, "enabled", translate("Enabled"))
+ enabled.default = "1"
+ enabled:value("1", translate("Yes"))
+ enabled:value("0", translate("No"))
+
+track_ip = mwan_interface:option(DynamicList, "track_ip", translate("Tracking IP"),
+ translate("This IP address will be pinged to dermine if the link is up or down. Leave blank to assume interface is always online"))
+ track_ip.datatype = "ipaddr"
+
+reliability = mwan_interface:option(Value, "reliability", translate("Tracking reliability"),
+ translate("Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up"))
+ reliability.datatype = "range(1, 100)"
+ reliability.default = "1"
+
+count = mwan_interface:option(ListValue, "count", translate("Ping count"))
+ count.default = "1"
+ count:value("1")
+ count:value("2")
+ count:value("3")
+ count:value("4")
+ count:value("5")
+
+timeout = mwan_interface:option(ListValue, "timeout", translate("Ping timeout"))
+ timeout.default = "2"
+ timeout:value("1", translate("1 second"))
+ timeout:value("2", translate("2 seconds"))
+ timeout:value("3", translate("3 seconds"))
+ timeout:value("4", translate("4 seconds"))
+ timeout:value("5", translate("5 seconds"))
+ timeout:value("6", translate("6 seconds"))
+ timeout:value("7", translate("7 seconds"))
+ timeout:value("8", translate("8 seconds"))
+ timeout:value("9", translate("9 seconds"))
+ timeout:value("10", translate("10 seconds"))
+
+interval = mwan_interface:option(ListValue, "interval", translate("Ping interval"))
+ interval.default = "5"
+ interval:value("1", translate("1 second"))
+ interval:value("3", translate("3 seconds"))
+ interval:value("5", translate("5 seconds"))
+ interval:value("10", translate("10 seconds"))
+ interval:value("20", translate("20 seconds"))
+ interval:value("30", translate("30 seconds"))
+ interval:value("60", translate("1 minute"))
+ interval:value("300", translate("5 minutes"))
+ interval:value("600", translate("10 minutes"))
+ interval:value("900", translate("15 minutes"))
+ interval:value("1800", translate("30 minutes"))
+ interval:value("3600", translate("1 hour"))
+
+down = mwan_interface:option(ListValue, "down", translate("Interface down"),
+ translate("Interface will be deemed down after this many failed ping tests"))
+ down.default = "3"
+ down:value("1")
+ down:value("2")
+ down:value("3")
+ down:value("4")
+ down:value("5")
+ down:value("6")
+ down:value("7")
+ down:value("8")
+ down:value("9")
+ down:value("10")
+
+up = mwan_interface:option(ListValue, "up", translate("Interface up"),
+ translate("Downed interface will be deemed up after this many successful ping tests"))
+ up.default = "3"
+ up:value("1")
+ up:value("2")
+ up:value("3")
+ up:value("4")
+ up:value("5")
+ up:value("6")
+ up:value("7")
+ up:value("8")
+ up:value("9")
+ up:value("10")
+
+metric = mwan_interface:option(DummyValue, "metric", translate("Metric"),
+ translate("This displays the metric assigned to this interface in /etc/config/network"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ if errorNoMetric == 0 then
+ return metricValue
+ else
+ return "—"
+ end
+ end
+
+
+return m5
--- /dev/null
+-- ------ member configuration ------ --
+
+ds = require "luci.dispatcher"
+
+
+m5 = Map("mwan3", translate("MWAN Member Configuration"))
+ m5:append(Template("mwan/config_css"))
+
+
+mwan_member = m5:section(TypedSection, "member", translate("Members"),
+ translate("Members are profiles attaching a metric and weight to an MWAN interface<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Members may not share the same name as configured interfaces, policies or rules"))
+ mwan_member.addremove = true
+ mwan_member.dynamic = false
+ mwan_member.sectionhead = "Member"
+ mwan_member.sortable = true
+ mwan_member.template = "cbi/tblsection"
+ mwan_member.extedit = ds.build_url("admin", "network", "mwan", "configuration", "member", "%s")
+ function mwan_member.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(ds.build_url("admin", "network", "mwan", "configuration", "member", section))
+ end
+
+
+interface = mwan_member:option(DummyValue, "interface", translate("Interface"))
+ interface.rawhtml = true
+ function interface.cfgvalue(self, s)
+ return self.map:get(s, "interface") or "—"
+ end
+
+metric = mwan_member:option(DummyValue, "metric", translate("Metric"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ return self.map:get(s, "metric") or "1"
+ end
+
+weight = mwan_member:option(DummyValue, "weight", translate("Weight"))
+ weight.rawhtml = true
+ function weight.cfgvalue(self, s)
+ return self.map:get(s, "weight") or "1"
+ end
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function cbi_add_interface(field)
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+-- ------ member configuration ------ --
+
+dsp = require "luci.dispatcher"
+arg[1] = arg[1] or ""
+
+
+m5 = Map("mwan3", translate("MWAN Member Configuration - ") .. arg[1])
+ m5.redirect = dsp.build_url("admin", "network", "mwan", "configuration", "member")
+
+
+mwan_member = m5:section(NamedSection, arg[1], "member", "")
+ mwan_member.addremove = false
+ mwan_member.dynamic = false
+
+
+interface = mwan_member:option(Value, "interface", translate("Interface"))
+ cbi_add_interface(interface)
+
+metric = mwan_member:option(Value, "metric", translate("Metric"),
+ translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
+ metric.datatype = "range(1, 1000)"
+
+weight = mwan_member:option(Value, "weight", translate("Weight"),
+ translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
+ weight.datatype = "range(1, 1000)"
+
+
+-- ------ currently configured interfaces ------ --
+
+mwan_interface = m5:section(TypedSection, "interface", translate("Currently Configured Interfaces"))
+ mwan_interface.addremove = false
+ mwan_interface.dynamic = false
+ mwan_interface.sortable = false
+ mwan_interface.template = "cbi/tblsection"
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function policyCheck() -- check to see if any policy names exceed the maximum of 15 characters
+ uci.cursor():foreach("mwan3", "policy",
+ function (section)
+ if string.len(section[".name"]) > 15 then
+ nameTooLong = 1
+ err_name_list = err_name_list .. section[".name"] .. " "
+ end
+ end
+ )
+end
+
+function policyWarn() -- display status and warning messages at the top of the page
+ if nameTooLong == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: Some policies have names exceeding the maximum of 15 characters!</strong></font>"
+ else
+ return ""
+ end
+end
+
+-- ------ policy configuration ------ --
+
+ds = require "luci.dispatcher"
+sys = require "luci.sys"
+
+nameTooLong = 0
+err_name_list = " "
+policyCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Policy Configuration"),
+ translate(policyWarn()))
+ m5:append(Template("mwan/config_css"))
+
+
+mwan_policy = m5:section(TypedSection, "policy", translate("Policies"),
+ translate("Policies are profiles grouping one or more members controlling how MWAN distributes traffic<br />" ..
+ "Member interfaces with lower metrics are used first. Interfaces with the same metric load-balance<br />" ..
+ "Load-balanced member interfaces distribute more traffic out those with higher weights<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be 15 characters or less<br />" ..
+ "Policies may not share the same name as configured interfaces, members or rules"))
+ mwan_policy.addremove = true
+ mwan_policy.dynamic = false
+ mwan_policy.sectionhead = "Policy"
+ mwan_policy.sortable = true
+ mwan_policy.template = "cbi/tblsection"
+ mwan_policy.extedit = ds.build_url("admin", "network", "mwan", "configuration", "policy", "%s")
+ function mwan_policy.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(ds.build_url("admin", "network", "mwan", "configuration", "policy", section))
+ end
+
+
+use_member = mwan_policy:option(DummyValue, "use_member", translate("Members assigned"))
+ use_member.rawhtml = true
+ function use_member.cfgvalue(self, s)
+ local memberConfig, memberList = self.map:get(s, "use_member"), ""
+ if memberConfig then
+ for k,v in pairs(memberConfig) do
+ memberList = memberList .. v .. "<br />"
+ end
+ return memberList
+ else
+ return "—"
+ end
+
+ end
+
+last_resort = mwan_policy:option(DummyValue, "last_resort", translate("Last resort"))
+ last_resort.rawhtml = true
+ function last_resort.cfgvalue(self, s)
+ local action = self.map:get(s, "last_resort")
+ if action == "blackhole" then
+ return "blackhole (drop)"
+ elseif action == "default" then
+ return "default (use main routing table)"
+ else
+ return "unreachable (reject)"
+ end
+ end
+
+errors = mwan_policy:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if not string.find(err_name_list, " " .. s .. " ") then
+ return ""
+ else
+ return "<span title=\"Name exceeds 15 characters\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ end
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function policyCheck() -- check to see if this policy's name exceed the maximum of 15 characters
+ policyNameLength = string.len(arg[1])
+ if policyNameLength > 15 then
+ nameTooLong = 1
+ end
+end
+
+function policyWarn() -- display status and warning messages at the top of the page
+ if nameTooLong == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: this policy's name is " .. policyNameLength .. " characters exceeding the maximum of 15!</strong></font>"
+ else
+ return ""
+ end
+end
+
+function cbiAddMember(field)
+ uci.cursor():foreach("mwan3", "member",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+-- ------ policy configuration ------ --
+
+dsp = require "luci.dispatcher"
+arg[1] = arg[1] or ""
+
+nameTooLong = 0
+policyCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Policy Configuration - " .. arg[1]),
+ translate(policyWarn()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan", "configuration", "policy")
+
+
+mwan_policy = m5:section(NamedSection, arg[1], "policy", "")
+ mwan_policy.addremove = false
+ mwan_policy.dynamic = false
+
+
+use_member = mwan_policy:option(DynamicList, "use_member", translate("Member used"))
+ cbiAddMember(use_member)
+
+last_resort = mwan_policy:option(ListValue, "last_resort", translate("Last resort"),
+ translate("When all policy members are offline use this behavior for matched traffic"))
+ last_resort.default = "unreachable"
+ last_resort:value("unreachable", translate("unreachable (reject)"))
+ last_resort:value("blackhole", translate("blackhole (drop)"))
+ last_resort:value("default", translate("default (use main routing table)"))
+
+
+-- ------ currently configured members ------ --
+
+mwan_member = m5:section(TypedSection, "member", translate("Currently Configured Members"))
+ mwan_member.addremove = false
+ mwan_member.dynamic = false
+ mwan_member.sortable = false
+ mwan_member.template = "cbi/tblsection"
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function ruleCheck() -- determine if rules needs a proper protocol configured
+ uci.cursor():foreach("mwan3", "rule",
+ function (section)
+ local sourcePort = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".src_port"))
+ local destPort = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".dest_port"))
+ if sourcePort ~= "" or destPort ~= "" then -- ports configured
+ local protocol = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".proto"))
+ if protocol == "" or protocol == "all" then -- no or improper protocol
+ error_protocol_list = error_protocol_list .. section[".name"] .. " "
+ end
+ end
+ end
+ )
+end
+
+function ruleWarn() -- display warning messages at the top of the page
+ if error_protocol_list ~= " " then
+ return "<font color=\"ff0000\"><strong>WARNING: some rules have a port configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
+ else
+ return ""
+ end
+end
+
+-- ------ rule configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+error_protocol_list = " "
+ruleCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Rule Configuration"),
+ translate(ruleWarn()))
+ m5:append(Template("mwan/config_css"))
+
+
+mwan_rule = m5:section(TypedSection, "rule", translate("Traffic Rules"),
+ translate("Rules specify which traffic will use a particular MWAN policy based on IP address, port or protocol<br />" ..
+ "Rules are matched from top to bottom. Rules below a matching rule are ignored. Traffic not matching any rule is routed using the main routing table<br />" ..
+ "Traffic destined for known (other than default) networks is handled by the main routing table. Traffic matching a rule, but all WAN interfaces for that policy are down will be blackholed<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Rules may not share the same name as configured interfaces, members or policies"))
+ mwan_rule.addremove = true
+ mwan_rule.anonymous = false
+ mwan_rule.dynamic = false
+ mwan_rule.sectionhead = "Rule"
+ mwan_rule.sortable = true
+ mwan_rule.template = "cbi/tblsection"
+ mwan_rule.extedit = dsp.build_url("admin", "network", "mwan", "configuration", "rule", "%s")
+ function mwan_rule.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(dsp.build_url("admin", "network", "mwan", "configuration", "rule", section))
+ end
+
+
+src_ip = mwan_rule:option(DummyValue, "src_ip", translate("Source address"))
+ src_ip.rawhtml = true
+ function src_ip.cfgvalue(self, s)
+ return self.map:get(s, "src_ip") or "—"
+ end
+
+src_port = mwan_rule:option(DummyValue, "src_port", translate("Source port"))
+ src_port.rawhtml = true
+ function src_port.cfgvalue(self, s)
+ return self.map:get(s, "src_port") or "—"
+ end
+
+dest_ip = mwan_rule:option(DummyValue, "dest_ip", translate("Destination address"))
+ dest_ip.rawhtml = true
+ function dest_ip.cfgvalue(self, s)
+ return self.map:get(s, "dest_ip") or "—"
+ end
+
+dest_port = mwan_rule:option(DummyValue, "dest_port", translate("Destination port"))
+ dest_port.rawhtml = true
+ function dest_port.cfgvalue(self, s)
+ return self.map:get(s, "dest_port") or "—"
+ end
+
+proto = mwan_rule:option(DummyValue, "proto", translate("Protocol"))
+ proto.rawhtml = true
+ function proto.cfgvalue(self, s)
+ return self.map:get(s, "proto") or "all"
+ end
+
+use_policy = mwan_rule:option(DummyValue, "use_policy", translate("Policy assigned"))
+ use_policy.rawhtml = true
+ function use_policy.cfgvalue(self, s)
+ return self.map:get(s, "use_policy") or "—"
+ end
+
+errors = mwan_rule:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if not string.find(error_protocol_list, " " .. s .. " ") then
+ return ""
+ else
+ return "<span title=\"No protocol specified\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ end
+
+
+return m5
--- /dev/null
+-- ------ extra functions ------ --
+
+function ruleCheck() -- determine if rule needs a protocol specified
+ local sourcePort = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".src_port"))
+ local destPort = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".dest_port"))
+ if sourcePort ~= "" or destPort ~= "" then -- ports configured
+ local protocol = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".proto"))
+ if protocol == "" or protocol == "all" then -- no or improper protocol
+ error_protocol = 1
+ end
+ end
+end
+
+function ruleWarn() -- display warning message at the top of the page
+ if error_protocol == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: this rule is incorrectly configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
+ else
+ return ""
+ end
+end
+
+function cbiAddPolicy(field)
+ uci.cursor():foreach("mwan3", "policy",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+function cbiAddProtocol(field)
+ local protocols = ut.trim(sys.exec("cat /etc/protocols | grep ' # ' | awk '{print $1}' | grep -vw -e 'ip' -e 'tcp' -e 'udp' -e 'icmp' -e 'esp' | grep -v 'ipv6' | sort | tr '\n' ' '"))
+ for p in string.gmatch(protocols, "%S+") do
+ field:value(p)
+ end
+end
+
+-- ------ rule configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+arg[1] = arg[1] or ""
+
+error_protocol = 0
+ruleCheck()
+
+
+m5 = Map("mwan3", translate("MWAN Rule Configuration - ") .. arg[1],
+ translate(ruleWarn()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan", "configuration", "rule")
+
+
+mwan_rule = m5:section(NamedSection, arg[1], "rule", "")
+ mwan_rule.addremove = false
+ mwan_rule.dynamic = false
+
+
+src_ip = mwan_rule:option(Value, "src_ip", translate("Source address"),
+ translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
+ src_ip.datatype = ipaddr
+
+src_port = mwan_rule:option(Value, "src_port", translate("Source port"),
+ translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
+
+dest_ip = mwan_rule:option(Value, "dest_ip", translate("Destination address"),
+ translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
+ dest_ip.datatype = ipaddr
+
+dest_port = mwan_rule:option(Value, "dest_port", translate("Destination port"),
+ translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
+
+proto = mwan_rule:option(Value, "proto", translate("Protocol"),
+ translate("View the contents of /etc/protocols for protocol descriptions"))
+ proto.default = "all"
+ proto.rmempty = false
+ proto:value("all")
+ proto:value("ip")
+ proto:value("tcp")
+ proto:value("udp")
+ proto:value("icmp")
+ proto:value("esp")
+ cbiAddProtocol(proto)
+
+use_policy = mwan_rule:option(Value, "use_policy", translate("Policy assigned"))
+ cbiAddPolicy(use_policy)
+ use_policy:value("unreachable", translate("unreachable (reject)"))
+ use_policy:value("blackhole", translate("blackhole (drop)"))
+ use_policy:value("default", translate("default (use main routing table)"))
+
+
+-- ------ currently configured policies ------ --
+
+mwan_policy = m5:section(TypedSection, "policy", translate("Currently Configured Policies"))
+ mwan_policy.addremove = false
+ mwan_policy.dynamic = false
+ mwan_policy.sortable = false
+ mwan_policy.template = "cbi/tblsection"
+
+
+return m5
+++ /dev/null
--- ------ hotplug script configuration ------ --
-
-fs = require "nixio.fs"
-sys = require "luci.sys"
-ut = require "luci.util"
-
-script = "/etc/hotplug.d/iface/16-mwan3custom"
-scriptbak = "/etc/hotplug.d/iface/16-mwan3custombak"
-
-if luci.http.formvalue("cbid.luci.1._restorebak") then -- restore button has been clicked
- luci.http.redirect(luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug") .. "?restore=yes")
-elseif luci.http.formvalue("restore") == "yes" then -- restore script from backup
- os.execute("cp -f " .. scriptbak .. " " .. script)
-end
-
-
-m5 = SimpleForm("luci", nil)
- m5:append(Template("mwan3/mwan3_adv_hotplug")) -- highlight current tab
-
-f = m5:section(SimpleSection, nil,
- translate("This section allows you to modify the contents of /etc/hotplug.d/iface/16-mwan3custom<br />" ..
- "This is useful for running system commands and/or scripts based on interface ifup or ifdown hotplug events<br /><br />" ..
- "Notes:<br />" ..
- "The first line of the script must be "#!/bin/sh" without quotes<br />" ..
- "Lines beginning with # are comments and are not executed<br /><br />" ..
- "Available variables:<br />" ..
- "$ACTION is the hotplug event (ifup, ifdown)<br />" ..
- "$INTERFACE is the interface name (wan1, wan2, etc.)<br />" ..
- "$DEVICE is the device name attached to the interface (eth0.1, eth1, etc.)"))
-
-
-restore = f:option(Button, "_restorebak", translate("Restore default hotplug script"))
- restore.inputtitle = translate("Restore...")
- restore.inputstyle = "apply"
-
-t = f:option(TextValue, "lines")
- t.rmempty = true
- t.rows = 20
-
- function t.cfgvalue()
- local hps = fs.readfile(script)
- if not hps or hps == "" then -- if script does not exist or is blank restore from backup
- sys.call("cp -f " .. scriptbak .. " " .. script)
- return fs.readfile(script)
- else
- return hps
- end
- end
-
- function t.write(self, section, data) -- format and write new data to script
- return fs.writefile(script, ut.trim(data:gsub("\r\n", "\n")) .. "\n")
- end
-
-
-return m5
+++ /dev/null
--- ------ mwan3 configuration ------ --
-
-ut = require "luci.util"
-
-mwan3file = "/etc/config/mwan3"
-
-
-m5 = SimpleForm("luci", nil)
- m5:append(Template("mwan3/mwan3_adv_mwan3")) -- highlight current tab
-
-
-f = m5:section(SimpleSection, nil,
- translate("This section allows you to modify the contents of /etc/config/mwan3"))
-
-t = f:option(TextValue, "lines")
- t.rmempty = true
- t.rows = 20
-
- function t.cfgvalue()
- return nixio.fs.readfile(mwan3file) or ""
- end
-
- function t.write(self, section, data) -- format and write new data to script
- return nixio.fs.writefile(mwan3file, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
- end
-
- function f.handle(self, state, data)
- return true
- end
-
-
-return m5
+++ /dev/null
--- ------ network configuration ------ --
-
-ut = require "luci.util"
-
-netfile = "/etc/config/network"
-
-
-m5 = SimpleForm("networkconf", nil)
- m5:append(Template("mwan3/mwan3_adv_network")) -- highlight current tab
-
-
-f = m5:section(SimpleSection, nil,
- translate("This section allows you to modify the contents of /etc/config/network"))
-
-t = f:option(TextValue, "lines")
- t.rmempty = true
- t.rows = 20
-
- function t.cfgvalue()
- return nixio.fs.readfile(netfile) or ""
- end
-
- function t.write(self, section, data) -- format and write new data to script
- return nixio.fs.writefile(netfile, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
- end
-
- function f.handle(self, state, data)
- return true
- end
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function iface_check() -- find issues with too many interfaces, reliability and metric
- uci.cursor():foreach("mwan3", "interface",
- function (section)
- local ifname = section[".name"]
- ifnum = ifnum+1 -- count number of mwan3 interfaces configured
- -- create list of metrics for none and duplicate checking
- local metlkp = ut.trim(sys.exec("uci get -p /var/state network." .. ifname .. ".metric"))
- if metlkp == "" then
- err_found = 1
- err_nomet_list = err_nomet_list .. ifname .. " "
- else
- metric_list = metric_list .. ifname .. " " .. metlkp .. "\n"
- end
- -- check if any interfaces have a higher reliability requirement than tracking IPs configured
- local tipnum = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. ifname .. ".track_ip) | wc -w")))
- if tipnum > 0 then
- local relnum = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".reliability")))
- if relnum and relnum > tipnum then
- err_found = 1
- err_rel_list = err_rel_list .. ifname .. " "
- end
- end
- -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
- if ut.trim(sys.exec("uci get -p /var/state network." .. ifname)) == "interface" then
- local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. ifname .. ".ifname"))
- if ifdev == "uci: Entry not found" or ifdev == "" then
- err_found = 1
- err_netcfg_list = err_netcfg_list .. ifname .. " "
- err_route_list = err_route_list .. ifname .. " "
- else
- local rtcheck = ut.trim(sys.exec("route -n | awk '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $1 }'"))
- if rtcheck == "" then
- err_found = 1
- err_route_list = err_route_list .. ifname .. " "
- end
- end
- else
- err_found = 1
- err_netcfg_list = err_netcfg_list .. ifname .. " "
- err_route_list = err_route_list .. ifname .. " "
- end
- end
- )
- -- check if any interfaces have duplicate metrics
- local metric_dupnums = sys.exec("echo '" .. metric_list .. "' | awk '{ print $2 }' | uniq -d")
- if metric_dupnums ~= "" then
- err_found = 1
- local metric_dupes = ""
- for line in metric_dupnums:gmatch("[^\r\n]+") do
- metric_dupes = sys.exec("echo '" .. metric_list .. "' | grep '" .. line .. "' | awk '{ print $1 }'")
- err_dupmet_list = err_dupmet_list .. metric_dupes
- end
- err_dupmet_list = sys.exec("echo '" .. err_dupmet_list .. "' | tr '\n' ' '")
- end
-end
-
-function iface_warn() -- display status and warning messages at the top of the page
- local warns = ""
- if ifnum <= 250 then
- warns = "<strong>There are currently " .. ifnum .. " of 250 supported interfaces configured</strong>"
- else
- warns = "<font color=\"ff0000\"><strong>WARNING: " .. ifnum .. " interfaces are configured exceeding the maximum of 250!</strong></font>"
- end
- if err_rel_list ~= " " then
- warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have a higher reliability requirement than there are tracking IP addresses!</strong></font>"
- end
- if err_route_list ~= " " then
- warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no default route in the main routing table!</strong></font>"
- end
- if err_netcfg_list ~= " " then
- warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces are configured incorrectly or not at all in /etc/config/network!</strong></font>"
- end
- if err_nomet_list ~= " " then
- warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no metric configured in /etc/config/network!</strong></font>"
- end
- if err_dupmet_list ~= " " then
- warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
- end
- return warns
-end
-
--- ------ interface configuration ------ --
-
-dsp = require "luci.dispatcher"
-sys = require "luci.sys"
-ut = require "luci.util"
-
-ifnum = 0
-metric_list = ""
-err_found = 0
-err_dupmet_list = " "
-err_netcfg_list = " "
-err_nomet_list = " "
-err_rel_list = " "
-err_route_list = " "
-iface_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Interface Configuration"),
- translate(iface_warn()))
- m5:append(Template("mwan3/mwan3_config_css"))
-
-
-mwan_interface = m5:section(TypedSection, "interface", translate("Interfaces"),
- translate("MWAN3 supports up to 250 physical and/or logical interfaces<br />" ..
- "MWAN3 requires that all interfaces have a unique metric configured in /etc/config/network<br />" ..
- "Names must match the interface name found in /etc/config/network (see advanced tab)<br />" ..
- "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
- "Interfaces may not share the same name as configured members, policies or rules"))
- mwan_interface.addremove = true
- mwan_interface.dynamic = false
- mwan_interface.sectionhead = "Interface"
- mwan_interface.sortable = true
- mwan_interface.template = "cbi/tblsection"
- mwan_interface.extedit = dsp.build_url("admin", "network", "mwan3", "configuration", "interface", "%s")
- function mwan_interface.create(self, section)
- TypedSection.create(self, section)
- m5.uci:save("mwan3")
- luci.http.redirect(dsp.build_url("admin", "network", "mwan3", "configuration", "interface", section))
- end
-
-
-enabled = mwan_interface:option(DummyValue, "enabled", translate("Enabled"))
- enabled.rawhtml = true
- function enabled.cfgvalue(self, s)
- if self.map:get(s, "enabled") == "1" then
- return "Yes"
- else
- return "No"
- end
- end
-
-track_ip = mwan_interface:option(DummyValue, "track_ip", translate("Tracking IP"))
- track_ip.rawhtml = true
- function track_ip.cfgvalue(self, s)
- local str = ""
- tracked = self.map:get(s, "track_ip")
- if tracked then
- for k,v in pairs(tracked) do
- str = str .. v .. "<br />"
- end
- return str
- else
- return "—"
- end
- end
-
-reliability = mwan_interface:option(DummyValue, "reliability", translate("Tracking reliability"))
- reliability.rawhtml = true
- function reliability.cfgvalue(self, s)
- if tracked then
- return self.map:get(s, "reliability") or "—"
- else
- return "—"
- end
- end
-
-count = mwan_interface:option(DummyValue, "count", translate("Ping count"))
- count.rawhtml = true
- function count.cfgvalue(self, s)
- if tracked then
- return self.map:get(s, "count") or "—"
- else
- return "—"
- end
- end
-
-timeout = mwan_interface:option(DummyValue, "timeout", translate("Ping timeout"))
- timeout.rawhtml = true
- function timeout.cfgvalue(self, s)
- if tracked then
- local tcheck = self.map:get(s, "timeout")
- if tcheck then
- return tcheck .. "s"
- else
- return "—"
- end
- else
- return "—"
- end
- end
-
-interval = mwan_interface:option(DummyValue, "interval", translate("Ping interval"))
- interval.rawhtml = true
- function interval.cfgvalue(self, s)
- if tracked then
- local icheck = self.map:get(s, "interval")
- if icheck then
- return icheck .. "s"
- else
- return "—"
- end
- else
- return "—"
- end
- end
-
-down = mwan_interface:option(DummyValue, "down", translate("Interface down"))
- down.rawhtml = true
- function down.cfgvalue(self, s)
- if tracked then
- return self.map:get(s, "down") or "—"
- else
- return "—"
- end
- end
-
-up = mwan_interface:option(DummyValue, "up", translate("Interface up"))
- up.rawhtml = true
- function up.cfgvalue(self, s)
- if tracked then
- return self.map:get(s, "up") or "—"
- else
- return "—"
- end
- end
-
-metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
- metric.rawhtml = true
- function metric.cfgvalue(self, s)
- local metcheck = sys.exec("uci get -p /var/state network." .. s .. ".metric")
- if metcheck ~= "" then
- return metcheck
- else
- return "—"
- end
- end
-
-errors = mwan_interface:option(DummyValue, "errors", translate("Errors"))
- errors.rawhtml = true
- function errors.cfgvalue(self, s)
- if err_found == 1 then
- local mouseover, linebrk = "", ""
- if string.find(err_rel_list, " " .. s .. " ") then
- mouseover = "Higher reliability requirement than there are tracking IP addresses"
- linebrk = " "
- end
- if string.find(err_route_list, " " .. s .. " ") then
- mouseover = mouseover .. linebrk .. "No default route in the main routing table"
- linebrk = " "
- end
- if string.find(err_netcfg_list, " " .. s .. " ") then
- mouseover = mouseover .. linebrk .. "Configured incorrectly or not at all in /etc/config/network"
- linebrk = " "
- end
- if string.find(err_nomet_list, " " .. s .. " ") then
- mouseover = mouseover .. linebrk .. "No metric configured in /etc/config/network"
- linebrk = " "
- end
- if string.find(err_dupmet_list, " " .. s .. " ") then
- mouseover = mouseover .. linebrk .. "Duplicate metric configured in /etc/config/network"
- end
- if mouseover == "" then
- return ""
- else
- return "<span title=\"" .. mouseover .. "\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
- end
- else
- return ""
- end
- end
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function iface_check()
- metcheck = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".metric"))
- if metcheck == "" then -- no metric
- err_nomet = 1
- else -- if metric exists create list of interface metrics to compare against for duplicates
- uci.cursor():foreach("mwan3", "interface",
- function (section)
- local metlkp = ut.trim(sys.exec("uci get -p /var/state network." .. section[".name"] .. ".metric"))
- metric_list = metric_list .. section[".name"] .. " " .. metlkp .. "\n"
- end
- )
- -- compare metric against list
- local metric_dupnums, metric_dupes = sys.exec("echo '" .. metric_list .. "' | awk '{ print $2 }' | uniq -d"), ""
- for line in metric_dupnums:gmatch("[^\r\n]+") do
- metric_dupes = sys.exec("echo '" .. metric_list .. "' | grep '" .. line .. "' | awk '{ print $1 }'")
- err_dupmet_list = err_dupmet_list .. metric_dupes
- end
- if sys.exec("echo '" .. err_dupmet_list .. "' | grep -w " .. arg[1]) ~= "" then
- err_dupmet = 1
- end
- end
- -- check if this interface has a higher reliability requirement than track IPs configured
- local tipnum = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. arg[1] .. ".track_ip) | wc -w")))
- if tipnum > 0 then
- local relnum = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".reliability")))
- if relnum and relnum > tipnum then
- err_reliability = 1
- end
- end
- -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
- if ut.trim(sys.exec("uci get -p /var/state network." .. arg[1])) == "interface" then
- local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".ifname"))
- if ifdev == "uci: Entry not found" or ifdev == "" then
- err_netcfg = 1
- err_route = 1
- else
- local rtcheck = ut.trim(sys.exec("route -n | awk '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $1 }'"))
- if rtcheck == "" then
- err_route = 1
- end
- end
- else
- err_netcfg = 1
- err_route = 1
- end
-end
-
-function iface_warn() -- display warning messages at the top of the page
- local warns, linebrk = "", ""
- if err_reliability == 1 then
- warns = "<font color=\"ff0000\"><strong>WARNING: this interface has a higher reliability requirement than there are tracking IP addresses!</strong></font>"
- linebrk = "<br /><br />"
- end
- if err_route == 1 then
- warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface has no default route in the main routing table!</strong></font>"
- linebrk = "<br /><br />"
- end
- if err_netcfg == 1 then
- warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface is configured incorrectly or not at all in /etc/config/network!</strong></font>"
- linebrk = "<br /><br />"
- end
- if err_nomet == 1 then
- warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface has no metric configured in /etc/config/network!</strong></font>"
- elseif err_dupmet == 1 then
- warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this and other interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
- end
- return warns
-end
-
--- ------ interface configuration ------ --
-
-dsp = require "luci.dispatcher"
-sys = require "luci.sys"
-ut = require "luci.util"
-arg[1] = arg[1] or ""
-
-metcheck = ""
-metric_list = ""
-err_dupmet_list = ""
-err_rel_list = ""
-err_nomet = 0
-err_dupmet = 0
-err_route = 0
-err_netcfg = 0
-err_reliability = 0
-iface_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Interface Configuration - " .. arg[1]),
- translate(iface_warn()))
- m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "interface")
-
-
-mwan_interface = m5:section(NamedSection, arg[1], "interface", "")
- mwan_interface.addremove = false
- mwan_interface.dynamic = false
-
-
-enabled = mwan_interface:option(ListValue, "enabled", translate("Enabled"))
- enabled.default = "1"
- enabled:value("1", translate("Yes"))
- enabled:value("0", translate("No"))
-
-track_ip = mwan_interface:option(DynamicList, "track_ip", translate("Tracking IP"),
- translate("This IP address will be pinged to dermine if the link is up or down. Leave blank to assume interface is always online"))
- track_ip.datatype = "ipaddr"
-
-reliability = mwan_interface:option(Value, "reliability", translate("Tracking reliability"),
- translate("Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up"))
- reliability.datatype = "range(1, 100)"
- reliability.default = "1"
-
-count = mwan_interface:option(ListValue, "count", translate("Ping count"))
- count.default = "1"
- count:value("1")
- count:value("2")
- count:value("3")
- count:value("4")
- count:value("5")
-
-timeout = mwan_interface:option(ListValue, "timeout", translate("Ping timeout"))
- timeout.default = "2"
- timeout:value("1", translate("1 second"))
- timeout:value("2", translate("2 seconds"))
- timeout:value("3", translate("3 seconds"))
- timeout:value("4", translate("4 seconds"))
- timeout:value("5", translate("5 seconds"))
- timeout:value("6", translate("6 seconds"))
- timeout:value("7", translate("7 seconds"))
- timeout:value("8", translate("8 seconds"))
- timeout:value("9", translate("9 seconds"))
- timeout:value("10", translate("10 seconds"))
-
-interval = mwan_interface:option(ListValue, "interval", translate("Ping interval"))
- interval.default = "5"
- interval:value("1", translate("1 second"))
- interval:value("3", translate("3 seconds"))
- interval:value("5", translate("5 seconds"))
- interval:value("10", translate("10 seconds"))
- interval:value("20", translate("20 seconds"))
- interval:value("30", translate("30 seconds"))
- interval:value("60", translate("1 minute"))
- interval:value("300", translate("5 minutes"))
- interval:value("600", translate("10 minutes"))
- interval:value("900", translate("15 minutes"))
- interval:value("1800", translate("30 minutes"))
- interval:value("3600", translate("1 hour"))
-
-down = mwan_interface:option(ListValue, "down", translate("Interface down"),
- translate("Interface will be deemed down after this many failed ping tests"))
- down.default = "3"
- down:value("1")
- down:value("2")
- down:value("3")
- down:value("4")
- down:value("5")
- down:value("6")
- down:value("7")
- down:value("8")
- down:value("9")
- down:value("10")
-
-up = mwan_interface:option(ListValue, "up", translate("Interface up"),
- translate("Downed interface will be deemed up after this many successful ping tests"))
- up.default = "3"
- up:value("1")
- up:value("2")
- up:value("3")
- up:value("4")
- up:value("5")
- up:value("6")
- up:value("7")
- up:value("8")
- up:value("9")
- up:value("10")
-
-metric = mwan_interface:option(DummyValue, "metric", translate("Metric"),
- translate("This displays the metric assigned to this interface in /etc/config/network"))
- metric.rawhtml = true
- function metric.cfgvalue(self, s)
- if err_nomet == 0 then
- return metcheck
- else
- return "—"
- end
- end
-
-
-return m5
+++ /dev/null
--- ------ member configuration ------ --
-
-ds = require "luci.dispatcher"
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Member Configuration"))
- m5:append(Template("mwan3/mwan3_config_css"))
-
-
-mwan_member = m5:section(TypedSection, "member", translate("Members"),
- translate("Members are profiles attaching a metric and weight to an MWAN3 interface<br />" ..
- "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
- "Members may not share the same name as configured interfaces, policies or rules"))
- mwan_member.addremove = true
- mwan_member.dynamic = false
- mwan_member.sectionhead = "Member"
- mwan_member.sortable = true
- mwan_member.template = "cbi/tblsection"
- mwan_member.extedit = ds.build_url("admin", "network", "mwan3", "configuration", "member", "%s")
- function mwan_member.create(self, section)
- TypedSection.create(self, section)
- m5.uci:save("mwan3")
- luci.http.redirect(ds.build_url("admin", "network", "mwan3", "configuration", "member", section))
- end
-
-
-interface = mwan_member:option(DummyValue, "interface", translate("Interface"))
- interface.rawhtml = true
- function interface.cfgvalue(self, s)
- return self.map:get(s, "interface") or "—"
- end
-
-metric = mwan_member:option(DummyValue, "metric", translate("Metric"))
- metric.rawhtml = true
- function metric.cfgvalue(self, s)
- return self.map:get(s, "metric") or "1"
- end
-
-weight = mwan_member:option(DummyValue, "weight", translate("Weight"))
- weight.rawhtml = true
- function weight.cfgvalue(self, s)
- return self.map:get(s, "weight") or "1"
- end
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function cbi_add_interface(field)
- uci.cursor():foreach("mwan3", "interface",
- function (section)
- field:value(section[".name"])
- end
- )
-end
-
--- ------ member configuration ------ --
-
-dsp = require "luci.dispatcher"
-arg[1] = arg[1] or ""
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Member Configuration - ") .. arg[1])
- m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "member")
-
-
-mwan_member = m5:section(NamedSection, arg[1], "member", "")
- mwan_member.addremove = false
- mwan_member.dynamic = false
-
-
-interface = mwan_member:option(Value, "interface", translate("Interface"))
- cbi_add_interface(interface)
-
-metric = mwan_member:option(Value, "metric", translate("Metric"),
- translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
- metric.datatype = "range(1, 1000)"
-
-weight = mwan_member:option(Value, "weight", translate("Weight"),
- translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
- weight.datatype = "range(1, 1000)"
-
-
--- ------ currently configured interfaces ------ --
-
-mwan_interface = m5:section(TypedSection, "interface", translate("Currently Configured Interfaces"))
- mwan_interface.addremove = false
- mwan_interface.dynamic = false
- mwan_interface.sortable = false
- mwan_interface.template = "cbi/tblsection"
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function policy_check() -- check to see if any policy names exceed the maximum of 15 characters
- uci.cursor():foreach("mwan3", "policy",
- function (section)
- if string.len(section[".name"]) > 15 then
- toolong = 1
- err_name_list = err_name_list .. section[".name"] .. " "
- end
- end
- )
-end
-
-function policy_warn() -- display status and warning messages at the top of the page
- if toolong == 1 then
- return "<font color=\"ff0000\"><strong>WARNING: Some policies have names exceeding the maximum of 15 characters!</strong></font>"
- else
- return ""
- end
-end
-
--- ------ policy configuration ------ --
-
-ds = require "luci.dispatcher"
-sys = require "luci.sys"
-
-toolong = 0
-err_name_list = " "
-policy_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Policy Configuration"),
- translate(policy_warn()))
- m5:append(Template("mwan3/mwan3_config_css"))
-
-
-mwan_policy = m5:section(TypedSection, "policy", translate("Policies"),
- translate("Policies are profiles grouping one or more members controlling how MWAN3 distributes traffic<br />" ..
- "Member interfaces with lower metrics are used first. Interfaces with the same metric load-balance<br />" ..
- "Load-balanced member interfaces distribute more traffic out those with higher weights<br />" ..
- "Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be 15 characters or less<br />" ..
- "Policies may not share the same name as configured interfaces, members or rules"))
- mwan_policy.addremove = true
- mwan_policy.dynamic = false
- mwan_policy.sectionhead = "Policy"
- mwan_policy.sortable = true
- mwan_policy.template = "cbi/tblsection"
- mwan_policy.extedit = ds.build_url("admin", "network", "mwan3", "configuration", "policy", "%s")
- function mwan_policy.create(self, section)
- TypedSection.create(self, section)
- m5.uci:save("mwan3")
- luci.http.redirect(ds.build_url("admin", "network", "mwan3", "configuration", "policy", section))
- end
-
-
-use_member = mwan_policy:option(DummyValue, "use_member", translate("Members assigned"))
- use_member.rawhtml = true
- function use_member.cfgvalue(self, s)
- local tab, str = self.map:get(s, "use_member"), ""
- if tab then
- for k,v in pairs(tab) do
- str = str .. v .. "<br />"
- end
- return str
- else
- return "—"
- end
-
- end
-
-last_resort = mwan_policy:option(DummyValue, "last_resort", translate("Last resort"))
- last_resort.rawhtml = true
- function last_resort.cfgvalue(self, s)
- local str = self.map:get(s, "last_resort")
- if str == "blackhole" then
- return "blackhole (drop)"
- elseif str == "default" then
- return "default (use main routing table)"
- else
- return "unreachable (reject)"
- end
- end
-
-errors = mwan_policy:option(DummyValue, "errors", translate("Errors"))
- errors.rawhtml = true
- function errors.cfgvalue(self, s)
- if not string.find(err_name_list, " " .. s .. " ") then
- return ""
- else
- return "<span title=\"Name exceeds 15 characters\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
- end
- end
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function policy_check() -- check to see if this policy's name exceed the maximum of 15 characters
- polchar = string.len(arg[1])
- if polchar > 15 then
- toolong = 1
- end
-end
-
-function policy_warn() -- display status and warning messages at the top of the page
- if toolong == 1 then
- return "<font color=\"ff0000\"><strong>WARNING: this policy's name is " .. polchar .. " characters exceeding the maximum of 15!</strong></font>"
- else
- return ""
- end
-end
-
-function cbi_add_member(field)
- uci.cursor():foreach("mwan3", "member",
- function (section)
- field:value(section[".name"])
- end
- )
-end
-
--- ------ policy configuration ------ --
-
-dsp = require "luci.dispatcher"
-arg[1] = arg[1] or ""
-
-toolong = 0
-policy_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Policy Configuration - " .. arg[1]),
- translate(policy_warn()))
- m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "policy")
-
-
-mwan_policy = m5:section(NamedSection, arg[1], "policy", "")
- mwan_policy.addremove = false
- mwan_policy.dynamic = false
-
-
-use_member = mwan_policy:option(DynamicList, "use_member", translate("Member used"))
- cbi_add_member(use_member)
-
-last_resort = mwan_policy:option(ListValue, "last_resort", translate("Last resort"),
- translate("When all policy members are offline use this behavior for matched traffic"))
- last_resort.default = "unreachable"
- last_resort:value("unreachable", translate("unreachable (reject)"))
- last_resort:value("blackhole", translate("blackhole (drop)"))
- last_resort:value("default", translate("default (use main routing table)"))
-
-
--- ------ currently configured members ------ --
-
-mwan_member = m5:section(TypedSection, "member", translate("Currently Configured Members"))
- mwan_member.addremove = false
- mwan_member.dynamic = false
- mwan_member.sortable = false
- mwan_member.template = "cbi/tblsection"
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function rule_check() -- determine if rules needs a proper protocol configured
- uci.cursor():foreach("mwan3", "rule",
- function (section)
- local sport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".src_port"))
- local dport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".dest_port"))
- if sport ~= "" or dport ~= "" then -- ports configured
- local proto = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".proto"))
- if proto == "" or proto == "all" then -- no or improper protocol
- err_proto_list = err_proto_list .. section[".name"] .. " "
- end
- end
- end
- )
-end
-
-function rule_warn() -- display warning messages at the top of the page
- if err_proto_list ~= " " then
- return "<font color=\"ff0000\"><strong>WARNING: some rules have a port configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
- else
- return ""
- end
-end
-
--- ------ rule configuration ------ --
-
-dsp = require "luci.dispatcher"
-sys = require "luci.sys"
-ut = require "luci.util"
-
-err_proto = 0
-err_proto_list = " "
-rule_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Traffic Rule Configuration"),
- translate(rule_warn()))
- m5:append(Template("mwan3/mwan3_config_css"))
-
-
-mwan_rule = m5:section(TypedSection, "rule", translate("Traffic Rules"),
- translate("Rules specify which traffic will use a particular MWAN3 policy based on IP address, port or protocol<br />" ..
- "Rules are matched from top to bottom. Rules below a matching rule are ignored. Traffic not matching any rule is routed using the main routing table<br />" ..
- "Traffic destined for known (other than default) networks is handled by the main routing table. Traffic matching a rule, but all WAN interfaces for that policy are down will be blackholed<br />" ..
- "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
- "Rules may not share the same name as configured interfaces, members or policies"))
- mwan_rule.addremove = true
- mwan_rule.anonymous = false
- mwan_rule.dynamic = false
- mwan_rule.sectionhead = "Rule"
- mwan_rule.sortable = true
- mwan_rule.template = "cbi/tblsection"
- mwan_rule.extedit = dsp.build_url("admin", "network", "mwan3", "configuration", "rule", "%s")
- function mwan_rule.create(self, section)
- TypedSection.create(self, section)
- m5.uci:save("mwan3")
- luci.http.redirect(dsp.build_url("admin", "network", "mwan3", "configuration", "rule", section))
- end
-
-
-src_ip = mwan_rule:option(DummyValue, "src_ip", translate("Source address"))
- src_ip.rawhtml = true
- function src_ip.cfgvalue(self, s)
- return self.map:get(s, "src_ip") or "—"
- end
-
-src_port = mwan_rule:option(DummyValue, "src_port", translate("Source port"))
- src_port.rawhtml = true
- function src_port.cfgvalue(self, s)
- return self.map:get(s, "src_port") or "—"
- end
-
-dest_ip = mwan_rule:option(DummyValue, "dest_ip", translate("Destination address"))
- dest_ip.rawhtml = true
- function dest_ip.cfgvalue(self, s)
- return self.map:get(s, "dest_ip") or "—"
- end
-
-dest_port = mwan_rule:option(DummyValue, "dest_port", translate("Destination port"))
- dest_port.rawhtml = true
- function dest_port.cfgvalue(self, s)
- return self.map:get(s, "dest_port") or "—"
- end
-
-proto = mwan_rule:option(DummyValue, "proto", translate("Protocol"))
- proto.rawhtml = true
- function proto.cfgvalue(self, s)
- return self.map:get(s, "proto") or "all"
- end
-
-use_policy = mwan_rule:option(DummyValue, "use_policy", translate("Policy assigned"))
- use_policy.rawhtml = true
- function use_policy.cfgvalue(self, s)
- return self.map:get(s, "use_policy") or "—"
- end
-
-errors = mwan_rule:option(DummyValue, "errors", translate("Errors"))
- errors.rawhtml = true
- function errors.cfgvalue(self, s)
- if not string.find(err_proto_list, " " .. s .. " ") then
- return ""
- else
- return "<span title=\"No protocol specified\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
- end
- end
-
-
-return m5
+++ /dev/null
--- ------ extra functions ------ --
-
-function rule_check() -- determine if rule needs a protocol specified
- local sport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".src_port"))
- local dport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".dest_port"))
- if sport ~= "" or dport ~= "" then -- ports configured
- local proto = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".proto"))
- if proto == "" or proto == "all" then -- no or improper protocol
- err_proto = 1
- end
- end
-end
-
-function rule_warn() -- display warning message at the top of the page
- if err_proto == 1 then
- return "<font color=\"ff0000\"><strong>WARNING: this rule is incorrectly configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
- else
- return ""
- end
-end
-
-function cbi_add_policy(field)
- uci.cursor():foreach("mwan3", "policy",
- function (section)
- field:value(section[".name"])
- end
- )
-end
-
-function cbi_add_protocol(field)
- local protos = ut.trim(sys.exec("cat /etc/protocols | grep ' # ' | awk '{print $1}' | grep -vw -e 'ip' -e 'tcp' -e 'udp' -e 'icmp' -e 'esp' | grep -v 'ipv6' | sort | tr '\n' ' '"))
- for p in string.gmatch(protos, "%S+") do
- field:value(p)
- end
-end
-
--- ------ rule configuration ------ --
-
-dsp = require "luci.dispatcher"
-sys = require "luci.sys"
-ut = require "luci.util"
-arg[1] = arg[1] or ""
-
-err_proto = 0
-rule_check()
-
-
-m5 = Map("mwan3", translate("MWAN3 Multi-WAN Rule Configuration - ") .. arg[1],
- translate(rule_warn()))
- m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "rule")
-
-
-mwan_rule = m5:section(NamedSection, arg[1], "rule", "")
- mwan_rule.addremove = false
- mwan_rule.dynamic = false
-
-
-src_ip = mwan_rule:option(Value, "src_ip", translate("Source address"),
- translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
- src_ip.datatype = ipaddr
-
-src_port = mwan_rule:option(Value, "src_port", translate("Source port"),
- translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
-
-dest_ip = mwan_rule:option(Value, "dest_ip", translate("Destination address"),
- translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
- dest_ip.datatype = ipaddr
-
-dest_port = mwan_rule:option(Value, "dest_port", translate("Destination port"),
- translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
-
-proto = mwan_rule:option(Value, "proto", translate("Protocol"),
- translate("View the contents of /etc/protocols for protocol descriptions"))
- proto.default = "all"
- proto.rmempty = false
- proto:value("all")
- proto:value("ip")
- proto:value("tcp")
- proto:value("udp")
- proto:value("icmp")
- proto:value("esp")
- cbi_add_protocol(proto)
-
-use_policy = mwan_rule:option(Value, "use_policy", translate("Policy assigned"))
- cbi_add_policy(use_policy)
- use_policy:value("unreachable", translate("unreachable (reject)"))
- use_policy:value("blackhole", translate("blackhole (drop)"))
- use_policy:value("default", translate("default (use main routing table)"))
-
-
--- ------ currently configured policies ------ --
-
-mwan_policy = m5:section(TypedSection, "policy", translate("Currently Configured Policies"))
- mwan_policy.addremove = false
- mwan_policy.dynamic = false
- mwan_policy.sortable = false
- mwan_policy.template = "cbi/tblsection"
-
-
-return m5
--- /dev/null
+<%+mwan/openwrt_overview_status%>
+++ /dev/null
-<%+mwan3/mwan3_status%>
--- /dev/null
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/mwanconfig")%>"><%:MWAN Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/networkconfig")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/diagnostics")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/troubleshooting")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<%
+ local uci = require "luci.model.uci"
+
+ interfaceNames = ""
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ interfaceNames = interfaceNames .. section[".name"] .. " "
+ end
+ )
+%>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ var stxhr = new XHR();
+
+ function update_status(tool, task)
+ {
+ var iface = document.getElementById('mwaniface').value;
+ var output = document.getElementById('diag_output');
+
+ if (tool == "service")
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
+ "Waiting for MWAN to " + task + "..."
+ ;
+ }
+ else
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
+ "Waiting for diagnostic results..."
+ ;
+ }
+
+ output.parentNode.style.display = 'block';
+ output.style.display = 'inline';
+
+ stxhr.get('<%=luci.dispatcher.build_url("admin", "network", "mwan", "advanced")%>/diagnostics_display' + '/' + iface + '/' + tool + '/' + task, null,
+ function(x, mArray)
+ {
+ if (mArray.diagnostics)
+ {
+ output.innerHTML = String.format('<pre id="diag_output_css">%h</pre>', mArray.diagnostics[0]);
+ }
+ else
+ {
+ output.innerHTML = '<pre id="diag_output_css"><strong>No diagnostic results returned</strong></pre>';
+ }
+ }
+ );
+ }
+//]]></script>
+
+<div id="mwan_diagnostics" class="cbi-map">
+ <fieldset id="diag_select" class="cbi-section">
+ <legend><%:MWAN Interface Diagnostics%></legend>
+ <select id="mwaniface">
+ <% for z in interfaceNames:gmatch("[^ ]+") do -%><option value="<%=z%>"><%=z%></option><%- end %>
+ </select>
+ <div id="buttoncss">
+ <input type="button" value="<%:Ping default gateway%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'gateway')" />
+ <input type="button" value="<%:Ping tracking IP%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'track_ip')" />
+ <input type="button" value="<%:Check IP rules%>" class="cbi-button cbi-button-apply" onclick="update_status('rulechk', null)" />
+ <input type="button" value="<%:Check routing table%>" class="cbi-button cbi-button-apply" onclick="update_status('routechk', null)" />
+ <input type="button" value="<%:Hotplug ifup%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifup')" />
+ <input type="button" value="<%:Hotplug ifdown%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifdown')" />
+ </div>
+ </fieldset>
+ <fieldset id="diag_select" class="cbi-section">
+ <legend><%:MWAN Service Control%></legend>
+ <div id="buttoncss">
+ <input type="button" value="<%:Restart MWAN%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'restart')" />
+ <input type="button" value="<%:Stop MWAN%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'stop')" />
+ <input type="button" value="<%:Start MWAN%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'start')" />
+ </div>
+ </fieldset>
+ <fieldset class="cbi-section" style="display:none">
+ <legend><%:Diagnostic Results%></legend>
+ <div id="diag_output"></div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan_diagnostics {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #diag_select {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwaniface {
+ float: left;
+ margin: 8px 20px 0px 0px;
+ }
+ #buttoncss {
+ display: table;
+ float: left;
+ text-align: left;
+ }
+ .cbi-button {
+ margin: 8px 20px 0px 0px;
+ min-width: 153px;
+ }
+ #diag_output_css {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
--- /dev/null
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/mwanconfig")%>"><%:MWAN Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/networkconfig")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/diagnostics")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/troubleshooting")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
--- /dev/null
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/mwanconfig")%>"><%:MWAN Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/networkconfig")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/diagnostics")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/troubleshooting")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
--- /dev/null
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/mwanconfig")%>"><%:MWAN Config%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/networkconfig")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/diagnostics")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/troubleshooting")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
--- /dev/null
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/hotplugscript")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/mwanconfig")%>"><%:MWAN Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/networkconfig")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/diagnostics")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/advanced/troubleshooting")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "network", "mwan", "advanced", "troubleshooting_display")%>', null,
+ function(x, mArray)
+ {
+ var tshoot = document.getElementById('troubleshoot_text');
+ if (mArray.versions)
+ {
+ var versions = '<span class="description">Software versions : </span><br /><br />';
+ var mwanConfig = '<br /><br /><span class="description">Output of "cat /etc/config/mwan3" : </span><br /><br />';
+ var netConfig = '<br /><br /><span class="description">Output of "cat /etc/config/network" : </span><br /><br />';
+ var ifconfig = '<br /><br /><span class="description">Output of "ifconfig" : </span><br /><br />';
+ var ipRoute = '<br /><br /><span class="description">Output of "route -n" : </span><br /><br />';
+ var ipRuleShow = '<br /><br /><span class="description">Output of "ip rule show" : </span><br /><br />';
+ var routeListTable = '<br /><br /><span class="description">Output of "ip route list table 1-250" : </span><br /><br />';
+ var firewallOut = '<br /><br /><span class="description">Firewall default output policy (must be ACCEPT) : </span><br /><br />';
+ var iptables = '<br /><br /><span class="description">Output of "iptables -L -t mangle -v -n" : </span><br /><br />';
+ tshoot.innerHTML = String.format(
+ '<pre>%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s</pre>',
+ versions, mArray.versions[0], mwanConfig, mArray.mwanconfig[0], netConfig, mArray.netconfig[0],
+ ifconfig, mArray.ifconfig[0], ipRoute, mArray.routeshow[0], ipRuleShow, mArray.iprule[0],
+ routeListTable, mArray.routelist[0], firewallOut, mArray.firewallout[0], iptables, mArray.iptables[0]
+ );
+ }
+ else
+ {
+ tshoot.innerHTML = '<strong>Error collecting troubleshooting information</strong>';
+ }
+ }
+ );
+//]]></script>
+
+<div id="troubleshoot">
+ <fieldset class="cbi-section">
+ <legend><%:Troubleshooting Data%></legend>
+ <div id="troubleshoot_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #troubleshoot {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #troubleshoot_text {
+ padding: 20px;
+ text-align: left;
+ }
+ .description {
+ background-color: rgb(78, 186, 241);
+ }
+</style>
+
+<%+footer%>
--- /dev/null
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ table td { /* cells showing the configuration values */
+ padding: 0px;
+ text-align: center;
+ vertical-align: middle;
+ }
+ table th { /* column for configuration section name */
+ padding: 0px;
+ text-align: center;
+ vertical-align: middle;
+ }
+ table tbody th { /* column for configuration section name */
+ padding: 0px;
+ vertical-align: middle;
+ }
+ .cbi-section-node table div { /* rows */
+ padding-top: 5px;
+ }
+ table.cbi-section-table td.cbi-section-table-cell { /* sort buttons column */
+ text-align: center;
+ }
+ .cbi-section h3 {
+ color: rgb(85, 85, 85);
+ font-family: Trebuchet MS,Verdana,sans-serif;
+ font-style: italic;
+ font-weight: normal;
+ }
+</style>
--- /dev/null
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan", "overview", "interface_status")%>', null,
+ function(x, mArray)
+ {
+ var status = document.getElementById('mwan_status_text');
+ if (mArray.wans)
+ {
+ var temp = '';
+ for( var i = 0; i < mArray.wans.length; i++ )
+ {
+ var stat = '';
+ var cssc = '';
+ switch (mArray.wans[i].status)
+ {
+ case 'online':
+ stat = 'Online (tracking active)';
+ cssc = 'wanon';
+ break;
+ case 'notMonitored':
+ stat = 'Online (tracking off)';
+ cssc = 'wanon';
+ break;
+ case 'offline':
+ stat = 'Offline';
+ cssc = 'wanoff';
+ break;
+ case 'notEnabled':
+ stat = 'Disabled';
+ cssc = 'wanoff';
+ break;
+ }
+ temp += String.format(
+ '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
+ cssc, mArray.wans[i].name, mArray.wans[i].link, mArray.wans[i].ifname, stat
+ );
+ }
+ status.innerHTML = temp;
+ }
+ else
+ {
+ status.innerHTML = '<strong>No MWAN interfaces found</strong>';
+ }
+ }
+ );
+//]]></script>
+
+<fieldset id="interface_field" class="cbi-section">
+ <legend><%:MWAN Interface Live Status%></legend>
+ <div id="mwan_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+</fieldset>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: 1044px;
+ }
+ #interface_field {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwan_status_text {
+ display: table;
+ font-size: 14px;
+ margin: auto;
+ max-width: 1044px;
+ min-width: 246px;
+ width: 100%;
+ }
+ .wanon {
+ background-color: rgb(144, 240, 144);
+ }
+ .wanoff {
+ background-color: rgb(240, 144, 144);
+ }
+ .wanon, .wanoff {
+ border-radius: 60px;
+ box-shadow: 0px 2px 5px -3px;
+ float: left;
+ margin: 8px 3px 0px 3px;
+ min-height: 30px;
+ min-width: 235px;
+ padding: 5px 10px 8px 10px;
+ text-align: center;
+ }
+</style>
--- /dev/null
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/overview")%>"><%:Interface Status%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/overview/overview_detailed")%>"><%:Detailed Status%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan", "overview", "detailed_status")%>', null,
+ function(x, mArray)
+ {
+ var status = document.getElementById('mwan_detail_text');
+ if (mArray.mwandetail)
+ {
+ status.innerHTML = String.format('<pre>%s</pre>', mArray.mwandetail[0]);
+ }
+ else
+ {
+ status.innerHTML = '<strong>No detailed status information available</strong>';
+ }
+ }
+ );
+//]]></script>
+
+<div id="mwan_detail_status">
+ <fieldset class="cbi-section">
+ <legend><%:MWAN Detailed Status%></legend>
+ <div id="mwan_detail_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan_detail_status {
+ border: 1px dotted #555555;
+ background-color: #FFFFFF;
+ padding: 20px;
+ }
+ #mwan_detail_text {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
--- /dev/null
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/overview")%>"><%:Interface Status%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan/overview/overview_detailed")%>"><%:Detailed Status%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan", "overview", "interface_status")%>', null,
+ function(x, mArray)
+ {
+ var statusDiv = document.getElementById('mwan_status_text');
+ if (mArray.wans)
+ {
+ var interfaceStatus = '';
+ for( var i = 0; i < mArray.wans.length; i++ )
+ {
+ var status = '';
+ var css = '';
+ switch (mArray.wans[i].status)
+ {
+ case 'online':
+ status = 'Online (tracking active)';
+ css = 'wanon';
+ break;
+ case 'notMonitored':
+ status = 'Online (tracking off)';
+ css = 'wanon';
+ break;
+ case 'offline':
+ status = 'Offline';
+ css = 'wanoff';
+ break;
+ case 'notEnabled':
+ status = 'Disabled';
+ css = 'wanoff';
+ break;
+ }
+ interfaceStatus += String.format(
+ '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
+ css, mArray.wans[i].name, mArray.wans[i].link, mArray.wans[i].ifname, status
+ );
+ }
+ statusDiv.innerHTML = interfaceStatus;
+ }
+ else
+ {
+ statusDiv.innerHTML = '<strong>No MWAN interfaces found</strong>';
+ }
+
+ var logs = document.getElementById('mwan_statuslog_text');
+ if (mArray.mwanlog)
+ {
+ var mwanLog = 'Last 50 MWAN systemlog entries. Newest entries sorted at the top :';
+ logs.innerHTML = String.format('<pre>%s<br /><br />%s</pre>', mwanLog, mArray.mwanlog[0]);
+ }
+ else
+ {
+ logs.innerHTML = '<strong>No MWAN systemlog history found</strong>';
+ }
+ }
+ );
+//]]></script>
+
+<div id="mwan_interface_status">
+ <fieldset id="interface_field" class="cbi-section">
+ <legend><%:MWAN Interface Live Status%></legend>
+ <div id="mwan_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+ <fieldset class="cbi-section">
+ <legend><%:MWAN Interface Systemlog%></legend>
+ <div id="mwan_statuslog_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /* container for entire page. fixes bootstrap theme's ridiculously small page width */
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan_interface_status {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #interface_field {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwan_status_text {
+ display: table;
+ font-size: 14px;
+ margin: auto;
+ max-width: 1044px;
+ min-width: 246px;
+ width: 100%;
+ }
+ .wanon {
+ background-color: rgb(144, 240, 144);
+ }
+ .wanoff {
+ background-color: rgb(240, 144, 144);
+ }
+ .wanon, .wanoff {
+ border-radius: 60px;
+ box-shadow: 0px 2px 5px -3px;
+ float: left;
+ margin: 8px 3px 0px 3px;
+ min-height: 30px;
+ min-width: 235px;
+ padding: 5px 10px 8px 10px;
+ text-align: center;
+ }
+ #mwan_statuslog_text {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
+++ /dev/null
-<%+header%>
-
-<ul class="cbi-tabmenu">
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
-</ul>
-
-<%
- local uci = require "luci.model.uci"
-
- str = ""
- uci.cursor():foreach("mwan3", "interface",
- function (section)
- str = str .. section[".name"] .. " "
- end
- )
-%>
-
-<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-<script type="text/javascript">//<![CDATA[
- var stxhr = new XHR();
-
- function update_status(tool, alt)
- {
- var iface = document.getElementById('mwan3iface').value;
- var output = document.getElementById('diag_output');
-
- if (tool == "service")
- {
- output.innerHTML =
- '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
- "Waiting for MWAN3 to " + alt + "..."
- ;
- }
- else
- {
- output.innerHTML =
- '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
- "Waiting for diagnostic results..."
- ;
- }
-
- output.parentNode.style.display = 'block';
- output.style.display = 'inline';
-
- stxhr.get('<%=luci.dispatcher.build_url("admin", "network", "mwan3", "advanced")%>/diag_display' + '/' + iface + '/' + tool + '/' + alt, null,
- function(x, st)
- {
- if (st.diagres)
- {
- output.innerHTML = String.format('<pre id="diag_output_css">%h</pre>', st.diagres[0].diagresult);
- }
- else
- {
- var temp = '';
- var ncint = 'No diagnostic results returned';
- temp = String.format('<pre id="diag_output_css"><strong>%s</strong></pre>', ncint);
- output.innerHTML = temp;
- }
- }
- );
- }
-//]]></script>
-
-<div id="mwan3_diagnostics" class="cbi-map">
- <fieldset id="diag_select" class="cbi-section">
- <legend><%:MWAN3 Interface Diagnostics%></legend>
- <select id="mwan3iface">
- <% for z in str:gmatch("[^ ]+") do -%><option value="<%=z%>"><%=z%></option><%- end %>
- </select>
- <div id="buttoncss">
- <input type="button" value="<%:Ping default gateway%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'gateway')" />
- <input type="button" value="<%:Ping tracking IP%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'track_ip')" />
- <input type="button" value="<%:Check IP rules%>" class="cbi-button cbi-button-apply" onclick="update_status('rulechk', null)" />
- <input type="button" value="<%:Check routing table%>" class="cbi-button cbi-button-apply" onclick="update_status('routechk', null)" />
- <input type="button" value="<%:Hotplug ifup%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifup')" />
- <input type="button" value="<%:Hotplug ifdown%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifdown')" />
- </div>
- </fieldset>
- <fieldset id="diag_select" class="cbi-section">
- <legend><%:MWAN3 Service Control%></legend>
- <div id="buttoncss">
- <input type="button" value="<%:Restart MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'restart')" />
- <input type="button" value="<%:Stop MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'stop')" />
- <input type="button" value="<%:Start MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'start')" />
- </div>
- </fieldset>
- <fieldset class="cbi-section" style="display:none">
- <legend><%:Diagnostic Results%></legend>
- <div id="diag_output"></div>
- </fieldset>
-</div>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin-left: 30px;
- padding-right: 30px;
- width: auto;
- }
- #mwan3_diagnostics {
- background-color: #FFFFFF;
- border: 1px dotted #555555;
- padding: 20px;
- }
- #diag_select {
- padding: 12px 20px 20px 20px;
- }
- #mwan3iface {
- float: left;
- margin: 8px 20px 0px 0px;
- }
- #buttoncss {
- display: table;
- float: left;
- text-align: left;
- }
- .cbi-button {
- margin: 8px 20px 0px 0px;
- min-width: 153px;
- }
- #diag_output_css {
- padding: 20px;
- text-align: left;
- }
-</style>
-
-<%+footer%>
+++ /dev/null
-<ul class="cbi-tabmenu">
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
-</ul>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin: 0px 0px 0px 30px;
- padding-right: 30px;
- width: auto;
- }
- .cbi-section-node {
- margin-top: 20px;
- }
- .cbi-section {
- border: 1px dotted #555555;
- padding: 20px;
- }
-</style>
+++ /dev/null
-<ul class="cbi-tabmenu">
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
-</ul>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin: 0px 0px 0px 30px;
- padding-right: 30px;
- width: auto;
- }
- .cbi-section-node {
- margin-top: 20px;
- }
- .cbi-section {
- border: 1px dotted #555555;
- padding: 20px;
- }
-</style>
+++ /dev/null
-<ul class="cbi-tabmenu">
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
-</ul>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin: 0px 0px 0px 30px;
- padding-right: 30px;
- width: auto;
- }
- .cbi-section-node {
- margin-top: 20px;
- }
- .cbi-section {
- border: 1px dotted #555555;
- padding: 20px;
- }
-</style>
+++ /dev/null
-<%+header%>
-
-<ul class="cbi-tabmenu">
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
-</ul>
-
-<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-<script type="text/javascript">//<![CDATA[
- XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "advanced", "tshoot_display")%>', null,
- function(x, st)
- {
- var tx = document.getElementById('mwan3_tshoot_text');
- if (st.mw3ver)
- {
- var temp = '';
- var mwanvers = 'Software versions : <br /><br />';
- var mwan3cnfg = '<br /><br />Output of "cat /etc/config/mwan3" : <br /><br />';
- var netcnfg = '<br /><br />Output of "cat /etc/config/network" : <br /><br />';
- var ifcnfg = '<br /><br />Output of "ifconfig" : <br /><br />';
- var iproute = '<br /><br />Output of "route -n" : <br /><br />';
- var iprulesh = '<br /><br />Output of "ip rule show" : <br /><br />';
- var routelisttbl = '<br /><br />Output of "ip route list table 1-250" : <br /><br />';
- var firewalldef = '<br /><br />Firewall default output policy (must be ACCEPT) : <br /><br />';
- var iptable = '<br /><br />Output of "iptables -L -t mangle -v -n" : <br /><br />';
-
- temp = String.format(
- '<pre><span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s</pre>',
- mwanvers, st.mw3ver[0].mwan3v, mwan3cnfg, st.mwan3config[0].mwn3cfg, netcnfg, st.netconfig[0].netcfg, ifcnfg, st.ifconfig[0].ifcfg, iproute, st.rtshow[0].iprtshow, iprulesh, st.iprule[0].rule, routelisttbl, st.routelist[0].iprtlist, firewalldef, st.fidef[0].firedef, iptable, st.iptables[0].iptbls
- );
- tx.innerHTML = temp;
- }
- else
- {
- var temp = '';
- var terror = 'Error collecting troubleshooting information';
- temp = String.format('<strong>%s</strong>', terror);
- tx.innerHTML = temp;
- }
- }
- );
-//]]></script>
-
-<div id="tshoot_div">
- <fieldset class="cbi-section">
- <legend><%:Troubleshooting Data%></legend>
- <div id="mwan3_tshoot_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
- </fieldset>
-</div>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin-left: 30px;
- padding-right: 30px;
- width: auto;
- }
- #tshoot_div {
- background-color: #FFFFFF;
- border: 1px dotted #555555;
- padding: 20px;
- }
- #mwan3_tshoot_text {
- padding: 20px;
- text-align: left;
- }
- .tsht {
- background-color: rgb(78, 186, 241);
- }
-</style>
-
-<%+footer%>
+++ /dev/null
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin-left: 30px;
- padding-right: 30px;
- width: auto;
- }
- table td { /*cells showing the configuration values*/
- padding: 0px;
- text-align: center;
- vertical-align: middle;
- }
- table th { /*column for configuration section name*/
- padding: 0px;
- text-align: center;
- vertical-align: middle;
- }
- table tbody th { /*column for configuration section name*/
- padding: 0px;
- vertical-align: middle;
- }
- .cbi-section-node table div { /*rows*/
- padding-top: 5px;
- }
- table.cbi-section-table td.cbi-section-table-cell { /*sort buttons column*/
- text-align: center;
- }
- .cbi-section h3 {
- color: rgb(85, 85, 85);
- font-family: Trebuchet MS,Verdana,sans-serif;
- font-style: italic;
- font-weight: normal;
- }
-</style>
+++ /dev/null
-<%+header%>
-
-<ul class="cbi-tabmenu">
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview")%>"><%:Interface Status%></a></li>
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview/over_detail")%>"><%:Detailed Status%></a></li>
-</ul>
-
-<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-<script type="text/javascript">//<![CDATA[
- XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "detail_status")%>', null,
- function(x, st)
- {
- var tx = document.getElementById('mwan3_detail_text');
- if (st.mwan3dst)
- {
- var temp = '';
- temp = String.format('<pre>%s</pre>', st.mwan3dst[0].detailstat);
- tx.innerHTML = temp;
- }
- else
- {
- var temp = '';
- var nslg = 'No detailed status information available';
- temp = String.format('<strong>%s</strong>', nslg);
- tx.innerHTML = temp;
- }
- }
- );
-//]]></script>
-
-<div id="mwan3_detail_status">
- <fieldset class="cbi-section">
- <legend><%:MWAN3 Multi-WAN Detailed Status%></legend>
- <div id="mwan3_detail_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
- </fieldset>
-</div>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin-left: 30px;
- padding-right: 30px;
- width: auto;
- }
- #mwan3_detail_status {
- border: 1px dotted #555555;
- background-color: #FFFFFF;
- padding: 20px;
- }
- #mwan3_detail_text {
- padding: 20px;
- text-align: left;
- }
-</style>
-
-<%+footer%>
+++ /dev/null
-<%+header%>
-
-<ul class="cbi-tabmenu">
- <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview")%>"><%:Interface Status%></a></li>
- <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview/over_detail")%>"><%:Detailed Status%></a></li>
-</ul>
-
-<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
-<script type="text/javascript">//<![CDATA[
- XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "iface_status")%>', null,
- function(x, st)
- {
- var tx = document.getElementById('mwan3_status_text');
- if (st.wans)
- {
- var temp = '';
-
- for( var i = 0; i < st.wans.length; i++ )
- {
- var stat = '';
- var cssc = '';
-
- switch (st.wans[i].status)
- {
- case 'on':
- stat = 'Online (tracking active)';
- cssc = 'wanon';
- break;
-
- case 'nm':
- stat = 'Online (tracking off)';
- cssc = 'wanon';
- break;
-
- case 'off':
- stat = 'Offline';
- cssc = 'wanoff';
- break;
-
- case 'ne':
- stat = 'Disabled';
- cssc = 'wanoff';
- break;
- }
-
- temp += String.format(
- '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
- cssc, st.wans[i].name, st.wans[i].link, st.wans[i].ifname, stat
- );
- }
- tx.innerHTML = temp;
- }
- else
- {
- var temp = '';
- var ncint = 'No MWAN3 interfaces found';
- temp = String.format('<strong>%s</strong>', ncint);
- tx.innerHTML = temp;
- }
-
- var tx = document.getElementById('mwan3_statuslog_text');
- if (st.mwan3log)
- {
- var temp = '';
- var mwan3lg = 'Last 50 MWAN3 systemlog entries. Newest entries sorted at the top :';
- temp = String.format('<pre>%s<br /><br />%s</pre>', mwan3lg, st.mwan3log[0].mwanlog);
- tx.innerHTML = temp;
- }
- else
- {
- var temp = '';
- var nslg = 'No MWAN3 systemlog history found';
- temp = String.format('<strong>%s</strong>', nslg);
- tx.innerHTML = temp;
- }
- }
- );
-//]]></script>
-
-<div id="mwan3_interface_status">
- <fieldset id="interface_field" class="cbi-section">
- <legend><%:MWAN3 Multi-WAN Interface Live Status%></legend>
- <div id="mwan3_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
- </fieldset>
- <fieldset class="cbi-section">
- <legend><%:MWAN3 Multi-WAN Interface Systemlog%></legend>
- <div id="mwan3_statuslog_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
- </fieldset>
-</div>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: none;
- margin-left: 30px;
- padding-right: 30px;
- width: auto;
- }
- #mwan3_interface_status {
- background-color: #FFFFFF;
- border: 1px dotted #555555;
- padding: 20px;
- }
- #interface_field {
- padding: 12px 20px 20px 20px;
- }
- #mwan3_status_text {
- display: table;
- font-size: 14px;
- margin: auto;
- max-width: 1044px;
- min-width: 246px;
- width: 100%;
- }
- .wanon {
- background-color: rgb(144, 240, 144);
- }
- .wanoff {
- background-color: rgb(240, 144, 144);
- }
- .wanon, .wanoff {
- border-radius: 60px;
- box-shadow: 0px 2px 5px -3px;
- float: left;
- margin: 8px 3px 0px 3px;
- min-height: 30px;
- min-width: 235px;
- padding: 5px 10px 8px 10px;
- text-align: center;
- }
- #mwan3_statuslog_text {
- padding: 20px;
- text-align: left;
- }
-</style>
-
-<%+footer%>
+++ /dev/null
-<script type="text/javascript">//<![CDATA[
- XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "iface_status")%>', null,
- function(x, st)
- {
- var tx = document.getElementById('mwan3_status_text');
- if (st.wans)
- {
- var temp = '';
-
- for( var i = 0; i < st.wans.length; i++ )
- {
- var stat = '';
- var cssc = '';
-
- switch (st.wans[i].status)
- {
- case 'on':
- stat = 'Online (tracking active)';
- cssc = 'wanon';
- break;
-
- case 'nm':
- stat = 'Online (tracking off)';
- cssc = 'wanon';
- break;
-
- case 'off':
- stat = 'Offline';
- cssc = 'wanoff';
- break;
-
- case 'ne':
- stat = 'Disabled';
- cssc = 'wanoff';
- break;
- }
-
- temp += String.format(
- '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
- cssc, st.wans[i].name, st.wans[i].link, st.wans[i].ifname, stat
- );
- }
- tx.innerHTML = temp;
- }
- else
- {
- var temp = '';
- var ncint = 'No MWAN3 interfaces found';
- temp += String.format('<strong>%s</strong>', ncint );
- tx.innerHTML = temp;
- }
- }
- );
-//]]></script>
-
-<fieldset id="interface_field" class="cbi-section">
- <legend><%:MWAN3 Multi-WAN Interface Live Status%></legend>
- <div id="mwan3_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
-</fieldset>
-
-<style type="text/css">
- .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
- max-width: 1044px;
- }
- #interface_field {
- padding: 12px 20px 20px 20px;
- }
- #mwan3_status_text {
- display: table;
- font-size: 14px;
- margin: auto;
- max-width: 1044px;
- min-width: 246px;
- width: 100%;
- }
- .wanon {
- background-color: rgb(144, 240, 144);
- }
- .wanoff {
- background-color: rgb(240, 144, 144);
- }
- .wanon, .wanoff {
- border-radius: 60px;
- box-shadow: 0px 2px 5px -3px;
- float: left;
- margin: 8px 3px 0px 3px;
- min-height: 30px;
- min-width: 235px;
- padding: 5px 10px 8px 10px;
- text-align: center;
- }
-</style>