summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-mod-network/htdocs/luci-static
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-mod-network/htdocs/luci-static')
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js96
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js8
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js437
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js93
4 files changed, 443 insertions, 191 deletions
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js b/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js
index 80b4b2b343..8ba259e2c9 100644
--- a/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/tools/network.js
@@ -1,5 +1,6 @@
'use strict';
'require ui';
+'require dom';
'require uci';
'require form';
'require network';
@@ -46,11 +47,15 @@ function validateQoSMap(section_id, value) {
return true;
}
-function deviceSectionExists(section_id, devname, devtype) {
+function deviceSectionExists(section_id, devname, ignore_type_match) {
var exists = false;
uci.sections('network', 'device', function(ss) {
- exists = exists || (ss['.name'] != section_id && ss.name == devname && (!devtype || devtype == ss.type));
+ exists = exists || (
+ ss['.name'] != section_id &&
+ ss.name == devname &&
+ (!ignore_type_match || !ignore_type_match.test(ss.type || ''))
+ );
});
return exists;
@@ -76,16 +81,54 @@ function isBridgePort(dev) {
return isPort;
}
-function renderDevBadge(dev) {
- var type = dev.getType(), up = dev.isUp();
+function updateDevBadge(node, dev) {
+ var type = dev.getType(),
+ up = dev.getCarrier();
- return E('span', { 'class': 'ifacebadge', 'style': 'font-weight:normal' }, [
+ dom.content(node, [
E('img', {
'class': 'middle',
'src': L.resource('icons/%s%s.png').format(type, up ? '' : '_disabled')
}),
'\x0a', dev.getName()
]);
+
+ return node;
+}
+
+function renderDevBadge(dev) {
+ return updateDevBadge(E('span', {
+ 'class': 'ifacebadge port-status-device',
+ 'style': 'font-weight:normal',
+ 'data-device': dev.getName()
+ }), dev);
+}
+
+function updatePortStatus(node, dev) {
+ var carrier = dev.getCarrier(),
+ duplex = dev.getDuplex(),
+ speed = dev.getSpeed(),
+ desc;
+
+ if (carrier && speed > 0 && duplex != null)
+ desc = E('abbr', {
+ 'title': '%d MBit/s, %s'.format(speed, duplex == 'full' ? _('full-duplex') : _('half-duplex'))
+ }, [ '%d%s'.format(speed, duplex == 'full' ? 'FD' : 'HD') ]);
+ else if (carrier)
+ desc = document.createTextNode(_('Connected'));
+ else
+ desc = document.createTextNode(_('no link'));
+
+ dom.content(node, [ desc ]);
+
+ return node;
+}
+
+function renderPortStatus(dev) {
+ return updatePortStatus(E('span', {
+ 'class': 'port-status-link',
+ 'data-device': dev.getName()
+ }), dev);
}
function lookupDevName(s, section_id) {
@@ -409,10 +452,11 @@ return baseclass.extend({
o.ucioption = 'name';
o.write = o.remove = setIfActive;
o.filter = function(section_id, value) {
- return !deviceSectionExists(section_id, value);
+ return !deviceSectionExists(section_id, value, /^(?:bridge|8021q|8021ad|macvlan|veth)$/);
};
o.validate = function(section_id, value) {
- return deviceSectionExists(section_id, value) ? _('A configuration for the device "%s" already exists').format(value) : true;
+ return deviceSectionExists(section_id, value, /^(?:bridge|8021q|8021ad|macvlan|veth)$/)
+ ? _('A configuration for the device "%s" already exists').format(value) : true;
};
o.depends('type', '');
@@ -479,7 +523,7 @@ return baseclass.extend({
o.ucioption = 'name';
o.write = o.remove = setIfActive;
o.validate = function(section_id, value) {
- return deviceSectionExists(section_id, value) ? _('The device name "%s" is already taken').format(value) : true;
+ return deviceSectionExists(section_id, value, /^$/) ? _('The device name "%s" is already taken').format(value) : true;
};
o.depends({ type: '', '!reverse': true });
@@ -651,7 +695,7 @@ return baseclass.extend({
o.datatype = 'uinteger';
o.depends('type', '');
- o = this.addOption(s, 'devadvanced', form.Flag, 'promisc', _('Enable promiscious mode'));
+ o = this.addOption(s, 'devadvanced', form.Flag, 'promisc', _('Enable promiscuous mode'));
o.default = o.disabled;
o.depends('type', '');
@@ -781,16 +825,6 @@ return baseclass.extend({
o = this.addOption(s, 'bridgevlan', form.SectionValue, 'bridge-vlan', form.TableSection, 'bridge-vlan');
o.depends('type', 'bridge');
- o.renderWidget = function(/* ... */) {
- return form.SectionValue.prototype.renderWidget.apply(this, arguments).then(L.bind(function(node) {
- node.style.overflowX = 'auto';
- node.style.overflowY = 'visible';
- node.style.paddingBottom = '100px';
- node.style.marginBottom = '-100px';
-
- return node;
- }, this));
- };
ss = o.subsection;
ss.addremove = true;
@@ -813,6 +847,8 @@ return baseclass.extend({
ss.render = function(/* ... */) {
return form.TableSection.prototype.render.apply(this, arguments).then(L.bind(function(node) {
+ node.style.overflow = 'auto hidden';
+
if (this.node)
this.node.parentNode.replaceChild(node, this.node);
@@ -836,7 +872,7 @@ return baseclass.extend({
this.children = this.children.filter(function(opt) { return !opt.option.match(/^port_/) });
for (var i = 0; i < devices.length; i++) {
- o = ss.option(cbiTagValue, 'port_%s'.format(sfh(devices[i].getName())), renderDevBadge(devices[i]));
+ o = ss.option(cbiTagValue, 'port_%s'.format(sfh(devices[i].getName())), renderDevBadge(devices[i]), renderPortStatus(devices[i]));
o.port = devices[i].getName();
}
@@ -886,6 +922,9 @@ return baseclass.extend({
s.getOption('vlan_filtering').updateDefaultValue(s.section);
+ s.map.addedVLANs = s.map.addedVLANs || [];
+ s.map.addedVLANs.push(section_id);
+
return this.redraw();
}, this));
};
@@ -938,8 +977,21 @@ return baseclass.extend({
for (var port_name in seen_ports)
ports.push(port_name);
- ports.sort();
+ ports.sort(function(a, b) {
+ var m1 = a.match(/^(.+?)([0-9]*)$/),
+ m2 = b.match(/^(.+?)([0-9]*)$/);
+
+ if (m1[1] < m2[1])
+ return -1;
+ else if (m1[1] > m2[1])
+ return 1;
+ else
+ return +(m1[2] || 0) - +(m2[2] || 0);
+ });
ss.updatePorts(ports);
- }
+ },
+
+ updateDevBadge: updateDevBadge,
+ updatePortStatus: updatePortStatus
});
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js
index 0d1420772e..4dd90cc326 100644
--- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js
@@ -34,8 +34,8 @@ CBILeaseStatus = form.DummyValue.extend({
E('table', { 'id': 'lease_status_table', 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Hostname')),
- E('th', { 'class': 'th' }, _('IPv4-Address')),
- E('th', { 'class': 'th' }, _('MAC-Address')),
+ E('th', { 'class': 'th' }, _('IPv4 address')),
+ E('th', { 'class': 'th' }, _('MAC address')),
E('th', { 'class': 'th' }, _('Lease time remaining'))
]),
E('tr', { 'class': 'tr placeholder' }, [
@@ -53,7 +53,7 @@ CBILease6Status = form.DummyValue.extend({
E('table', { 'id': 'lease6_status_table', 'class': 'table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th' }, _('Host')),
- E('th', { 'class': 'th' }, _('IPv6-Address')),
+ E('th', { 'class': 'th' }, _('IPv6 address')),
E('th', { 'class': 'th' }, _('DUID')),
E('th', { 'class': 'th' }, _('Lease time remaining'))
]),
@@ -409,7 +409,7 @@ return view.extend({
o = s.taboption('leases', form.SectionValue, '__leases__', form.GridSection, 'host', null,
_('Static leases are used to assign fixed IP addresses and symbolic hostnames to DHCP clients. They are also required for non-dynamic interface configurations where only hosts with a corresponding lease are served.') + '<br />' +
- _('Use the <em>Add</em> Button to add a new lease entry. The <em>MAC-Address</em> identifies the host, the <em>IPv4-Address</em> specifies the fixed address to use, and the <em>Hostname</em> is assigned as a symbolic name to the requesting host. The optional <em>Lease time</em> can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.'));
+ _('Use the <em>Add</em> Button to add a new lease entry. The <em>MAC address</em> identifies the host, the <em>IPv4 address</em> specifies the fixed address to use, and the <em>Hostname</em> is assigned as a symbolic name to the requesting host. The optional <em>Lease time</em> can be used to set non-standard host-specific lease time, e.g. 12h, 3d or infinite.'));
ss = o.subsection;
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js
index a8e289c480..a8fa727da7 100644
--- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/interfaces.js
@@ -128,7 +128,7 @@ function render_modal_status(node, ifc) {
function render_ifacebox_status(node, ifc) {
var dev = ifc.getL3Device() || ifc.getDevice(),
- subdevs = ifc.getDevices(),
+ subdevs = dev ? dev.getPorts() : null,
c = [ render_iface(dev, ifc.isAlias()) ];
if (subdevs && subdevs.length) {
@@ -228,6 +228,39 @@ function get_netmask(s, use_cfgvalue) {
return subnetmask;
}
+var cbiRichListValue = form.ListValue.extend({
+ renderWidget: function(section_id, option_index, cfgvalue) {
+ var choices = this.transformChoices();
+ var widget = new ui.Dropdown((cfgvalue != null) ? cfgvalue : this.default, choices, {
+ id: this.cbid(section_id),
+ sort: this.keylist,
+ optional: true,
+ select_placeholder: this.select_placeholder || this.placeholder,
+ custom_placeholder: this.custom_placeholder || this.placeholder,
+ validate: L.bind(this.validate, this, section_id),
+ disabled: (this.readonly != null) ? this.readonly : this.map.readonly
+ });
+
+ return widget.render();
+ },
+
+ value: function(value, title, description) {
+ if (description) {
+ form.ListValue.prototype.value.call(this, value, E([], [
+ E('span', { 'class': 'hide-open' }, [ title ]),
+ E('div', { 'class': 'hide-close', 'style': 'min-width:25vw' }, [
+ E('strong', [ title ]),
+ E('br'),
+ E('span', { 'style': 'white-space:normal' }, description)
+ ])
+ ]));
+ }
+ else {
+ form.ListValue.prototype.value.call(this, value, title);
+ }
+ }
+});
+
return view.extend({
poll_status: function(map, networks) {
var resolveZone = null;
@@ -286,6 +319,14 @@ return view.extend({
btn2.disabled = isReadonlyView || btn1.classList.contains('spinning') || btn2.classList.contains('spinning') || dynamic || disabled;
}
+ document.querySelectorAll('.port-status-device[data-device]').forEach(function(node) {
+ nettools.updateDevBadge(node, network.instantiateDevice(node.getAttribute('data-device')));
+ });
+
+ document.querySelectorAll('.port-status-link[data-device]').forEach(function(node) {
+ nettools.updatePortStatus(node, network.instantiateDevice(node.getAttribute('data-device')));
+ });
+
return Promise.all([ resolveZone, network.flushCache() ]);
},
@@ -327,13 +368,17 @@ return view.extend({
'name': device_name,
'type': 'bridge',
'ports': L.toArray(ns.ifname),
- 'macaddr': ns.macaddr
+ 'mtu': ns.mtu,
+ 'macaddr': ns.macaddr,
+ 'igmp_snooping': ns.igmp_snooping
}));
tasks.push(uci.callSet('network', ns['.name'], {
'type': '',
'ifname': '',
+ 'mtu': '',
'macaddr': '',
+ 'igmp_snooping': '',
'device': device_name
}));
});
@@ -359,7 +404,7 @@ return view.extend({
var tasks = [];
this.deviceWithIfnameSections().forEach(function(ds) {
- tasks.push(uci.add('network', ds['.name'], {
+ tasks.push(uci.callSet('network', ds['.name'], {
'ifname': '',
'ports': L.toArray(ds.ifname)
}));
@@ -578,7 +623,6 @@ return view.extend({
if (L.hasSystemFeature('dnsmasq') || L.hasSystemFeature('odhcpd')) {
o = s.taboption('dhcp', form.SectionValue, '_dhcp', form.TypedSection, 'dhcp');
- o.depends('proto', 'static');
ss = o.subsection;
ss.uciconfig = 'dhcp';
@@ -588,6 +632,7 @@ return view.extend({
ss.tab('general', _('General Setup'));
ss.tab('advanced', _('Advanced Settings'));
ss.tab('ipv6', _('IPv6 Settings'));
+ ss.tab('ipv6-ra', _('IPv6 RA Settings'));
ss.filter = function(section_id) {
return (uci.get('dhcp', section_id, 'interface') == ifc.getName());
@@ -603,9 +648,15 @@ return view.extend({
this.map.save(function() {
uci.add('dhcp', 'dhcp', section_id);
uci.set('dhcp', section_id, 'interface', section_id);
- uci.set('dhcp', section_id, 'start', 100);
- uci.set('dhcp', section_id, 'limit', 150);
- uci.set('dhcp', section_id, 'leasetime', '12h');
+
+ if (protoval == 'static') {
+ uci.set('dhcp', section_id, 'start', 100);
+ uci.set('dhcp', section_id, 'limit', 150);
+ uci.set('dhcp', section_id, 'leasetime', '12h');
+ }
+ else {
+ uci.set('dhcp', section_id, 'ignore', 1);
+ }
});
}, ifc.getName())
}, _('Setup DHCP Server'))
@@ -614,169 +665,252 @@ return view.extend({
ss.taboption('general', form.Flag, 'ignore', _('Ignore interface'), _('Disable <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr> for this interface.'));
- so = ss.taboption('general', form.Value, 'start', _('Start'), _('Lowest leased address as offset from the network address.'));
- so.optional = true;
- so.datatype = 'or(uinteger,ip4addr("nomask"))';
- so.default = '100';
+ if (protoval == 'static') {
+ so = ss.taboption('general', form.Value, 'start', _('Start'), _('Lowest leased address as offset from the network address.'));
+ so.optional = true;
+ so.datatype = 'or(uinteger,ip4addr("nomask"))';
+ so.default = '100';
- so = ss.taboption('general', form.Value, 'limit', _('Limit'), _('Maximum number of leased addresses.'));
- so.optional = true;
- so.datatype = 'uinteger';
- so.default = '150';
+ so = ss.taboption('general', form.Value, 'limit', _('Limit'), _('Maximum number of leased addresses.'));
+ so.optional = true;
+ so.datatype = 'uinteger';
+ so.default = '150';
- so = ss.taboption('general', form.Value, 'leasetime', _('Lease time'), _('Expiry time of leased addresses, minimum is 2 minutes (<code>2m</code>).'));
- so.optional = true;
- so.default = '12h';
+ so = ss.taboption('general', form.Value, 'leasetime', _('Lease time'), _('Expiry time of leased addresses, minimum is 2 minutes (<code>2m</code>).'));
+ so.optional = true;
+ so.default = '12h';
- so = ss.taboption('advanced', form.Flag, 'dynamicdhcp', _('Dynamic <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr>'), _('Dynamically allocate DHCP addresses for clients. If disabled, only clients having static leases will be served.'));
- so.default = so.enabled;
+ so = ss.taboption('advanced', form.Flag, 'dynamicdhcp', _('Dynamic <abbr title="Dynamic Host Configuration Protocol">DHCP</abbr>'), _('Dynamically allocate DHCP addresses for clients. If disabled, only clients having static leases will be served.'));
+ so.default = so.enabled;
- ss.taboption('advanced', form.Flag, 'force', _('Force'), _('Force DHCP on this network even if another server is detected.'));
+ ss.taboption('advanced', form.Flag, 'force', _('Force'), _('Force DHCP on this network even if another server is detected.'));
- // XXX: is this actually useful?
- //ss.taboption('advanced', form.Value, 'name', _('Name'), _('Define a name for this network.'));
+ // XXX: is this actually useful?
+ //ss.taboption('advanced', form.Value, 'name', _('Name'), _('Define a name for this network.'));
- so = ss.taboption('advanced', form.Value, 'netmask', _('<abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask'), _('Override the netmask sent to clients. Normally it is calculated from the subnet that is served.'));
- so.optional = true;
- so.datatype = 'ip4addr';
+ so = ss.taboption('advanced', form.Value, 'netmask', _('<abbr title="Internet Protocol Version 4">IPv4</abbr>-Netmask'), _('Override the netmask sent to clients. Normally it is calculated from the subnet that is served.'));
+ so.optional = true;
+ so.datatype = 'ip4addr';
- so.render = function(option_index, section_id, in_table) {
- this.placeholder = get_netmask(s, true);
- return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
- };
+ so.render = function(option_index, section_id, in_table) {
+ this.placeholder = get_netmask(s, true);
+ return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
+ };
+
+ so.validate = function(section_id, value) {
+ var uielem = this.getUIElement(section_id);
+ if (uielem)
+ uielem.setPlaceholder(get_netmask(s, false));
+ return form.Value.prototype.validate.apply(this, [ section_id, value ]);
+ };
+
+ ss.taboption('advanced', form.DynamicList, 'dhcp_option', _('DHCP-Options'), _('Define additional DHCP options, for example "<code>6,192.168.2.1,192.168.2.2</code>" which advertises different DNS servers to clients.'));
+ }
+
+
+ var has_other_master = uci.sections('dhcp', 'dhcp').filter(function(s) {
+ return (s.interface != ifc.getName() && s.master == '1');
+ })[0];
+
+ so = ss.taboption('ipv6', form.Flag , 'master', _('Designated master'));
+ so.readonly = has_other_master ? true : false;
+ so.description = has_other_master
+ ? _('Interface "%h" is already marked as designated master.').format(has_other_master.interface || has_other_master['.name'])
+ : _('Set this interface as master for RA and DHCPv6 relaying as well as NDP proxying.')
+ ;
so.validate = function(section_id, value) {
- var uielem = this.getUIElement(section_id);
- if (uielem)
- uielem.setPlaceholder(get_netmask(s, false));
- return form.Value.prototype.validate.apply(this, [ section_id, value ]);
+ var hybrid_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise fall back to <em>server mode</em>.'),
+ ndp_downstream_desc = _('Operate in <em>relay mode</em> if a designated master interface is configured and active, otherwise disable <abbr title="Neighbour Discovery Protocol">NDP</abbr> proxying.'),
+ hybrid_master_desc = _('Operate in <em>relay mode</em> if an upstream IPv6 prefix is present, otherwise disable service.'),
+ checked = this.formvalue(section_id),
+ dhcpv6 = this.section.getOption('dhcpv6').getUIElement(section_id),
+ ndp = this.section.getOption('ndp').getUIElement(section_id),
+ ra = this.section.getOption('ra').getUIElement(section_id);
+
+ if (checked == '1' || protoval != 'static') {
+ dhcpv6.node.querySelector('li[data-value="server"]').setAttribute('unselectable', '');
+
+ if (dhcpv6.getValue() == 'server')
+ dhcpv6.setValue('hybrid');
+
+ ra.node.querySelector('li[data-value="server"]').setAttribute('unselectable', '');
+
+ if (ra.getValue() == 'server')
+ ra.setValue('hybrid');
+ }
+
+ if (checked == '1') {
+ dhcpv6.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc;
+ ra.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc;
+ ndp.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_master_desc;
+ }
+ else {
+ if (protoval == 'static') {
+ dhcpv6.node.querySelector('li[data-value="server"]').removeAttribute('unselectable');
+ ra.node.querySelector('li[data-value="server"]').removeAttribute('unselectable');
+ }
+
+ dhcpv6.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_downstream_desc;
+ ra.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = hybrid_downstream_desc;
+ ndp.node.querySelector('li[data-value="hybrid"] > div > span').innerHTML = ndp_downstream_desc ;
+ }
+
+ return true;
+ };
+
+
+ so = ss.taboption('ipv6', cbiRichListValue, 'ra', _('<abbr title="Router Advertisement">RA</abbr>-Service'),
+ _('Configures the operation mode of the <abbr title="Router Advertisement">RA</abbr> service on this interface.'));
+ so.value('', _('disabled'),
+ _('Do not send any <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages on this interface.'));
+ so.value('server', _('server mode'),
+ _('Send <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages advertising this device as IPv6 router.'));
+ so.value('relay', _('relay mode'),
+ _('Forward <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages received on the designated master interface to downstream interfaces.'));
+ so.value('hybrid', _('hybrid mode'), ' ');
+
+
+ so = ss.taboption('ipv6-ra', cbiRichListValue, 'ra_default', _('Default router'),
+ _('Configures the default router advertisement in <abbr title="Router Advertisement">RA</abbr> messages.'));
+ so.value('', _('automatic'),
+ _('Announce this device as default router if a local IPv6 default route is present.'));
+ so.value('1', _('on available prefix'),
+ _('Announce this device as default router if a public IPv6 prefix is available, regardless of local default route availability.'));
+ so.value('2', _('forced'),
+ _('Announce this device as default router regardless of whether a prefix or default route is present.'));
+ so.depends('ra', 'server');
+ so.depends({ ra: 'hybrid', master: '0' });
+
+ so = ss.taboption('ipv6-ra', form.Flag, 'ra_slaac', _('Enable <abbr title="Stateless Address Auto Config">SLAAC</abbr>'),
+ _('Set the autonomous address-configuration flag in the prefix information options of sent <abbr title="Router Advertisement">RA</abbr> messages. When enabled, clients will perform stateless IPv6 address autoconfiguration.'));
+ so.default = so.enabled;
+ so.depends('ra', 'server');
+ so.depends({ ra: 'hybrid', master: '0' });
+
+ so = ss.taboption('ipv6-ra', cbiRichListValue, 'ra_flags', _('<abbr title="Router Advertisement">RA</abbr> Flags'),
+ _('Specifies the flags sent in <abbr title="Router Advertisement">RA</abbr> messages, for example to instruct clients to request further information via stateful DHCPv6.'));
+ so.value('managed-config', _('managed config (M)'),
+ _('The <em>Managed address configuration</em> (M) flag indicates that IPv6 addresses are available via DHCPv6.'));
+ so.value('other-config', _('other config (O)'),
+ _('The <em>Other configuration</em> (O) flag indicates that other information, such as DNS servers, is available via DHCPv6.'));
+ so.value('home-agent', _('mobile home agent (H)'),
+ _('The <em>Mobile IPv6 Home Agent</em> (H) flag indicates that the device is also acting as Mobile IPv6 home agent on this link.'));
+ so.multiple = true;
+ so.select_placeholder = _('none');
+ so.depends('ra', 'server');
+ so.depends({ ra: 'hybrid', master: '0' });
+ so.cfgvalue = function(section_id) {
+ var flags = L.toArray(uci.get('dhcp', section_id, 'ra_flags'));
+ return flags.length ? flags : [ 'other-config' ];
+ };
+ so.remove = function(section_id) {
+ uci.set('dhcp', section_id, 'ra_flags', [ 'none' ]);
};
- ss.taboption('advanced', form.DynamicList, 'dhcp_option', _('DHCP-Options'), _('Define additional DHCP options, \
- for example "<code>6,192.168.2.1,192.168.2.2</code>" which advertises different DNS servers to clients.'));
-
- for (var i = 0; i < ss.children.length; i++)
- if (ss.children[i].option != 'ignore')
- ss.children[i].depends('ignore', '0');
-
- so = ss.taboption('ipv6', form.ListValue, 'ra', _('<abbr title="Router Advertisement">RA</abbr>-Service'), _('<ul style="list-style-type:none;">\
- <li><strong>server mode</strong>: Router advertises itself as the default IPv6 gateway \
- via <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages \
- (to <code>ff02::1</code>) and provides <abbr title="Prefix Delegation">PD</abbr> to downstream devices.</li>\
- <li><strong>relay mode</strong>: Router relays <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> from upstream, \
- and extends upstream (e.g. WAN) interface config and prefix to downstream (e.g. LAN) interfaces.</li>\
- <li><strong>hybrid mode</strong>: Router does both server+relay; extends upstream config and prefix downstream, and \
- uses <abbr title="Prefix Delegation">PD</abbr> locally.</li></ul>'));
- so.value('', _('disabled'));
- so.value('server', _('server mode'));
- so.value('relay', _('relay mode'));
- so.value('hybrid', _('hybrid mode'));
-
- so = ss.taboption('ipv6', form.Value, 'ra_maxinterval', _('Max <abbr title="Router Advertisement">RA</abbr> interval'), _('Maximum time allowed \
- between sending unsolicited <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr>. Default is 600 seconds (<code>600</code>).'));
+ so = ss.taboption('ipv6-ra', form.Value, 'ra_maxinterval', _('Max <abbr title="Router Advertisement">RA</abbr> interval'), _('Maximum time allowed between sending unsolicited <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr>. Default is 600 seconds.'));
so.optional = true;
+ so.datatype = 'uinteger';
so.placeholder = '600';
so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
- so.depends('ra', 'relay');
-
+ so.depends({ ra: 'hybrid', master: '0' });
- so = ss.taboption('ipv6', form.Value, 'ra_mininterval', _('Min <abbr title="Router Advertisement">RA</abbr> interval'), _('Minimum time allowed \
- between sending unsolicited <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr>. Default is 200 seconds (<code>200</code>).'));
+ so = ss.taboption('ipv6-ra', form.Value, 'ra_mininterval', _('Min <abbr title="Router Advertisement">RA</abbr> interval'), _('Minimum time allowed between sending unsolicited <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr>. Default is 200 seconds.'));
so.optional = true;
+ so.datatype = 'uinteger';
so.placeholder = '200';
so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
- so.depends('ra', 'relay');
+ so.depends({ ra: 'hybrid', master: '0' });
- so = ss.taboption('ipv6', form.Value, 'ra_lifetime', _('<abbr title="Router Advertisement">RA</abbr> Lifetime'), _('Router Lifetime published \
- in <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages. Default is 1800 seconds (<code>1800</code>). \
- Max 9000 seconds.'));
+ so = ss.taboption('ipv6-ra', form.Value, 'ra_lifetime', _('<abbr title="Router Advertisement">RA</abbr> Lifetime'), _('Router Lifetime published in <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages. Maximum is 9000 seconds.'));
so.optional = true;
+ so.datatype = 'range(0, 9000)';
+ so.placeholder = '1800';
so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
- so.depends('ra', 'relay');
+ so.depends({ ra: 'hybrid', master: '0' });
- so = ss.taboption('ipv6', form.Value, 'ra_mtu', _('<abbr title="Router Advertisement">RA</abbr> MTU'), _('The <abbr title="Maximum Transmission Unit">MTU</abbr> \
- to be published in <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages. Default is 0 (<code>0</code>).\
- Min 1280.'));
+ so = ss.taboption('ipv6-ra', form.Value, 'ra_mtu', _('<abbr title="Router Advertisement">RA</abbr> MTU'), _('The <abbr title="Maximum Transmission Unit">MTU</abbr> to be published in <abbr title="Router Advertisement, ICMPv6 Type 134">RA</abbr> messages. Minimum is 1280 bytes.'));
so.optional = true;
+ so.datatype = 'range(1280, 65535)';
so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
- so.depends('ra', 'relay');
+ so.depends({ ra: 'hybrid', master: '0' });
+ so.load = function(section_id) {
+ var dev = ifc.getL3Device();
+
+ if (dev) {
+ var path = "/proc/sys/net/ipv6/conf/%s/mtu".format(dev.getName());
+
+ return L.resolveDefault(fs.read(path), dev.getMTU()).then(L.bind(function(data) {
+ this.placeholder = data;
+ }, this));
+ }
+ };
- so = ss.taboption('ipv6', form.Value, 'ra_hoplimit', _('<abbr title="Router Advertisement">RA</abbr> Hop Limit'), _('The maximum hops \
- to be published in <abbr title="Router Advertisement">RA</abbr> messages.<br />Default is 0 (<code>0</code>), meaning unspecified.\
- Max 255.'));
+ so = ss.taboption('ipv6-ra', form.Value, 'ra_hoplimit', _('<abbr title="Router Advertisement">RA</abbr> Hop Limit'), _('The maximum hops to be published in <abbr title="Router Advertisement">RA</abbr> messages. Maximum is 255 hops.'));
so.optional = true;
+ so.datatype = 'range(0, 255)';
so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
- so.depends('ra', 'relay');
-
- so = ss.taboption('ipv6', form.ListValue, 'ra_management', _('DHCPv6-Mode'), _('Default is stateless + stateful<br />\
- <ul style="list-style-type:none;">\
- <li><strong>stateless</strong>: Router advertises prefixes, host uses <abbr title="Stateless Address Auto Config">SLAAC</abbr> \
- to self assign its own address. No DHCPv6.</li>\
- <li><strong>stateless + stateful</strong>: SLAAC. In addition, router assigns an IPv6 address to a host via DHCPv6.</li>\
- <li><strong>stateful-only</strong>: No SLAAC. Router assigns an IPv6 address to a host via DHCPv6.</li></ul>'));
- so.value('0', _('stateless'));
- so.value('1', _('stateless + stateful'));
- so.value('2', _('stateful-only'));
+ so.depends({ ra: 'hybrid', master: '0' });
+ so.load = function(section_id) {
+ var dev = ifc.getL3Device();
+
+ if (dev) {
+ var path = "/proc/sys/net/ipv6/conf/%s/hop_limit".format(dev.getName());
+
+ return L.resolveDefault(fs.read(path), 64).then(L.bind(function(data) {
+ this.placeholder = data;
+ }, this));
+ }
+ };
+
+
+ so = ss.taboption('ipv6', cbiRichListValue, 'dhcpv6', _('DHCPv6-Service'),
+ _('Configures the operation mode of the DHCPv6 service on this interface.'));
+ so.value('', _('disabled'),
+ _('Do not offer DHCPv6 service on this interface.'));
+ so.value('server', _('server mode'),
+ _('Provide a DHCPv6 server on this interface and reply to DHCPv6 solicitations and requests.'));
+ so.value('relay', _('relay mode'),
+ _('Forward DHCPv6 messages between the designated master interface and downstream interfaces.'));
+ so.value('hybrid', _('hybrid mode'), ' ');
+
+
+ so = ss.taboption('ipv6', form.DynamicList, 'dns', _('Announced IPv6 DNS servers'),
+ _('Specifies a fixed list of IPv6 DNS server addresses to announce via DHCPv6. If left unspecified, the device will announce itself as IPv6 DNS server unless the <em>Local IPv6 DNS server</em> option is disabled.'));
+ so.datatype = 'ip6addr("nomask")'; /* restrict to IPv6 only for now since dnsmasq (DHCPv4) does not honour this option */
so.depends('dhcpv6', 'server');
- so.depends('dhcpv6', 'hybrid');
- so.default = '1';
-
- so = ss.taboption('ipv6', form.ListValue, 'dhcpv6', _('DHCPv6-Service'), _('<ul style="list-style-type:none;">\
- <li><strong>server mode</strong>: Router assigns IPs and delegates prefixes \
- (<abbr title="Prefix Delegation">PD</abbr>) to downstream interfaces.</li>\
- <li><strong>relay mode</strong>: Router relays WAN interface config downstream. Helps support upstream \
- links that lack <abbr title="Prefix Delegation">PD</abbr>.</li>\
- <li><strong>hybrid mode</strong>: Router does combination of server+relay.</li></ul>'));
- so.value('', _('disabled'));
- so.value('server', _('server mode'));
- so.value('relay', _('relay mode'));
- so.value('hybrid', _('hybrid mode'));
-
- so = ss.taboption('ipv6', form.ListValue, 'ndp', _('<abbr title="Neighbour Discovery Protocol">NDP</abbr>-Proxy'), _('Reverts to \
- disabled internally if there are no interfaces with boolean <code>ndproxy_slave</code> set to 1. Think of \
- <abbr title="Neighbour Discovery Protocol">NDP</abbr> Proxy as Proxy ARP for IPv6: unify hosts on different physical \
- hardware segments into the same IP subnet. Consists of <abbr title="Neighbour Solicitation, Type 135">NS</abbr> and \
- <abbr title="Neighbour Advertisement, Type 136">NA</abbr> messages. <abbr title="Neighbour Discovery Protocol">NDP</abbr>-Proxy \
- listens for <abbr title="Neighbour Solicitation, Type 135">NS</abbr> on an interface marked with boolean \
- <code>master</code> as 1 (i.e. upstream), then queries the slave/internal interfaces for that target IP before finally \
- sending an <abbr title="Neighbour Advertisement, Type 136">NA</abbr> message. \
- <abbr title="Neighbour Discovery Protocol">NDP</abbr> is effectively ARP for IPv6. \
- <abbr title="Neighbour Solicitation, Type 135">NS</abbr> and <abbr title="Neighbour Advertisement, Type 136">NA</abbr> \
- detect reachability and duplicate addresses on a link, themselves also a prerequisite for SLAAC autoconfig.<br />\
- <ul style="list-style-type:none;">\
- <li><strong>disabled</strong>: No <abbr title="Neighbour Discovery Protocol">NDP</abbr> messages are proxied through to \
- <code>ndproxy_slave</code> true interfaces.</li> \
- <li><strong>relay mode</strong>: Proxies <abbr title="Neighbour Discovery Protocol">NDP</abbr> messages from <code>master</code> to \
- <code>ndproxy_slave</code> true interfaces. Helps to support provider links without \
- <abbr title="Prefix Delegation">PD</abbr>, and to firewall proxied hosts.</li>\
- <li><strong>hybrid mode</strong>: Relay mode is disabled unless the interface boolean <code>master</code> is 1.</li></ul>'));
- so.value('', _('disabled'));
- so.value('relay', _('relay mode'));
- so.value('hybrid', _('hybrid mode'));
-
- so = ss.taboption('ipv6', form.Flag, 'ndproxy_routing', _('Learn routes from NDP'), _('Default is on.'));
- so.default = '1';
- so.optional = true;
+ so.depends({ dhcpv6: 'hybrid', master: '0' });
- so = ss.taboption('ipv6', form.Flag, 'ndproxy_slave', _('NDP-Proxy slave'), _('Set interface as NDP-Proxy external slave. Default is off.'));
+ so = ss.taboption('ipv6', form.Flag, 'dns_service', _('Local IPv6 DNS server'),
+ _('Announce this device as IPv6 DNS server.'));
+ so.default = so.enabled;
+ so.depends({ dhcpv6: 'server', dns: /^$/ });
+ so.depends({ dhcpv6: 'hybrid', dns: /^$/, master: '0' });
- so = ss.taboption('ipv6', form.DynamicList, 'ndproxy_static', _('Static NDP-Proxy prefixes'));
+ so = ss.taboption('ipv6', form.DynamicList, 'domain', _('Announced DNS domains'),
+ _('Specifies a fixed list of DNS search domains to announce via DHCPv6. If left unspecified, the local device DNS search domain will be announced.'));
+ so.datatype = 'hostname';
+ so.depends('dhcpv6', 'server');
+ so.depends({ dhcpv6: 'hybrid', master: '0' });
- so = ss.taboption('ipv6', form.Flag , 'master', _('Master'), _('Set this interface as master for the dhcpv6 relay.'));
- so.depends('dhcpv6', 'relay');
- so.depends('dhcpv6', 'hybrid');
- so = ss.taboption('ipv6', form.Flag, 'ra_default', _('Announce as default router'), _('Always, even if no public prefix is available.'));
- so.depends('ra', 'server');
- so.depends('ra', 'hybrid');
+ so = ss.taboption('ipv6', cbiRichListValue, 'ndp', _('<abbr title="Neighbour Discovery Protocol">NDP</abbr>-Proxy'),
+ _('Configures the operation mode of the NDP proxy service on this interface.'));
+ so.value('', _('disabled'),
+ _('Do not proxy any <abbr title="Neighbour Discovery Protocol">NDP</abbr> packets.'));
+ so.value('relay', _('relay mode'),
+ _('Forward <abbr title="Neighbour Discovery Protocol">NDP</abbr> <abbr title="Neighbour Solicitation, Type 135">NS</abbr> and <abbr title="Neighbour Advertisement, Type 136">NA</abbr> messages between the designated master interface and downstream interfaces.'));
+ so.value('hybrid', _('hybrid mode'), ' ');
- ss.taboption('ipv6', form.DynamicList, 'dns', _('Announced DNS servers'));
- ss.taboption('ipv6', form.DynamicList, 'domain', _('Announced DNS domains'));
+
+ so = ss.taboption('ipv6', form.Flag, 'ndproxy_routing', _('Learn routes'), _('Setup routes for proxied IPv6 neighbours.'));
+ so.default = so.enabled;
+ so.depends('ndp', 'relay');
+ so.depends('ndp', 'hybrid');
+
+ so = ss.taboption('ipv6', form.Flag, 'ndproxy_slave', _('NDP-Proxy slave'), _('Set interface as NDP-Proxy external slave. Default is off.'));
+ so.depends({ ndp: 'relay', master: '0' });
+ so.depends({ ndp: 'hybrid', master: '0' });
}
ifc.renderFormOptions(s);
@@ -1124,6 +1258,18 @@ return view.extend({
if (m) {
var devtype = getDevType(section_id);
+ /* Treat not explicitly configured, preexisting VLAN interfaces
+ as simple network devices when adding configuration for them,
+ since it is more likely that people want to set general device
+ properties such as MAC address instead of reconfiguring ingress/
+ egress QoS mapping, which is the only editable property of
+ preexisting VLAN device config dialogs.
+
+ Ref: https://github.com/openwrt/luci/issues/5102
+ */
+ if (devtype == '8021q')
+ devtype = 'ethernet';
+
section_id = uci.add('network', 'device');
uci.set('network', section_id, 'name', m[1]);
@@ -1160,7 +1306,7 @@ return view.extend({
nettools.addDeviceOptions(s, dev, isNew);
};
- s.handleModalCancel = function(/* ... */) {
+ s.handleModalCancel = function(map /*, ... */) {
var name = uci.get('network', this.addedSection, 'name')
uci.sections('network', 'bridge-vlan', function(bvs) {
@@ -1168,6 +1314,10 @@ return view.extend({
uci.remove('network', bvs['.name']);
});
+ if (map.addedVLANs)
+ for (var i = 0; i < map.addedVLANs.length; i++)
+ uci.remove('network', map.addedVLANs[i]);
+
return form.GridSection.prototype.handleModalCancel.apply(this, arguments);
};
@@ -1179,10 +1329,11 @@ return view.extend({
}
function getDevType(section_id) {
- var cfgtype = uci.get('network', section_id, 'type'),
- dev = getDevice(section_id);
+ var dev = getDevice(section_id),
+ cfg = uci.get('network', section_id),
+ type = cfg ? (uci.get('network', section_id, 'type') || 'ethernet') : (dev ? dev.getType() : '');
- switch (cfgtype || (dev ? dev.getType() : '')) {
+ switch (type) {
case '':
return null;
@@ -1292,9 +1443,7 @@ return view.extend({
s.addremove = false;
s.anonymous = true;
- o = s.option(form.Value, 'ula_prefix', _('IPv6 ULA-Prefix'), _('Unique Local Address - in the range <code>fc00::/7</code>. \
- Typically only within the &#8216;local&#8217; half <code>fd00::/8</code>. ULA for IPv6 is analogous to IPv4 private network addressing.\
- This prefix is randomly generated at first install.'));
+ o = s.option(form.Value, 'ula_prefix', _('IPv6 ULA-Prefix'), _('Unique Local Address - in the range <code>fc00::/7</code>. Typically only within the &#8216;local&#8217; half <code>fd00::/8</code>. ULA for IPv6 is analogous to IPv4 private network addressing. This prefix is randomly generated at first install.'));
o.datatype = 'cidr6';
o = s.option(form.Flag, 'packet_steering', _('Packet Steering'), _('Enable packet steering across all CPUs. May help or hinder network speed.'));
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js
index 748cb6254f..8f3f7a24ed 100644
--- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js
@@ -199,7 +199,9 @@ function format_wifirate(rate) {
var s = '%.1f\xa0%s, %d\xa0%s'.format(rate.rate / 1000, _('Mbit/s'), rate.mhz, _('MHz')),
ht = rate.ht, vht = rate.vht,
mhz = rate.mhz, nss = rate.nss,
- mcs = rate.mcs, sgi = rate.short_gi;
+ mcs = rate.mcs, sgi = rate.short_gi,
+ he = rate.he, he_gi = rate.he_gi,
+ he_dcm = rate.he_dcm;
if (ht || vht) {
if (vht) s += ', VHT-MCS\xa0%d'.format(mcs);
@@ -208,6 +210,13 @@ function format_wifirate(rate) {
if (sgi) s += ', ' + _('Short GI').replace(/ /g, '\xa0');
}
+ if (he) {
+ s += ', HE-MCS\xa0%d'.format(mcs);
+ if (nss) s += ', HE-NSS\xa0%d'.format(nss);
+ if (he_gi) s += ', HE-GI\xa0%d'.format(he_gi);
+ if (he_dcm) s += ', HE-DCM\xa0%d'.format(he_dcm);
+ }
+
return s;
}
@@ -303,16 +312,32 @@ var CBIWifiFrequencyValue = form.Value.extend({
this.callFrequencyList(section_id)
]).then(L.bind(function(data) {
this.channels = {
- '11g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [],
- '11a': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : []
+ '2g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [],
+ '5g': L.hasSystemFeature('hostapd', 'acs') ? [ 'auto', 'auto', true ] : [],
+ '6g': [],
+ '60g': []
};
- for (var i = 0; i < data[1].length; i++)
- this.channels[(data[1][i].mhz > 2484) ? '11a' : '11g'].push(
+ for (var i = 0; i < data[1].length; i++) {
+ var band;
+
+ if (data[1][i].mhz >= 2412 && data[1][i].mhz <= 2484)
+ band = '2g';
+ else if (data[1][i].mhz >= 5160 && data[1][i].mhz <= 5885)
+ band = '5g';
+ else if (data[1][i].mhz >= 5925 && data[1][i].mhz <= 7125)
+ band = '6g';
+ else if (data[1][i].mhz >= 58329 && data[1][i].mhz <= 69120)
+ band = '60g';
+ else
+ continue;
+
+ this.channels[band].push(
data[1][i].channel,
'%d (%d Mhz)'.format(data[1][i].channel, data[1][i].mhz),
!data[1][i].restricted
);
+ }
var hwmodelist = L.toArray(data[0] ? data[0].getHWModes() : null)
.reduce(function(o, v) { o[v] = true; return o }, {});
@@ -320,7 +345,8 @@ var CBIWifiFrequencyValue = form.Value.extend({
this.modes = [
'', 'Legacy', true,
'n', 'N', hwmodelist.n,
- 'ac', 'AC', hwmodelist.ac
+ 'ac', 'AC', hwmodelist.ac,
+ 'ax', 'AX', hwmodelist.ax
];
var htmodelist = L.toArray(data[0] ? data[0].getHTModes() : null)
@@ -337,20 +363,30 @@ var CBIWifiFrequencyValue = form.Value.extend({
'VHT40', '40 MHz', htmodelist.VHT40,
'VHT80', '80 MHz', htmodelist.VHT80,
'VHT160', '160 MHz', htmodelist.VHT160
+ ],
+ 'ax': [
+ 'HE20', '20 MHz', htmodelist.HE20,
+ 'HE40', '40 MHz', htmodelist.HE40,
+ 'HE80', '80 MHz', htmodelist.HE80,
+ 'HE160', '160 MHz', htmodelist.HE160
]
};
this.bands = {
'': [
- '11g', '2.4 GHz', this.channels['11g'].length > 3,
- '11a', '5 GHz', this.channels['11a'].length > 3
+ '2g', '2.4 GHz', this.channels['2g'].length > 3,
+ '5g', '5 GHz', this.channels['5g'].length > 3
],
'n': [
- '11g', '2.4 GHz', this.channels['11g'].length > 3,
- '11a', '5 GHz', this.channels['11a'].length > 3
+ '2g', '2.4 GHz', this.channels['2g'].length > 3,
+ '5g', '5 GHz', this.channels['5g'].length > 3
],
'ac': [
- '11a', '5 GHz', true
+ '5g', '5 GHz', true
+ ],
+ 'ax': [
+ '2g', '2.4 GHz', this.channels['2g'].length > 3,
+ '5g', '5 GHz', this.channels['5g'].length > 3
]
};
}, this));
@@ -410,7 +446,8 @@ var CBIWifiFrequencyValue = form.Value.extend({
bwdt = elem.querySelector('.htmode'),
htval = uci.get('wireless', section_id, 'htmode'),
hwval = uci.get('wireless', section_id, 'hwmode'),
- chval = uci.get('wireless', section_id, 'channel');
+ chval = uci.get('wireless', section_id, 'channel'),
+ bandval = uci.get('wireless', section_id, 'band');
this.setValues(mode, this.modes);
@@ -423,15 +460,24 @@ var CBIWifiFrequencyValue = form.Value.extend({
this.toggleWifiMode(elem);
- if (/a/.test(hwval))
- band.value = '11a';
- else
- band.value = '11g';
+ if (hwval != null) {
+ this.useBandOption = false;
+
+ if (/a/.test(hwval))
+ band.value = '5g';
+ else
+ band.value = '2g';
+ }
+ else {
+ this.useBandOption = true;
+
+ band.value = bandval;
+ }
this.toggleWifiBand(elem);
bwdt.value = htval;
- chan.value = chval;
+ chan.value = chval || chan.options[0].value;
return elem;
},
@@ -485,7 +531,7 @@ var CBIWifiFrequencyValue = form.Value.extend({
cfgvalue: function(section_id) {
return [
uci.get('wireless', section_id, 'htmode'),
- uci.get('wireless', section_id, 'hwmode'),
+ uci.get('wireless', section_id, 'hwmode') || uci.get('wireless', section_id, 'band'),
uci.get('wireless', section_id, 'channel')
];
},
@@ -502,7 +548,12 @@ var CBIWifiFrequencyValue = form.Value.extend({
write: function(section_id, value) {
uci.set('wireless', section_id, 'htmode', value[0] || null);
- uci.set('wireless', section_id, 'hwmode', value[1]);
+
+ if (this.useBandOption)
+ uci.set('wireless', section_id, 'band', value[1]);
+ else
+ uci.set('wireless', section_id, 'hwmode', (value[1] == '2g') ? '11g' : '11a');
+
uci.set('wireless', section_id, 'channel', value[2]);
}
});
@@ -1027,7 +1078,7 @@ return view.extend({
bssid.depends('mode', 'sta');
bssid.depends('mode', 'sta-wds');
- o = ss.taboption('macfilter', form.ListValue, 'macfilter', _('MAC-Address Filter'));
+ o = ss.taboption('macfilter', form.ListValue, 'macfilter', _('MAC Address Filter'));
o.depends('mode', 'ap');
o.depends('mode', 'ap-wds');
o.value('', _('disable'));
@@ -2093,7 +2144,7 @@ return view.extend({
var table = E('table', { 'class': 'table assoclist', 'id': 'wifi_assoclist_table' }, [
E('tr', { 'class': 'tr table-titles' }, [
E('th', { 'class': 'th nowrap' }, _('Network')),
- E('th', { 'class': 'th hide-xs' }, _('MAC-Address')),
+ E('th', { 'class': 'th hide-xs' }, _('MAC address')),
E('th', { 'class': 'th' }, _('Host')),
E('th', { 'class': 'th' }, _('Signal / Noise')),
E('th', { 'class': 'th' }, _('RX Rate / TX Rate'))