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