From ced8b84f1cbae7d1752cd6cfff65d14e0320112b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 8 Jun 2014 14:03:31 +0200 Subject: [PATCH] ddns-scripts: Copied from previous repository Signed-off-by: Nikos Mavrogiannopoulos --- net/ddns-scripts/Makefile | 44 +++ net/ddns-scripts/files/etc/config/ddns | 97 +++++ .../files/etc/hotplug.d/iface/25-ddns | 9 + net/ddns-scripts/files/etc/init.d/ddns | 12 + .../usr/lib/ddns/dynamic_dns_functions.sh | 144 +++++++ .../files/usr/lib/ddns/dynamic_dns_updater.sh | 360 ++++++++++++++++++ .../usr/lib/ddns/dynamic_dns_updater.sh~ | 360 ++++++++++++++++++ net/ddns-scripts/files/usr/lib/ddns/services | 65 ++++ .../files/usr/lib/ddns/url_escape.sed | 25 ++ 9 files changed, 1116 insertions(+) create mode 100644 net/ddns-scripts/Makefile create mode 100644 net/ddns-scripts/files/etc/config/ddns create mode 100644 net/ddns-scripts/files/etc/hotplug.d/iface/25-ddns create mode 100644 net/ddns-scripts/files/etc/init.d/ddns create mode 100644 net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh create mode 100755 net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh create mode 100755 net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh~ create mode 100644 net/ddns-scripts/files/usr/lib/ddns/services create mode 100644 net/ddns-scripts/files/usr/lib/ddns/url_escape.sed diff --git a/net/ddns-scripts/Makefile b/net/ddns-scripts/Makefile new file mode 100644 index 0000000000..4b50e8d8d5 --- /dev/null +++ b/net/ddns-scripts/Makefile @@ -0,0 +1,44 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=ddns-scripts +PKG_VERSION:=1.0.0 +PKG_RELEASE:=22 + +PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) + +include $(INCLUDE_DIR)/package.mk + +define Package/ddns-scripts + SECTION:=net + CATEGORY:=Network + SUBMENU:=IP Addresses and Names + TITLE:=Dynamic DNS Scripts + PKGARCH:=all +endef + +define Package/ddns-scripts/description + A highly configurable set of scripts for doing + dynamic dns updates +endef + +define Build/Prepare +endef + +define Build/Configure +endef + +define Build/Compile +endef + +define Package/ddns-scripts/conffiles +/etc/config/ddns +endef + +define Package/ddns-scripts/install + $(INSTALL_DIR) $(1) + $(CP) ./files/* $(1)/ + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_BIN) ./files/etc/init.d/ddns $(1)/etc/init.d/ +endef + +$(eval $(call BuildPackage,ddns-scripts)) diff --git a/net/ddns-scripts/files/etc/config/ddns b/net/ddns-scripts/files/etc/config/ddns new file mode 100644 index 0000000000..e7337b5ff7 --- /dev/null +++ b/net/ddns-scripts/files/etc/config/ddns @@ -0,0 +1,97 @@ +################################################################# +# In order to enable dynamic dns you need at least one section, +# and in that seciton the "enabled" option must be set to one +# +# Each section represents an update to a different service +# +# You specify your domain name, your username and your password +# with the optins "domain", "username" and "password" respectively +# +# Next you need to specify the name of the service you are +# connecting to "eg. dyndns.org". The format of the update +# urls for several different dynamic dns services is specified +# in the /usr/lib/ddns/services file. This list is hardly complete +# as there are many, many different dynamic dns services. If your +# service is on the list you can merely specify it with the +# "service_name" option. Otherwise you will need to determine +# the format of the url to update with. You can either add an +# entry to the /usr/lib/ddns/services file or specify this with +# the "update_url" option. +# +# We also need to specify the source of the ip address to associate with +# your domain. The "ip_source" option can be "network", "interface" +# or "web", with "network" as the default. +# +# If "ip_source" is "network" you specify a network section in your +# /etc/network config file (e.g. "wan", which is the default) with +# the "ip_network" option. If you specify "wan", you will update +# with whatever the ip for your wan is. +# +# If "ip_source" is "interface" you specify a hardware interface +# (e.g. "eth1") and whatever the current ip of this interface is +# will be associated with the domain when an update is performed. +# +# If "ip_source" is "script" you specify a script to obtain ip address. +# The "ip_script" option should contain path to your script. +# +# The last possibility is that "ip_source" is "web", which means +# that in order to obtain our ip address we will connect to a +# website, and the first valid ip address listed on that page +# will be assumed to be ours. If you are behind another firewall +# this is the best option since none of the local networks or +# interfaces will have the external ip. The website to connect +# to is specified by the "ip_url" option. You may specify multiple +# urls in the option, separated by whitespace. +# +# Finally we need to specify how often to check whether we need +# to check whether the ip address has changed (and if so update +# it) and how often we need to force an update ( many services +# will expire your domain if you don't connect and do an update +# every so often). Use the "check_interval" to specify how +# often to check whether an update is necessary, the "retry_interval" +# to specify how often to retry in case the update has failed, and +# the "force_interval" option to specify how often to force an +# update. Specify the units for these values with the "check_unit", +# the "retry_init" and the "force_unit" options. Units can be +# "days", "hours", "minutes" or "seconds". The default force_unit +# is hours, the default retry_unit is seconds and the default +# check_unit is seconds. The default check_interval is 600 seconds, +# or ten minutes. The default retry_interval is 60 seconds, or one +# minute. The default force_interval is 72 hours or 3 days. +# +# +######################################################### + +config service "myddns" + option enabled "0" + option interface "wan" + option use_syslog "1" + + option service_name "dyndns.org" + option domain "mypersonaldomain.dyndns.org" + option username "myusername" + option password "mypassword" + option use_https "0" + + option force_interval "72" + option force_unit "hours" + option check_interval "10" + option check_unit "minutes" + option retry_interval "60" + option retry_unit "seconds" + + #option ip_source "network" + #option ip_network "wan" + + #option ip_source "interface" + #option ip_interface "eth0.1" + + #option ip_source "script" + #option ip_script "path to your scrip" + + option ip_source "web" + option ip_url "http://checkip.dyndns.com/" + + #option update_url "http://[USERNAME]:[PASSWORD]@members.dyndns.org/nic/update?hostname=[DOMAIN]&myip=[IP]" + + diff --git a/net/ddns-scripts/files/etc/hotplug.d/iface/25-ddns b/net/ddns-scripts/files/etc/hotplug.d/iface/25-ddns new file mode 100644 index 0000000000..4495b5d854 --- /dev/null +++ b/net/ddns-scripts/files/etc/hotplug.d/iface/25-ddns @@ -0,0 +1,9 @@ +#!/bin/sh + +. /usr/lib/ddns/dynamic_dns_functions.sh + +if [ "$ACTION" = "ifup" ]; then + start_daemon_for_all_ddns_sections "$INTERFACE" +fi + + diff --git a/net/ddns-scripts/files/etc/init.d/ddns b/net/ddns-scripts/files/etc/init.d/ddns new file mode 100644 index 0000000000..3171d5ae92 --- /dev/null +++ b/net/ddns-scripts/files/etc/init.d/ddns @@ -0,0 +1,12 @@ +#!/bin/sh /etc/rc.common +START=95 + +start() { + . /usr/lib/ddns/dynamic_dns_functions.sh + start_daemon_for_all_ddns_sections +} + +stop() { + killall -9 dynamic_dns_updater.sh +} + diff --git a/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh new file mode 100644 index 0000000000..a59693210c --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_functions.sh @@ -0,0 +1,144 @@ +# /usr/lib/dynamic_dns/dynamic_dns_functions.sh +# +# Written by Eric Paul Bishop, Janary 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: +# http://forum.openwrt.org/viewtopic.php?id=14040 + + + +. /lib/functions.sh +. /lib/functions/network.sh + + +#loads all options for a given package and section +#also, sets all_option_variables to a list of the variable names +load_all_config_options() +{ + pkg_name="$1" + section_id="$2" + + ALL_OPTION_VARIABLES="" + # this callback loads all the variables + # in the section_id section when we do + # config_load. We need to redefine + # the option_cb for different sections + # so that the active one isn't still active + # after we're done with it. For reference + # the $1 variable is the name of the option + # and $2 is the name of the section + config_cb() + { + if [ ."$2" = ."$section_id" ]; then + option_cb() + { + ALL_OPTION_VARIABLES="$ALL_OPTION_VARIABLES $1" + } + else + option_cb() { return 0; } + fi + } + + + config_load "$pkg_name" + for var in $ALL_OPTION_VARIABLES + do + config_get "$var" "$section_id" "$var" + done +} + + +get_current_ip() +{ + + #if ip source is not defined, assume we want to get ip from wan + if [ "$ip_source" != "interface" ] && [ "$ip_source" != "web" ] && [ "$ip_source" != "script" ] + then + ip_source="network" + fi + + if [ "$ip_source" = "network" ] + then + if [ -z "$ip_network" ] + then + ip_network="wan" + fi + fi + + current_ip=''; + if [ "$ip_source" = "network" ] + then + network_get_ipaddr current_ip "$ip_network" || return + elif [ "$ip_source" = "interface" ] + then + current_ip=$(ifconfig $ip_interface | grep -o 'inet addr:[0-9.]*' | grep -o "$ip_regex") + elif [ "$ip_source" = "script" ] + then + # get ip from script + current_ip=$($ip_script) + else + # get ip from web + # we check each url in order in ip_url variable, and if no ips are found we use dyndns ip checker + # ip is set to FIRST expression in page that matches the ip_regex regular expression + for addr in $ip_url + do + if [ -z "$current_ip" ] + then + current_ip=$(echo $( wget -O - $addr 2>/dev/null) | grep -o "$ip_regex") + fi + done + + #here we hard-code the dyndns checkip url in case no url was specified + if [ -z "$current_ip" ] + then + current_ip=$(echo $( wget -O - http://checkip.dyndns.org 2>/dev/null) | grep -o "$ip_regex") + fi + fi + + echo "$current_ip" +} + + +verbose_echo() +{ + if [ "$verbose_mode" = 1 ] + then + echo $1 + fi +} + +syslog_echo() +{ + if [ "$use_syslog" = 1 ] + then + echo $1|logger -t ddns-scripts-$service_id + fi +} + +start_daemon_for_all_ddns_sections() +{ + local event_interface="$1" + + SECTIONS="" + config_cb() + { + SECTIONS="$SECTIONS $2" + } + config_load "ddns" + + for section in $SECTIONS + do + local iface + config_get iface "$section" interface "wan" + [ "$iface" = "$event_interface" ] || continue + /usr/lib/ddns/dynamic_dns_updater.sh $section 0 > /dev/null 2>&1 & + done +} + +monotonic_time() +{ + local uptime + read uptime < /proc/uptime + echo "${uptime%%.*}" +} 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 new file mode 100755 index 0000000000..e6d298740d --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh @@ -0,0 +1,360 @@ +#!/bin/sh +# /usr/lib/dynamic_dns/dynamic_dns_updater.sh +# +# Written by Eric Paul Bishop, Janary 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: +# 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 +# +# Now use load_all_config_options to load config +# options, which is a much more flexible solution. +# +# +#config_load "ddns" +# +#config_get enabled $service_id enabled +#config_get service_name $service_id service_name +#config_get update_url $service_id update_url +# +# +#config_get username $service_id username +#config_get password $service_id password +#config_get domain $service_id domain +# +# +#config_get use_https $service_id use_https +#config_get use_syslog $service_id use_syslog +#config_get cacert $service_id cacert +# +#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 +# +#config_get force_interval $service_id force_interval +#config_get force_unit $service_id force_unit +# +#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 + ;; +esac + + +verbose_echo "force seconds = $force_interval_seconds" +verbose_echo "check seconds = $check_interval_seconds" + +#kill old process if it exists & set new pid file +if [ -d /var/run/dynamic_dns ] +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 + fi + +else + #make dir since it doesn't exist + mkdir /var/run/dynamic_dns +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) +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 ) + 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 + 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" + + 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 + + #sleep for 10 minutes, then re-check ip && time since last update + sleep $check_interval_seconds +done + +#should never get here since we're a daemon, but I'll throw it in anyway +return 0 + + + + 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~ new file mode 100755 index 0000000000..e6d298740d --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/dynamic_dns_updater.sh~ @@ -0,0 +1,360 @@ +#!/bin/sh +# /usr/lib/dynamic_dns/dynamic_dns_updater.sh +# +# Written by Eric Paul Bishop, Janary 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: +# 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 +# +# Now use load_all_config_options to load config +# options, which is a much more flexible solution. +# +# +#config_load "ddns" +# +#config_get enabled $service_id enabled +#config_get service_name $service_id service_name +#config_get update_url $service_id update_url +# +# +#config_get username $service_id username +#config_get password $service_id password +#config_get domain $service_id domain +# +# +#config_get use_https $service_id use_https +#config_get use_syslog $service_id use_syslog +#config_get cacert $service_id cacert +# +#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 +# +#config_get force_interval $service_id force_interval +#config_get force_unit $service_id force_unit +# +#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 + ;; +esac + + +verbose_echo "force seconds = $force_interval_seconds" +verbose_echo "check seconds = $check_interval_seconds" + +#kill old process if it exists & set new pid file +if [ -d /var/run/dynamic_dns ] +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 + fi + +else + #make dir since it doesn't exist + mkdir /var/run/dynamic_dns +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) +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 ) + 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 + 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" + + 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 + + #sleep for 10 minutes, then re-check ip && time since last update + sleep $check_interval_seconds +done + +#should never get here since we're a daemon, but I'll throw it in anyway +return 0 + + + + diff --git a/net/ddns-scripts/files/usr/lib/ddns/services b/net/ddns-scripts/files/usr/lib/ddns/services new file mode 100644 index 0000000000..744de025af --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/services @@ -0,0 +1,65 @@ +# This file contains the update urls for various dynamic dns services. +# Column one contains the service name, column two contains the update url. +# within the update url there are 4 variables you can use: [USERNAME], +# [PASSWORD], [DOMAIN] and [IP]. These are substituted for the username, +# password, and domain name specified in the /etc/config/ddns file when an +# update is performed. The IP is substituted for the current ip address of the +# router. These variables are case sensitive, while urls generally are not, so +# if you need to enter the same text in the url (which seems very unlikely) put +# that text in lowercase, while the variables should remain in uppercase + +"dyndns.org" "http://[USERNAME]:[PASSWORD]@members.dyndns.org/nic/update?hostname=[DOMAIN]&myip=[IP]" +"changeip.com" "http://[USERNAME]:[PASSWORD]@nic.changeip.com/nic/update?u=[USERNAME]&p=[PASSWORD]&cmd=update&hostname=[DOMAIN]&ip=[IP]" +"zoneedit.com" "http://[USERNAME]:[PASSWORD]@dynamic.zoneedit.com/auth/dynamic.html?host=[DOMAIN]&dnsto=[IP]" +"free.editdns.net" "http://dyndns-free.editdns.net/api/dynLinux.php?p=[PASSWORD]&r=[DOMAIN]" + +#noip is an alias of no-ip, so allow both names for the same service +"no-ip.com" "http://[USERNAME]:[PASSWORD]@dynupdate.no-ip.com/nic/update?hostname=[DOMAIN]&myip=[IP]" +"noip.com" "http://[USERNAME]:[PASSWORD]@dynupdate.no-ip.com/nic/update?hostname=[DOMAIN]&myip=[IP]" + +#freedns.afraid.org is weird, you just need an update code, for which we use the password variable +"freedns.afraid.org" "http://freedns.afraid.org/dynamic/update.php?[PASSWORD]&address=[IP]" + +#### ADD YOURS HERE! ###################################################################################### +# # +# There are TONS of dynamic dns services out there. There's a huge list of them at: # +# http://www.dmoz.org/Computers/Software/Internet/Servers/Address_Management/Dynamic_DNS_Services/ # +# If anyone has time they could update this file to be compatible with a bunch of them # +# # +########################################################################################################### + +# DNS Max and resellers' update urls +"dnsmax.com" "http://update.dnsmax.com/update/?username=[USERNAME]&password=[PASSWORD]&resellerid=1&clientname=openwrt&clientversion=8.09&protocolversion=2.0&updatehostname=[DOMAIN]&ip=[IP]" +"thatip.com" "http://update.dnsmax.com/update/?username=[USERNAME]&password=[PASSWORD]&resellerid=2&clientname=openwrt&clientversion=8.09&protocolversion=2.0&updatehostname=[DOMAIN]&ip=[IP]" + +# Hurricane Electric Dynamic DNS +"he.net" "http://[DOMAIN]:[PASSWORD]@dyn.dns.he.net/nic/update?hostname=[DOMAIN]&myip=[IP]" + +# DNSdynamic.org +"dnsdynamic.org" "http://[USERNAME]:[PASSWORD]@www.dnsdynamic.org/api/?hostname=[DOMAIN]&myip=[IP]" + +# dnsExit.com free dynamic DNS update url +"dnsexit.com" "http://www.dnsexit.com/RemoteUpdate.sv?login=[USERNAME]&password=[PASSWORD]&host=[DOMAIN]&myip=[IP]" + +# OVH +"ovh.com" "http://[USERNAME]:[PASSWORD]@www.ovh.com/nic/update?system=dyndns&hostname=[DOMAIN]&myip=[IP]" + +# dns-o-matic is a free service by opendns.com for updating multiple hosts and +# dynamic dns services in one api call. To update all your configured services +# at once, use "all.dnsomatic.com as the hostname. +"dnsomatic.com" "http://[USERNAME]:[PASSWORD]@updates.dnsomatic.com/nic/update?hostname=[DOMAIN]&myip=[IP]" + +# 3322.org +"3322.org" "http://[USERNAME]:[PASSWORD]@members.3322.org/dyndns/update?system=dyndns&hostname=[DOMAIN]&myip=[IP]" + +# namecheap.com +"namecheap.com" "http://dynamicdns.park-your-domain.com/update?host=[USERNAME]&domain=[DOMAIN]&password=[PASSWORD]&ip=[IP]" + +# easydns.com dynamic DNS +"easydns.com" "http://[USERNAME]:[PASSWORD]@api.cp.easydns.com/dyn/tomato.php?hostname=[DOMAIN]&myip=[IP]" + +# Winco DDNS +"ddns.com.br" "http://[DOMAIN]:[PASSWORD]@members.ddns.com.br/nic/update?hostname=[DOMAIN]&myip=[IP]" + +# Mythic Beasts (https://www.mythic-beasts.com) Dynamic DNS +"mythic-beasts.com" "http://dnsapi4.mythic-beasts.com/?domain=[USERNAME]&password=[PASSWORD]&command=REPLACE%20[DOMAIN]%2060%20A%20DYNAMIC_IP" diff --git a/net/ddns-scripts/files/usr/lib/ddns/url_escape.sed b/net/ddns-scripts/files/usr/lib/ddns/url_escape.sed new file mode 100644 index 0000000000..eac400265d --- /dev/null +++ b/net/ddns-scripts/files/usr/lib/ddns/url_escape.sed @@ -0,0 +1,25 @@ +# sed url escaping +s:%:%25:g +s: :%20:g +s:<:%3C:g +s:>:%3E:g +s:#:%23:g +s:{:%7B:g +s:}:%7D:g +s:|:%7C:g +s:\\:%5C:g +s:\^:%5E:g +s:~:%7E:g +s:\[:%5B:g +s:\]:%5D:g +s:`:%60:g +s:;:%3B:g +s:/:%2F:g +s:?:%3F:g +s^:^%3A^g +s:@:%40:g +s:=:%3D:g +s:&:%26:g +s:\$:%24:g +s:\!:%21:g +s:\*:%2A:g