#!/bin/bash # # This script read Bind zone files from directory given as parameter, # translate it and save to MySQL of web interface smbind. # # To work properly, SCRIPT IS EXPECTING, that user running this script # can access to LOCAL smbind database WITHOUT authorisation # (you can set login information for mysql client in ~/.my.cnf, # don't forget chmod 600 ~/.my.cnf!!!) # # Extra MX records in zonefile are IGNORED! # Only MX records, which script translate are MX from head of zonefile. # for roundrobins in domains of the third and higher levels are created # extra zonefiles. # # Known bugs: # Script IGNORE SRV records!!! # # Written by JeromeHeretic (C) 2007 ##################################################################### #set -x SOURCEDIR="$1" # this must run as first, because everything other need to know zone ID! genzone(){ ZONE="$1" AREC="`head -30 $ZONE |tr '\t' ' ' |sed s/\ \ //g |sed s/^\ //g |grep ^A |sed s/.*\ //g |head -1`" echo "INSERT INTO smbind.zones VALUES ('','$ZONE','ns1.superhosting.cz','ns2.superhosting.cz',`date +%Y%m%d00 |tr -d '\n'`,3600,3600,2592000,3600,'yes',1,'yes');" |mysql ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" echo "INSERT INTO smbind.records VALUES ('',$ZONEID,'@','A','','$AREC','yes');" |mysql } # Read header of file and write MX records to database genmxses(){ ZONE="$1" for MX in `head -30 $ZONE |tr '\t' ' ' |sed s/\ \ //g |sed s/^\ //g |grep ^MX |sed 's/\.$//g' |tr ' ' '@'`; do ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" LEVEL="`echo $MX |awk -v FS="@" '{print $2}'`" MXSERVER="`echo $MX |awk -v FS="@" '{print $3}'`" echo "INSERT INTO smbind.records VALUES ('',$ZONEID,'@','MX','$LEVEL','$MXSERVER','yes');" |mysql done } # Function expect that '*' records are rewriten to '*', in other way # function "don't see" the record and is returning last ORIGIN inserted in # variable $ORIGIN genrecs(){ ZONE="$1" ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" HAVEORIGIN="0" while read; do if echo $REPLY |grep -q ^\$ORIGIN; then # Origin line HAVEORIGIN="1" ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" if echo $REPLY |grep '^\$ORIGIN $ZONE\.$'; then # The same origin as zonefile ORIGIN="$ZONE" else # Different origin ORIGIN="`echo $REPLY |sed s/.*\ //g |sed 's/\.$//g'`" fi else if [ "$HAVEORIGIN" = "1" ]; then # Record line if [ "$ORIGIN" = "$ZONE" ]; then # Here we do not need write FQDN NAME="`echo $REPLY |awk '{print $1}'`" # We do not need write FQDN if [ "$NAME" = "*" ]; then NAME="*" fi TYPE="`echo $REPLY |awk '{print $2}'`" DESTINATION="`echo $REPLY |awk '{print $3}' |sed 's/\.$//g'`" # If record is not A or CNAME, fuck off... if echo $REPLY |tr '\t' ' ' |grep -q -e ^A -e ^CNAME -e ' A ' -e ' CNAME '; then # If NAME = A, it means, that there is roundrobin for this zone, # We must offset variables to one number higher, because $1 was empty if [ "$NAME" = "A" ]; then DESTINATION="$TYPE" TYPE="$NAME" NAME="$BUFFER" fi BUFFER="$NAME" echo "$NAME.$ZONE $DESTINATION" >>/tmp/findrobin.$ZONE echo "INSERT INTO smbind.records VALUES ('',$ZONEID,'$NAME','$TYPE','','$DESTINATION','yes');" |mysql fi else # We need write FQDN, because ORIGIN != zonefile name NAME="`echo $REPLY |awk '{print $1}'`" if [ "$NAME" = "*" ]; then NAME="*.$ORIGIN" WASSTAR="1" else NAME="`echo $REPLY |awk '{print $1}'`.$ORIGIN" WASSTAR="0" fi TYPE="`echo $REPLY |awk '{print $2}'`" DESTINATION="`echo $REPLY |awk '{print $3}' |sed 's/\.$//g'`" # If record is not A or CNAME, fuck off... if echo $REPLY |tr '\t' ' ' |grep -q -e ^A -e ^CNAME -e ' A ' -e ' CNAME '; then # If NAME = A, it means, that there is roundrobin for this zone, # We must offset variables to one number higher, because $1 was empty if [ "$NAME" = "A.$ORIGIN" ]; then DESTINATION="$TYPE" TYPE="`echo $NAME |awk -v FS=".$ORIGIN" '{print $1}'`" if [ "$WASSTAR" = "0" ]; then NAME="$BUFFER" else NAME="*.$BUFFER" fi fi NAME="`echo $NAME |sed s/\.$ZONE//g`" BUFFER="$NAME" echo "$NAME.$ZONE $DESTINATION" >>/tmp/findrobin.$ZONE echo "INSERT INTO smbind.records VALUES ('',$ZONEID,'$NAME','$TYPE','','$DESTINATION','yes');" |mysql fi fi fi fi done <$ZONE } findrobin(){ echo "Searching roundrobin" for FILE in `cd /tmp; ls findrobin*`; do echo $FILE ZONE="`echo $FILE |sed s/findrobin\.//g`" for REC in `cat /tmp/$FILE |grep -v "^*" |sed s/\ .*//g`; do HOSTNAME="`echo $REC |awk '{print $1}' |sed s/^@\.//g`" if [ "`host $HOSTNAME |grep address |wc -l`" -gt "1" ]; then host $HOSTNAME |grep address >>/tmp/haverobin.$ZONE rm /tmp/$FILE fi done done echo } #updaterobin(){ #for FILE in `cd /tmp; ls haverobin*`; do # ZONE="`echo $FILE |sed s/haverobin\.//g`" # for IP in `host mimibazar.cz localhost |grep address |sed s/.*\ //g`; do # if grep $IP /tmp/$FILE ;then # UPDATEIP="$IP" # fi # done # ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" # HOST="`cat `" # mysql smbind -e "update records set #done #} # Create extra zone files for star records extrazones(){ echo "Generating extra zonefiles" for ID in `echo "select id from zones;" |mysql smbind |grep -v ^id$`; do PARENTZONE="`echo "select name from zones where id=$ID;" |mysql smbind |grep -v ^name$`" RECS="`mysql smbind -Be "select host,type,destination from records where zone=$ID and host like '*.%';" |grep -v ^host.*type.*destination$ |tr '\t' '@'`" for REC in $RECS ; do echo -n "." NAME="`echo $REC |sed s/@.*//g |sed s/'^*\.'//g`" ZONE="${NAME}.${PARENTZONE}" # Create new zone if doesn't exist ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" if [ "$ZONEID" = "" ]; then echo "INSERT INTO smbind.zones VALUES ('','$ZONE','ns1.superhosting.cz','ns2.superhosting.cz',`date +%Y%m%d00 |tr -d '\n'`,3600,3600,2592000,3600,'yes',1,'yes');" |mysql ZONEID="`mysql smbind -B -e \"select id from zones where name='$ZONE';\" |tail -1`" # Insert MX records for new zone MXRECS="`mysql smbind -Be "select pri,destination from records where zone=$ID and type='MX';" |grep -v ^pri.*destination$ |tr '\t' '@'`" for REC in $MXRECS; do PRI="`echo $REC |awk -v FS="@" '{print $1}'`" DESTINATION="`echo $REC |awk -v FS="@" '{print $2}'`" echo "INSERT INTO smbind.records VALUES ('',$ZONEID,'@','MX','$PRI','$DESTINATION','yes');" |mysql done fi # Update A and CNAME record => change id from parent id to current zoneid #echo "update smbind.records set host='@', zone=$ZONEID where host='$NAME' and type='A';" |mysql #echo "update smbind.records set host='@', zone=$ZONEID where host='$NAME' and type='CNAME';" |mysql # Now we update star records echo "update smbind.records set host='*', zone=$ZONEID where host='*.$NAME' and zone=$ID;" |mysql done done } # Let's Rock... # ------------------------------------------------------------ # Delete firts $ORIGIN line rm /tmp/findrobin* /tmp/haverobin* 2>/dev/null cd $SOURCEDIR echo "Cleaning first origin" for i in `ls`; do echo -n "." if head -1 $i |grep -q ^\$ORIGIN ; then sed -e '1d' -i $i fi done echo # A bit ugly patch, # we must rewrite '*' records to '*' string, # see genrecs for more info echo "Patching 'star' domains" for i in `ls`; do echo -n "." sed -i s/^\*/*/g $i done echo echo "Generating records to database" for ZONE in `ls`; do echo -n "." if [ -e $ZONE ]; then genzone $ZONE genmxses $ZONE genrecs $ZONE else echo -e "\nZone: $ZONE doesn't exist!" fi done echo findrobin extrazones