ACC SHELL
#!/bin/bash
#
# Exit codes:
# - 0 success
# - 1 on failure
###
unset POSIXLY_CORRECT ; set +o posix # we're using non-posix bash features
test "${DEBUG}" = yes && set -x
# helper functions
failure()
{
test -n "$*" && echo 1>&2 "FAILURE: $*"
}
warning()
{
test -n "$*" && echo 1>&2 "WARNING: $*"
}
message()
{
test -n "$*" && echo 1>&2 "$*"
}
verbose()
{
test "${VERBOSE}" = yes -a -n "$*" && echo 1>&2 "$*"
}
add_to_wordlist() {
local v="${1}"
local l=(${!v}) ; shift
local a w
for a in ${@} ; do
for w in ${l[@]} ; do
[ "x$w" = "x$a" ] && \
continue 2
done
l=(${l[@]} $a)
done
eval "$v='${l[@]}'"
}
try_to_find_original()
{
local filename="$1"
local root_dir="$2"
local original="$filename"
local backups=()
local backup=""
# we use direct/valid backups only
while test -n "$original" -a -r "${root_dir}${original}" ; do
backup=`sed -ne '/^### BEGIN INFO/,/^### END INFO/{
s/^[[:space:]]*[#][[:space:]]*Backup:[[:space:]]*//p
}' "${root_dir}${original}" | \
sed -ne 's/[[:space:]]*$//p' 2>/dev/null`
test -n "$backup" || break
for f in "$original" "$filename" "${backups[@]}" ; do
test "$f" = "$backup" && { original=""; break 2; }
done
if test -r "${root_dir}${backup}" ; then
backups=("${backups[@]}" "$backup")
original="$backup"
else
original=""
fi
done
echo "$original"
test -n "$original"
}
has_networkmanager_info()
{
test -n "$1" -a -f "$1" && grep -qs '^# generated by NetworkManager' "$1" 2>/dev/null
}
has_netconfig_info()
{
test -n "$1" -a -f "$1" && grep -qs '^### .* netconfig' "$1" 2>/dev/null
}
fake_netconfig_md5()
{
src=$1
dir=$2
pfx=$3
md5="${pfx}${dir}${src}"
test -n "$dir" -a -n "$src" -a -r "${pfx}${src}" || return 1
mkdir -p "${md5%/*}" 2>/dev/null || return 2
rm -f "${md5}" 2>/dev/null || return 3
grep -Ev '^#|^[[:space:]]*$' "${pfx}${src}" | md5sum > "${md5}" 2>/dev/null
}
contains_old_variables()
{
test -n "$1" && \
grep -qs "^[[:space:]]*\(\
MODIFY_NAMED_CONF_DYNAMICALLY\|\
MODIFY_RESOLV_CONF_DYNAMICALLY\|\
MODIFY_RESOLV_CONF_STATIC_DNS\|\
DHCLIENT_MODIFY_RESOLV_CONF\|\
DHCLIENT_KEEP_SEARCHLIST\)=" "${1}" 2>/dev/null
}
has_modify_resolvconf_info()
{
test -n "$1" -a -f "$1" && grep -qs '^### BEGIN INFO' "$1" 2>/dev/null
}
remove_modify_resolvconf_info()
{
has_modify_resolvconf_info "$1" && \
sed -e '/^### BEGIN INFO/,/^### END INFO/d;/^[[:space:]]*$/d' -i "$1"
}
delete_modify_resolvconf_backups()
{
local filename=$1
# remove all modify_resolvconf backup files
out=`LC_ALL=POSIX rm -vf "${filename}.saved.by"*`
if test "x$out" != x ; then
message "Deleted following modify_resolvconf backup files:"
message "$out"
fi
}
create_backup()
{
filename=$1
b_suffix=$2
root_dir=$3
test -s "${root_dir}${filename}" && \
cp -p --backup=t "${root_dir}${filename}" "${root_dir}${filename}${b_suffix}" && \
message "Created ${filename}${b_suffix}"
}
create_backup_once()
{
test -f "${3}${1}${2}" || create_backup "$1" "$2" "$3"
}
is_localhost_ip()
{
case $1 in
(127\.*\.*\.*|::1) return 0 ;;
(*) return 1 ;;
esac
}
################################################################################
SCRIPTNAME=${0##*/}
# act bellow of this "root" directory
test "${ROOT}" = "/" && unset ROOT
r=${ROOT}
# source sysconfig_remove_and_set()
test -f "$ROOT/etc/sysconfig/network/scripts/functions.rpm-utils" && \
. "$ROOT/etc/sysconfig/network/scripts/functions.rpm-utils" || exit 1
# the files modified by modify_resolvconf
network_config="/etc/sysconfig/network/config"
network_ifcfgs="/etc/sysconfig/network/ifcfg"
network_dhcp="/etc/sysconfig/network/dhcp"
resolver_conf="/etc/resolv.conf"
forwarder_dir="/etc/named.d"
forwarder_conf="${forwarder_dir}/forwarders.conf"
forwarder_script="/etc/init.d/named"
# backup files we create
backup_suffix=".backup.by.convert_to_netconfig"
netconfig_md5="/var/adm/netconfig/md5"
# internal flags
update_netconfig_settings=yes
resolver_conf_localhost_ns=no
resolver_conf_otherhost_ns=no
# set netconfig defaults
NETCONFIG_DNS_POLICY='auto'
NETCONFIG_DNS_FORWARDER='resolver'
NETCONFIG_DNS_STATIC_SERVERS=''
NETCONFIG_DNS_STATIC_SEARCHLIST=''
# modify_resolvconf variables
MODIFY_NAMED_CONF_DYNAMICALLY='no'
MODIFY_RESOLV_CONF_DYNAMICALLY='no'
MODIFY_RESOLV_CONF_STATIC_DNS=''
#
# check if there is netconfig and its variables
#
test -x "${r}/sbin/netconfig" -a \
$((`grep -c "^[[:space:]]*\(\
NETCONFIG_DNS_POLICY\|\
NETCONFIG_DNS_FORWARDER\|\
NETCONFIG_DNS_STATIC_SERVERS\|\
NETCONFIG_DNS_STATIC_SEARCHLIST\)=" \
"${r}${network_config}" 2>/dev/null`)) -eq 4 || {
failure "Unable to find netconfig and its sysconfig variables"
exit 1
}
#
# check if there are conversion backups
#
test -f "${r}${resolver_conf}${backup_suffix}" -o \
-f "${r}${forwarder_conf}${backup_suffix}" && {
verbose "$SCRIPTNAME backup files exists - done"
exit 0
}
#
# check if there are modify_resolvconf variables
#
contains_old_variables "${r}${network_config}" || \
contains_old_variables "${r}${network_dhcp}" || {
verbose "Unable to find modify_resolvconf or its sysconfig variables"
verbose "Disabled conversion to netconfig (cleanup backups only)"
update_netconfig_settings=no
}
#
# OK, read current settings
#
eval `grep "^[[:space:]]*\(\
NETWORKMANAGER\|\
NETCONFIG_DNS_POLICY\|\
NETCONFIG_DNS_FORWARDER\|\
NETCONFIG_DNS_STATIC_SERVERS\|\
NETCONFIG_DNS_STATIC_SEARCHLIST\|\
MODIFY_NAMED_CONF_DYNAMICALLY\|\
MODIFY_RESOLV_CONF_DYNAMICALLY\|\
MODIFY_RESOLV_CONF_STATIC_DNS\
\)=" "${r}${network_config}" 2>/dev/null`
_MODIFY_NAMED_CONF_DYNAMICALLY=$MODIFY_NAMED_CONF_DYNAMICALLY
_MODIFY_RESOLV_CONF_DYNAMICALLY=$MODIFY_RESOLV_CONF_DYNAMICALLY
#
# check if have netconfig default settings
#
test "x$NETCONFIG_DNS_POLICY" = xauto -a \
"x$NETCONFIG_DNS_FORWARDER" = xresolver -a \
"x$NETCONFIG_DNS_STATIC_SERVERS" = x -a \
"x$NETCONFIG_DNS_STATIC_SEARCHLIST" = x || {
verbose "Modified netconfig DNS settings found - disabled conversion"
update_netconfig_settings=no
}
if test "$update_netconfig_settings" = yes ; then
# just use the old static servers except of localhost ip's ...
for ns in $MODIFY_RESOLV_CONF_STATIC_DNS ; do
is_localhost_ip $ns && continue
add_to_wordlist NETCONFIG_DNS_STATIC_SERVERS $ns
done
# disable netconfig dns updates when modify was disabled
if test "$_MODIFY_NAMED_CONF_DYNAMICALLY" != yes -a \
"$_MODIFY_RESOLV_CONF_DYNAMICALLY" != yes -a \
"$NETWORKMANAGER" != yes ;
then
# disable netconfig dns updates
NETCONFIG_DNS_POLICY=''
fi
# make sure, only one of the modify variables is set
if test "$_MODIFY_NAMED_CONF_DYNAMICALLY" = yes ; then
# modify_resolvconf prefers to use named...
_MODIFY_RESOLV_CONF_DYNAMICALLY=no
fi
fi
#
# === resolv.conf ===
#
dns_domains=()
dns_servers=()
original=`try_to_find_original "${resolver_conf}" "${r}"`
# when "original" (that is valid backup or the file itself) exists,
# remove the info block, import the settings from the original and
# fake the current file as a netconfig generated one...
# don't remove the file, because it may be in a running system...
if test -n "$original" -a -r "${r}$original" ; then
if has_networkmanager_info "${r}${resolver_conf}" ; then
# just enable for netconfig when created by NM
create_backup_once "$resolver_conf" "$backup_suffix" "$r" && \
fake_netconfig_md5 "$resolver_conf" "$netconfig_md5" "$r" && {
message "Enabled $resolver_conf for use with netconfig"
}
elif ! has_netconfig_info "${r}${resolver_conf}" && \
test "$update_netconfig_settings" = yes ;
then
remove_modify_resolvconf_info "${r}${resolver_conf}"
# we need the search list in forwarder mode too...
if test -r "${r}$original" ; then
while read -rs key val rest ; do
case $key in
(domain|search)
# take the last one defined
dns_domains=($val)
;;
(nameserver)
# collect all except localhost
if is_localhost_ip $val ; then
resolver_conf_localhost_ns=yes
else
resolver_conf_otherhost_ns=yes
dns_servers=(${dns_servers[@]} $val)
fi
;;
esac
done < <(grep -Ev '^[[:space:]]*(#.*)?$' "${r}$original")
fi
# OK, apply to netconfig variables & remove
if test "$_MODIFY_RESOLV_CONF_DYNAMICALLY" = yes ; then
add_to_wordlist NETCONFIG_DNS_STATIC_SERVERS \
${dns_servers[@]}
add_to_wordlist NETCONFIG_DNS_STATIC_SEARCHLIST \
${dns_domains[@]}
# create backup and fake as a netconfig file
create_backup_once "$resolver_conf" "$backup_suffix" "$r" && \
fake_netconfig_md5 "$resolver_conf" "$netconfig_md5" "$r" && {
message "Enabled $resolver_conf for use with netconfig"
}
fi
fi
else
# remove info block also if it does not point to valid backup
remove_modify_resolvconf_info "${r}${resolver_conf}"
fi
# finally, delete the modify_resolvconf backups
delete_modify_resolvconf_backups "${r}${resolver_conf}"
# (re)create empty resolv.conf if missed
test -e "${r}$resolver_conf" || \
touch "${r}$resolver_conf"
chmod 0644 "${r}$resolver_conf"
#
# === forwarders.conf ===
#
original=`try_to_find_original "$forwarder_conf" "${r}"`
# when "original" (that is valid backup or the file itself) exists,
# remove the info block, import the settings from the original and
# fake the current file as a netconfig generated one...
# don't remove the file, because it may be in a running system...
if test -n "$original" -a -r "$original" ; then
if ! has_netconfig_info "${r}${forwarder_conf}" && \
test "$update_netconfig_settings" = yes ; then
remove_modify_resolvconf_info "${r}${forwarder_conf}"
if test "$NETWORKMANAGER" != yes -a \
"$_MODIFY_NAMED_CONF_DYNAMICALLY" = yes ;
then
# first, read the forwarders
dns_servers=(`
test -f "${r}${original}" && \
sed -e '/^### BEGIN INFO/,/^### END INFO/d' \
-e 's/[[:space:]]*#.*$//g;/^[[:space:]]*$/d' \
-e '/^[[:space:]]*forwarders/{
h
:a
s-/\*.*\*/--g
s-#.*$--
s-//.*$--
s-[[:space:]\n]\+- -g
/} *; *$/bb
N
ba
:b
x
s-for.*$--
G
s-\n --
s- ;-;-g
}' \
-ne '/^[[:space:]]*forwarders/{
s-[^0-9:. ]*--g
p
}' \
"${r}${original}"
`)
# modify_resolvconf didn't touched the resolv.conf in "bind" mode.
#
# netconfig writes the domain search list without nameserver to the
# resolv.conf and the static nameservers as forwarder, that is it
# configures the local dns server as forwarder for the system
# (glibc makes use of a local ns when no ns in resolv.conf set).
# Other scenarios need custom netconfig setup (e.g. -dns-resolver
# in the netconfig module list).
# apply forwarders & search list to netconfig
for ns in ${dns_servers[@]} ; do
is_localhost_ip "$ns" && continue
add_to_wordlist NETCONFIG_DNS_STATIC_SERVERS $ns
done
add_to_wordlist NETCONFIG_DNS_STATIC_SEARCHLIST \
${dns_domains[@]}
# enable bind as forwarder only when it is installed
if test ! -x "${r}${forwarder_script}" ; then
warning "The bind ($forwarder_script) nameserver seems to be not installed"
warning "Skipped to enable it as forwarder in netconfig. To enable it:"
warning "Install bind package, set NETCONFIG_DNS_FORWARDER='bind' variable"
warning "manually, verify other netconfig dns settings, remove the current"
warning "$forwarder_conf file and call 'netconfig update -v'"
else
# we need either no ns in resolv.conf or localhost IP
if test "$resolver_conf_localhost_ns" = no -a \
"$resolver_conf_otherhost_ns" = no ; then
resolver_conf_localhost_ns=yes
fi
if test "$resolver_conf_localhost_ns" = yes ; then
NETCONFIG_DNS_FORWARDER='bind'
message "Enabled bind as dns forwarder in netconfig"
if test "$resolver_conf_otherhost_ns" != yes ; then
has_netconfig_info "${r}${resolver_conf}" || {
# reset resolv.conf -- it contains no or local ns only
create_backup_once "$resolver_conf" "$backup_suffix" "$r" && {
remove_modify_resolvconf_info "${r}${resolver_conf}"
fake_netconfig_md5 "$resolver_conf" "$netconfig_md5" "$r" && {
message "Enabled $resolver_conf for use with netconfig"
}
}
}
touch "${r}${resolver_conf}"
chmod 0644 "${r}${resolver_conf}"
fi
fi
# here, just to write them in a nice order...
if test "$resolver_conf_otherhost_ns" = yes ; then
warning "Please verify $resolver_conf and netconfig settings"'!'
warning "Your resolv.conf seems to require disabling of the dns-resolver module"
fi
if test "$resolver_conf_localhost_ns" != yes ; then
warning "See the NETCONFIG_MODULES_ORDER variable and netconfig(8) manual page"
warning "and set NETCONFIG_DNS_FORWARDER='bind' manually to enable as forwarder"
fi
# create backup and reset the forwarders.conf
create_backup_once "$forwarder_conf" "$backup_suffix" "$r" && {
fake_netconfig_md5 "$forwarder_conf" "$netconfig_md5" "$r" && {
message "Enabling $forwarder_conf for use with netconfig"
}
}
touch "${r}$forwarder_conf"
chmod 0644 "${r}$forwarder_conf"
fi
fi
fi
else
# remove info block also if it does not point to valid backup
remove_modify_resolvconf_info "${r}${forwarder_conf}"
fi
delete_modify_resolvconf_backups "${r}${forwarder_conf}"
if test "$update_netconfig_settings" = yes ; then
# ok, test if we have some changes, create backup and change it
if test "x$NETCONFIG_DNS_POLICY" = xauto -a \
"x$NETCONFIG_DNS_FORWARDER" = xresolver -a \
"x$NETCONFIG_DNS_STATIC_SERVERS" = x -a \
"x$NETCONFIG_DNS_STATIC_SEARCHLIST" = x ;
then
verbose "No changes to netconfig settings necessary"
else
create_backup_once "$network_config" "$backup_suffix" "$r" && {
verbose "Converting DNS settings to netconfig:"
for v in NETCONFIG_DNS_POLICY \
NETCONFIG_DNS_FORWARDER \
NETCONFIG_DNS_STATIC_SERVERS \
NETCONFIG_DNS_STATIC_SEARCHLIST ;
do
verbose "${v}='${!v}'"
sed -e "s/^[[:space:]]*\(${v}\)=.*/\1='${!v}'/g" \
-i "${r}${network_config}" || break
done
message "DNS settings to netconfig conversion... done"
}
fi
fi
# collect a list of interface with old variables
clear_ifaces=()
for ifcfg in "${r}${network_ifcfgs}-"* ; do
ifname="${ifcfg##*\/ifcfg-}"
case $ifname in
(lo|""|*" "*|*~|*.old|*.rpmnew|*.rpmsave|*.scpmbackup) continue ;;
esac
# remember where to remove the variables later...
contains_old_variables "${r}${network_ifcfgs}-${ifname}" && \
clear_ifaces=("${clear_ifaces[@]}" "${ifname}")
done
msg="Removing obsolete DNS variables (config, dhcp, ifcfg-<${clear_ifaces[@]}> files)"
contains_old_variables "${r}${network_config}" && {
test -n "$msg" && message "$msg" ; msg=""
create_backup_once "$network_config" "$backup_suffix" "$r" && {
# remove also misrouted dhcp variables from config
sysconfig_remove_and_set -b "" \
"${r}${network_config}" \
MODIFY_NAMED_CONF_DYNAMICALLY \
MODIFY_RESOLV_CONF_DYNAMICALLY \
MODIFY_RESOLV_CONF_STATIC_DNS \
DHCLIENT_MODIFY_RESOLV_CONF \
DHCLIENT_KEEP_SEARCHLIST
}
}
contains_old_variables "${r}${network_dhcp}" && {
test -n "$msg" && message "$msg" ; msg=""
create_backup_once "$network_dhcp" "$backup_suffix" "$r" && {
# remove also misrouted config variables from dhcp
sysconfig_remove_and_set -b "" \
"${r}${network_dhcp}" \
MODIFY_NAMED_CONF_DYNAMICALLY \
MODIFY_RESOLV_CONF_DYNAMICALLY \
MODIFY_RESOLV_CONF_STATIC_DNS \
DHCLIENT_MODIFY_RESOLV_CONF \
DHCLIENT_KEEP_SEARCHLIST
}
}
for ifname in "${clear_ifaces[@]}" ; do
test -n "$msg" && message "$msg" ; msg=""
if test -f "${r}${network_ifcfgs}-${ifname}" ; then
test -f "${r}${network_ifcfgs}.${ifname}${backup_suffix}" || {
cp -p --backup=t "${r}${network_ifcfgs}-${ifname}" \
"${r}${network_ifcfgs}.${ifname}${backup_suffix}" || continue
}
sed -e '/^[[:space:]]*MODIFY_NAMED_CONF_DYNAMICALLY=/d' \
-e '/^[[:space:]]*MODIFY_RESOLV_CONF_DYNAMICALLY=/d'\
-e '/^[[:space:]]*MODIFY_RESOLV_CONF_STATIC_DNS=/d' \
-e '/^[[:space:]]*DHCLIENT_MODIFY_RESOLV_CONF=/d' \
-e '/^[[:space:]]*DHCLIENT_KEEP_SEARCHLIST=/d' \
-i "${r}${network_ifcfgs}-${ifname}"
fi
done
exit 0
ACC SHELL 2018