status.lua 7.0 KB

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