#!/bin/bash
###########################################################
# gen_dns
# generation de named.conf et des fichiers de zone pour bind
############################################################

. /usr/lib/eole/ihm.sh

container_path_dns="$(CreoleGet container_path_dns)"
nom_domaine_local=$(CreoleGet nom_domaine_local)
nom_domaine_local_supp=$(CreoleGet nom_domaine_local_supp)
nom_zone_forward=$(CreoleGet nom_zone_forward "")
ip_dns_zone_forward=$(CreoleGet ip_dns_zone_forward "")

declare -a VLAN_ID=('')
declare -a VLAN_Network=('')
declare -a VLAN_Netmask=('')
declare -a Cmd_supp=('')
declare -a DOMAINNAME_SUPP=('')

forwarded_ptr_zones_networks=''

# Ajout des droits pour bind (#5342)
chmod g+w $container_path_dns/etc/bind

# On fait le ménage des fichiers de zones (db.*)
rm -f $container_path_dns/etc/bind/db.*

ZONESCONF=$container_path_dns/etc/bind/local.zones
ZONESCONF_SUPP=$container_path_dns/etc/bind/local_supp.zones
ZONESDIR=$(dirname $ZONESCONF)
TMP_BIND_DIR=/tmp/tmp_bind
HOSTS=/etc/hosts
TMP_HOSTS=/tmp/hosts
# Suppression de localhost dans le HOSTFILE pour éviter les warnings
grep -v "^127\.0\.0\.1" $HOSTS > $TMP_HOSTS

declare -i I Max nb_int
cd $container_path_dns/etc/bind
if [ "$container_path_dns" = "" ]; then
    MACHINNAME=$(CreoleGet nom_machine)
else
    MACHINNAME=`echo $container_path_dns|awk -F/ '{ print $(NF-1) }'`
fi
DOMAINNAME=$MACHINNAME.$nom_domaine_local
if [ "${system_mail_to}" == "" ]
then
    system_mail_to="root";
fi

# Gestion de délégation de sous-domaines
NOM_ZONE_FORWARD=($nom_zone_forward)
IP_DNS_ZONE_FORWARD=($ip_dns_zone_forward)
NB_ZONE_FORWARD=${#NOM_ZONE_FORWARD[*]}
subdomain=""
if [ ! $NB_ZONE_FORWARD -eq 0 ]
then
    # Prise en compte des éventuels sous-domaines
    for ((i=0; i < $NB_ZONE_FORWARD; i+=1))
    do
        if [[ "${NOM_ZONE_FORWARD[i]}" == *"${nom_domaine_local}"* ]]
        then
            # Option pour ne générer qu'un CNAME si une entrée de ce sous-domaine existe dans le fichier hosts
            subdomain="-c ${NOM_ZONE_FORWARD[i]} ${subdomain}"

            # Ajout de la délégation DNS pour le sous-domaine
            echo """\$ORIGIN ${NOM_ZONE_FORWARD[i]}.
\$TTL 86400
@   IN  NS      dns${NOM_ZONE_FORWARD[i]}.""" >> db.subdomain.$nom_domaine_local

            # Ajout de l'entrée du serveur DNS dans le fichier hosts temporaire
            echo "${IP_DNS_ZONE_FORWARD[i]} dns${NOM_ZONE_FORWARD[i]}" >> $TMP_HOSTS
        fi
    done
fi

# Extraction du DN sans le dernier label
DB_FILENAME="db.$(echo $nom_domaine_local | rev | cut -d"." -f2- | rev)"
if [ "$subdomain" == "" ]
then
    # Pas de sous-domaine à déléguer
    Cmd="/usr/share/eole/sbin/h2n -h $MACHINNAME -d $nom_domaine_local db=$DB_FILENAME mode=D -s $DOMAINNAME -u $system_mail_to -H $TMP_HOSTS"

else
    # Prise en compte des sous-domaines à déléguer
    Cmd="/usr/share/eole/sbin/h2n -h $MACHINNAME -d $nom_domaine_local db=$DB_FILENAME spcl=db.subdomain.$nom_domaine_local mode=D $subdomain -s $DOMAINNAME -u $system_mail_to -H $TMP_HOSTS"
fi

DOMAIN_LOCAL_SUPP=($nom_domaine_local_supp)
NB_DOMAINNAME_SUPP=${#DOMAIN_LOCAL_SUPP[*]}
if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
then
    # Prise en compte des éventuels domaines supplémentaires
    for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
    do
        DOMAINNAME_SUPP[i]=$MACHINNAME.${DOMAIN_LOCAL_SUPP[i]}
        # Extraction du DN sans le dernier label
        DB_FILENAME="db.$(echo ${DOMAIN_LOCAL_SUPP[i]} | rev | cut -d"." -f2- | rev)"
        Cmd_supp[i]="/usr/share/eole/sbin/h2n -h $MACHINNAME -d ${DOMAIN_LOCAL_SUPP[i]} db=$DB_FILENAME mode=D -s ${DOMAINNAME_SUPP[i]} -u $system_mail_to -H $TMP_HOSTS"
    done
fi

Max=`expr $(CreoleGet nombre_interfaces) - 1`
I=0
while [ $I -le $Max ]
do
    Network=$(CreoleGet adresse_network_eth${I})
    Netmask=$(CreoleGet adresse_netmask_eth${I})
    Cmd=$Cmd" -n ${Network}:${Netmask}"
    if [ $(CreoleGet "dns_master_eth${I}" 'non' ) = 'non' -a "${I}" != "0" ]
    then
        # “db.<NETWORK>” is forwarded to another DNS server
        forwarded_ptr_zones_networks="${forwarded_ptr_zones_networks:+${forwarded_ptr_zones_networks} }${Network}"
    fi

    if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
    then
        for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
        do
            Cmd_supp[i]=${Cmd_supp[i]}" -n ${Network}:${Netmask} "
        done
    fi
    # Zones pour les éventuels VLAN
    VLAN=$(CreoleGet vlan_eth${I})
    if [ "$VLAN" == "oui" ]
    then
        VLAN_ID=($(CreoleGet vlan_id_eth${I}))
        VLAN_Network=($(CreoleGet vlan_network_eth${I}))
        VLAN_Netmask=($(CreoleGet vlan_netmask_eth${I}))
        VLAN_dns_master=($(CreoleGet dns_master_vlan_eth${I} 'non'))
        NB_VLAN=${#VLAN_ID[*]}
        for ((id=0; id < $NB_VLAN; id+=1))
        do
            if [ ${VLAN_dns_master[id]} = 'non' ]
            then
                # “db.<NETWORK>” is forwarded to another DNS server
                forwarded_ptr_zones_networks="${forwarded_ptr_zones_networks:+${forwarded_ptr_zones_networks} }${VLAN_Network[id]}"
            fi
            Cmd=$Cmd" -n ${VLAN_Network[id]}:${VLAN_Netmask[id]}"
            if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
            then
                for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
                do
                    Cmd_supp[i]=${Cmd_supp[i]}" -n ${VLAN_Network[id]}:${VLAN_Netmask[id]}"
                done
            fi
        done
    fi
    I=$I+1
done
if [ ! "$container_path_dns" = "" ]; then
    #mode conteneur
    adresse_network_br0=$(CreoleGet adresse_network_br0)
    adresse_netmask_br0=$(CreoleGet adresse_netmask_br0)
    Cmd=$Cmd" -n $adresse_network_br0:$adresse_netmask_br0"
    if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
    then
        for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
        do
            Cmd_supp[i]=${Cmd_supp[i]}" -n $adresse_network_br0:$adresse_netmask_br0"
        done
    fi
fi

Cmd=$Cmd" -M +c $ZONESCONF mode=S -y -b $ZONESCONF -W /etc/bind/ -I warn"
if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
then
    Cmd=$Cmd" -e ${DOMAIN_LOCAL_SUPP[*]}"
    for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
    do
        # On exclut tous les domaines sauf celui en cours
        EXCLUDED_DOMAINS=${DOMAIN_LOCAL_SUPP[*]#${DOMAIN_LOCAL_SUPP[i]}}
        Cmd_supp[i]=${Cmd_supp[i]}" -M +c $ZONESCONF_SUPP mode=S -y -b $ZONESCONF_SUPP -W /etc/bind/ -e $nom_domaine_local ${EXCLUDED_DOMAINS} -I warn"
    done
fi

# routes statiques
if [ $(CreoleGet activer_route) = "oui" ];then
    route_adresse=$(CreoleGet route_adresse)
    route_netmask=$(CreoleGet route_netmask)
    dns_master_route=$(CreoleGet dns_master_route)
    routes=`echo $route_adresse | wc -w`
    if [ $routes -gt 0 ];then
        adresse=($route_adresse)
        netmask=($route_netmask)
        dns_master=($dns_master_route)
        for index in `eval echo "{0..$((routes-1))}"`; do
            if [ ${dns_master[$index]} = 'non' ]
            then
                # “db.<NETWORK>” is forwarded to another DNS server
                forwarded_ptr_zones_networks="${forwarded_ptr_zones_networks:+${forwarded_ptr_zones_networks} }${adresse[$index]}"
            fi
            Cmd=$Cmd" -n ${adresse[$index]}:${netmask[$index]} mode=S"
            if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
            then
                for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
                do
                    Cmd_supp[i]=${Cmd_supp[i]}" -n ${adresse[$index]}:${netmask[$index]} mode=S"
                done
            fi
        done
    fi
fi
# Création des zones pour le domaine local
$Cmd > /dev/null 2>&1
[ ! $? -eq 0 ] && EchoRouge "ERREUR : pour plus d'information, lancer la commande \"$Cmd\" manuellement" && exit 1
if [ ! $NB_DOMAINNAME_SUPP -eq 0 ]
then
    for ((i=0; i < $NB_DOMAINNAME_SUPP; i+=1))
    do
        # Création des zones pour les domaines locaux supplémentaires
        # dans un répertoire temporaire pour ne pas écraser les existantes
        mkdir $TMP_BIND_DIR && cd $TMP_BIND_DIR
        ${Cmd_supp[i]} > /dev/null 2>&1
         [ ! $? -eq 0 ] && EchoRouge "ERREUR : pour plus d'information, lancer la commande \"${Cmd_supp[i]}\" manuellement" && exit 1
        cat $ZONESCONF_SUPP >> $ZONESCONF

        for TMP_DB_FILE in `ls $TMP_BIND_DIR/db.*`
        do
        # Concaténation et copie des fichiers de zones au bon endroit
            DB_FILE=$(basename $TMP_DB_FILE)
            DB_FULL_FILENAME=$ZONESDIR/$DB_FILE
            LEFT_DN_LABEL="db.$(echo ${DOMAIN_LOCAL_SUPP[i]} | rev | cut -d"." -f2- | rev)"

            if [ "$DB_FILE" = "$LEFT_DN_LABEL" ]
            then
                # Si fichier domaine, on le déplace
                mv $TMP_DB_FILE $DB_FULL_FILENAME
            else
                # Si fichier zone
                if [ -e "$DB_FULL_FILENAME" ]
                then
                    # On concatène les PTR uniquement avec celui existant
                    grep -P "\tPTR\t" $TMP_DB_FILE >> $DB_FULL_FILENAME
                else
                    # On le déplace si nouvelle zone
                    mv $TMP_DB_FILE $DB_FULL_FILENAME
                fi
            fi
        done
        rm -rf $TMP_BIND_DIR
        cd - > /dev/null
    done
fi

# On conserve uniquement les lignes de zones
# et on supprime les doublons
sed -n -e "/^zone/p" $ZONESCONF > $ZONESCONF_SUPP

# Remove forwarded reverse zone
for DB_FILE_PATH in $(ls $ZONESDIR/db.*)
do
    DB_FILE=$(basename "${DB_FILE_PATH}")
    # Match list of networks against the DB_FILE without the “db.” prefix
    # Strip CIDR suffix like “10.1.2.0-128” to match “10.1.2.”
    # Match word boundary (\b) before and after to avoid “10.1.2” matching “10.1.26”
    NET_MATCH=$(echo "${DB_FILE#db.}" | sed -E 's,[0-9]+-[0-9]+,,')
    if expr -- "${forwarded_ptr_zones_networks}" : ".*\b${NET_MATCH}\b" > /dev/null
    then
        # Delete the zone file db.<NETWORK>
        rm -f "${DB_FILE_PATH}"

        # Remove entries already set in forward.zones
        sed -i -e "/${DB_FILE}/d" "${ZONESCONF_SUPP}"
    fi
done

cat $ZONESCONF_SUPP | sort | uniq > $ZONESCONF

rm -f $ZONESCONF_SUPP $TMP_HOSTS
cp -f "$container_path_dns/usr/share/dns/root.hints" "$container_path_dns/etc/bind/db.cache"

if [ -f /etc/eole/db.safesearch ]; then
    cp -f "/etc/eole/db.safesearch" "$container_path_dns/etc/bind/db.safesearch"
fi

exit 0
