Merge pull request #546 from chris5560/master

ddns-scripts: new Version 2.1.0-2
This commit is contained in:
sbyx 2014-11-16 11:35:24 +01:00
commit f8a5222531
15 changed files with 550 additions and 262 deletions

View file

@ -1,3 +1,28 @@
Version 2.1.0-2
Date 2014-11-15
- moved /usr/lib/ddns/dynamic_dns_lucihelper.sh from luci-app-ddns into this package
(Github openwrt/luci issue 251)
(OpenWrt Trac tickets 18326 18347)
- fix: dynamic_dns_update.sh did not loop
(OpenWrt Trac ticket 18336)
- add provider cloudflare.com IPv4 and IPv6 (Thanks to Paul for support and testing)
(OpenWrt Trac ticket 12500)
- modified detection, if dynamic_dns_fuctions are used by dynamic_dns_lucihelper.sh
- redirect stdout of wget,curl,host,nslookup,nc etc to /tmp/ddns_$$.dat and *.err instead of variables
- extended error detection in get_local_ip function
- modified verify of option ip_script to allow parameters, when calling
- add provider selfhost.de IPv4
- add provider no-ip.pl (nothing to do with no-ip.com)
(Github openwrt/packages issue #542)
IPv4 (tested) and also added for
IPv6 (NOT tested) because client IP is autodetected be provider
- add getlocalip_sample.sh as sample script for usage of
option ip_source 'script' together with
option ip_script '/usr/lib/ddns/getlocalip.sh -4'
- cleanup whitespaces at line ends
--------------------------------------------------------------------------------
Version 2.1.0-1 Version 2.1.0-1
Date 2014-11-09 Date 2014-11-09

View file

@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=ddns-scripts PKG_NAME:=ddns-scripts
PKG_VERSION:=2.1.0 PKG_VERSION:=2.1.0
PKG_RELEASE:=1 PKG_RELEASE:=2
PKG_LICENSE:=GPL-2.0 PKG_LICENSE:=GPL-2.0
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
@ -67,6 +67,11 @@ define Package/ddns-scripts/postinst
# remove old sed script file # remove old sed script file
[ -f /usr/lib/ddns/url_escape.sed ] && rm -f /usr/lib/ddns/url_escape.sed [ -f /usr/lib/ddns/url_escape.sed ] && rm -f /usr/lib/ddns/url_escape.sed
# luci updates are not in sync with ddns-script updates !!!
# if old luci-app-ddns then errors during install because exist from differnt package
# copy dynamic_dns_helper.tmp.sh -> dynamic_dns_helper.sh
cp -f /usr/lib/ddns/dynamic_dns_lucihelper.tmp.sh /usr/lib/ddns/dynamic_dns_lucihelper.sh
# add new section "ddns" "global" if not exists # add new section "ddns" "global" if not exists
uci -q get ddns.global > /dev/null || uci -q set ddns.global='ddns' uci -q get ddns.global > /dev/null || uci -q set ddns.global='ddns'
uci -q get ddns.global.date_format > /dev/null || uci -q set ddns.global.date_format='%F %R' uci -q get ddns.global.date_format > /dev/null || uci -q set ddns.global.date_format='%F %R'

View file

@ -7,7 +7,7 @@ boot() {
} }
reload() { reload() {
killall -1 dynamic_dns_updater.sh # send SIGHUP killall -1 dynamic_dns_updater.sh 2>/dev/null # send SIGHUP
} }
restart() { restart() {
@ -22,5 +22,5 @@ start() {
} }
stop() { stop() {
killall dynamic_dns_updater.sh killall dynamic_dns_updater.sh 2>/dev/null
} }

View file

@ -1,34 +0,0 @@
#!/bin/sh
#
#set -vx
[ -d /etc/ssl/certs ] || {
echo "CA-Certificates not istalled - please install first"
exit 1
}
NUMCERT=$(find /etc/ssl/certs -name *.crt 2>/dev/null | wc -l)
NUMLINK=$(find /etc/ssl/certs -type l 2>/dev/null | wc -l)
[ $NUMLINK -gt 0 ] && {
echo "File-Links already exist. Exiting"
exit 0
}
[ -f /usr/bin/openssl ] && OPENSSL="EXIST"
[ -z "$OPENSSL" ] && {
opkg update || exit 1
opkg install openssl-util 2>/dev/null
}
for CERTFILE in `ls -1 $(1)/etc/ssl/certs`; do \
HASH=`openssl x509 -hash -noout -in /etc/ssl/certs/$CERTFILE`
SUFFIX=0
while [ -h "/etc/ssl/certs/$HASH.$SUFFIX" ]; do
let "SUFFIX += 1"
done
ln -s "$CERTFILE" "/etc/ssl/certs/$HASH.$SUFFIX"
echo "link $HASH.$SUFFIX created for $CERTFILE"
done
[ -z "$OPENSSL" ] && opkg remove --force-remove --autoremove openssl-util 2>/dev/null

View file

@ -32,14 +32,16 @@
SECTION_ID="" # hold config's section name SECTION_ID="" # hold config's section name
VERBOSE_MODE=1 # default mode is log to console, but easily changed with parameter VERBOSE_MODE=1 # default mode is log to console, but easily changed with parameter
PIDFILE="" # pid file
UPDFILE="" # store UPTIME of last update
# directory to store run information to. # directory to store run information to.
RUNDIR=$(uci -q get ddns.global.run_dir) || RUNDIR="/var/run/ddns" RUNDIR=$(uci -q get ddns.global.run_dir) || RUNDIR="/var/run/ddns"
# NEW # directory to store log files # NEW # directory to store log files
LOGDIR=$(uci -q get ddns.global.log_dir) || LOGDIR="/var/log/ddns" LOGDIR=$(uci -q get ddns.global.log_dir) || LOGDIR="/var/log/ddns"
LOGFILE="" # NEW # logfile can be enabled as new option LOGFILE="" # NEW # logfile can be enabled as new option
PIDFILE="" # pid file
UPDFILE="" # store UPTIME of last update
DATFILE="/tmp/ddns_$$.dat" # save stdout data of WGet and other extern programs called
ERRFILE="/tmp/ddns_$$.err" # save stderr output of WGet and other extern programs called
# number of lines to before rotate logfile # number of lines to before rotate logfile
LOGLINES=$(uci -q get ddns.global.log_lines) || LOGLINES=250 LOGLINES=$(uci -q get ddns.global.log_lines) || LOGLINES=250
LOGLINES=$((LOGLINES + 1)) # correct sed handling LOGLINES=$((LOGLINES + 1)) # correct sed handling
@ -74,6 +76,9 @@ IPV4_REGEX="[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
# IPv6 ( ( 0-9a-f 1-4char ":") min 1x) ( ( 0-9a-f 1-4char )optional) ( (":" 0-9a-f 1-4char ) min 1x) # IPv6 ( ( 0-9a-f 1-4char ":") min 1x) ( ( 0-9a-f 1-4char )optional) ( (":" 0-9a-f 1-4char ) min 1x)
IPV6_REGEX="\(\([0-9A-Fa-f]\{1,4\}:\)\{1,\}\)\(\([0-9A-Fa-f]\{1,4\}\)\{0,1\}\)\(\(:[0-9A-Fa-f]\{1,4\}\)\{1,\}\)" IPV6_REGEX="\(\([0-9A-Fa-f]\{1,4\}:\)\{1,\}\)\(\([0-9A-Fa-f]\{1,4\}\)\{0,1\}\)\(\(:[0-9A-Fa-f]\{1,4\}\)\{1,\}\)"
# detect if called by dynamic_dns_lucihelper.sh script, disable retrys (empty variable == false)
[ "$(basename $0)" = "dynamic_dns_lucihelper.sh" ] && LUCI_HELPER="TRUE" || LUCI_HELPER=""
# loads all options for a given package and section # loads all options for a given package and section
# also, sets all_option_variables to a list of the variable names # also, sets all_option_variables to a list of the variable names
# $1 = ddns, $2 = SECTION_ID # $1 = ddns, $2 = SECTION_ID
@ -123,7 +128,7 @@ load_all_service_sections() {
} }
config_load "ddns" config_load "ddns"
eval "$1='$__DATA'" eval "$1=\"$__DATA\""
return return
} }
@ -224,7 +229,7 @@ write_log() {
# VERBOSE_MODE > 1 then NO loop so NO truncate log to $LOGLINES lines # VERBOSE_MODE > 1 then NO loop so NO truncate log to $LOGLINES lines
[ $VERBOSE_MODE -gt 1 ] || sed -i -e :a -e '$q;N;'$LOGLINES',$D;ba' $LOGFILE [ $VERBOSE_MODE -gt 1 ] || sed -i -e :a -e '$q;N;'$LOGLINES',$D;ba' $LOGFILE
fi fi
[ "$SECTION_ID" = "lucihelper" ] && return # nothing else todo when running LuCI helper script [ $LUCI_HELPER ] && return # nothing else todo when running LuCI helper script
[ $__LEVEL -eq 7 ] && return # no syslog for debug messages [ $__LEVEL -eq 7 ] && return # no syslog for debug messages
[ $__EXIT -eq 1 ] && { [ $__EXIT -eq 1 ] && {
$__CMD # force syslog before exit $__CMD # force syslog before exit
@ -272,7 +277,7 @@ urlencode() {
__POS=$(( $__POS + 1 )) # increment position __POS=$(( $__POS + 1 )) # increment position
done done
eval "$1='$__ENC'" # transfer back to variable eval "$1=\"$__ENC\"" # transfer back to variable
return 0 return 0
} }
@ -313,8 +318,8 @@ get_service_data() {
__URL=$(echo "$__DATA" | grep "^http:") __URL=$(echo "$__DATA" | grep "^http:")
[ -z "$__URL" ] && __SCRIPT="/usr/lib/ddns/$__DATA" [ -z "$__URL" ] && __SCRIPT="/usr/lib/ddns/$__DATA"
eval "$1='$__URL'" eval "$1=\"$__URL\""
eval "$2='$__SCRIPT'" eval "$2=\"$__SCRIPT\""
return 0 return 0
} }
@ -438,7 +443,7 @@ timeout() {
verify_host_port() { verify_host_port() {
local __HOST=$1 local __HOST=$1
local __PORT=$2 local __PORT=$2
local __TMP __IP __IPV4 __IPV6 __RUNPROG __ERRPROG __ERR local __IP __IPV4 __IPV6 __RUNPROG __ERR
# return codes # return codes
# 1 system specific error # 1 system specific error
# 2 nslookup error # 2 nslookup error
@ -447,20 +452,19 @@ verify_host_port() {
[ $# -ne 2 ] && write_log 12 "Error calling 'verify_host_port()' - wrong number of parameters" [ $# -ne 2 ] && write_log 12 "Error calling 'verify_host_port()' - wrong number of parameters"
__RUNPROG="nslookup $__HOST 2>/dev/null" __RUNPROG="/usr/bin/nslookup $__HOST >$DATFILE 2>$ERRFILE"
__ERRPROG="nslookup $__HOST 2>&1"
write_log 7 "#> $__RUNPROG" write_log 7 "#> $__RUNPROG"
__TMP=$(eval $__RUNPROG) # test if nslookup runs without errors eval $__RUNPROG
__ERR=$? __ERR=$?
# command error # command error
[ $__ERR -gt 0 ] && { [ $__ERR -gt 0 ] && {
write_log 7 "Error:\n$(eval $__ERRPROG)"
write_log 3 "DNS Resolver Error - BusyBox nslookup Error '$__ERR'" write_log 3 "DNS Resolver Error - BusyBox nslookup Error '$__ERR'"
write_log 7 "Error:\n$(cat $ERRFILE)"
return 2 return 2
} }
# extract IP address # extract IP address
__IPV4=$(echo "$__TMP" | sed -ne "3,\$ { s/^Address [0-9]*: \($IPV4_REGEX\).*$/\\1/p }") __IPV4=$(cat $DATFILE | sed -ne "3,\$ { s/^Address [0-9]*: \($IPV4_REGEX\).*$/\\1/p }")
__IPV6=$(echo "$__TMP" | sed -ne "3,\$ { s/^Address [0-9]*: \($IPV6_REGEX\).*$/\\1/p }") __IPV6=$(cat $DATFILE | sed -ne "3,\$ { s/^Address [0-9]*: \($IPV6_REGEX\).*$/\\1/p }")
# check IP version if forced # check IP version if forced
if [ $force_ipversion -ne 0 ]; then if [ $force_ipversion -ne 0 ]; then
@ -468,17 +472,17 @@ verify_host_port() {
[ $use_ipv6 -eq 0 -a -z "$__IPV4" ] && __ERR=4 [ $use_ipv6 -eq 0 -a -z "$__IPV4" ] && __ERR=4
[ $use_ipv6 -eq 1 -a -z "$__IPV6" ] && __ERR=6 [ $use_ipv6 -eq 1 -a -z "$__IPV6" ] && __ERR=6
[ $__ERR -gt 0 ] && { [ $__ERR -gt 0 ] && {
[ "$SECTION_ID" = "lucihelper" ] && return 4 [ $LUCI_HELPER ] && return 4
write_log 14 "Invalid host Error '4' - Forced IP Version IPv$__ERR don't match" write_log 14 "Verify host Error '4' - Forced IP Version IPv$__ERR don't match"
} }
fi fi
# verify nc command # verify nc command
# busybox nc compiled without -l option "NO OPT l!" -> critical error # busybox nc compiled without -l option "NO OPT l!" -> critical error
nc --help 2>&1 | grep -i "NO OPT l!" >/dev/null 2>&1 && \ /usr/bin/nc --help 2>&1 | grep -i "NO OPT l!" >/dev/null 2>&1 && \
write_log 12 "Busybox nc (netcat) compiled without '-l' option, error 'NO OPT l!'" write_log 12 "Busybox nc (netcat) compiled without '-l' option, error 'NO OPT l!'"
# busybox nc compiled with extensions # busybox nc compiled with extensions
nc --help 2>&1 | grep "\-w" >/dev/null 2>&1 && __NCEXT="TRUE" /usr/bin/nc --help 2>&1 | grep "\-w" >/dev/null 2>&1 && __NCEXT="TRUE"
# connectivity test # connectivity test
# run busybox nc to HOST PORT # run busybox nc to HOST PORT
@ -488,18 +492,17 @@ verify_host_port() {
# so if not "force_ipversion" to use_ipv6 then connect test via ipv4, if availible # so if not "force_ipversion" to use_ipv6 then connect test via ipv4, if availible
[ $force_ipversion -ne 0 -a $use_ipv6 -ne 0 -o -z "$__IPV4" ] && __IP=$__IPV6 || __IP=$__IPV4 [ $force_ipversion -ne 0 -a $use_ipv6 -ne 0 -o -z "$__IPV4" ] && __IP=$__IPV6 || __IP=$__IPV4
if [ -n "$__NCEXT" ]; then # nc compiled with extensions (timeout support) if [ -n "$__NCEXT" ]; then # BusyBox nc compiled with extensions (timeout support)
__RUNPROG="nc -w 1 $__IP $__PORT </dev/null >/dev/null 2>&1" __RUNPROG="/usr/bin/nc -vw 1 $__IP $__PORT </dev/null >$DATFILE 2>$ERRFILE"
__ERRPROG="nc -vw 1 $__IP $__PORT </dev/null 2>&1"
write_log 7 "#> $__RUNPROG" write_log 7 "#> $__RUNPROG"
eval $__RUNPROG eval $__RUNPROG
__ERR=$? __ERR=$?
[ $__ERR -eq 0 ] && return 0 [ $__ERR -eq 0 ] && return 0
write_log 7 "Error:\n$(eval $__ERRPROG)"
write_log 3 "Connect error - BusyBox nc (netcat) Error '$__ERR'" write_log 3 "Connect error - BusyBox nc (netcat) Error '$__ERR'"
write_log 7 "Error:\n$(cat $ERRFILE)"
return 3 return 3
else # nc compiled without extensions (no timeout support) else # nc compiled without extensions (no timeout support)
__RUNPROG="timeout 2 -- nc $__IP $__PORT </dev/null >/dev/null 2>&1" __RUNPROG="timeout 2 -- /usr/bin/nc $__IP $__PORT </dev/null >$DATFILE 2>$ERRFILE"
write_log 7 "#> $__RUNPROG" write_log 7 "#> $__RUNPROG"
eval $__RUNPROG eval $__RUNPROG
__ERR=$? __ERR=$?
@ -518,16 +521,16 @@ verify_dns() {
[ $# -ne 1 ] && write_log 12 "Error calling 'verify_dns()' - wrong number of parameters" [ $# -ne 1 ] && write_log 12 "Error calling 'verify_dns()' - wrong number of parameters"
write_log 7 "Verify DNS server '$1'" write_log 7 "Verify DNS server '$1'"
while [ $__ERR -gt 0 ]; do while [ $__ERR -ne 0 ]; do
# DNS uses port 53 # DNS uses port 53
verify_host_port "$1" "53" verify_host_port "$1" "53"
__ERR=$? __ERR=$?
if [ "$SECTION_ID" = "lucihelper" ]; then # no retry if called by LuCI helper script if [ $LUCI_HELPER ]; then # no retry if called by LuCI helper script
return $__ERR return $__ERR
elif [ $__ERR -gt 0 -a $VERBOSE_MODE -gt 1 ]; then # VERBOSE_MODE > 1 then NO retry elif [ $__ERR -ne 0 -a $VERBOSE_MODE -gt 1 ]; then # VERBOSE_MODE > 1 then NO retry
write_log 7 "Verbose Mode: $VERBOSE_MODE - NO retry on error" write_log 4 "Verify DNS server '$1' failed - Verbose Mode: $VERBOSE_MODE - NO retry on error"
return $__ERR return $__ERR
elif [ $__ERR -gt 0 ]; then elif [ $__ERR -ne 0 ]; then
__CNT=$(( $__CNT + 1 )) # increment error counter __CNT=$(( $__CNT + 1 )) # increment error counter
# if error count > retry_count leave here # if error count > retry_count leave here
[ $__CNT -gt $retry_count ] && \ [ $__CNT -gt $retry_count ] && \
@ -575,17 +578,17 @@ verify_proxy() {
fi fi
# No Port detected - EXITING # No Port detected - EXITING
[ -z "$__PORT" ] && { [ -z "$__PORT" ] && {
[ "$SECTION_ID" = "lucihelper" ] && return 5 [ $LUCI_HELPER ] && return 5
write_log 14 "Invalid Proxy server Error '5' - proxy port missing" write_log 14 "Invalid Proxy server Error '5' - proxy port missing"
} }
while [ $__ERR -gt 0 ]; do while [ $__ERR -gt 0 ]; do
verify_host_port "$__HOST" "$__PORT" verify_host_port "$__HOST" "$__PORT"
__ERR=$? __ERR=$?
if [ "$SECTION_ID" = "lucihelper" ]; then # no retry if called by LuCI helper script if [ $LUCI_HELPER ]; then # no retry if called by LuCI helper script
return $__ERR return $__ERR
elif [ $__ERR -gt 0 -a $VERBOSE_MODE -gt 1 ]; then # VERBOSE_MODE > 1 then NO retry elif [ $__ERR -gt 0 -a $VERBOSE_MODE -gt 1 ]; then # VERBOSE_MODE > 1 then NO retry
write_log 7 "Verbose Mode: $VERBOSE_MODE - NO retry on error" write_log 4 "Verify Proxy server '$1' failed - Verbose Mode: $VERBOSE_MODE - NO retry on error"
return $__ERR return $__ERR
elif [ $__ERR -gt 0 ]; then elif [ $__ERR -gt 0 ]; then
__CNT=$(( $__CNT + 1 )) # increment error counter __CNT=$(( $__CNT + 1 )) # increment error counter
@ -604,18 +607,17 @@ verify_proxy() {
} }
do_transfer() { do_transfer() {
# $1 # Variable to store Answer of transfer # $1 # URL to use
# $2 # URL to use local __URL="$1"
local __URL="$2"
local __ERR=0 local __ERR=0
local __CNT=0 # error counter local __CNT=0 # error counter
local __PROG __RUNPROG __ERRPROG __DATA local __PROG __RUNPROG
[ $# -ne 2 ] && write_log 12 "Error in 'do_transfer()' - wrong number of parameters" [ $# -ne 1 ] && write_log 12 "Error in 'do_transfer()' - wrong number of parameters"
# lets prefer GNU Wget because it does all for us - IPv4/IPv6/HTTPS/PROXY/force IP version # lets prefer GNU Wget because it does all for us - IPv4/IPv6/HTTPS/PROXY/force IP version
if /usr/bin/wget --version 2>&1 | grep "\+ssl" >/dev/null 2>&1 ; then if /usr/bin/wget --version 2>&1 | grep "\+ssl" >/dev/null 2>&1 ; then
__PROG="/usr/bin/wget -t 2 -O -" # standard output only 2 retrys on error __PROG="/usr/bin/wget -nv -t 1 -O $DATFILE -o $ERRFILE" # non_verbose no_retry outfile errfile
# force ip version to use # force ip version to use
if [ $force_ipversion -eq 1 ]; then if [ $force_ipversion -eq 1 ]; then
[ $use_ipv6 -eq 0 ] && __PROG="$__PROG -4" || __PROG="$__PROG -6" # force IPv4/IPv6 [ $use_ipv6 -eq 0 ] && __PROG="$__PROG -4" || __PROG="$__PROG -6" # force IPv4/IPv6
@ -635,14 +637,13 @@ do_transfer() {
# disable proxy if no set (there might be .wgetrc or .curlrc or wrong environment set) # disable proxy if no set (there might be .wgetrc or .curlrc or wrong environment set)
[ -z "$proxy" ] && __PROG="$__PROG --no-proxy" [ -z "$proxy" ] && __PROG="$__PROG --no-proxy"
__RUNPROG="$__PROG -q '$__URL' 2>/dev/null" # do transfer with "-q" to suppress not needed output __RUNPROG="$__PROG $__URL" # build final command
__ERRPROG="$__PROG -d '$__URL' 2>&1" # do transfer with "-d" for debug mode
__PROG="GNU Wget" # reuse for error logging __PROG="GNU Wget" # reuse for error logging
# 2nd choice is cURL IPv4/IPv6/HTTPS # 2nd choice is cURL IPv4/IPv6/HTTPS
# libcurl might be compiled without Proxy Support (default in trunk) # libcurl might be compiled without Proxy Support (default in trunk)
elif [ -x /usr/bin/curl ]; then elif [ -x /usr/bin/curl ]; then
__PROG="/usr/bin/curl" __PROG="/usr/bin/curl -sS -o $DATFILE --stderr $ERRFILE"
# force ip version to use # force ip version to use
if [ $force_ipversion -eq 1 ]; then if [ $force_ipversion -eq 1 ]; then
[ $use_ipv6 -eq 0 ] && __PROG="$__PROG -4" || __PROG="$__PROG -6" # force IPv4/IPv6 [ $use_ipv6 -eq 0 ] && __PROG="$__PROG -4" || __PROG="$__PROG -6" # force IPv4/IPv6
@ -670,13 +671,12 @@ do_transfer() {
write_log 13 "cURL: libcurl compiled without Proxy support" write_log 13 "cURL: libcurl compiled without Proxy support"
fi fi
__RUNPROG="$__PROG -q '$__URL' 2>/dev/null" # do transfer with "-s" to suppress not needed output __RUNPROG="$__PROG $__URL" # build final command
__ERRPROG="$__PROG -v '$__URL' 2>&1" # do transfer with "-v" for verbose mode
__PROG="cURL" # reuse for error logging __PROG="cURL" # reuse for error logging
# busybox Wget (did not support neither IPv6 nor HTTPS) # busybox Wget (did not support neither IPv6 nor HTTPS)
elif [ -x /usr/bin/wget ]; then elif [ -x /usr/bin/wget ]; then
__PROG="/usr/bin/wget -O -" __PROG="/usr/bin/wget -q -O $DATFILE"
# force ip version not supported # force ip version not supported
[ $force_ipversion -eq 1 ] && \ [ $force_ipversion -eq 1 ] && \
write_log 14 "BusyBox Wget: can not force IP version to use" write_log 14 "BusyBox Wget: can not force IP version to use"
@ -686,8 +686,7 @@ do_transfer() {
# disable proxy if no set (there might be .wgetrc or .curlrc or wrong environment set) # disable proxy if no set (there might be .wgetrc or .curlrc or wrong environment set)
[ -z "$proxy" ] && __PROG="$__PROG -Y off" [ -z "$proxy" ] && __PROG="$__PROG -Y off"
__RUNPROG="$__PROG -q '$__URL' 2>/dev/null" # do transfer with "-q" to suppress not needed output __RUNPROG="$__PROG $__URL 2>$ERRFILE" # build final command
__ERRPROG="$__PROG '$__URL' 2>&1" #
__PROG="Busybox Wget" # reuse for error logging __PROG="Busybox Wget" # reuse for error logging
else else
@ -696,22 +695,17 @@ do_transfer() {
while : ; do while : ; do
write_log 7 "#> $__RUNPROG" write_log 7 "#> $__RUNPROG"
__DATA=$(eval $__RUNPROG) $__RUNPROG # DO transfer
__ERR=$? __ERR=$? # save error code
[ $__ERR -eq 0 ] && { [ $__ERR -eq 0 ] && return 0 # no error leave
eval "$1='$__DATA'" # everything ok [ $LUCI_HELPER ] && return 1 # no retry if called by LuCI helper script
return 0 # return
}
[ "$SECTION_ID" = "lucihelper" ] && return 1 # no retry if called by LuCI helper script write_log 3 "$__PROG Error: '$__ERR'"
write_log 7 "$(cat $ERRFILE)" # report error
write_log 7 "Error:\n$(eval $__ERRPROG)" # report error
write_log 3 "$__PROG error: '$__ERR'"
__DATA=""
[ $VERBOSE_MODE -gt 1 ] && { [ $VERBOSE_MODE -gt 1 ] && {
# VERBOSE_MODE > 1 then NO retry # VERBOSE_MODE > 1 then NO retry
write_log 7 "Verbose Mode: $VERBOSE_MODE - NO retry on error" write_log 4 "Transfer failed - Verbose Mode: $VERBOSE_MODE - NO retry on error"
return 1 return 1
} }
@ -739,27 +733,27 @@ send_update() {
# verify given IP / no private IPv4's / no IPv6 addr starting with fxxx of with ":" # verify given IP / no private IPv4's / no IPv6 addr starting with fxxx of with ":"
[ $use_ipv6 -eq 0 ] && __IP=$(echo $1 | grep -v -E "(^0|^10\.|^127|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-1]\.|^192\.168)") [ $use_ipv6 -eq 0 ] && __IP=$(echo $1 | grep -v -E "(^0|^10\.|^127|^172\.1[6-9]\.|^172\.2[0-9]\.|^172\.3[0-1]\.|^192\.168)")
[ $use_ipv6 -eq 1 ] && __IP=$(echo $1 | grep "^[0-9a-eA-E]") [ $use_ipv6 -eq 1 ] && __IP=$(echo $1 | grep "^[0-9a-eA-E]")
[ -z "$__IP" ] && write_log 14 "Private or invalid or no IP '$1' given" [ -z "$__IP" ] && write_log 4 "Private or invalid or no IP '$1' given"
if [ -n "$update_script" ]; then if [ -n "$update_script" ]; then
write_log 7 "parsing script '$update_script'" write_log 7 "parsing script '$update_script'"
. $update_script . $update_script
else else
local __URL __ANSWER __ERR local __URL __ERR
# do replaces in URL # do replaces in URL
__URL=$(echo $update_url | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#$URL_PASS#g" \ __URL=$(echo $update_url | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#$URL_PASS#g" \
-e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g") -e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g")
[ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#') [ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#')
do_transfer __ANSWER "$__URL" || return 1 # if VERBOSE_MODE > 1 do_transfer "$__URL" || return 1
write_log 7 "DDNS Provider answered:\n$__ANSWER" write_log 7 "DDNS Provider answered:\n$(cat $DATFILE)"
# analyse provider answers # analyse provider answers
# "good [IP_ADR]" = successful # "good [IP_ADR]" = successful
# "nochg [IP_ADR]" = no change but OK # "nochg [IP_ADR]" = no change but OK
echo "$__ANSWER" | grep -E "good|nochg" >/dev/null 2>&1 grep -E "good|nochg" $DATFILE >/dev/null 2>&1
return $? # "0" if "good" or "nochg" found return $? # "0" if "good" or "nochg" found
fi fi
} }
@ -767,7 +761,7 @@ send_update() {
get_local_ip () { get_local_ip () {
# $1 Name of Variable to store local IP (LOCAL_IP) # $1 Name of Variable to store local IP (LOCAL_IP)
local __CNT=0 # error counter local __CNT=0 # error counter
local __RUNPROG __DATA __URL __ANSWER local __RUNPROG __DATA __URL __ERR
[ $# -ne 1 ] && write_log 12 "Error calling 'get_local_ip()' - wrong number of parameters" [ $# -ne 1 ] && write_log 12 "Error calling 'get_local_ip()' - wrong number of parameters"
write_log 7 "Detect local IP" write_log 7 "Detect local IP"
@ -779,13 +773,16 @@ get_local_ip () {
[ $use_ipv6 -eq 0 ] && __RUNPROG="network_get_ipaddr" \ [ $use_ipv6 -eq 0 ] && __RUNPROG="network_get_ipaddr" \
|| __RUNPROG="network_get_ipaddr6" || __RUNPROG="network_get_ipaddr6"
write_log 7 "#> $__RUNPROG __DATA '$ip_network'" write_log 7 "#> $__RUNPROG __DATA '$ip_network'"
$__RUNPROG __DATA "$ip_network" eval "$__RUNPROG __DATA $ip_network" || write_log 3 "$__RUNPROG Error: '$?'"
[ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on network '$ip_network'" [ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on network '$ip_network'"
;; ;;
interface) interface)
write_log 7 "#> ifconfig '$ip_interface'" write_log 7 "#> ifconfig $ip_interface >$DATFILE 2>$ERRFILE"
ifconfig $ip_interface >$DATFILE 2>$ERRFILE
__ERR=$?
if [ $__ERR -eq 0 ]; then
if [ $use_ipv6 -eq 0 ]; then if [ $use_ipv6 -eq 0 ]; then
__DATA=$(ifconfig $ip_interface | awk ' __DATA=$(awk '
/inet addr:/ { # Filter IPv4 /inet addr:/ { # Filter IPv4
# inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0 # inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
$1=""; # remove inet $1=""; # remove inet
@ -797,10 +794,10 @@ get_local_ip () {
FS=" "; # set back separator to default " " FS=" "; # set back separator to default " "
$0=$0; # reread to activate separator (remove whitespaces) $0=$0; # reread to activate separator (remove whitespaces)
print $1; # print IPv4 addr print $1; # print IPv4 addr
}' }' $DATFILE
) )
else else
__DATA=$(ifconfig $ip_interface | awk ' __DATA=$(awk '
/inet6/ && /: [0-9a-eA-E]/ && !/\/128/ { # Filter IPv6 exclude fxxx and /128 prefix /inet6/ && /: [0-9a-eA-E]/ && !/\/128/ { # Filter IPv6 exclude fxxx and /128 prefix
# inet6 addr: 2001:db8::xxxx:xxxx/32 Scope:Global # inet6 addr: 2001:db8::xxxx:xxxx/32 Scope:Global
FS="/"; # separator "/" FS="/"; # separator "/"
@ -809,25 +806,33 @@ get_local_ip () {
FS=" "; # set back separator to default " " FS=" "; # set back separator to default " "
$0=$0; # reread to activate separator $0=$0; # reread to activate separator
print $3; # print IPv6 addr print $3; # print IPv6 addr
}' }' $DATFILE
) )
fi fi
[ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on interface '$ip_interface'" [ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on interface '$ip_interface'"
else
write_log 3 "ifconfig Error: '$__ERR'"
write_log 7 "$(cat $ERRFILE)" # report error
fi
;; ;;
script) script)
write_log 7 "#> $ip_script" write_log 7 "#> $ip_script >$DATFILE 2>$ERRFILE"
__DATA=$($ip_script) # get ip from script eval $ip_script >$DATFILE 2>$ERRFILE
__ERR=$?
if [ $__ERR -eq 0 ]; then
__DATA=$(cat $DATFILE)
[ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected via script '$ip_script'" [ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected via script '$ip_script'"
else
write_log 3 "$ip_script Error: '$__ERR'"
write_log 7 "$(cat $ERRFILE)" # report error
fi
;; ;;
web) web)
for __URL in $ip_url; do do_transfer "$ip_url"
do_transfer __ANSWER "$__URL"
[ -n "$__ANSWER" ] && break # Answer detected, leave "for do done"
done
# use correct regular expression # use correct regular expression
[ $use_ipv6 -eq 0 ] \ [ $use_ipv6 -eq 0 ] \
&& __DATA=$(echo "$__ANSWER" | grep -m 1 -o "$IPV4_REGEX") \ && __DATA=$(grep -m 1 -o "$IPV4_REGEX" $DATFILE) \
|| __DATA=$(echo "$__ANSWER" | grep -m 1 -o "$IPV6_REGEX") || __DATA=$(grep -m 1 -o "$IPV6_REGEX" $DATFILE)
[ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on web at '$__URL'" [ -n "$__DATA" ] && write_log 7 "Local IP '$__DATA' detected on web at '$__URL'"
;; ;;
*) *)
@ -836,14 +841,14 @@ get_local_ip () {
esac esac
# valid data found return here # valid data found return here
[ -n "$__DATA" ] && { [ -n "$__DATA" ] && {
eval "$1='$__DATA'" eval "$1=\"$__DATA\""
return 0 return 0
} }
[ "$SECTION_ID" = "lucihelper" ] && return 1 # no retry if called by LuCI helper script [ $LUCI_HELPER ] && return 1 # no retry if called by LuCI helper script
[ $VERBOSE_MODE -gt 1 ] && { [ $VERBOSE_MODE -gt 1 ] && {
# VERBOSE_MODE > 1 then NO retry # VERBOSE_MODE > 1 then NO retry
write_log 7 "Verbose Mode: $VERBOSE_MODE - NO retry on error" write_log 4 "Get local IP via '$ip_source' failed - Verbose Mode: $VERBOSE_MODE - NO retry on error"
return 1 return 1
} }
@ -867,7 +872,7 @@ get_registered_ip() {
# $2 (optional) if set, do not retry on error # $2 (optional) if set, do not retry on error
local __CNT=0 # error counter local __CNT=0 # error counter
local __ERR=255 local __ERR=255
local __REGEX __PROG __RUNPROG __ERRPROG __DATA local __REGEX __PROG __RUNPROG __DATA
# return codes # return codes
# 1 no IP detected # 1 no IP detected
@ -885,15 +890,13 @@ get_registered_ip() {
fi fi
[ $force_dnstcp -eq 1 ] && __PROG="$__PROG -T" # force TCP [ $force_dnstcp -eq 1 ] && __PROG="$__PROG -T" # force TCP
__RUNPROG="$__PROG $domain $dns_server 2>/dev/null" __RUNPROG="$__PROG $domain $dns_server >$DATFILE 2>$ERRFILE"
__ERRPROG="$__PROG -v $domain $dns_server 2>&1"
__PROG="BIND host" __PROG="BIND host"
elif [ -x /usr/bin/nslookup ]; then # last use BusyBox nslookup elif [ -x /usr/bin/nslookup ]; then # last use BusyBox nslookup
[ $force_ipversion -ne 0 -o $force_dnstcp -ne 0 ] && \ [ $force_ipversion -ne 0 -o $force_dnstcp -ne 0 ] && \
write_log 14 "Busybox nslookup - no support to 'force IP Version' or 'DNS over TCP'" write_log 14 "Busybox nslookup - no support to 'force IP Version' or 'DNS over TCP'"
__RUNPROG="nslookup $domain $dns_server 2>/dev/null" __RUNPROG="/usr/bin/nslookup $domain $dns_server >$DATFILE 2>$ERRFILE"
__ERRPROG="nslookup $domain $dns_server 2>&1"
__PROG="BusyBox nslookup" __PROG="BusyBox nslookup"
else # there must be an error else # there must be an error
write_log 12 "Error in 'get_registered_ip()' - no supported Name Server lookup software accessible" write_log 12 "Error in 'get_registered_ip()' - no supported Name Server lookup software accessible"
@ -901,32 +904,31 @@ get_registered_ip() {
while : ; do while : ; do
write_log 7 "#> $__RUNPROG" write_log 7 "#> $__RUNPROG"
__DATA=$(eval $__RUNPROG) eval $__RUNPROG
__ERR=$? __ERR=$?
if [ $__ERR -ne 0 ]; then if [ $__ERR -ne 0 ]; then
write_log 7 "Error:\n$(eval $__ERRPROG)"
write_log 3 "$__PROG error: '$__ERR'" write_log 3 "$__PROG error: '$__ERR'"
__DATA="" write_log 7 "Error:\n$(cat $ERRFILE)"
else else
if [ "$__PROG" = "BIND host" ]; then if [ "$__PROG" = "BIND host" ]; then
__DATA=$(echo "$__DATA" | awk -F "address " '/has/ {print $2; exit}' ) __DATA=$(cat $DATFILE | awk -F "address " '/has/ {print $2; exit}' )
else else
__DATA=$(echo "$__DATA" | sed -ne "3,\$ { s/^Address [0-9]*: \($__REGEX\).*$/\\1/p }" ) __DATA=$(cat $DATFILE | sed -ne "3,\$ { s/^Address [0-9]*: \($__REGEX\).*$/\\1/p }" )
fi fi
[ -n "$__DATA" ] && { [ -n "$__DATA" ] && {
write_log 7 "Registered IP '$__DATA' detected" write_log 7 "Registered IP '$__DATA' detected"
eval "$1='$__DATA'" # valid data found eval "$1=\"$__DATA\"" # valid data found
return 0 # leave here return 0 # leave here
} }
write_log 4 "NO valid IP found" write_log 4 "NO valid IP found"
__ERR=127 __ERR=127
fi fi
[ "$SECTION_ID" = "lucihelper" ] && return $__ERR # no retry if called by LuCI helper script [ $LUCI_HELPER ] && return $__ERR # no retry if called by LuCI helper script
[ -n "$2" ] && return $__ERR # $2 is given -> no retry [ -n "$2" ] && return $__ERR # $2 is given -> no retry
[ $VERBOSE_MODE -gt 1 ] && { [ $VERBOSE_MODE -gt 1 ] && {
# VERBOSE_MODE > 1 then NO retry # VERBOSE_MODE > 1 then NO retry
write_log 7 "Verbose Mode: $VERBOSE_MODE - NO retry on error" write_log 4 "Get registered/public IP for '$domain' failed - Verbose Mode: $VERBOSE_MODE - NO retry on error"
return $__ERR return $__ERR
} }
@ -949,7 +951,7 @@ get_uptime() {
# $1 Variable to store result in # $1 Variable to store result in
[ $# -ne 1 ] && write_log 12 "Error calling 'verify_host_port()' - wrong number of parameters" [ $# -ne 1 ] && write_log 12 "Error calling 'verify_host_port()' - wrong number of parameters"
local __UPTIME=$(cat /proc/uptime) local __UPTIME=$(cat /proc/uptime)
eval "$1='${__UPTIME%%.*}'" eval "$1=\"${__UPTIME%%.*}\""
} }
trap_handler() { trap_handler() {
@ -985,6 +987,10 @@ trap_handler() {
done done
IFS=$__OLD_IFS IFS=$__OLD_IFS
# remove out and err file
[ -f $DATFILE ] && rm -f $DATFILE
[ -f $ERRFILE ] && rm -f $ERRFILE
# exit with correct handling: # exit with correct handling:
# remove trap handling settings and send kill to myself # remove trap handling settings and send kill to myself
trap - 0 1 2 3 15 trap - 0 1 2 3 15

View file

@ -0,0 +1,100 @@
#!/bin/sh
# /usr/lib/ddns/luci_dns_helper.sh
#
# Written in August 2014
# by Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
# This script is used by luci-app-ddns
# - getting registered IP
# - check if possible to get local IP
# - verifing given DNS- or Proxy-Server
#
# variables in small chars are read from /etc/config/ddns as parameter given here
# variables in big chars are defined inside these scripts as gloval vars
# variables in big chars beginning with "__" are local defined inside functions only
# set -vx #script debugger
[ $# -lt 2 ] && exit 1
. /usr/lib/ddns/dynamic_dns_functions.sh # global vars are also defined here
# set -vx #script debugger
# preset some variables, wrong or not set in dynamic_dns_functions.sh
SECTION_ID="lucihelper"
LOGFILE="$LOGDIR/$SECTION_ID.log"
VERBOSE_MODE=0 # no console logging
# global variables normally set by reading DDNS UCI configuration
use_syslog=0 # no syslog
use_logfile=0 # by default no logfile, can be changed here
__RET=0
case "$1" in
get_registered_ip)
local IP
domain=$2 # Hostname/Domain
use_ipv6=${3:-"0"} # Use IPv6 - default IPv4
force_ipversion=${4:-"0"} # Force IP Version - default 0 - No
force_dnstcp=${5:-"0"} # Force TCP on DNS - default 0 - No
dns_server=${6:-""} # DNS server - default No DNS
write_log 7 "-----> get_registered_ip IP"
get_registered_ip IP
__RET=$?
[ $__RET -ne 0 ] && IP=""
echo -n "$IP" # suppress LF
;;
verify_dns)
# $2 : dns-server to verify # no need for force_dnstcp because
# verify with nc (netcat) uses tcp anyway
use_ipv6=${3:-"0"} # Use IPv6 - default IPv4
force_ipversion=${4:-"0"} # Force IP Version - default 0 - No
write_log 7 "-----> verify_dns '$2'"
verify_dns "$2"
__RET=$?
;;
verify_proxy)
# $2 : proxy string to verify
use_ipv6=${3:-"0"} # Use IPv6 - default IPv4
force_ipversion=${4:-"0"} # Force IP Version - default 0 - No
write_log 7 "-----> verify_proxy '$2'"
verify_proxy "$2"
__RET=$?
;;
get_local_ip)
local IP
use_ipv6="$2" # Use IPv6
ip_source="$3" # IP source
ip_network="$4" # set if source = "network" otherwise "-"
ip_url="$5" # set if source = "web" otherwise "-"
ip_interface="$6" # set if source = "interface" itherwiase "-"
ip_script="$7" # set if source = "script" otherwise "-"
proxy="$8" # proxy if set
force_ipversion="0" # not needed but must be set
use_https="0" # not needed but must be set
[ -n "$proxy" -a "$ip_source" = "web" ] && {
# proxy defined, used for ip_source=web
export HTTP_PROXY="http://$proxy"
export HTTPS_PROXY="http://$proxy"
export http_proxy="http://$proxy"
export https_proxy="http://$proxy"
}
# don't need IP only the return code
[ "$ip_source" = "web" -o "$ip_source" = "script" ] && {
# we wait only 3 seconds for an
# answer from "web" or "script"
write_log 7 "-----> timeout 3 -- get_local_ip IP"
timeout 3 -- get_local_ip IP
} || {
write_log 7 "-----> get_local_ip IP"
get_local_ip IP
}
__RET=$?
;;
*)
__RET=255
;;
esac
# remove out and err file
[ -f $DATFILE ] && rm -f $DATFILE
[ -f $ERRFILE ] && rm -f $ERRFILE
return $__RET

View file

@ -126,14 +126,14 @@ load_all_config_options "ddns" "$SECTION_ID"
write_log 7 "************ ************** ************** **************" write_log 7 "************ ************** ************** **************"
write_log 5 "PID '$$' started at $(eval $DATE_PROG)" write_log 5 "PID '$$' started at $(eval $DATE_PROG)"
write_log 7 "uci configuraion:\n$(uci -q show ddns.$SECTION_ID | sort)"
case $VERBOSE_MODE in case $VERBOSE_MODE in
0) write_log 7 "verbose mode '0' - run normal, NO console output";; 0) write_log 7 "verbose mode : 0 - run normal, NO console output";;
1) write_log 7 "verbose mode '1' - run normal, console mode";; 1) write_log 7 "verbose mode : 1 - run normal, console mode";;
2) write_log 7 "verbose mode '2' - run once, NO retry on error";; 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";; 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'";; *) write_log 14 "error detecting VERBOSE_MODE '$VERBOSE_MODE'";;
esac esac
write_log 7 "uci configuraion:\n$(uci -q show ddns.$SECTION_ID | sort)"
# set defaults if not defined # set defaults if not defined
[ -z "$enabled" ] && enabled=0 [ -z "$enabled" ] && enabled=0
@ -161,8 +161,9 @@ urlencode URL_PASS "$password" # encode password, might have special chars for s
# verify ip_source script if configured and executable # verify ip_source script if configured and executable
if [ "$ip_source" = "script" ]; then if [ "$ip_source" = "script" ]; then
[ -z "$ip_script" ] && write_log 14 "No script defined to detect local IP!" set -- $ip_script #handling script with parameters, we need a trick
[ -x "$ip_script" ] || write_log 14 "Script to detect local IP not found or not executable!" [ -z "$1" ] && write_log 14 "No script defined to detect local IP!"
[ -x "$1" ] || write_log 14 "Script to detect local IP not executable!"
fi fi
# compute update interval in seconds # compute update interval in seconds
@ -279,13 +280,14 @@ while : ; do
# do NOT retry after RETRY_SECONDS, do retry after CHECK_SECONDS # do NOT retry after RETRY_SECONDS, do retry after CHECK_SECONDS
# to early retrys will block most DDNS provider # to early retrys will block most DDNS provider
# providers answer is checked inside send_update() function # providers answer is checked inside send_update() function
[ $ERR_LAST -eq 0 ] && { if [ $ERR_LAST -eq 0 ]; then
get_uptime LAST_TIME # we send update, so get_uptime LAST_TIME # we send update, so
echo $LAST_TIME > $UPDFILE # save LASTTIME to file echo $LAST_TIME > $UPDFILE # save LASTTIME to file
[ "$LOCAL_IP" != "$REGISTERED_IP" ] \ [ "$LOCAL_IP" != "$REGISTERED_IP" ] && write_log 6 "Update successful - IP '$LOCAL_IP' send"
&& write_log 6 "Update successful - IP '$LOCAL_IP' send" \ [ "$LOCAL_IP" = "$REGISTERED_IP" ] || write_log 6 "Forced update successful - IP: '$LOCAL_IP' send"
|| write_log 6 "Forced update successful - IP: '$LOCAL_IP' send" else
} || write_log 3 "Can not update IP at DDNS Provider" write_log 3 "Can not update IP at DDNS Provider"
fi
fi fi
# now we wait for check interval before testing if update was recognized # now we wait for check interval before testing if update was recognized
@ -318,8 +320,10 @@ while : ; do
fi fi
# force_update=0 or VERBOSE_MODE > 1 - leave here # force_update=0 or VERBOSE_MODE > 1 - leave here
[ $VERBOSE_MODE -gt 1 ] && write_log 7 "Verbose Mode: $VERBOSE_MODE - NO reloop"; exit 0 [ $VERBOSE_MODE -gt 1 ] && write_log 7 "Verbose Mode: $VERBOSE_MODE - NO reloop"
[ $FORCE_SECONDS -eq 0 ] && write_log 6 "Configured to run once"; exit 0 [ $FORCE_SECONDS -eq 0 ] && write_log 6 "Configured to run once"
[ $VERBOSE_MODE -gt 1 -o $FORCE_SECONDS -eq 0 ] && exit 0
write_log 6 "Rerun IP check at $(eval $DATE_PROG)" write_log 6 "Rerun IP check at $(eval $DATE_PROG)"
done done
# we should never come here there must be a programming error # we should never come here there must be a programming error

View file

@ -0,0 +1,30 @@
#!/bin/sh
#
# sample script for detecting local IP
# 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
#
# activated inside /etc/config/ddns by setting
#
# option ip_source 'script'
# option ip_script '/usr/lib/ddns/getlocalip_sample.sh -6' !!! parameters ALLOWED
#
# the script is executed (not parsed) inside get_local_ip() function
# of /usr/lib/ddns/dynamic_dns_functions.sh
#
# This script should
# - return the IP address via stdout echo -n "...." !!! without line feed
# - report errors via stderr echo "...." >&2
# - return an error code ('0' for success) exit 123
case $1 in
-4) echo -n "8.8.8.8" # never append linefeed or simular
exit 0
;; # IP's of Googles public DNS
-6) echo -n "2001:4860:4860::8888"
exit 0
;;
*) echo "$0 - Invalid or missing parameter" >&2
exit 1
esac
echo "Should never come here" >&2
exit 2

View file

@ -87,3 +87,12 @@
# LoopiaDNS # LoopiaDNS
"loopia.se" "http://[USERNAME]:[PASSWORD]@dns.loopia.se/XDynDNSServer/XDynDNS.php?system=custom&hostname=[DOMAIN]&myip=[IP]" "loopia.se" "http://[USERNAME]:[PASSWORD]@dns.loopia.se/XDynDNSServer/XDynDNS.php?system=custom&hostname=[DOMAIN]&myip=[IP]"
# Cloudflare
"cloudflare.com" "update_cloudflare.sh"
# SelfHost.de
"selfhost.de" "http://carol.selfhost.de/update?username=[USERNAME]&password=[PASSWORD]&myip=[IP]&hostname=1"
# no-ip.pl nothing to do with no-ip.com (domain registered to www.domeny.tv) (IP autodetected by provider)
"no-ip.pl" "http://[USERNAME]:[PASSWORD]@update.no-ip.pl/?hostname=[DOMAIN]"

View file

@ -32,3 +32,9 @@
#IPv6 @ MyDNS.JP #IPv6 @ MyDNS.JP
"mydns.jp" "http://www.mydns.jp/directip.html?MID=[USERNAME]&PWD=[PASSWORD]&IPV6ADDR=[IP]" "mydns.jp" "http://www.mydns.jp/directip.html?MID=[USERNAME]&PWD=[PASSWORD]&IPV6ADDR=[IP]"
#IPv6 @ Cloudflare
"cloudflare.com" "update_cloudflare.sh"
#IPv6 @ no-ip.pl nothing to do with no-ip.com (domain registered to www.domeny.tv) (IP autodetected by provider)
"no-ip.pl" "http://[USERNAME]:[PASSWORD]@update.no-ip.pl/?hostname=[DOMAIN]"

View file

@ -0,0 +1,138 @@
#
# script for sending updates to cloudflare.com
# 2014 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
# many thanks to Paul for testing and feedback during development
#
# This script is parsed by dynamic_dns_functions.sh inside send_update() function
#
# using following options from /etc/config/ddns
# option username - your cloudflare e-mail
# option password - cloudflare api key, you can get it from cloudflare.com/my-account/
# option domain - your full hostname to update, in cloudflare its subdomain.domain
# i.e. myhost.example.com where myhost is the subdomain and example.com is your domain
#
# Attention !!! script will only work if there is only one subdomain-level at your domain
# subdomain2.subdomain1.domain i.e. mail.host.example.com will not work
#
# variable __IP already defined with the ip-address to use for update
#
[ $use_https -eq 0 ] && write_log 14 "Cloudflare only support updates via Secure HTTP (HTTPS). Please correct configuration!"
local __RECID __URL __KEY __KEYS __FOUND __DOMREC
local __SUBDOM=$(echo $domain | awk -F "." '{print $1}')
local __DOMAIN=$(echo $domain | awk -F "${__SUBDOM}." '{print $2}')
local __TMP="/tmp/$$.json"
# parse OpenWrt script with
# functions for parsing and generating json
. /usr/share/libubox/jshn.sh
# function copied from /usr/share/libubox/jshn.sh
# from BB14.09 for backward compatibility to AA12.09
json_get_keys() {
local __dest="$1"
local _tbl_cur
if [ -n "$2" ]; then
json_get_var _tbl_cur "$2"
else
_json_get_var _tbl_cur JSON_CUR
fi
local __var="${JSON_PREFIX}KEYS_${_tbl_cur}"
eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]"
}
# function to "sed" unwanted string parts from DATFILE
cleanup() {
#based on the sample output on cloudflare.com homepage we need to do some cleanup
sed -i 's/^[ \t]*//;s/[ \t]*$//' $DATFILE # remove invisible chars at beginning and end of lines
sed -i '/^-$/d' $DATFILE # remove lines with "-" (dash)
sed -i '/^$/d' $DATFILE # remove empty lines
sed -i "#'##g" $DATFILE # remove "'" (single quote)
}
# build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
# to "rec_load_all" to detect rec_id needed for update
__URL="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
__URL="${__URL}?a=rec_load_all" # -d 'a=rec_load_all'
__URL="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
__URL="${__URL}&email=$username" # -d 'email=sample@example.com'
__URL="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
# lets request the data
do_transfer "$__URL" || return 1
cleanup # cleanup dat file
json_load "$(cat $DATFILE)" # lets extract data
__FOUND=0 # found record indicator
json_get_var __RES "result" # cloudflare result of last request
json_get_var __MSG "msg" # cloudflare error message
[ "$__RES" != "success" ] && {
write_log 4 "'rec_load_all' failed with error: \n$__MSG"
return 1
}
json_select "response"
json_select "recs"
json_select "objs"
json_get_keys __KEYS
for __KEY in $__KEYS; do
local __ZONE __NAME __DISPLAY __TYPE
json_select "$__KEY"
json_get_var __ZONE "zone_name"
json_get_var __NAME "name"
json_get_var __DISPLAY "display_name"
json_get_var __TYPE "type"
# if "zone_name" == "name" == "display_name" == $domain, then we found a valid domain record
if [ "$__NAME" = "$domain" ]; then
[ "$__DISPLAY" = "$__ZONE" ] && __DOMREC=1 || __DOMREC=0
# we must verify IPv4 and IPv6 because there might be both for the same host
[ \( $use_ipv6 -eq 0 -a "$__TYPE" = "A" \) -o \( $use_ipv6 -eq 1 -a "$__TYPE" = "AAAA" \) ] && {
__FOUND=1 # mark found
break # found leave for loop
}
fi
json_select ..
done
[ $__FOUND -eq 0 ] && {
# we don't need to continue trying to update cloudflare because record to update does not exist
# user has to setup record first outside ddns-scripts
write_log 14 "No valid record found at Cloudflare setup. Please create first!"
}
json_get_var __RECID "rec_id" # last thing to do get rec_id
json_cleanup # cleanup
write_log 7 "rec_id '$__RECID' detected for host/domain '$domain'"
# build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
# for "rec_edit" to update IP address
__URL="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
__URL="${__URL}?a=rec_edit" # -d 'a=rec_edit'
__URL="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
__URL="${__URL}&id=$__RECID" # -d 'id=9001'
__URL="${__URL}&email=$username" # -d 'email=sample@example.com'
[ $__DOMREC -eq 0 ] && __URL="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
[ $__DOMREC -eq 1 ] && __URL="${__URL}&z=$domain" # -d 'z=example.com'
[ $use_ipv6 -eq 0 ] && __URL="${__URL}&type=A" # -d 'type=A' (IPv4)
[ $use_ipv6 -eq 1 ] && __URL="${__URL}&type=AAAA" # -d 'type=AAAA' (IPv6)
[ $__DOMREC -eq 0 ] && __URL="${__URL}&name=$__SUBDOM" # -d 'name=sub' (HOST/SUBDOMAIN)
[ $__DOMREC -eq 1 ] && __URL="${__URL}&name=$domain" # -d 'name=example.com'(DOMAIN)
__URL="${__URL}&content=$__IP" # -d 'content=1.2.3.4'
__URL="${__URL}&service_mode=0" # -d 'service_mode=0'
__URL="${__URL}&ttl=1" # -d 'ttl=1'
# lets do the update
do_transfer "$__URL" || return 1
cleanup # cleanup tmp file
json_load "$(cat $DATFILE)" # lets extract data
json_get_var __RES "result" # cloudflare result of last request
json_get_var __MSG "msg" # cloudflare error message
[ "$__RES" != "success" ] && {
write_log 4 "'rec_edit' failed with error:\n$__MSG"
return 1
}
write_log 7 "Update of rec_id '$__RECID' successful"
return 0

View file

@ -7,25 +7,25 @@
# provider did not reactivate records, if no IP change was recognized # provider did not reactivate records, if no IP change was recognized
# so we send a dummy (localhost) and a seconds later we send the correct IP addr # so we send a dummy (localhost) and a seconds later we send the correct IP addr
# #
local __ANSWER __LH local __DUMMY
local __UPDURL="http://[USERNAME]:[PASSWORD]@dynupdate.no-ip.com/nic/update?hostname=[DOMAIN]&myip=[IP]" local __UPDURL="http://[USERNAME]:[PASSWORD]@dynupdate.no-ip.com/nic/update?hostname=[DOMAIN]&myip=[IP]"
# set IP version dependend dummy (localhost) # set IP version dependend dummy (localhost)
[ $use_ipv6 -eq 0 ] && __LH="127.0.0.1" || __LH="::1" [ $use_ipv6 -eq 0 ] && __DUMMY="127.0.0.1" || __DUMMY="::1"
# lets do DUMMY transfer # lets do DUMMY transfer
write_log 7 "sending dummy IP to 'no-ip.com'" write_log 7 "sending dummy IP to 'no-ip.com'"
__URL=$(echo $__UPDURL | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#$URL_PASS#g" \ __URL=$(echo $__UPDURL | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#$URL_PASS#g" \
-e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__LH#g") -e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__DUMMY#g")
[ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#') [ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#')
do_transfer __ANSWER "$__URL" || return 1 do_transfer "$__URL" || return 1
write_log 7 "'no-ip.com' answered:\n$__ANSWER" write_log 7 "'no-ip.com' answered:\n$(cat $DATFILE)"
# analyse provider answers # analyse provider answers
# "good [IP_ADR]" = successful # "good [IP_ADR]" = successful
# "nochg [IP_ADR]" = no change but OK # "nochg [IP_ADR]" = no change but OK
echo "$__ANSWER" | grep -E "good|nochg" >/dev/null 2>&1 || return 1 grep -E "good|nochg" $DATFILE >/dev/null 2>&1 || return 1
# lets wait a seconds # lets wait a seconds
sleep 1 sleep 1
@ -36,12 +36,12 @@ __URL=$(echo $__UPDURL | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#
-e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g") -e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g")
[ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#') [ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#')
do_transfer __ANSWER "$__URL" || return 1 do_transfer "$__URL" || return 1
write_log 7 "'no-ip.com' answered:\n$__ANSWER" write_log 7 "'no-ip.com' answered:\n$(cat $DATFILE)"
# analyse provider answers # analyse provider answers
# "good [IP_ADR]" = successful # "good [IP_ADR]" = successful
# "nochg [IP_ADR]" = no change but OK # "nochg [IP_ADR]" = no change but OK
echo "$__ANSWER" | grep -E "good|nochg" >/dev/null 2>&1 grep -E "good|nochg" $DATFILE >/dev/null 2>&1
return $? # "0" if "good" or "nochg" found return $? # "0" if "good" or "nochg" found

View file

@ -16,7 +16,6 @@
# #
# the code here is the copy of the default used inside send_update() # the code here is the copy of the default used inside send_update()
# #
local __ANSWER
# tested with spdns.de # tested with spdns.de
local __URL="http://[USERNAME]:[PASSWORD]@update.spdns.de/nic/update?hostname=[DOMAIN]&myip=[IP]" local __URL="http://[USERNAME]:[PASSWORD]@update.spdns.de/nic/update?hostname=[DOMAIN]&myip=[IP]"
@ -25,13 +24,13 @@ __URL=$(echo $__URL | sed -e "s#\[USERNAME\]#$URL_USER#g" -e "s#\[PASSWORD\]#$UR
-e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g") -e "s#\[DOMAIN\]#$domain#g" -e "s#\[IP\]#$__IP#g")
[ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#') [ $use_https -ne 0 ] && __URL=$(echo $__URL | sed -e 's#^http:#https:#')
do_transfer __ANSWER "$__URL" || return 1 do_transfer "$__URL" || return 1
write_log 7 "DDNS Provider answered:\n$__ANSWER" write_log 7 "DDNS Provider answered:\n$(cat $DATFILE)"
# analyse provider answers # analyse provider answers
# "good [IP_ADR]" = successful # "good [IP_ADR]" = successful
# "nochg [IP_ADR]" = no change but OK # "nochg [IP_ADR]" = no change but OK
echo "$__ANSWER" | grep -E "good|nochg" >/dev/null 2>&1 grep -E "good|nochg" $DATFILE >/dev/null 2>&1
return $? # "0" if "good" or "nochg" found return $? # "0" if "good" or "nochg" found