From e4ceab6648f954cfc240f805607c0a4da6b8f804 Mon Sep 17 00:00:00 2001 From: Erich Eckner Date: Mon, 1 Apr 2019 09:57:00 +0200 Subject: update-ddns.in: refactor --- update-ddns.in | 177 +++++++++++++++++++-------------------------------------- 1 file changed, 60 insertions(+), 117 deletions(-) diff --git a/update-ddns.in b/update-ddns.in index 7aef624..bd86294 100644 --- a/update-ddns.in +++ b/update-ddns.in @@ -15,143 +15,86 @@ if ! ipCmd=$(which ip 2> /dev/null); then done fi -unset ignoreIps - -i=0 - -while read -r ipVer updateUrl dnsName; do - - if [[ "${ipVer}" = '#'* ]] || [ -z "${ipVer}" ]; then - continue - fi +sed ' + /^\(#\|\s\)/ d + s/^\([46]!\?\)\([46]!\?\)\(\s.*$\)/\1\3\n\2\3/ +' #ETCDIR#/update-ddns.conf \ +| while read -r ipVer updateUrl dnsName; do if [[ "${ipVer}" == 'ignore' ]]; then - ignoreIps="${ignoreIps} ${updateUrl} ${dnsName}" + ignoreIps=$( + printf '%s\n' "${ignoreIps}" "${updateUrl}" "${dnsName}" \ + | grep -vxF '' \ + | sort -u + ) continue fi - if [[ "${ipVer}" == *"?" ]]; then - ipVer="${ipVer%?}" + if [ -z "${ipVer##*!}" ]; then + ipVer="${ipVer%!}" + else [ -z "$(${ipCmd} -o -${ipVer} addr show scope global)" ] && continue fi if [ "${ipVer}" == '4' ]; then - dnsVers[${i}]='A' - inetVers[${i}]='inet' - ipCmdVers[${i}]='-4' + dnsVer='A' + inetVer='inet' + ipRegex='[0-9.]\+' elif [ "${ipVer}" == '6' ]; then - dnsVers[${i}]='AAAA' - inetVers[${i}]='inet6' - ipCmdVers[${i}]='-6' - elif [ "${ipVer}" == '46' ] || [ "${ipVer}" == '64' ]; then - dnsVers[${i}]='A' - inetVers[${i}]='inet' - ipCmdVers[${i}]='-4' - - updateUrls[${i}]="${updateUrl}" - dnsNamen[${i}]="${dnsName}" - i=$[${i}+1] - - dnsVers[${i}]='AAAA' - inetVers[${i}]='inet6' - ipCmdVers[${i}]='-6' + dnsVer='AAAA' + inetVer='inet6' + ipRegex='[0-9a-f:]\+' else - >&2 echo 'Error: First column in "#ETCDIR#/update-ddns.conf" needs to be "4", "6", "46" or "64"!' + >&2 echo 'Syntax error in "#ETCDIR#/update-ddns.conf"!' + >&2 echo 'Syntax should be:' + >&2 echo '# comments start with "#" or white space' + >&2 echo '4/6/46/64 update-url dns-name/check-url' + >&2 echo 'digits in the first column may be followed by "!" to indicate' + >&2 echo 'that this ip version should be updated regardless of whether' + >&2 echo 'an according global ip was found (mostly useful with "auto")' exit 1 fi - updateUrls[${i}]="${updateUrl}" - dnsNamen[${i}]="${dnsName}" - - i=$[${i}+1] - -done < #ETCDIR#/update-ddns.conf - -ignoreIps='^\('"$( - echo ${ignoreIps} | \ - tr '[:space:]' '\n' | \ - grep -vxF '' | \ - sort -u | \ - sed ' - s@$@\\|@ - ' | \ - tr -d '\n' | \ - sed ' - s@\\|$@@ - ' -)"'\)$' - -err=0 - -for dnsName in $( \ - echo "${dnsNamen[@]}" | \ - tr ' ' '\n' | \ - sort -u -); do - unset updateIps - unset updateUrl - unset curlForceIpVer - needsUpdate=false - - for ((j=0; j<${i}; j++)); do - [ "${dnsName}" != "${dnsNamen[${j}]}" ] && continue - - updateUrl="${updateUrls[${j}]}" - - if [[ "${dnsName}" == *'/'* ]]; then - dnsIps=$( - curl ${ipCmdVers[${j}]} "${dnsName}" 2> /dev/null - ) - ips='1' - updateIps="${updateIps}"',auto' - if [ -n "${curlForceIpVer}" ] && [ "${curlForceIpVer}" != "${ipCmdVers[${j}]}" ]; then - >&2 echo 'Error: I cannot determine two different ip versions automatically (because Erich didn'"'"'t need it).' - exit 1 - fi - curlForceIpVer="${ipCmdVers[${j}]}" + if [ -z "${dnsName##*/*}" ]; then + dnsIps=$( + # this test yields 1 if the dns record is already properly set + curl -s${ipVer} "${dnsName}" + ) + ips='1' + updateIps='auto' + else + dnsIps=$( + dig +short $1 "${dnsName}" ${dnsVers[${j}]} \ + | grep -x "${ipRegex}" \ + |sort -u + ) + ips=$( + "${ipCmd}" -o -${ipVer} addr show scope global | \ + awk '{print $4}' | \ + cut -d/ -f1 | \ + grep -vx "${ignoreIps}" | \ + sort -u + ) + + if [ -z "${ips}" ]; then + updateIps='auto' else - dnsIps=$( - dig $1 "${dnsName}" ${dnsVers[${j}]} | \ - sed '/^;; AUTHORITY SECTION:$/Q' | \ - grep '^[^;]' | \ - grep "\s${dnsVers[${j}]}\s" | \ - awk '{print $5}' | \ - sort -u + updateIps=$( + printf '%s\n' "${ips}" \ + | tr '\n' ',' \ + | sed 's/,$//' ) - - ips=$( - "${ipCmd}" -o ${ipCmdVers[${j}]} addr show scope global | \ - awk '{print $4}' | \ - cut -d/ -f1 | \ - grep -vx "${ignoreIps}" | \ - sort -u - ) - - if [ $(echo "${ips}" | grep -c '.') -eq 0 ]; then - updateIps="${updateIps}"',auto' - if [ -n "${curlForceIpVer}" ] && [ "${curlForceIpVer}" != "${ipCmdVers[${j}]}" ]; then - >&2 echo 'Error: I cannot determine two different ip versions automatically (because Erich didn'"'"'t need it).' - exit 1 - fi - curlForceIpVer="${ipCmdVers[${j}]}" - else - updateIps="${updateIps},$(echo -n "${ips}" | tr '\n' ',')" - fi fi + fi - if [ "${dnsIps}" != "${ips}" ]; then - needsUpdate=true - fi - done + [ "${dnsIps}" = "${ips}" ] && continue - if ${needsUpdate}; then - if [[ "${updateUrl}" = *'?'* ]]; then - updateIps='&address='"${updateIps#,}" - else - updateIps='?address='"${updateIps#,}" - fi - curl ${curlForceIpVer} -sS "${updateUrl}${updateIps}" 2> /dev/null || err=$? + if [ -z "${updateUrl##*?*}" ]; then + updateIps='&address='"${updateIps}" + else + updateIps='?address='"${updateIps}" fi + curl -${ipVer} -sS "${updateUrl}${updateIps}" 2>/dev/null || err=$? done exit ${err} -- cgit v1.2.3-54-g00ecf