#!/bin/sh # # This script uses the named D-BUS support, which must be enabled in # the running named with the named '-D' option, to get and print the # list of forwarding zones in the running server. # # It accepts an optional first argument which is the DNS name # of the zone whose forwarders (if any) will be retrieved. # # If no zone argument is specified, all forwarding zones will be listed. # # Usage: namedGetForwarders [-n -r] [ ] # -n : output forward zone statements for named.conf # -r : output in resolv.conf format # : no -r or -n: just list the forwarders # # This script is based on perl script of Jason Vas Dias . # # Copyright(C) Baris Cicek Nerd Software. 2007 # # 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 at # http://www.fsf.org/licensing/licenses/gpl.txt # and included in this software distribution as the "LICENSE" file. # # 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. declare -a zones; declare -a servers; declare -a ports; declare -a only; output_format='plain'; zonecnt=0; function push () { local array array=( `echo $1` ); array[${#array[*]}]=$2; echo ${array[@]}; } function concat () { local string while [ $# -gt 0 ]; do string=${string}$1; shift; done echo $string; } if [ $# -ge 0 ]; then if [ "$1" == "-r" ]; then output_format='resolv'; shift; elif [ "$1" == "-n" ]; then output_format='named'; shift; fi zone=""; for arg in $*; do zone=$(push "$zone" " string:'$arg'"); done fi DNS=`/bin/dbus-send --system --type=method_call --print-reply --reply-timeout=20000 --dest=com.redhat.named /com/redhat/named com.redhat.named.text.GetForwarders $zone`; if [ $? -ne 0 ]; then echo -e "dbus-send failed: $? $!"; exit 1; fi IFS=$'\n' for line in $DNS; do match_ip=$( echo "$line" | awk --re-interval '{ match ($0, /([[:digit:]]{1,3})\.([[:digit:]]{1,3})\.([[:digit:]]{1,3})\.([[:digit:]]{1,3})/, a); printf "%s.%s.%s.%s", substr($0, a[1, "start"], a[1, "length"]), substr($0, a[2, "start"], a[2, "length"]), substr($0, a[3, "start"], a[3, "length"]), substr($0, a[4, "start"], a[4, "length"]);}' ); match_port=$( echo "$line" | awk '{ match ($0, /\"([[:digit:]]+)\"$/, a); printf "%s", substr($0, a[1, "start"], a[1,"length"]);}' ); match_string=$( echo "$line" | awk '{ match ($0, /string.+\"([^\"]+)\"$/, a); printf "%s", substr($0, a[1, "start"], a[1,"length"]);}' ); if [ "$match_ip" != "" ] && [ "$match_ip" != "..." ]; then servers[$zonecnt]=$(push "${servers[$zonecnt]}" "$match_ip"); elif [ "$match_port" != "" ]; then ports[$zonecnt]=$(push "${ports[$zonecnt]}" "$match_port"); elif [ "$match_string" == "only" ]; then only[$zonecnt]="1"; elif [ "$match_string" != "" ] && [ "$match_string" != "first" ]; then zonecnt=$((zonecnt + 1)); zones[$zonecnt]="$match_string"; fi done if [ "$output_format" == "resolv" ]; then # resolv.conf style: search_line='search'; nameserver_lines=''; for index in $(seq 1 $zonecnt); do if [ "` echo ${zones[$index]} | awk ' /\.in-addr\.arpa$/ { print $0 }'`" == '' ]; then search_line=$(push "$search_line" "${zones[$index]}"); fi IFS=$' '; for ns in ${servers[$index]}; do nameserver_lines=$(concat "$nameserver_lines" "\nnameserver " "$ns"); done done echo -n $search_line; echo -e $nameserver_lines; elif [ "$output_format" == "named" ]; then # named.conf style: zone_lines=''; for index in $(seq 1 $zonecnt); do zone_line=$(concat 'zone "' "${zones[$index]}" '." IN { type forward; forwarders { '); srvcnt=1; IFS=$' '; for ns in ${servers[$index]}; do srvport=$(eval "echo ${ports[$index]} | awk '{ print \$${srvcnt} }'"); if [ "$srvport" != "53" ]; then zone_line=$(concat "$zone_line" " $ns port $srvport;"); else zone_line=$(concat "$zone_line" " $ns;"); fi srvcnt=$((srvcnt+1)); done zone_line=$(concat "$zone_line" " };"); if [ "${only[$index]}" == '1' ]; then zone_line=$(concat "$zone_line" " forward only;"); fi zone_line=$(concat "$zone_line" " };"); zone_lines=$(concat "$zone_lines" "$zone_line\n"); done echo -e ${zone_lines%\\n}; elif [ "$output_format" == "plain" ]; then # just list: output=''; for index in $(seq 1 $zonecnt); do output=$(concat "$output" "${zones[$index]}" "\n"); if [ "${only[$index]}" == "1" ]; then output=$(concat "$output" "\t" "forward only" "\n"); fi srvcnt=1; IFS=$' '; for ns in ${servers[$index]}; do srvport=$(eval "echo ${ports[$index]} | awk '{ print \$${srvcnt} }'"); if [ "$srvport" != "53" ]; then output=$(concat "$output" "\t" "$ns:$srvport" "\n"); else output=$(concat "$output" "\t" "$ns" "\n"); fi srvcnt=$((srvcnt+1)); done done echo -e ${output%\\n}; fi