blob: af3452583224c9c4d9dcc7643102ca1457d16f18 (
plain) (
tree)
|
|
#!/bin/sh
WG=/usr/bin/wg
if [ ! -x "$WG" ]; then
logger -t "wgconfd" "error: missing wgconfd (${WG})"
exit 1
fi
CURL=/usr/bin/curl
if [ ! -x "$CURL" ]; then
logger -t "wgconfd" "error: missing curl (${CURL})"
exit 1
fi
WGCONFD=/usr/bin/wgconfd
if [ ! -x "$WGCONFD" ]; then
logger -t "wgconfd" "error: missing wgconfd (${WGCONFD})"
exit 1
fi
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. ../netifd-proto.sh
init_proto "$@"
}
proto_wgconfd_init_config() {
proto_config_add_array 'ipaddr:ipaddr'
proto_config_add_array 'ip6addr:ip6addr'
proto_config_add_int 'mtu'
proto_config_add_string 'private_key'
proto_config_add_int 'listen_port'
proto_config_add_string 'fwmark'
proto_config_add_int 'refresh_sec'
proto_config_add_int 'min_keepalive'
proto_config_add_int 'max_keepalive'
available=1
}
proto_wgconfd_setup__print() {
local i
for i; do
# TODO: escape
echo -n "$i "
done
}
proto_wgconfd_setup__source() {
local name val
config_get name "$1" name
[ -z "$name" ] && return
config_get val "$1" url
[ -z "$val" ] && return
proto_wgconfd_setup__print source "$name" "$val"
config_get val "$1" psk
[ -n "$val" ] && proto_wgconfd_setup__print psk "$val"
config_get_bool val "$1" required 0
[ "$val" -eq 1 ] && proto_wgconfd_setup__print required
config_get_bool val "$1" allow_road_warriors 1
[ "$val" -eq 0 ] && proto_wgconfd_setup__print deny_road_warriors
config_list_foreach "$1" ipv4 proto_wgconfd_setup__source_route ipv4 32
config_list_foreach "$1" ipv6 proto_wgconfd_setup__source_route ipv6 128
}
proto_wgconfd_setup__source_route() {
local p="$2"
local maxlen="$3"
local route=1
set -- $1
local r="$1"
shift 1
local i
for i; do case "$i" in
no-route)
route=0
;;
*)
true
;;
esac; done
proto_wgconfd_setup__print "$p" "$r"
if [ "$route" -eq 1 ]; then
case "$r" in
'')
true
;;
*/*)
echo "${p}_route ${r%/*} ${r##*/}" >> "$dir/update"
;;
*)
echo "${p}_route $r $maxlen" >> "$dir/update"
;;
esac
fi
}
proto_wgconfd_setup__peer() {
local val
config_get val "$1" key
[ -z "$val" ] && return
proto_wgconfd_setup__print public_key "$val"
config_get val "$1" endpoint
[ -n "$val" ] && proto_wgconfd_setup__print endpoint "$val"
config_get val "$1" psk
[ -n "$val" ] && proto_wgconfd_setup__print psk "$val"
config_get val "$1" keepalive
[ -n "$val" ] && proto_wgconfd_setup__print keepalive "$val"
config_get val "$1" source
[ -n "$val" ] && proto_wgconfd_setup__print source "$val"
}
proto_wgconfd__echo_addr() {
case "$1" in
'')
true
;;
*/*)
echo "${3}_address ${1%/*} ${1##*/}" >> "$dir/update"
;;
*)
echo "${3}_address $1 $4" >> "$dir/update"
;;
esac
}
proto_wgconfd_setup() {
local interface="$1" ifname="$2" i r
if [ -z "$ifname" ]; then
ifname="$interface"
fi
local mtu
local private_key listen_port fwmark
local refresh_sec min_keepalive max_keepalive
json_get_vars mtu private_key listen_port fwmark refresh_sec min_keepalive max_keepalive
if [ -z "$private_key" ]; then
proto_notify_error "$interface" NO_PRIVATE_KEY
proto_block_restart "$interface"
exit
fi
[ -n "$fwmark" ] && fwmark="fwmark $fwmark"
dir="/tmp/wgconfd/$interface"
if [ -d "$dir" ]; then
rm -rf "$dir"
fi
mkdir -p /tmp/wgconfd
if ! mkdir -m 0700 "$dir" || ! mkdir "$dir/cache" || ! echo "$private_key" > "$dir/private" || ! true > "$dir/update" ; then
proto_notify_error "$interface" FS_ERROR
return 1
fi
json_for_each_item proto_wgconfd__echo_addr ipaddr ipv4 32
json_for_each_item proto_wgconfd__echo_addr ip6addr ipv6 128
wgconfd_command="$(
proto_wgconfd_setup__print "$WGCONFD" --cmdline "$ifname"
config_load network
config_foreach proto_wgconfd_setup__source wgconfd_source_"$interface"
config_foreach proto_wgconfd_setup__peer wgconfd_peer_"$interface"
)"
ip link del dev "$ifname" 2>/dev/null
if ! ip link add dev "$ifname" mtu "${mtu:-1420}" type wireguard; then
proto_notify_error "$interface" IFACE_ERROR
exit
fi
"$WG" set "$ifname" private-key "$dir/private" listen-port "${listen_port:-656}" $fwmark
r="$?"
rm -f "$dir/private"
if [ "$r" != 0 ]; then
ip link del dev "$ifname" 2>/dev/null
proto_notify_error "$interface" WG_ERROR
exit
fi
proto_init_update "$ifname" 1 0
proto_set_keep 0
while read i r; do
proto_add_"$i" $r
done < "$dir/update"
# rm -f "$dir/update"
proto_send_update "$interface"
proto_export "WG=$WG"
proto_export "CURL=$CURL"
proto_export "RUNTIME_DIRECTORY=$dir"
proto_export "CACHE_DIRECTORY=$dir/cache"
proto_run_command "$interface" $wgconfd_command
}
proto_wgconfd_teardown() {
local interface="$1" ifname="$2" i r
if [ -z "$ifname" ]; then
ifname="$interface"
fi
proto_kill_command "$interface"
ip link del dev "$ifname" 2>/dev/null
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol wgconfd
}
|