blob: 6cc5c18bca8acf37451f8f76bc51337f73794e53 [file] [edit]
#! /bin/sh
# Copyright (c) 2016 Nest Labs, Inc.
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
display_usage ()
{
echo "Thread Network Retain - Save/Recall thread network info"
echo ""
echo "Usage: $(basename $0) [primary-net-info-file] [secondary-net-info-file] [wpanctl path] [command]"
echo ""
echo " Command:"
echo " 'S' or 'save' : Save current network info."
echo " 'R' or 'recall' : Recall/Restore previously saved network info."
echo " 'E' or 'erase' : Erase previously saved network info."
echo ""
echo " [primary-net-info-file] and [secondary-net-info-file] give full path to files to store network info."
echo " [wpanctl path] gives the full path to 'wpanctl'."
echo ""
}
# Check the input args
if [ $# -ne 4 ]; then
display_usage
exit 1
fi
primary_file_name="$1"
secondary_file_name="$2"
wpanctl_command="$3"
retain_command=$4
# List of all wpantund properties saved
WPANTUND_PROP_NAME="Network:Name"
WPANTUND_PROP_KEY="Network:Key"
WPANTUND_PROP_PANID="Network:PANID"
WPANTUND_PROP_XPANID="Network:XPANID"
WPANTUND_PROP_CHANNEL="NCP:Channel"
WPANTUND_PROP_MACADDR="NCP:MACAddress"
WPANTUND_PROP_NODE_TYPE="Network:NodeType"
WPANTUND_PROP_KEY_INDEX="Network:KeyIndex"
WPANTUND_PROP_ROUTER_ID="Thread:RouterID"
WPANTUND_PROP_PREFERRED_ROUTER_ID="Thread:PreferredRouterID"
MAX_ROUTER_ID=60
WPANTUND_PROP_IS_COMMISSIONED="Network:IsCommissioned"
WPANTUND_PROP_AUTO_RESUME="Daemon:AutoAssociateAfterReset"
cur_name=
cur_key=
cur_panid=
cur_xpanid=
cur_channel=
cur_macaddr=
cur_type=
cur_keyindex=
cur_routerid=
new_name=
new_key=
new_panid=
new_xpanid=
new_channel=
new_macaddr=
new_type=
new_keyindex=
new_routerid=
# Populate the new network info variables by reading the values from wpanctl
get_new_network_info_from_wpantund ()
{
val=$($wpanctl_command get -v $WPANTUND_PROP_NAME)
val=${val#\"}
new_name=${val%\"}
val=$($wpanctl_command get $WPANTUND_PROP_KEY)
val=${val#*\[}
new_key=${val%\]*}
val=$($wpanctl_command get $WPANTUND_PROP_PANID)
new_panid=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
val=$($wpanctl_command get $WPANTUND_PROP_XPANID)
new_xpanid=$(echo "$val" | sed -e 's/.*=[[:space:]]*0x//')
val=$($wpanctl_command get $WPANTUND_PROP_CHANNEL)
new_channel=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
val=$($wpanctl_command get $WPANTUND_PROP_MACADDR)
val=${val#*\[}
new_macaddr=${val%\]*}
val=$($wpanctl_command get $WPANTUND_PROP_NODE_TYPE)
new_type=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
val=$($wpanctl_command get $WPANTUND_PROP_KEY_INDEX)
new_keyindex=$(echo "$val" | sed -e 's/.*=[[:space:]]*//')
val=$($wpanctl_command get -v $WPANTUND_PROP_ROUTER_ID)
new_routerid=$(printf "%d" $val)
}
restore_network_info_on_wpantund ()
{
# Calculate a new router id value by adding one to it
# This ensures router id is different upon every reset/restore
router_id=$(($cur_routerid+1))
if [ "$router_id" -ge "$MAX_ROUTER_ID" ]
then
router_id=0
fi
$wpanctl_command set $WPANTUND_PROP_PREFERRED_ROUTER_ID $router_id
$wpanctl_command set $WPANTUND_PROP_MACADDR $cur_macaddr
$wpanctl_command set $WPANTUND_PROP_NAME $cur_name
$wpanctl_command set $WPANTUND_PROP_KEY -d $cur_key
$wpanctl_command set $WPANTUND_PROP_PANID $cur_panid
$wpanctl_command set $WPANTUND_PROP_XPANID -d $cur_xpanid
$wpanctl_command set $WPANTUND_PROP_CHANNEL $cur_channel
$wpanctl_command set $WPANTUND_PROP_KEY_INDEX $cur_keyindex
$wpanctl_command attach
}
is_ncp_commissioned ()
{
val=$($wpanctl_command get -v $WPANTUND_PROP_IS_COMMISSIONED)
if [ "$val" != "true" ]; then
return 1
fi
return 0
}
is_auto_resume_enabled ()
{
val=$($wpanctl_command get -v $WPANTUND_PROP_AUTO_RESUME)
if [ "$val" != "true" ]; then
return 1
fi
return 0
}
verify_cur_info ()
{
if [ -z "$cur_name" ] || \
[ -z "$cur_key" ] || \
[ -z "$cur_panid" ] || \
[ -z "$cur_xpanid" ] || \
[ -z "$cur_channel" ] || \
[ -z "$cur_macaddr" ] || \
[ -z "$cur_type" ] || \
[ -z "$cur_keyindex" ] || \
[ -z "$cur_routerid" ]
then
return 1
fi
return 0
}
verify_new_info ()
{
if [ -z "$new_name" ] || \
[ -z "$new_key" ] || \
[ -z "$new_panid" ] || \
[ -z "$new_xpanid" ] || \
[ -z "$new_channel" ] || \
[ -z "$new_macaddr" ] || \
[ -z "$new_type" ] || \
[ -z "$new_keyindex" ] || \
[ -z "$new_routerid" ]
then
return 1
fi
return 0
}
is_new_info_same_as_cur_info ()
{
if [ "$cur_name" != "$new_name" ] || \
[ "$cur_key" != "$new_key" ] || \
[ "$cur_panid" != "$new_panid" ] || \
[ "$cur_xpanid" != "$new_xpanid" ] || \
[ "$cur_channel" != "$new_channel" ] || \
[ "$cur_macaddr" != "$new_macaddr" ] || \
[ "$cur_type" != "$new_type" ] || \
[ "$cur_keyindex" != "$new_keyindex" ] || \
[ "$cur_routerid" != "$new_routerid" ]
then
return 1
fi
return 0
}
# Reads and parses the network info from a file and populate old network info variables
# First arg ($1) is the file name
read_cur_network_info_from_file ()
{
if [ -r $1 ]; then
while IFS="\= " read -r key value; do
case $key in
$WPANTUND_PROP_NAME)
cur_name=$value
;;
$WPANTUND_PROP_KEY)
cur_key=$value
;;
$WPANTUND_PROP_PANID)
cur_panid=$value
;;
$WPANTUND_PROP_XPANID)
cur_xpanid=$value
;;
$WPANTUND_PROP_CHANNEL)
cur_channel=$value
;;
$WPANTUND_PROP_MACADDR)
cur_macaddr=$value
;;
$WPANTUND_PROP_NODE_TYPE)
cur_type=$value
;;
$WPANTUND_PROP_KEY_INDEX)
cur_keyindex=$value
;;
$WPANTUND_PROP_ROUTER_ID)
cur_routerid=$value
;;
esac
done < $1
fi
}
# Writes the new info into a given file name (first arg should be filename)
write_new_info_to_file ()
{
fname=$1
if [ -e $fname ]; then
rm $fname > /dev/null 2>&1
fi
mkdir -p $(dirname "$fname")
# Write all the contents to the file
echo "${WPANTUND_PROP_NAME} = $new_name" >> $fname
echo "${WPANTUND_PROP_KEY} = $new_key" >> $fname
echo "${WPANTUND_PROP_PANID} = $new_panid" >> $fname
echo "${WPANTUND_PROP_XPANID} = $new_xpanid" >> $fname
echo "${WPANTUND_PROP_CHANNEL} = $new_channel" >> $fname
echo "${WPANTUND_PROP_MACADDR} = $new_macaddr" >> $fname
echo "${WPANTUND_PROP_NODE_TYPE} = $new_type" >> $fname
echo "${WPANTUND_PROP_KEY_INDEX} = $new_keyindex" >> $fname
echo "${WPANTUND_PROP_ROUTER_ID} = $new_routerid" >> $fname
# Add a time stamp
echo "# Saved on " $(date) >> $fname
}
# For test and debugging only
display_cur_network_info ()
{
echo "cur_name is" $cur_name
echo "cur_key is" $cur_key
echo "cur_panid is" $cur_panid
echo "cur_xpanid is" $cur_xpanid
echo "cur_channel is" $cur_channel
echo "cur_macaddr is" $cur_macaddr
echo "cur_type is" $cur_type
echo "cur_keyindex is" $cur_keyindex
echo "cur_routerid is" $cur_routerid
}
# For test and debugging only
display_new_network_info ()
{
echo "new_name is" $new_name
echo "new_key is" $new_key
echo "new_panid is" $new_panid
echo "new_xpanid is" $new_xpanid
echo "new_channel is" $new_channel
echo "new_macaddr is" $new_macaddr
echo "new_type is" $new_type
echo "new_keyindex is" $new_keyindex
echo "new_routerid is" $new_routerid
}
save_network_info ()
{
get_new_network_info_from_wpantund
read_cur_network_info_from_file $primary_file_name
if verify_new_info; then
if is_new_info_same_as_cur_info; then
echo "Saved network info in \"$primary_file_name\" is up-to-date and valid."
else
write_new_info_to_file $secondary_file_name
# verify the file content match what was written
read_cur_network_info_from_file $secondary_file_name
if is_new_info_same_as_cur_info; then
cp $secondary_file_name $primary_file_name
echo "Successfully saved network info in \"$primary_file_name\" and \"$secondary_file_name\""
else
echo "ERROR: Could not save the network data"
fi
# need to figure out if it fails what to do...
fi
else
echo "ERROR: Network info from wpantund is not valid"
fi
}
erase_network_info ()
{
if [ -e $primary_file_name ]; then
rm $primary_file_name
fi
if [ -e $secondary_file_name ]; then
rm $secondary_file_name
fi
echo "Successfully erased network data in \"$primary_file_name\" and \"$secondary_file_name\"".
}
recall_network_info ()
{
if is_ncp_commissioned; then
if is_auto_resume_enabled; then
echo "NCP is commissioned and AutoResume is enabled. Skipping recall."
return
else
echo "NCP is commissioned but AutoResume is not enabled. Skipping recall. Resuming instead."
$wpanctl_command resume
return
fi
fi
echo "NCP is NOT commissioned, trying to recall."
read_cur_network_info_from_file $primary_file_name
# if no valid data from the main file, try to read from the second (backup) file
verify_cur_info || read_cur_network_info_from_file $secondary_file_name
if verify_cur_info; then
restore_network_info_on_wpantund
echo "Successfully recalled network info from \"$primary_file_name\""
else
echo "No valid saved network info to recall."
fi
}
case $retain_command in
R|recall)
recall_network_info
;;
S|save)
save_network_info
;;
E|erase)
erase_network_info
;;
*)
echo "Error: Unknown command \"$retain_command\""
echo " "
display_usage
;;
esac
exit 0