#!/usr/bin/lua -- Created by jiaqiang.ye@lnxall.com -- 2024/02/20 -- for Non-openwrt systems local uci = require "uci" local cjson = require "cjson" local invoker = require "invoker" local gfmt = string.format local function get_netdev(name) local nuci = uci.cursor('/etc/config') if not nuci then io.stderr:write("Error, failed to local uci-conf from /etc/config\n") io.stderr:flush() return nil end if name == 'lan' then local ports = nuci:get("network", '@device[0]', 'ports') nuci:close(); nuci = nil if type(ports) ~= "table" or type(ports[1]) ~= "string" then io.stderr:write("Error, failed to find ports for LAN.\n") io.stderr:flush() return false end return table.concat(ports, " ") end local ndev = nuci:get('network', name, 'device') nuci:close(); nuci = nil if type(ndev) ~= "string" or #ndev == 0 then io.stderr:write(gfmt("Error, failed to determine network device for '%s'\n", name)) io.stderr:flush() return nil end return ndev end local function get_proto(name) local nuci, proto = uci.cursor('/etc/config'), nil if nuci then proto = nuci:get('network', name, 'proto') nuci:close(); nuci = nil end if not proto then io.stderr:write(gfmt("Error, failed to get proto for '%s'\n", name)) io.stderr:flush() return "" end return proto end local function get_macaddr(ndev) local okay, output = invoker.invoke(invoker.OUTPUT + invoker.NOSTDIO, "ip", "addr", "show", ndev) if okay ~= 0 or type(output) ~= "string" then io.stderr:write(gfmt("Error, network device not found: %s\n", ndev)) io.stderr:flush() return "", "" end local macaddr = string.match(output, "link/ether%s+([%x:]+)%s+brd") if not macaddr then io.stderr:write(gfmt("Error, no MAC address found for %s => %s\n", ndev, output)) io.stderr:flush() return "", "" end local updown = string.find(output, "state UP", 1, true) and "1" or "0" local ipaddr = string.match(output, "inet%s+([%d./]+)%s+brd") return macaddr, updown, ipaddr end local function fill_status(name, ninfo) local netdev = name == "lan" and "br-lan" or ninfo.l3_device if type(netdev) ~= "string" or #netdev == 0 then netdev = "non0" end ninfo['uptime'] = invoker.uptime() -- what does this mean? ninfo['macaddr'], ninfo['status'], ninfo['subnet'] = get_macaddr(netdev) ninfo["dnss"] = "" -- get DNS via `nmcli con show name local okay, output = invoker.invoke(0xF0000 + invoker.OUTPUT + invoker.NOSTDIO, "nmcli", "con", "show", name) if okay == 0 and type(output) == "string" then local dnss = string.match(output, "domain_name_servers = ([^\r\n]+)") if dnss then ninfo.dnss = dnss end end local prefix = gfmt("/sys/class/net/%s/", netdev) ninfo['speed'] = invoker.readfile(prefix .. 'speed', invoker.TRIMEND) or "" prefix = prefix .. 'statistics/' ninfo['txbytes'] = invoker.readfile(prefix .. 'tx_bytes', invoker.TRIMEND) or "" ninfo['rxbytes'] = invoker.readfile(prefix .. 'rx_bytes', invoker.TRIMEND) or "" ninfo['txpackets'] = invoker.readfile(prefix .. 'tx_packets', invoker.TRIMEND) or "" ninfo['rxpackets'] = invoker.readfile(prefix .. 'rx_packets', invoker.TRIMEND) or "" return true end local function fetch_main() local allinfo = {} local waninfo, wan1_info, winfo, linfo = {}, {}, {}, {} waninfo.l3_device = get_netdev('wan') waninfo.proto = get_proto('wan') fill_status('wan', waninfo) allinfo['wan'] = waninfo local ldev1, proto1 = get_netdev('wan1'), get_proto('wan1') if ldev1 and proto1 then wan1_info.l3_device = ldev1 wan1_info.proto = proto1 fill_status('wan1', wan1_info) allinfo['wan1'] = wan1_info end winfo.l3_device = get_netdev('wwan') winfo.proto = get_proto('wwan') fill_status('wwan', winfo) allinfo['wwan'] = winfo linfo.l3_device = get_netdev('lan') linfo.proto = get_proto('lan') fill_status('lan', linfo) allinfo['lan'] = linfo io.stdout:write(cjson.encode(allinfo)) io.stdout:flush() return true end fetch_main() os.exit(0)