summaryrefslogtreecommitdiffhomepage
path: root/applications
diff options
context:
space:
mode:
Diffstat (limited to 'applications')
-rw-r--r--applications/luci-app-adblock/Makefile9
-rw-r--r--applications/luci-app-adblock/luasrc/controller/adblock.lua47
-rw-r--r--applications/luci-app-adblock/luasrc/model/cbi/adblock.lua63
-rw-r--r--applications/luci-app-adblock/luasrc/model/cbi/adblock/blacklist_tab.lua39
-rw-r--r--applications/luci-app-adblock/luasrc/model/cbi/adblock/configuration_tab.lua36
-rw-r--r--applications/luci-app-adblock/luasrc/model/cbi/adblock/overview_tab.lua128
-rw-r--r--applications/luci-app-adblock/luasrc/model/cbi/adblock/whitelist_tab.lua39
-rw-r--r--applications/luci-app-adblock/luasrc/view/adblock/config_css.htm10
-rw-r--r--applications/luci-app-adblock/luasrc/view/adblock/logread.htm15
-rw-r--r--applications/luci-app-adblock/luasrc/view/adblock/query.htm66
-rw-r--r--applications/luci-app-adblock/luasrc/view/adblock/runtime.htm11
-rw-r--r--applications/luci-app-adblock/po/ja/adblock.po224
-rw-r--r--applications/luci-app-adblock/po/pt-br/adblock.po186
-rw-r--r--applications/luci-app-adblock/po/sv/adblock.po143
-rw-r--r--applications/luci-app-adblock/po/templates/adblock.pot118
-rw-r--r--applications/luci-app-adblock/po/zh-cn/adblock.po164
-rw-r--r--applications/luci-app-clamav/po/ja/clamav.po130
-rw-r--r--applications/luci-app-clamav/po/templates/clamav.pot119
-rw-r--r--applications/luci-app-cshark/Makefile17
-rw-r--r--applications/luci-app-cshark/luasrc/controller/cshark.lua125
-rw-r--r--applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua30
-rw-r--r--applications/luci-app-cshark/luasrc/view/cshark.htm291
-rw-r--r--applications/luci-app-mwan3/Makefile19
-rw-r--r--applications/luci-app-mwan3/luasrc/controller/mwan3.lua331
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_hotplugscript.lua55
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_mwanconfig.lua32
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_networkconfig.lua32
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_wirelessconfig.lua32
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua266
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua250
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/member.lua46
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/memberconfig.lua47
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua95
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/policyconfig.lua65
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua141
-rw-r--r--applications/luci-app-mwan3/luasrc/model/cbi/mwan/ruleconfig.lua113
-rw-r--r--applications/luci-app-mwan3/luasrc/view/admin_status/index/mwan.htm1
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_diagnostics.htm129
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_hotplugscript.htm24
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_mwanconfig.htm24
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_networkconfig.htm24
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_troubleshooting.htm74
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/advanced_wirelessconfig.htm24
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/config_css.htm34
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/openwrt_overview_status.htm83
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/overview_detailed.htm51
-rw-r--r--applications/luci-app-mwan3/luasrc/view/mwan/overview_interface.htm122
-rw-r--r--applications/luci-app-mwan3/po/ja/mwan3.po519
-rw-r--r--applications/luci-app-mwan3/po/templates/mwan3.pot395
-rwxr-xr-xapplications/luci-app-mwan3/root/etc/hotplug.d/iface/16-mwancustombak38
-rwxr-xr-xapplications/luci-app-mwan3/root/etc/uci-defaults/60_luci-mwan314
-rw-r--r--applications/luci-app-simple-adblock/Makefile16
-rw-r--r--applications/luci-app-simple-adblock/luasrc/controller/simpleadblock.lua7
-rw-r--r--applications/luci-app-simple-adblock/luasrc/model/cbi/simpleadblock.lua79
-rw-r--r--applications/luci-app-simple-adblock/po/ja/simple-adblock.po93
-rw-r--r--applications/luci-app-simple-adblock/po/templates/simple-adblock.pot80
-rw-r--r--applications/luci-app-simple-adblock/root/etc/uci-defaults/40_luci-simple-adblock10
-rw-r--r--applications/luci-app-vpnbypass/po/pt-br/vpnbypass.po7
58 files changed, 5194 insertions, 188 deletions
diff --git a/applications/luci-app-adblock/Makefile b/applications/luci-app-adblock/Makefile
index 8efe2d6048..614faf0e83 100644
--- a/applications/luci-app-adblock/Makefile
+++ b/applications/luci-app-adblock/Makefile
@@ -1,7 +1,6 @@
-# Copyright (C) 2016 Openwrt.org
-#
-# This is free software, licensed under the Apache License, Version 2.0 .
-#
+# Copyright 2016 Hannu Nyman
+# Copyright 2017 Dirk Brenken (dev@brenken.org)
+# This is free software, licensed under the Apache License, Version 2.0
include $(TOPDIR)/rules.mk
@@ -11,4 +10,4 @@ LUCI_PKGARCH:=all
include ../../luci.mk
-# call BuildPackage - OpenWrt buildroot signature
+# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file
diff --git a/applications/luci-app-adblock/luasrc/controller/adblock.lua b/applications/luci-app-adblock/luasrc/controller/adblock.lua
index d8b471814f..bcb2976033 100644
--- a/applications/luci-app-adblock/luasrc/controller/adblock.lua
+++ b/applications/luci-app-adblock/luasrc/controller/adblock.lua
@@ -1,12 +1,53 @@
--- Copyright 2016 Openwrt.org
--- Licensed to the public under the Apache License 2.0.
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
module("luci.controller.adblock", package.seeall)
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local template = require("luci.template")
+local i18n = require("luci.i18n")
+
function index()
if not nixio.fs.access("/etc/config/adblock") then
return
end
+ entry({"admin", "services", "adblock"}, firstchild(), _("Adblock"), 30).dependent = false
+ entry({"admin", "services", "adblock", "tab_from_cbi"}, cbi("adblock/overview_tab"), _("Overview"), 10).leaf = true
+ entry({"admin", "services", "adblock", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true
+ entry({"admin", "services", "adblock", "advanced"}, firstchild(), _("Advanced"), 100)
+ entry({"admin", "services", "adblock", "advanced", "blacklist"}, cbi("adblock/blacklist_tab"), _("Edit Blacklist"), 110).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "whitelist"}, cbi("adblock/whitelist_tab"), _("Edit Whitelist"), 120).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "configuration"}, cbi("adblock/configuration_tab"), _("Edit Configuration"), 130).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "query"}, call("query"), _("Query domains"), 140).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "result"}, call("queryData"), nil, 150).leaf = true
+end
+
+function logread()
+ local logfile = util.trim(util.exec("logread -e 'adblock'"))
+ template.render("adblock/logread", {title = i18n.translate("Adblock Logfile"), content = logfile})
+end
- entry({"admin", "services", "adblock"}, cbi("adblock"), _("Adblock"), 40)
+function query()
+ template.render("adblock/query", {title = i18n.translate("Adblock Domain Query")})
+end
+
+function queryData(domain)
+ if domain and domain:match("^[a-zA-Z0-9%-%._]+$") then
+ luci.http.prepare_content("text/plain")
+ local cmd = "/etc/init.d/adblock query %q 2>&1"
+ local util = io.popen(cmd % domain)
+ if util then
+ while true do
+ local line = util:read("*l")
+ if not line then
+ break
+ end
+ luci.http.write(line)
+ luci.http.write("\n")
+ end
+ util:close()
+ end
+ end
end
diff --git a/applications/luci-app-adblock/luasrc/model/cbi/adblock.lua b/applications/luci-app-adblock/luasrc/model/cbi/adblock.lua
deleted file mode 100644
index 0a4a4cdd2f..0000000000
--- a/applications/luci-app-adblock/luasrc/model/cbi/adblock.lua
+++ /dev/null
@@ -1,63 +0,0 @@
--- Copyright 2016 Hannu Nyman
--- Licensed to the public under the Apache License 2.0.
-
-m = Map("adblock", translate("Adblock"),
- translate("Configuration of the adblock package to block ad/abuse domains by using DNS."))
-
--- General options
-
-s = m:section(NamedSection, "global", "adblock", translate("Global options"))
-
-o1 = s:option(Flag, "adb_enabled", translate("Enable adblock"))
-o1.rmempty = false
-o1.default = 0
-
-o3 = s:option(Value, "adb_whitelist", translate("Whitelist file"),
- translate("File with whitelisted hosts/domains that are allowed despite being on a blocklist."))
-o3.rmempty = false
-o3.datatype = "file"
-
--- Blocklist options
-
-bl = m:section(TypedSection, "source", translate("Blocklist sources"),
- translate("Available blocklist sources (")
- .. [[<a href="https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md" target="_blank">]]
- .. translate("see list details")
- .. [[</a>]]
- .. translate("). Note that list URLs and Shallalist category selections are not configurable via Luci."))
-bl.template = "cbi/tblsection"
-
-name = bl:option(Flag, "enabled", translate("Enabled"))
-name.rmempty = false
-
-des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
-
--- Additional options
-
-s2 = m:section(NamedSection, "global", "adblock", translate("Backup options"))
-
-o4 = s2:option(Flag, "adb_backup", translate("Enable blocklist backup"))
-o4.rmempty = false
-o4.default = 0
-
-o5 = s2:option(Value, "adb_backupdir", translate("Backup directory"))
-o5.rmempty = false
-o5.datatype = "directory"
-
--- Extra options
-
-e = m:section(NamedSection, "global", "adblock", translate("Extra options"),
- translate("Options for further tweaking in case the defaults are not suitable for you."))
-
-a = e:option(Flag, "adb_debug", translate("Enable verbose debug logging"))
-a.default = a.disabled
-a.rmempty = false
-
-a = e:option(Value, "adb_iface", translate("Restrict reload trigger to certain interface(s)"),
- translate("Space separated list of wan interfaces that trigger reload action. " ..
- "To disable reload trigger set it to 'false'. Default: empty"))
-a.datatype = "network"
-a.rmempty = true
-
-return m
-
diff --git a/applications/luci-app-adblock/luasrc/model/cbi/adblock/blacklist_tab.lua b/applications/luci-app-adblock/luasrc/model/cbi/adblock/blacklist_tab.lua
new file mode 100644
index 0000000000..efe40e09e5
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/model/cbi/adblock/blacklist_tab.lua
@@ -0,0 +1,39 @@
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local uci = require("uci")
+local adbinput = uci.get("adblock", "blacklist", "adb_src")
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+ translatef("This form allows you to modify the content of the adblock blacklist (%s).<br />", adbinput)
+ .. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards and regex are not."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.datatype = "string"
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
diff --git a/applications/luci-app-adblock/luasrc/model/cbi/adblock/configuration_tab.lua b/applications/luci-app-adblock/luasrc/model/cbi/adblock/configuration_tab.lua
new file mode 100644
index 0000000000..035b99e5e3
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/model/cbi/adblock/configuration_tab.lua
@@ -0,0 +1,36 @@
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local adbinput = "/etc/config/adblock"
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+translate("This form allows you to modify the content of the main adblock configuration file (/etc/config/adblock)."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
diff --git a/applications/luci-app-adblock/luasrc/model/cbi/adblock/overview_tab.lua b/applications/luci-app-adblock/luasrc/model/cbi/adblock/overview_tab.lua
new file mode 100644
index 0000000000..b8318fe994
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/model/cbi/adblock/overview_tab.lua
@@ -0,0 +1,128 @@
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local sys = require("luci.sys")
+local util = require("luci.util")
+local data = util.ubus("service", "get_data", "name", "adblock") or { }
+local dnsFile1 = sys.exec("find '/tmp/dnsmasq.d' -maxdepth 1 -type f -name 'adb_list*' -print 2>/dev/null")
+local dnsFile2 = sys.exec("find '/var/lib/unbound' -maxdepth 1 -type f -name 'adb_list*' -print 2>/dev/null")
+
+m = Map("adblock", translate("Adblock"),
+ translate("Configuration of the adblock package to block ad/abuse domains by using DNS. ")
+ .. translate("For further information ")
+ .. [[<a href="https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md" target="_blank">]]
+ .. translate("see online documentation")
+ .. [[</a>]]
+ .. translate("."))
+
+-- Main adblock options
+
+s = m:section(NamedSection, "global", "adblock")
+
+o1 = s:option(Flag, "adb_enabled", translate("Enable adblock"))
+o1.rmempty = false
+o1.default = 0
+
+btn = s:option(Button, "", translate("Suspend / Resume adblock"))
+if data.adblock == nil then
+ btn.inputtitle = "n/a"
+ btn.inputstyle = nil
+ btn.disabled = true
+elseif dnsFile1 ~= "" or dnsFile2 ~= "" then
+ btn.inputtitle = translate("Suspend adblock")
+ btn.inputstyle = "reset"
+ btn.disabled = false
+ function btn.write()
+ luci.sys.call("/etc/init.d/adblock suspend >/dev/null 2>&1")
+ end
+else
+ btn.inputtitle = translate("Resume adblock")
+ btn.inputstyle = "apply"
+ btn.disabled = false
+ function btn.write()
+ luci.sys.call("/etc/init.d/adblock resume >/dev/null 2>&1")
+ end
+end
+
+o2 = s:option(Flag, "adb_debug", translate("Enable verbose debug logging"))
+o2.default = o2.disabled
+o2.rmempty = false
+
+o3 = s:option(Value, "adb_iface", translate("Restrict interface reload trigger to certain interface(s)"),
+ translate("Space separated list of interfaces that trigger a reload action. "..
+ "To disable reload trigger at all remove all entries."))
+o3.rmempty =true
+
+-- Runtime information
+
+ ds = s:option(DummyValue, "_dummy", translate("Runtime information"))
+ ds.template = "cbi/nullsection"
+
+ dv1 = s:option(DummyValue, "adblock_version", translate("Adblock version"))
+ dv1.template = "adblock/runtime"
+ if data.adblock ~= nil then
+ dv1.value = data.adblock.adblock.adblock_version or "n/a"
+ else
+ dv1.value = "n/a"
+ end
+
+ dv2 = s:option(DummyValue, "status", translate("Status"))
+ dv2.template = "adblock/runtime"
+ if data.adblock == nil then
+ dv2.value = "n/a"
+ elseif dnsFile1 ~= "" or dnsFile2 ~= "" then
+ dv2.value = "active"
+ else
+ dv2.value = "suspended"
+ end
+
+ dv3 = s:option(DummyValue, "dns_backend", translate("DNS backend"))
+ dv3.template = "adblock/runtime"
+ if data.adblock ~= nil then
+ dv3.value = data.adblock.adblock.dns_backend or "n/a"
+ else
+ dv3.value = "n/a"
+ end
+
+ dv4 = s:option(DummyValue, "blocked_domains", translate("Blocked domains (overall)"))
+ dv4.template = "adblock/runtime"
+ if data.adblock ~= nil then
+ dv4.value = data.adblock.adblock.blocked_domains or "n/a"
+ else
+ dv4.value = "n/a"
+ end
+
+ dv5 = s:option(DummyValue, "last_rundate", translate("Last rundate"))
+ dv5.template = "adblock/runtime"
+ if data.adblock ~= nil then
+ dv5.value = data.adblock.adblock.last_rundate or "n/a"
+ else
+ dv5.value = "n/a"
+ end
+
+-- Blocklist options
+
+bl = m:section(TypedSection, "source", translate("Blocklist sources"),
+ translate("Available blocklist sources. ")
+ .. translate("Note that list URLs and Shallalist category selections are configurable in the 'Advanced' section."))
+bl.template = "cbi/tblsection"
+
+name = bl:option(Flag, "enabled", translate("Enabled"))
+name.rmempty = false
+
+des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
+
+-- Backup options
+
+s = m:section(NamedSection, "global", "adblock", translate("Backup options"))
+
+o4 = s:option(Flag, "adb_backup", translate("Enable blocklist backup"))
+o4.rmempty = false
+o4.default = 0
+
+o5 = s:option(Value, "adb_backupdir", translate("Backup directory"))
+o5.rmempty = false
+o5.datatype = "directory"
+
+return m
diff --git a/applications/luci-app-adblock/luasrc/model/cbi/adblock/whitelist_tab.lua b/applications/luci-app-adblock/luasrc/model/cbi/adblock/whitelist_tab.lua
new file mode 100644
index 0000000000..6c4dee4676
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/model/cbi/adblock/whitelist_tab.lua
@@ -0,0 +1,39 @@
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local uci = require("uci")
+local adbinput = uci.get("adblock", "global", "adb_whitelist") or " "
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+ translatef("This form allows you to modify the content of the adblock whitelist (%s).<br />", adbinput)
+ .. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards and regex are not."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.datatype = "string"
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
diff --git a/applications/luci-app-adblock/luasrc/view/adblock/config_css.htm b/applications/luci-app-adblock/luasrc/view/adblock/config_css.htm
new file mode 100644
index 0000000000..53493a18fb
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/view/adblock/config_css.htm
@@ -0,0 +1,10 @@
+<style type="text/css">
+ textarea
+ {
+ border: 1px solid #cccccc;
+ padding: 5px;
+ font-size: 12px;
+ font-family: monospace;
+ resize: none;
+ }
+</style>
diff --git a/applications/luci-app-adblock/luasrc/view/adblock/logread.htm b/applications/luci-app-adblock/luasrc/view/adblock/logread.htm
new file mode 100644
index 0000000000..ce842a88e8
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/view/adblock/logread.htm
@@ -0,0 +1,15 @@
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+header%>
+
+<div class="cbi-map">
+ <fieldset class="cbi-section">
+ <div class="cbi-section-descr"><%:This form shows the syslog output, pre-filtered for adblock related messages only.%></div>
+ <textarea id="logread_id" style="width: 100%; height: 450px; border: 1px solid #cccccc; padding: 5px; font-size: 12px; font-family: monospace; resize: none;" readonly="readonly" wrap="off" rows="<%=content:cmatch("\n")+2%>"><%=content:pcdata()%></textarea>
+ </fieldset>
+</div>
+<%+footer%>
diff --git a/applications/luci-app-adblock/luasrc/view/adblock/query.htm b/applications/luci-app-adblock/luasrc/view/adblock/query.htm
new file mode 100644
index 0000000000..5e064af858
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/view/adblock/query.htm
@@ -0,0 +1,66 @@
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+header%>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">
+//<![CDATA[
+ var stxhr = new XHR();
+
+ function update_status(data)
+ {
+ var domain = data.value;
+ var input = document.getElementById('query_input');
+ var output = document.getElementById('query_output');
+
+ if (input && output)
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
+ '<%:Waiting for command to complete...%>'
+ ;
+ input.parentNode.style.display = 'block';
+ input.style.display = 'inline';
+ stxhr.post('<%=luci.dispatcher.build_url('admin/services/adblock/advanced/result/')%>' + domain, { token: '<%=token%>' },
+ function(x)
+ {
+ if (x.responseText)
+ {
+ input.style.display = 'none';
+ output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
+ }
+ else
+ {
+ input.style.display = 'none';
+ output.innerHTML = '<span class="error"><%:Invalid domain specified!%></span>';
+ }
+ }
+ );
+ }
+ }
+//]]>
+</script>
+
+<form method="post" action="<%=REQUEST_URI%>">
+ <div class="cbi-map">
+ <fieldset class="cbi-section">
+ <div class="cbi-section-descr"><%:This form allows you to query active block lists for certain domains, e.g. for whitelisting.%></div>
+ <div style="width:33%; float:left;">
+ <input style="margin: 5px 0" type="text" value="www.lede-project.org" name="input" />
+ <input type="button" value="<%:Query%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.input)" />
+ </div>
+ <br style="clear:both" />
+ <br />
+ </fieldset>
+ </div>
+ <fieldset class="cbi-section" style="display:none">
+ <legend id="query_input"><%:Collecting data...%></legend>
+ <span id="query_output"></span>
+ </fieldset>
+</form>
+
+<%+footer%>
diff --git a/applications/luci-app-adblock/luasrc/view/adblock/runtime.htm b/applications/luci-app-adblock/luasrc/view/adblock/runtime.htm
new file mode 100644
index 0000000000..4a90d41966
--- /dev/null
+++ b/applications/luci-app-adblock/luasrc/view/adblock/runtime.htm
@@ -0,0 +1,11 @@
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+cbi/valueheader%>
+
+<input name="runtime" id="runtime" type="text" class="cbi-input-text" style="border: none; box-shadow: none; background-color: #ffffff; color: #0069d6;" value="<%=self:cfgvalue(section)%>" disabled="disabled" />
+
+<%+cbi/valuefooter%>
diff --git a/applications/luci-app-adblock/po/ja/adblock.po b/applications/luci-app-adblock/po/ja/adblock.po
index f436f5cc2b..d37fa748cb 100644
--- a/applications/luci-app-adblock/po/ja/adblock.po
+++ b/applications/luci-app-adblock/po/ja/adblock.po
@@ -8,21 +8,29 @@ msgstr ""
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 1.8.12\n"
+"X-Generator: Poedit 2.0\n"
"Language: ja\n"
-msgid ""
-"). Note that list URLs and Shallalist category selections are not "
-"configurable via Luci."
-msgstr ""
-")。これらのリストのURLおよびshallaリストの選択済みカテゴリーは、Luciを通して"
-"設定することができません。"
+msgid "."
+msgstr "。"
msgid "Adblock"
msgstr "Adblock"
-msgid "Available blocklist sources ("
-msgstr "利用可能なブロックリスト提供元です("
+msgid "Adblock Domain Query"
+msgstr "Adblock ドメイン検索"
+
+msgid "Adblock Logfile"
+msgstr "Adblock ログファイル"
+
+msgid "Adblock version"
+msgstr "Adblock バージョン"
+
+msgid "Advanced"
+msgstr "詳細設定"
+
+msgid "Available blocklist sources."
+msgstr "利用可能なブロックリスト提供元です。"
msgid "Backup directory"
msgstr "バックアップ先 ディレクトリ"
@@ -30,20 +38,38 @@ msgstr "バックアップ先 ディレクトリ"
msgid "Backup options"
msgstr "バックアップ オプション"
+msgid "Blocked domains (overall)"
+msgstr "ブロック済みドメイン(全体)"
+
msgid "Blocklist sources"
msgstr "ブロックリスト提供元"
+msgid "Collecting data..."
+msgstr "データ収集中です..."
+
msgid ""
"Configuration of the adblock package to block ad/abuse domains by using DNS."
msgstr ""
-"DNSの利用によって広告/不正ドメインをブロックする、adblock パッケージの設定で"
+"DNS の利用によって広告/不正ドメインをブロックする、Adblock パッケージの設定で"
"す。"
+msgid "DNS backend"
+msgstr "DNS バックエンド"
+
msgid "Description"
msgstr "説明"
+msgid "Edit Blacklist"
+msgstr "ブラックリストの編集"
+
+msgid "Edit Configuration"
+msgstr "設定の編集"
+
+msgid "Edit Whitelist"
+msgstr "ホワイトリストの編集"
+
msgid "Enable adblock"
-msgstr "adblockの有効化"
+msgstr "Adblock の有効化"
msgid "Enable blocklist backup"
msgstr "ブロックリスト バックアップの有効化"
@@ -54,38 +80,174 @@ msgstr "詳細なデバッグ ログの有効化"
msgid "Enabled"
msgstr "有効"
-msgid "Extra options"
-msgstr "拡張設定"
+msgid "For further information"
+msgstr "詳細な情報は"
+
+msgid "Input file not found, please check your configuration."
+msgstr "入力ファイルが見つかりません。設定を確認してください。"
+
+msgid "Invalid domain specified!"
+msgstr "無効なドメインが指定されています!"
+
+msgid "Last rundate"
+msgstr "最終実行日時"
+
+msgid "Loading"
+msgstr "読込中"
+
+msgid ""
+"Note that list URLs and Shallalist category selections are configurable in "
+"the 'Advanced' section."
+msgstr ""
+"リストの URL 及び \"Shalla\" リストのカテゴリー設定は、'詳細設定' セクション"
+"で設定することができます。"
+
+msgid "Overview"
+msgstr "概要"
+
+msgid ""
+"Please add only one domain per line. Comments introduced with '#' are "
+"allowed - ip addresses, wildcards and regex are not."
+msgstr ""
+"1行に1つのドメインを追加してください。'#' から始まるコメントを記述できます"
+"が、IP アドレスやワイルドカード、正規表現を設定値として使用することはできませ"
+"ん。"
+
+msgid "Query"
+msgstr "検索"
+
+msgid "Query domains"
+msgstr "ドメインの検索"
+
+msgid "Restrict interface reload trigger to certain interface(s)"
+msgstr "リロード トリガを特定のインターフェースに限定する"
+
+msgid "Resume adblock"
+msgstr "Adblock の再開"
+
+msgid "Runtime information"
+msgstr "実行情報"
+
+msgid ""
+"Space separated list of interfaces that trigger a reload action. To disable "
+"reload trigger at all remove all entries."
+msgstr ""
+"リロードのトリガとなる、スペースで区切られたインターフェースのリストです。リ"
+"ロード トリガを無効にするには、全てのエントリーを削除して空欄にします。"
+
+msgid "Status"
+msgstr "ステータス"
+
+msgid "Suspend / Resume adblock"
+msgstr "Adblock の一時停止/再開"
+
+msgid "Suspend adblock"
+msgstr "Adblock の一時停止"
msgid ""
-"File with whitelisted hosts/domains that are allowed despite being on a "
-"blocklist."
+"This form allows you to modify the content of the adblock blacklist (%s)."
+"<br />"
msgstr ""
-"ホワイトリスト ファイル内のホスト/ドメインは、ブロックリストの登録に関わらず"
-"許可されます。"
+"このフォームでは、Adblock ブラックリスト (%s) の内容を変更することができま"
+"す。<br />"
-msgid "Global options"
-msgstr "一般設定"
+msgid ""
+"This form allows you to modify the content of the adblock whitelist (%s)."
+"<br />"
+msgstr ""
+"このフォームでは、Adblock ホワイトリスト (%s) の内容を変更することができま"
+"す。<br />"
msgid ""
-"Options for further tweaking in case the defaults are not suitable for you."
-msgstr "デフォルト設定が適切でない場合、追加で設定するためのオプションです。"
+"This form allows you to modify the content of the main adblock configuration "
+"file (/etc/config/adblock)."
+msgstr ""
+"このフォームでは、メインのAdblock 設定ファイル (/etc/config/adblock) の内容を"
+"変更することができます。"
-msgid "Restrict reload trigger to certain interface(s)"
-msgstr "リロードトリガを特定のインターフェースに限定する"
+msgid ""
+"This form allows you to query active block lists for certain domains, e.g. "
+"for whitelisting."
+msgstr ""
+"このフォームでは、現在有効なリスト内で特定のドメインを検索することができま"
+"す。例: ホワイトリスト内"
msgid ""
-"Space separated list of wan interfaces that trigger reload action. To "
-"disable reload trigger set it to 'false'. Default: empty"
+"This form shows the syslog output, pre-filtered for adblock related messages "
+"only."
msgstr ""
-"リロード実行のトリガとなる、スペースで区切られたWANインターフェースのリストで"
-"す。リロードトリガを無効にするには、 false を設定します。デフォルト:(空)"
+"このフォームには、システムログ内の Adblock に関連するメッセージのみが表示され"
+"ます。"
+
+msgid "View Logfile"
+msgstr "ログファイルを見る"
+
+msgid "Waiting for command to complete..."
+msgstr "コマンドの完了をお待ちください..."
+
+msgid "see online documentation"
+msgstr "オンライン ドキュメントを確認してください"
+
+#~ msgid ""
+#~ "Space separated list of interfaces that trigger a reload action. To "
+#~ "disable reload trigger at all set it to 'false'."
+#~ msgstr ""
+#~ "リロードのトリガとなる、スペースで区切られたインターフェースのリストで"
+#~ "す。'false' に設定した場合、全てのリロード トリガは無効になります。"
+
+#~ msgid ""
+#~ "Please add only one domain per line. Comments introduced with '#' are "
+#~ "allowed - ip addresses, wildcards & regex are not."
+#~ msgstr ""
+#~ "一行に一つのドメインを追加してください。'#' から始まるコメントを記述できま"
+#~ "すが、IPアドレスやワイルドカード、正規表現を設定値として使用することはでき"
+#~ "ません。"
+
+#~ msgid ""
+#~ "). Note that list URLs and Shallalist category selections are not "
+#~ "configurable via Luci."
+#~ msgstr ""
+#~ ")。これらのリストのURLおよびshallaリストの選択済みカテゴリーは、Luciを通"
+#~ "して設定することができません。"
+
+#~ msgid "Available blocklist sources ("
+#~ msgstr "利用可能なブロックリスト提供元です("
+
+#~ msgid "Extra options"
+#~ msgstr "拡張設定"
+
+#~ msgid ""
+#~ "File with whitelisted hosts/domains that are allowed despite being on a "
+#~ "blocklist."
+#~ msgstr ""
+#~ "ホワイトリスト ファイル内のホスト/ドメインは、ブロックリストの登録に関わら"
+#~ "ず許可されます。"
+
+#~ msgid "Global options"
+#~ msgstr "一般設定"
+
+#~ msgid ""
+#~ "Options for further tweaking in case the defaults are not suitable for "
+#~ "you."
+#~ msgstr ""
+#~ "デフォルト設定が適切でない場合、追加で設定するためのオプションです。"
+
+#~ msgid "Restrict reload trigger to certain interface(s)"
+#~ msgstr "リロードトリガを特定のインターフェースに限定する"
+
+#~ msgid ""
+#~ "Space separated list of wan interfaces that trigger reload action. To "
+#~ "disable reload trigger set it to 'false'. Default: empty"
+#~ msgstr ""
+#~ "リロード実行のトリガとなる、スペースで区切られたWANインターフェースのリス"
+#~ "トです。リロードトリガを無効にするには、 false を設定します。デフォルト:"
+#~ "(空)"
-msgid "Whitelist file"
-msgstr "ホワイトリスト ファイル"
+#~ msgid "Whitelist file"
+#~ msgstr "ホワイトリスト ファイル"
-msgid "see list details"
-msgstr "リストの詳細を見る"
+#~ msgid "see list details"
+#~ msgstr "リストの詳細を見る"
#~ msgid "Count"
#~ msgstr "カウント"
diff --git a/applications/luci-app-adblock/po/pt-br/adblock.po b/applications/luci-app-adblock/po/pt-br/adblock.po
index a238dc7f94..32553277b2 100644
--- a/applications/luci-app-adblock/po/pt-br/adblock.po
+++ b/applications/luci-app-adblock/po/pt-br/adblock.po
@@ -12,18 +12,26 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: pt_BR\n"
-msgid ""
-"). Note that list URLs and Shallalist category selections are not "
-"configurable via Luci."
+msgid "."
msgstr ""
-"). Note que a lista de URL e as seleções de categoria da Shallalist não são "
-"configuráveis pelo Luci."
msgid "Adblock"
msgstr "Adblock"
-msgid "Available blocklist sources ("
-msgstr "Fontes de listas de bloqueio disponíveis ("
+msgid "Adblock Domain Query"
+msgstr ""
+
+msgid "Adblock Logfile"
+msgstr ""
+
+msgid "Adblock version"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Available blocklist sources."
+msgstr ""
msgid "Backup directory"
msgstr "Diretório da cópia de segurança"
@@ -31,18 +39,36 @@ msgstr "Diretório da cópia de segurança"
msgid "Backup options"
msgstr "Opções da cópia de segurança"
+msgid "Blocked domains (overall)"
+msgstr ""
+
msgid "Blocklist sources"
msgstr "Fontes de listas de bloqueio"
+msgid "Collecting data..."
+msgstr ""
+
msgid ""
"Configuration of the adblock package to block ad/abuse domains by using DNS."
msgstr ""
"Configuração do pacote adblock para bloquear, usando o DNS, domínios que "
"distribuem propagandas abusivas."
+msgid "DNS backend"
+msgstr ""
+
msgid "Description"
msgstr "Descrição"
+msgid "Edit Blacklist"
+msgstr ""
+
+msgid "Edit Configuration"
+msgstr ""
+
+msgid "Edit Whitelist"
+msgstr ""
+
msgid "Enable adblock"
msgstr "Habilitar adblock"
@@ -55,38 +81,140 @@ msgstr "Habilite registros detalhados para depuração"
msgid "Enabled"
msgstr "Habilitado"
-msgid "Extra options"
-msgstr "Opções adicionais"
+msgid "For further information"
+msgstr ""
+
+msgid "Input file not found, please check your configuration."
+msgstr ""
+
+msgid "Invalid domain specified!"
+msgstr ""
+
+msgid "Last rundate"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
msgid ""
-"File with whitelisted hosts/domains that are allowed despite being on a "
-"blocklist."
+"Note that list URLs and Shallalist category selections are configurable in "
+"the 'Advanced' section."
msgstr ""
-"Arquivo com a lista branca dos equipamentos/domínios que serão autorizados "
-"mesmo estando na lista de bloqueio."
-msgid "Global options"
-msgstr "Opções Globais"
+msgid "Overview"
+msgstr ""
msgid ""
-"Options for further tweaking in case the defaults are not suitable for you."
+"Please add only one domain per line. Comments introduced with '#' are "
+"allowed - ip addresses, wildcards and regex are not."
msgstr ""
-"Opções para aprimoramentos adicionais caso as opções padrão não sejam "
-"suficientes para você."
-msgid "Restrict reload trigger to certain interface(s)"
-msgstr "Restringir o gatilho de recarga para somente alguma(s) interface(s)"
+msgid "Query"
+msgstr ""
+
+msgid "Query domains"
+msgstr ""
+
+msgid "Restrict interface reload trigger to certain interface(s)"
+msgstr ""
+
+msgid "Resume adblock"
+msgstr ""
+
+msgid "Runtime information"
+msgstr ""
msgid ""
-"Space separated list of wan interfaces that trigger reload action. To "
-"disable reload trigger set it to 'false'. Default: empty"
+"Space separated list of interfaces that trigger a reload action. To disable "
+"reload trigger at all remove all entries."
+msgstr ""
+
+msgid "Status"
msgstr ""
-"Lista das interfaces WAN, separadas por espaço, que podem disparar uma ação "
-"de recarga. Para desabilitar este gatilho, defina-o como 'false'. Padrão: em "
-"branco"
-msgid "Whitelist file"
-msgstr "Arquivo da lista branca"
+msgid "Suspend / Resume adblock"
+msgstr ""
+
+msgid "Suspend adblock"
+msgstr ""
+
+msgid ""
+"This form allows you to modify the content of the adblock blacklist (%s)."
+"<br />"
+msgstr ""
+
+msgid ""
+"This form allows you to modify the content of the adblock whitelist (%s)."
+"<br />"
+msgstr ""
+
+msgid ""
+"This form allows you to modify the content of the main adblock configuration "
+"file (/etc/config/adblock)."
+msgstr ""
+
+msgid ""
+"This form allows you to query active block lists for certain domains, e.g. "
+"for whitelisting."
+msgstr ""
+
+msgid ""
+"This form shows the syslog output, pre-filtered for adblock related messages "
+"only."
+msgstr ""
+
+msgid "View Logfile"
+msgstr ""
+
+msgid "Waiting for command to complete..."
+msgstr ""
+
+msgid "see online documentation"
+msgstr ""
-msgid "see list details"
-msgstr "veja os detalhes da lista"
+#~ msgid ""
+#~ "). Note that list URLs and Shallalist category selections are not "
+#~ "configurable via Luci."
+#~ msgstr ""
+#~ "). Note que a lista de URL e as seleções de categoria da Shallalist não "
+#~ "são configuráveis pelo Luci."
+
+#~ msgid "Available blocklist sources ("
+#~ msgstr "Fontes de listas de bloqueio disponíveis ("
+
+#~ msgid "Extra options"
+#~ msgstr "Opções adicionais"
+
+#~ msgid ""
+#~ "File with whitelisted hosts/domains that are allowed despite being on a "
+#~ "blocklist."
+#~ msgstr ""
+#~ "Arquivo com a lista branca dos equipamentos/domínios que serão "
+#~ "autorizados mesmo estando na lista de bloqueio."
+
+#~ msgid "Global options"
+#~ msgstr "Opções Globais"
+
+#~ msgid ""
+#~ "Options for further tweaking in case the defaults are not suitable for "
+#~ "you."
+#~ msgstr ""
+#~ "Opções para aprimoramentos adicionais caso as opções padrão não sejam "
+#~ "suficientes para você."
+
+#~ msgid "Restrict reload trigger to certain interface(s)"
+#~ msgstr "Restringir o gatilho de recarga para somente alguma(s) interface(s)"
+
+#~ msgid ""
+#~ "Space separated list of wan interfaces that trigger reload action. To "
+#~ "disable reload trigger set it to 'false'. Default: empty"
+#~ msgstr ""
+#~ "Lista das interfaces WAN, separadas por espaço, que podem disparar uma "
+#~ "ação de recarga. Para desabilitar este gatilho, defina-o como 'false'. "
+#~ "Padrão: em branco"
+
+#~ msgid "Whitelist file"
+#~ msgstr "Arquivo da lista branca"
+
+#~ msgid "see list details"
+#~ msgstr "veja os detalhes da lista"
diff --git a/applications/luci-app-adblock/po/sv/adblock.po b/applications/luci-app-adblock/po/sv/adblock.po
index 22a30e9a10..0e2f039de7 100644
--- a/applications/luci-app-adblock/po/sv/adblock.po
+++ b/applications/luci-app-adblock/po/sv/adblock.po
@@ -1,16 +1,26 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8\n"
-msgid ""
-"). Note that list URLs and Shallalist category selections are not "
-"configurable via Luci."
+msgid "."
msgstr ""
msgid "Adblock"
msgstr "Blockering av annonser"
-msgid "Available blocklist sources ("
-msgstr "Tillgängliga källor för blockeringslistor ("
+msgid "Adblock Domain Query"
+msgstr ""
+
+msgid "Adblock Logfile"
+msgstr ""
+
+msgid "Adblock version"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Available blocklist sources."
+msgstr ""
msgid "Backup directory"
msgstr "Säkerhetskopiera mapp"
@@ -18,18 +28,36 @@ msgstr "Säkerhetskopiera mapp"
msgid "Backup options"
msgstr "Alternativ för säkerhetskopiering"
+msgid "Blocked domains (overall)"
+msgstr ""
+
msgid "Blocklist sources"
msgstr "Källor för blockeringslistor"
+msgid "Collecting data..."
+msgstr ""
+
msgid ""
"Configuration of the adblock package to block ad/abuse domains by using DNS."
msgstr ""
"Konfiguration av paket adblock för att blockera annons/otillåtna domäner "
"genom att användning DNS."
+msgid "DNS backend"
+msgstr ""
+
msgid "Description"
msgstr "Beskrivning"
+msgid "Edit Blacklist"
+msgstr ""
+
+msgid "Edit Configuration"
+msgstr ""
+
+msgid "Edit Whitelist"
+msgstr ""
+
msgid "Enable adblock"
msgstr "Aktivera abblock"
@@ -42,34 +70,111 @@ msgstr ""
msgid "Enabled"
msgstr "Aktiverad"
-msgid "Extra options"
-msgstr "Extra alternativ"
+msgid "For further information"
+msgstr ""
+
+msgid "Input file not found, please check your configuration."
+msgstr ""
+
+msgid "Invalid domain specified!"
+msgstr ""
+
+msgid "Last rundate"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid ""
+"Note that list URLs and Shallalist category selections are configurable in "
+"the 'Advanced' section."
+msgstr ""
+
+msgid "Overview"
+msgstr ""
msgid ""
-"File with whitelisted hosts/domains that are allowed despite being on a "
-"blocklist."
+"Please add only one domain per line. Comments introduced with '#' are "
+"allowed - ip addresses, wildcards and regex are not."
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query domains"
+msgstr ""
+
+msgid "Restrict interface reload trigger to certain interface(s)"
+msgstr ""
+
+msgid "Resume adblock"
msgstr ""
-msgid "Global options"
-msgstr "Globala alternativ"
+msgid "Runtime information"
+msgstr ""
msgid ""
-"Options for further tweaking in case the defaults are not suitable for you."
+"Space separated list of interfaces that trigger a reload action. To disable "
+"reload trigger at all remove all entries."
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Suspend / Resume adblock"
msgstr ""
-msgid "Restrict reload trigger to certain interface(s)"
+msgid "Suspend adblock"
msgstr ""
msgid ""
-"Space separated list of wan interfaces that trigger reload action. To "
-"disable reload trigger set it to 'false'. Default: empty"
+"This form allows you to modify the content of the adblock blacklist (%s)."
+"<br />"
msgstr ""
-msgid "Whitelist file"
-msgstr "Vitlista fil"
+msgid ""
+"This form allows you to modify the content of the adblock whitelist (%s)."
+"<br />"
+msgstr ""
+
+msgid ""
+"This form allows you to modify the content of the main adblock configuration "
+"file (/etc/config/adblock)."
+msgstr ""
+
+msgid ""
+"This form allows you to query active block lists for certain domains, e.g. "
+"for whitelisting."
+msgstr ""
+
+msgid ""
+"This form shows the syslog output, pre-filtered for adblock related messages "
+"only."
+msgstr ""
+
+msgid "View Logfile"
+msgstr ""
+
+msgid "Waiting for command to complete..."
+msgstr ""
+
+msgid "see online documentation"
+msgstr ""
+
+#~ msgid "Available blocklist sources ("
+#~ msgstr "Tillgängliga källor för blockeringslistor ("
+
+#~ msgid "Extra options"
+#~ msgstr "Extra alternativ"
+
+#~ msgid "Global options"
+#~ msgstr "Globala alternativ"
+
+#~ msgid "Whitelist file"
+#~ msgstr "Vitlista fil"
-msgid "see list details"
-msgstr "se listans detaljer"
+#~ msgid "see list details"
+#~ msgstr "se listans detaljer"
#~ msgid "Count"
#~ msgstr "Räkna"
diff --git a/applications/luci-app-adblock/po/templates/adblock.pot b/applications/luci-app-adblock/po/templates/adblock.pot
index 6b2dbd13b3..464ffd9949 100644
--- a/applications/luci-app-adblock/po/templates/adblock.pot
+++ b/applications/luci-app-adblock/po/templates/adblock.pot
@@ -1,15 +1,25 @@
msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8"
-msgid ""
-"). Note that list URLs and Shallalist category selections are not "
-"configurable via Luci."
+msgid "."
msgstr ""
msgid "Adblock"
msgstr ""
-msgid "Available blocklist sources ("
+msgid "Adblock Domain Query"
+msgstr ""
+
+msgid "Adblock Logfile"
+msgstr ""
+
+msgid "Adblock version"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Available blocklist sources."
msgstr ""
msgid "Backup directory"
@@ -18,16 +28,34 @@ msgstr ""
msgid "Backup options"
msgstr ""
+msgid "Blocked domains (overall)"
+msgstr ""
+
msgid "Blocklist sources"
msgstr ""
+msgid "Collecting data..."
+msgstr ""
+
msgid ""
"Configuration of the adblock package to block ad/abuse domains by using DNS."
msgstr ""
+msgid "DNS backend"
+msgstr ""
+
msgid "Description"
msgstr ""
+msgid "Edit Blacklist"
+msgstr ""
+
+msgid "Edit Configuration"
+msgstr ""
+
+msgid "Edit Whitelist"
+msgstr ""
+
msgid "Enable adblock"
msgstr ""
@@ -40,31 +68,93 @@ msgstr ""
msgid "Enabled"
msgstr ""
-msgid "Extra options"
+msgid "For further information"
+msgstr ""
+
+msgid "Input file not found, please check your configuration."
+msgstr ""
+
+msgid "Invalid domain specified!"
+msgstr ""
+
+msgid "Last rundate"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid ""
+"Note that list URLs and Shallalist category selections are configurable in "
+"the 'Advanced' section."
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid ""
+"Please add only one domain per line. Comments introduced with '#' are "
+"allowed - ip addresses, wildcards and regex are not."
+msgstr ""
+
+msgid "Query"
+msgstr ""
+
+msgid "Query domains"
+msgstr ""
+
+msgid "Restrict interface reload trigger to certain interface(s)"
+msgstr ""
+
+msgid "Resume adblock"
+msgstr ""
+
+msgid "Runtime information"
msgstr ""
msgid ""
-"File with whitelisted hosts/domains that are allowed despite being on a "
-"blocklist."
+"Space separated list of interfaces that trigger a reload action. To disable "
+"reload trigger at all remove all entries."
+msgstr ""
+
+msgid "Status"
msgstr ""
-msgid "Global options"
+msgid "Suspend / Resume adblock"
+msgstr ""
+
+msgid "Suspend adblock"
msgstr ""
msgid ""
-"Options for further tweaking in case the defaults are not suitable for you."
+"This form allows you to modify the content of the adblock blacklist (%s)."
+"<br />"
msgstr ""
-msgid "Restrict reload trigger to certain interface(s)"
+msgid ""
+"This form allows you to modify the content of the adblock whitelist (%s)."
+"<br />"
msgstr ""
msgid ""
-"Space separated list of wan interfaces that trigger reload action. To "
-"disable reload trigger set it to 'false'. Default: empty"
+"This form allows you to modify the content of the main adblock configuration "
+"file (/etc/config/adblock)."
+msgstr ""
+
+msgid ""
+"This form allows you to query active block lists for certain domains, e.g. "
+"for whitelisting."
+msgstr ""
+
+msgid ""
+"This form shows the syslog output, pre-filtered for adblock related messages "
+"only."
+msgstr ""
+
+msgid "View Logfile"
msgstr ""
-msgid "Whitelist file"
+msgid "Waiting for command to complete..."
msgstr ""
-msgid "see list details"
+msgid "see online documentation"
msgstr ""
diff --git a/applications/luci-app-adblock/po/zh-cn/adblock.po b/applications/luci-app-adblock/po/zh-cn/adblock.po
index 2878d8afaf..36af78bdab 100644
--- a/applications/luci-app-adblock/po/zh-cn/adblock.po
+++ b/applications/luci-app-adblock/po/zh-cn/adblock.po
@@ -12,16 +12,26 @@ msgstr ""
"X-Generator: Poedit 1.8.5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
-msgid ""
-"). Note that list URLs and Shallalist category selections are not "
-"configurable via Luci."
-msgstr ")。需要注意的是列表URL和列表类别选项无法通过Luci设置。"
+msgid "."
+msgstr ""
msgid "Adblock"
msgstr "Adblock"
-msgid "Available blocklist sources ("
-msgstr "可用拦截列表来源("
+msgid "Adblock Domain Query"
+msgstr ""
+
+msgid "Adblock Logfile"
+msgstr ""
+
+msgid "Adblock version"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Available blocklist sources."
+msgstr ""
msgid "Backup directory"
msgstr "备份目录"
@@ -29,16 +39,34 @@ msgstr "备份目录"
msgid "Backup options"
msgstr "备份选项"
+msgid "Blocked domains (overall)"
+msgstr ""
+
msgid "Blocklist sources"
msgstr "拦截列表来源"
+msgid "Collecting data..."
+msgstr ""
+
msgid ""
"Configuration of the adblock package to block ad/abuse domains by using DNS."
msgstr "Adblock 配置工具,通过 DNS 来拦截广告和阻止域名。"
+msgid "DNS backend"
+msgstr ""
+
msgid "Description"
msgstr "描述"
+msgid "Edit Blacklist"
+msgstr ""
+
+msgid "Edit Configuration"
+msgstr ""
+
+msgid "Edit Whitelist"
+msgstr ""
+
msgid "Enable adblock"
msgstr "启用Adblock"
@@ -51,34 +79,126 @@ msgstr ""
msgid "Enabled"
msgstr "启用"
-msgid "Extra options"
-msgstr "额外选项"
+msgid "For further information"
+msgstr ""
+
+msgid "Input file not found, please check your configuration."
+msgstr ""
+
+msgid "Invalid domain specified!"
+msgstr ""
+
+msgid "Last rundate"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
msgid ""
-"File with whitelisted hosts/domains that are allowed despite being on a "
-"blocklist."
-msgstr "允许的主机/域名列表"
+"Note that list URLs and Shallalist category selections are configurable in "
+"the 'Advanced' section."
+msgstr ""
-msgid "Global options"
-msgstr "全局选项"
+msgid "Overview"
+msgstr ""
msgid ""
-"Options for further tweaking in case the defaults are not suitable for you."
-msgstr "在默认设置并不适合你时的额外选项。"
+"Please add only one domain per line. Comments introduced with '#' are "
+"allowed - ip addresses, wildcards and regex are not."
+msgstr ""
-msgid "Restrict reload trigger to certain interface(s)"
+msgid "Query"
+msgstr ""
+
+msgid "Query domains"
+msgstr ""
+
+msgid "Restrict interface reload trigger to certain interface(s)"
+msgstr ""
+
+msgid "Resume adblock"
+msgstr ""
+
+msgid "Runtime information"
+msgstr ""
+
+msgid ""
+"Space separated list of interfaces that trigger a reload action. To disable "
+"reload trigger at all remove all entries."
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Suspend / Resume adblock"
+msgstr ""
+
+msgid "Suspend adblock"
+msgstr ""
+
+msgid ""
+"This form allows you to modify the content of the adblock blacklist (%s)."
+"<br />"
msgstr ""
msgid ""
-"Space separated list of wan interfaces that trigger reload action. To "
-"disable reload trigger set it to 'false'. Default: empty"
+"This form allows you to modify the content of the adblock whitelist (%s)."
+"<br />"
msgstr ""
-msgid "Whitelist file"
-msgstr "白名单文件"
+msgid ""
+"This form allows you to modify the content of the main adblock configuration "
+"file (/etc/config/adblock)."
+msgstr ""
+
+msgid ""
+"This form allows you to query active block lists for certain domains, e.g. "
+"for whitelisting."
+msgstr ""
+
+msgid ""
+"This form shows the syslog output, pre-filtered for adblock related messages "
+"only."
+msgstr ""
+
+msgid "View Logfile"
+msgstr ""
+
+msgid "Waiting for command to complete..."
+msgstr ""
+
+msgid "see online documentation"
+msgstr ""
+
+#~ msgid ""
+#~ "). Note that list URLs and Shallalist category selections are not "
+#~ "configurable via Luci."
+#~ msgstr ")。需要注意的是列表URL和列表类别选项无法通过Luci设置。"
+
+#~ msgid "Available blocklist sources ("
+#~ msgstr "可用拦截列表来源("
+
+#~ msgid "Extra options"
+#~ msgstr "额外选项"
+
+#~ msgid ""
+#~ "File with whitelisted hosts/domains that are allowed despite being on a "
+#~ "blocklist."
+#~ msgstr "允许的主机/域名列表"
+
+#~ msgid "Global options"
+#~ msgstr "全局选项"
+
+#~ msgid ""
+#~ "Options for further tweaking in case the defaults are not suitable for "
+#~ "you."
+#~ msgstr "在默认设置并不适合你时的额外选项。"
+
+#~ msgid "Whitelist file"
+#~ msgstr "白名单文件"
-msgid "see list details"
-msgstr "查看列表详情"
+#~ msgid "see list details"
+#~ msgstr "查看列表详情"
#~ msgid "Count"
#~ msgstr "数量"
diff --git a/applications/luci-app-clamav/po/ja/clamav.po b/applications/luci-app-clamav/po/ja/clamav.po
new file mode 100644
index 0000000000..c54c7b18aa
--- /dev/null
+++ b/applications/luci-app-clamav/po/ja/clamav.po
@@ -0,0 +1,130 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.12\n"
+"Last-Translator: INAGAKI Hiroshi <musashino.open@gmail.com>\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Language: ja\n"
+
+msgid "10"
+msgstr "10"
+
+msgid "1024"
+msgstr "1024"
+
+msgid "15"
+msgstr "15"
+
+msgid "150M"
+msgstr "150M"
+
+msgid "1M"
+msgstr "1M"
+
+msgid "20"
+msgstr "20"
+
+msgid "2048"
+msgstr "2048"
+
+msgid "2M"
+msgstr "2M"
+
+msgid "50M"
+msgstr "50M"
+
+msgid "512K"
+msgstr "512K"
+
+msgid "600"
+msgstr "600"
+
+msgid "Block encrypted archives"
+msgstr "暗号化されたアーカイブのブロック"
+
+msgid "ClamAV"
+msgstr "ClamAV"
+
+msgid "Database check every N sec"
+msgstr "データベース チェック間隔(秒)"
+
+msgid "Detect broken executables"
+msgstr "破損した実行ファイルの検出"
+
+msgid "Detect possibly unwanted apps"
+msgstr "不必要と思われるアプリケーションの検出"
+
+msgid "Enable verbose logging"
+msgstr "詳細なログの有効化"
+
+msgid "Follow directory symlinks"
+msgstr "ディレクトリ シンボリックリンクに従う"
+
+msgid "Follow file symlinks"
+msgstr "ファイル シンボリックリンクに従う"
+
+msgid "Log"
+msgstr "ログ"
+
+msgid "Log additional infection info"
+msgstr "追加の感染情報ログ"
+
+msgid "Log time with each message"
+msgstr "ログ メッセージ毎に時刻を付加"
+
+msgid "Max directory scan depth"
+msgstr "ディレクトリ スキャンの最大深度"
+
+msgid "Max number of threads"
+msgstr "スレッドの最大数"
+
+msgid "Max size of log file"
+msgstr "ログの最大サイズ"
+
+msgid "Max size of scanned file"
+msgstr ""
+
+msgid "No"
+msgstr "いいえ"
+
+msgid "Port range, highest port"
+msgstr "ポート範囲(上限)"
+
+msgid "Port range, lowest port"
+msgstr "ポート範囲(下限)"
+
+msgid "Scan ELF files"
+msgstr "ELF ファイルのスキャン"
+
+msgid "Scan MS Office and .msi files"
+msgstr "MS Office と .msi ファイルのスキャン"
+
+msgid "Scan RFC1341 messages split over many emails"
+msgstr ""
+
+msgid "Scan archives"
+msgstr "アーカイブのスキャン"
+
+msgid "Scan emails"
+msgstr "E-mailのスキャン"
+
+msgid "Scan pdf files"
+msgstr "PDF ファイルのスキャン"
+
+msgid "Scan portable executables"
+msgstr "ポータブル 実行ファイルのスキャン"
+
+msgid "Scan swf files"
+msgstr "SWF ファイルのスキャン"
+
+msgid "Settings"
+msgstr "設定"
+
+msgid "Yes"
+msgstr "はい"
diff --git a/applications/luci-app-clamav/po/templates/clamav.pot b/applications/luci-app-clamav/po/templates/clamav.pot
new file mode 100644
index 0000000000..768f73093a
--- /dev/null
+++ b/applications/luci-app-clamav/po/templates/clamav.pot
@@ -0,0 +1,119 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+msgid "10"
+msgstr ""
+
+msgid "1024"
+msgstr ""
+
+msgid "15"
+msgstr ""
+
+msgid "150M"
+msgstr ""
+
+msgid "1M"
+msgstr ""
+
+msgid "20"
+msgstr ""
+
+msgid "2048"
+msgstr ""
+
+msgid "2M"
+msgstr ""
+
+msgid "50M"
+msgstr ""
+
+msgid "512K"
+msgstr ""
+
+msgid "600"
+msgstr ""
+
+msgid "Block encrypted archives"
+msgstr ""
+
+msgid "ClamAV"
+msgstr ""
+
+msgid "Database check every N sec"
+msgstr ""
+
+msgid "Detect broken executables"
+msgstr ""
+
+msgid "Detect possibly unwanted apps"
+msgstr ""
+
+msgid "Enable verbose logging"
+msgstr ""
+
+msgid "Follow directory symlinks"
+msgstr ""
+
+msgid "Follow file symlinks"
+msgstr ""
+
+msgid "Log"
+msgstr ""
+
+msgid "Log additional infection info"
+msgstr ""
+
+msgid "Log time with each message"
+msgstr ""
+
+msgid "Max directory scan depth"
+msgstr ""
+
+msgid "Max number of threads"
+msgstr ""
+
+msgid "Max size of log file"
+msgstr ""
+
+msgid "Max size of scanned file"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "Port range, highest port"
+msgstr ""
+
+msgid "Port range, lowest port"
+msgstr ""
+
+msgid "Scan ELF files"
+msgstr ""
+
+msgid "Scan MS Office and .msi files"
+msgstr ""
+
+msgid "Scan RFC1341 messages split over many emails"
+msgstr ""
+
+msgid "Scan archives"
+msgstr ""
+
+msgid "Scan emails"
+msgstr ""
+
+msgid "Scan pdf files"
+msgstr ""
+
+msgid "Scan portable executables"
+msgstr ""
+
+msgid "Scan swf files"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
diff --git a/applications/luci-app-cshark/Makefile b/applications/luci-app-cshark/Makefile
new file mode 100644
index 0000000000..40b0e9fb7f
--- /dev/null
+++ b/applications/luci-app-cshark/Makefile
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2017 Dan Luedtke <mail@danrl.com>
+#
+# This is free software, licensed under the Apache License, Version 2.0 .
+#
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=Cloudshark capture tool Web UI
+LUCI_DEPENDS:=+cshark
+LUCI_PKGARCH:=all
+
+PKG_MAINTAINER:=Luka Perkov <luka@openwrt.org>
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/applications/luci-app-cshark/luasrc/controller/cshark.lua b/applications/luci-app-cshark/luasrc/controller/cshark.lua
new file mode 100644
index 0000000000..4d9bbba290
--- /dev/null
+++ b/applications/luci-app-cshark/luasrc/controller/cshark.lua
@@ -0,0 +1,125 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright (C) 2014, QA Cafe, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+]]--
+
+module("luci.controller.cshark", package.seeall)
+
+function index()
+ page = node("admin", "network", "cloudshark")
+ page.target = cbi("admin_network/cshark")
+ page.title = _("CloudShark")
+ page.order = 70
+
+ page = entry({"admin", "network", "cshark_iface_dump_start"}, call("cshark_iface_dump_start"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "cshark_iface_dump_stop"}, call("cshark_iface_dump_stop"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "cshark_check_status"}, call("cshark_check_status"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "cshark_link_list_get"}, call("cshark_link_list_get"), nil)
+ page.leaf = true
+
+ page = entry({"admin", "network", "cshark_link_list_clear"}, call("cshark_link_list_clear"), nil)
+ page.leaf = true
+end
+
+function cshark_iface_dump_start(ifname, value, flag, filter)
+ if ifname == nil or ifname == '' then
+ ifname = 'any'
+ end
+ if tonumber(value) == nil
+ then
+ value = '0'
+ end
+ if filter == nil or filter == '' then
+ filter = ''
+ end
+
+ if flag == nil or flag == '' then
+ filter = 'T'
+ end
+
+ luci.http.prepare_content("text/plain")
+
+ local res = os.execute("(/sbin/cshark -i " .. ifname .. " -" .. flag .. " " .. value .. " -p /tmp/cshark-luci.pid " .. filter .. " > /tmp/cshark-luci.out 2>&1) &")
+ luci.http.write(tostring(res))
+end
+
+function cshark_iface_dump_stop()
+ luci.http.prepare_content("text/plain")
+
+ local f = io.open("/tmp/cshark-luci.pid", "rb")
+ local pid = f:read("*all")
+ io.close(f)
+
+ local res = os.execute("kill -TERM " .. pid)
+ luci.http.write(tostring(res))
+end
+
+function cshark_check_status()
+
+ local msg = "";
+ local status;
+ local f = io.open("/tmp/cshark-luci.pid","r")
+ if f ~= nil then
+ status = 1;
+ io.close(f)
+ else
+ status = 0;
+ end
+
+ f = io.open("/tmp/cshark-luci.out","r")
+ if f ~= nil then
+ msg = f:read("*all")
+ io.close(f)
+ if msg ~= '' then
+ os.remove('/tmp/cshark-luci.out')
+ end
+ end
+
+ luci.http.prepare_content("application/json")
+
+ local res = {}
+ res["status"] = status;
+ res["msg"] = msg;
+
+ luci.http.write_json(res)
+end
+
+function cshark_link_list_get()
+ local uci = require("uci").cursor()
+
+ luci.http.prepare_content("application/json")
+
+ luci.http.write("[")
+
+ local t = uci:get("cshark", "cshark", "entry")
+ if (t ~= nil) then
+ for i = #t, 1, -1 do
+ luci.http.write("[\"" .. t[i] .. "\"],")
+ end
+ end
+
+ luci.http.write("[]]")
+end
+
+function cshark_link_list_clear()
+ local uci = require("uci").cursor()
+
+ uci:delete("cshark", "cshark", "entry")
+ uci:commit("cshark");
+
+ luci.http.status(200, "OK")
+end
diff --git a/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua b/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua
new file mode 100644
index 0000000000..8db95596f8
--- /dev/null
+++ b/applications/luci-app-cshark/luasrc/model/cbi/admin_network/cshark.lua
@@ -0,0 +1,30 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright (C) 2014, QA Cafe, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+
+local fs = require "nixio.fs"
+
+m = Map("cshark", translate("CloudShark"))
+
+if fs.access("/etc/config/cshark") then
+ m:section(SimpleSection).template = "cshark"
+
+ s = m:section(TypedSection, "cshark", translate("Options"))
+ s.anonymous = true
+ s.addremove = false
+
+ s:option(Value, "url", translate("CloudShark URL"))
+ s:option(Value, "token", translate("CloudShark API token"))
+end
+
+return m
diff --git a/applications/luci-app-cshark/luasrc/view/cshark.htm b/applications/luci-app-cshark/luasrc/view/cshark.htm
new file mode 100644
index 0000000000..bc67f806c4
--- /dev/null
+++ b/applications/luci-app-cshark/luasrc/view/cshark.htm
@@ -0,0 +1,291 @@
+<%#
+LuCI - Lua Configuration Interface
+
+Copyright (C) 2014, QA Cafe, Inc.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+
+-%>
+
+<fieldset class="cbi-section">
+ <legend><%:Start network capture%></legend>
+ <div class="cbi-section-node">
+ <table class="cbi-section-table">
+ <tr>
+ <th><%:Interface%></th>
+ <th colspan='2'><%:seconds, packets, bytes%></th>
+ <th><%:Filter%></th>
+ <th><%:Actions%></th>
+ </tr>
+ <tr>
+ <td>
+ <select title="<%:Interface%>" style="width:auto" id="s_interfaces">
+ <%
+ local nixio = require "nixio"
+ for k, v in ipairs(nixio.getifaddrs()) do
+ if v.family == "packet" then
+ %>
+ <option value="<%=v.name%>"><%=v.name%> </option>
+ <%
+ end
+ end
+ %>
+ <option value="any"><%:any%></option>
+ </select>
+ </td>
+ <td colspan='2'>
+ <input id="tx_value" type="text" value="0" />
+ <select title="<%:timeout, bytes, seconds%>" id="s_value_type" style="width:auto">
+ <option value="T"><%:seconds%></option>
+ <option value="P"><%:packets%></option>
+ <option value="S"><%:bytes%></option>
+ </select>
+ </td>
+ <td>
+ <input style="margin: 5px 0" type="text" title="<%:Filter%>" placeholder="filter" id="i_filter" />
+ </td>
+ <td>
+ <input type="button" id="bt_action" data-action="start" value="<%:Start capture%>" class="cbi-button" />
+ </td>
+ </tr>
+ </table>
+ </div>
+</fieldset>
+
+<fieldset class="cbi-section">
+ <span id="cshark-rc-output"></span>
+</fieldset>
+
+<hr/>
+
+<fieldset class="cbi-section">
+ <legend><%:Capture links%></legend>
+ <div class="cbi-section-node">
+ <table id="t_link_list" class="cbi-section-table">
+ <tr class="cbi-section-table-titles">
+ <th class="cbi-section-table-cell"><%:Capture URL%></th>
+ <th class="cbi-section-table-cell"><%:Capture time%></th>
+ </tr>
+ </table>
+ </div>
+</fieldset>
+
+<fieldset class="cbi-section">
+ <a href="https://support.cloudshark.org/openwrt/openwrt-cloudshark.html" target="_blank">Visit support.cloudshark.org for help.</a>
+</fieldset>
+
+<hr/>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+
+ var capture_running = 0;
+ var pid_file = 0;
+ var bt_action = document.getElementById('bt_action');
+ var a_clear_links = document.getElementById('a_clear_links');
+ var output = document.getElementById('cshark-rc-output');
+ var loader = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" /> ';
+ var msg = { 'start' : '<%:Waiting for capture to complete...%>', 'stop' : '<%:Waiting for upload to complete...%>' };
+ var status_msg = msg['start'];
+
+ function get_date(timestamp)
+ {
+ function pad_str(str)
+ {
+ return (str < 10) ? "0" + str : str;
+ }
+
+ var current_date = new Date(timestamp * 1000);
+ return current_date.getFullYear() + "-" +
+ pad_str(current_date.getMonth() + 1) + "-" +
+ pad_str(current_date.getDate()) + " " +
+ pad_str(current_date.getHours()) + ":" +
+ pad_str(current_date.getMinutes()) + ":" +
+ pad_str(current_date.getSeconds());
+ }
+
+ bt_action.onclick = function()
+ {
+ var action = this.getAttribute("data-action");
+ var csxhr = new XHR();
+
+ if (action == "stop")
+ {
+ update_status(action);
+
+ bt_action.disabled = true;
+
+ csxhr.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_iface_dump_stop', null,
+ function(x)
+ {
+ if (!x || x.responseText.trim() != "0")
+ {
+ update_status("failed", "Invalid response on stop.");
+ }
+ });
+
+ }
+ else if (action == "start")
+ {
+
+ var s_interfaces = document.getElementById('s_interfaces');
+ var s_value_type = document.getElementById('s_value_type');
+ var i_filter = document.getElementById('i_filter');
+
+ var if_n = s_interfaces.selectedIndex;
+ var t_n = s_value_type.selectedIndex;
+ var ifname = s_interfaces.options[if_n].value.trim();
+ var filter_val = i_filter.value.trim();
+ var tx_val = document.getElementById('tx_value').value.trim();
+ var type_val = s_value_type.options[t_n].value.trim();
+
+ if (type_val != 'P' && type_val != 'T' && type_val != 'S') type_val = 'T';
+
+ if (!ifname || !type_val) return;
+
+ if (isNaN(tx_val)) return alert("<%:value for [seconds, packets, bytes] must be Integer%>");
+
+ update_status(action);
+
+ csxhr.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_iface_dump_start/' + ifname + '/' + tx_val + '/' + type_val + '/'+ filter_val, null,
+ function(x)
+ {
+ if (!x)
+ update_status("failed", "Invalid response on start.");
+ else
+ update_status("running");
+ });
+ }
+ }
+
+ function update_status(status, message)
+ {
+ switch (status)
+ {
+ case 'start':
+ case 'stop':
+ status_msg = msg[status];
+ output.innerHTML = loader + status_msg;
+ break
+
+ case 'running':
+ if (capture_running) break;;
+
+ output.innerHTML = loader + status_msg;
+
+ bt_action.value = '<%:Stop capture%>';
+ bt_action.setAttribute('data-action', 'stop');
+ capture_running = 1;
+ break;
+
+ case 'completed':
+ case 'failed':
+ if (!capture_running) break;
+
+ if (status == "completed")
+ {
+ link_list_update();
+ }
+
+ output.innerHTML = "<pre>" + message + "</pre>";
+ bt_action.value = '<%:Start capture%>';
+ bt_action.setAttribute('data-action', 'start');
+ bt_action.disabled = false;
+ capture_running = 0;
+ break;
+ }
+ }
+
+
+ function check_status()
+ {
+
+ XHR.poll(3, '<%=luci.dispatcher.build_url("admin", "network")%>/cshark_check_status', null,
+ function(x, data)
+ {
+ if (!x)
+ {
+ if (capture_running)
+ update_status("failed", "Invalid response when fetching status.");
+
+ return;
+ }
+ console.log(data)
+
+ update_status( (data.status == 1) && "running" || "completed", data.msg);
+ })
+ }
+
+ function link_list_clear()
+ {
+ var csxhr_del = new XHR();
+ csxhr_del.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_link_list_clear', null,
+ function(x)
+ {
+ if (!x)
+ return false;
+
+ link_list_update();
+ });
+ }
+
+
+ function link_list_update()
+ {
+ var t_link = document.getElementById("t_link_list");
+ if (!t_link) return;
+
+ var row_count = t_link.rows.length;
+ while(--row_count) t_link.deleteRow(row_count);
+
+ var cell = t_link.insertRow(-1).insertCell(0);
+ cell.colSpan = 2;
+ cell.innerHTML = loader;
+
+ var csxhr_link = new XHR();
+ csxhr_link.get('<%=luci.dispatcher.build_url("admin", "network")%>/cshark_link_list_get', null,
+ function(x, entries)
+ {
+ var row = t_link.deleteRow(1);
+
+ if (!x) return;
+
+ if (!entries || !entries.length)
+ {
+ var cell = t_link.insertRow(-1).insertCell(0);
+ cell.colSpan = 2;
+ cell.innerHTML = '<em><br />There are no captures available yet.</em>';
+
+ return;
+ }
+
+ for (var i = 0, len = entries.length; i < len ; i++)
+ {
+ var entry = entries[i][0];
+ if (!entry) continue;
+
+ var data = entry.split(",");
+ var url = data[0];
+ var timestamp = data[1];
+
+ var row = t_link.insertRow(-1);
+ row.insertCell(0).innerHTML = '<a href="'+url+'" target="_blank">'+url+'</a>';
+ row.insertCell(1).innerHTML = get_date(timestamp);
+ }
+
+ var cell = t_link.insertRow(-1).insertCell(0);
+ cell.colSpan = 2;
+ cell.style.textAlign="center";
+ cell.innerHTML = '<input type="button" onclick="link_list_clear()" class="cbi-button" value ="<%:Clear list%>" />';
+ })
+ }
+
+ check_status();
+ link_list_update();
+//]]></script>
diff --git a/applications/luci-app-mwan3/Makefile b/applications/luci-app-mwan3/Makefile
new file mode 100644
index 0000000000..d65cd3af16
--- /dev/null
+++ b/applications/luci-app-mwan3/Makefile
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2017 Dan Luedtke <mail@danrl.com>
+#
+# This is free software, licensed under the Apache License, Version 2.0 .
+#
+
+include $(TOPDIR)/rules.mk
+
+LUCI_TITLE:=LuCI support for the MWAN3 multiwan hotplug script
+LUCI_DEPENDS:=+mwan3 +luci-mod-admin-full +luci-app-firewall +luci-lib-nixio
+LUCI_PKGARCH:=all
+PKG_LICENSE:=GPLv2
+
+PKG_MAINTAINER:=Aedan Renner <chipdankly@gmail.com> \
+ Florian Eckert <fe@dev.tdt.de>
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/applications/luci-app-mwan3/luasrc/controller/mwan3.lua b/applications/luci-app-mwan3/luasrc/controller/mwan3.lua
new file mode 100644
index 0000000000..3d5a23dd03
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/controller/mwan3.lua
@@ -0,0 +1,331 @@
+module("luci.controller.mwan3", package.seeall)
+
+sys = require "luci.sys"
+ut = require "luci.util"
+
+ip = "/usr/bin/ip -4 "
+
+function index()
+ if not nixio.fs.access("/etc/config/mwan3") then
+ return
+ end
+
+ entry({"admin", "network", "mwan"},
+ alias("admin", "network", "mwan", "overview"),
+ _("Load Balancing"), 600)
+
+ entry({"admin", "network", "mwan", "overview"},
+ alias("admin", "network", "mwan", "overview", "overview_interface"),
+ _("Overview"), 10)
+ 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", "mwan", "configuration", "interface"},
+ arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
+ _("Interfaces"), 10).leaf = true
+ entry({"admin", "network", "mwan", "configuration", "member"},
+ arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
+ _("Members"), 20).leaf = true
+ entry({"admin", "network", "mwan", "configuration", "policy"},
+ arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
+ _("Policies"), 30).leaf = true
+ entry({"admin", "network", "mwan", "configuration", "rule"},
+ arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
+ _("Rules"), 40).leaf = true
+
+ entry({"admin", "network", "mwan", "advanced"},
+ alias("admin", "network", "mwan", "advanced", "hotplugscript"),
+ _("Advanced"), 100)
+ 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", "wirelessconfig"},
+ form("mwan/advanced_wirelessconfig"))
+ 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 getInterfaceStatus(ruleNumber, interfaceName)
+ if ut.trim(sys.exec("uci -p /var/state get mwan3." .. interfaceName .. ".enabled")) == "1" then
+ if ut.trim(sys.exec(ip .. "route list table " .. ruleNumber)) ~= "" then
+ if ut.trim(sys.exec("uci -p /var/state get mwan3." .. interfaceName .. ".track_ip")) ~= "" then
+ return "online"
+ else
+ return "notMonitored"
+ end
+ else
+ return "offline"
+ end
+ else
+ return "notEnabled"
+ end
+end
+
+function getInterfaceName()
+ local ruleNumber, status = 0, ""
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ ruleNumber = ruleNumber+1
+ status = status .. section[".name"] .. "[" .. getInterfaceStatus(ruleNumber, section[".name"]) .. "]"
+ end
+ )
+ return status
+end
+
+function interfaceStatus()
+ local ntm = require "luci.model.network".init()
+
+ local mArray = {}
+
+ -- overview status
+ local statusString = getInterfaceName()
+ if statusString ~= "" then
+ mArray.wans = {}
+ wansid = {}
+
+ for wanName, interfaceState in string.gfind(statusString, "([^%[]+)%[([^%]]+)%]") do
+ local wanInterfaceName = ut.trim(sys.exec("uci -p /var/state get network." .. wanName .. ".ifname"))
+ if wanInterfaceName == "" then
+ wanInterfaceName = "X"
+ end
+ 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 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(mArray)
+end
+
+function detailedStatus()
+ local mArray = {}
+
+ -- 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(mArray)
+end
+
+function diagnosticsData(interface, tool, task)
+ function getInterfaceNumber()
+ local number = 0
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ number = number+1
+ if section[".name"] == interface then
+ interfaceNumber = number
+ end
+ end
+ )
+ end
+
+ local mArray = {}
+
+ local results = ""
+ if tool == "service" then
+ os.execute("/usr/sbin/mwan3 " .. task)
+ if task == "restart" then
+ results = "MWAN3 restarted"
+ elseif task == "stop" then
+ results = "MWAN3 stopped"
+ else
+ results = "MWAN3 started"
+ end
+ else
+ local interfaceDevice = ut.trim(sys.exec("uci -p /var/state get network." .. interface .. ".ifname"))
+ if interfaceDevice ~= "" then
+ if tool == "ping" then
+ 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 task == "gateway" then
+ local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. gateway
+ results = pingCommand .. "\n\n" .. sys.exec(pingCommand)
+ else
+ local tracked = ut.trim(sys.exec("uci -p /var/state get 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
+ results = "No tracking IP addresses configured on " .. interface
+ end
+ end
+ else
+ results = "No default gateway for " .. interface .. " found. Default route does not exist or is configured incorrectly"
+ end
+ elseif tool == "rulechk" then
+ 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
+ results = "All required interface IP rules found:\n\n" .. rule1 .. rule2
+ elseif rule1 ~= "" or rule2 ~= "" then
+ results = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
+ else
+ results = "Missing both of the required interface IP rules"
+ end
+ elseif tool == "routechk" then
+ getInterfaceNumber()
+ local routeTable = sys.exec(ip .. "route list table " .. interfaceNumber)
+ if routeTable ~= "" then
+ results = "Interface routing table " .. interfaceNumber .. " was found:\n\n" .. routeTable
+ else
+ results = "Missing required interface routing table " .. interfaceNumber
+ end
+ elseif tool == "hotplug" then
+ if task == "ifup" then
+ os.execute("/usr/sbin/mwan3 ifup " .. interface)
+ results = "Hotplug ifup sent to interface " .. interface .. "..."
+ else
+ os.execute("/usr/sbin/mwan3 ifdown " .. interface)
+ results = "Hotplug ifdown sent to interface " .. interface .. "..."
+ end
+ end
+ else
+ results = "Unable to perform diagnostic tests on " .. interface .. ". There is no physical or virtual device associated with this interface"
+ end
+ end
+ if results ~= "" then
+ results = ut.trim(results)
+ mArray.diagnostics = { results }
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(mArray)
+end
+
+function troubleshootingData()
+ local ver = require "luci.version"
+
+ local mArray = {}
+
+ -- software versions
+ local wrtRelease = ut.trim(ver.distversion)
+ if wrtRelease ~= "" then
+ wrtRelease = "OpenWrt - " .. wrtRelease
+ else
+ wrtRelease = "OpenWrt - unknown"
+ end
+ local luciRelease = ut.trim(ver.luciversion)
+ if luciRelease ~= "" then
+ luciRelease = "\nLuCI - " .. luciRelease
+ else
+ luciRelease = "\nLuCI - unknown"
+ end
+ local mwanVersion = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{print $2}'"))
+ if mwanVersion ~= "" then
+ mwanVersion = "\n\nmwan3 - " .. mwanVersion
+ else
+ mwanVersion = "\n\nmwan3 - unknown"
+ end
+ local mwanLuciVersion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{print $2}'"))
+ if mwanLuciVersion ~= "" then
+ mwanLuciVersion = "\nmwan3-luci - " .. mwanLuciVersion
+ else
+ mwanLuciVersion = "\nmwan3-luci - unknown"
+ end
+ 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
+ mArray.mwanconfig = { mwanConfig }
+
+ -- network config
+ 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
+ mArray.netconfig = { networkConfig }
+
+ -- wireless config
+ local wirelessConfig = ut.trim(sys.exec("cat /etc/config/wireless | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/' -e 's/.*key.*/ KEY HIDDEN/'"))
+ if wirelessConfig == "" then
+ wirelessConfig = "No data found"
+ end
+ mArray.wificonfig = { wirelessConfig }
+
+ -- ifconfig
+ local ifconfig = ut.trim(sys.exec("ifconfig"))
+ if ifconfig == "" then
+ ifconfig = "No data found"
+ end
+ mArray.ifconfig = { ifconfig }
+
+ -- route -n
+ local routeShow = ut.trim(sys.exec("route -n"))
+ if routeShow == "" then
+ routeShow = "No data found"
+ end
+ mArray.routeshow = { routeShow }
+
+ -- ip rule show
+ local ipRuleShow = ut.trim(sys.exec(ip .. "rule show"))
+ if ipRuleShow == "" then
+ ipRuleShow = "No data found"
+ end
+ mArray.iprule = { ipRuleShow }
+
+ -- ip route list table 1-250
+ 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
+ routeString = ut.trim(routeString)
+ else
+ routeString = "No data found"
+ end
+ mArray.routelist = { routeString }
+
+ -- default firewall output policy
+ local firewallOut = ut.trim(sys.exec("uci -p /var/state get firewall.@defaults[0].output"))
+ if firewallOut == "" then
+ firewallOut = "No data found"
+ end
+ mArray.firewallout = { firewallOut }
+
+ -- iptables
+ local iptables = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
+ if iptables == "" then
+ iptables = "No data found"
+ end
+ mArray.iptables = { iptables }
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(mArray)
+end
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_hotplugscript.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_hotplugscript.lua
new file mode 100644
index 0000000000..0e7b8b11d0
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_hotplugscript.lua
@@ -0,0 +1,55 @@
+-- ------ 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 &#34;#!/bin/sh&#34; 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_mwanconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_mwanconfig.lua
new file mode 100644
index 0000000000..e0a99e8366
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_mwanconfig.lua
@@ -0,0 +1,32 @@
+-- ------ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_networkconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_networkconfig.lua
new file mode 100644
index 0000000000..b93d89751b
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_networkconfig.lua
@@ -0,0 +1,32 @@
+-- ------ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_wirelessconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_wirelessconfig.lua
new file mode 100644
index 0000000000..95e9f7c7e5
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/advanced_wirelessconfig.lua
@@ -0,0 +1,32 @@
+-- ------ wireless configuration ------ --
+
+ut = require "luci.util"
+
+wirelessConfig = "/etc/config/wireless"
+
+
+m5 = SimpleForm("wirelessconf", nil)
+ m5:append(Template("mwan/advanced_wirelessconfig")) -- highlight current tab
+
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/config/wireless"))
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ return nixio.fs.readfile(wirelessConfig) or ""
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return nixio.fs.writefile(wirelessConfig, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function f.handle(self, state, data)
+ return true
+ end
+
+
+return m5
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua
new file mode 100644
index 0000000000..a8e68a01be
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua
@@ -0,0 +1,266 @@
+-- ------ 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 -p /var/state get 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 -p /var/state get mwan3." .. interfaceName .. ".track_ip) | wc -w")))
+ if trackingNumber > 0 then
+ local reliabilityNumber = tonumber(ut.trim(sys.exec("uci -p /var/state get 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 -p /var/state get network." .. interfaceName)) == "interface" then
+ local interfaceDevice = ut.trim(sys.exec("uci -p /var/state get 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 "&#8212;"
+ 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 "&#8212;"
+ else
+ return "&#8212;"
+ 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 "&#8212;"
+ else
+ return "&#8212;"
+ 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 "&#8212;"
+ end
+ else
+ return "&#8212;"
+ 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 "&#8212;"
+ end
+ else
+ return "&#8212;"
+ 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 "&#8212;"
+ else
+ return "&#8212;"
+ 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 "&#8212;"
+ else
+ return "&#8212;"
+ end
+ end
+
+metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ local metricValue = sys.exec("uci -p /var/state get network." .. s .. ".metric")
+ if metricValue ~= "" then
+ return metricValue
+ else
+ return "&#8212;"
+ 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 = "&#10;&#10;"
+ end
+ if string.find(errorRouteList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "No default route in the main routing table"
+ lineBreak = "&#10;&#10;"
+ end
+ if string.find(errorNetConfigList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "Configured incorrectly or not at all in /etc/config/network"
+ lineBreak = "&#10;&#10;"
+ end
+ if string.find(errorNoMetricList, " " .. s .. " ") then
+ mouseOver = mouseOver .. lineBreak .. "No metric configured in /etc/config/network"
+ lineBreak = "&#10;&#10;"
+ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua
new file mode 100644
index 0000000000..e81ef74d2a
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua
@@ -0,0 +1,250 @@
+-- ------ extra functions ------ --
+
+function interfaceCheck()
+ metricValue = ut.trim(sys.exec("uci -p /var/state get 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 -p /var/state get 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 -p /var/state get mwan3." .. arg[1] .. ".track_ip) | wc -w")))
+ if trackingNumber > 0 then
+ local reliabilityNumber = tonumber(ut.trim(sys.exec("uci -p /var/state get 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 -p /var/state get network." .. arg[1])) == "interface" then
+ local interfaceDevice = ut.trim(sys.exec("uci -p /var/state get 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"))
+
+family = mwan_interface:option(ListValue, "family", translate("Internet Protocol"))
+ family.default = "ipv4"
+ family:value("ipv4", translate("IPv4"))
+ family:value("ipv6", translate("IPv6"))
+
+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")
+
+size = mwan_interface:option(Value, "size", translate("Ping size"))
+ size.default = "56"
+ size:value("8")
+ size:value("24")
+ size:value("56")
+ size:value("120")
+ size:value("248")
+ size:value("504")
+ size:value("1016")
+ size:value("1472")
+ size:value("2040")
+ size.datatype = "range(1, 65507)"
+ size.rmempty = false
+ size.optional = false
+
+timeout = mwan_interface:option(ListValue, "timeout", translate("Ping timeout"))
+ timeout.default = "2"
+ timeout:value("1", translatef("%d second", 1))
+ timeout:value("2", translatef("%d seconds", 2))
+ timeout:value("3", translatef("%d seconds", 3))
+ timeout:value("4", translatef("%d seconds", 4))
+ timeout:value("5", translatef("%d seconds", 5))
+ timeout:value("6", translatef("%d seconds", 6))
+ timeout:value("7", translatef("%d seconds", 7))
+ timeout:value("8", translatef("%d seconds", 8))
+ timeout:value("9", translatef("%d seconds", 9))
+ timeout:value("10", translatef("%d seconds", 10))
+
+interval = mwan_interface:option(ListValue, "interval", translate("Ping interval"))
+ interval.default = "5"
+ interval:value("1", translatef("%d second", 1))
+ interval:value("3", translatef("%d seconds", 3))
+ interval:value("5", translatef("%d seconds", 5))
+ interval:value("10", translatef("%d seconds", 10))
+ interval:value("20", translatef("%d seconds", 20))
+ interval:value("30", translatef("%d seconds", 30))
+ interval:value("60", translatef("%d minute", 1))
+ interval:value("300", translatef("%d minutes", 5))
+ interval:value("600", translatef("%d minutes", 10))
+ interval:value("900", translatef("%d minutes", 15))
+ interval:value("1800", translatef("%d minutes", 30))
+ interval:value("3600", translatef("%d hour", 1))
+
+failure = mwan_interface:option(Value, "failure_interval", translate("Failure interval"),
+ translate("Ping interval during failure detection"))
+ failure.default = "5"
+ failure:value("1", translatef("%d second", 1))
+ failure:value("3", translatef("%d seconds", 3))
+ failure:value("5", translatef("%d seconds", 5))
+ failure:value("10", translatef("%d seconds", 10))
+ failure:value("20", translatef("%d seconds", 20))
+ failure:value("30", translatef("%d seconds", 30))
+ failure:value("60", translatef("%d minute", 1))
+ failure:value("300", translatef("%d minutes", 5))
+ failure:value("600", translatef("%d minutes", 10))
+ failure:value("900", translatef("%d minutes", 15))
+ failure:value("1800", translatef("%d minutes", 30))
+ failure:value("3600", translatef("%d hour", 1))
+
+recovery = mwan_interface:option(Value, "recovery_interval", translate("Recovery interval"),
+ translate("Ping interval during failure recovering"))
+ recovery.default = "5"
+ recovery:value("1", translatef("%d second", 1))
+ recovery:value("3", translatef("%d seconds", 3))
+ recovery:value("5", translatef("%d seconds", 5))
+ recovery:value("10", translatef("%d seconds", 10))
+ recovery:value("20", translatef("%d seconds", 20))
+ recovery:value("30", translatef("%d seconds", 30))
+ recovery:value("60", translatef("%d minute", 1))
+ recovery:value("300", translatef("%d minutes", 5))
+ recovery:value("600", translatef("%d minutes", 10))
+ recovery:value("900", translatef("%d minutes", 15))
+ recovery:value("1800", translatef("%d minutes", 30))
+ recovery:value("3600", translatef("%d hour", 1))
+
+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")
+
+flush = mwan_interface:option(ListValue, "flush_conntrack", translate("Flush conntrack table"),
+ translate("Flush global firewall conntrack table on interface events"))
+ flush.default = "never"
+ flush:value("ifup", translate("ifup"))
+ flush:value("ifdown", translate("ifdown"))
+ flush:value("never", translate("never"))
+ flush:value("always", translate("always"))
+
+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 "&#8212;"
+ end
+ end
+
+
+return m5
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/member.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/member.lua
new file mode 100644
index 0000000000..3bccbd942f
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/member.lua
@@ -0,0 +1,46 @@
+-- ------ 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 "&#8212;"
+ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/memberconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/memberconfig.lua
new file mode 100644
index 0000000000..181d22e06f
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/memberconfig.lua
@@ -0,0 +1,47 @@
+-- ------ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua
new file mode 100644
index 0000000000..e141d696a9
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua
@@ -0,0 +1,95 @@
+-- ------ 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 "&#8212;"
+ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policyconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policyconfig.lua
new file mode 100644
index 0000000000..f48a104c67
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policyconfig.lua
@@ -0,0 +1,65 @@
+-- ------ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua
new file mode 100644
index 0000000000..a22e01054c
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua
@@ -0,0 +1,141 @@
+-- ------ 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 -p /var/state get mwan3." .. section[".name"] .. ".src_port"))
+ local destPort = ut.trim(sys.exec("uci -p /var/state get mwan3." .. section[".name"] .. ".dest_port"))
+ if sourcePort ~= "" or destPort ~= "" then -- ports configured
+ local protocol = ut.trim(sys.exec("uci -p /var/state get 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 "&#8212;"
+ 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 "&#8212;"
+ 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 "&#8212;"
+ 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 "&#8212;"
+ 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
+
+sticky = mwan_rule:option(DummyValue, "sticky", translate("Sticky"))
+ sticky.rawhtml = true
+ function sticky.cfgvalue(self, s)
+ if self.map:get(s, "sticky") == "1" then
+ stickied = 1
+ return "Yes"
+ else
+ stickied = nil
+ return "No"
+ end
+ end
+
+timeout = mwan_rule:option(DummyValue, "timeout", translate("Sticky timeout"))
+ timeout.rawhtml = true
+ function timeout.cfgvalue(self, s)
+ if stickied then
+ local timeoutValue = self.map:get(s, "timeout")
+ if timeoutValue then
+ return timeoutValue .. "s"
+ else
+ return "600s"
+ end
+ else
+ return "&#8212;"
+ end
+ end
+
+ipset = mwan_rule:option(DummyValue, "ipset", translate("IPset"))
+ ipset.rawhtml = true
+ function ipset.cfgvalue(self, s)
+ return self.map:get(s, "ipset") or "&#8212;"
+ 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 "&#8212;"
+ 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
diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/ruleconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/ruleconfig.lua
new file mode 100644
index 0000000000..f7fb341e1f
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/ruleconfig.lua
@@ -0,0 +1,113 @@
+-- ------ extra functions ------ --
+
+function ruleCheck() -- determine if rule needs a protocol specified
+ local sourcePort = ut.trim(sys.exec("uci -p /var/state get mwan3." .. arg[1] .. ".src_port"))
+ local destPort = ut.trim(sys.exec("uci -p /var/state get mwan3." .. arg[1] .. ".dest_port"))
+ if sourcePort ~= "" or destPort ~= "" then -- ports configured
+ local protocol = ut.trim(sys.exec("uci -p /var/state get 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)
+
+sticky = mwan_rule:option(ListValue, "sticky", translate("Sticky"),
+ translate("Traffic from the same source IP address that previously matched this rule within the sticky timeout period will use the same WAN interface"))
+ sticky.default = "0"
+ sticky:value("1", translate("Yes"))
+ sticky:value("0", translate("No"))
+
+timeout = mwan_rule:option(Value, "timeout", translate("Sticky timeout"),
+ translate("Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set"))
+ timeout.datatype = "range(1, 1000000)"
+
+ipset = mwan_rule:option(Value, "ipset", translate("IPset"),
+ translate("Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/youtube.com/youtube\")"))
+
+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
diff --git a/applications/luci-app-mwan3/luasrc/view/admin_status/index/mwan.htm b/applications/luci-app-mwan3/luasrc/view/admin_status/index/mwan.htm
new file mode 100644
index 0000000000..53b997af90
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/admin_status/index/mwan.htm
@@ -0,0 +1 @@
+<%+mwan/openwrt_overview_status%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_diagnostics.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_diagnostics.htm
new file mode 100644
index 0000000000..14d404bc7c
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_diagnostics.htm
@@ -0,0 +1,129 @@
+<%+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/wirelessconfig")%>"><%:Wireless 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%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_hotplugscript.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_hotplugscript.htm
new file mode 100644
index 0000000000..4c2a0dc208
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_hotplugscript.htm
@@ -0,0 +1,24 @@
+<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/wirelessconfig")%>"><%:Wireless 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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_mwanconfig.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_mwanconfig.htm
new file mode 100644
index 0000000000..fba3fa6940
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_mwanconfig.htm
@@ -0,0 +1,24 @@
+<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/wirelessconfig")%>"><%:Wireless 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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_networkconfig.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_networkconfig.htm
new file mode 100644
index 0000000000..cf90112078
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_networkconfig.htm
@@ -0,0 +1,24 @@
+<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/wirelessconfig")%>"><%:Wireless 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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_troubleshooting.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_troubleshooting.htm
new file mode 100644
index 0000000000..0a12496899
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_troubleshooting.htm
@@ -0,0 +1,74 @@
+<%+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/wirelessconfig")%>"><%:Wireless 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 &#34;cat /etc/config/mwan3&#34; : </span><br /><br />';
+ var netConfig = '<br /><br /><span class="description">Output of &#34;cat /etc/config/network&#34; : </span><br /><br />';
+ var wifiConfig = '<br /><br /><span class="description">Output of &#34;cat /etc/config/wireless&#34; : </span><br /><br />';
+ var ifconfig = '<br /><br /><span class="description">Output of &#34;ifconfig&#34; : </span><br /><br />';
+ var ipRoute = '<br /><br /><span class="description">Output of &#34;route -n&#34; : </span><br /><br />';
+ var ipRuleShow = '<br /><br /><span class="description">Output of &#34;ip rule show&#34; : </span><br /><br />';
+ var routeListTable = '<br /><br /><span class="description">Output of &#34;ip route list table 1-250&#34; : </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 &#34;iptables -L -t mangle -v -n&#34; : </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%s%s</pre>',
+ versions, mArray.versions[0], mwanConfig, mArray.mwanconfig[0], netConfig, mArray.netconfig[0],
+ wifiConfig, mArray.wificonfig[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%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/advanced_wirelessconfig.htm b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_wirelessconfig.htm
new file mode 100644
index 0000000000..5077674185
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/advanced_wirelessconfig.htm
@@ -0,0 +1,24 @@
+<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/wirelessconfig")%>"><%:Wireless 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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/config_css.htm b/applications/luci-app-mwan3/luasrc/view/mwan/config_css.htm
new file mode 100644
index 0000000000..99da4875b0
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/config_css.htm
@@ -0,0 +1,34 @@
+<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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/openwrt_overview_status.htm b/applications/luci-app-mwan3/luasrc/view/mwan/openwrt_overview_status.htm
new file mode 100644
index 0000000000..9329b92735
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/openwrt_overview_status.htm
@@ -0,0 +1,83 @@
+<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>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/overview_detailed.htm b/applications/luci-app-mwan3/luasrc/view/mwan/overview_detailed.htm
new file mode 100644
index 0000000000..b80b9f3acf
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/overview_detailed.htm
@@ -0,0 +1,51 @@
+<%+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%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/overview_interface.htm b/applications/luci-app-mwan3/luasrc/view/mwan/overview_interface.htm
new file mode 100644
index 0000000000..472c7ce7fc
--- /dev/null
+++ b/applications/luci-app-mwan3/luasrc/view/mwan/overview_interface.htm
@@ -0,0 +1,122 @@
+<%+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%>
diff --git a/applications/luci-app-mwan3/po/ja/mwan3.po b/applications/luci-app-mwan3/po/ja/mwan3.po
new file mode 100644
index 0000000000..2df8fead33
--- /dev/null
+++ b/applications/luci-app-mwan3/po/ja/mwan3.po
@@ -0,0 +1,519 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 2.0\n"
+"Last-Translator: INAGAKI Hiroshi <musashino.open@gmail.com>\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Language: ja\n"
+
+msgid "%d hour"
+msgstr "%d 時間"
+
+msgid "%d minute"
+msgstr "%d 分"
+
+msgid "%d minutes"
+msgstr "%d 分"
+
+msgid "%d second"
+msgstr "%d 秒"
+
+msgid "%d seconds"
+msgstr "%d 秒"
+
+msgid ""
+"Acceptable values: 1-100. This many Tracking IP addresses must respond for "
+"the link to be deemed up"
+msgstr ""
+"利用可能な値: 1-100。上記の追跡 IP の合計個数のうち、Up 状態と判定するために"
+"に必要な、レスポンスが返された追跡 IP アドレスの個数です。"
+
+msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
+msgstr "利用可能な値: 1-1000。空欄の場合のデフォルトは1です。"
+
+msgid "Advanced"
+msgstr "詳細設定"
+
+msgid "Check IP rules"
+msgstr "IP ルールのチェック"
+
+msgid "Check routing table"
+msgstr "ルーティング テーブルのチェック"
+
+msgid "Configuration"
+msgstr "設定"
+
+msgid "Currently Configured Interfaces"
+msgstr "設定済みインターフェース"
+
+msgid "Currently Configured Members"
+msgstr "設定済みメンバー"
+
+msgid "Currently Configured Policies"
+msgstr "設定済みポリシー"
+
+msgid "Destination address"
+msgstr "宛先アドレス"
+
+msgid "Destination port"
+msgstr "宛先ポート"
+
+msgid "Detailed Status"
+msgstr "詳細ステータス"
+
+msgid "Diagnostic Results"
+msgstr "診断結果"
+
+msgid "Diagnostics"
+msgstr "診断機能"
+
+msgid ""
+"Downed interface will be deemed up after this many successful ping tests"
+msgstr ""
+"Down 状態のインターフェースが Up 状態と判断されるまでに要する ping テストの成"
+"功回数です。"
+
+msgid "Enabled"
+msgstr "有効"
+
+msgid "Errors"
+msgstr "エラー"
+
+msgid "Failure interval"
+msgstr "障害検出 インターバル"
+
+msgid "Flush conntrack table"
+msgstr ""
+
+msgid "Flush global firewall conntrack table on interface events"
+msgstr ""
+
+msgid "Hotplug Script"
+msgstr "ホットプラグ スクリプト"
+
+msgid "Hotplug ifdown"
+msgstr "ホットプラグ ifdown"
+
+msgid "Hotplug ifup"
+msgstr "ホットプラグ ifup"
+
+msgid "IPset"
+msgstr "IPset"
+
+msgid "IPv4"
+msgstr "IPv4"
+
+msgid "IPv6"
+msgstr "IPv6"
+
+msgid "Interface"
+msgstr "インターフェース"
+
+msgid "Interface Status"
+msgstr "インターフェース ステータス"
+
+msgid "Interface down"
+msgstr "インターフェース Down"
+
+msgid "Interface up"
+msgstr "インターフェース Up"
+
+msgid "Interface will be deemed down after this many failed ping tests"
+msgstr ""
+"インターフェースが Down 状態と判断されるまでに要する ping テストの失敗回数で"
+"す。"
+
+msgid "Interfaces"
+msgstr "インターフェース"
+
+msgid "Internet Protocol"
+msgstr "インターネット プロトコル"
+
+msgid "Last resort"
+msgstr "最終手段"
+
+msgid "Load Balancing"
+msgstr "負荷分散"
+
+msgid "Loading"
+msgstr "読込中"
+
+msgid "MWAN Config"
+msgstr "MWAN 設定"
+
+msgid "MWAN Detailed Status"
+msgstr "MWAN 詳細ステータス"
+
+msgid "MWAN Interface Configuration"
+msgstr "MWAN インターフェース設定"
+
+msgid "MWAN Interface Configuration -"
+msgstr "MWAN インターフェース設定 -"
+
+msgid "MWAN Interface Diagnostics"
+msgstr "MWAN インターフェース診断"
+
+msgid "MWAN Interface Live Status"
+msgstr "MWAN インターフェース Live ステータス"
+
+msgid "MWAN Interface Systemlog"
+msgstr "MWAN インターフェース システムログ"
+
+msgid "MWAN Member Configuration"
+msgstr "MWAN メンバー設定"
+
+msgid "MWAN Member Configuration -"
+msgstr "MWAN メンバー設定 -"
+
+msgid "MWAN Policy Configuration"
+msgstr "MWAN ポリシー設定"
+
+msgid "MWAN Policy Configuration -"
+msgstr "MWAN ポリシー設定 -"
+
+msgid "MWAN Rule Configuration"
+msgstr "MWAN ルール設定"
+
+msgid "MWAN Rule Configuration -"
+msgstr "MWAN ルール設定 -"
+
+msgid "MWAN Service Control"
+msgstr "MWAN サービス コントロール"
+
+msgid ""
+"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"
+msgstr ""
+"MWAN は、250個までの物理または論理、あるいは両方のインターフェースをサポート"
+"します。<br />MWAN は、全てのインターフェースが /etc/config/network で設定さ"
+"れるユニークなメトリックを持つことを必要とします。<br />下記 \"インターフェー"
+"ス\" の名前は、 /etc/config/network に存在するインターフェース名と同じでなけ"
+"ればなりません(詳細設定タブを確認)。<br />名前は A-Z, a-z, 0-9, _ を含むこ"
+"とができますが、スペースは使用できません。<br />インターフェースには、設定済"
+"みのメンバーやポリシー、ルールと同じ名前を使用することはできません。"
+
+msgid ""
+"May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or "
+"as a portrange (eg \"1024:2048\") without quotes"
+msgstr ""
+"単一または複数のポート(例: \"22\" または \"80,443\")、あるいはポートの範囲"
+"(例: \"1024:2048\")を、クオーテーション無しで指定することができます。"
+
+msgid "Member used"
+msgstr "使用されるメンバー"
+
+msgid "Members"
+msgstr "メンバー"
+
+msgid ""
+"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"
+msgstr ""
+"メンバーは、MWAN インターフェースのメトリックおよびウエイトを関連付けたプロ"
+"ファイルです。<br />名前は A-Z, a-z, 0-9, _ を含むことができますが、スペース"
+"は使用できません。<br />メンバーには、設定済みのインターフェースやポリシー、"
+"ルールと同じ名前を使用することはできません。"
+
+msgid "Members assigned"
+msgstr "アサイン済みメンバー"
+
+msgid "Metric"
+msgstr "メトリック"
+
+msgid ""
+"Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/"
+"youtube.com/youtube\")"
+msgstr ""
+"IPset ルールの名前です。このルールは、 /etc/dnsmasq.conf で必要です。(例: "
+"\"ipset=/youtube.com/youtube\")"
+
+msgid "Network Config"
+msgstr "ネットワーク設定"
+
+msgid "No"
+msgstr "いいえ"
+
+msgid "Overview"
+msgstr "概要"
+
+msgid "Ping count"
+msgstr "Ping 回数"
+
+msgid "Ping default gateway"
+msgstr "Ping デフォルト ゲートウェイ"
+
+msgid "Ping interval"
+msgstr "Ping インターバル"
+
+msgid "Ping interval during failure detection"
+msgstr "障害検出動作中の Ping 実行間隔です。"
+
+msgid "Ping interval during failure recovering"
+msgstr "障害復旧中の Ping 実行間隔です。"
+
+msgid "Ping size"
+msgstr "Ping サイズ"
+
+msgid "Ping timeout"
+msgstr "Ping タイムアウト"
+
+msgid "Ping tracking IP"
+msgstr "Ping トラッキング IP"
+
+msgid "Policies"
+msgstr "ポリシー"
+
+msgid ""
+"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"
+msgstr ""
+"ポリシーは、MWANがどのようにトラフィックの分配を行うかを制御する、1つ以上のメ"
+"ンバーをグループ化するプロファイルです。<br />最小のメトリックを持つメンバー "
+"インターフェースが最初に使用されます。同じメトリックを持つ複数のインター"
+"フェースでは、負荷分散を行います。<br />負荷分散に設定されたメンバー インター"
+"フェースでは、ウェイトの値が大きい方により多くのトラフィックを分配します。"
+"<br />名前は A-Z, a-z, 0-9, _ を含むことができますが、スペースは使用できませ"
+"ん。また、15文字以内でなければなりません。<br />ポリシーでは、設定済みのイン"
+"ターフェースやメンバー、ルールと同じ名前を使用することはできません。"
+
+msgid "Policy assigned"
+msgstr "アサイン済みポリシー"
+
+msgid "Protocol"
+msgstr "プロトコル"
+
+msgid "Recovery interval"
+msgstr "障害復旧 インターバル"
+
+msgid "Restart MWAN"
+msgstr "MWAN の再起動"
+
+msgid "Restore default hotplug script"
+msgstr "デフォルトのホットプラグ スクリプトの復元"
+
+msgid "Restore..."
+msgstr "復元..."
+
+msgid "Rules"
+msgstr "ルール"
+
+msgid ""
+"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"
+msgstr ""
+"ルールは IP アドレスやポート、プロトコルを基に、トラフィックがどの MWAN ポリ"
+"シーを使用するかを設定します。<br />ルールは上から下へマッチングが行われ、合"
+"致したルールより下のルールは無視されます。全てのルールに合致しないトラフィッ"
+"クは、メインのルーティング テーブルを使用してルートが決定されます。<br />既知"
+"(デフォルト以外)のネットワークへのトラフィックは、メインのルーティング テー"
+"ブルによって制御されます。ルールに合致したトラフィックでも、当該ポリシーの全 "
+"WAN インターフェースが Down 状態の場合は blackhole 状態となります。<br />名前"
+"は A-Z, a-z, 0-9, _ を含むことができますが、スペースは使用できません。<br />"
+"ルールは、設定済みのインターフェースやメンバー、ポリシーと同じ名前を使用する"
+"ことはできません。"
+
+msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set"
+msgstr "秒。利用可能な値: 1-1000000。空欄の場合のデフォルト値は600です。"
+
+msgid "Source address"
+msgstr "送信元アドレス"
+
+msgid "Source port"
+msgstr "送信元ポート"
+
+msgid "Start MWAN"
+msgstr "MWAN の起動"
+
+msgid "Sticky"
+msgstr "Sticky"
+
+msgid "Sticky timeout"
+msgstr "Sticky タイムアウト"
+
+msgid "Stop MWAN"
+msgstr "MWAN の停止"
+
+msgid "Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"
+msgstr "CIDR 表記のサポート(例: \"192.168.100.0/24\")"
+
+msgid ""
+"This IP address will be pinged to dermine if the link is up or down. Leave "
+"blank to assume interface is always online"
+msgstr ""
+"これらは、リンクの Up または Down を判定するために Ping が送信されるIP アドレ"
+"スです。常にオンラインとする場合、空欄のままにします。"
+
+msgid ""
+"This displays the metric assigned to this interface in /etc/config/network"
+msgstr ""
+"/etc/config/network で、このインターフェースに割り当てられたメトリックです。"
+
+msgid "This section allows you to modify the contents of /etc/config/mwan3"
+msgstr ""
+"このセクションでは、 /etc/config/mwan3 の内容を変更することができます。"
+
+msgid "This section allows you to modify the contents of /etc/config/network"
+msgstr ""
+"このセクションでは、 /etc/config/network の内容を変更することができます。"
+
+msgid "This section allows you to modify the contents of /etc/config/wireless"
+msgstr ""
+"このセクションでは、 /etc/config/wireless の内容を変更することができます。"
+
+msgid ""
+"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 &#34;#!/bin/sh&#34; 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.)"
+msgstr ""
+"このセクションでは、 /etc/hotplug.d/iface/16-mwancustom の内容を変更すること"
+"ができます。<br />これは、インターフェースの ifup または ifdown ホットプラグ "
+"イベント時にシステムコマンドまたはスクリプト、もしくはその両方を実行すること"
+"に役立ちます。<br /><br />注意:<br />スクリプトの1行目は、&#34;#!bin/sh&#34; "
+"である必要があります(クオーテーション不要)。<br /># で始まる行はコメントと"
+"して認識され、実行されません。<br /><br />利用可能な変数:<br />$ACTION - ホッ"
+"トプラグ イベント (ifup, ifdown)<br />$INTERFACE - インターフェース名(wan1, "
+"wan2, その他)<br />$DEVICE - インターフェースにアタッチされたデバイスの名前"
+"(eth0.1, eth1, その他)"
+
+msgid "Tracking IP"
+msgstr "追跡 IP"
+
+msgid "Tracking reliability"
+msgstr "追跡の信頼性"
+
+msgid "Traffic Rules"
+msgstr "トラフィック ルール"
+
+msgid ""
+"Traffic from the same source IP address that previously matched this rule "
+"within the sticky timeout period will use the same WAN interface"
+msgstr ""
+"以前このルールにマッチした同じアクセス元 IP アドレスからのトラフィックが、再"
+"度 Sticky 制限時間内にマッチした場合には、同じ WAN インターフェースが使用され"
+"ます。"
+
+msgid "Troubleshooting"
+msgstr "トラブルシューティング"
+
+msgid "Troubleshooting Data"
+msgstr "トラブルシューティング データ"
+
+msgid "View the contents of /etc/protocols for protocol descriptions"
+msgstr "プロトコルの説明については、 /etc/protocols の内容を確認してください。"
+
+msgid "Weight"
+msgstr "ウエイト"
+
+msgid ""
+"When all policy members are offline use this behavior for matched traffic"
+msgstr ""
+"ポリシーの全メンバーがオフラインの場合、合致したトラフィックに対してこのふる"
+"まいが使用されます。"
+
+msgid "Wireless Config"
+msgstr "無線設定"
+
+msgid "Yes"
+msgstr "はい"
+
+msgid "always"
+msgstr "always"
+
+msgid "blackhole (drop)"
+msgstr "blackhole (drop)"
+
+msgid "default (use main routing table)"
+msgstr "デフォルト(メインのルーティング テーブルを使用)"
+
+msgid "ifdown"
+msgstr "ifdown"
+
+msgid "ifup"
+msgstr "ifup"
+
+msgid "never"
+msgstr "never"
+
+msgid "unreachable (reject)"
+msgstr "unreachable (reject)"
+
+#~ msgid "1 hour"
+#~ msgstr "1時間"
+
+#~ msgid "1 minute"
+#~ msgstr "1分"
+
+#~ msgid "1 second"
+#~ msgstr "1秒"
+
+#~ msgid "10 minutes"
+#~ msgstr "10分"
+
+#~ msgid "10 seconds"
+#~ msgstr "10秒"
+
+#~ msgid "15 minutes"
+#~ msgstr "15分"
+
+#~ msgid "2 seconds"
+#~ msgstr "2秒"
+
+#~ msgid "20 seconds"
+#~ msgstr "20秒"
+
+#~ msgid "3 seconds"
+#~ msgstr "3秒"
+
+#~ msgid "30 minutes"
+#~ msgstr "30分"
+
+#~ msgid "30 seconds"
+#~ msgstr "30秒"
+
+#~ msgid "4 seconds"
+#~ msgstr "4秒"
+
+#~ msgid "5 minutes"
+#~ msgstr "5分"
+
+#~ msgid "5 seconds"
+#~ msgstr "5秒"
+
+#~ msgid "6 seconds"
+#~ msgstr "6秒"
+
+#~ msgid "7 seconds"
+#~ msgstr "7秒"
+
+#~ msgid "8 seconds"
+#~ msgstr "8秒"
+
+#~ msgid "9 seconds"
+#~ msgstr "9秒"
diff --git a/applications/luci-app-mwan3/po/templates/mwan3.pot b/applications/luci-app-mwan3/po/templates/mwan3.pot
new file mode 100644
index 0000000000..0b423c85a5
--- /dev/null
+++ b/applications/luci-app-mwan3/po/templates/mwan3.pot
@@ -0,0 +1,395 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+msgid "%d hour"
+msgstr ""
+
+msgid "%d minute"
+msgstr ""
+
+msgid "%d minutes"
+msgstr ""
+
+msgid "%d second"
+msgstr ""
+
+msgid "%d seconds"
+msgstr ""
+
+msgid ""
+"Acceptable values: 1-100. This many Tracking IP addresses must respond for "
+"the link to be deemed up"
+msgstr ""
+
+msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
+msgstr ""
+
+msgid "Advanced"
+msgstr ""
+
+msgid "Check IP rules"
+msgstr ""
+
+msgid "Check routing table"
+msgstr ""
+
+msgid "Configuration"
+msgstr ""
+
+msgid "Currently Configured Interfaces"
+msgstr ""
+
+msgid "Currently Configured Members"
+msgstr ""
+
+msgid "Currently Configured Policies"
+msgstr ""
+
+msgid "Destination address"
+msgstr ""
+
+msgid "Destination port"
+msgstr ""
+
+msgid "Detailed Status"
+msgstr ""
+
+msgid "Diagnostic Results"
+msgstr ""
+
+msgid "Diagnostics"
+msgstr ""
+
+msgid ""
+"Downed interface will be deemed up after this many successful ping tests"
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Errors"
+msgstr ""
+
+msgid "Failure interval"
+msgstr ""
+
+msgid "Flush conntrack table"
+msgstr ""
+
+msgid "Flush global firewall conntrack table on interface events"
+msgstr ""
+
+msgid "Hotplug Script"
+msgstr ""
+
+msgid "Hotplug ifdown"
+msgstr ""
+
+msgid "Hotplug ifup"
+msgstr ""
+
+msgid "IPset"
+msgstr ""
+
+msgid "IPv4"
+msgstr ""
+
+msgid "IPv6"
+msgstr ""
+
+msgid "Interface"
+msgstr ""
+
+msgid "Interface Status"
+msgstr ""
+
+msgid "Interface down"
+msgstr ""
+
+msgid "Interface up"
+msgstr ""
+
+msgid "Interface will be deemed down after this many failed ping tests"
+msgstr ""
+
+msgid "Interfaces"
+msgstr ""
+
+msgid "Internet Protocol"
+msgstr ""
+
+msgid "Last resort"
+msgstr ""
+
+msgid "Load Balancing"
+msgstr ""
+
+msgid "Loading"
+msgstr ""
+
+msgid "MWAN Config"
+msgstr ""
+
+msgid "MWAN Detailed Status"
+msgstr ""
+
+msgid "MWAN Interface Configuration"
+msgstr ""
+
+msgid "MWAN Interface Configuration -"
+msgstr ""
+
+msgid "MWAN Interface Diagnostics"
+msgstr ""
+
+msgid "MWAN Interface Live Status"
+msgstr ""
+
+msgid "MWAN Interface Systemlog"
+msgstr ""
+
+msgid "MWAN Member Configuration"
+msgstr ""
+
+msgid "MWAN Member Configuration -"
+msgstr ""
+
+msgid "MWAN Policy Configuration"
+msgstr ""
+
+msgid "MWAN Policy Configuration -"
+msgstr ""
+
+msgid "MWAN Rule Configuration"
+msgstr ""
+
+msgid "MWAN Rule Configuration -"
+msgstr ""
+
+msgid "MWAN Service Control"
+msgstr ""
+
+msgid ""
+"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"
+msgstr ""
+
+msgid ""
+"May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or "
+"as a portrange (eg \"1024:2048\") without quotes"
+msgstr ""
+
+msgid "Member used"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid ""
+"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"
+msgstr ""
+
+msgid "Members assigned"
+msgstr ""
+
+msgid "Metric"
+msgstr ""
+
+msgid ""
+"Name of IPset rule. Requires IPset rule in /etc/dnsmasq.conf (eg \"ipset=/"
+"youtube.com/youtube\")"
+msgstr ""
+
+msgid "Network Config"
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Ping count"
+msgstr ""
+
+msgid "Ping default gateway"
+msgstr ""
+
+msgid "Ping interval"
+msgstr ""
+
+msgid "Ping interval during failure detection"
+msgstr ""
+
+msgid "Ping interval during failure recovering"
+msgstr ""
+
+msgid "Ping size"
+msgstr ""
+
+msgid "Ping timeout"
+msgstr ""
+
+msgid "Ping tracking IP"
+msgstr ""
+
+msgid "Policies"
+msgstr ""
+
+msgid ""
+"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"
+msgstr ""
+
+msgid "Policy assigned"
+msgstr ""
+
+msgid "Protocol"
+msgstr ""
+
+msgid "Recovery interval"
+msgstr ""
+
+msgid "Restart MWAN"
+msgstr ""
+
+msgid "Restore default hotplug script"
+msgstr ""
+
+msgid "Restore..."
+msgstr ""
+
+msgid "Rules"
+msgstr ""
+
+msgid ""
+"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"
+msgstr ""
+
+msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set"
+msgstr ""
+
+msgid "Source address"
+msgstr ""
+
+msgid "Source port"
+msgstr ""
+
+msgid "Start MWAN"
+msgstr ""
+
+msgid "Sticky"
+msgstr ""
+
+msgid "Sticky timeout"
+msgstr ""
+
+msgid "Stop MWAN"
+msgstr ""
+
+msgid "Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"
+msgstr ""
+
+msgid ""
+"This IP address will be pinged to dermine if the link is up or down. Leave "
+"blank to assume interface is always online"
+msgstr ""
+
+msgid ""
+"This displays the metric assigned to this interface in /etc/config/network"
+msgstr ""
+
+msgid "This section allows you to modify the contents of /etc/config/mwan3"
+msgstr ""
+
+msgid "This section allows you to modify the contents of /etc/config/network"
+msgstr ""
+
+msgid "This section allows you to modify the contents of /etc/config/wireless"
+msgstr ""
+
+msgid ""
+"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 &#34;#!/bin/sh&#34; 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.)"
+msgstr ""
+
+msgid "Tracking IP"
+msgstr ""
+
+msgid "Tracking reliability"
+msgstr ""
+
+msgid "Traffic Rules"
+msgstr ""
+
+msgid ""
+"Traffic from the same source IP address that previously matched this rule "
+"within the sticky timeout period will use the same WAN interface"
+msgstr ""
+
+msgid "Troubleshooting"
+msgstr ""
+
+msgid "Troubleshooting Data"
+msgstr ""
+
+msgid "View the contents of /etc/protocols for protocol descriptions"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid ""
+"When all policy members are offline use this behavior for matched traffic"
+msgstr ""
+
+msgid "Wireless Config"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "always"
+msgstr ""
+
+msgid "blackhole (drop)"
+msgstr ""
+
+msgid "default (use main routing table)"
+msgstr ""
+
+msgid "ifdown"
+msgstr ""
+
+msgid "ifup"
+msgstr ""
+
+msgid "never"
+msgstr ""
+
+msgid "unreachable (reject)"
+msgstr ""
diff --git a/applications/luci-app-mwan3/root/etc/hotplug.d/iface/16-mwancustombak b/applications/luci-app-mwan3/root/etc/hotplug.d/iface/16-mwancustombak
new file mode 100755
index 0000000000..6e2875e3de
--- /dev/null
+++ b/applications/luci-app-mwan3/root/etc/hotplug.d/iface/16-mwancustombak
@@ -0,0 +1,38 @@
+#!/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 -p /var/state get 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
diff --git a/applications/luci-app-mwan3/root/etc/uci-defaults/60_luci-mwan3 b/applications/luci-app-mwan3/root/etc/uci-defaults/60_luci-mwan3
new file mode 100755
index 0000000000..ff9a229edd
--- /dev/null
+++ b/applications/luci-app-mwan3/root/etc/uci-defaults/60_luci-mwan3
@@ -0,0 +1,14 @@
+#!/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
diff --git a/applications/luci-app-simple-adblock/Makefile b/applications/luci-app-simple-adblock/Makefile
new file mode 100644
index 0000000000..d7be6850ba
--- /dev/null
+++ b/applications/luci-app-simple-adblock/Makefile
@@ -0,0 +1,16 @@
+# Copyright (c) 2017 Stan Grishin (stangri@melmac.net)
+# This is free software, licensed under the GNU General Public License v3.
+
+include $(TOPDIR)/rules.mk
+
+PKG_LICENSE:=GPL-3.0+
+PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
+
+LUCI_TITLE:=Simple Adblock Web UI
+LUCI_DEPENDS:=+simple-adblock
+LUCI_PKGARCH:=all
+PKG_RELEASE:=2
+
+include ../../luci.mk
+
+# call BuildPackage - OpenWrt buildroot signature
diff --git a/applications/luci-app-simple-adblock/luasrc/controller/simpleadblock.lua b/applications/luci-app-simple-adblock/luasrc/controller/simpleadblock.lua
new file mode 100644
index 0000000000..46125b3098
--- /dev/null
+++ b/applications/luci-app-simple-adblock/luasrc/controller/simpleadblock.lua
@@ -0,0 +1,7 @@
+module("luci.controller.simpleadblock", package.seeall)
+function index()
+ if not nixio.fs.access("/etc/config/simple-adblock") then
+ return
+ end
+ entry({"admin", "services", "simpleadblock"}, cbi("simpleadblock"), _("Simple AdBlock"))
+end
diff --git a/applications/luci-app-simple-adblock/luasrc/model/cbi/simpleadblock.lua b/applications/luci-app-simple-adblock/luasrc/model/cbi/simpleadblock.lua
new file mode 100644
index 0000000000..214f298292
--- /dev/null
+++ b/applications/luci-app-simple-adblock/luasrc/model/cbi/simpleadblock.lua
@@ -0,0 +1,79 @@
+m = Map("simple-adblock", translate("Simple AdBlock Settings"))
+s = m:section(NamedSection, "config", "simple-adblock")
+
+-- General options
+e = s:option(Flag, "enabled", translate("Enable/start service"))
+e.rmempty = false
+
+function e.cfgvalue(self, section)
+ return self.map:get(section, "enabled") == "1" and luci.sys.init.enabled("simple-adblock") and self.enabled or self.disabled
+end
+
+function e.write(self, section, value)
+ if value == "1" then
+ luci.sys.call("/etc/init.d/simple-adblock enable >/dev/null")
+ luci.sys.call("/etc/init.d/simple-adblock start >/dev/null")
+ else
+ luci.sys.call("/etc/init.d/simple-adblock stop >/dev/null")
+ end
+ return Flag.write(self, section, value)
+end
+
+o2 = s:option(ListValue, "verbosity", translate("Output Verbosity Setting"),translate("Controls system log and console output verbosity"))
+o2:value("0", translate("Suppress output"))
+o2:value("1", translate("Some output"))
+o2:value("2", translate("Verbose output"))
+o2.rmempty = false
+o2.default = 2
+
+o3 = s:option(ListValue, "force_dns", translate("Force Router DNS"), translate("Forces Router DNS use on local devices, also known as DNS Hijacking"))
+o3:value("0", translate("Let local devices use their own DNS servers if set"))
+o3:value("1", translate("Force Router DNS server to all local devices"))
+o3.rmempty = false
+o3.default = 1
+
+
+local sysfs_path = "/sys/class/leds/"
+local leds = {}
+if nixio.fs.access(sysfs_path) then
+ leds = nixio.util.consume((nixio.fs.dir(sysfs_path)))
+end
+if #leds ~= 0 then
+ o3 = s:option(Value, "led", translate("LED to indicate status"), translate("Pick the LED not already used in ")
+ .. [[<a href="]] .. luci.dispatcher.build_url("admin/system/leds") .. [[">]]
+ .. translate("System LED Configuration") .. [[</a>]])
+ o3.rmempty = true
+ o3:value("", translate("none"))
+ for k, v in ipairs(leds) do
+ o3:value(v)
+ end
+end
+
+
+s2 = m:section(NamedSection, "config", "simple-adblock")
+-- Whitelisted Domains
+d1 = s2:option(DynamicList, "whitelist_domain", translate("Whitelisted Domains"), translate("Individual domains to be whitelisted"))
+d1.addremove = false
+d1.optional = false
+
+-- Blacklisted Domains
+d3 = s2:option(DynamicList, "blacklist_domain", translate("Blacklisted Domains"), translate("Individual domains to be blacklisted"))
+d3.addremove = false
+d3.optional = false
+
+-- Whitelisted Domains URLs
+d2 = s2:option(DynamicList, "whitelist_domains_url", translate("Whitelisted Domain URLs"), translate("URLs to lists of domains to be whitelisted"))
+d2.addremove = false
+d2.optional = false
+
+-- Blacklisted Domains URLs
+d4 = s2:option(DynamicList, "blacklist_domains_url", translate("Blacklisted Domain URLs"), translate("URLs to lists of domains to be blacklisted"))
+d4.addremove = false
+d4.optional = false
+
+-- Blacklisted Hosts URLs
+d5 = s2:option(DynamicList, "blacklist_hosts_url", translate("Blacklisted Hosts URLs"), translate("URLs to lists of hosts to be blacklisted"))
+d5.addremove = false
+d5.optional = false
+
+return m
diff --git a/applications/luci-app-simple-adblock/po/ja/simple-adblock.po b/applications/luci-app-simple-adblock/po/ja/simple-adblock.po
new file mode 100644
index 0000000000..7926595b6e
--- /dev/null
+++ b/applications/luci-app-simple-adblock/po/ja/simple-adblock.po
@@ -0,0 +1,93 @@
+msgid ""
+msgstr ""
+"Content-Type: text/plain; charset=UTF-8\n"
+"Project-Id-Version: \n"
+"POT-Creation-Date: \n"
+"PO-Revision-Date: \n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.8.12\n"
+"Last-Translator: INAGAKI Hiroshi <musashino.open@gmail.com>\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+"Language: ja\n"
+
+msgid "Blacklisted Domain URLs"
+msgstr "ドメイン ブラックリストのURL"
+
+msgid "Blacklisted Domains"
+msgstr "ブラックリスト ドメイン"
+
+msgid "Blacklisted Hosts URLs"
+msgstr "hosts ブラックリストのURL"
+
+msgid "Controls system log and console output verbosity"
+msgstr "システム ログとコンソール出力の冗長性を設定します。"
+
+msgid "Enable/start service"
+msgstr "サービスの有効化/開始"
+
+msgid "Force Router DNS"
+msgstr "ルーターDNSの強制"
+
+msgid "Force Router DNS server to all local devices"
+msgstr "全ローカル デバイスにルーター DNSサーバーの使用を強制"
+
+msgid "Forces Router DNS use on local devices, also known as DNS Hijacking"
+msgstr ""
+"ローカル デバイスに対し、ルーター上のDNSサーバーの使用を強制します。これは、"
+"DNS ハイジャックとしても知られています。"
+
+msgid "Individual domains to be blacklisted"
+msgstr "ブラックリストに登録する、個々のドメインです。"
+
+msgid "Individual domains to be whitelisted"
+msgstr "ホワイトリストに登録する、個々のドメインです。"
+
+msgid "LED to indicate status"
+msgstr "ステータスを表示するLED"
+
+msgid "Let local devices use their own DNS servers if set"
+msgstr "DNSサーバーの使用を強制しない"
+
+msgid "Output Verbosity Setting"
+msgstr "出力詳細度の設定"
+
+msgid "Pick the LED not already used in"
+msgstr "右の設定で既に使用されていないLEDを選択します:"
+
+msgid "Simple AdBlock"
+msgstr "Simple AdBlock"
+
+msgid "Simple AdBlock Settings"
+msgstr "Simple AdBlock 設定"
+
+msgid "Some output"
+msgstr "軽量出力"
+
+msgid "Suppress output"
+msgstr "出力の抑制"
+
+msgid "System LED Configuration"
+msgstr "LED 設定"
+
+msgid "URLs to lists of domains to be blacklisted"
+msgstr "ブラックリストに登録するドメインのリストのURLです。"
+
+msgid "URLs to lists of domains to be whitelisted"
+msgstr "ホワイトリストに登録するドメインのリストのURLです。"
+
+msgid "URLs to lists of hosts to be blacklisted"
+msgstr "ブラックリストに登録するドメインが列挙された、hostsファイルのURLです。"
+
+msgid "Verbose output"
+msgstr "詳細出力"
+
+msgid "Whitelisted Domain URLs"
+msgstr "ドメイン ホワイトリストのURL"
+
+msgid "Whitelisted Domains"
+msgstr "ホワイトリスト ドメイン"
+
+msgid "none"
+msgstr "なし"
diff --git a/applications/luci-app-simple-adblock/po/templates/simple-adblock.pot b/applications/luci-app-simple-adblock/po/templates/simple-adblock.pot
new file mode 100644
index 0000000000..4cfff964a3
--- /dev/null
+++ b/applications/luci-app-simple-adblock/po/templates/simple-adblock.pot
@@ -0,0 +1,80 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+msgid "Blacklisted Domain URLs"
+msgstr ""
+
+msgid "Blacklisted Domains"
+msgstr ""
+
+msgid "Blacklisted Hosts URLs"
+msgstr ""
+
+msgid "Controls system log and console output verbosity"
+msgstr ""
+
+msgid "Enable/start service"
+msgstr ""
+
+msgid "Force Router DNS"
+msgstr ""
+
+msgid "Force Router DNS server to all local devices"
+msgstr ""
+
+msgid "Forces Router DNS use on local devices, also known as DNS Hijacking"
+msgstr ""
+
+msgid "Individual domains to be blacklisted"
+msgstr ""
+
+msgid "Individual domains to be whitelisted"
+msgstr ""
+
+msgid "LED to indicate status"
+msgstr ""
+
+msgid "Let local devices use their own DNS servers if set"
+msgstr ""
+
+msgid "Output Verbosity Setting"
+msgstr ""
+
+msgid "Pick the LED not already used in"
+msgstr ""
+
+msgid "Simple AdBlock"
+msgstr ""
+
+msgid "Simple AdBlock Settings"
+msgstr ""
+
+msgid "Some output"
+msgstr ""
+
+msgid "Suppress output"
+msgstr ""
+
+msgid "System LED Configuration"
+msgstr ""
+
+msgid "URLs to lists of domains to be blacklisted"
+msgstr ""
+
+msgid "URLs to lists of domains to be whitelisted"
+msgstr ""
+
+msgid "URLs to lists of hosts to be blacklisted"
+msgstr ""
+
+msgid "Verbose output"
+msgstr ""
+
+msgid "Whitelisted Domain URLs"
+msgstr ""
+
+msgid "Whitelisted Domains"
+msgstr ""
+
+msgid "none"
+msgstr ""
diff --git a/applications/luci-app-simple-adblock/root/etc/uci-defaults/40_luci-simple-adblock b/applications/luci-app-simple-adblock/root/etc/uci-defaults/40_luci-simple-adblock
new file mode 100644
index 0000000000..3b7137e026
--- /dev/null
+++ b/applications/luci-app-simple-adblock/root/etc/uci-defaults/40_luci-simple-adblock
@@ -0,0 +1,10 @@
+#!/bin/sh
+uci -q batch <<-EOF >/dev/null
+ delete ucitrack.@simple-adblock[-1]
+ add ucitrack simple-adblock
+ set ucitrack.@simple-adblock[-1].init=simple-adblock
+ commit ucitrack
+EOF
+
+rm -f /tmp/luci-indexcache
+exit 0
diff --git a/applications/luci-app-vpnbypass/po/pt-br/vpnbypass.po b/applications/luci-app-vpnbypass/po/pt-br/vpnbypass.po
index 5adc5ed4f4..9f3fa2a679 100644
--- a/applications/luci-app-vpnbypass/po/pt-br/vpnbypass.po
+++ b/applications/luci-app-vpnbypass/po/pt-br/vpnbypass.po
@@ -18,8 +18,8 @@ msgstr "Domínios para evitar a VPN"
msgid "Domains to be accessed directly (outside of the VPN tunnel), see"
msgstr ""
-msgid "Enable VPN Bypass"
-msgstr "Habilitar o VPN Bypass"
+msgid "Enable/start service"
+msgstr ""
msgid "Local IP Addresses to Bypass"
msgstr ""
@@ -61,6 +61,9 @@ msgstr "Configurações do VPN Bypass"
msgid "for syntax"
msgstr ""
+#~ msgid "Enable VPN Bypass"
+#~ msgstr "Habilitar o VPN Bypass"
+
#~ msgid "Configuration of VPN Bypass Settings"
#~ msgstr "Configurações do VPN Bypass"