]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Enhance contrib/pull-resolv-conf/client.{up,down} scripts
authorDavide Brini <dave_br@gmx.com>
Mon, 19 Apr 2010 20:41:42 +0000 (22:41 +0200)
committerDavid Sommerseth <dazo@users.sourceforge.net>
Thu, 21 Oct 2010 09:37:03 +0000 (11:37 +0200)
Patch arrived from Davide Brini:

- No more bashisms (AFAICT). Should work with any POSIX-compatible shell
(which means "almost all reasonably recent shells"), though I've only tested
with bash and dash.

- Unnecessary calls to external tools (sed) removed

- Manages multiple DNS and DOMAIN options. Each DNS option becomes a
"nameserver" line in the new resolv.conf (up to a maximum of 3). If there's a
single DOMAIN option, it becomes a "domain" line in resolv.conf; otherwise,
all the domains are listed in a "search" line in resolv.conf (eg "search
foo.com example.net").

- Client.up renames the existing resolv.conf and creates a brand new one;
client.down restores it from the saved copy when the VPN terminates (the usual
rules about running as root apply). This is how Gentoo does that; the old
scripts instead added/removed some lines at the beginning of the file, which
looks a less clean approach to me. The rename approach also dramatically
simplifies and shortens client.down, as you'll see.

- Uses resolvconf if it's available (detected by the presence of
/sbin/resolvconf) rather than writing to resolv.conf directly. Not sure
whether this is a Linux-only thing or other systems use it though.

Script has been smoke tested on Fedora 12 with OpenVPN 2.1.1 without
the resolvconf package , and in addition Debian Lenny with
OpenVPN 2.1_rc11 according to the patch.

Signed-off-by: Davide Brini <dave_br@gmx.com>
Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
Acked-by: David Sommerseth <dazo@users.sourceforge.net>
contrib/pull-resolv-conf/client.down
contrib/pull-resolv-conf/client.up

index 82dff54a7815407df6cdba31b4dafc62760f57d6..2dffeaf4ea523bfc221245abfb38e01408e30e14 100644 (file)
@@ -14,7 +14,6 @@
 # Place this in /etc/openvpn/client.down
 # Then, add the following to your /etc/openvpn/<clientconfig>.conf:
 #   client
-#   pull dhcp-options
 #   up /etc/openvpn/client.up
 #   down /etc/openvpn/client.down
 # Next, "chmod a+x /etc/openvpn/client.down"
@@ -23,8 +22,8 @@
 # Note that this script is best served with the companion "client.up"
 # script.
 
-# Only tested on Gentoo Linux 2005.0 with OpenVPN 2.0
-# It should work with any GNU/Linux with /etc/resolv.conf
+# Tested under Debian lenny with OpenVPN 2.1_rc11
+# It should work with any UNIX with a POSIX sh, /etc/resolv.conf or resolvconf
 
 # This runs with the context of the OpenVPN UID/GID 
 # at the time of execution. This generally means that
 # is to run OpenVPN as root. THIS IS NOT RECOMMENDED. You have
 # been WARNED.
 
-# init variables
-
-i=1
-j=1
-unset fopt
-unset dns
-unset opt
-
-# Convert ENVs to an array
-
-while fopt=foreign_option_$i; [ -n "${!fopt}" ]; do
-{
-       opt[i-1]=${!fopt}
-       case ${opt[i-1]} in
-               *DOMAIN* ) domain=`echo ${opt[i-1]} | \
-                               sed -e 's/dhcp-option DOMAIN //g'` ;;
-               *DNS*    ) dns[j-1]=`echo ${opt[i-1]} | \
-                               sed -e 's/dhcp-option DNS //g'`
-                              let j++ ;;
-       esac
-       let i++
-}
-done
-
-# Now, do the work
-
-if [ -n "${dns[*]}" ]; then
-       for i in "${dns[@]}"; do
-               sed -i -e "/nameserver ${i}/D" /etc/resolv.conf || die
-       done
-fi
-
-if [ -n "${domain}" ]; then
-       sed -i -e "/search ${domain}/D" /etc/resolv.conf || die
+if [ -x /sbin/resolvconf ] ; then
+  /sbin/resolvconf -d "${1}"
+elif [ -e /etc/resolv.conf.ovpnsave ] ; then
+  # cp + rm rather than mv in case it's a symlink
+  cp /etc/resolv.conf.ovpnsave /etc/resolv.conf
+  rm -f /etc/resolv.conf.ovpnsave
 fi
 
-# all done...
 exit 0
index 0eed609d4b8203d538adba0378450444a9f21910..e81bd3a8b419dd973f60f60178d1f7375036e3a2 100644 (file)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 # Copyright (c) 2005-2010 OpenVPN Technologies, Inc.
 # Licensed under the GPL version 2
@@ -14,7 +14,6 @@
 # Place this in /etc/openvpn/client.up
 # Then, add the following to your /etc/openvpn/<clientconfig>.conf:
 #   client
-#   pull dhcp-options
 #   up /etc/openvpn/client.up
 # Next, "chmod a+x /etc/openvpn/client.up"
 
@@ -22,8 +21,8 @@
 # Note that this script is best served with the companion "client.down"
 # script.
 
-# Only tested on Gentoo Linux 2005.0 with OpenVPN 2.0
-# It should work with any GNU/Linux with /etc/resolv.conf
+# Tested under Debian lenny with OpenVPN 2.1_rc11
+# It should work with any UNIX with a POSIX sh, /etc/resolv.conf or resolvconf
 
 # This runs with the context of the OpenVPN UID/GID 
 # at the time of execution. This generally means that
 # init variables
 
 i=1
-j=1
-unset fopt
-unset dns
-unset opt
-
-# Convert ENVs to an array
-
-while fopt=foreign_option_$i; [ -n "${!fopt}" ]; do
-{
-       opt[i-1]=${!fopt}
-       case ${opt[i-1]} in
-               *DOMAIN* ) domain=`echo ${opt[i-1]} | \
-                               sed -e 's/dhcp-option DOMAIN //g'` ;;
-               *DNS*    ) dns[j-1]=`echo ${opt[i-1]} | \
-                               sed -e 's/dhcp-option DNS //g'`
-                              let j++ ;;
+domains=
+fopt=
+ndoms=0
+nns=0
+nl='
+'
+
+# $foreign_option_<n> is something like
+# "dhcp-option DOMAIN example.com" (multiple allowed)
+# or
+# "dhcp-option DNS 10.10.10.10" (multiple allowed)
+
+# each DNS option becomes a "nameserver" option in resolv.con
+# if we get one DOMAIN, that becomes "domain" in resolv.conf
+# if we get multiple DOMAINS, those become "search" lines in resolv.conf
+
+while true; do
+  eval fopt=\$foreign_option_${i}
+  [ -z "${fopt}" ] && break
+
+  case ${fopt} in
+               dhcp-option\ DOMAIN\ *)
+           ndoms=$((ndoms + 1))
+           domains="${domains} ${fopt#dhcp-option DOMAIN }"
+           ;;
+               dhcp-option\ DNS\ *)
+           nns=$((nns + 1))
+           if [ $nns -le 3 ]; then
+             dns="${dns}${dns:+$nl}nameserver ${fopt#dhcp-option DNS }"
+           else
+             printf "%s\n" "Too many nameservers - ignoring after third" >&2
+           fi
+           ;;
+        *)
+           printf "%s\n" "Unknown option \"${fopt}\" - ignored" >&2
+           ;;
        esac
-       let i++
-}
+  i=$((i + 1))
 done
 
-# Now, do the work
-
-if [ -n "${dns[*]}" ]; then
-       for i in "${dns[@]}"; do
-               sed -i -e "1,1 i nameserver ${i}" /etc/resolv.conf || die
-       done
+ds=domain
+if [ $ndoms -gt 1 ]; then
+  ds=search
 fi
 
-if [ -n "${domain}" ]; then
-       sed -i -e "$j,1 i search ${domain}" /etc/resolv.conf || die
+# This is the complete file - "$domains" has a leading space already
+out="# resolv.conf autogenerated by ${0} (${1})${nl}${dns}${nl}${ds}${domains}"
+
+# use resolvconf if it's available
+if [ -x /sbin/resolvconf ] ; then
+  printf "%s\n" "${out}" | /sbin/resolvconf -a "${1}"
+else
+  # Preserve the existing resolv.conf
+  if [ -e /etc/resolv.conf ] ; then
+    cp /etc/resolv.conf /etc/resolv.conf.ovpnsave
+  fi
+  printf "%s\n" "${out}" > /etc/resolv.conf
+  chmod 644 /etc/resolv.conf
 fi
 
-# all done...
 exit 0