olsr.lua 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. module("luci.controller.olsr", package.seeall)
  2. local neigh_table = nil
  3. local ifaddr_table = nil
  4. function index()
  5. local ipv4,ipv6
  6. if nixio.fs.access("/etc/config/olsrd") then
  7. ipv4 = 1
  8. end
  9. if nixio.fs.access("/etc/config/olsrd6") then
  10. ipv6 = 1
  11. end
  12. if not ipv4 and not ipv6 then
  13. return
  14. end
  15. require("luci.model.uci")
  16. local uci = luci.model.uci.cursor_state()
  17. uci:foreach("olsrd", "olsrd", function(s)
  18. if s.SmartGateway and s.SmartGateway == "yes" then has_smartgw = true end
  19. end)
  20. local page = node("admin", "status", "olsr")
  21. page.target = template("status-olsr/overview")
  22. page.title = _("OLSR")
  23. page.subindex = true
  24. local page = node("admin", "status", "olsr", "json")
  25. page.target = call("action_json")
  26. page.title = nil
  27. page.leaf = true
  28. local page = node("admin", "status", "olsr", "neighbors")
  29. page.target = call("action_neigh")
  30. page.title = _("Neighbours")
  31. page.subindex = true
  32. page.order = 5
  33. local page = node("admin", "status", "olsr", "routes")
  34. page.target = call("action_routes")
  35. page.title = _("Routes")
  36. page.order = 10
  37. local page = node("admin", "status", "olsr", "topology")
  38. page.target = call("action_topology")
  39. page.title = _("Topology")
  40. page.order = 20
  41. local page = node("admin", "status", "olsr", "hna")
  42. page.target = call("action_hna")
  43. page.title = _("HNA")
  44. page.order = 30
  45. local page = node("admin", "status", "olsr", "mid")
  46. page.target = call("action_mid")
  47. page.title = _("MID")
  48. page.order = 50
  49. if has_smartgw then
  50. local page = node("admin", "status", "olsr", "smartgw")
  51. page.target = call("action_smartgw")
  52. page.title = _("SmartGW")
  53. page.order = 60
  54. end
  55. local page = node("admin", "status", "olsr", "interfaces")
  56. page.target = call("action_interfaces")
  57. page.title = _("Interfaces")
  58. page.order = 70
  59. odsp = entry(
  60. {"admin", "services", "olsrd", "display"},
  61. cbi("olsr/olsrddisplay"), _("Display")
  62. )
  63. end
  64. function action_json()
  65. local http = require "luci.http"
  66. local utl = require "luci.util"
  67. local uci = require "luci.model.uci".cursor()
  68. local jsonreq4
  69. local jsonreq6
  70. local v4_port = uci:get("olsrd", "olsrd_jsoninfo", "port") or 9090
  71. local v6_port = uci:get("olsrd6", "olsrd_jsoninfo", "port") or 9090
  72. jsonreq4 = utl.exec("(echo /status | nc 127.0.0.1 " .. v4_port .. ") 2>/dev/null" )
  73. jsonreq6 = utl.exec("(echo /status | nc ::1 " .. v6_port .. ") 2>/dev/null")
  74. http.prepare_content("application/json")
  75. if not jsonreq4 or jsonreq4 == "" then
  76. jsonreq4 = "{}"
  77. end
  78. if not jsonreq6 or jsonreq6 == "" then
  79. jsonreq6 = "{}"
  80. end
  81. http.write('{"v4":' .. jsonreq4 .. ', "v6":' .. jsonreq6 .. '}')
  82. end
  83. local function local_mac_lookup(ipaddr)
  84. local _, ifa, dev
  85. ipaddr = tostring(ipaddr)
  86. if not ifaddr_table then
  87. ifaddr_table = nixio.getifaddrs()
  88. end
  89. -- ipaddr -> ifname
  90. for _, ifa in ipairs(ifaddr_table) do
  91. if ifa.addr == ipaddr then
  92. dev = ifa.name
  93. break
  94. end
  95. end
  96. -- ifname -> macaddr
  97. for _, ifa in ipairs(ifaddr_table) do
  98. if ifa.name == dev and ifa.family == "packet" then
  99. return ifa.addr
  100. end
  101. end
  102. end
  103. local function remote_mac_lookup(ipaddr)
  104. local _, n
  105. if not neigh_table then
  106. neigh_table = luci.ip.neighbors()
  107. end
  108. for _, n in ipairs(neigh_table) do
  109. if n.mac and n.dest and n.dest:equal(ipaddr) then
  110. return n.mac
  111. end
  112. end
  113. end
  114. function action_neigh(json)
  115. local data, has_v4, has_v6, error = fetch_jsoninfo('links')
  116. if error then
  117. return
  118. end
  119. local uci = require "luci.model.uci".cursor_state()
  120. local resolve = uci:get("luci_olsr", "general", "resolve")
  121. local ntm = require "luci.model.network".init()
  122. local devices = ntm:get_wifidevs()
  123. local sys = require "luci.sys"
  124. local assoclist = {}
  125. --local neightbl = require "neightbl"
  126. local ntm = require "luci.model.network"
  127. local ipc = require "luci.ip"
  128. local nxo = require "nixio"
  129. local defaultgw
  130. ipc.routes({ family = 4, type = 1, dest_exact = "0.0.0.0/0" },
  131. function(rt) defaultgw = rt.gw end)
  132. local function compare(a,b)
  133. if a.proto == b.proto then
  134. return a.linkCost < b.linkCost
  135. else
  136. return a.proto < b.proto
  137. end
  138. end
  139. for _, dev in ipairs(devices) do
  140. for _, net in ipairs(dev:get_wifinets()) do
  141. assoclist[#assoclist+1] = {}
  142. assoclist[#assoclist]['ifname'] = net.iwdata.ifname
  143. assoclist[#assoclist]['network'] = net.iwdata.network
  144. assoclist[#assoclist]['device'] = net.iwdata.device
  145. assoclist[#assoclist]['list'] = net.iwinfo.assoclist
  146. end
  147. end
  148. for k, v in ipairs(data) do
  149. local snr = 0
  150. local signal = 0
  151. local noise = 0
  152. local mac = ""
  153. local ip
  154. local neihgt = {}
  155. if resolve == "1" then
  156. hostname = nixio.getnameinfo(v.remoteIP, nil, 100)
  157. if hostname then
  158. v.hostname = hostname
  159. end
  160. end
  161. local interface = ntm:get_status_by_address(v.localIP)
  162. local lmac = local_mac_lookup(v.localIP)
  163. local rmac = remote_mac_lookup(v.remoteIP)
  164. for _, val in ipairs(assoclist) do
  165. if val.network == interface and val.list then
  166. for assocmac, assot in pairs(val.list) do
  167. assocmac = string.lower(assocmac or "")
  168. if rmac == assocmac then
  169. signal = tonumber(assot.signal)
  170. noise = tonumber(assot.noise)
  171. snr = (noise*-1) - (signal*-1)
  172. end
  173. end
  174. end
  175. end
  176. if interface then
  177. v.interface = interface
  178. end
  179. v.snr = snr
  180. v.signal = signal
  181. v.noise = noise
  182. if rmac then
  183. v.remoteMAC = rmac
  184. end
  185. if lmac then
  186. v.localMAC = lmac
  187. end
  188. if defaultgw == v.remoteIP then
  189. v.defaultgw = 1
  190. end
  191. end
  192. table.sort(data, compare)
  193. luci.template.render("status-olsr/neighbors", {links=data, has_v4=has_v4, has_v6=has_v6})
  194. end
  195. function action_routes()
  196. local data, has_v4, has_v6, error = fetch_jsoninfo('routes')
  197. if error then
  198. return
  199. end
  200. local uci = require "luci.model.uci".cursor_state()
  201. local resolve = uci:get("luci_olsr", "general", "resolve")
  202. for k, v in ipairs(data) do
  203. if resolve == "1" then
  204. local hostname = nixio.getnameinfo(v.gateway, nil, 100)
  205. if hostname then
  206. v.hostname = hostname
  207. end
  208. end
  209. end
  210. local function compare(a,b)
  211. if a.proto == b.proto then
  212. return a.rtpMetricCost < b.rtpMetricCost
  213. else
  214. return a.proto < b.proto
  215. end
  216. end
  217. table.sort(data, compare)
  218. luci.template.render("status-olsr/routes", {routes=data, has_v4=has_v4, has_v6=has_v6})
  219. end
  220. function action_topology()
  221. local data, has_v4, has_v6, error = fetch_jsoninfo('topology')
  222. if error then
  223. return
  224. end
  225. local function compare(a,b)
  226. if a.proto == b.proto then
  227. return a.tcEdgeCost < b.tcEdgeCost
  228. else
  229. return a.proto < b.proto
  230. end
  231. end
  232. table.sort(data, compare)
  233. luci.template.render("status-olsr/topology", {routes=data, has_v4=has_v4, has_v6=has_v6})
  234. end
  235. function action_hna()
  236. local data, has_v4, has_v6, error = fetch_jsoninfo('hna')
  237. if error then
  238. return
  239. end
  240. local uci = require "luci.model.uci".cursor_state()
  241. local resolve = uci:get("luci_olsr", "general", "resolve")
  242. local function compare(a,b)
  243. if a.proto == b.proto then
  244. return a.genmask < b.genmask
  245. else
  246. return a.proto < b.proto
  247. end
  248. end
  249. for k, v in ipairs(data) do
  250. if resolve == "1" then
  251. hostname = nixio.getnameinfo(v.gateway, nil, 100)
  252. if hostname then
  253. v.hostname = hostname
  254. end
  255. end
  256. if v.validityTime then
  257. v.validityTime = tonumber(string.format("%.0f", v.validityTime / 1000))
  258. end
  259. end
  260. table.sort(data, compare)
  261. luci.template.render("status-olsr/hna", {hna=data, has_v4=has_v4, has_v6=has_v6})
  262. end
  263. function action_mid()
  264. local data, has_v4, has_v6, error = fetch_jsoninfo('mid')
  265. if error then
  266. return
  267. end
  268. local function compare(a,b)
  269. if a.proto == b.proto then
  270. return a.ipAddress < b.ipAddress
  271. else
  272. return a.proto < b.proto
  273. end
  274. end
  275. table.sort(data, compare)
  276. luci.template.render("status-olsr/mid", {mids=data, has_v4=has_v4, has_v6=has_v6})
  277. end
  278. function action_smartgw()
  279. local data, has_v4, has_v6, error = fetch_jsoninfo('gateways')
  280. if error then
  281. return
  282. end
  283. local function compare(a,b)
  284. if a.proto == b.proto then
  285. return a.tcPathCost < b.tcPathCost
  286. else
  287. return a.proto < b.proto
  288. end
  289. end
  290. table.sort(data, compare)
  291. luci.template.render("status-olsr/smartgw", {gws=data, has_v4=has_v4, has_v6=has_v6})
  292. end
  293. function action_interfaces()
  294. local data, has_v4, has_v6, error = fetch_jsoninfo('interfaces')
  295. if error then
  296. return
  297. end
  298. local function compare(a,b)
  299. return a.proto < b.proto
  300. end
  301. table.sort(data, compare)
  302. luci.template.render("status-olsr/interfaces", {iface=data, has_v4=has_v4, has_v6=has_v6})
  303. end
  304. -- Internal
  305. function fetch_jsoninfo(otable)
  306. local uci = require "luci.model.uci".cursor_state()
  307. local utl = require "luci.util"
  308. local json = require "luci.json"
  309. local IpVersion = uci:get_first("olsrd", "olsrd","IpVersion")
  310. local jsonreq4 = ""
  311. local jsonreq6 = ""
  312. local v4_port = uci:get("olsrd", "olsrd_jsoninfo", "port") or 9090
  313. local v6_port = uci:get("olsrd6", "olsrd_jsoninfo", "port") or 9090
  314. jsonreq4 = utl.exec("(echo /" .. otable .. " | nc 127.0.0.1 " .. v4_port .. ") 2>/dev/null")
  315. jsonreq6 = utl.exec("(echo /" .. otable .. " | nc ::1 " .. v6_port .. ") 2>/dev/null")
  316. local jsondata4 = {}
  317. local jsondata6 = {}
  318. local data4 = {}
  319. local data6 = {}
  320. local has_v4 = False
  321. local has_v6 = False
  322. if jsonreq4 == '' and jsonreq6 == '' then
  323. luci.template.render("status-olsr/error_olsr")
  324. return nil, 0, 0, true
  325. end
  326. if jsonreq4 ~= "" then
  327. has_v4 = 1
  328. jsondata4 = json.decode(jsonreq4)
  329. if otable == 'status' then
  330. data4 = jsondata4 or {}
  331. else
  332. data4 = jsondata4[otable] or {}
  333. end
  334. for k, v in ipairs(data4) do
  335. data4[k]['proto'] = '4'
  336. end
  337. end
  338. if jsonreq6 ~= "" then
  339. has_v6 = 1
  340. jsondata6 = json.decode(jsonreq6)
  341. if otable == 'status' then
  342. data6 = jsondata6 or {}
  343. else
  344. data6 = jsondata6[otable] or {}
  345. end
  346. for k, v in ipairs(data6) do
  347. data6[k]['proto'] = '6'
  348. end
  349. end
  350. for k, v in ipairs(data6) do
  351. table.insert(data4, v)
  352. end
  353. return data4, has_v4, has_v6, false
  354. end