summaryrefslogtreecommitdiffhomepage
path: root/protocols
diff options
context:
space:
mode:
Diffstat (limited to 'protocols')
-rw-r--r--protocols/luci-proto-bonding/Makefile17
-rw-r--r--protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js425
-rw-r--r--protocols/luci-proto-gre/Makefile21
-rw-r--r--protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js96
-rw-r--r--protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js101
-rw-r--r--protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js98
-rw-r--r--protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js103
-rw-r--r--protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js1
-rwxr-xr-xprotocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect12
-rw-r--r--protocols/luci-proto-vxlan/Makefile16
-rw-r--r--protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js89
-rw-r--r--protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js84
-rw-r--r--protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js19
13 files changed, 1075 insertions, 7 deletions
diff --git a/protocols/luci-proto-bonding/Makefile b/protocols/luci-proto-bonding/Makefile
new file mode 100644
index 0000000000..81988cfa2f
--- /dev/null
+++ b/protocols/luci-proto-bonding/Makefile
@@ -0,0 +1,17 @@
+#
+# 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
diff --git a/protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js b/protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js
new file mode 100644
index 0000000000..aadc2306d3
--- /dev/null
+++ b/protocols/luci-proto-bonding/htdocs/luci-static/resources/protocol/bonding.js
@@ -0,0 +1,425 @@
+'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] && interfaces[j]['.name'] != section_id) {
+ in_use = true;
+ }
+ }
+ }
+ }
+ if (in_use == false) {
+ rv.push(devices[i].ifname);
+ }
+ }
+ }
+
+ 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-rr');
+ o.depends('bonding_policy', 'active-backup');
+ o.depends('bonding_policy', 'balance-tlb');
+ o.depends('bonding_policy', 'balance-alb');
+ o.depends('bonding_policy', 'balance-xor');
+
+ 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');
+ }
+});
diff --git a/protocols/luci-proto-gre/Makefile b/protocols/luci-proto-gre/Makefile
new file mode 100644
index 0000000000..0b0fa541cb
--- /dev/null
+++ b/protocols/luci-proto-gre/Makefile
@@ -0,0 +1,21 @@
+#
+# 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
diff --git a/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js
new file mode 100644
index 0000000000..e431bccd76
--- /dev/null
+++ b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gre.js
@@ -0,0 +1,96 @@
+'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")';
+
+ // -- 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 either <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value starting with <code>0x</code> (optional)."));
+ o.optional = true;
+ o.validate = function(section_id, value) {
+ if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,2}$/) && !value.match(/^inherit$/i))
+ return _('Invalid value');
+
+ 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.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 (optinal)."));
+ 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)."));
+
+ }
+});
diff --git a/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js
new file mode 100644
index 0000000000..426b5d98df
--- /dev/null
+++ b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/gretap.js
@@ -0,0 +1,101 @@
+'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 = 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 either <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value starting with <code>0x</code> (optional)."));
+ o.optional = true;
+ o.validate = function(section_id, value) {
+ if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,2}$/) && !value.match(/^inherit$/i))
+ return _('Invalid value');
+
+ 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.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 (optinal)."));
+ 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)."));
+
+ }
+});
diff --git a/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js
new file mode 100644
index 0000000000..bd9a43e27b
--- /dev/null
+++ b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6.js
@@ -0,0 +1,98 @@
+'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 = 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 Traffic Class. Can be either <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value starting with <code>0x</code> (optional)."));
+ o.optional = true;
+ o.validate = function(section_id, value) {
+ if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,2}$/) && !value.match(/^inherit$/i))
+ return _('Invalid value');
+
+ 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.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 (optinal)."));
+ 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)."));
+
+ }
+});
diff --git a/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js
new file mode 100644
index 0000000000..3b1a503719
--- /dev/null
+++ b/protocols/luci-proto-gre/htdocs/luci-static/resources/protocol/grev6tap.js
@@ -0,0 +1,103 @@
+'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 = 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 either <code>inherit</code> (the outer header inherits the value of the inner header) or an hexadecimal value starting with <code>0x</code> (optional)."));
+ o.optional = true;
+ o.validate = function(section_id, value) {
+ if (value.length > 0 && !value.match(/^0x[a-fA-F0-9]{1,2}$/) && !value.match(/^inherit$/i))
+ return _('Invalid value');
+
+ 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.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 (optinal)."));
+ 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)."));
+
+ }
+});
diff --git a/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js
index 86fd27f294..1f07f97513 100644
--- a/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js
+++ b/protocols/luci-proto-openconnect/htdocs/luci-static/resources/protocol/openconnect.js
@@ -102,6 +102,7 @@ return network.registerProtocol('openconnect', {
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'));
diff --git a/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect b/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
index 9378cc518b..38650a615f 100755
--- a/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
+++ b/protocols/luci-proto-openconnect/root/usr/libexec/rpcd/luci.openconnect
@@ -59,19 +59,19 @@ elseif arg[1] == "call" then
if arg[2] == "getCertificates" then
print(json.stringify({
- user_certificate = readfile(string.format("/etc/openconnect/user-cert-%s.pem", args.interface)),
- user_privatekey = readfile(string.format("/etc/openconnect/user-key-%s.pem", args.interface)),
- ca_certificate = readfile(string.format("/etc/openconnect/ca-%s.pem", args.interface))
+ 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-%s.pem", args.interface), args.user_certificate)
+ 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-%s.pem", args.interface), args.user_privatekey)
+ 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-%s.pem", args.interface), args.ca_certificate)
+ writefile(string.format("/etc/openconnect/ca-vpn-%s.pem", args.interface), args.ca_certificate)
end
print(json.stringify({ result = true }))
end
diff --git a/protocols/luci-proto-vxlan/Makefile b/protocols/luci-proto-vxlan/Makefile
new file mode 100644
index 0000000000..d6b2e6faaa
--- /dev/null
+++ b/protocols/luci-proto-vxlan/Makefile
@@ -0,0 +1,16 @@
+#
+# 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
diff --git a/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js b/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js
new file mode 100644
index 0000000000..9927f0bc65
--- /dev/null
+++ b/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan.js
@@ -0,0 +1,89 @@
+'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, '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.Value, 'macaddr', _('Override MAC address'));
+ o.optional = true;
+ o.datatype = 'macaddr';
+
+ 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;
+
+ }
+});
diff --git a/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js b/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js
new file mode 100644
index 0000000000..f568e7e244
--- /dev/null
+++ b/protocols/luci-proto-vxlan/htdocs/luci-static/resources/protocol/vxlan6.js
@@ -0,0 +1,84 @@
+'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, '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.Value, 'macaddr', _('Override MAC address'));
+ o.optional = true;
+ o.datatype = 'macaddr';
+
+ 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;
+
+ }
+});
diff --git a/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js b/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js
index c8e1f8403e..e88c07c339 100644
--- a/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js
+++ b/protocols/luci-proto-wireguard/htdocs/luci-static/resources/protocol/wireguard.js
@@ -1,4 +1,5 @@
'use strict';
+'require uci';
'require form';
'require network';
@@ -9,6 +10,9 @@ function validateBase64(section_id, value) {
if (value.length != 44 || !value.match(/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/))
return _('Invalid Base64 key string');
+ if (value[43] != "=" )
+ return _('Invalid Base64 key string');
+
return true;
}
@@ -123,7 +127,14 @@ return network.registerProtocol('wireguard', {
o = ss.option(form.DynamicList, 'allowed_ips', _('Allowed IPs'), _("Required. IP addresses and prefixes that this peer is allowed to use inside the tunnel. Usually the peer's tunnel IP addresses and the networks the peer routes through the tunnel."));
o.datatype = 'ipaddr';
- o.rmempty = false;
+ o.validate = function(section, value) {
+ var opt = this.map.lookupOption('allowed_ips', section);
+ var ips = opt[0].formvalue(section);
+ if (ips.length == 0) {
+ return _('Value must not be empty');
+ }
+ return true;
+ };
o = ss.option(form.Flag, 'route_allowed_ips', _('Route Allowed IPs'), _('Optional. Create routes for Allowed IPs for this peer.'));
@@ -138,5 +149,11 @@ return network.registerProtocol('wireguard', {
o = ss.option(form.Value, 'persistent_keepalive', _('Persistent Keep Alive'), _('Optional. Seconds between keep alive messages. Default is 0 (disabled). Recommended value if this device is behind a NAT is 25.'));
o.datatype = 'range(0,65535)';
o.placeholder = '0';
+ },
+
+ deleteConfiguration: function() {
+ uci.sections('network', 'wireguard_%s'.format(this.sid), function(s) {
+ uci.remove('network', s['.name']);
+ });
}
});