openresolv no longer applies any semantics to resolv.conf for
authorRoy Marples <roy@marples.name>
Wed, 1 Oct 2008 15:29:51 +0000 (15:29 +0000)
committerRoy Marples <roy@marples.name>
Wed, 1 Oct 2008 15:29:51 +0000 (15:29 +0000)
making certain domains/nameservers private.
Instead we require explicit marking of being private.
The variables exposed to the helpers have also been changed, so any 3rd party
helpers will need to be updated.
As such the major version is bumped to 2.
Fixes bug #1 :)

Makefile
dnsmasq.in
libc.in
named.in
resolvconf.8.in
resolvconf.in

index 3cb2920921ef97a540d2a2fefca82c39a8f3e079..17eb4124d52ee4c29568a9e8f0680598f0d0f998 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 NAME=          openresolv
-VERSION=       1.9
+VERSION=       2.0
 PKG=           ${NAME}-${VERSION}
 
 INSTALL?=      install
index b26973d34a0fd10533618e42566e4de5f2172fac..5ae8b863c3cde3a9c3637c707a8e4f8304b80ccd 100755 (executable)
@@ -49,8 +49,7 @@
 # to resolv.conf.d/base
 
 # Load our variables from resolvconf
-VARS="$(resolvconf -v)"
-eval "${VARS}"
+eval "$(resolvconf -v)"
 
 PREFIX=@PREFIX@
 DNSMASQRESOLV="${PREFIX}/etc/dnsmasq-resolv.conf"
@@ -65,6 +64,7 @@ NEWRESOLV="${NEWCONF}"
 # whilst changing DNS options around. However, DBUS support is optional
 # so we need to validate a few things first.
 # Check for DBus support in the binary
+
 DBUS=no
 DBUSPID=/var/run/dbus/dbus.pid
 [ -s "${DBUSPID}" ] || DBUSPID=/var/run/dbus.pid
@@ -82,56 +82,35 @@ if [ -s "${DBUSPID}" -a -s ${DNSMASQPID} ]; then
        fi
 fi
 
-uniqify() {
-    local result=
-    while [ -n "$1" ]; do
-               case " ${result} " in
-                       *" $1 "*);;
-                       *) result="${result} $1";;
-               esac
-               shift
-       done
-    echo "${result# *}"
-}
-
-# If we only have domain information then put it in search too
-[ -z "${NEWSEARCH}" -a -z "${NEWNS}" ] && NEWSEARCH="${NEWDOMAIN}"
-
-for N in ${NEWSEARCH}; do
-       case " ${NEWSL} " in
-               *" ${N%,*} "*);;
-               *) NEWSL="${NEWSL} ${N%,*}";;
-       esac
-       case "\n${NEWRESOLV}\n" in
-               *"\nnameserver ${N#*,}\n"*);;
-               *) NEWRESOLV="${NEWRESOLV}nameserver ${N#*,}\n";;
-       esac
-done
-for N in ${NEWNS}; do
+for N in ${NAMESERVERS}; do
        case "\n${NEWRESOLV}\n" in
                *"\nnameserver ${N}\n");;
                *) NEWRESOLV="${NEWRESOLV}nameserver ${N}\n";;
        esac
 done
-[ -n "${NEWSL}" ] && NEWRESOLV="${NEWRESOLV}search${NEWSL}\n"
 
 DBUSDEST=
-for DN in $(uniqify ${NEWDOMAIN}); do
-       if [ "${DBUS}" = "yes" ]; then
-               IP=${DN#*,}
-               SIFS=${IFS-y} OIFS=$IFS
-               IFS=.
-               set -- ${IP}
-               NUM="0x$(printf "%02x" $1 $2 $3 $4)"
-               if [ "${SIFS}" = "y" ]; then
-                       unset IFS
+for D in ${DOMAINS}; do
+       DN="${D%%:*}"
+       NS="${D#*:}"
+       while [ -n "${NS}" ]; do
+               if [ "${DBUS}" = "yes" ]; then
+                       SIFS=${IFS-y} OIFS=$IFS
+                       IFS=.
+                       set -- ${NS%%,*}
+                       NUM="0x$(printf "%02x" $1 $2 $3 $4)"
+                       if [ "${SIFS}" = "y" ]; then
+                               unset IFS
+                       else
+                               IFS=$OIFS
+                       fi
+                       DBUSDEST="${DBUSDEST} uint32:$(printf "%d" ${NUM}) string:${DN}"
                else
-                       IFS=$OIFS
+                       NEWCONF="${NEWCONF}server=/${DN}/${NS%%,*}\n"
                fi
-               DBUSDEST="${DBUSDEST} uint32:$(printf "%d" ${NUM}) string:${DN%,*}"
-       else
-               NEWCONF="${NEWCONF}server=/${DN%,*}/${DN#*,}\n"
-       fi
+               [ "${NS}" = "${NS#*,}" ] && break
+               NS="${NS#*,}"
+       done
 done
 
 RELOAD="no"
diff --git a/libc.in b/libc.in
index 165cbdb64be9a37525f122bf09da50fd7a52ba4d..e25e84d1f9526145ed8e04d05b477ae99c198cca 100755 (executable)
--- a/libc.in
+++ b/libc.in
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+# Load our variables from resolvconf
+eval "$(resolvconf -v)"
+
 RESOLVCONF=/etc/resolv.conf
 PREFIX=@PREFIX@
 SYSCONFDIR=@SYSCONFDIR@
-RESOLVCONFS="$(resolvconf -l)"
 BASE="${SYSCONFDIR}/resolv.conf.d/base"
 
 uniqify()
@@ -70,73 +72,33 @@ key_get_value()
        fi
 }
 
-OUR_NS=
+NEWNS=
+NEWSEARCH=
 if [ -e "${BASE}" ]; then
-       OUR_NS="$(key_get_value "nameserver " "${BASE}")"
-fi
-OUR_NS="$(uniqify \
-       ${OUR_NS} \
-       $(echo "${RESOLVCONFS}" | key_get_value "nameserver "))"
-
-# libc only allows for 3 nameservers
-# truncate after 127 as well
-i=0
-NS=
-LOCALH=false
-for N in ${OUR_NS}; do
-       i=$((${i} + 1))
-       NS="${NS} ${N}"
-       [ "${i}" = "3" ] && break
-       case "${N}" in
-               127.*) LOCALH=true; break;;
-       esac
-done
-
-# This is nasty!
-# If we have a local nameserver then assume they are intelligent enough
-# to be forwarding domain requests to the correct nameserver and not search
-# ones. This means we prefer search then domain, otherwise, we use them in
-# the order given to us.
-OUR_SEARCH=
-if ${LOCALH}; then
-       if [ -e "${BASE}" ]; then
-               OUR_SEARCH="$(key_get_value "search " "${BASE}")"
+       NEWNS="$(key_get_value "nameserver " "${BASE}")"
+       NEWSEARCH="$(key_get_value "search " "${BASE}")"
+       if [ -z "${NEWSEARCH}" ]; then
+               NEWSEARCH="$(key_get_value "domain " "${BASE}")"
        fi
-       RESS="$(echo "${RESOLVCONFS}" | key_get_value "search ")"
-       OUR_SEARCH="${OUR_SEARCH} ${RESS}"
-       if [ -e "${BASE}" ]; then
-               RESD="$(key_get_value "domain " "${BASE}")"
-               OUR_SEARCH="${OUR_SEARCH} ${RESD}"
-       fi
-       RESD="$(echo "${RESOLVCONFS}" | key_get_value "domain ")"
-       OUR_SEARCH="${OUR_SEARCH} ${RESD}"
-else
-       if [ -e "${BASE}" ]; then
-               RESS="$(key_get_value "search " "${BASE}")"
-               RESD="$(key_get_value "domain " "${BASE}")"
-               OUR_SEARCH="${RESS} ${RESD}"
-       fi
-       RESS="$(echo "${RESOLVCONFS}" | key_get_value "search ")"
-       RESD="$(echo "${RESOLVCONFS}" | key_get_value "domain ")"
-       OUR_SEARCH="${OUR_SEARCH} ${RESS} ${RESD}"
 fi
-
-# libc only allows for 6 search domains 
-i=0
-SEARCH=
-for S in $(uniqify ${OUR_SEARCH}); do
-       i=$((${i} + 1))
-       SEARCH="${SEARCH} ${S}"
-       [ "${i}" = "6" ] && break
+for D in ${DOMAINS}; do
+       NEWSEARCH="${NEWSEARCH} ${D%%:*}"
+       NS="${D#*:}"
+       while [ -n "${NS}" ]; do
+               NEWNS="${NEWNS} ${NS%%,*}"
+               [ "${NS}" = "${NS#*,}" ] && break
+               NS="${NS#*,}"
+       done
 done
-[ -n "${SEARCH}" ] && SEARCH="search${SEARCH}"
+NEWSEARCH="$(uniqify ${NEWSEARCH} ${SEARCH})"
+NEWNS="$(uniqify ${NEWNS} ${NAMESERVERS})"
 
 # Hold our new resolv.conf in a variable to save on temporary files
 NEWCONF=""
 [ -e "${SYSCONFDIR}"/resolv.conf.d/head ] \
        && NEWCONF="${NEWCONF}$(cat "${SYSCONFDIR}"/resolv.conf.d/head)\n"
-[ -n "${SEARCH}" ] && NEWCONF="${NEWCONF}${SEARCH}\n"
-for N in ${NS}; do
+[ -n "${NEWSEARCH}" ] && NEWCONF="${NEWCONF}search ${NEWSEARCH}\n"
+for N in ${NEWNS}; do
        NEWCONF="${NEWCONF}nameserver ${N}\n"
 done
 
@@ -145,7 +107,7 @@ OPTS=
 if [ -e "${BASE}" ]; then
        OPTS="$(key_get_value "options " "${BASE}")"
 fi
-OPTS="${OPTS}${OPTS:+ }$(echo ${RESOLVCONFS} | key_get_value "options ")"
+OPTS="${OPTS}${OPTS:+ }$(resolvconf -l | key_get_value "options ")"
 if [ -n "${OPTS}" ]; then
        NEWCONF="${NEWCONF}options"
        for OPT in $(uniqify ${OPTS}); do
index 1b3801b25fdc400e8b0566e62fe8528371ee6b78..0a3f8f197ca6531df1453e2fdf5f4f7583c9afd0 100755 (executable)
--- a/named.in
+++ b/named.in
@@ -48,8 +48,7 @@
 #echo "nameserver 127.0.0.1" > /usr/local/etc/resolvconf/resolv.conf.d/base
 
 # Load our variables from resolvconf
-VARS="$(resolvconf -v)"
-eval "${VARS}"
+eval "$(resolvconf -v)"
 
 # If our dir doesn't exist then don't do anything
 NAMEDB=/etc/namedb
@@ -59,19 +58,10 @@ NAMEDB=/etc/namedb
 NAMEDOPTIONS="${NAMEDB}/resolvconf-options.conf"
 NAMEDZONES="${NAMEDB}/resolvconf-zones.conf"
 
-# If we only have domain information then put it in search too
-[ -z "${NEWSEARCH}" -a -z "${NEWNS}" ] && NEWSEARCH="${NEWDOMAIN}"
-
 NEWOPTIONS="# Generated by resolvconf\n"
 NEWZONES="${NEWOPTIONS}"
 FORWARD=
-for N in ${NEWSEARCH}; do
-       case "${FORWARD}" in
-               *"\n\t${N#*,};"*);;
-               *) FORWARD="${FORWARD}\n\t${N#*,};";;
-       esac
-done
-for N in ${NEWNS}; do
+for N in ${NAMESERVERS}; do
        case "${FORWARD}" in
                *"\n\t${N};"*);;
                *) FORWARD="${FORWARD}\n\t${N};";;
@@ -81,23 +71,17 @@ if [ -n "${FORWARD}" ]; then
        NEWOPTIONS="${NEWOPTIONS}forward first;\nforwarders {${FORWARD}\n};\n"
 fi
 
-LASTDN=
-ZONES=
-for DN in $(printf "%s\n" ${NEWDOMAIN} | sort -u); do
-       case "${LASTDN}" in
-               "${DN%,*}");;
-               *)
-               LASTDN="${DN%,*}"
-               [ -n "${ZONES}" ] && ZONES="${ZONES}\n\t};\n};\n"
-               ZONES="${ZONES}zone \"${LASTDN}\" {\n"
-               ZONES="${ZONES}\ttype forward;\n"
-               ZONES="${ZONES}\tforward first;\n"
-               ZONES="${ZONES}\tforwarders {"
-               ;;
-       esac
-       ZONES="${ZONES}\n\t\t${DN#*,};"
+for D in ${DOMAINS}; do
+       NEWZONES="${NEWZONES}zone \"${D%%:*}\" {\n"
+       NEWZONES="${NEWZONES}\ttype forward;\n\tforward first;\n\tforwarders {\n"
+       NS="${D#*:}"
+       while [ -n "${NS}" ]; do
+               NEWZONES="${NEWZONES}\t\t${NS%%,*};\n"
+               [ "${NS}" = "${NS#*,}" ] && break
+               NS="${NS#*,}"
+       done
+       NEWZONES="${NEWZONES}\t};\n};\n"
 done
-[ -n "${ZONES}" ] && NEWZONES="${NEWZONES}${ZONES}\n\t};\n};\n"
 
 # No point in changing files or reloading bind if the end result has not
 # changed
index c5436ec89e868c4c55ab32c58130ee7463e2310a..b409c1de5f369bc67dd8e79dcbaf47f00c3ac50f 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd September 17, 2008
+.Dd October 01, 2008
 .Dt RESOLVCONF 8 SMM
 .Sh NAME
 .Nm resolvconf
@@ -30,6 +30,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl m Ar metric
+.Op Fl p
 .Fl a Ar interface No < Ns Pa file
 .Nm
 .Op Fl f
@@ -72,28 +73,19 @@ or
 then
 .Nm
 will supply files that the resolver should be configured to include.
-This allows
+.Pp
 .Nm
-to configure the local resolver such that
+can mark an interfaces
 .Pa resolv.conf
-files specifiying a domain only query the listed nameservers when resolving
-for that domain.
-Otherwise the nameservers are treated as global nameservers.
-This in turn means, that you can trivially configure nameservers for say
-VPN domains.
-Example:-
-.Bd -literal -offset indent
-# resolv.conf from bge0
-search foo.com
-nameserver 1.2.3.4
-
-# resolv.conf from tap0
-domain bar.org
-nameserver 5.6.7.8
-.Ed
-.Pp
-In this instance, nameserver 5.6.7.8 will only handle requests for bar.org
-and nameserver 1.2.3.4 will handle everything else.
+as private.
+This means that any queries for a host in the private domain or search
+paths are only send to the nameservers in the same
+.Pa resolv.conf .
+If only private
+.Pa resolv.conf
+files exist then
+.Nm installs them as global ones too.
+This only works when a local resolver other than libc is installed.
 Doing this, you would probably want
 .Nm
 to always configure
@@ -136,6 +128,10 @@ is specified then we list the files for the interfaces that match it.
 Set the metric of the interface when adding it, default of 0.
 Lower metrics take precedence.
 This affects the default order of interfaces when listed.
+.It Fl p
+Marks the interface
+.Pa resolv.conf
+as private.
 .It Fl u
 Force
 .Nm
@@ -158,7 +154,7 @@ Normally this is something like
 We have this command, so the helpers don't have to know too much about the
 operating system on the host.
 .It Fl v
-Echo variables NEWDOMAIN, NEWSEARCH and NEWNS so that the helper can configure
+Echo variables DOMAINS, SEARCH and NAMESERVERS so that the helper can configure
 the resolver easily.
 .El
 .Sh ENVIRONMENT
@@ -169,6 +165,10 @@ If the
 option is not present then we use
 .Va IF_METRIC
 for the metric.
+.It Va IF_PRIVATE
+Marks the interface
+.Pa resolv.conf
+as private.
 .El
 .Sh FILES
 .Bl -ohang
@@ -184,6 +184,8 @@ Directory of helper scripts which are run after the libc helper script is run.
 .It Pa @SYSCONFDIR@/interface-order
 Determines the order in which nameserver information records are processed
 by resolvconf -l.
+.It Pa @SYSCONFDIR@/private-interfaces
+A list of interfaces who should be marked as private by default.
 .It Pa @SYSCONFDIR@/resolv.conf.d/base
 Contains basic resolver information which is included in
 .Pa /etc/resolv.conf
index f38b354a3afab9a2a4885ba0f35ba83fe408e282..d8f69085365be1aafbfb1ba3c7923657d8f33fdc 100755 (executable)
@@ -29,6 +29,7 @@ SYSCONFDIR=@SYSCONFDIR@
 VARDIR=@VARBASE@/run/resolvconf
 IFACEDIR="${VARDIR}/interfaces"
 METRICDIR="${VARDIR}/metrics"
+PRIVATEDIR="${VARDIR}/private"
 
 error_exit()
 {
@@ -47,6 +48,7 @@ usage()
          -a \$INTERFACE    Add DNS information to the specified interface
                           (DNS supplied via stdin in resolv.conf format)
          -m metric        Give the added DNS information a metric
+         -p               Mark the interface as private
          -d \$INTERFACE    Delete DNS information from the specified interface
          -f               Ignore non existant interfaces
          -u               Run updates from our current DNS information
@@ -79,18 +81,48 @@ echo_resolv()
        echo
 }
 
+# Return 1 if an interface is private
+# ie, we only use the listed nameservers for the domain/search path
+is_private()
+{
+       [ -e "${PRIVATEDIR}/$1" ] && return 0
+       if [ -e "${SYSCONFDIR}/private-interfaces" ]; then
+               for IFACE in $(cat "${SYSCONFDIR}/private-interfaces"); do
+                       [ "${IFACE}" = "$1" ] && return 0
+               done
+       else
+               cd "${IFACEDIR}"
+               for IFACE in tap[0-9]* tun[0-9]* vpn vpn[0-9]*; do
+                       [ -e "${IFACE}" ] || continue
+                       [ "${IFACE}" = "$1" ] && return 0
+               done
+       fi
+       return 1
+}
+
 # Parse resolv.conf's and make variables
 # for domain name servers, search name servers and global nameservers
 parse_resolv()
 {
-       local LINE= NS= DOMAIN= SEARCH= N= NEWDOMAIN= NEWSEARCH= NEWNS=
+       local LINE= NS= DOMAINS= SEARCH= D= N= NEWNS=
+       local NEW=true PRIVATE=false
 
-       echo "NEWDOMAIN="
-       echo "NEWSEARCH="
-       echo "NEWNS="
+       echo "DOMAINS="
+       echo "SEARCH="
+       echo "NAMESERVERS="
 
        while read LINE; do
                case "${LINE}" in
+               "# resolv.conf from "*)
+                       if ${NEW}; then
+                               if is_private "${LINE#\# resolv.conf from *}"; then
+                                       PRIVATE=true
+                               else
+                                       PRIVATE=false
+                               fi
+                               NEW=false
+                       fi
+                       ;;
                "nameserver "*)
                        case "${LINE#* }" in
                        127.*) continue;;
@@ -98,28 +130,31 @@ parse_resolv()
                        NS="${NS}${LINE#* } "
                        ;;
                "domain "*)
-                       [ -z "${SEARCH}" ] && DOMAIN="${LINE#* }"
+                       SEARCH="${LINE#* }"
                        ;;
                "search "*)
                        SEARCH="${LINE#* }"
-                       DOMAIN=
                        ;;
                *)
                        if [ -z "${LINE}" ]; then
-                               for N in ${NS}; do
-                                       if [ -n "${DOMAIN}" ]; then
-                                               echo "NEWDOMAIN=\"\${NEWDOMAIN} ${DOMAIN},${N}\""
-                                       elif [ -n "${SEARCH}" ]; then
-                                               for S in ${SEARCH}; do
-                                                       echo "NEWSEARCH=\"\${NEWSEARCH} ${S},${N}\""
-                                               done
-                                       else
-                                               echo "NEWNS=\"\${NEWNS} ${N}\""
-                                       fi
-                               done
+                               if [ -n "${NS}" -a -n "${SEARCH}" ] && ${PRIVATE}; then
+                                       unset NEWNS
+                                       for N in ${NS}; do
+                                               NEWNS="${NEWNS}${NEWNS:+,}${N}"
+                                       done
+                                       DOMAINS=
+                                       for D in ${SEARCH}; do
+                                               DOMAINS="${DOMAINS}${DOMAINS:+ }${D}:${NEWNS}"
+                                       done
+                                       echo "DOMAINS=\"\${DOMAINS} ${DOMAINS}\""
+                               else
+                                       echo "NAMESERVERS=\"\${NAMESERVERS} ${NS}\""
+                               fi
+                               echo "SEARCH=\"\${SEARCH} ${SEARCH}\""
                                NS=
-                               DOMAIN=
                                SEARCH=
+                               PRIVATE=false
+                               NEW=true
                        fi
                        ;;
                esac
@@ -140,11 +175,12 @@ uniqify()
 }
 
 FORCE=false
-while getopts a:d:fhilm:s:uv OPT; do
+while getopts a:d:fhilm:ps:uv OPT; do
        case "${OPT}" in
        f) FORCE=true;;
        h) usage;;
        m) IF_METRIC="${OPTARG}";;
+       p) IF_PRIVATE=1;;
        s) CMD=s; SERVICE="${OPTARG}";;
        '?') ;;
        *) CMD="${OPT}"; IFACE="${OPTARG}";;
@@ -247,37 +283,25 @@ fi
 if [ "${CMD}" = "v" ]; then
        eval "$("${ARGV0}" -l "${IFACE}" | parse_resolv)"
 
-       # Prefer DOMAIN nameservers over SEARCH nameservers
-       # if we are supplied both, but put them in the SEARCH list
-       NEWDOMAIN="$(uniqify ${NEWDOMAIN})"
-       NEWSEARCH="$(uniqify ${NEWSEARCH})"
-       NEWNS="$(uniqify ${NEWNS})"
-       _NEWDOMAIN=
-       _NEWSEARCH=
-       for S in ${NEWSEARCH}; do
-               for DN in ${NEWDOMAIN}; do
-                       if [ "${S%,*}" = "${DN%,*}" ]; then
-                               S="${DN}"
-                               break
-                       fi
-               done
-               _NEWSEARCH="${_NEWSEARCH}${_NEWSEARCH:+ }${S}"
-       done
-       for DN in ${NEWDOMAIN}; do
-               for S in ${_NEWSEARCH}; do
-                       if [ "${S%,*}" = "${DN%,*}" ]; then
-                               DN=
-                               break
-                       fi
+       DOMAINS="$(uniqify ${DOMAINS})"
+       SEARCH="$(uniqify ${SEARCH})"
+       # If we don't have any non private nameservers
+       # then make them all private ones public
+       if [ -z "${NAMESERVERS}" ]; then
+               NAMESERVERS=
+               for D in ${DOMAINS}; do
+                       NS="${D#*:}"
+                       while [ -n "${NS}" ]; do
+                               NAMESERVERS="${NAMESERVERS} ${NS%%,*}"
+                               [ "${NS}" = "${NS#*,}" ] && break
+                               NS="${NS#*,}"
+                       done
                done
-               if [ -n "${DN}" ]; then
-                       _NEWDOMAIN="${_NEWDOMAIN}${_NEWDOMAIN:+ }${DN}"
-               fi
-       done
-
-       echo "NEWDOMAIN='${_NEWDOMAIN}'"
-       echo "NEWSEARCH='${_NEWSEARCH}'"
-       echo "NEWNS='${NEWNS}'"
+       fi
+       NAMESERVERS="$(uniqify ${NAMESERVERS})"
+       echo "DOMAINS='${DOMAINS}'"
+       echo "SEARCH='${SEARCH}'"
+       echo "NAMESERVERS='${NAMESERVERS}'"
        exit 0
 fi
 
@@ -332,7 +356,7 @@ else
                                ${FORCE} && continue
                                error_exit "No resolv.conf for interface ${ARG}"
                        fi
-                       rm -f "${ARG}" "${METRICDIR}/"*" ${ARG}" || exit $?
+                       rm -f "${ARG}" "${METRICDIR}/"*" ${ARG}" "${PRIVATEDIR}/${ARG}" || exit $?
                done
        fi
 fi
@@ -360,6 +384,18 @@ if [ "${CMD}" = "a" ]; then
                IF_METRIC="0${IF_METRIC}"
        done
        echo " " >"${METRICDIR}/${IF_METRIC} ${IFACE}"
+       case "${IF_PRIVATE}" in
+       [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+               if [ ! -d "${PRIVATEDIR}" ]; then
+                       [ -e "${PRIVATEDIR}" ] && rm "${PRIVATEDIR}"
+                       mkdir "${PRIVATEDIR}"
+               fi
+               [ -d "${PRIVATEDIR}" ] && echo " " >"${PRIVATEDIR}/${IFACE}"
+               ;;
+       *)
+               [ -e "${PRIVATEDIR}/${IFACE}" ] && rm -f "${PRIVATEDIR}/${IFACE}"
+               ;;
+       esac
 fi
 
 RETVAL=0