Merge pull request #22645 from yggdrasil-openwrt/yggdrasil-2023-11-11
yggdrasil: overhaul package with netifd support
This commit is contained in:
commit
e5dba39ebf
5 changed files with 211 additions and 317 deletions
|
@ -1,12 +1,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=yggdrasil
|
PKG_NAME:=yggdrasil
|
||||||
PKG_VERSION:=0.4.7
|
PKG_VERSION:=0.5.4
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/yggdrasil-network/yggdrasil-go/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/yggdrasil-network/yggdrasil-go/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=47429f75b87d9b2450108471991e84c90d748606642e8778e9f578485b05a56f
|
PKG_HASH:=c1cceb9a7a4a8959536b1d930ca081bcfbc76ab655e4bcb55d5d0ab6520d9241
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-go-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-go-$(PKG_VERSION)
|
||||||
|
|
||||||
PKG_MAINTAINER:=William Fleurant <meshnet@protonmail.com>
|
PKG_MAINTAINER:=William Fleurant <meshnet@protonmail.com>
|
||||||
|
@ -33,7 +33,7 @@ define Package/yggdrasil
|
||||||
SUBMENU:=Routing and Redirection
|
SUBMENU:=Routing and Redirection
|
||||||
TITLE:=Yggdrasil supports end-to-end encrypted IPv6 networks
|
TITLE:=Yggdrasil supports end-to-end encrypted IPv6 networks
|
||||||
URL:=https://yggdrasil-network.github.io/
|
URL:=https://yggdrasil-network.github.io/
|
||||||
DEPENDS:=$(GO_ARCH_DEPENDS) @IPV6 +kmod-tun +dkjson +libuci-lua
|
DEPENDS:=$(GO_ARCH_DEPENDS) @IPV6 +kmod-tun
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/yggdrasil/description
|
define Package/yggdrasil/description
|
||||||
|
@ -46,14 +46,9 @@ define Package/yggdrasil/description
|
||||||
interfaces simultaneously with much greater throughput.
|
interfaces simultaneously with much greater throughput.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/yggdrasil/conffiles
|
|
||||||
/etc/config/yggdrasil
|
|
||||||
endef
|
|
||||||
|
|
||||||
define Package/yggdrasil/install
|
define Package/yggdrasil/install
|
||||||
$(INSTALL_DIR) \
|
$(INSTALL_DIR) \
|
||||||
$(1)/etc/init.d \
|
$(1)/lib/netifd/proto \
|
||||||
$(1)/etc/uci-defaults \
|
|
||||||
$(1)/usr/sbin
|
$(1)/usr/sbin
|
||||||
|
|
||||||
$(INSTALL_BIN) \
|
$(INSTALL_BIN) \
|
||||||
|
@ -65,16 +60,8 @@ define Package/yggdrasil/install
|
||||||
$(1)/usr/sbin
|
$(1)/usr/sbin
|
||||||
|
|
||||||
$(INSTALL_BIN) \
|
$(INSTALL_BIN) \
|
||||||
./files/ygguci \
|
./files/yggdrasil.sh \
|
||||||
$(1)/usr/sbin
|
$(1)/lib/netifd/proto
|
||||||
|
|
||||||
$(INSTALL_BIN) \
|
|
||||||
./files/yggdrasil.defaults \
|
|
||||||
$(1)/etc/uci-defaults/yggdrasil
|
|
||||||
|
|
||||||
$(INSTALL_BIN) \
|
|
||||||
./files/yggdrasil.init \
|
|
||||||
$(1)/etc/init.d/yggdrasil
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call GoBinPackage,yggdrasil))
|
$(eval $(call GoBinPackage,yggdrasil))
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
yggConfig="/etc/config/yggdrasil"
|
|
||||||
|
|
||||||
first_boot_genConfig()
|
|
||||||
{
|
|
||||||
. /usr/share/libubox/jshn.sh
|
|
||||||
boardcfg=$(ubus call system board)
|
|
||||||
touch ${yggConfig}
|
|
||||||
yggdrasil -genconf -json | ygguci set
|
|
||||||
|
|
||||||
json_load "$boardcfg"
|
|
||||||
json_get_var kernel kernel
|
|
||||||
json_get_var system system
|
|
||||||
json_get_var model model
|
|
||||||
json_get_var board_name board_name
|
|
||||||
nodeinfo='{"kernel": "'$kernel'", "hostname":"'OpenWrt'", "system": "'$system'", "model": "'$model'", "board_name": "'$board_name'"}'
|
|
||||||
|
|
||||||
uci set yggdrasil.yggdrasil.IfName="ygg0"
|
|
||||||
uci set yggdrasil.yggdrasil.NodeInfo="$nodeinfo"
|
|
||||||
uci commit yggdrasil
|
|
||||||
}
|
|
||||||
|
|
||||||
if [ -e /etc/yggdrasil.conf ]; then
|
|
||||||
echo "config: import config from /etc/yggdrasil.conf to /etc/config/yggdrasil" | logger -t yggdrasil
|
|
||||||
touch ${yggConfig}
|
|
||||||
cat /etc/yggdrasil.conf | ygguci set
|
|
||||||
mv /etc/yggdrasil.conf /etc/yggdrasil.conf.bak
|
|
||||||
elif [ ! -e ${yggConfig} ]; then
|
|
||||||
echo "first_boot: adding system board details to NodeInfo[] in NEW config: ${yggConfig}" | logger -t yggdrasil
|
|
||||||
|
|
||||||
first_boot_genConfig
|
|
||||||
|
|
||||||
# create the network interface
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
set network.yggdrasil=interface
|
|
||||||
set network.yggdrasil.device=ygg0
|
|
||||||
set network.yggdrasil.proto=none
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# create the firewall zone
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
set firewall.yggdrasil=zone
|
|
||||||
set firewall.yggdrasil.name=yggdrasil
|
|
||||||
add_list firewall.yggdrasil.network=yggdrasil
|
|
||||||
set firewall.yggdrasil.input=REJECT
|
|
||||||
set firewall.yggdrasil.output=ACCEPT
|
|
||||||
set firewall.yggdrasil.forward=REJECT
|
|
||||||
set firewall.yggdrasil.conntrack=1
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# allow ICMP from yggdrasil zone, e.g. ping6
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
add firewall rule
|
|
||||||
set firewall.@rule[-1].name='Allow-ICMPv6-yggdrasil'
|
|
||||||
set firewall.@rule[-1].src=yggdrasil
|
|
||||||
set firewall.@rule[-1].proto=icmp
|
|
||||||
add_list firewall.@rule[-1].icmp_type=echo-request
|
|
||||||
add_list firewall.@rule[-1].icmp_type=echo-reply
|
|
||||||
add_list firewall.@rule[-1].icmp_type=destination-unreachable
|
|
||||||
add_list firewall.@rule[-1].icmp_type=packet-too-big
|
|
||||||
add_list firewall.@rule[-1].icmp_type=time-exceeded
|
|
||||||
add_list firewall.@rule[-1].icmp_type=bad-header
|
|
||||||
add_list firewall.@rule[-1].icmp_type=unknown-header-type
|
|
||||||
set firewall.@rule[-1].limit='1000/sec'
|
|
||||||
set firewall.@rule[-1].family=ipv6
|
|
||||||
set firewall.@rule[-1].target=ACCEPT
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# allow SSH from yggdrasil zone, needs to be explicitly enabled
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
add firewall rule
|
|
||||||
set firewall.@rule[-1].enabled=0
|
|
||||||
set firewall.@rule[-1].name='Allow-SSH-yggdrasil'
|
|
||||||
set firewall.@rule[-1].src=yggdrasil
|
|
||||||
set firewall.@rule[-1].proto=tcp
|
|
||||||
set firewall.@rule[-1].dest_port=22
|
|
||||||
set firewall.@rule[-1].target=ACCEPT
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# allow LuCI access from yggdrasil zone, needs to be explicitly enabled
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
add firewall rule
|
|
||||||
set firewall.@rule[-1].enabled=0
|
|
||||||
set firewall.@rule[-1].name='Allow-HTTP-yggdrasil'
|
|
||||||
set firewall.@rule[-1].src=yggdrasil
|
|
||||||
set firewall.@rule[-1].proto=tcp
|
|
||||||
set firewall.@rule[-1].dest_port=80
|
|
||||||
set firewall.@rule[-1].target=ACCEPT
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# allow LuCI access with SSL from yggdrasil zone, needs to be explicitly enabled
|
|
||||||
uci -q batch <<-EOF >/dev/null
|
|
||||||
add firewall rule
|
|
||||||
set firewall.@rule[-1].enabled=0
|
|
||||||
set firewall.@rule[-1].name='Allow-HTTPS-yggdrasil'
|
|
||||||
set firewall.@rule[-1].src=yggdrasil
|
|
||||||
set firewall.@rule[-1].proto=tcp
|
|
||||||
set firewall.@rule[-1].dest_port=443
|
|
||||||
set firewall.@rule[-1].target=ACCEPT
|
|
||||||
EOF
|
|
||||||
|
|
||||||
uci commit firewall
|
|
||||||
uci commit network
|
|
||||||
|
|
||||||
else
|
|
||||||
:
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
|
@ -1,33 +0,0 @@
|
||||||
#!/bin/sh /etc/rc.common
|
|
||||||
|
|
||||||
START=90
|
|
||||||
STOP=85
|
|
||||||
|
|
||||||
USE_PROCD=1
|
|
||||||
BIN_FILE="/usr/sbin/yggdrasil"
|
|
||||||
CONFIG_FILE="/tmp/yggdrasil.conf"
|
|
||||||
DAEMON_OPTS="-useconffile $CONFIG_FILE"
|
|
||||||
|
|
||||||
start_service()
|
|
||||||
{
|
|
||||||
[ -f /etc/uci-defaults/yggdrasil ] && ( . /etc/uci-defaults/yggdrasil )
|
|
||||||
|
|
||||||
/usr/sbin/ygguci get | $BIN_FILE -useconf -normaliseconf -json > $CONFIG_FILE
|
|
||||||
|
|
||||||
procd_open_instance
|
|
||||||
procd_set_param respawn
|
|
||||||
procd_set_param command $BIN_FILE $DAEMON_OPTS
|
|
||||||
procd_set_param stdout 1
|
|
||||||
procd_set_param stderr 1
|
|
||||||
procd_close_instance
|
|
||||||
}
|
|
||||||
|
|
||||||
reload_service()
|
|
||||||
{
|
|
||||||
restart
|
|
||||||
}
|
|
||||||
|
|
||||||
service_triggers()
|
|
||||||
{
|
|
||||||
procd_add_reload_trigger yggdrasil
|
|
||||||
}
|
|
205
net/yggdrasil/files/yggdrasil.sh
Executable file
205
net/yggdrasil/files/yggdrasil.sh
Executable file
|
@ -0,0 +1,205 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
|
||||||
|
[ -n "$INCLUDE_ONLY" ] || {
|
||||||
|
. /lib/functions.sh
|
||||||
|
. ../netifd-proto.sh
|
||||||
|
init_proto "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_init_config() {
|
||||||
|
proto_config_add_string "private_key"
|
||||||
|
available=1
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_setup_peer_if_non_interface() {
|
||||||
|
local peer_config="$1"
|
||||||
|
local peer_address
|
||||||
|
local peer_interface
|
||||||
|
config_get peer_address "${peer_config}" "address"
|
||||||
|
config_get peer_interface "${peer_config}" "interface"
|
||||||
|
if [ -z ${peer_interface} ]; then
|
||||||
|
json_add_string "" ${peer_address}
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_dump_peer_interface() {
|
||||||
|
local peer_config="$1"
|
||||||
|
local peer_interface
|
||||||
|
|
||||||
|
config_get peer_interface "${peer_config}" "interface"
|
||||||
|
|
||||||
|
if [ ! -z ${peer_interface} ]; then
|
||||||
|
peer_interfaces="${peer_interfaces}\n${peer_interface}"
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_setup_peer_if_interface() {
|
||||||
|
local peer_config="$1"
|
||||||
|
local peer_address
|
||||||
|
local peer_interface
|
||||||
|
config_get peer_interface "${peer_config}" "interface"
|
||||||
|
if [ "${peer_interface}" = "${peer_interface_filter}" ]; then
|
||||||
|
config_get peer_address "${peer_config}" "address"
|
||||||
|
json_add_string "" ${peer_address}
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_append_to_interface_regex() {
|
||||||
|
if [ -z "${regex}" ]; then
|
||||||
|
regex="$1"
|
||||||
|
else
|
||||||
|
regex="${regex}|$1";
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_setup_multicast_interface() {
|
||||||
|
local interface_config="$1"
|
||||||
|
local beacon
|
||||||
|
local listen
|
||||||
|
local port=0
|
||||||
|
local password
|
||||||
|
local regex=""
|
||||||
|
|
||||||
|
config_get beacon "${interface_config}" "beacon"
|
||||||
|
config_get listen "${interface_config}" "listen"
|
||||||
|
config_get port "${interface_config}" "port"
|
||||||
|
config_get password "${interface_config}" "password"
|
||||||
|
|
||||||
|
json_add_object ""
|
||||||
|
json_add_boolean "Beacon" $beacon
|
||||||
|
json_add_boolean "Listen" $listen
|
||||||
|
if [ ! -z ${port} ]; then
|
||||||
|
json_add_int "Port" $port
|
||||||
|
else
|
||||||
|
json_add_int "Port" 0
|
||||||
|
fi;
|
||||||
|
if [ ! -z ${password} ]; then
|
||||||
|
json_add_string "Password" $password
|
||||||
|
fi;
|
||||||
|
|
||||||
|
config_list_foreach "${interface_config}" interface proto_yggdrasil_append_to_interface_regex
|
||||||
|
|
||||||
|
json_add_string "Regex" "^(${regex})\$"
|
||||||
|
|
||||||
|
json_close_object
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_add_string() {
|
||||||
|
json_add_string "" $1
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_generate_keypair() {
|
||||||
|
json_load "$(yggdrasil -genconf -json)"
|
||||||
|
json_get_vars PrivateKey
|
||||||
|
json_cleanup
|
||||||
|
private_key=$PrivateKey
|
||||||
|
public_key=${PrivateKey:64}
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_setup() {
|
||||||
|
local config="$1"
|
||||||
|
local device="$2"
|
||||||
|
local ygg_dir="/tmp/yggdrasil"
|
||||||
|
local ygg_cfg="${ygg_dir}/${config}.conf"
|
||||||
|
local ygg_sock="unix://${ygg_dir}/${config}.sock"
|
||||||
|
|
||||||
|
|
||||||
|
local private_key
|
||||||
|
local public_key
|
||||||
|
local mtu
|
||||||
|
local listen_addresses
|
||||||
|
local whitelisted_keys
|
||||||
|
local node_info
|
||||||
|
local node_info_privacy
|
||||||
|
|
||||||
|
config_load network
|
||||||
|
config_get private_key "${config}" "private_key"
|
||||||
|
config_get public_key "${config}" "public_key"
|
||||||
|
config_get mtu "${config}" "mtu"
|
||||||
|
config_get node_info "${config}" "node_info"
|
||||||
|
config_get node_info_privacy "${config}" "node_info_privacy"
|
||||||
|
|
||||||
|
if [ -z $private_key ]; then
|
||||||
|
proto_yggdrasil_generate_keypair
|
||||||
|
fi;
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
mkdir -p "${ygg_dir}"
|
||||||
|
|
||||||
|
if [ $private_key = "auto" ]; then
|
||||||
|
proto_yggdrasil_generate_keypair
|
||||||
|
uci -t ${ygg_dir}/.uci.${config} batch <<EOF
|
||||||
|
set network.${config}.private_key='${private_key}'
|
||||||
|
set network.${config}.public_key='${public_key}'
|
||||||
|
EOF
|
||||||
|
uci -t ${ygg_dir}/.uci.${config} commit;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Generate config file
|
||||||
|
json_init
|
||||||
|
json_add_string "IfName" ${config}
|
||||||
|
json_add_string "AdminListen" ${ygg_sock}
|
||||||
|
|
||||||
|
json_add_string "PrivateKey" ${private_key}
|
||||||
|
json_add_string "PublicKey" ${public_key}
|
||||||
|
|
||||||
|
if [ ! -z $mtu ]; then
|
||||||
|
json_add_int "IfMTU" ${mtu}
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if [ ! -z $node_info ]; then
|
||||||
|
json_add_string "NodeInfo" "%%_YGGDRASIL_NODEINFO_TEMPLATE_%%"
|
||||||
|
fi;
|
||||||
|
|
||||||
|
json_add_boolean "NodeInfoPrivacy" ${node_info_privacy}
|
||||||
|
|
||||||
|
# Peers
|
||||||
|
json_add_array "Peers"
|
||||||
|
config_foreach proto_yggdrasil_setup_peer_if_non_interface "yggdrasil_${config}_peer"
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
local peer_interfaces
|
||||||
|
peer_interfaces=""
|
||||||
|
config_foreach proto_yggdrasil_dump_peer_interface "yggdrasil_${config}_peer"
|
||||||
|
peer_interfaces=$(echo -e ${peer_interfaces} | sort | uniq)
|
||||||
|
|
||||||
|
json_add_object "InterfacePeers"
|
||||||
|
for peer_interface_filter in ${peer_interfaces}; do
|
||||||
|
json_add_array "${peer_interface_filter}"
|
||||||
|
config_foreach proto_yggdrasil_setup_peer_if_interface "yggdrasil_${config}_peer"
|
||||||
|
json_close_array
|
||||||
|
done
|
||||||
|
json_close_object
|
||||||
|
|
||||||
|
json_add_array "AllowedPublicKeys"
|
||||||
|
config_list_foreach "$config" allowed_public_key proto_yggdrasil_add_string
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
json_add_array "Listen"
|
||||||
|
config_list_foreach "$config" listen_address proto_yggdrasil_add_string
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
json_add_array "MulticastInterfaces"
|
||||||
|
config_foreach proto_yggdrasil_setup_multicast_interface "yggdrasil_${config}_interface"
|
||||||
|
json_close_array
|
||||||
|
|
||||||
|
json_dump > "${ygg_cfg}.1"
|
||||||
|
awk -v s='"%%_YGGDRASIL_NODEINFO_TEMPLATE_%%"' -v r="${node_info}" '{gsub(s, r)} 1' "${ygg_cfg}.1" > ${ygg_cfg}
|
||||||
|
rm "${ygg_cfg}.1"
|
||||||
|
|
||||||
|
proto_run_command "$config" /usr/sbin/yggdrasil -useconffile "${ygg_cfg}"
|
||||||
|
proto_init_update "$config" 1
|
||||||
|
proto_add_ipv6_address "$(yggdrasil -useconffile "${ygg_cfg}" -address)" "7"
|
||||||
|
proto_add_ipv6_prefix "$(yggdrasil -useconffile "${ygg_cfg}" -subnet)"
|
||||||
|
proto_send_update "$config"
|
||||||
|
}
|
||||||
|
|
||||||
|
proto_yggdrasil_teardown() {
|
||||||
|
local interface="$1"
|
||||||
|
proto_kill_command "$interface"
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -n "$INCLUDE_ONLY" ] || {
|
||||||
|
add_protocol yggdrasil
|
||||||
|
}
|
|
@ -1,155 +0,0 @@
|
||||||
#!/usr/bin/env lua
|
|
||||||
|
|
||||||
dkjson = require("dkjson")
|
|
||||||
uci = require("uci")
|
|
||||||
|
|
||||||
UCI = {}
|
|
||||||
|
|
||||||
--- Return the configuration defaults as a table suitable for JSON output
|
|
||||||
--
|
|
||||||
-- Mostly taken from yggdrasil -genconf -json
|
|
||||||
-- @return table with configuration defaults
|
|
||||||
function UCI.defaults()
|
|
||||||
return {
|
|
||||||
AdminListen = "unix:///var/run/yggdrasil.sock", IfName = "ygg0",
|
|
||||||
NodeInfoPrivacy = false,
|
|
||||||
IfMTU = 65535,
|
|
||||||
|
|
||||||
Peers = { }, Listen = { }, MulticastInterfaces = { }, AllowedPublicKeys = { },
|
|
||||||
InterfacePeers = setmetatable({ }, {__jsontype = "object"}),
|
|
||||||
NodeInfo = setmetatable({ }, {__jsontype = "object"})
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Return the yggdrasil configuration as a table suitable for JSON output
|
|
||||||
--
|
|
||||||
-- @return table with yggdrasil configuration
|
|
||||||
function UCI.get()
|
|
||||||
local obj = UCI.defaults()
|
|
||||||
|
|
||||||
local cursor = uci.cursor()
|
|
||||||
local config = cursor:get_all("yggdrasil", "yggdrasil")
|
|
||||||
if not config then return obj end
|
|
||||||
|
|
||||||
obj.PublicKey = config.PublicKey
|
|
||||||
obj.PrivateKey = config.PrivateKey
|
|
||||||
obj.AdminListen = config.AdminListen or obj.AdminListen
|
|
||||||
obj.IfName = config.IfName or obj.IfName
|
|
||||||
obj.NodeInfo = dkjson.decode(config.NodeInfo) or obj.NodeInfo
|
|
||||||
for _, v in pairs({ "NodeInfoPrivacy" }) do
|
|
||||||
if config[v] ~= nil then obj[v] = to_bool(config[v]) end
|
|
||||||
end
|
|
||||||
if config["IfMTU"] ~= nil then obj["IfMTU"] = tonumber(config["IfMTU"]) end
|
|
||||||
|
|
||||||
cursor:foreach("yggdrasil", "peer", function (s)
|
|
||||||
table.insert(obj.Peers, s.uri)
|
|
||||||
end)
|
|
||||||
cursor:foreach("yggdrasil", "listen_address", function (s)
|
|
||||||
table.insert(obj.Listen, s.uri)
|
|
||||||
end)
|
|
||||||
cursor:foreach("yggdrasil", "multicast_interface", function (s)
|
|
||||||
table.insert(obj.MulticastInterfaces, {
|
|
||||||
Beacon = to_bool(s.beacon), Listen = to_bool(s.listen),
|
|
||||||
Port = tonumber(s.port), Regex = s.regex
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
cursor:foreach("yggdrasil", "allowed_public_key", function (s)
|
|
||||||
table.insert(obj.AllowedPublicKeys, s.key)
|
|
||||||
end)
|
|
||||||
|
|
||||||
cursor:foreach("yggdrasil", "interface_peer", function (s)
|
|
||||||
if obj.InterfacePeers[s.interface] == nil then
|
|
||||||
obj.InterfacePeers[s.interface] = {}
|
|
||||||
end
|
|
||||||
table.insert(obj.InterfacePeers[s["interface"]], s.uri)
|
|
||||||
end)
|
|
||||||
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Parse and save updated configuration from JSON input
|
|
||||||
--
|
|
||||||
-- Transforms general settings into UCI sections, and replaces the UCI config's
|
|
||||||
-- contents with them.
|
|
||||||
-- @param table JSON input
|
|
||||||
-- @return Boolean whether saving succeeded
|
|
||||||
function UCI.set(obj)
|
|
||||||
local cursor = uci.cursor()
|
|
||||||
|
|
||||||
for i, section in pairs(cursor:get_all("yggdrasil")) do
|
|
||||||
cursor:delete("yggdrasil", section[".name"])
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "yggdrasil")
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "PublicKey", obj.PublicKey)
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "PrivateKey", obj.PrivateKey)
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "AdminListen", obj.AdminListen)
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "IfName", obj.IfName)
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "NodeInfoPrivacy", to_int(obj.NodeInfoPrivacy))
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "NodeInfo", dkjson.encode(obj.NodeInfo))
|
|
||||||
cursor:set("yggdrasil", "yggdrasil", "IfMTU", obj.IfMTU)
|
|
||||||
|
|
||||||
set_values(cursor, "peer", "uri", obj.Peers)
|
|
||||||
set_values(cursor, "listen_address", "uri", obj.Listen)
|
|
||||||
|
|
||||||
for _, interface in pairs(obj.MulticastInterfaces) do
|
|
||||||
local name = cursor:add("yggdrasil", "multicast_interface")
|
|
||||||
cursor:set("yggdrasil", name, "beacon", to_int(interface.Beacon))
|
|
||||||
cursor:set("yggdrasil", name, "listen", to_int(interface.Listen))
|
|
||||||
cursor:set("yggdrasil", name, "port", interface.Port)
|
|
||||||
cursor:set("yggdrasil", name, "regex", interface.Regex)
|
|
||||||
end
|
|
||||||
|
|
||||||
set_values(cursor, "allowed_public_key", "key", obj.AllowedPublicKeys)
|
|
||||||
|
|
||||||
for interface, peers in pairs(obj.InterfacePeers) do
|
|
||||||
for _, v in pairs(peers) do
|
|
||||||
local name = cursor:add("yggdrasil", "interface_peer")
|
|
||||||
cursor:set("yggdrasil", name, "interface", interface)
|
|
||||||
cursor:set("yggdrasil", name, "uri", v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return cursor:commit("yggdrasil")
|
|
||||||
end
|
|
||||||
|
|
||||||
function set_values(cursor, section_name, parameter, values)
|
|
||||||
if values == nil then return false end
|
|
||||||
|
|
||||||
for k, v in pairs(values) do
|
|
||||||
local name = cursor:add("yggdrasil", section_name)
|
|
||||||
cursor:set("yggdrasil", name, parameter, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function to_int(bool) return bool and '1' or '0' end
|
|
||||||
|
|
||||||
function to_bool(int) return int ~= '0' end
|
|
||||||
|
|
||||||
function help()
|
|
||||||
print("JSON interface to /etc/config/yggdrasil\n\nExamples: \
|
|
||||||
ygguci get > /tmp/etc/yggdrasil.conf \
|
|
||||||
cat /tmp/etc/yggdrasil.conf | ygguci set \
|
|
||||||
uci changes \
|
|
||||||
ygguci get | yggdrasil -useconf")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- main
|
|
||||||
|
|
||||||
if arg[1] == "get" then
|
|
||||||
local json = dkjson.encode(UCI.get(), { indent = true })
|
|
||||||
print(json)
|
|
||||||
elseif arg[1] == "set" then
|
|
||||||
local json = io.stdin:read("*a")
|
|
||||||
local obj, pos, err = dkjson.decode(json, 1, nil)
|
|
||||||
|
|
||||||
if obj then
|
|
||||||
UCI.set(obj)
|
|
||||||
else
|
|
||||||
print("dkjson: " .. err)
|
|
||||||
os.exit(1)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
help()
|
|
||||||
end
|
|
Loading…
Reference in a new issue