Merge pull request #2164 from Ansuel/ddns_fix
[oweals/luci.git] / modules / luci-mod-network / luasrc / model / cbi / admin_network / wifi_overview.lua
1 -- Copyright 2018 Jo-Philipp Wich <jo@mein.io>
2 -- Licensed to the public under the Apache License 2.0.
3
4 local fs = require "nixio.fs"
5 local utl = require "luci.util"
6 local tpl = require "luci.template"
7 local ntm = require "luci.model.network"
8
9 local has_iwinfo = pcall(require, "iwinfo")
10
11 function guess_wifi_hw(dev)
12         local bands = ""
13         local ifname = dev:name()
14         local name, idx = ifname:match("^([a-z]+)(%d+)")
15         idx = tonumber(idx)
16
17         if has_iwinfo then
18                 local bl = dev.iwinfo.hwmodelist
19                 if bl and next(bl) then
20                         if bl.a then bands = bands .. "a" end
21                         if bl.b then bands = bands .. "b" end
22                         if bl.g then bands = bands .. "g" end
23                         if bl.n then bands = bands .. "n" end
24                         if bl.ac then bands = bands .. "ac" end
25                 end
26
27                 local hw = dev.iwinfo.hardware_name
28                 if hw then
29                         return "%s 802.11%s" %{ hw, bands }
30                 end
31         end
32
33         -- wl.o
34         if name == "wl" then
35                 local name = translatef("Broadcom 802.11%s Wireless Controller", bands)
36                 local nm   = 0
37
38                 local fd = nixio.open("/proc/bus/pci/devices", "r")
39                 if fd then
40                         local ln
41                         for ln in fd:linesource() do
42                                 if ln:match("wl$") then
43                                         if nm == idx then
44                                                 local version = ln:match("^%S+%s+%S%S%S%S([0-9a-f]+)")
45                                                 name = translatef(
46                                                         "Broadcom BCM%04x 802.11 Wireless Controller",
47                                                         tonumber(version, 16)
48                                                 )
49
50                                                 break
51                                         else
52                                                 nm = nm + 1
53                                         end
54                                 end
55                         end
56                         fd:close()
57                 end
58
59                 return name
60
61         -- dunno yet
62         else
63                 return translatef("Generic 802.11%s Wireless Controller", bands)
64         end
65 end
66
67 local tpl_radio = tpl.Template(nil, [[
68         <div class="cbi-section-node">
69                 <div class="table">
70                         <!-- physical device -->
71                         <div class="tr cbi-rowstyle-2">
72                                 <div class="td col-2 center middle">
73                                         <span class="ifacebadge"><img src="<%=resource%>/icons/wifi_disabled.png" id="<%=dev:name()%>-iw-upstate" /> <%=dev:name()%></span>
74                                 </div>
75                                 <div class="td col-7 left middle">
76                                         <big><strong><%=hw%></strong></big><br />
77                                         <span id="<%=dev:name()%>-iw-devinfo"></span>
78                                 </div>
79                                 <div class="td middle cbi-section-actions">
80                                         <div>
81                                                 <input type="button" class="cbi-button cbi-button-neutral" title="<%:Restart radio interface%>" value="<%:Restart%>" data-radio="<%=dev:name()%>" onclick="wifi_restart(event)" />
82                                                 <input type="button" class="cbi-button cbi-button-action important" title="<%:Find and join network%>" value="<%:Scan%>" onclick="cbi_submit(this, 'device', '<%=dev:name()%>', '<%=url('admin/network/wireless_join')%>')" />
83                                                 <input type="button" class="cbi-button cbi-button-add" title="<%:Provide new network%>" value="<%:Add%>" onclick="cbi_submit(this, 'device', '<%=dev:name()%>', '<%=url('admin/network/wireless_add')%>')" />
84                                         </div>
85                                 </div>
86                         </div>
87                         <!-- /physical device -->
88
89                         <!-- network list -->
90                         <% if #wnets > 0 then %>
91                                 <% for i, net in ipairs(wnets) do local disabled = (dev:get("disabled") == "1" or net:get("disabled") == "1") %>
92                                 <div class="tr cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
93                                         <div class="td col-2 center middle" id="<%=net:id()%>-iw-signal">
94                                                 <span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-<%= disabled and "none" or "0" %>.png" /> 0%</span>
95                                         </div>
96                                         <div class="td col-7 left middle" id="<%=net:id()%>-iw-status" data-network="<%=net:id()%>" data-disabled="<%= disabled and "true" or "false" %>">
97                                                 <em><%= disabled and translate("Wireless is disabled") or translate("Collecting data...") %></em>
98                                         </div>
99                                         <div class="td middle cbi-section-actions">
100                                                 <div>
101                                                         <% if disabled then %>
102                                                                 <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="1" />
103                                                                 <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Enable this network%>" value="<%:Enable%>" onclick="this.previousElementSibling.value='0'" />
104                                                         <% else %>
105                                                                 <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="0" />
106                                                                 <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Disable this network%>" value="<%:Disable%>" onclick="this.previousElementSibling.value='1'" />
107                                                         <% end %>
108
109                                                         <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
110
111                                                         <input name="cbid.wireless.<%=net:name()%>.__delete__" type="hidden" value="" />
112                                                         <input name="cbi.apply" type="submit" class="cbi-button cbi-button-negative" title="<%:Delete this network%>" value="<%:Remove%>" onclick="wifi_delete(event)" />
113                                                 </div>
114                                         </div>
115                                 </div>
116                                 <% end %>
117                         <% else %>
118                                 <div class="tr placeholder">
119                                         <div class="td">
120                                                 <em><%:No network configured on this device%></em>
121                                         </div>
122                                 </div>
123                         <% end %>
124                         <!-- /network list -->
125                 </div>
126         </div>
127 ]])
128
129
130 m = Map("wireless", translate("Wireless Overview"))
131 m:chain("network")
132 m.pageaction = false
133
134 if not has_iwinfo then
135         s = m:section(NamedSection, "__warning__")
136
137         function s.render(self)
138                 tpl.render_string([[
139                         <div class="alert-message warning">
140                                 <h4><%:Package libiwinfo required!%></h4>
141                                 <p><%_The <em>libiwinfo-lua</em> package is not installed. You must install this component for working wireless configuration!%></p>
142                         </div>
143                 ]])
144         end
145 end
146
147 local _, dev, net
148 for _, dev in ipairs(ntm:get_wifidevs()) do
149         s = m:section(TypedSection)
150         s.wnets = dev:get_wifinets()
151
152         function s.render(self, sid)
153                 tpl_radio:render({
154                         hw = guess_wifi_hw(dev),
155                         dev = dev,
156                         wnets = self.wnets
157                 })
158         end
159
160         function s.cfgsections(self)
161                 local _, net, sl = nil, nil, { }
162                 for _, net in ipairs(self.wnets) do
163                         sl[#sl+1] = net:name()
164                         self.wnets[net:name()] = net
165                 end
166                 return sl
167         end
168
169         o = s:option(Value, "__disable__")
170
171         function o.cfgvalue(self, sid)
172                 local wnet = self.section.wnets[sid]
173                 local wdev = wnet:get_device()
174
175                 return ((wnet and wnet:get("disabled") == "1") or
176                             (wdev and wdev:get("disabled") == "1")) and "1" or "0"
177         end
178
179         function o.write(self, sid, value)
180                 local wnet = self.section.wnets[sid]
181                 local wdev = wnet:get_device()
182
183                 if value ~= "1" then
184                         wnet:set("disabled", nil)
185                         wdev:set("disabled", nil)
186                 else
187                         wnet:set("disabled", "1")
188                 end
189         end
190
191         o.remove = o.write
192
193
194         o = s:option(Value, "__delete__")
195
196         function o.write(self, sid, value)
197                 local wnet = self.section.wnets[sid]
198                 local nets = wnet:get_networks()
199
200                 ntm:del_wifinet(wnet:id())
201
202                 local _, net
203                 for _, net in ipairs(nets) do
204                         if net:is_empty() then
205                                 ntm:del_network(net:name())
206                         end
207                 end
208         end
209 end
210
211 s = m:section(NamedSection, "__script__")
212 s.template = "admin_network/wifi_overview_status"
213
214 s = m:section(NamedSection, "__assoclist__")
215
216 function s.render(self, sid)
217         tpl.render_string([[
218                 <h2><%:Associated Stations%></h2>
219                 <%+wifi_assoclist%>
220         ]])
221 end
222
223 return m