mwan3.lua 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. -- Copyright 2014 Aedan Renner <chipdankly@gmail.com>
  2. -- Copyright 2018 Florian Eckert <fe@dev.tdt.de>
  3. -- Licensed to the public under the GNU General Public License v2.
  4. module("luci.controller.mwan3", package.seeall)
  5. sys = require "luci.sys"
  6. ut = require "luci.util"
  7. ip = "ip -4 "
  8. function index()
  9. if not nixio.fs.access("/etc/config/mwan3") then
  10. return
  11. end
  12. entry({"admin", "status", "mwan"},
  13. alias("admin", "status", "mwan", "overview"),
  14. _("Load Balancing"), 600)
  15. entry({"admin", "status", "mwan", "overview"},
  16. template("mwan/status_interface"))
  17. entry({"admin", "status", "mwan", "detail"},
  18. template("mwan/status_detail"))
  19. entry({"admin", "status", "mwan", "diagnostics"},
  20. template("mwan/status_diagnostics"))
  21. entry({"admin", "status", "mwan", "troubleshooting"},
  22. template("mwan/status_troubleshooting"))
  23. entry({"admin", "status", "mwan", "interface_status"},
  24. call("mwan_Status"))
  25. entry({"admin", "status", "mwan", "detailed_status"},
  26. call("detailedStatus"))
  27. entry({"admin", "status", "mwan", "diagnostics_display"},
  28. call("diagnosticsData"), nil).leaf = true
  29. entry({"admin", "status", "mwan", "troubleshooting_display"},
  30. call("troubleshootingData"))
  31. entry({"admin", "network", "mwan"},
  32. alias("admin", "network", "mwan", "interface"),
  33. _("Load Balancing"), 600)
  34. entry({"admin", "network", "mwan", "globals"},
  35. cbi("mwan/globalsconfig"),
  36. _("Globals"), 5).leaf = true
  37. entry({"admin", "network", "mwan", "interface"},
  38. arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
  39. _("Interfaces"), 10).leaf = true
  40. entry({"admin", "network", "mwan", "member"},
  41. arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
  42. _("Members"), 20).leaf = true
  43. entry({"admin", "network", "mwan", "policy"},
  44. arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
  45. _("Policies"), 30).leaf = true
  46. entry({"admin", "network", "mwan", "rule"},
  47. arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
  48. _("Rules"), 40).leaf = true
  49. entry({"admin", "network", "mwan", "notify"},
  50. form("mwan/notify"),
  51. _("Notification"), 50).leaf = true
  52. end
  53. function mwan_Status()
  54. local status = ut.ubus("mwan3", "status", {})
  55. luci.http.prepare_content("application/json")
  56. if status ~= nil then
  57. luci.http.write_json(status)
  58. else
  59. luci.http.write_json({})
  60. end
  61. end
  62. function detailedStatus()
  63. local statusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
  64. luci.http.prepare_content("text/plain")
  65. if statusInfo ~= "" then
  66. luci.http.write(statusInfo)
  67. else
  68. luci.http.write("Unable to get status information")
  69. end
  70. end
  71. function diagnosticsData(interface, task)
  72. function getInterfaceNumber(interface)
  73. local number = 0
  74. local interfaceNumber
  75. local uci = require "luci.model.uci".cursor()
  76. uci:foreach("mwan3", "interface",
  77. function (section)
  78. number = number+1
  79. if section[".name"] == interface then
  80. interfaceNumber = number
  81. end
  82. end
  83. )
  84. return interfaceNumber
  85. end
  86. function diag_command(cmd, device, addr)
  87. if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
  88. local util = io.popen(cmd %{ut.shellquote(device), ut.shellquote(addr)})
  89. if util then
  90. luci.http.write("Command:\n")
  91. luci.http.write(cmd %{ut.shellquote(device),
  92. ut.shellquote(addr)} .. "\n\n")
  93. luci.http.write("Result:\n")
  94. while true do
  95. local ln = util:read("*l")
  96. if not ln then break end
  97. luci.http.write(ln)
  98. luci.http.write("\n")
  99. end
  100. util:close()
  101. end
  102. return
  103. end
  104. end
  105. function get_gateway(interface)
  106. local gateway = nil
  107. local dump = nil
  108. dump = require("luci.util").ubus("network.interface.%s_4" % interface, "status", {})
  109. if not dump then
  110. dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
  111. end
  112. if dump and dump.route then
  113. local _, route
  114. for _, route in ipairs(dump.route) do
  115. if dump.route[_].target == "0.0.0.0" then
  116. gateway = dump.route[_].nexthop
  117. end
  118. end
  119. end
  120. return gateway
  121. end
  122. local mArray = {}
  123. local results = ""
  124. local number = getInterfaceNumber(interface)
  125. local uci = require "luci.model.uci".cursor(nil, "/var/state")
  126. local nw = require "luci.model.network".init()
  127. local i18n = require "luci.i18n"
  128. local network = nw:get_network(interface)
  129. local device = network and network:get_interface()
  130. device = device:name()
  131. luci.http.prepare_content("text/plain")
  132. if device then
  133. if task == "ping_gateway" then
  134. local gateway = get_gateway(interface)
  135. if gateway ~= nil then
  136. diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, gateway)
  137. else
  138. luci.http.prepare_content("text/plain")
  139. luci.http.write(i18n.translatef("No gateway for interface %s found.", interface))
  140. end
  141. elseif task == "ping_trackips" then
  142. local trackips = uci:get("mwan3", interface, "track_ip")
  143. if #trackips > 0 then
  144. for i in pairs(trackips) do
  145. diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, trackips[i])
  146. end
  147. else
  148. luci.http.write(i18n.translatef("No tracking Hosts for interface %s defined.", interface))
  149. end
  150. elseif task == "check_rules" then
  151. local number = getInterfaceNumber(interface)
  152. local iif = 1000 + number
  153. local fwmark = 2000 + number
  154. local iif_rule = sys.exec(string.format("ip rule | grep %d", iif))
  155. local fwmark_rule = sys.exec(string.format("ip rule | grep %d", fwmark))
  156. if iif_rule ~= "" and fwmark_rule ~= "" then
  157. luci.http.write(i18n.translatef("All required IP rules for interface %s found", interface))
  158. luci.http.write("\n")
  159. luci.http.write(fwmark_rule)
  160. luci.http.write(iif_rule)
  161. elseif iif_rule == "" and fwmark_rule ~= "" then
  162. luci.http.write(i18n.translatef("Only one IP rules for interface %s found", interface))
  163. luci.http.write("\n")
  164. luci.http.write(fwmark_rule)
  165. elseif iif_rule ~= "" and fwmark_rule == "" then
  166. luci.http.write(i18n.translatef("Only one IP rules for interface %s found", interface))
  167. luci.http.write("\n")
  168. luci.http.write(iif_rule)
  169. else
  170. luci.http.write(i18n.translatef("Missing both IP rules for interface %s", interface))
  171. end
  172. elseif task == "check_routes" then
  173. local number = getInterfaceNumber(interface)
  174. local routeTable = sys.exec(string.format("ip route list table %s", number))
  175. if routeTable ~= "" then
  176. luci.http.write(i18n.translatef("Routing table %s for interface %s found", number, interface))
  177. luci.http.write("\n")
  178. luci.http.write(routeTable)
  179. else
  180. luci.http.write(i18n.translatef("Routing table %s for interface %s not found", number, interface))
  181. end
  182. elseif task == "hotplug_ifup" then
  183. os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface)))
  184. luci.http.write(string.format("Hotplug ifup sent to interface %s", interface))
  185. elseif task == "hotplug_ifdown" then
  186. os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface)))
  187. luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface))
  188. else
  189. luci.http.write("Unknown task")
  190. end
  191. else
  192. luci.http.write(string.format("Unable to perform diagnostic tests on %s.", interface))
  193. luci.http.write("\n")
  194. luci.http.write("There is no physical or virtual device associated with this interface.")
  195. end
  196. end
  197. function troubleshootingData()
  198. local ver = require "luci.version"
  199. local dash = "-------------------------------------------------"
  200. luci.http.prepare_content("text/plain")
  201. luci.http.write("\n")
  202. luci.http.write("\n")
  203. luci.http.write("Software-Version")
  204. luci.http.write("\n")
  205. luci.http.write(dash)
  206. luci.http.write("\n")
  207. if ver.distversion then
  208. luci.http.write(string.format("OpenWrt - %s", ver.distversion))
  209. luci.http.write("\n")
  210. else
  211. luci.http.write("OpenWrt - unknown")
  212. luci.http.write("\n")
  213. end
  214. if ver.luciversion then
  215. luci.http.write(string.format("LuCI - %s", ver.luciversion))
  216. luci.http.write("\n")
  217. else
  218. luci.http.write("LuCI - unknown")
  219. luci.http.write("\n")
  220. end
  221. luci.http.write("\n")
  222. luci.http.write("\n")
  223. local output = ut.trim(sys.exec("ip a show"))
  224. luci.http.write("Output of \"ip a show\"")
  225. luci.http.write("\n")
  226. luci.http.write(dash)
  227. luci.http.write("\n")
  228. if output ~= "" then
  229. luci.http.write(output)
  230. luci.http.write("\n")
  231. else
  232. luci.http.write("No data found")
  233. luci.http.write("\n")
  234. end
  235. luci.http.write("\n")
  236. luci.http.write("\n")
  237. local output = ut.trim(sys.exec("ip route show"))
  238. luci.http.write("Output of \"ip route show\"")
  239. luci.http.write("\n")
  240. luci.http.write(dash)
  241. luci.http.write("\n")
  242. if output ~= "" then
  243. luci.http.write(output)
  244. luci.http.write("\n")
  245. else
  246. luci.http.write("No data found")
  247. luci.http.write("\n")
  248. end
  249. luci.http.write("\n")
  250. luci.http.write("\n")
  251. local output = ut.trim(sys.exec("ip rule show"))
  252. luci.http.write("Output of \"ip rule show\"")
  253. luci.http.write("\n")
  254. luci.http.write(dash)
  255. luci.http.write("\n")
  256. if output ~= "" then
  257. luci.http.write(output)
  258. luci.http.write("\n")
  259. else
  260. luci.http.write("No data found")
  261. luci.http.write("\n")
  262. end
  263. luci.http.write("\n")
  264. luci.http.write("\n")
  265. luci.http.write("Output of \"ip route list table 1-250\"")
  266. luci.http.write("\n")
  267. luci.http.write(dash)
  268. luci.http.write("\n")
  269. for i=1,250 do
  270. local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
  271. if output ~= "" then
  272. luci.http.write(string.format("Table %s: ", i))
  273. luci.http.write(output)
  274. luci.http.write("\n")
  275. end
  276. end
  277. luci.http.write("\n")
  278. luci.http.write("\n")
  279. local output = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
  280. luci.http.write("Output of \"iptables -L -t mangle -v -n\"")
  281. luci.http.write("\n")
  282. luci.http.write(dash)
  283. luci.http.write("\n")
  284. if output ~= "" then
  285. luci.http.write(output)
  286. luci.http.write("\n")
  287. else
  288. luci.http.write("No data found")
  289. luci.http.write("\n")
  290. end
  291. end