From 6aa6f4560686d0ca481e874bdbac1622f4d64729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Bida?= Date: Tue, 2 Jul 2024 04:14:53 +0200 Subject: [PATCH] [tcat] implement decommissioning in tcat_agent (#10415) Commits adds handling of TCAT TLV 0x60 `kTlvDecommission`. --- src/core/meshcop/tcat_agent.cpp | 25 +++++++- src/core/meshcop/tcat_agent.hpp | 1 + .../scripts/expect/cli-tcat-decommission.exp | 64 +++++++++++++++++++ tools/tcat_ble_client/bbtc.py | 3 +- tools/tcat_ble_client/cli/base_commands.py | 16 +++++ tools/tcat_ble_client/cli/cli.py | 4 +- 6 files changed, 110 insertions(+), 3 deletions(-) create mode 100755 tests/scripts/expect/cli-tcat-decommission.exp diff --git a/src/core/meshcop/tcat_agent.cpp b/src/core/meshcop/tcat_agent.cpp index 48dcba714..86e543966 100644 --- a/src/core/meshcop/tcat_agent.cpp +++ b/src/core/meshcop/tcat_agent.cpp @@ -410,7 +410,9 @@ Error TcatAgent::HandleSingleTlv(const Message &aIncommingMessage, Message &aOut response = true; error = kErrorNone; break; - + case kTlvDecommission: + error = HandleDecomission(); + break; default: error = kErrorInvalidCommand; } @@ -479,6 +481,27 @@ exit: return error; } +Error TcatAgent::HandleDecomission(void) +{ + Error error = kErrorNone; + + IgnoreReturnValue(otThreadSetEnabled(&GetInstance(), false)); + Get().Clear(); + Get().Clear(); + + error = Get().ErasePersistentInfo(); + +#if !OPENTHREAD_CONFIG_PLATFORM_KEY_REFERENCES_ENABLE + { + NetworkKey networkKey; + networkKey.Clear(); + Get().SetNetworkKey(networkKey); + } +#endif + + return error; +} + Error TcatAgent::HandleStartThreadInterface(void) { Error error; diff --git a/src/core/meshcop/tcat_agent.hpp b/src/core/meshcop/tcat_agent.hpp index 468c40ffe..a95b42cfd 100644 --- a/src/core/meshcop/tcat_agent.hpp +++ b/src/core/meshcop/tcat_agent.hpp @@ -352,6 +352,7 @@ private: Error HandleSingleTlv(const Message &aIncommingMessage, Message &aOutgoingMessage); Error HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength); + Error HandleDecomission(void); Error HandleStartThreadInterface(void); bool CheckCommandClassAuthorizationFlags(CommandClassFlags aCommissionerCommandClassFlags, diff --git a/tests/scripts/expect/cli-tcat-decommission.exp b/tests/scripts/expect/cli-tcat-decommission.exp new file mode 100755 index 000000000..c0488c031 --- /dev/null +++ b/tests/scripts/expect/cli-tcat-decommission.exp @@ -0,0 +1,64 @@ +#!/usr/bin/expect -f +# +# Copyright (c) 2024, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +source "tests/scripts/expect/_common.exp" + +spawn_node 1 "cli" + +switch_node 1 +send "tcat start\n" +expect_line "Done" + +spawn python "tools/tcat_ble_client/bbtc.py" --simulation 1 --cert_path "tools/tcat_ble_client/auth" +set py_client "$spawn_id" +expect_line "Done" +send "commission\n" +expect_line "\tTYPE:\tRESPONSE_W_STATUS" +expect_line "\tVALUE:\t0x00" + +send "thread start\n" +expect_line "\tTYPE:\tRESPONSE_W_STATUS" +expect_line "\tVALUE:\t0x00" + +send "decommission\n" +expect_line "\tTYPE:\tRESPONSE_W_STATUS" + +send "exit\n" +expect eof + +switch_node 1 +send "tcat stop\n" +expect_line "Done" + +send "dataset active\n" +expect_line "Error 23: NotFound" + +send "networkkey\n" +expect_line "00000000000000000000000000000000" +expect_line "Done" diff --git a/tools/tcat_ble_client/bbtc.py b/tools/tcat_ble_client/bbtc.py index d2c7ea687..2824e5aca 100755 --- a/tools/tcat_ble_client/bbtc.py +++ b/tools/tcat_ble_client/bbtc.py @@ -125,7 +125,8 @@ async def get_device_by_args(args): elif args.scan: tcat_devices = await ble_scanner.scan_tcat_devices() device = select_device_by_user_input(tcat_devices) - device = await BleStream.create(device.address, BBTC_SERVICE_UUID, BBTC_TX_CHAR_UUID, BBTC_RX_CHAR_UUID) + if device: + device = await BleStream.create(device.address, BBTC_SERVICE_UUID, BBTC_TX_CHAR_UUID, BBTC_RX_CHAR_UUID) elif args.simulation: device = UdpStream("127.0.0.1", int(args.simulation)) diff --git a/tools/tcat_ble_client/cli/base_commands.py b/tools/tcat_ble_client/cli/base_commands.py index a865b8711..20d48dcb3 100644 --- a/tools/tcat_ble_client/cli/base_commands.py +++ b/tools/tcat_ble_client/cli/base_commands.py @@ -87,6 +87,22 @@ class CommissionCommand(Command): return CommandResultTLV(tlv_response) +class DecommissionCommand(Command): + + def get_help_string(self) -> str: + return 'Stop Thread interface and decommission device from current network.' + + async def execute_default(self, args, context): + bless: BleStreamSecure = context['ble_sstream'] + print('Disabling Thread and decommissioning device...') + data = (TLV(TcatTLVType.DECOMMISSION.value, bytes()).to_bytes()) + response = await bless.send_with_resp(data) + if not response: + return + tlv_response = TLV.from_bytes(response) + return CommandResultTLV(tlv_response) + + class ThreadStartCommand(Command): def get_help_string(self) -> str: diff --git a/tools/tcat_ble_client/cli/cli.py b/tools/tcat_ble_client/cli/cli.py index bfe6cd3d1..838295805 100644 --- a/tools/tcat_ble_client/cli/cli.py +++ b/tools/tcat_ble_client/cli/cli.py @@ -29,7 +29,8 @@ import readline import shlex from ble.ble_stream_secure import BleStreamSecure -from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, ThreadStateCommand, ScanCommand) +from cli.base_commands import (HelpCommand, HelloCommand, CommissionCommand, DecommissionCommand, ThreadStateCommand, + ScanCommand) from cli.dataset_commands import (DatasetCommand) from dataset.dataset import ThreadDataset from typing import Optional @@ -42,6 +43,7 @@ class CLI: 'help': HelpCommand(), 'hello': HelloCommand(), 'commission': CommissionCommand(), + 'decommission': DecommissionCommand(), 'dataset': DatasetCommand(), 'thread': ThreadStateCommand(), 'scan': ScanCommand(),