OpenVPN supports more hooks than just 'up' and 'down'. Especially reacting to 'route-up' and 'route-pre-down' events could be important. When routing table changes, it can make sense to adapt firewall, run some tests or change even more routes. This change passes those events to hotplug, so it is easy to react to them without changing configuration files provided by VPN provider. Signed-off-by: Michal Hrusecky <michal.hrusecky@turris.com>
257 lines
6.2 KiB
Bash
257 lines
6.2 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
|
|
|
|
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="$3"
|
|
local security="$4"
|
|
local up="$5"
|
|
local down="$6"
|
|
|
|
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" \
|
|
--ipchange "/usr/libexec/openvpn-hotplug ipchange $name" \
|
|
${up:+--setenv user_up "$up"} \
|
|
${down:+--setenv user_down "$down"} \
|
|
--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_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 script_security
|
|
config_get up "$s" up
|
|
config_get down "$s" down
|
|
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
|
|
openvpn_add_instance "$s" "${config%/*}" "$config" "$script_security" "$up" "$down"
|
|
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"
|
|
}
|
|
|
|
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
|
|
[ "$instance_found" -gt 0 ] || return
|
|
start_instance "$instance"
|
|
else
|
|
config_foreach start_instance 'openvpn'
|
|
|
|
local path name up down
|
|
for path in /etc/openvpn/*.conf; do
|
|
if [ -f "$path" ]; then
|
|
name="${path##*/}"; name="${name%.conf}"
|
|
|
|
# don't start configs again that are already started by uci
|
|
if echo "$UCI_STARTED" | grep -qxF "$path"; then
|
|
continue
|
|
|
|
# don't start configs which are set to disabled in uci
|
|
elif echo "$UCI_DISABLED" | grep -qxF "$path"; then
|
|
logger -t openvpn "$name.conf is disabled in /etc/config/openvpn"
|
|
continue
|
|
fi
|
|
|
|
get_openvpn_option "$path" up up || up=""
|
|
get_openvpn_option "$path" down down || down=""
|
|
openvpn_add_instance "$name" "${path%/*}" "$path" "" "$up" "$down"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger openvpn
|
|
}
|