Merge pull request #1801 from dibdot/adblock
[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                 local uci = require "luci.model.uci".cursor()
89                 uci:foreach("mwan3", "interface",
90                         function (section)
91                                 number = number+1
92                                 if section[".name"] == interface then
93                                         interfaceNumber = number
94                                 end
95                         end
96                 )
97                 return interfaceNumber
98         end
99
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)})
103                         if util then
104                                 while true do
105                                         local ln = util:read("*l")
106                                         if not ln then break end
107                                         luci.http.write(ln)
108                                         luci.http.write("\n")
109                                 end
110                                 util:close()
111                         end
112                         return
113                 end
114         end
115
116         function get_gateway(inteface)
117                 local gateway = nil
118                 local dump = nil
119
120                 dump = require("luci.util").ubus("network.interface.%s_4" % interface, "status", {})
121                 if not dump then
122                         dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
123                 end
124
125                 if dump and dump.route then
126                         local _, route
127                         for _, route in ipairs(dump.route) do
128                                 if dump.route[_].target == "0.0.0.0" then
129                                         gateway = dump.route[_].nexthop
130                                 end
131                         end
132                 end
133                 return gateway
134         end
135
136         local mArray = {}
137         local results = ""
138         local number = getInterfaceNumber(interface)
139
140         local uci = require "luci.model.uci".cursor(nil, "/var/state")
141         local device = uci:get("network", interface, "ifname")
142
143         luci.http.prepare_content("text/plain")
144         if device ~= "" then
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)
149                         else
150                                 luci.http.prepare_content("text/plain")
151                                 luci.http.write(string.format("No gateway for interface %s found.", interface))
152                         end
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])
158                                 end
159                         else
160                                 luci.http.write(string.format("No tracking Hosts for interface %s defined.", interface))
161                         end
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)
181                         else
182                                 luci.http.write(string.format("Missing both IP rules for interface %s", interface))
183                         end
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)
191                         else
192                                 luci.http.write(string.format("Routing table %s for interface %s not found", number, interface))
193                         end
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))
200                 else
201                         luci.http.write("Unknown task")
202                 end
203         else
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.")
207         end
208 end
209
210 function troubleshootingData()
211         local ver = require "luci.version"
212         local dash = "-------------------------------------------------"
213
214         luci.http.prepare_content("text/plain")
215
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")
225         else
226                 luci.http.write("OpenWrt - unknown")
227                 luci.http.write("\n")
228         end
229
230         if ver.luciversion then
231                 luci.http.write(string.format("LuCI - %s", ver.luciversion))
232                 luci.http.write("\n")
233         else
234                 luci.http.write("LuCI - unknown")
235                 luci.http.write("\n")
236         end
237
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")
245         if output ~= "" then
246                 luci.http.write(output)
247                 luci.http.write("\n")
248         else
249                 luci.http.write("No data found")
250                 luci.http.write("\n")
251         end
252
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")
260         if output ~= "" then
261                 luci.http.write(output)
262                 luci.http.write("\n")
263         else
264                 luci.http.write("No data found")
265                 luci.http.write("\n")
266         end
267
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")
275         if output ~= "" then
276                 luci.http.write(output)
277                 luci.http.write("\n")
278         else
279                 luci.http.write("No data found")
280                 luci.http.write("\n")
281         end
282
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")
289         for i=1,250 do
290                 local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
291                 if output ~= "" then
292                         luci.http.write(string.format("Table %s: ", i))
293                         luci.http.write(output)
294                         luci.http.write("\n")
295                 end
296         end
297
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")
305         if output ~= "" then
306                 luci.http.write(output)
307                 luci.http.write("\n")
308         else
309                 luci.http.write("No data found")
310                 luci.http.write("\n")
311         end
312 end