luci/applications/luci-app-mwan3/luasrc/controller/mwan3.lua
Florian Eckert ee54a9542f luci-app-mwan3: pin diag ping command to interface device
If the physical device is not set in the diag_command then the ping will
always use the route with the lowest metric from the default routing
table.
To fix this add the physical device of the logical interface to the ping
command.

Signed-off-by: Florian Eckert <fe@dev.tdt.de>
2018-05-09 14:20:03 +02:00

312 lines
9.2 KiB
Lua

-- Copyright 2014 Aedan Renner <chipdankly@gmail.com>
-- Copyright 2018 Florian Eckert <fe@dev.tdt.de>
-- Licensed to the public under the GNU General Public License v2.
module("luci.controller.mwan3", package.seeall)
sys = require "luci.sys"
ut = require "luci.util"
ip = "ip -4 "
function index()
if not nixio.fs.access("/etc/config/mwan3") then
return
end
entry({"admin", "status", "mwan"},
alias("admin", "status", "mwan", "overview"),
_("Load Balancing"), 600)
entry({"admin", "status", "mwan", "overview"},
template("mwan/status_interface"))
entry({"admin", "status", "mwan", "detail"},
template("mwan/status_detail"))
entry({"admin", "status", "mwan", "diagnostics"},
template("mwan/status_diagnostics"))
entry({"admin", "status", "mwan", "troubleshooting"},
template("mwan/status_troubleshooting"))
entry({"admin", "status", "mwan", "interface_status"},
call("mwan_Status"))
entry({"admin", "status", "mwan", "detailed_status"},
call("detailedStatus"))
entry({"admin", "status", "mwan", "diagnostics_display"},
call("diagnosticsData"), nil).leaf = true
entry({"admin", "status", "mwan", "troubleshooting_display"},
call("troubleshootingData"))
entry({"admin", "network", "mwan"},
alias("admin", "network", "mwan", "interface"),
_("Load Balancing"), 600)
entry({"admin", "network", "mwan", "globals"},
cbi("mwan/globalsconfig"),
_("Globals"), 5).leaf = true
entry({"admin", "network", "mwan", "interface"},
arcombine(cbi("mwan/interface"), cbi("mwan/interfaceconfig")),
_("Interfaces"), 10).leaf = true
entry({"admin", "network", "mwan", "member"},
arcombine(cbi("mwan/member"), cbi("mwan/memberconfig")),
_("Members"), 20).leaf = true
entry({"admin", "network", "mwan", "policy"},
arcombine(cbi("mwan/policy"), cbi("mwan/policyconfig")),
_("Policies"), 30).leaf = true
entry({"admin", "network", "mwan", "rule"},
arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")),
_("Rules"), 40).leaf = true
entry({"admin", "network", "mwan", "notify"},
form("mwan/notify"),
_("Notification"), 50).leaf = true
end
function mwan_Status()
local status = ut.ubus("mwan3", "status", {})
luci.http.prepare_content("application/json")
if status ~= nil then
luci.http.write_json(status)
else
luci.http.write_json({})
end
end
function detailedStatus()
local statusInfo = ut.trim(sys.exec("/usr/sbin/mwan3 status"))
luci.http.prepare_content("text/plain")
if statusInfo ~= "" then
luci.http.write(statusInfo)
else
luci.http.write("Unable to get status information")
end
end
function diagnosticsData(interface, task)
function getInterfaceNumber(interface)
local number = 0
local interfaceNumber
local uci = require "luci.model.uci".cursor()
uci:foreach("mwan3", "interface",
function (section)
number = number+1
if section[".name"] == interface then
interfaceNumber = number
end
end
)
return interfaceNumber
end
function diag_command(cmd, device, addr)
if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then
local util = io.popen(cmd %{ut.shellquote(device), ut.shellquote(addr)})
if util then
while true do
local ln = util:read("*l")
if not ln then break end
luci.http.write(ln)
luci.http.write("\n")
end
util:close()
end
return
end
end
function get_gateway(inteface)
local gateway = nil
local dump = nil
dump = require("luci.util").ubus("network.interface.%s_4" % interface, "status", {})
if not dump then
dump = require("luci.util").ubus("network.interface.%s" % interface, "status", {})
end
if dump and dump.route then
local _, route
for _, route in ipairs(dump.route) do
if dump.route[_].target == "0.0.0.0" then
gateway = dump.route[_].nexthop
end
end
end
return gateway
end
local mArray = {}
local results = ""
local number = getInterfaceNumber(interface)
local uci = require "luci.model.uci".cursor(nil, "/var/state")
local device = uci:get("network", interface, "ifname")
luci.http.prepare_content("text/plain")
if device ~= "" then
if task == "ping_gateway" then
local gateway = get_gateway(interface)
if gateway ~= nil then
diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, gateway)
else
luci.http.prepare_content("text/plain")
luci.http.write(string.format("No gateway for interface %s found.", interface))
end
elseif task == "ping_trackips" then
local trackips = uci:get("mwan3", interface, "track_ip")
if #trackips > 0 then
for i in pairs(trackips) do
diag_command("ping -I %s -c 5 -W 1 %s 2>&1", device, trackips[i])
end
else
luci.http.write(string.format("No tracking Hosts for interface %s defined.", interface))
end
elseif task == "check_rules" then
local number = getInterfaceNumber(interface)
local iif = 1000 + number
local fwmark = 2000 + number
local iif_rule = sys.exec(string.format("ip rule | grep %d", iif))
local fwmark_rule = sys.exec(string.format("ip rule | grep %d", fwmark))
if iif_rule ~= "" and fwmark_rule ~= "" then
luci.http.write(string.format("All required IP rules for interface %s found", interface))
luci.http.write("\n")
luci.http.write(fwmark_rule)
luci.http.write(iif_rule)
elseif iif_rule == "" and fwmark_rule ~= "" then
luci.http.write(string.format("Only one IP rules for interface %s found", interface))
luci.http.write("\n")
luci.http.write(fwmark_rule)
elseif iif_rule ~= "" and fwmark_rule == "" then
luci.http.write(string.format("Only one IP rules for interface %s found", interface))
luci.http.write("\n")
luci.http.write(iif_rule)
else
luci.http.write(string.format("Missing both IP rules for interface %s", interface))
end
elseif task == "check_routes" then
local number = getInterfaceNumber(interface)
local routeTable = sys.exec(string.format("ip route list table %s", number))
if routeTable ~= "" then
luci.http.write(string.format("Routing table %s for interface %s found", number, interface))
luci.http.write("\n")
luci.http.write(routeTable)
else
luci.http.write(string.format("Routing table %s for interface %s not found", number, interface))
end
elseif task == "hotplug_ifup" then
os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface)))
luci.http.write(string.format("Hotplug ifup sent to interface %s", interface))
elseif task == "hotplug_ifdown" then
os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface)))
luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface))
else
luci.http.write("Unknown task")
end
else
luci.http.write(string.format("Unable to perform diagnostic tests on %s.", interface))
luci.http.write("\n")
luci.http.write("There is no physical or virtual device associated with this interface.")
end
end
function troubleshootingData()
local ver = require "luci.version"
local dash = "-------------------------------------------------"
luci.http.prepare_content("text/plain")
luci.http.write("\n")
luci.http.write("\n")
luci.http.write("Software-Version")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
if ver.distversion then
luci.http.write(string.format("OpenWrt - %s", ver.distversion))
luci.http.write("\n")
else
luci.http.write("OpenWrt - unknown")
luci.http.write("\n")
end
if ver.luciversion then
luci.http.write(string.format("LuCI - %s", ver.luciversion))
luci.http.write("\n")
else
luci.http.write("LuCI - unknown")
luci.http.write("\n")
end
luci.http.write("\n")
luci.http.write("\n")
local output = ut.trim(sys.exec("ip a show"))
luci.http.write("Output of \"ip a show\"")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
if output ~= "" then
luci.http.write(output)
luci.http.write("\n")
else
luci.http.write("No data found")
luci.http.write("\n")
end
luci.http.write("\n")
luci.http.write("\n")
local output = ut.trim(sys.exec("ip route show"))
luci.http.write("Output of \"ip route show\"")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
if output ~= "" then
luci.http.write(output)
luci.http.write("\n")
else
luci.http.write("No data found")
luci.http.write("\n")
end
luci.http.write("\n")
luci.http.write("\n")
local output = ut.trim(sys.exec("ip rule show"))
luci.http.write("Output of \"ip rule show\"")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
if output ~= "" then
luci.http.write(output)
luci.http.write("\n")
else
luci.http.write("No data found")
luci.http.write("\n")
end
luci.http.write("\n")
luci.http.write("\n")
luci.http.write("Output of \"ip route list table 1-250\"")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
for i=1,250 do
local output = ut.trim(sys.exec(string.format("ip route list table %d", i)))
if output ~= "" then
luci.http.write(string.format("Table %s: ", i))
luci.http.write(output)
luci.http.write("\n")
end
end
luci.http.write("\n")
luci.http.write("\n")
local output = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
luci.http.write("Output of \"iptables -L -t mangle -v -n\"")
luci.http.write("\n")
luci.http.write(dash)
luci.http.write("\n")
if output ~= "" then
luci.http.write(output)
luci.http.write("\n")
else
luci.http.write("No data found")
luci.http.write("\n")
end
end