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.

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