From df8601c86415bd048b00ce992b2bf2a81e9c4b38 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 8 Aug 2012 15:20:03 +0000 Subject: [PATCH] libs/sys: introduce net.mac_hints(), net.ipv4_hints() and net.ipv6_hints() functions to obtain lists of peers from various sources (e.g. ethers, leases, arp cache) --- libs/sys/luasrc/sys.lua | 143 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 141 insertions(+), 2 deletions(-) diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index b8a1c5041..f6f95625d 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -36,8 +36,8 @@ local luci = {} luci.util = require "luci.util" luci.ip = require "luci.ip" -local tonumber, ipairs, pairs, pcall, type, next, setmetatable, require = - tonumber, ipairs, pairs, pcall, type, next, setmetatable, require +local tonumber, ipairs, pairs, pcall, type, next, setmetatable, require, select = + tonumber, ipairs, pairs, pcall, type, next, setmetatable, require, select --- LuCI Linux and POSIX system utilities. @@ -233,6 +233,145 @@ function net.arptable(callback) return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+", callback) end +local function _nethints(what, callback) + local _, k, e, mac, ip, name + local ifn = { } + local hosts = { } + + local function _add(i, ...) + local k = select(i, ...) + if k then + if not hosts[k] then hosts[k] = { } end + hosts[k][1] = select(1, ...) or hosts[k][1] + hosts[k][2] = select(2, ...) or hosts[k][2] + hosts[k][3] = select(3, ...) or hosts[k][3] + hosts[k][4] = select(4, ...) or hosts[k][4] + end + end + + if fs.access("/proc/net/arp") then + for e in io.lines("/proc/net/arp") do + ip, mac = e:match("^([%d%.]+)%s+%S+%s+%S+%s+([a-fA-F0-9:]+)%s+") + if ip and mac then + _add(what, mac:upper(), ip, nil, nil) + end + end + end + + if fs.access("/etc/ethers") then + for e in io.lines("/etc/ethers") do + mac, ip = e:match("^([a-f0-9]%S+) (%S+)") + if mac and ip then + _add(what, mac:upper(), ip, nil, nil) + end + end + end + + if fs.access("/var/dhcp.leases") then + for e in io.lines("/var/dhcp.leases") do + mac, ip, name = e:match("^%d+ (%S+) (%S+) (%S+)") + if mac and ip then + _add(what, mac:upper(), ip, nil, name ~= "*" and name) + end + end + end + + for _, e in ipairs(nixio.getifaddrs()) do + if e.name ~= "lo" then + ifn[e.name] = ifn[e.name] or { } + if e.family == "packet" and e.addr and #e.addr == 17 then + ifn[e.name][1] = e.addr:upper() + elseif e.family == "inet" then + ifn[e.name][2] = e.addr + elseif e.family == "inet6" then + ifn[e.name][3] = e.addr + end + end + end + + for _, e in pairs(ifn) do + if e[what] and (e[2] or e[3]) then + _add(what, e[1], e[2], e[3], e[4]) + end + end + + for _, e in luci.util.kspairs(hosts) do + callback(e[1], e[2], e[3], e[4]) + end +end + +--- Returns a two-dimensional table of mac address hints. +-- @return Table of table containing known hosts from various sources. +-- Each entry contains the values in the following order: +-- [ "mac", "name" ] +function net.mac_hints(callback) + if callback then + _nethints(1, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v4 or v6) or v4 + if name and name ~= mac then + callback(mac, name or nixio.getnameinfo(v4 or v6) or v4) + end + end) + else + local rv = { } + _nethints(1, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v4 or v6) or v4 + if name and name ~= mac then + rv[#rv+1] = { mac, name or nixio.getnameinfo(v4 or v6) or v4 } + end + end) + return rv + end +end + +--- Returns a two-dimensional table of IPv4 address hints. +-- @return Table of table containing known hosts from various sources. +-- Each entry contains the values in the following order: +-- [ "ip", "name" ] +function net.ipv4_hints(callback) + if callback then + _nethints(2, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v4) or mac + if name and name ~= v4 then + callback(v4, name) + end + end) + else + local rv = { } + _nethints(2, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v4) or mac + if name and name ~= v4 then + rv[#rv+1] = { v4, name } + end + end) + return rv + end +end + +--- Returns a two-dimensional table of IPv6 address hints. +-- @return Table of table containing known hosts from various sources. +-- Each entry contains the values in the following order: +-- [ "ip", "name" ] +function net.ipv6_hints(callback) + if callback then + _nethints(3, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v6) or mac + if name and name ~= v6 then + callback(v6, name) + end + end) + else + local rv = { } + _nethints(3, function(mac, v4, v6, name) + name = name or nixio.getnameinfo(v6) or mac + if name and name ~= v6 then + rv[#rv+1] = { v6, name } + end + end) + return rv + end +end + --- Returns conntrack information -- @return Table with the currently tracked IP connections function net.conntrack(callback) -- 2.25.1