Subject: [alpine-devel] Modified: Multiple VPN Tunnels

From: Steve Fink <[email-masked]>
Date: Sat, 8 Jan 2011 07:37:02 -0700 (MST)

Natanael, 

I have made changes to the /etc/init.d/openvpn script. I believe we have now covered everything. 

In the part where the script locates the symlinks I wanted to do a "ls -l|awk 'print{$5}'|grep -c 10" but the BusyBox version of ls does not support showing the file type. So I had to come up with an alternate method which isn't necessarily the best way I would have liked to do it but it works. 

If someone has just the file openvpn.conf or client.conf or whatever.conf it starts that file through the new method. 

If there are symlinks or multiple openvpn.whatever in /etc/init.d then they are located and launched with the Gentoo method. 

If the only symlink being started in the default runlevel is openvpn.client or openvpn.whatever it works too. 

If someone does not have a .conf file to match their symlinks and tries to start all openvpn init scripts there is an error message saying the .conf file does not exist for whatever their symlink is. 

Because we're now using the directory /var/run/openvpn for both we only require one stop method. 

I also put the before netmount back in there. 

Let me know what you think. 

Best, 

Steve 

#!/sbin/runscript 

# OpenVPN start/stop script 
# 
# Adapted to Gentoo by James Yonan 
# Modified by Steve Fink to support /etc/conf.d/openvpn 
# and to support multiple .conf files or Gentoo style symlinks 
# 
# - Starts an OpenVPN process for each .conf file in $CONFDIR 
# 
# - If /etc/openvpn/xxx.start exists for a xxx.conf file then it executes 
# it before starting OpenVPN (useful for doing openvpn --mktun...). 
# 
# - If /etc/openvpn/xxx.stop exists for a xxx.conf file then it executes 
# it after stopping OpenVPN (useful for doing openvpn --rmtun...). 
# 

# OpenRC options 
opts="start stop restart" 

depend() { 
need net 
use dns 
after sshd 
before netmount 
} 

PIDDIR=/var/run/openvpn 
# Default location of openvpn 
DEF_OPENVPN=/usr/sbin/openvpn 
# Default conf directory 
DEF_CONFDIR=/etc/openvpn 

#Determine whether it's symlinked or not. 
SMLNK="1" 
if [ `ls -l /etc/init.d/openvpn*|grep -c openvpn` -eq 1 ]; then 
SMLNK="0" 
else 
# Set variables for symlinked 
VPN="${SVCNAME#*.}" 
if [ -n "${VPN}" ] && [ "${SVCNAME}" != "openvpn" ]; then 
VPNPID="${PIDDIR}/${VPN}.pid" 
else 
VPNPID="${PIDDIR}/${SVCNAME}.pid" 
fi 
VPNCONF="${CONFDIR}/${VPN}.conf" 
fi 

chkconfd() { 
if [ -z $OPENVPN ]; then 
OPENVPN=$DEF_OPENVPN 
einfo "No path to OpenVPN defined in /etc/conf.d/openvpn using default $OPENVPN." 
fi 
if [ -z $CONFDIR ]; then 
CONFDIR=$DEF_CONFDIR 
einfo "No config file directory defined in /etc/conf.d/openvpn using default $CONFDIR." 
fi 

} 

chktundev() { 
if [ ! -e /dev/net/tun ]; then 
if ! modprobe tun ; then 
eerror "TUN/TAP module unable to load into kernel" 
return 1 
fi 
fi 
if [ -h /dev/net/tun ] && [ -c /dev/misc/net/tun ]; then 
ebegin "Detected broken /dev/net/tun symlink, fixing..." 
rm -f /dev/net/tun 
ln -s /dev/misc/net/tun /dev/net/tun 
eend $? 
fi 
} 

start() { 
chkconfd 
chktundev || return 1 
ebegin "Starting OpenVPN" 

# Load the TUN/TAP module 
/sbin/modprobe tun >/dev/null 2>&1 

if [ ! -d $PIDDIR ]; then 
mkdir $PIDDIR 
fi 

if [ "$SMLNK" = "1" ]; then 
# Start Gentoo symlinked 
ebegin "Starting VPN ${SVCNAME}" 

chktundev || return 1 
if [ ! -e "${VPNCONF}" ]; then 
eend 1 "${VPNCONF} does not exist" 
return 1 
fi 
local args="" 
# If the config file does not specify the cd option, we do 
# But if we specify it, we override the config option which we do not want 
if ! grep -q "^[ \t]*cd[ \t].*" "${VPNCONF}" ; then 
args="${args} --cd ${CONFDIR}" 
fi 
start-stop-daemon --start --exec /usr/sbin/openvpn --pidfile "${VPNPID}" \ 
-- --config "${VPNCONF}" --writepid "${VPNPID}" --daemon ${args} 
eend $? "Check your logs to see why startup failed" 
else 
cd $CONFDIR 

# Start every .conf file in $CONFDIR and run .start if available 
local errors=0 
local successes=0 
local retstatus=0 
for c in `/bin/ls *.conf 2>/dev/null`; do 
VPN=${c%%.conf} 
ebegin "Starting VPN: $VPN" 
if [ -f "$VPN.start" ]; then 
. $VPN.start 
fi 
rm -f $PIDDIR/$VPN.pid 
$OPENVPN --daemon OpenVPN-$VPN --writepid $PIDDIR/$VPN.pid --config $CONFDIR/$c --cd $CONFDIR 
result=$? 
if [ $result = 0 ]; then 
successes=1 
else 
errors=1 
FAILED="$FAILED $VPN" 
fi 
eend $result 
done 

# Decide status based on errors/successes. 
# If at least one tunnel succeeded, we return success. 
# If some tunnels succeeded and some failed, we return success but give a warning. 
if [ $successes = 1 ]; then 
if [ $errors = 1 ]; then 
ewarn "The VPN$FAILED failed to start" 
fi 
else 
retstatus=1 
if [ $errors = 0 ]; then 
ewarn "Note: No OpenVPN configuration files were found in $CONFDIR" 
fi 
fi 
eend $retstatus "Error starting OpenVPN" 
fi 
} 

stop() { 
ebegin "Stopping OpenVPN" 
if [ ! -d $PIDDIR ]; then 
ewarn "The pid directory $PIDDIR does not exist" 
eend 1 "Error stopping OpenVPN" 
else 
for PIDF in `find $PIDDIR -name '*.pid' 2>/dev/null`; do 
if [ -s $PIDF ]; then 
VPN=${PIDF%%.pid} 
VPN=${VPN##$PIDDIR/} 
einfo "Stopping VPN: $VPN ..." 
kill `cat $PIDF` >/dev/null 2>&1 
if [ -f "${CONFDIR}/${VPN}.stop" ]; then 
. ${CONFDIR}/${VPN}.stop 
fi 
eend $? 
rm -rf $PIDF >/dev/null 2>&1 
if [ `ls -A "$PIDDIR"|wc -w` = 0 ]; then 
rm -rf "${PIDDIR}" 
fi 
fi 
done 
eend 0 
fi 
}