Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • v2023.2.5-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • hoodselector
  • master
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.x
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
56 results
Show changes
Showing
with 236 additions and 114 deletions
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-vpn-fastd-l2tp
PKG_VERSION:=1
include ../gluon.mk
define Package/gluon-mesh-vpn-fastd-l2tp
TITLE:=Support for connecting meshes via fastd (with L2TP kernel offloading)
DEPENDS:=+gluon-core +gluon-mesh-vpn-fastd +kmod-l2tp-eth
endef
$(eval $(call BuildPackageGluon,gluon-mesh-vpn-fastd-l2tp))
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-vpn-fastd PKG_NAME:=gluon-mesh-vpn-fastd
PKG_VERSION:=3
include ../gluon.mk include ../gluon.mk
define Package/gluon-mesh-vpn-fastd define Package/gluon-mesh-vpn-fastd
TITLE:=Support for connecting meshes via fastd TITLE:=Support for connecting meshes via fastd
DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +fastd +@GLUON_SPECIALIZE_KERNEL:KERNEL_TUN DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +fastd +simple-tc
endef endef
$(eval $(call BuildPackageGluon,gluon-mesh-vpn-fastd)) $(eval $(call BuildPackageGluon,gluon-mesh-vpn-fastd))
local fastd_methods = {'salsa2012+gmac', 'salsa2012+umac', 'null+salsa2012+gmac', 'null+salsa2012+umac', 'null'} local fastd_methods = {'salsa2012+umac', 'null+salsa2012+umac', 'null@l2tp', 'null'}
need_array_of({'mesh_vpn', 'fastd', 'methods'}, fastd_methods) need_array_of({'mesh_vpn', 'fastd', 'methods'}, fastd_methods)
need_boolean(in_site({'mesh_vpn', 'fastd', 'configurable'}), false) need_boolean(in_site({'mesh_vpn', 'fastd', 'configurable'}), false)
need_number({'mesh_vpn', 'fastd', 'mtu'})
need_one_of(in_site({'mesh_vpn', 'fastd', 'syslog_level'}), {'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false) need_one_of(in_site({'mesh_vpn', 'fastd', 'syslog_level'}),
{'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false)
local function check_peer(k) local function check_peer(k)
need_alphanumeric_key(k) need_alphanumeric_key(k)
......
#!/bin/sh
/etc/init.d/fastd stop
#!/bin/sh
/etc/init.d/fastd start
...@@ -2,29 +2,39 @@ ...@@ -2,29 +2,39 @@
local site = require 'gluon.site' local site = require 'gluon.site'
local util = require 'gluon.util' local util = require 'gluon.util'
local vpn_core = require 'gluon.mesh-vpn'
local _, active_vpn = vpn_core.get_active_provider()
local uci = require('simple-uci').cursor() local uci = require('simple-uci').cursor()
local unistd = require 'posix.unistd'
local syslog_level = uci:get('fastd', 'mesh_vpn', 'syslog_level') or 'verbose' local syslog_level = uci:get('fastd', 'mesh_vpn', 'syslog_level') or 'verbose'
local secret = uci:get('fastd', 'mesh_vpn', 'secret')
if not secret or not secret:match(('%x'):rep(64)) then
secret = 'generate'
end
local methods local methods
if site.mesh_vpn.fastd.configurable(false) then if site.mesh_vpn.fastd.configurable(false) then
local has_null = util.contains(site.mesh_vpn.fastd.methods(), 'null') local site_methods = site.mesh_vpn.fastd.methods()
local has_null = util.contains(site_methods, 'null@l2tp') or util.contains(site_methods, 'null')
local old_methods = uci:get('fastd', 'mesh_vpn', 'method') local old_methods = uci:get('fastd', 'mesh_vpn', 'method')
if old_methods then if old_methods then
has_null = util.contains(old_methods, 'null') has_null = util.contains(old_methods, 'null@l2tp') or util.contains(old_methods, 'null')
end end
methods = {} methods = {}
if has_null then if has_null then
table.insert(methods, 'null@l2tp')
table.insert(methods, 'null') table.insert(methods, 'null')
end end
for _, method in ipairs(site.mesh_vpn.fastd.methods()) do for _, method in ipairs(site_methods) do
if method ~= 'null' then if method ~= 'null@l2tp' and method ~= 'null' then
table.insert(methods, method) table.insert(methods, method)
end end
end end
...@@ -37,36 +47,74 @@ end ...@@ -37,36 +47,74 @@ end
uci:section('fastd', 'fastd', 'mesh_vpn', { uci:section('fastd', 'fastd', 'mesh_vpn', {
group = 'gluon-mesh-vpn', group = 'gluon-mesh-vpn',
syslog_level = syslog_level, syslog_level = syslog_level,
interface = 'mesh-vpn', secret = secret,
interface = vpn_core.get_interface(),
mode = 'tap', mode = 'tap',
mtu = site.mesh_vpn.mtu(), mtu = active_vpn.mtu(),
secure_handshakes = true, secure_handshakes = true,
method = methods, method = methods,
packet_mark = 1, packet_mark = 1,
persist_interface = true,
offload_l2tp = false,
status_socket = '/var/run/fastd.mesh_vpn.socket', status_socket = '/var/run/fastd.mesh_vpn.socket',
}) })
uci:delete('fastd', 'mesh_vpn', 'user') uci:delete('fastd', 'mesh_vpn', 'peer_limit')
-- L2TP offload support
if unistd.access('/lib/gluon/mesh-vpn/fastd/l2tp') then
uci:set('fastd', 'mesh_vpn', 'mode', 'multitap')
uci:set('fastd', 'mesh_vpn', 'persist_interface', false)
uci:set('fastd', 'mesh_vpn', 'offload_l2tp', true)
uci:set('fastd', 'mesh_vpn', 'peer_limit', 1)
end
-- Collect list of groups that have peers with 'preserve' flag
local preserve_groups = {}
local function preserve_group(name)
if not name or preserve_groups[name] then
return
end
preserve_groups[name] = true
local parent = uci:get('fastd', name, 'group')
preserve_group(parent)
end
uci:foreach('fastd', 'peer', function(peer)
if peer.net == 'mesh_vpn' and peer.preserve == '1' then
preserve_group(peer.group)
end
end)
-- Clean up previous configuration
uci:delete_all('fastd', 'peer', function(peer)
return (peer.net == 'mesh_vpn' and peer.preserve ~= '1')
end)
uci:delete_all('fastd', 'peer_group', function(group)
return (group.net == 'mesh_vpn' and not preserve_groups[group['.name']])
end)
local add_groups local add_groups
local function add_peer(group, name, config) local function add_peer(group, name, config)
uci:section('fastd', 'peer', group .. '_peer_' .. name, { local uci_name = group .. '_peer_' .. name
if uci:get_bool('fastd', uci_name, 'preserve') then
return
end
uci:section('fastd', 'peer', uci_name, {
enabled = true, enabled = true,
net = 'mesh_vpn', net = 'mesh_vpn',
group = group, group = group,
interface = 'mesh-vpn',
key = config.key, key = config.key,
remote = config.remotes, remote = config.remotes,
}) })
end end
local function add_group(name, config, parent) local function add_group(name, config, parent)
uci:delete('fastd', name)
uci:delete_all('fastd', 'peer', function(peer)
return (peer.net == 'mesh_vpn' and peer.group == name)
end)
uci:section('fastd', 'peer_group', name, { uci:section('fastd', 'peer_group', name, {
enabled = true, enabled = true,
net = 'mesh_vpn', net = 'mesh_vpn',
...@@ -74,25 +122,27 @@ local function add_group(name, config, parent) ...@@ -74,25 +122,27 @@ local function add_group(name, config, parent)
peer_limit = config.limit, peer_limit = config.limit,
}) })
if config.peers then for peername, peerconfig in pairs(config.peers or {}) do
for peername, peerconfig in pairs(config.peers) do
add_peer(name, peername, peerconfig) add_peer(name, peername, peerconfig)
end end
end
add_groups(name, config.groups, name) add_groups(name, config.groups, name)
end end
-- declared local above -- declared local above
function add_groups(prefix, groups, parent) function add_groups(prefix, groups, parent)
if groups then for name, group in pairs(groups or {}) do
for name, group in pairs(groups) do
add_group(prefix .. '_' .. name, group, parent) add_group(prefix .. '_' .. name, group, parent)
end end
end end
end
add_groups('mesh_vpn', site.mesh_vpn.fastd.groups()) add_groups('mesh_vpn', site.mesh_vpn.fastd.groups())
-- Update preserved peers as well
uci:foreach('fastd', 'peer', function(peer)
if peer.net == 'mesh_vpn' then
uci:set('fastd', peer['.name'], 'interface', 'mesh-vpn')
end
end)
uci:save('fastd') uci:save('fastd')
#!/usr/bin/lua
local uci = require 'simple-uci'
local c = uci.cursor()
local secret = c:get("fastd", "mesh_vpn", "secret")
if not secret or not secret:match(("%x"):rep(64)) then
c:set("fastd", "mesh_vpn", "secret", "generate")
c:save("fastd")
end
local uci = require('simple-uci').cursor()
local site = require 'gluon.site'
local util = require 'gluon.util'
local vpn_core = require 'gluon.mesh-vpn'
local unistd = require 'posix.unistd'
local M = {}
function M.public_key()
local key = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn'))
if key == '' then
key = nil
end
return key
end
function M.enable(val)
uci:set('fastd', 'mesh_vpn', 'enabled', val)
uci:save('fastd')
end
function M.active()
return site.mesh_vpn.fastd() ~= nil
end
local function set_limit_simple_tc(ingress_limit, egress_limit)
uci:section('simple-tc', 'interface', 'mesh_vpn', {
ifname = vpn_core.get_interface(),
enabled = true,
limit_egress = egress_limit,
limit_ingress = ingress_limit,
})
end
local function set_limit_sqm(ingress_limit, egress_limit)
uci:section('sqm', 'queue', 'mesh_vpn', {
interface = vpn_core.get_interface(),
enabled = true,
upload = egress_limit,
download = ingress_limit,
qdisc = 'cake',
script = 'piece_of_cake.qos',
debug_logging = '0',
verbosity = '5',
})
end
local function sqm_available()
return unistd.access('/lib/gluon/mesh-vpn/sqm')
end
function M.set_limit(ingress_limit, egress_limit)
uci:delete('simple-tc', 'mesh_vpn')
uci:delete('sqm', 'mesh_vpn')
if ingress_limit ~= nil and egress_limit ~= nil then
if sqm_available() and util.get_mem_total() > 200*1024 then
set_limit_sqm(ingress_limit, egress_limit)
else
set_limit_simple_tc(ingress_limit, egress_limit)
end
end
uci:save('simple-tc')
uci:save('sqm')
end
function M.mtu()
return site.mesh_vpn.fastd.mtu()
end
return M
/* /* SPDX-License-Identifier: BSD-2-Clause */
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net> /* SPDX-FileCopyrightText: 2016, Matthias Schiffer <mschiffer@universe-factory.net> */
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <respondd.h> #include <respondd.h>
...@@ -65,7 +43,7 @@ static struct json_object * get_fastd_version(void) { ...@@ -65,7 +43,7 @@ static struct json_object * get_fastd_version(void) {
} }
const char *version = line; const char *version = line;
if (strncmp(version, "fastd ", 6) == 0) if (version && strncmp(version, "fastd ", 6) == 0)
version += 6; version += 6;
struct json_object *ret = gluonutil_wrap_string(version); struct json_object *ret = gluonutil_wrap_string(version);
...@@ -239,7 +217,7 @@ static bool get_peer_connection(struct json_object **ret, struct json_object *co ...@@ -239,7 +217,7 @@ static bool get_peer_connection(struct json_object **ret, struct json_object *co
if (!key) if (!key)
return false; return false;
struct json_object *peer, *connection, *established; struct json_object *peer, *connection, *established, *method;
if (!json_object_object_get_ex(peers, key, &peer) || if (!json_object_object_get_ex(peers, key, &peer) ||
!json_object_object_get_ex(peer, "connection", &connection)) !json_object_object_get_ex(peer, "connection", &connection))
return false; return false;
...@@ -251,6 +229,10 @@ static bool get_peer_connection(struct json_object **ret, struct json_object *co ...@@ -251,6 +229,10 @@ static bool get_peer_connection(struct json_object **ret, struct json_object *co
struct json_object *jso = json_object_new_double(established_time/1000.0); struct json_object *jso = json_object_new_double(established_time/1000.0);
json_object_set_serializer(jso, json_object_double_to_json_string, "%.3f", NULL); json_object_set_serializer(jso, json_object_double_to_json_string, "%.3f", NULL);
json_object_object_add(*ret, "established", jso); json_object_object_add(*ret, "established", jso);
if (json_object_object_get_ex(connection, "method", &method)) {
json_object_object_add(*ret, "method", json_object_get(method));
}
} }
else { else {
*ret = NULL; *ret = NULL;
......
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-vpn-sqm
include ../gluon.mk
define Package/gluon-mesh-vpn-sqm
TITLE:=Adds support for SQM with CAKE on VPN links
DEPENDS:= +gluon-mesh-vpn-core +sqm-scripts
endef
define Package/gluon-mesh-vpn-sqm/install
$(Gluon/Build/Install)
$(INSTALL_DIR) $(1)/lib/gluon/mesh-vpn
touch $(1)/lib/gluon/mesh-vpn/sqm
endef
$(eval $(call BuildPackageGluon,gluon-mesh-vpn-sqm))
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-vpn-tunneldigger
PKG_VERSION:=3
include ../gluon.mk
define Package/gluon-mesh-vpn-tunneldigger
TITLE:=Support for connecting meshes via tunneldigger/L2TPv3 pseudowire
DEPENDS:=+gluon-core +gluon-mesh-vpn-core +tunneldigger +@GLUON_SPECIALIZE_KERNEL:KERNEL_L2TP
endef
$(eval $(call BuildPackageGluon,gluon-mesh-vpn-tunneldigger))
need_string_array(in_domain({'mesh_vpn', 'tunneldigger', 'brokers'}))
#!/usr/bin/lua
local site = require 'gluon.site'
local util = require 'gluon.util'
local uci = require('simple-uci').cursor()
local enabled
-- Delete old broker config section (remove in 2019)
if not uci:get('tunneldigger', 'mesh_vpn') then
if uci:get_first('tunneldigger', 'broker', 'interface') == 'mesh-vpn' then
enabled = uci:get_first('tunneldigger', 'broker', 'enabled')
end
-- In the usual case (no migration from old tunneldigger package), the
-- enabled state is set in the 500-mesh-vpn script
uci:delete_all('tunneldigger', 'broker')
end
uci:section('tunneldigger', 'broker', 'mesh_vpn', {
enabled = enabled,
uuid = util.node_id(),
interface = 'mesh-vpn',
bind_interface = 'br-wan',
group = 'gluon-mesh-vpn',
broker_selection = 'usage',
address = site.mesh_vpn.tunneldigger.brokers(),
})
uci:save('tunneldigger')
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-vpn-wireguard
include ../gluon.mk
define Package/gluon-mesh-vpn-wireguard
TITLE:=Support for connecting meshes via wireguard
DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +wireguard-tools +wgpeerselector +libubox +libubus +simple-tc
endef
define Package/gluon-mesh-vpn-wireguard/install
$(Gluon/Build/Install)
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-hex-to-b64 $(1)/usr/sbin/
endef
$(eval $(call BuildPackageGluon,gluon-mesh-vpn-wireguard))
local function check_peer(k)
need_alphanumeric_key(k)
need_string_match(in_domain(extend(k,
{'public_key'})), "^" .. ("[%a%d+/]"):rep(42) .. "[AEIMQUYcgkosw480]=$")
need_string(in_domain(extend(k, {'endpoint'})))
end
need_table({'mesh_vpn', 'wireguard', 'peers'}, check_peer)
need_number({'mesh_vpn', 'wireguard', 'mtu'})
#!/bin/sh
# shellcheck disable=SC1091,SC2034
INCLUDE_ONLY=1
. /lib/netifd/proto/wireguard.sh
ensure_key_is_generated wg_mesh
uci get "network.wg_mesh.private_key" | /usr/bin/wg pubkey