From e810357adb1f31e7e8fb55042317c451e87535a6 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Wed, 5 Aug 2020 14:41:10 -0700 Subject: [PATCH] [cli] support reading individual operational dataset values (#5344) --- src/cli/README_DATASET.md | 121 +++++++++- src/cli/cli_dataset.cpp | 328 ++++++++++++++++++++------- tests/scripts/expect/cli-dataset.exp | 44 +++- 3 files changed, 390 insertions(+), 103 deletions(-) diff --git a/src/cli/README_DATASET.md b/src/cli/README_DATASET.md index 3b25167b7..aea620c35 100644 --- a/src/cli/README_DATASET.md +++ b/src/cli/README_DATASET.md @@ -194,7 +194,15 @@ Done ### activetimestamp -Usage: `dataset activetimestamp ` +Usage: `dataset activetimestamp [timestamp]` + +Get active timestamp. + +```bash +> dataset activetimestamp +123456789 +Done +``` Set active timestamp. @@ -205,7 +213,15 @@ Done ### channel -Usage: `channel ` +Usage: `channel [channel]` + +Get channel. + +```bash +> dataset channel +12 +Done +``` Set channel. @@ -216,7 +232,15 @@ Done ### channelmask -Usage: `dataset channelmask ` +Usage: `dataset channelmask [channelmask]` + +Get channel mask. + +```bash +> dataset channelmask +0x07fff800 +Done +``` Set channel mask. @@ -249,7 +273,15 @@ Done ### delay -Usage: `dataset delay ` +Usage: `dataset delay [delay]` + +Get delay timer value. + +```bash +> dataset delay +1000 +Done +``` Set delay timer value. @@ -260,7 +292,15 @@ Done ### extpanid -Usage: `dataset extpanid ` +Usage: `dataset extpanid [extpanid]` + +Get extended panid. + +```bash +> dataset extpanid +000db80123456789 +Done +``` Set extended panid. @@ -284,7 +324,15 @@ Done ### masterkey -Usage: `dataset masterkey ` +Usage: `dataset masterkey [key]` + +Get master key + +```bash +> dataset masterkey +00112233445566778899aabbccddeeff +Done +``` Set master key. @@ -295,7 +343,14 @@ Done ### meshlocalprefix -Usage: `dataset meshlocalprefix ` +Usage: `dataset meshlocalprefix [prefix]` + +Get mesh local prefix. + +```bash +> dataset meshlocalprefix fd00:db8:0:0::/64 +Done +``` Set mesh local prefix. @@ -328,7 +383,15 @@ Done ### networkname -Usage: `dataset networkname ` +Usage: `dataset networkname [name]` + +Get network name. + +```bash +> datset networkname +OpenThread +Done +``` Set network name. @@ -341,7 +404,15 @@ Done ### panid -Usage: `dataset panid ` +Usage: `dataset panid [panid]` + +Get panid. + +```bash +> dataset panid +0x1234 +Done +``` Set panid. @@ -383,7 +454,15 @@ Done ### pendingtimestamp -Usage: `dataset pendingtimestamp ` +Usage: `dataset pendingtimestamp [timestamp]` + +Get pending timestamp. + +```bash +> dataset pendingtimestamp +123456789 +Done +``` Set pending timestamp. @@ -394,7 +473,17 @@ Done ### pskc -Usage: `pskc [-p] |` +Usage: `pskc [-p] [|]` + +Get pskc. + +```bash +> dataset pskc +67c0c203aa0b042bfb5381c47aef4d9e +Done +``` + +Set pskc. With `-p`(**only for FTD**) generate pskc from \ (UTF-8 encoded) together with network name and extended PAN ID in the dataset buffer if set or values in the current stack if not, otherwise set pskc as \ (hex format). @@ -407,7 +496,15 @@ Done ### securitypolicy -Usage: `dataset securitypolicy [onrcb]` +Usage: `dataset securitypolicy [ [onrcb]]` + +Get security policy. + +```bash +> dataset securitypolicy +672 onrcb +Done +``` Set security policy. diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 05ca042be..8633dce78 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -310,12 +310,22 @@ exit: otError Dataset::ProcessActiveTimestamp(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mActiveTimestamp = static_cast(value); - sDataset.mComponents.mIsActiveTimestampPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsActiveTimestampPresent) + { + mInterpreter.mServer->OutputFormat("%lu\r\n", sDataset.mActiveTimestamp); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mActiveTimestamp = static_cast(value); + sDataset.mComponents.mIsActiveTimestampPresent = true; + } exit: return error; @@ -324,12 +334,22 @@ exit: otError Dataset::ProcessChannel(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mChannel = static_cast(value); - sDataset.mComponents.mIsChannelPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsChannelPresent) + { + mInterpreter.mServer->OutputFormat("%d\r\n", sDataset.mChannel); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mChannel = static_cast(value); + sDataset.mComponents.mIsChannelPresent = true; + } exit: return error; @@ -338,12 +358,22 @@ exit: otError Dataset::ProcessChannelMask(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mChannelMask = static_cast(value); - sDataset.mComponents.mIsChannelMaskPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsChannelMaskPresent) + { + mInterpreter.mServer->OutputFormat("0x%08x\r\n", sDataset.mChannelMask); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mChannelMask = static_cast(value); + sDataset.mComponents.mIsChannelMaskPresent = true; + } exit: return error; @@ -384,12 +414,22 @@ exit: otError Dataset::ProcessDelay(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mDelay = static_cast(value); - sDataset.mComponents.mIsDelayPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsDelayPresent) + { + mInterpreter.mServer->OutputFormat("%d\r\n", sDataset.mDelay); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mDelay = static_cast(value); + sDataset.mComponents.mIsDelayPresent = true; + } exit: return error; @@ -398,14 +438,25 @@ exit: otError Dataset::ProcessExtPanId(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - uint8_t extPanId[OT_EXT_PAN_ID_SIZE]; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], extPanId, sizeof(extPanId)) == sizeof(extPanId), - error = OT_ERROR_INVALID_ARGS); + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsExtendedPanIdPresent) + { + OutputBytes(sDataset.mExtendedPanId.m8, sizeof(sDataset.mExtendedPanId)); + mInterpreter.mServer->OutputFormat("\r\n"); + } + } + else + { + uint8_t extPanId[OT_EXT_PAN_ID_SIZE]; - memcpy(sDataset.mExtendedPanId.m8, extPanId, sizeof(sDataset.mExtendedPanId)); - sDataset.mComponents.mIsExtendedPanIdPresent = true; + VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], extPanId, sizeof(extPanId)) == sizeof(extPanId), + error = OT_ERROR_INVALID_ARGS); + + memcpy(sDataset.mExtendedPanId.m8, extPanId, sizeof(sDataset.mExtendedPanId)); + sDataset.mComponents.mIsExtendedPanIdPresent = true; + } exit: return error; @@ -414,14 +465,25 @@ exit: otError Dataset::ProcessMasterKey(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - uint8_t key[OT_MASTER_KEY_SIZE]; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit((Interpreter::Hex2Bin(aArgs[0], key, sizeof(key))) == OT_MASTER_KEY_SIZE, - error = OT_ERROR_INVALID_ARGS); + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsMasterKeyPresent) + { + OutputBytes(sDataset.mMasterKey.m8, sizeof(sDataset.mMasterKey)); + mInterpreter.mServer->OutputFormat("\r\n"); + } + } + else + { + uint8_t key[OT_MASTER_KEY_SIZE]; - memcpy(sDataset.mMasterKey.m8, key, sizeof(sDataset.mMasterKey)); - sDataset.mComponents.mIsMasterKeyPresent = true; + VerifyOrExit((Interpreter::Hex2Bin(aArgs[0], key, sizeof(key))) == OT_MASTER_KEY_SIZE, + error = OT_ERROR_INVALID_ARGS); + + memcpy(sDataset.mMasterKey.m8, key, sizeof(sDataset.mMasterKey)); + sDataset.mComponents.mIsMasterKeyPresent = true; + } exit: return error; @@ -429,14 +491,29 @@ exit: otError Dataset::ProcessMeshLocalPrefix(uint8_t aArgsLength, char *aArgs[]) { - otError error = OT_ERROR_NONE; - otIp6Address prefix; + otError error = OT_ERROR_NONE; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &prefix)); + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsMeshLocalPrefixPresent) + { + const uint8_t *prefix = sDataset.mMeshLocalPrefix.m8; + mInterpreter.mServer->OutputFormat("Mesh Local Prefix: %x:%x:%x:%x::/64\r\n", + (static_cast(prefix[0]) << 8) | prefix[1], + (static_cast(prefix[2]) << 8) | prefix[3], + (static_cast(prefix[4]) << 8) | prefix[5], + (static_cast(prefix[6]) << 8) | prefix[7]); + } + } + else + { + otIp6Address prefix; - memcpy(sDataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(sDataset.mMeshLocalPrefix.m8)); - sDataset.mComponents.mIsMeshLocalPrefixPresent = true; + SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &prefix)); + + memcpy(sDataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(sDataset.mMeshLocalPrefix.m8)); + sDataset.mComponents.mIsMeshLocalPrefixPresent = true; + } exit: return error; @@ -445,14 +522,25 @@ exit: otError Dataset::ProcessNetworkName(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - size_t length; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - VerifyOrExit((length = strlen(aArgs[0])) <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsNetworkNamePresent) + { + mInterpreter.mServer->OutputFormat("%.*s\r\n", static_cast(sizeof(sDataset.mNetworkName)), + sDataset.mNetworkName.m8); + } + } + else + { + size_t length; - memset(&sDataset.mNetworkName, 0, sizeof(sDataset.mNetworkName)); - memcpy(sDataset.mNetworkName.m8, aArgs[0], length); - sDataset.mComponents.mIsNetworkNamePresent = true; + VerifyOrExit((length = strlen(aArgs[0])) <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS); + + memset(&sDataset.mNetworkName, 0, sizeof(sDataset.mNetworkName)); + memcpy(sDataset.mNetworkName.m8, aArgs[0], length); + sDataset.mComponents.mIsNetworkNamePresent = true; + } exit: return error; @@ -461,12 +549,22 @@ exit: otError Dataset::ProcessPanId(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mPanId = static_cast(value); - sDataset.mComponents.mIsPanIdPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsPanIdPresent) + { + mInterpreter.mServer->OutputFormat("0x%04x\r\n", sDataset.mPanId); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mPanId = static_cast(value); + sDataset.mComponents.mIsPanIdPresent = true; + } exit: return error; @@ -475,12 +573,22 @@ exit: otError Dataset::ProcessPendingTimestamp(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mPendingTimestamp = static_cast(value); - sDataset.mComponents.mIsPendingTimestampPresent = true; + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsPendingTimestampPresent) + { + mInterpreter.mServer->OutputFormat("%lu\r\n", sDataset.mPendingTimestamp); + } + } + else + { + long value; + + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mPendingTimestamp = static_cast(value); + sDataset.mComponents.mIsPendingTimestampPresent = true; + } exit: return error; @@ -711,7 +819,15 @@ otError Dataset::ProcessPskc(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - if (aArgsLength == 1) + if (aArgsLength == 0) + { + if (sDataset.mComponents.mIsPskcPresent) + { + OutputBytes(sDataset.mPskc.m8, sizeof(sDataset.mPskc.m8)); + mInterpreter.mServer->OutputFormat("\r\n"); + } + } + else if (aArgsLength == 1) { VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], sDataset.mPskc.m8, sizeof(sDataset.mPskc)) == sizeof(sDataset.mPskc), @@ -745,47 +861,83 @@ exit: otError Dataset::ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[]) { otError error = OT_ERROR_NONE; - long value; - VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS); - - SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); - sDataset.mSecurityPolicy.mRotationTime = static_cast(value); - sDataset.mSecurityPolicy.mFlags = 0; - - if (aArgsLength > 1) + if (aArgsLength == 0) { - for (char *arg = aArgs[1]; *arg != '\0'; arg++) + if (sDataset.mComponents.mIsSecurityPolicyPresent) { - switch (*arg) + mInterpreter.mServer->OutputFormat("%d ", sDataset.mSecurityPolicy.mRotationTime); + + if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_OBTAIN_MASTER_KEY) { - case 'o': - sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_OBTAIN_MASTER_KEY; - break; - - case 'n': - sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_NATIVE_COMMISSIONING; - break; - - case 'r': - sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_ROUTERS; - break; - - case 'c': - sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER; - break; - - case 'b': - sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_BEACONS; - break; - - default: - ExitNow(error = OT_ERROR_INVALID_ARGS); + mInterpreter.mServer->OutputFormat("o"); } + + if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_NATIVE_COMMISSIONING) + { + mInterpreter.mServer->OutputFormat("n"); + } + + if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_ROUTERS) + { + mInterpreter.mServer->OutputFormat("r"); + } + + if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER) + { + mInterpreter.mServer->OutputFormat("c"); + } + + if (sDataset.mSecurityPolicy.mFlags & OT_SECURITY_POLICY_BEACONS) + { + mInterpreter.mServer->OutputFormat("b"); + } + + mInterpreter.mServer->OutputFormat("\r\n"); } } + else + { + long value; - sDataset.mComponents.mIsSecurityPolicyPresent = true; + SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value)); + sDataset.mSecurityPolicy.mRotationTime = static_cast(value); + sDataset.mSecurityPolicy.mFlags = 0; + + if (aArgsLength > 1) + { + for (char *arg = aArgs[1]; *arg != '\0'; arg++) + { + switch (*arg) + { + case 'o': + sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_OBTAIN_MASTER_KEY; + break; + + case 'n': + sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_NATIVE_COMMISSIONING; + break; + + case 'r': + sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_ROUTERS; + break; + + case 'c': + sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_EXTERNAL_COMMISSIONER; + break; + + case 'b': + sDataset.mSecurityPolicy.mFlags |= OT_SECURITY_POLICY_BEACONS; + break; + + default: + ExitNow(error = OT_ERROR_INVALID_ARGS); + } + } + } + + sDataset.mComponents.mIsSecurityPolicyPresent = true; + } exit: return error; diff --git a/tests/scripts/expect/cli-dataset.exp b/tests/scripts/expect/cli-dataset.exp index 63addc72c..1aa3926d8 100755 --- a/tests/scripts/expect/cli-dataset.exp +++ b/tests/scripts/expect/cli-dataset.exp @@ -51,32 +51,72 @@ send "dataset init active\n" expect "Done" send "dataset activetimestamp 100\n" expect "Done" +send "dataset activetimestamp\n" +expect "100" +expect "Done" if {$channel == 11} { send "dataset channel 18\n" + expect "Done" + send "dataset channel\n" + expect "18" + expect "Done" } else { send "dataset channel 11\n" + expect "Done" + send "dataset channel\n" + expect "11" + expect "Done" } -expect "Done" send "dataset channelmask 0x03fff800\n" expect "Done" +send "dataset channelmask\n" +expect "0x03fff800" +expect "Done" send "dataset extpanid aabbccddeeff0011\n" expect "Done" +send "dataset extpanid\n" +expect "aabbccddeeff0011" +expect "Done" send "dataset masterkey aabbccddeeff00112233445566778899\n" expect "Done" +send "dataset masterkey\n" +expect "aabbccddeeff00112233445566778899" +expect "Done" send "dataset meshlocalprefix fdde:4860::\n" expect "Done" +send "dataset meshlocalprefix\n" +expect "fdde:4860:0:0::/64" +expect "Done" send "dataset networkname OT-network\n" expect "Done" +send "dataset networkname\n" +expect "OT-network" +expect "Done" send "dataset panid 0xface\n" expect "Done" +send "dataset panid\n" +expect "0xface" +expect "Done" send "dataset pskc 00112233445566778899aabbccddeeff\n" expect "Done" +send "dataset pskc\n" +expect "00112233445566778899aabbccddeeff" +expect "Done" send "dataset securitypolicy 678 onrcb\n" expect "Done" +send "dataset securitypolicy\n" +expect "678 onrcb" +expect "Done" send "dataset pendingtimestamp 100\n" expect "Done" +send "dataset pendingtimestamp\n" +expect "100" +expect "Done" send "dataset delay 30000\n" expect "Done" +send "dataset delay\n" +expect "30000" +expect "Done" send "dataset commit pending\n" expect "Done" send "dataset pending\n" @@ -198,8 +238,6 @@ send "dataset mgmtgetcommand active something_invalid\n" expect "Error 7: InvalidArgs" send "dataset pskc -p 123456\n" expect "Done" -send "dataset pskc\n" -expect "Error 7: InvalidArgs" send "dataset securitypolicy 678 something_invalid\n" expect "Error 7: InvalidArgs" send "dataset set something_invalid 00\n"