#!/bin/sh PROG="/usr/sbin/inadyn" CONFIGPATH="/tmp/inadyn_config" PIDPATH="/etc/inadyn_pid" CLIENT_INTFS="" CONFIG_FILES="" SERVER_PATH="/etc/ddnsmngr/servers" FORMAT="custom [SECTION] {\n\tusername\t= [USER]\n\tpassword\t= [PWD]\n\tddns-server\t= [SERV]\n\tddns-path\t= [URI]\n\tssl\t\t= [SSL]\n\thostname\t= [NAME]\n\tcheckip-command\t= [CMD]\n\tddns-response\t= [RESPONSES]\n}" . /usr/share/libubox/jshn.sh log() { echo "$*"|logger -t ddnsmngr.init -p debug } get_service_data() { local provider="$1" shift local dir="$1" shift local ipv6="$1" shift local name data url answer script [ $# -ne 2 ] && { return 1 } [ -f "${dir}/${provider}.json" ] || { eval "$1=\"\"" eval "$2=\"\"" return 1 } json_load_file "${dir}/${provider}.json" json_get_var name "name" if [ "$ipv6" -eq "1" ]; then json_select "ipv6" else json_select "ipv4" fi json_get_var data "url" json_get_var answer "answer" json_select ".." json_cleanup response="" if [ -n "${answer}" ]; then answer=$(echo "${answer}" | sed 's/|/ /g') for ans in $answer; do if [ -z "${response}" ]; then response="${ans}" else response="${response}, ${ans}" fi done response="{ ${response} }" fi eval "$1=\"$data\"" eval "$2=\"$response\"" return 0 } generate_inadyn_config() { json_load "${1}" json_get_var service_name service_name json_get_var use_ipv6 use_ipv6 json_get_var interface interface json_get_var username username json_get_var password password json_get_var host lookup_host json_get_var conf_file config_file json_get_var conf_dir config_dir json_get_var server_address server_address json_cleanup if [ -z "${service_name}" ] || [ -z "${host}" ]; then return 1 fi if [ -z "${conf_file}" ]; then return 1 fi if [ -z "${conf_dir}" ]; then return 1 fi # First look into custom path to load the url otherwise default path get_service_data "${service_name}" "${SERVER_PATH}" "${use_ipv6}" server_url server_answer if [ -z "${server_url}" ]; then return 1 fi # Need to pick proto, server address and request uri separately from the url # format http://[server_address]/[update_Request_uri] proto=$(echo $server_url | cut -d':' -f 1) serv=$(echo $server_url | cut -d'/' -f 3 | cut -d'@' -f 2) uri=${server_url#*$serv} if [ -z $proto ] || [ -z $serv ] || [ -z $uri ]; then return 1 fi path=$(echo "$uri" | sed 's/&/\\&/g') update_uri=$(echo $path | sed -e "s#\[DOMAIN\]#%h#g" -e "s#\[PASSWORD\]#%p#g" \ -e "s#\[USERNAME\]#%u#g" -e "s#\[IP\]#%i#g") if [ -z "${interface}" ]; then if [ "${use_ipv6}" -eq 0 ]; then interface="wan" else interface="wan6" fi fi # now get the physical interface name intf=$(ifstatus "${interface}" | jsonfilter -e '@.device') if [ -z "${intf}" ]; then return 1 fi # command to get ip of the interface if [ "${use_ipv6}" -eq 0 ]; then get_ip="\"ifstatus ${interface} | jsonfilter -e '@[\\\\\"ipv4-address\\\\\"][0].address'\"" else get_ip="\"ifstatus ${interface} | jsonfilter -e '@[\\\\\"ipv6-address\\\\\"][0].address'\"" fi if [ "${proto}" = "http" ]; then ssl="false" else ssl="true" fi inadyn_ver=$(inadyn -v) user_agent="inadyn/${inadyn_ver}" config_file="${conf_dir}/${conf_file}" touch "${config_file}" echo "iface = ${intf}" > "${config_file}" echo "period = 600" >> "${config_file}" echo "user-agent = ${user_agent}" >> "${config_file}" if [ "${use_ipv6}" -eq 1 ]; then echo "allow-ipv6 = true" >> "${config_file}" fi if [ -z "${password}" ]; then FORMAT=$(echo "${FORMAT}" | sed 's/\\tpassword\\t= \[PWD\]\\n//g') fi if [ -z "${server_answer}" ]; then FORMAT=$(echo "${FORMAT}" | sed 's/\\tddns-response\\t= \[RESPONSES\]\\n//g') fi config=$(echo $FORMAT | sed -e "s#\[SECTION\]#$conf_file#g" -e "s#\[PWD\]#$password#g" \ -e "s#\[USER\]#$username#g" -e "s#\[SERV\]#$serv#g" \ -e "s#\[URI\]#\"$update_uri\"#g" -e "s#\[SSL\]#$ssl#g" \ -e "s#\[NAME\]#$host#g" -e "s#\[CMD\]#$get_ip#g" \ -e "s#\[RESPONSES\]#$server_answer#g") echo -e "\n\n${config}" >> "${config_file}" return 0 } validate_host_section() { uci_validate_section ddnsmngr host "${1}" \ 'enabled:bool:0' \ 'lookup_host:string' \ 'dm_parent:string' } validate_client_section() { uci_validate_section ddnsmngr client "${1}" \ 'enabled:bool:0' \ 'service_name:string' \ 'interface:string' \ 'ip_network:string' \ 'username:string' \ 'password:string' \ 'use_https:bool:0' \ 'force_dnstcp:bool:0' \ 'use_ipv6:bool:0' \ 'force_ipversion:bool:0' } add_object() { local enabled lookup_host dm_parent use_ipv6 force_ipversion local service_name interface ip_network username password use_https force_dnstcp validate_host_section "${1}" || { log "Validation of host section failed" return } if [ "${enabled}" -ne 1 ] || [ -z "${dm_parent}" ]; then return fi validate_client_section "${dm_parent}" || { log "Validation of client section failed" return } if [ "${enabled}" -ne 1 ]; then return fi service_name=$(uci -q get ddnsmngr.${dm_parent}.service_name) if [ -z "${service_name}" ]; then return fi service_section=$(uci show ddnsmngr | grep "service=\'${service_name}\'" | cut -d'.' -f 2 | head -1) if [ -z "${service_section}" ]; then return fi service_enabled=$(uci -q get ddnsmngr.${service_section}.enabled) if [ "${service_enabled}" -ne 1 ]; then return fi json_init json_add_string "interface" "${interface}" json_add_string "service_name" "${service_name}" json_add_string "username" "${username}" json_add_string "password" "${password}" json_add_string "lookup_host" "${lookup_host}" json_add_string "ip_network" "${ip_network}" json_add_string "use_ipv6" "${use_ipv6}" json_add_string "force_ipversion" "${force_ipversion}" json_add_string "use_https" "${use_https}" json_add_string "force_dnstcp" "${force_dnstcp}" json_add_string "config_file" "${1}" json_add_string "config_dir" "${CONFIGPATH}" json_str=$(json_dump) json_cleanup generate_inadyn_config "${json_str}" if [ "$?" -ne 0 ]; then return fi CONFIG_FILES="${CONFIG_FILES} ${1}" if [ -z "${interface}" ]; then if [ "${use_ipv6}" -eq 0 ]; then interface="wan" else interface="wan6" fi fi for intf in $CLIENT_INTFS; do if [ "${intf}" == "${interface}" ]; then return fi done CLIENT_INTFS="${CLIENT_INTFS} ${interface}" } start_ddnsmngr_service() { rm -rf $CONFIGPATH mkdir $CONFIGPATH mkdir -p $PIDPATH config_load ddnsmngr config_foreach add_object host i=1 for conf in $CONFIG_FILES; do instance="ddnsmngr_${i}" i=$(( i + 1 )) procd_open_instance $instance procd_set_param command "$PROG" procd_append_param command -f "${CONFIGPATH}/${conf}" procd_append_param command -l debug procd_append_param command -P "${PIDPATH}/${conf}" procd_append_param command -n -C procd_close_instance done } stop_ddnsmngr_service() { rm -rf $CONFIGPATH return 0 } add_ddnsmngr_triggers() { procd_open_trigger for intf in $CLIENT_INTFS; do # No need to handle other ifevents like ifupdate etc procd_add_interface_trigger "interface.*.up" $intf /etc/init.d/ddnsmngr restart done procd_close_trigger }