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