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.

309 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. domains\.google\.com)
  165. $uc_uci set $g_cfgfile.$uc_name.$uc_var="google.com";;
  166. loopia\.com)
  167. $uc_uci set $g_cfgfile.$uc_name.$uc_var="loopia.se";;
  168. NoIP\.com|No-IP\.com)
  169. $uc_uci set $g_cfgfile.$uc_name.$uc_var="no-ip.com";;
  170. spdns\.de)
  171. $uc_uci set $g_cfgfile.$uc_name.$uc_var="spdyn.de";;
  172. strato\.de)
  173. $uc_uci set $g_cfgfile.$uc_name.$uc_var="strato.com";;
  174. *)
  175. # all others leave unchanged
  176. ;;
  177. esac
  178. # rename option service_name to option upd_provider
  179. # $uc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_provider"
  180. ;;
  181. domain|upd_object)
  182. # verify if lookup_host is set
  183. $uc_uci get $g_cfgfile.$uc_name.lookup_host >/dev/null 2>&1 || \
  184. $uc_uci set $g_cfgfile.$uc_name.lookup_host="$uc_val"
  185. if [ -f "$g_pslfile" ]; then
  186. # if service_name/upd_provider cloudflare_v1 then change domain/upd_object to new syntax
  187. # there is no sort order inside uci data so we need multiple checks
  188. uco_provider=$($uc_uci get $g_cfgfile.$uc_name.upd_provider 2>/dev/null) || \
  189. uco_provider=$($uc_uci get $g_cfgfile.$uc_name.service_name 2>/dev/null)
  190. if [ "$uco_provider" = "CloudFlare" \
  191. -o "$uco_provider" = "cloudflare.com" \
  192. -o "$uco_provider" = "cloudflare.com-v1" ]; then
  193. ucv_new=$(mod_cloudflare_v1_domain "$uc_val") || g_pslerr=1
  194. # no error save data save data
  195. [ $g_pslerr -eq 0 ] && \
  196. $uc_uci set $g_cfgfile.$uc_name.$uc_var="$ucv_new"
  197. unset ucv_new
  198. fi
  199. unset uco_provider
  200. fi
  201. # rename option domain to option upd_object
  202. # $uc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_object"
  203. ;;
  204. # dns_server)
  205. # # if bind-nsupdate takeover old "dns_server" value as new "upd_nsupd_server" value
  206. # uco_provider=$($uc_uci get $g_cfgfile.$uc_name.upd_provider 2>/dev/null) || \
  207. # uco_provider=$($uc_uci get $g_cfgfile.$uc_name.service_name 2>/dev/null)
  208. # [ "$uco_provider" = "Bind-nsupdate" -o \
  209. # "$uco_provider" = "bind-nsupdate" ] && \
  210. # $uc_uci set $g_cfgfile.$uc_name.upd_nsupd_server="$uc_val"
  211. # # rename option dns_server to new option global_dnssvr
  212. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="global_dnssvr"
  213. # ;;
  214. # bind_network)
  215. # $udc_uci set $g_cfgfile.$uc_name.upd_url_bindnet="$uc_val"
  216. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_url_bindnet"
  217. # ;;
  218. # proxy)
  219. # # proxy value must include protocoll
  220. # $udc_uci set $g_cfgfile.$uc_name.$uc_var="http://$uc_val"
  221. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_proxy"
  222. # ;;
  223. # use_ipv6)
  224. # $udc_uci set $g_cfgfile.$uc_name.$uc_var="$(( 4 + ( 2 * $uc_val ) ))"
  225. # $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_ipversion"
  226. # TODO update_url)
  227. # TODO update_script)
  228. # other renames
  229. # TODO lookup_host) -> rip_host
  230. # enabled) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_enabled";;
  231. # force_dnstcp) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="rip_host_dnstcp";;
  232. # is_glue) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="rip_host_isglue";;
  233. # ip_interface) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_iface";;
  234. # ip_network) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="lip_net";;
  235. # use_https) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_secure";;
  236. # cacert) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_url_cacert";;
  237. # username) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_username";;
  238. # password) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_password";;
  239. # param_opt) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_paramopt";;
  240. # param_enc) $udc_uci rename $g_cfgfile.$uc_name.$uc_var="upd_paramenc";;
  241. # leave all other options currently unchanged
  242. *) ;;
  243. esac
  244. return 0
  245. }
  246. return 0
  247. # ignore unknown
  248. else
  249. return 0
  250. fi
  251. }
  252. # read config file
  253. uc_data=$($uc_uci -S -n export "$g_cfgfile")
  254. uc_ret="$?"
  255. # Error then create config file
  256. [ $uc_ret -ne 0 ] && {
  257. touch /etc/config/$uc_cfgfile
  258. chmod 644 /etc/config/$uc_cfgfile
  259. }
  260. # No error and uc_data then execute (eval)
  261. # this will call functions defined above
  262. [ $uc_ret -eq 0 -a -n "$uc_data" ] && eval "$uc_data"
  263. # add config ddns "global" (ignore error if exists)
  264. $uc_uci set ddns.global="$g_cfgfile"
  265. # write changes to config file
  266. $uc_uci commit "$g_cfgfile"
  267. unset uc_uci uc_cfg uc_name uc_var uc_val uc_ret uc_data
  268. return 0
  269. }
  270. # clear LuCI indexcache
  271. rm -f /tmp/luci-indexcache >/dev/null 2>&1
  272. # do config update
  273. update_config
  274. #cleanup
  275. [ $g_pslerr -ne 0 ] && {
  276. unset g_pslfile g_pslerr g_cfgfile
  277. return 1
  278. }
  279. [ -f "$g_pslfile" ] && rm -f "$g_pslfile"
  280. unset g_pslfile g_pslerr g_cfgfile
  281. return 0