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