#!/bin/bash # # Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . # # Author: Michael Calmer # Sven Schober # Marius Tomaschewski # ## unset POSIXLY_CORRECT ; set +o posix # we're using non-posix bash features if test "$UID" != "0" -a "$USER" != root -a -z "$ROOT" ; then echo "You must be root to start $0." >&2 exit 1 fi # The environment variable ROOT indicates the root of the system to be # managed by SuSEconfig when that root is not '/' r="$ROOT" . "$r/etc/sysconfig/network/scripts/functions.netconfig" PROGNAME="${0##*/}" STATEDIR="$r/var/run/netconfig" debug "$PROGNAME Module called" . "$r/etc/sysconfig/network/config" unset DNS_SERVERS ${!DNS_SERVERS_*} DESTFILE="$r/var/run/dnsmasq-forwarders.conf" TMP_FILE="" # ********************* # FUNCTIONS # ********************* function write_dnsmasq_forwarders () { test -z "$1" && return 1 debug "write_dnsmasq_forwarders: $1 " local NAMESERVER=() # DESTFILE may be a symlink on a read only /-fs DST_FILE=`read_symlink "${DESTFILE}"` TMP_FILE=`mktemp "${DST_FILE}.XXXXXX" 2>/dev/null || \ mktemp -t "${DST_FILE##*/}.XXXXXX"` || return 1 if test ! -s "$DST_FILE" ; then touch "$DST_FILE" ; chmod 644 "$DST_FILE" fi # * copy dest => tmp to get the file attributes # * remove the content # * print a warning on top of this file #cp -p "$DST_FILE" "$TMP_FILE" # set explicit mode on tmp file instead to preserve the # mode of original file that can be wrong (bnc#428458) chmod 644 "$TMP_FILE" cat << EOT > "$TMP_FILE" ### $DESTFILE file autogenerated by netconfig! # # Before you change this file manually, consider to define the # static DNS configuration using the following variables in the # /etc/sysconfig/network/config file: # NETCONFIG_DNS_STATIC_SEARCHLIST # NETCONFIG_DNS_STATIC_SERVERS # NETCONFIG_DNS_FORWARDER # or disable DNS configuration updates via netconfig by setting: # NETCONFIG_DNS_POLICY='' # # See also the netconfig(8) manual page and other documentation. # # Note: Manual change of this file disables netconfig too, but # may get lost when this file contains comments or empty lines # only, the netconfig settings are same with settings in this # file and in case of a "netconfig update -f" call. # ### Please remove (at least) this line when you modify the file! EOT for ns in $1; do # skip duplicates for os in ${NAMESERVER[@]} ; do [ "x$ns" == "x$os" ] && continue 2 done # resolv.conf supports up to 3 nameserver, # but AFAIK not for dnsmasq ... #[ ${#NAMESERVER[@]} -lt 3 ] || break NAMESERVER=(${NAMESERVER[@]} ${ns}) done if [ ${#NAMESERVER[@]} -gt 0 ]; then { for ns in ${NAMESERVER[@]}; do echo "nameserver ${ns}" done } >> "$TMP_FILE" fi netconfig_check_md5_and_move "$TMP_FILE" "$DESTFILE" ".netconfig" TMP_FILE return $? } function get_dns_settings() { local cfg=$1 ; shift test "x$cfg" = x && return 1 local SERVICE DNSSERVERS local var idx DNS_SERVERS debug "exec get_dns_settings: $cfg" get_variable "SERVICE" "$cfg" idx=`get_ranking_idx "$SERVICE" "$@"` debug " get_dns_settings: service '$SERVICE' => rank '$idx'" var="DNS_SERVERS_$idx" DNS_SERVERS=(${!var}) get_variable "DNSSERVERS" "$cfg" if [ "x$DNSSERVERS" != "x" ]; then DNS_SERVERS=(${DNS_SERVERS[@]} $DNSSERVERS) fi unset DNSSERVERS eval "${var}='${DNS_SERVERS[@]}'" debug " get_dns_settings: ${var}='${!var}'" debug "exit get_dns_settings: $cfg" return 0 } function manage_interfaceconfig() { local cfg dir="$1" ; shift test "x$dir" != x -a -d "$dir" || return 1 debug "exec manage_interfaceconfig: $dir" for cfg in `ls -X -r "$dir/" 2>/dev/null`; do get_dns_settings "$dir/$cfg" "$@" done debug "exit manage_interfaceconfig: $dir" return 0 } # ********************* # EXECUTION STARTS HERE # ********************* if [ "$NETCONFIG_DNS_FORWARDER" != "dnsmasq" ]; then exit 0; fi # just for the case we need the original value... _NETCONFIG_DNS_RANKING="$NETCONFIG_DNS_RANKING" case "$_NETCONFIG_DNS_RANKING" in auto) _NETCONFIG_DNS_RANKING="$NETCONFIG_DNS_RANKING_DEFAULT" ;; none) _NETCONFIG_DNS_RANKING="" ;; esac # just for the case we need the original value... _NETCONFIG_DNS_POLICY=`netconfig_policy "$NETCONFIG_DNS_POLICY"` if [ "x$_NETCONFIG_DNS_POLICY" = "x" ]; then # # empty policy means do not touch anything. # successful exit. # exit 0; fi sf=0 _g=1 # disable filename glob expansion if needed shopt -o -q noglob || _g=0 [ $_g ] && shopt -o -s noglob for POL in $_NETCONFIG_DNS_POLICY; do shopt -o -u noglob case "$POL" in (NetworkManager) debug "Use NetworkManager policy merged settings" cfg="$STATEDIR/NetworkManager.netconfig" if [ -r "$cfg" ] ; then get_dns_settings "$cfg" "$_NETCONFIG_DNS_RANKING" fi break ;; (STATIC) debug "Keep Static" DNS_SERVERS_1="$DNS_SERVERS_1 $NETCONFIG_DNS_STATIC_SERVERS" ;; (STATIC_FALLBACK) debug "Static Fallback" sf=1 ;; (*) debug "Other: $POL" for IFDIR in $STATEDIR/$POL; do test -d "$IFDIR" -a \ -d "/sys/class/net/${IFDIR##*/}" || continue # proceed every interface we find with this match manage_interfaceconfig "$IFDIR" "$_NETCONFIG_DNS_RANKING" done ;; esac done [ $_g ] && shopt -o -u noglob if [ $sf -eq 1 -a -z "$DNS_SERVERS_0" \ -a -z "$DNS_SERVERS_1" ]; then DNS_SERVERS_2="$DNS_SERVERS_2 $NETCONFIG_DNS_STATIC_SERVERS" fi # filter out loopback addresses and all own IPs that would case a loop own_ips=(`ip addr show 2>/dev/null | \ LANG=C LC_ALL=C gawk '/[ ]+(inet|inet6)[ ]+/ { sub("/.*","",$2); print $2; }' 2>/dev/null`) for idx in 0 1 2 ; do var="DNS_SERVERS_$idx" val=(${!var}) new=() for ns in ${val[@]} ; do case $ns in 127.*|::1) ;; *) for ip in "${own_ips[@]}" ; do test "x$ip" = "x" && continue test "x$ip" = "x$ns" && continue 2 done new+=("$ns") ;; esac done eval "${var}='${new[@]}'" done write_dnsmasq_forwarders "$DNS_SERVERS_0 $DNS_SERVERS_1 $DNS_SERVERS_2" RET=$? if [ $RET -eq 1 ]; then # nothing changed; we are finished exit 0 elif [ $RET -eq 2 ]; then # user modified the config. Copy aborted echo "ATTENTION: You have modified $DESTFILE. Leaving it untouched..." echo "You can find my version in $TMP_FILE ..." exit 20 fi # here we should restart services if needed # => not needed, dnsmasq polls and reloads itself exit 0; # vim: set ts=8 sts=4 sw=4 ai et: