You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
8.5 KiB

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