Merge pull request #1311 from dibdot/dnscrypt-proxy
[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