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