diff options
author | Hristo Venev <hristo@venev.name> | 2019-11-10 13:24:27 +0000 |
---|---|---|
committer | Hristo Venev <hristo@venev.name> | 2019-11-10 13:24:35 +0000 |
commit | 86969f07ca4a76c5b981fec1062cc2280d7f0248 (patch) | |
tree | 99b9dce2982833ce4e9a91689edf3e3b2e56fbe9 | |
parent | d9f3505278b0bcf90ef6bab5ca0c6a9889695938 (diff) |
Add netifd protocol script.
-rwxr-xr-x | dist/netifd/wgconfd.sh | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/dist/netifd/wgconfd.sh b/dist/netifd/wgconfd.sh new file mode 100755 index 0000000..1fa6aba --- /dev/null +++ b/dist/netifd/wgconfd.sh @@ -0,0 +1,213 @@ +#!/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_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" psk + [ -n "$val" ] && proto_wgconfd_setup__print psk "$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 +} |