0342bde49b0479a2aaf9c82227cf8374293a2b5e
[project/luci.git] / applications / luci-olsr / luasrc / controller / olsr.lua
1 module("luci.controller.olsr", package.seeall)
2
3 function index()
4 if not nixio.fs.access("/etc/config/olsrd") then
5 return
6 end
7
8 local page = node("admin", "status", "olsr")
9 page.target = template("status-olsr/overview")
10 page.title = _("OLSR")
11 page.subindex = true
12
13 local page = node("admin", "status", "olsr", "neighbors")
14 page.target = call("action_neigh")
15 page.title = _("Neighbours")
16 page.subindex = true
17 page.order = 5
18
19 local page = node("admin", "status", "olsr", "routes")
20 page.target = call("action_routes")
21 page.title = _("Routes")
22 page.order = 10
23
24 local page = node("admin", "status", "olsr", "topology")
25 page.target = call("action_topology")
26 page.title = _("Topology")
27 page.order = 20
28
29 local page = node("admin", "status", "olsr", "hna")
30 page.target = call("action_hna")
31 page.title = _("HNA")
32 page.order = 30
33
34 local page = node("admin", "status", "olsr", "mid")
35 page.target = call("action_mid")
36 page.title = _("MID")
37 page.order = 50
38
39 local page = node("admin", "status", "olsr", "smartgw")
40 page.target = call("action_smartgw")
41 page.title = _("SmartGW")
42 page.order = 60
43
44 local page = node("admin", "status", "olsr", "interfaces")
45 page.target = call("action_interfaces")
46 page.title = _("Interfaces")
47 page.order = 70
48
49 local ol = entry(
50 {"admin", "services", "olsrd"},
51 cbi("olsr/olsrd"), "OLSR"
52 )
53 ol.subindex = true
54
55 entry(
56 {"admin", "services", "olsrd", "iface"},
57 cbi("olsr/olsrdiface")
58 ).leaf = true
59
60 entry(
61 {"admin", "services", "olsrd", "hna"},
62 cbi("olsr/olsrdhna"), _("HNA Announcements")
63 )
64
65 oplg = entry(
66 {"admin", "services", "olsrd", "plugins"},
67 cbi("olsr/olsrdplugins"), _("Plugins")
68 )
69
70 odsp = entry(
71 {"admin", "services", "olsrd", "display"},
72 cbi("olsr/olsrddisplay"), _("Display")
73 )
74
75 oplg.leaf = true
76 oplg.subindex = true
77
78 local uci = require("luci.model.uci").cursor()
79 uci:foreach("olsrd", "LoadPlugin",
80 function (section)
81 local lib = section.library
82 entry(
83 {"admin", "services", "olsrd", "plugins", lib },
84 cbi("olsr/olsrdplugins"),
85 nil --'Plugin "%s"' % lib:gsub("^olsrd_",""):gsub("%.so.+$","")
86 )
87 end
88 )
89 end
90
91 local function compare_links(a, b)
92 local c = tonumber(a.Cost)
93 local d = tonumber(b.Cost)
94
95 if not c or c == 0 then
96 return false
97 end
98
99 if not d or d == 0 then
100 return true
101 end
102 return c < d
103 end
104
105 function action_neigh(json)
106 local data = fetch_txtinfo("links")
107
108 if not data or not data.Links then
109 luci.template.render("status-olsr/error_olsr")
110 return nil
111 end
112
113 table.sort(data.Links, compare_links)
114
115 luci.template.render("status-olsr/neighbors", {links=data.Links})
116 end
117
118 function action_routes()
119 local data = fetch_txtinfo("routes")
120
121 if not data or not data.Routes then
122 luci.template.render("status-olsr/error_olsr")
123 return nil
124 end
125
126 local function compare(a, b)
127 local c = tonumber(a.ETX)
128 local d = tonumber(b.ETX)
129
130 if not c or c == 0 then
131 return false
132 end
133
134 if not d or d == 0 then
135 return true
136 end
137
138 return c < d
139 end
140
141 table.sort(data.Routes, compare)
142
143 luci.template.render("status-olsr/routes", {routes=data.Routes})
144 end
145
146 function action_topology()
147 local data = fetch_txtinfo("topology")
148
149 if not data or not data.Topology then
150 luci.template.render("status-olsr/error_olsr")
151 return nil
152 end
153
154 local function compare(a, b)
155 return a["Dest. IP"] < b["Dest. IP"]
156 end
157
158 table.sort(data.Topology, compare)
159
160 luci.template.render("status-olsr/topology", {routes=data.Topology})
161 end
162
163 function action_hna()
164 local data = fetch_txtinfo("hna")
165
166 if not data or not data.HNA then
167 luci.template.render("status-olsr/error_olsr")
168 return nil
169 end
170
171 local function compare(a, b)
172 return a.Destination < b.Destination
173 end
174
175 table.sort(data.HNA, compare)
176
177 luci.template.render("status-olsr/hna", {routes=data.HNA})
178 end
179
180 function action_mid()
181 local data = fetch_txtinfo("mid")
182
183 if not data or not data.MID then
184 luci.template.render("status-olsr/error_olsr")
185 return nil
186 end
187
188 local function compare(a, b)
189 return a["IP address"] < b["IP address"]
190 end
191
192 table.sort(data.MID, compare)
193
194 luci.template.render("status-olsr/mid", {mids=data.MID})
195 end
196
197 function action_smartgw()
198 local data = fetch_txtinfo("gateways")
199
200 if not data or not data.Gateways then
201 luci.template.render("status-olsr/error_olsr")
202 return nil
203 end
204
205 local function compare(a, b)
206 return a["ETX"] < b["ETX"]
207 end
208
209 table.sort(data.Gateways, compare)
210
211 luci.template.render("status-olsr/smartgw", {gws=data.Gateways})
212 end
213
214 function action_interfaces()
215 local data = fetch_txtinfo("interfaces")
216
217 if not data or not data.Interfaces then
218 luci.template.render("status-olsr/error_olsr")
219 return nil
220 end
221
222 luci.template.render("status-olsr/interfaces", {iface=data.Interfaces})
223 end
224
225 -- Internal
226 function fetch_txtinfo(otable)
227 require("luci.sys")
228 local uci = require "luci.model.uci".cursor_state()
229 local resolve = uci:get("luci_olsr", "general", "resolve")
230 otable = otable or ""
231 local rawdata = luci.sys.httpget("http://127.0.0.1:2006/"..otable)
232 local rawdatav6 = luci.sys.httpget("http://[::1]:2006/"..otable)
233 local data = {}
234 local dataindex = 0
235 local name = ""
236 local defaultgw
237
238 if #rawdata ~= 0 then
239 local tables = luci.util.split(luci.util.trim(rawdata), "\r?\n\r?\n", nil, true)
240
241 if otable == "links" then
242 local route = {}
243 luci.sys.net.routes(function(r) if r.dest:prefix() == 0 then defaultgw = r.gateway:string() end end)
244 end
245
246 for i, tbl in ipairs(tables) do
247 local lines = luci.util.split(tbl, "\r?\n", nil, true)
248 name = table.remove(lines, 1):sub(8)
249 local keys = luci.util.split(table.remove(lines, 1), "\t")
250 local split = #keys - 1
251 if not data[name] then
252 data[name] = {}
253 end
254
255 for j, line in ipairs(lines) do
256 dataindex = ( dataindex + 1 )
257 di = dataindex
258 local fields = luci.util.split(line, "\t", split)
259 data[name][di] = {}
260 for k, key in pairs(keys) do
261 if key == "Remote IP" or key == "Dest. IP" or key == "Gateway IP" or key == "Gateway" then
262 data[name][di][key] = fields[k]
263 if resolve == "1" then
264 hostname = nixio.getnameinfo(fields[k], "inet")
265 if hostname then
266 data[name][di]["Hostname"] = hostname
267 end
268 end
269 if key == "Remote IP" and defaultgw then
270 if defaultgw == fields[k] then
271 data[name][di]["defaultgw"] = 1
272 end
273 end
274 elseif key == "Local IP" then
275 data[name][di][key] = fields[k]
276 data[name][di]['Local Device'] = fields[k]
277 uci:foreach("network", "interface",
278 function(s)
279 localip = string.gsub(fields[k], ' ', '')
280 if s.ipaddr == localip then
281 data[name][di]['Local Device'] = s['.name'] or interface
282 end
283 end)
284 elseif key == "Interface" then
285 data[name][di][key] = fields[k]
286 uci:foreach("network", "interface",
287 function(s)
288 interface = string.gsub(fields[k], ' ', '')
289 if s.ifname == interface then
290 data[name][di][key] = s['.name'] or interface
291 end
292 end)
293 else
294 data[name][di][key] = fields[k]
295 end
296 end
297 if data[name][di].Linkcost then
298 data[name][di].LinkQuality,
299 data[name][di].NLQ,
300 data[name][di].ETX =
301 data[name][di].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)")
302 end
303 end
304 end
305 end
306
307 if #rawdatav6 ~= 0 then
308 local tables = luci.util.split(luci.util.trim(rawdatav6), "\r?\n\r?\n", nil, true)
309 for i, tbl in ipairs(tables) do
310 local lines = luci.util.split(tbl, "\r?\n", nil, true)
311 name = table.remove(lines, 1):sub(8)
312 local keys = luci.util.split(table.remove(lines, 1), "\t")
313 local split = #keys - 1
314 if not data[name] then
315 data[name] = {}
316 end
317 for j, line in ipairs(lines) do
318 dataindex = ( dataindex + 1 )
319 di = dataindex
320 local fields = luci.util.split(line, "\t", split)
321 data[name][di] = {}
322 for k, key in pairs(keys) do
323 if key == "Remote IP" then
324 data[name][di][key] = "[" .. fields[k] .. "]"
325 if resolve == "1" then
326 hostname = nixio.getnameinfo(fields[k], "inet6")
327 if hostname then
328 data[name][di]["Hostname"] = hostname
329 end
330 end
331 elseif key == "Local IP" then
332 data[name][di][key] = fields[k]
333 data[name][di]['Local Device'] = fields[k]
334 uci:foreach("network", "interface",
335 function(s)
336 local localip = string.gsub(fields[k], ' ', ''):upper()
337 if s.ip6addr then
338 s.ip6addr = luci.ip.IPv6(s.ip6addr):string()
339 local ip6addr = string.gsub(s.ip6addr, '\/.*', '')
340 if ip6addr == localip then
341 data[name][di]['Local Device'] = s['.name'] or s.interface
342 end
343 end
344 end)
345 elseif key == "Dest. IP" then
346 data[name][di][key] = "[" .. fields[k] .. "]"
347 elseif key == "Last hop IP" then
348 data[name][di][key] = "[" .. fields[k] .. "]"
349 elseif key == "IP address" then
350 data[name][di][key] = "[" .. fields[k] .. "]"
351 elseif key == "Gateway" then
352 data[name][di][key] = "[" .. fields[k] .. "]"
353 else
354 data[name][di][key] = fields[k]
355 end
356 end
357
358 if data[name][di].Linkcost then
359 data[name][di].LinkQuality,
360 data[name][di].NLQ,
361 data[name][di].ETX =
362 data[name][di].Linkcost:match("([%w.]+)/([%w.]+)[%s]+([%w.]+)")
363 end
364 end
365 end
366 end
367
368
369 if data then
370 return data
371 end
372 end