mirror of
https://github.com/openwrt/luci.git
synced 2025-12-21 17:04:35 +04:00
luci-mod-network: DHCP; ES6 treatment
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
This commit is contained in:
@@ -9,35 +9,32 @@
|
||||
'require validation';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
var callHostHints, callDUIDHints, callDHCPLeases, CBILeaseStatus, CBILease6Status;
|
||||
var callUfpList;
|
||||
|
||||
callHostHints = rpc.declare({
|
||||
const callHostHints = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getHostHints',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
callDUIDHints = rpc.declare({
|
||||
const callDUIDHints = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getDUIDHints',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
callDHCPLeases = rpc.declare({
|
||||
const callDHCPLeases = rpc.declare({
|
||||
object: 'luci-rpc',
|
||||
method: 'getDHCPLeases',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
callUfpList = rpc.declare({
|
||||
const callUfpList = rpc.declare({
|
||||
object: 'fingerprint',
|
||||
method: 'fingerprint',
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
CBILeaseStatus = form.DummyValue.extend({
|
||||
renderWidget: function(section_id, option_id, cfgvalue) {
|
||||
const CBILeaseStatus = form.DummyValue.extend({
|
||||
renderWidget(section_id, option_id, cfgvalue) {
|
||||
return E([
|
||||
E('h4', _('Active DHCP Leases')),
|
||||
E('table', { 'id': 'lease_status_table', 'class': 'table' }, [
|
||||
@@ -55,8 +52,8 @@ CBILeaseStatus = form.DummyValue.extend({
|
||||
}
|
||||
});
|
||||
|
||||
CBILease6Status = form.DummyValue.extend({
|
||||
renderWidget: function(section_id, option_id, cfgvalue) {
|
||||
const CBILease6Status = form.DummyValue.extend({
|
||||
renderWidget(section_id, option_id, cfgvalue) {
|
||||
return E([
|
||||
E('h4', _('Active DHCPv6 Leases')),
|
||||
E('table', { 'id': 'lease6_status_table', 'class': 'table' }, [
|
||||
@@ -114,18 +111,17 @@ function generateDnsmasqInstanceEntry(data) {
|
||||
|
||||
function getDHCPPools() {
|
||||
return uci.load('dhcp').then(function() {
|
||||
let sections = uci.sections('dhcp', 'dhcp'),
|
||||
tasks = [], pools = [];
|
||||
const tasks = [], pools = [];
|
||||
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
if (sections[i].ignore == '1' || !sections[i].interface)
|
||||
for (const section of uci.sections('dhcp', 'dhcp')) {
|
||||
if (section.ignore == '1' || !section.interface)
|
||||
continue;
|
||||
|
||||
tasks.push(network.getNetwork(sections[i].interface).then(L.bind(function(section_id, net) {
|
||||
var cidr = net ? (net.getIPAddrs()[0] || '').split('/') : null;
|
||||
tasks.push(network.getNetwork(section.interface).then(L.bind(function(section_id, net) {
|
||||
const cidr = net ? (net.getIPAddrs()[0] || '').split('/') : null;
|
||||
|
||||
if (cidr && cidr.length == 2) {
|
||||
var net_mask = calculateNetwork(cidr[0], cidr[1]);
|
||||
const net_mask = calculateNetwork(cidr[0], cidr[1]);
|
||||
|
||||
pools.push({
|
||||
section_id: section_id,
|
||||
@@ -133,7 +129,7 @@ function getDHCPPools() {
|
||||
netmask: net_mask[1]
|
||||
});
|
||||
}
|
||||
}, null, sections[i]['.name'])));
|
||||
}, null, section['.name'])));
|
||||
}
|
||||
|
||||
return Promise.all(tasks).then(function() {
|
||||
@@ -143,26 +139,25 @@ function getDHCPPools() {
|
||||
}
|
||||
|
||||
function validateHostname(sid, s) {
|
||||
if (s == null || s == '')
|
||||
return true;
|
||||
if (!s) return true;
|
||||
|
||||
if (s.length > 256)
|
||||
return _('Expecting: %s').format(_('valid hostname'));
|
||||
|
||||
var labels = s.replace(/^\*?\.?|\.$/g, '').split(/\./);
|
||||
const labels = s.replace(/^\*?\.?|\.$/g, '').split(/\./);
|
||||
|
||||
for (var i = 0; i < labels.length; i++)
|
||||
if (!labels[i].match(/^[a-z0-9_](?:[a-z0-9-]{0,61}[a-z0-9])?$/i))
|
||||
for (const label of labels) {
|
||||
if (!label.match(/^[a-z0-9_](?:[a-z0-9-]{0,61}[a-z0-9])?$/i))
|
||||
return _('Expecting: %s').format(_('valid hostname'));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateDUIDIAID(sid, s) {
|
||||
if (s == null || s == '')
|
||||
return true;
|
||||
if (!s) return true;
|
||||
|
||||
var parts = s.split('%');
|
||||
const parts = s.split('%');
|
||||
if (parts.length > 2)
|
||||
return _('Expecting: %s').format(_('maximum one "%"'));
|
||||
|
||||
@@ -177,7 +172,7 @@ function validateDUIDIAID(sid, s) {
|
||||
};
|
||||
|
||||
function expandAndFormatMAC(macs) {
|
||||
let result = [];
|
||||
const result = [];
|
||||
|
||||
macs.forEach(mac => {
|
||||
if (isValidMAC(mac)) {
|
||||
@@ -192,20 +187,17 @@ function expandAndFormatMAC(macs) {
|
||||
}
|
||||
|
||||
function isValidMAC(sid, s) {
|
||||
if (!s)
|
||||
return true;
|
||||
if (!s) return true;
|
||||
|
||||
let macaddrs = L.toArray(s);
|
||||
|
||||
for (var i = 0; i < macaddrs.length; i++)
|
||||
if (!macaddrs[i].match(/^(([0-9a-f]{1,2}|\*)[:-]){5}([0-9a-f]{1,2}|\*)$/i))
|
||||
return _('Expecting a valid MAC address, optionally including wildcards') + _('; invalid MAC: ') + macaddrs[i];
|
||||
for (const mac of L.toArray(s))
|
||||
if (!mac.match(/^(([0-9a-f]{1,2}|\*)[:-]){5}([0-9a-f]{1,2}|\*)$/i))
|
||||
return _('Expecting a valid MAC address, optionally including wildcards') + _('; invalid MAC: ') + mac;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function() {
|
||||
load() {
|
||||
return Promise.all([
|
||||
callHostHints(),
|
||||
callDUIDHints(),
|
||||
@@ -215,7 +207,7 @@ return view.extend({
|
||||
]);
|
||||
},
|
||||
|
||||
render: function([hosts, duids, pools, networks, macdata]) {
|
||||
render([hosts, duids, pools, networks, macdata]) {
|
||||
let m;
|
||||
|
||||
m = new form.Map('dhcp', _('DHCP'));
|
||||
@@ -230,13 +222,13 @@ return view.extend({
|
||||
return m.render().then(function(mapEl) {
|
||||
poll.add(function() {
|
||||
return callDHCPLeases().then(function(leaseinfo) {
|
||||
var leases = Array.isArray(leaseinfo.dhcp_leases) ? leaseinfo.dhcp_leases : [],
|
||||
leases6 = Array.isArray(leaseinfo.dhcp6_leases) ? leaseinfo.dhcp6_leases : [];
|
||||
const leases = Array.isArray(leaseinfo.dhcp_leases) ? leaseinfo.dhcp_leases : [];
|
||||
const leases6 = Array.isArray(leaseinfo.dhcp6_leases) ? leaseinfo.dhcp6_leases : [];
|
||||
|
||||
cbi_update_table('#lease_status_table',
|
||||
leases.map(function(lease) {
|
||||
var exp;
|
||||
var vendor;
|
||||
let exp;
|
||||
let vendor;
|
||||
|
||||
if (lease.expires === false)
|
||||
exp = E('em', _('unlimited'));
|
||||
@@ -252,9 +244,9 @@ return view.extend({
|
||||
}
|
||||
}
|
||||
|
||||
var hint = lease.macaddr ? hosts[lease.macaddr] : null,
|
||||
name = hint ? hint.name : null,
|
||||
host = null;
|
||||
const hint = lease.macaddr ? hosts[lease.macaddr] : null;
|
||||
const name = hint ? hint.name : null;
|
||||
let host = null;
|
||||
|
||||
if (name && lease.hostname && lease.hostname != name)
|
||||
host = '%s (%s)'.format(lease.hostname, name);
|
||||
@@ -273,7 +265,7 @@ return view.extend({
|
||||
|
||||
cbi_update_table('#lease6_status_table',
|
||||
leases6.map(function(lease) {
|
||||
var exp;
|
||||
let exp;
|
||||
|
||||
if (lease.expires === false)
|
||||
exp = E('em', _('unlimited'));
|
||||
@@ -282,9 +274,9 @@ return view.extend({
|
||||
else
|
||||
exp = '%t'.format(lease.expires);
|
||||
|
||||
var hint = lease.macaddr ? hosts[lease.macaddr] : null,
|
||||
name = hint ? (hint.name || L.toArray(hint.ipaddrs || hint.ipv4)[0] || L.toArray(hint.ip6addrs || hint.ipv6)[0]) : null,
|
||||
host = null;
|
||||
const hint = lease.macaddr ? hosts[lease.macaddr] : null;
|
||||
const name = hint ? (hint.name || L.toArray(hint.ipaddrs || hint.ipv4)[0] || L.toArray(hint.ip6addrs || hint.ipv6)[0]) : null;
|
||||
let host = null;
|
||||
|
||||
if (name && lease.hostname && lease.hostname != name && lease.ip6addr != name)
|
||||
host = '%s (%s)'.format(lease.hostname, name);
|
||||
@@ -310,8 +302,8 @@ return view.extend({
|
||||
});
|
||||
},
|
||||
|
||||
add_dnsmasq_cfg: function(m, networks) {
|
||||
var s, o, ss, so;
|
||||
add_dnsmasq_cfg(m, networks) {
|
||||
let s, o, ss, so;
|
||||
|
||||
s = m.section(form.TypedSection, 'dnsmasq', _('dnsmasq'));
|
||||
s.hidetitle = true;
|
||||
@@ -319,8 +311,8 @@ return view.extend({
|
||||
s.addremove = true;
|
||||
s.addbtntitle = _('Add server instance', 'Dnsmasq instance');
|
||||
s.renderContents = function(/* ... */) {
|
||||
var renderTask = form.TypedSection.prototype.renderContents.apply(this, arguments),
|
||||
sections = this.cfgsections();
|
||||
const renderTask = form.TypedSection.prototype.renderContents.apply(this, arguments);
|
||||
const sections = this.cfgsections();
|
||||
|
||||
return Promise.resolve(renderTask).then(function(nodes) {
|
||||
if (sections.length < 2) {
|
||||
@@ -329,9 +321,9 @@ return view.extend({
|
||||
}
|
||||
else {
|
||||
nodes.querySelectorAll('#cbi-dhcp-dnsmasq > .cbi-section-remove').forEach(function(div, i) {
|
||||
var section = uci.get('dhcp', sections[i]),
|
||||
hline = div.nextElementSibling,
|
||||
btn = div.firstElementChild;
|
||||
const section = uci.get('dhcp', sections[i]);
|
||||
const hline = div.nextElementSibling;
|
||||
const btn = div.firstElementChild;
|
||||
|
||||
if (!section || section['.anonymous']) {
|
||||
hline.innerText = i ? _('Unnamed instance #%d', 'Dnsmasq instance').format(i+1) : _('Default instance', 'Dnsmasq instance');
|
||||
@@ -474,9 +466,9 @@ return view.extend({
|
||||
so.optional = false;
|
||||
so.placeholder = '192.168.10.1#535';
|
||||
so.validate = function(section, value) {
|
||||
var m = this.section.formvalue(section, 'local_addr'),
|
||||
n = this.section.formvalue(section, 'server_addr'),
|
||||
p;
|
||||
const m = this.section.formvalue(section, 'local_addr');
|
||||
let n = this.section.formvalue(section, 'server_addr');
|
||||
let p;
|
||||
|
||||
if (!m || !n) {
|
||||
return _('Both "Relay from" and "Relay to address" must be specified.');
|
||||
@@ -575,7 +567,7 @@ return view.extend({
|
||||
so.optional = true;
|
||||
|
||||
Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) {
|
||||
var [name, display_str] = generateDnsmasqInstanceEntry(val);
|
||||
const [name, display_str] = generateDnsmasqInstanceEntry(val);
|
||||
so.value(name, display_str);
|
||||
});
|
||||
// End pxe_tftp
|
||||
@@ -583,8 +575,8 @@ return view.extend({
|
||||
return s;
|
||||
},
|
||||
|
||||
add_odhcpd_cfg: function(m) {
|
||||
var s, o, ss, so;
|
||||
add_odhcpd_cfg(m) {
|
||||
let s, o, ss, so;
|
||||
|
||||
s = m.section(form.TypedSection, 'odhcpd', _('odhcpd'));
|
||||
s.hidetitle = true;
|
||||
@@ -688,9 +680,9 @@ return view.extend({
|
||||
// End pxe6
|
||||
},
|
||||
|
||||
add_leases_cfg: function(m, hosts, duids, pools, macdata) {
|
||||
var has_dhcpv6 = L.hasSystemFeature('dnsmasq', 'dhcpv6') || L.hasSystemFeature('odhcpd'),
|
||||
s, o, ss, so;
|
||||
add_leases_cfg(m, hosts, duids, pools, macdata) {
|
||||
const has_dhcpv6 = L.hasSystemFeature('dnsmasq', 'dhcpv6') || L.hasSystemFeature('odhcpd');
|
||||
let s, o, ss, so;
|
||||
|
||||
s = m.section(form.TypedSection, '__leases__', _('Leases'));
|
||||
s.hidetitle = true;
|
||||
@@ -730,9 +722,9 @@ return view.extend({
|
||||
_('Only one of the MAC addresses is expected to be in active use on the network at any given time.'));
|
||||
so.rmempty = true;
|
||||
so.cfgvalue = function(section) {
|
||||
var macs = uci.get('dhcp', section, 'mac');
|
||||
var formattedMacs;
|
||||
var hint, entry;
|
||||
const macs = uci.get('dhcp', section, 'mac');
|
||||
let formattedMacs;
|
||||
let hint, entry;
|
||||
|
||||
if(!Array.isArray(macs)){
|
||||
formattedMacs = expandAndFormatMAC(L.toArray(macs));
|
||||
@@ -780,8 +772,8 @@ return view.extend({
|
||||
return isValidMAC(section_id, value);
|
||||
}
|
||||
Object.keys(hosts).forEach(function(mac) {
|
||||
var vendor;
|
||||
var lower_mac = mac.toLowerCase();
|
||||
let vendor;
|
||||
const lower_mac = mac.toLowerCase();
|
||||
if (macdata)
|
||||
vendor = macdata[lower_mac] ? macdata[lower_mac].vendor : null;
|
||||
const hint = vendor || hosts[mac].name || L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4)[0];
|
||||
@@ -792,8 +784,8 @@ return view.extend({
|
||||
so.value('ignore', _('Ignore'));
|
||||
so.datatype = 'or(ip4addr,"ignore")';
|
||||
so.validate = function(section, value) {
|
||||
var m = this.section.formvalue(section, 'mac'),
|
||||
n = this.section.formvalue(section, 'name');
|
||||
const m = this.section.formvalue(section, 'mac');
|
||||
const n = this.section.formvalue(section, 'name');
|
||||
|
||||
if ((m && !m.length > 0) && !n)
|
||||
return _('One of hostname or MAC address must be specified!');
|
||||
@@ -801,27 +793,25 @@ return view.extend({
|
||||
if (!value || value == 'ignore')
|
||||
return true;
|
||||
|
||||
var leases = uci.sections('dhcp', 'host');
|
||||
const leases = uci.sections('dhcp', 'host');
|
||||
|
||||
for (var i = 0; i < leases.length; i++)
|
||||
if (leases[i]['.name'] != section && leases[i].ip == value)
|
||||
for (const lease of leases)
|
||||
if (lease['.name'] != section && lease.ip == value)
|
||||
return _('The IP address %h is already used by another static lease').format(value);
|
||||
|
||||
for (var i = 0; i < pools.length; i++) {
|
||||
var net_mask = calculateNetwork(value, pools[i].netmask);
|
||||
for (const pool of pools) {
|
||||
const net_mask = calculateNetwork(value, pool.netmask);
|
||||
|
||||
if (net_mask && net_mask[0] == pools[i].network)
|
||||
if (net_mask && net_mask[0] == pool.network)
|
||||
return true;
|
||||
}
|
||||
|
||||
return _('The IP address is outside of any DHCP pool address range');
|
||||
};
|
||||
var ipaddrs = {};
|
||||
const ipaddrs = {};
|
||||
Object.keys(hosts).forEach(function(mac) {
|
||||
var addrs = L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4);
|
||||
|
||||
for (var i = 0; i < addrs.length; i++)
|
||||
ipaddrs[addrs[i]] = hosts[mac].name || mac;
|
||||
for (const ip of L.toArray(hosts[mac].ipaddrs || hosts[mac].ipv4))
|
||||
ipaddrs[ip] = hosts[mac].name || mac;
|
||||
});
|
||||
L.sortedKeys(ipaddrs, null, 'addr').forEach(function(ipv4) {
|
||||
o.value(ipv4, ipaddrs[ipv4] ? '%s (%s)'.format(ipv4, ipaddrs[ipv4]) : ipv4);
|
||||
@@ -845,7 +835,7 @@ return view.extend({
|
||||
so.rmempty = true;
|
||||
so.validate = validateDUIDIAID;
|
||||
Object.keys(duids).forEach(function(duid_iaid) {
|
||||
var desc = duids[duid_iaid].hostname || duids[duid_iaid].macaddr || duids[duid_iaid].ip6addrs[0] || '?';
|
||||
const desc = duids[duid_iaid].hostname || duids[duid_iaid].macaddr || duids[duid_iaid].ip6addrs[0] || '?';
|
||||
so.value(duid_iaid, '%s (%s)'.format(duid_iaid, desc));
|
||||
});
|
||||
|
||||
@@ -874,7 +864,7 @@ return view.extend({
|
||||
_('Dnsmasq instance to which this DHCP host section is bound. If unspecified, the section is valid for all dnsmasq instances.'));
|
||||
so.optional = true;
|
||||
Object.values(L.uci.sections('dhcp', 'dnsmasq')).forEach(function(val, index) {
|
||||
var [name, display_str] = generateDnsmasqInstanceEntry(val);
|
||||
const [name, display_str] = generateDnsmasqInstanceEntry(val);
|
||||
so.value(name, display_str);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user