luci-app-mwan3: fix legacy uci api usage
[project/luci.git] / applications / luci-app-mwan3 / luasrc / controller / mwan3.lua
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.
4
5 module("luci.controller.mwan3", package.seeall)
6
7 sys = require "luci.sys"
8 ut = require "luci.util"
9
10 ip = "ip -4 "
11
12 function index()
13         if not nixio.fs.access("/etc/config/mwan3") then
14                 return
15         end
16
17         entry({"admin", "status", "mwan"},
18                 alias("admin", "status", "mwan", "overview"),
19                 _("Load Balancing"), 600)
20
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"},
30                 call("mwan_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"))
37
38
39         entry({"admin", "network", "mwan"},
40                 alias("admin", "network", "mwan", "interface"),
41                 _("Load Balancing"), 600)
42
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"},
59                 form("mwan/notify"),
60                 _("Notification"), 50).leaf = true
61 end
62
63 function mwan_Status()
64         local status = ut.ubus("mwan3", "status", {})
65
66         luci.http.prepare_content("application/json")
67         if status ~= nil then
68                 luci.http.write_json(status)
69         else
70                 luci.http.write_json({})
71         end
72 end
73
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)
79         else
80                 luci.http.write("Unable to get status information")
81         end
82 end
83
84 function diagnosticsData(interface, task)
85         function getInterfaceNumber(interface)
86                 local number = 0
87                 local interfaceNumber
88                 uci.cursor():foreach("mwan3", "interface",
89                         function (section)
90                                 number = number+1
91                                 if section[".name"] == interface then
92                                         interfaceNumber = number
93                                 end
94                         end
95                 )
96                 return interfaceNumber
97         end
98
99         function diag_command(cmd, addr)
100                 if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
101                         local util = io.popen(cmd % ut.shellquote(addr))
102                         if util then
103                                 while true do
104                                         local ln = util:read("*l")
105                                         if not ln then break end
106                                         luci.http.write(ln)
107                                         luci.http.write("\n")
108                                 end
109                                 util:close()
110                         end
111                         return
112                 end
113         end
114
115         function get_gateway(inteface)
116                 local dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
117                 local gateway
118                 if dump and dump.route then
119                         local _, route
120                         for _, route in ipairs(dump.route) do
121                                 if dump.route[_].target == "0.0.0.0" then
122                                         gateway = dump.route[_].nexthop
123                                 end
124                         end
125                 end
126                 return gateway
127         end
128
129         local mArray = {}
130         local results = ""
131         local number = getInterfaceNumber(interface)
132
133         local uci = uci.cursor(nil, "/var/state")
134         local device = uci:get("network", interface, "ifname")
135
136         luci.http.prepare_content("text/plain")
137         if device ~= "" then
138                 if task == "ping_gateway" then
139                         local gateway = get_gateway(interface)
140                         if gateway ~= nil then
141                                 diag_command("ping -c 5 -W 1 %s 2>&1", gateway)
142                         else
143                                 luci.http.prepare_content("text/plain")
144                                 luci.http.write(string.format("No gateway for interface %s found.", interface))
145                         end
146                 elseif task == "ping_trackips" then
147                         local trackips = uci:get("mwan3", interface, "track_ip")
148                         if #trackips > 0 then
149                                 for i in pairs(trackips) do
150                                         diag_command("ping -c 5 -W 1 %s 2>&1", trackips[i])
151                                 end
152                         else
153                                 luci.http.write(string.format("No tracking Hosts for interface %s defined.", interface))
154                         end
155                 elseif task == "check_rules" then
156                         local number = getInterfaceNumber(interface)
157                         local iif = 1000 + number
158                         local fwmark = 2000 + number
159                         local iif_rule  = sys.exec(string.format("ip rule | grep %d", iif))
160                         local fwmark_rule = sys.exec(string.format("ip rule | grep %d", fwmark))
161                         if iif_rule ~= "" and fwmark_rule ~= "" then
162                                 luci.http.write(string.format("All required IP rules for interface %s found", interface))
163                                 luci.http.write("\n")
164                                 luci.http.write(fwmark_rule)
165                                 luci.http.write(iif_rule)
166                         elseif iif_rule == "" and fwmark_rule ~= "" then
167                                 luci.http.write(string.format("Only one IP rules for interface %s found", interface))
168                                 luci.http.write("\n")
169                                 luci.http.write(fwmark_rule)
170                         elseif iif_rule ~= "" and fwmark_rule == "" then
171                                 luci.http.write(string.format("Only one IP rules for interface %s found", interface))
172                                 luci.http.write("\n")
173                                 luci.http.write(iif_rule)
174                         else
175                                 luci.http.write(string.format("Missing both IP rules for interface %s", interface))
176                         end
177                 elseif task == "check_routes" then
178                         local number = getInterfaceNumber(interface)
179                         local routeTable = sys.exec(string.format("ip route list table %s", number))
180                         if routeTable ~= "" then
181                                 luci.http.write(string.format("Routing table %s for interface %s found", number, interface))
182                                 luci.http.write("\n")
183                                 luci.http.write(routeTable)
184                         else
185                                 luci.http.write(string.format("Routing table %s for interface %s not found", number, interface))
186                         end
187                 elseif task == "hotplug_ifup" then
188                         os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface)))
189                         luci.http.write(string.format("Hotplug ifup sent to interface %s", interface))
190                 elseif task == "hotplug_ifdown" then
191                         os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface)))
192                         luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface))
193                 else
194                         luci.http.write("Unknown task")
195                 end
196         else
197                 luci.http.write(string.format("Unable to perform diagnostic tests on %s.", interface))
198                 luci.http.write("\n")
199                 luci.http.write("There is no physical or virtual device associated with this interface.")
200         end
201 end
202
203 function troubleshootingData()
204         local ver = require "luci.version"
205         local dash = "-------------------------------------------------"
206
207         luci.http.prepare_content("text/plain")
208
209         luci.http.write("\n")
210         luci.http.write("\n")
211         luci.http.write("Software-Version")
212         luci.http.write("\n")
213         luci.http.write(dash)
214         luci.http.write("\n")
215         if ver.distversion then
216                 luci.http.write(string.format("OpenWrt - %s", ver.distversion))
217                 luci.http.write("\n")
218         else
219                 luci.http.write("OpenWrt - unknown")
220                 luci.http.write("\n")
221         end
222
223         if ver.luciversion then
224                 luci.http.write(string.format("LuCI - %s", ver.luciversion))
225                 luci.http.write("\n")
226         else
227                 luci.http.write("LuCI - unknown")
228                 luci.http.write("\n")
229         end
230
231         luci.http.write("\n")
232         luci.http.write("\n")
233         local output = ut.trim(sys.exec("ip a show"))
234         luci.http.write("Output of \"ip a show\"")
235         luci.http.write("\n")
236         luci.http.write(dash)
237         luci.http.write("\n")
238         if output ~= "" then
239                 luci.http.write(output)
240                 luci.http.write("\n")
241         else
242                 luci.http.write("No data found")
243                 luci.http.write("\n")
244         end
245
246         luci.http.write("\n")
247         luci.http.write("\n")
248         local output = ut.trim(sys.exec("ip route show"))
249         luci.http.write("Output of \"ip route show\"")
250         luci.http.write("\n")
251         luci.http.write(dash)
252         luci.http.write("\n")
253         if output ~= "" then
254                 luci.http.write(output)
255                 luci.http.write("\n")
256         else
257                 luci.http.write("No data found")
258                 luci.http.write("\n")
259         end
260
261         luci.http.write("\n")
262         luci.http.write("\n")
263         local output = ut.trim(sys.exec("ip rule show"))
264         luci.http.write("Output of \"ip rule show\"")
265         luci.http.write("\n")
266         luci.http.write(dash)
267         luci.http.write("\n")
268         if output ~= "" then
269                 luci.http.write(output)
270                 luci.http.write("\n")
271         else
272                 luci.http.write("No data found")
273                 luci.http.write("\n")
274         end
275
276         luci.http.write("\n")
277         luci.http.write("\n")
278         luci.http.write("Output of \"ip route list table 1-250\"")
279         luci.http.write("\n")
280         luci.http.write(dash)
281         luci.http.write("\n")
282         for i=1,250 do
283                 local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
284                 if output ~= "" then
285                         luci.http.write(string.format("Table %s: ", i))
286                         luci.http.write(output)
287                         luci.http.write("\n")
288                 end
289         end
290
291         luci.http.write("\n")
292         luci.http.write("\n")
293         local output = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
294         luci.http.write("Output of \"iptables -L -t mangle -v -n\"")
295         luci.http.write("\n")
296         luci.http.write(dash)
297         luci.http.write("\n")
298         if output ~= "" then
299                 luci.http.write(output)
300                 luci.http.write("\n")
301         else
302                 luci.http.write("No data found")
303                 luci.http.write("\n")
304         end
305 end