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.

311 lines
11 KiB

  1. #!/bin/sh
  2. g_pslfile=/usr/share/public_suffix_list.dat.gz
  3. [ -f "$g_pslfile" ] || g_pslfile="$(dirname $0)/public_suffix_list.dat.gz"
  4. g_pslerr=0
  5. g_cfgfile="ddns"
  6. # modify "cloudflare.com-v1" domain to new syntax
  7. # returns "host[.subdom]@domain.TLD" of given FQDN #############################
  8. mod_cloudflare_v1_domain() {
  9. # $1 entry to validate/split
  10. [ -f "$g_pslfile" ] || return 1
  11. [ $# -ne 1 -o -z "$1" ] && \
  12. { printf "%s\\n" "mod_cloudflare_v1_domain() - Invalid number of parameters" >&2; return 1; }
  13. local mcd_fqdn=$1
  14. local mcd_fsub=""
  15. local mcd_fdom=""
  16. local mcd_ctld=""
  17. local mcd_ftld=""
  18. # check if already new syntax, "@" inside string
  19. if [ $( printf "%s" "$mcd_fqdn" | grep -cF "@" 2>/dev/null ) -gt 0 ]; then
  20. # already done
  21. printf "%s" "$mcd_fqdn"
  22. return 0
  23. fi
  24. # we need to do in one line because otherwise sh doesn't work correctly
  25. # to lower | replace "." to " " | awk invert word order
  26. set -- $(printf %s "$mcd_fqdn" | tr [A-Z] [a-z] | tr "." " " \
  27. | awk '{do printf "%s"(NF>1?OFS:ORS),$NF;while (--NF)}' )
  28. while [ -n "${1:-}" ] ; do # as long we have parameters
  29. if [ -z "$mcd_ctld" ]; then # first loop
  30. mcd_ctld="$1" # CURRENT TLD to look at
  31. shift
  32. else
  33. mcd_ctld="$1.$mcd_ctld" # Next TLD to look at
  34. shift
  35. fi
  36. # check if TLD exact match in public_suffix_name.dat, save TLD
  37. zcat $g_pslfile | grep -E "^$mcd_ctld$" >/dev/null 2>&1 && {
  38. mcd_ftld="$mcd_ctld" # save found
  39. mcd_fdom="${1:-}" # save domain next step might be invalid
  40. continue
  41. }
  42. # check if match any "*" in public_suffix_name.dat,
  43. zcat $g_pslfile | grep -E "^\*.$mcd_ctld$" >/dev/null 2>&1 && {
  44. [ -z "${1:-}" ] && break # no more data break
  45. # check if next level TLD match excludes "!" in tld_names.dat
  46. if zcat $g_pslfile | grep -E "^!$1.$mcd_ctld$" >/dev/null 2>&1 ; then
  47. mcd_ftld="$mcd_ctld" # Yes
  48. else
  49. mcd_ftld="$1.$mcd_ctld"
  50. shift
  51. fi
  52. mcd_fdom="$1"; shift
  53. }
  54. [ -n "$mcd_ftld" ] && break # we have something valid, break
  55. done
  56. # the leftover parameters are the HOST/SUBDOMAIN
  57. while [ -n "${1:-}" ]; do
  58. mcd_fsub="${1}${mcd_fsub:+.$mcd_fsub}" # remember we need to invert
  59. shift # and insert dot if mcd_fsub not empty
  60. done
  61. # now validate found data
  62. [ -z "$mcd_ftld" ] && { printf "%s\\n" "mod_cloudflare_v1_domain() - no TLD not found in '$mcd_fqdn'" >&1; return 1; }
  63. [ -z "$mcd_fdom" ] && { printf "%s\\n" "mod_cloudflare_v1_domain() - no registrable Domain not found in '$mcd_fqdn'" >&1; return 1; }
  64. # return data
  65. printf "%s" "${mcd_fsub:+${mcd_fsub}@}${mcd_fdom}.${mcd_ftld}"
  66. return 0
  67. }
  68. # modify timer settings from interval and unit to dhms format
  69. timer2dhms() {
  70. # $1 Number and
  71. # $2 Unit of time interval
  72. local t=0
  73. case $2 in
  74. days) t=$(( $1 * 86400 ));;
  75. hours) t=$(( $1 * 3600 ));;
  76. minutes) t=$(( $1 * 60 ));;
  77. *) t=$1;;
  78. esac
  79. local d=$(( $t / 86400 ))
  80. local h=$(( $t % 86400 / 3600 ))
  81. local m=$(( $t % 3600 / 60 ))
  82. local s=$(( $t % 60 ))
  83. if [ $d -gt 0 ]; then printf "%dd %02dh %02dm %02ds" "$d" "$h" "$m" "$s"
  84. elif [ $h -gt 0 ]; then printf "%dh %02dm %02ds" "$h" "$m" "$s"
  85. elif [ $m -gt 0 ]; then printf "%dm %02ds" "$m" "$s"
  86. else printf "%ds" "$s"; fi
  87. unset d h m s t
  88. return 0
  89. }
  90. # using function to not confuse function calls with existing ones inside /lib/functions.sh
  91. update_config() {
  92. uc_uci="$(which uci) -q" # ignore errors
  93. uc_cfg=""
  94. uc_name=""
  95. uc_var=""
  96. uc_val=""
  97. package() { return 0; }
  98. config () {
  99. uc_cfg="$1"
  100. uc_name="$2"
  101. # Type = ddns Name = global
  102. if [ "$uc_cfg" = "$g_cfgfile" -a "$uc_name" = "global" ]; then
  103. option() {
  104. uc_var="$1"; shift
  105. uc_val="$*"
  106. case "$uc_var" in
  107. allow_local_ip) $uc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_privateip";;
  108. date_format) $uc_uci rename $g_cfgfile.$uc_name.$uc_var="ddns_dateformat";;
  109. log_lines) $uc_uci rename $g_cfgfile.$uc_name.$uc_var="ddns_loglines";;
  110. log_dir) $uc_uci rename $g_cfgfile.$uc_name.$uc_var="ddns_logdir";;
  111. run_dir) $uc_uci rename $g_cfgfile.$uc_name.$uc_var="ddns_rundir";;
  112. # leave all other options currently unchanged
  113. *) ;;
  114. esac
  115. }
  116. # Type = service Name = ???
  117. elif [ "$uc_cfg" = "service" ]; then
  118. option() {
  119. uc_var="$1"; shift
  120. uc_val="$*"
  121. case "$uc_var" in
  122. # fix some option service_name values
  123. # and some settings for specific providers
  124. service_name|upd_provider)
  125. case "$uc_val" in
  126. freedns\.afraid\.org|afraid\.org)
  127. $uc_uci set $g_cfgfile.$uc_name.$uc_var="afraid.org-keyauth";;
  128. Bind-nsupdate)
  129. $uc_uci set $g_cfgfile.$uc_name.$uc_var="bind-nsupdate";;
  130. CloudFlare|cloudflare\.com|cloudflare\.com-v1)
  131. # verify if lookup_host is set
  132. $uc_uci get $g_cfgfile.$uc_name.lookup_host >/dev/null 2>&1 || {
  133. ucv_domain=$($uc_uci get $g_cfgfile.$uc_name.domain 2>/dev/null)
  134. $uc_uci set $g_cfgfile.$uc_name.lookup_host="$ucv_domain"
  135. }
  136. if [ -f "$g_pslfile" ]; then
  137. # change value of domain/upd_object to new syntax
  138. # there is no sort order inside uci data so we need multiple checks
  139. ucv_domain=$($uc_uci get $g_cfgfile.$uc_name.domain 2>/dev/null)
  140. ucv_object=$($uc_uci get $g_cfgfile.$uc_name.upd_object 2>/dev/null)
  141. # still old option domain
  142. if [ -n "$ucv_domain" ]; then
  143. ucv_new=$(mod_cloudflare_v1_domain "$ucv_domain") || g_pslerr=1
  144. # no error save data save data
  145. [ $g_pslerr -eq 0 ] && \
  146. $uc_uci set $g_cfgfile.$uc_name.domain="$ucv_new"
  147. fi
  148. # already new option upd_object
  149. if [ -n "$ucv_object" ]; then
  150. ucv_new=$(mod_cloudflare_v1_domain "$ucv_object") || g_pslerr=1
  151. # no error save data save data
  152. [ $g_pslerr -eq 0 ] && \
  153. $uc_uci set $g_cfgfile.$uc_name.upd_object="$ucv_new"
  154. fi
  155. fi
  156. unset ucv_domain ucv_object ucv_new
  157. # set new option value
  158. $uc_uci set $g_cfgfile.$uc_name.$uc_var="cloudflare.com-v1"
  159. ;;
  160. dyndns\.org|dyndns\.com)
  161. $uc_uci set $g_cfgfile.$uc_name.$uc_var="dyn.com";;
  162. free\.editdns\.net)
  163. $uc_uci set $g_cfgfile.$uc_name.$uc_var="editdns.net";;
  164. FreeDNS\.42\.pl)
  165. $uc_uci set $g_cfgfile.$uc_name.$uc_var="freedns.42.pl";;
  166. domains\.google\.com)
  167. $uc_uci set $g_cfgfile.$uc_name.$uc_var="google.com";;
  168. loopia\.com)
  169. $uc_uci set $g_cfgfile.$uc_name.$uc_var="loopia.se";;
  170. NoIP\.com|No-IP\.com)
  171. $uc_uci set $g_cfgfile.$uc_name.$uc_var="no-ip.com";;
  172. spdns\.de)
  173. $uc_uci set $g_cfgfile.$uc_name.$uc_var="spdyn.de";;
  174. strato\.de)
  175. $uc_uci set $g_cfgfile.$uc_name.$uc_var="strato.com";;
  176. *)
  177. # all others leave unchanged
  178. ;;
  179. esac
  180. # rename option service_name to option upd_provider
  181. # $uc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_provider"
  182. ;;
  183. domain|upd_object)
  184. # verify if lookup_host is set
  185. $uc_uci get $g_cfgfile.$uc_name.lookup_host >/dev/null 2>&1 || \
  186. $uc_uci set $g_cfgfile.$uc_name.lookup_host="$uc_val"
  187. if [ -f "$g_pslfile" ]; then
  188. # if service_name/upd_provider cloudflare_v1 then change domain/upd_object to new syntax
  189. # there is no sort order inside uci data so we need multiple checks
  190. uco_provider=$($uc_uci get $g_cfgfile.$uc_name.upd_provider 2>/dev/null) || \
  191. uco_provider=$($uc_uci get $g_cfgfile.$uc_name.service_name 2>/dev/null)
  192. if [ "$uco_provider" = "CloudFlare" \
  193. -o "$uco_provider" = "cloudflare.com" \
  194. -o "$uco_provider" = "cloudflare.com-v1" ]; then
  195. ucv_new=$(mod_cloudflare_v1_domain "$uc_val") || g_pslerr=1
  196. # no error save data save data
  197. [ $g_pslerr -eq 0 ] && \
  198. $uc_uci set $g_cfgfile.$uc_name.$uc_var="$ucv_new"
  199. unset ucv_new
  200. fi
  201. unset uco_provider
  202. fi
  203. # rename option domain to option upd_object
  204. # $uc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_object"
  205. ;;
  206. # dns_server)
  207. # # if bind-nsupdate takeover old "dns_server" value as new "upd_nsupd_server" value
  208. # uco_provider=$($uc_uci get $g_cfgfile.$uc_name.upd_provider 2>/dev/null) || \
  209. # uco_provider=$($uc_uci get $g_cfgfile.$uc_name.service_name 2>/dev/null)
  210. # [ "$uco_provider" = "Bind-nsupdate" -o \
  211. # "$uco_provider" = "bind-nsupdate" ] && \
  212. # $uc_uci set $g_cfgfile.$uc_name.upd_nsupd_server="$uc_val"
  213. # # rename option dns_server to new option global_dnssvr
  214. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="global_dnssvr"
  215. # ;;
  216. # bind_network)
  217. # $udc_uci set $g_cfgfile.$uc_name.upd_url_bindnet="$uc_val"
  218. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_url_bindnet"
  219. # ;;
  220. # proxy)
  221. # # proxy value must include protocoll
  222. # $udc_uci set $g_cfgfile.$uc_name.$uc_var="http://$uc_val"
  223. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_proxy"
  224. # ;;
  225. # use_ipv6)
  226. # $udc_uci set $g_cfgfile.$uc_name.$uc_var="$(( 4 + ( 2 * $uc_val ) ))"
  227. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_ipversion"
  228. # TODO update_url)
  229. # TODO update_script)
  230. # other renames
  231. # TODO lookup_host) -> rip_host
  232. # enabled) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_enabled";;
  233. # force_dnstcp) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="rip_host_dnstcp";;
  234. # is_glue) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="rip_host_isglue";;
  235. # ip_interface) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_iface";;
  236. # ip_network) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_net";;
  237. # use_https) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_secure";;
  238. # cacert) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_cacert";;
  239. # username) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_username";;
  240. # password) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_password";;
  241. # param_opt) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_paramopt";;
  242. # param_enc) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_paramenc";;
  243. # leave all other options currently unchanged
  244. *) ;;
  245. esac
  246. return 0
  247. }
  248. return 0
  249. # ignore unknown
  250. else
  251. return 0
  252. fi
  253. }
  254. # read config file
  255. uc_data=$($uc_uci -S -n export "$g_cfgfile")
  256. uc_ret="$?"
  257. # Error then create config file
  258. [ $uc_ret -ne 0 ] && {
  259. touch /etc/config/$uc_cfgfile
  260. chmod 644 /etc/config/$uc_cfgfile
  261. }
  262. # No error and uc_data then execute (eval)
  263. # this will call functions defined above
  264. [ $uc_ret -eq 0 -a -n "$uc_data" ] && eval "$uc_data"
  265. # add config ddns "global" (ignore error if exists)
  266. $uc_uci set ddns.global="$g_cfgfile"
  267. # write changes to config file
  268. $uc_uci commit "$g_cfgfile"
  269. unset uc_uci uc_cfg uc_name uc_var uc_val uc_ret uc_data
  270. return 0
  271. }
  272. # clear LuCI indexcache
  273. rm -f /tmp/luci-indexcache >/dev/null 2>&1
  274. # do config update
  275. update_config
  276. #cleanup
  277. [ $g_pslerr -ne 0 ] && {
  278. unset g_pslfile g_pslerr g_cfgfile
  279. return 1
  280. }
  281. [ -f "$g_pslfile" ] && rm -f "$g_pslfile"
  282. unset g_pslfile g_pslerr g_cfgfile
  283. return 0