2 # script for sending updates to cloudflare.com
3 # 2014-2015 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
4 # many thanks to Paul for testing and feedback during development
6 # This script is parsed by dynamic_dns_functions.sh inside send_update() function
8 # using following options from /etc/config/ddns
9 # option username - your cloudflare e-mail
10 # option password - cloudflare api key, you can get it from cloudflare.com/my-account/
11 # option domain - your full hostname to update, in cloudflare its subdomain.domain
12 # i.e. myhost.example.com where myhost is the subdomain and example.com is your domain
14 # variable __IP already defined with the ip-address to use for update
16 [ $use_https -eq 0 ] && write_log
14 "Cloudflare only support updates via Secure HTTP (HTTPS). Please correct configuration!"
17 [ -z "$username" ] && write_log
14 "Service section not configured correctly! Missing 'username'"
18 [ -z "$password" ] && write_log
14 "Service section not configured correctly! Missing 'password'"
20 local __RECID __URL __KEY __KEYS __FOUND __SUBDOM __DOMAIN __TLD
22 # split given Host/Domain into TLD, registrable domain, and subdomain
23 split_FQDN
$domain __TLD __DOMAIN __SUBDOM
24 [ $?
-ne 0 -o -z "$__DOMAIN" ] && \
25 write_log
14 "Wrong Host/Domain configuration ($domain). Please correct configuration!"
27 # put together what we need
28 __DOMAIN
="$__DOMAIN.$__TLD"
30 # parse OpenWrt script with
31 # functions for parsing and generating json
32 .
/usr
/share
/libubox
/jshn.sh
34 # function copied from /usr/share/libubox/jshn.sh
35 # from BB14.09 for backward compatibility to AA12.09
36 grep -i "json_get_keys" /usr
/share
/libubox
/jshn.sh
>/dev
/null
2>&1 || json_get_keys
() {
41 json_get_var _tbl_cur
"$2"
43 _json_get_var _tbl_cur JSON_CUR
45 local __var
="${JSON_PREFIX}KEYS_${_tbl_cur}"
46 eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]"
49 # function to "sed" unwanted string parts from DATFILE
51 # based on the sample output on cloudflare.com homepage we need to do some cleanup
52 sed -i 's/^[ \t]*//;s/[ \t]*$//' $DATFILE # remove invisible chars at beginning and end of lines
53 sed -i '/^-$/d' $DATFILE # remove lines with "-" (dash)
54 sed -i '/^$/d' $DATFILE # remove empty lines
55 sed -i "#'##g" $DATFILE # remove "'" (single quote)
58 # build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
59 # to "rec_load_all" to detect rec_id needed for update
60 __URL
="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
61 __URL
="${__URL}?a=rec_load_all" # -d 'a=rec_load_all'
62 __URL
="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
63 __URL
="${__URL}&email=$username" # -d 'email=sample@example.com'
64 __URL
="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
66 # lets request the data
67 do_transfer
"$__URL" ||
return 1
69 cleanup
# cleanup dat file
70 json_load
"$(cat $DATFILE)" # lets extract data
71 __FOUND
=0 # found record indicator
72 json_get_var __RES
"result" # cloudflare result of last request
73 json_get_var __MSG
"msg" # cloudflare error message
74 [ "$__RES" != "success" ] && {
75 write_log
4 "'rec_load_all' failed with error: \n$__MSG"
79 json_select
"response"
83 for __KEY
in $__KEYS; do
84 local __ZONE __DISPLAY __NAME __TYPE
86 # json_get_var __ZONE "zone_name" # for debugging
87 # json_get_var __DISPLAY "display_name" # for debugging
88 json_get_var __NAME
"name"
89 json_get_var __TYPE
"type"
90 if [ "$__NAME" = "$domain" ]; then
91 # we must verify IPv4 and IPv6 because there might be both for the same host
92 [ \
( $use_ipv6 -eq 0 -a "$__TYPE" = "A" \
) -o \
( $use_ipv6 -eq 1 -a "$__TYPE" = "AAAA" \
) ] && {
93 __FOUND
=1 # mark found
94 break # found leave for loop
99 [ $__FOUND -eq 0 ] && {
100 # we don't need to continue trying to update cloudflare because record to update does not exist
101 # user has to setup record first outside ddns-scripts
102 write_log
14 "No valid record found at Cloudflare setup. Please create first!"
104 json_get_var __RECID
"rec_id" # last thing to do get rec_id
105 json_cleanup
# cleanup
106 write_log
7 "rec_id '$__RECID' detected for host/domain '$domain'"
108 # build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
109 # for "rec_edit" to update IP address
110 __URL
="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
111 __URL
="${__URL}?a=rec_edit" # -d 'a=rec_edit'
112 __URL
="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
113 __URL
="${__URL}&id=$__RECID" # -d 'id=9001'
114 __URL
="${__URL}&email=$username" # -d 'email=sample@example.com'
115 __URL
="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
117 [ $use_ipv6 -eq 0 ] && __URL
="${__URL}&type=A" # -d 'type=A' (IPv4)
118 [ $use_ipv6 -eq 1 ] && __URL
="${__URL}&type=AAAA" # -d 'type=AAAA' (IPv6)
120 # handle subdomain or domain record
121 [ -n "$__SUBDOM" ] && __URL
="${__URL}&name=$__SUBDOM" # -d 'name=sub' (HOST/SUBDOMAIN)
122 [ -z "$__SUBDOM" ] && __URL
="${__URL}&name=$__DOMAIN" # -d 'name=example.com'(DOMAIN)
124 __URL
="${__URL}&content=$__IP" # -d 'content=1.2.3.4'
125 __URL
="${__URL}&service_mode=0" # -d 'service_mode=0'
126 __URL
="${__URL}&ttl=1" # -d 'ttl=1'
129 do_transfer
"$__URL" ||
return 1
131 cleanup
# cleanup tmp file
132 json_load
"$(cat $DATFILE)" # lets extract data
133 json_get_var __RES
"result" # cloudflare result of last request
134 json_get_var __MSG
"msg" # cloudflare error message
135 [ "$__RES" != "success" ] && {
136 write_log
4 "'rec_edit' failed with error:\n$__MSG"
139 write_log
7 "Update of rec_id '$__RECID' successful"