Improve LQM interface detection (#1207)

This commit is contained in:
Tim Wilkinson 2024-05-15 18:39:55 -07:00 committed by GitHub
parent 250db5605f
commit 5069f0e480
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 81 additions and 87 deletions

View File

@ -57,6 +57,7 @@ local NFT = "/usr/sbin/nft"
local IW = "/usr/sbin/iw" local IW = "/usr/sbin/iw"
local ARPING = "/usr/sbin/arping" local ARPING = "/usr/sbin/arping"
local CURL = "/usr/bin/curl" local CURL = "/usr/bin/curl"
local IPCMD = "/sbin/ip"
local now = 0 local now = 0
local config = {} local config = {}
@ -172,7 +173,7 @@ function update_block(track)
return "blocked" return "blocked"
end end
else else
if not nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " drop") then if not nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac .. " drop") then
nft_insert("input_lqm", "udp dport 698 ether saddr " .. track.mac .. " drop 2> /dev/null") nft_insert("input_lqm", "udp dport 698 ether saddr " .. track.mac .. " drop 2> /dev/null")
return "blocked" return "blocked"
end end
@ -186,7 +187,7 @@ function update_block(track)
return "unblocked" return "unblocked"
end end
else else
local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " drop") local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac .. " drop")
if handle then if handle then
nft_delete("input_lqm", handle) nft_delete("input_lqm", handle)
return "unblocked" return "unblocked"
@ -198,7 +199,7 @@ end
function force_remove_block(track) function force_remove_block(track)
track.blocked = false track.blocked = false
local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac:lower() .. " drop") local handle = nft_handle("input_lqm", "udp dport 698 ether saddr " .. track.mac .. " drop")
if handle then if handle then
nft_delete("input_lqm", handle) nft_delete("input_lqm", handle)
end end
@ -318,20 +319,46 @@ function lqm()
lon = tonumber(lon) lon = tonumber(lon)
local arps = {} local arps = {}
arptable( for line in io.popen(IPCMD .. " neigh show"):lines()
function (entry) do
if entry["Flags"] ~= "0x0" then local ip, dev, mac, probes, state = line:match("^(%S+) dev (%S+) lladdr (%S+) .+ probes (%d+) (.+)$")
entry["HW address"] = entry["HW address"]:upper() if ip and (tonumber(probes) < 4 or state ~= "STALE") then
arps[#arps + 1] = entry arps[#arps + 1] = {
Device = dev,
["HW address"] = mac:lower(),
["IP address"] = ip
}
end end
end end
)
-- Know our macs so we can exclude them -- Find all our devices and know our macs so we can exclude them
local devices = {}
local our_macs = {} local our_macs = {}
for _, i in ipairs(nixio.getifaddrs()) do for _, i in ipairs(nixio.getifaddrs())
if i.family == "packet" and i.addr then do
our_macs[i.addr:upper()] = true if i.name then
local dev = devices[i.name]
if not dev then
dev = { name = i.name }
devices[i.name] = dev
end
if i.family == "packet" then
if i.addr then
dev.mac = i.addr:lower()
our_macs[dev.mac] = true
end
dev.tx_packets = i.data.tx_packets
dev.tx_fail = i.data.tx_errors
end
if i.family == "inet" then
dev.ip = i.addr
dev.dstip = i.dstaddr
if not dev.mac then
-- Fake a mac from the ip if we need one
local a, b, c, d = dev.ip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
dev.mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d)
end
end
end end
end end
@ -359,7 +386,7 @@ function lqm()
station = { station = {
type = "RF", type = "RF",
device = wlan, device = wlan,
mac = mac:upper(), mac = mac:lower(),
signal = 0, signal = 0,
noise = noise, noise = noise,
ip = nil, ip = nil,
@ -389,71 +416,41 @@ function lqm()
end end
end end
-- Legacy tunnels -- Legacy and wireguard tunnels
local tunnel = {} local tunnel = {}
for line in io.popen("ifconfig"):lines() for _, dev in pairs(devices)
do do
local tun = line:match("^(tun%d+)%s") if dev.name:match("^tun") then
if tun then stations[#stations + 1] = {
tunnel = {
type = "Tunnel", type = "Tunnel",
device = tun, device = dev.name,
signal = nil, ip = dev.dstip,
ip = nil, mac = dev.mac,
mac = nil tx_packets = dev.tx_packets,
tx_fail = dev.tx_fail
} }
stations[#stations + 1] = tunnel elseif dev.name:match("^wgc") then
elseif line:match("^%s*$") then local ip123, ip4 = dev.ip:match("^(%d+%.%d+%.%d+%.)(%d+)$")
tunnel = nil
elseif tunnel then
local ip = line:match("P-t-P:(%d+%.%d+%.%d+%.%d+)")
if ip then
tunnel.ip = ip
-- Fake a mac from the ip
local a, b, c, d = ip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+)$")
tunnel.mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d)
else
local txp, txf = line:match("TX packets:(%d+)%s+errors:(%d+)")
if txp and txf then
tunnel.tx_packets = tonumber(txp)
tunnel.tx_fail = tonumber(txf)
end
end
end
end
-- Wireguard
local wgc = 0
cursorm:foreach("wireguard", "client",
function(s)
if s.enabled == "1" then
local a, b, c, d = s.clientip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+):")
d = tonumber(d) + 1
stations[#stations + 1] = { stations[#stations + 1] = {
type = "Wireguard", type = "Wireguard",
device = "wgc" .. wgc, device = dev.name,
ip = string.format("%d.%d.%d.%d", a, b, c, d), ip = ip123 .. (tonumber(ip4) + 1),
mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d) mac = dev.mac,
tx_packets = dev.tx_packets,
tx_fail = dev.tx_fail
} }
wgc = wgc + 1 elseif dev.name:match("^wgs") then
end local ip123, ip4 = dev.ip:match("^(%d+%.%d+%.%d+%.)(%d+)$")
end
)
local wgs = 0
cursorm:foreach("vtun", "server",
function(s)
if s.enabled == "1" and s.netip:match(":") then
local a, b, c, d, _ = s.netip:match("^(%d+)%.(%d+)%.(%d+)%.(%d+):(%d+)$")
stations[#stations + 1] = { stations[#stations + 1] = {
type = "Wireguard", type = "Wireguard",
device = "wgs" .. wgs, device = dev.name,
ip = string.format("%d.%d.%d.%d", a, b, c, d), ip = ip123 .. (tonumber(ip4) - 1),
mac = string.format("00:00:%02X:%02X:%02X:%02X", a, b, c, d) mac = dev.mac,
tx_packets = dev.tx_packets,
tx_fail = dev.tx_fail
} }
wgs = wgs + 1
end end
end end
)
-- DtD -- DtD
for _, entry in ipairs(arps) for _, entry in ipairs(arps)
@ -472,20 +469,17 @@ function lqm()
cursorm:foreach("xlink", "interface", cursorm:foreach("xlink", "interface",
function(section) function(section)
if section.ifname then if section.ifname then
for _, entry in ipairs(arps) local entry = devices[section.ifname]
do if entry then
if entry["Device"] == section.ifname then
stations[#stations + 1] = { stations[#stations + 1] = {
type = "Xlink", type = "Xlink",
device = section.ifname, device = entry.name,
signal = nil, ip = entry.ip,
ip = entry["IP address"], mac = entry.mac
mac = entry["HW address"]
} }
end end
end end
end end
end
) )
-- Update the trackers based on the latest station information -- Update the trackers based on the latest station information
@ -778,7 +772,7 @@ function lqm()
-- Always allow if user requested it -- Always allow if user requested it
for val in string.gmatch(config.user_allows, "([^,]+)") for val in string.gmatch(config.user_allows, "([^,]+)")
do do
if val:gsub("%s+", ""):gsub("-", ":"):upper() == track.mac then if val:gsub("%s+", ""):gsub("-", ":"):lower() == track.mac then
track.user_allow = true track.user_allow = true
break break
end end
@ -790,7 +784,7 @@ function lqm()
-- Block if user requested it -- Block if user requested it
for val in string.gmatch(config.user_blocks, "([^,]+)") for val in string.gmatch(config.user_blocks, "([^,]+)")
do do
if val:gsub("%s+", ""):gsub("-", ":"):upper() == track.mac then if val:gsub("%s+", ""):gsub("-", ":"):lower() == track.mac then
track.blocks.user = true track.blocks.user = true
break break
end end