luci-app-mwan3: move/rename hotplugscript tab
[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", "network", "mwan"},
14                 alias("admin", "network", "mwan", "overview"),
15                 _("Load Balancing"), 600)
16
17         entry({"admin", "network", "mwan", "overview"},
18                 alias("admin", "network", "mwan", "overview", "overview_interface"),
19                 _("Overview"), 10)
20         entry({"admin", "network", "mwan", "overview", "overview_interface"},
21                 template("mwan/overview_interface"))
22         entry({"admin", "network", "mwan", "overview", "interface_status"},
23                 call("interfaceStatus"))
24         entry({"admin", "network", "mwan", "overview", "overview_detailed"},
25                 template("mwan/overview_detailed"))
26         entry({"admin", "network", "mwan", "overview", "detailed_status"},
27                 call("detailedStatus"))
28
29         entry({"admin", "network", "mwan", "configuration"},
30                 alias("admin", "network", "mwan", "configuration", "interface"),
31                 _("Configuration"), 20)
32         entry({"admin", "network", "mwan", "configuration", "globals"},
33                 cbi("mwan/globalsconfig"),_("Globals"), 5).leaf = true
34         entry({"admin", "network", "mwan", "configuration", "interface"},
35                 arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
36                 _("Interfaces"), 10).leaf = true
37         entry({"admin", "network", "mwan", "configuration", "member"},
38                 arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
39                 _("Members"), 20).leaf = true
40         entry({"admin", "network", "mwan", "configuration", "policy"},
41                 arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
42                 _("Policies"), 30).leaf = true
43         entry({"admin", "network", "mwan", "configuration", "rule"},
44                 arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
45                 _("Rules"), 40).leaf = true
46         entry({"admin", "network", "mwan", "configuration", "notify"},
47                 cbi("mwan/notify"),
48                 _("Notification"), 50).leaf = true
49
50         entry({"admin", "network", "mwan", "advanced"},
51                 alias("admin", "network", "mwan", "advanced", "mwanconfig"),
52                 _("Advanced"), 100)
53         entry({"admin", "network", "mwan", "advanced", "mwanconfig"},
54                 form("mwan/advanced_mwanconfig"))
55         entry({"admin", "network", "mwan", "advanced", "networkconfig"},
56                 form("mwan/advanced_networkconfig"))
57         entry({"admin", "network", "mwan", "advanced", "wirelessconfig"},
58                 form("mwan/advanced_wirelessconfig"))
59         entry({"admin", "network", "mwan", "advanced", "diagnostics"},
60                 template("mwan/advanced_diagnostics"))
61         entry({"admin", "network", "mwan", "advanced", "diagnostics_display"},
62                 call("diagnosticsData"), nil).leaf = true
63         entry({"admin", "network", "mwan", "advanced", "troubleshooting"},
64                 template("mwan/advanced_troubleshooting"))
65         entry({"admin", "network", "mwan", "advanced", "troubleshooting_display"},
66                 call("troubleshootingData"))
67 end
68
69 function getInterfaceStatus(ruleNumber, interfaceName)
70         if ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interfaceName .. ".enabled")) == "1" then
71                 if ut.trim(sys.exec(ip .. "route list table " .. ruleNumber)) ~= "" then
72                         if ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interfaceName .. ".track_ip")) ~= "" then
73                                 return "online"
74                         else
75                                 return "notMonitored"
76                         end
77                 else
78                         return "offline"
79                 end
80         else
81                 return "notEnabled"
82         end
83 end
84
85 function getInterfaceName()
86         local ruleNumber, status = 0, ""
87         uci.cursor():foreach("mwan3", "interface",
88                 function (section)
89                         ruleNumber = ruleNumber+1
90                         status = status .. section[".name"] .. "[" .. getInterfaceStatus(ruleNumber, section[".name"]) .. "]"
91                 end
92         )
93         return status
94 end
95
96 function interfaceStatus()
97         local ntm = require "luci.model.network".init()
98
99         local mArray = {}
100
101         -- overview status
102         local statusString = getInterfaceName()
103         if statusString ~= "" then
104                 mArray.wans = {}
105                 wansid = {}
106
107                 for wanName, interfaceState in string.gfind(statusString, "([^%[]+)%[([^%]]+)%]") do
108                         local wanInterfaceName = ut.trim(sys.exec("uci -q -p /var/state get network." .. wanName .. ".ifname"))
109                                 if wanInterfaceName == "" then
110                                         wanInterfaceName = "X"
111                                 end
112                         local wanDeviceLink = ntm:get_interface(wanInterfaceName)
113                                 wanDeviceLink = wanDeviceLink and wanDeviceLink:get_network()
114                                 wanDeviceLink = wanDeviceLink and wanDeviceLink:adminlink() or "#"
115                         wansid[wanName] = #mArray.wans + 1
116                         mArray.wans[wansid[wanName]] = { name = wanName, link = wanDeviceLink, ifname = wanInterfaceName, status = interfaceState }
117                 end
118         end
119
120         -- overview status log
121         local mwanLog = ut.trim(sys.exec("logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x' 2>/dev/null"))
122         if mwanLog ~= "" then
123                 mArray.mwanlog = { mwanLog }
124         end
125
126         luci.http.prepare_content("application/json")
127         luci.http.write_json(mArray)
128 end
129
130 function detailedStatus()
131         local mArray = {}
132
133         -- detailed mwan status
134         local detailStatusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
135         if detailStatusInfo ~= "" then
136                 mArray.mwandetail = { detailStatusInfo }
137         end
138
139         luci.http.prepare_content("application/json")
140         luci.http.write_json(mArray)
141 end
142
143 function diagnosticsData(interface, tool, task)
144         function getInterfaceNumber()
145                 local number = 0
146                 uci.cursor():foreach("mwan3", "interface",
147                         function (section)
148                                 number = number+1
149                                 if section[".name"] == interface then
150                                         interfaceNumber = number
151                                 end
152                         end
153                 )
154         end
155
156         local mArray = {}
157
158         local results = ""
159         if tool == "service" then
160                 os.execute("/usr/sbin/mwan3 " .. task)
161                 if task == "restart" then
162                         results = "MWAN3 restarted"
163                 elseif task == "stop" then
164                         results = "MWAN3 stopped"
165                 else
166                         results = "MWAN3 started"
167                 end
168         else
169                 local interfaceDevice = ut.trim(sys.exec("uci -q -p /var/state get network." .. interface .. ".ifname"))
170                 if interfaceDevice ~= "" then
171                         if tool == "ping" then
172                                 local gateway = ut.trim(sys.exec("route -n | awk '{if ($8 == \"" .. interfaceDevice .. "\" && $1 == \"0.0.0.0\" && $3 == \"0.0.0.0\") print $2}'"))
173                                 if gateway ~= "" then
174                                         if task == "gateway" then
175                                                 local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. gateway
176                                                 results = pingCommand .. "\n\n" .. sys.exec(pingCommand)
177                                         else
178                                                 local tracked = ut.trim(sys.exec("uci -q -p /var/state get mwan3." .. interface .. ".track_ip"))
179                                                 if tracked ~= "" then
180                                                         for z in tracked:gmatch("[^ ]+") do
181                                                                 local pingCommand = "ping -c 3 -W 2 -I " .. interfaceDevice .. " " .. z
182                                                                 results = results .. pingCommand .. "\n\n" .. sys.exec(pingCommand) .. "\n\n"
183                                                         end
184                                                 else
185                                                         results = "No tracking IP addresses configured on " .. interface
186                                                 end
187                                         end
188                                 else
189                                         results = "No default gateway for " .. interface .. " found. Default route does not exist or is configured incorrectly"
190                                 end
191                         elseif tool == "rulechk" then
192                                 getInterfaceNumber()
193                                 local rule1 = sys.exec(ip .. "rule | grep $(echo $((" .. interfaceNumber .. " + 1000)))")
194                                 local rule2 = sys.exec(ip .. "rule | grep $(echo $((" .. interfaceNumber .. " + 2000)))")
195                                 if rule1 ~= "" and rule2 ~= "" then
196                                         results = "All required interface IP rules found:\n\n" .. rule1 .. rule2
197                                 elseif rule1 ~= "" or rule2 ~= "" then
198                                         results = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
199                                 else
200                                         results = "Missing both of the required interface IP rules"
201                                 end
202                         elseif tool == "routechk" then
203                                 getInterfaceNumber()
204                                 local routeTable = sys.exec(ip .. "route list table " .. interfaceNumber)
205                                 if routeTable ~= "" then
206                                         results = "Interface routing table " .. interfaceNumber .. " was found:\n\n" .. routeTable
207                                 else
208                                         results = "Missing required interface routing table " .. interfaceNumber
209                                 end
210                         elseif tool == "hotplug" then
211                                 if task == "ifup" then
212                                         os.execute("/usr/sbin/mwan3 ifup " .. interface)
213                                         results = "Hotplug ifup sent to interface " .. interface .. "..."
214                                 else
215                                         os.execute("/usr/sbin/mwan3 ifdown " .. interface)
216                                         results = "Hotplug ifdown sent to interface " .. interface .. "..."
217                                 end
218                         end
219                 else
220                         results = "Unable to perform diagnostic tests on " .. interface .. ". There is no physical or virtual device associated with this interface"
221                 end
222         end
223         if results ~= "" then
224                 results = ut.trim(results)
225                 mArray.diagnostics = { results }
226         end
227
228         luci.http.prepare_content("application/json")
229         luci.http.write_json(mArray)
230 end
231
232 function troubleshootingData()
233         local ver = require "luci.version"
234
235         local mArray = {}
236
237         -- software versions
238         local wrtRelease = ut.trim(ver.distversion)
239                 if wrtRelease ~= "" then
240                         wrtRelease = "OpenWrt - " .. wrtRelease
241                 else
242                         wrtRelease = "OpenWrt - unknown"
243                 end
244         local luciRelease = ut.trim(ver.luciversion)
245                 if luciRelease ~= "" then
246                         luciRelease = "\nLuCI - " .. luciRelease
247                 else
248                         luciRelease = "\nLuCI - unknown"
249                 end
250         local mwanVersion = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{print $2}'"))
251                 if mwanVersion ~= "" then
252                         mwanVersion = "\n\nmwan3 - " .. mwanVersion
253                 else
254                         mwanVersion = "\n\nmwan3 - unknown"
255                 end
256         local mwanLuciVersion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{print $2}'"))
257                 if mwanLuciVersion ~= "" then
258                         mwanLuciVersion = "\nmwan3-luci - " .. mwanLuciVersion
259                 else
260                         mwanLuciVersion = "\nmwan3-luci - unknown"
261                 end
262         mArray.versions = { wrtRelease .. luciRelease .. mwanVersion .. mwanLuciVersion }
263
264         -- mwan config
265         local mwanConfig = ut.trim(sys.exec("cat /etc/config/mwan3"))
266                 if mwanConfig == "" then
267                         mwanConfig = "No data found"
268                 end
269         mArray.mwanconfig = { mwanConfig }
270
271         -- network config
272         local networkConfig = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/       USERNAME HIDDEN/' -e 's/.*password.*/   PASSWORD HIDDEN/'"))
273                 if networkConfig == "" then
274                         networkConfig = "No data found"
275                 end
276         mArray.netconfig = { networkConfig }
277
278         -- wireless config
279         local wirelessConfig = ut.trim(sys.exec("cat /etc/config/wireless | sed -e 's/.*username.*/     USERNAME HIDDEN/' -e 's/.*password.*/   PASSWORD HIDDEN/' -e 's/.*key.*/        KEY HIDDEN/'"))
280                 if wirelessConfig == "" then
281                         wirelessConfig = "No data found"
282                 end
283         mArray.wificonfig = { wirelessConfig }
284         
285         -- ifconfig
286         local ifconfig = ut.trim(sys.exec("ifconfig"))
287                 if ifconfig == "" then
288                         ifconfig = "No data found"
289                 end
290         mArray.ifconfig = { ifconfig }
291
292         -- route -n
293         local routeShow = ut.trim(sys.exec("route -n"))
294                 if routeShow == "" then
295                         routeShow = "No data found"
296                 end
297         mArray.routeshow = { routeShow }
298
299         -- ip rule show
300         local ipRuleShow = ut.trim(sys.exec(ip .. "rule show"))
301                 if ipRuleShow == "" then
302                         ipRuleShow = "No data found"
303                 end
304         mArray.iprule = { ipRuleShow }
305
306         -- ip route list table 1-250
307         local routeList, routeString = ut.trim(sys.exec(ip .. "rule | sed 's/://g' 2>/dev/null | awk '$1>=2001 && $1<=2250' | awk '{print $NF}'")), ""
308                 if routeList ~= "" then
309                         for line in routeList:gmatch("[^\r\n]+") do
310                                 routeString = routeString .. line .. "\n" .. sys.exec(ip .. "route list table " .. line)
311                         end
312                         routeString = ut.trim(routeString)
313                 else
314                         routeString = "No data found"
315                 end
316         mArray.routelist = { routeString }
317
318         -- default firewall output policy
319         local firewallOut = ut.trim(sys.exec("uci -q -p /var/state get firewall.@defaults[0].output"))
320                 if firewallOut == "" then
321                         firewallOut = "No data found"
322                 end
323         mArray.firewallout = { firewallOut }
324
325         -- iptables
326         local iptables = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
327                 if iptables == "" then
328                         iptables = "No data found"
329                 end
330         mArray.iptables = { iptables }
331
332         luci.http.prepare_content("application/json")
333         luci.http.write_json(mArray)
334 end