Set executable bit on ddns-scripts files (#3673)
[packages.git] / net / ddns-scripts / files / usr / lib / ddns / dynamic_dns_updater.sh
1 #!/bin/sh
2 # /usr/lib/dynamic_dns/dynamic_dns_updater.sh
3 #
4 # Written by Eric Paul Bishop, Janary 2008
5 # Distributed under the terms of the GNU General Public License (GPL) version 2.0
6 #
7 # This script is (loosely) based on the one posted by exobyte in the forums here:
8 # http://forum.openwrt.org/viewtopic.php?id=14040
9 #
10
11 . /usr/lib/ddns/dynamic_dns_functions.sh
12 . /usr/lib/ddns/shell_get.sh
13
14
15
16
17
18
19 service_id=$1
20 if [ -z "$service_id" ]
21 then
22         echo "ERRROR: You must specify a service id (the section name in the /etc/config/ddns file) to initialize dynamic DNS."
23         return 1
24 fi
25
26 #default mode is verbose_mode, but easily turned off with second parameter
27 verbose_mode="1"
28 if [ -n "$2" ]
29 then
30         verbose_mode="$2"
31 fi
32
33 ###############################################################
34 # Leave this comment here, to clearly document variable names
35 # that are expected/possible
36 #
37 # Now use load_all_config_options to load config
38 # options, which is a much more flexible solution.
39 #
40 #
41 #config_load "ddns"
42 #
43 #config_get enabled $service_id enabled
44 #config_get service_name $service_id service_name
45 #config_get update_url $service_id update_url
46 #
47 #
48 #config_get username $service_id username
49 #config_get password $service_id password
50 #config_get domain $service_id domain
51 #
52 #
53 #config_get ip_source $service_id ip_source
54 #config_get ip_interface $service_id ip_interface
55 #config_get ip_network $service_id ip_network
56 #config_get ip_url $service_id ip_url
57 #
58 #config_get force_interval $service_id force_interval
59 #config_get force_unit $service_id force_unit
60 #
61 #config_get check_interval $service_id check_interval
62 #config_get check_unit $service_id check_unit
63 #########################################################
64 load_all_config_options "ddns" "$service_id"
65
66
67 #some defaults
68 if [ -z "$check_interval" ]
69 then
70         check_interval=600
71 fi
72
73 if [ -z "$check_unit" ]
74 then
75         check_unit="seconds"
76 fi
77
78
79 if [ -z "$force_interval" ]
80 then
81         force_interval=72
82 fi
83
84 if [ -z "$force_unit" ]
85 then
86         force_unit="hours"
87 fi
88
89
90
91 #some constants
92
93 retrieve_prog="/usr/bin/wget --no-check-certificate -O - ";
94 if [ -h "/usr/bin/wget" ]
95 then
96         busybox_wget=$(ls -l /usr/bin/wget | awk ' { if ($0~/busybox/) { print "BUSYBOX"}} ')
97         if [ -n "$busybox_wget" ]; then
98                 retrieve_prog="shell_get"
99         fi
100 fi
101
102 verbose_echo "retrieve_prog=\"$retrieve_prog\""
103
104 service_file="/usr/lib/ddns/services"
105
106 ip_regex="[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
107
108 NEWLINE_IFS='
109 '
110
111
112 #determine what update url we're using if the service_name is supplied
113 if [ -n "$service_name" ]
114 then
115         #remove any lines not containing data, and then make sure fields are enclosed in double quotes
116         quoted_services=$(cat $service_file |  grep "^[\t ]*[^#]" |  awk ' gsub("\x27", "\"") { if ($1~/^[^\"]*$/) $1="\""$1"\"" }; { if ( $NF~/^[^\"]*$/) $NF="\""$NF"\""  }; { print $0 }' )
117
118
119         #echo "quoted_services = $quoted_services"
120         OLD_IFS=$IFS
121         IFS=$NEWLINE_IFS
122         for service_line in $quoted_services
123         do
124                 #grep out proper parts of data and use echo to remove quotes
125                 next_name=$(echo $service_line | grep -o "^[\t ]*\"[^\"]*\"" | xargs -r -n1 echo)
126                 next_url=$(echo $service_line | grep -o "\"[^\"]*\"[\t ]*$" | xargs -r -n1 echo)
127
128                 if [ "$next_name" = "$service_name" ]
129                 then
130                         update_url=$next_url
131                 fi
132         done
133         IFS=$OLD_IFS
134 fi
135
136
137
138 verbose_echo "update_url=$update_url"
139
140
141
142 #if this service isn't enabled then quit
143 if [ "$enabled" != "1" ] 
144 then
145         return 0
146 fi
147
148
149
150
151
152 #compute update interval in seconds
153 case "$force_unit" in
154         "days" )
155                 force_interval_seconds=$(($force_interval*60*60*24))
156                 ;;
157         "hours" )
158                 force_interval_seconds=$(($force_interval*60*60))
159                 ;;
160         "minutes" )
161                 force_interval_seconds=$(($force_interval*60))
162                 ;;
163         "seconds" )
164                 force_interval_seconds=$force_interval
165                 ;;
166         * )
167                 #default is hours
168                 force_interval_seconds=$(($force_interval*60*60))
169                 ;;
170 esac
171
172
173
174 #compute check interval in seconds
175 case "$check_unit" in
176         "days" )
177                 check_interval_seconds=$(($check_interval*60*60*24))
178                 ;;
179         "hours" )
180                 check_interval_seconds=$(($check_interval*60*60))
181                 ;;
182         "minutes" )
183                 check_interval_seconds=$(($check_interval*60))
184                 ;;
185         "seconds" )
186                 check_interval_seconds=$check_interval
187                 ;;
188         * )
189                 #default is seconds
190                 check_interval_seconds=$check_interval
191                 ;;
192 esac
193
194
195
196 verbose_echo "force seconds = $force_interval_seconds"
197 verbose_echo "check seconds = $check_interval_seconds"
198
199 #kill old process if it exists & set new pid file
200 if [ -d /var/run/dynamic_dns ]
201 then
202         #if process is already running, stop it
203         if [ -e "/var/run/dynamic_dns/$service_id.pid" ]
204         then
205                 old_pid=$(cat /var/run/dynamic_dns/$service_id.pid)
206                 test_match=$(ps | grep "^[\t ]*$old_pid")
207                 verbose_echo "old process id (if it exists) = \"$test_match\""
208                 if [ -n  "$test_match" ]
209                 then
210                         kill $old_pid
211                 fi
212         fi
213
214 else
215         #make dir since it doesn't exist
216         mkdir /var/run/dynamic_dns
217 fi
218 echo $$ > /var/run/dynamic_dns/$service_id.pid
219
220
221
222
223 #determine when the last update was
224 current_time=$(date +%s)
225 last_update=$(( $current_time - (2*$force_interval_seconds) ))
226 if [ -e "/var/run/dynamic_dns/$service_id.update" ]
227 then
228         last_update=$(cat /var/run/dynamic_dns/$service_id.update)
229 fi
230 time_since_update=$(($current_time - $last_update))
231
232
233 human_time_since_update=$(( $time_since_update / ( 60 * 60 ) ))
234 verbose_echo "time_since_update = $human_time_since_update hours"
235
236
237
238
239 registered_ip=$(echo $(nslookup "$domain" 2>/dev/null) |  grep -o "Name:.*" | grep -o "$ip_regex")
240
241
242 #do update and then loop endlessly, checking ip every check_interval and forcing an updating once every force_interval
243
244 while [ true ]
245 do
246         current_ip=$(get_current_ip)
247
248
249         current_time=$(date +%s)
250         time_since_update=$(($current_time - $last_update))
251         
252
253         verbose_echo "Running IP check..."
254         verbose_echo "current system ip = $current_ip"
255         verbose_echo "registered domain ip = $registered_ip"
256
257
258         if [ "$current_ip" != "$registered_ip" ]  || [ $force_interval_seconds -lt $time_since_update ]
259         then
260                 verbose_echo "update necessary, performing update ..."
261
262                 #do replacement
263                 final_url=$update_url
264                 for option_var in $ALL_OPTION_VARIABLES
265                 do
266                         replace_name=$(echo "\[$option_var\]" | tr 'a-z' 'A-Z')
267                         replace_value=$(eval echo "\$$option_var")
268                         final_url=$(echo $final_url | sed s/"$replace_name"/"$replace_value"/g )
269                 done    
270                 final_url=$(echo $final_url | sed s/"\[IP\]"/"$current_ip"/g )
271                 
272
273                 verbose_echo "updating with url=\"$final_url\""
274
275                 #here we actually connect, and perform the update
276                 update_output=$( $retrieve_prog "$final_url" )
277
278                 verbose_echo "Update Output:"
279                 verbose_echo "$update_output"
280                 verbose_echo ""
281
282                 #save the time of the update
283                 current_time=$(date +%s)
284                 last_update=$current_time
285                 time_since_update='0'
286                 registered_ip=$current_ip
287                 
288                 human_time=$(date)
289                 verbose_echo "update complete, time is: $human_time"
290                 
291                 echo "$last_update" > "/var/run/dynamic_dns/$service_id.update"
292         else
293                 human_time=$(date)
294                 human_time_since_update=$(( $time_since_update / ( 60 * 60 ) ))
295                 verbose_echo "update unnecessary"
296                 verbose_echo "time since last update = $human_time_since_update hours"
297                 verbose_echo "the time is now $human_time"
298         fi
299
300         #sleep for 10 minutes, then re-check ip && time since last update
301         sleep $check_interval_seconds
302 done
303
304 #should never get here since we're a daemon, but I'll throw it in anyway
305 return 0
306
307
308
309