protocols: add client side protocol handler implementations
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
0674fc2041
commit
6a2a53a829
27 changed files with 2730 additions and 0 deletions
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callHostname = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getHostname',
|
||||
expect: { result: '' }
|
||||
});
|
||||
|
||||
return network.registerProtocol('dhcp', {
|
||||
getI18n: function() {
|
||||
return _('DHCP client');
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL2Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'hostname', _('Hostname to send when requesting DHCP'));
|
||||
o.datatype = 'hostname';
|
||||
o.load = function(section_id) {
|
||||
return callHostname().then(L.bind(function(hostname) {
|
||||
this.placeholder = hostname;
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'broadcast', _('Use broadcast flag'), _('Required for certain ISPs, e.g. Charter with DOCSIS 3'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'clientid', _('Client ID to send when requesting DHCP'));
|
||||
o.datatype = 'hexstring';
|
||||
|
||||
s.taboption('advanced', form.Value, 'vendorid', _('Vendor Class to send when requesting DHCP'));
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
|
||||
o.datatype = 'macaddr';
|
||||
o.placeholder = dev ? (dev.getMAC() || '') : '';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('none', {
|
||||
getI18n: function() {
|
||||
return _('Unmanaged');
|
||||
}
|
||||
});
|
|
@ -0,0 +1,222 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
'require validation';
|
||||
|
||||
function isCIDR(value) {
|
||||
return Array.isArray(value) || /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/(\d{1,2}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/.test(value);
|
||||
}
|
||||
|
||||
function calculateBroadcast(s, use_cfgvalue) {
|
||||
var readfn = use_cfgvalue ? 'cfgvalue' : 'formvalue',
|
||||
addropt = s.children.filter(function(o) { return o.option == 'ipaddr'})[0],
|
||||
addrvals = addropt ? L.toArray(addropt[readfn](s.section)) : [],
|
||||
maskopt = s.children.filter(function(o) { return o.option == 'netmask'})[0],
|
||||
maskval = maskopt ? maskopt[readfn](s.section) : null,
|
||||
firstsubnet = maskval ? addrvals[0] + '/' + maskval : addrvals.filter(function(a) { return a.indexOf('/') > 0 })[0];
|
||||
|
||||
if (firstsubnet == null)
|
||||
return null;
|
||||
|
||||
var addr_mask = firstsubnet.split('/'),
|
||||
addr = validation.parseIPv4(addr_mask[0]),
|
||||
mask = addr_mask[1];
|
||||
|
||||
if (!isNaN(mask))
|
||||
mask = validation.parseIPv4(network.prefixToMask(+mask));
|
||||
else
|
||||
mask = validation.parseIPv4(mask);
|
||||
|
||||
var bc = [
|
||||
addr[0] | (~mask[0] >>> 0 & 255),
|
||||
addr[1] | (~mask[1] >>> 0 & 255),
|
||||
addr[2] | (~mask[2] >>> 0 & 255),
|
||||
addr[3] | (~mask[3] >>> 0 & 255)
|
||||
];
|
||||
|
||||
return bc.join('.');
|
||||
}
|
||||
|
||||
function validateBroadcast(section_id, value) {
|
||||
var opt = this.map.lookupOption('broadcast', section_id),
|
||||
node = opt ? this.map.findElement('id', opt[0].cbid(section_id)) : null,
|
||||
addr = node ? calculateBroadcast(this.section, false) : null;
|
||||
|
||||
if (node != null) {
|
||||
if (addr != null)
|
||||
node.querySelector('input').setAttribute('placeholder', addr);
|
||||
else
|
||||
node.querySelector('input').removeAttribute('placeholder');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return network.registerProtocol('static', {
|
||||
CBIIPValue: form.Value.extend({
|
||||
handleSwitch: function(section_id, option_index, ev) {
|
||||
var maskopt = this.map.lookupOption('netmask', section_id);
|
||||
|
||||
if (maskopt == null || !this.isValid(section_id))
|
||||
return;
|
||||
|
||||
var maskval = maskopt[0].formvalue(section_id),
|
||||
addrval = this.formvalue(section_id),
|
||||
prefix = maskval ? network.maskToPrefix(maskval) : 32;
|
||||
|
||||
if (prefix == null)
|
||||
return;
|
||||
|
||||
this.datatype = 'or(cidr4,ipmask4)';
|
||||
|
||||
var parent = L.dom.parent(ev.target, '.cbi-value-field');
|
||||
L.dom.content(parent, form.DynamicList.prototype.renderWidget.apply(this, [
|
||||
section_id,
|
||||
option_index,
|
||||
addrval ? '%s/%d'.format(addrval, prefix) : ''
|
||||
]));
|
||||
|
||||
var masknode = this.map.findElement('id', maskopt[0].cbid(section_id));
|
||||
if (masknode) {
|
||||
parent = L.dom.parent(masknode, '.cbi-value');
|
||||
parent.parentNode.removeChild(parent);
|
||||
}
|
||||
},
|
||||
|
||||
renderWidget: function(section_id, option_index, cfgvalue) {
|
||||
var maskopt = this.map.lookupOption('netmask', section_id),
|
||||
widget = isCIDR(cfgvalue) ? 'DynamicList' : 'Value';
|
||||
|
||||
if (widget == 'DynamicList') {
|
||||
this.datatype = 'or(cidr4,ipmask4)';
|
||||
this.placeholder = _('Add IPv4 address…');
|
||||
}
|
||||
else {
|
||||
this.datatype = 'ip4addr("nomask")';
|
||||
}
|
||||
|
||||
var node = form[widget].prototype.renderWidget.apply(this, [ section_id, option_index, cfgvalue ]);
|
||||
|
||||
if (widget == 'Value')
|
||||
L.dom.append(node, E('button', {
|
||||
'class': 'cbi-button cbi-button-neutral',
|
||||
'title': _('Switch to CIDR list notation'),
|
||||
'aria-label': _('Switch to CIDR list notation'),
|
||||
'click': L.bind(this.handleSwitch, this, section_id, option_index)
|
||||
}, '…'));
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
validate: validateBroadcast
|
||||
}),
|
||||
|
||||
CBINetmaskValue: form.Value.extend({
|
||||
render: function(option_index, section_id, in_table) {
|
||||
var addropt = this.section.children.filter(function(o) { return o.option == 'ipaddr' })[0],
|
||||
addrval = addropt ? addropt.cfgvalue(section_id) : null;
|
||||
|
||||
if (addrval != null && isCIDR(addrval))
|
||||
return E([]);
|
||||
|
||||
this.value('255.255.255.0');
|
||||
this.value('255.255.0.0');
|
||||
this.value('255.0.0.0');
|
||||
|
||||
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
|
||||
},
|
||||
|
||||
validate: validateBroadcast
|
||||
}),
|
||||
|
||||
CBIGatewayValue: form.Value.extend({
|
||||
datatype: 'ip4addr("nomask")',
|
||||
|
||||
render: function(option_index, section_id, in_table) {
|
||||
return network.getWANNetworks().then(L.bind(function(wans) {
|
||||
if (wans.length == 1) {
|
||||
var gwaddr = wans[0].getGatewayAddr();
|
||||
this.placeholder = gwaddr ? '%s (%s)'.format(gwaddr, wans[0].getName()) : '';
|
||||
}
|
||||
|
||||
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
|
||||
}, this));
|
||||
},
|
||||
|
||||
validate: function(section_id, value) {
|
||||
var addropt = this.section.children.filter(function(o) { return o.option == 'ipaddr' })[0],
|
||||
addrval = addropt ? L.toArray(addropt.cfgvalue(section_id)) : null;
|
||||
|
||||
if (addrval != null) {
|
||||
for (var i = 0; i < addrval.length; i++) {
|
||||
var addr = addrval[i].split('/')[0];
|
||||
if (value == addr)
|
||||
return _('The gateway address must not be a local IP address');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
|
||||
CBIBroadcastValue: form.Value.extend({
|
||||
datatype: 'ip4addr("nomask")',
|
||||
|
||||
render: function(option_index, section_id, in_table) {
|
||||
this.placeholder = calculateBroadcast(this.section, true);
|
||||
return form.Value.prototype.render.apply(this, [ option_index, section_id, in_table ]);
|
||||
}
|
||||
}),
|
||||
|
||||
getI18n: function() {
|
||||
return _('Static address');
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL2Device() || this.getDevice(), o;
|
||||
|
||||
s.taboption('general', this.CBIIPValue, 'ipaddr', _('IPv4 address'));
|
||||
s.taboption('general', this.CBINetmaskValue, 'netmask', _('IPv4 netmask'));
|
||||
s.taboption('general', this.CBIGatewayValue, 'gateway', _('IPv4 gateway'));
|
||||
s.taboption('general', this.CBIBroadcastValue, 'broadcast', _('IPv4 broadcast'));
|
||||
s.taboption('general', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface'));
|
||||
o.value('', _('disabled'));
|
||||
o.value('64');
|
||||
o.datatype = 'max(64)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6hint', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.'));
|
||||
for (var i = 33; i <= 64; i++)
|
||||
o.depends('ip6assign', i);
|
||||
|
||||
o = s.taboption('general', form.DynamicList, 'ip6addr', _('IPv6 address'));
|
||||
o.datatype = 'ip6addr';
|
||||
o.placeholder = _('Add IPv6 address…');
|
||||
o.depends('ip6assign', '');
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6gw', _('IPv6 gateway'));
|
||||
o.datatype = 'ip6addr("nomask")';
|
||||
o.depends('ip6assign', '');
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 routed prefix'), _('Public prefix routed to this device for distribution to clients.'));
|
||||
o.datatype = 'ip6addr';
|
||||
o.depends('ip6assign', '');
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6ifaceid', _('IPv6 suffix'), _("Optional. Allowed values: 'eui64', 'random', fixed value like '::1' or '::1:2'. When IPv6 prefix (like 'a:b:c:d::') is received from a delegating server, use the suffix (like '::1') to form the IPv6 address ('a:b:c:d::1') for the interface."));
|
||||
o.datatype = 'ip6hostid';
|
||||
o.placeholder = '::1';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
|
||||
o.datatype = 'macaddr';
|
||||
o.placeholder = dev ? (dev.getMAC() || '') : '';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.datatype = 'max(9200)';
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = this.getMetric() || '0';
|
||||
o.datatype = 'uinteger';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,152 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callTTYDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTTYDevices',
|
||||
params: [ 'with_cdc', 'with_tts' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
network.registerPatternVirtual(/^3g-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('3g', {
|
||||
getI18n: function() {
|
||||
return _('UMTS/GPRS/EV-DO');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || '3g-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'comgt';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'device', _('Modem device'));
|
||||
o.rmempty = false;
|
||||
o.load = function(section_id) {
|
||||
return callTTYDevices(false, true).then(L.bind(function(devices) {
|
||||
if (Array.isArray(devices))
|
||||
for (var i = 0; i < devices.length; i++)
|
||||
this.value(devices[i]);
|
||||
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'service', _('Service Type'));
|
||||
o.value('', _('-- Please choose --'));
|
||||
o.value('umts', 'UMTS/GPRS');
|
||||
o.value('umts_only', _('UMTS only'));
|
||||
o.value('gprs_only', _('GPRS only'));
|
||||
o.value('evdo', 'CDMA/EV-DO');
|
||||
|
||||
s.taboption('general', form.Value, 'apn', _('APN'));
|
||||
s.taboption('general', form.Value, 'pincode', _('PIN'));
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'dialnumber', _('Dial number'));
|
||||
o.placeholder = '*99***1#';
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
|
||||
o.placeholder = '10';
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('hnet', {
|
||||
getI18n: function() {
|
||||
return _('Automatic Homenet (HNCP)');
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'hnet-full';
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL2Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'mode', _('Category'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('external', _('External'));
|
||||
o.value('internal', _('Internal'));
|
||||
o.value('leaf', _('Leaf'));
|
||||
o.value('guest', _('Guest'));
|
||||
o.value('adhoc', _('Ad-Hoc'));
|
||||
o.value('hybrid', _('Hybrid'));
|
||||
o.default = 'auto';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ip6assign', _('IPv6 assignment length'), _('Assign a part of given length of every public IPv6-prefix to this interface'));
|
||||
o.datatype = 'max(128)';
|
||||
o.default = '64';
|
||||
|
||||
s.taboption('advanced', form.Value, 'link_id', _('IPv6 assignment hint'), _('Assign prefix parts using this hexadecimal subprefix ID for this interface.'));
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ip4assign', _('IPv4 assignment length'));
|
||||
o.datatype = 'max(32)';
|
||||
o.default = '24';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'dnsname', _('DNS-Label / FQDN'));
|
||||
o.default = s.section;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
|
||||
o.datatype = 'macaddr';
|
||||
o.placeholder = dev ? (dev.getMAC() || '') : '';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.datatype = 'max(9200)';
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,69 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
network.registerPatternVirtual(/^ipip-.+$/);
|
||||
|
||||
return network.registerProtocol('ipip', {
|
||||
getI18n: function() {
|
||||
return _('IPv4-in-IPv4 (RFC2003)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'ipip-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ipip';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address or FQDN'), _('The IPv4 address or the fully-qualified domain name of the remote tunnel end.'));
|
||||
o.optional = false;
|
||||
o.datatype = 'or(hostname,ip4addr("nomask"))';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('The local IPv4 address over which the tunnel is created (optional).'));
|
||||
o.optional = true;
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
|
||||
o = s.taboption('general', widgets.NetworkSelect, 'tunlink', _('Bind interface'), _('Bind the tunnel to this interface (optional).'));
|
||||
o.exclude = s.section;
|
||||
o.nocreate = true;
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'), _('Specify an MTU (Maximum Transmission Unit) other than the default (1280 bytes).'));
|
||||
o.optional = true;
|
||||
o.placeholder = 1280;
|
||||
o.datatype = 'range(68, 9200)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ttl', _('Override TTL'), _('Specify a TTL (Time to Live) for the encapsulating packet other than the default (64).'));
|
||||
o.optional = true;
|
||||
o.placeholder = 64;
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'tos', _('Override TOS'), _('Specify a TOS (Type of Service).'));
|
||||
o.optional = true;
|
||||
o.datatype = 'range(0, 255)';
|
||||
|
||||
s.taboption('advanced', form.Flag, 'df', _("Don't Fragment"), _("Enable the DF (Don't Fragment) flag of the encapsulating packets."));
|
||||
}
|
||||
});
|
|
@ -0,0 +1,60 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
network.registerPatternVirtual(/^464-.+$/);
|
||||
network.registerErrorCode('CLAT_CONFIG_FAILED', _('CLAT configuration failed'));
|
||||
|
||||
return network.registerProtocol('464xlat', {
|
||||
getI18n: function() {
|
||||
return _('464XLAT (CLAT)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || '464-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return '464xlat';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefix', _('NAT64 Prefix'), _('Leave empty to autodetect'));
|
||||
o.datatype = 'cidr6';
|
||||
|
||||
o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
|
||||
o.nocreate = true;
|
||||
o.exclude = s.section;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,101 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^6in4-.+$/);
|
||||
|
||||
return network.registerProtocol('6in4', {
|
||||
getI18n: function() {
|
||||
return _('IPv6-in-IPv4 (RFC4213)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || '6in4-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return '6in4';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
o.load = function(section_id) {
|
||||
return network.getWANNetworks().then(L.bind(function(nets) {
|
||||
if (nets.length)
|
||||
this.placeholder = nets[0].getIPAddr();
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address'), _('This is usually the address of the nearest PoP operated by the tunnel broker'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6addr', _('Local IPv6 address'), _('This is the local endpoint address assigned by the tunnel broker, it usually ends with <code>...:2/64</code>'));
|
||||
o.datatype = 'cidr6';
|
||||
|
||||
o = s.taboption('general', form.DynamicList, 'ip6prefix', _('IPv6 routed prefix'), _('This is the prefix routed to you by the tunnel broker for use by clients'));
|
||||
o.datatype = 'cidr6';
|
||||
|
||||
o = s.taboption('general', form.Flag, '_update', _('Dynamic tunnel'), _('Enable HE.net dynamic endpoint update'));
|
||||
o.enabled = '1';
|
||||
o.disabled = '0';
|
||||
o.write = function() {};
|
||||
o.remove = function() {};
|
||||
o.cfgvalue = function(section_id) {
|
||||
return !isNaN(+uci.get('network', section_id, 'tunnelid')) ? this.enabled : this.disabled;
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'tunnelid', _('Tunnel ID'));
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('_update', '1');
|
||||
|
||||
o = s.taboption('general', form.Value, 'username', _('HE.net username'), _('This is the plain username for logging into the account'));
|
||||
o.depends('_update', '1');
|
||||
o.validate = function(section_id, value) {
|
||||
if (/^[a-fA-F0-9]{32}$/.test(value))
|
||||
return _('The HE.net endpoint update configuration changed, you must now use the plain username instead of the user ID!');
|
||||
return true;
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('HE.net password'), _('This is either the \'Update Key\' configured for the tunnel or the account password if no update key has been configured'));
|
||||
o.password = true;
|
||||
o.depends('_update', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
|
||||
o.placeholder = '64';
|
||||
o.datatype = 'range(1,255)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,81 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^6rd-.+$/);
|
||||
|
||||
return network.registerProtocol('6rd', {
|
||||
getI18n: function() {
|
||||
return _('IPv6-over-IPv4 (6rd)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || '6rd-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return '6rd';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
o.load = function(section_id) {
|
||||
return network.getWANNetworks().then(L.bind(function(nets) {
|
||||
if (nets.length)
|
||||
this.placeholder = nets[0].getIPAddr();
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('Remote IPv4 address'), _('This IPv4 address of the relay'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 prefix'), _('The IPv6 prefix assigned to the provider, usually ends with <code>::</code>'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'ip6addr';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefixlen', _('IPv6 prefix length'), _('The length of the IPv6 prefix in bits'));
|
||||
o.placeholder = '16';
|
||||
o.datatype = 'range(0,128)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip4prefixlen', _('IPv4 prefix length'), _('The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses.'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'range(0,32)';
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
|
||||
o.placeholder = '64';
|
||||
o.datatype = 'range(1,255)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^6to4-.+$/);
|
||||
|
||||
return network.registerProtocol('6to4', {
|
||||
getI18n: function() {
|
||||
return _('IPv6-over-IPv4 (6to4)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || '6to4-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return '6rd';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Leave empty to use the current WAN address'));
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
o.load = function(section_id) {
|
||||
return network.getWANNetworks().then(L.bind(function(nets) {
|
||||
if (nets.length)
|
||||
this.placeholder = nets[0].getIPAddr();
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
|
||||
o.placeholder = '64';
|
||||
o.datatype = 'range(1,255)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,58 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
return network.registerProtocol('dhcpv6', {
|
||||
getI18n: function() {
|
||||
return _('DHCPv6 client');
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'odhcp6c';
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL2Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'reqaddress', _('Request IPv6-address'));
|
||||
o.value('try');
|
||||
o.value('force');
|
||||
o.value('none', 'disabled');
|
||||
o.default = 'try';
|
||||
|
||||
o = s.taboption('general', form.Value, 'reqprefix', _('Request IPv6-prefix of length'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('no', _('disabled'));
|
||||
o.value('48');
|
||||
o.value('52');
|
||||
o.value('56');
|
||||
o.value('60');
|
||||
o.value('64');
|
||||
o.default = 'auto';
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'ip6prefix', _('Custom delegated IPv6-prefix'));
|
||||
o.datatype = 'cidr6';
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'clientid', _('Client ID to send when requesting DHCP'));
|
||||
o.datatype = 'hexstring';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'macaddr', _('Override MAC address'));
|
||||
o.datatype = 'macaddr';
|
||||
o.placeholder = dev ? (dev.getMAC() || '') : '';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,79 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
network.registerPatternVirtual(/^ds-.+$/);
|
||||
network.registerErrorCode('AFTR_DNS_FAIL', _('Unable to resolve AFTR host name'));
|
||||
|
||||
return network.registerProtocol('dslite', {
|
||||
getI18n: function() {
|
||||
return _('Dual-Stack Lite (RFC6333)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'ds-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ds-lite';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('DS-Lite AFTR address'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'or(hostname,ip6addr("nomask"))';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6addr', _('Local IPv6 address'), _('Leave empty to use the current WAN address'));
|
||||
o.datatype = 'ip6addr("nomask")';
|
||||
o.load = function(section_id) {
|
||||
return network.getWAN6Networks().then(L.bind(function(nets) {
|
||||
if (Array.isArray(nets) && nets.length)
|
||||
this.placeholder = nets[0].getIP6Addr();
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
|
||||
o.nocreate = true;
|
||||
o.exclude = s.section;
|
||||
|
||||
o = s.taboption('advanced', form.ListValue, 'encaplimit', _('Encapsulation limit'));
|
||||
o.rmempty = false;
|
||||
o.default = 'ignore';
|
||||
o.datatype = 'or("ignore",range(0,255))';
|
||||
o.value('ignore', _('ignore'));
|
||||
for (var i = 0; i < 256; i++)
|
||||
o.value(i);
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,96 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
network.registerPatternVirtual(/^map-.+$/);
|
||||
network.registerErrorCode('INVALID_MAP_RULE', _('MAP rule is invalid'));
|
||||
network.registerErrorCode('NO_MATCHING_PD', _('No matching prefix delegation'));
|
||||
network.registerErrorCode('UNSUPPORTED_TYPE', _('Unsupported MAP type'));
|
||||
|
||||
return network.registerProtocol('map', {
|
||||
getI18n: function() {
|
||||
return _('MAP / LW4over6');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'map-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'map-t';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'type', _('Type'));
|
||||
o.value('map-e', 'MAP-E');
|
||||
o.value('map-t', 'MAP-T');
|
||||
o.value('lw4o6', 'LW4over6');
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('BR / DMR / AFTR'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'ip6addr';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('IPv4 prefix'));
|
||||
o.datatype = 'ip4addr';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip4prefixlen', _('IPv4 prefix length'), _('The length of the IPv4 prefix in bits, the remainder is used in the IPv6 addresses.'));
|
||||
o.placeholder = '32';
|
||||
o.datatype = 'range(0,32)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefix', _('IPv6 prefix'), _('The IPv6 prefix assigned to the provider, usually ends with <code>::</code>'));
|
||||
o.rmempty = false;
|
||||
o.datatype = 'ip6addr';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ip6prefixlen', _('IPv6 prefix length'), _('The length of the IPv6 prefix in bits'));
|
||||
o.placeholder = '16';
|
||||
o.datatype = 'range(0,64)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ealen', _('EA-bits length'));
|
||||
o.datatype = 'range(0,48)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'psidlen', _('PSID-bits length'));
|
||||
o.datatype = 'range(0,16)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'offset', _('PSID offset'));
|
||||
o.datatype = 'range(0,16)';
|
||||
|
||||
o = s.taboption('advanced', widgets.NetworkSelect, 'tunlink', _('Tunnel Link'));
|
||||
o.nocreate = true;
|
||||
o.exclude = s.section;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'ttl', _('Use TTL on tunnel interface'));
|
||||
o.placeholder = '64';
|
||||
o.datatype = 'range(1,255)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Use MTU on tunnel interface'));
|
||||
o.placeholder = '1280';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,119 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callTTYDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTTYDevices',
|
||||
params: [ 'with_cdc', 'with_tts' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
network.registerPatternVirtual(/^ncm-.+$/);
|
||||
network.registerErrorCode('CONFIGURE_FAILED', _('Configuration failed'));
|
||||
network.registerErrorCode('DISCONNECT_FAILED', _('Disconnection attempt failed'));
|
||||
network.registerErrorCode('FINALIZE_FAILED', _('Finalizing failed'));
|
||||
network.registerErrorCode('GETINFO_FAILED', _('Modem information query failed'));
|
||||
network.registerErrorCode('INITIALIZE_FAILED', _('Initialization failure'));
|
||||
network.registerErrorCode('SETMODE_FAILED', _('Setting operation mode failed'));
|
||||
network.registerErrorCode('UNSUPPORTED_MODEM', _('Unsupported modem'));
|
||||
|
||||
return network.registerProtocol('ncm', {
|
||||
getI18n: function() {
|
||||
return _('NCM');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'wan';
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'comgt-ncm';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'device', _('Modem device'));
|
||||
o.rmempty = false;
|
||||
o.load = function(section_id) {
|
||||
return callTTYDevices(true, false).then(L.bind(function(devices) {
|
||||
if (Array.isArray(devices))
|
||||
for (var i = 0; i < devices.length; i++)
|
||||
if (/(ttyUSB|cdc-wdm)/.test(devices[i]))
|
||||
this.value(devices[i]);
|
||||
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'service', _('Service Type'));
|
||||
o.value('', _('Modem default'));
|
||||
o.value('preferlte', _('Prefer LTE'));
|
||||
o.value('preferumts', _('Prefer UMTS'));
|
||||
o.value('lte', 'LTE');
|
||||
o.value('umts', 'UMTS/GPRS');
|
||||
o.value('gsm', _('GPRS only'));
|
||||
o.value('auto', _('auto'));
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'pdptype', _('IP Protocol'));
|
||||
o.default = 'IP';
|
||||
o.value('IP', _('IPv4'));
|
||||
o.value('IPV4V6', _('IPv4+IPv6'));
|
||||
o.value('IPV6', _('IPv6'));
|
||||
|
||||
s.taboption('general', form.Value, 'apn', _('APN'));
|
||||
s.taboption('general', form.Value, 'pincode', _('PIN'));
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'dialnumber', _('Dial number'));
|
||||
o.placeholder = '*99***1#';
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
|
||||
o.placeholder = '10';
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,159 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callGetCertificateFiles = rpc.declare({
|
||||
object: 'luci.openconnect',
|
||||
method: 'getCertificates',
|
||||
params: [ 'interface' ],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
var callSetCertificateFiles = rpc.declare({
|
||||
object: 'luci.openconnect',
|
||||
method: 'setCertificates',
|
||||
params: [ 'interface', 'user_certificate', 'user_privatekey', 'ca_certificate' ],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
network.registerPatternVirtual(/^vpn-.+$/);
|
||||
|
||||
function sanitizeCert(s) {
|
||||
if (typeof(s) != 'string')
|
||||
return null;
|
||||
|
||||
s = s.trim();
|
||||
|
||||
if (s == '')
|
||||
return null;
|
||||
|
||||
s = s.replace(/\r\n?/g, '\n');
|
||||
|
||||
if (!s.match(/\n$/))
|
||||
s += '\n';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function validateCert(priv, section_id, value) {
|
||||
var beg = priv ? /^-----BEGIN RSA PRIVATE KEY-----$/ : /^-----BEGIN CERTIFICATE-----$/,
|
||||
end = priv ? /^-----END RSA PRIVATE KEY-----$/ : /^-----END CERTIFICATE-----$/,
|
||||
lines = value.trim().split(/[\r\n]/),
|
||||
start = false,
|
||||
i;
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (lines[i].match(beg))
|
||||
start = true;
|
||||
else if (start && !lines[i].match(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!start || i < lines.length - 1 || !lines[i].match(end))
|
||||
return _('This does not look like a valid PEM file');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return network.registerProtocol('openconnect', {
|
||||
getI18n: function() {
|
||||
return _('OpenConnect (CISCO AnyConnect)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'openconnect';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getDevice().getName(),
|
||||
certLoadPromise = null,
|
||||
o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'server', _('VPN Server'));
|
||||
o.datatype = 'host(0)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'port', _('VPN Server port'));
|
||||
o.placeholder = '443';
|
||||
o.datatype = 'port';
|
||||
|
||||
s.taboption('general', form.Value, 'serverhash', _("VPN Server's certificate SHA1 hash"));
|
||||
s.taboption('general', form.Value, 'authgroup', _('Auth Group'));
|
||||
s.taboption("general", form.Value, "username", _("Username"));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('Password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'password2', _('Password2'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.TextValue, 'usercert', _('User certificate (PEM encoded)'));
|
||||
o.rows = 10;
|
||||
o.monospace = true;
|
||||
o.validate = L.bind(validateCert, o, false);
|
||||
o.load = function(section_id) {
|
||||
certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
|
||||
return certLoadPromise.then(function(certs) { return certs.user_certificate });
|
||||
};
|
||||
o.write = function(section_id, value) {
|
||||
return callSetCertificateFiles(section_id, sanitizeCert(value), null, null);
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.TextValue, 'userkey', _('User key (PEM encoded)'));
|
||||
o.rows = 10;
|
||||
o.monospace = true;
|
||||
o.validate = L.bind(validateCert, o, true);
|
||||
o.load = function(section_id) {
|
||||
certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
|
||||
return certLoadPromise.then(function(certs) { return certs.user_privatekey });
|
||||
};
|
||||
o.write = function(section_id, value) {
|
||||
return callSetCertificateFiles(section_id, null, sanitizeCert(value), null);
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.TextValue, 'ca', _('CA certificate; if empty it will be saved after the first connection.'));
|
||||
o.rows = 10;
|
||||
o.monospace = true;
|
||||
o.validate = L.bind(validateCert, o, false);
|
||||
o.load = function(section_id) {
|
||||
certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
|
||||
return certLoadPromise.then(function(certs) { return certs.ca_certificate });
|
||||
};
|
||||
o.write = function(section_id, value) {
|
||||
return callSetCertificateFiles(section_id, null, null, sanitizeCert(value));
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.depends('defaultroute', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.optional = true;
|
||||
o.placeholder = 1406;
|
||||
o.datatype = 'range(68, 9200)';
|
||||
}
|
||||
});
|
78
protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
Executable file
78
protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
Executable file
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env lua
|
||||
|
||||
local json = require "luci.jsonc"
|
||||
local fs = require "nixio.fs"
|
||||
|
||||
local function readfile(path)
|
||||
local s = fs.readfile(path)
|
||||
return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
|
||||
end
|
||||
|
||||
local function writefile(path, data)
|
||||
local n = fs.writefile(path, data)
|
||||
return (n == #data)
|
||||
end
|
||||
|
||||
local function parseInput()
|
||||
local parse = json.new()
|
||||
local done, err
|
||||
|
||||
while true do
|
||||
local chunk = io.read(4096)
|
||||
if not chunk then
|
||||
break
|
||||
elseif not done and not err then
|
||||
done, err = parse:parse(chunk)
|
||||
end
|
||||
end
|
||||
|
||||
if not done then
|
||||
print(json.stringify({ error = err or "Incomplete input" }))
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
return parse:get()
|
||||
end
|
||||
|
||||
if arg[1] == "list" then
|
||||
print(json.stringify({
|
||||
getCertificates = {
|
||||
interface = "interface"
|
||||
},
|
||||
setCertificates = {
|
||||
interface = "interface",
|
||||
user_certificate = "PEM file data",
|
||||
user_privatekey = "PEM file data",
|
||||
ca_certificate = "PEM file data"
|
||||
}
|
||||
}))
|
||||
elseif arg[1] == "call" then
|
||||
local args = parseInput()
|
||||
|
||||
if not args.interface or
|
||||
type(args.interface) ~= "string" or
|
||||
not args.interface:match("^[a-zA-Z0-9_]+$")
|
||||
then
|
||||
print(json.stringify({ error = "Invalid interface name" }))
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
if arg[2] == "getCertificates" then
|
||||
print(json.stringify({
|
||||
user_certificate = readfile(string.format("/etc/openconnect/user-cert-%s.pem", args.interface)),
|
||||
user_privatekey = readfile(string.format("/etc/openconnect/user-key-%s.pem", args.interface)),
|
||||
ca_certificate = readfile(string.format("/etc/openconnect/ca-%s.pem", args.interface))
|
||||
}))
|
||||
elseif arg[2] == "setCertificates" then
|
||||
if args.user_certificate then
|
||||
writefile(string.format("/etc/openconnect/user-cert-%s.pem", args.interface), args.user_certificate)
|
||||
end
|
||||
if args.user_privatekey then
|
||||
writefile(string.format("/etc/openconnect/user-key-%s.pem", args.interface), args.user_privatekey)
|
||||
end
|
||||
if args.ca_certificate then
|
||||
writefile(string.format("/etc/openconnect/ca-%s.pem", args.interface), args.ca_certificate)
|
||||
end
|
||||
print(json.stringify({ result = true }))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"luci-proto-openconnect": {
|
||||
"description": "Grant access to LuCI OpenConnect procedures",
|
||||
"read": {
|
||||
"ubus": {
|
||||
"luci.openconnect": [ "getCertificates" ]
|
||||
},
|
||||
"uci": [ "network" ]
|
||||
},
|
||||
"write": {
|
||||
"ubus": {
|
||||
"luci.openconnect": [ "setCertificates" ]
|
||||
},
|
||||
"uci": [ "network" ]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^l2tp-.+$/);
|
||||
|
||||
return network.registerProtocol('l2tp', {
|
||||
getI18n: function() {
|
||||
return _('L2TP');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'l2tp-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'xl2tpd';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'server', _('L2TP Server'));
|
||||
o.datatype = 'or(host(1), hostport(1))';
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,140 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callTTYDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTTYDevices',
|
||||
params: [ 'with_cdc', 'with_tts' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
network.registerPatternVirtual(/^ppp-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('ppp', {
|
||||
getI18n: function() {
|
||||
return _('PPP');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'ppp-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ppp';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'device', _('Modem device'));
|
||||
o.rmempty = false;
|
||||
o.load = function(section_id) {
|
||||
return callTTYDevices(true, true).then(L.bind(function(devices) {
|
||||
if (Array.isArray(devices))
|
||||
for (var i = 0; i < devices.length; i++)
|
||||
this.value(devices[i]);
|
||||
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,136 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^pppoa-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('pppoa', {
|
||||
getI18n: function() {
|
||||
return _('PPPoATM');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'pppoa-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ppp-mod-pppoa';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'encaps', _('PPPoA Encapsulation'));
|
||||
o.value('vc', 'VC-Mux');
|
||||
o.value('llc', 'LLC');
|
||||
|
||||
o = s.taboption('general', form.Value, 'atmdev', _('ATM device number'));
|
||||
o.default = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('general', form.Value, 'vci', _('ATM Virtual Channel Identifier (VCI)'));
|
||||
o.default = '35';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('general', form.Value, 'vpi', _('ATM Virtual Path Identifier (VPI)'));
|
||||
o.default = '8';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,114 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^pppoe-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('pppoe', {
|
||||
getI18n: function() {
|
||||
return _('PPPoE');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'pppoe-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ppp-mod-pppoe';
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ac', _('Access Concentrator'), _('Leave empty to autodetect'));
|
||||
o.placeholder = _('auto');
|
||||
|
||||
o = s.taboption('general', form.Value, 'service', _('Service Name'), _('Leave empty to autodetect'));
|
||||
o.placeholder = _('auto');
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'host_uniq', _('Host-Uniq tag content'), _('Raw hex-encoded bytes. Leave empty unless your ISP require this'));
|
||||
o.placeholder = _('auto');
|
||||
o.datatype = 'hexstring';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,123 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^pptp-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('pptp', {
|
||||
getI18n: function() {
|
||||
return _('PPtP');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'pptp-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'ppp-mod-pptp';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'server', _('VPN Server'));
|
||||
o.datatype = 'host(0)';
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.password = true;
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.ListValue, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.value('auto', _('Automatic'));
|
||||
o.value('0', _('Disabled'));
|
||||
o.value('1', _('Manual'));
|
||||
o.default = 'auto';
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,142 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^pppossh-.+$/);
|
||||
|
||||
function write_keepalive(section_id, value) {
|
||||
var f_opt = this.map.lookupOption('_keepalive_failure', section_id),
|
||||
i_opt = this.map.lookupOption('_keepalive_interval', section_id),
|
||||
f = (f_opt != null) ? +f_opt[0].formvalue(section_id) : null,
|
||||
i = (i_opt != null) ? +i_opt[0].formvalue(section_id) : null;
|
||||
|
||||
if (f == null || f == '' || isNaN(f))
|
||||
f = 0;
|
||||
|
||||
if (i == null || i == '' || isNaN(i) || i < 1)
|
||||
i = 1;
|
||||
|
||||
if (f > 0)
|
||||
uci.set('network', section_id, 'keepalive', '%d %d'.format(f, i));
|
||||
else
|
||||
uci.unset('network', section_id, 'keepalive');
|
||||
}
|
||||
|
||||
return network.registerProtocol('pppossh', {
|
||||
getI18n: function() {
|
||||
return _('PPPoSSH');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'pppossh-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'pppossh';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'sshuser', _('SSH username'));
|
||||
o.rmempty = false;
|
||||
o.validate = function(section_id, value) {
|
||||
var id_opt = this.section.children.filter(function(o) { return o.option == 'identity' })[0];
|
||||
if (id_opt && value.length) {
|
||||
var input = this.map.findElement('id', id_opt.cbid(section_id)).querySelector('input[type="text"]');
|
||||
if (input)
|
||||
input.placeholder = (value == 'root' ? '/root' : '/home/' + value) + '/.ssh/id_rsa';
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
o = s.taboption('general', form.Value, 'server', _('SSH server address'));
|
||||
o.datatype = 'host(0)';
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('general', form.Value, 'port', _('SSH server port'));
|
||||
o.datatype = 'port';
|
||||
o.optional = true;
|
||||
o.placeholder = 22;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ssh_options', _('Extra SSH command options'));
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('general', form.DynamicList, 'identity', _('List of SSH key files for auth'));
|
||||
o.optional = true;
|
||||
o.datatype = 'file';
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IP address to assign'));
|
||||
o.datatype = 'ipaddr("nomask")';
|
||||
|
||||
o = s.taboption('general', form.Value, 'peeraddr', _('Peer IP address to assign'));
|
||||
o.datatype = 'ipaddr("nomask")';
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.Flag, 'ipv6', _('Obtain IPv6-Address'), _('Enable IPv6 negotiation on the PPP link'));
|
||||
o.default = o.disabled;
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'peerdns', _('Use DNS servers advertised by peer'), _('If unchecked, the advertised DNS server addresses are ignored'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'dns', _('Use custom DNS servers'));
|
||||
o.depends('peerdns', '0');
|
||||
o.datatype = 'ipaddr';
|
||||
o.cast = 'string';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_failure', _('LCP echo failure threshold'), _('Presume peer to be dead after given amount of LCP echo failures, use 0 to ignore failures'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^(\d+)[ ,]\d+$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, '_keepalive_interval', _('LCP echo interval'), _('Send LCP echo requests at the given interval in seconds, only effective in conjunction with failure threshold'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
o.write = write_keepalive;
|
||||
o.remove = write_keepalive;
|
||||
o.cfgvalue = function(section_id) {
|
||||
var v = uci.get('network', section_id, 'keepalive');
|
||||
if (typeof(v) == 'string' && v != '') {
|
||||
var m = v.match(/^\d+[ ,](\d+)$/);
|
||||
return m ? m[1] : v;
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'demand', _('Inactivity timeout'), _('Close inactive connection after the given amount of seconds, use 0 to persist connection'));
|
||||
o.placeholder = '0';
|
||||
o.datatype = 'uinteger';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,97 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
var callTTYDevices = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getTTYDevices',
|
||||
params: [ 'with_cdc', 'with_tts' ],
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
network.registerPatternVirtual(/^qmi-.+$/);
|
||||
network.registerErrorCode('CALL_FAILED', _('Call failed'));
|
||||
network.registerErrorCode('NO_CID', _('Unable to obtain client ID'));
|
||||
network.registerErrorCode('PLMN_FAILED', _('Setting PLMN failed'));
|
||||
|
||||
return network.registerProtocol('qmi', {
|
||||
getI18n: function() {
|
||||
return _('QMI Cellular');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'qmi-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'uqmi';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var dev = this.getL3Device() || this.getDevice(), o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'device', _('Modem device'));
|
||||
o.rmempty = false;
|
||||
o.load = function(section_id) {
|
||||
return callTTYDevices(true, false).then(L.bind(function(devices) {
|
||||
if (Array.isArray(devices))
|
||||
for (var i = 0; i < devices.length; i++)
|
||||
if (/cdc-wdm/.test(devices[i]))
|
||||
this.value(devices[i]);
|
||||
|
||||
return form.Value.prototype.load.apply(this, [section_id]);
|
||||
}, this));
|
||||
};
|
||||
|
||||
s.taboption('general', form.Value, 'apn', _('APN'));
|
||||
s.taboption('general', form.Value, 'pincode', _('PIN'));
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type'));
|
||||
o.value('both', 'PAP/CHAP (both)');
|
||||
o.value('pap', 'PAP');
|
||||
o.value('chap', 'CHAP');
|
||||
o.value('none', 'NONE');
|
||||
o.default = 'none';
|
||||
|
||||
o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
|
||||
o.depends('auth', 'pap');
|
||||
o.depends('auth', 'chap');
|
||||
o.depends('auth', 'both');
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
|
||||
o.depends('auth', 'pap');
|
||||
o.depends('auth', 'chap');
|
||||
o.depends('auth', 'both');
|
||||
o.password = true;
|
||||
|
||||
if (L.hasSystemFeature('ipv6')) {
|
||||
o = s.taboption('advanced', form.Flag, 'ipv6', _('Enable IPv6 negotiation'));
|
||||
o.default = o.disabled;
|
||||
}
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), _('Maximum amount of seconds to wait for the modem to become ready'));
|
||||
o.placeholder = '10';
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
|
||||
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
|
||||
o.datatype = 'max(9200)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,183 @@
|
|||
'use strict';
|
||||
'require uci';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
network.registerPatternVirtual(/^relay-.+$/);
|
||||
|
||||
var RelayDevicePrototype = {
|
||||
__init__: function(ifname, network) {
|
||||
this.ifname = ifname;
|
||||
this.network = network;
|
||||
},
|
||||
|
||||
_aggregateDevices: function(fn, first) {
|
||||
var devices = this.network ? this.network.getDevices() : [],
|
||||
rv = 0;
|
||||
|
||||
for (var i = 0; i < devices.length; i++) {
|
||||
var v = devices[i][fn].apply(devices[i]);
|
||||
|
||||
if (v != null) {
|
||||
if (first)
|
||||
return v;
|
||||
|
||||
rv += v;
|
||||
}
|
||||
}
|
||||
|
||||
return first ? null : [ rv, devices.length ];
|
||||
},
|
||||
|
||||
getPorts: function() { return this.network ? this.network.getDevices() : [] },
|
||||
|
||||
getType: function() { return 'tunnel' },
|
||||
getTypeI18n: function() { return _('Relay Bridge') },
|
||||
|
||||
getShortName: function() {
|
||||
return '%s "%h"'.format(_('Relay'), this.ifname);
|
||||
},
|
||||
|
||||
isUp: function() {
|
||||
var res = this._aggregateDevices('isUp');
|
||||
return (res[1] > 0 && res[0] == res[1]);
|
||||
},
|
||||
|
||||
getTXBytes: function() { return this._aggregateDevices('getTXBytes')[0] },
|
||||
getRXBytes: function() { return this._aggregateDevices('getRXBytes')[0] },
|
||||
getTXPackets: function() { return this._aggregateDevices('getTXPackets')[0] },
|
||||
getRXPackets: function() { return this._aggregateDevices('getRXPackets')[0] },
|
||||
|
||||
getMAC: function() { return this._aggregateDevices('getMAC', true) },
|
||||
|
||||
getIPAddrs: function() {
|
||||
var ipaddr = this.network ? L.toArray(uci.get('network', this.network.getName(), 'ipaddr'))[0] : null;
|
||||
return (ipaddr != null ? [ ipaddr ] : []);
|
||||
},
|
||||
|
||||
getIP6Addrs: function() { return [] }
|
||||
};
|
||||
|
||||
return network.registerProtocol('relay', {
|
||||
getI18n: function() {
|
||||
return _('Relay bridge');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return 'relay-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'relayd';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
isUp: function() {
|
||||
var dev = this.getDevice();
|
||||
return (dev ? dev.isUp() : false);
|
||||
},
|
||||
|
||||
getDevice: function() {
|
||||
return network.instantiateDevice(this.sid, this, RelayDevicePrototype);
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
if (this.devices)
|
||||
return this.devices;
|
||||
|
||||
var networkNames = L.toArray(uci.get('network', this.sid, 'network')),
|
||||
deviceNames = L.toArray(uci.get('network', this.sid, 'ifname')),
|
||||
devices = {},
|
||||
rv = [];
|
||||
|
||||
for (var i = 0; i < networkNames.length; i++) {
|
||||
var net = network.instantiateNetwork(networkNames[i]),
|
||||
dev = net ? net.getDevice() : null;
|
||||
|
||||
if (dev)
|
||||
devices[dev.getName()] = dev;
|
||||
}
|
||||
|
||||
for (var i = 0; i < deviceNames.length; i++) {
|
||||
var dev = network.getDevice(deviceNames[i]);
|
||||
|
||||
if (dev)
|
||||
devices[dev.getName()] = dev;
|
||||
}
|
||||
|
||||
deviceNames = Object.keys(devices);
|
||||
deviceNames.sort();
|
||||
|
||||
for (var i = 0; i < deviceNames.length; i++)
|
||||
rv.push(devices[deviceNames[i]]);
|
||||
|
||||
this.devices = rv;
|
||||
|
||||
return rv;
|
||||
},
|
||||
|
||||
getUptime: function() {
|
||||
var networkNames = L.toArray(uci.get('network', this.sid, 'network')),
|
||||
uptime = 0;
|
||||
|
||||
for (var i = 0; i < networkNames.length; i++) {
|
||||
var net = network.instantiateNetwork(networkNames[i]);
|
||||
if (net)
|
||||
uptime = Math.max(uptime, net.getUptime());
|
||||
}
|
||||
|
||||
return uptime;
|
||||
},
|
||||
|
||||
getErrors: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'ipaddr', _('Local IPv4 address'), _('Address to access local relay bridge'));
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
|
||||
o = s.taboption('general', widgets.NetworkSelect, 'network', _('Relay between networks'));
|
||||
o.exclude = s.section;
|
||||
o.multiple = true;
|
||||
o.nocreate = true;
|
||||
o.nobridges = true;
|
||||
o.novirtual = true;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'forward_bcast', _('Forward broadcast traffic'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'forward_dhcp', _('Forward DHCP traffic'));
|
||||
o.default = o.enabled;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'gateway', _('Use DHCP gateway'), _('Override the gateway in DHCP responses'));
|
||||
o.datatype = 'ip4addr("nomask")';
|
||||
o.depends('forward_dhcp', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'expiry', _('Host expiry timeout'), _('Specifies the maximum amount of seconds after which hosts are presumed to be dead'));
|
||||
o.placeholder = '30';
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'retry', _('ARP retry threshold'), _('Specifies the maximum amount of failed ARP requests until hosts are presumed to be dead'));
|
||||
o.placeholder = '5';
|
||||
o.datatype = 'min(1)';
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'table', _('Use routing table'), _('Override the table used for internal routes'));
|
||||
o.placeholder = '16800';
|
||||
o.datatype = 'range(0,65535)';
|
||||
}
|
||||
});
|
|
@ -0,0 +1,111 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
network.registerPatternVirtual(/^vpn-.+$/);
|
||||
|
||||
return network.registerProtocol('vpnc', {
|
||||
getI18n: function() {
|
||||
return _('VPNC (CISCO 3000 (and others) VPN)');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'vpnc';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o;
|
||||
|
||||
o = s.taboption('general', form.Value, 'server', _('VPN Server'));
|
||||
o.datatype = 'host(0)';
|
||||
|
||||
o = s.taboption('general', form.Value, 'local_addr', _('VPN Local address'));
|
||||
o.placeholder = '0.0.0.0';
|
||||
o.datatype = 'ipaddr';
|
||||
|
||||
o = s.taboption('general', form.Value, 'local_port', _('VPN Local port'));
|
||||
o.placeholder = '500';
|
||||
o.datatype = 'port';
|
||||
|
||||
o = s.taboption('general', form.Value, 'interface', _('Output Interface'));
|
||||
o.template = 'cbi/network_netlist';
|
||||
|
||||
o = s.taboption('general', form.Value, 'mtu', _('MTU'));
|
||||
o.datatype = 'uinteger';
|
||||
|
||||
s.taboption('general', form.Value, 'username', _('Username'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'password', _('Password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'hexpassword', _('Obfuscated Password'));
|
||||
o.password = true;
|
||||
|
||||
s.taboption('general', form.Value, 'authgroup', _('Auth Group'));
|
||||
|
||||
o = s.taboption('general', form.Value, 'passgroup', _('Group Password'));
|
||||
o.password = true;
|
||||
|
||||
o = s.taboption('general', form.Value, 'hexpassgroup', _('Obfuscated Group Password'));
|
||||
o.password= true;
|
||||
|
||||
s.taboption('general', form.Value, 'domain', _('NT Domain'));
|
||||
s.taboption('general', form.Value, 'vendor', _('Vendor'));
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'dh_group', _('IKE DH Group'));
|
||||
o.value('dh2');
|
||||
o.value('dh1');
|
||||
o.value('dh5');
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'pfs', _('Perfect Forward Secrecy'));
|
||||
o.value('server');
|
||||
o.value('nopfs');
|
||||
o.value('dh1');
|
||||
o.value('dh2');
|
||||
o.value('dh5');
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'natt_mode', _('NAT-T Mode'));
|
||||
o.value('natt', _('RFC3947 NAT-T mode'));
|
||||
o.value('none', _('No NAT-T'));
|
||||
o.value('force-natt', _('Force use of NAT-T'));
|
||||
o.value('cisco-udp', _('Cisco UDP encapsulation'));
|
||||
|
||||
o = s.taboption('general', form.Flag, 'enable_no_enc', _('Disable Encryption'), _('If checked, encryption is disabled'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.taboption('general', form.Flag, 'enable_single_des', _('Enable Single DES'), _('If checked, 1DES is enabled'));
|
||||
o.default = o.disabled;
|
||||
|
||||
o = s.taboption('general', form.Value, 'dpd_idle', _('DPD Idle Timeout'));
|
||||
o.datatype = 'uinteger';
|
||||
o.placeholder = '600';
|
||||
|
||||
o = s.taboption('general', form.Value, 'target_network', _('Target network'));
|
||||
o.placeholder = '0.0.0.0/0';
|
||||
o.datatype = 'network';
|
||||
|
||||
o = s.taboption('general', form.ListValue, 'defaultroute', _('Default Route'), _('Set VPN as Default Route'));
|
||||
o.value('0', _('No'));
|
||||
o.value('1', _('Yes'));
|
||||
}
|
||||
});
|
|
@ -0,0 +1,137 @@
|
|||
'use strict';
|
||||
'require form';
|
||||
'require network';
|
||||
|
||||
function validateBase64(section_id, value) {
|
||||
if (value.length != 44 || !value.match(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/))
|
||||
return _('Invalid Base64 key string');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return network.registerProtocol('wireguard', {
|
||||
getI18n: function() {
|
||||
return _('WireGuard VPN');
|
||||
},
|
||||
|
||||
getIfname: function() {
|
||||
return this._ubus('l3_device') || this.sid;
|
||||
},
|
||||
|
||||
getOpkgPackage: function() {
|
||||
return 'wireguard-tools';
|
||||
},
|
||||
|
||||
isFloating: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
isVirtual: function() {
|
||||
return true;
|
||||
},
|
||||
|
||||
getDevices: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
containsDevice: function(ifname) {
|
||||
return (network.getIfnameOf(ifname) == this.getIfname());
|
||||
},
|
||||
|
||||
renderFormOptions: function(s) {
|
||||
var o, ss;
|
||||
|
||||
// -- general ---------------------------------------------------------------------
|
||||
|
||||
o = s.taboption('general', form.Value, 'private_key', _('Private Key'), _('Required. Base64-encoded private key for this interface.'));
|
||||
o.password = true;
|
||||
o.validate = validateBase64;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('general', form.Value, 'listen_port', _('Listen Port'), _('Optional. UDP port used for outgoing and incoming packets.'));
|
||||
o.datatype = 'port';
|
||||
o.placeholder = _('random');
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('general', form.DynamicList, 'addresses', _('IP Addresses'), _('Recommended. IP addresses of the WireGuard interface.'));
|
||||
o.datatype = 'ipaddr';
|
||||
o.optional = true;
|
||||
|
||||
|
||||
// -- advanced --------------------------------------------------------------------
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'metric', _('Metric'), _('Optional'));
|
||||
o.datatype = 'uinteger';
|
||||
o.placeholder = '0';
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'mtu', _('MTU'), _('Optional. Maximum Transmission Unit of tunnel interface.'));
|
||||
o.datatype = 'range(1280,1420)';
|
||||
o.placeholder = '1420';
|
||||
o.optional = true;
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'fwmark', _('Firewall Mark'), _('Optional. 32-bit mark for outgoing encrypted packets. Enter value in hex, starting with <code>0x</code>.'));
|
||||
o.optional = true;
|
||||
o.validate = function(section_id, value) {
|
||||
if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,4}$/))
|
||||
return _('Invalid hexadecimal value');
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
// -- peers -----------------------------------------------------------------------
|
||||
|
||||
try {
|
||||
s.tab('peers', _('Peers'), _('Further information about WireGuard interfaces and peers at <a href=\'http://wireguard.com\'>wireguard.com</a>.'));
|
||||
}
|
||||
catch(e) {}
|
||||
|
||||
o = s.taboption('peers', form.SectionValue, '_peers', form.TypedSection, 'wireguard_%s'.format(s.section));
|
||||
o.depends('proto', 'wireguard');
|
||||
|
||||
ss = o.subsection;
|
||||
ss.anonymous = true;
|
||||
ss.addremove = true;
|
||||
ss.addbtntitle = _('Add peer');
|
||||
|
||||
ss.renderSectionPlaceholder = function() {
|
||||
return E([], [
|
||||
E('br'),
|
||||
E('em', _('No peers defined yet'))
|
||||
]);
|
||||
};
|
||||
|
||||
o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
|
||||
o.placeholder = 'My Peer';
|
||||
o.datatype = 'string';
|
||||
o.optional = true;
|
||||
|
||||
o = ss.option(form.Value, 'public_key', _('Public Key'), _('Required. Base64-encoded public key of peer.'));
|
||||
o.validate = validateBase64;
|
||||
o.rmempty = false;
|
||||
|
||||
o = ss.option(form.Value, 'preshared_key', _('Preshared Key'), _('Optional. Base64-encoded preshared key. Adds in an additional layer of symmetric-key cryptography for post-quantum resistance.'));
|
||||
o.password = true;
|
||||
o.validate = validateBase64;
|
||||
o.optional = true;
|
||||
|
||||
o = ss.option(form.DynamicList, 'allowed_ips', _('Allowed IPs'), _("Required. IP addresses and prefixes that this peer is allowed to use inside the tunnel. Usually the peer's tunnel IP addresses and the networks the peer routes through the tunnel."));
|
||||
o.datatype = 'ipaddr';
|
||||
o.rmempty = false;
|
||||
|
||||
o = ss.option(form.Flag, 'route_allowed_ips', _('Route Allowed IPs'), _('Optional. Create routes for Allowed IPs for this peer.'));
|
||||
|
||||
o = ss.option(form.Value, 'endpoint_host', _('Endpoint Host'), _('Optional. Host of peer. Names are resolved prior to bringing up the interface.'));
|
||||
o.placeholder = 'vpn.example.com';
|
||||
o.datatype = 'host';
|
||||
|
||||
o = ss.option(form.Value, 'endpoint_port', _('Endpoint Port'), _('Optional. Port of peer.'));
|
||||
o.placeholder = '51820';
|
||||
o.datatype = 'port';
|
||||
|
||||
o = ss.option(form.Value, 'persistent_keepalive', _('Persistent Keep Alive'), _('Optional. Seconds between keep alive messages. Default is 0 (disabled). Recommended value if this device is behind a NAT is 25.'));
|
||||
o.datatype = 'range(0,65535)';
|
||||
o.placeholder = '0';
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue