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