Merge pull request #1735 from sumpfralle/olsr-jsoninfo-parser-handle-empty-result
[oweals/luci.git] / modules / luci-base / luasrc / tools / status.lua
index 0efc51be23a5145f5586074f1ce4fbf6ef214421..dc30c064c04bd73438e305debca54c2fc3436d8c 100644 (file)
@@ -1,24 +1,16 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
+-- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
 
 module("luci.tools.status", package.seeall)
 
 local uci = require "luci.model.uci".cursor()
+local ipc = require "luci.ip"
 
 local function dhcp_leases_common(family)
        local rv = { }
        local nfs = require "nixio.fs"
-       local leasefile = "/var/dhcp.leases"
+       local sys = require "luci.sys"
+       local leasefile = "/tmp/dhcp.leases"
 
        uci:foreach("dhcp", "dnsmasq",
                function(s)
@@ -36,17 +28,18 @@ local function dhcp_leases_common(family)
                                break
                        else
                                local ts, mac, ip, name, duid = ln:match("^(%d+) (%S+) (%S+) (%S+) (%S+)")
+                               local expire = tonumber(ts) or 0
                                if ts and mac and ip and name and duid then
                                        if family == 4 and not ip:match(":") then
                                                rv[#rv+1] = {
-                                                       expires  = os.difftime(tonumber(ts) or 0, os.time()),
-                                                       macaddr  = mac,
+                                                       expires  = (expire ~= 0) and os.difftime(expire, os.time()),
+                                                       macaddr  = ipc.checkmac(mac) or "00:00:00:00:00:00",
                                                        ipaddr   = ip,
                                                        hostname = (name ~= "*") and name
                                                }
                                        elseif family == 6 and ip:match(":") then
                                                rv[#rv+1] = {
-                                                       expires  = os.difftime(tonumber(ts) or 0, os.time()),
+                                                       expires  = (expire ~= 0) and os.difftime(expire, os.time()),
                                                        ip6addr  = ip,
                                                        duid     = (duid ~= "*") and duid,
                                                        hostname = (name ~= "*") and name
@@ -58,25 +51,34 @@ local function dhcp_leases_common(family)
                fd:close()
        end
 
-       local fd = io.open("/tmp/hosts/odhcpd", "r")
+       local lease6file = "/tmp/hosts/odhcpd"
+       uci:foreach("dhcp", "odhcpd",
+               function(t)
+                       if t.leasefile and nfs.access(t.leasefile) then
+                               lease6file = t.leasefile
+                               return false
+                       end
+               end)
+       local fd = io.open(lease6file, "r")
        if fd then
                while true do
                        local ln = fd:read("*l")
                        if not ln then
                                break
                        else
-                               local iface, duid, iaid, name, ts, id, length, ip = ln:match("^# (%S+) (%S+) (%S+) (%S+) (%d+) (%S+) (%S+) (.*)")
+                               local iface, duid, iaid, name, ts, id, length, ip = ln:match("^# (%S+) (%S+) (%S+) (%S+) (-?%d+) (%S+) (%S+) (.*)")
+                               local expire = tonumber(ts) or 0
                                if ip and iaid ~= "ipv4" and family == 6 then
                                        rv[#rv+1] = {
-                                               expires  = os.difftime(tonumber(ts) or 0, os.time()),
+                                               expires  = (expire >= 0) and os.difftime(expire, os.time()),
                                                duid     = duid,
                                                ip6addr  = ip,
                                                hostname = (name ~= "-") and name
                                        }
                                elseif ip and iaid == "ipv4" and family == 4 then
                                        rv[#rv+1] = {
-                                               expires  = os.difftime(tonumber(ts) or 0, os.time()),
-                                               macaddr  = duid,
+                                               expires  = (expire >= 0) and os.difftime(expire, os.time()),
+                                               macaddr  = sys.net.duid_to_mac(duid) or "00:00:00:00:00:00",
                                                ipaddr   = ip,
                                                hostname = (name ~= "-") and name
                                        }
@@ -86,6 +88,22 @@ local function dhcp_leases_common(family)
                fd:close()
        end
 
+       if family == 6 then
+               local _, lease
+               local hosts = sys.net.host_hints()
+               for _, lease in ipairs(rv) do
+                       local mac = sys.net.duid_to_mac(lease.duid)
+                       local host = mac and hosts[mac]
+                       if host then
+                               if not lease.name then
+                                       lease.host_hint = host.name or host.ipv4 or host.ipv6
+                               elseif host.name and lease.hostname ~= host.name then
+                                       lease.host_hint = host.name
+                               end
+                       end
+               end
+       end
+
        return rv
 end
 
@@ -112,6 +130,11 @@ function wifi_networks()
 
                local net
                for _, net in ipairs(dev:get_wifinets()) do
+                       local a, an = nil, 0
+                       for _, a in pairs(net:assoclist() or {}) do
+                               an = an + 1
+                       end
+
                        rd.networks[#rd.networks+1] = {
                                name       = net:shortname(),
                                link       = net:adminlink(),
@@ -127,10 +150,12 @@ function wifi_networks()
                                noise      = net:noise(),
                                bitrate    = net:bitrate(),
                                ifname     = net:ifname(),
-                               assoclist  = net:assoclist(),
                                country    = net:country(),
                                txpower    = net:txpower(),
-                               txpoweroff = net:txpower_offset()
+                               txpoweroff = net:txpower_offset(),
+                               num_assoc  = an,
+                               disabled   = (dev:get("disabled") == "1" or
+                                            net:get("disabled") == "1")
                        }
                end
 
@@ -162,7 +187,6 @@ function wifi_network(id)
                                noise      = net:noise(),
                                bitrate    = net:bitrate(),
                                ifname     = net:ifname(),
-                               assoclist  = net:assoclist(),
                                country    = net:country(),
                                txpower    = net:txpower(),
                                txpoweroff = net:txpower_offset(),
@@ -179,40 +203,48 @@ function wifi_network(id)
        return { }
 end
 
-function switch_status(devs)
-       local dev
-       local switches = { }
-       for dev in devs:gmatch("[^%s,]+") do
-               local ports = { }
-               local swc = io.popen("swconfig dev %q show" % dev, "r")
-               if swc then
-                       local l
-                       repeat
-                               l = swc:read("*l")
-                               if l then
-                                       local port, up = l:match("port:(%d+) link:(%w+)")
-                                       if port then
-                                               local speed  = l:match(" speed:(%d+)")
-                                               local duplex = l:match(" (%w+)-duplex")
-                                               local txflow = l:match(" (txflow)")
-                                               local rxflow = l:match(" (rxflow)")
-                                               local auto   = l:match(" (auto)")
-
-                                               ports[#ports+1] = {
-                                                       port   = tonumber(port) or 0,
-                                                       speed  = tonumber(speed) or 0,
-                                                       link   = (up == "up"),
-                                                       duplex = (duplex == "full"),
-                                                       rxflow = (not not rxflow),
-                                                       txflow = (not not txflow),
-                                                       auto   = (not not auto)
-                                               }
-                                       end
-                               end
-                       until not l
-                       swc:close()
+function wifi_assoclist()
+       local sys = require "luci.sys"
+       local ntm = require "luci.model.network".init()
+       local hosts = sys.net.host_hints()
+
+       local assoc = {}
+       local _, dev, net, bss
+
+       for _, dev in ipairs(ntm:get_wifidevs()) do
+               local radioname = dev:get_i18n()
+
+               for _, net in ipairs(dev:get_wifinets()) do
+                       local netname = net:shortname()
+                       local netlink = net:adminlink()
+                       local ifname  = net:ifname()
+
+                       for _, bss in pairs(net:assoclist() or {}) do
+                               local host = hosts[_]
+
+                               bss.bssid  = _
+                               bss.ifname = ifname
+                               bss.radio  = radioname
+                               bss.name   = netname
+                               bss.link   = netlink
+
+                               bss.host_name = (host) and (host.name or host.ipv4 or host.ipv6)
+                               bss.host_hint = (host and host.name and (host.ipv4 or host.ipv6)) and (host.ipv4 or host.ipv6)
+
+                               assoc[#assoc+1] = bss
+                       end
                end
-               switches[dev] = ports
        end
-       return switches
+
+       table.sort(assoc, function(a, b)
+               if a.radio ~= b.radio then
+                       return a.radio < b.radio
+               elseif a.ifname ~= b.ifname then
+                       return a.ifname < b.ifname
+               else
+                       return a.bssid < b.bssid
+               end
+       end)
+
+       return assoc
 end