1b1b8bc3fSopenharmony_ci/* 2b1b8bc3fSopenharmony_ci * Copyright (c) 2021-2022 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 16b1b8bc3fSopenharmony_ci#include <arpa/inet.h> 17b1b8bc3fSopenharmony_ci#include <cstdint> 18b1b8bc3fSopenharmony_ci#include <cstring> 19b1b8bc3fSopenharmony_ci#include <iostream> 20b1b8bc3fSopenharmony_ci#include <linux/fib_rules.h> 21b1b8bc3fSopenharmony_ci#include <linux/netlink.h> 22b1b8bc3fSopenharmony_ci#include <linux/rtnetlink.h> 23b1b8bc3fSopenharmony_ci#include <map> 24b1b8bc3fSopenharmony_ci#include <mutex> 25b1b8bc3fSopenharmony_ci#include <net/if.h> 26b1b8bc3fSopenharmony_ci#include <netlink_socket.h> 27b1b8bc3fSopenharmony_ci#include <sstream> 28b1b8bc3fSopenharmony_ci#include <sys/ioctl.h> 29b1b8bc3fSopenharmony_ci#include <sys/socket.h> 30b1b8bc3fSopenharmony_ci#include <sys/uio.h> 31b1b8bc3fSopenharmony_ci#include <unistd.h> 32b1b8bc3fSopenharmony_ci 33b1b8bc3fSopenharmony_ci#include "fwmark.h" 34b1b8bc3fSopenharmony_ci#include "net_manager_constants.h" 35b1b8bc3fSopenharmony_ci#include "netlink_manager.h" 36b1b8bc3fSopenharmony_ci#include "netlink_msg.h" 37b1b8bc3fSopenharmony_ci#include "netmanager_base_common_utils.h" 38b1b8bc3fSopenharmony_ci#include "netnative_log_wrapper.h" 39b1b8bc3fSopenharmony_ci#include "securec.h" 40b1b8bc3fSopenharmony_ci#include "distributed_manager.h" 41b1b8bc3fSopenharmony_ci 42b1b8bc3fSopenharmony_ci#include "route_manager.h" 43b1b8bc3fSopenharmony_ci 44b1b8bc3fSopenharmony_ciusing namespace OHOS::NetManagerStandard; 45b1b8bc3fSopenharmony_ciusing namespace OHOS::NetManagerStandard::CommonUtils; 46b1b8bc3fSopenharmony_cinamespace OHOS { 47b1b8bc3fSopenharmony_cinamespace nmd { 48b1b8bc3fSopenharmony_cinamespace { 49b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_CLAT_TUN = 8000; 50b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_VPN_OUTPUT_TO_LOCAL = 9000; 51b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_SECURE_VPN = 10000; 52b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_VNIC_NETWORK = 10500; 53b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_EXPLICIT_NETWORK = 11000; 54b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_OUTPUT_IFACE_VPN = 11500; 55b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_OUTPUT_INTERFACE = 12000; 56b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_LOCAL_NETWORK = 13000; 57b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_SHARING = 14000; 58b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_DEFAULT = 16000; 59b1b8bc3fSopenharmony_ciconstexpr int32_t RULE_LEVEL_DISTRIBUTE_COMMUNICATION = 16500; 60b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_DISTRIBUTE_TO_CLIENT_TABLE = 90; 61b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_DISTRIBUTE_FROM_CLIENT_TABLE = 91; 62b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_VNIC_TABLE = 97; 63b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_VPN_NETWORK_TABLE = 98; 64b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_LOCAL_NETWORK_TABLE = 99; 65b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTE_INTERNAL_DEFAULT_TABLE = 1; 66b1b8bc3fSopenharmony_ciconstexpr uint32_t OUTPUT_MAX = 128; 67b1b8bc3fSopenharmony_ciconstexpr uint32_t BIT_32_LEN = 32; 68b1b8bc3fSopenharmony_ciconstexpr uint32_t BIT_MAX_LEN = 255; 69b1b8bc3fSopenharmony_ciconstexpr uint32_t DECIMAL_DIGITAL = 10; 70b1b8bc3fSopenharmony_ciconstexpr uint32_t BYTE_ALIGNMENT = 8; 71b1b8bc3fSopenharmony_ciconstexpr uint32_t THOUSAND_LEN = 100; 72b1b8bc3fSopenharmony_ciconstexpr uint16_t LOCAL_NET_ID = 99; 73b1b8bc3fSopenharmony_ciconstexpr uint16_t NETID_UNSET = 0; 74b1b8bc3fSopenharmony_ciconstexpr uint32_t MARK_UNSET = 0; 75b1b8bc3fSopenharmony_ciconstexpr uid_t UID_ROOT = 0; 76b1b8bc3fSopenharmony_ciconstexpr std::pair<uid_t, uid_t> UID_ALLOW_INTERNAL = {7023, 7023}; 77b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTEMANAGER_SUCCESS = 0; 78b1b8bc3fSopenharmony_ciconstexpr uint32_t ROUTEMANAGER_ERROR = -1; 79b1b8bc3fSopenharmony_ciconstexpr bool ADD_CONTROL = true; 80b1b8bc3fSopenharmony_ciconstexpr bool DEL_CONTROL = false; 81b1b8bc3fSopenharmony_ciconst std::string RULEIIF_LOOPBACK = "lo"; 82b1b8bc3fSopenharmony_ciconst std::string RULEIIF_NULL = ""; 83b1b8bc3fSopenharmony_ciconst std::string RULEOIF_NULL = ""; 84b1b8bc3fSopenharmony_ciconst std::string RULEIP_NULL = ""; 85b1b8bc3fSopenharmony_ciconst std::string LOCAL_MANGLE_INPUT = "routectrl_mangle_INPUT"; 86b1b8bc3fSopenharmony_ciconstexpr const char *DISTRIBUTED_TUN_CARD_NAME = "virnic"; 87b1b8bc3fSopenharmony_ciconstexpr const char *NETSYS_ROUTE_INIT_DIR_PATH = "/data/service/el1/public/netmanager/route"; 88b1b8bc3fSopenharmony_ci 89b1b8bc3fSopenharmony_cistruct FibRuleUidRange { 90b1b8bc3fSopenharmony_ci __u32 start; 91b1b8bc3fSopenharmony_ci __u32 end; 92b1b8bc3fSopenharmony_ci}; 93b1b8bc3fSopenharmony_ci} // namespace 94b1b8bc3fSopenharmony_ci 95b1b8bc3fSopenharmony_cistd::mutex RouteManager::interfaceToTableLock_; 96b1b8bc3fSopenharmony_cistd::map<std::string, uint32_t> RouteManager::interfaceToTable_; 97b1b8bc3fSopenharmony_ci 98b1b8bc3fSopenharmony_ciRouteManager::RouteManager() 99b1b8bc3fSopenharmony_ci{ 100b1b8bc3fSopenharmony_ci Init(); 101b1b8bc3fSopenharmony_ci} 102b1b8bc3fSopenharmony_ci 103b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVnicRoute(const std::string &interfaceName, const std::string &destinationName, 104b1b8bc3fSopenharmony_ci const std::string &nextHop, bool add) 105b1b8bc3fSopenharmony_ci{ 106b1b8bc3fSopenharmony_ci NETNATIVE_LOGI( 107b1b8bc3fSopenharmony_ci "VnicChangeRoute,interfaceName:%{public}s,destination:%{public}s, nextHop:%{public}s, add:%{public}d ", 108b1b8bc3fSopenharmony_ci interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str(), add); 109b1b8bc3fSopenharmony_ci 110b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 111b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_VNIC_TABLE; 112b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = interfaceName; 113b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = destinationName; 114b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = nextHop; 115b1b8bc3fSopenharmony_ci uint16_t flags = add ? (NLM_F_CREATE | NLM_F_EXCL) : NLM_F_EXCL; 116b1b8bc3fSopenharmony_ci uint16_t action = add ? RTM_NEWROUTE : RTM_DELROUTE; 117b1b8bc3fSopenharmony_ci 118b1b8bc3fSopenharmony_ci return UpdateRouteRule(action, flags, routeInfo); 119b1b8bc3fSopenharmony_ci} 120b1b8bc3fSopenharmony_ci 121b1b8bc3fSopenharmony_ciint32_t RouteManager::AddRoute(TableType tableType, const std::string &interfaceName, 122b1b8bc3fSopenharmony_ci const std::string &destinationName, const std::string &nextHop, bool& routeRepeat) 123b1b8bc3fSopenharmony_ci{ 124b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddRoute,interfaceName:%{public}s,destination:%{public}s, nextHop:%{public}s", 125b1b8bc3fSopenharmony_ci interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str()); 126b1b8bc3fSopenharmony_ci 127b1b8bc3fSopenharmony_ci // This is a user-defined structure used to integrate the information required for setting up routes. 128b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 129b1b8bc3fSopenharmony_ci if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) { 130b1b8bc3fSopenharmony_ci return -1; 131b1b8bc3fSopenharmony_ci } 132b1b8bc3fSopenharmony_ci 133b1b8bc3fSopenharmony_ci int32_t ret = UpdateRouteRule(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, routeInfo); 134b1b8bc3fSopenharmony_ci if (ret == EEXIST) { 135b1b8bc3fSopenharmony_ci routeRepeat = true; 136b1b8bc3fSopenharmony_ci } else { 137b1b8bc3fSopenharmony_ci routeRepeat = false; 138b1b8bc3fSopenharmony_ci } 139b1b8bc3fSopenharmony_ci return ret; 140b1b8bc3fSopenharmony_ci} 141b1b8bc3fSopenharmony_ci 142b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveRoute(TableType tableType, const std::string &interfaceName, 143b1b8bc3fSopenharmony_ci const std::string &destinationName, const std::string &nextHop) 144b1b8bc3fSopenharmony_ci{ 145b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("RemoveRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s", 146b1b8bc3fSopenharmony_ci interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str()); 147b1b8bc3fSopenharmony_ci 148b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 149b1b8bc3fSopenharmony_ci if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) { 150b1b8bc3fSopenharmony_ci return -1; 151b1b8bc3fSopenharmony_ci } 152b1b8bc3fSopenharmony_ci return UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo); 153b1b8bc3fSopenharmony_ci} 154b1b8bc3fSopenharmony_ci 155b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateRoute(TableType tableType, const std::string &interfaceName, 156b1b8bc3fSopenharmony_ci const std::string &destinationName, const std::string &nextHop) 157b1b8bc3fSopenharmony_ci{ 158b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s", 159b1b8bc3fSopenharmony_ci interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str()); 160b1b8bc3fSopenharmony_ci 161b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 162b1b8bc3fSopenharmony_ci if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) { 163b1b8bc3fSopenharmony_ci return -1; 164b1b8bc3fSopenharmony_ci } 165b1b8bc3fSopenharmony_ci return UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo); 166b1b8bc3fSopenharmony_ci} 167b1b8bc3fSopenharmony_ci 168b1b8bc3fSopenharmony_ciint32_t RouteManager::AddInterfaceToDefaultNetwork(const std::string &interfaceName, NetworkPermission permission) 169b1b8bc3fSopenharmony_ci{ 170b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddInterfaceToDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(), 171b1b8bc3fSopenharmony_ci permission); 172b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(interfaceName); 173b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 174b1b8bc3fSopenharmony_ci return -1; 175b1b8bc3fSopenharmony_ci } 176b1b8bc3fSopenharmony_ci Fwmark fwmark; 177b1b8bc3fSopenharmony_ci fwmark.netId = NETID_UNSET; 178b1b8bc3fSopenharmony_ci fwmark.permission = permission; 179b1b8bc3fSopenharmony_ci 180b1b8bc3fSopenharmony_ci Fwmark mask; 181b1b8bc3fSopenharmony_ci mask.netId = FWMARK_NET_ID_MASK; 182b1b8bc3fSopenharmony_ci mask.permission = permission; 183b1b8bc3fSopenharmony_ci 184b1b8bc3fSopenharmony_ci // This is a user-defined structure used to integrate the information required for setting up rules. 185b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 186b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 187b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DEFAULT; 188b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 189b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 190b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 191b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 192b1b8bc3fSopenharmony_ci return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo); 193b1b8bc3fSopenharmony_ci} 194b1b8bc3fSopenharmony_ci 195b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveInterfaceFromDefaultNetwork(const std::string &interfaceName, NetworkPermission permission) 196b1b8bc3fSopenharmony_ci{ 197b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("RemoveInterfaceFromDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(), 198b1b8bc3fSopenharmony_ci permission); 199b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(interfaceName); 200b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 201b1b8bc3fSopenharmony_ci return -1; 202b1b8bc3fSopenharmony_ci } 203b1b8bc3fSopenharmony_ci 204b1b8bc3fSopenharmony_ci Fwmark fwmark; 205b1b8bc3fSopenharmony_ci fwmark.netId = NETID_UNSET; 206b1b8bc3fSopenharmony_ci fwmark.permission = permission; 207b1b8bc3fSopenharmony_ci 208b1b8bc3fSopenharmony_ci Fwmark mask; 209b1b8bc3fSopenharmony_ci mask.netId = FWMARK_NET_ID_MASK; 210b1b8bc3fSopenharmony_ci mask.permission = permission; 211b1b8bc3fSopenharmony_ci 212b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 213b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 214b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DEFAULT; 215b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 216b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 217b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 218b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 219b1b8bc3fSopenharmony_ci return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo); 220b1b8bc3fSopenharmony_ci} 221b1b8bc3fSopenharmony_ci 222b1b8bc3fSopenharmony_ciint32_t RouteManager::AddInterfaceToPhysicalNetwork(uint16_t netId, const std::string &interfaceName, 223b1b8bc3fSopenharmony_ci NetworkPermission permission) 224b1b8bc3fSopenharmony_ci{ 225b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddInterfaceToPhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;", 226b1b8bc3fSopenharmony_ci netId, interfaceName.c_str(), permission); 227b1b8bc3fSopenharmony_ci return UpdatePhysicalNetwork(netId, interfaceName, permission, ADD_CONTROL); 228b1b8bc3fSopenharmony_ci} 229b1b8bc3fSopenharmony_ci 230b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveInterfaceFromPhysicalNetwork(uint16_t netId, const std::string &interfaceName, 231b1b8bc3fSopenharmony_ci NetworkPermission permission) 232b1b8bc3fSopenharmony_ci{ 233b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("RemoveInterfacePhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;", 234b1b8bc3fSopenharmony_ci netId, interfaceName.c_str(), permission); 235b1b8bc3fSopenharmony_ci if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, permission, DEL_CONTROL)) { 236b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret); 237b1b8bc3fSopenharmony_ci return ret; 238b1b8bc3fSopenharmony_ci } 239b1b8bc3fSopenharmony_ci if (int32_t ret = ClearRoutes(interfaceName, netId)) { 240b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ClearRoutes err, error is %{public}d", ret); 241b1b8bc3fSopenharmony_ci return ret; 242b1b8bc3fSopenharmony_ci } 243b1b8bc3fSopenharmony_ci if (NetManagerStandard::IsInternalNetId(netId)) { 244b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("InternalNetId skip"); 245b1b8bc3fSopenharmony_ci return 0; 246b1b8bc3fSopenharmony_ci } 247b1b8bc3fSopenharmony_ci if (int32_t ret = ClearSharingRules(interfaceName)) { 248b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ClearSharingRules err, error is %{public}d", ret); 249b1b8bc3fSopenharmony_ci return ret; 250b1b8bc3fSopenharmony_ci } 251b1b8bc3fSopenharmony_ci 252b1b8bc3fSopenharmony_ci return 0; 253b1b8bc3fSopenharmony_ci} 254b1b8bc3fSopenharmony_ci 255b1b8bc3fSopenharmony_ciint32_t RouteManager::ModifyPhysicalNetworkPermission(uint16_t netId, const std::string &interfaceName, 256b1b8bc3fSopenharmony_ci NetworkPermission oldPermission, NetworkPermission newPermission) 257b1b8bc3fSopenharmony_ci{ 258b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("ModifyPhysicalNetworkPermission, %{public}s", interfaceName.c_str()); 259b1b8bc3fSopenharmony_ci if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, newPermission, ADD_CONTROL)) { 260b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret); 261b1b8bc3fSopenharmony_ci return ret; 262b1b8bc3fSopenharmony_ci } 263b1b8bc3fSopenharmony_ci 264b1b8bc3fSopenharmony_ci return UpdatePhysicalNetwork(netId, interfaceName, newPermission, DEL_CONTROL); 265b1b8bc3fSopenharmony_ci} 266b1b8bc3fSopenharmony_ci 267b1b8bc3fSopenharmony_ciint32_t RouteManager::AddInterfaceToVirtualNetwork(int32_t netId, const std::string &interfaceName) 268b1b8bc3fSopenharmony_ci{ 269b1b8bc3fSopenharmony_ci return ModifyVirtualNetBasedRules(netId, interfaceName, true); 270b1b8bc3fSopenharmony_ci} 271b1b8bc3fSopenharmony_ci 272b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveInterfaceFromVirtualNetwork(int32_t netId, const std::string &interfaceName) 273b1b8bc3fSopenharmony_ci{ 274b1b8bc3fSopenharmony_ci if (ModifyVirtualNetBasedRules(netId, interfaceName, false) != ROUTEMANAGER_SUCCESS) { 275b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 276b1b8bc3fSopenharmony_ci } 277b1b8bc3fSopenharmony_ci return ClearRouteInfo(RTM_GETROUTE, ROUTE_VPN_NETWORK_TABLE); 278b1b8bc3fSopenharmony_ci} 279b1b8bc3fSopenharmony_ci 280b1b8bc3fSopenharmony_ciint32_t RouteManager::ModifyVirtualNetBasedRules(int32_t netId, const std::string &ifaceName, bool add) 281b1b8bc3fSopenharmony_ci{ 282b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("ModifyVirtualNetBasedRules,add===%{public}d", add); 283b1b8bc3fSopenharmony_ci uint32_t table = GetRouteTableFromType(RouteManager::VPN_NETWORK, ifaceName); 284b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 285b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error"); 286b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 287b1b8bc3fSopenharmony_ci } 288b1b8bc3fSopenharmony_ci 289b1b8bc3fSopenharmony_ci // If the rule fails to be added, continue to execute the next rule 290b1b8bc3fSopenharmony_ci int32_t ret = UpdateVpnOutputToLocalRule(ifaceName, add); 291b1b8bc3fSopenharmony_ci ret += UpdateVpnSystemPermissionRule(netId, table, add); 292b1b8bc3fSopenharmony_ci ret += UpdateExplicitNetworkRuleWithUid(netId, table, PERMISSION_NONE, UID_ROOT, UID_ROOT, add); 293b1b8bc3fSopenharmony_ci return ret; 294b1b8bc3fSopenharmony_ci} 295b1b8bc3fSopenharmony_ci 296b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVpnOutputToLocalRule(const std::string &interfaceName, bool add) 297b1b8bc3fSopenharmony_ci{ 298b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 299b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_LOCAL_NETWORK_TABLE; 300b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_VPN_OUTPUT_TO_LOCAL; 301b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 302b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 303b1b8bc3fSopenharmony_ci if (interfaceName.find("vpn") == std::string::npos) { 304b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = interfaceName; 305b1b8bc3fSopenharmony_ci } 306b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 307b1b8bc3fSopenharmony_ci 308b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 309b1b8bc3fSopenharmony_ci} 310b1b8bc3fSopenharmony_ci 311b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVpnSystemPermissionRule(int32_t netId, uint32_t table, bool add) 312b1b8bc3fSopenharmony_ci{ 313b1b8bc3fSopenharmony_ci Fwmark fwmark; 314b1b8bc3fSopenharmony_ci fwmark.netId = netId; 315b1b8bc3fSopenharmony_ci NetworkPermission permission = NetworkPermission::PERMISSION_SYSTEM; 316b1b8bc3fSopenharmony_ci fwmark.permission = permission; 317b1b8bc3fSopenharmony_ci 318b1b8bc3fSopenharmony_ci Fwmark mask; 319b1b8bc3fSopenharmony_ci mask.netId = FWMARK_NET_ID_MASK; 320b1b8bc3fSopenharmony_ci mask.permission = permission; 321b1b8bc3fSopenharmony_ci 322b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 323b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 324b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_SECURE_VPN; 325b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 326b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 327b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_NULL; 328b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 329b1b8bc3fSopenharmony_ci 330b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 331b1b8bc3fSopenharmony_ci} 332b1b8bc3fSopenharmony_ci 333b1b8bc3fSopenharmony_ciint32_t RouteManager::AddUsersToVirtualNetwork(int32_t netId, const std::string &interfaceName, 334b1b8bc3fSopenharmony_ci const std::vector<NetManagerStandard::UidRange> &uidRanges) 335b1b8bc3fSopenharmony_ci{ 336b1b8bc3fSopenharmony_ci return UpdateVirtualNetwork(netId, interfaceName, uidRanges, true); 337b1b8bc3fSopenharmony_ci} 338b1b8bc3fSopenharmony_ci 339b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveUsersFromVirtualNetwork(int32_t netId, const std::string &interfaceName, 340b1b8bc3fSopenharmony_ci const std::vector<NetManagerStandard::UidRange> &uidRanges) 341b1b8bc3fSopenharmony_ci{ 342b1b8bc3fSopenharmony_ci return UpdateVirtualNetwork(netId, interfaceName, uidRanges, false); 343b1b8bc3fSopenharmony_ci} 344b1b8bc3fSopenharmony_ci 345b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVirtualNetwork(int32_t netId, const std::string &interfaceName, 346b1b8bc3fSopenharmony_ci const std::vector<NetManagerStandard::UidRange> &uidRanges, bool add) 347b1b8bc3fSopenharmony_ci{ 348b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateVirtualNetwork, add == %{public}d", add); 349b1b8bc3fSopenharmony_ci uint32_t table = GetRouteTableFromType(RouteManager::VPN_NETWORK, interfaceName); 350b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 351b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error"); 352b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 353b1b8bc3fSopenharmony_ci } 354b1b8bc3fSopenharmony_ci int32_t ret = ROUTEMANAGER_SUCCESS; 355b1b8bc3fSopenharmony_ci for (auto range : uidRanges) { 356b1b8bc3fSopenharmony_ci // If the rule fails to be added, continue to execute the next rule 357b1b8bc3fSopenharmony_ci ret += UpdateVpnUidRangeRule(table, range.begin_, range.end_, add); 358b1b8bc3fSopenharmony_ci ret += UpdateExplicitNetworkRuleWithUid(netId, table, PERMISSION_NONE, range.begin_, range.end_, add); 359b1b8bc3fSopenharmony_ci ret += UpdateOutputInterfaceRulesWithUid(interfaceName, table, PERMISSION_NONE, range.begin_, range.end_, add); 360b1b8bc3fSopenharmony_ci } 361b1b8bc3fSopenharmony_ci return ret; 362b1b8bc3fSopenharmony_ci} 363b1b8bc3fSopenharmony_ci 364b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVnicUidRangesRule(const std::vector<NetManagerStandard::UidRange> &uidRanges, bool add) 365b1b8bc3fSopenharmony_ci{ 366b1b8bc3fSopenharmony_ci int32_t ret = ROUTEMANAGER_SUCCESS; 367b1b8bc3fSopenharmony_ci for (const auto &range : uidRanges) { 368b1b8bc3fSopenharmony_ci Fwmark fwmark; 369b1b8bc3fSopenharmony_ci Fwmark mask; 370b1b8bc3fSopenharmony_ci fwmark.protectedFromVpn = false; 371b1b8bc3fSopenharmony_ci mask.protectedFromVpn = false; 372b1b8bc3fSopenharmony_ci 373b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 374b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_VNIC_TABLE; 375b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_VNIC_NETWORK; 376b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 377b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 378b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 379b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 380b1b8bc3fSopenharmony_ci ret += UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, range.begin_, range.end_); 381b1b8bc3fSopenharmony_ci } 382b1b8bc3fSopenharmony_ci return ret; 383b1b8bc3fSopenharmony_ci} 384b1b8bc3fSopenharmony_ci 385b1b8bc3fSopenharmony_ciint32_t RouteManager::EnableDistributedClientNet(const std::string &virNicAddr, const std::string &iif) 386b1b8bc3fSopenharmony_ci{ 387b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("EnableDistributedClientNet virNicAddr:%{public}s,iif:%{public}s", 388b1b8bc3fSopenharmony_ci ToAnonymousIp(virNicAddr).c_str(), iif.c_str()); 389b1b8bc3fSopenharmony_ci int32_t ret = DistributedManager::GetInstance().CreateDistributedNic(virNicAddr, DISTRIBUTED_TUN_CARD_NAME); 390b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 391b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("CreateDistributedNic err, error is %{public}d", ret); 392b1b8bc3fSopenharmony_ci return ret; 393b1b8bc3fSopenharmony_ci } 394b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("EnableDistributedClientNet CreateDistributedNic success."); 395b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 396b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 397b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DISTRIBUTE_COMMUNICATION; 398b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = iif; 399b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 400b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 401b1b8bc3fSopenharmony_ci ret = UpdateDistributedRule(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 402b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 403b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedClientNet UpdateDistributedRule err, error is %{public}d", ret); 404b1b8bc3fSopenharmony_ci return ret; 405b1b8bc3fSopenharmony_ci } 406b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("EnableDistributedClientNet add rule success."); 407b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 408b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 409b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = DISTRIBUTED_TUN_CARD_NAME; 410b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = "0.0.0.0/0"; 411b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = "0.0.0.0"; 412b1b8bc3fSopenharmony_ci uint16_t flags = (NLM_F_CREATE | NLM_F_EXCL); 413b1b8bc3fSopenharmony_ci uint16_t action = RTM_NEWROUTE; 414b1b8bc3fSopenharmony_ci ret = UpdateRouteRule(action, flags, routeInfo); 415b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 416b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedClientNet UpdateRouteRule err, NLM_F_REPLACE"); 417b1b8bc3fSopenharmony_ci if (UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo)) { 418b1b8bc3fSopenharmony_ci UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 419b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 420b1b8bc3fSopenharmony_ci } 421b1b8bc3fSopenharmony_ci } 422b1b8bc3fSopenharmony_ci 423b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("EnableDistributedClientNet add route success."); 424b1b8bc3fSopenharmony_ci return ROUTEMANAGER_SUCCESS; 425b1b8bc3fSopenharmony_ci} 426b1b8bc3fSopenharmony_ci 427b1b8bc3fSopenharmony_ciint32_t RouteManager::AddServerUplinkRoute(const std::string &UplinkIif, const std::string &devIface) 428b1b8bc3fSopenharmony_ci{ 429b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 430b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_DISTRIBUTE_FROM_CLIENT_TABLE; 431b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DISTRIBUTE_COMMUNICATION; 432b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = UplinkIif; 433b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 434b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 435b1b8bc3fSopenharmony_ci int32_t ret = UpdateDistributedRule(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 436b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 437b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet Update Uplink RuleInfo err, error is %{public}d", ret); 438b1b8bc3fSopenharmony_ci return ret; 439b1b8bc3fSopenharmony_ci } 440b1b8bc3fSopenharmony_ci 441b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 442b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_FROM_CLIENT_TABLE; 443b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = devIface; 444b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = "0.0.0.0/0"; 445b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = "0.0.0.0"; 446b1b8bc3fSopenharmony_ci uint16_t flags = (NLM_F_CREATE | NLM_F_EXCL); 447b1b8bc3fSopenharmony_ci uint16_t action = RTM_NEWROUTE; 448b1b8bc3fSopenharmony_ci ret = UpdateRouteRule(action, flags, routeInfo); 449b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 450b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet Update Uplink RouteRule err, NLM_F_REPLACE"); 451b1b8bc3fSopenharmony_ci if (UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo)) { 452b1b8bc3fSopenharmony_ci UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 453b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 454b1b8bc3fSopenharmony_ci } 455b1b8bc3fSopenharmony_ci } 456b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet AddServerUplinkRoute success"); 457b1b8bc3fSopenharmony_ci 458b1b8bc3fSopenharmony_ci return ROUTEMANAGER_SUCCESS; 459b1b8bc3fSopenharmony_ci} 460b1b8bc3fSopenharmony_ci 461b1b8bc3fSopenharmony_ciint32_t RouteManager::AddServerDownlinkRoute(const std::string &UplinkIif, const std::string &dstAddr) 462b1b8bc3fSopenharmony_ci{ 463b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 464b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 465b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DISTRIBUTE_COMMUNICATION; 466b1b8bc3fSopenharmony_ci ruleInfo.ruleDstIp = dstAddr; 467b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 468b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 469b1b8bc3fSopenharmony_ci int32_t ret = UpdateDistributedRule(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 470b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 471b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet Update Downlink RuleInfo err, error is %{public}d", ret); 472b1b8bc3fSopenharmony_ci return ret; 473b1b8bc3fSopenharmony_ci } 474b1b8bc3fSopenharmony_ci 475b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 476b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 477b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = UplinkIif; 478b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = "0.0.0.0/0"; 479b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = "0.0.0.0"; 480b1b8bc3fSopenharmony_ci uint16_t flags = (NLM_F_CREATE | NLM_F_EXCL); 481b1b8bc3fSopenharmony_ci uint16_t action = RTM_NEWROUTE; 482b1b8bc3fSopenharmony_ci ret = UpdateRouteRule(action, flags, routeInfo); 483b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 484b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet Update Downlink RouteRule err, NLM_F_REPLACE"); 485b1b8bc3fSopenharmony_ci if (UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo)) { 486b1b8bc3fSopenharmony_ci UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 487b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 488b1b8bc3fSopenharmony_ci } 489b1b8bc3fSopenharmony_ci } 490b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("EnableDistributedServerNet AddServerDownlinkRoute success"); 491b1b8bc3fSopenharmony_ci 492b1b8bc3fSopenharmony_ci return ROUTEMANAGER_SUCCESS; 493b1b8bc3fSopenharmony_ci} 494b1b8bc3fSopenharmony_ci 495b1b8bc3fSopenharmony_ciint32_t RouteManager::EnableDistributedServerNet(const std::string &iif, const std::string &devIface, 496b1b8bc3fSopenharmony_ci const std::string &dstAddr) 497b1b8bc3fSopenharmony_ci{ 498b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("EnableDistributedServerNet iif:%{public}s,devIface:%{public}s,dstAddr:%{public}s", 499b1b8bc3fSopenharmony_ci iif.c_str(), devIface.c_str(), ToAnonymousIp(dstAddr).c_str()); 500b1b8bc3fSopenharmony_ci 501b1b8bc3fSopenharmony_ci int32_t ret = ROUTEMANAGER_SUCCESS; 502b1b8bc3fSopenharmony_ci DistributedManager::GetInstance().SetServerNicInfo(iif, devIface); 503b1b8bc3fSopenharmony_ci ret += AddServerUplinkRoute(iif, devIface); 504b1b8bc3fSopenharmony_ci ret += AddServerDownlinkRoute(iif, dstAddr); 505b1b8bc3fSopenharmony_ci 506b1b8bc3fSopenharmony_ci return ret; 507b1b8bc3fSopenharmony_ci} 508b1b8bc3fSopenharmony_ci 509b1b8bc3fSopenharmony_ciint32_t RouteManager::DisableDistributedNet(bool isServer) 510b1b8bc3fSopenharmony_ci{ 511b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("DisableDistributedNet Enter, isServer:%{public}d", isServer); 512b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 513b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 514b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 515b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_NULL; 516b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 517b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = RT_TABLE_UNSPEC; 518b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_DISTRIBUTE_COMMUNICATION; 519b1b8bc3fSopenharmony_ci RouteInfo routeInfo; 520b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 521b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = DISTRIBUTED_TUN_CARD_NAME; 522b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = "0.0.0.0/0"; 523b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = "0.0.0.0"; 524b1b8bc3fSopenharmony_ci int32_t ret = ROUTEMANAGER_SUCCESS; 525b1b8bc3fSopenharmony_ci if (isServer) { 526b1b8bc3fSopenharmony_ci ret += UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 527b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 528b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del server uplink rule err, rule prio is %{public}d", ruleInfo.rulePriority); 529b1b8bc3fSopenharmony_ci } 530b1b8bc3fSopenharmony_ci ret += UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 531b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 532b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del server downlink rule err, rule prio is %{public}d", ruleInfo.rulePriority); 533b1b8bc3fSopenharmony_ci } 534b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_FROM_CLIENT_TABLE; 535b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = DistributedManager::GetInstance().GetServerDevIfaceNic(); 536b1b8bc3fSopenharmony_ci ret += UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo); 537b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 538b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del server uplink route err, route table is %{public}d", routeInfo.routeTable); 539b1b8bc3fSopenharmony_ci } 540b1b8bc3fSopenharmony_ci routeInfo.routeTable = ROUTE_DISTRIBUTE_TO_CLIENT_TABLE; 541b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = DistributedManager::GetInstance().GetServerIifNic(); 542b1b8bc3fSopenharmony_ci ret += UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo); 543b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 544b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del server downlink route err, route table is %{public}d", routeInfo.routeTable); 545b1b8bc3fSopenharmony_ci } 546b1b8bc3fSopenharmony_ci } else { 547b1b8bc3fSopenharmony_ci ret += UpdateDistributedRule(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID); 548b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 549b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del client rule err, rule prio is %{public}d", ruleInfo.rulePriority); 550b1b8bc3fSopenharmony_ci } 551b1b8bc3fSopenharmony_ci ret += UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo); 552b1b8bc3fSopenharmony_ci if (ret != ROUTEMANAGER_SUCCESS) { 553b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("del client route err, route table is %{public}d", routeInfo.routeTable); 554b1b8bc3fSopenharmony_ci } 555b1b8bc3fSopenharmony_ci DistributedManager::GetInstance().CloseDistributedTunFd(); 556b1b8bc3fSopenharmony_ci } 557b1b8bc3fSopenharmony_ci return ret; 558b1b8bc3fSopenharmony_ci} 559b1b8bc3fSopenharmony_ci 560b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateVpnUidRangeRule(uint32_t table, uid_t uidStart, uid_t uidEnd, bool add) 561b1b8bc3fSopenharmony_ci{ 562b1b8bc3fSopenharmony_ci Fwmark fwmark; 563b1b8bc3fSopenharmony_ci Fwmark mask; 564b1b8bc3fSopenharmony_ci fwmark.protectedFromVpn = false; 565b1b8bc3fSopenharmony_ci mask.protectedFromVpn = true; 566b1b8bc3fSopenharmony_ci 567b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 568b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 569b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_SECURE_VPN; 570b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 571b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 572b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 573b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 574b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd); 575b1b8bc3fSopenharmony_ci} 576b1b8bc3fSopenharmony_ci 577b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateExplicitNetworkRuleWithUid(int32_t netId, uint32_t table, NetworkPermission permission, 578b1b8bc3fSopenharmony_ci uid_t uidStart, uid_t uidEnd, bool add) 579b1b8bc3fSopenharmony_ci{ 580b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateExplicitNetworkRuleWithUid"); 581b1b8bc3fSopenharmony_ci Fwmark fwmark; 582b1b8bc3fSopenharmony_ci fwmark.netId = netId; 583b1b8bc3fSopenharmony_ci fwmark.explicitlySelected = true; 584b1b8bc3fSopenharmony_ci fwmark.permission = permission; 585b1b8bc3fSopenharmony_ci 586b1b8bc3fSopenharmony_ci Fwmark mask; 587b1b8bc3fSopenharmony_ci mask.netId = FWMARK_NET_ID_MASK; 588b1b8bc3fSopenharmony_ci mask.explicitlySelected = true; 589b1b8bc3fSopenharmony_ci mask.permission = permission; 590b1b8bc3fSopenharmony_ci 591b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 592b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 593b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_EXPLICIT_NETWORK; 594b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 595b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 596b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 597b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 598b1b8bc3fSopenharmony_ci 599b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd); 600b1b8bc3fSopenharmony_ci} 601b1b8bc3fSopenharmony_ci 602b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateOutputInterfaceRulesWithUid(const std::string &interface, uint32_t table, 603b1b8bc3fSopenharmony_ci NetworkPermission permission, uid_t uidStart, uid_t uidEnd, 604b1b8bc3fSopenharmony_ci bool add) 605b1b8bc3fSopenharmony_ci{ 606b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateOutputInterfaceRulesWithUid interface:%{public}s", interface.c_str()); 607b1b8bc3fSopenharmony_ci Fwmark fwmark; 608b1b8bc3fSopenharmony_ci fwmark.permission = permission; 609b1b8bc3fSopenharmony_ci 610b1b8bc3fSopenharmony_ci Fwmark mask; 611b1b8bc3fSopenharmony_ci mask.permission = permission; 612b1b8bc3fSopenharmony_ci 613b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 614b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 615b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_OUTPUT_IFACE_VPN; 616b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 617b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 618b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 619b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = interface; 620b1b8bc3fSopenharmony_ci 621b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd); 622b1b8bc3fSopenharmony_ci} 623b1b8bc3fSopenharmony_ci 624b1b8bc3fSopenharmony_ciint32_t RouteManager::AddInterfaceToLocalNetwork(uint16_t netId, const std::string &interfaceName) 625b1b8bc3fSopenharmony_ci{ 626b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddInterfaceToLocalNetwork, %{public}s", interfaceName.c_str()); 627b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, ADD_CONTROL)) { 628b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret); 629b1b8bc3fSopenharmony_ci return ret; 630b1b8bc3fSopenharmony_ci } 631b1b8bc3fSopenharmony_ci std::lock_guard lock(interfaceToTableLock_); 632b1b8bc3fSopenharmony_ci interfaceToTable_[interfaceName] = ROUTE_LOCAL_NETWORK_TABLE; 633b1b8bc3fSopenharmony_ci 634b1b8bc3fSopenharmony_ci return 0; 635b1b8bc3fSopenharmony_ci} 636b1b8bc3fSopenharmony_ci 637b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveInterfaceFromLocalNetwork(uint16_t netId, const std::string &interfaceName) 638b1b8bc3fSopenharmony_ci{ 639b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("RemoveInterfaceFromLocalNetwork"); 640b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, DEL_CONTROL)) { 641b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret); 642b1b8bc3fSopenharmony_ci return ret; 643b1b8bc3fSopenharmony_ci } 644b1b8bc3fSopenharmony_ci std::lock_guard lock(interfaceToTableLock_); 645b1b8bc3fSopenharmony_ci interfaceToTable_.erase(interfaceName); 646b1b8bc3fSopenharmony_ci 647b1b8bc3fSopenharmony_ci return 0; 648b1b8bc3fSopenharmony_ci} 649b1b8bc3fSopenharmony_ci 650b1b8bc3fSopenharmony_ciint32_t RouteManager::EnableSharing(const std::string &inputInterface, const std::string &outputInterface) 651b1b8bc3fSopenharmony_ci{ 652b1b8bc3fSopenharmony_ci return UpdateSharingNetwork(RTM_NEWRULE, inputInterface, outputInterface); 653b1b8bc3fSopenharmony_ci} 654b1b8bc3fSopenharmony_ci 655b1b8bc3fSopenharmony_ciint32_t RouteManager::DisableSharing(const std::string &inputInterface, const std::string &outputInterface) 656b1b8bc3fSopenharmony_ci{ 657b1b8bc3fSopenharmony_ci return UpdateSharingNetwork(RTM_DELRULE, inputInterface, outputInterface); 658b1b8bc3fSopenharmony_ci} 659b1b8bc3fSopenharmony_ci 660b1b8bc3fSopenharmony_ciint32_t RouteManager::ReadAddrGw(const std::string &addr, InetAddr *res) 661b1b8bc3fSopenharmony_ci{ 662b1b8bc3fSopenharmony_ci if (res == nullptr) { 663b1b8bc3fSopenharmony_ci return -1; 664b1b8bc3fSopenharmony_ci } 665b1b8bc3fSopenharmony_ci 666b1b8bc3fSopenharmony_ci std::string addressString(addr.c_str()); 667b1b8bc3fSopenharmony_ci if (strchr(addr.c_str(), ':')) { 668b1b8bc3fSopenharmony_ci res->family = AF_INET6; 669b1b8bc3fSopenharmony_ci res->bitlen = OUTPUT_MAX; 670b1b8bc3fSopenharmony_ci } else { 671b1b8bc3fSopenharmony_ci res->family = AF_INET; 672b1b8bc3fSopenharmony_ci res->bitlen = BIT_32_LEN; 673b1b8bc3fSopenharmony_ci } 674b1b8bc3fSopenharmony_ci 675b1b8bc3fSopenharmony_ci return inet_pton(res->family, addressString.c_str(), res->data); 676b1b8bc3fSopenharmony_ci} 677b1b8bc3fSopenharmony_ci 678b1b8bc3fSopenharmony_ciint32_t RouteManager::ReadAddr(const std::string &addr, InetAddr *res) 679b1b8bc3fSopenharmony_ci{ 680b1b8bc3fSopenharmony_ci if (res == nullptr) { 681b1b8bc3fSopenharmony_ci return -EINVAL; 682b1b8bc3fSopenharmony_ci } 683b1b8bc3fSopenharmony_ci 684b1b8bc3fSopenharmony_ci const char *slashStr = strchr(addr.c_str(), '/'); 685b1b8bc3fSopenharmony_ci if (slashStr == nullptr) { 686b1b8bc3fSopenharmony_ci return -EINVAL; 687b1b8bc3fSopenharmony_ci } 688b1b8bc3fSopenharmony_ci 689b1b8bc3fSopenharmony_ci const char *maskLenStr = slashStr + 1; 690b1b8bc3fSopenharmony_ci if (*maskLenStr == 0) { 691b1b8bc3fSopenharmony_ci return -EINVAL; 692b1b8bc3fSopenharmony_ci } 693b1b8bc3fSopenharmony_ci 694b1b8bc3fSopenharmony_ci char *endptr = nullptr; 695b1b8bc3fSopenharmony_ci unsigned templen = strtoul(maskLenStr, &endptr, DECIMAL_DIGITAL); 696b1b8bc3fSopenharmony_ci if ((endptr == nullptr) || (templen > BIT_MAX_LEN)) { 697b1b8bc3fSopenharmony_ci return -EINVAL; 698b1b8bc3fSopenharmony_ci } 699b1b8bc3fSopenharmony_ci res->prefixlen = templen; 700b1b8bc3fSopenharmony_ci 701b1b8bc3fSopenharmony_ci std::string addressString(addr.c_str(), slashStr - addr.c_str()); 702b1b8bc3fSopenharmony_ci if (strchr(addr.c_str(), ':')) { 703b1b8bc3fSopenharmony_ci res->family = AF_INET6; 704b1b8bc3fSopenharmony_ci res->bitlen = OUTPUT_MAX; 705b1b8bc3fSopenharmony_ci } else { 706b1b8bc3fSopenharmony_ci res->family = AF_INET; 707b1b8bc3fSopenharmony_ci res->bitlen = BIT_32_LEN; 708b1b8bc3fSopenharmony_ci } 709b1b8bc3fSopenharmony_ci 710b1b8bc3fSopenharmony_ci return inet_pton(res->family, addressString.c_str(), res->data); 711b1b8bc3fSopenharmony_ci} 712b1b8bc3fSopenharmony_ci 713b1b8bc3fSopenharmony_ciint32_t RouteManager::AddClatTunInterface(const std::string &interfaceName, const std::string &dstAddr, 714b1b8bc3fSopenharmony_ci const std::string &nxtHop) 715b1b8bc3fSopenharmony_ci{ 716b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddClatTunInterface, interfaceName:%{public}s; dstAddr:%{public}s; nxtHop:%{public}s;", 717b1b8bc3fSopenharmony_ci interfaceName.c_str(), dstAddr.c_str(), nxtHop.c_str()); 718b1b8bc3fSopenharmony_ci bool routeRepeat = false; 719b1b8bc3fSopenharmony_ci if (int32_t ret = AddRoute(RouteManager::INTERFACE, interfaceName, dstAddr, nxtHop, routeRepeat)) { 720b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("AddRoute err, error is %{public}d", ret); 721b1b8bc3fSopenharmony_ci return ret; 722b1b8bc3fSopenharmony_ci } 723b1b8bc3fSopenharmony_ci return UpdateClatTunInterface(interfaceName, PERMISSION_NONE, ADD_CONTROL); 724b1b8bc3fSopenharmony_ci} 725b1b8bc3fSopenharmony_ci 726b1b8bc3fSopenharmony_ciint32_t RouteManager::RemoveClatTunInterface(const std::string &interfaceName) 727b1b8bc3fSopenharmony_ci{ 728b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("RemoveClatTunInterface, interfaceName:%{public}s", interfaceName.c_str()); 729b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateClatTunInterface(interfaceName, PERMISSION_NONE, DEL_CONTROL)) { 730b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret); 731b1b8bc3fSopenharmony_ci return ret; 732b1b8bc3fSopenharmony_ci } 733b1b8bc3fSopenharmony_ci if (int32_t ret = ClearRoutes(interfaceName)) { 734b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ClearRoutes err, error is %{public}d", ret); 735b1b8bc3fSopenharmony_ci return ret; 736b1b8bc3fSopenharmony_ci } 737b1b8bc3fSopenharmony_ci if (int32_t ret = ClearSharingRules(interfaceName)) { 738b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ClearSharingRules err, error is %{public}d", ret); 739b1b8bc3fSopenharmony_ci return ret; 740b1b8bc3fSopenharmony_ci } 741b1b8bc3fSopenharmony_ci 742b1b8bc3fSopenharmony_ci return 0; 743b1b8bc3fSopenharmony_ci} 744b1b8bc3fSopenharmony_ci 745b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateClatTunInterface(const std::string &interfaceName, NetworkPermission permission, bool add) 746b1b8bc3fSopenharmony_ci{ 747b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateClatTunInterface, interfaceName: %{public}s, permission: %{public}d, add: %{public}d", 748b1b8bc3fSopenharmony_ci interfaceName.c_str(), static_cast<int32_t>(permission), add); 749b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(interfaceName); 750b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 751b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error"); 752b1b8bc3fSopenharmony_ci return -1; 753b1b8bc3fSopenharmony_ci } 754b1b8bc3fSopenharmony_ci 755b1b8bc3fSopenharmony_ci Fwmark fwmark; 756b1b8bc3fSopenharmony_ci fwmark.permission = permission; 757b1b8bc3fSopenharmony_ci 758b1b8bc3fSopenharmony_ci Fwmark mask; 759b1b8bc3fSopenharmony_ci mask.permission = permission; 760b1b8bc3fSopenharmony_ci 761b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 762b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 763b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_CLAT_TUN; 764b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 765b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 766b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 767b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 768b1b8bc3fSopenharmony_ci 769b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo)) { 770b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateRuleInfo failed, err is %{public}d", ret); 771b1b8bc3fSopenharmony_ci return ret; 772b1b8bc3fSopenharmony_ci } 773b1b8bc3fSopenharmony_ci 774b1b8bc3fSopenharmony_ci return 0; 775b1b8bc3fSopenharmony_ci} 776b1b8bc3fSopenharmony_ci 777b1b8bc3fSopenharmony_ciint32_t RouteManager::Init() 778b1b8bc3fSopenharmony_ci{ 779b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("Init"); 780b1b8bc3fSopenharmony_ci // need to call IptablesWrapper's RunCommand function. 781b1b8bc3fSopenharmony_ci std::string commandNew; 782b1b8bc3fSopenharmony_ci commandNew.append(" -t mangle -N "); 783b1b8bc3fSopenharmony_ci commandNew.append(LOCAL_MANGLE_INPUT); 784b1b8bc3fSopenharmony_ci 785b1b8bc3fSopenharmony_ci std::string commandJump; 786b1b8bc3fSopenharmony_ci commandJump.append(" -A INPUT -j "); 787b1b8bc3fSopenharmony_ci commandJump.append(LOCAL_MANGLE_INPUT); 788b1b8bc3fSopenharmony_ci 789b1b8bc3fSopenharmony_ci if (int32_t ret = ClearRules()) { 790b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("ClearRules failed, err is %{public}d", ret); 791b1b8bc3fSopenharmony_ci return ret; 792b1b8bc3fSopenharmony_ci } 793b1b8bc3fSopenharmony_ci 794b1b8bc3fSopenharmony_ci if (access(NETSYS_ROUTE_INIT_DIR_PATH, F_OK) == 0) { 795b1b8bc3fSopenharmony_ci if (int32_t ret = AddLocalNetworkRules()) { 796b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("AddLocalNetworkRules failed, err is %{public}d", ret); 797b1b8bc3fSopenharmony_ci return ret; 798b1b8bc3fSopenharmony_ci } 799b1b8bc3fSopenharmony_ci } else { 800b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddLocalNetworkRules init ok, do not need repeat"); 801b1b8bc3fSopenharmony_ci } 802b1b8bc3fSopenharmony_ci 803b1b8bc3fSopenharmony_ci return 0; 804b1b8bc3fSopenharmony_ci} 805b1b8bc3fSopenharmony_ci 806b1b8bc3fSopenharmony_ciint32_t RouteManager::ClearRules() 807b1b8bc3fSopenharmony_ci{ 808b1b8bc3fSopenharmony_ci return ClearRouteInfo(RTM_GETRULE, 0) >= 0 ? 0 : -1; 809b1b8bc3fSopenharmony_ci} 810b1b8bc3fSopenharmony_ci 811b1b8bc3fSopenharmony_ciint32_t RouteManager::ClearRoutes(const std::string &interfaceName, int32_t netId) 812b1b8bc3fSopenharmony_ci{ 813b1b8bc3fSopenharmony_ci std::lock_guard lock(RouteManager::interfaceToTableLock_); 814b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(interfaceName, netId); 815b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("ClearRoutes--table==:%{public}d", table); 816b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 817b1b8bc3fSopenharmony_ci return -1; 818b1b8bc3fSopenharmony_ci } 819b1b8bc3fSopenharmony_ci int32_t ret = ClearRouteInfo(RTM_GETROUTE, table); 820b1b8bc3fSopenharmony_ci if (ret == 0 && table != ROUTE_INTERNAL_DEFAULT_TABLE) { 821b1b8bc3fSopenharmony_ci interfaceToTable_.erase(interfaceName); 822b1b8bc3fSopenharmony_ci } 823b1b8bc3fSopenharmony_ci 824b1b8bc3fSopenharmony_ci return 0; 825b1b8bc3fSopenharmony_ci} 826b1b8bc3fSopenharmony_ci 827b1b8bc3fSopenharmony_ciint32_t RouteManager::AddLocalNetworkRules() 828b1b8bc3fSopenharmony_ci{ 829b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("AddLocalNetworkRules"); 830b1b8bc3fSopenharmony_ci if (int32_t ret = 831b1b8bc3fSopenharmony_ci UpdateExplicitNetworkRule(LOCAL_NET_ID, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, ADD_CONTROL)) { 832b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret); 833b1b8bc3fSopenharmony_ci return ret; 834b1b8bc3fSopenharmony_ci } 835b1b8bc3fSopenharmony_ci Fwmark fwmark; 836b1b8bc3fSopenharmony_ci fwmark.explicitlySelected = false; 837b1b8bc3fSopenharmony_ci 838b1b8bc3fSopenharmony_ci Fwmark mask; 839b1b8bc3fSopenharmony_ci mask.explicitlySelected = true; 840b1b8bc3fSopenharmony_ci 841b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 842b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = ROUTE_LOCAL_NETWORK_TABLE; 843b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_LOCAL_NETWORK; 844b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 845b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 846b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_NULL; 847b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 848b1b8bc3fSopenharmony_ci 849b1b8bc3fSopenharmony_ci return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo); 850b1b8bc3fSopenharmony_ci} 851b1b8bc3fSopenharmony_ci 852b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdatePhysicalNetwork(uint16_t netId, const std::string &interfaceName, 853b1b8bc3fSopenharmony_ci NetworkPermission permission, bool add) 854b1b8bc3fSopenharmony_ci{ 855b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdatePhysicalNetwork,add===%{public}d", add); 856b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(interfaceName, netId); 857b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 858b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error"); 859b1b8bc3fSopenharmony_ci return -1; 860b1b8bc3fSopenharmony_ci } 861b1b8bc3fSopenharmony_ci 862b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateExplicitNetworkRule(netId, table, permission, add)) { 863b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret); 864b1b8bc3fSopenharmony_ci return ret; 865b1b8bc3fSopenharmony_ci } 866b1b8bc3fSopenharmony_ci 867b1b8bc3fSopenharmony_ci if (int32_t ret = UpdateOutputInterfaceRules(interfaceName, table, permission, add)) { 868b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("UpdateOutputInterfaceRules failed, err is %{public}d", ret); 869b1b8bc3fSopenharmony_ci return ret; 870b1b8bc3fSopenharmony_ci } 871b1b8bc3fSopenharmony_ci 872b1b8bc3fSopenharmony_ci return 0; 873b1b8bc3fSopenharmony_ci} 874b1b8bc3fSopenharmony_ci 875b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateLocalNetwork(uint16_t netId, const std::string &interfaceName, bool add) 876b1b8bc3fSopenharmony_ci{ 877b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateLocalNetwork"); 878b1b8bc3fSopenharmony_ci return UpdateOutputInterfaceRules(interfaceName, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, add); 879b1b8bc3fSopenharmony_ci} 880b1b8bc3fSopenharmony_ci 881b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateIncomingPacketMark(uint16_t netId, const std::string &interfaceName, 882b1b8bc3fSopenharmony_ci NetworkPermission permission, bool add) 883b1b8bc3fSopenharmony_ci{ 884b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateIncomingPacketMark"); 885b1b8bc3fSopenharmony_ci Fwmark fwmark; 886b1b8bc3fSopenharmony_ci fwmark.netId = netId; 887b1b8bc3fSopenharmony_ci fwmark.explicitlySelected = true; 888b1b8bc3fSopenharmony_ci fwmark.protectedFromVpn = true; 889b1b8bc3fSopenharmony_ci fwmark.permission = permission; 890b1b8bc3fSopenharmony_ci const uint32_t mask = ~Fwmark::GetUidBillingMask(); 891b1b8bc3fSopenharmony_ci std::string action = ""; 892b1b8bc3fSopenharmony_ci if (add) { 893b1b8bc3fSopenharmony_ci action = " -A "; 894b1b8bc3fSopenharmony_ci } else { 895b1b8bc3fSopenharmony_ci action = " -D "; 896b1b8bc3fSopenharmony_ci } 897b1b8bc3fSopenharmony_ci std::stringstream ss; 898b1b8bc3fSopenharmony_ci ss << action << LOCAL_MANGLE_INPUT << " -i " << interfaceName << " -j MARK --set-mark 0x" << std::nouppercase 899b1b8bc3fSopenharmony_ci << std::hex << fwmark.intValue << "/0x" << std::nouppercase << std::hex << mask; 900b1b8bc3fSopenharmony_ci // need to call IptablesWrapper's RunCommand function. 901b1b8bc3fSopenharmony_ci 902b1b8bc3fSopenharmony_ci return 0; 903b1b8bc3fSopenharmony_ci} 904b1b8bc3fSopenharmony_ci 905b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateExplicitNetworkRule(uint16_t netId, uint32_t table, NetworkPermission permission, bool add) 906b1b8bc3fSopenharmony_ci{ 907b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateExplicitNetworkRule"); 908b1b8bc3fSopenharmony_ci Fwmark fwmark; 909b1b8bc3fSopenharmony_ci fwmark.netId = netId; 910b1b8bc3fSopenharmony_ci fwmark.explicitlySelected = true; 911b1b8bc3fSopenharmony_ci fwmark.permission = permission; 912b1b8bc3fSopenharmony_ci 913b1b8bc3fSopenharmony_ci Fwmark mask; 914b1b8bc3fSopenharmony_ci mask.netId = FWMARK_NET_ID_MASK; 915b1b8bc3fSopenharmony_ci mask.explicitlySelected = true; 916b1b8bc3fSopenharmony_ci mask.permission = permission; 917b1b8bc3fSopenharmony_ci 918b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 919b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 920b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_EXPLICIT_NETWORK; 921b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 922b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 923b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 924b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 925b1b8bc3fSopenharmony_ci 926b1b8bc3fSopenharmony_ci if (NetManagerStandard::IsInternalNetId(netId)) { 927b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, UID_ALLOW_INTERNAL.first, 928b1b8bc3fSopenharmony_ci UID_ALLOW_INTERNAL.second); 929b1b8bc3fSopenharmony_ci } 930b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo); 931b1b8bc3fSopenharmony_ci} 932b1b8bc3fSopenharmony_ci 933b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateOutputInterfaceRules(const std::string &interfaceName, uint32_t table, 934b1b8bc3fSopenharmony_ci NetworkPermission permission, bool add) 935b1b8bc3fSopenharmony_ci{ 936b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateOutputInterfaceRules"); 937b1b8bc3fSopenharmony_ci Fwmark fwmark; 938b1b8bc3fSopenharmony_ci fwmark.permission = permission; 939b1b8bc3fSopenharmony_ci 940b1b8bc3fSopenharmony_ci Fwmark mask; 941b1b8bc3fSopenharmony_ci mask.permission = permission; 942b1b8bc3fSopenharmony_ci 943b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 944b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 945b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_OUTPUT_INTERFACE; 946b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = fwmark.intValue; 947b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = mask.intValue; 948b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = RULEIIF_LOOPBACK; 949b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = interfaceName; 950b1b8bc3fSopenharmony_ci 951b1b8bc3fSopenharmony_ci return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo); 952b1b8bc3fSopenharmony_ci} 953b1b8bc3fSopenharmony_ci 954b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateSharingNetwork(uint16_t action, const std::string &inputInterface, 955b1b8bc3fSopenharmony_ci const std::string &outputInterface) 956b1b8bc3fSopenharmony_ci{ 957b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateSharingNetwork"); 958b1b8bc3fSopenharmony_ci uint32_t table = FindTableByInterfacename(outputInterface); 959b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 960b1b8bc3fSopenharmony_ci return -1; 961b1b8bc3fSopenharmony_ci } 962b1b8bc3fSopenharmony_ci 963b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 964b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = table; 965b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_SHARING; 966b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 967b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 968b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = inputInterface; 969b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 970b1b8bc3fSopenharmony_ci 971b1b8bc3fSopenharmony_ci return UpdateRuleInfo(action, FR_ACT_TO_TBL, ruleInfo); 972b1b8bc3fSopenharmony_ci} 973b1b8bc3fSopenharmony_ci 974b1b8bc3fSopenharmony_ciint32_t RouteManager::ClearSharingRules(const std::string &inputInterface) 975b1b8bc3fSopenharmony_ci{ 976b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("ClearSharingRules"); 977b1b8bc3fSopenharmony_ci 978b1b8bc3fSopenharmony_ci RuleInfo ruleInfo; 979b1b8bc3fSopenharmony_ci ruleInfo.ruleTable = 0; 980b1b8bc3fSopenharmony_ci ruleInfo.rulePriority = RULE_LEVEL_SHARING; 981b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark = MARK_UNSET; 982b1b8bc3fSopenharmony_ci ruleInfo.ruleMask = MARK_UNSET; 983b1b8bc3fSopenharmony_ci ruleInfo.ruleIif = inputInterface; 984b1b8bc3fSopenharmony_ci ruleInfo.ruleOif = RULEOIF_NULL; 985b1b8bc3fSopenharmony_ci 986b1b8bc3fSopenharmony_ci return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo); 987b1b8bc3fSopenharmony_ci} 988b1b8bc3fSopenharmony_ci 989b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateRuleInfo(uint32_t action, uint8_t ruleType, RuleInfo ruleInfo, uid_t uidStart, uid_t uidEnd) 990b1b8bc3fSopenharmony_ci{ 991b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateRuleInfo"); 992b1b8bc3fSopenharmony_ci if (ruleInfo.rulePriority < 0) { 993b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("invalid IP-rule priority %{public}d", ruleInfo.rulePriority); 994b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 995b1b8bc3fSopenharmony_ci } 996b1b8bc3fSopenharmony_ci 997b1b8bc3fSopenharmony_ci if (ruleInfo.ruleFwmark & ~ruleInfo.ruleMask) { 998b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("mask 0x%{public}x does not select all the bits set in fwmark 0x%{public}x", ruleInfo.ruleMask, 999b1b8bc3fSopenharmony_ci ruleInfo.ruleFwmark); 1000b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 1001b1b8bc3fSopenharmony_ci } 1002b1b8bc3fSopenharmony_ci 1003b1b8bc3fSopenharmony_ci if (ruleInfo.ruleTable == RT_TABLE_UNSPEC && ruleType == FR_ACT_TO_TBL && action != RTM_DELRULE) { 1004b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("RT_TABLE_UNSPEC only allowed when deleting rules"); 1005b1b8bc3fSopenharmony_ci return -ENOTUNIQ; 1006b1b8bc3fSopenharmony_ci } 1007b1b8bc3fSopenharmony_ci 1008b1b8bc3fSopenharmony_ci // The main work is to assemble the structure required for rule. 1009b1b8bc3fSopenharmony_ci for (const uint8_t family : {AF_INET, AF_INET6}) { 1010b1b8bc3fSopenharmony_ci if (SendRuleToKernel(action, family, ruleType, ruleInfo, uidStart, uidEnd) < 0) { 1011b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Update %{public}s rule info failed, action = %{public}d", 1012b1b8bc3fSopenharmony_ci (family == AF_INET) ? "IPv4" : "IPv6", action); 1013b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INTERNAL; 1014b1b8bc3fSopenharmony_ci } 1015b1b8bc3fSopenharmony_ci } 1016b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 1017b1b8bc3fSopenharmony_ci} 1018b1b8bc3fSopenharmony_ci 1019b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateDistributedRule(uint32_t action, uint8_t ruleType, RuleInfo ruleInfo, uid_t uidStart, 1020b1b8bc3fSopenharmony_ci uid_t uidEnd) 1021b1b8bc3fSopenharmony_ci{ 1022b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("UpdateDistributedRule"); 1023b1b8bc3fSopenharmony_ci if (ruleInfo.rulePriority < 0) { 1024b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("invalid IP-rule priority %{public}d", ruleInfo.rulePriority); 1025b1b8bc3fSopenharmony_ci return ROUTEMANAGER_ERROR; 1026b1b8bc3fSopenharmony_ci } 1027b1b8bc3fSopenharmony_ci 1028b1b8bc3fSopenharmony_ci if (ruleInfo.ruleTable == RT_TABLE_UNSPEC && ruleType == FR_ACT_TO_TBL && action != RTM_DELRULE) { 1029b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("RT_TABLE_UNSPEC only allowed when deleting rules"); 1030b1b8bc3fSopenharmony_ci return -ENOTUNIQ; 1031b1b8bc3fSopenharmony_ci } 1032b1b8bc3fSopenharmony_ci 1033b1b8bc3fSopenharmony_ci int32_t family; 1034b1b8bc3fSopenharmony_ci if (!ruleInfo.ruleDstIp.empty() && strchr(ruleInfo.ruleDstIp.c_str(), ':')) { 1035b1b8bc3fSopenharmony_ci family = AF_INET6; 1036b1b8bc3fSopenharmony_ci } else { 1037b1b8bc3fSopenharmony_ci family = AF_INET; 1038b1b8bc3fSopenharmony_ci } 1039b1b8bc3fSopenharmony_ci 1040b1b8bc3fSopenharmony_ci if (SendRuleToKernelEx(action, family, ruleType, ruleInfo, uidStart, uidEnd) < 0) { 1041b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("Update %{public}s rule info failed, action = %{public}d", 1042b1b8bc3fSopenharmony_ci (family == AF_INET) ? "IPv4" : "IPv6", action); 1043b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_INTERNAL; 1044b1b8bc3fSopenharmony_ci } 1045b1b8bc3fSopenharmony_ci 1046b1b8bc3fSopenharmony_ci return NETMANAGER_SUCCESS; 1047b1b8bc3fSopenharmony_ci} 1048b1b8bc3fSopenharmony_ci 1049b1b8bc3fSopenharmony_ciint32_t RouteManager::SendRuleToKernel(uint32_t action, uint8_t family, uint8_t ruleType, RuleInfo ruleInfo, 1050b1b8bc3fSopenharmony_ci uid_t uidStart, uid_t uidEnd) 1051b1b8bc3fSopenharmony_ci{ 1052b1b8bc3fSopenharmony_ci struct fib_rule_hdr msg = {0}; 1053b1b8bc3fSopenharmony_ci msg.action = ruleType; 1054b1b8bc3fSopenharmony_ci msg.family = family; 1055b1b8bc3fSopenharmony_ci uint16_t ruleFlag = (action == RTM_NEWRULE) ? NLM_F_CREATE : NLM_F_EXCL; 1056b1b8bc3fSopenharmony_ci NetlinkMsg nlmsg(ruleFlag, NETLINK_MAX_LEN, getpid()); 1057b1b8bc3fSopenharmony_ci nlmsg.AddRule(action, msg); 1058b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_PRIORITY, ruleInfo.rulePriority)) { 1059b1b8bc3fSopenharmony_ci return ret; 1060b1b8bc3fSopenharmony_ci } 1061b1b8bc3fSopenharmony_ci if (ruleInfo.ruleTable != RT_TABLE_UNSPEC) { 1062b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_TABLE, ruleInfo.ruleTable)) { 1063b1b8bc3fSopenharmony_ci return ret; 1064b1b8bc3fSopenharmony_ci } 1065b1b8bc3fSopenharmony_ci } 1066b1b8bc3fSopenharmony_ci if (ruleInfo.ruleMask != 0) { 1067b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_FWMARK, ruleInfo.ruleFwmark)) { 1068b1b8bc3fSopenharmony_ci return ret; 1069b1b8bc3fSopenharmony_ci } 1070b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_FWMASK, ruleInfo.ruleMask)) { 1071b1b8bc3fSopenharmony_ci return ret; 1072b1b8bc3fSopenharmony_ci } 1073b1b8bc3fSopenharmony_ci } 1074b1b8bc3fSopenharmony_ci if ((uidStart != INVALID_UID) && (uidEnd != INVALID_UID)) { 1075b1b8bc3fSopenharmony_ci FibRuleUidRange uidRange = {uidStart, uidEnd}; 1076b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(FRA_UID_RANGE, &uidRange, sizeof(uidRange))) { 1077b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("SendRuleToKernel FRA_UID_RANGE is error."); 1078b1b8bc3fSopenharmony_ci return ret; 1079b1b8bc3fSopenharmony_ci } 1080b1b8bc3fSopenharmony_ci } 1081b1b8bc3fSopenharmony_ci if (ruleInfo.ruleIif != RULEIIF_NULL) { 1082b1b8bc3fSopenharmony_ci char ruleIifName[IFNAMSIZ] = {0}; 1083b1b8bc3fSopenharmony_ci size_t ruleIifLength = strlcpy(ruleIifName, ruleInfo.ruleIif.c_str(), IFNAMSIZ) + 1; 1084b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(FRA_IIFNAME, ruleIifName, ruleIifLength)) { 1085b1b8bc3fSopenharmony_ci return ret; 1086b1b8bc3fSopenharmony_ci } 1087b1b8bc3fSopenharmony_ci } 1088b1b8bc3fSopenharmony_ci if (ruleInfo.ruleOif != RULEOIF_NULL) { 1089b1b8bc3fSopenharmony_ci char ruleOifName[IFNAMSIZ] = {0}; 1090b1b8bc3fSopenharmony_ci size_t ruleOifLength = strlcpy(ruleOifName, ruleInfo.ruleOif.c_str(), IFNAMSIZ) + 1; 1091b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(FRA_OIFNAME, ruleOifName, ruleOifLength)) { 1092b1b8bc3fSopenharmony_ci return ret; 1093b1b8bc3fSopenharmony_ci } 1094b1b8bc3fSopenharmony_ci } 1095b1b8bc3fSopenharmony_ci 1096b1b8bc3fSopenharmony_ci return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage()); 1097b1b8bc3fSopenharmony_ci} 1098b1b8bc3fSopenharmony_ci 1099b1b8bc3fSopenharmony_ciint32_t RouteManager::SendRuleToKernelEx(uint32_t action, uint8_t family, uint8_t ruleType, RuleInfo ruleInfo, 1100b1b8bc3fSopenharmony_ci uid_t uidStart, uid_t uidEnd) 1101b1b8bc3fSopenharmony_ci{ 1102b1b8bc3fSopenharmony_ci struct fib_rule_hdr msg = {0}; 1103b1b8bc3fSopenharmony_ci msg.action = ruleType; 1104b1b8bc3fSopenharmony_ci msg.family = family; 1105b1b8bc3fSopenharmony_ci if (ruleInfo.ruleDstIp != RULEIP_NULL && family == AF_INET) { 1106b1b8bc3fSopenharmony_ci msg.dst_len = BIT_32_LEN; 1107b1b8bc3fSopenharmony_ci } 1108b1b8bc3fSopenharmony_ci uint16_t ruleFlag = (action == RTM_NEWRULE) ? NLM_F_CREATE : NLM_F_EXCL; 1109b1b8bc3fSopenharmony_ci NetlinkMsg nlmsg(ruleFlag, NETLINK_MAX_LEN, getpid()); 1110b1b8bc3fSopenharmony_ci nlmsg.AddRule(action, msg); 1111b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_PRIORITY, ruleInfo.rulePriority)) { 1112b1b8bc3fSopenharmony_ci return ret; 1113b1b8bc3fSopenharmony_ci } 1114b1b8bc3fSopenharmony_ci if (ruleInfo.ruleTable != RT_TABLE_UNSPEC) { 1115b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_TABLE, ruleInfo.ruleTable)) { 1116b1b8bc3fSopenharmony_ci return ret; 1117b1b8bc3fSopenharmony_ci } 1118b1b8bc3fSopenharmony_ci } 1119b1b8bc3fSopenharmony_ci if (ruleInfo.ruleMask != 0) { 1120b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_FWMARK, ruleInfo.ruleFwmark)) { 1121b1b8bc3fSopenharmony_ci return ret; 1122b1b8bc3fSopenharmony_ci } 1123b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(FRA_FWMASK, ruleInfo.ruleMask)) { 1124b1b8bc3fSopenharmony_ci return ret; 1125b1b8bc3fSopenharmony_ci } 1126b1b8bc3fSopenharmony_ci } 1127b1b8bc3fSopenharmony_ci if (ruleInfo.ruleIif != RULEIIF_NULL) { 1128b1b8bc3fSopenharmony_ci char ruleIifName[IFNAMSIZ] = {0}; 1129b1b8bc3fSopenharmony_ci size_t ruleIifLength = strlcpy(ruleIifName, ruleInfo.ruleIif.c_str(), IFNAMSIZ) + 1; 1130b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(FRA_IIFNAME, ruleIifName, ruleIifLength)) { 1131b1b8bc3fSopenharmony_ci return ret; 1132b1b8bc3fSopenharmony_ci } 1133b1b8bc3fSopenharmony_ci } 1134b1b8bc3fSopenharmony_ci if (ruleInfo.ruleDstIp != RULEIP_NULL) { 1135b1b8bc3fSopenharmony_ci InetAddr dst = {0}; 1136b1b8bc3fSopenharmony_ci if (ReadAddrGw(ruleInfo.ruleDstIp, &dst) <= 0) { 1137b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("dest addr parse failed."); 1138b1b8bc3fSopenharmony_ci return NETMANAGER_ERR_OPERATION_FAILED; 1139b1b8bc3fSopenharmony_ci } 1140b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(FRA_DST, dst.data, dst.bitlen / BYTE_ALIGNMENT)) { 1141b1b8bc3fSopenharmony_ci return ret; 1142b1b8bc3fSopenharmony_ci } 1143b1b8bc3fSopenharmony_ci } 1144b1b8bc3fSopenharmony_ci return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage()); 1145b1b8bc3fSopenharmony_ci} 1146b1b8bc3fSopenharmony_ci 1147b1b8bc3fSopenharmony_ciint32_t RouteManager::UpdateRouteRule(uint16_t action, uint16_t flags, RouteInfo routeInfo) 1148b1b8bc3fSopenharmony_ci{ 1149b1b8bc3fSopenharmony_ci NETNATIVE_LOG_D("UpdateRouteRule"); 1150b1b8bc3fSopenharmony_ci RouteInfo routeInfoModify = routeInfo; 1151b1b8bc3fSopenharmony_ci // The main work is to assemble the structure required for route. 1152b1b8bc3fSopenharmony_ci struct rtmsg msg; 1153b1b8bc3fSopenharmony_ci (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg)); 1154b1b8bc3fSopenharmony_ci msg.rtm_family = AF_INET; 1155b1b8bc3fSopenharmony_ci msg.rtm_dst_len = BIT_32_LEN; 1156b1b8bc3fSopenharmony_ci msg.rtm_protocol = RTPROT_STATIC; 1157b1b8bc3fSopenharmony_ci msg.rtm_scope = RT_SCOPE_UNIVERSE; 1158b1b8bc3fSopenharmony_ci msg.rtm_type = RTN_UNICAST; 1159b1b8bc3fSopenharmony_ci msg.rtm_table = RT_TABLE_UNSPEC; 1160b1b8bc3fSopenharmony_ci 1161b1b8bc3fSopenharmony_ci uint32_t index = 0; 1162b1b8bc3fSopenharmony_ci if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "unreachable")) { 1163b1b8bc3fSopenharmony_ci msg.rtm_type = RTN_UNREACHABLE; 1164b1b8bc3fSopenharmony_ci routeInfoModify.routeInterfaceName = ""; 1165b1b8bc3fSopenharmony_ci routeInfoModify.routeNextHop = ""; 1166b1b8bc3fSopenharmony_ci } else if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "throw")) { 1167b1b8bc3fSopenharmony_ci msg.rtm_type = RTN_THROW; 1168b1b8bc3fSopenharmony_ci routeInfoModify.routeInterfaceName = ""; 1169b1b8bc3fSopenharmony_ci routeInfoModify.routeNextHop = ""; 1170b1b8bc3fSopenharmony_ci } else { 1171b1b8bc3fSopenharmony_ci index = if_nametoindex(routeInfo.routeInterfaceName.c_str()); 1172b1b8bc3fSopenharmony_ci } 1173b1b8bc3fSopenharmony_ci 1174b1b8bc3fSopenharmony_ci int32_t ret = SendRouteToKernel(action, flags, msg, routeInfoModify, index); 1175b1b8bc3fSopenharmony_ci if (ret < 0) { 1176b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("SendNetlinkMsgToKernel Error ret = %{public}d", ret); 1177b1b8bc3fSopenharmony_ci return ret; 1178b1b8bc3fSopenharmony_ci } 1179b1b8bc3fSopenharmony_ci 1180b1b8bc3fSopenharmony_ci return 0; 1181b1b8bc3fSopenharmony_ci} 1182b1b8bc3fSopenharmony_ci 1183b1b8bc3fSopenharmony_ciint32_t RouteManager::SendRouteToKernel(uint16_t action, uint16_t routeFlag, rtmsg msg, RouteInfo routeInfo, 1184b1b8bc3fSopenharmony_ci uint32_t index) 1185b1b8bc3fSopenharmony_ci{ 1186b1b8bc3fSopenharmony_ci InetAddr dst; 1187b1b8bc3fSopenharmony_ci int32_t readAddrResult = ReadAddr(routeInfo.routeDestinationName, &dst); 1188b1b8bc3fSopenharmony_ci if (readAddrResult != 1) { 1189b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("dest parse failed:%{public}d", readAddrResult); 1190b1b8bc3fSopenharmony_ci return -1; 1191b1b8bc3fSopenharmony_ci } 1192b1b8bc3fSopenharmony_ci msg.rtm_family = static_cast<uint8_t>(dst.family); 1193b1b8bc3fSopenharmony_ci msg.rtm_dst_len = static_cast<uint8_t>(dst.prefixlen); 1194b1b8bc3fSopenharmony_ci if (dst.family == AF_INET) { 1195b1b8bc3fSopenharmony_ci msg.rtm_scope = RT_SCOPE_LINK; 1196b1b8bc3fSopenharmony_ci } else if (dst.family == AF_INET6) { 1197b1b8bc3fSopenharmony_ci msg.rtm_scope = RT_SCOPE_UNIVERSE; 1198b1b8bc3fSopenharmony_ci } 1199b1b8bc3fSopenharmony_ci 1200b1b8bc3fSopenharmony_ci InetAddr gw = {0}; 1201b1b8bc3fSopenharmony_ci if (!routeInfo.routeNextHop.empty() && ReadAddrGw(routeInfo.routeNextHop, &gw) <= 0) { 1202b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("gw parse failed:%{public}d", readAddrResult); 1203b1b8bc3fSopenharmony_ci return -1; 1204b1b8bc3fSopenharmony_ci } 1205b1b8bc3fSopenharmony_ci if (gw.bitlen != 0) { 1206b1b8bc3fSopenharmony_ci msg.rtm_scope = RT_SCOPE_UNIVERSE; 1207b1b8bc3fSopenharmony_ci msg.rtm_family = static_cast<uint8_t>(gw.family); 1208b1b8bc3fSopenharmony_ci } 1209b1b8bc3fSopenharmony_ci NetlinkMsg nlmsg(routeFlag, NETLINK_MAX_LEN, getpid()); 1210b1b8bc3fSopenharmony_ci nlmsg.AddRoute(action, msg); 1211b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(RTA_TABLE, routeInfo.routeTable)) { 1212b1b8bc3fSopenharmony_ci return ret; 1213b1b8bc3fSopenharmony_ci } 1214b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(RTA_DST, dst.data, dst.bitlen / BYTE_ALIGNMENT)) { 1215b1b8bc3fSopenharmony_ci return ret; 1216b1b8bc3fSopenharmony_ci } 1217b1b8bc3fSopenharmony_ci if (!routeInfo.routeNextHop.empty()) { 1218b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr(RTA_GATEWAY, gw.data, gw.bitlen / BYTE_ALIGNMENT)) { 1219b1b8bc3fSopenharmony_ci return ret; 1220b1b8bc3fSopenharmony_ci } 1221b1b8bc3fSopenharmony_ci } 1222b1b8bc3fSopenharmony_ci if (!routeInfo.routeInterfaceName.empty()) { 1223b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("index is :%{public}d", index); 1224b1b8bc3fSopenharmony_ci if (int32_t ret = nlmsg.AddAttr32(RTA_OIF, index)) { 1225b1b8bc3fSopenharmony_ci return ret; 1226b1b8bc3fSopenharmony_ci } 1227b1b8bc3fSopenharmony_ci } 1228b1b8bc3fSopenharmony_ci 1229b1b8bc3fSopenharmony_ci return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage()); 1230b1b8bc3fSopenharmony_ci} 1231b1b8bc3fSopenharmony_ci 1232b1b8bc3fSopenharmony_ciuint32_t RouteManager::FindTableByInterfacename(const std::string &interfaceName, int32_t netId) 1233b1b8bc3fSopenharmony_ci{ 1234b1b8bc3fSopenharmony_ci NETNATIVE_LOGI("FindTableByInterfacename netId %{public}d", netId); 1235b1b8bc3fSopenharmony_ci if (NetManagerStandard::IsInternalNetId(netId)) { 1236b1b8bc3fSopenharmony_ci return ROUTE_INTERNAL_DEFAULT_TABLE; 1237b1b8bc3fSopenharmony_ci } 1238b1b8bc3fSopenharmony_ci auto iter = interfaceToTable_.find(interfaceName); 1239b1b8bc3fSopenharmony_ci if (iter != interfaceToTable_.end()) { 1240b1b8bc3fSopenharmony_ci return iter->second; 1241b1b8bc3fSopenharmony_ci } 1242b1b8bc3fSopenharmony_ci 1243b1b8bc3fSopenharmony_ci uint32_t table = if_nametoindex(interfaceName.c_str()); 1244b1b8bc3fSopenharmony_ci if (table == 0) { 1245b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("RouteManager cannot find interface %{public}s", interfaceName.c_str()); 1246b1b8bc3fSopenharmony_ci return RT_TABLE_UNSPEC; 1247b1b8bc3fSopenharmony_ci } 1248b1b8bc3fSopenharmony_ci table += THOUSAND_LEN; 1249b1b8bc3fSopenharmony_ci interfaceToTable_[interfaceName] = table; 1250b1b8bc3fSopenharmony_ci return table; 1251b1b8bc3fSopenharmony_ci} 1252b1b8bc3fSopenharmony_ci 1253b1b8bc3fSopenharmony_ciuint32_t RouteManager::GetRouteTableFromType(TableType tableType, const std::string &interfaceName) 1254b1b8bc3fSopenharmony_ci{ 1255b1b8bc3fSopenharmony_ci switch (tableType) { 1256b1b8bc3fSopenharmony_ci case RouteManager::INTERFACE: 1257b1b8bc3fSopenharmony_ci return FindTableByInterfacename(interfaceName); 1258b1b8bc3fSopenharmony_ci case RouteManager::LOCAL_NETWORK: 1259b1b8bc3fSopenharmony_ci return ROUTE_LOCAL_NETWORK_TABLE; 1260b1b8bc3fSopenharmony_ci case RouteManager::VPN_NETWORK: 1261b1b8bc3fSopenharmony_ci return ROUTE_VPN_NETWORK_TABLE; 1262b1b8bc3fSopenharmony_ci case RouteManager::INTERNAL_DEFAULT: 1263b1b8bc3fSopenharmony_ci return ROUTE_INTERNAL_DEFAULT_TABLE; 1264b1b8bc3fSopenharmony_ci default: 1265b1b8bc3fSopenharmony_ci NETNATIVE_LOGE("tableType [%{tableType}d] is error", tableType); 1266b1b8bc3fSopenharmony_ci return RT_TABLE_UNSPEC; 1267b1b8bc3fSopenharmony_ci } 1268b1b8bc3fSopenharmony_ci} 1269b1b8bc3fSopenharmony_ci 1270b1b8bc3fSopenharmony_ciint32_t RouteManager::SetRouteInfo(TableType tableType, const std::string &interfaceName, 1271b1b8bc3fSopenharmony_ci const std::string &destinationName, const std::string &nextHop, RouteInfo &routeInfo) 1272b1b8bc3fSopenharmony_ci{ 1273b1b8bc3fSopenharmony_ci uint32_t table = GetRouteTableFromType(tableType, interfaceName); 1274b1b8bc3fSopenharmony_ci if (table == RT_TABLE_UNSPEC) { 1275b1b8bc3fSopenharmony_ci return -1; 1276b1b8bc3fSopenharmony_ci } 1277b1b8bc3fSopenharmony_ci 1278b1b8bc3fSopenharmony_ci routeInfo.routeTable = table; 1279b1b8bc3fSopenharmony_ci routeInfo.routeInterfaceName = interfaceName; 1280b1b8bc3fSopenharmony_ci routeInfo.routeDestinationName = destinationName; 1281b1b8bc3fSopenharmony_ci routeInfo.routeNextHop = nextHop; 1282b1b8bc3fSopenharmony_ci return 0; 1283b1b8bc3fSopenharmony_ci} 1284b1b8bc3fSopenharmony_ci} // namespace nmd 1285b1b8bc3fSopenharmony_ci} // namespace OHOS 1286