X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=libs%2Fsys%2Fluasrc%2Fsys.lua;h=3412b32b703983397bd59f91df210521ae16af94;hb=98996e380a7301ec5127de83e047d0bf8cf3df43;hp=b4b6f68058832e2b47c43112537553cfe341476e;hpb=950825d323964b40dc53d7386e2d337e655ed33e;p=project%2Fluci.git diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index b4b6f6805..3412b32b7 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -35,7 +35,8 @@ luci.util = require "luci.util" luci.fs = require "luci.fs" luci.ip = require "luci.ip" -local tonumber, ipairs, pairs, pcall = tonumber, ipairs, pairs, pcall +local tonumber, ipairs, pairs, pcall, type = + tonumber, ipairs, pairs, pcall, type --- LuCI Linux and POSIX system utilities. @@ -129,10 +130,16 @@ end -- @return Table containing all variables if no variable name is given getenv = posix.getenv ---- Determine the current hostname. +--- Get or set the current hostname. +-- @param String containing a new hostname to set (optional) -- @return String containing the system hostname -function hostname() - return posix.uname("%n") +function hostname(newname) + if type(newname) == "string" and #newname > 0 then + luci.fs.writefile( "/proc/sys/kernel/hostname", newname .. "\n" ) + return newname + else + return posix.uname("%n") + end end --- Returns the contents of a documented referred by an URL. @@ -266,19 +273,21 @@ end -- @return Table with the currently tracked IP connections function net.conntrack() local connt = {} - if luci.fs.access("/proc/net/nf_conntrack") then + if luci.fs.access("/proc/net/nf_conntrack", "r") then for line in io.lines("/proc/net/nf_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" local entry, flags = _parse_mixed_record(line, " +") entry.layer3 = flags[1] - entry.layer4 = flags[2] + entry.layer4 = flags[3] for i=1, #entry do entry[i] = nil end connt[#connt+1] = entry end - elseif luci.fs.access("/proc/net/ip_conntrack") then + elseif luci.fs.access("/proc/net/ip_conntrack", "r") then for line in io.lines("/proc/net/ip_conntrack") do + line = line:match "^(.-( [^ =]+=).-)%2" local entry, flags = _parse_mixed_record(line, " +") entry.layer3 = "ipv4" entry.layer4 = flags[1] @@ -294,21 +303,40 @@ function net.conntrack() return connt end ---- Determine the current default route. +--- Determine the current IPv4 default route. If multiple default routes exist, +-- return the one with the lowest metric. -- @return Table with the properties of the current default route. -- The following fields are defined: --- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT", --- "MTU", "Gateway", "Destination", "Metric", "Use" } +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } function net.defaultroute() - local routes = net.routes() local route = nil - - for i, r in pairs(luci.sys.net.routes()) do - if r.Destination == "00000000" and (not route or route.Metric > r.Metric) then + for _, r in pairs(net.routes()) do + if r.dest:prefix() == 0 and (not route or route.metric > r.metric) then route = r end end + return route +end +--- Determine the current IPv6 default route. If multiple default routes exist, +-- return the one with the lowest metric. +-- @return Table with the properties of the current default route. +-- The following fields are defined: +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } +function net.defaultroute6() + local route = nil + local routes6 = net.routes6() + if routes6 then + for _, r in pairs(routes6) do + if r.dest:prefix() == 0 and + (not route or route.metric > r.metric) + then + route = r + end + end + end return route end @@ -355,57 +383,88 @@ end --- Returns the current kernel routing table entries. -- @return Table of tables with properties of the corresponding routes. -- The following fields are defined for route entry tables: --- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT", --- "MTU", "Gateway", "Destination", "Metric", "Use" } +-- { "dest", "gateway", "metric", "refcount", "usecount", "irtt", +-- "flags", "device" } function net.routes() - return _parse_delimited_table(io.lines("/proc/net/route")) + local routes = { } + + for line in io.lines("/proc/net/route") do + + local dev, dst_ip, gateway, flags, refcnt, usecnt, metric, + dst_mask, mtu, win, irtt = line:match( + "([^%s]+)\t([A-F0-9]+)\t([A-F0-9]+)\t([A-F0-9]+)\t" .. + "(%d+)\t(%d+)\t(%d+)\t([A-F0-9]+)\t(%d+)\t(%d+)\t(%d+)" + ) + + if dev then + gateway = luci.ip.Hex( gateway, 32, luci.ip.FAMILY_INET4 ) + dst_mask = luci.ip.Hex( dst_mask, 32, luci.ip.FAMILY_INET4 ) + dst_ip = luci.ip.Hex( + dst_ip, dst_mask:prefix(dst_mask), luci.ip.FAMILY_INET4 + ) + + routes[#routes+1] = { + dest = dst_ip, + gateway = gateway, + metric = tonumber(metric), + refcount = tonumber(refcnt), + usecount = tonumber(usecnt), + mtu = tonumber(mtu), + window = tonumber(window), + irtt = tonumber(irtt), + flags = tonumber(flags, 16), + device = dev + } + end + end + + return routes end --- Returns the current ipv6 kernel routing table entries. -- @return Table of tables with properties of the corresponding routes. -- The following fields are defined for route entry tables: --- { "src_ip", "src_prefix", "dst_ip", "dst_prefix", "nexthop_ip", --- "metric", "refcount", "usecount", "flags", "device" } +-- { "source", "dest", "nexthop", "metric", "refcount", "usecount", +-- "flags", "device" } function net.routes6() - local routes = { } - - for line in io.lines("/proc/net/ipv6_route") do - - local dst_ip, dst_prefix, src_ip, src_prefix, nexthop, - metric, refcnt, usecnt, flags, dev = line:match( - "([a-f0-9]+) ([a-f0-9]+) " .. - "([a-f0-9]+) ([a-f0-9]+) " .. - "([a-f0-9]+) ([a-f0-9]+) " .. - "(%d+) (%d+) ([^%s]+) +([^%s]+)" - ) - - src_ip = luci.ip.Hex( - src_ip, tonumber(src_prefix, 16), - luci.ip.FAMILY_INET6, false - ) - - dst_ip = luci.ip.Hex( - dst_ip, tonumber(dst_prefix, 16), - luci.ip.FAMILY_INET6, false - ) - - nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false ) - - routes[#routes+1] = { - src_ip = src_ip:host():string(), - src_prefix = src_ip:prefix(), - dst_ip = dst_ip:host():string(), - dst_prefix = dst_ip:prefix(), - nexthop_ip = nexthop:string(), - metric = tonumber(metric, 16), - refcount = tonumber(refcnt), - usecount = tonumber(usecnt), - flags = tonumber(flags), -- hex? - device = dev - } - end + if luci.fs.access("/proc/net/ipv6_route", "r") then + local routes = { } + + for line in io.lines("/proc/net/ipv6_route") do + + local dst_ip, dst_prefix, src_ip, src_prefix, nexthop, + metric, refcnt, usecnt, flags, dev = line:match( + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) ([a-f0-9]+) " .. + "([a-f0-9]+) +([^%s]+)" + ) + + src_ip = luci.ip.Hex( + src_ip, tonumber(src_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + dst_ip = luci.ip.Hex( + dst_ip, tonumber(dst_prefix, 16), luci.ip.FAMILY_INET6, false + ) + + nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false ) + + routes[#routes+1] = { + source = src_ip, + dest = dst_ip, + nexthop = nexthop, + metric = tonumber(metric, 16), + refcount = tonumber(refcnt, 16), + usecount = tonumber(usecnt, 16), + flags = tonumber(flags, 16), + device = dev + } + end - return routes + return routes + end end --- Tests whether the given host responds to ping probes. @@ -575,7 +634,7 @@ wifi = {} --- Get iwconfig output for all wireless devices. -- @return Table of tables containing the iwconfing output for each wifi device function wifi.getiwconfig() - local cnt = luci.util.exec("/usr/sbin/iwconfig 2>/dev/null") + local cnt = luci.util.exec("PATH=/sbin:/usr/sbin iwconfig 2>/dev/null") local iwc = {} for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do @@ -622,6 +681,36 @@ function wifi.iwscan(iface) return iface and (iws[iface] or {}) or iws end +--- Get available channels from given wireless iface. +-- @param iface Wireless interface (optional) +-- @return Table of available channels +function wifi.channels(iface) + local cmd = "iwlist " .. ( iface or "" ) .. " freq 2>/dev/null" + local cns = { } + + local fd = io.popen(cmd) + if fd then + local ln, c, f + repeat + ln = fd:read("*l") or "" + c, f = ln:match("Channel (%d+) : (%d+%.%d+) GHz") + if c and f then + cns[tonumber(c)] = tonumber(f) + end + until not ( #ln > 0 ) + fd:close() + end + + if #cns == 0 then + cms = { + 2.412, 2.417, 2.422, 2.427, 2.432, 2.437, + 2.442, 2.447, 2.452, 2.457, 2.462 + } + end + + return cns +end + --- LuCI system utilities / init related functions. -- @class module @@ -714,17 +803,17 @@ function _parse_mixed_record(cnt, delimiter) for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do for j, f in pairs(luci.util.split(luci.util.trim(l), delimiter, nil, true)) do - local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*') + local k, x, v = f:match('([^%s][^:=]*) *([:=]*) *"*([^\n"]*)"*') - if k then + if k then if x == "" then table.insert(flags, k) else - data[k] = v + data[k] = v end - end - end + end + end end - return data, flags + return data, flags end