You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
11 KiB

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