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>
301 lines
7.7 KiB
Bash
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
|
|
}
|
|
|