packages/net/openvpn/files/openvpn.init
Erik Conijn 7735cdfe60 Openvpn: add missing script event options
Maintainer: @mkrkn  @neheb
Compile tested: aarch64, cortex-a53, OpenWRT Master
Run tested: Dynalink DL-WRX36

Description:
[A previous commit](f8a8b71e26) has added more script event options.
However it looked like that commit was not complete as it stops the use of the script events route-up, route-pre-down, and ipchange when those are placed in the openvpn config file.

This PR fixes a regression that makes it problematic to specify certain event options in the OpenVPN configuration file.

Discussion in [this thread](https://forum.openwrt.org/t/openvpn-custom-route-up-script-in-23-05-rc2/167105/13) and [here](https://forum.openwrt.org/t/openvpn-route-up-and-route-pre-down-broken-in-23-05/176568)

Please have a look and consider implementing or make it possible to use all script event options in the openvpn config file in another way.

Pull request has been discussed and improved with the help of @AuthorReflex, see: https://github.com/openwrt/packages/pull/21732

Signed-off-by: Erik Conijn <egc112@msn.com>
2024-01-02 15:27:52 -08:00

301 lines
7.7 KiB
Bash

#!/bin/sh /etc/rc.common
# Copyright (C) 2008-2013 OpenWrt.org
# Copyright (C) 2008 Jo-Philipp Wich
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
START=90
STOP=10
USE_PROCD=1
PROG=/usr/sbin/openvpn
PATH_INSTANCE_DIR="/etc/openvpn"
LIST_SEP="
"
UCI_STARTED=
UCI_DISABLED=
append_param() {
local s="$1"
local v="$2"
case "$v" in
*_*_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;;
*_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;;
*_*) v=${v%%_*}-${v#*_} ;;
esac
echo -n "$v" >> "/var/etc/openvpn-$s.conf"
return 0
}
append_bools() {
local p; local v; local s="$1"; shift
for p in $*; do
config_get_bool v "$s" "$p"
[ "$v" = 1 ] && append_param "$s" "$p" && echo >> "/var/etc/openvpn-$s.conf"
done
}
append_params() {
local p; local v; local s="$1"; shift
for p in $*; do
config_get v "$s" "$p"
IFS="$LIST_SEP"
for v in $v; do
[ "$v" = "frames_only" ] && [ "$p" = "compress" ] && unset v && append_param "$s" "$p" && echo >> "/var/etc/openvpn-$s.conf"
[ -n "$v" ] && [ "$p" != "push" ] && append_param "$s" "$p" && echo " $v" >> "/var/etc/openvpn-$s.conf"
[ -n "$v" ] && [ "$p" = "push" ] && append_param "$s" "$p" && echo " \"$v\"" >> "/var/etc/openvpn-$s.conf"
done
unset IFS
done
}
append_list() {
local p; local v; local s="$1"; shift
list_cb_append() {
v="${v}:$1"
}
for p in $*; do
unset v
config_list_foreach "$s" "$p" list_cb_append
[ -n "$v" ] && append_param "$s" "$p" && echo " ${v:1}" >> "/var/etc/openvpn-$s.conf"
done
}
section_enabled() {
config_get_bool enable "$1" 'enable' 0
config_get_bool enabled "$1" 'enabled' 0
[ $enable -gt 0 ] || [ $enabled -gt 0 ]
}
create_temp_file() {
mkdir -p "$(dirname "$1")"
rm -f "$1"
touch "$1"
chown root "$1"
chmod 0600 "$1"
}
openvpn_get_dev() {
local dev dev_type
local name="$1"
local conf="$2"
# Do override only for configurations with config_file
config_get config_file "$name" config
[ -n "$config_file" ] || return
# Check there is someething to override
config_get dev "$name" dev
config_get dev_type "$name" dev_type
[ -n "$dev" ] || return
# If there is a no dev_type, try to guess it
if [ -z "$dev_type" ]; then
. /lib/functions/openvpn.sh
local odev odev_type
get_openvpn_option "$conf" odev dev
get_openvpn_option "$conf" odev_type dev-type
[ -n "$odev_type" ] || odev_type="$odev"
case "$odev_type" in
tun*) dev_type="tun" ;;
tap*) dev_type="tap" ;;
*) return;;
esac
fi
# Return overrides
echo "--dev-type $dev_type --dev $dev"
}
openvpn_get_credentials() {
local name="$1"
local ret=""
config_get cert_password "$name" cert_password
config_get password "$name" password
config_get username "$name" username
if [ -n "$cert_password" ]; then
create_temp_file /var/run/openvpn.$name.pass
echo "$cert_password" > /var/run/openvpn.$name.pass
ret=" --askpass /var/run/openvpn.$name.pass "
fi
if [ -n "$username" ]; then
create_temp_file /var/run/openvpn.$name.userpass
echo "$username" > /var/run/openvpn.$name.userpass
echo "$password" >> /var/run/openvpn.$name.userpass
ret=" --auth-user-pass /var/run/openvpn.$name.userpass "
fi
# Return overrides
echo "$ret"
}
openvpn_add_instance() {
local name="$1"
local dir="$2"
local conf=$(basename "$3")
local security="$4"
local up="$5"
local down="$6"
local route_up="$7"
local route_pre_down="$8"
local ipchange="$9"
local client=$(grep -qEx "client|tls-client" "$dir/$conf" && echo 1)
procd_open_instance "$name"
procd_set_param command "$PROG" \
--syslog "openvpn($name)" \
--status "/var/run/openvpn.$name.status" \
--cd "$dir" \
--config "$conf" \
--up "/usr/libexec/openvpn-hotplug up $name" \
--down "/usr/libexec/openvpn-hotplug down $name" \
--route-up "/usr/libexec/openvpn-hotplug route-up $name" \
--route-pre-down "/usr/libexec/openvpn-hotplug route-pre-down $name" \
${client:+--ipchange "/usr/libexec/openvpn-hotplug ipchange $name"} \
${up:+--setenv user_up "$up"} \
${down:+--setenv user_down "$down"} \
${route_up:+--setenv user_route_up "$route_up"} \
${route_pre_down:+--setenv user_route_pre_down "$route_pre_down"} \
${client:+${ipchange:+--setenv user_ipchange "$ipchange"}} \
--script-security "${security:-2}" \
$(openvpn_get_dev "$name" "$conf") \
$(openvpn_get_credentials "$name" "$conf")
procd_set_param file "$dir/$conf"
procd_set_param term_timeout 15
procd_set_param respawn
procd_append_param respawn 3600
procd_append_param respawn 5
procd_append_param respawn -1
procd_close_instance
}
start_uci_instance() {
local s="$1"
config_get config "$s" config
config="${config:+$(readlink -f "$config")}"
section_enabled "$s" || {
append UCI_DISABLED "$config" "$LIST_SEP"
return 1
}
local up down route_up route_pre_down ipchange script_security
config_get up "$s" up
config_get down "$s" down
config_get route_up "$s" route_up
config_get route_pre_down "$s" route_pre_down
config_get ipchange "$s" ipchange
config_get script_security "$s" script_security
[ ! -d "/var/run" ] && mkdir -p "/var/run"
if [ ! -z "$config" ]; then
append UCI_STARTED "$config" "$LIST_SEP"
[ -n "$up" ] || get_openvpn_option "$config" up up
[ -n "$down" ] || get_openvpn_option "$config" down down
[ -n "$route_up" ] || get_openvpn_option "$config" route_up route-up
[ -n "$route_pre_down" ] || get_openvpn_option "$config" route_pre_down route-pre-down
[ -n "$ipchange" ] || get_openvpn_option "$config" ipchange ipchange
openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange"
return
fi
create_temp_file "/var/etc/openvpn-$s.conf"
append_bools "$s" $OPENVPN_BOOLS
append_params "$s" $OPENVPN_PARAMS
append_list "$s" $OPENVPN_LIST
openvpn_add_instance "$s" "/var/etc" "openvpn-$s.conf" "$script_security" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange"
}
start_path_instances() {
local path name
for path in ${PATH_INSTANCE_DIR}/*.conf; do
[ -f "$path" ] && {
name="${path##*/}"
name="${name%.conf}"
start_path_instance "$name"
}
done
}
start_path_instance() {
local name="$1"
local path name up down route_up route_pre_down ipchange
path="${PATH_INSTANCE_DIR}/${name}.conf"
# don't start configs again that are already started by uci
if echo "$UCI_STARTED" | grep -qxF "$path"; then
logger -t openvpn "$name.conf already started"
return
fi
# don't start configs which are set to disabled in uci
if echo "$UCI_DISABLED" | grep -qxF "$path"; then
logger -t openvpn "$name.conf is disabled in /etc/config/openvpn"
return
fi
get_openvpn_option "$path" up up || up=""
get_openvpn_option "$path" down down || down=""
get_openvpn_option "$path" route_up route-up || route_up=""
get_openvpn_option "$path" route_pre_down route-pre-down || route_pre_down=""
get_openvpn_option "$path" ipchange ipchange || ipchange=""
openvpn_add_instance "$name" "${path%/*}" "$path" "" "$up" "$down" "$route_up" "$route_pre_down" "$ipchange"
}
start_service() {
local instance="$1"
local instance_found=0
config_cb() {
local type="$1"
local name="$2"
if [ "$type" = "openvpn" ]; then
if [ -n "$instance" -a "$instance" = "$name" ]; then
instance_found=1
fi
fi
}
. /lib/functions/openvpn.sh
. /usr/share/openvpn/openvpn.options
config_load 'openvpn'
if [ -n "$instance" ]; then
if [ "$instance_found" -gt 0 ]; then
start_uci_instance "$instance"
else
start_path_instance "$instance"
fi
else
config_foreach start_uci_instance 'openvpn'
auto="$(uci_get openvpn globals autostart 1)"
if [ "$auto" = "1" ]; then
start_path_instances
else
logger -t openvpn "Autostart for configs in '$PATH_INSTANCE_DIR/*.conf' disabled"
fi
fi
}
service_triggers() {
procd_add_reload_trigger openvpn
}