1b1b8bc3fSopenharmony_ci/* 2b1b8bc3fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3b1b8bc3fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1b8bc3fSopenharmony_ci * you may not use this file except in compliance with the License. 5b1b8bc3fSopenharmony_ci * You may obtain a copy of the License at 6b1b8bc3fSopenharmony_ci * 7b1b8bc3fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1b8bc3fSopenharmony_ci * 9b1b8bc3fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1b8bc3fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1b8bc3fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1b8bc3fSopenharmony_ci * See the License for the specific language governing permissions and 13b1b8bc3fSopenharmony_ci * limitations under the License. 14b1b8bc3fSopenharmony_ci */ 15b1b8bc3fSopenharmony_ci#include "nat464_service.h" 16b1b8bc3fSopenharmony_ci 17b1b8bc3fSopenharmony_ci#include <algorithm> 18b1b8bc3fSopenharmony_ci#include <arpa/inet.h> 19b1b8bc3fSopenharmony_ci#include <netinet/in.h> 20b1b8bc3fSopenharmony_ci#include <string> 21b1b8bc3fSopenharmony_ci 22b1b8bc3fSopenharmony_ci#include "ffrt.h" 23b1b8bc3fSopenharmony_ci#include "inet_addr.h" 24b1b8bc3fSopenharmony_ci#include "net_all_capabilities.h" 25b1b8bc3fSopenharmony_ci#include "net_interface_config.h" 26b1b8bc3fSopenharmony_ci#include "net_manager_constants.h" 27b1b8bc3fSopenharmony_ci#include "net_mgr_log_wrapper.h" 28b1b8bc3fSopenharmony_ci#include "netsys_controller.h" 29b1b8bc3fSopenharmony_ci 30b1b8bc3fSopenharmony_cinamespace OHOS { 31b1b8bc3fSopenharmony_cinamespace NetManagerStandard { 32b1b8bc3fSopenharmony_ciNat464Service::Nat464Service(int32_t netId, const std::string &v6Iface) 33b1b8bc3fSopenharmony_ci{ 34b1b8bc3fSopenharmony_ci netId_ = netId; 35b1b8bc3fSopenharmony_ci v6Iface_ = v6Iface; 36b1b8bc3fSopenharmony_ci v4TunIface_ = std::string(CLAT_PREFIX) + v6Iface; 37b1b8bc3fSopenharmony_ci tryStopDiscovery_ = false; 38b1b8bc3fSopenharmony_ci discoveryCycleMs_ = INITIAL_DISCOVERY_CYCLE_MS; 39b1b8bc3fSopenharmony_ci discoveryIter_ = 1; 40b1b8bc3fSopenharmony_ci serviceState_ = NAT464_SERVICE_STATE_IDLE; 41b1b8bc3fSopenharmony_ci} 42b1b8bc3fSopenharmony_ci 43b1b8bc3fSopenharmony_civoid Nat464Service::MaybeUpdateV6Iface(const std::string &v6Iface) 44b1b8bc3fSopenharmony_ci{ 45b1b8bc3fSopenharmony_ci if (serviceState_ == NAT464_SERVICE_STATE_IDLE) { 46b1b8bc3fSopenharmony_ci v6Iface_ = v6Iface; 47b1b8bc3fSopenharmony_ci v4TunIface_ = std::string(CLAT_PREFIX) + v6Iface; 48b1b8bc3fSopenharmony_ci } 49b1b8bc3fSopenharmony_ci} 50b1b8bc3fSopenharmony_ci 51b1b8bc3fSopenharmony_civoid Nat464Service::UpdateService(Nat464UpdateFlag updateFlag) 52b1b8bc3fSopenharmony_ci{ 53b1b8bc3fSopenharmony_ci auto handle = serviceUpdateQueue_.submit_h([this, updateFlag]() { UpdateServiceState(updateFlag); }, 54b1b8bc3fSopenharmony_ci ffrt::task_attr().name("UpdateNat464ServiceState")); 55b1b8bc3fSopenharmony_ci serviceUpdateQueue_.wait(handle); 56b1b8bc3fSopenharmony_ci} 57b1b8bc3fSopenharmony_ci 58b1b8bc3fSopenharmony_civoid Nat464Service::UpdateServiceState(Nat464UpdateFlag updateFlag) 59b1b8bc3fSopenharmony_ci{ 60b1b8bc3fSopenharmony_ci NETMGR_LOG_I("update nat464 service state"); 61b1b8bc3fSopenharmony_ci switch (serviceState_) { 62b1b8bc3fSopenharmony_ci case NAT464_SERVICE_STATE_IDLE: 63b1b8bc3fSopenharmony_ci if (updateFlag == NAT464_SERVICE_CONTINUE) { 64b1b8bc3fSopenharmony_ci StartPrefixDiscovery(); 65b1b8bc3fSopenharmony_ci serviceState_ = NAT464_SERVICE_STATE_DISCOVERING; 66b1b8bc3fSopenharmony_ci } 67b1b8bc3fSopenharmony_ci break; 68b1b8bc3fSopenharmony_ci 69b1b8bc3fSopenharmony_ci case NAT464_SERVICE_STATE_DISCOVERING: 70b1b8bc3fSopenharmony_ci if (updateFlag == NAT464_SERVICE_STOP) { 71b1b8bc3fSopenharmony_ci StopPrefixDiscovery(); 72b1b8bc3fSopenharmony_ci serviceState_ = NAT464_SERVICE_STATE_IDLE; 73b1b8bc3fSopenharmony_ci } 74b1b8bc3fSopenharmony_ci if (updateFlag == NAT464_SERVICE_CONTINUE && !nat64PrefixFromDns_.address_.empty()) { 75b1b8bc3fSopenharmony_ci StartService(); 76b1b8bc3fSopenharmony_ci serviceState_ = NAT464_SERVICE_STATE_RUNNING; 77b1b8bc3fSopenharmony_ci } 78b1b8bc3fSopenharmony_ci break; 79b1b8bc3fSopenharmony_ci 80b1b8bc3fSopenharmony_ci case NAT464_SERVICE_STATE_RUNNING: 81b1b8bc3fSopenharmony_ci if (updateFlag == NAT464_SERVICE_STOP) { 82b1b8bc3fSopenharmony_ci StopService(); 83b1b8bc3fSopenharmony_ci serviceState_ = NAT464_SERVICE_STATE_IDLE; 84b1b8bc3fSopenharmony_ci break; 85b1b8bc3fSopenharmony_ci } 86b1b8bc3fSopenharmony_ci break; 87b1b8bc3fSopenharmony_ci } 88b1b8bc3fSopenharmony_ci} 89b1b8bc3fSopenharmony_ci 90b1b8bc3fSopenharmony_civoid Nat464Service::StartPrefixDiscovery() 91b1b8bc3fSopenharmony_ci{ 92b1b8bc3fSopenharmony_ci NETMGR_LOG_I("start to discover prefix64 from DNS64 server"); 93b1b8bc3fSopenharmony_ci ffrt::submit([this]() { DiscoverPrefix(); }, {}, {}, 94b1b8bc3fSopenharmony_ci ffrt::task_attr().name(("Prefix64DiscoveryIter" + std::to_string(discoveryIter_)).c_str())); 95b1b8bc3fSopenharmony_ci} 96b1b8bc3fSopenharmony_ci 97b1b8bc3fSopenharmony_civoid Nat464Service::DiscoverPrefix() 98b1b8bc3fSopenharmony_ci{ 99b1b8bc3fSopenharmony_ci if (tryStopDiscovery_) { 100b1b8bc3fSopenharmony_ci NETMGR_LOG_I("stop flag is true, stop cycle"); 101b1b8bc3fSopenharmony_ci tryStopDiscovery_ = false; 102b1b8bc3fSopenharmony_ci discoveryCycleMs_ = INITIAL_DISCOVERY_CYCLE_MS; 103b1b8bc3fSopenharmony_ci discoveryIter_ = 1; 104b1b8bc3fSopenharmony_ci return; 105b1b8bc3fSopenharmony_ci } 106b1b8bc3fSopenharmony_ci if (GetPrefixFromDns64()) { 107b1b8bc3fSopenharmony_ci NETMGR_LOG_I("Get prefix64 from DNS64 server, stop cycle"); 108b1b8bc3fSopenharmony_ci discoveryCycleMs_ = INITIAL_DISCOVERY_CYCLE_MS; 109b1b8bc3fSopenharmony_ci discoveryIter_ = 1; 110b1b8bc3fSopenharmony_ci UpdateService(NAT464_SERVICE_CONTINUE); 111b1b8bc3fSopenharmony_ci } else if (discoveryCycleMs_ > MAX_DISCOVERY_CYCLE_MS) { 112b1b8bc3fSopenharmony_ci NETMGR_LOG_W("Fail to get prefix64 from DNS64 after %{public}u iterations, stop cycle", discoveryIter_); 113b1b8bc3fSopenharmony_ci } else { 114b1b8bc3fSopenharmony_ci NETMGR_LOG_I("Fail to get prefix64 from DNS64 server, try again after %{public}u ms", discoveryCycleMs_); 115b1b8bc3fSopenharmony_ci ffrt::this_task::sleep_for(std::chrono::milliseconds(discoveryCycleMs_)); 116b1b8bc3fSopenharmony_ci discoveryIter_ += 1; 117b1b8bc3fSopenharmony_ci discoveryCycleMs_ *= DISCOVERY_CYCLE_MULTIPLIER; 118b1b8bc3fSopenharmony_ci ffrt::submit([this]() { DiscoverPrefix(); }, {}, {}, 119b1b8bc3fSopenharmony_ci ffrt::task_attr().name(("Prefix64DiscoveryIter" + std::to_string(discoveryIter_)).c_str())); 120b1b8bc3fSopenharmony_ci } 121b1b8bc3fSopenharmony_ci} 122b1b8bc3fSopenharmony_ci 123b1b8bc3fSopenharmony_cibool Nat464Service::GetPrefixFromDns64() 124b1b8bc3fSopenharmony_ci{ 125b1b8bc3fSopenharmony_ci addrinfo hint = {}; 126b1b8bc3fSopenharmony_ci addrinfo *result; 127b1b8bc3fSopenharmony_ci hint.ai_family = AF_INET6; 128b1b8bc3fSopenharmony_ci 129b1b8bc3fSopenharmony_ci queryparam qparam = {}; 130b1b8bc3fSopenharmony_ci qparam.qp_netid = netId_; 131b1b8bc3fSopenharmony_ci qparam.qp_type = 1; 132b1b8bc3fSopenharmony_ci 133b1b8bc3fSopenharmony_ci int32_t ret = getaddrinfo_ext(IPV4_ONLY_HOST, NULL, &hint, &result, &qparam); 134b1b8bc3fSopenharmony_ci if (ret != 0) { 135b1b8bc3fSopenharmony_ci NETMGR_LOG_W("fail to get v6Addr of the well-known ipv4-only host from dns, errno: %{public}d", ret); 136b1b8bc3fSopenharmony_ci return false; 137b1b8bc3fSopenharmony_ci } 138b1b8bc3fSopenharmony_ci 139b1b8bc3fSopenharmony_ci INetAddr prefixAddr; 140b1b8bc3fSopenharmony_ci for (addrinfo *tmp = result; tmp != nullptr; tmp = tmp->ai_next) { 141b1b8bc3fSopenharmony_ci if (tmp->ai_family != AF_INET6) { 142b1b8bc3fSopenharmony_ci continue; 143b1b8bc3fSopenharmony_ci } 144b1b8bc3fSopenharmony_ci auto addr = reinterpret_cast<sockaddr_in6 *>(tmp->ai_addr); 145b1b8bc3fSopenharmony_ci char addrstr[INET6_ADDRSTRLEN]; 146b1b8bc3fSopenharmony_ci inet_ntop(AF_INET6, &addr->sin6_addr, addrstr, sizeof(addrstr)); 147b1b8bc3fSopenharmony_ci prefixAddr.address_ = addrstr; 148b1b8bc3fSopenharmony_ci prefixAddr.family_ = tmp->ai_family; 149b1b8bc3fSopenharmony_ci prefixAddr.prefixlen_ = CLAT_PREFIX_BYTE_LEN * CHAR_BIT; 150b1b8bc3fSopenharmony_ci break; 151b1b8bc3fSopenharmony_ci } 152b1b8bc3fSopenharmony_ci freeaddrinfo(result); 153b1b8bc3fSopenharmony_ci 154b1b8bc3fSopenharmony_ci nat64PrefixFromDns_ = prefixAddr; 155b1b8bc3fSopenharmony_ci return true; 156b1b8bc3fSopenharmony_ci} 157b1b8bc3fSopenharmony_ci 158b1b8bc3fSopenharmony_civoid Nat464Service::StopPrefixDiscovery() 159b1b8bc3fSopenharmony_ci{ 160b1b8bc3fSopenharmony_ci tryStopDiscovery_ = true; 161b1b8bc3fSopenharmony_ci} 162b1b8bc3fSopenharmony_ci 163b1b8bc3fSopenharmony_civoid Nat464Service::StartService() 164b1b8bc3fSopenharmony_ci{ 165b1b8bc3fSopenharmony_ci if (serviceState_ == NAT464_SERVICE_STATE_RUNNING) { 166b1b8bc3fSopenharmony_ci NETMGR_LOG_W("Nat464 service already started"); 167b1b8bc3fSopenharmony_ci return; 168b1b8bc3fSopenharmony_ci } 169b1b8bc3fSopenharmony_ci 170b1b8bc3fSopenharmony_ci int32_t ret = NetsysController::GetInstance().StartClat(v6Iface_, netId_, nat64PrefixFromDns_.address_); 171b1b8bc3fSopenharmony_ci if (ret != NETMANAGER_SUCCESS) { 172b1b8bc3fSopenharmony_ci NETMGR_LOG_W("fail to start clat, error no: %{public}d", ret); 173b1b8bc3fSopenharmony_ci return; 174b1b8bc3fSopenharmony_ci } 175b1b8bc3fSopenharmony_ci} 176b1b8bc3fSopenharmony_ci 177b1b8bc3fSopenharmony_civoid Nat464Service::StopService() 178b1b8bc3fSopenharmony_ci{ 179b1b8bc3fSopenharmony_ci NetsysController::GetInstance().StopClat(v6Iface_); 180b1b8bc3fSopenharmony_ci nat64PrefixFromDns_ = INetAddr(); 181b1b8bc3fSopenharmony_ci} 182b1b8bc3fSopenharmony_ci 183b1b8bc3fSopenharmony_ci} // namespace NetManagerStandard 184b1b8bc3fSopenharmony_ci} // namespace OHOS