@ -10,11 +10,12 @@
# by Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
# to support:
# - IPv6 DDNS services
# - DNS Server to retrieve registered IP including TCP transport
# - DNS Server to retrieve registered IP including TCP transport (Ticket 7820)
# - Proxy Server to send out updates
# - force_interval=0 to run once
# - force_interval=0 to run once (Luci Ticket 538)
# - the usage of BIND's host command instead of BusyBox's nslookup if installed
# - extended Verbose Mode and log file support for better error detection
# - wait for interface to fully come up, before the first update is done
#
# variables in small chars are read from /etc/config/ddns
# variables in big chars are defined inside these scripts as global vars
@ -38,7 +39,7 @@
. /usr/lib/ddns/dynamic_dns_functions.sh # global vars are also defined here
SECTION_ID = " $1 "
VERBOSE_MODE = ${ 2 :- 1 } #default mode is log to console
VERBOSE_MODE = ${ 2 :- 1 } # default mode is log to console
# set file names
PIDFILE = " $RUNDIR / $SECTION_ID .pid " # Process ID file
@ -47,15 +48,23 @@ LOGFILE="$LOGDIR/$SECTION_ID.log" # log file
# VERBOSE_MODE > 1 delete logfile if exist to create an empty one
# only with this data of this run for easier diagnostic
# new one created by verbose_echo function
# new one created by write_log function
[ $VERBOSE_MODE -gt 1 -a -f $LOGFILE ] && rm -f $LOGFILE
# TRAP handler
trap "trap_handler 0 \$?" 0 # handle script exit with exit status
trap "trap_handler 1" 1 # SIGHUP Hangup / reload config
trap "trap_handler 2" 2 # SIGINT Terminal interrupt
trap "trap_handler 3" 3 # SIGQUIT Terminal quit
#trap "trap_handler 9" 9 # SIGKILL no chance to trap
trap "trap_handler 15" 15 # SIGTERM Termination
################################################################################
# Leave this comment here, to clearly document variable names that are expected/possible
# Use load_all_config_options to load config options, which is a much more flexible solution.
#
# config_load "ddns"
# config_get <variable> $SECTION_ID <option]>
# config_get <variable> $SECTION_ID <option>
#
# defined options (also used as variable):
#
@ -108,23 +117,23 @@ LOGFILE="$LOGDIR/$SECTION_ID.log" # log file
[ " $( uci_get ddns $SECTION_ID ) " != "service" ] && {
[ $VERBOSE_MODE -le 1 ] && VERBOSE_MODE = 2 # force console out and logfile output
[ -f $LOGFILE ] && rm -f $LOGFILE # clear logfile before first entry
verbose_echo "\n ************** =: ************** ************** **************"
verbose_echo " STARTED =: PID ' $$ ' at $( eval $DATE_PROG ) "
verbose_echo " UCI CONFIG = :\n $( uci -q show ddns | grep '=service' | sort) "
critical_error " Service ' $SECTION_ID ' not defined "
write_log 7 "************ ************** ************** **************"
write_log 5 " PID ' $$ ' started at $( eval $DATE_PROG ) "
write_log 7 " uci configuration :\n $( uci -q show ddns | grep '=service' | sort) "
write_log 14 " Service section ' $SECTION_ID ' not defined "
}
load_all_config_options "ddns" " $SECTION_ID "
verbose_echo "\n ************** =: ************** ************** **************"
verbose_echo " STARTED =: PID ' $$ ' at $( eval $DATE_PROG ) "
write_log 7 "************ ************** ************** **************"
write_log 5 " PID ' $$ ' started at $( eval $DATE_PROG ) "
case $VERBOSE_MODE in
0) verbose_echo " verbose mode =: '0' - run normal, NO console output" ; ;
1) verbose_echo " verbose mode =: '1' - run normal, console mode" ; ;
2) verbose_echo " verbose mode =: '2' - run once, NO retry on error" ; ;
3) verbose_echo " verbose mode =: '3' - run once, NO retry on error, NOT sending update" ; ;
*) critical_error " ERROR detecting VERBOSE_MODE ' $VERBOSE_MODE ' "
0) write_log 7 "verbose mode '0' - run normal, NO console output" ; ;
1) write_log 7 "verbose mode '1' - run normal, console mode" ; ;
2) write_log 7 "verbose mode '2' - run once, NO retry on error" ; ;
3) write_log 7 "verbose mode '3' - run once, NO retry on error, NOT sending update" ; ;
*) write_log 14 " error detecting VERBOSE_MODE ' $VERBOSE_MODE ' " ; ;
esac
verbose_echo " UCI CONFIG = :\n $( uci -q show ddns.$SECTION_ID | sort) "
write_log 7 " uci configuraion :\n $( uci -q show ddns.$SECTION_ID | sort) "
# set defaults if not defined
[ -z " $enabled " ] && enabled = 0
@ -142,48 +151,47 @@ verbose_echo " UCI CONFIG =:\n$(uci -q show ddns.$SECTION_ID | sort)"
[ " $ip_source " = "web" -a -z " $ip_url " -a $use_ipv6 -eq 1 ] && ip_url = "http://checkipv6.dyndns.com"
[ " $ip_source " = "interface" -a -z " $ip_interface " ] && ip_interface = "eth1"
# check configuration and enabled state
[ -z " $domain " -o -z " $username " -o -z " $password " ] && critical_error "Service Configuration not correctly configured"
[ $enabled -eq 0 ] && critical_error "Service Configuration is disabled"
# check enabled state otherwise we don't need to continue
[ $enabled -eq 0 ] && write_log 14 "Service section disabled!"
# without domain or username or password we can do nothing for you
[ -z " $domain " -o -z " $username " -o -z " $password " ] && write_log 14 "Service section not correctly configured!"
urlencode URL_USER " $username " # encode username, might be email or something like this
urlencode URL_PASS " $password " # encode password, might have special chars for security reason
# verify script if configured and executable
# verify ip_source script if configured and executable
if [ " $ip_source " = "script" ] ; then
[ -z " $ip_script " ] && critical_error "No script defined to detect local IP"
[ -x " $ip_script " ] || critical_error "Script to detect local IP not found or not executable"
[ -z " $ip_script " ] && write_log 14 "No script defined to detect local IP! "
[ -x " $ip_script " ] || write_log 14 "Script to detect local IP not found or not executable! "
fi
# compute update interval in seconds
get_seconds CHECK_SECONDS ${ check_interval :- 10 } ${ check_unit :- "minutes" } # default 10 min
get_seconds FORCE_SECONDS ${ force_interval :- 72 } ${ force_unit :- "hours" } # default 3 days
get_seconds RETRY_SECONDS ${ retry_interval :- 60 } ${ retry_unit :- "seconds" } # default 60 sec
verbose_echo " check interval =: $CHECK_SECONDS seconds "
verbose_echo " force interval =: $FORCE_SECONDS seconds "
verbose_echo " retry interval =: $RETRY_SECONDS seconds "
verbose_echo " retry counter =: $retry_count times "
[ $CHECK_SECONDS -lt 300 ] && CHECK_SECONDS = 300 # minimum 5 minutes
[ $FORCE_SECONDS -gt 0 -a $FORCE_SECONDS -lt $CHECK_SECONDS ] && FORCE_SECONDS = $CHECK_SECONDS # FORCE_SECONDS >= CHECK_SECONDS or 0
write_log 7 " check interval: $CHECK_SECONDS seconds "
write_log 7 " force interval: $FORCE_SECONDS seconds "
write_log 7 " retry interval: $RETRY_SECONDS seconds "
write_log 7 " retry counter : $retry_count times "
# determine what update url we're using if a service_name is supplied
# otherwise update_url is set inside configuration (custom service )
# otherwise update_url is set inside configuration (custom update url )
# or update_script is set inside configuration (custom update script)
[ -n " $service_name " ] && get_service_data update_url update_script
[ -z " $update_url " -a -z " $update_script " ] && critical_error "n o update_url found/defined or no update_script found/defined"
[ -n " $update_script " -a ! -f " $update_script " ] && critical_error "custom update_script not found "
[ -z " $update_url " -a -z " $update_script " ] && write_log 14 "N o update_url found/defined or no update_script found/defined! "
[ -n " $update_script " -a ! -f " $update_script " ] && write_log 14 "Custom update_script not found! "
#kill old process if it exists & set new pid file
if [ -d $RUNDIR ] ; then
#if process is already running, stop it
if [ -e " $PIDFILE " ] ; then
OLD_PID = $( cat $PIDFILE )
ps | grep -q " ^[\t ]* $OLD_PID " && {
verbose_echo " old process =: PID ' $OLD_PID ' "
kill $OLD_PID
} || verbose_echo "old process id =: PID 'none'"
else
verbose_echo "old process id =: PID 'none'"
fi
#if process for section is already running, stop it
stop_section_processes " $SECTION_ID "
[ $? -gt 0 ] && write_log 7 "Send 'SIGTERM' to old process" || write_log 7 "No old process"
else
#make dir since it doesn't exist
mkdir -p $RUNDIR
verbose_echo "old process id =: PID 'none' "
write_log 7 "No old process"
fi
echo $$ > $PIDFILE
@ -201,242 +209,118 @@ get_uptime CURR_TIME
[ $LAST_TIME -gt $CURR_TIME ] && LAST_TIME = 0
}
if [ $LAST_TIME -eq 0 ] ; then
verbose_echo " last update = : never"
write_log 7 "last update : never"
else
EPOCH_TIME = $(( $( date +%s) - CURR_TIME + LAST_TIME ))
EPOCH_TIME = " date -d @ $EPOCH_TIME +' $DATE_FORMAT ' "
verbose_echo " last update = : $( eval $EPOCH_TIME ) "
write_log 7 " last update : $( eval $EPOCH_TIME ) "
fi
# we need time here because hotplug.d is fired by netifd
# but IP addresses are not set by DHCP/DHCPv6 etc.
verbose_echo " waiting =: 10 seconds for interfaces to fully come up"
sleep 10
# verify DNS server:
# do with retry's because there might be configurations
# not directly could connect to outside dns when interface is already up
ERR_VERIFY = 0 # reset err counter
while [ -n " $dns_server " ] ; do
[ $ERR_VERIFY -eq 0 ] && verbose_echo " ******* VERIFY =: DNS server ' $dns_server ' "
verify_dns " $dns_server "
ERR_LAST = $? # save return value
[ $ERR_LAST -eq 0 ] && break # everything ok leave while loop
ERR_VERIFY = $(( $ERR_VERIFY + 1 ))
# if error count > retry_count leave here with critical error
[ $ERR_VERIFY -gt $retry_count ] && {
case $ERR_LAST in
2) critical_error "Invalid DNS server Error: '2' - nslookup can not resolve host" ; ;
3) critical_error "Invalid DNS server Error: '3' - nc (netcat) can not connect" ; ;
*) critical_error " Invalid DNS server Error: ' $ERR_LAST ' - unspecific error " ; ;
esac
}
case $ERR_LAST in
2) syslog_err " Invalid DNS server Error: '2' - nslookup can not resolve host - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
3) syslog_err " Invalid DNS server Error: '3' - nc (netcat) can not connect - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
*) syslog_err " Invalid DNS server Error: ' $ERR_LAST ' - unspecific error - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
esac
[ $VERBOSE_MODE -gt 1 ] && {
# VERBOSE_MODE > 1 then NO retry
verbose_echo "\n!!!!!!!!! ERROR =: Verbose Mode - NO retry\n"
break
}
verbose_echo " ******** RETRY =: DNS server ' $dns_server ' - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds "
sleep $RETRY_SECONDS
done
write_log 7 "Waiting 10 seconds for interfaces to fully come up"
sleep 10 &
PID_SLEEP = $!
wait $PID_SLEEP # enable trap-handler
PID_SLEEP = 0
# verify DNS server
[ -n " $dns_server " ] && verify_dns " $dns_server "
# verify Proxy server and set environment
# do with retry's because there might be configurations
# not directly could connect to outside dns when interface is already up
ERR_VERIFY = 0 # reset err counter
[ -n " $proxy " ] && {
[ $ERR_VERIFY -eq 0 ] && verbose_echo " ******* VERIFY =: Proxy server 'http:// $proxy ' "
verify_proxy " $proxy "
ERR_LAST = $? # save return value
[ $ERR_LAST -eq 0 ] && {
# everything ok set proxy and leave while loop
verify_proxy " $proxy " && {
# everything ok set proxy
export HTTP_PROXY = " http:// $proxy "
export HTTPS_PROXY = " http:// $proxy "
export http_proxy = " http:// $proxy "
export https_proxy = " http:// $proxy "
break
}
ERR_VERIFY = $(( $ERR_VERIFY + 1 ))
# if error count > retry_count leave here with critical error
[ $ERR_VERIFY -gt $retry_count ] && {
case $ERR_LAST in
2) critical_error "Invalid Proxy server Error '2' - nslookup can not resolve host" ; ;
3) critical_error "Invalid Proxy server Error '3' - nc (netcat) can not connect" ; ;
*) critical_error " Invalid Proxy server Error ' $ERR_LAST ' - unspecific error " ; ;
esac
}
case $ERR_LAST in
2) syslog_err " Invalid Proxy server Error '2' - nslookup can not resolve host - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
3) syslog_err " Invalid Proxy server Error '3' - nc (netcat) can not connect - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
*) syslog_err " Invalid Proxy server Error ' $ERR_LAST ' - unspecific error - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds\n " ; ;
esac
[ $VERBOSE_MODE -gt 1 ] && {
# VERBOSE_MODE > 1 then NO retry
verbose_echo "\n!!!!!!!!! ERROR =: Verbose Mode - NO retry\n"
break
}
verbose_echo " ******** RETRY =: Proxy server 'http:// $proxy ' - retry $ERR_VERIFY / $retry_count in $RETRY_SECONDS seconds "
sleep $RETRY_SECONDS
}
# let's check if there is already an IP registered at the web
# but ignore errors if not
verbose_echo "******* DETECT =: Registered IP"
get_registered_ip REGISTERED_IP
get_registered_ip REGISTERED_IP "NO_RETRY"
# loop endlessly, checking ip every check_interval and forcing an updating once every force_interval
# NEW: ### Luci Ticket 538
# a "force_interval" of "0" will run this script only once
# the update is only done once when an interface goes up
# or you run /etc/init.d/ddns start or you can use a cron job
# it will force an update without check when lastupdate happen
# but it will verify after "check_interval" if update is seen in the web
# and retries on error retry_count times
# CHANGES: ### Ticket 16363
# modified nslookup / sed / grep to detect registered ip
# NEW: ### Ticket 7820
# modified nslookup to support non standard dns_server (needs to be defined in /etc/config/ddns)
# support for BIND host command.
# Wait for interface to fully come up, before the first update is done
verbose_echo " *** START LOOP =: $( eval $DATE_PROG ) "
# we run NOT once
[ $FORCE_SECONDS -gt 0 -o $VERBOSE_MODE -le 1 ] && syslog_info "Starting main loop"
write_log 6 " Starting main loop at $( eval $DATE_PROG ) "
while : ; do
# read local IP
verbose_echo "******* DETECT =: Local IP"
get_local_ip LOCAL_IP
ERR_LAST = $? # save return value
# Error in function
[ $ERR_LAST -gt 0 ] && {
if [ $VERBOSE_MODE -le 1 ] ; then # VERBOSE_MODE <= 1 then retry
# we can't read local IP
ERR_LOCAL_IP = $(( $ERR_LOCAL_IP + 1 ))
[ $ERR_LOCAL_IP -gt $retry_count ] && critical_error "Can not detect local IP"
verbose_echo " \n!!!!!!!!! ERROR =: detecting local IP - retry $ERR_LOCAL_IP / $retry_count in $RETRY_SECONDS seconds\n "
syslog_err " Error detecting local IP - retry $ERR_LOCAL_IP / $retry_count in $RETRY_SECONDS seconds "
sleep $RETRY_SECONDS
continue # jump back to the beginning of while loop
else
verbose_echo "\n!!!!!!!!! ERROR =: detecting local IP - NO retry\n"
fi
}
ERR_LOCAL_IP = 0 # reset err counter
get_local_ip LOCAL_IP # read local IP
# prepare update
# never updated or forced immediate then NEXT_TIME = 0
# never updated or forced immediate then NEXT_TIME = 0
[ $FORCE_SECONDS -eq 0 -o $LAST_TIME -eq 0 ] \
&& NEXT_TIME = 0 \
|| NEXT_TIME = $(( $LAST_TIME + $FORCE_SECONDS ))
# get current uptime
get_uptime CURR_TIME
# send update when current time > next time or local ip different from registered ip (as loop on error)
ERR_SEND = 0
while [ $CURR_TIME -ge $NEXT_TIME -o " $LOCAL_IP " != " $REGISTERED_IP " ] ; do
get_uptime CURR_TIME # get current uptime
# send update when current time > next time or local ip different from registered ip
if [ $CURR_TIME -ge $NEXT_TIME -o " $LOCAL_IP " != " $REGISTERED_IP " ] ; then
if [ $VERBOSE_MODE -gt 2 ] ; then
verbose_echo " VERBOSE MODE =: NO UPDATE send to DDNS provider "
write_log 7 " Verbose Mode: $VERBOSE_MODE - NO UPDATE send "
elif [ " $LOCAL_IP " != " $REGISTERED_IP " ] ; then
verbose_echo " ******* UPDATE =: LOCA L: ' $LOCAL_IP ' <> REGISTERED : ' $REGISTERED_IP ' "
write_log 7 " Update needed - L: ' $LOCAL_IP ' <> R: ' $REGISTERED_IP ' "
else
verbose_echo " ******* FORCED =: LOCA L: ' $LOCAL_IP ' == REGISTERED : ' $REGISTERED_IP ' "
write_log 7 " Forced Update - L: ' $LOCAL_IP ' == R: ' $REGISTERED_IP ' "
fi
# only send if VERBOSE_MODE < 3
ERR_LAST = 0
[ $VERBOSE_MODE -lt 3 ] && {
send_update " $LOCAL_IP "
# only send if VERBOSE_MODE < 3
send_update " $LOCAL_IP "
ERR_LAST = $? # save return value
}
# Error in function
if [ $ERR_LAST -gt 0 ] ; then
if [ $VERBOSE_MODE -le 1 ] ; then # VERBOSE_MODE <=1 then retry
# error sending local IP
ERR_SEND = $(( $ERR_SEND + 1 ))
[ $ERR_SEND -gt $retry_count ] && critical_error "can not send update to DDNS Provider"
verbose_echo " \n!!!!!!!!! ERROR =: sending update - retry $ERR_SEND / $retry_count in $RETRY_SECONDS seconds\n "
syslog_err " Error sending update - retry $ERR_SEND / $retry_count in $RETRY_SECONDS seconds "
sleep $RETRY_SECONDS
continue # re-loop
else
verbose_echo "\n!!!!!!!!! ERROR =: sending update to DDNS service - NO retry\n"
break
fi
else
# we send data so save "last time"
get_uptime LAST_TIME
# error sending local IP to provider
# we have no communication error (handled inside send_update/do_transfer)
# but update was not recognized
# do NOT retry after RETRY_SECONDS, do retry after CHECK_SECONDS
# to early retrys will block most DDNS provider
# providers answer is checked inside send_update() function
[ $ERR_LAST -eq 0 ] && {
get_uptime LAST_TIME # we send update, so
echo $LAST_TIME > $UPDFILE # save LASTTIME to file
[ " $LOCAL_IP " != " $REGISTERED_IP " ] \
&& syslog_notice " Changed IP: ' $LOCAL_IP ' successfully send " \
|| syslog_notice " Forced Update: IP: ' $LOCAL_IP ' successfully send "
break # leave while
fi
done
&& write_log 6 " Update successful - IP ' $LOCAL_IP ' send " \
|| write_log 6 " Forced update successful - IP: ' $LOCAL_IP ' send "
} || write_log 3 "Can not update IP at DDNS Provider"
fi
# now we wait for check interval before testing if update was recognized
# only sleep if VERBOSE_MODE <= 2 because nothing send so do not wait
# only sleep if VERBOSE_MODE <= 2 because otherwise nothing was send
[ $VERBOSE_MODE -le 2 ] && {
verbose_echo " ****** WAITING =: $CHECK_SECONDS seconds (Check Interval) before continue "
sleep $CHECK_SECONDS
} || verbose_echo " VERBOSE MODE =: NO WAITING for Check Interval\n"
# read at DDNS service registered IP (in loop on error)
REGISTERED_IP = ""
ERR_REG_IP = 0
while : ; do
verbose_echo "******* DETECT =: Registered IP"
get_registered_ip REGISTERED_IP
ERR_LAST = $? # save return value
# No Error in function we leave while loop
[ $ERR_LAST -eq 0 ] && break
# we can't read Registered IP
if [ $VERBOSE_MODE -le 1 ] ; then # VERBOSE_MODE <=1 then retry
ERR_REG_IP = $(( $ERR_REG_IP + 1 ))
[ $ERR_REG_IP -gt $retry_count ] && critical_error "can not detect registered local IP"
verbose_echo " \n!!!!!!!!! ERROR =: detecting Registered IP - retry $ERR_REG_IP / $retry_count in $RETRY_SECONDS seconds\n "
syslog_err " Error detecting Registered IP - retry $ERR_REG_IP / $retry_count in $RETRY_SECONDS seconds "
sleep $RETRY_SECONDS
else
verbose_echo "\n!!!!!!!!! ERROR =: detecting Registered IP - NO retry\n"
break # leave while loop
fi
done
write_log 7 " Waiting $CHECK_SECONDS seconds (Check Interval) "
sleep $CHECK_SECONDS &
PID_SLEEP = $!
wait $PID_SLEEP # enable trap-handler
PID_SLEEP = 0
} || write_log 7 " Verbose Mode: $VERBOSE_MODE - NO Check Interval waiting "
REGISTERED_IP = "" # clear variable
get_registered_ip REGISTERED_IP # get registered/public IP
# IP's are still different
if [ " $LOCAL_IP " != " $REGISTERED_IP " ] ; then
if [ $VERBOSE_MODE -le 1 ] ; then # VERBOSE_MODE <=1 then retry
ERR_UPDATE = $(( $ERR_UPDATE + 1 ))
[ $ERR_UPDATE -gt $retry_count ] && critical_error " Registered IP <> Local IP - LocalIP: ' $LOCAL_IP ' - RegisteredIP: ' $REGISTERED_IP ' "
verbose_echo " \n!!!!!!!!! ERROR =: Registered IP <> Local IP - starting retry $ERR_UPDATE / $retry_count \n "
syslog_warn " Warning: Registered IP <> Local IP - starting retry $ERR_UPDATE / $retry_count "
[ $ERR_UPDATE -gt $retry_count ] && write_log 14 " Updating IP at DDNS provider failed after $retry_count retries "
write_log 4 " Updating IP at DDNS provider failed - starting retry $ERR_UPDATE / $retry_count "
continue # loop to beginning
else
verbose_echo " \n!!!!!!!!! ERROR =: Registered IP <> Local IP - LocalIP: ' $LOCAL_IP ' - RegisteredIP: ' $REGISTERED_IP ' - NO retry\n "
write_log 4 "Updating IP at DDNS provider failed"
write_log 7 " Verbose Mode: $VERBOSE_MODE - NO retry " ; exit 1
fi
fi
# we checked successful the last update
ERR_UPDATE = 0 # reset error counter
else
# we checked successful the last update
ERR_UPDATE = 0 # reset error counter
fi
# force_update=0 or VERBOSE_MODE > 1 - leave the main loop
[ $FORCE_SECONDS -eq 0 -o $VERBOSE_MODE -gt 1 ] && {
verbose_echo " ****** LEAVING =: $( eval $DATE_PROG ) "
syslog_info "Leaving"
break
}
verbose_echo " ********* LOOP =: $( eval $DATE_PROG ) "
syslog_info "Rerun IP check"
# force_update=0 or VERBOSE_MODE > 1 - leave here
[ $VERBOSE_MODE -gt 1 ] && write_log 7 " Verbose Mode: $VERBOSE_MODE - NO reloop " ; exit 0
[ $FORCE_SECONDS -eq 0 ] && write_log 6 "Configured to run once" ; exit 0
write_log 6 " Rerun IP check at $( eval $DATE_PROG ) "
done
verbose_echo " ****** STOPPED =: PID ' $$ ' at $( eval $DATE_PROG ) \n "
syslog_info "Done"
exit 0
# we should never come here there must be a programming error
write_log 12 "Error in 'dynamic_dns_updater.sh - program coding error"