/* * Copyright (C) 2022-2023 Huawei Device Co., Ltd. * 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. */ #include "ethernet_configuration.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "net_manager_constants.h" #include "netmanager_base_common_utils.h" #include "netmgr_ext_log_wrapper.h" #include "route.h" #include "securec.h" namespace OHOS { namespace NetManagerStandard { namespace { const std::string IFACE_MATCH = "eth\\d"; const std::string CONFIG_KEY_ETH_COMPONENT_FLAG = "config_ethernet_interfaces"; const std::string CONFIG_KEY_ETH_IFACE = "iface"; const std::string CONFIG_KEY_ETH_CAPS = "caps"; const std::string CONFIG_KEY_ETH_IP = "ip"; const std::string CONFIG_KEY_ETH_GATEWAY = "gateway"; const std::string CONFIG_KEY_ETH_DNS = "dns"; const std::string CONFIG_KEY_ETH_NETMASK = "netmask"; const std::string CONFIG_KEY_ETH_ROUTE = "route"; const std::string CONFIG_KEY_ETH_ROUTE_MASK = "routemask"; constexpr int32_t MKDIR_ERR = -1; constexpr int32_t USER_PATH_LEN = 25; constexpr const char *FILE_OBLIQUE_LINE = "/"; constexpr const char *KEY_DEVICE = "DEVICE="; constexpr const char *KEY_BOOTPROTO = "BOOTPROTO="; constexpr const char *KEY_STATIC = "STATIC"; constexpr const char *KEY_DHCP = "DHCP"; constexpr const char *KEY_IPADDR = "IPADDR="; constexpr const char *KEY_NETMASK = "NETMASK="; constexpr const char *KEY_GATEWAY = "GATEWAY="; constexpr const char *KEY_ROUTE = "ROUTE="; constexpr const char *KEY_ROUTE_NETMASK = "ROUTE_NETMASK="; constexpr const char *KEY_DNS = "DNS="; constexpr const char *KEY_PROXY_HOST = "PROXY_HOST="; constexpr const char *KEY_PROXY_PORT = "PROXY_PORT="; constexpr const char *KEY_PROXY_EXCLUSIONS = "PROXY_EXCLUSIONS="; constexpr const char *WRAP = "\n"; constexpr const char *DEFAULT_IPV4_ADDR = "0.0.0.0"; constexpr const char *DEFAULT_IPV6_ADDR = "::"; constexpr const char *DEFAULT_IPV6_MAX_ADDRESS = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; constexpr const char *EMPTY_NET_ADDR = "*"; constexpr const char *ADDR_SEPARATOR = ","; constexpr const char *EXCLUSIONS_DELIMITER = ","; } // namespace EthernetConfiguration::EthernetConfiguration() { CreateDir(USER_CONFIG_DIR); } bool EthernetConfiguration::ReadSystemConfiguration(std::map> &devCaps, std::map> &devCfgs) { const auto &jsonStr = ReadJsonFile(NETWORK_CONFIG_PATH); if (jsonStr.length() == 0) { NETMGR_EXT_LOG_E("ReadConfigData config file is return empty!"); return false; } const auto &jsonCfg = nlohmann::json::parse(jsonStr); if (jsonCfg.find(CONFIG_KEY_ETH_COMPONENT_FLAG) == jsonCfg.end()) { NETMGR_EXT_LOG_E("ReadConfigData not find network_ethernet_component!"); return false; } const auto &arrIface = jsonCfg.at(CONFIG_KEY_ETH_COMPONENT_FLAG); NETMGR_EXT_LOG_D("read ConfigData ethValue:%{public}s", arrIface.dump().c_str()); for (const auto &item : arrIface) { const auto &iface = item[CONFIG_KEY_ETH_IFACE].get(); const auto &caps = item.at(CONFIG_KEY_ETH_CAPS).get>(); if (!caps.empty()) { devCaps[iface] = caps; } const auto &fit = devCfgs.find(iface); if (fit != devCfgs.end()) { NETMGR_EXT_LOG_E("The iface=%{public}s device have set!", fit->first.c_str()); continue; } sptr config = ConvertJsonToConfiguration(item); if (config == nullptr) { NETMGR_EXT_LOG_E("config is nullptr"); return false; } std::regex re(IFACE_MATCH); if (!item[CONFIG_KEY_ETH_IP].empty() && std::regex_search(iface, re)) { devCfgs[iface] = config; } } return true; } sptr EthernetConfiguration::ConvertJsonToConfiguration(const nlohmann::json &jsonData) { sptr config = new (std::nothrow) InterfaceConfiguration(); if (config == nullptr) { NETMGR_EXT_LOG_E("config is nullptr"); return nullptr; } config->mode_ = STATIC; StaticConfiguration::ExtractNetAddrBySeparator(jsonData[CONFIG_KEY_ETH_IP], config->ipStatic_.ipAddrList_); StaticConfiguration::ExtractNetAddrBySeparator(jsonData[CONFIG_KEY_ETH_ROUTE], config->ipStatic_.routeList_); StaticConfiguration::ExtractNetAddrBySeparator(jsonData[CONFIG_KEY_ETH_GATEWAY], config->ipStatic_.gatewayList_); StaticConfiguration::ExtractNetAddrBySeparator(jsonData[CONFIG_KEY_ETH_NETMASK], config->ipStatic_.netMaskList_); StaticConfiguration::ExtractNetAddrBySeparator(jsonData[CONFIG_KEY_ETH_DNS], config->ipStatic_.dnsServers_); ParserIfaceIpAndRoute(config, jsonData[CONFIG_KEY_ETH_ROUTE_MASK]); return config; } bool EthernetConfiguration::ReadUserConfiguration(std::map> &devCfgs) { DIR *dir = nullptr; dirent *ptr = nullptr; if ((dir = opendir(USER_CONFIG_DIR)) == nullptr) { NETMGR_EXT_LOG_E("Read user configuration open dir error dir=[%{public}s]", USER_CONFIG_DIR); return false; } std::string iface; while ((ptr = readdir(dir)) != nullptr) { if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) { continue; } if (ptr->d_type == DT_REG) { std::string filePath = std::string(USER_CONFIG_DIR) + FILE_OBLIQUE_LINE + ptr->d_name; std::string fileContent; if (!ReadFile(filePath, fileContent)) { continue; } std::string().swap(iface); sptr cfg = new (std::nothrow) InterfaceConfiguration(); if (cfg == nullptr) { NETMGR_EXT_LOG_E("cfg new failed for devname[%{public}s]", iface.c_str()); continue; } ParserFileConfig(fileContent, iface, cfg); std::regex re(IFACE_MATCH); if (!iface.empty() && std::regex_search(iface, re)) { NETMGR_EXT_LOG_D("ReadFileList devname[%{public}s]", iface.c_str()); devCfgs[iface] = cfg; } } } closedir(dir); return true; } bool EthernetConfiguration::WriteUserConfiguration(const std::string &iface, sptr &cfg) { if (cfg == nullptr) { NETMGR_EXT_LOG_E("cfg is nullptr"); return false; } if (!CreateDir(USER_CONFIG_DIR)) { NETMGR_EXT_LOG_E("create dir failed"); return false; } if (cfg->mode_ == STATIC) { ParserIfaceIpAndRoute(cfg, std::string()); } std::string fileContent; GenCfgContent(iface, cfg, fileContent); std::string filePath = std::string(USER_CONFIG_DIR) + FILE_OBLIQUE_LINE + iface; return WriteFile(filePath, fileContent); } bool EthernetConfiguration::ClearAllUserConfiguration() { return DelDir(USER_CONFIG_DIR); } bool EthernetConfiguration::ConvertToConfiguration(const EthernetDhcpCallback::DhcpResult &dhcpResult, sptr &config) { if (config == nullptr) { NETMGR_EXT_LOG_E("Error ConvertToIpConfiguration config is null"); return false; } if (!IsValidDhcpResult(dhcpResult, config)) { return false; } INetAddr ipAddr; ipAddr.address_ = dhcpResult.ipAddr; ipAddr.family_ = static_cast(CommonUtils::GetAddrFamily(dhcpResult.ipAddr)); ipAddr.prefixlen_ = (ipAddr.family_ == AF_INET6) ? static_cast(CommonUtils::Ipv6PrefixLen(dhcpResult.subNet)) : static_cast(CommonUtils::Ipv4PrefixLen(dhcpResult.subNet)); config->ipAddrList_.push_back(ipAddr); INetAddr netMask; netMask.address_ = dhcpResult.subNet; config->netMaskList_.push_back(netMask); INetAddr gateway; gateway.address_ = dhcpResult.gateWay; gateway.family_ = static_cast(CommonUtils::GetAddrFamily(dhcpResult.gateWay)); config->gatewayList_.push_back(gateway); INetAddr route; if (dhcpResult.gateWay != dhcpResult.route1 && dhcpResult.route1 != EMPTY_NET_ADDR) { route.address_ = dhcpResult.route1; route.prefixlen_ = ipAddr.prefixlen_; } else if (dhcpResult.gateWay != dhcpResult.route2 && dhcpResult.route2 != EMPTY_NET_ADDR) { route.address_ = dhcpResult.route2; route.prefixlen_ = ipAddr.prefixlen_; } else { route.address_ = (ipAddr.family_ == AF_INET6) ? DEFAULT_IPV6_ADDR : DEFAULT_IPV4_ADDR; route.prefixlen_ = 0; } route.family_ = static_cast(CommonUtils::GetAddrFamily(route.address_)); config->routeList_.push_back(route); INetAddr dnsNet1; dnsNet1.address_ = dhcpResult.dns1; INetAddr dnsNet2; dnsNet2.address_ = dhcpResult.dns2; config->dnsServers_.push_back(dnsNet1); config->dnsServers_.push_back(dnsNet2); return true; } sptr EthernetConfiguration::MakeInterfaceConfiguration( const sptr &devCfg, const sptr &devLinkInfo) { if (devCfg == nullptr || devLinkInfo == nullptr) { NETMGR_EXT_LOG_E("param is nullptr"); return nullptr; } sptr cfg = new (std::nothrow) InterfaceConfiguration(); if (cfg == nullptr) { NETMGR_EXT_LOG_E("cfg new failed"); return nullptr; } cfg->mode_ = devCfg->mode_; for (const auto &ipAddr : devLinkInfo->netAddrList_) { cfg->ipStatic_.ipAddrList_.push_back(ipAddr); auto family = CommonUtils::GetAddrFamily(ipAddr.address_); INetAddr netMask; netMask.address_ = ipAddr.netMask_.empty() ? (((family == AF_INET6) ? CommonUtils::GetIpv6Prefix(DEFAULT_IPV6_MAX_ADDRESS, ipAddr.prefixlen_) : CommonUtils::GetMaskByLength(ipAddr.prefixlen_))) : ipAddr.netMask_; cfg->ipStatic_.netMaskList_.push_back(netMask); } for (const auto &route : devLinkInfo->routeList_) { cfg->ipStatic_.routeList_.push_back(route.destination_); cfg->ipStatic_.gatewayList_.push_back(route.gateway_); } cfg->ipStatic_.domain_ = devLinkInfo->domain_; for (const auto &addr : devLinkInfo->dnsList_) { cfg->ipStatic_.dnsServers_.push_back(addr); } return cfg; } std::string EthernetConfiguration::ReadJsonFile(const std::string &filePath) { std::ifstream infile; std::string strLine; std::string strAll; infile.open(filePath); if (!infile.is_open()) { NETMGR_EXT_LOG_E("ReadJsonFile filePath failed"); return strAll; } while (getline(infile, strLine)) { strAll.append(strLine); } infile.close(); return strAll; } bool EthernetConfiguration::IsDirExist(const std::string &dirPath) { struct stat status; if (dirPath.empty()) { return false; } return (stat(dirPath.c_str(), &status) == 0); } bool EthernetConfiguration::CreateDir(const std::string &dirPath) { if (IsDirExist(dirPath)) { return true; } if (mkdir(dirPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == MKDIR_ERR) { NETMGR_EXT_LOG_E("mkdir failed %{public}d: %{public}s", errno, strerror(errno)); return false; } return true; } bool EthernetConfiguration::DelDir(const std::string &dirPath) { DIR *dir = nullptr; dirent *entry = nullptr; struct stat statbuf; if ((dir = opendir(dirPath.c_str())) == nullptr) { NETMGR_EXT_LOG_E("EthernetConfiguration DelDir open user dir failed!"); return false; } while ((entry = readdir(dir)) != nullptr) { std::string filePath = dirPath + FILE_OBLIQUE_LINE + entry->d_name; lstat(filePath.c_str(), &statbuf); if (S_ISREG(statbuf.st_mode)) { remove(filePath.c_str()); } } closedir(dir); sync(); return rmdir(dirPath.c_str()) >= 0; } bool EthernetConfiguration::IsFileExist(const std::string &filePath, std::string &realPath) { char tmpPath[PATH_MAX] = {0}; if (!realpath(filePath.c_str(), tmpPath)) { NETMGR_EXT_LOG_E("file name is error"); return false; } if (strncmp(tmpPath, USER_CONFIG_DIR, USER_PATH_LEN) != 0) { NETMGR_EXT_LOG_E("file path is error"); return false; } realPath = tmpPath; return true; } bool EthernetConfiguration::ReadFile(const std::string &filePath, std::string &fileContent) { std::unique_lock lock(mutex_); if (filePath.empty()) { NETMGR_EXT_LOG_E("filePath empty."); return false; } std::string realPath; if (!IsFileExist(filePath, realPath)) { NETMGR_EXT_LOG_E("[%{public}s] not exist.", filePath.c_str()); return false; } std::fstream file(realPath.c_str(), std::fstream::in); if (!file.is_open()) { NETMGR_EXT_LOG_E("EthernetConfiguration read file failed.err %{public}d %{public}s", errno, strerror(errno)); return false; } std::stringstream buffer; buffer << file.rdbuf(); fileContent = buffer.str(); file.close(); return true; } bool EthernetConfiguration::WriteFile(const std::string &filePath, const std::string &fileContent) { std::fstream file(filePath.c_str(), std::fstream::out | std::fstream::trunc); if (!file.is_open()) { NETMGR_EXT_LOG_E("EthernetConfiguration write file=%{public}s fstream failed. err %{public}d %{public}s", filePath.c_str(), errno, strerror(errno)); return false; } file << fileContent.c_str(); file.close(); sync(); return true; } void EthernetConfiguration::ParserFileConfig(const std::string &fileContent, std::string &iface, sptr cfg) { ParseDevice(fileContent, iface); ParseBootProto(fileContent, cfg); ParseStaticConfig(fileContent, cfg); ParserFileHttpProxy(fileContent, cfg); } void EthernetConfiguration::ParseDevice(const std::string &fileContent, std::string &iface) { std::string::size_type pos = fileContent.find(KEY_DEVICE); if (pos == std::string::npos) { return; } pos += strlen(KEY_DEVICE); const auto &device = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); iface = device; } void EthernetConfiguration::ParseBootProto(const std::string &fileContent, sptr cfg) { std::string::size_type pos = fileContent.find(KEY_BOOTPROTO); if (pos == std::string::npos) { return; } pos += strlen(KEY_BOOTPROTO); const auto &bootProto = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); cfg->mode_ = (bootProto == KEY_STATIC) ? STATIC : DHCP; } void EthernetConfiguration::ParseStaticConfig(const std::string &fileContent, sptr cfg) { if (cfg->mode_ != STATIC) { return; } std::string ipAddresses, netMasks, gateways, routes, routeMasks, dnsServers; auto pos = fileContent.find(KEY_IPADDR); if (pos != std::string::npos) { pos += strlen(KEY_IPADDR); ipAddresses = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } pos = fileContent.find(KEY_NETMASK); if (pos != std::string::npos) { pos += strlen(KEY_NETMASK); netMasks = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } pos = fileContent.find(KEY_GATEWAY); if (pos != std::string::npos) { pos += strlen(KEY_GATEWAY); gateways = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } pos = fileContent.find(KEY_ROUTE); if (pos != std::string::npos) { pos += strlen(KEY_ROUTE); routes = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } pos = fileContent.find(KEY_ROUTE_NETMASK); if (pos != std::string::npos) { pos += strlen(KEY_ROUTE_NETMASK); routeMasks = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } pos = fileContent.find(KEY_DNS); if (pos != std::string::npos) { pos += strlen(KEY_DNS); dnsServers = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); } StaticConfiguration::ExtractNetAddrBySeparator(ipAddresses, cfg->ipStatic_.ipAddrList_); StaticConfiguration::ExtractNetAddrBySeparator(routes, cfg->ipStatic_.routeList_); StaticConfiguration::ExtractNetAddrBySeparator(gateways, cfg->ipStatic_.gatewayList_); StaticConfiguration::ExtractNetAddrBySeparator(netMasks, cfg->ipStatic_.netMaskList_); StaticConfiguration::ExtractNetAddrBySeparator(dnsServers, cfg->ipStatic_.dnsServers_); ParserIfaceIpAndRoute(cfg, routeMasks); } void EthernetConfiguration::ParserFileHttpProxy(const std::string &fileContent, const sptr &cfg) { std::string::size_type pos = fileContent.find(KEY_PROXY_HOST); if (pos != std::string::npos) { pos += strlen(KEY_PROXY_HOST); cfg->httpProxy_.SetHost(fileContent.substr(pos, fileContent.find(WRAP, pos) - pos)); } pos = fileContent.find(KEY_PROXY_PORT); if (pos != std::string::npos) { pos += strlen(KEY_PROXY_PORT); uint32_t port = CommonUtils::StrToUint(fileContent.substr(pos, fileContent.find(WRAP, pos) - pos)); cfg->httpProxy_.SetPort(static_cast(port)); } pos = fileContent.find(KEY_PROXY_EXCLUSIONS); if (pos != std::string::npos) { pos += strlen(KEY_PROXY_EXCLUSIONS); auto exclusions = fileContent.substr(pos, fileContent.find(WRAP, pos) - pos); std::list exclusionList; for (const auto &exclusion : CommonUtils::Split(exclusions, EXCLUSIONS_DELIMITER)) { exclusionList.push_back(exclusion); } cfg->httpProxy_.SetExclusionList(exclusionList); } } void EthernetConfiguration::ParserIfaceIpAndRoute(sptr &cfg, const std::string &rootNetMask) { if (cfg == nullptr) { NETMGR_EXT_LOG_E("cfg is nullptr"); return; } std::for_each(cfg->ipStatic_.netMaskList_.begin(), cfg->ipStatic_.netMaskList_.end(), [&cfg](const auto &netMask) { auto maskFamily = CommonUtils::GetAddrFamily(netMask.address_); for (auto &ipAddr : cfg->ipStatic_.ipAddrList_) { if (maskFamily != CommonUtils::GetAddrFamily(ipAddr.address_)) { continue; } ipAddr.netMask_ = netMask.address_; ipAddr.prefixlen_ = (maskFamily == AF_INET6) ? CommonUtils::Ipv6PrefixLen(netMask.address_) : CommonUtils::Ipv4PrefixLen(netMask.address_); break; } }); for (const auto &routeMask : CommonUtils::Split(rootNetMask, ADDR_SEPARATOR)) { auto maskFamily = CommonUtils::GetAddrFamily(routeMask); for (auto &route : cfg->ipStatic_.routeList_) { if (maskFamily != CommonUtils::GetAddrFamily(route.address_)) { continue; } route.prefixlen_ = (maskFamily == AF_INET6) ? CommonUtils::Ipv6PrefixLen(routeMask) : CommonUtils::Ipv4PrefixLen(routeMask); break; } } } void EthernetConfiguration::GenCfgContent(const std::string &iface, sptr cfg, std::string &fileContent) { if (cfg == nullptr) { NETMGR_EXT_LOG_E("cfg is nullptr"); return; } std::string().swap(fileContent); fileContent = fileContent + KEY_DEVICE + iface + WRAP; std::string mode = (cfg->mode_ == STATIC) ? KEY_STATIC : KEY_DHCP; fileContent = fileContent + KEY_BOOTPROTO + mode + WRAP; if (cfg->mode_ == STATIC) { std::string ipAddresses = AccumulateNetAddress(cfg->ipStatic_.ipAddrList_); std::string netMasks = AccumulateNetAddress(cfg->ipStatic_.netMaskList_); std::string gateways = AccumulateNetAddress(cfg->ipStatic_.gatewayList_); std::string routes = AccumulateNetAddress(cfg->ipStatic_.routeList_); std::string routeMasks = std::accumulate(cfg->ipStatic_.routeList_.begin(), cfg->ipStatic_.routeList_.end(), std::string(), [](const std::string &routeMask, const INetAddr &iter) { auto family = CommonUtils::GetAddrFamily(iter.address_); std::string mask = (family == AF_INET6) ? DEFAULT_IPV6_ADDR : DEFAULT_IPV4_ADDR; return routeMask.empty() ? routeMask + mask : (routeMask + ADDR_SEPARATOR + mask); }); std::string dnsServers = AccumulateNetAddress(cfg->ipStatic_.dnsServers_); fileContent = fileContent + KEY_IPADDR + ipAddresses + WRAP; fileContent = fileContent + KEY_NETMASK + netMasks + WRAP; fileContent = fileContent + KEY_GATEWAY + gateways + WRAP; fileContent = fileContent + KEY_ROUTE + routes + WRAP; fileContent = fileContent + KEY_ROUTE_NETMASK + routeMasks + WRAP; fileContent = fileContent + KEY_DNS + dnsServers + WRAP; } GenHttpProxyContent(cfg, fileContent); } void EthernetConfiguration::GenHttpProxyContent(const sptr &cfg, std::string &fileContent) { const auto &exclusionList = cfg->httpProxy_.GetExclusionList(); std::string exclusions = std::accumulate(exclusionList.begin(), exclusionList.end(), std::string(), [](const std::string &exclusion, const std::string &next) { return exclusion.empty() ? exclusion + next : (exclusion + EXCLUSIONS_DELIMITER + next); }); fileContent = fileContent + KEY_PROXY_HOST + cfg->httpProxy_.GetHost() + WRAP; fileContent = fileContent + KEY_PROXY_PORT + std::to_string(cfg->httpProxy_.GetPort()) + WRAP; fileContent = fileContent + KEY_PROXY_EXCLUSIONS + exclusions + WRAP; } std::string EthernetConfiguration::AccumulateNetAddress(const std::vector &netAddrList) { return std::accumulate(netAddrList.begin(), netAddrList.end(), std::string(), [](const std::string &addr, const INetAddr &iter) { return addr.empty() ? (addr + iter.address_) : (addr + ADDR_SEPARATOR + iter.address_); }); } bool EthernetConfiguration::IsValidDhcpResult(const EthernetDhcpCallback::DhcpResult &dhcpResult, sptr &config) { if (config == nullptr) { NETMGR_EXT_LOG_E("config is nullptr"); return false; } if (dhcpResult.ipAddr.empty()) { NETMGR_EXT_LOG_E("DhcpResult ip addr is empty"); return false; } bool isSameIp = false; bool isSameGateway = false; for (const auto &ipAddr : config->ipAddrList_) { if (dhcpResult.ipAddr == ipAddr.address_) { NETMGR_EXT_LOG_E("Same ip addr:%{public}s", CommonUtils::ToAnonymousIp(dhcpResult.ipAddr).c_str()); isSameIp = true; break; } } for (const auto &gateway : config->gatewayList_) { if (dhcpResult.gateWay == gateway.address_) { NETMGR_EXT_LOG_E("Same gateway:%{public}s", CommonUtils::ToAnonymousIp(dhcpResult.gateWay).c_str()); isSameGateway = true; break; } } return !(isSameIp && isSameGateway); } } // namespace NetManagerStandard } // namespace OHOS