modules/admin-full: add realtime iface status to config page
[project/luci.git] / modules / admin-full / luasrc / controller / admin / network.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13 ]]--
14 module("luci.controller.admin.network", package.seeall)
15
16 function index()
17         require("luci.i18n")
18         local uci = require("luci.model.uci").cursor()
19         local i18n = luci.i18n.translate
20         local has_wifi = nixio.fs.stat("/etc/config/wireless")
21         local has_switch = false
22
23         uci:foreach("network", "switch",
24                 function(s)
25                         has_switch = true
26                         return false
27                 end
28         )
29
30         local page
31
32         page = node("admin", "network")
33         page.target = alias("admin", "network", "network")
34         page.title  = i18n("Network")
35         page.order  = 50
36         page.index  = true
37
38         if has_switch then
39                 page  = node("admin", "network", "vlan")
40                 page.target = cbi("admin_network/vlan")
41                 page.title  = i18n("Switch")
42                 page.order  = 20
43         end
44
45         if has_wifi and has_wifi.size > 0 then
46                 page = entry({"admin", "network", "wireless"}, arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), i18n("Wifi"), 15)
47                 page.leaf = true
48                 page.subindex = true
49
50                 page = entry({"admin", "network", "wireless_join"}, call("wifi_join"), nil, 16)
51                 page.leaf = true
52
53                 page = entry({"admin", "network", "wireless_add"}, call("wifi_add"), nil, 16)
54                 page.leaf = true
55
56                 page = entry({"admin", "network", "wireless_delete"}, call("wifi_delete"), nil, 16)
57                 page.leaf = true
58
59                 page = entry({"admin", "network", "wireless_status"}, call("wifi_status"), nil, 16)
60                 page.leaf = true
61         end
62
63         page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), i18n("Interfaces"), 10)
64         page.leaf   = true
65         page.subindex = true
66
67         page = entry({"admin", "network", "add"}, cbi("admin_network/iface_add"), nil)
68         page.leaf = true
69
70         page = entry({"admin", "network", "iface_status"}, call("iface_status"), nil)
71         page.leaf = true
72
73         uci:foreach("network", "interface",
74                 function (section)
75                         local ifc = section[".name"]
76                         if ifc ~= "loopback" then
77                                 entry({"admin", "network", "network", ifc},
78                                  true,
79                                  ifc:upper())
80                         end
81                 end
82         )
83
84         if nixio.fs.access("/etc/config/dhcp") then
85                 page  = node("admin", "network", "dhcpleases")
86                 page.target = cbi("admin_network/dhcpleases")
87                 page.title  = i18n("DHCP Leases")
88                 page.order  = 30
89         end
90
91         page  = node("admin", "network", "hosts")
92         page.target = cbi("admin_network/hosts")
93         page.title  = i18n("Hostnames")
94         page.order  = 40
95
96         page  = node("admin", "network", "routes")
97         page.target = cbi("admin_network/routes")
98         page.title  = i18n("Static Routes")
99         page.order  = 50
100
101 end
102
103 function wifi_join()
104         local function param(x)
105                 return luci.http.formvalue(x)
106         end
107
108         local function ptable(x)
109                 x = param(x)
110                 return x and (type(x) ~= "table" and { x } or x) or {}
111         end
112
113         local dev  = param("device")
114         local ssid = param("join")
115
116         if dev and ssid then
117                 local cancel  = (param("cancel") or param("cbi.cancel")) and true or false
118
119                 if cancel then
120                         luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless_join?device=" .. dev))
121                 else
122                         local cbi = require "luci.cbi"
123                         local tpl = require "luci.template"
124                         local map = luci.cbi.load("admin_network/wifi_add")[1]
125
126                         if map:parse() ~= cbi.FORM_DONE then
127                                 tpl.render("header")
128                                 map:render()
129                                 tpl.render("footer")
130                         end
131                 end
132         else
133                 luci.template.render("admin_network/wifi_join")
134         end
135 end
136
137 function wifi_add()
138         local dev = luci.http.formvalue("device")
139         local uci = require "luci.model.uci".cursor()
140         local wlm = require "luci.model.wireless"
141
142         if dev then
143                 wlm.init(uci)
144
145                 local net = wlm:add_network({
146                         device     = dev,
147                         mode       = "ap",
148                         ssid       = "OpenWrt",
149                         encryption = "none"
150                 })
151
152                 uci:save("wireless")
153                 luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", dev, net:name()))
154         end
155 end
156
157 function wifi_delete(network)
158         local uci = require "luci.model.uci".cursor()
159         local wlm = require "luci.model.wireless"
160
161         wlm.init(uci)
162         wlm:del_network(network)
163
164         uci:save("wireless")
165         luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
166 end
167
168 function jsondump(x)
169         if x == nil then
170                 luci.http.write("null")
171         elseif type(x) == "table" then
172                 local k, v
173                 if type(next(x)) == "number" then
174                         luci.http.write("[ ")
175                         for k, v in ipairs(x) do
176                                 jsondump(v)
177                                 if next(x, k) then
178                                         luci.http.write(", ")
179                                 end
180                         end
181                         luci.http.write(" ]")
182                 else
183                         luci.http.write("{ ")
184                         for k, v in pairs(x) do
185                         luci.http.write("%q: " % k)
186                                 jsondump(v)
187                                 if next(x, k) then
188                                         luci.http.write(", ")
189                                 end
190                         end
191                         luci.http.write(" }")
192                 end
193         elseif type(x) == "number" or type(x) == "boolean" then
194                 luci.http.write(tostring(x))
195         elseif type(x) == "string" then
196                 luci.http.write("%q" % tostring(x))
197         end
198 end
199
200
201 function iface_status()
202         local path  = luci.dispatcher.context.requestpath
203         local iface = path[#path]
204         local data  = { }
205         local info
206         local x = luci.model.uci.cursor_state()
207
208         local dev = x:get("network", iface, "device") or ""
209         if #dev == 0 or dev:match("^%d") or dev:match("%W") then
210                 dev = x:get("network", iface, "ifname") or ""
211                 dev = dev:match("%S+")
212         end
213
214         for _, info in ipairs(nixio.getifaddrs()) do
215                 local name = info.name:match("[^:]+")
216                 if name == dev then
217                         if info.family == "packet" then
218                                 data.flags   = info.flags
219                                 data.stats   = info.data
220                                 data.macaddr = info.addr
221                                 data.ifname  = name
222                         elseif info.family == "inet" then
223                                 data.ipaddrs = data.ipaddrs or { }
224                                 data.ipaddrs[#data.ipaddrs+1] = {
225                                         addr      = info.addr,
226                                         broadaddr = info.broadaddr,
227                                         dstaddr   = info.dstaddr,
228                                         netmask   = info.netmask,
229                                         prefix    = info.prefix
230                                 }
231                         elseif info.family == "inet6" then
232                                 data.ip6addrs = data.ip6addrs or { }
233                                 data.ip6addrs[#data.ip6addrs+1] = {
234                                         addr    = info.addr,
235                                         netmask = info.netmask,
236                                         prefix  = info.prefix
237                                 }
238                         end
239                 end
240         end
241
242         if next(data) then
243                 luci.http.prepare_content("application/json")
244                 jsondump(data)
245                 return
246         end
247
248         luci.http.status(404, "No such device")
249 end
250
251 function wifi_status()
252         local path = luci.dispatcher.context.requestpath
253         local dev  = path[#path]
254         local iw   = luci.sys.wifi.getiwinfo(dev)
255
256         if iw then
257                 local f
258                 local j = { }
259                 for _, f in ipairs({
260                         "channel", "frequency", "txpower", "bitrate", "signal", "noise",
261                         "quality", "quality_max", "mode", "ssid", "bssid", "country",
262                         "encryption", "ifname"
263                 }) do
264                         j[f] = iw[f]
265                 end
266
267                 luci.http.prepare_content("application/json")
268                 jsondump(j)
269                 return
270         end
271
272         luci.http.status(404, "No such device")
273 end