#!/bin/bash
noVerify=0
set -e
while getopts ":d:A:M:n" opt; do
    case $opt in
    d )
        domain="$OPTARG"
        ;;
    A )
        rootA="$OPTARG"
        ;;
    M )
        MX="$OPTARG"
        ;;
    n )
        noVerify=1
        ;;
    ? )
        echo "script usage: $(basename $0) [-d domain] [-A rootARecord,[record,...]] [-M MXRecord,[record,...]] [-n noVerify]" >&2
        exit 3
        ;;
    esac
done

# Function to join an array on a string, used for displaying output.
join() {
    local separator="$1"
    shift
    local first="$1"
    shift
    printf "%s" "$first" "${@/#/$separator}"
}

# Parameter checking.
if ! [[ $domain ]] ; then
    echo "domain required with -d flag"
    exit 3
elif ! [[ $MX ]] && (($noVerify == 0)) ; then
    echo "-M flag required with MX record."
    exit 3
elif ! [[ $rootA ]] && (($noVerify == 0)) ;then
    echo "-A flag required with root A record."
    exit 3
fi

# Split parameters into array
IFS=',' read -r -a rootAarray <<< "$rootA"
IFS=',' read -r -a MXarrayTemp <<< "$MX"

# Remove trailing period from MXarray if exists.
for (( i=0; i<${#MXarrayTemp[@]}; i++)) do
    MXarray+=(${MXarrayTemp[$i]%.})
done

# Get results from quad 8 and quad 1
MXresult=$(dig @8.8.8.8 @1.1.1.1 $domain MX +short)
Aresult=$(dig @8.8.8.8 @1.1.1.1 $domain A +short)

# Split MX into a temporary array
MXresultArrayTemp=($MXresult)

# Take the odd numbered items (the addresses) and remove the trailing period. This insures we get only the addresses
# and not the weights.
for (( i=1; i<=${#MXresultArrayTemp[@]}; i=(($i+2)) )); do
    MXresultArray+=(${MXresultArrayTemp[$i]%.})
done


# Split A into an array. No further processing is needed.
AresultArray=($Aresult)

# Gets the difference between the arrays (i.e. items that are only in one array but not the other)
Adiff=$(echo ${AresultArray[@]} ${rootAarray[@]} | tr ' ' '\n' | sort | uniq -u)
MXdiff=$(echo ${MXresultArray[@]} ${MXarray[@]}  | tr ' ' '\n' | sort | uniq -u)


returnString=""
returnStat=0

# If the length of the result is 0, crit
if [[ ${#MXresultArray[@]} == 0 ]] ; then
    returnString+="MX record missing;  "
    returnStat=3
# If we're not verifying, return OK and print result.
elif (($noVerify == 1)) ; then
    returnString+="MX record returned $(join ', ' ${MXresultArray[@]}); "
# If the difference is >0 length, then we have a DNS record that exists on one that does not exist on the other.
elif [[ ${#MXdiff} != 0 ]] ; then
    returnString+="An MX record differs from expected value. Expected: $(join ', ' ${MXarray[@]}) Returned: $(join ', ' ${MXresultArray[@]}); "
    returnStat=3
elif [[ ${#MXdiff} == 0 ]] ; then
    returnString+="MX record OK. Expected: $(join ', ' ${MXarray[@]}) Returned: $(join ', ' ${MXresultArray[@]}); "
else
    returnString+="An unknown error occurred while processing the MX record. Expected: $(join ', ' ${MXarray[@]}) Returned: $(join ', ' ${MXresultArray[@]}); "
    returnStat=$(($returnStat>2 ? $returnStat : 2))
fi


if [[ ${#AresultArray[@]} == 0 ]] ; then
    returnString+="A record missing."
    returnStat=3
elif (($noVerify == 1)) ; then
    returnString+="A record returned $(join ', ' ${AresultArray[@]})"
elif [[ ${#Adiff} != 0 ]] ; then
    returnString+="An A record differs from expected value. Expected: $(join ', ' ${rootAarray[@]}) Returned: $(join ', ' ${AresultArray[@]})"
    returnStat=3
elif [[ ${#Adiff} == 0 ]] ; then
    returnString+="A record OK. Expected: $(join ', ' ${rootAarray[@]}) Returned: $(join ', ' ${AresultArray[@]})"
else
    returnString+="An unknown error occurred while processing the A record. Expected: $(join ', ' ${rootAarray[@]}) Returned: $(join ', ' ${AresultArray[@]})"
    returnStat=$(($returnStat>2 ? $returnStat : 2))
fi

case $returnStat in
    0)
        echo "OK - $returnString"
        exit 0
        ;;
    2)
        echo "UNKN - $returnString"
        exit 3
        ;;
    3)
        echo "CRIT - $returnString"
        exit 2
        ;;
    *)
        echo "UNKN - Error processing return value. $returnString"
        exit 2
        ;;
esac
