1 -- Copyright 2014 Aedan Renner <chipdankly@gmail.com>
2 -- Copyright 2018 Florian Eckert <fe@dev.tdt.de>
3 -- Licensed to the public under the GNU General Public License v2.
5 module("luci.controller.mwan3", package.seeall)
7 sys = require "luci.sys"
8 ut = require "luci.util"
13 if not nixio.fs.access("/etc/config/mwan3") then
17 entry({"admin", "status", "mwan"},
18 alias("admin", "status", "mwan", "overview"),
19 _("Load Balancing"), 600).acl_depends = { "luci-app-mwan3" }
21 entry({"admin", "status", "mwan", "overview"},
22 template("mwan/status_interface"))
23 entry({"admin", "status", "mwan", "detail"},
24 template("mwan/status_detail"))
25 entry({"admin", "status", "mwan", "diagnostics"},
26 template("mwan/status_diagnostics"))
27 entry({"admin", "status", "mwan", "troubleshooting"},
28 template("mwan/status_troubleshooting"))
29 entry({"admin", "status", "mwan", "interface_status"},
31 entry({"admin", "status", "mwan", "detailed_status"},
32 call("detailedStatus"))
33 entry({"admin", "status", "mwan", "diagnostics_display"},
34 call("diagnosticsData"), nil).leaf = true
35 entry({"admin", "status", "mwan", "troubleshooting_display"},
36 call("troubleshootingData"))
39 entry({"admin", "network", "mwan"},
40 alias("admin", "network", "mwan", "interface"),
41 _("Load Balancing"), 600).acl_depends = { "luci-app-mwan3" }
43 entry({"admin", "network", "mwan", "globals"},
44 cbi("mwan/globalsconfig"),
45 _("Globals"), 5).leaf = true
46 entry({"admin", "network", "mwan", "interface"},
47 arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
48 _("Interfaces"), 10).leaf = true
49 entry({"admin", "network", "mwan", "member"},
50 arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
51 _("Members"), 20).leaf = true
52 entry({"admin", "network", "mwan", "policy"},
53 arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
54 _("Policies"), 30).leaf = true
55 entry({"admin", "network", "mwan", "rule"},
56 arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
57 _("Rules"), 40).leaf = true
58 entry({"admin", "network", "mwan", "notify"},
60 _("Notification"), 50).leaf = true
63 function mwan_Status()
64 local status = ut.ubus("mwan3", "status", {})
66 luci.http.prepare_content("application/json")
68 luci.http.write_json(status)
70 luci.http.write_json({})
74 function detailedStatus()
75 local statusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
76 luci.http.prepare_content("text/plain")
77 if statusInfo ~= "" then
78 luci.http.write(statusInfo)
80 luci.http.write("Unable to get status information")
84 function diagnosticsData(interface, task)
85 function getInterfaceNumber(interface)
88 local uci = require "luci.model.uci".cursor()
89 uci:foreach("mwan3", "interface",
92 if section[".name"] == interface then
93 interfaceNumber = number
97 return interfaceNumber
100 function diag_command(cmd, device, addr)
101 if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
102 local util = io.popen(cmd %{ut.shellquote(device), ut.shellquote(addr)})
104 luci.http.write("Command:\n")
105 luci.http.write(cmd %{ut.shellquote(device),
106 ut.shellquote(addr)} .. "\n\n")
107 luci.http.write("Result:\n")
109 local ln = util:read("*l")
110 if not ln then break end
112 luci.http.write("\n")
120 function get_gateway(interface)
124 dump = require("luci.util").ubus("network.interface.%s_4" % interface, "status", {})
126 dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
129 if dump and dump.route then
131 for _, route in ipairs(dump.route) do
132 if dump.route[_].target == "0.0.0.0" then
133 gateway = dump.route[_].nexthop
142 local number = getInterfaceNumber(interface)
144 local uci = require "luci.model.uci".cursor(nil, "/var/state")
145 local nw = require "luci.model.network".init()
146 local i18n = require "luci.i18n"
147 local network = nw:get_network(interface)
148 local device = network and network:get_interface()
149 device = device:name()
151 luci.http.prepare_content("text/plain")
153 if task == "ping_gateway" then
154 local gateway = get_gateway(interface)
155 if gateway ~= nil then
156 diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, gateway)
158 luci.http.prepare_content("text/plain")
159 luci.http.write(i18n.translatef("No gateway for interface %s found.", interface))
161 elseif task == "ping_trackips" then
162 local trackips = uci:get("mwan3", interface, "track_ip")
163 if #trackips > 0 then
164 for i in pairs(trackips) do
165 diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, trackips[i])
168 luci.http.write(i18n.translatef("No tracking Hosts for interface %s defined.", interface))
170 elseif task == "check_rules" then
171 local number = getInterfaceNumber(interface)
172 local iif = 1000 + number
173 local fwmark = 2000 + number
174 local iif_rule = sys.exec(string.format("ip rule | grep %d", iif))
175 local fwmark_rule = sys.exec(string.format("ip rule | grep %d", fwmark))
176 if iif_rule ~= "" and fwmark_rule ~= "" then
177 luci.http.write(i18n.translatef("All required IP rules for interface %s found", interface))
178 luci.http.write("\n")
179 luci.http.write(fwmark_rule)
180 luci.http.write(iif_rule)
181 elseif iif_rule == "" and fwmark_rule ~= "" then
182 luci.http.write(i18n.translatef("Only one IP rules for interface %s found", interface))
183 luci.http.write("\n")
184 luci.http.write(fwmark_rule)
185 elseif iif_rule ~= "" and fwmark_rule == "" then
186 luci.http.write(i18n.translatef("Only one IP rules for interface %s found", interface))
187 luci.http.write("\n")
188 luci.http.write(iif_rule)
190 luci.http.write(i18n.translatef("Missing both IP rules for interface %s", interface))
192 elseif task == "check_routes" then
193 local number = getInterfaceNumber(interface)
194 local routeTable = sys.exec(string.format("ip route list table %s", number))
195 if routeTable ~= "" then
196 luci.http.write(i18n.translatef("Routing table %s for interface %s found", number, interface))
197 luci.http.write("\n")
198 luci.http.write(routeTable)
200 luci.http.write(i18n.translatef("Routing table %s for interface %s not found", number, interface))
202 elseif task == "hotplug_ifup" then
203 os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface)))
204 luci.http.write(string.format("Hotplug ifup sent to interface %s", interface))
205 elseif task == "hotplug_ifdown" then
206 os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface)))
207 luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface))
209 luci.http.write("Unknown task")
212 luci.http.write(string.format("Unable to perform diagnostic tests on %s.", interface))
213 luci.http.write("\n")
214 luci.http.write("There is no physical or virtual device associated with this interface.")
218 function troubleshootingData()
219 local ver = require "luci.version"
220 local dash = "-------------------------------------------------"
222 luci.http.prepare_content("text/plain")
224 luci.http.write("\n")
225 luci.http.write("\n")
226 luci.http.write("Software-Version")
227 luci.http.write("\n")
228 luci.http.write(dash)
229 luci.http.write("\n")
230 if ver.distversion then
231 luci.http.write(string.format("OpenWrt - %s", ver.distversion))
232 luci.http.write("\n")
234 luci.http.write("OpenWrt - unknown")
235 luci.http.write("\n")
238 if ver.luciversion then
239 luci.http.write(string.format("LuCI - %s", ver.luciversion))
240 luci.http.write("\n")
242 luci.http.write("LuCI - unknown")
243 luci.http.write("\n")
246 luci.http.write("\n")
247 luci.http.write("\n")
248 local output = ut.trim(sys.exec("ip a show"))
249 luci.http.write("Output of \"ip a show\"")
250 luci.http.write("\n")
251 luci.http.write(dash)
252 luci.http.write("\n")
254 luci.http.write(output)
255 luci.http.write("\n")
257 luci.http.write("No data found")
258 luci.http.write("\n")
261 luci.http.write("\n")
262 luci.http.write("\n")
263 local output = ut.trim(sys.exec("ip route show"))
264 luci.http.write("Output of \"ip route show\"")
265 luci.http.write("\n")
266 luci.http.write(dash)
267 luci.http.write("\n")
269 luci.http.write(output)
270 luci.http.write("\n")
272 luci.http.write("No data found")
273 luci.http.write("\n")
276 luci.http.write("\n")
277 luci.http.write("\n")
278 local output = ut.trim(sys.exec("ip rule show"))
279 luci.http.write("Output of \"ip rule show\"")
280 luci.http.write("\n")
281 luci.http.write(dash)
282 luci.http.write("\n")
284 luci.http.write(output)
285 luci.http.write("\n")
287 luci.http.write("No data found")
288 luci.http.write("\n")
291 luci.http.write("\n")
292 luci.http.write("\n")
293 luci.http.write("Output of \"ip route list table 1-250\"")
294 luci.http.write("\n")
295 luci.http.write(dash)
296 luci.http.write("\n")
298 local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
300 luci.http.write(string.format("Table %s: ", i))
301 luci.http.write(output)
302 luci.http.write("\n")
306 luci.http.write("\n")
307 luci.http.write("\n")
308 local output = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
309 luci.http.write("Output of \"iptables -L -t mangle -v -n\"")
310 luci.http.write("\n")
311 luci.http.write(dash)
312 luci.http.write("\n")
314 luci.http.write(output)
315 luci.http.write("\n")
317 luci.http.write("No data found")
318 luci.http.write("\n")