/* * * Copyright (c) 2020 Project CHIP Authors * Copyright (c) 2013-2017 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. */ /** * @file * Common command-line option handling code for test applications. * */ #include "TestInetCommonOptions.h" #include #include #include #include #include #include #include #include #include #include using namespace chip; using namespace chip::ArgParser; using namespace chip::Inet; // Global Variables NetworkOptions gNetworkOptions; FaultInjectionOptions gFaultInjectionOptions; NetworkOptions::NetworkOptions() { static OptionDef optionDefs[] = { { "local-addr", kArgumentRequired, 'a' }, { "node-addr", kArgumentRequired, kToolCommonOpt_NodeAddr }, /* alias for local-addr */ #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT { "tap-device", kArgumentRequired, kToolCommonOpt_TapDevice }, { "ipv4-gateway", kArgumentRequired, kToolCommonOpt_IPv4GatewayAddr }, { "ipv6-gateway", kArgumentRequired, kToolCommonOpt_IPv6GatewayAddr }, { "dns-server", kArgumentRequired, 'X' }, { "debug-lwip", kNoArgument, kToolCommonOpt_DebugLwIP }, { "event-delay", kArgumentRequired, kToolCommonOpt_EventDelay }, { "tap-system-config", kNoArgument, kToolCommonOpt_TapInterfaceConfig }, #endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT {} }; OptionDefs = optionDefs; HelpGroupName = "NETWORK OPTIONS"; OptionHelp = " -a, --local-addr, --node-addr \n" " Local address for the node.\n" "\n" #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT " --tap-device \n" " TAP device name for LwIP hosted OS usage. Defaults to chip-dev-.\n" "\n" " --ipv4-gateway \n" " Address of default IPv4 gateway.\n" "\n" " --ipv6-gateway \n" " Address of default IPv6 gateway.\n" "\n" " -X, --dns-server \n" " IPv4 address of local DNS server.\n" "\n" " --debug-lwip\n" " Enable LwIP debug messages.\n" "\n" " --event-delay \n" " Delay event processing by specified number of iterations. Defaults to 0.\n" "\n" " --tap-system-config\n" " Use configuration on each of the Linux TAP interfaces to configure LwIP's interfaces.\n" "\n" #endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT ; // Defaults. LocalIPv4Addr.clear(); LocalIPv6Addr.clear(); #if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT TapDeviceName.clear(); LwIPDebugFlags = 0; EventDelay = 0; IPv4GatewayAddr.clear(); IPv6GatewayAddr.clear(); DNSServerAddr = Inet::IPAddress::Any; TapUseSystemConfig = false; #endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_USE_OPEN_THREAD_ENDPOINT } bool NetworkOptions::HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg) { Inet::IPAddress localAddr; switch (id) { case 'a': case kToolCommonOpt_NodeAddr: if (!ParseIPAddress(arg, localAddr)) { PrintArgError("%s: Invalid value specified for local IP address: %s\n", progName, arg); return false; } #if INET_CONFIG_ENABLE_IPV4 if (localAddr.IsIPv4()) { LocalIPv4Addr.push_back(localAddr); } else { LocalIPv6Addr.push_back(localAddr); } #else // INET_CONFIG_ENABLE_IPV4 LocalIPv6Addr.push_back(localAddr); #endif // INET_CONFIG_ENABLE_IPV4 break; #if CHIP_SYSTEM_CONFIG_USE_LWIP case 'X': if (!ParseIPAddress(arg, DNSServerAddr)) { PrintArgError("%s: Invalid value specified for DNS server address: %s\n", progName, arg); return false; } break; case kToolCommonOpt_TapDevice: TapDeviceName.push_back(arg); break; case kToolCommonOpt_IPv4GatewayAddr: { if (!ParseIPAddress(arg, localAddr) || !localAddr.IsIPv4()) { PrintArgError("%s: Invalid value specified for IPv4 gateway address: %s\n", progName, arg); return false; } IPv4GatewayAddr.push_back(localAddr); } break; case kToolCommonOpt_IPv6GatewayAddr: { if (!ParseIPAddress(arg, localAddr)) { PrintArgError("%s: Invalid value specified for IPv6 gateway address: %s\n", progName, arg); return false; } IPv6GatewayAddr.push_back(localAddr); } break; case kToolCommonOpt_DebugLwIP: #if defined(LWIP_DEBUG) #if CHIP_TARGET_STYLE_UNIX gLwIP_DebugFlags = (LWIP_DBG_ON | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_FRESH | LWIP_DBG_HALT); #endif #endif break; case kToolCommonOpt_EventDelay: if (!ParseInt(arg, EventDelay)) { PrintArgError("%s: Invalid value specified for event delay: %s\n", progName, arg); return false; } break; case kToolCommonOpt_TapInterfaceConfig: TapUseSystemConfig = true; break; #endif // CHIP_SYSTEM_CONFIG_USE_LWIP default: PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name); return false; } return true; } FaultInjectionOptions::FaultInjectionOptions() { static OptionDef optionDefs[] = { { "faults", kArgumentRequired, kToolCommonOpt_FaultInjection }, { "iterations", kArgumentRequired, kToolCommonOpt_FaultTestIterations }, { "debug-resource-usage", kNoArgument, kToolCommonOpt_DebugResourceUsage }, { "print-fault-counters", kNoArgument, kToolCommonOpt_PrintFaultCounters }, { "extra-cleanup-time", kArgumentRequired, kToolCommonOpt_ExtraCleanupTime }, {} }; OptionDefs = optionDefs; HelpGroupName = "FAULT INJECTION OPTIONS"; OptionHelp = " --faults \n" " Inject specified fault(s) into the operation of the tool at runtime.\n" "\n" " --iterations \n" " Execute the program operation the given number of times\n" "\n" " --debug-resource-usage\n" " Print all stats counters before exiting.\n" "\n" " --print-fault-counters\n" " Print the fault-injection counters before exiting.\n" "\n" " --extra-cleanup-time\n" " Allow extra time before asserting resource leaks; this is useful when\n" " running fault-injection tests to let the system free stale ExchangeContext\n" " instances after RMP has exhausted all retransmission; a failed RMP transmission\n" " should fail a normal happy-sequence test, but not necessarily a fault-injection test.\n" " The value is in milliseconds; a common value is 10000.\n" "\n" ""; // Defaults TestIterations = 1; DebugResourceUsage = false; PrintFaultCounters = false; ExtraCleanupTimeMsec = 0; } #if defined(CHIP_WITH_NLFAULTINJECTION) && CHIP_WITH_NLFAULTINJECTION bool FaultInjectionOptions::HandleOption(const char * progName, OptionSet * optSet, int id, const char * name, const char * arg) { using namespace nl::FaultInjection; GetManagerFn faultMgrFnTable[] = { Inet::FaultInjection::GetManager, System::FaultInjection::GetManager }; size_t faultMgrFnTableLen = sizeof(faultMgrFnTable) / sizeof(faultMgrFnTable[0]); switch (id) { case kToolCommonOpt_FaultInjection: { chip::Platform::ScopedMemoryString mutableArg(arg, strlen(arg)); assert(mutableArg); bool parseRes = ParseFaultInjectionStr(mutableArg.Get(), faultMgrFnTable, faultMgrFnTableLen); if (!parseRes) { PrintArgError("%s: Invalid string specified for fault injection option: %s\n", progName, arg); return false; } break; } case kToolCommonOpt_FaultTestIterations: if ((!ParseInt(arg, TestIterations)) || (TestIterations == 0)) { PrintArgError("%s: Invalid value specified for the number of iterations to execute: %s\n", progName, arg); return false; } break; case kToolCommonOpt_DebugResourceUsage: DebugResourceUsage = true; break; case kToolCommonOpt_PrintFaultCounters: PrintFaultCounters = true; break; case kToolCommonOpt_ExtraCleanupTime: if ((!ParseInt(arg, ExtraCleanupTimeMsec)) || (ExtraCleanupTimeMsec == 0)) { PrintArgError("%s: Invalid value specified for the extra time to wait before checking for leaks: %s\n", progName, arg); return false; } break; default: PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name); return false; } return true; } #endif // defined(CHIP_WITH_NLFAULTINJECTION) && CHIP_WITH_NLFAULTINJECTION