status 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #!/usr/bin/lua
  2. local util = require("luci.util")
  3. local fs = require("luci.fs")
  4. local ltn12 = require 'luci.ltn12'
  5. local sys = require("luci.sys")
  6. local json = require("luci.json")
  7. local nixio = require 'nixio'
  8. local platform_info = require("platform_info")
  9. local hostname = sys.hostname()
  10. local model = platform_info.get_model()
  11. local release = util.trim(fs.readfile("/lib/gluon/release") or "")
  12. function escape_html(s)
  13. return (s:gsub('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;'):gsub('"', '&quot;'))
  14. end
  15. function neighbours(ifname)
  16. local info = util.exec("gluon-neighbour-info -d ff02::2:1001 -p 1001 -r nodeinfo -t 3 -i " .. ifname)
  17. local macs = {}
  18. for _, line in ipairs(util.split(info)) do
  19. local data = json.decode(line)
  20. if data then
  21. local function add_macs(list)
  22. if list then
  23. for _, mac in ipairs(list) do
  24. macs[mac] = data
  25. end
  26. end
  27. end
  28. if data["network"] then
  29. add_macs(data["network"]["mesh_interfaces"])
  30. if data["network"]["mesh"] and data["network"]["mesh"]["bat0"] and
  31. data["network"]["mesh"]["bat0"]["interfaces"] then
  32. local interfaces = data["network"]["mesh"]["bat0"]["interfaces"]
  33. add_macs(interfaces["other"])
  34. add_macs(interfaces["wireless"])
  35. add_macs(interfaces["tunnel"])
  36. end
  37. end
  38. end
  39. end
  40. return macs
  41. end
  42. io.write("Content-type: text/html\n\n")
  43. io.write("<!DOCTYPE html>\n")
  44. io.write("<html>")
  45. io.write("<head>")
  46. io.write("<script src=\"/status.js\"></script>")
  47. io.write("<title>" .. escape_html(hostname) .. "</title>")
  48. io.write("</head>")
  49. io.write("<body>")
  50. io.write("<h1>" .. escape_html(hostname) .. "</h1>")
  51. io.write("<pre>")
  52. io.write("Model: " .. escape_html(model) .. "\n")
  53. io.write("Firmware release: " .. escape_html(release) .. "\n\n")
  54. io.write(escape_html(util.trim(sys.exec("uptime | sed 's/^ \+//'"))) .. "\n\n")
  55. io.write(escape_html(sys.exec("ip address show dev br-client")) .. "\n")
  56. io.write(escape_html(sys.exec("free -m")) .. "\n")
  57. io.write(escape_html(sys.exec("df /rom /overlay")))
  58. io.write("</pre>")
  59. io.write("<h2>Neighbours</h2>")
  60. local interfaces = util.split(util.trim(util.exec("iw dev | grep IBSS -B 5 | grep Interface | cut -d' ' -f2")))
  61. for _, ifname in ipairs(interfaces) do
  62. io.write("<h3>" .. escape_html(ifname) .. "</h3>")
  63. io.write("<pre>")
  64. io.write(escape_html(sys.exec("iw dev " .. ifname .. " link")) .. "\n")
  65. for _, line in ipairs(util.split(util.exec("iw dev " .. ifname .. " station dump"))) do
  66. local mac = line:match("^Station (.*) %(on ")
  67. if mac then
  68. io.write("Station <a id=\"" .. escape_html(ifname) .. "-" .. mac .. "\">" .. mac .. "</a> (on " .. escape_html(ifname) .. ")\n")
  69. else
  70. io.write(escape_html(line) .. "\n")
  71. end
  72. end
  73. io.write("</pre>")
  74. end
  75. local stat, fastd_status = pcall(
  76. function()
  77. local fastd_sock = nixio.socket('unix', 'stream')
  78. assert(fastd_sock:connect('/var/run/fastd.mesh_vpn.socket'))
  79. decoder = json.Decoder()
  80. ltn12.pump.all(ltn12.source.file(fastd_sock), decoder:sink())
  81. return decoder:get()
  82. end
  83. )
  84. io.write("<h2>VPN status</h2>")
  85. io.write("<pre>")
  86. if stat then
  87. io.write(string.format("fastd running for %.3f seconds\n", fastd_status.uptime/1000))
  88. local peers = 0
  89. local connections = 0
  90. for key, peer in pairs(fastd_status.peers) do
  91. peers = peers+1
  92. if peer.connection then
  93. connections = connections+1
  94. end
  95. end
  96. io.write(string.format("There are %i peers configured, of which %i are connected:\n\n", peers, connections))
  97. for key, peer in pairs(fastd_status.peers) do
  98. io.write(string.format("%s: ", escape_html(peer.name)))
  99. if peer.connection then
  100. io.write(string.format("connected for %.3f seconds\n", peer.connection.established/1000))
  101. else
  102. io.write("not connected\n")
  103. end
  104. end
  105. else
  106. io.write("fastd not running")
  107. end
  108. io.write("</pre>")
  109. io.write("<script>")
  110. for _, ifname in ipairs(interfaces) do
  111. local macs = neighbours(ifname)
  112. for mac, node in pairs(macs) do
  113. local hostname = node["hostname"]
  114. local ip
  115. if node["network"] and node["network"]["addresses"] then
  116. for _, myip in ipairs(node["network"]["addresses"]) do
  117. if ip == nil and myip:sub(1, 5) ~= "fe80:" then
  118. ip = myip
  119. end
  120. end
  121. end
  122. if ip and hostname then
  123. io.write("update_node(\"" .. escape_html(ifname) .. "-" .. mac .. "\", \"" .. escape_html(ip) .. "\", \"" .. escape_html(hostname) .. "\");")
  124. end
  125. end
  126. end
  127. io.write("</script>")
  128. io.write("</body>")
  129. io.write("</html>")