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.

318 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 get -p /var/state mwan3." .. interfaceName .. ".enabled")) == "1" then
  57. if ut.trim(sys.exec("ip route list table " .. ruleNumber)) ~= "" then
  58. if ut.trim(sys.exec("uci get -p /var/state 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 get -p /var/state 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 get -p /var/state 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 get -p /var/state 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 mArray = {}
  205. -- software versions
  206. local wrtRelease = ut.trim(luci.version.distversion)
  207. if wrtRelease ~= "" then
  208. wrtRelease = "OpenWrt - " .. wrtRelease
  209. else
  210. wrtRelease = "OpenWrt - unknown"
  211. end
  212. local luciRelease = ut.trim(luci.version.luciversion)
  213. if luciRelease ~= "" then
  214. luciRelease = "\nLuCI - " .. luciRelease
  215. else
  216. luciRelease = "\nLuCI - unknown"
  217. end
  218. local mwanVersion = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk '{print $2}'"))
  219. if mwanVersion ~= "" then
  220. mwanVersion = "\n\nmwan3 - " .. mwanVersion
  221. else
  222. mwanVersion = "\n\nmwan3 - unknown"
  223. end
  224. local mwanLuciVersion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk '{print $2}'"))
  225. if mwanLuciVersion ~= "" then
  226. mwanLuciVersion = "\nmwan3-luci - " .. mwanLuciVersion
  227. else
  228. mwanLuciVersion = "\nmwan3-luci - unknown"
  229. end
  230. mArray.versions = { wrtRelease .. luciRelease .. mwanVersion .. mwanLuciVersion }
  231. -- mwan config
  232. local mwanConfig = ut.trim(sys.exec("cat /etc/config/mwan3"))
  233. if mwanConfig == "" then
  234. mwanConfig = "No data found"
  235. end
  236. mArray.mwanconfig = { mwanConfig }
  237. -- network config
  238. local networkConfig = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/'"))
  239. if networkConfig == "" then
  240. networkConfig = "No data found"
  241. end
  242. mArray.netconfig = { networkConfig }
  243. -- ifconfig
  244. local ifconfig = ut.trim(sys.exec("ifconfig"))
  245. if ifconfig == "" then
  246. ifconfig = "No data found"
  247. end
  248. mArray.ifconfig = { ifconfig }
  249. -- route -n
  250. local routeShow = ut.trim(sys.exec("route -n"))
  251. if routeShow == "" then
  252. routeShow = "No data found"
  253. end
  254. mArray.routeshow = { routeShow }
  255. -- ip rule show
  256. local ipRuleShow = ut.trim(sys.exec("ip rule show"))
  257. if ipRuleShow == "" then
  258. ipRuleShow = "No data found"
  259. end
  260. mArray.iprule = { ipRuleShow }
  261. -- ip route list table 1-250
  262. local routeList, routeString = ut.trim(sys.exec("ip rule | sed 's/://g' | awk '$1>=2001 && $1<=2250' | awk '{print $NF}'")), ""
  263. if routeList ~= "" then
  264. for line in routeList:gmatch("[^\r\n]+") do
  265. routeString = routeString .. line .. "\n" .. sys.exec("ip route list table " .. line)
  266. end
  267. routeString = ut.trim(routeString)
  268. else
  269. routeString = "No data found"
  270. end
  271. mArray.routelist = { routeString }
  272. -- default firewall output policy
  273. local firewallOut = ut.trim(sys.exec("uci get -p /var/state firewall.@defaults[0].output"))
  274. if firewallOut == "" then
  275. firewallOut = "No data found"
  276. end
  277. mArray.firewallout = { firewallOut }
  278. -- iptables
  279. local iptables = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
  280. if iptables == "" then
  281. iptables = "No data found"
  282. end
  283. mArray.iptables = { iptables }
  284. luci.http.prepare_content("application/json")
  285. luci.http.write_json(mArray)
  286. end