mwan3.lua 11 KB

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