1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00

fix luci proto

This commit is contained in:
suyuan 2023-04-27 14:30:39 +08:00
parent 660fb657a3
commit 2f1c73c3f1
74 changed files with 0 additions and 5748 deletions

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for 3G
LUCI_DEPENDS:=+comgt
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,160 +0,0 @@
'use strict';
'require rpc';
'require uci';
'require form';
'require network';
var callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ],
expect: { entries: [] },
filter: function(list, params) {
var rv = [];
for (var i = 0; i < list.length; i++)
if (list[i].name.match(/^tty[A-Z]/) || list[i].name.match(/^cdc-wdm/) || list[i].name.match(/^[0-9]+$/))
rv.push(params.path + list[i].name);
return rv.sort();
}
});
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, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(devices) {
for (var i = 0; i < devices.length; i++)
this.value(devices[i]);
return callFileList('/dev/tts/');
}, this)).then(L.bind(function(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');
o = s.taboption('general', form.Value, 'apn', _('APN'));
o.validate = function(section_id, value) {
if (value == null || value == '')
return true;
if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value))
return _('Invalid APN provided');
return true;
};
o = s.taboption('general', form.Value, 'pincode', _('PIN'));
o.datatype = 'and(uinteger,minlength(4),maxlength(8))';
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, 'ppp_ipv6', _('Obtain IPv6 address'));
o.ucioption = 'ipv6';
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.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';
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for Avahi IPv4LL configuration
LUCI_DEPENDS:=+avahi-autoipd
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,16 +0,0 @@
'use strict';
'require network';
return network.registerProtocol('autoip', {
getI18n: function() {
return _('Avahi IPv4LL');
},
getOpkgPackage: function() {
return 'avahi-autoipd';
},
renderFormOptions: function(s) {
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2022 Marc Ahlgrim <marc@onemarcfifty.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for the batman-adv protocol
LUCI_DEPENDS:=+kmod-batman-adv
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,109 +0,0 @@
'use strict';
'require form';
'require network';
network.registerPatternVirtual(/^bat\d+/);
return network.registerProtocol('batadv', {
getI18n: function() {
return _('Batman Device');
},
getIfname: function() {
return this._ubus('l3_device') || this.sid;
},
getOpkgPackage: function() {
return 'kmod-batman-adv';
},
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;
s.tab('mesh', _('Mesh Routing'), _('Mesh and routing related options'));
// @FIXME - the list of routing protocols should not be hard coded but come from batctl
o = s.taboption('mesh', form.ListValue, 'routing_algo', _('Routing Algorithm'),
_('The algorithm that is used to discover mesh routes'));
o.value('BATMAN_IV', 'BATMAN_IV');
o.value('BATMAN_V', 'BATMAN_V');
o.default = 'BATMAN_IV';
o = s.taboption('mesh', form.Flag, 'aggregated_ogms', _('Aggregate Originator Messages'),
_('reduces overhead by collecting and aggregating originator messages in a single packet rather than many small ones'));
o.ucioption = 'aggregated_ogms';
o.default = o.disabled;
o = s.taboption('mesh', form.Value, 'orig_interval', _('Originator Interval'),
_('The value specifies the interval (milliseconds) in which batman-adv floods the network with its protocol information.'));
o.placeholder = '1000';
o.datatype = 'min(1)';
o = s.taboption('mesh', form.Flag, 'ap_isolation', _('Access Point Isolation'),
_('Prevents one wireless client to talk to another. This setting only affects packets without any VLAN tag (untagged packets).'));
o.ucioption = 'ap_isolation';
o.default = o.disabled;
o = s.taboption('mesh', form.Flag, 'bonding', _('Bonding Mode'),
_('When running the mesh over multiple WiFi interfaces per node batman-adv is capable of optimizing the traffic flow to gain maximum performance.'));
o.ucioption = 'bonding';
o.default = o.disabled;
o = s.taboption('mesh', form.Flag, 'bridge_loop_avoidance', _('Avoid Bridge Loops'),
_('In bridged LAN setups it is advisable to enable the bridge loop avoidance in order to avoid broadcast loops that can bring the entire LAN to a standstill.'));
o.ucioption = 'bridge_loop_avoidance';
o.default = o.disabled;
o = s.taboption('mesh', form.Flag, 'distributed_arp_table', _('Distributed ARP Table'),
_('When enabled the distributed ARP table forms a mesh-wide ARP cache that helps non-mesh clients to get ARP responses much more reliably and without much delay.'));
o.ucioption = 'distributed_arp_table';
o.default = o.enabled;
o = s.taboption('mesh', form.Flag, 'fragmentation', _('Fragmentation'),
_('Batman-adv has a built-in layer 2 fragmentation for unicast data flowing through the mesh which will allow to run batman-adv over interfaces / connections that don\'t allow to increase the MTU beyond the standard Ethernet packet size of 1500 bytes. When the fragmentation is enabled batman-adv will automatically fragment over-sized packets and defragment them on the other end. Per default fragmentation is enabled and inactive if the packet fits but it is possible to deactivate the fragmentation entirely.'));
o.ucioption = 'fragmentation';
o.default = o.enabled;
o = s.taboption('mesh', form.ListValue, 'gw_mode', _('Gateway Mode'),
_('A batman-adv node can either run in server mode (sharing its internet connection with the mesh) or in client mode (searching for the most suitable internet connection in the mesh) or having the gateway support turned off entirely (which is the default setting).'));
o.value('off', _('Off'));
o.value('client', _('Client'));
o.value('server', _('Server'));
o.default = 'off';
o = s.taboption('mesh', form.Value, 'hop_penalty', _('Hop Penalty'),
_('The hop penalty setting allows to modify batman-adv\'s preference for multihop routes vs. short routes. The value is applied to the TQ of each forwarded OGM, thereby propagating the cost of an extra hop (the packet has to be received and retransmitted which costs airtime)'));
o.ucioption = 'hop_penalty';
o.datatype = 'min(1)';
o.placeholder = '30';
o.default = '30';
o = s.taboption('mesh', form.Flag, 'multicast_mode', _('Multicast Mode'),
_('Enables more efficient, group aware multicast forwarding infrastructure in batman-adv.'));
o.ucioption = 'multicast_mode';
o.default = o.enabled;
o = s.taboption('mesh', form.Flag, 'network_coding', _('Network Coding'),
_('When enabled network coding increases the WiFi throughput by combining multiple frames into a single frame, thus reducing the needed air time.'));
o.ucioption = 'network_coding';
o.default = o.enabled;
}
});

View file

@ -1,58 +0,0 @@
'use strict';
'require uci';
'require form';
'require network';
network.registerPatternVirtual(/^bat.+$/);
return network.registerProtocol('batadv_hardif', {
getI18n: function() {
return _('Batman Interface');
},
getIfname: function() {
return this._ubus('l3_device') || this.sid;
},
getOpkgPackage: function() {
return 'kmod-batman-adv';
},
isFloating: function() {
return false;
},
isVirtual: function() {
return false;
},
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, 'master', _('Batman Device'),
_('This is the batman-adv device where you want to link the physical Device from above to. If this list is empty, then you need to create one first. If you want to route mesh traffic over a wired network device, then please select it from the above Device selector. If you want to assign the batman-adv interface to a Wi-fi mesh then do not select a Device in the Device selector but rather go to the Wireless settings and select this Interface as a network from there.'));
var uciInterfaces = uci.sections('network', 'interface');
for (var i = 0; i < uciInterfaces.length; i++)
{
if (uciInterfaces[i].proto == 'batadv')
{
var x=uciInterfaces[i]['.name'];
o.value(x);
}
}
o = s.taboption('general', form.Value, 'mtu', _('Override MTU'));
o.placeholder = dev ? (dev.getMTU() || '1536') : '1536';
o.datatype = 'max(9200)';
}
});

View file

@ -1,17 +0,0 @@
#
# Copyright (C) 2020 TDT AG <development@tdt.de>
#
# This is free software, licensed under the Apache License Version 2.0.
# See https://www.apache.org/licenses/LICENSE-2.0 for more information.
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for Link Aggregation (Channel Bonding)
LUCI_DEPENDS:=+proto-bonding
PKG_MAINTAINER:=Helge Mader <ma@dev.tdt.de>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,426 +0,0 @@
'use strict';
'require ui';
'require uci';
'require form';
'require fs';
'require network';
'require tools.widgets as widgets';
function getSelectableSlaves(section_id) {
var rv = [];
var NonUsableMac = /^(00:00:00:00:00:00|null)/;
var interfaces = uci.sections('network', 'interface');
return network.getDevices().then(function(devices) {
for (var i = 0; i < devices.length; i++) {
var in_use = false;
var NotUsable = NonUsableMac.test(devices[i].getMAC());
// Only "real" interfaces for slaves needed
if (NotUsable == false) {
for (var j = 0; j < interfaces.length; j++) {
if (uci.get('network', interfaces[j]['.name'], 'proto') == 'bonding') {
var slaves = L.toArray(uci.get('network', interfaces[j]['.name'], 'slaves'));
for (var k = 0; k < slaves.length; k++) {
if (devices[i].ifname == slaves[k] || devices[i].device == slaves[k]) {
if (interfaces[j]['.name'] != section_id) {
in_use = true;
}
}
}
}
}
if (in_use == false) {
devices[i].device == null ? rv.push(devices[i].ifname) : rv.push(devices[i].device)
}
}
}
return rv.sort();
});
}
function validateEmpty(section, value) {
if (value) {
return true;
}
else {
return _('Expecting: non-empty value');
}
}
function updatePrimaries(section, value) {
var opt = this.map.lookupOption('slaves', section);
var selected_slaves = opt[0].formvalue(section);
var uielem = this.map.lookupOption('primary', section)[0].getUIElement(section);
uielem.clearChoices();
for (var i = 0; i < selected_slaves.length; i++) {
uielem.addChoices(selected_slaves[i], selected_slaves[i]);
}
return true;
}
function validate_arp_policy(section, value) {
var opt = this.map.lookupOption('link_monitoring', section);
var selected_link_monitoring = opt[0].formvalue(section);
var opt = this.map.lookupOption('bonding_policy', section);
var selected_policy = opt[0].formvalue(section);
if (selected_link_monitoring == 'arp') {
if (selected_policy == '802.3ad' || selected_policy == 'balance-tlb' || selected_policy == 'balance-alb') {
return _('ARP monitoring is not supported for the selected policy!');
}
}
return true;
}
function validate_arp_ip_targets(section, value) {
var opt = this.map.lookupOption('link_monitoring', section);
var selected_link_monitoring = opt[0].formvalue(section);
var opt = this.map.lookupOption('arp_ip_target', section);
var selected_arp_ip_targets = opt[0].formvalue(section);
var opt = this.map.lookupOption('bonding_policy', section);
var selected_policy = opt[0].formvalue(section);
if (selected_link_monitoring == 'arp' && selected_arp_ip_targets.length == 0) {
return _('You must select at least one ARP IP target if ARP monitoring is selected!');
}
return true;
}
function validate_primary_interface(section, value) {
var opt = this.map.lookupOption('bonding_policy', section);
var selected_policy = opt[0].formvalue(section);
var opt = this.map.lookupOption('slaves', section);
var selected_slaves = opt[0].formvalue(section);
var opt = this.map.lookupOption('primary', section);
var selected_primary = opt[0].formvalue(section);
if (selected_policy == 'active-backup' || selected_policy == 'balance-tlb' || selected_policy == 'balance-alb') {
if (selected_slaves.filter(function(slave) { return slave == selected_primary }).length == 0)
return _('You must select a primary interface which is included in selected slave interfaces!');
}
return true;
}
return network.registerProtocol('bonding', {
getI18n: function() {
return _('Link Aggregation (Channel Bonding)');
},
getIfname: function() {
return null;
},
getOpkgPackage: function() {
return 'bonding';
},
isFloating: function() {
return true;
},
isCreateable: function(ifname) {
return getSelectableSlaves(ifname).then(L.bind(function(devices) {
return devices.length == 0 ? _('No more slaves available') : null;
}, this));
return _('No more slaves available');
},
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',
_('IPv4 address'),
_('The local IPv4 address'));
o.datatype = 'ip4addr';
o.rmempty = false;
o = s.taboption('general', form.Value, 'netmask',
_('IPv4 netmask'),
_('The local IPv4 netmask'));
o.datatype = 'ip4addr';
o.validate = validateEmpty;
o.rmempty = false;
o.value("255.255.255.0");
o.value("255.255.0.0");
o.value("255.0.0.0");
o = s.taboption('advanced', form.MultiValue, 'slaves',
_('Slave Interfaces'),
_('Specifies which slave interfaces should be attached to this bonding interface'));
o.load = function(section_id) {
return getSelectableSlaves(section_id).then(L.bind(function(devices) {
for (var i = 0; i < devices.length; i++) {
this.value(devices[i], devices[i]);
}
if (devices.length == 0) {
this.placeholder = _('No more slaves available, can not save interface');
this.value('', '');
return '';
}
return uci.get('network', section_id, 'slaves');
}, this));
};
o.validate = updatePrimaries;
o.rmempty = false;
o = s.taboption('advanced', form.ListValue, 'bonding_policy',
_('Bonding Policy'),
_('Specifies the mode to be used for this bonding interface'));
o.default = 'balance-rr';
o.value('balance-rr', _('Round-Robin policy (balance-rr, 0)'));
o.value('active-backup', _('Active-Backup policy (active-backup, 1)'));
o.value('balance-xor', _('XOR policy (balance-xor, 2)'));
o.value('broadcast', _('Broadcast policy (broadcast, 3)'));
o.value('802.3ad', _('IEEE 802.3ad Dynamic link aggregation (802.3ad, 4)'));
o.value('balance-tlb', _('Adaptive transmit load balancing (balance-tlb, 5)'));
o.value('balance-alb', _('Adaptive load balancing (balance-alb, 6)'));
o = s.taboption('advanced', widgets.DeviceSelect, 'primary',
_('Primary Slave'),
_('Specifies which slave is the primary device. It will always be the active slave while it is available'));
o.depends('bonding_policy', 'active-backup');
o.depends('bonding_policy', 'balance-tlb');
o.depends('bonding_policy', 'balance-alb');
o.filter = function(section_id, value) {
// Never return anything as valid, as the valid possibilities
// will be set in the slaves validate function
return false;
};
o.validate = validate_primary_interface;
o = s.taboption('advanced', form.ListValue, 'primary_reselect',
_('Reselection policy for primary slave'),
_('Specifies the reselection policy for the primary slave when failure of the active slave or recovery of the primary slave occurs'));
o.default = 'always';
o.value('always', _('Primary becomes active slave whenever it comes back up (always, 0)'));
o.value('better', _('Primary becomes active slave when it comes back up if speed and duplex better than current slave (better, 1)'));
o.value('failure', _('Only if current active slave fails and the primary slave is up (failure, 2)'));
o.depends('bonding_policy', 'active-backup');
o.depends('bonding_policy', 'balance-tlb');
o.depends('bonding_policy', 'balance-alb');
o = s.taboption('advanced', form.Value, 'min_links',
_('Minimum Number of Links'),
_('Specifies the minimum number of links that must be active before asserting carrier'));
o.datatype = 'uinteger';
o.default = 0;
o.rmempty = false;
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.Value, 'ad_actor_sys_prio',
_('System Priority'),
_('Specifies the system priority'));
o.datatype = 'range(1,65535)';
o.default = 65535;
o.rmempty = false;
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.Value, 'ad_actor_system',
_('MAC Address For The Actor'),
_("Specifies the mac-address for the actor in protocol packet exchanges (LACPDUs). If empty, masters' mac address defaults to system default"));
o.datatype = 'macaddr';
o.default = '';
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.ListValue, 'ad_select',
_('Aggregation Selection Logic'),
_('Specifies the aggregation selection logic to use'));
o.default = 'stable';
o.value('stable', _('Aggregator: All slaves down or has no slaves (stable, 0)'));
o.value('bandwidth', _('Aggregator: Slave added/removed or state changes (bandwidth, 1)'));
o.value('count', _('Aggregator: Chosen by the largest number of ports + slave added/removed or state changes (count, 2)'));
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.ListValue, 'lacp_rate',
_('LACPDU Packets'),
_('Specifies the rate in which the link partner will be asked to transmit LACPDU packets'));
o.default = 'slow';
o.value('slow', _('Every 30 seconds (slow, 0)'));
o.value('fast', _('Every second (fast, 1)'));
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.Value, 'packets_per_slave',
_('Packets To Transmit Before Moving To Next Slave'),
_("Specifies the number of packets to transmit through a slave before moving to the next one"));
o.datatype = 'range(0,65535)';
o.default = '1';
o.rmempty = false;
o.depends('bonding_policy', 'balance-rr');
o = s.taboption('advanced', form.Value, 'lp_interval',
_('Interval For Sending Learning Packets'),
_("Specifies the number of seconds between instances where the bonding driver sends learning packets to each slaves peer switch"));
o.datatype = 'range(1,2147483647)';
o.default = '1';
o.rmempty = false;
o.depends('bonding_policy', 'balance-tlb');
o.depends('bonding_policy', 'balance-alb');
o = s.taboption('advanced', form.ListValue, 'tlb_dynamic_lb',
_('Enable Dynamic Shuffling Of Flows'),
_('Specifies whether to shuffle active flows across slaves based on the load'));
o.default = '1';
o.value('1', _('Yes'));
o.value('0', _('No'));
o.depends('bonding_policy', 'balance-tlb');
o = s.taboption('advanced', form.ListValue, 'fail_over_mac',
_('Set same MAC Address to all slaves'),
_('Specifies whether active-backup mode should set all slaves to the same MAC address at enslavement'));
o.default = 'none';
o.value('none', _('Yes (none, 0)'));
o.value('active', _('Set to currently active slave (active, 1)'));
o.value('follow', _('Set to first slave added to the bond (follow, 2)'));
o.depends('bonding_policy', 'active-backup');
o = s.taboption('advanced', form.Value, 'num_grat_arp__num_unsol_na',
_('Number of peer notifications after failover event'),
_("Specifies the number of peer notifications (gratuitous ARPs and unsolicited IPv6 Neighbor Advertisements) to be issued after a failover event"));
o.datatype = 'range(0,255)';
o.default = '1';
o.rmempty = false;
o.depends('bonding_policy', 'active-backup');
o = s.taboption('advanced', form.ListValue, 'xmit_hash_policy',
_('Transmit Hash Policy'),
_('Selects the transmit hash policy to use for slave selection'));
o.default = 'layer2';
o.value('layer2', _('Use XOR of hardware MAC addresses (layer2)'));
o.value('layer2+3', _('Use XOR of hardware MAC addresses and IP addresses (layer2+3)'));
o.value('layer3+4', _('Use upper layer protocol information (layer3+4)'));
o.value('encap2+3', _('Use XOR of hardware MAC addresses and IP addresses, rely on skb_flow_dissect (encap2+3)'));
o.value('encap3+4', _('Use upper layer protocol information, rely on skb_flow_dissect (encap3+4)'));
o.depends('bonding_policy', 'balance-xor');
o.depends('bonding_policy', 'balance-alb');
o.depends('bonding_policy', 'balance-tlb');
o.depends('bonding_policy', '802.3ad');
o = s.taboption('advanced', form.Value, 'resend_igmp',
_('Number of IGMP membership reports'),
_("Specifies the number of IGMP membership reports to be issued after a failover event in 200ms intervals"));
o.datatype = 'range(0,255)';
o.default = '1';
o.rmempty = false;
o.depends('bonding_policy', 'balance-tlb');
o.depends('bonding_policy', 'balance-alb');
o = s.taboption('advanced', form.ListValue, 'all_slaves_active',
_('Drop Duplicate Frames'),
_('Specifies that duplicate frames (received on inactive ports) should be dropped or delivered'));
o.default = '0';
o.value('0', _('Yes'));
o.value('1', _('No'));
o = s.taboption('advanced', form.ListValue, 'link_monitoring',
_('Link Monitoring'),
_('Method of link monitoring'));
o.default = 'off';
o.value('off', _('Off'));
o.value('arp', _('ARP'));
o.value('mii', _('MII'));
o.validate = validate_arp_policy;
o = s.taboption('advanced', form.Value, 'arp_interval',
_('ARP Interval'),
_("Specifies the ARP link monitoring frequency in milliseconds"));
o.datatype = 'uinteger';
o.default = '0';
o.rmempty = false;
o.depends('link_monitoring', 'arp');
o = s.taboption('advanced', form.DynamicList, 'arp_ip_target',
_('ARP IP Targets'),
_('Specifies the IP addresses to use for ARP monitoring'));
o.datatype = 'ipaddr';
o.cast = 'string';
o.depends('link_monitoring', 'arp');
o.validate = validate_arp_ip_targets;
o = s.taboption('advanced', form.ListValue, 'arp_all_targets',
_('ARP mode to consider a slave as being up'),
_('Specifies the quantity of ARP IP targets that must be reachable'));
o.default = 'any';
o.value('any', _('Consider the slave up when any ARP IP target is reachable (any, 0)'));
o.value('all', _('Consider the slave up when all ARP IP targets are reachable (all, 1)'));
o.depends({link_monitoring: 'arp', bonding_policy: 'active-backup'});
o = s.taboption('advanced', form.ListValue, 'arp_validate',
_('ARP Validation'),
_('Specifies whether ARP probes and replies should be validated or non-ARP traffic should be filtered for link monitoring'));
o.default = 'filter';
o.value('none', _('No validation or filtering'));
o.value('active', _('Validation only for active slave'));
o.value('backup', _('Validation only for backup slaves'));
o.value('all', _('Validation for all slaves'));
o.value('filter', _('Filtering for all slaves, no validation'));
o.value('filter_active', _('Filtering for all slaves, validation only for active slave'));
o.value('filter_backup', _('Filtering for all slaves, validation only for backup slaves'));
o.depends('link_monitoring', 'arp');
o = s.taboption('advanced', form.Value, 'miimon',
_('MII Interval'),
_("Specifies the MII link monitoring frequency in milliseconds"));
o.datatype = 'uinteger';
o.default = '0';
o.rmempty = false;
o.depends('link_monitoring', 'mii');
o = s.taboption('advanced', form.Value, 'downdelay',
_('Down Delay'),
_("Specifies the time in milliseconds to wait before disabling a slave after a link failure detection"));
o.datatype = 'uinteger';
o.default = '0';
o.rmempty = false;
o.depends('link_monitoring', 'mii');
o = s.taboption('advanced', form.Value, 'updelay',
_('Up Delay'),
_("Specifies the time in milliseconds to wait before enabling a slave after a link recovery detection"));
o.datatype = 'uinteger';
o.default = '0';
o.rmempty = false;
o.depends('link_monitoring', 'mii');
o = s.taboption('advanced', form.ListValue, 'use_carrier',
_('Method to determine link status'),
_('Specifies whether or not miimon should use MII or ETHTOOL ioctls vs. netif_carrier_ok()'));
o.default = '1';
o.value('0', _('MII / ETHTOOL ioctls'));
o.value('1', _('netif_carrier_ok()'));
o.depends('link_monitoring', 'mii');
}
});

View file

@ -1,8 +0,0 @@
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for CNI protocol
LUCI_DEPENDS:=+cni-protocol
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,8 +0,0 @@
'use strict';
'require network';
return network.registerProtocol('cni', {
getI18n: function () {
return _('CNI (Externally managed interface)');
}
});

View file

@ -1,21 +0,0 @@
#
# Based on luci-proto-ipip.
# Credited author of luci-proto-ipip is Roger Pueyo Centelles <roger.pueyo@guifi.net>
# Copyright 2016 Roger Pueyo Centelles <roger.pueyo@guifi.net>
#
# Modified by Jan Betik <jan.betik@svine.su>
# Copyright 2020 Jan Betik <jan.betik@svine.su>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for GRE tunnels (RFC2784)
LUCI_DEPENDS:=+gre
PKG_MAINTAINER:=Jan Betik <jan.betik@svine.su>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,106 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^gre4-.+$/);
return network.registerProtocol('gre', {
getI18n: function() {
return _('GRE tunnel over IPv4');
},
getIfname: function() {
return this._ubus('l3_device') || 'gre4-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'gre';
},
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;
// -- general ---------------------------------------------------------------------
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.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));
};
// -- advanced ---------------------------------------------------------------------
o = s.taboption('advanced', 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) (optional)."));
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). Can be <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value <code>00..FF</code> (optional)."));
o.optional = true;
o.validate = function(section_id, value) {
if (value.length > 0 && !value.match(/^[a-f0-9]{1,2}$/i) && !value.match(/^inherit$/i))
return _("Invalid TOS value, expected 00..FF or inherit");
return true;
};
o = s.taboption('advanced', form.Flag, 'df', _("Don't Fragment"), _("Enable the DF (Don't Fragment) flag of the encapsulating packets."));
o.default = o.enabled;
o = s.taboption('advanced', form.Flag, 'nohostroute', _("No host route"), _("Do not create host route to peer (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Flag, 'multicast', _("Multicast"), _("Enable support for multicast traffic (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Value, 'ikey', _("Incoming key"), _("Key for incoming packets (optional)."));
o.optional = true;
o.datatype = 'integer';
o = s.taboption('advanced', form.Value, 'okey', _("Outgoing key"), _("Key for outgoing packets (optional)."));
o.optional = true;
o.datatype = 'integer';
s.taboption('advanced', form.Flag, 'icsum', _("Incoming checksum"), _("Require incoming checksum (optional)."));
s.taboption('advanced', form.Flag, 'ocsum', _("Outgoing checksum"), _("Compute outgoing checksum (optional)."));
s.taboption('advanced', form.Flag, 'iseqno', _("Incoming serialization"), _("Require incoming packets serialization (optional)."));
s.taboption('advanced', form.Flag, 'oseqno', _("Outgoing serialization"), _("Perform outgoing packets serialization (optional)."));
}
});

View file

@ -1,111 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^gre4t-.+$/);
return network.registerProtocol('gretap', {
getI18n: function() {
return _('GRETAP tunnel over IPv4');
},
getIfname: function() {
return this._ubus('l3_device') || 'gre4t-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'gre';
},
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;
// -- general ---------------------------------------------------------------------
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.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', widgets.NetworkSelect, 'network', _("Network interface"), _("Logical network to which the tunnel will be added (bridged) (optional)."));
o.exclude = s.section;
o.nocreate = true;
o.optional = true;
// -- advanced ---------------------------------------------------------------------
o = s.taboption('advanced', 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) (optional)."));
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) (optional)."));
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). Can be <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value <code>00..FF</code> (optional)."));
o.optional = true;
o.validate = function(section_id, value) {
if (value.length > 0 && !value.match(/^[a-f0-9]{1,2}$/i) && !value.match(/^inherit$/i))
return _("Invalid TOS value, expected 00..FF or inherit");
return true;
};
o = s.taboption('advanced', form.Flag, 'df', _("Don't Fragment"), _("Enable the DF (Don't Fragment) flag of the encapsulating packets."));
o.default = o.enabled;
o = s.taboption('advanced', form.Flag, 'nohostroute', _("No host route"), _("Do not create host route to peer (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Flag, 'multicast', _("Multicast"), _("Enable support for multicast traffic (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Value, 'ikey', _("Incoming key"), _("Key for incoming packets (optional)."));
o.optional = true;
o.datatype = 'integer';
o = s.taboption('advanced', form.Value, 'okey', _("Outgoing key"), _("Key for outgoing packets (optional)."));
o.optional = true;
o.datatype = 'integer';
s.taboption('advanced', form.Flag, 'icsum', _("Incoming checksum"), _("Require incoming checksum (optional)."));
s.taboption('advanced', form.Flag, 'ocsum', _("Outgoing checksum"), _("Compute outgoing checksum (optional)."));
s.taboption('advanced', form.Flag, 'iseqno', _("Incoming serialization"), _("Require incoming packets serialization (optional)."));
s.taboption('advanced', form.Flag, 'oseqno', _("Outgoing serialization"), _("Perform outgoing packets serialization (optional)."));
}
});

View file

@ -1,108 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^gre6-.+$/);
return network.registerProtocol('grev6', {
getI18n: function() {
return _('GRE tunnel over IPv6');
},
getIfname: function() {
return this._ubus('l3_device') || 'gre6-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'gre';
},
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;
// -- general ---------------------------------------------------------------------
o = s.taboption('general', form.Value, 'peer6addr', _("Remote IPv6 address or FQDN"), _("The IPv6 address or the fully-qualified domain name of the remote tunnel end."));
o.optional = false;
o.datatype = 'or(hostname,ip6addr("nomask"))';
o = s.taboption('general', form.Value, 'ip6addr', _("Local IPv6 address"), _("The local IPv6 address over which the tunnel is created (optional)."));
o.optional = true;
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('general', widgets.NetworkSelect, 'weakif', _("Source interface"), _("Logical network from which to select the local endpoint if local IPv6 address is empty and no WAN IPv6 is available (optional)."));
o.exclude = s.section;
o.nocreate = true;
o.optional = true;
// -- advanced ---------------------------------------------------------------------
o = s.taboption('advanced', 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) (optional)."));
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) (optional)."));
o.optional = true;
o.placeholder = 64;
o.datatype = 'min(1)';
o = s.taboption('advanced', form.Value, 'tos', _("Traffic Class"), _("Specify a TOS (Type of Service). Can be <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value <code>00..FF</code> (optional)."));
o.optional = true;
o.validate = function(section_id, value) {
if (value.length > 0 && !value.match(/^[a-f0-9]{1,2}$/i) && !value.match(/^inherit$/i))
return _("Invalid Traffic Class value, expected 00..FF or inherit");
return true;
};
o = s.taboption('advanced', form.Flag, 'nohostroute', _("No host route"), _("Do not create host route to peer (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Flag, 'multicast', _("Multicast"), _("Enable support for multicast traffic (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Value, 'ikey', _("Incoming key"), _("Key for incoming packets (optional)."));
o.optional = true;
o.datatype = 'integer';
o = s.taboption('advanced', form.Value, 'okey', _("Outgoing key"), _("Key for outgoing packets (optional)."));
o.optional = true;
o.datatype = 'integer';
s.taboption('advanced', form.Flag, 'icsum', _("Incoming checksum"), _("Require incoming checksum (optional)."));
s.taboption('advanced', form.Flag, 'ocsum', _("Outgoing checksum"), _("Compute outgoing checksum (optional)."));
s.taboption('advanced', form.Flag, 'iseqno', _("Incoming serialization"), _("Require incoming packets serialization (optional)."));
s.taboption('advanced', form.Flag, 'oseqno', _("Outgoing serialization"), _("Perform outgoing packets serialization (optional)."));
}
});

View file

@ -1,113 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^gre6t-.+$/);
return network.registerProtocol('grev6tap', {
getI18n: function() {
return _('GRETAP tunnel over IPv6');
},
getIfname: function() {
return this._ubus('l3_device') || 'gre6t-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'gre';
},
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;
// -- general ---------------------------------------------------------------------
o = s.taboption('general', form.Value, 'peer6addr', _("Remote IPv6 address or FQDN"), _("The IPv6 address or the fully-qualified domain name of the remote tunnel end."));
o.optional = false;
o.datatype = 'or(hostname,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('general', form.Value, 'ip6addr', _("Local IPv6 address"), _("The local IPv6 address over which the tunnel is created (optional)."));
o.optional = true;
o.datatype = 'ip6addr("nomask")';
o = s.taboption('general', widgets.NetworkSelect, 'weakif', _("Source interface"), _("Logical network from which to select the local endpoint if local IPv6 address is empty and no WAN IPv6 is available (optional)."));
o.exclude = s.section;
o.nocreate = true;
o.optional = true;
o = s.taboption('general', widgets.NetworkSelect, 'network', _("Network interface"), _("Logical network to which the tunnel will be added (bridged) (optional)."));
o.exclude = s.section;
o.nocreate = true;
o.optional = true;
// -- advanced ---------------------------------------------------------------------
o = s.taboption('advanced', 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) (optional)."));
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) (optional)."));
o.optional = true;
o.placeholder = 64;
o.datatype = 'min(1)';
o = s.taboption('advanced', form.Value, 'tos', _("Traffic Class"), _("Specify a Traffic Class. Can be <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value <code>00..FF</code> (optional)."));
o.optional = true;
o.validate = function(section_id, value) {
if (value.length > 0 && !value.match(/^[a-f0-9]{1,2}$/i) && !value.match(/^inherit$/i))
return _("Invalid Traffic Class value, expected 00..FF or inherit");
return true;
};
o = s.taboption('advanced', form.Flag, 'nohostroute', _("No host route"), _("Do not create host route to peer (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Flag, 'multicast', _("Multicast"), _("Enable support for multicast traffic (optional)."));
o.optional = true;
o = s.taboption('advanced', form.Value, 'ikey', _("Incoming key"), _("Key for incoming packets (optional)."));
o.optional = true;
o.datatype = 'integer';
o = s.taboption('advanced', form.Value, 'okey', _("Outgoing key"), _("Key for outgoing packets (optional)."));
o.optional = true;
o.datatype = 'integer';
s.taboption('advanced', form.Flag, 'icsum', _("Incoming checksum"), _("Require incoming checksum (optional)."));
s.taboption('advanced', form.Flag, 'ocsum', _("Outgoing checksum"), _("Compute outgoing checksum (optional)."));
s.taboption('advanced', form.Flag, 'iseqno', _("Incoming serialization"), _("Require incoming packets serialization (optional)."));
s.taboption('advanced', form.Flag, 'oseqno', _("Outgoing serialization"), _("Perform outgoing packets serialization (optional)."));
}
});

View file

@ -1,17 +0,0 @@
#
# Copyright (C) 2018 Florian Eckert <fe@dev.tdt.de>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for hnet
LUCI_DEPENDS:=
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Steven Barth <steven@midlink.org>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,36 +0,0 @@
'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 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';
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;
}
});

View file

@ -1,16 +0,0 @@
#
# Copyright 2016 Roger Pueyo Centelles <roger.pueyo@guifi.net>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for IPIP tunnels (IPv4-in-IPv4 RFC2003)
LUCI_DEPENDS:=+ipip
PKG_MAINTAINER:=Roger Pueyo Centelles <roger.pueyo@guifi.net>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,73 +0,0 @@
'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)';
o = s.taboption('advanced', form.Flag, 'df', _("Don't Fragment"), _("Enable the DF (Don't Fragment) flag of the encapsulating packets."));
o.optional = true;
o = s.taboption('advanced', form.Flag, 'nohostroute', _("No host route"), _("Do not create host route to peer (optional)."));
o.optional = true;
}
});

View file

@ -1,16 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for DHCPv6/6in4/6to4/6rd/DS-Lite
LUCI_DEPENDS:=@IPV6
PKG_LICENSE:=Apache-2.0
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,52 +0,0 @@
'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.Value, 'mtu', _('Use MTU on tunnel interface'));
o.placeholder = '1280';
o.datatype = 'max(9200)';
}
});

View file

@ -1,93 +0,0 @@
'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.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)';
}
});

View file

@ -1,73 +0,0 @@
'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.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)';
}
});

View file

@ -1,57 +0,0 @@
'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.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)';
}
});

View file

@ -1,36 +0,0 @@
'use strict';
'require form';
'require network';
return network.registerProtocol('dhcpv6', {
getI18n: function() {
return _('DHCPv6 client');
},
getOpkgPackage: function() {
return 'odhcp6c';
},
renderFormOptions: function(s) {
var 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.Value, 'clientid', _('Client ID to send when requesting DHCP'));
o.datatype = 'hexstring';
}
});

View file

@ -1,71 +0,0 @@
'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.Value, 'mtu', _('Use MTU on tunnel interface'));
o.placeholder = '1280';
o.datatype = 'max(9200)';
}
});

View file

@ -1,90 +0,0 @@
'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, 'maptype', _('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.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)';
o = s.taboption('advanced', form.Flag, 'legacymap', _('Use legacy MAP'), _('Use legacy MAP interface identifier format (draft-ietf-softwire-map-00) instead of RFC7597'));
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for ModemManager
LUCI_DEPENDS:=+modemmanager
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,139 +0,0 @@
'use strict';
'require fs';
'require form';
'require network';
function getModemList() {
return fs.exec_direct('/usr/bin/mmcli', [ '-L' ]).then(function(res) {
var lines = (res || '').split(/\n/),
tasks = [];
for (var i = 0; i < lines.length; i++) {
var m = lines[i].match(/\/Modem\/(\d+)/);
if (m)
tasks.push(fs.exec_direct('/usr/bin/mmcli', [ '-m', m[1] ]));
}
return Promise.all(tasks).then(function(res) {
var modems = [];
for (var i = 0; i < res.length; i++) {
var man = res[i].match(/manufacturer: ([^\n]+)/),
mod = res[i].match(/model: ([^\n]+)/),
dev = res[i].match(/device: ([^\n]+)/);
if (dev) {
modems.push({
device: dev[1].trim(),
manufacturer: (man ? man[1].trim() : '') || '?',
model: (mod ? mod[1].trim() : '') || dev[1].trim()
});
}
}
return modems;
});
});
}
network.registerPatternVirtual(/^mobiledata-.+$/);
network.registerErrorCode('MM_CONNECT_FAILED', _('Connection attempt failed.'));
network.registerErrorCode('MM_DISCONNECT_IN_PROGRESS', _('Modem disconnection in progress. Please wait.'));
network.registerErrorCode('MM_CONNECT_IN_PROGRESS', _('Modem connection in progress. Please wait. This process will timeout after 2 minutes.'));
network.registerErrorCode('MM_TEARDOWN_IN_PROGRESS', _('Modem bearer teardown in progress.'));
network.registerErrorCode('MM_MODEM_DISABLED', _('Modem is disabled.'));
network.registerErrorCode('DEVICE_NOT_MANAGED', _('Device not managed by ModemManager.'));
network.registerErrorCode('INVALID_BEARER_LIST', _('Invalid bearer list. Possibly too many bearers created. This protocol supports one and only one bearer.'));
network.registerErrorCode('UNKNOWN_METHOD', _('Unknown and unsupported connection method.'));
network.registerErrorCode('DISCONNECT_FAILED', _('Disconnection attempt failed.'));
return network.registerProtocol('modemmanager', {
getI18n: function() {
return _('ModemManager');
},
getIfname: function() {
return this._ubus('l3_device') || 'modemmanager-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'modemmanager';
},
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, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return getModemList().then(L.bind(function(devices) {
for (var i = 0; i < devices.length; i++)
this.value(devices[i].device,
'%s - %s'.format(devices[i].manufacturer, devices[i].model));
return form.Value.prototype.load.apply(this, [section_id]);
}, this));
};
o = s.taboption('general', form.Value, 'apn', _('APN'));
o.validate = function(section_id, value) {
if (value == null || value == '')
return true;
if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value))
return _('Invalid APN provided');
return true;
};
o = s.taboption('general', form.Value, 'pincode', _('PIN'));
o.datatype = 'and(uinteger,minlength(4),maxlength(8))';
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;
o = s.taboption('general', form.ListValue, 'iptype', _('IP Type'));
o.value('ipv4v6', _('IPv4/IPv6 (both - defaults to IPv4)'))
o.value('ipv4', _('IPv4 only'));
o.value('ipv6', _('IPv6 only'));
o.default = 'ipv4v6';
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
o.datatype = 'max(9200)';
o = s.taboption('general', form.Value, 'signalrate', _('Signal Refresh Rate'), _("In seconds"));
o.datatype = 'uinteger';
}
});

View file

@ -1,14 +0,0 @@
{
"luci-proto-modemmanager": {
"description": "Grant access to mmcli",
"read": {
"cgi-io": [ "exec" ],
"file": {
"/usr/bin/mmcli -L": [ "exec" ],
"/usr/bin/mmcli -m [0-9]": [ "exec" ],
"/usr/bin/mmcli -m [0-9][0-9]": [ "exec" ],
"/usr/bin/mmcli -m [0-9][0-9][0-9]": [ "exec" ]
}
}
}
}

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for NCM
LUCI_DEPENDS:=+comgt-ncm
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,123 +0,0 @@
'use strict';
'require rpc';
'require form';
'require network';
var callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ],
expect: { entries: [] },
filter: function(list, params) {
var rv = [];
for (var i = 0; i < list.length; i++)
if (list[i].name.match(/^ttyUSB/) || list[i].name.match(/^cdc-wdm/))
rv.push(params.path + list[i].name);
return rv.sort();
}
});
network.registerPatternVirtual(/^ncm-.+$/);
network.registerErrorCode('CONFIGURE_FAILED', _('Failed to configure modem'));
network.registerErrorCode('CONNECT_FAILED', _('Failed to connect'));
network.registerErrorCode('DISCONNECT_FAILED', _('Failed to disconnect'));
network.registerErrorCode('FINALIZE_FAILED', _('Finalizing failed'));
network.registerErrorCode('GETINFO_FAILED', _('Failed to get modem information'));
network.registerErrorCode('INITIALIZE_FAILED', _('Failed to initialize modem'));
network.registerErrorCode('NO_DEVICE', _('No control device specified'));
network.registerErrorCode('NO_IFACE', _('The interface could not be found'));
network.registerErrorCode('PIN_FAILED', _('Unable to verify PIN'));
network.registerErrorCode('SETMODE_FAILED', _('Failed to set operating mode'));
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, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(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, 'mode', _('Network Mode'));
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'));
o = s.taboption('general', form.Value, 'apn', _('APN'));
o.validate = function(section_id, value) {
if (value == null || value == '')
return true;
if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value))
return _('Invalid APN provided');
return true;
};
o = s.taboption('general', form.Value, 'pincode', _('PIN'));
o.datatype = 'and(uinteger,minlength(4),maxlength(8))';
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, 'ppp_ipv6', _('Obtain IPv6 address'));
o.ucioption = 'ipv6';
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'), _('Amount of seconds to wait for the modem to become ready'));
o.placeholder = '0';
o.datatype = 'min(0)';
}
});

View file

@ -1,17 +0,0 @@
# Copyright 2021 Stan Grishin (stangri@melmac.ca)
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_LICENSE:=GPL-3.0-or-later
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_VERSION:=1.6.1-1
LUCI_TITLE:=Support for Nebula
LUCI_DESCRIPTION:=Provides Web UI for Nebula protocol/interface.
LUCI_DEPENDS:=+nebula +nebula-proto
LUCI_PKGARCH:=all
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,50 +0,0 @@
'use strict';
'require ui';
'require uci';
'require rpc';
'require form';
'require network';
return network.registerProtocol('nebula', {
getI18n: function () {
return _('Nebula Network');
},
getIfname: function () {
return this._ubus('l3_device') || this.sid;
},
getOpkgPackage: function () {
return 'nebula';
},
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, 'config_file', _('Config File'), _('Required. Path to the .yml config file for this interface.'));
o.rmempty = false;
},
deleteConfiguration: function () {
uci.sections('network', 'nebula_%s'.format(this.sid), function (s) {
uci.remove('network', s['.name']);
});
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for OpenConnect VPN
LUCI_DEPENDS:=+openconnect +luci-lua-runtime
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,204 +0,0 @@
'use strict';
'require rpc';
'require form';
'require network';
'require validation';
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;
if (value === null || value === '')
return true;
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.ListValue, 'vpn_protocol', _('VPN Protocol'));
o.value('anyconnect', 'Cisco AnyConnect SSL VPN');
o.value('nc', 'Juniper Network Connect');
o.value('gp', 'GlobalProtect SSL VPN');
o.value('pulse', 'Pulse Connect Secure SSL VPN');
o = s.taboption('general', form.Value, 'server', _('VPN Server'));
o.validate = function(section_id, value) {
var m = String(value).match(/^(?:(\w+):\/\/|)(?:\[([0-9a-f:.]{2,45})\]|([^\/:]+))(?::([0-9]{1,5}))?(?:\/.*)?$/i);
if (!m)
return _('Invalid server URL');
if (m[1] != null) {
if (!m[1].match(/^(?:http|https|socks|socks4|socks5)$/i))
return _('Unsupported protocol');
}
if (m[2] != null) {
if (!validation.parseIPv6(m[2]))
return _('Invalid IPv6 address');
}
if (m[3] != null) {
if (!validation.parseIPv4(m[3])) {
if (!(m[3].length <= 253 &&
(m[3].match(/^[a-zA-Z0-9_]+$/) != null ||
(m[3].match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) &&
m[3].match(/[^0-9.]/)))))
return _('Invalid hostname or IPv4 address');
}
}
if (m[4] != null) {
var p = +m[4];
if (p < 0 || p > 65535)
return _('Invalid port');
}
return true;
};
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, 'usergroup', _('User 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.Value, 'proxy', _('Proxy Server'));
o.optional = 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.Value, 'mtu', _('Override MTU'));
o.optional = true;
o.placeholder = 1406;
o.datatype = 'range(68, 9200)';
o = s.taboption('advanced', form.Value, 'reconnect_timeout', _('Reconnect Timeout'));
o.optional = true;
o.placeholder = 300;
o.datatype = 'min(10)';
}
});

View file

@ -1,78 +0,0 @@
#!/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-vpn-%s.pem", args.interface)),
user_privatekey = readfile(string.format("/etc/openconnect/user-key-vpn-%s.pem", args.interface)),
ca_certificate = readfile(string.format("/etc/openconnect/ca-vpn-%s.pem", args.interface))
}))
elseif arg[2] == "setCertificates" then
if args.user_certificate then
writefile(string.format("/etc/openconnect/user-cert-vpn-%s.pem", args.interface), args.user_certificate)
end
if args.user_privatekey then
writefile(string.format("/etc/openconnect/user-key-vpn-%s.pem", args.interface), args.user_privatekey)
end
if args.ca_certificate then
writefile(string.format("/etc/openconnect/ca-vpn-%s.pem", args.interface), args.ca_certificate)
end
print(json.stringify({ result = true }))
end
end

View file

@ -1,17 +0,0 @@
{
"luci-proto-openconnect": {
"description": "Grant access to LuCI OpenConnect procedures",
"read": {
"ubus": {
"luci.openconnect": [ "getCertificates" ]
},
"uci": [ "network" ]
},
"write": {
"ubus": {
"luci.openconnect": [ "setCertificates" ]
},
"uci": [ "network" ]
}
}
}

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2020 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for OpenFortivpn
LUCI_DEPENDS:=+openfortivpn +luci-lua-runtime
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,175 +0,0 @@
'use strict';
'require rpc';
'require form';
'require network';
'require tools.widgets as widgets';
var callGetCertificateFiles = rpc.declare({
object: 'luci.openfortivpn',
method: 'getCertificates',
params: [ 'interface' ],
expect: { '': {} }
});
var callSetCertificateFiles = rpc.declare({
object: 'luci.openfortivpn',
method: 'setCertificates',
params: [ 'interface', 'user_cert', 'user_key', 'ca_file' ],
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 lines = value.trim().split(/[\r\n]/),
start = false,
i;
if (value === null || value === '')
return true;
for (i = 0; i < lines.length; i++) {
if (lines[i].match(/^-{5}BEGIN ((|RSA |DSA )PRIVATE KEY|(|TRUSTED |X509 )CERTIFICATE)-{5}$/))
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(/^-{5}END ((|RSA |DSA )PRIVATE KEY|(|TRUSTED |X509 )CERTIFICATE)-{5}$/))
return _('This does not look like a valid PEM file');
return true;
}
return network.registerProtocol('openfortivpn', {
getI18n: function() {
return _('OpenFortivpn');
},
getIfname: function() {
return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'openfortivpn';
},
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', _('VPN Server'));
o.datatype = 'host(0)';
o = s.taboption('general', form.Value, 'port', _('VPN Server port'));
o.placeholder = '443';
o.datatype = 'port';
o.optional = true;
s.taboption("general", form.Value, "username", _("Username"));
o = s.taboption('general', form.Value, 'password', _('Password'));
o.password = true;
o = s.taboption('general', form.TextValue, 'user_cert', _('User certificate (PEM encoded)'));
o.rows = 10;
o.monospace = true;
o.validate = L.bind(validateCert, o, false);
o.load = function(section_id) {
var certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
return certLoadPromise.then(function(certs) { return certs.user_cert });
};
o.write = function(section_id, value) {
return callSetCertificateFiles(section_id, sanitizeCert(value), null, null);
};
o = s.taboption('general', form.TextValue, 'user_key', _('User key (PEM encoded)'));
o.rows = 10;
o.monospace = true;
o.validate = L.bind(validateCert, o, true);
o.load = function(section_id) {
var certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
return certLoadPromise.then(function(certs) { return certs.user_key });
};
o.write = function(section_id, value) {
return callSetCertificateFiles(section_id, null, sanitizeCert(value), null);
};
o = s.taboption('general', form.TextValue, 'ca_file', _('CA certificate (PEM encoded; Use instead of system-wide store to verify the gateway certificate.'));
o.rows = 10;
o.monospace = true;
o.validate = L.bind(validateCert, o, false);
o.load = function(section_id) {
var certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
return certLoadPromise.then(function(certs) { return certs.ca_file });
};
o.write = function(section_id, value) {
return callSetCertificateFiles(section_id, null, null, sanitizeCert(value));
};
o = s.taboption('advanced', 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, 'persist_int', _('Persistent reconnect interval'), _("Optional, in seconds. If set to '0', no reconnect is attempted."));
o.placeholder = '0';
o.datatype = 'uinteger';
o.optional = true;
o = s.taboption('advanced', form.Value, 'trusted_cert', _("VPN Server certificate's SHA256 hash"));
o.datatype = 'and(hexstring,length(64))'
o.optional = true;
o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), _('If unchecked, no default route is configured'));
o.default = o.enabled;
o.optional = true;
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.optional = true;
o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric'));
o.placeholder = '0';
o.datatype = 'uinteger';
o.optional = true;
o = s.taboption("advanced", form.Value, 'local_ip', _("Local IP address"));
o.placeholder = '192.168.0.5'
o.dataype = 'ipaddr'
o.optional = true;
}
});

View file

@ -1,86 +0,0 @@
#!/usr/bin/env lua
local json = require "luci.jsonc"
local fs = require "nixio.fs"
local function readfile(path)
if fs.stat(path, "type") == "reg" then
local s = fs.readfile(path)
return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
else
return null
end
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_cert = "user_cert",
user_key = "user_key",
ca_file = "ca_file"
}
}))
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
local user_cert_pem = string.format("/etc/openfortivpn/user-cert-%s.pem", args.interface)
local user_key_pem = string.format("/etc/openfortivpn/user-key-%s.pem", args.interface)
local ca_file_pem = string.format("/etc/openfortivpn/ca-%s.pem", args.interface)
if arg[2] == "getCertificates" then
print(json.stringify({
user_cert = readfile(user_cert_pem),
user_key = readfile(user_key_pem),
ca_file = readfile(ca_file_pem)
}))
elseif arg[2] == "setCertificates" then
if args.user_cert then
writefile(user_cert_pem, args.user_cert)
end
if args.user_key then
writefile(user_key_pem, args.user_key)
end
if args.ca_file then
writefile(ca_file_pem, args.ca_file)
end
print(json.stringify({ result = true }))
end
end

View file

@ -1,15 +0,0 @@
{
"luci-proto-openfortivpn": {
"description": "Grant access to LuCI openfortivpn procedures",
"read": {
"ubus": {
"luci.openfortivpn": [ "getCertificates" ]
}
},
"write": {
"ubus": {
"luci.openfortivpn": [ "setCertificates" ]
}
}
}
}

View file

@ -1,16 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for PPP/PPPoE/PPPoA/PPtP
LUCI_DEPENDS:=
PKG_LICENSE:=Apache-2.0
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,61 +0,0 @@
'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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.value('auto', _('Automatic'));
o.value('0', _('Disabled'));
o.value('1', _('Manual'));
o.default = 'auto';
}
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
o.datatype = 'max(9200)';
}
});

View file

@ -1,136 +0,0 @@
'use strict';
'require rpc';
'require uci';
'require form';
'require network';
var callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ],
expect: { entries: [] },
filter: function(list, params) {
var rv = [];
for (var i = 0; i < list.length; i++)
if (list[i].name.match(/^tty[A-Z]/) || list[i].name.match(/^cdc-wdm/) || list[i].name.match(/^[0-9]+$/))
rv.push(params.path + list[i].name);
return rv.sort();
}
});
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, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(devices) {
for (var i = 0; i < devices.length; i++)
this.value(devices[i]);
return callFileList('/dev/tts/');
}, this)).then(L.bind(function(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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.value('auto', _('Automatic'));
o.value('0', _('Disabled'));
o.value('1', _('Manual'));
o.default = 'auto';
}
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)';
}
});

View file

@ -1,122 +0,0 @@
'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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.value('auto', _('Automatic'));
o.value('0', _('Disabled'));
o.value('1', _('Manual'));
o.default = 'auto';
}
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)';
}
});

View file

@ -1,100 +0,0 @@
'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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.value('auto', _('Automatic'));
o.value('0', _('Disabled'));
o.value('1', _('Manual'));
o.default = 'auto';
}
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)';
}
});

View file

@ -1,109 +0,0 @@
'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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.value('auto', _('Automatic'));
o.value('0', _('Disabled'));
o.value('1', _('Manual'));
o.default = 'auto';
}
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)';
}
});

View file

@ -1,17 +0,0 @@
#
# Copyright (C) 2018 Florian Eckert <fe@dev.tdt.de>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for pppossh
LUCI_DEPENDS:=+pppossh
PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Yousong Zhou <yszhou4tech@gmail.com>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,128 +0,0 @@
'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, 'ppp_ipv6', _('Obtain IPv6 address'), _('Enable IPv6 negotiation on the PPP link'));
o.ucioption = 'ipv6';
o.default = o.disabled;
}
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';
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for QMI
LUCI_DEPENDS:=+uqmi
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,137 +0,0 @@
'use strict';
'require rpc';
'require form';
'require network';
var callFileList = rpc.declare({
object: 'file',
method: 'list',
params: [ 'path' ],
expect: { entries: [] },
filter: function(list, params) {
var rv = [];
for (var i = 0; i < list.length; i++)
if (list[i].name.match(/^cdc-wdm/))
rv.push(params.path + list[i].name);
return rv.sort();
}
});
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, '_modem_device', _('Modem device'));
o.ucioption = 'device';
o.rmempty = false;
o.load = function(section_id) {
return callFileList('/dev/').then(L.bind(function(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, 'apn', _('APN'));
o.validate = function(section_id, value) {
if (value == null || value == '')
return true;
if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value))
return _('Invalid APN provided');
return true;
};
o = s.taboption('general', form.Value, 'pincode', _('PIN'));
o.datatype = 'and(uinteger,minlength(4),maxlength(8))';
o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type'));
o.value('both', 'PAP/CHAP');
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, 'ppp_ipv6', _('Enable IPv6 negotiation'));
o.ucioption = 'ipv6';
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)';
o = s.taboption('general', form.ListValue, 'pdptype', _('PDP Type'));
o.value('ipv4v6', 'IPv4/IPv6');
o.value('ipv4', 'IPv4');
o.value('ipv6', 'IPv6');
o.default = 'ipv4v6';
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;
}
});

View file

@ -1,14 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for relayd pseudo bridges
LUCI_DEPENDS:=+relayd
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,183 +0,0 @@
'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)';
}
});

View file

@ -1,15 +0,0 @@
#
# Copyright (C) 2020 Robert Koszewski <rkkoszewski@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for SSTP
LUCI_DEPENDS:=+sstp-client
LUCI_PKGARCH:=all
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,70 +0,0 @@
'use strict';
'require form';
'require network';
network.registerPatternVirtual(/^sstp-.+$/);
return network.registerProtocol('sstp', {
getI18n: function() {
return _('SSTP');
},
getIfname: function() {
return this._ubus('l3_device') || 'sstp-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'sstp-client';
},
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;
// -- general ---------------------------------------------------------------------
o = s.taboption('general', form.Value, 'server', _('SSTP Server'));
o.datatype = 'host';
o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username'));
o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password'));
o.password = true;
// -- advanced --------------------------------------------------------------------
o = s.taboption('advanced', form.Flag, 'ppp_ipv6', _('IPv6 support'), _('If checked, adds "+ipv6" to the pppd options'));
o.ucioption = 'ipv6';
o = s.taboption('advanced', form.ListValue, 'log_level', _('sstpc Log-level'));
o.value('0', _('0', 'sstp log level value'));
o.value('1', _('1', 'sstp log level value'));
o.value('2', _('2', 'sstp log level value'));
o.value('3', _('3', 'sstp log level value'));
o.value('4', _('4', 'sstp log level value'));
o.default = '0';
o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
o.placeholder = dev ? (dev.getMTU() || '1500') : '1500';
o.datatype = 'max(9200)';
o = s.taboption('advanced', form.Value, 'sstp_options', _('Extra sstpc options'), _('e.g: --proxy 10.10.10.10'));
o = s.taboption('advanced', form.Value, 'pppd_options', _('Extra pppd options'), _('e.g: dump'));
}
});

View file

@ -1,15 +0,0 @@
#
# Copyright (C) 2022 Hannu Nyman <hannu.nyman@iki.fi>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for unetd VPN
LUCI_DEPENDS:=+unetd +unet-cli
LUCI_PKGARCH:=all
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,48 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
return network.registerProtocol('unet', {
getI18n: function() {
return _('Unet');
},
getIfname: function() {
return this._ubus('l3_device') || this.sid;
},
getOpkgPackage: function() {
return 'unetd';
},
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.DummyValue, 'device', _('Name of the tunnel device'));
o.optional = false;
o = s.taboption('general', form.DummyValue, 'key', _('Local wireguard key'));
o.optional = false;
o = s.taboption('general', form.DummyValue, 'auth_key', _('Key used to sign network config'));
o.optional = false;
}
});

View file

@ -1,20 +0,0 @@
#
# Copyright (C) 2008-2014 The LuCI Team <luci@lists.subsignal.org>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for VPNC VPN
LUCI_DEPENDS:=+vpnc
LUCI_PKGARCH:=all
PKG_MAINTAINER:=Daniel Dickinson <openwrt@daniel.thecshore.com>
PKG_LICENSE:=Apache-2.0
LUA_TARGET:=source
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,107 +0,0 @@
'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';
}
});

View file

@ -1,14 +0,0 @@
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for VTI interfaces
LUCI_DEPENDS:=+vti
PKG_MAINTAINER:=Jaymin Patel <jem.patel@gmail.com>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,72 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^vti-.+$/);
return network.registerProtocol('vti', {
getI18n: function() {
return _('VTI');
},
getIfname: function() {
return this._ubus('l3_device') || 'vti-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'vti';
},
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, '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.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, 'mtu', _('Override MTU'));
o.placeholder = dev ? (dev.getMTU() || '1280') : '1280';
o.datatype = 'max(1500)';
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('general', form.Value, 'ikey', _("Incoming key"), _("Key for incoming packets (optional)."));
o.optional = true;
o.datatype = 'uinteger';
o = s.taboption('general', form.Value, 'okey', _("Outgoing key"), _("Key for outgoing packets (optional)."));
o.optional = true;
o.datatype = 'uinteger';
}
});

View file

@ -1,16 +0,0 @@
#
# Copyright 2020 Wojciech Jowsa <wojciech.jowsa@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for Virtual eXtensible Local Area Network (VXLAN, RFC7348)
LUCI_DEPENDS:=+vxlan
PKG_MAINTAINER:=Wojciech Jowsa <wojciech.jowsa@gmail.com>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,80 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^vxlan-.+$/);
return network.registerProtocol('vxlan', {
getI18n: function() {
return _('VXLAN (RFC7348)');
},
getIfname: function() {
return this._ubus('l3_device') || 'vxlan-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'vxlan';
},
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'), _('The IPv4 address or the fully-qualified domain name of the remote 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', form.Value, 'port', _('Destination port'));
o.optional = true;
o.placeholder = 4789;
o.datatype = 'port';
o = s.taboption('general', form.Value, 'vid', _('VXLAN network identifier'), _('ID used to uniquely identify the VXLAN'));
o.optional = true;
o.datatype = 'range(1, 16777216)';
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, '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)';
o = s.taboption('advanced', form.Flag, 'rxcsum', _('Enable rx checksum'));
o.optional = true;
o.default = o.enabled;
o = s.taboption('advanced', form.Flag, 'txcsum', _('Enable tx checksum'));
o.optional = true;
o.default = o.enabled;
}
});

View file

@ -1,75 +0,0 @@
'use strict';
'require form';
'require network';
'require tools.widgets as widgets';
network.registerPatternVirtual(/^vxlan-.+$/);
return network.registerProtocol('vxlan6', {
getI18n: function() {
return _('VXLANv6 (RFC7348)');
},
getIfname: function() {
return this._ubus('l3_device') || 'vxlan-%s'.format(this.sid);
},
getOpkgPackage: function() {
return 'vxlan';
},
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, 'peer6addr', _('Remote IPv6 address'), _('The IPv6 address or the fully-qualified domain name of the remote end.'));
o.optional = false;
o.datatype = 'or(hostname,cidr6)';
o = s.taboption('general', form.Value, 'ip6addr', _('Local IPv6 address'), _('The local IPv6 address over which the tunnel is created (optional).'));
o.optional = true;
o.datatype = 'cidr6';
o = s.taboption('general', form.Value, 'vid', _('VXLAN network identifier'), _('ID used to uniquely identify the VXLAN'));
o.optional = true;
o.datatype = 'range(1, 16777216)';
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, '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)';
o = s.taboption('advanced', form.Flag, 'rxcsum', _('Enable rx checksum'));
o.optional = true;
o.default = o.enabled;
o = s.taboption('advanced', form.Flag, 'txcsum', _('Enable tx checksum'));
o.optional = true;
o.default = o.enabled;
}
});

View file

@ -1,17 +0,0 @@
#
# Copyright (C) 2016 Dan Luedtke <mail@danrl.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for WireGuard VPN
LUCI_DEPENDS:=+wireguard-tools +ucode
LUCI_PKGARCH:=all
PKG_PROVIDES:=luci-app-wireguard
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,869 +0,0 @@
'use strict';
'require fs';
'require ui';
'require dom';
'require uci';
'require rpc';
'require form';
'require network';
'require validation';
var generateKey = rpc.declare({
object: 'luci.wireguard',
method: 'generateKeyPair',
expect: { keys: {} }
});
var getPublicAndPrivateKeyFromPrivate = rpc.declare({
object: 'luci.wireguard',
method: 'getPublicAndPrivateKeyFromPrivate',
params: ['privkey'],
expect: { keys: {} }
});
var generatePsk = rpc.declare({
object: 'luci.wireguard',
method: 'generatePsk',
expect: { psk: '' }
});
var qrIcon = '<svg viewBox="0 0 29 29" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M0 0h29v29H0z"/><path d="M4 4h1v1H4zM5 4h1v1H5zM6 4h1v1H6zM7 4h1v1H7zM8 4h1v1H8zM9 4h1v1H9zM10 4h1v1h-1zM12 4h1v1h-1zM13 4h1v1h-1zM14 4h1v1h-1zM15 4h1v1h-1zM16 4h1v1h-1zM18 4h1v1h-1zM19 4h1v1h-1zM20 4h1v1h-1zM21 4h1v1h-1zM22 4h1v1h-1zM23 4h1v1h-1zM24 4h1v1h-1zM4 5h1v1H4zM10 5h1v1h-1zM12 5h1v1h-1zM14 5h1v1h-1zM16 5h1v1h-1zM18 5h1v1h-1zM24 5h1v1h-1zM4 6h1v1H4zM6 6h1v1H6zM7 6h1v1H7zM8 6h1v1H8zM10 6h1v1h-1zM12 6h1v1h-1zM18 6h1v1h-1zM20 6h1v1h-1zM21 6h1v1h-1zM22 6h1v1h-1zM24 6h1v1h-1zM4 7h1v1H4zM6 7h1v1H6zM7 7h1v1H7zM8 7h1v1H8zM10 7h1v1h-1zM12 7h1v1h-1zM13 7h1v1h-1zM14 7h1v1h-1zM15 7h1v1h-1zM18 7h1v1h-1zM20 7h1v1h-1zM21 7h1v1h-1zM22 7h1v1h-1zM24 7h1v1h-1zM4 8h1v1H4zM6 8h1v1H6zM7 8h1v1H7zM8 8h1v1H8zM10 8h1v1h-1zM16 8h1v1h-1zM18 8h1v1h-1zM20 8h1v1h-1zM21 8h1v1h-1zM22 8h1v1h-1zM24 8h1v1h-1zM4 9h1v1H4zM10 9h1v1h-1zM12 9h1v1h-1zM13 9h1v1h-1zM15 9h1v1h-1zM18 9h1v1h-1zM24 9h1v1h-1zM4 10h1v1H4zM5 10h1v1H5zM6 10h1v1H6zM7 10h1v1H7zM8 10h1v1H8zM9 10h1v1H9zM10 10h1v1h-1zM12 10h1v1h-1zM14 10h1v1h-1zM16 10h1v1h-1zM18 10h1v1h-1zM19 10h1v1h-1zM20 10h1v1h-1zM21 10h1v1h-1zM22 10h1v1h-1zM23 10h1v1h-1zM24 10h1v1h-1zM13 11h1v1h-1zM14 11h1v1h-1zM15 11h1v1h-1zM16 11h1v1h-1zM4 12h1v1H4zM5 12h1v1H5zM8 12h1v1H8zM9 12h1v1H9zM10 12h1v1h-1zM13 12h1v1h-1zM15 12h1v1h-1zM19 12h1v1h-1zM21 12h1v1h-1zM22 12h1v1h-1zM23 12h1v1h-1zM24 12h1v1h-1zM5 13h1v1H5zM6 13h1v1H6zM8 13h1v1H8zM11 13h1v1h-1zM13 13h1v1h-1zM14 13h1v1h-1zM15 13h1v1h-1zM16 13h1v1h-1zM19 13h1v1h-1zM22 13h1v1h-1zM4 14h1v1H4zM5 14h1v1H5zM9 14h1v1H9zM10 14h1v1h-1zM11 14h1v1h-1zM15 14h1v1h-1zM18 14h1v1h-1zM19 14h1v1h-1zM20 14h1v1h-1zM21 14h1v1h-1zM22 14h1v1h-1zM23 14h1v1h-1zM7 15h1v1H7zM8 15h1v1H8zM9 15h1v1H9zM11 15h1v1h-1zM12 15h1v1h-1zM13 15h1v1h-1zM17 15h1v1h-1zM18 15h1v1h-1zM20 15h1v1h-1zM21 15h1v1h-1zM23 15h1v1h-1zM4 16h1v1H4zM6 16h1v1H6zM10 16h1v1h-1zM11 16h1v1h-1zM13 16h1v1h-1zM14 16h1v1h-1zM16 16h1v1h-1zM17 16h1v1h-1zM18 16h1v1h-1zM22 16h1v1h-1zM23 16h1v1h-1zM24 16h1v1h-1zM12 17h1v1h-1zM16 17h1v1h-1zM17 17h1v1h-1zM18 17h1v1h-1zM4 18h1v1H4zM5 18h1v1H5zM6 18h1v1H6zM7 18h1v1H7zM8 18h1v1H8zM9 18h1v1H9zM10 18h1v1h-1zM14 18h1v1h-1zM16 18h1v1h-1zM17 18h1v1h-1zM21 18h1v1h-1zM22 18h1v1h-1zM23 18h1v1h-1zM4 19h1v1H4zM10 19h1v1h-1zM12 19h1v1h-1zM13 19h1v1h-1zM15 19h1v1h-1zM16 19h1v1h-1zM19 19h1v1h-1zM21 19h1v1h-1zM23 19h1v1h-1zM24 19h1v1h-1zM4 20h1v1H4zM6 20h1v1H6zM7 20h1v1H7zM8 20h1v1H8zM10 20h1v1h-1zM12 20h1v1h-1zM13 20h1v1h-1zM15 20h1v1h-1zM18 20h1v1h-1zM19 20h1v1h-1zM20 20h1v1h-1zM22 20h1v1h-1zM23 20h1v1h-1zM24 20h1v1h-1zM4 21h1v1H4zM6 21h1v1H6zM7 21h1v1H7zM8 21h1v1H8zM10 21h1v1h-1zM13 21h1v1h-1zM15 21h1v1h-1zM16 21h1v1h-1zM19 21h1v1h-1zM21 21h1v1h-1zM23 21h1v1h-1zM24 21h1v1h-1zM4 22h1v1H4zM6 22h1v1H6zM7 22h1v1H7zM8 22h1v1H8zM10 22h1v1h-1zM13 22h1v1h-1zM15 22h1v1h-1zM18 22h1v1h-1zM19 22h1v1h-1zM20 22h1v1h-1zM21 22h1v1h-1zM22 22h1v1h-1zM4 23h1v1H4zM10 23h1v1h-1zM12 23h1v1h-1zM13 23h1v1h-1zM14 23h1v1h-1zM17 23h1v1h-1zM18 23h1v1h-1zM20 23h1v1h-1zM22 23h1v1h-1zM4 24h1v1H4zM5 24h1v1H5zM6 24h1v1H6zM7 24h1v1H7zM8 24h1v1H8zM9 24h1v1H9zM10 24h1v1h-1zM12 24h1v1h-1zM13 24h1v1h-1zM14 24h1v1h-1zM16 24h1v1h-1zM17 24h1v1h-1zM18 24h1v1h-1zM22 24h1v1h-1zM24 24h1v1h-1z"/></svg>';
function validateBase64(section_id, value) {
if (value.length == 0)
return true;
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');
if (value[43] != "=" )
return _('Invalid Base64 key string');
return true;
}
var stubValidator = {
factory: validation,
apply: function(type, value, args) {
if (value != null)
this.value = value;
return validation.types[type].apply(this, args);
},
assert: function(condition) {
return !!condition;
}
};
function generateDescription(name, texts) {
return E('li', { 'style': 'color: inherit;' }, [
E('span', name),
E('ul', texts.map(function (text) {
return E('li', { 'style': 'color: inherit;' }, text);
}))
]);
}
function invokeQREncode(data, code) {
return fs.exec_direct('/usr/bin/qrencode', [
'--inline', '--8bit', '--type=SVG',
'--output=-', '--', data
]).then(function(svg) {
code.style.opacity = '';
dom.content(code, Object.assign(E(svg), { style: 'width:100%;height:auto' }));
}).catch(function(error) {
code.style.opacity = '';
if (L.isObject(error) && error.name == 'NotFoundError') {
dom.content(code, [
Object.assign(E(qrIcon), { style: 'width:32px;height:32px;opacity:.2' }),
E('p', _('The <em>qrencode</em> package is required for generating an QR code image of the configuration.'))
]);
}
else {
dom.content(code, [
_('Unable to generate QR code: %s').format(L.isObject(error) ? error.message : error)
]);
}
});
}
var cbiKeyPairGenerate = form.DummyValue.extend({
cfgvalue: function(section_id, value) {
return E('button', {
'class': 'btn',
'click': ui.createHandlerFn(this, function(section_id, ev) {
var prv = this.section.getUIElement(section_id, 'private_key'),
pub = this.section.getUIElement(section_id, 'public_key'),
map = this.map;
if ((prv.getValue() || pub.getValue()) && !confirm(_('Do you want to replace the current keys?')))
return;
return generateKey().then(function(keypair) {
prv.setValue(keypair.priv);
pub.setValue(keypair.pub);
map.save(null, true);
});
}, section_id)
}, [ _('Generate new key pair') ]);
}
});
function handleWindowDragDropIgnore(ev) {
ev.preventDefault()
}
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, ss2;
// -- 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;
var serverName = this.getIfname();
o = s.taboption('general', form.Value, 'public_key', _('Public Key'), _('Base64-encoded public key of this interface for sharing.'));
o.rmempty = false;
o.write = function() {/* write nothing */};
o.load = function(section_id) {
var privKey = s.formvalue(section_id, 'private_key') || uci.get('network', section_id, 'private_key');
return getPublicAndPrivateKeyFromPrivate(privKey).then(
function(keypair) {
return keypair.pub || '';
},
function(error) {
return _('Error getting PublicKey');
}, this)
};
s.taboption('general', cbiKeyPairGenerate, '_gen_server_keypair', ' ');
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;
o = s.taboption('general', form.Flag, 'nohostroute', _('No Host Routes'), _('Optional. Do not create host routes to peers.'));
o.optional = true;
o = s.taboption('general', form.Button, '_import', _('Import configuration'), _('Imports settings from an existing WireGuard configuration file'));
o.inputtitle = _('Load configuration…');
o.onclick = function() {
return ss.handleConfigImport('full');
};
// -- advanced --------------------------------------------------------------------
o = s.taboption('advanced', form.Value, 'mtu', _('MTU'), _('Optional. Maximum Transmission Unit of tunnel interface.'));
o.datatype = 'range(0,8940)';
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,8}$/))
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.GridSection, 'wireguard_%s'.format(s.section));
o.depends('proto', 'wireguard');
ss = o.subsection;
ss.anonymous = true;
ss.addremove = true;
ss.addbtntitle = _('Add peer');
ss.nodescriptions = true;
ss.modaltitle = _('Edit peer');
ss.handleDragConfig = function(ev) {
ev.stopPropagation();
ev.preventDefault();
ev.dataTransfer.dropEffect = 'copy';
};
ss.handleDropConfig = function(mode, ev) {
var file = ev.dataTransfer.files[0],
nodes = ev.currentTarget,
input = nodes.querySelector('textarea'),
reader = new FileReader();
if (file) {
reader.onload = function(rev) {
input.value = rev.target.result.trim();
ss.handleApplyConfig(mode, nodes, file.name, ev);
};
reader.readAsText(file);
}
ev.stopPropagation();
ev.preventDefault();
};
ss.parseConfig = function(data) {
var lines = String(data).split(/(\r?\n)+/),
section = null,
config = { peers: [] },
s;
for (var i = 0; i < lines.length; i++) {
var line = lines[i].replace(/#.*$/, '').trim();
if (line.match(/^\[(\w+)\]$/)) {
section = RegExp.$1.toLowerCase();
if (section == 'peer')
config.peers.push(s = {});
else
s = config;
}
else if (section && line.match(/^(\w+)\s*=\s*(.+)$/)) {
var key = RegExp.$1,
val = RegExp.$2.trim();
if (val.length)
s[section + '_' + key.toLowerCase()] = val;
}
}
if (config.interface_address) {
config.interface_address = config.interface_address.split(/[, ]+/);
for (var i = 0; i < config.interface_address.length; i++)
if (!stubValidator.apply('ipaddr', config.interface_address[i]))
return _('Address setting is invalid');
}
if (config.interface_dns) {
config.interface_dns = config.interface_dns.split(/[, ]+/);
for (var i = 0; i < config.interface_dns.length; i++)
if (!stubValidator.apply('ipaddr', config.interface_dns[i], ['nomask']))
return _('DNS setting is invalid');
}
if (!config.interface_privatekey || validateBase64(null, config.interface_privatekey) !== true)
return _('PrivateKey setting is missing or invalid');
if (!stubValidator.apply('port', config.interface_listenport || '0'))
return _('ListenPort setting is invalid');
for (var i = 0; i < config.peers.length; i++) {
var pconf = config.peers[i];
if (pconf.peer_publickey != null && validateBase64(null, pconf.peer_publickey) !== true)
return _('PublicKey setting is invalid');
if (pconf.peer_presharedkey != null && validateBase64(null, pconf.peer_presharedkey) !== true)
return _('PresharedKey setting is invalid');
if (pconf.peer_allowedips) {
pconf.peer_allowedips = pconf.peer_allowedips.split(/[, ]+/);
for (var j = 0; j < pconf.peer_allowedips.length; j++)
if (!stubValidator.apply('ipaddr', pconf.peer_allowedips[j]))
return _('AllowedIPs setting is invalid');
}
else {
pconf.peer_allowedips = [ '0.0.0.0/0', '::/0' ];
}
if (pconf.peer_endpoint) {
var host_port = pconf.peer_endpoint.match(/^\[([a-fA-F0-9:]+)\]:(\d+)$/) || pconf.peer_endpoint.match(/^(.+):(\d+)$/);
if (!host_port || !stubValidator.apply('host', host_port[1]) || !stubValidator.apply('port', host_port[2]))
return _('Endpoint setting is invalid');
pconf.peer_endpoint = [ host_port[1], host_port[2] ];
}
if (pconf.peer_persistentkeepalive == 'off' || pconf.peer_persistentkeepalive == '0')
delete pconf.peer_persistentkeepalive;
if (!stubValidator.apply('port', pconf.peer_persistentkeepalive || '0'))
return _('PersistentKeepAlive setting is invalid');
}
return config;
};
ss.handleApplyConfig = function(mode, nodes, comment, ev) {
var input = nodes.querySelector('textarea').value,
error = nodes.querySelector('.alert-message'),
cancel = nodes.nextElementSibling.querySelector('.btn'),
config = this.parseConfig(input);
if (typeof(config) == 'string') {
error.firstChild.data = _('Cannot parse configuration: %s').format(config);
error.style.display = 'block';
return;
}
if (mode == 'full') {
var prv = s.formvalue(s.section, 'private_key');
if (prv && prv != config.interface_privatekey && !confirm(_('Overwrite the current settings with the imported configuration?')))
return;
return getPublicAndPrivateKeyFromPrivate(config.interface_privatekey).then(function(keypair) {
s.getOption('private_key').getUIElement(s.section).setValue(keypair.priv);
s.getOption('public_key').getUIElement(s.section).setValue(keypair.pub);
s.getOption('listen_port').getUIElement(s.section).setValue(config.interface_listenport || '');
s.getOption('addresses').getUIElement(s.section).setValue(config.interface_address);
if (config.interface_dns)
s.getOption('dns').getUIElement(s.section).setValue(config.interface_dns);
for (var i = 0; i < config.peers.length; i++) {
var pconf = config.peers[i];
var sid = uci.add('network', 'wireguard_' + s.section);
uci.sections('network', 'wireguard_' + s.section, function(peer) {
if (peer.public_key == pconf.peer_publickey)
uci.remove('network', peer['.name']);
});
uci.set('network', sid, 'description', comment || _('Imported peer configuration'));
uci.set('network', sid, 'public_key', pconf.peer_publickey);
uci.set('network', sid, 'preshared_key', pconf.peer_presharedkey);
uci.set('network', sid, 'allowed_ips', pconf.peer_allowedips);
uci.set('network', sid, 'persistent_keepalive', pconf.peer_persistentkeepalive);
if (pconf.peer_endpoint) {
uci.set('network', sid, 'endpoint_host', pconf.peer_endpoint[0]);
uci.set('network', sid, 'endpoint_port', pconf.peer_endpoint[1]);
}
}
return s.map.save(null, true);
}).then(function() {
cancel.click();
});
}
else {
return getPublicAndPrivateKeyFromPrivate(config.interface_privatekey).then(function(keypair) {
var sid = uci.add('network', 'wireguard_' + s.section);
var pub = s.formvalue(s.section, 'public_key');
uci.sections('network', 'wireguard_' + s.section, function(peer) {
if (peer.public_key == keypair.pub)
uci.remove('network', peer['.name']);
});
uci.set('network', sid, 'description', comment || _('Imported peer configuration'));
uci.set('network', sid, 'public_key', keypair.pub);
uci.set('network', sid, 'private_key', keypair.priv);
for (var i = 0; i < config.peers.length; i++) {
var pconf = config.peers[i];
if (pconf.peer_publickey == pub) {
uci.set('network', sid, 'preshared_key', pconf.peer_presharedkey);
uci.set('network', sid, 'allowed_ips', pconf.peer_allowedips);
uci.set('network', sid, 'persistent_keepalive', pconf.peer_persistentkeepalive);
break;
}
}
return s.map.save(null, true);
}).then(function() {
cancel.click();
});
}
};
ss.handleConfigImport = function(mode) {
var mapNode = ss.getActiveModalMap(),
headNode = mapNode.parentNode.querySelector('h4'),
parent = this.map;
var nodes = E('div', {
'dragover': this.handleDragConfig,
'drop': this.handleDropConfig.bind(this, mode)
}, [
E([], (mode == 'full') ? [
E('p', _('Drag or paste a valid <em>*.conf</em> file below to configure the local WireGuard interface.'))
] : [
E('p', _('Paste or drag a WireGuard configuration (commonly <em>wg0.conf</em>) from another system below to create a matching peer entry allowing that system to connect to the local WireGuard interface.')),
E('p', _('To fully configure the local WireGuard interface from an existing (e.g. provider supplied) configuration file, use the <strong><a class="full-import" href="#">configuration import</a></strong> instead.'))
]),
E('p', [
E('textarea', {
'placeholder': (mode == 'full')
? _('Paste or drag supplied WireGuard configuration file…')
: _('Paste or drag WireGuard peer configuration (wg0.conf) file…'),
'style': 'height:5em;width:100%; white-space:pre'
})
]),
E('div', {
'class': 'alert-message',
'style': 'display:none'
}, [''])
]);
var cancelFn = function() {
nodes.parentNode.removeChild(nodes.nextSibling);
nodes.parentNode.removeChild(nodes);
mapNode.classList.remove('hidden');
mapNode.nextSibling.classList.remove('hidden');
headNode.removeChild(headNode.lastChild);
window.removeEventListener('dragover', handleWindowDragDropIgnore);
window.removeEventListener('drop', handleWindowDragDropIgnore);
};
var a = nodes.querySelector('a.full-import');
if (a) {
a.addEventListener('click', ui.createHandlerFn(this, function(mode) {
cancelFn();
this.handleConfigImport('full');
}));
}
mapNode.classList.add('hidden');
mapNode.nextElementSibling.classList.add('hidden');
headNode.appendChild(E('span', [ ' » ', (mode == 'full') ? _('Import configuration') : _('Import as peer') ]));
mapNode.parentNode.appendChild(E([], [
nodes,
E('div', {
'class': 'right'
}, [
E('button', {
'class': 'btn',
'click': cancelFn
}, [ _('Cancel') ]),
' ',
E('button', {
'class': 'btn primary',
'click': ui.createHandlerFn(this, 'handleApplyConfig', mode, nodes, null)
}, [ _('Import settings') ])
])
]));
window.addEventListener('dragover', handleWindowDragDropIgnore);
window.addEventListener('drop', handleWindowDragDropIgnore);
};
ss.renderSectionAdd = function(/* ... */) {
var nodes = this.super('renderSectionAdd', arguments);
nodes.appendChild(E('button', {
'class': 'btn',
'click': ui.createHandlerFn(this, 'handleConfigImport', 'peer')
}, [ _('Import configuration as peer…') ]));
return nodes;
};
ss.renderSectionPlaceholder = function() {
return E('em', _('No peers defined yet.'));
};
o = ss.option(form.Flag, 'disabled', _('Peer disabled'), _('Enable / Disable peer. Restart wireguard interface to apply changes.'));
o.modalonly = true;
o.optional = true;
o = ss.option(form.Value, 'description', _('Description'), _('Optional. Description of peer.'));
o.placeholder = 'My Peer';
o.datatype = 'string';
o.optional = true;
o.width = '30%';
o.textvalue = function(section_id) {
var dis = ss.getOption('disabled'),
pub = ss.getOption('public_key'),
prv = ss.getOption('private_key'),
psk = ss.getOption('preshared_key'),
name = this.cfgvalue(section_id),
key = pub.cfgvalue(section_id);
var desc = [
E('p', [
name ? E('span', [ name ]) : E('em', [ _('Untitled peer') ])
])
];
if (dis.cfgvalue(section_id) == '1')
desc.push(E('span', {
'class': 'ifacebadge',
'data-tooltip': _('WireGuard peer is disabled')
}, [
E('em', [ _('Disabled', 'Label indicating that WireGuard peer is disabled') ])
]), ' ');
if (!key || !pub.isValid(section_id)) {
desc.push(E('span', {
'class': 'ifacebadge',
'data-tooltip': _('Public key is missing')
}, [
E('em', [ _('Key missing', 'Label indicating that WireGuard peer lacks public key') ])
]));
}
else {
desc.push(
E('span', {
'class': 'ifacebadge',
'data-tooltip': _('Public key: %h', 'Tooltip displaying full WireGuard peer public key').format(key)
}, [
E('code', [ key.replace(/^(.{5}).+(.{6})$/, '$1…$2') ])
]),
' ',
(prv.cfgvalue(section_id) && prv.isValid(section_id))
? E('span', {
'class': 'ifacebadge',
'data-tooltip': _('Private key present')
}, [ _('Private', 'Label indicating that WireGuard peer private key is stored') ]) : '',
' ',
(psk.cfgvalue(section_id) && psk.isValid(section_id))
? E('span', {
'class': 'ifacebadge',
'data-tooltip': _('Preshared key in use')
}, [ _('PSK', 'Label indicating that WireGuard peer uses a PSK') ]) : ''
);
}
return E([], desc);
};
function handleKeyChange(ev, section_id, value) {
var prv = this.section.getUIElement(section_id, 'private_key'),
btn = this.map.findElement('.btn.qr-code');
btn.disabled = (!prv.isValid() || !prv.getValue());
}
o = ss.option(form.Value, 'public_key', _('Public Key'), _('Required. Public key of the WireGuard peer.'));
o.modalonly = true;
o.validate = validateBase64;
o.onchange = handleKeyChange;
o = ss.option(form.Value, 'private_key', _('Private Key'), _('Optional. Private key of the WireGuard peer. The key is not required for establishing a connection but allows generating a peer configuration or QR code if available. It can be removed after the configuration has been exported.'));
o.modalonly = true;
o.validate = validateBase64;
o.onchange = handleKeyChange;
o.password = true;
o = ss.option(cbiKeyPairGenerate, '_gen_peer_keypair', ' ');
o.modalonly = true;
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.modalonly = true;
o.validate = validateBase64;
o.password = true;
o = ss.option(form.DummyValue, '_gen_psk', ' ');
o.modalonly = true;
o.cfgvalue = function(section_id, value) {
return E('button', {
'class': 'btn',
'click': ui.createHandlerFn(this, function(section_id, ev) {
var psk = this.section.getUIElement(section_id, 'preshared_key'),
map = this.map;
if (psk.getValue() && !confirm(_('Do you want to replace the current PSK?')))
return;
return generatePsk().then(function(key) {
psk.setValue(key);
map.save(null, true);
});
}, section_id)
}, [ _('Generate preshared key') ]);
};
o = ss.option(form.DynamicList, 'allowed_ips', _('Allowed IPs'), _("Optional. 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.textvalue = function(section_id) {
var ips = L.toArray(this.cfgvalue(section_id)),
list = [];
for (var i = 0; i < ips.length; i++) {
if (i > 7) {
list.push(E('em', {
'class': 'ifacebadge cbi-tooltip-container'
}, [
_('+ %d more', 'Label indicating further amount of allowed ips').format(ips.length - i),
E('span', {
'class': 'cbi-tooltip'
}, [
E('ul', ips.map(function(ip) {
return E('li', [
E('span', { 'class': 'ifacebadge' }, [ ip ])
]);
}))
])
]));
break;
}
list.push(E('span', { 'class': 'ifacebadge' }, [ ips[i] ]));
}
if (!list.length)
list.push('*');
return E('span', { 'style': 'display:inline-flex;flex-wrap:wrap;gap:.125em' }, list);
};
o = ss.option(form.Flag, 'route_allowed_ips', _('Route Allowed IPs'), _('Optional. Create routes for Allowed IPs for this peer.'));
o.modalonly = true;
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.textvalue = function(section_id) {
var host = this.cfgvalue(section_id),
port = this.section.cfgvalue(section_id, 'endpoint_port');
return (host && port)
? '%h:%d'.format(host, port)
: (host
? '%h:*'.format(host)
: (port
? '*:%d'.format(port)
: '*'));
};
o = ss.option(form.Value, 'endpoint_port', _('Endpoint Port'), _('Optional. Port of peer.'));
o.modalonly = true;
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.modalonly = true;
o.datatype = 'range(0,65535)';
o.placeholder = '0';
o = ss.option(form.DummyValue, '_keyops', _('Configuration Export'),
_('Generates a configuration suitable for import on a WireGuard peer'));
o.modalonly = true;
o.createPeerConfig = function(section_id, endpoint, ips) {
var pub = s.formvalue(s.section, 'public_key'),
port = s.formvalue(s.section, 'listen_port') || '51820',
prv = this.section.formvalue(section_id, 'private_key'),
psk = this.section.formvalue(section_id, 'preshared_key'),
eport = this.section.formvalue(section_id, 'endpoint_port'),
keep = this.section.formvalue(section_id, 'persistent_keepalive');
return [
'[Interface]',
'PrivateKey = ' + prv,
eport ? 'ListenPort = ' + eport : '# ListenPort not defined',
'',
'[Peer]',
'PublicKey = ' + pub,
psk ? 'PresharedKey = ' + psk : '# PresharedKey not used',
ips && ips.length ? 'AllowedIPs = ' + ips.join(', ') : '# AllowedIPs not defined',
endpoint ? 'Endpoint = ' + endpoint + ':' + port : '# Endpoint not defined',
keep ? 'PersistentKeepAlive = ' + keep : '# PersistentKeepAlive not defined'
].join('\n');
};
o.handleGenerateQR = function(section_id, ev) {
var mapNode = ss.getActiveModalMap(),
headNode = mapNode.parentNode.querySelector('h4'),
configGenerator = this.createPeerConfig.bind(this, section_id),
parent = this.map;
return Promise.all([
network.getWANNetworks(),
network.getWAN6Networks(),
L.resolveDefault(uci.load('ddns')),
L.resolveDefault(uci.load('system')),
parent.save(null, true)
]).then(function(data) {
var hostnames = [];
uci.sections('ddns', 'service', function(s) {
if (typeof(s.lookup_host) == 'string' && s.enabled == '1')
hostnames.push(s.lookup_host);
});
uci.sections('system', 'system', function(s) {
if (typeof(s.hostname) == 'string' && s.hostname.indexOf('.') > 0)
hostnames.push(s.hostname);
});
for (var i = 0; i < data[0].length; i++)
hostnames.push.apply(hostnames, data[0][i].getIPAddrs().map(function(ip) { return ip.split('/')[0] }));
for (var i = 0; i < data[1].length; i++)
hostnames.push.apply(hostnames, data[1][i].getIP6Addrs().map(function(ip) { return ip.split('/')[0] }));
var ips = [ '0.0.0.0/0', '::/0' ];
var qrm, qrs, qro;
qrm = new form.JSONMap({ config: { endpoint: hostnames[0], allowed_ips: ips } }, null, _('The generated configuration can be imported into a WireGuard client application to setup a connection towards this device.'));
qrm.parent = parent;
qrs = qrm.section(form.NamedSection, 'config');
function handleConfigChange(ev, section_id, value) {
var code = this.map.findElement('.qr-code'),
conf = this.map.findElement('.client-config'),
endpoint = this.section.getUIElement(section_id, 'endpoint'),
ips = this.section.getUIElement(section_id, 'allowed_ips');
if (this.isValid(section_id)) {
conf.firstChild.data = configGenerator(endpoint.getValue(), ips.getValue());
code.style.opacity = '.5';
invokeQREncode(conf.firstChild.data, code);
}
};
qro = qrs.option(form.Value, 'endpoint', _('Connection endpoint'), _('The public hostname or IP address of this system the peer should connect to. This usually is a static public IP address, a static hostname or a DDNS domain.'));
qro.datatype = 'or(ipaddr,hostname)';
hostnames.forEach(function(hostname) { qro.value(hostname) });
qro.onchange = handleConfigChange;
qro = qrs.option(form.DynamicList, 'allowed_ips', _('Allowed IPs'), _('IP addresses that are allowed inside the tunnel. The peer will accept tunnelled packets with source IP addresses matching this list and route back packets with matching destination IP.'));
qro.datatype = 'ipaddr';
qro.default = ips;
ips.forEach(function(ip) { qro.value(ip) });
qro.onchange = handleConfigChange;
qro = qrs.option(form.DummyValue, 'output');
qro.renderWidget = function() {
var peer_config = configGenerator(hostnames[0], ips);
var node = E('div', {
'style': 'display:flex;flex-wrap:wrap;align-items:center;gap:.5em;width:100%'
}, [
E('div', {
'class': 'qr-code',
'style': 'width:320px;flex:0 1 320px;text-align:center'
}, [
E('em', { 'class': 'spinning' }, [ _('Generating QR code…') ])
]),
E('pre', {
'class': 'client-config',
'style': 'flex:1;white-space:pre;overflow:auto',
'click': function(ev) {
var sel = window.getSelection(),
range = document.createRange();
range.selectNodeContents(ev.currentTarget);
sel.removeAllRanges();
sel.addRange(range);
}
}, [ peer_config ])
]);
invokeQREncode(peer_config, node.firstChild);
return node;
};
return qrm.render().then(function(nodes) {
mapNode.classList.add('hidden');
mapNode.nextElementSibling.classList.add('hidden');
headNode.appendChild(E('span', [ ' » ', _('Generate configuration') ]));
mapNode.parentNode.appendChild(E([], [
nodes,
E('div', {
'class': 'right'
}, [
E('button', {
'class': 'btn',
'click': function() {
nodes.parentNode.removeChild(nodes.nextSibling);
nodes.parentNode.removeChild(nodes);
mapNode.classList.remove('hidden');
mapNode.nextSibling.classList.remove('hidden');
headNode.removeChild(headNode.lastChild);
}
}, [ _('Back to peer configuration') ])
])
]));
if (!s.formvalue(s.section, 'listen_port')) {
nodes.appendChild(E('div', { 'class': 'alert-message' }, [
E('p', [
_('No fixed interface listening port defined, peers might not be able to initiate connections to this WireGuard instance!')
])
]));
}
});
});
};
o.cfgvalue = function(section_id, value) {
var privkey = this.section.cfgvalue(section_id, 'private_key');
return E('button', {
'class': 'btn qr-code',
'style': 'display:inline-flex;align-items:center;gap:.5em',
'click': ui.createHandlerFn(this, 'handleGenerateQR', section_id),
'disabled': privkey ? null : ''
}, [
Object.assign(E(qrIcon), { style: 'width:22px;height:22px' }),
_('Generate configuration…')
]);
};
},
deleteConfiguration: function() {
uci.sections('network', 'wireguard_%s'.format(this.sid), function(s) {
uci.remove('network', s['.name']);
});
}
});

View file

@ -1,175 +0,0 @@
'use strict';
'require view';
'require rpc';
'require poll';
'require dom';
'require ui';
var callGetWgInstances = rpc.declare({
object: 'luci.wireguard',
method: 'getWgInstances'
});
function timestampToStr(timestamp) {
if (timestamp < 1)
return _('Never', 'No WireGuard peer handshake yet');
var seconds = (Date.now() / 1000) - timestamp;
var ago;
if (seconds < 60)
ago = _('%ds ago').format(seconds);
else if (seconds < 3600)
ago = _('%dm ago').format(seconds / 60);
else if (seconds < 86401)
ago = _('%dh ago').format(seconds / 3600);
else
ago = _('over a day ago');
return (new Date(timestamp * 1000)).toUTCString() + ' (' + ago + ')';
}
function handleInterfaceDetails(iface) {
ui.showModal(_('Instance Details'), [
ui.itemlist(E([]), [
_('Name'), iface.name,
_('Public Key'), E('code', [ iface.public_key ]),
_('Listen Port'), iface.listen_port,
_('Firewall Mark'), iface.fwmark != 'off' ? iface.fwmark : E('em', _('none'))
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn cbi-button',
'click': ui.hideModal
}, [ _('Dismiss') ])
])
]);
}
function handlePeerDetails(peer) {
ui.showModal(_('Peer Details'), [
ui.itemlist(E([]), [
_('Description'), peer.name,
_('Public Key'), E('code', [ peer.public_key ]),
_('Endpoint'), peer.endpoint,
_('Allowed IPs'), (Array.isArray(peer.allowed_ips) && peer.allowed_ips.length) ? peer.allowed_ips.join(', ') : E('em', _('none')),
_('Received Data'), '%1024mB'.format(peer.transfer_rx),
_('Transmitted Data'), '%1024mB'.format(peer.transfer_tx),
_('Latest Handshake'), timestampToStr(+peer.latest_handshake),
_('Keep-Alive'), (peer.persistent_keepalive != 'off') ? _('every %ds', 'WireGuard keep alive interval').format(+peer.persistent_keepalive) : E('em', _('none')),
]),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn cbi-button',
'click': ui.hideModal
}, [ _('Dismiss') ])
])
]);
}
function renderPeerTable(instanceName, peers) {
var t = new L.ui.Table(
[
_('Peer'),
_('Endpoint'),
_('Data Received'),
_('Data Transmitted'),
_('Latest Handshake')
],
{
id: 'peers-' + instanceName
},
E('em', [
_('No peers connected')
])
);
t.update(peers.map(function(peer) {
return [
[
peer.name || '',
E('div', {
'style': 'cursor:pointer',
'click': ui.createHandlerFn(this, handlePeerDetails, peer)
}, [
E('p', [
peer.name ? E('span', [ peer.name ]) : E('em', [ _('Untitled peer') ])
]),
E('span', {
'class': 'ifacebadge hide-sm',
'data-tooltip': _('Public key: %h', 'Tooltip displaying full WireGuard peer public key').format(peer.public_key)
}, [
E('code', [ peer.public_key.replace(/^(.{5}).+(.{6})$/, '$1…$2') ])
])
])
],
peer.endpoint,
[ +peer.transfer_rx, '%1024mB'.format(+peer.transfer_rx) ],
[ +peer.transfer_tx, '%1024mB'.format(+peer.transfer_tx) ],
[ +peer.latest_handshake, timestampToStr(+peer.latest_handshake) ]
];
}));
return t.render();
}
return view.extend({
renderIfaces: function(ifaces) {
var res = [
E('h2', [ _('WireGuard Status') ])
];
for (var instanceName in ifaces) {
res.push(
E('h3', [ _('Instance "%h"', 'WireGuard instance heading').format(instanceName) ]),
E('p', {
'style': 'cursor:pointer',
'click': ui.createHandlerFn(this, handleInterfaceDetails, ifaces[instanceName])
}, [
E('span', { 'class': 'ifacebadge' }, [
E('img', { 'src': L.resource('icons', 'tunnel.png') }),
'\xa0',
instanceName
]),
E('span', { 'style': 'opacity:.8' }, [
' · ',
_('Port %d', 'WireGuard listen port').format(ifaces[instanceName].listen_port),
' · ',
E('code', { 'click': '' }, [ ifaces[instanceName].public_key ])
])
]),
renderPeerTable(instanceName, ifaces[instanceName].peers)
);
}
if (res.length == 1)
res.push(E('p', { 'class': 'center', 'style': 'margin-top:5em' }, [
E('em', [ _('No WireGuard interfaces configured.') ])
]));
return E([], res);
},
render: function() {
poll.add(L.bind(function () {
return callGetWgInstances().then(L.bind(function(ifaces) {
dom.content(
document.querySelector('#view'),
this.renderIfaces(ifaces)
);
}, this));
}, this), 5);
return E([], [
E('h2', [ _('WireGuard Status') ]),
E('p', { 'class': 'center', 'style': 'margin-top:5em' }, [
E('em', [ _('Loading data…') ])
])
]);
},
handleReset: null,
handleSaveApply: null,
handleSave: null
});

View file

@ -1,14 +0,0 @@
{
"admin/status/wireguard": {
"title": "WireGuard",
"order": 92,
"action": {
"type": "view",
"path": "wireguard/status"
},
"depends": {
"acl": [ "luci-proto-wireguard" ],
"uci": { "network": true }
}
}
}

View file

@ -1,25 +0,0 @@
{
"luci-proto-wireguard": {
"description": "Grant access to LuCI Wireguard procedures",
"read": {
"file": {
"/usr/bin/qrencode --inline --8bit --type=SVG --output=- -- *": [ "exec" ]
},
"ubus": {
"luci.wireguard": [
"getWgInstances"
]
},
"uci": [ "ddns", "system" ]
},
"write": {
"ubus": {
"luci.wireguard": [
"generateKeyPair",
"getPublicAndPrivateKeyFromPrivate",
"generatePsk"
]
}
}
}
}

View file

@ -1,107 +0,0 @@
// Copyright 2022 Jo-Philipp Wich <jo@mein.io>
// Licensed to the public under the Apache License 2.0.
'use strict';
import { cursor } from 'uci';
import { popen } from 'fs';
function shellquote(s) {
return `'${replace(s ?? '', "'", "'\\''")}'`;
}
function command(cmd) {
return trim(popen(cmd)?.read?.('all'));
}
const methods = {
generatePsk: {
call: function() {
return { psk: command('wg genpsk 2>/dev/null') };
}
},
generateKeyPair: {
call: function() {
const priv = command('wg genkey 2>/dev/null');
const pub = command(`echo ${shellquote(priv)} | wg pubkey 2>/dev/null`);
return { keys: { priv, pub } };
}
},
getPublicAndPrivateKeyFromPrivate: {
args: { privkey: "privkey" },
call: function(req) {
const priv = req.args?.privkey;
const pub = command(`echo ${shellquote(priv)} | wg pubkey 2>/dev/null`);
return { keys: { priv, pub } };
}
},
getWgInstances: {
call: function() {
const data = {};
let last_device;
let qr_pubkey = {};
const uci = cursor();
const wg_dump = popen("wg show all dump 2>/dev/null");
if (wg_dump) {
uci.load("network");
for (let line = wg_dump.read('line'); length(line); line = wg_dump.read('line')) {
const record = split(rtrim(line, '\n'), '\t');
if (last_device != record[0]) {
last_device = record[0];
data[last_device] = {
name: last_device,
public_key: record[2],
listen_port: record[3],
fwmark: record[4],
peers: []
};
if (!length(record[2]) || record[2] == '(none)')
qr_pubkey[last_device] = '';
else
qr_pubkey[last_device] = `PublicKey = ${record[2]}`;
}
else {
let peer_name;
uci.foreach('network', `wireguard_${last_device}`, (s) => {
if (s.public_key == record[1])
peer_name = s.description;
});
const peer = {
name: peer_name,
public_key: record[1],
endpoint: record[3],
allowed_ips: [],
latest_handshake: record[5],
transfer_rx: record[6],
transfer_tx: record[7],
persistent_keepalive: record[8]
};
if (record[3] != '(none)' && length(record[4]))
push(peer.allowed_ips, ...split(record[4], ','));
push(data[last_device].peers, peer);
}
}
}
return data;
}
}
};
return { 'luci.wireguard': methods };

View file

@ -1,14 +0,0 @@
#
# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for XFRM interfaces
LUCI_DEPENDS:=+xfrm
PKG_MAINTAINER:=Glen Huang <heyhgl@gmail.com>
include ../../luci.mk
# call BuildPackage - OpenWrt buildroot signature

View file

@ -1,51 +0,0 @@
'use strict';
'require uci';
'require form';
'require network';
'require tools.widgets as widgets';
return network.registerProtocol('xfrm', {
getI18n: function() {
return _('IPsec XFRM');
},
getIfname: function() {
return this._ubus('l3_device') || this.sid;
},
getOpkgPackage: function() {
return 'xfrm';
},
isFloating: function() {
return true;
},
isVirtual: function() {
return true;
},
getDevice: function() {
return null;
},
containsDevice: function(ifname) {
return (network.getIfnameOf(ifname) == this.getIfname());
},
renderFormOptions: function(s) {
var o, ss;
o = s.taboption('general', form.Value, 'ifid', _('Interface ID'), _('Required. XFRM interface ID to be used for SA.'));
o.datatype = 'integer';
o = s.taboption('general', widgets.NetworkSelect, 'tunlink', _('Required. Underlying interface.'));
o.exclude = s.section;
o.nocreate = true;
o = s.taboption('general', form.Value, 'mtu', _('MTU'), _('Optional. Maximum Transmission Unit of the XFRM interface.'));
o.datatype = 'range(68,65535)';
o.placeholder = '1280';
o.optional = true;
}
});