9 /^wlan[0-9]+\.sta[0-9]+$/,
15 'protolist', 0, L.rpc.declare({
17 method: 'get_proto_handlers',
20 'ifstate', 1, L.rpc.declare({
21 object: 'network.interface',
23 expect: { 'interface': [ ] }
25 'devstate', 2, L.rpc.declare({
26 object: 'network.device',
30 'wifistate', 0, L.rpc.declare({
31 object: 'network.wireless',
35 'bwstate', 2, L.rpc.declare({
36 object: 'luci2.network.bwmon',
38 expect: { 'statistics': { } }
40 'devlist', 2, L.rpc.declare({
41 object: 'luci2.network',
42 method: 'device_list',
43 expect: { 'devices': [ ] }
45 'swlist', 0, L.rpc.declare({
46 object: 'luci2.network',
47 method: 'switch_list',
48 expect: { 'switches': [ ] }
52 loadProtocolHandler: function(proto)
54 var url = L.globals.resource + '/proto/' + proto + '.js';
57 var def = $.Deferred();
63 }).then(function(data) {
65 var protoConstructorSource = (
66 '(function(L, $) { ' +
70 ).format(data, window.location.origin, url);
72 var protoClass = eval(protoConstructorSource);
74 self.protocolHandlers[proto] = new protoClass();
77 alert('Unable to instantiate proto "%s": %s'.format(url, e));
88 loadProtocolHandlers: function()
92 self.loadProtocolHandler('none')
95 for (var proto in self.rpcCache.protolist)
96 deferreds.push(self.loadProtocolHandler(proto));
98 return $.when.apply($, deferreds);
101 callSwitchInfo: L.rpc.declare({
102 object: 'luci2.network',
103 method: 'switch_info',
104 params: [ 'switch' ],
105 expect: { 'info': { } }
108 callSwitchInfoCallback: function(responses) {
109 var self = L.network;
110 var swlist = self.rpcCache.swlist;
111 var swstate = self.rpcCache.swstate = { };
113 for (var i = 0; i < responses.length; i++)
114 swstate[swlist[i]] = responses[i];
117 loadCacheCallback: function(level)
119 var self = L.network;
120 var name = '_fetch_cache_cb_' + level;
122 return self[name] || (
123 self[name] = function(responses)
125 for (var i = 0; i < self.rpcCacheFunctions.length; i += 3)
126 if (!level || self.rpcCacheFunctions[i + 1] == level)
127 self.rpcCache[self.rpcCacheFunctions[i]] = responses.shift();
133 for (var i = 0; i < self.rpcCache.swlist.length; i++)
134 self.callSwitchInfo(self.rpcCache.swlist[i]);
136 return L.rpc.flush().then(self.callSwitchInfoCallback);
139 return L.deferrable();
144 loadCache: function(level)
146 var self = L.network;
148 return L.uci.load(['network', 'wireless']).then(function() {
151 for (var i = 0; i < self.rpcCacheFunctions.length; i += 3)
152 if (!level || self.rpcCacheFunctions[i + 1] == level)
153 self.rpcCacheFunctions[i + 2]();
155 return L.rpc.flush().then(self.loadCacheCallback(level || 0));
159 isBlacklistedDevice: function(dev)
161 for (var i = 0; i < this.deviceBlacklist.length; i++)
162 if (dev.match(this.deviceBlacklist[i]))
168 sortDevicesCallback: function(a, b)
170 if (a.options.kind < b.options.kind)
172 else if (a.options.kind > b.options.kind)
175 if (a.options.name < b.options.name)
177 else if (a.options.name > b.options.name)
183 getDeviceObject: function(ifname)
185 var alias = (ifname.charAt(0) == '@');
186 return this.deviceObjects[ifname] || (
187 this.deviceObjects[ifname] = {
189 kind: alias ? 'alias' : 'ethernet',
197 getInterfaceObject: function(name)
199 return this.interfaceObjects[name] || (
200 this.interfaceObjects[name] = {
202 proto: this.protocolHandlers.none,
208 loadDevicesCallback: function()
210 var self = L.network;
213 for (var ifname in self.rpcCache.devstate)
215 if (self.isBlacklistedDevice(ifname))
218 var dev = self.rpcCache.devstate[ifname];
219 var entry = self.getDeviceObject(ifname);
226 entry.kind = 'tunnel';
230 entry.kind = 'bridge';
231 //entry.ports = dev['bridge-members'].sort();
236 for (var i = 0; i < self.rpcCache.devlist.length; i++)
238 var dev = self.rpcCache.devlist[i];
240 if (self.isBlacklistedDevice(dev.device))
243 var entry = self.getDeviceObject(dev.device);
245 entry.up = dev.is_up;
246 entry.type = dev.type;
250 case 1: /* Ethernet */
252 entry.kind = 'bridge';
253 else if (dev.is_tuntap)
254 entry.kind = 'tunnel';
255 else if (dev.is_wireless)
260 case 768: /* IP-IP Tunnel */
261 case 769: /* IP6-IP6 Tunnel */
262 case 776: /* IPv6-in-IPv4 */
263 case 778: /* GRE over IP */
264 entry.kind = 'tunnel';
269 var net = L.uci.sections('network');
270 for (var i = 0; i < net.length; i++)
273 var sid = s['.name'];
275 if (s['.type'] == 'device' && s.name)
277 var entry = self.getDeviceObject(s.name);
283 entry.kind = 'tunnel';
289 else if (s['.type'] == 'interface' && !s['.anonymous'] && s.ifname)
291 var ifnames = L.toArray(s.ifname);
293 for (var j = 0; j < ifnames.length; j++)
294 self.getDeviceObject(ifnames[j]);
296 if (s['.name'] != 'loopback')
298 var entry = self.getDeviceObject('@%s'.format(s['.name']));
301 entry.kind = 'alias';
305 else if (s['.type'] == 'switch_vlan' && s.device)
307 var sw = self.rpcCache.swstate[s.device];
308 var vid = parseInt(s.vid || s.vlan);
309 var ports = L.toArray(s.ports);
311 if (!sw || !ports.length || isNaN(vid))
314 var ifname = undefined;
316 for (var j = 0; j < ports.length; j++)
318 var port = parseInt(ports[j]);
319 var tag = (ports[j].replace(/[^tu]/g, '') == 't');
321 if (port == sw.cpu_port)
323 // XXX: need a way to map switch to netdev
325 ifname = 'eth0.%d'.format(vid);
336 var entry = self.getDeviceObject(ifname);
345 var wifi = L.uci.sections('wireless');
346 for (var i = 0, c = 0; i < wifi.length; i++)
350 if (s['.type'] == 'wifi-iface')
352 var sid = '@wifi-iface[%d]'.format(c++);
357 var r = parseInt(s.device.replace(/^[^0-9]+/, ''));
358 var n = wificount[s.device] = (wificount[s.device] || 0) + 1;
359 var id = 'radio%d.network%d'.format(r, n);
362 if (self.rpcCache.wifistate[s.device])
364 var ifcs = self.rpcCache.wifistate[s.device].interfaces;
365 for (var ifc in ifcs)
367 if (ifcs[ifc].section == sid && ifcs[ifc].ifname)
369 ifname = ifcs[ifc].ifname;
375 var entry = self.getDeviceObject(ifname);
378 entry.sid = s['.name'];
380 entry.wdev = s.device;
381 entry.wmode = s.mode;
382 entry.wssid = s.ssid;
383 entry.wbssid = s.bssid;
387 for (var i = 0; i < net.length; i++)
390 var sid = s['.name'];
392 if (s['.type'] == 'interface' && !s['.anonymous'] && s.type == 'bridge')
394 var ifnames = L.toArray(s.ifname);
396 for (var ifname in self.deviceObjects)
398 var dev = self.deviceObjects[ifname];
400 if (dev.kind != 'wifi')
403 var wnets = L.toArray(L.uci.get('wireless', dev.sid, 'network'));
404 if ($.inArray(sid, wnets) > -1)
405 ifnames.push(ifname);
408 entry = self.getDeviceObject('br-%s'.format(s['.name']));
410 entry.kind = 'bridge';
412 entry.ports = ifnames.sort();
417 loadInterfacesCallback: function()
419 var self = L.network;
420 var net = L.uci.sections('network');
422 for (var i = 0; i < net.length; i++)
425 var sid = s['.name'];
427 if (s['.type'] == 'interface' && !s['.anonymous'] && s.proto)
429 var entry = self.getInterfaceObject(s['.name']);
430 var proto = self.protocolHandlers[s.proto] || self.protocolHandlers.none;
432 var l3dev = undefined;
433 var l2dev = undefined;
435 var ifnames = L.toArray(s.ifname);
437 for (var ifname in self.deviceObjects)
439 var dev = self.deviceObjects[ifname];
441 if (dev.kind != 'wifi')
444 var wnets = L.toArray(L.uci.get('wireless', dev.sid, 'network'));
445 if ($.inArray(entry.name, wnets) > -1)
446 ifnames.push(ifname);
450 l3dev = '%s-%s'.format(s.proto, entry.name);
451 else if (s.type == 'bridge')
452 l3dev = 'br-%s'.format(entry.name);
456 if (!proto.virtual && s.type == 'bridge')
457 l2dev = 'br-%s'.format(entry.name);
458 else if (!proto.virtual)
468 for (var i = 0; i < self.rpcCache.ifstate.length; i++)
470 var iface = self.rpcCache.ifstate[i];
471 var entry = self.getInterfaceObject(iface['interface']);
472 var proto = self.protocolHandlers[iface.proto] || self.protocolHandlers.none;
474 /* this is a virtual interface, either deleted from config but
475 not applied yet or set up from external tools (6rd) */
479 entry.l2dev = iface.device;
480 entry.l3dev = iface.l3_device;
490 return L.deferrable();
493 self.deviceObjects = { };
494 self.interfaceObjects = { };
495 self.protocolHandlers = { };
497 return self.loadCache()
498 .then(self.loadProtocolHandlers)
499 .then(self.loadDevicesCallback)
500 .then(self.loadInterfacesCallback);
505 delete this.rpcCache;
509 refreshInterfaceStatus: function()
511 return this.loadCache(1).then(this.loadInterfacesCallback);
514 refreshDeviceStatus: function()
516 return this.loadCache(2).then(this.loadDevicesCallback);
519 refreshStatus: function()
521 return this.loadCache(1)
522 .then(this.loadCache(2))
523 .then(this.loadDevicesCallback)
524 .then(this.loadInterfacesCallback);
527 getDevices: function()
531 for (var ifname in this.deviceObjects)
533 devs.push(new L.network.Device(this.deviceObjects[ifname]));
535 return devs.sort(this.sortDevicesCallback);
538 getDeviceByInterface: function(iface)
540 if (iface instanceof L.network.Interface)
541 iface = iface.name();
543 if (this.interfaceObjects[iface])
544 return this.getDevice(this.interfaceObjects[iface].l3dev) ||
545 this.getDevice(this.interfaceObjects[iface].l2dev);
550 getDevice: function(ifname)
552 if (this.deviceObjects[ifname])
553 return new L.network.Device(this.deviceObjects[ifname]);
558 createDevice: function(name)
560 return new L.network.Device(this.getDeviceObject(name));
563 getInterfaces: function()
567 for (var name in this.interfaceObjects)
568 if (name != 'loopback')
569 ifaces.push(this.getInterface(name));
571 ifaces.sort(function(a, b) {
572 if (a.name() < b.name())
574 else if (a.name() > b.name())
583 getInterfacesByDevice: function(dev)
587 if (dev instanceof L.network.Device)
590 for (var name in this.interfaceObjects)
592 var iface = this.interfaceObjects[name];
593 if (iface.l2dev == dev || iface.l3dev == dev)
594 ifaces.push(this.getInterface(name));
597 ifaces.sort(function(a, b) {
598 if (a.name() < b.name())
600 else if (a.name() > b.name())
609 getInterface: function(iface)
611 if (this.interfaceObjects[iface])
612 return new L.network.Interface(this.interfaceObjects[iface]);
617 getProtocols: function()
621 for (var proto in this.protocolHandlers)
623 var pr = this.protocolHandlers[proto];
627 description: pr.description,
633 return rv.sort(function(a, b) {
636 else if (a.name > b.name)
643 findWANByAddr: function(ipaddr)
645 for (var i = 0; i < this.rpcCache.ifstate.length; i++)
647 var ifstate = this.rpcCache.ifstate[i];
652 for (var j = 0; j < ifstate.route.length; j++)
653 if (ifstate.route[j].mask == 0 &&
654 ifstate.route[j].target == ipaddr &&
655 typeof(ifstate.route[j].table) == 'undefined')
657 return this.getInterface(ifstate['interface']);
666 return this.findWANByAddr('0.0.0.0');
671 return this.findWANByAddr('::');
674 resolveAlias: function(ifname)
676 if (ifname instanceof L.network.Device)
677 ifname = ifname.name();
679 var dev = this.deviceObjects[ifname];
682 while (dev && dev.kind == 'alias')
685 if (seen[dev.ifname])
688 var ifc = this.interfaceObjects[dev.sid];
690 seen[dev.ifname] = true;
691 dev = ifc ? this.deviceObjects[ifc.l3dev] : undefined;
694 return dev ? this.getDevice(dev.ifname) : undefined;
698 network_class.Interface = Class.extend({
699 getStatus: function(key)
701 var s = L.network.rpcCache.ifstate;
703 for (var i = 0; i < s.length; i++)
704 if (s[i]['interface'] == this.options.name)
705 return key ? s[i][key] : s[i];
712 return L.uci.get('network', this.options.name, key);
715 set: function(key, val)
717 return L.uci.set('network', this.options.name, key, val);
722 return this.options.name;
727 return (this.get('proto') || 'none');
732 return (this.getStatus('up') === true);
735 isVirtual: function()
737 return (typeof(this.options.sid) != 'string');
740 getProtocol: function()
742 var prname = this.get('proto') || 'none';
743 return L.network.protocolHandlers[prname] || L.network.protocolHandlers.none;
746 getUptime: function()
748 var uptime = this.getStatus('uptime');
749 return isNaN(uptime) ? 0 : uptime;
752 getDevice: function(resolveAlias)
754 if (this.options.l3dev)
755 return L.network.getDevice(this.options.l3dev);
760 getPhysdev: function()
762 if (this.options.l2dev)
763 return L.network.getDevice(this.options.l2dev);
768 getSubdevices: function()
771 var dev = this.options.l2dev ?
772 L.network.deviceObjects[this.options.l2dev] : undefined;
774 if (dev && dev.kind == 'bridge' && dev.ports && dev.ports.length)
775 for (var i = 0; i < dev.ports.length; i++)
776 rv.push(L.network.getDevice(dev.ports[i]));
781 getIPv4Addrs: function(mask)
784 var addrs = this.getStatus('ipv4-address');
787 for (var i = 0; i < addrs.length; i++)
789 rv.push(addrs[i].address);
791 rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
796 getIPv6Addrs: function(mask)
801 addrs = this.getStatus('ipv6-address');
804 for (var i = 0; i < addrs.length; i++)
806 rv.push(addrs[i].address);
808 rv.push('%s/%d'.format(addrs[i].address, addrs[i].mask));
810 addrs = this.getStatus('ipv6-prefix-assignment');
813 for (var i = 0; i < addrs.length; i++)
815 rv.push('%s1'.format(addrs[i].address));
817 rv.push('%s1/%d'.format(addrs[i].address, addrs[i].mask));
822 getDNSAddrs: function()
825 var addrs = this.getStatus('dns-server');
828 for (var i = 0; i < addrs.length; i++)
834 getIPv4DNS: function()
837 var dns = this.getStatus('dns-server');
840 for (var i = 0; i < dns.length; i++)
841 if (dns[i].indexOf(':') == -1)
847 getIPv6DNS: function()
850 var dns = this.getStatus('dns-server');
853 for (var i = 0; i < dns.length; i++)
854 if (dns[i].indexOf(':') > -1)
860 getIPv4Gateway: function()
862 var rt = this.getStatus('route');
865 for (var i = 0; i < rt.length; i++)
866 if (rt[i].target == '0.0.0.0' && rt[i].mask == 0)
867 return rt[i].nexthop;
872 getIPv6Gateway: function()
874 var rt = this.getStatus('route');
877 for (var i = 0; i < rt.length; i++)
878 if (rt[i].target == '::' && rt[i].mask == 0)
879 return rt[i].nexthop;
884 getStatistics: function()
886 var dev = this.getDevice() || new L.network.Device({});
887 return dev.getStatistics();
890 getTrafficHistory: function()
892 var dev = this.getDevice() || new L.network.Device({});
893 return dev.getTrafficHistory();
896 renderBadge: function()
898 var badge = $('<span />')
900 .text('%s: '.format(this.name()));
902 var dev = this.getDevice();
903 var subdevs = this.getSubdevices();
906 for (var j = 0; j < subdevs.length; j++)
907 badge.append($('<img />')
908 .attr('src', subdevs[j].icon())
909 .attr('title', '%s (%s)'.format(subdevs[j].description(), subdevs[j].name() || '?')));
911 badge.append($('<img />')
912 .attr('src', dev.icon())
913 .attr('title', '%s (%s)'.format(dev.description(), dev.name() || '?')));
915 badge.append($('<em />').text(L.tr('(No devices attached)')));
920 setDevices: function(devs)
922 var dev = this.getPhysdev();
926 if (dev && dev.isBridge())
927 old_devs = this.getSubdevices();
931 if (old_devs.length != devs.length)
934 for (var i = 0; i < old_devs.length; i++)
938 if (dev instanceof L.network.Device)
941 if (!dev || old_devs[i].name() != dev)
950 for (var i = 0; i < old_devs.length; i++)
951 old_devs[i].removeFromInterface(this);
953 for (var i = 0; i < devs.length; i++)
957 if (!(dev instanceof L.network.Device))
958 dev = L.network.getDevice(dev);
961 dev.attachToInterface(this);
966 changeProtocol: function(proto)
968 var pr = L.network.protocolHandlers[proto];
973 for (var opt in (this.get() || { }))
981 this.set(opt, undefined);
989 this.set(opt, pr.protocol);
993 this.set(opt, undefined);
999 createFormPrepareCallback: function()
1002 var iface = map.options.netIface;
1003 var proto = iface.getProtocol();
1004 var device = iface.getDevice();
1006 map.options.caption = L.tr('Configure "%s"').format(iface.name());
1008 var section = map.section(L.cbi.SingleSection, iface.name(), {
1014 caption: L.tr('General Settings')
1019 caption: L.tr('Advanced Settings')
1024 caption: L.tr('IPv6')
1029 caption: L.tr('Physical Settings')
1033 section.taboption('general', L.cbi.CheckboxValue, 'auto', {
1034 caption: L.tr('Start on boot'),
1039 var pr = section.taboption('general', L.cbi.ListValue, 'proto', {
1040 caption: L.tr('Protocol')
1043 pr.ucivalue = function(sid) {
1044 return iface.get('proto') || 'none';
1047 var ok = section.taboption('general', L.cbi.ButtonValue, '_confirm', {
1048 caption: L.tr('Really switch?'),
1049 description: L.tr('Changing the protocol will clear all configuration for this interface!'),
1050 text: L.tr('Change protocol')
1053 ok.on('click', function(ev) {
1054 iface.changeProtocol(pr.formvalue(ev.data.sid));
1055 iface.createForm(mapwidget).show();
1058 var protos = L.network.getProtocols();
1060 for (var i = 0; i < protos.length; i++)
1061 pr.value(protos[i].name, protos[i].description);
1063 proto.populateForm(section, iface);
1067 var br = section.taboption('physical', L.cbi.CheckboxValue, 'type', {
1068 caption: L.tr('Network bridge'),
1069 description: L.tr('Merges multiple devices into one logical bridge'),
1076 section.taboption('physical', L.cbi.DeviceList, '__iface_multi', {
1077 caption: L.tr('Devices'),
1080 }).depends('type', true);
1082 section.taboption('physical', L.cbi.DeviceList, '__iface_single', {
1083 caption: L.tr('Device'),
1086 }).depends('type', false);
1088 var mac = section.taboption('physical', L.cbi.InputValue, 'macaddr', {
1089 caption: L.tr('Override MAC'),
1091 placeholder: device ? device.getMACAddress() : undefined,
1095 mac.ucivalue = function(sid)
1098 return device.get('macaddr');
1100 return this.callSuper('ucivalue', sid);
1103 mac.save = function(sid)
1105 if (!this.changed(sid))
1109 device.set('macaddr', this.formvalue(sid));
1111 this.callSuper('set', sid);
1117 section.taboption('physical', L.cbi.InputValue, 'mtu', {
1118 caption: L.tr('Override MTU'),
1120 placeholder: device ? device.getMTU() : undefined,
1121 datatype: 'range(1, 9000)'
1124 section.taboption('physical', L.cbi.InputValue, 'metric', {
1125 caption: L.tr('Override Metric'),
1128 datatype: 'uinteger'
1131 for (var field in section.fields)
1139 for (var i = 0; i < protos.length; i++)
1140 if (protos[i].name != proto.protocol)
1141 section.fields[field].depends('proto', protos[i].name);
1145 section.fields[field].depends('proto', proto.protocol, true);
1151 createForm: function(mapwidget)
1156 mapwidget = L.cbi.Map;
1158 var map = new mapwidget('network', {
1159 prepare: self.createFormPrepareCallback,
1167 network_class.Device = Class.extend({
1170 sta: L.tr('Client'),
1171 adhoc: L.tr('Ad-Hoc'),
1172 monitor: L.tr('Monitor'),
1173 wds: L.tr('Static WDS')
1176 getStatus: function(key)
1178 var s = L.network.rpcCache.devstate[this.options.ifname];
1181 return key ? s[key] : s;
1188 var sid = this.options.sid;
1189 var pkg = (this.options.kind == 'wifi') ? 'wireless' : 'network';
1190 return L.uci.get(pkg, sid, key);
1193 set: function(key, val)
1195 var sid = this.options.sid;
1196 var pkg = (this.options.kind == 'wifi') ? 'wireless' : 'network';
1197 return L.uci.set(pkg, sid, key, val);
1202 if (typeof(this.options.type) == 'undefined')
1203 this.options.type = 1;
1205 if (typeof(this.options.kind) == 'undefined')
1206 this.options.kind = 'ethernet';
1208 if (typeof(this.options.networks) == 'undefined')
1209 this.options.networks = [ ];
1214 return this.options.ifname;
1217 description: function()
1219 switch (this.options.kind)
1222 return L.tr('Alias for network "%s"').format(this.options.ifname.substring(1));
1225 return L.tr('Network bridge');
1228 return L.tr('Network device');
1231 switch (this.options.type)
1233 case 1: /* tuntap */
1234 return L.tr('TAP device');
1237 return L.tr('PPP tunnel');
1239 case 768: /* IP-IP Tunnel */
1240 return L.tr('IP-in-IP tunnel');
1242 case 769: /* IP6-IP6 Tunnel */
1243 return L.tr('IPv6-in-IPv6 tunnel');
1245 case 776: /* IPv6-in-IPv4 */
1246 return L.tr('IPv6-over-IPv4 tunnel');
1249 case 778: /* GRE over IP */
1250 return L.tr('GRE-over-IP tunnel');
1253 return L.tr('Tunnel device');
1257 return L.tr('VLAN %d on %s').format(this.options.vid, this.options.vsw.model);
1260 var o = this.options;
1261 return L.trc('(Wifi-Mode) "(SSID)" on (radioX)', '%s "%h" on %s').format(
1262 o.wmode ? this.wifiModeStrings[o.wmode] : L.tr('Unknown mode'),
1263 o.wssid || '?', o.wdev
1267 return L.tr('Unknown device');
1272 var kind = this.options.kind;
1274 if (kind == 'alias')
1277 if (typeof(up) == 'undefined')
1280 return L.globals.resource + '/icons/%s%s.png'.format(kind, up ? '' : '_disabled');
1285 var l = L.network.rpcCache.devlist;
1287 for (var i = 0; i < l.length; i++)
1288 if (l[i].device == this.options.ifname)
1289 return (l[i].is_up === true);
1296 return (this.options.kind == 'alias');
1299 isBridge: function()
1301 return (this.options.kind == 'bridge');
1304 isBridgeable: function()
1306 return (this.options.type == 1 && this.options.kind != 'bridge');
1309 isWireless: function()
1311 return (this.options.kind == 'wifi');
1314 isInNetwork: function(net)
1316 if (!(net instanceof L.network.Interface))
1317 net = L.network.getInterface(net);
1321 if (net.options.l3dev == this.options.ifname ||
1322 net.options.l2dev == this.options.ifname)
1325 var dev = L.network.deviceObjects[net.options.l2dev];
1326 if (dev && dev.kind == 'bridge' && dev.ports)
1327 return ($.inArray(this.options.ifname, dev.ports) > -1);
1335 var dev = L.network.rpcCache.devstate[this.options.ifname];
1336 if (dev && !isNaN(dev.mtu))
1342 getMACAddress: function()
1344 if (this.options.type != 1)
1347 var dev = L.network.rpcCache.devstate[this.options.ifname];
1348 if (dev && dev.macaddr)
1349 return dev.macaddr.toUpperCase();
1354 getInterfaces: function()
1356 return L.network.getInterfacesByDevice(this.options.name);
1359 getStatistics: function()
1361 var s = this.getStatus('statistics') || { };
1363 rx_bytes: (s.rx_bytes || 0),
1364 tx_bytes: (s.tx_bytes || 0),
1365 rx_packets: (s.rx_packets || 0),
1366 tx_packets: (s.tx_packets || 0)
1370 getTrafficHistory: function()
1372 var def = new Array(120);
1374 for (var i = 0; i < 120; i++)
1377 var h = L.network.rpcCache.bwstate[this.options.ifname] || { };
1379 rx_bytes: (h.rx_bytes || def),
1380 tx_bytes: (h.tx_bytes || def),
1381 rx_packets: (h.rx_packets || def),
1382 tx_packets: (h.tx_packets || def)
1386 removeFromInterface: function(iface)
1388 if (!(iface instanceof L.network.Interface))
1389 iface = L.network.getInterface(iface);
1394 var ifnames = L.toArray(iface.get('ifname'));
1395 if ($.inArray(this.options.ifname, ifnames) > -1)
1396 iface.set('ifname', L.filterArray(ifnames, this.options.ifname));
1398 if (this.options.kind != 'wifi')
1401 var networks = L.toArray(this.get('network'));
1402 if ($.inArray(iface.name(), networks) > -1)
1403 this.set('network', L.filterArray(networks, iface.name()));
1406 attachToInterface: function(iface)
1408 if (!(iface instanceof L.network.Interface))
1409 iface = L.network.getInterface(iface);
1414 if (this.options.kind != 'wifi')
1416 var ifnames = L.toArray(iface.get('ifname'));
1417 if ($.inArray(this.options.ifname, ifnames) < 0)
1419 ifnames.push(this.options.ifname);
1420 iface.set('ifname', (ifnames.length > 1) ? ifnames : ifnames[0]);
1425 var networks = L.toArray(this.get('network'));
1426 if ($.inArray(iface.name(), networks) < 0)
1428 networks.push(iface.name());
1429 this.set('network', (networks.length > 1) ? networks : networks[0]);
1435 network_class.Protocol = network_class.Interface.extend({
1436 description: '__unknown__',
1440 populateForm: function(section, iface)
1446 return Class.extend(network_class);