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.

322 lines
11 KiB

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