58f3fd874f903cf149584989c3710b4b98c5f54c
[oweals/luci.git] / docs / jsapi / network.js.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4     <meta charset="utf-8">
5     <title>Source: network.js</title>
6     
7     
8     <script src="scripts/prettify/prettify.js"></script>
9     <script src="scripts/prettify/lang-css.js"></script>
10     <script src="scripts/jquery.min.js"></script>
11     <!--[if lt IE 9]>
12       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13     <![endif]-->
14     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
15     <link type="text/css" rel="stylesheet" href="styles/bootstrap.min.css">
16     <link type="text/css" rel="stylesheet" href="styles/jaguar.css">
17     
18     
19     <script>
20     var config = {"monospaceLinks":true,"cleverLinks":true,"default":{"outputSourceFiles":true}};
21     </script>
22     
23
24     
25 </head>
26 <body>
27 <div id="wrap" class="clearfix">
28     
29 <div class="navigation">
30     <h3 class="applicationName"><a href="index.html"></a></h3>
31
32     <div class="search">
33         <input id="search" type="text" class="form-control input-sm" placeholder="Search Documentations">
34     </div>
35     <ul class="list">
36     
37         <li class="item" data-name="LuCI">
38             <span class="title">
39                 <a href="LuCI.html">LuCI</a>
40                 
41             </span>
42             <ul class="members itemMembers">
43             
44             <span class="subtitle">Members</span>
45             
46                 <li data-name="LuCI#Class"><a href="LuCI.html#Class">Class</a></li>
47             
48                 <li data-name="LuCI#dom"><a href="LuCI.html#dom">dom</a></li>
49             
50                 <li data-name="LuCI#env"><a href="LuCI.html#env">env</a></li>
51             
52                 <li data-name="LuCI#Poll"><a href="LuCI.html#Poll">Poll</a></li>
53             
54                 <li data-name="LuCI#Request"><a href="LuCI.html#Request">Request</a></li>
55             
56                 <li data-name="LuCI#view"><a href="LuCI.html#view">view</a></li>
57             
58             </ul>
59             <ul class="typedefs itemMembers">
60             
61             <span class="subtitle">Typedefs</span>
62             
63                 <li data-name="LuCI.requestCallbackFn"><a href="LuCI.html#.requestCallbackFn">requestCallbackFn</a></li>
64             
65             </ul>
66             <ul class="typedefs itemMembers">
67             
68             </ul>
69             <ul class="methods itemMembers">
70             
71             <span class="subtitle">Methods</span>
72             
73                 <li data-name="LuCI#bind"><a href="LuCI.html#bind">bind</a></li>
74             
75                 <li data-name="LuCI#error"><a href="LuCI.html#error">error</a></li>
76             
77                 <li data-name="LuCI#get"><a href="LuCI.html#get">get</a></li>
78             
79                 <li data-name="LuCI#halt"><a href="LuCI.html#halt">halt</a></li>
80             
81                 <li data-name="LuCI#hasSystemFeature"><a href="LuCI.html#hasSystemFeature">hasSystemFeature</a></li>
82             
83                 <li data-name="LuCI#isObject"><a href="LuCI.html#isObject">isObject</a></li>
84             
85                 <li data-name="LuCI#location"><a href="LuCI.html#location">location</a></li>
86             
87                 <li data-name="LuCI#media"><a href="LuCI.html#media">media</a></li>
88             
89                 <li data-name="LuCI#path"><a href="LuCI.html#path">path</a></li>
90             
91                 <li data-name="LuCI#poll"><a href="LuCI.html#poll">poll</a></li>
92             
93                 <li data-name="LuCI#post"><a href="LuCI.html#post">post</a></li>
94             
95                 <li data-name="LuCI#raise"><a href="LuCI.html#raise">raise</a></li>
96             
97                 <li data-name="LuCI#require"><a href="LuCI.html#require">require</a></li>
98             
99                 <li data-name="LuCI#resolveDefault"><a href="LuCI.html#resolveDefault">resolveDefault</a></li>
100             
101                 <li data-name="LuCI#resource"><a href="LuCI.html#resource">resource</a></li>
102             
103                 <li data-name="LuCI#run"><a href="LuCI.html#run">run</a></li>
104             
105                 <li data-name="LuCI#sortedKeys"><a href="LuCI.html#sortedKeys">sortedKeys</a></li>
106             
107                 <li data-name="LuCI#stop"><a href="LuCI.html#stop">stop</a></li>
108             
109                 <li data-name="LuCI#toArray"><a href="LuCI.html#toArray">toArray</a></li>
110             
111                 <li data-name="LuCI#url"><a href="LuCI.html#url">url</a></li>
112             
113             </ul>
114             <ul class="events itemMembers">
115             
116             </ul>
117         </li>
118     
119         <li class="item" data-name="LuCI.baseclass">
120             <span class="title">
121                 <a href="LuCI.baseclass.html">LuCI.baseclass</a>
122                 
123             </span>
124             <ul class="members itemMembers">
125             
126             </ul>
127             <ul class="typedefs itemMembers">
128             
129             </ul>
130             <ul class="typedefs itemMembers">
131             
132             </ul>
133             <ul class="methods itemMembers">
134             
135             <span class="subtitle">Methods</span>
136             
137                 <li data-name="LuCI.baseclass.extend"><a href="LuCI.baseclass.html#.extend">extend</a></li>
138             
139                 <li data-name="LuCI.baseclass.instantiate"><a href="LuCI.baseclass.html#.instantiate">instantiate</a></li>
140             
141                 <li data-name="LuCI.baseclass.isSubclass"><a href="LuCI.baseclass.html#.isSubclass">isSubclass</a></li>
142             
143                 <li data-name="LuCI.baseclass.singleton"><a href="LuCI.baseclass.html#.singleton">singleton</a></li>
144             
145                 <li data-name="LuCI.baseclass#super"><a href="LuCI.baseclass.html#super">super</a></li>
146             
147                 <li data-name="LuCI.baseclass#varargs"><a href="LuCI.baseclass.html#varargs">varargs</a></li>
148             
149             </ul>
150             <ul class="events itemMembers">
151             
152             </ul>
153         </li>
154     
155         <li class="item" data-name="LuCI.dom">
156             <span class="title">
157                 <a href="LuCI.dom.html">LuCI.dom</a>
158                 
159             </span>
160             <ul class="members itemMembers">
161             
162             </ul>
163             <ul class="typedefs itemMembers">
164             
165             <span class="subtitle">Typedefs</span>
166             
167                 <li data-name="LuCI.dom~ignoreCallbackFn"><a href="LuCI.dom.html#~ignoreCallbackFn">ignoreCallbackFn</a></li>
168             
169             </ul>
170             <ul class="typedefs itemMembers">
171             
172             </ul>
173             <ul class="methods itemMembers">
174             
175             <span class="subtitle">Methods</span>
176             
177                 <li data-name="LuCI.dom#append"><a href="LuCI.dom.html#append">append</a></li>
178             
179                 <li data-name="LuCI.dom#attr"><a href="LuCI.dom.html#attr">attr</a></li>
180             
181                 <li data-name="LuCI.dom#bindClassInstance"><a href="LuCI.dom.html#bindClassInstance">bindClassInstance</a></li>
182             
183                 <li data-name="LuCI.dom#callClassMethod"><a href="LuCI.dom.html#callClassMethod">callClassMethod</a></li>
184             
185                 <li data-name="LuCI.dom#content"><a href="LuCI.dom.html#content">content</a></li>
186             
187                 <li data-name="LuCI.dom#create"><a href="LuCI.dom.html#create">create</a></li>
188             
189                 <li data-name="LuCI.dom#data"><a href="LuCI.dom.html#data">data</a></li>
190             
191                 <li data-name="LuCI.dom#elem"><a href="LuCI.dom.html#elem">elem</a></li>
192             
193                 <li data-name="LuCI.dom#findClassInstance"><a href="LuCI.dom.html#findClassInstance">findClassInstance</a></li>
194             
195                 <li data-name="LuCI.dom#isEmpty"><a href="LuCI.dom.html#isEmpty">isEmpty</a></li>
196             
197                 <li data-name="LuCI.dom#matches"><a href="LuCI.dom.html#matches">matches</a></li>
198             
199                 <li data-name="LuCI.dom#parent"><a href="LuCI.dom.html#parent">parent</a></li>
200             
201                 <li data-name="LuCI.dom#parse"><a href="LuCI.dom.html#parse">parse</a></li>
202             
203             </ul>
204             <ul class="events itemMembers">
205             
206             </ul>
207         </li>
208     
209         <li class="item" data-name="LuCI.fs">
210             <span class="title">
211                 <a href="LuCI.fs.html">LuCI.fs</a>
212                 
213             </span>
214             <ul class="members itemMembers">
215             
216             </ul>
217             <ul class="typedefs itemMembers">
218             
219             <span class="subtitle">Typedefs</span>
220             
221                 <li data-name="LuCI.fs.FileExecResult"><a href="LuCI.fs.html#.FileExecResult">FileExecResult</a></li>
222             
223                 <li data-name="LuCI.fs.FileStatEntry"><a href="LuCI.fs.html#.FileStatEntry">FileStatEntry</a></li>
224             
225             </ul>
226             <ul class="typedefs itemMembers">
227             
228             </ul>
229             <ul class="methods itemMembers">
230             
231             <span class="subtitle">Methods</span>
232             
233                 <li data-name="LuCI.fs#exec"><a href="LuCI.fs.html#exec">exec</a></li>
234             
235                 <li data-name="LuCI.fs#exec_direct"><a href="LuCI.fs.html#exec_direct">exec_direct</a></li>
236             
237                 <li data-name="LuCI.fs#lines"><a href="LuCI.fs.html#lines">lines</a></li>
238             
239                 <li data-name="LuCI.fs#list"><a href="LuCI.fs.html#list">list</a></li>
240             
241                 <li data-name="LuCI.fs#read"><a href="LuCI.fs.html#read">read</a></li>
242             
243                 <li data-name="LuCI.fs#read_direct"><a href="LuCI.fs.html#read_direct">read_direct</a></li>
244             
245                 <li data-name="LuCI.fs#remove"><a href="LuCI.fs.html#remove">remove</a></li>
246             
247                 <li data-name="LuCI.fs#stat"><a href="LuCI.fs.html#stat">stat</a></li>
248             
249                 <li data-name="LuCI.fs#trimmed"><a href="LuCI.fs.html#trimmed">trimmed</a></li>
250             
251                 <li data-name="LuCI.fs#write"><a href="LuCI.fs.html#write">write</a></li>
252             
253             </ul>
254             <ul class="events itemMembers">
255             
256             </ul>
257         </li>
258     
259         <li class="item" data-name="LuCI.headers">
260             <span class="title">
261                 <a href="LuCI.headers.html">LuCI.headers</a>
262                 
263             </span>
264             <ul class="members itemMembers">
265             
266             </ul>
267             <ul class="typedefs itemMembers">
268             
269             </ul>
270             <ul class="typedefs itemMembers">
271             
272             </ul>
273             <ul class="methods itemMembers">
274             
275             <span class="subtitle">Methods</span>
276             
277                 <li data-name="LuCI.headers#get"><a href="LuCI.headers.html#get">get</a></li>
278             
279                 <li data-name="LuCI.headers#has"><a href="LuCI.headers.html#has">has</a></li>
280             
281             </ul>
282             <ul class="events itemMembers">
283             
284             </ul>
285         </li>
286     
287         <li class="item" data-name="LuCI.network">
288             <span class="title">
289                 <a href="LuCI.network.html">LuCI.network</a>
290                 
291             </span>
292             <ul class="members itemMembers">
293             
294             </ul>
295             <ul class="typedefs itemMembers">
296             
297             <span class="subtitle">Typedefs</span>
298             
299                 <li data-name="LuCI.network.SwitchTopology"><a href="LuCI.network.html#.SwitchTopology">SwitchTopology</a></li>
300             
301                 <li data-name="LuCI.network.WifiEncryption"><a href="LuCI.network.html#.WifiEncryption">WifiEncryption</a></li>
302             
303                 <li data-name="LuCI.network.WifiPeerEntry"><a href="LuCI.network.html#.WifiPeerEntry">WifiPeerEntry</a></li>
304             
305                 <li data-name="LuCI.network.WifiRateEntry"><a href="LuCI.network.html#.WifiRateEntry">WifiRateEntry</a></li>
306             
307                 <li data-name="LuCI.network.WifiScanResult"><a href="LuCI.network.html#.WifiScanResult">WifiScanResult</a></li>
308             
309             </ul>
310             <ul class="typedefs itemMembers">
311             
312             </ul>
313             <ul class="methods itemMembers">
314             
315             <span class="subtitle">Methods</span>
316             
317                 <li data-name="LuCI.network#addNetwork"><a href="LuCI.network.html#addNetwork">addNetwork</a></li>
318             
319                 <li data-name="LuCI.network#addWifiNetwork"><a href="LuCI.network.html#addWifiNetwork">addWifiNetwork</a></li>
320             
321                 <li data-name="LuCI.network#deleteNetwork"><a href="LuCI.network.html#deleteNetwork">deleteNetwork</a></li>
322             
323                 <li data-name="LuCI.network#deleteWifiNetwork"><a href="LuCI.network.html#deleteWifiNetwork">deleteWifiNetwork</a></li>
324             
325                 <li data-name="LuCI.network#flushCache"><a href="LuCI.network.html#flushCache">flushCache</a></li>
326             
327                 <li data-name="LuCI.network#formatWifiEncryption"><a href="LuCI.network.html#formatWifiEncryption">formatWifiEncryption</a></li>
328             
329                 <li data-name="LuCI.network#getDevice"><a href="LuCI.network.html#getDevice">getDevice</a></li>
330             
331                 <li data-name="LuCI.network#getDevices"><a href="LuCI.network.html#getDevices">getDevices</a></li>
332             
333                 <li data-name="LuCI.network#getDSLModemType"><a href="LuCI.network.html#getDSLModemType">getDSLModemType</a></li>
334             
335                 <li data-name="LuCI.network#getHostHints"><a href="LuCI.network.html#getHostHints">getHostHints</a></li>
336             
337                 <li data-name="LuCI.network#getIfnameOf"><a href="LuCI.network.html#getIfnameOf">getIfnameOf</a></li>
338             
339                 <li data-name="LuCI.network#getNetwork"><a href="LuCI.network.html#getNetwork">getNetwork</a></li>
340             
341                 <li data-name="LuCI.network#getNetworks"><a href="LuCI.network.html#getNetworks">getNetworks</a></li>
342             
343                 <li data-name="LuCI.network#getProtocol"><a href="LuCI.network.html#getProtocol">getProtocol</a></li>
344             
345                 <li data-name="LuCI.network#getProtocols"><a href="LuCI.network.html#getProtocols">getProtocols</a></li>
346             
347                 <li data-name="LuCI.network#getSwitchTopologies"><a href="LuCI.network.html#getSwitchTopologies">getSwitchTopologies</a></li>
348             
349                 <li data-name="LuCI.network#getWAN6Networks"><a href="LuCI.network.html#getWAN6Networks">getWAN6Networks</a></li>
350             
351                 <li data-name="LuCI.network#getWANNetworks"><a href="LuCI.network.html#getWANNetworks">getWANNetworks</a></li>
352             
353                 <li data-name="LuCI.network#getWifiDevice"><a href="LuCI.network.html#getWifiDevice">getWifiDevice</a></li>
354             
355                 <li data-name="LuCI.network#getWifiDevices"><a href="LuCI.network.html#getWifiDevices">getWifiDevices</a></li>
356             
357                 <li data-name="LuCI.network#getWifiNetwork"><a href="LuCI.network.html#getWifiNetwork">getWifiNetwork</a></li>
358             
359                 <li data-name="LuCI.network#getWifiNetworks"><a href="LuCI.network.html#getWifiNetworks">getWifiNetworks</a></li>
360             
361                 <li data-name="LuCI.network#isIgnoredDevice"><a href="LuCI.network.html#isIgnoredDevice">isIgnoredDevice</a></li>
362             
363                 <li data-name="LuCI.network#maskToPrefix"><a href="LuCI.network.html#maskToPrefix">maskToPrefix</a></li>
364             
365                 <li data-name="LuCI.network#prefixToMask"><a href="LuCI.network.html#prefixToMask">prefixToMask</a></li>
366             
367                 <li data-name="LuCI.network#registerErrorCode"><a href="LuCI.network.html#registerErrorCode">registerErrorCode</a></li>
368             
369                 <li data-name="LuCI.network#registerPatternVirtual"><a href="LuCI.network.html#registerPatternVirtual">registerPatternVirtual</a></li>
370             
371                 <li data-name="LuCI.network#registerProtocol"><a href="LuCI.network.html#registerProtocol">registerProtocol</a></li>
372             
373                 <li data-name="LuCI.network#renameNetwork"><a href="LuCI.network.html#renameNetwork">renameNetwork</a></li>
374             
375             </ul>
376             <ul class="events itemMembers">
377             
378             </ul>
379         </li>
380     
381         <li class="item" data-name="LuCI.network.Device">
382             <span class="title">
383                 <a href="LuCI.network.Device.html">LuCI.network.Device</a>
384                 
385             </span>
386             <ul class="members itemMembers">
387             
388             </ul>
389             <ul class="typedefs itemMembers">
390             
391             </ul>
392             <ul class="typedefs itemMembers">
393             
394             </ul>
395             <ul class="methods itemMembers">
396             
397             <span class="subtitle">Methods</span>
398             
399                 <li data-name="LuCI.network.Device#getBridgeID"><a href="LuCI.network.Device.html#getBridgeID">getBridgeID</a></li>
400             
401                 <li data-name="LuCI.network.Device#getBridgeSTP"><a href="LuCI.network.Device.html#getBridgeSTP">getBridgeSTP</a></li>
402             
403                 <li data-name="LuCI.network.Device#getI18n"><a href="LuCI.network.Device.html#getI18n">getI18n</a></li>
404             
405                 <li data-name="LuCI.network.Device#getIP6Addrs"><a href="LuCI.network.Device.html#getIP6Addrs">getIP6Addrs</a></li>
406             
407                 <li data-name="LuCI.network.Device#getIPAddrs"><a href="LuCI.network.Device.html#getIPAddrs">getIPAddrs</a></li>
408             
409                 <li data-name="LuCI.network.Device#getMAC"><a href="LuCI.network.Device.html#getMAC">getMAC</a></li>
410             
411                 <li data-name="LuCI.network.Device#getMTU"><a href="LuCI.network.Device.html#getMTU">getMTU</a></li>
412             
413                 <li data-name="LuCI.network.Device#getName"><a href="LuCI.network.Device.html#getName">getName</a></li>
414             
415                 <li data-name="LuCI.network.Device#getNetwork"><a href="LuCI.network.Device.html#getNetwork">getNetwork</a></li>
416             
417                 <li data-name="LuCI.network.Device#getNetworks"><a href="LuCI.network.Device.html#getNetworks">getNetworks</a></li>
418             
419                 <li data-name="LuCI.network.Device#getPorts"><a href="LuCI.network.Device.html#getPorts">getPorts</a></li>
420             
421                 <li data-name="LuCI.network.Device#getRXBytes"><a href="LuCI.network.Device.html#getRXBytes">getRXBytes</a></li>
422             
423                 <li data-name="LuCI.network.Device#getRXPackets"><a href="LuCI.network.Device.html#getRXPackets">getRXPackets</a></li>
424             
425                 <li data-name="LuCI.network.Device#getShortName"><a href="LuCI.network.Device.html#getShortName">getShortName</a></li>
426             
427                 <li data-name="LuCI.network.Device#getTXBytes"><a href="LuCI.network.Device.html#getTXBytes">getTXBytes</a></li>
428             
429                 <li data-name="LuCI.network.Device#getTXPackets"><a href="LuCI.network.Device.html#getTXPackets">getTXPackets</a></li>
430             
431                 <li data-name="LuCI.network.Device#getType"><a href="LuCI.network.Device.html#getType">getType</a></li>
432             
433                 <li data-name="LuCI.network.Device#getTypeI18n"><a href="LuCI.network.Device.html#getTypeI18n">getTypeI18n</a></li>
434             
435                 <li data-name="LuCI.network.Device#getWifiNetwork"><a href="LuCI.network.Device.html#getWifiNetwork">getWifiNetwork</a></li>
436             
437                 <li data-name="LuCI.network.Device#isBridge"><a href="LuCI.network.Device.html#isBridge">isBridge</a></li>
438             
439                 <li data-name="LuCI.network.Device#isBridgePort"><a href="LuCI.network.Device.html#isBridgePort">isBridgePort</a></li>
440             
441                 <li data-name="LuCI.network.Device#isUp"><a href="LuCI.network.Device.html#isUp">isUp</a></li>
442             
443             </ul>
444             <ul class="events itemMembers">
445             
446             </ul>
447         </li>
448     
449         <li class="item" data-name="LuCI.network.Hosts">
450             <span class="title">
451                 <a href="LuCI.network.Hosts.html">LuCI.network.Hosts</a>
452                 
453             </span>
454             <ul class="members itemMembers">
455             
456             </ul>
457             <ul class="typedefs itemMembers">
458             
459             </ul>
460             <ul class="typedefs itemMembers">
461             
462             </ul>
463             <ul class="methods itemMembers">
464             
465             <span class="subtitle">Methods</span>
466             
467                 <li data-name="LuCI.network.Hosts#getHostnameByIP6Addr"><a href="LuCI.network.Hosts.html#getHostnameByIP6Addr">getHostnameByIP6Addr</a></li>
468             
469                 <li data-name="LuCI.network.Hosts#getHostnameByIPAddr"><a href="LuCI.network.Hosts.html#getHostnameByIPAddr">getHostnameByIPAddr</a></li>
470             
471                 <li data-name="LuCI.network.Hosts#getHostnameByMACAddr"><a href="LuCI.network.Hosts.html#getHostnameByMACAddr">getHostnameByMACAddr</a></li>
472             
473                 <li data-name="LuCI.network.Hosts#getIP6AddrByMACAddr"><a href="LuCI.network.Hosts.html#getIP6AddrByMACAddr">getIP6AddrByMACAddr</a></li>
474             
475                 <li data-name="LuCI.network.Hosts#getIPAddrByMACAddr"><a href="LuCI.network.Hosts.html#getIPAddrByMACAddr">getIPAddrByMACAddr</a></li>
476             
477                 <li data-name="LuCI.network.Hosts#getMACAddrByIP6Addr"><a href="LuCI.network.Hosts.html#getMACAddrByIP6Addr">getMACAddrByIP6Addr</a></li>
478             
479                 <li data-name="LuCI.network.Hosts#getMACAddrByIPAddr"><a href="LuCI.network.Hosts.html#getMACAddrByIPAddr">getMACAddrByIPAddr</a></li>
480             
481                 <li data-name="LuCI.network.Hosts#getMACHints"><a href="LuCI.network.Hosts.html#getMACHints">getMACHints</a></li>
482             
483             </ul>
484             <ul class="events itemMembers">
485             
486             </ul>
487         </li>
488     
489         <li class="item" data-name="LuCI.network.Protocol">
490             <span class="title">
491                 <a href="LuCI.network.Protocol.html">LuCI.network.Protocol</a>
492                 
493             </span>
494             <ul class="members itemMembers">
495             
496             </ul>
497             <ul class="typedefs itemMembers">
498             
499             </ul>
500             <ul class="typedefs itemMembers">
501             
502             </ul>
503             <ul class="methods itemMembers">
504             
505             <span class="subtitle">Methods</span>
506             
507                 <li data-name="LuCI.network.Protocol#addDevice"><a href="LuCI.network.Protocol.html#addDevice">addDevice</a></li>
508             
509                 <li data-name="LuCI.network.Protocol#containsDevice"><a href="LuCI.network.Protocol.html#containsDevice">containsDevice</a></li>
510             
511                 <li data-name="LuCI.network.Protocol#deleteConfiguration"><a href="LuCI.network.Protocol.html#deleteConfiguration">deleteConfiguration</a></li>
512             
513                 <li data-name="LuCI.network.Protocol#deleteDevice"><a href="LuCI.network.Protocol.html#deleteDevice">deleteDevice</a></li>
514             
515                 <li data-name="LuCI.network.Protocol#get"><a href="LuCI.network.Protocol.html#get">get</a></li>
516             
517                 <li data-name="LuCI.network.Protocol#getDevice"><a href="LuCI.network.Protocol.html#getDevice">getDevice</a></li>
518             
519                 <li data-name="LuCI.network.Protocol#getDevices"><a href="LuCI.network.Protocol.html#getDevices">getDevices</a></li>
520             
521                 <li data-name="LuCI.network.Protocol#getDNS6Addrs"><a href="LuCI.network.Protocol.html#getDNS6Addrs">getDNS6Addrs</a></li>
522             
523                 <li data-name="LuCI.network.Protocol#getDNSAddrs"><a href="LuCI.network.Protocol.html#getDNSAddrs">getDNSAddrs</a></li>
524             
525                 <li data-name="LuCI.network.Protocol#getErrors"><a href="LuCI.network.Protocol.html#getErrors">getErrors</a></li>
526             
527                 <li data-name="LuCI.network.Protocol#getExpiry"><a href="LuCI.network.Protocol.html#getExpiry">getExpiry</a></li>
528             
529                 <li data-name="LuCI.network.Protocol#getGateway6Addr"><a href="LuCI.network.Protocol.html#getGateway6Addr">getGateway6Addr</a></li>
530             
531                 <li data-name="LuCI.network.Protocol#getGatewayAddr"><a href="LuCI.network.Protocol.html#getGatewayAddr">getGatewayAddr</a></li>
532             
533                 <li data-name="LuCI.network.Protocol#getI18n"><a href="LuCI.network.Protocol.html#getI18n">getI18n</a></li>
534             
535                 <li data-name="LuCI.network.Protocol#getIfname"><a href="LuCI.network.Protocol.html#getIfname">getIfname</a></li>
536             
537                 <li data-name="LuCI.network.Protocol#getIP6Addr"><a href="LuCI.network.Protocol.html#getIP6Addr">getIP6Addr</a></li>
538             
539                 <li data-name="LuCI.network.Protocol#getIP6Addrs"><a href="LuCI.network.Protocol.html#getIP6Addrs">getIP6Addrs</a></li>
540             
541                 <li data-name="LuCI.network.Protocol#getIP6Prefix"><a href="LuCI.network.Protocol.html#getIP6Prefix">getIP6Prefix</a></li>
542             
543                 <li data-name="LuCI.network.Protocol#getIPAddr"><a href="LuCI.network.Protocol.html#getIPAddr">getIPAddr</a></li>
544             
545                 <li data-name="LuCI.network.Protocol#getIPAddrs"><a href="LuCI.network.Protocol.html#getIPAddrs">getIPAddrs</a></li>
546             
547                 <li data-name="LuCI.network.Protocol#getL2Device"><a href="LuCI.network.Protocol.html#getL2Device">getL2Device</a></li>
548             
549                 <li data-name="LuCI.network.Protocol#getL3Device"><a href="LuCI.network.Protocol.html#getL3Device">getL3Device</a></li>
550             
551                 <li data-name="LuCI.network.Protocol#getMetric"><a href="LuCI.network.Protocol.html#getMetric">getMetric</a></li>
552             
553                 <li data-name="LuCI.network.Protocol#getName"><a href="LuCI.network.Protocol.html#getName">getName</a></li>
554             
555                 <li data-name="LuCI.network.Protocol#getNetmask"><a href="LuCI.network.Protocol.html#getNetmask">getNetmask</a></li>
556             
557                 <li data-name="LuCI.network.Protocol#getOpkgPackage"><a href="LuCI.network.Protocol.html#getOpkgPackage">getOpkgPackage</a></li>
558             
559                 <li data-name="LuCI.network.Protocol#getProtocol"><a href="LuCI.network.Protocol.html#getProtocol">getProtocol</a></li>
560             
561                 <li data-name="LuCI.network.Protocol#getType"><a href="LuCI.network.Protocol.html#getType">getType</a></li>
562             
563                 <li data-name="LuCI.network.Protocol#getUptime"><a href="LuCI.network.Protocol.html#getUptime">getUptime</a></li>
564             
565                 <li data-name="LuCI.network.Protocol#getZoneName"><a href="LuCI.network.Protocol.html#getZoneName">getZoneName</a></li>
566             
567                 <li data-name="LuCI.network.Protocol#isAlias"><a href="LuCI.network.Protocol.html#isAlias">isAlias</a></li>
568             
569                 <li data-name="LuCI.network.Protocol#isBridge"><a href="LuCI.network.Protocol.html#isBridge">isBridge</a></li>
570             
571                 <li data-name="LuCI.network.Protocol#isDynamic"><a href="LuCI.network.Protocol.html#isDynamic">isDynamic</a></li>
572             
573                 <li data-name="LuCI.network.Protocol#isEmpty"><a href="LuCI.network.Protocol.html#isEmpty">isEmpty</a></li>
574             
575                 <li data-name="LuCI.network.Protocol#isFloating"><a href="LuCI.network.Protocol.html#isFloating">isFloating</a></li>
576             
577                 <li data-name="LuCI.network.Protocol#isInstalled"><a href="LuCI.network.Protocol.html#isInstalled">isInstalled</a></li>
578             
579                 <li data-name="LuCI.network.Protocol#isUp"><a href="LuCI.network.Protocol.html#isUp">isUp</a></li>
580             
581                 <li data-name="LuCI.network.Protocol#isVirtual"><a href="LuCI.network.Protocol.html#isVirtual">isVirtual</a></li>
582             
583                 <li data-name="LuCI.network.Protocol#set"><a href="LuCI.network.Protocol.html#set">set</a></li>
584             
585             </ul>
586             <ul class="events itemMembers">
587             
588             </ul>
589         </li>
590     
591         <li class="item" data-name="LuCI.network.WifiDevice">
592             <span class="title">
593                 <a href="LuCI.network.WifiDevice.html">LuCI.network.WifiDevice</a>
594                 
595             </span>
596             <ul class="members itemMembers">
597             
598             </ul>
599             <ul class="typedefs itemMembers">
600             
601             </ul>
602             <ul class="typedefs itemMembers">
603             
604             </ul>
605             <ul class="methods itemMembers">
606             
607             <span class="subtitle">Methods</span>
608             
609                 <li data-name="LuCI.network.WifiDevice#addWifiNetwork"><a href="LuCI.network.WifiDevice.html#addWifiNetwork">addWifiNetwork</a></li>
610             
611                 <li data-name="LuCI.network.WifiDevice#deleteWifiNetwork"><a href="LuCI.network.WifiDevice.html#deleteWifiNetwork">deleteWifiNetwork</a></li>
612             
613                 <li data-name="LuCI.network.WifiDevice#get"><a href="LuCI.network.WifiDevice.html#get">get</a></li>
614             
615                 <li data-name="LuCI.network.WifiDevice#getHTModes"><a href="LuCI.network.WifiDevice.html#getHTModes">getHTModes</a></li>
616             
617                 <li data-name="LuCI.network.WifiDevice#getHWModes"><a href="LuCI.network.WifiDevice.html#getHWModes">getHWModes</a></li>
618             
619                 <li data-name="LuCI.network.WifiDevice#getI18n"><a href="LuCI.network.WifiDevice.html#getI18n">getI18n</a></li>
620             
621                 <li data-name="LuCI.network.WifiDevice#getName"><a href="LuCI.network.WifiDevice.html#getName">getName</a></li>
622             
623                 <li data-name="LuCI.network.WifiDevice#getScanList"><a href="LuCI.network.WifiDevice.html#getScanList">getScanList</a></li>
624             
625                 <li data-name="LuCI.network.WifiDevice#getWifiNetwork"><a href="LuCI.network.WifiDevice.html#getWifiNetwork">getWifiNetwork</a></li>
626             
627                 <li data-name="LuCI.network.WifiDevice#getWifiNetworks"><a href="LuCI.network.WifiDevice.html#getWifiNetworks">getWifiNetworks</a></li>
628             
629                 <li data-name="LuCI.network.WifiDevice#isDisabled"><a href="LuCI.network.WifiDevice.html#isDisabled">isDisabled</a></li>
630             
631                 <li data-name="LuCI.network.WifiDevice#isUp"><a href="LuCI.network.WifiDevice.html#isUp">isUp</a></li>
632             
633                 <li data-name="LuCI.network.WifiDevice#set"><a href="LuCI.network.WifiDevice.html#set">set</a></li>
634             
635             </ul>
636             <ul class="events itemMembers">
637             
638             </ul>
639         </li>
640     
641         <li class="item" data-name="LuCI.network.WifiNetwork">
642             <span class="title">
643                 <a href="LuCI.network.WifiNetwork.html">LuCI.network.WifiNetwork</a>
644                 
645             </span>
646             <ul class="members itemMembers">
647             
648             </ul>
649             <ul class="typedefs itemMembers">
650             
651             </ul>
652             <ul class="typedefs itemMembers">
653             
654             </ul>
655             <ul class="methods itemMembers">
656             
657             <span class="subtitle">Methods</span>
658             
659                 <li data-name="LuCI.network.WifiNetwork#disconnectClient"><a href="LuCI.network.WifiNetwork.html#disconnectClient">disconnectClient</a></li>
660             
661                 <li data-name="LuCI.network.WifiNetwork#get"><a href="LuCI.network.WifiNetwork.html#get">get</a></li>
662             
663                 <li data-name="LuCI.network.WifiNetwork#getActiveBSSID"><a href="LuCI.network.WifiNetwork.html#getActiveBSSID">getActiveBSSID</a></li>
664             
665                 <li data-name="LuCI.network.WifiNetwork#getActiveEncryption"><a href="LuCI.network.WifiNetwork.html#getActiveEncryption">getActiveEncryption</a></li>
666             
667                 <li data-name="LuCI.network.WifiNetwork#getActiveMode"><a href="LuCI.network.WifiNetwork.html#getActiveMode">getActiveMode</a></li>
668             
669                 <li data-name="LuCI.network.WifiNetwork#getActiveModeI18n"><a href="LuCI.network.WifiNetwork.html#getActiveModeI18n">getActiveModeI18n</a></li>
670             
671                 <li data-name="LuCI.network.WifiNetwork#getActiveSSID"><a href="LuCI.network.WifiNetwork.html#getActiveSSID">getActiveSSID</a></li>
672             
673                 <li data-name="LuCI.network.WifiNetwork#getAssocList"><a href="LuCI.network.WifiNetwork.html#getAssocList">getAssocList</a></li>
674             
675                 <li data-name="LuCI.network.WifiNetwork#getBitRate"><a href="LuCI.network.WifiNetwork.html#getBitRate">getBitRate</a></li>
676             
677                 <li data-name="LuCI.network.WifiNetwork#getBSSID"><a href="LuCI.network.WifiNetwork.html#getBSSID">getBSSID</a></li>
678             
679                 <li data-name="LuCI.network.WifiNetwork#getChannel"><a href="LuCI.network.WifiNetwork.html#getChannel">getChannel</a></li>
680             
681                 <li data-name="LuCI.network.WifiNetwork#getCountryCode"><a href="LuCI.network.WifiNetwork.html#getCountryCode">getCountryCode</a></li>
682             
683                 <li data-name="LuCI.network.WifiNetwork#getDevice"><a href="LuCI.network.WifiNetwork.html#getDevice">getDevice</a></li>
684             
685                 <li data-name="LuCI.network.WifiNetwork#getFrequency"><a href="LuCI.network.WifiNetwork.html#getFrequency">getFrequency</a></li>
686             
687                 <li data-name="LuCI.network.WifiNetwork#getI18n"><a href="LuCI.network.WifiNetwork.html#getI18n">getI18n</a></li>
688             
689                 <li data-name="LuCI.network.WifiNetwork#getID"><a href="LuCI.network.WifiNetwork.html#getID">getID</a></li>
690             
691                 <li data-name="LuCI.network.WifiNetwork#getIfname"><a href="LuCI.network.WifiNetwork.html#getIfname">getIfname</a></li>
692             
693                 <li data-name="LuCI.network.WifiNetwork#getMeshID"><a href="LuCI.network.WifiNetwork.html#getMeshID">getMeshID</a></li>
694             
695                 <li data-name="LuCI.network.WifiNetwork#getMode"><a href="LuCI.network.WifiNetwork.html#getMode">getMode</a></li>
696             
697                 <li data-name="LuCI.network.WifiNetwork#getName"><a href="LuCI.network.WifiNetwork.html#getName">getName</a></li>
698             
699                 <li data-name="LuCI.network.WifiNetwork#getNetwork"><a href="LuCI.network.WifiNetwork.html#getNetwork">getNetwork</a></li>
700             
701                 <li data-name="LuCI.network.WifiNetwork#getNetworkNames"><a href="LuCI.network.WifiNetwork.html#getNetworkNames">getNetworkNames</a></li>
702             
703                 <li data-name="LuCI.network.WifiNetwork#getNetworks"><a href="LuCI.network.WifiNetwork.html#getNetworks">getNetworks</a></li>
704             
705                 <li data-name="LuCI.network.WifiNetwork#getNoise"><a href="LuCI.network.WifiNetwork.html#getNoise">getNoise</a></li>
706             
707                 <li data-name="LuCI.network.WifiNetwork#getShortName"><a href="LuCI.network.WifiNetwork.html#getShortName">getShortName</a></li>
708             
709                 <li data-name="LuCI.network.WifiNetwork#getSignal"><a href="LuCI.network.WifiNetwork.html#getSignal">getSignal</a></li>
710             
711                 <li data-name="LuCI.network.WifiNetwork#getSignalLevel"><a href="LuCI.network.WifiNetwork.html#getSignalLevel">getSignalLevel</a></li>
712             
713                 <li data-name="LuCI.network.WifiNetwork#getSignalPercent"><a href="LuCI.network.WifiNetwork.html#getSignalPercent">getSignalPercent</a></li>
714             
715                 <li data-name="LuCI.network.WifiNetwork#getSSID"><a href="LuCI.network.WifiNetwork.html#getSSID">getSSID</a></li>
716             
717                 <li data-name="LuCI.network.WifiNetwork#getTXPower"><a href="LuCI.network.WifiNetwork.html#getTXPower">getTXPower</a></li>
718             
719                 <li data-name="LuCI.network.WifiNetwork#getTXPowerOffset"><a href="LuCI.network.WifiNetwork.html#getTXPowerOffset">getTXPowerOffset</a></li>
720             
721                 <li data-name="LuCI.network.WifiNetwork#getWifiDevice"><a href="LuCI.network.WifiNetwork.html#getWifiDevice">getWifiDevice</a></li>
722             
723                 <li data-name="LuCI.network.WifiNetwork#getWifiDeviceName"><a href="LuCI.network.WifiNetwork.html#getWifiDeviceName">getWifiDeviceName</a></li>
724             
725                 <li data-name="LuCI.network.WifiNetwork#isClientDisconnectSupported"><a href="LuCI.network.WifiNetwork.html#isClientDisconnectSupported">isClientDisconnectSupported</a></li>
726             
727                 <li data-name="LuCI.network.WifiNetwork#isDisabled"><a href="LuCI.network.WifiNetwork.html#isDisabled">isDisabled</a></li>
728             
729                 <li data-name="LuCI.network.WifiNetwork#isUp"><a href="LuCI.network.WifiNetwork.html#isUp">isUp</a></li>
730             
731                 <li data-name="LuCI.network.WifiNetwork#set"><a href="LuCI.network.WifiNetwork.html#set">set</a></li>
732             
733             </ul>
734             <ul class="events itemMembers">
735             
736             </ul>
737         </li>
738     
739         <li class="item" data-name="LuCI.poll">
740             <span class="title">
741                 <a href="LuCI.poll.html">LuCI.poll</a>
742                 
743             </span>
744             <ul class="members itemMembers">
745             
746             </ul>
747             <ul class="typedefs itemMembers">
748             
749             </ul>
750             <ul class="typedefs itemMembers">
751             
752             </ul>
753             <ul class="methods itemMembers">
754             
755             <span class="subtitle">Methods</span>
756             
757                 <li data-name="LuCI.poll#active"><a href="LuCI.poll.html#active">active</a></li>
758             
759                 <li data-name="LuCI.poll#add"><a href="LuCI.poll.html#add">add</a></li>
760             
761                 <li data-name="LuCI.poll#remove"><a href="LuCI.poll.html#remove">remove</a></li>
762             
763                 <li data-name="LuCI.poll#start"><a href="LuCI.poll.html#start">start</a></li>
764             
765                 <li data-name="LuCI.poll#stop"><a href="LuCI.poll.html#stop">stop</a></li>
766             
767             </ul>
768             <ul class="events itemMembers">
769             
770             </ul>
771         </li>
772     
773         <li class="item" data-name="LuCI.request">
774             <span class="title">
775                 <a href="LuCI.request.html">LuCI.request</a>
776                 
777             </span>
778             <ul class="members itemMembers">
779             
780             </ul>
781             <ul class="typedefs itemMembers">
782             
783             <span class="subtitle">Typedefs</span>
784             
785                 <li data-name="LuCI.request.interceptorFn"><a href="LuCI.request.html#.interceptorFn">interceptorFn</a></li>
786             
787                 <li data-name="LuCI.request.RequestOptions"><a href="LuCI.request.html#.RequestOptions">RequestOptions</a></li>
788             
789             </ul>
790             <ul class="typedefs itemMembers">
791             
792             </ul>
793             <ul class="methods itemMembers">
794             
795             <span class="subtitle">Methods</span>
796             
797                 <li data-name="LuCI.request#addInterceptor"><a href="LuCI.request.html#addInterceptor">addInterceptor</a></li>
798             
799                 <li data-name="LuCI.request#expandURL"><a href="LuCI.request.html#expandURL">expandURL</a></li>
800             
801                 <li data-name="LuCI.request#get"><a href="LuCI.request.html#get">get</a></li>
802             
803                 <li data-name="LuCI.request#post"><a href="LuCI.request.html#post">post</a></li>
804             
805                 <li data-name="LuCI.request#removeInterceptor"><a href="LuCI.request.html#removeInterceptor">removeInterceptor</a></li>
806             
807                 <li data-name="LuCI.request#request"><a href="LuCI.request.html#request">request</a></li>
808             
809             </ul>
810             <ul class="events itemMembers">
811             
812             </ul>
813         </li>
814     
815         <li class="item" data-name="LuCI.request.poll">
816             <span class="title">
817                 <a href="LuCI.request.poll.html">LuCI.request.poll</a>
818                 
819             </span>
820             <ul class="members itemMembers">
821             
822             </ul>
823             <ul class="typedefs itemMembers">
824             
825             <span class="subtitle">Typedefs</span>
826             
827                 <li data-name="LuCI.request.poll~callbackFn"><a href="LuCI.request.poll.html#~callbackFn">callbackFn</a></li>
828             
829             </ul>
830             <ul class="typedefs itemMembers">
831             
832             </ul>
833             <ul class="methods itemMembers">
834             
835             <span class="subtitle">Methods</span>
836             
837                 <li data-name="LuCI.request.poll#active"><a href="LuCI.request.poll.html#active">active</a></li>
838             
839                 <li data-name="LuCI.request.poll#add"><a href="LuCI.request.poll.html#add">add</a></li>
840             
841                 <li data-name="LuCI.request.poll#remove"><a href="LuCI.request.poll.html#remove">remove</a></li>
842             
843                 <li data-name="LuCI.request.poll#start"><a href="LuCI.request.poll.html#start">start</a></li>
844             
845                 <li data-name="LuCI.request.poll#stop"><a href="LuCI.request.poll.html#stop">stop</a></li>
846             
847             </ul>
848             <ul class="events itemMembers">
849             
850             </ul>
851         </li>
852     
853         <li class="item" data-name="LuCI.response">
854             <span class="title">
855                 <a href="LuCI.response.html">LuCI.response</a>
856                 
857             </span>
858             <ul class="members itemMembers">
859             
860             <span class="subtitle">Members</span>
861             
862                 <li data-name="LuCI.response#duration"><a href="LuCI.response.html#duration">duration</a></li>
863             
864                 <li data-name="LuCI.response#headers"><a href="LuCI.response.html#headers">headers</a></li>
865             
866                 <li data-name="LuCI.response#ok"><a href="LuCI.response.html#ok">ok</a></li>
867             
868                 <li data-name="LuCI.response#status"><a href="LuCI.response.html#status">status</a></li>
869             
870                 <li data-name="LuCI.response#statusText"><a href="LuCI.response.html#statusText">statusText</a></li>
871             
872                 <li data-name="LuCI.response#url"><a href="LuCI.response.html#url">url</a></li>
873             
874             </ul>
875             <ul class="typedefs itemMembers">
876             
877             </ul>
878             <ul class="typedefs itemMembers">
879             
880             </ul>
881             <ul class="methods itemMembers">
882             
883             <span class="subtitle">Methods</span>
884             
885                 <li data-name="LuCI.response#blob"><a href="LuCI.response.html#blob">blob</a></li>
886             
887                 <li data-name="LuCI.response#clone"><a href="LuCI.response.html#clone">clone</a></li>
888             
889                 <li data-name="LuCI.response#json"><a href="LuCI.response.html#json">json</a></li>
890             
891                 <li data-name="LuCI.response#text"><a href="LuCI.response.html#text">text</a></li>
892             
893             </ul>
894             <ul class="events itemMembers">
895             
896             </ul>
897         </li>
898     
899         <li class="item" data-name="LuCI.rpc">
900             <span class="title">
901                 <a href="LuCI.rpc.html">LuCI.rpc</a>
902                 
903             </span>
904             <ul class="members itemMembers">
905             
906             </ul>
907             <ul class="typedefs itemMembers">
908             
909             <span class="subtitle">Typedefs</span>
910             
911                 <li data-name="LuCI.rpc.DeclareOptions"><a href="LuCI.rpc.html#.DeclareOptions">DeclareOptions</a></li>
912             
913                 <li data-name="LuCI.rpc~filterFn"><a href="LuCI.rpc.html#~filterFn">filterFn</a></li>
914             
915                 <li data-name="LuCI.rpc~interceptorFn"><a href="LuCI.rpc.html#~interceptorFn">interceptorFn</a></li>
916             
917                 <li data-name="LuCI.rpc~invokeFn"><a href="LuCI.rpc.html#~invokeFn">invokeFn</a></li>
918             
919             </ul>
920             <ul class="typedefs itemMembers">
921             
922             </ul>
923             <ul class="methods itemMembers">
924             
925             <span class="subtitle">Methods</span>
926             
927                 <li data-name="LuCI.rpc#addInterceptor"><a href="LuCI.rpc.html#addInterceptor">addInterceptor</a></li>
928             
929                 <li data-name="LuCI.rpc#declare"><a href="LuCI.rpc.html#declare">declare</a></li>
930             
931                 <li data-name="LuCI.rpc#getBaseURL"><a href="LuCI.rpc.html#getBaseURL">getBaseURL</a></li>
932             
933                 <li data-name="LuCI.rpc#getSessionID"><a href="LuCI.rpc.html#getSessionID">getSessionID</a></li>
934             
935                 <li data-name="LuCI.rpc#getStatusText"><a href="LuCI.rpc.html#getStatusText">getStatusText</a></li>
936             
937                 <li data-name="LuCI.rpc#list"><a href="LuCI.rpc.html#list">list</a></li>
938             
939                 <li data-name="LuCI.rpc#removeInterceptor"><a href="LuCI.rpc.html#removeInterceptor">removeInterceptor</a></li>
940             
941                 <li data-name="LuCI.rpc#setBaseURL"><a href="LuCI.rpc.html#setBaseURL">setBaseURL</a></li>
942             
943                 <li data-name="LuCI.rpc#setSessionID"><a href="LuCI.rpc.html#setSessionID">setSessionID</a></li>
944             
945             </ul>
946             <ul class="events itemMembers">
947             
948             </ul>
949         </li>
950     
951         <li class="item" data-name="LuCI.uci">
952             <span class="title">
953                 <a href="LuCI.uci.html">LuCI.uci</a>
954                 
955             </span>
956             <ul class="members itemMembers">
957             
958             </ul>
959             <ul class="typedefs itemMembers">
960             
961             <span class="subtitle">Typedefs</span>
962             
963                 <li data-name="LuCI.uci.ChangeRecord"><a href="LuCI.uci.html#.ChangeRecord">ChangeRecord</a></li>
964             
965                 <li data-name="LuCI.uci.SectionObject"><a href="LuCI.uci.html#.SectionObject">SectionObject</a></li>
966             
967                 <li data-name="LuCI.uci~sectionsFn"><a href="LuCI.uci.html#~sectionsFn">sectionsFn</a></li>
968             
969             </ul>
970             <ul class="typedefs itemMembers">
971             
972             </ul>
973             <ul class="methods itemMembers">
974             
975             <span class="subtitle">Methods</span>
976             
977                 <li data-name="LuCI.uci#add"><a href="LuCI.uci.html#add">add</a></li>
978             
979                 <li data-name="LuCI.uci#apply"><a href="LuCI.uci.html#apply">apply</a></li>
980             
981                 <li data-name="LuCI.uci#changes"><a href="LuCI.uci.html#changes">changes</a></li>
982             
983                 <li data-name="LuCI.uci#createSID"><a href="LuCI.uci.html#createSID">createSID</a></li>
984             
985                 <li data-name="LuCI.uci#get"><a href="LuCI.uci.html#get">get</a></li>
986             
987                 <li data-name="LuCI.uci#get_first"><a href="LuCI.uci.html#get_first">get_first</a></li>
988             
989                 <li data-name="LuCI.uci#load"><a href="LuCI.uci.html#load">load</a></li>
990             
991                 <li data-name="LuCI.uci#move"><a href="LuCI.uci.html#move">move</a></li>
992             
993                 <li data-name="LuCI.uci#remove"><a href="LuCI.uci.html#remove">remove</a></li>
994             
995                 <li data-name="LuCI.uci#resolveSID"><a href="LuCI.uci.html#resolveSID">resolveSID</a></li>
996             
997                 <li data-name="LuCI.uci#save"><a href="LuCI.uci.html#save">save</a></li>
998             
999                 <li data-name="LuCI.uci#sections"><a href="LuCI.uci.html#sections">sections</a></li>
1000             
1001                 <li data-name="LuCI.uci#set"><a href="LuCI.uci.html#set">set</a></li>
1002             
1003                 <li data-name="LuCI.uci#set_first"><a href="LuCI.uci.html#set_first">set_first</a></li>
1004             
1005                 <li data-name="LuCI.uci#unload"><a href="LuCI.uci.html#unload">unload</a></li>
1006             
1007                 <li data-name="LuCI.uci#unset"><a href="LuCI.uci.html#unset">unset</a></li>
1008             
1009                 <li data-name="LuCI.uci#unset_first"><a href="LuCI.uci.html#unset_first">unset_first</a></li>
1010             
1011             </ul>
1012             <ul class="events itemMembers">
1013             
1014             </ul>
1015         </li>
1016     
1017         <li class="item" data-name="LuCI.ui">
1018             <span class="title">
1019                 <a href="LuCI.ui.html">LuCI.ui</a>
1020                 
1021             </span>
1022             <ul class="members itemMembers">
1023             
1024             </ul>
1025             <ul class="typedefs itemMembers">
1026             
1027             <span class="subtitle">Typedefs</span>
1028             
1029                 <li data-name="LuCI.ui.FileUploadReply"><a href="LuCI.ui.html#.FileUploadReply">FileUploadReply</a></li>
1030             
1031             </ul>
1032             <ul class="typedefs itemMembers">
1033             
1034             </ul>
1035             <ul class="methods itemMembers">
1036             
1037             <span class="subtitle">Methods</span>
1038             
1039                 <li data-name="LuCI.ui#addNotification"><a href="LuCI.ui.html#addNotification">addNotification</a></li>
1040             
1041                 <li data-name="LuCI.ui#addValidator"><a href="LuCI.ui.html#addValidator">addValidator</a></li>
1042             
1043                 <li data-name="LuCI.ui#awaitReconnect"><a href="LuCI.ui.html#awaitReconnect">awaitReconnect</a></li>
1044             
1045                 <li data-name="LuCI.ui#createHandlerFn"><a href="LuCI.ui.html#createHandlerFn">createHandlerFn</a></li>
1046             
1047                 <li data-name="LuCI.ui#hideIndicator"><a href="LuCI.ui.html#hideIndicator">hideIndicator</a></li>
1048             
1049                 <li data-name="LuCI.ui#hideModal"><a href="LuCI.ui.html#hideModal">hideModal</a></li>
1050             
1051                 <li data-name="LuCI.ui#instantiateView"><a href="LuCI.ui.html#instantiateView">instantiateView</a></li>
1052             
1053                 <li data-name="LuCI.ui#itemlist"><a href="LuCI.ui.html#itemlist">itemlist</a></li>
1054             
1055                 <li data-name="LuCI.ui#pingDevice"><a href="LuCI.ui.html#pingDevice">pingDevice</a></li>
1056             
1057                 <li data-name="LuCI.ui#showIndicator"><a href="LuCI.ui.html#showIndicator">showIndicator</a></li>
1058             
1059                 <li data-name="LuCI.ui#showModal"><a href="LuCI.ui.html#showModal">showModal</a></li>
1060             
1061                 <li data-name="LuCI.ui#uploadFile"><a href="LuCI.ui.html#uploadFile">uploadFile</a></li>
1062             
1063             </ul>
1064             <ul class="events itemMembers">
1065             
1066             </ul>
1067         </li>
1068     
1069         <li class="item" data-name="LuCI.ui.AbstractElement">
1070             <span class="title">
1071                 <a href="LuCI.ui.AbstractElement.html">LuCI.ui.AbstractElement</a>
1072                 
1073             </span>
1074             <ul class="members itemMembers">
1075             
1076             </ul>
1077             <ul class="typedefs itemMembers">
1078             
1079             <span class="subtitle">Typedefs</span>
1080             
1081                 <li data-name="LuCI.ui.AbstractElement.InitOptions"><a href="LuCI.ui.AbstractElement.html#.InitOptions">InitOptions</a></li>
1082             
1083             </ul>
1084             <ul class="typedefs itemMembers">
1085             
1086             </ul>
1087             <ul class="methods itemMembers">
1088             
1089             <span class="subtitle">Methods</span>
1090             
1091                 <li data-name="LuCI.ui.AbstractElement#getValue"><a href="LuCI.ui.AbstractElement.html#getValue">getValue</a></li>
1092             
1093                 <li data-name="LuCI.ui.AbstractElement#isValid"><a href="LuCI.ui.AbstractElement.html#isValid">isValid</a></li>
1094             
1095                 <li data-name="LuCI.ui.AbstractElement#registerEvents"><a href="LuCI.ui.AbstractElement.html#registerEvents">registerEvents</a></li>
1096             
1097                 <li data-name="LuCI.ui.AbstractElement#render"><a href="LuCI.ui.AbstractElement.html#render">render</a></li>
1098             
1099                 <li data-name="LuCI.ui.AbstractElement#setChangeEvents"><a href="LuCI.ui.AbstractElement.html#setChangeEvents">setChangeEvents</a></li>
1100             
1101                 <li data-name="LuCI.ui.AbstractElement#setUpdateEvents"><a href="LuCI.ui.AbstractElement.html#setUpdateEvents">setUpdateEvents</a></li>
1102             
1103                 <li data-name="LuCI.ui.AbstractElement#setValue"><a href="LuCI.ui.AbstractElement.html#setValue">setValue</a></li>
1104             
1105                 <li data-name="LuCI.ui.AbstractElement#triggerValidation"><a href="LuCI.ui.AbstractElement.html#triggerValidation">triggerValidation</a></li>
1106             
1107             </ul>
1108             <ul class="events itemMembers">
1109             
1110             </ul>
1111         </li>
1112     
1113         <li class="item" data-name="LuCI.ui.changes">
1114             <span class="title">
1115                 <a href="LuCI.ui.changes.html">LuCI.ui.changes</a>
1116                 
1117             </span>
1118             <ul class="members itemMembers">
1119             
1120             </ul>
1121             <ul class="typedefs itemMembers">
1122             
1123             </ul>
1124             <ul class="typedefs itemMembers">
1125             
1126             </ul>
1127             <ul class="methods itemMembers">
1128             
1129             <span class="subtitle">Methods</span>
1130             
1131                 <li data-name="LuCI.ui.changes#apply"><a href="LuCI.ui.changes.html#apply">apply</a></li>
1132             
1133                 <li data-name="LuCI.ui.changes#displayChanges"><a href="LuCI.ui.changes.html#displayChanges">displayChanges</a></li>
1134             
1135                 <li data-name="LuCI.ui.changes#renderChangeIndicator"><a href="LuCI.ui.changes.html#renderChangeIndicator">renderChangeIndicator</a></li>
1136             
1137                 <li data-name="LuCI.ui.changes#revert"><a href="LuCI.ui.changes.html#revert">revert</a></li>
1138             
1139                 <li data-name="LuCI.ui.changes#setIndicator"><a href="LuCI.ui.changes.html#setIndicator">setIndicator</a></li>
1140             
1141             </ul>
1142             <ul class="events itemMembers">
1143             
1144             </ul>
1145         </li>
1146     
1147         <li class="item" data-name="LuCI.ui.Checkbox">
1148             <span class="title">
1149                 <a href="LuCI.ui.Checkbox.html">LuCI.ui.Checkbox</a>
1150                 
1151             </span>
1152             <ul class="members itemMembers">
1153             
1154             </ul>
1155             <ul class="typedefs itemMembers">
1156             
1157             <span class="subtitle">Typedefs</span>
1158             
1159                 <li data-name="LuCI.ui.Checkbox.InitOptions"><a href="LuCI.ui.Checkbox.html#.InitOptions">InitOptions</a></li>
1160             
1161             </ul>
1162             <ul class="typedefs itemMembers">
1163             
1164             </ul>
1165             <ul class="methods itemMembers">
1166             
1167             <span class="subtitle">Methods</span>
1168             
1169                 <li data-name="LuCI.ui.Checkbox#getValue"><a href="LuCI.ui.Checkbox.html#getValue">getValue</a></li>
1170             
1171                 <li data-name="LuCI.ui.Checkbox#isChecked"><a href="LuCI.ui.Checkbox.html#isChecked">isChecked</a></li>
1172             
1173                 <li data-name="LuCI.ui.Checkbox#isValid"><a href="LuCI.ui.Checkbox.html#isValid">isValid</a></li>
1174             
1175                 <li data-name="LuCI.ui.Checkbox#registerEvents"><a href="LuCI.ui.Checkbox.html#registerEvents">registerEvents</a></li>
1176             
1177                 <li data-name="LuCI.ui.Checkbox#render"><a href="LuCI.ui.Checkbox.html#render">render</a></li>
1178             
1179                 <li data-name="LuCI.ui.Checkbox#setChangeEvents"><a href="LuCI.ui.Checkbox.html#setChangeEvents">setChangeEvents</a></li>
1180             
1181                 <li data-name="LuCI.ui.Checkbox#setUpdateEvents"><a href="LuCI.ui.Checkbox.html#setUpdateEvents">setUpdateEvents</a></li>
1182             
1183                 <li data-name="LuCI.ui.Checkbox#setValue"><a href="LuCI.ui.Checkbox.html#setValue">setValue</a></li>
1184             
1185                 <li data-name="LuCI.ui.Checkbox#triggerValidation"><a href="LuCI.ui.Checkbox.html#triggerValidation">triggerValidation</a></li>
1186             
1187             </ul>
1188             <ul class="events itemMembers">
1189             
1190             </ul>
1191         </li>
1192     
1193         <li class="item" data-name="LuCI.ui.Combobox">
1194             <span class="title">
1195                 <a href="LuCI.ui.Combobox.html">LuCI.ui.Combobox</a>
1196                 
1197             </span>
1198             <ul class="members itemMembers">
1199             
1200             </ul>
1201             <ul class="typedefs itemMembers">
1202             
1203             <span class="subtitle">Typedefs</span>
1204             
1205                 <li data-name="LuCI.ui.Combobox.InitOptions"><a href="LuCI.ui.Combobox.html#.InitOptions">InitOptions</a></li>
1206             
1207             </ul>
1208             <ul class="typedefs itemMembers">
1209             
1210             </ul>
1211             <ul class="methods itemMembers">
1212             
1213             <span class="subtitle">Methods</span>
1214             
1215                 <li data-name="LuCI.ui.Combobox#addChoices"><a href="LuCI.ui.Combobox.html#addChoices">addChoices</a></li>
1216             
1217                 <li data-name="LuCI.ui.Combobox#clearChoices"><a href="LuCI.ui.Combobox.html#clearChoices">clearChoices</a></li>
1218             
1219                 <li data-name="LuCI.ui.Combobox#closeAllDropdowns"><a href="LuCI.ui.Combobox.html#closeAllDropdowns">closeAllDropdowns</a></li>
1220             
1221                 <li data-name="LuCI.ui.Combobox#isValid"><a href="LuCI.ui.Combobox.html#isValid">isValid</a></li>
1222             
1223                 <li data-name="LuCI.ui.Combobox#registerEvents"><a href="LuCI.ui.Combobox.html#registerEvents">registerEvents</a></li>
1224             
1225                 <li data-name="LuCI.ui.Combobox#setChangeEvents"><a href="LuCI.ui.Combobox.html#setChangeEvents">setChangeEvents</a></li>
1226             
1227                 <li data-name="LuCI.ui.Combobox#setUpdateEvents"><a href="LuCI.ui.Combobox.html#setUpdateEvents">setUpdateEvents</a></li>
1228             
1229                 <li data-name="LuCI.ui.Combobox#triggerValidation"><a href="LuCI.ui.Combobox.html#triggerValidation">triggerValidation</a></li>
1230             
1231             </ul>
1232             <ul class="events itemMembers">
1233             
1234             </ul>
1235         </li>
1236     
1237         <li class="item" data-name="LuCI.ui.ComboButton">
1238             <span class="title">
1239                 <a href="LuCI.ui.ComboButton.html">LuCI.ui.ComboButton</a>
1240                 
1241             </span>
1242             <ul class="members itemMembers">
1243             
1244             </ul>
1245             <ul class="typedefs itemMembers">
1246             
1247             <span class="subtitle">Typedefs</span>
1248             
1249                 <li data-name="LuCI.ui.ComboButton.InitOptions"><a href="LuCI.ui.ComboButton.html#.InitOptions">InitOptions</a></li>
1250             
1251             </ul>
1252             <ul class="typedefs itemMembers">
1253             
1254             </ul>
1255             <ul class="methods itemMembers">
1256             
1257             <span class="subtitle">Methods</span>
1258             
1259                 <li data-name="LuCI.ui.ComboButton#addChoices"><a href="LuCI.ui.ComboButton.html#addChoices">addChoices</a></li>
1260             
1261                 <li data-name="LuCI.ui.ComboButton#clearChoices"><a href="LuCI.ui.ComboButton.html#clearChoices">clearChoices</a></li>
1262             
1263                 <li data-name="LuCI.ui.ComboButton#closeAllDropdowns"><a href="LuCI.ui.ComboButton.html#closeAllDropdowns">closeAllDropdowns</a></li>
1264             
1265                 <li data-name="LuCI.ui.ComboButton#isValid"><a href="LuCI.ui.ComboButton.html#isValid">isValid</a></li>
1266             
1267                 <li data-name="LuCI.ui.ComboButton#registerEvents"><a href="LuCI.ui.ComboButton.html#registerEvents">registerEvents</a></li>
1268             
1269                 <li data-name="LuCI.ui.ComboButton#setChangeEvents"><a href="LuCI.ui.ComboButton.html#setChangeEvents">setChangeEvents</a></li>
1270             
1271                 <li data-name="LuCI.ui.ComboButton#setUpdateEvents"><a href="LuCI.ui.ComboButton.html#setUpdateEvents">setUpdateEvents</a></li>
1272             
1273                 <li data-name="LuCI.ui.ComboButton#triggerValidation"><a href="LuCI.ui.ComboButton.html#triggerValidation">triggerValidation</a></li>
1274             
1275             </ul>
1276             <ul class="events itemMembers">
1277             
1278             </ul>
1279         </li>
1280     
1281         <li class="item" data-name="LuCI.ui.Dropdown">
1282             <span class="title">
1283                 <a href="LuCI.ui.Dropdown.html">LuCI.ui.Dropdown</a>
1284                 
1285             </span>
1286             <ul class="members itemMembers">
1287             
1288             </ul>
1289             <ul class="typedefs itemMembers">
1290             
1291             <span class="subtitle">Typedefs</span>
1292             
1293                 <li data-name="LuCI.ui.Dropdown.InitOptions"><a href="LuCI.ui.Dropdown.html#.InitOptions">InitOptions</a></li>
1294             
1295             </ul>
1296             <ul class="typedefs itemMembers">
1297             
1298             </ul>
1299             <ul class="methods itemMembers">
1300             
1301             <span class="subtitle">Methods</span>
1302             
1303                 <li data-name="LuCI.ui.Dropdown#addChoices"><a href="LuCI.ui.Dropdown.html#addChoices">addChoices</a></li>
1304             
1305                 <li data-name="LuCI.ui.Dropdown#clearChoices"><a href="LuCI.ui.Dropdown.html#clearChoices">clearChoices</a></li>
1306             
1307                 <li data-name="LuCI.ui.Dropdown#closeAllDropdowns"><a href="LuCI.ui.Dropdown.html#closeAllDropdowns">closeAllDropdowns</a></li>
1308             
1309                 <li data-name="LuCI.ui.Dropdown#getValue"><a href="LuCI.ui.Dropdown.html#getValue">getValue</a></li>
1310             
1311                 <li data-name="LuCI.ui.Dropdown#isValid"><a href="LuCI.ui.Dropdown.html#isValid">isValid</a></li>
1312             
1313                 <li data-name="LuCI.ui.Dropdown#registerEvents"><a href="LuCI.ui.Dropdown.html#registerEvents">registerEvents</a></li>
1314             
1315                 <li data-name="LuCI.ui.Dropdown#render"><a href="LuCI.ui.Dropdown.html#render">render</a></li>
1316             
1317                 <li data-name="LuCI.ui.Dropdown#setChangeEvents"><a href="LuCI.ui.Dropdown.html#setChangeEvents">setChangeEvents</a></li>
1318             
1319                 <li data-name="LuCI.ui.Dropdown#setUpdateEvents"><a href="LuCI.ui.Dropdown.html#setUpdateEvents">setUpdateEvents</a></li>
1320             
1321                 <li data-name="LuCI.ui.Dropdown#setValue"><a href="LuCI.ui.Dropdown.html#setValue">setValue</a></li>
1322             
1323                 <li data-name="LuCI.ui.Dropdown#triggerValidation"><a href="LuCI.ui.Dropdown.html#triggerValidation">triggerValidation</a></li>
1324             
1325             </ul>
1326             <ul class="events itemMembers">
1327             
1328             </ul>
1329         </li>
1330     
1331         <li class="item" data-name="LuCI.ui.DynamicList">
1332             <span class="title">
1333                 <a href="LuCI.ui.DynamicList.html">LuCI.ui.DynamicList</a>
1334                 
1335             </span>
1336             <ul class="members itemMembers">
1337             
1338             </ul>
1339             <ul class="typedefs itemMembers">
1340             
1341             <span class="subtitle">Typedefs</span>
1342             
1343                 <li data-name="LuCI.ui.DynamicList.InitOptions"><a href="LuCI.ui.DynamicList.html#.InitOptions">InitOptions</a></li>
1344             
1345             </ul>
1346             <ul class="typedefs itemMembers">
1347             
1348             </ul>
1349             <ul class="methods itemMembers">
1350             
1351             <span class="subtitle">Methods</span>
1352             
1353                 <li data-name="LuCI.ui.DynamicList#addChoices"><a href="LuCI.ui.DynamicList.html#addChoices">addChoices</a></li>
1354             
1355                 <li data-name="LuCI.ui.DynamicList#clearChoices"><a href="LuCI.ui.DynamicList.html#clearChoices">clearChoices</a></li>
1356             
1357                 <li data-name="LuCI.ui.DynamicList#getValue"><a href="LuCI.ui.DynamicList.html#getValue">getValue</a></li>
1358             
1359                 <li data-name="LuCI.ui.DynamicList#isValid"><a href="LuCI.ui.DynamicList.html#isValid">isValid</a></li>
1360             
1361                 <li data-name="LuCI.ui.DynamicList#registerEvents"><a href="LuCI.ui.DynamicList.html#registerEvents">registerEvents</a></li>
1362             
1363                 <li data-name="LuCI.ui.DynamicList#render"><a href="LuCI.ui.DynamicList.html#render">render</a></li>
1364             
1365                 <li data-name="LuCI.ui.DynamicList#setChangeEvents"><a href="LuCI.ui.DynamicList.html#setChangeEvents">setChangeEvents</a></li>
1366             
1367                 <li data-name="LuCI.ui.DynamicList#setUpdateEvents"><a href="LuCI.ui.DynamicList.html#setUpdateEvents">setUpdateEvents</a></li>
1368             
1369                 <li data-name="LuCI.ui.DynamicList#setValue"><a href="LuCI.ui.DynamicList.html#setValue">setValue</a></li>
1370             
1371                 <li data-name="LuCI.ui.DynamicList#triggerValidation"><a href="LuCI.ui.DynamicList.html#triggerValidation">triggerValidation</a></li>
1372             
1373             </ul>
1374             <ul class="events itemMembers">
1375             
1376             </ul>
1377         </li>
1378     
1379         <li class="item" data-name="LuCI.ui.FileUpload">
1380             <span class="title">
1381                 <a href="LuCI.ui.FileUpload.html">LuCI.ui.FileUpload</a>
1382                 
1383             </span>
1384             <ul class="members itemMembers">
1385             
1386             </ul>
1387             <ul class="typedefs itemMembers">
1388             
1389             <span class="subtitle">Typedefs</span>
1390             
1391                 <li data-name="LuCI.ui.FileUpload.InitOptions"><a href="LuCI.ui.FileUpload.html#.InitOptions">InitOptions</a></li>
1392             
1393             </ul>
1394             <ul class="typedefs itemMembers">
1395             
1396             </ul>
1397             <ul class="methods itemMembers">
1398             
1399             <span class="subtitle">Methods</span>
1400             
1401                 <li data-name="LuCI.ui.FileUpload#getValue"><a href="LuCI.ui.FileUpload.html#getValue">getValue</a></li>
1402             
1403                 <li data-name="LuCI.ui.FileUpload#isValid"><a href="LuCI.ui.FileUpload.html#isValid">isValid</a></li>
1404             
1405                 <li data-name="LuCI.ui.FileUpload#registerEvents"><a href="LuCI.ui.FileUpload.html#registerEvents">registerEvents</a></li>
1406             
1407                 <li data-name="LuCI.ui.FileUpload#render"><a href="LuCI.ui.FileUpload.html#render">render</a></li>
1408             
1409                 <li data-name="LuCI.ui.FileUpload#setChangeEvents"><a href="LuCI.ui.FileUpload.html#setChangeEvents">setChangeEvents</a></li>
1410             
1411                 <li data-name="LuCI.ui.FileUpload#setUpdateEvents"><a href="LuCI.ui.FileUpload.html#setUpdateEvents">setUpdateEvents</a></li>
1412             
1413                 <li data-name="LuCI.ui.FileUpload#setValue"><a href="LuCI.ui.FileUpload.html#setValue">setValue</a></li>
1414             
1415                 <li data-name="LuCI.ui.FileUpload#triggerValidation"><a href="LuCI.ui.FileUpload.html#triggerValidation">triggerValidation</a></li>
1416             
1417             </ul>
1418             <ul class="events itemMembers">
1419             
1420             </ul>
1421         </li>
1422     
1423         <li class="item" data-name="LuCI.ui.Hiddenfield">
1424             <span class="title">
1425                 <a href="LuCI.ui.Hiddenfield.html">LuCI.ui.Hiddenfield</a>
1426                 
1427             </span>
1428             <ul class="members itemMembers">
1429             
1430             </ul>
1431             <ul class="typedefs itemMembers">
1432             
1433             </ul>
1434             <ul class="typedefs itemMembers">
1435             
1436             </ul>
1437             <ul class="methods itemMembers">
1438             
1439             <span class="subtitle">Methods</span>
1440             
1441                 <li data-name="LuCI.ui.Hiddenfield#getValue"><a href="LuCI.ui.Hiddenfield.html#getValue">getValue</a></li>
1442             
1443                 <li data-name="LuCI.ui.Hiddenfield#isValid"><a href="LuCI.ui.Hiddenfield.html#isValid">isValid</a></li>
1444             
1445                 <li data-name="LuCI.ui.Hiddenfield#registerEvents"><a href="LuCI.ui.Hiddenfield.html#registerEvents">registerEvents</a></li>
1446             
1447                 <li data-name="LuCI.ui.Hiddenfield#render"><a href="LuCI.ui.Hiddenfield.html#render">render</a></li>
1448             
1449                 <li data-name="LuCI.ui.Hiddenfield#setChangeEvents"><a href="LuCI.ui.Hiddenfield.html#setChangeEvents">setChangeEvents</a></li>
1450             
1451                 <li data-name="LuCI.ui.Hiddenfield#setUpdateEvents"><a href="LuCI.ui.Hiddenfield.html#setUpdateEvents">setUpdateEvents</a></li>
1452             
1453                 <li data-name="LuCI.ui.Hiddenfield#setValue"><a href="LuCI.ui.Hiddenfield.html#setValue">setValue</a></li>
1454             
1455                 <li data-name="LuCI.ui.Hiddenfield#triggerValidation"><a href="LuCI.ui.Hiddenfield.html#triggerValidation">triggerValidation</a></li>
1456             
1457             </ul>
1458             <ul class="events itemMembers">
1459             
1460             </ul>
1461         </li>
1462     
1463         <li class="item" data-name="LuCI.ui.Select">
1464             <span class="title">
1465                 <a href="LuCI.ui.Select.html">LuCI.ui.Select</a>
1466                 
1467             </span>
1468             <ul class="members itemMembers">
1469             
1470             </ul>
1471             <ul class="typedefs itemMembers">
1472             
1473             <span class="subtitle">Typedefs</span>
1474             
1475                 <li data-name="LuCI.ui.Select.InitOptions"><a href="LuCI.ui.Select.html#.InitOptions">InitOptions</a></li>
1476             
1477             </ul>
1478             <ul class="typedefs itemMembers">
1479             
1480             </ul>
1481             <ul class="methods itemMembers">
1482             
1483             <span class="subtitle">Methods</span>
1484             
1485                 <li data-name="LuCI.ui.Select#getValue"><a href="LuCI.ui.Select.html#getValue">getValue</a></li>
1486             
1487                 <li data-name="LuCI.ui.Select#isValid"><a href="LuCI.ui.Select.html#isValid">isValid</a></li>
1488             
1489                 <li data-name="LuCI.ui.Select#registerEvents"><a href="LuCI.ui.Select.html#registerEvents">registerEvents</a></li>
1490             
1491                 <li data-name="LuCI.ui.Select#render"><a href="LuCI.ui.Select.html#render">render</a></li>
1492             
1493                 <li data-name="LuCI.ui.Select#setChangeEvents"><a href="LuCI.ui.Select.html#setChangeEvents">setChangeEvents</a></li>
1494             
1495                 <li data-name="LuCI.ui.Select#setUpdateEvents"><a href="LuCI.ui.Select.html#setUpdateEvents">setUpdateEvents</a></li>
1496             
1497                 <li data-name="LuCI.ui.Select#setValue"><a href="LuCI.ui.Select.html#setValue">setValue</a></li>
1498             
1499                 <li data-name="LuCI.ui.Select#triggerValidation"><a href="LuCI.ui.Select.html#triggerValidation">triggerValidation</a></li>
1500             
1501             </ul>
1502             <ul class="events itemMembers">
1503             
1504             </ul>
1505         </li>
1506     
1507         <li class="item" data-name="LuCI.ui.tabs">
1508             <span class="title">
1509                 <a href="LuCI.ui.tabs.html">LuCI.ui.tabs</a>
1510                 
1511             </span>
1512             <ul class="members itemMembers">
1513             
1514             </ul>
1515             <ul class="typedefs itemMembers">
1516             
1517             </ul>
1518             <ul class="typedefs itemMembers">
1519             
1520             </ul>
1521             <ul class="methods itemMembers">
1522             
1523             <span class="subtitle">Methods</span>
1524             
1525                 <li data-name="LuCI.ui.tabs#initTabGroup"><a href="LuCI.ui.tabs.html#initTabGroup">initTabGroup</a></li>
1526             
1527                 <li data-name="LuCI.ui.tabs#isEmptyPane"><a href="LuCI.ui.tabs.html#isEmptyPane">isEmptyPane</a></li>
1528             
1529             </ul>
1530             <ul class="events itemMembers">
1531             
1532             </ul>
1533         </li>
1534     
1535         <li class="item" data-name="LuCI.ui.Textarea">
1536             <span class="title">
1537                 <a href="LuCI.ui.Textarea.html">LuCI.ui.Textarea</a>
1538                 
1539             </span>
1540             <ul class="members itemMembers">
1541             
1542             </ul>
1543             <ul class="typedefs itemMembers">
1544             
1545             <span class="subtitle">Typedefs</span>
1546             
1547                 <li data-name="LuCI.ui.Textarea.InitOptions"><a href="LuCI.ui.Textarea.html#.InitOptions">InitOptions</a></li>
1548             
1549             </ul>
1550             <ul class="typedefs itemMembers">
1551             
1552             </ul>
1553             <ul class="methods itemMembers">
1554             
1555             <span class="subtitle">Methods</span>
1556             
1557                 <li data-name="LuCI.ui.Textarea#getValue"><a href="LuCI.ui.Textarea.html#getValue">getValue</a></li>
1558             
1559                 <li data-name="LuCI.ui.Textarea#isValid"><a href="LuCI.ui.Textarea.html#isValid">isValid</a></li>
1560             
1561                 <li data-name="LuCI.ui.Textarea#registerEvents"><a href="LuCI.ui.Textarea.html#registerEvents">registerEvents</a></li>
1562             
1563                 <li data-name="LuCI.ui.Textarea#render"><a href="LuCI.ui.Textarea.html#render">render</a></li>
1564             
1565                 <li data-name="LuCI.ui.Textarea#setChangeEvents"><a href="LuCI.ui.Textarea.html#setChangeEvents">setChangeEvents</a></li>
1566             
1567                 <li data-name="LuCI.ui.Textarea#setUpdateEvents"><a href="LuCI.ui.Textarea.html#setUpdateEvents">setUpdateEvents</a></li>
1568             
1569                 <li data-name="LuCI.ui.Textarea#setValue"><a href="LuCI.ui.Textarea.html#setValue">setValue</a></li>
1570             
1571                 <li data-name="LuCI.ui.Textarea#triggerValidation"><a href="LuCI.ui.Textarea.html#triggerValidation">triggerValidation</a></li>
1572             
1573             </ul>
1574             <ul class="events itemMembers">
1575             
1576             </ul>
1577         </li>
1578     
1579         <li class="item" data-name="LuCI.ui.Textfield">
1580             <span class="title">
1581                 <a href="LuCI.ui.Textfield.html">LuCI.ui.Textfield</a>
1582                 
1583             </span>
1584             <ul class="members itemMembers">
1585             
1586             </ul>
1587             <ul class="typedefs itemMembers">
1588             
1589             <span class="subtitle">Typedefs</span>
1590             
1591                 <li data-name="LuCI.ui.Textfield.InitOptions"><a href="LuCI.ui.Textfield.html#.InitOptions">InitOptions</a></li>
1592             
1593             </ul>
1594             <ul class="typedefs itemMembers">
1595             
1596             </ul>
1597             <ul class="methods itemMembers">
1598             
1599             <span class="subtitle">Methods</span>
1600             
1601                 <li data-name="LuCI.ui.Textfield#getValue"><a href="LuCI.ui.Textfield.html#getValue">getValue</a></li>
1602             
1603                 <li data-name="LuCI.ui.Textfield#isValid"><a href="LuCI.ui.Textfield.html#isValid">isValid</a></li>
1604             
1605                 <li data-name="LuCI.ui.Textfield#registerEvents"><a href="LuCI.ui.Textfield.html#registerEvents">registerEvents</a></li>
1606             
1607                 <li data-name="LuCI.ui.Textfield#render"><a href="LuCI.ui.Textfield.html#render">render</a></li>
1608             
1609                 <li data-name="LuCI.ui.Textfield#setChangeEvents"><a href="LuCI.ui.Textfield.html#setChangeEvents">setChangeEvents</a></li>
1610             
1611                 <li data-name="LuCI.ui.Textfield#setUpdateEvents"><a href="LuCI.ui.Textfield.html#setUpdateEvents">setUpdateEvents</a></li>
1612             
1613                 <li data-name="LuCI.ui.Textfield#setValue"><a href="LuCI.ui.Textfield.html#setValue">setValue</a></li>
1614             
1615                 <li data-name="LuCI.ui.Textfield#triggerValidation"><a href="LuCI.ui.Textfield.html#triggerValidation">triggerValidation</a></li>
1616             
1617             </ul>
1618             <ul class="events itemMembers">
1619             
1620             </ul>
1621         </li>
1622     
1623         <li class="item" data-name="LuCI.view">
1624             <span class="title">
1625                 <a href="LuCI.view.html">LuCI.view</a>
1626                 
1627             </span>
1628             <ul class="members itemMembers">
1629             
1630             </ul>
1631             <ul class="typedefs itemMembers">
1632             
1633             </ul>
1634             <ul class="typedefs itemMembers">
1635             
1636             </ul>
1637             <ul class="methods itemMembers">
1638             
1639             <span class="subtitle">Methods</span>
1640             
1641                 <li data-name="LuCI.view#addFooter"><a href="LuCI.view.html#addFooter">addFooter</a></li>
1642             
1643                 <li data-name="LuCI.view#handleReset"><a href="LuCI.view.html#handleReset">handleReset</a></li>
1644             
1645                 <li data-name="LuCI.view#handleSave"><a href="LuCI.view.html#handleSave">handleSave</a></li>
1646             
1647                 <li data-name="LuCI.view#handleSaveApply"><a href="LuCI.view.html#handleSaveApply">handleSaveApply</a></li>
1648             
1649                 <li data-name="LuCI.view#load"><a href="LuCI.view.html#load">load</a></li>
1650             
1651                 <li data-name="LuCI.view#render"><a href="LuCI.view.html#render">render</a></li>
1652             
1653             </ul>
1654             <ul class="events itemMembers">
1655             
1656             </ul>
1657         </li>
1658     
1659         <li class="item" data-name="LuCI.xhr">
1660             <span class="title">
1661                 <a href="LuCI.xhr.html">LuCI.xhr</a>
1662                 
1663             </span>
1664             <ul class="members itemMembers">
1665             
1666             </ul>
1667             <ul class="typedefs itemMembers">
1668             
1669             </ul>
1670             <ul class="typedefs itemMembers">
1671             
1672             </ul>
1673             <ul class="methods itemMembers">
1674             
1675             <span class="subtitle">Methods</span>
1676             
1677                 <li data-name="LuCI.xhr#abort"><a href="LuCI.xhr.html#abort">abort</a></li>
1678             
1679                 <li data-name="LuCI.xhr#busy"><a href="LuCI.xhr.html#busy">busy</a></li>
1680             
1681                 <li data-name="LuCI.xhr#cancel"><a href="LuCI.xhr.html#cancel">cancel</a></li>
1682             
1683                 <li data-name="LuCI.xhr#get"><a href="LuCI.xhr.html#get">get</a></li>
1684             
1685                 <li data-name="LuCI.xhr#post"><a href="LuCI.xhr.html#post">post</a></li>
1686             
1687                 <li data-name="LuCI.xhr#send_form"><a href="LuCI.xhr.html#send_form">send_form</a></li>
1688             
1689             </ul>
1690             <ul class="events itemMembers">
1691             
1692             </ul>
1693         </li>
1694     
1695     </ul>
1696 </div>
1697     <div class="main">
1698         <h1 class="page-title" data-filename="network.js.html">Source: network.js</h1>
1699         
1700
1701
1702     
1703     <section>
1704         <article>
1705             <pre id="source-code" class="prettyprint source "><code>'use strict';
1706 'require uci';
1707 'require rpc';
1708 'require validation';
1709 'require baseclass';
1710 'require firewall';
1711
1712 var proto_errors = {
1713         CONNECT_FAILED:                 _('Connection attempt failed'),
1714         INVALID_ADDRESS:                _('IP address is invalid'),
1715         INVALID_GATEWAY:                _('Gateway address is invalid'),
1716         INVALID_LOCAL_ADDRESS:  _('Local IP address is invalid'),
1717         MISSING_ADDRESS:                _('IP address is missing'),
1718         MISSING_PEER_ADDRESS:   _('Peer address is missing'),
1719         NO_DEVICE:                              _('Network device is not present'),
1720         NO_IFACE:                               _('Unable to determine device name'),
1721         NO_IFNAME:                              _('Unable to determine device name'),
1722         NO_WAN_ADDRESS:                 _('Unable to determine external IP address'),
1723         NO_WAN_LINK:                    _('Unable to determine upstream interface'),
1724         PEER_RESOLVE_FAIL:              _('Unable to resolve peer host name'),
1725         PIN_FAILED:                             _('PIN code rejected')
1726 };
1727
1728 var iface_patterns_ignore = [
1729         /^wmaster\d+/,
1730         /^wifi\d+/,
1731         /^hwsim\d+/,
1732         /^imq\d+/,
1733         /^ifb\d+/,
1734         /^mon\.wlan\d+/,
1735         /^sit\d+/,
1736         /^gre\d+/,
1737         /^gretap\d+/,
1738         /^ip6gre\d+/,
1739         /^ip6tnl\d+/,
1740         /^tunl\d+/,
1741         /^lo$/
1742 ];
1743
1744 var iface_patterns_wireless = [
1745         /^wlan\d+/,
1746         /^wl\d+/,
1747         /^ath\d+/,
1748         /^\w+\.network\d+/
1749 ];
1750
1751 var iface_patterns_virtual = [ ];
1752
1753 var callLuciNetworkDevices = rpc.declare({
1754         object: 'luci-rpc',
1755         method: 'getNetworkDevices',
1756         expect: { '': {} }
1757 });
1758
1759 var callLuciWirelessDevices = rpc.declare({
1760         object: 'luci-rpc',
1761         method: 'getWirelessDevices',
1762         expect: { '': {} }
1763 });
1764
1765 var callLuciBoardJSON = rpc.declare({
1766         object: 'luci-rpc',
1767         method: 'getBoardJSON'
1768 });
1769
1770 var callLuciHostHints = rpc.declare({
1771         object: 'luci-rpc',
1772         method: 'getHostHints',
1773         expect: { '': {} }
1774 });
1775
1776 var callIwinfoAssoclist = rpc.declare({
1777         object: 'iwinfo',
1778         method: 'assoclist',
1779         params: [ 'device', 'mac' ],
1780         expect: { results: [] }
1781 });
1782
1783 var callIwinfoScan = rpc.declare({
1784         object: 'iwinfo',
1785         method: 'scan',
1786         params: [ 'device' ],
1787         nobatch: true,
1788         expect: { results: [] }
1789 });
1790
1791 var callNetworkInterfaceDump = rpc.declare({
1792         object: 'network.interface',
1793         method: 'dump',
1794         expect: { 'interface': [] }
1795 });
1796
1797 var callNetworkProtoHandlers = rpc.declare({
1798         object: 'network',
1799         method: 'get_proto_handlers',
1800         expect: { '': {} }
1801 });
1802
1803 var _init = null,
1804     _state = null,
1805     _protocols = {},
1806     _protospecs = {};
1807
1808 function getProtocolHandlers(cache) {
1809         return callNetworkProtoHandlers().then(function(protos) {
1810                 /* Register "none" protocol */
1811                 if (!protos.hasOwnProperty('none'))
1812                         Object.assign(protos, { none: { no_device: false } });
1813
1814                 /* Hack: emulate relayd protocol */
1815                 if (!protos.hasOwnProperty('relay'))
1816                         Object.assign(protos, { relay: { no_device: true } });
1817
1818                 Object.assign(_protospecs, protos);
1819
1820                 return Promise.all(Object.keys(protos).map(function(p) {
1821                         return Promise.resolve(L.require('protocol.%s'.format(p))).catch(function(err) {
1822                                 if (L.isObject(err) &amp;&amp; err.name != 'NetworkError')
1823                                         L.error(err);
1824                         });
1825                 })).then(function() {
1826                         return protos;
1827                 });
1828         }).catch(function() {
1829                 return {};
1830         });
1831 }
1832
1833 function getWifiStateBySid(sid) {
1834         var s = uci.get('wireless', sid);
1835
1836         if (s != null &amp;&amp; s['.type'] == 'wifi-iface') {
1837                 for (var radioname in _state.radios) {
1838                         for (var i = 0; i &lt; _state.radios[radioname].interfaces.length; i++) {
1839                                 var netstate = _state.radios[radioname].interfaces[i];
1840
1841                                 if (typeof(netstate.section) != 'string')
1842                                         continue;
1843
1844                                 var s2 = uci.get('wireless', netstate.section);
1845
1846                                 if (s2 != null &amp;&amp; s['.type'] == s2['.type'] &amp;&amp; s['.name'] == s2['.name']) {
1847                                         if (s2['.anonymous'] == false &amp;&amp; netstate.section.charAt(0) == '@')
1848                                                 return null;
1849
1850                                         return [ radioname, _state.radios[radioname], netstate ];
1851                                 }
1852                         }
1853                 }
1854         }
1855
1856         return null;
1857 }
1858
1859 function getWifiStateByIfname(ifname) {
1860         for (var radioname in _state.radios) {
1861                 for (var i = 0; i &lt; _state.radios[radioname].interfaces.length; i++) {
1862                         var netstate = _state.radios[radioname].interfaces[i];
1863
1864                         if (typeof(netstate.ifname) != 'string')
1865                                 continue;
1866
1867                         if (netstate.ifname == ifname)
1868                                 return [ radioname, _state.radios[radioname], netstate ];
1869                 }
1870         }
1871
1872         return null;
1873 }
1874
1875 function isWifiIfname(ifname) {
1876         for (var i = 0; i &lt; iface_patterns_wireless.length; i++)
1877                 if (iface_patterns_wireless[i].test(ifname))
1878                         return true;
1879
1880         return false;
1881 }
1882
1883 function getWifiSidByNetid(netid) {
1884         var m = /^(\w+)\.network(\d+)$/.exec(netid);
1885         if (m) {
1886                 var sections = uci.sections('wireless', 'wifi-iface');
1887                 for (var i = 0, n = 0; i &lt; sections.length; i++) {
1888                         if (sections[i].device != m[1])
1889                                 continue;
1890
1891                         if (++n == +m[2])
1892                                 return sections[i]['.name'];
1893                 }
1894         }
1895
1896         return null;
1897 }
1898
1899 function getWifiSidByIfname(ifname) {
1900         var sid = getWifiSidByNetid(ifname);
1901
1902         if (sid != null)
1903                 return sid;
1904
1905         var res = getWifiStateByIfname(ifname);
1906
1907         if (res != null &amp;&amp; L.isObject(res[2]) &amp;&amp; typeof(res[2].section) == 'string')
1908                 return res[2].section;
1909
1910         return null;
1911 }
1912
1913 function getWifiNetidBySid(sid) {
1914         var s = uci.get('wireless', sid);
1915         if (s != null &amp;&amp; s['.type'] == 'wifi-iface') {
1916                 var radioname = s.device;
1917                 if (typeof(s.device) == 'string') {
1918                         var i = 0, netid = null, sections = uci.sections('wireless', 'wifi-iface');
1919                         for (var i = 0, n = 0; i &lt; sections.length; i++) {
1920                                 if (sections[i].device != s.device)
1921                                         continue;
1922
1923                                 n++;
1924
1925                                 if (sections[i]['.name'] != s['.name'])
1926                                         continue;
1927
1928                                 return [ '%s.network%d'.format(s.device, n), s.device ];
1929                         }
1930
1931                 }
1932         }
1933
1934         return null;
1935 }
1936
1937 function getWifiNetidByNetname(name) {
1938         var sections = uci.sections('wireless', 'wifi-iface');
1939         for (var i = 0; i &lt; sections.length; i++) {
1940                 if (typeof(sections[i].network) != 'string')
1941                         continue;
1942
1943                 var nets = sections[i].network.split(/\s+/);
1944                 for (var j = 0; j &lt; nets.length; j++) {
1945                         if (nets[j] != name)
1946                                 continue;
1947
1948                         return getWifiNetidBySid(sections[i]['.name']);
1949                 }
1950         }
1951
1952         return null;
1953 }
1954
1955 function isVirtualIfname(ifname) {
1956         for (var i = 0; i &lt; iface_patterns_virtual.length; i++)
1957                 if (iface_patterns_virtual[i].test(ifname))
1958                         return true;
1959
1960         return false;
1961 }
1962
1963 function isIgnoredIfname(ifname) {
1964         for (var i = 0; i &lt; iface_patterns_ignore.length; i++)
1965                 if (iface_patterns_ignore[i].test(ifname))
1966                         return true;
1967
1968         return false;
1969 }
1970
1971 function appendValue(config, section, option, value) {
1972         var values = uci.get(config, section, option),
1973             isArray = Array.isArray(values),
1974             rv = false;
1975
1976         if (isArray == false)
1977                 values = L.toArray(values);
1978
1979         if (values.indexOf(value) == -1) {
1980                 values.push(value);
1981                 rv = true;
1982         }
1983
1984         uci.set(config, section, option, isArray ? values : values.join(' '));
1985
1986         return rv;
1987 }
1988
1989 function removeValue(config, section, option, value) {
1990         var values = uci.get(config, section, option),
1991             isArray = Array.isArray(values),
1992             rv = false;
1993
1994         if (isArray == false)
1995                 values = L.toArray(values);
1996
1997         for (var i = values.length - 1; i >= 0; i--) {
1998                 if (values[i] == value) {
1999                         values.splice(i, 1);
2000                         rv = true;
2001                 }
2002         }
2003
2004         if (values.length > 0)
2005                 uci.set(config, section, option, isArray ? values : values.join(' '));
2006         else
2007                 uci.unset(config, section, option);
2008
2009         return rv;
2010 }
2011
2012 function prefixToMask(bits, v6) {
2013         var w = v6 ? 128 : 32,
2014             m = [];
2015
2016         if (bits > w)
2017                 return null;
2018
2019         for (var i = 0; i &lt; w / 16; i++) {
2020                 var b = Math.min(16, bits);
2021                 m.push((0xffff &lt;&lt; (16 - b)) &amp; 0xffff);
2022                 bits -= b;
2023         }
2024
2025         if (v6)
2026                 return String.prototype.format.apply('%x:%x:%x:%x:%x:%x:%x:%x', m).replace(/:0(?::0)+$/, '::');
2027         else
2028                 return '%d.%d.%d.%d'.format(m[0] >>> 8, m[0] &amp; 0xff, m[1] >>> 8, m[1] &amp; 0xff);
2029 }
2030
2031 function maskToPrefix(mask, v6) {
2032         var m = v6 ? validation.parseIPv6(mask) : validation.parseIPv4(mask);
2033
2034         if (!m)
2035                 return null;
2036
2037         var bits = 0;
2038
2039         for (var i = 0, z = false; i &lt; m.length; i++) {
2040                 z = z || !m[i];
2041
2042                 while (!z &amp;&amp; (m[i] &amp; (v6 ? 0x8000 : 0x80))) {
2043                         m[i] = (m[i] &lt;&lt; 1) &amp; (v6 ? 0xffff : 0xff);
2044                         bits++;
2045                 }
2046
2047                 if (m[i])
2048                         return null;
2049         }
2050
2051         return bits;
2052 }
2053
2054 function initNetworkState(refresh) {
2055         if (_state == null || refresh) {
2056                 _init = _init || Promise.all([
2057                         L.resolveDefault(callNetworkInterfaceDump(), []),
2058                         L.resolveDefault(callLuciBoardJSON(), {}),
2059                         L.resolveDefault(callLuciNetworkDevices(), {}),
2060                         L.resolveDefault(callLuciWirelessDevices(), {}),
2061                         L.resolveDefault(callLuciHostHints(), {}),
2062                         getProtocolHandlers(),
2063                         uci.load(['network', 'wireless', 'luci'])
2064                 ]).then(function(data) {
2065                         var netifd_ifaces = data[0],
2066                             board_json    = data[1],
2067                             luci_devs     = data[2];
2068
2069                         var s = {
2070                                 isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {},
2071                                 ifaces: netifd_ifaces, radios: data[3], hosts: data[4],
2072                                 netdevs: {}, bridges: {}, switches: {}, hostapd: {}
2073                         };
2074
2075                         for (var name in luci_devs) {
2076                                 var dev = luci_devs[name];
2077
2078                                 if (isVirtualIfname(name))
2079                                         s.isTunnel[name] = true;
2080
2081                                 if (!s.isTunnel[name] &amp;&amp; isIgnoredIfname(name))
2082                                         continue;
2083
2084                                 s.netdevs[name] = s.netdevs[name] || {
2085                                         idx:      dev.ifindex,
2086                                         name:     name,
2087                                         rawname:  name,
2088                                         flags:    dev.flags,
2089                                         stats:    dev.stats,
2090                                         macaddr:  dev.mac,
2091                                         type:     dev.type,
2092                                         mtu:      dev.mtu,
2093                                         qlen:     dev.qlen,
2094                                         wireless: dev.wireless,
2095                                         ipaddrs:  [],
2096                                         ip6addrs: []
2097                                 };
2098
2099                                 if (Array.isArray(dev.ipaddrs))
2100                                         for (var i = 0; i &lt; dev.ipaddrs.length; i++)
2101                                                 s.netdevs[name].ipaddrs.push(dev.ipaddrs[i].address + '/' + dev.ipaddrs[i].netmask);
2102
2103                                 if (Array.isArray(dev.ip6addrs))
2104                                         for (var i = 0; i &lt; dev.ip6addrs.length; i++)
2105                                                 s.netdevs[name].ip6addrs.push(dev.ip6addrs[i].address + '/' + dev.ip6addrs[i].netmask);
2106                         }
2107
2108                         for (var name in luci_devs) {
2109                                 var dev = luci_devs[name];
2110
2111                                 if (!dev.bridge)
2112                                         continue;
2113
2114                                 var b = {
2115                                         name:    name,
2116                                         id:      dev.id,
2117                                         stp:     dev.stp,
2118                                         ifnames: []
2119                                 };
2120
2121                                 for (var i = 0; dev.ports &amp;&amp; i &lt; dev.ports.length; i++) {
2122                                         var subdev = s.netdevs[dev.ports[i]];
2123
2124                                         if (subdev == null)
2125                                                 continue;
2126
2127                                         b.ifnames.push(subdev);
2128                                         subdev.bridge = b;
2129                                 }
2130
2131                                 s.bridges[name] = b;
2132                                 s.isBridge[name] = true;
2133                         }
2134
2135                         if (L.isObject(board_json.switch)) {
2136                                 for (var switchname in board_json.switch) {
2137                                         var layout = board_json.switch[switchname],
2138                                             netdevs = {},
2139                                             nports = {},
2140                                             ports = [],
2141                                             pnum = null,
2142                                             role = null;
2143
2144                                         if (L.isObject(layout) &amp;&amp; Array.isArray(layout.ports)) {
2145                                                 for (var i = 0, port; (port = layout.ports[i]) != null; i++) {
2146                                                         if (typeof(port) == 'object' &amp;&amp; typeof(port.num) == 'number' &amp;&amp;
2147                                                                 (typeof(port.role) == 'string' || typeof(port.device) == 'string')) {
2148                                                                 var spec = {
2149                                                                         num:   port.num,
2150                                                                         role:  port.role || 'cpu',
2151                                                                         index: (port.index != null) ? port.index : port.num
2152                                                                 };
2153
2154                                                                 if (port.device != null) {
2155                                                                         spec.device = port.device;
2156                                                                         spec.tagged = spec.need_tag;
2157                                                                         netdevs[port.num] = port.device;
2158                                                                 }
2159
2160                                                                 ports.push(spec);
2161
2162                                                                 if (port.role != null)
2163                                                                         nports[port.role] = (nports[port.role] || 0) + 1;
2164                                                         }
2165                                                 }
2166
2167                                                 ports.sort(function(a, b) {
2168                                                         if (a.role != b.role)
2169                                                                 return (a.role &lt; b.role) ? -1 : 1;
2170
2171                                                         return (a.index - b.index);
2172                                                 });
2173
2174                                                 for (var i = 0, port; (port = ports[i]) != null; i++) {
2175                                                         if (port.role != role) {
2176                                                                 role = port.role;
2177                                                                 pnum = 1;
2178                                                         }
2179
2180                                                         if (role == 'cpu')
2181                                                                 port.label = 'CPU (%s)'.format(port.device);
2182                                                         else if (nports[role] > 1)
2183                                                                 port.label = '%s %d'.format(role.toUpperCase(), pnum++);
2184                                                         else
2185                                                                 port.label = role.toUpperCase();
2186
2187                                                         delete port.role;
2188                                                         delete port.index;
2189                                                 }
2190
2191                                                 s.switches[switchname] = {
2192                                                         ports: ports,
2193                                                         netdevs: netdevs
2194                                                 };
2195                                         }
2196                                 }
2197                         }
2198
2199                         if (L.isObject(board_json.dsl) &amp;&amp; L.isObject(board_json.dsl.modem)) {
2200                                 s.hasDSLModem = board_json.dsl.modem;
2201                         }
2202
2203                         _init = null;
2204
2205                         var objects = [];
2206
2207                         if (L.isObject(s.radios))
2208                                 for (var radio in s.radios)
2209                                         if (L.isObject(s.radios[radio]) &amp;&amp; Array.isArray(s.radios[radio].interfaces))
2210                                                 for (var i = 0; i &lt; s.radios[radio].interfaces.length; i++)
2211                                                         if (L.isObject(s.radios[radio].interfaces[i]) &amp;&amp; s.radios[radio].interfaces[i].ifname)
2212                                                                 objects.push('hostapd.%s'.format(s.radios[radio].interfaces[i].ifname));
2213
2214                         return (objects.length ? L.resolveDefault(rpc.list.apply(rpc, objects), {}) : Promise.resolve({})).then(function(res) {
2215                                 for (var k in res) {
2216                                         var m = k.match(/^hostapd\.(.+)$/);
2217                                         if (m)
2218                                                 s.hostapd[m[1]] = res[k];
2219                                 }
2220
2221                                 return (_state = s);
2222                         });
2223                 });
2224         }
2225
2226         return (_state != null ? Promise.resolve(_state) : _init);
2227 }
2228
2229 function ifnameOf(obj) {
2230         if (obj instanceof Protocol)
2231                 return obj.getIfname();
2232         else if (obj instanceof Device)
2233                 return obj.getName();
2234         else if (obj instanceof WifiDevice)
2235                 return obj.getName();
2236         else if (obj instanceof WifiNetwork)
2237                 return obj.getIfname();
2238         else if (typeof(obj) == 'string')
2239                 return obj.replace(/:.+$/, '');
2240
2241         return null;
2242 }
2243
2244 function networkSort(a, b) {
2245         return a.getName() > b.getName();
2246 }
2247
2248 function deviceSort(a, b) {
2249         var typeWeigth = { wifi: 2, alias: 3 },
2250         weightA = typeWeigth[a.getType()] || 1,
2251         weightB = typeWeigth[b.getType()] || 1;
2252
2253     if (weightA != weightB)
2254         return weightA - weightB;
2255
2256         return a.getName() > b.getName();
2257 }
2258
2259 function formatWifiEncryption(enc) {
2260         if (!L.isObject(enc))
2261                 return null;
2262
2263         if (!enc.enabled)
2264                 return 'None';
2265
2266         var ciphers = Array.isArray(enc.ciphers)
2267                 ? enc.ciphers.map(function(c) { return c.toUpperCase() }) : [ 'NONE' ];
2268
2269         if (Array.isArray(enc.wep)) {
2270                 var has_open = false,
2271                     has_shared = false;
2272
2273                 for (var i = 0; i &lt; enc.wep.length; i++)
2274                         if (enc.wep[i] == 'open')
2275                                 has_open = true;
2276                         else if (enc.wep[i] == 'shared')
2277                                 has_shared = true;
2278
2279                 if (has_open &amp;&amp; has_shared)
2280                         return 'WEP Open/Shared (%s)'.format(ciphers.join(', '));
2281                 else if (has_open)
2282                         return 'WEP Open System (%s)'.format(ciphers.join(', '));
2283                 else if (has_shared)
2284                         return 'WEP Shared Auth (%s)'.format(ciphers.join(', '));
2285
2286                 return 'WEP';
2287         }
2288
2289         if (Array.isArray(enc.wpa)) {
2290                 var versions = [],
2291                     suites = Array.isArray(enc.authentication)
2292                         ? enc.authentication.map(function(a) { return a.toUpperCase() }) : [ 'NONE' ];
2293
2294                 for (var i = 0; i &lt; enc.wpa.length; i++)
2295                         switch (enc.wpa[i]) {
2296                         case 1:
2297                                 versions.push('WPA');
2298                                 break;
2299
2300                         default:
2301                                 versions.push('WPA%d'.format(enc.wpa[i]));
2302                                 break;
2303                         }
2304
2305                 if (versions.length > 1)
2306                         return 'mixed %s %s (%s)'.format(versions.join('/'), suites.join(', '), ciphers.join(', '));
2307
2308                 return '%s %s (%s)'.format(versions[0], suites.join(', '), ciphers.join(', '));
2309         }
2310
2311         return 'Unknown';
2312 }
2313
2314 function enumerateNetworks() {
2315         var uciInterfaces = uci.sections('network', 'interface'),
2316             networks = {};
2317
2318         for (var i = 0; i &lt; uciInterfaces.length; i++)
2319                 networks[uciInterfaces[i]['.name']] = this.instantiateNetwork(uciInterfaces[i]['.name']);
2320
2321         for (var i = 0; i &lt; _state.ifaces.length; i++)
2322                 if (networks[_state.ifaces[i].interface] == null)
2323                         networks[_state.ifaces[i].interface] =
2324                                 this.instantiateNetwork(_state.ifaces[i].interface, _state.ifaces[i].proto);
2325
2326         var rv = [];
2327
2328         for (var network in networks)
2329                 if (networks.hasOwnProperty(network))
2330                         rv.push(networks[network]);
2331
2332         rv.sort(networkSort);
2333
2334         return rv;
2335 }
2336
2337
2338 var Hosts, Network, Protocol, Device, WifiDevice, WifiNetwork;
2339
2340 /**
2341  * @class network
2342  * @memberof LuCI
2343  * @hideconstructor
2344  * @classdesc
2345  *
2346  * The `LuCI.network` class combines data from multiple `ubus` apis to
2347  * provide an abstraction of the current network configuration state.
2348  *
2349  * It provides methods to enumerate interfaces and devices, to query
2350  * current configuration details and to manipulate settings.
2351  */
2352 Network = baseclass.extend(/** @lends LuCI.network.prototype */ {
2353         /**
2354          * Converts the given prefix size in bits to a netmask.
2355          *
2356          * @method
2357          *
2358          * @param {number} bits
2359          * The prefix size in bits.
2360          *
2361          * @param {boolean} [v6=false]
2362          * Whether to convert the bits value into an IPv4 netmask (`false`) or
2363          * an IPv6 netmask (`true`).
2364          *
2365          * @returns {null|string}
2366          * Returns a string containing the netmask corresponding to the bit count
2367          * or `null` when the given amount of bits exceeds the maximum possible
2368          * value of `32` for IPv4 or `128` for IPv6.
2369          */
2370         prefixToMask: prefixToMask,
2371
2372         /**
2373          * Converts the given netmask to a prefix size in bits.
2374          *
2375          * @method
2376          *
2377          * @param {string} netmask
2378          * The netmask to convert into a bit count.
2379          *
2380          * @param {boolean} [v6=false]
2381          * Whether to parse the given netmask as IPv4 (`false`) or IPv6 (`true`)
2382          * address.
2383          *
2384          * @returns {null|number}
2385          * Returns the number of prefix bits contained in the netmask or `null`
2386          * if the given netmask value was invalid.
2387          */
2388         maskToPrefix: maskToPrefix,
2389
2390         /**
2391          * An encryption entry describes active wireless encryption settings
2392          * such as the used key management protocols, active ciphers and
2393          * protocol versions.
2394          *
2395          * @typedef {Object&lt;string, boolean|Array&lt;number|string>>} LuCI.network.WifiEncryption
2396          * @memberof LuCI.network
2397          *
2398          * @property {boolean} enabled
2399          * Specifies whether any kind of encryption, such as `WEP` or `WPA` is
2400          * enabled. If set to `false`, then no encryption is active and the
2401          * corresponding network is open.
2402          *
2403          * @property {string[]} [wep]
2404          * When the `wep` property exists, the network uses WEP encryption.
2405          * In this case, the property is set to an array of active WEP modes
2406          * which might be either `open`, `shared` or both.
2407          *
2408          * @property {number[]} [wpa]
2409          * When the `wpa` property exists, the network uses WPA security.
2410          * In this case, the property is set to an array containing the WPA
2411          * protocol versions used, e.g. `[ 1, 2 ]` for WPA/WPA2 mixed mode or
2412          * `[ 3 ]` for WPA3-SAE.
2413          *
2414          * @property {string[]} [authentication]
2415          * The `authentication` property only applies to WPA encryption and
2416          * is defined when the `wpa` property is set as well. It points to
2417          * an array of active authentication suites used by the network, e.g.
2418          * `[ "psk" ]` for a WPA(2)-PSK network or `[ "psk", "sae" ]` for
2419          * mixed WPA2-PSK/WPA3-SAE encryption.
2420          *
2421          * @property {string[]} [ciphers]
2422          * If either WEP or WPA encryption is active, then the `ciphers`
2423          * property will be set to an array describing the active encryption
2424          * ciphers used by the network, e.g. `[ "tkip", "ccmp" ]` for a
2425          * WPA/WPA2-PSK mixed network or `[ "wep-40", "wep-104" ]` for an
2426          * WEP network.
2427          */
2428
2429         /**
2430          * Converts a given {@link LuCI.network.WifiEncryption encryption entry}
2431          * into a human readable string such as `mixed WPA/WPA2 PSK (TKIP, CCMP)`
2432          * or `WPA3 SAE (CCMP)`.
2433          *
2434          * @method
2435          *
2436          * @param {LuCI.network.WifiEncryption} encryption
2437          * The wireless encryption entry to convert.
2438          *
2439          * @returns {null|string}
2440          * Returns the description string for the given encryption entry or
2441          * `null` if the given entry was invalid.
2442          */
2443         formatWifiEncryption: formatWifiEncryption,
2444
2445         /**
2446          * Flushes the local network state cache and fetches updated information
2447          * from the remote `ubus` apis.
2448          *
2449          * @returns {Promise&lt;Object>}
2450          * Returns a promise resolving to the internal network state object.
2451          */
2452         flushCache: function() {
2453                 initNetworkState(true);
2454                 return _init;
2455         },
2456
2457         /**
2458          * Instantiates the given {@link LuCI.network.Protocol Protocol} backend,
2459          * optionally using the given network name.
2460          *
2461          * @param {string} protoname
2462          * The protocol backend to use, e.g. `static` or `dhcp`.
2463          *
2464          * @param {string} [netname=__dummy__]
2465          * The network name to use for the instantiated protocol. This should be
2466          * usually set to one of the interfaces described in /etc/config/network
2467          * but it is allowed to omit it, e.g. to query protocol capabilities
2468          * without the need for an existing interface.
2469          *
2470          * @returns {null|LuCI.network.Protocol}
2471          * Returns the instantiated protocol backend class or `null` if the given
2472          * protocol isn't known.
2473          */
2474         getProtocol: function(protoname, netname) {
2475                 var v = _protocols[protoname];
2476                 if (v != null)
2477                         return new v(netname || '__dummy__');
2478
2479                 return null;
2480         },
2481
2482         /**
2483          * Obtains instances of all known {@link LuCI.network.Protocol Protocol}
2484          * backend classes.
2485          *
2486          * @returns {Array&lt;LuCI.network.Protocol>}
2487          * Returns an array of protocol class instances.
2488          */
2489         getProtocols: function() {
2490                 var rv = [];
2491
2492                 for (var protoname in _protocols)
2493                         rv.push(new _protocols[protoname]('__dummy__'));
2494
2495                 return rv;
2496         },
2497
2498         /**
2499          * Registers a new {@link LuCI.network.Protocol Protocol} subclass
2500          * with the given methods and returns the resulting subclass value.
2501          *
2502          * This functions internally calls
2503          * {@link LuCI.Class.extend Class.extend()} on the `Network.Protocol`
2504          * base class.
2505          *
2506          * @param {string} protoname
2507          * The name of the new protocol to register.
2508          *
2509          * @param {Object&lt;string, *>} methods
2510          * The member methods and values of the new `Protocol` subclass to
2511          * be passed to {@link LuCI.Class.extend Class.extend()}.
2512          *
2513          * @returns {LuCI.network.Protocol}
2514          * Returns the new `Protocol` subclass.
2515          */
2516         registerProtocol: function(protoname, methods) {
2517                 var spec = L.isObject(_protospecs) ? _protospecs[protoname] : null;
2518                 var proto = Protocol.extend(Object.assign({
2519                         getI18n: function() {
2520                                 return protoname;
2521                         },
2522
2523                         isFloating: function() {
2524                                 return false;
2525                         },
2526
2527                         isVirtual: function() {
2528                                 return (L.isObject(spec) &amp;&amp; spec.no_device == true);
2529                         },
2530
2531                         renderFormOptions: function(section) {
2532
2533                         }
2534                 }, methods, {
2535                         __init__: function(name) {
2536                                 this.sid = name;
2537                         },
2538
2539                         getProtocol: function() {
2540                                 return protoname;
2541                         }
2542                 }));
2543
2544                 _protocols[protoname] = proto;
2545
2546                 return proto;
2547         },
2548
2549         /**
2550          * Registers a new regular expression pattern to recognize
2551          * virtual interfaces.
2552          *
2553          * @param {RegExp} pat
2554          * A `RegExp` instance to match a virtual interface name
2555          * such as `6in4-wan` or `tun0`.
2556          */
2557         registerPatternVirtual: function(pat) {
2558                 iface_patterns_virtual.push(pat);
2559         },
2560
2561         /**
2562          * Registers a new human readable translation string for a `Protocol`
2563          * error code.
2564          *
2565          * @param {string} code
2566          * The `ubus` protocol error code to register a translation for, e.g.
2567          * `NO_DEVICE`.
2568          *
2569          * @param {string} message
2570          * The message to use as translation for the given protocol error code.
2571          *
2572          * @returns {boolean}
2573          * Returns `true` if the error code description has been added or `false`
2574          * if either the arguments were invalid or if there already was a
2575          * description for the given code.
2576          */
2577         registerErrorCode: function(code, message) {
2578                 if (typeof(code) == 'string' &amp;&amp;
2579                     typeof(message) == 'string' &amp;&amp;
2580                     !proto_errors.hasOwnProperty(code)) {
2581                         proto_errors[code] = message;
2582                         return true;
2583                 }
2584
2585                 return false;
2586         },
2587
2588         /**
2589          * Adds a new network of the given name and update it with the given
2590          * uci option values.
2591          *
2592          * If a network with the given name already exist but is empty, then
2593          * this function will update its option, otherwise it will do nothing.
2594          *
2595          * @param {string} name
2596          * The name of the network to add. Must be in the format `[a-zA-Z0-9_]+`.
2597          *
2598          * @param {Object&lt;string, string|string[]>} [options]
2599          * An object of uci option values to set on the new network or to
2600          * update in an existing, empty network.
2601          *
2602          * @returns {Promise&lt;null|LuCI.network.Protocol>}
2603          * Returns a promise resolving to the `Protocol` subclass instance
2604          * describing the added network or resolving to `null` if the name
2605          * was invalid or if a non-empty network of the given name already
2606          * existed.
2607          */
2608         addNetwork: function(name, options) {
2609                 return this.getNetwork(name).then(L.bind(function(existingNetwork) {
2610                         if (name != null &amp;&amp; /^[a-zA-Z0-9_]+$/.test(name) &amp;&amp; existingNetwork == null) {
2611                                 var sid = uci.add('network', 'interface', name);
2612
2613                                 if (sid != null) {
2614                                         if (L.isObject(options))
2615                                                 for (var key in options)
2616                                                         if (options.hasOwnProperty(key))
2617                                                                 uci.set('network', sid, key, options[key]);
2618
2619                                         return this.instantiateNetwork(sid);
2620                                 }
2621                         }
2622                         else if (existingNetwork != null &amp;&amp; existingNetwork.isEmpty()) {
2623                                 if (L.isObject(options))
2624                                         for (var key in options)
2625                                                 if (options.hasOwnProperty(key))
2626                                                         existingNetwork.set(key, options[key]);
2627
2628                                 return existingNetwork;
2629                         }
2630                 }, this));
2631         },
2632
2633         /**
2634          * Get a {@link LuCI.network.Protocol Protocol} instance describing
2635          * the network with the given name.
2636          *
2637          * @param {string} name
2638          * The logical interface name of the network get, e.g. `lan` or `wan`.
2639          *
2640          * @returns {Promise&lt;null|LuCI.network.Protocol>}
2641          * Returns a promise resolving to a
2642          * {@link LuCI.network.Protocol Protocol} subclass instance describing
2643          * the network or `null` if the network did not exist.
2644          */
2645         getNetwork: function(name) {
2646                 return initNetworkState().then(L.bind(function() {
2647                         var section = (name != null) ? uci.get('network', name) : null;
2648
2649                         if (section != null &amp;&amp; section['.type'] == 'interface') {
2650                                 return this.instantiateNetwork(name);
2651                         }
2652                         else if (name != null) {
2653                                 for (var i = 0; i &lt; _state.ifaces.length; i++)
2654                                         if (_state.ifaces[i].interface == name)
2655                                                 return this.instantiateNetwork(name, _state.ifaces[i].proto);
2656                         }
2657
2658                         return null;
2659                 }, this));
2660         },
2661
2662         /**
2663          * Gets an array containing all known networks.
2664          *
2665          * @returns {Promise&lt;Array&lt;LuCI.network.Protocol>>}
2666          * Returns a promise resolving to a name-sorted array of
2667          * {@link LuCI.network.Protocol Protocol} subclass instances
2668          * describing all known networks.
2669          */
2670         getNetworks: function() {
2671                 return initNetworkState().then(L.bind(enumerateNetworks, this));
2672         },
2673
2674         /**
2675          * Deletes the given network and its references from the network and
2676          * firewall configuration.
2677          *
2678          * @param {string} name
2679          * The name of the network to delete.
2680          *
2681          * @returns {Promise&lt;boolean>}
2682          * Returns a promise resolving to either `true` if the network and
2683          * references to it were successfully deleted from the configuration or
2684          * `false` if the given network could not be found.
2685          */
2686         deleteNetwork: function(name) {
2687                 var requireFirewall = Promise.resolve(L.require('firewall')).catch(function() {}),
2688                     network = this.instantiateNetwork(name);
2689
2690                 return Promise.all([ requireFirewall, initNetworkState() ]).then(function(res) {
2691                         var uciInterface = uci.get('network', name),
2692                             firewall = res[0];
2693
2694                         if (uciInterface != null &amp;&amp; uciInterface['.type'] == 'interface') {
2695                                 return Promise.resolve(network ? network.deleteConfiguration() : null).then(function() {
2696                                         uci.remove('network', name);
2697
2698                                         uci.sections('luci', 'ifstate', function(s) {
2699                                                 if (s.interface == name)
2700                                                         uci.remove('luci', s['.name']);
2701                                         });
2702
2703                                         uci.sections('network', 'alias', function(s) {
2704                                                 if (s.interface == name)
2705                                                         uci.remove('network', s['.name']);
2706                                         });
2707
2708                                         uci.sections('network', 'route', function(s) {
2709                                                 if (s.interface == name)
2710                                                         uci.remove('network', s['.name']);
2711                                         });
2712
2713                                         uci.sections('network', 'route6', function(s) {
2714                                                 if (s.interface == name)
2715                                                         uci.remove('network', s['.name']);
2716                                         });
2717
2718                                         uci.sections('wireless', 'wifi-iface', function(s) {
2719                                                 var networks = L.toArray(s.network).filter(function(network) { return network != name });
2720
2721                                                 if (networks.length > 0)
2722                                                         uci.set('wireless', s['.name'], 'network', networks.join(' '));
2723                                                 else
2724                                                         uci.unset('wireless', s['.name'], 'network');
2725                                         });
2726
2727                                         if (firewall)
2728                                                 return firewall.deleteNetwork(name).then(function() { return true });
2729
2730                                         return true;
2731                                 }).catch(function() {
2732                                         return false;
2733                                 });
2734                         }
2735
2736                         return false;
2737                 });
2738         },
2739
2740         /**
2741          * Rename the given network and its references to a new name.
2742          *
2743          * @param {string} oldName
2744          * The current name of the network.
2745          *
2746          * @param {string} newName
2747          * The name to rename the network to, must be in the format
2748          * `[a-z-A-Z0-9_]+`.
2749          *
2750          * @returns {Promise&lt;boolean>}
2751          * Returns a promise resolving to either `true` if the network was
2752          * successfully renamed or `false` if the new name was invalid, if
2753          * a network with the new name already exists or if the network to
2754          * rename could not be found.
2755          */
2756         renameNetwork: function(oldName, newName) {
2757                 return initNetworkState().then(function() {
2758                         if (newName == null || !/^[a-zA-Z0-9_]+$/.test(newName) || uci.get('network', newName) != null)
2759                                 return false;
2760
2761                         var oldNetwork = uci.get('network', oldName);
2762
2763                         if (oldNetwork == null || oldNetwork['.type'] != 'interface')
2764                                 return false;
2765
2766                         var sid = uci.add('network', 'interface', newName);
2767
2768                         for (var key in oldNetwork)
2769                                 if (oldNetwork.hasOwnProperty(key) &amp;&amp; key.charAt(0) != '.')
2770                                         uci.set('network', sid, key, oldNetwork[key]);
2771
2772                         uci.sections('luci', 'ifstate', function(s) {
2773                                 if (s.interface == oldName)
2774                                         uci.set('luci', s['.name'], 'interface', newName);
2775                         });
2776
2777                         uci.sections('network', 'alias', function(s) {
2778                                 if (s.interface == oldName)
2779                                         uci.set('network', s['.name'], 'interface', newName);
2780                         });
2781
2782                         uci.sections('network', 'route', function(s) {
2783                                 if (s.interface == oldName)
2784                                         uci.set('network', s['.name'], 'interface', newName);
2785                         });
2786
2787                         uci.sections('network', 'route6', function(s) {
2788                                 if (s.interface == oldName)
2789                                         uci.set('network', s['.name'], 'interface', newName);
2790                         });
2791
2792                         uci.sections('wireless', 'wifi-iface', function(s) {
2793                                 var networks = L.toArray(s.network).map(function(network) { return (network == oldName ? newName : network) });
2794
2795                                 if (networks.length > 0)
2796                                         uci.set('wireless', s['.name'], 'network', networks.join(' '));
2797                         });
2798
2799                         uci.remove('network', oldName);
2800
2801                         return true;
2802                 });
2803         },
2804
2805         /**
2806          * Get a {@link LuCI.network.Device Device} instance describing the
2807          * given network device.
2808          *
2809          * @param {string} name
2810          * The name of the network device to get, e.g. `eth0` or `br-lan`.
2811          *
2812          * @returns {Promise&lt;null|LuCI.network.Device>}
2813          * Returns a promise resolving to the `Device` instance describing
2814          * the network device or `null` if the given device name could not
2815          * be found.
2816          */
2817         getDevice: function(name) {
2818                 return initNetworkState().then(L.bind(function() {
2819                         if (name == null)
2820                                 return null;
2821
2822                         if (_state.netdevs.hasOwnProperty(name) || isWifiIfname(name))
2823                                 return this.instantiateDevice(name);
2824
2825                         var netid = getWifiNetidBySid(name);
2826                         if (netid != null)
2827                                 return this.instantiateDevice(netid[0]);
2828
2829                         return null;
2830                 }, this));
2831         },
2832
2833         /**
2834          * Get a sorted list of all found network devices.
2835          *
2836          * @returns {Promise&lt;Array&lt;LuCI.network.Device>>}
2837          * Returns a promise resolving to a sorted array of `Device` class
2838          * instances describing the network devices found on the system.
2839          */
2840         getDevices: function() {
2841                 return initNetworkState().then(L.bind(function() {
2842                         var devices = {};
2843
2844                         /* find simple devices */
2845                         var uciInterfaces = uci.sections('network', 'interface');
2846                         for (var i = 0; i &lt; uciInterfaces.length; i++) {
2847                                 var ifnames = L.toArray(uciInterfaces[i].ifname);
2848
2849                                 for (var j = 0; j &lt; ifnames.length; j++) {
2850                                         if (ifnames[j].charAt(0) == '@')
2851                                                 continue;
2852
2853                                         if (isIgnoredIfname(ifnames[j]) || isVirtualIfname(ifnames[j]) || isWifiIfname(ifnames[j]))
2854                                                 continue;
2855
2856                                         devices[ifnames[j]] = this.instantiateDevice(ifnames[j]);
2857                                 }
2858                         }
2859
2860                         for (var ifname in _state.netdevs) {
2861                                 if (devices.hasOwnProperty(ifname))
2862                                         continue;
2863
2864                                 if (isIgnoredIfname(ifname) || isWifiIfname(ifname))
2865                                         continue;
2866
2867                                 if (_state.netdevs[ifname].wireless)
2868                                         continue;
2869
2870                                 devices[ifname] = this.instantiateDevice(ifname);
2871                         }
2872
2873                         /* find VLAN devices */
2874                         var uciSwitchVLANs = uci.sections('network', 'switch_vlan');
2875                         for (var i = 0; i &lt; uciSwitchVLANs.length; i++) {
2876                                 if (typeof(uciSwitchVLANs[i].ports) != 'string' ||
2877                                     typeof(uciSwitchVLANs[i].device) != 'string' ||
2878                                     !_state.switches.hasOwnProperty(uciSwitchVLANs[i].device))
2879                                         continue;
2880
2881                                 var ports = uciSwitchVLANs[i].ports.split(/\s+/);
2882                                 for (var j = 0; j &lt; ports.length; j++) {
2883                                         var m = ports[j].match(/^(\d+)([tu]?)$/);
2884                                         if (m == null)
2885                                                 continue;
2886
2887                                         var netdev = _state.switches[uciSwitchVLANs[i].device].netdevs[m[1]];
2888                                         if (netdev == null)
2889                                                 continue;
2890
2891                                         if (!devices.hasOwnProperty(netdev))
2892                                                 devices[netdev] = this.instantiateDevice(netdev);
2893
2894                                         _state.isSwitch[netdev] = true;
2895
2896                                         if (m[2] != 't')
2897                                                 continue;
2898
2899                                         var vid = uciSwitchVLANs[i].vid || uciSwitchVLANs[i].vlan;
2900                                             vid = (vid != null ? +vid : null);
2901
2902                                         if (vid == null || vid &lt; 0 || vid > 4095)
2903                                                 continue;
2904
2905                                         var vlandev = '%s.%d'.format(netdev, vid);
2906
2907                                         if (!devices.hasOwnProperty(vlandev))
2908                                                 devices[vlandev] = this.instantiateDevice(vlandev);
2909
2910                                         _state.isSwitch[vlandev] = true;
2911                                 }
2912                         }
2913
2914                         /* find wireless interfaces */
2915                         var uciWifiIfaces = uci.sections('wireless', 'wifi-iface'),
2916                             networkCount = {};
2917
2918                         for (var i = 0; i &lt; uciWifiIfaces.length; i++) {
2919                                 if (typeof(uciWifiIfaces[i].device) != 'string')
2920                                         continue;
2921
2922                                 networkCount[uciWifiIfaces[i].device] = (networkCount[uciWifiIfaces[i].device] || 0) + 1;
2923
2924                                 var netid = '%s.network%d'.format(uciWifiIfaces[i].device, networkCount[uciWifiIfaces[i].device]);
2925
2926                                 devices[netid] = this.instantiateDevice(netid);
2927                         }
2928
2929                         var rv = [];
2930
2931                         for (var netdev in devices)
2932                                 if (devices.hasOwnProperty(netdev))
2933                                         rv.push(devices[netdev]);
2934
2935                         rv.sort(deviceSort);
2936
2937                         return rv;
2938                 }, this));
2939         },
2940
2941         /**
2942          * Test if a given network device name is in the list of patterns for
2943          * device names to ignore.
2944          *
2945          * Ignored device names are usually Linux network devices which are
2946          * spawned implicitly by kernel modules such as `tunl0` or `hwsim0`
2947          * and which are unsuitable for use in network configuration.
2948          *
2949          * @param {string} name
2950          * The device name to test.
2951          *
2952          * @returns {boolean}
2953          * Returns `true` if the given name is in the ignore pattern list,
2954          * else returns `false`.
2955          */
2956         isIgnoredDevice: function(name) {
2957                 return isIgnoredIfname(name);
2958         },
2959
2960         /**
2961          * Get a {@link LuCI.network.WifiDevice WifiDevice} instance describing
2962          * the given wireless radio.
2963          *
2964          * @param {string} devname
2965          * The configuration name of the wireless radio to lookup, e.g. `radio0`
2966          * for the first mac80211 phy on the system.
2967          *
2968          * @returns {Promise&lt;null|LuCI.network.WifiDevice>}
2969          * Returns a promise resolving to the `WifiDevice` instance describing
2970          * the underlying radio device or `null` if the wireless radio could not
2971          * be found.
2972          */
2973         getWifiDevice: function(devname) {
2974                 return initNetworkState().then(L.bind(function() {
2975                         var existingDevice = uci.get('wireless', devname);
2976
2977                         if (existingDevice == null || existingDevice['.type'] != 'wifi-device')
2978                                 return null;
2979
2980                         return this.instantiateWifiDevice(devname, _state.radios[devname] || {});
2981                 }, this));
2982         },
2983
2984         /**
2985          * Obtain a list of all configured radio devices.
2986          *
2987          * @returns {Promise&lt;Array&lt;LuCI.network.WifiDevice>>}
2988          * Returns a promise resolving to an array of `WifiDevice` instances
2989          * describing the wireless radios configured in the system.
2990          * The order of the array corresponds to the order of the radios in
2991          * the configuration.
2992          */
2993         getWifiDevices: function() {
2994                 return initNetworkState().then(L.bind(function() {
2995                         var uciWifiDevices = uci.sections('wireless', 'wifi-device'),
2996                             rv = [];
2997
2998                         for (var i = 0; i &lt; uciWifiDevices.length; i++) {
2999                                 var devname = uciWifiDevices[i]['.name'];
3000                                 rv.push(this.instantiateWifiDevice(devname, _state.radios[devname] || {}));
3001                         }
3002
3003                         return rv;
3004                 }, this));
3005         },
3006
3007         /**
3008          * Get a {@link LuCI.network.WifiNetwork WifiNetwork} instance describing
3009          * the given wireless network.
3010          *
3011          * @param {string} netname
3012          * The name of the wireless network to lookup. This may be either an uci
3013          * configuration section ID, a network ID in the form `radio#.network#`
3014          * or a Linux network device name like `wlan0` which is resolved to the
3015          * corresponding configuration section through `ubus` runtime information.
3016          *
3017          * @returns {Promise&lt;null|LuCI.network.WifiNetwork>}
3018          * Returns a promise resolving to the `WifiNetwork` instance describing
3019          * the wireless network or `null` if the corresponding network could not
3020          * be found.
3021          */
3022         getWifiNetwork: function(netname) {
3023                 return initNetworkState()
3024                         .then(L.bind(this.lookupWifiNetwork, this, netname));
3025         },
3026
3027         /**
3028          * Get an array of all {@link LuCI.network.WifiNetwork WifiNetwork}
3029          * instances describing the wireless networks present on the system.
3030          *
3031          * @returns {Promise&lt;Array&lt;LuCI.network.WifiNetwork>>}
3032          * Returns a promise resolving to an array of `WifiNetwork` instances
3033          * describing the wireless networks. The array will be empty if no networks
3034          * are found.
3035          */
3036         getWifiNetworks: function() {
3037                 return initNetworkState().then(L.bind(function() {
3038                         var wifiIfaces = uci.sections('wireless', 'wifi-iface'),
3039                             rv = [];
3040
3041                         for (var i = 0; i &lt; wifiIfaces.length; i++)
3042                                 rv.push(this.lookupWifiNetwork(wifiIfaces[i]['.name']));
3043
3044                         rv.sort(function(a, b) {
3045                                 return (a.getID() > b.getID());
3046                         });
3047
3048                         return rv;
3049                 }, this));
3050         },
3051
3052         /**
3053          * Adds a new wireless network to the configuration and sets its options
3054          * to the provided values.
3055          *
3056          * @param {Object&lt;string, string|string[]>} options
3057          * The options to set for the newly added wireless network. This object
3058          * must at least contain a `device` property which is set to the radio
3059          * name the new network belongs to.
3060          *
3061          * @returns {Promise&lt;null|LuCI.network.WifiNetwork>}
3062          * Returns a promise resolving to a `WifiNetwork` instance describing
3063          * the newly added wireless network or `null` if the given options
3064          * were invalid or if the associated radio device could not be found.
3065          */
3066         addWifiNetwork: function(options) {
3067                 return initNetworkState().then(L.bind(function() {
3068                         if (options == null ||
3069                             typeof(options) != 'object' ||
3070                             typeof(options.device) != 'string')
3071                             return null;
3072
3073                         var existingDevice = uci.get('wireless', options.device);
3074                         if (existingDevice == null || existingDevice['.type'] != 'wifi-device')
3075                                 return null;
3076
3077                         /* XXX: need to add a named section (wifinet#) here */
3078                         var sid = uci.add('wireless', 'wifi-iface');
3079                         for (var key in options)
3080                                 if (options.hasOwnProperty(key))
3081                                         uci.set('wireless', sid, key, options[key]);
3082
3083                         var radioname = existingDevice['.name'],
3084                             netid = getWifiNetidBySid(sid) || [];
3085
3086                         return this.instantiateWifiNetwork(sid, radioname, _state.radios[radioname], netid[0], null);
3087                 }, this));
3088         },
3089
3090         /**
3091          * Deletes the given wireless network from the configuration.
3092          *
3093          * @param {string} netname
3094          * The name of the network to remove. This may be either a
3095          * network ID in the form `radio#.network#` or a Linux network device
3096          * name like `wlan0` which is resolved to the corresponding configuration
3097          * section through `ubus` runtime information.
3098          *
3099          * @returns {Promise&lt;boolean>}
3100          * Returns a promise resolving to `true` if the wireless network has been
3101          * successfully deleted from the configuration or `false` if it could not
3102          * be found.
3103          */
3104         deleteWifiNetwork: function(netname) {
3105                 return initNetworkState().then(L.bind(function() {
3106                         var sid = getWifiSidByIfname(netname);
3107
3108                         if (sid == null)
3109                                 return false;
3110
3111                         uci.remove('wireless', sid);
3112                         return true;
3113                 }, this));
3114         },
3115
3116         /* private */
3117         getStatusByRoute: function(addr, mask) {
3118                 return initNetworkState().then(L.bind(function() {
3119                         var rv = [];
3120
3121                         for (var i = 0; i &lt; _state.ifaces.length; i++) {
3122                                 if (!Array.isArray(_state.ifaces[i].route))
3123                                         continue;
3124
3125                                 for (var j = 0; j &lt; _state.ifaces[i].route.length; j++) {
3126                                         if (typeof(_state.ifaces[i].route[j]) != 'object' ||
3127                                             typeof(_state.ifaces[i].route[j].target) != 'string' ||
3128                                             typeof(_state.ifaces[i].route[j].mask) != 'number')
3129                                             continue;
3130
3131                                         if (_state.ifaces[i].route[j].table)
3132                                                 continue;
3133
3134                                         if (_state.ifaces[i].route[j].target != addr ||
3135                                             _state.ifaces[i].route[j].mask != mask)
3136                                             continue;
3137
3138                                         rv.push(_state.ifaces[i]);
3139                                 }
3140                         }
3141
3142                         return rv;
3143                 }, this));
3144         },
3145
3146         /* private */
3147         getStatusByAddress: function(addr) {
3148                 return initNetworkState().then(L.bind(function() {
3149                         var rv = [];
3150
3151                         for (var i = 0; i &lt; _state.ifaces.length; i++) {
3152                                 if (Array.isArray(_state.ifaces[i]['ipv4-address']))
3153                                         for (var j = 0; j &lt; _state.ifaces[i]['ipv4-address'].length; j++)
3154                                                 if (typeof(_state.ifaces[i]['ipv4-address'][j]) == 'object' &amp;&amp;
3155                                                     _state.ifaces[i]['ipv4-address'][j].address == addr)
3156                                                         return _state.ifaces[i];
3157
3158                                 if (Array.isArray(_state.ifaces[i]['ipv6-address']))
3159                                         for (var j = 0; j &lt; _state.ifaces[i]['ipv6-address'].length; j++)
3160                                                 if (typeof(_state.ifaces[i]['ipv6-address'][j]) == 'object' &amp;&amp;
3161                                                     _state.ifaces[i]['ipv6-address'][j].address == addr)
3162                                                         return _state.ifaces[i];
3163
3164                                 if (Array.isArray(_state.ifaces[i]['ipv6-prefix-assignment']))
3165                                         for (var j = 0; j &lt; _state.ifaces[i]['ipv6-prefix-assignment'].length; j++)
3166                                                 if (typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]) == 'object' &amp;&amp;
3167                                                         typeof(_state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address']) == 'object' &amp;&amp;
3168                                                     _state.ifaces[i]['ipv6-prefix-assignment'][j]['local-address'].address == addr)
3169                                                         return _state.ifaces[i];
3170                         }
3171
3172                         return null;
3173                 }, this));
3174         },
3175
3176         /**
3177          * Get IPv4 wan networks.
3178          *
3179          * This function looks up all networks having a default `0.0.0.0/0` route
3180          * and returns them as array.
3181          *
3182          * @returns {Promise&lt;Array&lt;LuCI.network.Protocol>>}
3183          * Returns a promise resolving to an array of `Protocol` subclass
3184          * instances describing the found default route interfaces.
3185          */
3186         getWANNetworks: function() {
3187                 return this.getStatusByRoute('0.0.0.0', 0).then(L.bind(function(statuses) {
3188                         var rv = [], seen = {};
3189
3190                         for (var i = 0; i &lt; statuses.length; i++) {
3191                                 if (!seen.hasOwnProperty(statuses[i].interface)) {
3192                                         rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
3193                                         seen[statuses[i].interface] = true;
3194                                 }
3195                         }
3196
3197                         return rv;
3198                 }, this));
3199         },
3200
3201         /**
3202          * Get IPv6 wan networks.
3203          *
3204          * This function looks up all networks having a default `::/0` route
3205          * and returns them as array.
3206          *
3207          * @returns {Promise&lt;Array&lt;LuCI.network.Protocol>>}
3208          * Returns a promise resolving to an array of `Protocol` subclass
3209          * instances describing the found IPv6 default route interfaces.
3210          */
3211         getWAN6Networks: function() {
3212                 return this.getStatusByRoute('::', 0).then(L.bind(function(statuses) {
3213                         var rv = [], seen = {};
3214
3215                         for (var i = 0; i &lt; statuses.length; i++) {
3216                                 if (!seen.hasOwnProperty(statuses[i].interface)) {
3217                                         rv.push(this.instantiateNetwork(statuses[i].interface, statuses[i].proto));
3218                                         seen[statuses[i].interface] = true;
3219                                 }
3220                         }
3221
3222                         return rv;
3223                 }, this));
3224         },
3225
3226         /**
3227          * Describes an swconfig switch topology by specifying the CPU
3228          * connections and external port labels of a switch.
3229          *
3230          * @typedef {Object&lt;string, Object|Array>} SwitchTopology
3231          * @memberof LuCI.network
3232          *
3233          * @property {Object&lt;number, string>} netdevs
3234          * The `netdevs` property points to an object describing the CPU port
3235          * connections of the switch. The numeric key of the enclosed object is
3236          * the port number, the value contains the Linux network device name the
3237          * port is hardwired to.
3238          *
3239          * @property {Array&lt;Object&lt;string, boolean|number|string>>} ports
3240          * The `ports` property points to an array describing the populated
3241          * ports of the switch in the external label order. Each array item is
3242          * an object containg the following keys:
3243          *  - `num` - the internal switch port number
3244          *  - `label` - the label of the port, e.g. `LAN 1` or `CPU (eth0)`
3245          *  - `device` - the connected Linux network device name (CPU ports only)
3246          *  - `tagged` - a boolean indicating whether the port must be tagged to
3247          *     function (CPU ports only)
3248          */
3249
3250         /**
3251          * Returns the topologies of all swconfig switches found on the system.
3252          *
3253          * @returns {Promise&lt;Object&lt;string, LuCI.network.SwitchTopology>>}
3254          * Returns a promise resolving to an object containing the topologies
3255          * of each switch. The object keys correspond to the name of the switches
3256          * such as `switch0`, the values are
3257          * {@link LuCI.network.SwitchTopology SwitchTopology} objects describing
3258          * the layout.
3259          */
3260         getSwitchTopologies: function() {
3261                 return initNetworkState().then(function() {
3262                         return _state.switches;
3263                 });
3264         },
3265
3266         /* private */
3267         instantiateNetwork: function(name, proto) {
3268                 if (name == null)
3269                         return null;
3270
3271                 proto = (proto == null ? uci.get('network', name, 'proto') : proto);
3272
3273                 var protoClass = _protocols[proto] || Protocol;
3274                 return new protoClass(name);
3275         },
3276
3277         /* private */
3278         instantiateDevice: function(name, network, extend) {
3279                 if (extend != null)
3280                         return new (Device.extend(extend))(name, network);
3281
3282                 return new Device(name, network);
3283         },
3284
3285         /* private */
3286         instantiateWifiDevice: function(radioname, radiostate) {
3287                 return new WifiDevice(radioname, radiostate);
3288         },
3289
3290         /* private */
3291         instantiateWifiNetwork: function(sid, radioname, radiostate, netid, netstate, hostapd) {
3292                 return new WifiNetwork(sid, radioname, radiostate, netid, netstate, hostapd);
3293         },
3294
3295         /* private */
3296         lookupWifiNetwork: function(netname) {
3297                 var sid, res, netid, radioname, radiostate, netstate;
3298
3299                 sid = getWifiSidByNetid(netname);
3300
3301                 if (sid != null) {
3302                         res        = getWifiStateBySid(sid);
3303                         netid      = netname;
3304                         radioname  = res ? res[0] : null;
3305                         radiostate = res ? res[1] : null;
3306                         netstate   = res ? res[2] : null;
3307                 }
3308                 else {
3309                         res = getWifiStateByIfname(netname);
3310
3311                         if (res != null) {
3312                                 radioname  = res[0];
3313                                 radiostate = res[1];
3314                                 netstate   = res[2];
3315                                 sid        = netstate.section;
3316                                 netid      = L.toArray(getWifiNetidBySid(sid))[0];
3317                         }
3318                         else {
3319                                 res = getWifiStateBySid(netname);
3320
3321                                 if (res != null) {
3322                                         radioname  = res[0];
3323                                         radiostate = res[1];
3324                                         netstate   = res[2];
3325                                         sid        = netname;
3326                                         netid      = L.toArray(getWifiNetidBySid(sid))[0];
3327                                 }
3328                                 else {
3329                                         res = getWifiNetidBySid(netname);
3330
3331                                         if (res != null) {
3332                                                 netid     = res[0];
3333                                                 radioname = res[1];
3334                                                 sid       = netname;
3335                                         }
3336                                 }
3337                         }
3338                 }
3339
3340                 return this.instantiateWifiNetwork(sid || netname, radioname,
3341                         radiostate, netid, netstate,
3342                         netstate ? _state.hostapd[netstate.ifname] : null);
3343         },
3344
3345         /**
3346          * Obtains the the network device name of the given object.
3347          *
3348          * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} obj
3349          * The object to get the device name from.
3350          *
3351          * @returns {null|string}
3352          * Returns a string containing the device name or `null` if the given
3353          * object could not be converted to a name.
3354          */
3355         getIfnameOf: function(obj) {
3356                 return ifnameOf(obj);
3357         },
3358
3359         /**
3360          * Queries the internal DSL modem type from board information.
3361          *
3362          * @returns {Promise&lt;null|string>}
3363          * Returns a promise resolving to the type of the internal modem
3364          * (e.g. `vdsl`) or to `null` if no internal modem is present.
3365          */
3366         getDSLModemType: function() {
3367                 return initNetworkState().then(function() {
3368                         return _state.hasDSLModem ? _state.hasDSLModem.type : null;
3369                 });
3370         },
3371
3372         /**
3373          * Queries aggregated information about known hosts.
3374          *
3375          * This function aggregates information from various sources such as
3376          * DHCP lease databases, ARP and IPv6 neighbour entries, wireless
3377          * association list etc. and returns a {@link LuCI.network.Hosts Hosts}
3378          * class instance describing the found hosts.
3379          *
3380          * @returns {Promise&lt;LuCI.network.Hosts>}
3381          * Returns a `Hosts` instance describing host known on the system.
3382          */
3383         getHostHints: function() {
3384                 return initNetworkState().then(function() {
3385                         return new Hosts(_state.hosts);
3386                 });
3387         }
3388 });
3389
3390 /**
3391  * @class
3392  * @memberof LuCI.network
3393  * @hideconstructor
3394  * @classdesc
3395  *
3396  * The `LuCI.network.Hosts` class encapsulates host information aggregated
3397  * from multiple sources and provides convenience functions to access the
3398  * host information by different criteria.
3399  */
3400 Hosts = baseclass.extend(/** @lends LuCI.network.Hosts.prototype */ {
3401         __init__: function(hosts) {
3402                 this.hosts = hosts;
3403         },
3404
3405         /**
3406          * Lookup the hostname associated with the given MAC address.
3407          *
3408          * @param {string} mac
3409          * The MAC address to lookup.
3410          *
3411          * @returns {null|string}
3412          * Returns the hostname associated with the given MAC or `null` if
3413          * no matching host could be found or if no hostname is known for
3414          * the corresponding host.
3415          */
3416         getHostnameByMACAddr: function(mac) {
3417                 return this.hosts[mac] ? this.hosts[mac].name : null;
3418         },
3419
3420         /**
3421          * Lookup the IPv4 address associated with the given MAC address.
3422          *
3423          * @param {string} mac
3424          * The MAC address to lookup.
3425          *
3426          * @returns {null|string}
3427          * Returns the IPv4 address associated with the given MAC or `null` if
3428          * no matching host could be found or if no IPv4 address is known for
3429          * the corresponding host.
3430          */
3431         getIPAddrByMACAddr: function(mac) {
3432                 return this.hosts[mac] ? this.hosts[mac].ipv4 : null;
3433         },
3434
3435         /**
3436          * Lookup the IPv6 address associated with the given MAC address.
3437          *
3438          * @param {string} mac
3439          * The MAC address to lookup.
3440          *
3441          * @returns {null|string}
3442          * Returns the IPv6 address associated with the given MAC or `null` if
3443          * no matching host could be found or if no IPv6 address is known for
3444          * the corresponding host.
3445          */
3446         getIP6AddrByMACAddr: function(mac) {
3447                 return this.hosts[mac] ? this.hosts[mac].ipv6 : null;
3448         },
3449
3450         /**
3451          * Lookup the hostname associated with the given IPv4 address.
3452          *
3453          * @param {string} ipaddr
3454          * The IPv4 address to lookup.
3455          *
3456          * @returns {null|string}
3457          * Returns the hostname associated with the given IPv4 or `null` if
3458          * no matching host could be found or if no hostname is known for
3459          * the corresponding host.
3460          */
3461         getHostnameByIPAddr: function(ipaddr) {
3462                 for (var mac in this.hosts)
3463                         if (this.hosts[mac].ipv4 == ipaddr &amp;&amp; this.hosts[mac].name != null)
3464                                 return this.hosts[mac].name;
3465                 return null;
3466         },
3467
3468         /**
3469          * Lookup the MAC address associated with the given IPv4 address.
3470          *
3471          * @param {string} ipaddr
3472          * The IPv4 address to lookup.
3473          *
3474          * @returns {null|string}
3475          * Returns the MAC address associated with the given IPv4 or `null` if
3476          * no matching host could be found or if no MAC address is known for
3477          * the corresponding host.
3478          */
3479         getMACAddrByIPAddr: function(ipaddr) {
3480                 for (var mac in this.hosts)
3481                         if (this.hosts[mac].ipv4 == ipaddr)
3482                                 return mac;
3483                 return null;
3484         },
3485
3486         /**
3487          * Lookup the hostname associated with the given IPv6 address.
3488          *
3489          * @param {string} ipaddr
3490          * The IPv6 address to lookup.
3491          *
3492          * @returns {null|string}
3493          * Returns the hostname associated with the given IPv6 or `null` if
3494          * no matching host could be found or if no hostname is known for
3495          * the corresponding host.
3496          */
3497         getHostnameByIP6Addr: function(ip6addr) {
3498                 for (var mac in this.hosts)
3499                         if (this.hosts[mac].ipv6 == ip6addr &amp;&amp; this.hosts[mac].name != null)
3500                                 return this.hosts[mac].name;
3501                 return null;
3502         },
3503
3504         /**
3505          * Lookup the MAC address associated with the given IPv6 address.
3506          *
3507          * @param {string} ipaddr
3508          * The IPv6 address to lookup.
3509          *
3510          * @returns {null|string}
3511          * Returns the MAC address associated with the given IPv6 or `null` if
3512          * no matching host could be found or if no MAC address is known for
3513          * the corresponding host.
3514          */
3515         getMACAddrByIP6Addr: function(ip6addr) {
3516                 for (var mac in this.hosts)
3517                         if (this.hosts[mac].ipv6 == ip6addr)
3518                                 return mac;
3519                 return null;
3520         },
3521
3522         /**
3523          * Return an array of (MAC address, name hint) tuples sorted by
3524          * MAC address.
3525          *
3526          * @param {boolean} [preferIp6=false]
3527          * Whether to prefer IPv6 addresses (`true`) or IPv4 addresses (`false`)
3528          * as name hint when no hostname is known for a specific MAC address.
3529          *
3530          * @returns {Array&lt;Array&lt;string>>}
3531          * Returns an array of arrays containing a name hint for each found
3532          * MAC address on the system. The array is sorted ascending by MAC.
3533          *
3534          * Each item of the resulting array is a two element array with the
3535          * MAC being the first element and the name hint being the second
3536          * element. The name hint is either the hostname, an IPv4 or an IPv6
3537          * address related to the MAC address.
3538          *
3539          * If no hostname but both IPv4 and IPv6 addresses are known, the
3540          * `preferIP6` flag specifies whether the IPv6 or the IPv4 address
3541          * is used as hint.
3542          */
3543         getMACHints: function(preferIp6) {
3544                 var rv = [];
3545                 for (var mac in this.hosts) {
3546                         var hint = this.hosts[mac].name ||
3547                                 this.hosts[mac][preferIp6 ? 'ipv6' : 'ipv4'] ||
3548                                 this.hosts[mac][preferIp6 ? 'ipv4' : 'ipv6'];
3549
3550                         rv.push([mac, hint]);
3551                 }
3552                 return rv.sort(function(a, b) { return a[0] > b[0] });
3553         }
3554 });
3555
3556 /**
3557  * @class
3558  * @memberof LuCI.network
3559  * @hideconstructor
3560  * @classdesc
3561  *
3562  * The `Network.Protocol` class serves as base for protocol specific
3563  * subclasses which describe logical UCI networks defined by `config
3564  * interface` sections in `/etc/config/network`.
3565  */
3566 Protocol = baseclass.extend(/** @lends LuCI.network.Protocol.prototype */ {
3567         __init__: function(name) {
3568                 this.sid = name;
3569         },
3570
3571         _get: function(opt) {
3572                 var val = uci.get('network', this.sid, opt);
3573
3574                 if (Array.isArray(val))
3575                         return val.join(' ');
3576
3577                 return val || '';
3578         },
3579
3580         _ubus: function(field) {
3581                 for (var i = 0; i &lt; _state.ifaces.length; i++) {
3582                         if (_state.ifaces[i].interface != this.sid)
3583                                 continue;
3584
3585                         return (field != null ? _state.ifaces[i][field] : _state.ifaces[i]);
3586                 }
3587         },
3588
3589         /**
3590          * Read the given UCI option value of this network.
3591          *
3592          * @param {string} opt
3593          * The UCI option name to read.
3594          *
3595          * @returns {null|string|string[]}
3596          * Returns the UCI option value or `null` if the requested option is
3597          * not found.
3598          */
3599         get: function(opt) {
3600                 return uci.get('network', this.sid, opt);
3601         },
3602
3603         /**
3604          * Set the given UCI option of this network to the given value.
3605          *
3606          * @param {string} opt
3607          * The name of the UCI option to set.
3608          *
3609          * @param {null|string|string[]} val
3610          * The value to set or `null` to remove the given option from the
3611          * configuration.
3612          */
3613         set: function(opt, val) {
3614                 return uci.set('network', this.sid, opt, val);
3615         },
3616
3617         /**
3618          * Get the associared Linux network device of this network.
3619          *
3620          * @returns {null|string}
3621          * Returns the name of the associated network device or `null` if
3622          * it could not be determined.
3623          */
3624         getIfname: function() {
3625                 var ifname;
3626
3627                 if (this.isFloating())
3628                         ifname = this._ubus('l3_device');
3629                 else
3630                         ifname = this._ubus('device') || this._ubus('l3_device');
3631
3632                 if (ifname != null)
3633                         return ifname;
3634
3635                 var res = getWifiNetidByNetname(this.sid);
3636                 return (res != null ? res[0] : null);
3637         },
3638
3639         /**
3640          * Get the name of this network protocol class.
3641          *
3642          * This function will be overwritten by subclasses created by
3643          * {@link LuCI.network#registerProtocol Network.registerProtocol()}.
3644          *
3645          * @abstract
3646          * @returns {string}
3647          * Returns the name of the network protocol implementation, e.g.
3648          * `static` or `dhcp`.
3649          */
3650         getProtocol: function() {
3651                 return null;
3652         },
3653
3654         /**
3655          * Return a human readable description for the protcol, such as
3656          * `Static address` or `DHCP client`.
3657          *
3658          * This function should be overwritten by subclasses.
3659          *
3660          * @abstract
3661          * @returns {string}
3662          * Returns the description string.
3663          */
3664         getI18n: function() {
3665                 switch (this.getProtocol()) {
3666                 case 'none':   return _('Unmanaged');
3667                 case 'static': return _('Static address');
3668                 case 'dhcp':   return _('DHCP client');
3669                 default:       return _('Unknown');
3670                 }
3671         },
3672
3673         /**
3674          * Get the type of the underlying interface.
3675          *
3676          * This function actually is a convenience wrapper around
3677          * `proto.get("type")` and is mainly used by other `LuCI.network` code
3678          * to check whether the interface is declared as bridge in UCI.
3679          *
3680          * @returns {null|string}
3681          * Returns the value of the `type` option of the associated logical
3682          * interface or `null` if no `type` option is set.
3683          */
3684         getType: function() {
3685                 return this._get('type');
3686         },
3687
3688         /**
3689          * Get the name of the associated logical interface.
3690          *
3691          * @returns {string}
3692          * Returns the logical interface name, such as `lan` or `wan`.
3693          */
3694         getName: function() {
3695                 return this.sid;
3696         },
3697
3698         /**
3699          * Get the uptime of the logical interface.
3700          *
3701          * @returns {number}
3702          * Returns the uptime of the associated interface in seconds.
3703          */
3704         getUptime: function() {
3705                 return this._ubus('uptime') || 0;
3706         },
3707
3708         /**
3709          * Get the logical interface expiry time in seconds.
3710          *
3711          * For protocols that have a concept of a lease, such as DHCP or
3712          * DHCPv6, this function returns the remaining time in seconds
3713          * until the lease expires.
3714          *
3715          * @returns {number}
3716          * Returns the amount of seconds until the lease expires or `-1`
3717          * if it isn't applicable to the associated protocol.
3718          */
3719         getExpiry: function() {
3720                 var u = this._ubus('uptime'),
3721                     d = this._ubus('data');
3722
3723                 if (typeof(u) == 'number' &amp;&amp; d != null &amp;&amp;
3724                     typeof(d) == 'object' &amp;&amp; typeof(d.leasetime) == 'number') {
3725                         var r = d.leasetime - (u % d.leasetime);
3726                         return (r > 0 ? r : 0);
3727                 }
3728
3729                 return -1;
3730         },
3731
3732         /**
3733          * Get the metric value of the logical interface.
3734          *
3735          * @returns {number}
3736          * Returns the current metric value used for device and network
3737          * routes spawned by the associated logical interface.
3738          */
3739         getMetric: function() {
3740                 return this._ubus('metric') || 0;
3741         },
3742
3743         /**
3744          * Get the requested firewall zone name of the logical interface.
3745          *
3746          * Some protocol implementations request a specific firewall zone
3747          * to trigger inclusion of their resulting network devices into the
3748          * firewall rule set.
3749          *
3750          * @returns {null|string}
3751          * Returns the requested firewall zone name as published in the
3752          * `ubus` runtime information or `null` if the remote protocol
3753          * handler didn't request a zone.
3754          */
3755         getZoneName: function() {
3756                 var d = this._ubus('data');
3757
3758                 if (L.isObject(d) &amp;&amp; typeof(d.zone) == 'string')
3759                         return d.zone;
3760
3761                 return null;
3762         },
3763
3764         /**
3765          * Query the first (primary) IPv4 address of the logical interface.
3766          *
3767          * @returns {null|string}
3768          * Returns the primary IPv4 address registered by the protocol handler
3769          * or `null` if no IPv4 addresses were set.
3770          */
3771         getIPAddr: function() {
3772                 var addrs = this._ubus('ipv4-address');
3773                 return ((Array.isArray(addrs) &amp;&amp; addrs.length) ? addrs[0].address : null);
3774         },
3775
3776         /**
3777          * Query all IPv4 addresses of the logical interface.
3778          *
3779          * @returns {string[]}
3780          * Returns an array of IPv4 addresses in CIDR notation which have been
3781          * registered by the protocol handler. The order of the resulting array
3782          * follows the order of the addresses in `ubus` runtime information.
3783          */
3784         getIPAddrs: function() {
3785                 var addrs = this._ubus('ipv4-address'),
3786                     rv = [];
3787
3788                 if (Array.isArray(addrs))
3789                         for (var i = 0; i &lt; addrs.length; i++)
3790                                 rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
3791
3792                 return rv;
3793         },
3794
3795         /**
3796          * Query the first (primary) IPv4 netmask of the logical interface.
3797          *
3798          * @returns {null|string}
3799          * Returns the netmask of the primary IPv4 address registered by the
3800          * protocol handler or `null` if no IPv4 addresses were set.
3801          */
3802         getNetmask: function() {
3803                 var addrs = this._ubus('ipv4-address');
3804                 if (Array.isArray(addrs) &amp;&amp; addrs.length)
3805                         return prefixToMask(addrs[0].mask, false);
3806         },
3807
3808         /**
3809          * Query the gateway (nexthop) of the default route associated with
3810          * this logical interface.
3811          *
3812          * @returns {string}
3813          * Returns a string containing the IPv4 nexthop address of the associated
3814          * default route or `null` if no default route was found.
3815          */
3816         getGatewayAddr: function() {
3817                 var routes = this._ubus('route');
3818
3819                 if (Array.isArray(routes))
3820                         for (var i = 0; i &lt; routes.length; i++)
3821                                 if (typeof(routes[i]) == 'object' &amp;&amp;
3822                                     routes[i].target == '0.0.0.0' &amp;&amp;
3823                                     routes[i].mask == 0)
3824                                     return routes[i].nexthop;
3825
3826                 return null;
3827         },
3828
3829         /**
3830          * Query the IPv4 DNS servers associated with the logical interface.
3831          *
3832          * @returns {string[]}
3833          * Returns an array of IPv4 DNS servers registered by the remote
3834          * protocol backend.
3835          */
3836         getDNSAddrs: function() {
3837                 var addrs = this._ubus('dns-server'),
3838                     rv = [];
3839
3840                 if (Array.isArray(addrs))
3841                         for (var i = 0; i &lt; addrs.length; i++)
3842                                 if (!/:/.test(addrs[i]))
3843                                         rv.push(addrs[i]);
3844
3845                 return rv;
3846         },
3847
3848         /**
3849          * Query the first (primary) IPv6 address of the logical interface.
3850          *
3851          * @returns {null|string}
3852          * Returns the primary IPv6 address registered by the protocol handler
3853          * in CIDR notation or `null` if no IPv6 addresses were set.
3854          */
3855         getIP6Addr: function() {
3856                 var addrs = this._ubus('ipv6-address');
3857
3858                 if (Array.isArray(addrs) &amp;&amp; L.isObject(addrs[0]))
3859                         return '%s/%d'.format(addrs[0].address, addrs[0].mask);
3860
3861                 addrs = this._ubus('ipv6-prefix-assignment');
3862
3863                 if (Array.isArray(addrs) &amp;&amp; L.isObject(addrs[0]) &amp;&amp; L.isObject(addrs[0]['local-address']))
3864                         return '%s/%d'.format(addrs[0]['local-address'].address, addrs[0]['local-address'].mask);
3865
3866                 return null;
3867         },
3868
3869         /**
3870          * Query all IPv6 addresses of the logical interface.
3871          *
3872          * @returns {string[]}
3873          * Returns an array of IPv6 addresses in CIDR notation which have been
3874          * registered by the protocol handler. The order of the resulting array
3875          * follows the order of the addresses in `ubus` runtime information.
3876          */
3877         getIP6Addrs: function() {
3878                 var addrs = this._ubus('ipv6-address'),
3879                     rv = [];
3880
3881                 if (Array.isArray(addrs))
3882                         for (var i = 0; i &lt; addrs.length; i++)
3883                                 if (L.isObject(addrs[i]))
3884                                         rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
3885
3886                 addrs = this._ubus('ipv6-prefix-assignment');
3887
3888                 if (Array.isArray(addrs))
3889                         for (var i = 0; i &lt; addrs.length; i++)
3890                                 if (L.isObject(addrs[i]) &amp;&amp; L.isObject(addrs[i]['local-address']))
3891                                         rv.push('%s/%d'.format(addrs[i]['local-address'].address, addrs[i]['local-address'].mask));
3892
3893                 return rv;
3894         },
3895
3896         /**
3897          * Query the gateway (nexthop) of the IPv6 default route associated with
3898          * this logical interface.
3899          *
3900          * @returns {string}
3901          * Returns a string containing the IPv6 nexthop address of the associated
3902          * default route or `null` if no default route was found.
3903          */
3904         getGateway6Addr: function() {
3905                 var routes = this._ubus('route');
3906
3907                 if (Array.isArray(routes))
3908                         for (var i = 0; i &lt; routes.length; i++)
3909                                 if (typeof(routes[i]) == 'object' &amp;&amp;
3910                                     routes[i].target == '::' &amp;&amp;
3911                                     routes[i].mask == 0)
3912                                     return routes[i].nexthop;
3913
3914                 return null;
3915         },
3916
3917         /**
3918          * Query the IPv6 DNS servers associated with the logical interface.
3919          *
3920          * @returns {string[]}
3921          * Returns an array of IPv6 DNS servers registered by the remote
3922          * protocol backend.
3923          */
3924         getDNS6Addrs: function() {
3925                 var addrs = this._ubus('dns-server'),
3926                     rv = [];
3927
3928                 if (Array.isArray(addrs))
3929                         for (var i = 0; i &lt; addrs.length; i++)
3930                                 if (/:/.test(addrs[i]))
3931                                         rv.push(addrs[i]);
3932
3933                 return rv;
3934         },
3935
3936         /**
3937          * Query the routed IPv6 prefix associated with the logical interface.
3938          *
3939          * @returns {null|string}
3940          * Returns the routed IPv6 prefix registered by the remote protocol
3941          * handler or `null` if no prefix is present.
3942          */
3943         getIP6Prefix: function() {
3944                 var prefixes = this._ubus('ipv6-prefix');
3945
3946                 if (Array.isArray(prefixes) &amp;&amp; L.isObject(prefixes[0]))
3947                         return '%s/%d'.format(prefixes[0].address, prefixes[0].mask);
3948
3949                 return null;
3950         },
3951
3952         /**
3953          * Query interface error messages published in `ubus` runtime state.
3954          *
3955          * Interface errors are emitted by remote protocol handlers if the setup
3956          * of the underlying logical interface failed, e.g. due to bad
3957          * configuration or network connectivity issues.
3958          *
3959          * This function will translate the found error codes to human readable
3960          * messages using the descriptions registered by
3961          * {@link LuCI.network#registerErrorCode Network.registerErrorCode()}
3962          * and fall back to `"Unknown error (%s)"` where `%s` is replaced by the
3963          * error code in case no translation can be found.
3964          *
3965          * @returns {string[]}
3966          * Returns an array of translated interface error messages.
3967          */
3968         getErrors: function() {
3969                 var errors = this._ubus('errors'),
3970                     rv = null;
3971
3972                 if (Array.isArray(errors)) {
3973                         for (var i = 0; i &lt; errors.length; i++) {
3974                                 if (!L.isObject(errors[i]) || typeof(errors[i].code) != 'string')
3975                                         continue;
3976
3977                                 rv = rv || [];
3978                                 rv.push(proto_errors[errors[i].code] || _('Unknown error (%s)').format(errors[i].code));
3979                         }
3980                 }
3981
3982                 return rv;
3983         },
3984
3985         /**
3986          * Checks whether the underlying logical interface is declared as bridge.
3987          *
3988          * @returns {boolean}
3989          * Returns `true` when the interface is declared with `option type bridge`
3990          * and when the associated protocol implementation is not marked virtual
3991          * or `false` when the logical interface is no bridge.
3992          */
3993         isBridge: function() {
3994                 return (!this.isVirtual() &amp;&amp; this.getType() == 'bridge');
3995         },
3996
3997         /**
3998          * Get the name of the opkg package providing the protocol functionality.
3999          *
4000          * This function should be overwritten by protocol specific subclasses.
4001          *
4002          * @abstract
4003          *
4004          * @returns {string}
4005          * Returns the name of the opkg package required for the protocol to
4006          * function, e.g. `odhcp6c` for the `dhcpv6` prototocol.
4007          */
4008         getOpkgPackage: function() {
4009                 return null;
4010         },
4011
4012         /**
4013          * Checks whether the protocol functionality is installed.
4014          *
4015          * This function exists for compatibility with old code, it always
4016          * returns `true`.
4017          *
4018          * @deprecated
4019          * @abstract
4020          *
4021          * @returns {boolean}
4022          * Returns `true` if the protocol support is installed, else `false`.
4023          */
4024         isInstalled: function() {
4025                 return true;
4026         },
4027
4028         /**
4029          * Checks whether this protocol is "virtual".
4030          *
4031          * A "virtual" protocol is a protocol which spawns its own interfaces
4032          * on demand instead of using existing physical interfaces.
4033          *
4034          * Examples for virtual protocols are `6in4` which `gre` spawn tunnel
4035          * network device on startup, examples for non-virtual protcols are
4036          * `dhcp` or `static` which apply IP configuration to existing interfaces.
4037          *
4038          * This function should be overwritten by subclasses.
4039          *
4040          * @returns {boolean}
4041          * Returns a boolean indicating whether the underlying protocol spawns
4042          * dynamic interfaces (`true`) or not (`false`).
4043          */
4044         isVirtual: function() {
4045                 return false;
4046         },
4047
4048         /**
4049          * Checks whether this protocol is "floating".
4050          *
4051          * A "floating" protocol is a protocol which spawns its own interfaces
4052          * on demand, like a virtual one but which relies on an existinf lower
4053          * level interface to initiate the connection.
4054          *
4055          * An example for such a protocol is "pppoe".
4056          *
4057          * This function exists for backwards compatibility with older code
4058          * but should not be used anymore.
4059          *
4060          * @deprecated
4061          * @returns {boolean}
4062          * Returns a boolean indicating whether this protocol is floating (`true`)
4063          * or not (`false`).
4064          */
4065         isFloating: function() {
4066                 return false;
4067         },
4068
4069         /**
4070          * Checks whether this logical interface is dynamic.
4071          *
4072          * A dynamic interface is an interface which has been created at runtime,
4073          * e.g. as sub-interface of another interface, but which is not backed by
4074          * any user configuration. Such dynamic interfaces cannot be edited but
4075          * only brought down or restarted.
4076          *
4077          * @returns {boolean}
4078          * Returns a boolean indicating whether this interface is dynamic (`true`)
4079          * or not (`false`).
4080          */
4081         isDynamic: function() {
4082                 return (this._ubus('dynamic') == true);
4083         },
4084
4085         /**
4086          * Checks whether this interface is an alias interface.
4087          *
4088          * Alias interfaces are interfaces layering on top of another interface
4089          * and are denoted by a special `@interfacename` notation in the
4090          * underlying `ifname` option.
4091          *
4092          * @returns {null|string}
4093          * Returns the name of the parent interface if this logical interface
4094          * is an alias or `null` if it is not an alias interface.
4095          */
4096         isAlias: function() {
4097                 var ifnames = L.toArray(uci.get('network', this.sid, 'ifname')),
4098                     parent = null;
4099
4100                 for (var i = 0; i &lt; ifnames.length; i++)
4101                         if (ifnames[i].charAt(0) == '@')
4102                                 parent = ifnames[i].substr(1);
4103                         else if (parent != null)
4104                                 parent = null;
4105
4106                 return parent;
4107         },
4108
4109         /**
4110          * Checks whether this logical interface is "empty", meaning that ut
4111          * has no network devices attached.
4112          *
4113          * @returns {boolean}
4114          * Returns `true` if this logical interface is empty, else `false`.
4115          */
4116         isEmpty: function() {
4117                 if (this.isFloating())
4118                         return false;
4119
4120                 var empty = true,
4121                     ifname = this._get('ifname');
4122
4123                 if (ifname != null &amp;&amp; ifname.match(/\S+/))
4124                         empty = false;
4125
4126                 if (empty == true &amp;&amp; getWifiNetidBySid(this.sid) != null)
4127                         empty = false;
4128
4129                 return empty;
4130         },
4131
4132         /**
4133          * Checks whether this logical interface is configured and running.
4134          *
4135          * @returns {boolean}
4136          * Returns `true` when the interface is active or `false` when it is not.
4137          */
4138         isUp: function() {
4139                 return (this._ubus('up') == true);
4140         },
4141
4142         /**
4143          * Add the given network device to the logical interface.
4144          *
4145          * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
4146          * The object or device name to add to the logical interface. In case the
4147          * given argument is not a string, it is resolved though the
4148          * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
4149          *
4150          * @returns {boolean}
4151          * Returns `true` if the device name has been added or `false` if any
4152          * argument was invalid, if the device was already part of the logical
4153          * interface or if the logical interface is virtual.
4154          */
4155         addDevice: function(ifname) {
4156                 ifname = ifnameOf(ifname);
4157
4158                 if (ifname == null || this.isFloating())
4159                         return false;
4160
4161                 var wif = getWifiSidByIfname(ifname);
4162
4163                 if (wif != null)
4164                         return appendValue('wireless', wif, 'network', this.sid);
4165
4166                 return appendValue('network', this.sid, 'ifname', ifname);
4167         },
4168
4169         /**
4170          * Remove the given network device from the logical interface.
4171          *
4172          * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
4173          * The object or device name to remove from the logical interface. In case
4174          * the given argument is not a string, it is resolved though the
4175          * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
4176          *
4177          * @returns {boolean}
4178          * Returns `true` if the device name has been added or `false` if any
4179          * argument was invalid, if the device was already part of the logical
4180          * interface or if the logical interface is virtual.
4181          */
4182         deleteDevice: function(ifname) {
4183                 var rv = false;
4184
4185                 ifname = ifnameOf(ifname);
4186
4187                 if (ifname == null || this.isFloating())
4188                         return false;
4189
4190                 var wif = getWifiSidByIfname(ifname);
4191
4192                 if (wif != null)
4193                         rv = removeValue('wireless', wif, 'network', this.sid);
4194
4195                 if (removeValue('network', this.sid, 'ifname', ifname))
4196                         rv = true;
4197
4198                 return rv;
4199         },
4200
4201         /**
4202          * Returns the Linux network device associated with this logical
4203          * interface.
4204          *
4205          * @returns {LuCI.network.Device}
4206          * Returns a `Network.Device` class instance representing the
4207          * expected Linux network device according to the configuration.
4208          */
4209         getDevice: function() {
4210                 if (this.isVirtual()) {
4211                         var ifname = '%s-%s'.format(this.getProtocol(), this.sid);
4212                         _state.isTunnel[this.getProtocol() + '-' + this.sid] = true;
4213                         return Network.prototype.instantiateDevice(ifname, this);
4214                 }
4215                 else if (this.isBridge()) {
4216                         var ifname = 'br-%s'.format(this.sid);
4217                         _state.isBridge[ifname] = true;
4218                         return new Device(ifname, this);
4219                 }
4220                 else {
4221                         var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
4222
4223                         for (var i = 0; i &lt; ifnames.length; i++) {
4224                                 var m = ifnames[i].match(/^([^:/]+)/);
4225                                 return ((m &amp;&amp; m[1]) ? Network.prototype.instantiateDevice(m[1], this) : null);
4226                         }
4227
4228                         ifname = getWifiNetidByNetname(this.sid);
4229
4230                         return (ifname != null ? Network.prototype.instantiateDevice(ifname[0], this) : null);
4231                 }
4232         },
4233
4234         /**
4235          * Returns the layer 2 linux network device currently associated
4236          * with this logical interface.
4237          *
4238          * @returns {LuCI.network.Device}
4239          * Returns a `Network.Device` class instance representing the Linux
4240          * network device currently associated with the logical interface.
4241          */
4242         getL2Device: function() {
4243                 var ifname = this._ubus('device');
4244                 return (ifname != null ? Network.prototype.instantiateDevice(ifname, this) : null);
4245         },
4246
4247         /**
4248          * Returns the layer 3 linux network device currently associated
4249          * with this logical interface.
4250          *
4251          * @returns {LuCI.network.Device}
4252          * Returns a `Network.Device` class instance representing the Linux
4253          * network device currently associated with the logical interface.
4254          */
4255         getL3Device: function() {
4256                 var ifname = this._ubus('l3_device');
4257                 return (ifname != null ? Network.prototype.instantiateDevice(ifname, this) : null);
4258         },
4259
4260         /**
4261          * Returns a list of network sub-devices associated with this logical
4262          * interface.
4263          *
4264          * @returns {null|Array&lt;LuCI.network.Device>}
4265          * Returns an array of of `Network.Device` class instances representing
4266          * the sub-devices attached to this logical interface or `null` if the
4267          * logical interface does not support sub-devices, e.g. because it is
4268          * virtual and not a bridge.
4269          */
4270         getDevices: function() {
4271                 var rv = [];
4272
4273                 if (!this.isBridge() &amp;&amp; !(this.isVirtual() &amp;&amp; !this.isFloating()))
4274                         return null;
4275
4276                 var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
4277
4278                 for (var i = 0; i &lt; ifnames.length; i++) {
4279                         if (ifnames[i].charAt(0) == '@')
4280                                 continue;
4281
4282                         var m = ifnames[i].match(/^([^:/]+)/);
4283                         if (m != null)
4284                                 rv.push(Network.prototype.instantiateDevice(m[1], this));
4285                 }
4286
4287                 var uciWifiIfaces = uci.sections('wireless', 'wifi-iface');
4288
4289                 for (var i = 0; i &lt; uciWifiIfaces.length; i++) {
4290                         if (typeof(uciWifiIfaces[i].device) != 'string')
4291                                 continue;
4292
4293                         var networks = L.toArray(uciWifiIfaces[i].network);
4294
4295                         for (var j = 0; j &lt; networks.length; j++) {
4296                                 if (networks[j] != this.sid)
4297                                         continue;
4298
4299                                 var netid = getWifiNetidBySid(uciWifiIfaces[i]['.name']);
4300
4301                                 if (netid != null)
4302                                         rv.push(Network.prototype.instantiateDevice(netid[0], this));
4303                         }
4304                 }
4305
4306                 rv.sort(deviceSort);
4307
4308                 return rv;
4309         },
4310
4311         /**
4312          * Checks whether this logical interface contains the given device
4313          * object.
4314          *
4315          * @param {LuCI.network.Protocol|LuCI.network.Device|LuCI.network.WifiDevice|LuCI.network.WifiNetwork|string} device
4316          * The object or device name to check. In case the given argument is not
4317          * a string, it is resolved though the
4318          * {@link LuCI.network#getIfnameOf Network.getIfnameOf()} function.
4319          *
4320          * @returns {boolean}
4321          * Returns `true` when this logical interface contains the given network
4322          * device or `false` if not.
4323          */
4324         containsDevice: function(ifname) {
4325                 ifname = ifnameOf(ifname);
4326
4327                 if (ifname == null)
4328                         return false;
4329                 else if (this.isVirtual() &amp;&amp; '%s-%s'.format(this.getProtocol(), this.sid) == ifname)
4330                         return true;
4331                 else if (this.isBridge() &amp;&amp; 'br-%s'.format(this.sid) == ifname)
4332                         return true;
4333
4334                 var ifnames = L.toArray(uci.get('network', this.sid, 'ifname'));
4335
4336                 for (var i = 0; i &lt; ifnames.length; i++) {
4337                         var m = ifnames[i].match(/^([^:/]+)/);
4338                         if (m != null &amp;&amp; m[1] == ifname)
4339                                 return true;
4340                 }
4341
4342                 var wif = getWifiSidByIfname(ifname);
4343
4344                 if (wif != null) {
4345                         var networks = L.toArray(uci.get('wireless', wif, 'network'));
4346
4347                         for (var i = 0; i &lt; networks.length; i++)
4348                                 if (networks[i] == this.sid)
4349                                         return true;
4350                 }
4351
4352                 return false;
4353         },
4354
4355         /**
4356          * Cleanup related configuration entries.
4357          *
4358          * This function will be invoked if an interface is about to be removed
4359          * from the configuration and is responsible for performing any required
4360          * cleanup tasks, such as unsetting uci entries in related configurations.
4361          *
4362          * It should be overwritten by protocol specific subclasses.
4363          *
4364          * @abstract
4365          *
4366          * @returns {*|Promise&lt;*>}
4367          * This function may return a promise which is awaited before the rest of
4368          * the configuration is removed. Any non-promise return value and any
4369          * resolved promise value is ignored. If the returned promise is rejected,
4370          * the interface removal will be aborted.
4371          */
4372         deleteConfiguration: function() {}
4373 });
4374
4375 /**
4376  * @class
4377  * @memberof LuCI.network
4378  * @hideconstructor
4379  * @classdesc
4380  *
4381  * A `Network.Device` class instance represents an underlying Linux network
4382  * device and allows querying device details such as packet statistics or MTU.
4383  */
4384 Device = baseclass.extend(/** @lends LuCI.network.Device.prototype */ {
4385         __init__: function(ifname, network) {
4386                 var wif = getWifiSidByIfname(ifname);
4387
4388                 if (wif != null) {
4389                         var res = getWifiStateBySid(wif) || [],
4390                             netid = getWifiNetidBySid(wif) || [];
4391
4392                         this.wif    = new WifiNetwork(wif, res[0], res[1], netid[0], res[2], { ifname: ifname });
4393                         this.ifname = this.wif.getIfname();
4394                 }
4395
4396                 this.ifname  = this.ifname || ifname;
4397                 this.dev     = _state.netdevs[this.ifname];
4398                 this.network = network;
4399         },
4400
4401         _devstate: function(/* ... */) {
4402                 var rv = this.dev;
4403
4404                 for (var i = 0; i &lt; arguments.length; i++)
4405                         if (L.isObject(rv))
4406                                 rv = rv[arguments[i]];
4407                         else
4408                                 return null;
4409
4410                 return rv;
4411         },
4412
4413         /**
4414          * Get the name of the network device.
4415          *
4416          * @returns {string}
4417          * Returns the name of the device, e.g. `eth0` or `wlan0`.
4418          */
4419         getName: function() {
4420                 return (this.wif != null ? this.wif.getIfname() : this.ifname);
4421         },
4422
4423         /**
4424          * Get the MAC address of the device.
4425          *
4426          * @returns {null|string}
4427          * Returns the MAC address of the device or `null` if not applicable,
4428          * e.g. for non-ethernet tunnel devices.
4429          */
4430         getMAC: function() {
4431                 var mac = this._devstate('macaddr');
4432                 return mac ? mac.toUpperCase() : null;
4433         },
4434
4435         /**
4436          * Get the MTU of the device.
4437          *
4438          * @returns {number}
4439          * Returns the MTU of the device.
4440          */
4441         getMTU: function() {
4442                 return this._devstate('mtu');
4443         },
4444
4445         /**
4446          * Get the IPv4 addresses configured on the device.
4447          *
4448          * @returns {string[]}
4449          * Returns an array of IPv4 address strings.
4450          */
4451         getIPAddrs: function() {
4452                 var addrs = this._devstate('ipaddrs');
4453                 return (Array.isArray(addrs) ? addrs : []);
4454         },
4455
4456         /**
4457          * Get the IPv6 addresses configured on the device.
4458          *
4459          * @returns {string[]}
4460          * Returns an array of IPv6 address strings.
4461          */
4462         getIP6Addrs: function() {
4463                 var addrs = this._devstate('ip6addrs');
4464                 return (Array.isArray(addrs) ? addrs : []);
4465         },
4466
4467         /**
4468          * Get the type of the device..
4469          *
4470          * @returns {string}
4471          * Returns a string describing the type of the network device:
4472          *  - `alias` if it is an abstract alias device (`@` notation)
4473          *  - `wifi` if it is a wireless interface (e.g. `wlan0`)
4474          *  - `bridge` if it is a bridge device (e.g. `br-lan`)
4475          *  - `tunnel` if it is a tun or tap device (e.g. `tun0`)
4476          *  - `vlan` if it is a vlan device (e.g. `eth0.1`)
4477          *  - `switch` if it is a switch device (e.g.`eth1` connected to switch0)
4478          *  - `ethernet` for all other device types
4479          */
4480         getType: function() {
4481                 if (this.ifname != null &amp;&amp; this.ifname.charAt(0) == '@')
4482                         return 'alias';
4483                 else if (this.wif != null || isWifiIfname(this.ifname))
4484                         return 'wifi';
4485                 else if (_state.isBridge[this.ifname])
4486                         return 'bridge';
4487                 else if (_state.isTunnel[this.ifname])
4488                         return 'tunnel';
4489                 else if (this.ifname.indexOf('.') > -1)
4490                         return 'vlan';
4491                 else if (_state.isSwitch[this.ifname])
4492                         return 'switch';
4493                 else
4494                         return 'ethernet';
4495         },
4496
4497         /**
4498          * Get a short description string for the device.
4499          *
4500          * @returns {string}
4501          * Returns the device name for non-wifi devices or a string containing
4502          * the operation mode and SSID for wifi devices.
4503          */
4504         getShortName: function() {
4505                 if (this.wif != null)
4506                         return this.wif.getShortName();
4507
4508                 return this.ifname;
4509         },
4510
4511         /**
4512          * Get a long description string for the device.
4513          *
4514          * @returns {string}
4515          * Returns a string containing the type description and device name
4516          * for non-wifi devices or operation mode and ssid for wifi ones.
4517          */
4518         getI18n: function() {
4519                 if (this.wif != null) {
4520                         return '%s: %s "%s"'.format(
4521                                 _('Wireless Network'),
4522                                 this.wif.getActiveMode(),
4523                                 this.wif.getActiveSSID() || this.wif.getActiveBSSID() || this.wif.getID() || '?');
4524                 }
4525
4526                 return '%s: "%s"'.format(this.getTypeI18n(), this.getName());
4527         },
4528
4529         /**
4530          * Get a string describing the device type.
4531          *
4532          * @returns {string}
4533          * Returns a string describing the type, e.g. "Wireless Adapter" or
4534          * "Bridge".
4535          */
4536         getTypeI18n: function() {
4537                 switch (this.getType()) {
4538                 case 'alias':
4539                         return _('Alias Interface');
4540
4541                 case 'wifi':
4542                         return _('Wireless Adapter');
4543
4544                 case 'bridge':
4545                         return _('Bridge');
4546
4547                 case 'switch':
4548                         return _('Ethernet Switch');
4549
4550                 case 'vlan':
4551                         return (_state.isSwitch[this.ifname] ? _('Switch VLAN') : _('Software VLAN'));
4552
4553                 case 'tunnel':
4554                         return _('Tunnel Interface');
4555
4556                 default:
4557                         return _('Ethernet Adapter');
4558                 }
4559         },
4560
4561         /**
4562          * Get the associated bridge ports of the device.
4563          *
4564          * @returns {null|Array&lt;LuCI.network.Device>}
4565          * Returns an array of `Network.Device` instances representing the ports
4566          * (slave interfaces) of the bridge or `null` when this device isn't
4567          * a Linux bridge.
4568          */
4569         getPorts: function() {
4570                 var br = _state.bridges[this.ifname],
4571                     rv = [];
4572
4573                 if (br == null || !Array.isArray(br.ifnames))
4574                         return null;
4575
4576                 for (var i = 0; i &lt; br.ifnames.length; i++)
4577                         rv.push(Network.prototype.instantiateDevice(br.ifnames[i].name));
4578
4579                 rv.sort(deviceSort);
4580
4581                 return rv;
4582         },
4583
4584         /**
4585          * Get the bridge ID
4586          *
4587          * @returns {null|string}
4588          * Returns the ID of this network bridge or `null` if this network
4589          * device is not a Linux bridge.
4590          */
4591         getBridgeID: function() {
4592                 var br = _state.bridges[this.ifname];
4593                 return (br != null ? br.id : null);
4594         },
4595
4596         /**
4597          * Get the bridge STP setting
4598          *
4599          * @returns {boolean}
4600          * Returns `true` when this device is a Linux bridge and has `stp`
4601          * enabled, else `false`.
4602          */
4603         getBridgeSTP: function() {
4604                 var br = _state.bridges[this.ifname];
4605                 return (br != null ? !!br.stp : false);
4606         },
4607
4608         /**
4609          * Checks whether this device is up.
4610          *
4611          * @returns {boolean}
4612          * Returns `true` when the associated device is running pr `false`
4613          * when it is down or absent.
4614          */
4615         isUp: function() {
4616                 var up = this._devstate('flags', 'up');
4617
4618                 if (up == null)
4619                         up = (this.getType() == 'alias');
4620
4621                 return up;
4622         },
4623
4624         /**
4625          * Checks whether this device is a Linux bridge.
4626          *
4627          * @returns {boolean}
4628          * Returns `true` when the network device is present and a Linux bridge,
4629          * else `false`.
4630          */
4631         isBridge: function() {
4632                 return (this.getType() == 'bridge');
4633         },
4634
4635         /**
4636          * Checks whether this device is part of a Linux bridge.
4637          *
4638          * @returns {boolean}
4639          * Returns `true` when this network device is part of a bridge,
4640          * else `false`.
4641          */
4642         isBridgePort: function() {
4643                 return (this._devstate('bridge') != null);
4644         },
4645
4646         /**
4647          * Get the amount of transmitted bytes.
4648          *
4649          * @returns {number}
4650          * Returns the amount of bytes transmitted by the network device.
4651          */
4652         getTXBytes: function() {
4653                 var stat = this._devstate('stats');
4654                 return (stat != null ? stat.tx_bytes || 0 : 0);
4655         },
4656
4657         /**
4658          * Get the amount of received bytes.
4659          *
4660          * @returns {number}
4661          * Returns the amount of bytes received by the network device.
4662          */
4663         getRXBytes: function() {
4664                 var stat = this._devstate('stats');
4665                 return (stat != null ? stat.rx_bytes || 0 : 0);
4666         },
4667
4668         /**
4669          * Get the amount of transmitted packets.
4670          *
4671          * @returns {number}
4672          * Returns the amount of packets transmitted by the network device.
4673          */
4674         getTXPackets: function() {
4675                 var stat = this._devstate('stats');
4676                 return (stat != null ? stat.tx_packets || 0 : 0);
4677         },
4678
4679         /**
4680          * Get the amount of received packets.
4681          *
4682          * @returns {number}
4683          * Returns the amount of packets received by the network device.
4684          */
4685         getRXPackets: function() {
4686                 var stat = this._devstate('stats');
4687                 return (stat != null ? stat.rx_packets || 0 : 0);
4688         },
4689
4690         /**
4691          * Get the primary logical interface this device is assigned to.
4692          *
4693          * @returns {null|LuCI.network.Protocol}
4694          * Returns a `Network.Protocol` instance representing the logical
4695          * interface this device is attached to or `null` if it is not
4696          * assigned to any logical interface.
4697          */
4698         getNetwork: function() {
4699                 return this.getNetworks()[0];
4700         },
4701
4702         /**
4703          * Get the logical interfaces this device is assigned to.
4704          *
4705          * @returns {Array&lt;LuCI.network.Protocol>}
4706          * Returns an array of `Network.Protocol` instances representing the
4707          * logical interfaces this device is assigned to.
4708          */
4709         getNetworks: function() {
4710                 if (this.networks == null) {
4711                         this.networks = [];
4712
4713                         var networks = enumerateNetworks.apply(L.network);
4714
4715                         for (var i = 0; i &lt; networks.length; i++)
4716                                 if (networks[i].containsDevice(this.ifname) || networks[i].getIfname() == this.ifname)
4717                                         this.networks.push(networks[i]);
4718
4719                         this.networks.sort(networkSort);
4720                 }
4721
4722                 return this.networks;
4723         },
4724
4725         /**
4726          * Get the related wireless network this device is related to.
4727          *
4728          * @returns {null|LuCI.network.WifiNetwork}
4729          * Returns a `Network.WifiNetwork` instance representing the wireless
4730          * network corresponding to this network device or `null` if this device
4731          * is not a wireless device.
4732          */
4733         getWifiNetwork: function() {
4734                 return (this.wif != null ? this.wif : null);
4735         }
4736 });
4737
4738 /**
4739  * @class
4740  * @memberof LuCI.network
4741  * @hideconstructor
4742  * @classdesc
4743  *
4744  * A `Network.WifiDevice` class instance represents a wireless radio device
4745  * present on the system and provides wireless capability information as
4746  * well as methods for enumerating related wireless networks.
4747  */
4748 WifiDevice = baseclass.extend(/** @lends LuCI.network.WifiDevice.prototype */ {
4749         __init__: function(name, radiostate) {
4750                 var uciWifiDevice = uci.get('wireless', name);
4751
4752                 if (uciWifiDevice != null &amp;&amp;
4753                     uciWifiDevice['.type'] == 'wifi-device' &amp;&amp;
4754                     uciWifiDevice['.name'] != null) {
4755                         this.sid    = uciWifiDevice['.name'];
4756                 }
4757
4758                 this.sid    = this.sid || name;
4759                 this._ubusdata = {
4760                         radio: name,
4761                         dev:   radiostate
4762                 };
4763         },
4764
4765         /* private */
4766         ubus: function(/* ... */) {
4767                 var v = this._ubusdata;
4768
4769                 for (var i = 0; i &lt; arguments.length; i++)
4770                         if (L.isObject(v))
4771                                 v = v[arguments[i]];
4772                         else
4773                                 return null;
4774
4775                 return v;
4776         },
4777
4778         /**
4779          * Read the given UCI option value of this wireless device.
4780          *
4781          * @param {string} opt
4782          * The UCI option name to read.
4783          *
4784          * @returns {null|string|string[]}
4785          * Returns the UCI option value or `null` if the requested option is
4786          * not found.
4787          */
4788         get: function(opt) {
4789                 return uci.get('wireless', this.sid, opt);
4790         },
4791
4792         /**
4793          * Set the given UCI option of this network to the given value.
4794          *
4795          * @param {string} opt
4796          * The name of the UCI option to set.
4797          *
4798          * @param {null|string|string[]} val
4799          * The value to set or `null` to remove the given option from the
4800          * configuration.
4801          */
4802         set: function(opt, value) {
4803                 return uci.set('wireless', this.sid, opt, value);
4804         },
4805
4806         /**
4807          * Checks whether this wireless radio is disabled.
4808          *
4809          * @returns {boolean}
4810          * Returns `true` when the wireless radio is marked as disabled in `ubus`
4811          * runtime state or when the `disabled` option is set in the corresponding
4812          * UCI configuration.
4813          */
4814         isDisabled: function() {
4815                 return this.ubus('dev', 'disabled') || this.get('disabled') == '1';
4816         },
4817
4818         /**
4819          * Get the configuration name of this wireless radio.
4820          *
4821          * @returns {string}
4822          * Returns the UCI section name (e.g. `radio0`) of the corresponding
4823          * radio configuration which also serves as unique logical identifier
4824          * for the wireless phy.
4825          */
4826         getName: function() {
4827                 return this.sid;
4828         },
4829
4830         /**
4831          * Gets a list of supported hwmodes.
4832          *
4833          * The hwmode values describe the frequency band and wireless standard
4834          * versions supported by the wireless phy.
4835          *
4836          * @returns {string[]}
4837          * Returns an array of valid hwmode values for this radio. Currently
4838          * known mode values are:
4839          *  - `a` - Legacy 802.11a mode, 5 GHz, up to 54 Mbit/s
4840          *  - `b` - Legacy 802.11b mode, 2.4 GHz, up to 11 Mbit/s
4841          *  - `g` - Legacy 802.11g mode, 2.4 GHz, up to 54 Mbit/s
4842          *  - `n` - IEEE 802.11n mode, 2.4 or 5 GHz, up to 600 Mbit/s
4843          *  - `ac` - IEEE 802.11ac mode, 5 GHz, up to 6770 Mbit/s
4844          */
4845         getHWModes: function() {
4846                 var hwmodes = this.ubus('dev', 'iwinfo', 'hwmodes');
4847                 return Array.isArray(hwmodes) ? hwmodes : [ 'b', 'g' ];
4848         },
4849
4850         /**
4851          * Gets a list of supported htmodes.
4852          *
4853          * The htmode values describe the wide-frequency options supported by
4854          * the wireless phy.
4855          *
4856          * @returns {string[]}
4857          * Returns an array of valid htmode values for this radio. Currently
4858          * known mode values are:
4859          *  - `HT20` - applicable to IEEE 802.11n, 20 MHz wide channels
4860          *  - `HT40` - applicable to IEEE 802.11n, 40 MHz wide channels
4861          *  - `VHT20` - applicable to IEEE 802.11ac, 20 MHz wide channels
4862          *  - `VHT40` - applicable to IEEE 802.11ac, 40 MHz wide channels
4863          *  - `VHT80` - applicable to IEEE 802.11ac, 80 MHz wide channels
4864          *  - `VHT160` - applicable to IEEE 802.11ac, 160 MHz wide channels
4865          */
4866         getHTModes: function() {
4867                 var htmodes = this.ubus('dev', 'iwinfo', 'htmodes');
4868                 return (Array.isArray(htmodes) &amp;&amp; htmodes.length) ? htmodes : null;
4869         },
4870
4871         /**
4872          * Get a string describing the wireless radio hardware.
4873          *
4874          * @returns {string}
4875          * Returns the description string.
4876          */
4877         getI18n: function() {
4878                 var hw = this.ubus('dev', 'iwinfo', 'hardware'),
4879                     type = L.isObject(hw) ? hw.name : null;
4880
4881                 if (this.ubus('dev', 'iwinfo', 'type') == 'wl')
4882                         type = 'Broadcom';
4883
4884                 var hwmodes = this.getHWModes(),
4885                     modestr = '';
4886
4887                 hwmodes.sort(function(a, b) {
4888                         return (a.length != b.length ? a.length > b.length : a > b);
4889                 });
4890
4891                 modestr = hwmodes.join('');
4892
4893                 return '%s 802.11%s Wireless Controller (%s)'.format(type || 'Generic', modestr, this.getName());
4894         },
4895
4896         /**
4897          * A wireless scan result object describes a neighbouring wireless
4898          * network found in the vincinity.
4899          *
4900          * @typedef {Object&lt;string, number|string|LuCI.network.WifiEncryption>} WifiScanResult
4901          * @memberof LuCI.network
4902          *
4903          * @property {string} ssid
4904          * The SSID / Mesh ID of the network.
4905          *
4906          * @property {string} bssid
4907          * The BSSID if the network.
4908          *
4909          * @property {string} mode
4910          * The operation mode of the network (`Master`, `Ad-Hoc`, `Mesh Point`).
4911          *
4912          * @property {number} channel
4913          * The wireless channel of the network.
4914          *
4915          * @property {number} signal
4916          * The received signal strength of the network in dBm.
4917          *
4918          * @property {number} quality
4919          * The numeric quality level of the signal, can be used in conjunction
4920          * with `quality_max` to calculate a quality percentage.
4921          *
4922          * @property {number} quality_max
4923          * The maximum possible quality level of the signal, can be used in
4924          * conjunction with `quality` to calculate a quality percentage.
4925          *
4926          * @property {LuCI.network.WifiEncryption} encryption
4927          * The encryption used by the wireless network.
4928          */
4929
4930         /**
4931          * Trigger a wireless scan on this radio device and obtain a list of
4932          * nearby networks.
4933          *
4934          * @returns {Promise&lt;Array&lt;LuCI.network.WifiScanResult>>}
4935          * Returns a promise resolving to an array of scan result objects
4936          * describing the networks found in the vincinity.
4937          */
4938         getScanList: function() {
4939                 return callIwinfoScan(this.sid);
4940         },
4941
4942         /**
4943          * Check whether the wireless radio is marked as up in the `ubus`
4944          * runtime state.
4945          *
4946          * @returns {boolean}
4947          * Returns `true` when the radio device is up, else `false`.
4948          */
4949         isUp: function() {
4950                 if (L.isObject(_state.radios[this.sid]))
4951                         return (_state.radios[this.sid].up == true);
4952
4953                 return false;
4954         },
4955
4956         /**
4957          * Get the wifi network of the given name belonging to this radio device
4958          *
4959          * @param {string} network
4960          * The name of the wireless network to lookup. This may be either an uci
4961          * configuration section ID, a network ID in the form `radio#.network#`
4962          * or a Linux network device name like `wlan0` which is resolved to the
4963          * corresponding configuration section through `ubus` runtime information.
4964          *
4965          * @returns {Promise&lt;LuCI.network.WifiNetwork>}
4966          * Returns a promise resolving to a `Network.WifiNetwork` instance
4967          * representing the wireless network and rejecting with `null` if
4968          * the given network could not be found or is not associated with
4969          * this radio device.
4970          */
4971         getWifiNetwork: function(network) {
4972                 return Network.prototype.getWifiNetwork(network).then(L.bind(function(networkInstance) {
4973                         var uciWifiIface = (networkInstance.sid ? uci.get('wireless', networkInstance.sid) : null);
4974
4975                         if (uciWifiIface == null || uciWifiIface['.type'] != 'wifi-iface' || uciWifiIface.device != this.sid)
4976                                 return Promise.reject();
4977
4978                         return networkInstance;
4979                 }, this));
4980         },
4981
4982         /**
4983          * Get all wireless networks associated with this wireless radio device.
4984          *
4985          * @returns {Promise&lt;Array&lt;LuCI.network.WifiNetwork>>}
4986          * Returns a promise resolving to an array of `Network.WifiNetwork`
4987          * instances respresenting the wireless networks associated with this
4988          * radio device.
4989          */
4990         getWifiNetworks: function() {
4991                 return Network.prototype.getWifiNetworks().then(L.bind(function(networks) {
4992                         var rv = [];
4993
4994                         for (var i = 0; i &lt; networks.length; i++)
4995                                 if (networks[i].getWifiDeviceName() == this.getName())
4996                                         rv.push(networks[i]);
4997
4998                         return rv;
4999                 }, this));
5000         },
5001
5002         /**
5003          * Adds a new wireless network associated with this radio device to the
5004          * configuration and sets its options to the provided values.
5005          *
5006          * @param {Object&lt;string, string|string[]>} [options]
5007          * The options to set for the newly added wireless network.
5008          *
5009          * @returns {Promise&lt;null|LuCI.network.WifiNetwork>}
5010          * Returns a promise resolving to a `WifiNetwork` instance describing
5011          * the newly added wireless network or `null` if the given options
5012          * were invalid.
5013          */
5014         addWifiNetwork: function(options) {
5015                 if (!L.isObject(options))
5016                         options = {};
5017
5018                 options.device = this.sid;
5019
5020                 return Network.prototype.addWifiNetwork(options);
5021         },
5022
5023         /**
5024          * Deletes the wireless network with the given name associated with this
5025          * radio device.
5026          *
5027          * @param {string} network
5028          * The name of the wireless network to lookup. This may be either an uci
5029          * configuration section ID, a network ID in the form `radio#.network#`
5030          * or a Linux network device name like `wlan0` which is resolved to the
5031          * corresponding configuration section through `ubus` runtime information.
5032          *
5033          * @returns {Promise&lt;boolean>}
5034          * Returns a promise resolving to `true` when the wireless network was
5035          * successfully deleted from the configuration or `false` when the given
5036          * network could not be found or if the found network was not associated
5037          * with this wireless radio device.
5038          */
5039         deleteWifiNetwork: function(network) {
5040                 var sid = null;
5041
5042                 if (network instanceof WifiNetwork) {
5043                         sid = network.sid;
5044                 }
5045                 else {
5046                         var uciWifiIface = uci.get('wireless', network);
5047
5048                         if (uciWifiIface == null || uciWifiIface['.type'] != 'wifi-iface')
5049                                 sid = getWifiSidByIfname(network);
5050                 }
5051
5052                 if (sid == null || uci.get('wireless', sid, 'device') != this.sid)
5053                         return Promise.resolve(false);
5054
5055                 uci.delete('wireless', network);
5056
5057                 return Promise.resolve(true);
5058         }
5059 });
5060
5061 /**
5062  * @class
5063  * @memberof LuCI.network
5064  * @hideconstructor
5065  * @classdesc
5066  *
5067  * A `Network.WifiNetwork` instance represents a wireless network (vif)
5068  * configured on top of a radio device and provides functions for querying
5069  * the runtime state of the network. Most radio devices support multiple
5070  * such networks in parallel.
5071  */
5072 WifiNetwork = baseclass.extend(/** @lends LuCI.network.WifiNetwork.prototype */ {
5073         __init__: function(sid, radioname, radiostate, netid, netstate, hostapd) {
5074                 this.sid    = sid;
5075                 this.netid  = netid;
5076                 this._ubusdata = {
5077                         hostapd: hostapd,
5078                         radio:   radioname,
5079                         dev:     radiostate,
5080                         net:     netstate
5081                 };
5082         },
5083
5084         ubus: function(/* ... */) {
5085                 var v = this._ubusdata;
5086
5087                 for (var i = 0; i &lt; arguments.length; i++)
5088                         if (L.isObject(v))
5089                                 v = v[arguments[i]];
5090                         else
5091                                 return null;
5092
5093                 return v;
5094         },
5095
5096         /**
5097          * Read the given UCI option value of this wireless network.
5098          *
5099          * @param {string} opt
5100          * The UCI option name to read.
5101          *
5102          * @returns {null|string|string[]}
5103          * Returns the UCI option value or `null` if the requested option is
5104          * not found.
5105          */
5106         get: function(opt) {
5107                 return uci.get('wireless', this.sid, opt);
5108         },
5109
5110         /**
5111          * Set the given UCI option of this network to the given value.
5112          *
5113          * @param {string} opt
5114          * The name of the UCI option to set.
5115          *
5116          * @param {null|string|string[]} val
5117          * The value to set or `null` to remove the given option from the
5118          * configuration.
5119          */
5120         set: function(opt, value) {
5121                 return uci.set('wireless', this.sid, opt, value);
5122         },
5123
5124         /**
5125          * Checks whether this wireless network is disabled.
5126          *
5127          * @returns {boolean}
5128          * Returns `true` when the wireless radio is marked as disabled in `ubus`
5129          * runtime state or when the `disabled` option is set in the corresponding
5130          * UCI configuration.
5131          */
5132         isDisabled: function() {
5133                 return this.ubus('dev', 'disabled') || this.get('disabled') == '1';
5134         },
5135
5136         /**
5137          * Get the configured operation mode of the wireless network.
5138          *
5139          * @returns {string}
5140          * Returns the configured operation mode. Possible values are:
5141          *  - `ap` - Master (Access Point) mode
5142          *  - `sta` - Station (client) mode
5143          *  - `adhoc` - Ad-Hoc (IBSS) mode
5144          *  - `mesh` - Mesh (IEEE 802.11s) mode
5145          *  - `monitor` - Monitor mode
5146          */
5147         getMode: function() {
5148                 return this.ubus('net', 'config', 'mode') || this.get('mode') || 'ap';
5149         },
5150
5151         /**
5152          * Get the configured SSID of the wireless network.
5153          *
5154          * @returns {null|string}
5155          * Returns the configured SSID value or `null` when this network is
5156          * in mesh mode.
5157          */
5158         getSSID: function() {
5159                 if (this.getMode() == 'mesh')
5160                         return null;
5161
5162                 return this.ubus('net', 'config', 'ssid') || this.get('ssid');
5163         },
5164
5165         /**
5166          * Get the configured Mesh ID of the wireless network.
5167          *
5168          * @returns {null|string}
5169          * Returns the configured mesh ID value or `null` when this network
5170          * is not in mesh mode.
5171          */
5172         getMeshID: function() {
5173                 if (this.getMode() != 'mesh')
5174                         return null;
5175
5176                 return this.ubus('net', 'config', 'mesh_id') || this.get('mesh_id');
5177         },
5178
5179         /**
5180          * Get the configured BSSID of the wireless network.
5181          *
5182          * @returns {null|string}
5183          * Returns the BSSID value or `null` if none has been specified.
5184          */
5185         getBSSID: function() {
5186                 return this.ubus('net', 'config', 'bssid') || this.get('bssid');
5187         },
5188
5189         /**
5190          * Get the names of the logical interfaces this wireless network is
5191          * attached to.
5192          *
5193          * @returns {string[]}
5194          * Returns an array of logical interface names.
5195          */
5196         getNetworkNames: function() {
5197                 return L.toArray(this.ubus('net', 'config', 'network') || this.get('network'));
5198         },
5199
5200         /**
5201          * Get the internal network ID of this wireless network.
5202          *
5203          * The network ID is a LuCI specific identifer in the form
5204          * `radio#.network#` to identify wireless networks by their corresponding
5205          * radio and network index numbers.
5206          *
5207          * @returns {string}
5208          * Returns the LuCI specific network ID.
5209          */
5210         getID: function() {
5211                 return this.netid;
5212         },
5213
5214         /**
5215          * Get the configuration ID of this wireless network.
5216          *
5217          * @returns {string}
5218          * Returns the corresponding UCI section ID of the network.
5219          */
5220         getName: function() {
5221                 return this.sid;
5222         },
5223
5224         /**
5225          * Get the Linux network device name.
5226          *
5227          * @returns {null|string}
5228          * Returns the current Linux network device name as resolved from
5229          * `ubus` runtime information or `null` if this network has no
5230          * associated network device, e.g. when not configured or up.
5231          */
5232         getIfname: function() {
5233                 var ifname = this.ubus('net', 'ifname') || this.ubus('net', 'iwinfo', 'ifname');
5234
5235                 if (ifname == null || ifname.match(/^(wifi|radio)\d/))
5236                         ifname = this.netid;
5237
5238                 return ifname;
5239         },
5240
5241         /**
5242          * Get the name of the corresponding wifi radio device.
5243          *
5244          * @returns {null|string}
5245          * Returns the name of the radio device this network is configured on
5246          * or `null` if it cannot be determined.
5247          */
5248         getWifiDeviceName: function() {
5249                 return this.ubus('radio') || this.get('device');
5250         },
5251
5252         /**
5253          * Get the corresponding wifi radio device.
5254          *
5255          * @returns {null|LuCI.network.WifiDevice}
5256          * Returns a `Network.WifiDevice` instance representing the corresponding
5257          * wifi radio device or `null` if the related radio device could not be
5258          * found.
5259          */
5260         getWifiDevice: function() {
5261                 var radioname = this.getWifiDeviceName();
5262
5263                 if (radioname == null)
5264                         return Promise.reject();
5265
5266                 return Network.prototype.getWifiDevice(radioname);
5267         },
5268
5269         /**
5270          * Check whether the radio network is up.
5271          *
5272          * This function actually queries the up state of the related radio
5273          * device and assumes this network to be up as well when the parent
5274          * radio is up. This is due to the fact that OpenWrt does not control
5275          * virtual interfaces individually but within one common hostapd
5276          * instance.
5277          *
5278          * @returns {boolean}
5279          * Returns `true` when the network is up, else `false`.
5280          */
5281         isUp: function() {
5282                 var device = this.getDevice();
5283
5284                 if (device == null)
5285                         return false;
5286
5287                 return device.isUp();
5288         },
5289
5290         /**
5291          * Query the current operation mode from runtime information.
5292          *
5293          * @returns {string}
5294          * Returns the human readable mode name as reported by `ubus` runtime
5295          * state. Possible returned values are:
5296          *  - `Master`
5297          *  - `Ad-Hoc`
5298          *  - `Client`
5299          *  - `Monitor`
5300          *  - `Master (VLAN)`
5301          *  - `WDS`
5302          *  - `Mesh Point`
5303          *  - `P2P Client`
5304          *  - `P2P Go`
5305          *  - `Unknown`
5306          */
5307         getActiveMode: function() {
5308                 var mode = this.ubus('net', 'iwinfo', 'mode') || this.ubus('net', 'config', 'mode') || this.get('mode') || 'ap';
5309
5310                 switch (mode) {
5311                 case 'ap':      return 'Master';
5312                 case 'sta':     return 'Client';
5313                 case 'adhoc':   return 'Ad-Hoc';
5314                 case 'mesh':    return 'Mesh';
5315                 case 'monitor': return 'Monitor';
5316                 default:        return mode;
5317                 }
5318         },
5319
5320         /**
5321          * Query the current operation mode from runtime information as
5322          * translated string.
5323          *
5324          * @returns {string}
5325          * Returns the translated, human readable mode name as reported by
5326          *`ubus` runtime state.
5327          */
5328         getActiveModeI18n: function() {
5329                 var mode = this.getActiveMode();
5330
5331                 switch (mode) {
5332                 case 'Master':  return _('Master');
5333                 case 'Client':  return _('Client');
5334                 case 'Ad-Hoc':  return _('Ad-Hoc');
5335                 case 'Mash':    return _('Mesh');
5336                 case 'Monitor': return _('Monitor');
5337                 default:        return mode;
5338                 }
5339         },
5340
5341         /**
5342          * Query the current SSID from runtime information.
5343          *
5344          * @returns {string}
5345          * Returns the current SSID or Mesh ID as reported by `ubus` runtime
5346          * information.
5347          */
5348         getActiveSSID: function() {
5349                 return this.ubus('net', 'iwinfo', 'ssid') || this.ubus('net', 'config', 'ssid') || this.get('ssid');
5350         },
5351
5352         /**
5353          * Query the current BSSID from runtime information.
5354          *
5355          * @returns {string}
5356          * Returns the current BSSID or Mesh ID as reported by `ubus` runtime
5357          * information.
5358          */
5359         getActiveBSSID: function() {
5360                 return this.ubus('net', 'iwinfo', 'bssid') || this.ubus('net', 'config', 'bssid') || this.get('bssid');
5361         },
5362
5363         /**
5364          * Query the current encryption settings from runtime information.
5365          *
5366          * @returns {string}
5367          * Returns a string describing the current encryption or `-` if the the
5368          * encryption state could not be found in `ubus` runtime information.
5369          */
5370         getActiveEncryption: function() {
5371                 return formatWifiEncryption(this.ubus('net', 'iwinfo', 'encryption')) || '-';
5372         },
5373
5374         /**
5375          * A wireless peer entry describes the properties of a remote wireless
5376          * peer associated with a local network.
5377          *
5378          * @typedef {Object&lt;string, boolean|number|string|LuCI.network.WifiRateEntry>} WifiPeerEntry
5379          * @memberof LuCI.network
5380          *
5381          * @property {string} mac
5382          * The MAC address (BSSID).
5383          *
5384          * @property {number} signal
5385          * The received signal strength.
5386          *
5387          * @property {number} [signal_avg]
5388          * The average signal strength if supported by the driver.
5389          *
5390          * @property {number} [noise]
5391          * The current noise floor of the radio. May be `0` or absent if not
5392          * supported by the driver.
5393          *
5394          * @property {number} inactive
5395          * The amount of milliseconds the peer has been inactive, e.g. due
5396          * to powersave.
5397          *
5398          * @property {number} connected_time
5399          * The amount of milliseconds the peer is associated to this network.
5400          *
5401          * @property {number} [thr]
5402          * The estimated throughput of the peer, May be `0` or absent if not
5403          * supported by the driver.
5404          *
5405          * @property {boolean} authorized
5406          * Specifies whether the peer is authorized to associate to this network.
5407          *
5408          * @property {boolean} authenticated
5409          * Specifies whether the peer completed authentication to this network.
5410          *
5411          * @property {string} preamble
5412          * The preamble mode used by the peer. May be `long` or `short`.
5413          *
5414          * @property {boolean} wme
5415          * Specifies whether the peer supports WME/WMM capabilities.
5416          *
5417          * @property {boolean} mfp
5418          * Specifies whether management frame protection is active.
5419          *
5420          * @property {boolean} tdls
5421          * Specifies whether TDLS is active.
5422          *
5423          * @property {number} [mesh llid]
5424          * The mesh LLID, may be `0` or absent if not applicable or supported
5425          * by the driver.
5426          *
5427          * @property {number} [mesh plid]
5428          * The mesh PLID, may be `0` or absent if not applicable or supported
5429          * by the driver.
5430          *
5431          * @property {string} [mesh plink]
5432          * The mesh peer link state description, may be an empty string (`''`)
5433          * or absent if not applicable or supported by the driver.
5434          *
5435          * The following states are known:
5436          *  - `LISTEN`
5437          *  - `OPN_SNT`
5438          *  - `OPN_RCVD`
5439          *  - `CNF_RCVD`
5440          *  - `ESTAB`
5441          *  - `HOLDING`
5442          *  - `BLOCKED`
5443          *  - `UNKNOWN`
5444          *
5445          * @property {number} [mesh local PS]
5446          * The local powersafe mode for the peer link, may be an empty
5447          * string (`''`) or absent if not applicable or supported by
5448          * the driver.
5449          *
5450          * The following modes are known:
5451          *  - `ACTIVE` (no power save)
5452          *  - `LIGHT SLEEP`
5453          *  - `DEEP SLEEP`
5454          *  - `UNKNOWN`
5455          *
5456          * @property {number} [mesh peer PS]
5457          * The remote powersafe mode for the peer link, may be an empty
5458          * string (`''`) or absent if not applicable or supported by
5459          * the driver.
5460          *
5461          * The following modes are known:
5462          *  - `ACTIVE` (no power save)
5463          *  - `LIGHT SLEEP`
5464          *  - `DEEP SLEEP`
5465          *  - `UNKNOWN`
5466          *
5467          * @property {number} [mesh non-peer PS]
5468          * The powersafe mode for all non-peer neigbours, may be an empty
5469          * string (`''`) or absent if not applicable or supported by the driver.
5470          *
5471          * The following modes are known:
5472          *  - `ACTIVE` (no power save)
5473          *  - `LIGHT SLEEP`
5474          *  - `DEEP SLEEP`
5475          *  - `UNKNOWN`
5476          *
5477          * @property {LuCI.network.WifiRateEntry} rx
5478          * Describes the receiving wireless rate from the peer.
5479          *
5480          * @property {LuCI.network.WifiRateEntry} tx
5481          * Describes the transmitting wireless rate to the peer.
5482          */
5483
5484         /**
5485          * A wireless rate entry describes the properties of a wireless
5486          * transmission rate to or from a peer.
5487          *
5488          * @typedef {Object&lt;string, boolean|number>} WifiRateEntry
5489          * @memberof LuCI.network
5490          *
5491          * @property {number} [drop_misc]
5492          * The amount of received misc. packages that have been dropped, e.g.
5493          * due to corruption or missing authentication. Only applicable to
5494          * receiving rates.
5495          *
5496          * @property {number} packets
5497          * The amount of packets that have been received or sent.
5498          *
5499          * @property {number} bytes
5500          * The amount of bytes that have been received or sent.
5501          *
5502          * @property {number} [failed]
5503          * The amount of failed tranmission attempts. Only applicable to
5504          * transmit rates.
5505          *
5506          * @property {number} [retries]
5507          * The amount of retried transmissions. Only applicable to transmit
5508          * rates.
5509          *
5510          * @property {boolean} is_ht
5511          * Specifies whether this rate is an HT (IEEE 802.11n) rate.
5512          *
5513          * @property {boolean} is_vht
5514          * Specifies whether this rate is an VHT (IEEE 802.11ac) rate.
5515          *
5516          * @property {number} mhz
5517          * The channel width in MHz used for the transmission.
5518          *
5519          * @property {number} rate
5520          * The bitrate in bit/s of the transmission.
5521          *
5522          * @property {number} [mcs]
5523          * The MCS index of the used transmission rate. Only applicable to
5524          * HT or VHT rates.
5525          *
5526          * @property {number} [40mhz]
5527          * Specifies whether the tranmission rate used 40MHz wide channel.
5528          * Only applicable to HT or VHT rates.
5529          *
5530          * Note: this option exists for backwards compatibility only and its
5531          * use is discouraged. The `mhz` field should be used instead to
5532          * determine the channel width.
5533          *
5534          * @property {boolean} [short_gi]
5535          * Specifies whether a short guard interval is used for the transmission.
5536          * Only applicable to HT or VHT rates.
5537          *
5538          * @property {number} [nss]
5539          * Specifies the number of spatial streams used by the transmission.
5540          * Only applicable to VHT rates.
5541          */
5542
5543         /**
5544          * Fetch the list of associated peers.
5545          *
5546          * @returns {Promise&lt;Array&lt;LuCI.network.WifiPeerEntry>>}
5547          * Returns a promise resolving to an array of wireless peers associated
5548          * with this network.
5549          */
5550         getAssocList: function() {
5551                 return callIwinfoAssoclist(this.getIfname());
5552         },
5553
5554         /**
5555          * Query the current operating frequency of the wireless network.
5556          *
5557          * @returns {null|string}
5558          * Returns the current operating frequency of the network from `ubus`
5559          * runtime information in GHz or `null` if the information is not
5560          * available.
5561          */
5562         getFrequency: function() {
5563                 var freq = this.ubus('net', 'iwinfo', 'frequency');
5564
5565                 if (freq != null &amp;&amp; freq > 0)
5566                         return '%.03f'.format(freq / 1000);
5567
5568                 return null;
5569         },
5570
5571         /**
5572          * Query the current average bitrate of all peers associated to this
5573          * wireless network.
5574          *
5575          * @returns {null|number}
5576          * Returns the average bit rate among all peers associated to the network
5577          * as reported by `ubus` runtime information or `null` if the information
5578          * is not available.
5579          */
5580         getBitRate: function() {
5581                 var rate = this.ubus('net', 'iwinfo', 'bitrate');
5582
5583                 if (rate != null &amp;&amp; rate > 0)
5584                         return (rate / 1000);
5585
5586                 return null;
5587         },
5588
5589         /**
5590          * Query the current wireless channel.
5591          *
5592          * @returns {null|number}
5593          * Returns the wireless channel as reported by `ubus` runtime information
5594          * or `null` if it cannot be determined.
5595          */
5596         getChannel: function() {
5597                 return this.ubus('net', 'iwinfo', 'channel') || this.ubus('dev', 'config', 'channel') || this.get('channel');
5598         },
5599
5600         /**
5601          * Query the current wireless signal.
5602          *
5603          * @returns {null|number}
5604          * Returns the wireless signal in dBm as reported by `ubus` runtime
5605          * information or `null` if it cannot be determined.
5606          */
5607         getSignal: function() {
5608                 return this.ubus('net', 'iwinfo', 'signal') || 0;
5609         },
5610
5611         /**
5612          * Query the current radio noise floor.
5613          *
5614          * @returns {number}
5615          * Returns the radio noise floor in dBm as reported by `ubus` runtime
5616          * information or `0` if it cannot be determined.
5617          */
5618         getNoise: function() {
5619                 return this.ubus('net', 'iwinfo', 'noise') || 0;
5620         },
5621
5622         /**
5623          * Query the current country code.
5624          *
5625          * @returns {string}
5626          * Returns the wireless country code as reported by `ubus` runtime
5627          * information or `00` if it cannot be determined.
5628          */
5629         getCountryCode: function() {
5630                 return this.ubus('net', 'iwinfo', 'country') || this.ubus('dev', 'config', 'country') || '00';
5631         },
5632
5633         /**
5634          * Query the current radio TX power.
5635          *
5636          * @returns {null|number}
5637          * Returns the wireless network transmit power in dBm as reported by
5638          * `ubus` runtime information or `null` if it cannot be determined.
5639          */
5640         getTXPower: function() {
5641                 return this.ubus('net', 'iwinfo', 'txpower');
5642         },
5643
5644         /**
5645          * Query the radio TX power offset.
5646          *
5647          * Some wireless radios have a fixed power offset, e.g. due to the
5648          * use of external amplifiers.
5649          *
5650          * @returns {number}
5651          * Returns the wireless network transmit power offset in dBm as reported
5652          * by `ubus` runtime information or `0` if there is no offset, or if it
5653          * cannot be determined.
5654          */
5655         getTXPowerOffset: function() {
5656                 return this.ubus('net', 'iwinfo', 'txpower_offset') || 0;
5657         },
5658
5659         /**
5660          * Calculate the current signal.
5661          *
5662          * @deprecated
5663          * @returns {number}
5664          * Returns the calculated signal level, which is the difference between
5665          * noise and signal (SNR), divided by 5.
5666          */
5667         getSignalLevel: function(signal, noise) {
5668                 if (this.getActiveBSSID() == '00:00:00:00:00:00')
5669                         return -1;
5670
5671                 signal = signal || this.getSignal();
5672                 noise  = noise  || this.getNoise();
5673
5674                 if (signal &lt; 0 &amp;&amp; noise &lt; 0) {
5675                         var snr = -1 * (noise - signal);
5676                         return Math.floor(snr / 5);
5677                 }
5678
5679                 return 0;
5680         },
5681
5682         /**
5683          * Calculate the current signal quality percentage.
5684          *
5685          * @returns {number}
5686          * Returns the calculated signal quality in percent. The value is
5687          * calculated from the `quality` and `quality_max` indicators reported
5688          * by `ubus` runtime state.
5689          */
5690         getSignalPercent: function() {
5691                 var qc = this.ubus('net', 'iwinfo', 'quality') || 0,
5692                     qm = this.ubus('net', 'iwinfo', 'quality_max') || 0;
5693
5694                 if (qc > 0 &amp;&amp; qm > 0)
5695                         return Math.floor((100 / qm) * qc);
5696
5697                 return 0;
5698         },
5699
5700         /**
5701          * Get a short description string for this wireless network.
5702          *
5703          * @returns {string}
5704          * Returns a string describing this network, consisting of the
5705          * active operation mode, followed by either the SSID, BSSID or
5706          * internal network ID, depending on which information is available.
5707          */
5708         getShortName: function() {
5709                 return '%s "%s"'.format(
5710                         this.getActiveModeI18n(),
5711                         this.getActiveSSID() || this.getActiveBSSID() || this.getID());
5712         },
5713
5714         /**
5715          * Get a description string for this wireless network.
5716          *
5717          * @returns {string}
5718          * Returns a string describing this network, consisting of the
5719          * term `Wireless Network`, followed by the active operation mode,
5720          * the SSID, BSSID or internal network ID and the Linux network device
5721          * name, depending on which information is available.
5722          */
5723         getI18n: function() {
5724                 return '%s: %s "%s" (%s)'.format(
5725                         _('Wireless Network'),
5726                         this.getActiveModeI18n(),
5727                         this.getActiveSSID() || this.getActiveBSSID() || this.getID(),
5728                         this.getIfname());
5729         },
5730
5731         /**
5732          * Get the primary logical interface this wireless network is attached to.
5733          *
5734          * @returns {null|LuCI.network.Protocol}
5735          * Returns a `Network.Protocol` instance representing the logical
5736          * interface or `null` if this network is not attached to any logical
5737          * interface.
5738          */
5739         getNetwork: function() {
5740                 return this.getNetworks()[0];
5741         },
5742
5743         /**
5744          * Get the logical interfaces this wireless network is attached to.
5745          *
5746          * @returns {Array&lt;LuCI.network.Protocol>}
5747          * Returns an array of `Network.Protocol` instances representing the
5748          * logical interfaces this wireless network is attached to.
5749          */
5750         getNetworks: function() {
5751                 var networkNames = this.getNetworkNames(),
5752                     networks = [];
5753
5754                 for (var i = 0; i &lt; networkNames.length; i++) {
5755                         var uciInterface = uci.get('network', networkNames[i]);
5756
5757                         if (uciInterface == null || uciInterface['.type'] != 'interface')
5758                                 continue;
5759
5760                         networks.push(Network.prototype.instantiateNetwork(networkNames[i]));
5761                 }
5762
5763                 networks.sort(networkSort);
5764
5765                 return networks;
5766         },
5767
5768         /**
5769          * Get the associated Linux network device.
5770          *
5771          * @returns {LuCI.network.Device}
5772          * Returns a `Network.Device` instance representing the Linux network
5773          * device associted with this wireless network.
5774          */
5775         getDevice: function() {
5776                 return Network.prototype.instantiateDevice(this.getIfname());
5777         },
5778
5779         /**
5780          * Check whether this wifi network supports deauthenticating clients.
5781          *
5782          * @returns {boolean}
5783          * Returns `true` when this wifi network instance supports forcibly
5784          * deauthenticating clients, otherwise `false`.
5785          */
5786         isClientDisconnectSupported: function() {
5787                 return L.isObject(this.ubus('hostapd', 'del_client'));
5788         },
5789
5790         /**
5791          * Forcibly disconnect the given client from the wireless network.
5792          *
5793          * @param {string} mac
5794          * The MAC address of the client to disconnect.
5795          *
5796          * @param {boolean} [deauth=false]
5797          * Specifies whether to deauthenticate (`true`) or disassociate (`false`)
5798          * the client.
5799          *
5800          * @param {number} [reason=1]
5801          * Specifies the IEEE 802.11 reason code to disassoc/deauth the client
5802          * with. Default is `1` which corresponds to `Unspecified reason`.
5803          *
5804          * @param {number} [ban_time=0]
5805          * Specifies the amount of milliseconds to ban the client from
5806          * reconnecting. By default, no ban time is set which allows the client
5807          * to reassociate / reauthenticate immediately.
5808          *
5809          * @returns {Promise&lt;number>}
5810          * Returns a promise resolving to the underlying ubus call result code
5811          * which is typically `0`, even for not existing MAC addresses.
5812          * The promise might reject with an error in case invalid arguments
5813          * are passed.
5814          */
5815         disconnectClient: function(mac, deauth, reason, ban_time) {
5816                 if (reason == null || reason == 0)
5817                         reason = 1;
5818
5819                 if (ban_time == 0)
5820                         ban_time = null;
5821
5822                 return rpc.declare({
5823                         object: 'hostapd.%s'.format(this.getIfname()),
5824                         method: 'del_client',
5825                         params: [ 'addr', 'deauth', 'reason', 'ban_time' ]
5826                 })(mac, deauth, reason, ban_time);
5827         }
5828 });
5829
5830 return Network;
5831 </code></pre>
5832         </article>
5833     </section>
5834
5835
5836
5837
5838
5839
5840         
5841
5842         <footer>
5843             Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.3</a> on Fri Apr 03 2020 13:28:08 GMT+0200 (Central European Summer Time)
5844         </footer>
5845     </div>
5846 </div>
5847 <script>prettyPrint();</script>
5848 <script src="scripts/jaguar.js"></script>
5849 </body>
5850 </html>