#!/usr/bin/lua local site = require 'gluon.site' 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 unistd = require 'posix.unistd' 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 if site.mesh_vpn.fastd.configurable(false) then 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') if old_methods then has_null = util.contains(old_methods, 'null@l2tp') or util.contains(old_methods, 'null') end methods = {} if has_null then table.insert(methods, 'null@l2tp') table.insert(methods, 'null') end for _, method in ipairs(site_methods) do if method ~= 'null@l2tp' and method ~= 'null' then table.insert(methods, method) end end else methods = site.mesh_vpn.fastd.methods() end uci:section('fastd', 'fastd', 'mesh_vpn', { group = 'gluon-mesh-vpn', syslog_level = syslog_level, secret = secret, interface = vpn_core.get_interface(), mode = 'tap', mtu = active_vpn.mtu(), secure_handshakes = true, method = methods, packet_mark = 1, persist_interface = true, offload_l2tp = false, status_socket = '/var/run/fastd.mesh_vpn.socket', }) 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 function add_peer(group, name, config) 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, net = 'mesh_vpn', group = group, interface = 'mesh-vpn', key = config.key, remote = config.remotes, }) end local function add_group(name, config, parent) uci:section('fastd', 'peer_group', name, { enabled = true, net = 'mesh_vpn', parent = parent, peer_limit = config.limit, }) for peername, peerconfig in pairs(config.peers or {}) do add_peer(name, peername, peerconfig) end add_groups(name, config.groups, name) end -- declared local above function add_groups(prefix, groups, parent) for name, group in pairs(groups or {}) do add_group(prefix .. '_' .. name, group, parent) end end 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')