Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>lilik-openwrt-22.03
@ -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)) |
@ -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]" | |||||
@ -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 | |||||
@ -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 | |||||
} | |||||
@ -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%%.*}" | |||||
} |
@ -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 | |||||
@ -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 | |||||
@ -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" |
@ -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 |