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