#!/bin/sh # Copyright (C) 2011-2012 Luka Perkov # Copyright (C) 2013 Inteno Broadband Technology AB # Author Ahmed Zribi # TODO: merge this one somewhere in OpenWrt uci_remove_list_element() { local option="$1" local value="$2" local list="$(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q get $option)" local elem /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q delete $option for elem in $list; do if [ "$elem" != "$value" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add_list $option=$elem fi done } freecwmp_output() { if [ "$FLAGS_value" = "${FLAGS_TRUE}" ]; then local parameter="$1" local value="$2" local delimiter="$3" if [ "$delimiter" = "" ]; then delimiter=":" fi if [ -n "$value" -o ${FLAGS_empty} -eq ${FLAGS_TRUE} ]; then if [ ${FLAGS_value} -eq ${FLAGS_TRUE} ]; then echo $ECHO_newline $value else echo $ECHO_newline $parameter "$delimiter" $value fi fi fi if [ ${FLAGS_empty} -eq ${FLAGS_TRUE} ]; then local parameter="$1" echo $ECHO_newline $parameter fi if [ "$FLAGS_json" = "${FLAGS_TRUE}" ]; then local parameter="$1" local value="$2" local permissions="$3" local type="$4" local fault_code="$5" local status="$6" local instance="$7" local success="$8" echo `freecwmp_json_output "$parameter" "$value" "$permissions" "$type" "$fault_code" "$status" "$instance" "$success"` fi } freecwmp_json_output() { local MSG="" local parameter="$1" local value="$2" local permissions="$3" local type="$4" local fault_code="$5" local status="$6" local instance="$7" local success="$8" if [ "$type" = "" ]; then type="xsd:string" fi case "$action" in get_value) json_init json_add_string "parameter" "$parameter" json_add_string "value" "$value" json_add_string "type" "$type" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; get_name) json_init json_add_string "parameter" "$parameter" json_add_string "writable" "$permissions" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; get_notification) json_init json_add_string "parameter" "$parameter" json_add_string "notification" "$value" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; add_object) json_init json_add_string "instance" "$instance" json_add_string "status" "$status" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; delete_object) json_init json_add_string "status" "$status" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; apply_value) json_init json_add_string "status" "$status" json_close_object MSG=`json_dump` ;; apply_notification) json_init json_add_string "success" "$success" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; esac echo "$MSG" } freecwmp_fault_output() { local MSG="" local parameter="$1" local fault_code="$2" local success="$3" case "$action" in apply_value) json_init json_add_string "parameter" "$parameter" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; apply_notification) json_init json_add_string "success" "$success" json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; *download) json_init json_add_string "fault_code" "$fault_code" json_close_object MSG=`json_dump` ;; esac echo "$MSG" } freecwmp_value_output() { local tmp_value=${FLAGS_value} FLAGS_value=${FLAGS_TRUE} local tmp_json=${FLAGS_json} FLAGS_json=${FLAGS_FALSE} freecwmp_output "$1" "$2" "V" FLAGS_value=$tmp_value FLAGS_json=$tmp_json } freecwmp_notification_output() { local tmp_value=${FLAGS_value} FLAGS_value=${FLAGS_TRUE} local tmp_json=${FLAGS_json} FLAGS_json=${FLAGS_FALSE} freecwmp_output "$1" "$2" "N" FLAGS_value=$tmp_value FLAGS_json=$tmp_json } freecwmp_tags_output() { local tmp_value=${FLAGS_value} FLAGS_value=${FLAGS_TRUE} local tmp_json=${FLAGS_json} FLAGS_json=${FLAGS_FALSE} freecwmp_output "$1" "$2" "T" FLAGS_value=$tmp_value FLAGS_json=$tmp_json } freecwmp_not_implemented() { local tmp_value=${FLAGS_value} FLAGS_value=${FLAGS_TRUE} local tmp_json=${FLAGS_json} FLAGS_json=${FLAGS_FALSE} freecwmp_output "$1" "NOT_IMPLEMENTED" FLAGS_value=$tmp_value FLAGS_json=$tmp_json } freecwmp_parse_formated_parameter() { local _clean_parameter="$1" local _formated_parameter="$2" local _values local _clean_parameter_array=`echo $_clean_parameter | sed 's/\./ /g'` local _formated_parameter_array=`echo $_formated_parameter | sed 's/\./ /g'` local i local j=0 for i in $_formated_parameter_array do let j=$j+1 if [ "x$i" == "x{i}" ]; then # get value for sections maked as {i} local m local n=0 for m in $_clean_parameter_array do let n=$n+1 if [ $n -eq $j ]; then if [ "x$_values" == "x" ]; then _values="$m" else _values="$_values $m" fi fi done else # check if sections not marked as {i} match local m local n=0 for m in $_clean_parameter_array do let n=$n+1 if [ $n -eq $j -a "x$m" != "x$i" ]; then eval "export -- \"$3=-1\"" return fi done fi done eval "export -- \"$3=0\"" eval "export -- \"$4=\"\"$_values\"\"\"" } freecwmp_config_cwmp() { config_get __parameter "$1" "parameter" config_get __value "$1" "value" config_get __tags "$1" "tag" if [ "$__parameter" = "$4" ]; then if [ "get" = "$2" ]; then if [ "value" = "$3" ]; then eval "export -- \"$5=\"\"$__value\"\"\"" fi if [ "tags" = "$3" ]; then eval "export -- \"$5=\"\"$__tags\"\"\"" fi elif [ "set" = "$2" ]; then if [ "value" = "$3" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set cwmp.$1.value=$5 2> /dev/null fi elif [ "check" = "$2" ]; then if [ "parameter" = "$3" ]; then eval "export -- \"$5=\"$1\"\"" fi fi fi } freecwmp_config_notifications() { config_get __active "$1" "active" config_get __passive "$1" "passive" config_get __disabled "$1" "disabled" local length="0" for item in $__disabled do if [ "$item" = "$3" ]; then eval "export -- \"$4=0\"" return 0 elif [ "`echo $3|grep $item`" = "$3" -a "`echo $item|grep '\.$'`" != "" ]; then if [ $length -lt ${#item} ]; then eval "export -- \"$4=0\"" length="${#item}" fi fi done for item in $__active do if [ "$item" = "$3" ]; then eval "export -- \"$4=2\"" return 0 elif [ "`echo $3|grep $item`" = "$3" -a "`echo $item|grep '\.$'`" != "" ]; then if [ $length -lt ${#item} ]; then eval "export -- \"$4=2\"" length="${#item}" fi fi done for item in $__passive do if [ "$item" = "$3" ]; then eval "export -- \"$4=1\"" return 0 elif [ "`echo $3|grep $item`" = "$3" -a "`echo $item|grep '\.$'`" != "" ]; then if [ $length -lt ${#item} ]; then eval "export -- \"$4=1\"" length="${#item}" fi fi done return 0 } freecwmp_get_parameter_value() { local _dest="$1" local _parm="$2" local _val config_foreach freecwmp_config_cwmp "cwmp" "get" "value" "$_parm" "_val" eval "export -- \"$_dest=\"\"$_val\"\"\"" } freecwmp_set_parameter_value() { local _parm="$1" local _val="$2" config_foreach freecwmp_config_cwmp "cwmp" "check" "parameter" "$_parm" "_section" if [ ! "$_section" = "" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set cwmp.$_section.value=$_val 2> /dev/null else /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q batch << EOF 2>&1 >/dev/null add cwmp cwmp set cwmp.@cwmp[-1].parameter="$_parm" set cwmp.@cwmp[-1].value="$_val" EOF fi config_foreach freecwmp_config_notifications "notifications" "get" "$_parm" "tmp" # TODO: notify freecwmpd about the change # if [ "$tmp" -eq "2" ]; then # fi } freecwmp_get_parameter_notification() { local _dest="$1" local _parm="$2" local _val local _parent config_foreach freecwmp_config_notifications "notifications" "get" "$_parm" "_val" if [ "$_val" = "" ]; then if [ "`echo $_parm|grep '\.$'`" = "" ]; then _parent="${_parm%.*}." config_foreach freecwmp_config_notifications "notifications" "get" "$_parent" "_val" else _parent="${_parm%.*.}." config_foreach freecwmp_config_notifications "notifications" "get" "$_parent" "_val" fi fi if [ "$_val" = "" ];then _val="0" ;fi eval "export -- \"$_dest=$_val\"" } freecwmp_notify() { local parm="$1" local val="$2" local attribute local type="$3" freecwmp_get_parameter_notification "attribute" "$parm" if [ "$attribute" != "0" ];then ubus ${UBUS_SOCKET:+-s $UBUS_SOCKET} call tr069 notify '{ "parameter": "'$parm'", "value": "'$val'", "attribute": "'$attribute'", "type": "'$type'" }' & fi } freecwmp_update_notification() { local list="$1" local __parm="$2" for i in $(/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q get cwmp.@notifications[0].$list);do if [ "`echo $i|grep $__parm`" != "" ];then uci_remove_list_element "cwmp.@notifications[0].$list" "$i" 2>/dev/null fi done } freecwmp_set_parameter_notification() { local _parm="$1" local _val="$2" local tmp=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q get cwmp.@notifications[0] 2>/dev/null` if [ "$tmp" = "" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add cwmp notifications 2>&1 >/dev/null else uci_remove_list_element "cwmp.@notifications[0].passive" "$_parm" 2>/dev/null uci_remove_list_element "cwmp.@notifications[0].active" "$_parm" 2>/dev/null uci_remove_list_element "cwmp.@notifications[0].disabled" "$_parm" 2>/dev/null freecwmp_update_notification "passive" "$_parm" 2>/dev/null freecwmp_update_notification "active" "$_parm" 2>/dev/null freecwmp_update_notification "disabled" "$_parm" 2>/dev/null fi if [ "`echo $_parm|grep '\.$'`" = "" ]; then _parent="${_parm%.*}." config_foreach freecwmp_config_notifications "notifications" "get" "$_parent" "_val_p" else _parent="${_parm%.*.}." config_foreach freecwmp_config_notifications "notifications" "get" "$_parent" "_val_p" fi if [ "$_val" -eq "1" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add_list cwmp.@notifications[0].passive="$_parm" 2>&1 >/dev/null elif [ "$_val" -eq "2" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add_list cwmp.@notifications[0].active="$_parm" 2>&1 >/dev/null elif [ "$_val" -eq "0" -a "$_val_p" != "" -a "$_val_p" != "0" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add_list cwmp.@notifications[0].disabled="$_parm" 2>&1 >/dev/null fi } freecwmp_get_parameter_tags() { local _dest="$1" local _parm="$2" config_foreach freecwmp_config_cwmp "cwmp" "get" "tags" "$_parm" "_tags" eval "export -- \"$_dest=\"\"$_tags\"\"\"" } freecwmp_set_parameter_tag() { local _parm="$1" local _tag="$2" config_foreach freecwmp_config_cwmp "cwmp" "check" "parameter" "$_parm" "_section" if [ ! "$_section" = "" ]; then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q add_list cwmp.$_section.tag=$_tag 2> /dev/null else /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q batch << EOF 2>&1 >/dev/null add cwmp cwmp set cwmp.@cwmp[-1].parameter="$_parm" add_list cwmp.@cwmp[-1].tag="$_tag" EOF fi } delay_service_restart() { local service="$1" local delay="$2" if [ ! -f /tmp/end_session.sh ];then ubus ${UBUS_SOCKET:+-s $UBUS_SOCKET} call tr069 command '{ "command": "action_end_session" }' &> /dev/null & echo '#!/bin/sh' > /tmp/end_session.sh chmod +x /tmp/end_session.sh else check="`cat /tmp/end_session.sh|grep /etc/init.d/$service`" if [ "$check" != "" ];then return 0 fi fi cat << EOF >> /tmp/end_session.sh /etc/init.d/$service stop &> /dev/null sleep $delay /etc/init.d/$service start &> /dev/null EOF } delay_command() { local command="$1" local delay="$2" if [ ! -f /tmp/end_session.sh ];then ubus ${UBUS_SOCKET:+-s $UBUS_SOCKET} call tr069 command '{ "command": "action_end_session" }' &> /dev/null & echo '#!/bin/sh' > /tmp/end_session.sh chmod +x /tmp/end_session.sh else check="`cat /tmp/end_session.sh|grep $command`" if [ "$check" != "" ];then return 0 fi fi cat << EOF >> /tmp/end_session.sh sleep $delay $command &> /dev/null EOF } freecwmp_check_fault() { if [ "$1" = "." ]; then return $FAULT_CPE_INVALID_PARAMETER_NAME fi return $FAULT_CPE_NO_FAULT } freecwmp_set_parameter_fault() { local _parm="$1" local _fault="$2" /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q -P /var/state batch << EOF 2>&1 >/dev/null add cwmp fault set cwmp.@fault[-1].parameter="$_parm" set cwmp.@fault[-1].fault_code="$_fault" EOF } freecwmp_add_lan_device_ip_interface() { local _parm="$1" local _instance="$2" if [ "$_instance" = "1" ];then indice="" else indice=$_instance fi /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q batch << EOF 2>&1 >/dev/null add cwmp object set cwmp.@object[-1].parameter="$_parm" set cwmp.@object[-1].instance="$_instance" set cwmp.@object[-1].interface="lan$indice" EOF if [ "$indice" != "" ]; then let i=$indice-1 /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set network.lan$indice=interface 2> /dev/null /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set network.lan$indice.ifname=eth$i 2> /dev/null /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set network.lan$indice.type=bridge 2> /dev/null /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q set network.lan$indice.proto=dhcp 2> /dev/null fi } freecwmp_execute_functions() { local function_list="$1" local arg1="$2" local arg2="$3" local arg3="$4" local no_fault="0" local fault_code="" for function_name in $function_list do func=$(echo "$arg1" | cut -d "." -f 2) func_config=`/sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} get -q cwmp.@$func[0].function` if [ "`echo $function_name|grep \"$func_config\"`" != "" -o "$func" = "" ];then $function_name "$arg1" "$arg2" "$arg3" fault_code="$?" if [ "$fault_code" = "0" ]; then no_fault="1" fi if [ "$fault_code" != "0" -a "$fault_code" != "$FAULT_CPE_INVALID_PARAMETER_NAME" ]; then return $fault_code fi fi done if [ "$no_fault" = "1" ]; then fault_code="0"; fi return $fault_code } freecwmp_check_image() { . /etc/functions.sh; include /lib/upgrade; platform_check_image /tmp/firmware_upgrade_image return $? } freecwmp_check_flash_size() { local size=0 if [ -f /proc/mtd ];then for line in `cat /proc/mtd` do if [ "`echo $line|grep "^([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+\"([^[:space:]]+)\""`" != "" ] then b=`cat $line|cut -f1 -d " "` n=`cat $line|cut -f3 -d " "` if [ "$n" = "\"linux\"" -o "$n" = "\"firmware\"" ];then size=`echo $(($s))` break; fi fi done elif [ -f /proc/partitions ] then for line in `cat /proc/partitions` do if [ "`echo $line|grep "[[:space:]]*([[:digit:]]+)[[:space:]]+([[:digit:]]+)[[:space:]]+([^[:space:]]+)[[:space:]]+([^[:space:]]+)"`" != "" ] then b=`cat $line|cut -f2 -d " "` n=`cat $line|cut -f3 -d " "` if [ checkline "([^[:space:]]+)" $n ];then size=`let $b*1024`; break; fi fi done fi echo "$size" } freecwmp_apply_firmware() { local fault_code="9000" sync killall dropbear uhttpd; sleep 1; /sbin/sysupgrade /tmp/firmware_upgrade_image_last_valid if [ "$?" != "0" ];then let fault_code=$fault_code+$FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED freecwmp_fault_output "" "$fault_code" else freecwmp_fault_output "" "$FAULT_CPE_NO_FAULT" fi } freecwmp_apply_web_content() { local fault_code="9000" /bin/opkg install /tmp/web_content.ipk if [ "$?" != "0" ];then rm /tmp/web_content.ipk 2> /dev/null let fault_code=$fault_code+$FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED freecwmp_fault_output "" "$fault_code" else freecwmp_fault_output "" "$FAULT_CPE_NO_FAULT" fi } freecwmp_apply_vendor_configuration() { local fault_code="9000" /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q import < /tmp/vendor_configuration_file.cfg if [ "$?" = "0" ];then /sbin/uci ${UCI_CONFIG_DIR:+-c $UCI_CONFIG_DIR} -q commit if [ "$?" != "0" ];then let fault_code=$fault_code+$FAULT_CPE_INTERNAL_ERROR freecwmp_fault_output "" "$fault_code" else freecwmp_fault_output "" "$FAULT_CPE_NO_FAULT" sync reboot fi else rm /tmp/vendor_configuration_file.cfg 2> /dev/null let fault_code=$fault_code+$FAULT_CPE_DOWNLOAD_FAIL_FILE_CORRUPTED freecwmp_fault_output "" "$fault_code" fi }