From: Christian Schoenebeck Date: Sun, 21 Sep 2014 15:56:05 +0000 (+0200) Subject: [ddns-scripts] Update to Version 2.0.1-1 X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=df8f6c9d5d31fde24fe1d673949d272d887505e1;p=feed%2Fpackages.git [ddns-scripts] Update to Version 2.0.1-1 rewritten Sorry GitHub web interface only supports single commits that will be summarized into one pull request. Signed-off-by: Christian Schoenebeck --- diff --git a/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh index e6d298740d..20e40b310d 100755 --- a/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh +++ b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh @@ -1,360 +1,399 @@ #!/bin/sh -# /usr/lib/dynamic_dns/dynamic_dns_updater.sh +# /usr/lib/ddns/dynamic_dns_updater.sh # -# Written by Eric Paul Bishop, Janary 2008 +# Original written by Eric Paul Bishop, January 2008 # Distributed under the terms of the GNU General Public License (GPL) version 2.0 -# -# This script is (loosely) based on the one posted by exobyte in the forums here: +# (Loosely) based on the script on the one posted by exobyte in the forums here: # http://forum.openwrt.org/viewtopic.php?id=14040 # - -. /usr/lib/ddns/dynamic_dns_functions.sh - - -service_id=$1 -if [ -z "$service_id" ] -then - echo "ERRROR: You must specify a service id (the section name in the /etc/config/ddns file) to initialize dynamic DNS." - return 1 -fi - -#default mode is verbose_mode, but easily turned off with second parameter -verbose_mode="1" -if [ -n "$2" ] -then - verbose_mode="$2" -fi - -############################################################### -# Leave this comment here, to clearly document variable names -# that are expected/possible +# extended and partial rewritten by Christian Schoenebeck in August 2014 to support: +# - IPv6 DDNS services +# - DNS Server to retrieve registered IP including TCP transport +# - Proxy Server to send out updates +# - force_interval=0 to run once +# - 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 # -# Now use load_all_config_options to load config -# options, which is a much more flexible solution. +# variables in small chars are read from /etc/config/ddns +# variables in big chars are defined inside these scripts as global vars +# variables in big chars beginning with "__" are local defined inside functions only +#set -vx #script debugger + +[ $# -lt 1 -o -n "${2//[0-3]/}" -o ${#2} -gt 1 ] && { + echo -e "\n USAGE:" + echo -e " $0 [SECTION] [VERBOSE_MODE]\n" + echo " [SECTION] - service section as defined in /etc/config/ddns" + echo " [VERBOSE_MODE] - '0' NO output to console" + echo " '1' output to console" + echo " '2' output to console AND logfile" + echo " + run once WITHOUT retry on error" + echo " '3' output to console AND logfile" + echo " + run once WITHOUT retry on error" + echo -e " + NOT sending update to DDNS service\n" + exit 1 +} + +. /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 + +# set file names +PIDFILE="$RUNDIR/$SECTION_ID.pid" # Process ID file +UPDFILE="$RUNDIR/$SECTION_ID.update" # last update successful send (system uptime) +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 +[ $VERBOSE_MODE -gt 1 -a -f $LOGFILE ] && rm -f $LOGFILE + +################################################################################ +# 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 $SECTION_ID # -#config_load "ddns" +# defined options (also used as variable): +# +# enable self-explanatory +# interface network interface used by hotplug.d i.e. 'wan' or 'wan6' # -#config_get enabled $service_id enabled -#config_get service_name $service_id service_name -#config_get update_url $service_id update_url +# service_name Which DDNS service do you use or "custom" +# update_url URL to use to update your "custom" DDNS service # +# domain Your DNS name / replace [DOMAIN] in update_url +# username Username of your DDNS service account / replace [USERNAME] in update_url +# password Password of your DDNS service account / replace [PASSWORD] in update_url # -#config_get username $service_id username -#config_get password $service_id password -#config_get domain $service_id domain +# use_https use HTTPS to update DDNS service +# cacert file or directory where HTTPS can find certificates to verify server; 'IGNORE' ignore check of server certificate # +# use_syslog log activity to syslog # -#config_get use_https $service_id use_https -#config_get use_syslog $service_id use_syslog -#config_get cacert $service_id cacert +# ip_source source to detect current local IP ('network' or 'web' or 'script' or 'interface') +# ip_network local defined network to read IP from i.e. 'wan' or 'wan6' +# ip_url URL to read local address from i.e. http://checkip.dyndns.com/ or http://checkipv6.dyndns.com/ +# ip_script full path and name of your script to detect local IP +# ip_interface physical interface to use for detecting # -#config_get ip_source $service_id ip_source -#config_get ip_interface $service_id ip_interface -#config_get ip_network $service_id ip_network -#config_get ip_url $service_id ip_url +# check_interval check for changes every !!! checks below 10 minutes make no sense because the Internet +# check_unit 'days' 'hours' 'minutes' !!! needs about 5-10 minutes to sync an IP-change for an DNS entry # -#config_get force_interval $service_id force_interval -#config_get force_unit $service_id force_unit +# force_interval force to send an update to your service if no change was detected +# force_unit 'days' 'hours' 'minutes' !!! force_interval="0" runs this script once for use i.e. with cron # -#config_get check_interval $service_id check_interval -#config_get check_unit $service_id check_unit -######################################################### -load_all_config_options "ddns" "$service_id" - - -#some defaults -if [ -z "$check_interval" ] -then - check_interval=600 -fi - -if [ -z "$retry_interval" ] -then - retry_interval=60 -fi - -if [ -z "$check_unit" ] -then - check_unit="seconds" -fi - -if [ -z "$force_interval" ] -then - force_interval=72 -fi - -if [ -z "$force_unit" ] -then - force_unit="hours" -fi - -if [ -z $use_syslog ] -then - use_syslog=0 -fi - -if [ -z "$use_https" ] -then - use_https=0 -fi - - -#some constants - -retrieve_prog="/usr/bin/wget -O - "; -if [ "x$use_https" = "x1" ] -then - /usr/bin/wget --version 2>&1 |grep -q "\+ssl" - if [ $? -eq 0 ] - then - if [ -f "$cacert" ] - then - retrieve_prog="${retrieve_prog}--ca-certificate=${cacert} " - elif [ -d "$cacert" ] - then - retrieve_prog="${retrieve_prog}--ca-directory=${cacert} " - fi - else - retrieve_prog="/usr/bin/curl " - if [ -f "$cacert" ] - then - retrieve_prog="${retrieve_prog}--cacert $cacert " - elif [ -d "$cacert" ] - then - retrieve_prog="${retrieve_prog}--capath $cacert " - fi - fi -fi - - -service_file="/usr/lib/ddns/services" - -ip_regex="[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" - -NEWLINE_IFS=' -' - -#determine what update url we're using if the service_name is supplied -if [ -n "$service_name" ] -then - #remove any lines not containing data, and then make sure fields are enclosed in double quotes - quoted_services=$(cat $service_file | grep "^[\t ]*[^#]" | awk ' gsub("\x27", "\"") { if ($1~/^[^\"]*$/) $1="\""$1"\"" }; { if ( $NF~/^[^\"]*$/) $NF="\""$NF"\"" }; { print $0 }' ) - - - #echo "quoted_services = $quoted_services" - OLD_IFS=$IFS - IFS=$NEWLINE_IFS - for service_line in $quoted_services - do - #grep out proper parts of data and use echo to remove quotes - next_name=$(echo $service_line | grep -o "^[\t ]*\"[^\"]*\"" | xargs -r -n1 echo) - next_url=$(echo $service_line | grep -o "\"[^\"]*\"[\t ]*$" | xargs -r -n1 echo) - - if [ "$next_name" = "$service_name" ] - then - update_url=$next_url - fi - done - IFS=$OLD_IFS -fi - -if [ "x$use_https" = x1 ] -then - update_url=$(echo $update_url | sed -e 's/^http:/https:/') -fi - -verbose_echo "update_url=$update_url" - -#if this service isn't enabled then quit -if [ "$enabled" != "1" ] -then - return 0 -fi - -#compute update interval in seconds -case "$force_unit" in - "days" ) - force_interval_seconds=$(($force_interval*60*60*24)) - ;; - "hours" ) - force_interval_seconds=$(($force_interval*60*60)) - ;; - "minutes" ) - force_interval_seconds=$(($force_interval*60)) - ;; - "seconds" ) - force_interval_seconds=$force_interval - ;; - * ) - #default is hours - force_interval_seconds=$(($force_interval*60*60)) - ;; -esac - - -#compute check interval in seconds -case "$check_unit" in - "days" ) - check_interval_seconds=$(($check_interval*60*60*24)) - ;; - "hours" ) - check_interval_seconds=$(($check_interval*60*60)) - ;; - "minutes" ) - check_interval_seconds=$(($check_interval*60)) - ;; - "seconds" ) - check_interval_seconds=$check_interval - ;; - * ) - #default is seconds - check_interval_seconds=$check_interval - ;; -esac - - -#compute retry interval in seconds -case "$retry_unit" in - "days" ) - retry_interval_seconds=$(($retry_interval*60*60*24)) - ;; - "hours" ) - retry_interval_seconds=$(($retry_interval*60*60)) - ;; - "minutes" ) - retry_interval_seconds=$(($retry_interval*60)) - ;; - "seconds" ) - retry_interval_seconds=$retry_interval - ;; - * ) - #default is seconds - retry_interval_seconds=$retry_interval - ;; +# retry_interval if error was detected retry in +# retry_unit 'days' 'hours' 'minutes' 'seconds' +# retry_count #NEW# number of retries before scripts stops +# +# use_ipv6 #NEW# detecting/sending IPv6 address +# force_ipversion #NEW# force usage of IPv4 or IPv6 for the whole detection and update communication +# dns_server #NEW# using a non default dns server to get Registered IP from Internet +# force_dnstcp #NEW# force communication with DNS server via TCP instead of default UDP +# proxy #NEW# using a proxy for communication !!! ALSO used to detect local IP via web => return proxy's IP !!! +# use_logfile #NEW# self-explanatory "/var/log/ddns/$SECTION_ID.log" +# +# some functionality needs +# - GNU Wget or cURL installed for sending updates to DDNS service +# - BIND host installed to detect Registered IP +# +################################################################################ + +# verify and load SECTION_ID is exists +[ "$(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" +} +load_all_config_options "ddns" "$SECTION_ID" + +verbose_echo "\n ************** =: ************** ************** **************" +verbose_echo " STARTED =: PID '$$' at $(eval $DATE_PROG)" +syslog_info "Started" +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'" esac +verbose_echo " UCI CONFIG =:\n$(uci -q show ddns.$SECTION_ID | sort)" + +# set defaults if not defined +[ -z "$enabled" ] && enabled=0 +[ -z "$retry_count" ] && retry_count=5 +[ -z "$use_syslog" ] && use_syslog=0 # not use syslog +[ -z "$use_https" ] && use_https=0 # not use https +[ -z "$use_logfile" ] && use_logfile=1 # NEW - use logfile by default +[ -z "$use_ipv6" ] && use_ipv6=0 # NEW - use IPv4 by default +[ -z "$force_ipversion" ] && force_ipversion=0 # NEW - default let system decide +[ -z "$force_dnstcp" ] && force_dnstcp=0 # NEW - default UDP +[ -z "$ip_source" ] && ip_source="network" +[ "$ip_source" = "network" -a -z "$ip_network" -a $use_ipv6 -eq 0 ] && ip_network="wan" # IPv4: default wan +[ "$ip_source" = "network" -a -z "$ip_network" -a $use_ipv6 -eq 1 ] && ip_network="wan6" # IPv6: default wan6 +[ "$ip_source" = "web" -a -z "$ip_url" -a $use_ipv6 -eq 0 ] && ip_url="http://checkip.dyndns.com" +[ "$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" + +# verify 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" +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" -verbose_echo "force seconds = $force_interval_seconds" -verbose_echo "check seconds = $check_interval_seconds" +# determine what update url we're using if a service_name is supplied +# otherwise update_url is set inside configuration (custom service) +[ -n "$service_name" ] && get_service_url update_url +[ -z "$update_url" ] && critical_error "no update url found/defined" #kill old process if it exists & set new pid file -if [ -d /var/run/dynamic_dns ] -then +if [ -d $RUNDIR ]; then #if process is already running, stop it - if [ -e "/var/run/dynamic_dns/$service_id.pid" ] - then - old_pid=$(cat /var/run/dynamic_dns/$service_id.pid) - test_match=$(ps | grep "^[\t ]*$old_pid") - verbose_echo "old process id (if it exists) = \"$test_match\"" - if [ -n "$test_match" ] - then - kill $old_pid - fi + 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 - else #make dir since it doesn't exist - mkdir /var/run/dynamic_dns + mkdir -p $RUNDIR + verbose_echo "old process id =: PID 'none'" fi -echo $$ > /var/run/dynamic_dns/$service_id.pid - - - - -#determine when the last update was -current_time=$(monotonic_time) -last_update=$(( $current_time - (2*$force_interval_seconds) )) -if [ -e "/var/run/dynamic_dns/$service_id.update" ] -then - last_update=$(cat /var/run/dynamic_dns/$service_id.update) +echo $$ > $PIDFILE + +# determine when the last update was +# the following lines should prevent multiple updates if hotplug fires multiple startups +# as described in Ticket #7820, but did not function if never an update take place +# i.e. after a reboot (/var is linked to /tmp) +# using uptime as reference because date might not be updated via NTP client +get_uptime CURR_TIME +[ -e "$UPDFILE" ] && { + LAST_TIME=$(cat $UPDFILE) + # check also LAST > CURR because link of /var/run to /tmp might be removed + # i.e. boxes with larger filesystems + [ -z "$LAST_TIME" ] && LAST_TIME=0 + [ $LAST_TIME -gt $CURR_TIME ] && LAST_TIME=0 +} +if [ $LAST_TIME -eq 0 ]; then + verbose_echo " 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)" fi -time_since_update=$(($current_time - $last_update)) - - -human_time_since_update=$(( $time_since_update / ( 60 * 60 ) )) -verbose_echo "time_since_update = $human_time_since_update hours" - - -#do update and then loop endlessly, checking ip every check_interval and forcing an updating once every force_interval - -while [ true ] -do - registered_ip=$(echo $(nslookup "$domain" 2>/dev/null) | grep -o "Name:.*" | grep -o "$ip_regex") - current_ip=$(get_current_ip) - - - current_time=$(monotonic_time) - time_since_update=$(($current_time - $last_update)) - - syslog_echo "Running IP check ..." - verbose_echo "Running IP check..." - verbose_echo "current system ip = $current_ip" - verbose_echo "registered domain ip = $registered_ip" - - - if [ "$current_ip" != "$registered_ip" ] || [ $force_interval_seconds -lt $time_since_update ] - then - verbose_echo "update necessary, performing update ..." - - #do replacement - final_url=$update_url - for option_var in $ALL_OPTION_VARIABLES - do - if [ "$option_var" != "update_url" ] - then - replace_name=$(echo "\[$option_var\]" | tr 'a-z' 'A-Z') - replace_value=$(eval echo "\$$option_var") - replace_value=$(echo $replace_value | sed -f /usr/lib/ddns/url_escape.sed) - final_url=$(echo $final_url | sed s^"$replace_name"^"$replace_value"^g ) +# 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 +[ -n "$dns_server" ] && { + verbose_echo "******* VERIFY =: DNS server '$dns_server'" + verify_dns "$dns_server" + case $? in + 0) ;; # everything OK + 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";; + 4) critical_error "Invalid DNS server Error: '4' - Forced IP Version don't matched";; + *) critical_error "Invalid DNS server Error: '1' - unspecific error";; + esac +} + +# verify Proxy server and set environment +[ -n "$proxy" ] && { + verbose_echo "******* VERIFY =: Proxy server 'http://$proxy'" + verify_proxy "$proxy" + case $? in + 0) # everything OK + export HTTP_PROXY="http://$proxy" + export HTTPS_PROXY="http://$proxy" + export http_proxy="http://$proxy" + export https_proxy="http://$proxy" + ;; + 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";; + 4) critical_error "Invalid Proxy server Error: '4' - Forced IP Version don't matched";; + 5) critical_error "Invalid Proxy server Error: '5' - proxy port missing";; + *) critical_error "Invalid Proxy server Error: '1' - unspecific error";; + esac +} + +# 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 + +# 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" + +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 + + # prepare update + # 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 + if [ $VERBOSE_MODE -gt 2 ]; then + verbose_echo " VERBOSE MODE =: NO UPDATE send to DDNS provider" + elif [ "$LOCAL_IP" != "$REGISTERED_IP" ]; then + verbose_echo "******* UPDATE =: LOCAL: '$LOCAL_IP' <=> REGISTERED: '$REGISTERED_IP'" + else + verbose_echo "******* FORCED =: LOCAL: '$LOCAL_IP' == REGISTERED: '$REGISTERED_IP'" + fi + # only send if VERBOSE_MODE < 3 + ERR_LAST=0 + [ $VERBOSE_MODE -lt 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 - done - final_url=$(echo $final_url | sed s^"\[HTTPAUTH\]"^"${username//^/\\^}${password:+:${password//^/\\^}}"^g ) - final_url=$(echo $final_url | sed s/"\[IP\]"/"$current_ip"/g ) - - - verbose_echo "updating with url=\"$final_url\"" - - #here we actually connect, and perform the update - update_output=$( $retrieve_prog "$final_url" ) - if [ $? -gt 0 ] - then - syslog_echo "update failed, retrying in $retry_interval_seconds seconds" - verbose_echo "update failed" - sleep $retry_interval_seconds - continue + else + # we send data so save "last time" + get_uptime LAST_TIME + 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 - syslog_echo "Update successful" - verbose_echo "Update Output:" - verbose_echo "$update_output" - verbose_echo "" - - #save the time of the update - current_time=$(monotonic_time) - last_update=$current_time - time_since_update='0' - registered_ip=$current_ip - - human_time=$(date) - verbose_echo "update complete, time is: $human_time" + done - echo "$last_update" > "/var/run/dynamic_dns/$service_id.update" - else - human_time=$(date) - human_time_since_update=$(( $time_since_update / ( 60 * 60 ) )) - verbose_echo "update unnecessary" - verbose_echo "time since last update = $human_time_since_update hours" - verbose_echo "the time is now $human_time" - 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 + [ $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 - #sleep for 10 minutes, then re-check ip && time since last update - sleep $check_interval_seconds + # 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" + continue # loop to beginning + else + verbose_echo "\n!!!!!!!!! ERROR =: Registered IP <> Local IP - LocalIP: '$LOCAL_IP' - RegisteredIP: '$REGISTERED_IP' - NO retry\n" + fi + fi + + # we checked successful the last update + ERR_UPDATE=0 # reset error counter + + # 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" done -#should never get here since we're a daemon, but I'll throw it in anyway -return 0 - - - +verbose_echo "****** STOPPED =: PID '$$' at $(eval $DATE_PROG)\n" +syslog_info "Done" +exit 0