#!/bin/sh /etc/rc.common # SPDX-License-Identifier: MIT # # OpenWRT PLC interface init script for D-Link COVR-P2500 # # Copyright (C) 2024 Daniel Linjama # # Permission is hereby granted, free of charge, to any person obtaining a copy of # this software and associated documentation files (the “Software”), to deal in the # Software without restriction, including without limitation the rights to use, copy, # modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, subject to the # following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. USE_PROCD=1 START=60 STOP=80 EXTRA_COMMANDS="setup" EXTRA_HELP=" setup PLC configuration setup helper" mtd_get_key() { local mtdname="$1" local key="$2" local part local value_dirty part=$(find_mtd_part "$mtdname") if [ -z "$part" ]; then echo "mtd_get_key: partition $mtdname not found!" >&2 return fi value_dirty=$(strings "$part" | sed -n 's/^'"$key"'=//p') echo "$value_dirty" } board=$(board_name) start_service() { if [ ! -f /etc/config/plc ] || [ "$(uci show plc 2>/dev/null)" = "" ]; then touch /etc/config/plc uci set plc.config=config uci commit plc fi local NvmPath local PibPath local Mac local device local NmkSelected local NetworkPasswd local Nmk local Dek local Dak local AdapterName local Enabled local Network local pibpath_tmp config_load plc config_get NvmPath config NvmPath config_get PibPath config PibPath config_get Mac config Mac config_get NmkSelected config NmkSelected config_get NetworkPasswd config NetworkPasswd config_get Nmk config Nmk config_get Dek config Dek config_get Dak config Dak config_get AdapterName config AdapterName config_get Enabled config Enabled config_get Network config Network config_load network config_get device plc device if [ -z "$NvmPath" ]; then echo "plc.config.NvmPath not defined" >&2 exit 1 fi if [ ! -f "$NvmPath" ]; then echo "plc.config.NvmPath does not exist" >&2 exit 1 fi if [ -z "$PibPath" ]; then echo "plc.config.PibPath not defined" >&2 exit 1 fi if [ ! -f "$PibPath" ]; then echo "plc.config.PibPath file does not exist" >&2 exit 1 fi if [ -z "$Mac" ]; then Mac="$(mtd_get_mac_ascii art protest_plc_mac)" fi if [ -z "$device" ]; then echo "network.plc.device not defined" >&2 exit 1 fi # Create modded pib pibpath_tmp="${PibPath}.tmp" rm -f "$pibpath_tmp" cp "$PibPath" "$pibpath_tmp" # Patch MAC into pib if [ ! -z "$Mac" ]; then modpib -M "$Mac" "$pibpath_tmp" fi # Patch NMK if [ 'true' != "$NmkSelected" ]; then if [ -z "$NetworkPwd" ]; then NetworkPwd="$(nmk_get_key art plc_networkpwd)" fi Nmk="$(hpavkey -M "$NetworkPwd")" fi if [ ! -z "$Nmk" ]; then modpib -N "$Nmk" "$pibpath_tmp" fi # Patch DAK if [ -z "$Dek" ]; then if [ -z "$Dak" ]; then Dek="$(mtd_get_key art plc_dek)" if [ ! -z "$Dek" ]; then Dak="$(hpavkey -D "$Dek")" fi fi else Dak="$(hpavkey -D "$Dek")" fi if [ ! -z "$Dak" ]; then modpib -D "$Dak" "$pibpath_tmp" fi # Patch USR if [ -z "$AdapterName" ]; then AdapterName="$(uci get system.@system[0].hostname)" fi modpib -U "$AdapterName" -S "D-Link COVR-P2500" -T "$NetworkPwd" "$pibpath_tmp" if [ -z "$Enabled" ]; then echo "plc.config.Enabled not defined" >&2 exit 1 fi if [ "$Enabled" -ne 1 ]; then echo "plc.config.Enabled is not 1" >&2 exit 1 fi cd /tmp for i in $(seq 1 30); do if [ -d /sys/class/net/$device ]; then break fi sleep 1s done procd_open_instance if [ -z "$Network" ]; then procd_set_param command /usr/bin/plchost -i "$device" -N "$NvmPath" -P "$pibpath_tmp" else [ ! -e /dev/fd ] && ln -s /proc/self/fd /dev/fd procd_set_param command sh -c '/usr/bin/plchost -i '"$device"' -N '"$NvmPath"' -P '"$pibpath_tmp"' 2> >(\ while read line; do \ echo "$line" >&2; \ if [ $(expr match "$line" ".*'$device'.*is running.*") -gt 0 ]; then \ echo "Adding '$device' to br-'$Network'"; \ brctl addif "br-'$Network'" "'$device'"; \ fi; \ done)' fi procd_set_param file /etc/config/plc procd_set_param stdout 1 procd_set_param stderr 1 procd_set_param netdev "$device" procd_close_instance } service_triggers() { procd_add_reload_trigger "plc" "network" } reload_service() { stop start } stop_service() { local device local Network config_load plc config_get Network config Network config_load network config_get device plc device if [ ! -z "$Network" ]; then brctl delif "br-$Network" "$device" fi } service_stopped() { local PibPath local Mac local device config_load plc config_get PibPath config PibPath config_get Mac config Mac config_load network config_get device plc device if [ ! -z "$PibPath" ] && [ -f "${PibPath}.tmp" ]; then rm "${PibPath}.tmp" fi if [ -z "$Mac" ]; then Mac="$(mtd_get_mac_ascii art protest_plc_mac)" fi plctool -i "$device" -R "$Mac" } setup() { if [ ! -f /etc/config/plc ] || [ "$(uci show plc 2>/dev/null)" = "" ]; then touch /etc/config/plc uci set plc.config=config uci commit plc fi for tool in hpavkey modpib plchost; do which $tool >/dev/null if [ $? -ne 0 ]; then echo -n "open-plc-utils missing. Install required packages? (y/N) " read i if [ "$i" = "y" ] || [ "$i" = "Y" ]; then opkg update opkg install open-plc-utils open-plc-utils-hpavkey open-plc-utils-modpib open-plc-utils-plchost open-plc-utils-plctool if [ $? -ne 0 ]; then echo "Failed to install open-plc-utils" >&2 exit 1 fi else echo 'Please run "opkg install open-plc-utils open-plc-utils-hpavkey open-plc-utils-modpib open-plc-utils-plchost open-plc-utils-plctool"' >&2 exit 1 fi break fi done echo -n "Download original firmware and extract files from /lib/plc to /etc/plc? (y/N) " read i if [ "$i" = "y" ] || [ "$i" = "Y" ]; then if [ -z "$(which unsquashfs)" ]; then echo -n "unsquashfs missing. Install squashfs-tools-unsquashfs package? (y/N)" read i if [ "$i" = "y" ] || [ "$i" = "Y" ]; then opkg update opkg install squashfs-tools-unsquashfs if [ $? -ne 0 ]; then echo "Failed to install squashfs-tools-unsquashfs" >&2 exit 1 fi else echo 'Please run "opkg install squashfs-tools-unsquashfs" or put extracted firmware files to /etc/plc directory' >&2 exit 1 fi fi cd /tmp FW="COVRP2500A1_FW101b08_decrypted.bin" rm -f "$FW" wget -O "$FW" "http://pmdap.dlink.com.tw/PMD/GetAgileFile?itemNumber=FIR1800225&fileName=COVRP2500A1_FW101b08_decrypted.bin&fileSize=1.5990457E7;1.5992229E7;65141.0;" if [ ! -f "$FW" ]; then echo "Download failed. Check network" >&2 exit 1 fi unsquashfs -lls "$FW" /lib/plc | grep -q '\.pib$' if [ $? -ne 0 ]; then echo "$FW does not contain any /lib/plc/*.pib files" >&2 exit 1 fi unsquashfs "$FW" /lib/plc mkdir -p /etc/plc/ cp squashfs-root/lib/plc/* /etc/plc/ rm -rf squashfs-root rm "$FW" fi options=$(echo /etc/plc/*.pib) if [ "$options" = "/etc/plc/*.pib" ]; then echo "No files matching /etc/plc/*.pib" >&2 exit 1 fi count=$(echo $options | wc -w) i="" while [ -z "$i" ] || [ $i -lt 1 ] || [ $i -gt $count ]; do i=1 for f in $options; do echo "${i}) $f" i=$((i+1)) done echo -n "Select PibPath [1-${count}]: " read i done pibpath=$(echo $options | awk '{print$'$i'}') uci set plc.config.PibPath=$pibpath options=$(echo /etc/plc/*.nvm) if [ "$options" = "/etc/plc/*.nvm" ]; then echo "No files matching /etc/plc/*.nvm" >&2 exit 1 fi count=$(echo $options | wc -w) if [ $count -gt 1 ]; then i="" while [ -z "$i" ] || [ $i -lt 1 ] || [ $i -gt $count ]; do i=1 for f in $options; do echo "${i}) $f" i=$((i+1)) done echo -n "Select NvmPath [1-${count}]: " read i done nvmpath=$(echo $options | awk '{print$'$i'}') else nvmpath=$options fi uci set plc.config.NvmPath=$nvmpath echo -n "NetworkPasswd (leave empty to use default plc_networkpwd): " read networkpwd if [ -z "$networkpwd" ]; then networkpwd="$(mtd_get_key art plc_networkpwd)" fi uci set plc.config.NetworkPasswd="$networkpwd" uci set plc.config.Nmk="$(hpavkey -M "$networkpwd")" uci set plc.config.NmkSelected='true' uci set plc.config.Mac="$(mtd_get_key art protest_plc_mac)" dek="$(mtd_get_key art plc_dek)" uci set plc.config.Dek="$dek" uci set plc.config.Dak="$(hpavkey -D "$dek")" uci set plc.config.AdapterName="$(uci get system.@system[0].hostname)" echo -n "Enable plc? (Y/n) " read i if [ "$i" = "n" ] || [ "$i" = "N" ]; then uci set plc.config.Enabled=0 disable else uci set plc.config.Enabled=1 enable fi echo -n "Automatically add to br-lan bridge? (Y/n) " read i if [ "$i" = "n" ] || [ "$i" = "N" ]; then uci set plc.config.Network="" else uci set plc.config.Network="lan" fi # Commit changes if [ ! -z "$(uci changes plc)" ]; then uci commit plc fi echo 'PLC configured. Start plc service with "/etc/init.d/plc start" and enable on boot with "/etc/init.d/plc enable".' }