Merge pull request #1709 from dibdot/get_interface-fix
[project/luci.git] / modules / luci-base / luasrc / tools / status.lua
1 -- Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
2 -- Licensed to the public under the Apache License 2.0.
3
4 module("luci.tools.status", package.seeall)
5
6 local uci = require "luci.model.uci".cursor()
7 local ipc = require "luci.ip"
8
9 local function dhcp_leases_common(family)
10         local rv = { }
11         local nfs = require "nixio.fs"
12         local leasefile = "/tmp/dhcp.leases"
13
14         uci:foreach("dhcp", "dnsmasq",
15                 function(s)
16                         if s.leasefile and nfs.access(s.leasefile) then
17                                 leasefile = s.leasefile
18                                 return false
19                         end
20                 end)
21
22         local fd = io.open(leasefile, "r")
23         if fd then
24                 while true do
25                         local ln = fd:read("*l")
26                         if not ln then
27                                 break
28                         else
29                                 local ts, mac, ip, name, duid = ln:match("^(%d+) (%S+) (%S+) (%S+) (%S+)")
30                                 local expire = tonumber(ts) or 0
31                                 if ts and mac and ip and name and duid then
32                                         if family == 4 and not ip:match(":") then
33                                                 rv[#rv+1] = {
34                                                         expires  = (expire ~= 0) and os.difftime(expire, os.time()),
35                                                         macaddr  = ipc.checkmac(mac) or "00:00:00:00:00:00",
36                                                         ipaddr   = ip,
37                                                         hostname = (name ~= "*") and name
38                                                 }
39                                         elseif family == 6 and ip:match(":") then
40                                                 rv[#rv+1] = {
41                                                         expires  = (expire ~= 0) and os.difftime(expire, os.time()),
42                                                         ip6addr  = ip,
43                                                         duid     = (duid ~= "*") and duid,
44                                                         hostname = (name ~= "*") and name
45                                                 }
46                                         end
47                                 end
48                         end
49                 end
50                 fd:close()
51         end
52
53         local lease6file = "/tmp/hosts/odhcpd"
54         uci:foreach("dhcp", "odhcpd",
55                 function(t)
56                         if t.leasefile and nfs.access(t.leasefile) then
57                                 lease6file = t.leasefile
58                                 return false
59                         end
60                 end)
61         local fd = io.open(lease6file, "r")
62         if fd then
63                 while true do
64                         local ln = fd:read("*l")
65                         if not ln then
66                                 break
67                         else
68                                 local iface, duid, iaid, name, ts, id, length, ip = ln:match("^# (%S+) (%S+) (%S+) (%S+) (-?%d+) (%S+) (%S+) (.*)")
69                                 local expire = tonumber(ts) or 0
70                                 if ip and iaid ~= "ipv4" and family == 6 then
71                                         rv[#rv+1] = {
72                                                 expires  = (expire >= 0) and os.difftime(expire, os.time()),
73                                                 duid     = duid,
74                                                 ip6addr  = ip,
75                                                 hostname = (name ~= "-") and name
76                                         }
77                                 elseif ip and iaid == "ipv4" and family == 4 then
78                                         rv[#rv+1] = {
79                                                 expires  = (expire >= 0) and os.difftime(expire, os.time()),
80                                                 macaddr  = ipc.checkmac(duid:gsub("^(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)$", "%1:%2:%3:%4:%5:%6")) or "00:00:00:00:00:00",
81                                                 ipaddr   = ip,
82                                                 hostname = (name ~= "-") and name
83                                         }
84                                 end
85                         end
86                 end
87                 fd:close()
88         end
89
90         return rv
91 end
92
93 function dhcp_leases()
94         return dhcp_leases_common(4)
95 end
96
97 function dhcp6_leases()
98         return dhcp_leases_common(6)
99 end
100
101 function wifi_networks()
102         local rv = { }
103         local ntm = require "luci.model.network".init()
104
105         local dev
106         for _, dev in ipairs(ntm:get_wifidevs()) do
107                 local rd = {
108                         up       = dev:is_up(),
109                         device   = dev:name(),
110                         name     = dev:get_i18n(),
111                         networks = { }
112                 }
113
114                 local net
115                 for _, net in ipairs(dev:get_wifinets()) do
116                         rd.networks[#rd.networks+1] = {
117                                 name       = net:shortname(),
118                                 link       = net:adminlink(),
119                                 up         = net:is_up(),
120                                 mode       = net:active_mode(),
121                                 ssid       = net:active_ssid(),
122                                 bssid      = net:active_bssid(),
123                                 encryption = net:active_encryption(),
124                                 frequency  = net:frequency(),
125                                 channel    = net:channel(),
126                                 signal     = net:signal(),
127                                 quality    = net:signal_percent(),
128                                 noise      = net:noise(),
129                                 bitrate    = net:bitrate(),
130                                 ifname     = net:ifname(),
131                                 assoclist  = net:assoclist(),
132                                 country    = net:country(),
133                                 txpower    = net:txpower(),
134                                 txpoweroff = net:txpower_offset(),
135                                 disabled   = (dev:get("disabled") == "1" or
136                                              net:get("disabled") == "1")
137                         }
138                 end
139
140                 rv[#rv+1] = rd
141         end
142
143         return rv
144 end
145
146 function wifi_network(id)
147         local ntm = require "luci.model.network".init()
148         local net = ntm:get_wifinet(id)
149         if net then
150                 local dev = net:get_device()
151                 if dev then
152                         return {
153                                 id         = id,
154                                 name       = net:shortname(),
155                                 link       = net:adminlink(),
156                                 up         = net:is_up(),
157                                 mode       = net:active_mode(),
158                                 ssid       = net:active_ssid(),
159                                 bssid      = net:active_bssid(),
160                                 encryption = net:active_encryption(),
161                                 frequency  = net:frequency(),
162                                 channel    = net:channel(),
163                                 signal     = net:signal(),
164                                 quality    = net:signal_percent(),
165                                 noise      = net:noise(),
166                                 bitrate    = net:bitrate(),
167                                 ifname     = net:ifname(),
168                                 assoclist  = net:assoclist(),
169                                 country    = net:country(),
170                                 txpower    = net:txpower(),
171                                 txpoweroff = net:txpower_offset(),
172                                 disabled   = (dev:get("disabled") == "1" or
173                                               net:get("disabled") == "1"),
174                                 device     = {
175                                         up     = dev:is_up(),
176                                         device = dev:name(),
177                                         name   = dev:get_i18n()
178                                 }
179                         }
180                 end
181         end
182         return { }
183 end
184
185 function switch_status(devs)
186         local dev
187         local switches = { }
188         for dev in devs:gmatch("[^%s,]+") do
189                 local ports = { }
190                 local swc = io.popen("swconfig dev %s show"
191                         % luci.util.shellquote(dev), "r")
192
193                 if swc then
194                         local l
195                         repeat
196                                 l = swc:read("*l")
197                                 if l then
198                                         local port, up = l:match("port:(%d+) link:(%w+)")
199                                         if port then
200                                                 local speed  = l:match(" speed:(%d+)")
201                                                 local duplex = l:match(" (%w+)-duplex")
202                                                 local txflow = l:match(" (txflow)")
203                                                 local rxflow = l:match(" (rxflow)")
204                                                 local auto   = l:match(" (auto)")
205
206                                                 ports[#ports+1] = {
207                                                         port   = tonumber(port) or 0,
208                                                         speed  = tonumber(speed) or 0,
209                                                         link   = (up == "up"),
210                                                         duplex = (duplex == "full"),
211                                                         rxflow = (not not rxflow),
212                                                         txflow = (not not txflow),
213                                                         auto   = (not not auto)
214                                                 }
215                                         end
216                                 end
217                         until not l
218                         swc:close()
219                 end
220                 switches[dev] = ports
221         end
222         return switches
223 end