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)
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)
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)})
105 local ln = util:read("*l")
106 if not ln then break end
108 luci.http.write("\n")
116 function get_gateway(inteface)
120 dump = require("luci.util").ubus("network.interface.%s_4" % interface, "status", {})
122 dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
125 if dump and dump.route then
127 for _, route in ipairs(dump.route) do
128 if dump.route[_].target == "0.0.0.0" then
129 gateway = dump.route[_].nexthop
138 local number = getInterfaceNumber(interface)
140 local uci = require "luci.model.uci".cursor(nil, "/var/state")
141 local device = uci:get("network", interface, "ifname")
143 luci.http.prepare_content("text/plain")
145 if task == "ping_gateway" then
146 local gateway = get_gateway(interface)
147 if gateway ~= nil then
148 diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, gateway)
150 luci.http.prepare_content("text/plain")
151 luci.http.write(string.format("No gateway for interface %s found.", interface))
153 elseif task == "ping_trackips" then
154 local trackips = uci:get("mwan3", interface, "track_ip")
155 if #trackips > 0 then
156 for i in pairs(trackips) do
157 diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, trackips[i])
160 luci.http.write(string.format("No tracking Hosts for interface %s defined.", interface))
162 elseif task == "check_rules" then
163 local number = getInterfaceNumber(interface)
164 local iif = 1000 + number
165 local fwmark = 2000 + number
166 local iif_rule = sys.exec(string.format("ip rule | grep %d", iif))
167 local fwmark_rule = sys.exec(string.format("ip rule | grep %d", fwmark))
168 if iif_rule ~= "" and fwmark_rule ~= "" then
169 luci.http.write(string.format("All required IP rules for interface %s found", interface))
170 luci.http.write("\n")
171 luci.http.write(fwmark_rule)
172 luci.http.write(iif_rule)
173 elseif iif_rule == "" and fwmark_rule ~= "" then
174 luci.http.write(string.format("Only one IP rules for interface %s found", interface))
175 luci.http.write("\n")
176 luci.http.write(fwmark_rule)
177 elseif iif_rule ~= "" and fwmark_rule == "" then
178 luci.http.write(string.format("Only one IP rules for interface %s found", interface))
179 luci.http.write("\n")
180 luci.http.write(iif_rule)
182 luci.http.write(string.format("Missing both IP rules for interface %s", interface))
184 elseif task == "check_routes" then
185 local number = getInterfaceNumber(interface)
186 local routeTable = sys.exec(string.format("ip route list table %s", number))
187 if routeTable ~= "" then
188 luci.http.write(string.format("Routing table %s for interface %s found", number, interface))
189 luci.http.write("\n")
190 luci.http.write(routeTable)
192 luci.http.write(string.format("Routing table %s for interface %s not found", number, interface))
194 elseif task == "hotplug_ifup" then
195 os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface)))
196 luci.http.write(string.format("Hotplug ifup sent to interface %s", interface))
197 elseif task == "hotplug_ifdown" then
198 os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface)))
199 luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface))
201 luci.http.write("Unknown task")
204 luci.http.write(string.format("Unable to perform diagnostic tests on %s.", interface))
205 luci.http.write("\n")
206 luci.http.write("There is no physical or virtual device associated with this interface.")
210 function troubleshootingData()
211 local ver = require "luci.version"
212 local dash = "-------------------------------------------------"
214 luci.http.prepare_content("text/plain")
216 luci.http.write("\n")
217 luci.http.write("\n")
218 luci.http.write("Software-Version")
219 luci.http.write("\n")
220 luci.http.write(dash)
221 luci.http.write("\n")
222 if ver.distversion then
223 luci.http.write(string.format("OpenWrt - %s", ver.distversion))
224 luci.http.write("\n")
226 luci.http.write("OpenWrt - unknown")
227 luci.http.write("\n")
230 if ver.luciversion then
231 luci.http.write(string.format("LuCI - %s", ver.luciversion))
232 luci.http.write("\n")
234 luci.http.write("LuCI - unknown")
235 luci.http.write("\n")
238 luci.http.write("\n")
239 luci.http.write("\n")
240 local output = ut.trim(sys.exec("ip a show"))
241 luci.http.write("Output of \"ip a show\"")
242 luci.http.write("\n")
243 luci.http.write(dash)
244 luci.http.write("\n")
246 luci.http.write(output)
247 luci.http.write("\n")
249 luci.http.write("No data found")
250 luci.http.write("\n")
253 luci.http.write("\n")
254 luci.http.write("\n")
255 local output = ut.trim(sys.exec("ip route show"))
256 luci.http.write("Output of \"ip route show\"")
257 luci.http.write("\n")
258 luci.http.write(dash)
259 luci.http.write("\n")
261 luci.http.write(output)
262 luci.http.write("\n")
264 luci.http.write("No data found")
265 luci.http.write("\n")
268 luci.http.write("\n")
269 luci.http.write("\n")
270 local output = ut.trim(sys.exec("ip rule show"))
271 luci.http.write("Output of \"ip rule show\"")
272 luci.http.write("\n")
273 luci.http.write(dash)
274 luci.http.write("\n")
276 luci.http.write(output)
277 luci.http.write("\n")
279 luci.http.write("No data found")
280 luci.http.write("\n")
283 luci.http.write("\n")
284 luci.http.write("\n")
285 luci.http.write("Output of \"ip route list table 1-250\"")
286 luci.http.write("\n")
287 luci.http.write(dash)
288 luci.http.write("\n")
290 local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
292 luci.http.write(string.format("Table %s: ", i))
293 luci.http.write(output)
294 luci.http.write("\n")
298 luci.http.write("\n")
299 luci.http.write("\n")
300 local output = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
301 luci.http.write("Output of \"iptables -L -t mangle -v -n\"")
302 luci.http.write("\n")
303 luci.http.write(dash)
304 luci.http.write("\n")
306 luci.http.write(output)
307 luci.http.write("\n")
309 luci.http.write("No data found")
310 luci.http.write("\n")