1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <arpa/inet.h>
17 #include <cstdint>
18 #include <cstring>
19 #include <iostream>
20 #include <linux/fib_rules.h>
21 #include <linux/netlink.h>
22 #include <linux/rtnetlink.h>
23 #include <map>
24 #include <mutex>
25 #include <net/if.h>
26 #include <netlink_socket.h>
27 #include <sstream>
28 #include <sys/ioctl.h>
29 #include <sys/socket.h>
30 #include <sys/uio.h>
31 #include <unistd.h>
32 
33 #include "fwmark.h"
34 #include "net_manager_constants.h"
35 #include "netlink_manager.h"
36 #include "netlink_msg.h"
37 #include "netmanager_base_common_utils.h"
38 #include "netnative_log_wrapper.h"
39 #include "securec.h"
40 
41 #include "route_manager.h"
42 
43 using namespace OHOS::NetManagerStandard;
44 using namespace OHOS::NetManagerStandard::CommonUtils;
45 namespace OHOS {
46 namespace nmd {
47 namespace {
48 constexpr int32_t RULE_LEVEL_CLAT_TUN = 8000;
49 constexpr int32_t RULE_LEVEL_VPN_OUTPUT_TO_LOCAL = 9000;
50 constexpr int32_t RULE_LEVEL_SECURE_VPN = 10000;
51 constexpr int32_t RULE_LEVEL_VNIC_NETWORK = 10500;
52 constexpr int32_t RULE_LEVEL_EXPLICIT_NETWORK = 11000;
53 constexpr int32_t RULE_LEVEL_OUTPUT_IFACE_VPN = 11500;
54 constexpr int32_t RULE_LEVEL_OUTPUT_INTERFACE = 12000;
55 constexpr int32_t RULE_LEVEL_LOCAL_NETWORK = 13000;
56 constexpr int32_t RULE_LEVEL_SHARING = 14000;
57 constexpr int32_t RULE_LEVEL_DEFAULT = 16000;
58 constexpr uint32_t ROUTE_VNIC_TABLE = 97;
59 constexpr uint32_t ROUTE_VPN_NETWORK_TABLE = 98;
60 constexpr uint32_t ROUTE_LOCAL_NETWORK_TABLE = 99;
61 constexpr uint32_t ROUTE_INTERNAL_DEFAULT_TABLE = 1;
62 constexpr uint32_t OUTPUT_MAX = 128;
63 constexpr uint32_t BIT_32_LEN = 32;
64 constexpr uint32_t BIT_MAX_LEN = 255;
65 constexpr uint32_t DECIMAL_DIGITAL = 10;
66 constexpr uint32_t BYTE_ALIGNMENT = 8;
67 constexpr uint32_t THOUSAND_LEN = 100;
68 constexpr uint16_t LOCAL_NET_ID = 99;
69 constexpr uint16_t NETID_UNSET = 0;
70 constexpr uint32_t MARK_UNSET = 0;
71 constexpr uid_t UID_ROOT = 0;
72 constexpr std::pair<uid_t, uid_t> UID_ALLOW_INTERNAL = {7023, 7023};
73 constexpr uint32_t ROUTEMANAGER_SUCCESS = 0;
74 constexpr uint32_t ROUTEMANAGER_ERROR = -1;
75 constexpr bool ADD_CONTROL = true;
76 constexpr bool DEL_CONTROL = false;
77 const std::string RULEIIF_LOOPBACK = "lo";
78 const std::string RULEIIF_NULL = "";
79 const std::string RULEOIF_NULL = "";
80 const std::string LOCAL_MANGLE_INPUT = "routectrl_mangle_INPUT";
81 constexpr const char *NETSYS_ROUTE_INIT_DIR_PATH = "/data/service/el1/public/netmanager/route";
82 
83 struct FibRuleUidRange {
84     __u32 start;
85     __u32 end;
86 };
87 } // namespace
88 
89 std::mutex RouteManager::interfaceToTableLock_;
90 std::map<std::string, uint32_t> RouteManager::interfaceToTable_;
91 
RouteManager()92 RouteManager::RouteManager()
93 {
94     Init();
95 }
96 
UpdateVnicRoute(const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop,bool add)97 int32_t RouteManager::UpdateVnicRoute(const std::string &interfaceName, const std::string &destinationName,
98                                       const std::string &nextHop, bool add)
99 {
100     NETNATIVE_LOGI(
101         "VnicChangeRoute,interfaceName:%{public}s,destination:%{public}s, nextHop:%{public}s, add:%{public}d ",
102         interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str(), add);
103 
104     RouteInfo routeInfo;
105     routeInfo.routeTable = ROUTE_VNIC_TABLE;
106     routeInfo.routeInterfaceName = interfaceName;
107     routeInfo.routeDestinationName = destinationName;
108     routeInfo.routeNextHop = nextHop;
109     uint16_t flags = add ? (NLM_F_CREATE | NLM_F_EXCL) : NLM_F_EXCL;
110     uint16_t action = add ? RTM_NEWROUTE : RTM_DELROUTE;
111 
112     return UpdateRouteRule(action, flags, routeInfo);
113 }
114 
AddRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)115 int32_t RouteManager::AddRoute(TableType tableType, const std::string &interfaceName,
116                                const std::string &destinationName, const std::string &nextHop)
117 {
118     NETNATIVE_LOGI("AddRoute,interfaceName:%{public}s,destination:%{public}s, nextHop:%{public}s",
119                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
120 
121     // This is a user-defined structure used to integrate the information required for setting up routes.
122     RouteInfo routeInfo;
123     if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) {
124         return -1;
125     }
126 
127     return UpdateRouteRule(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, routeInfo);
128 }
129 
RemoveRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)130 int32_t RouteManager::RemoveRoute(TableType tableType, const std::string &interfaceName,
131                                   const std::string &destinationName, const std::string &nextHop)
132 {
133     NETNATIVE_LOGI("RemoveRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s",
134                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
135 
136     RouteInfo routeInfo;
137     if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) {
138         return -1;
139     }
140     return UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo);
141 }
142 
UpdateRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)143 int32_t RouteManager::UpdateRoute(TableType tableType, const std::string &interfaceName,
144                                   const std::string &destinationName, const std::string &nextHop)
145 {
146     NETNATIVE_LOGI("UpdateRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s",
147                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
148 
149     RouteInfo routeInfo;
150     if (SetRouteInfo(tableType, interfaceName, destinationName, nextHop, routeInfo) != 0) {
151         return -1;
152     }
153     return UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo);
154 }
155 
AddInterfaceToDefaultNetwork(const std::string & interfaceName,NetworkPermission permission)156 int32_t RouteManager::AddInterfaceToDefaultNetwork(const std::string &interfaceName, NetworkPermission permission)
157 {
158     NETNATIVE_LOGI("AddInterfaceToDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(),
159                    permission);
160     uint32_t table = FindTableByInterfacename(interfaceName);
161     if (table == RT_TABLE_UNSPEC) {
162         return -1;
163     }
164     Fwmark fwmark;
165     fwmark.netId = NETID_UNSET;
166     fwmark.permission = permission;
167 
168     Fwmark mask;
169     mask.netId = FWMARK_NET_ID_MASK;
170     mask.permission = permission;
171 
172     // This is a user-defined structure used to integrate the information required for setting up rules.
173     RuleInfo ruleInfo;
174     ruleInfo.ruleTable = table;
175     ruleInfo.rulePriority = RULE_LEVEL_DEFAULT;
176     ruleInfo.ruleFwmark = fwmark.intValue;
177     ruleInfo.ruleMask = mask.intValue;
178     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
179     ruleInfo.ruleOif = RULEOIF_NULL;
180     return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo);
181 }
182 
RemoveInterfaceFromDefaultNetwork(const std::string & interfaceName,NetworkPermission permission)183 int32_t RouteManager::RemoveInterfaceFromDefaultNetwork(const std::string &interfaceName, NetworkPermission permission)
184 {
185     NETNATIVE_LOGI("RemoveInterfaceFromDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(),
186                    permission);
187     uint32_t table = FindTableByInterfacename(interfaceName);
188     if (table == RT_TABLE_UNSPEC) {
189         return -1;
190     }
191 
192     Fwmark fwmark;
193     fwmark.netId = NETID_UNSET;
194     fwmark.permission = permission;
195 
196     Fwmark mask;
197     mask.netId = FWMARK_NET_ID_MASK;
198     mask.permission = permission;
199 
200     RuleInfo ruleInfo;
201     ruleInfo.ruleTable = table;
202     ruleInfo.rulePriority = RULE_LEVEL_DEFAULT;
203     ruleInfo.ruleFwmark = fwmark.intValue;
204     ruleInfo.ruleMask = mask.intValue;
205     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
206     ruleInfo.ruleOif = RULEOIF_NULL;
207     return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
208 }
209 
AddInterfaceToPhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission)210 int32_t RouteManager::AddInterfaceToPhysicalNetwork(uint16_t netId, const std::string &interfaceName,
211                                                     NetworkPermission permission)
212 {
213     NETNATIVE_LOGI("AddInterfaceToPhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;",
214                    netId, interfaceName.c_str(), permission);
215     return UpdatePhysicalNetwork(netId, interfaceName, permission, ADD_CONTROL);
216 }
217 
RemoveInterfaceFromPhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission)218 int32_t RouteManager::RemoveInterfaceFromPhysicalNetwork(uint16_t netId, const std::string &interfaceName,
219                                                          NetworkPermission permission)
220 {
221     NETNATIVE_LOGI("RemoveInterfacePhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;",
222                    netId, interfaceName.c_str(), permission);
223     if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, permission, DEL_CONTROL)) {
224         NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret);
225         return ret;
226     }
227     if (int32_t ret = ClearRoutes(interfaceName, netId)) {
228         NETNATIVE_LOGE("ClearRoutes err, error is %{public}d", ret);
229         return ret;
230     }
231     if (NetManagerStandard::IsInternalNetId(netId)) {
232         NETNATIVE_LOGI("InternalNetId skip");
233         return 0;
234     }
235     if (int32_t ret = ClearSharingRules(interfaceName)) {
236         NETNATIVE_LOGE("ClearSharingRules err, error is %{public}d", ret);
237         return ret;
238     }
239 
240     return 0;
241 }
242 
ModifyPhysicalNetworkPermission(uint16_t netId,const std::string & interfaceName,NetworkPermission oldPermission,NetworkPermission newPermission)243 int32_t RouteManager::ModifyPhysicalNetworkPermission(uint16_t netId, const std::string &interfaceName,
244                                                       NetworkPermission oldPermission, NetworkPermission newPermission)
245 {
246     NETNATIVE_LOGI("ModifyPhysicalNetworkPermission, %{public}s", interfaceName.c_str());
247     if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, newPermission, ADD_CONTROL)) {
248         NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret);
249         return ret;
250     }
251 
252     return UpdatePhysicalNetwork(netId, interfaceName, newPermission, DEL_CONTROL);
253 }
254 
AddInterfaceToVirtualNetwork(int32_t netId,const std::string & interfaceName)255 int32_t RouteManager::AddInterfaceToVirtualNetwork(int32_t netId, const std::string &interfaceName)
256 {
257     return ModifyVirtualNetBasedRules(netId, interfaceName, true);
258 }
259 
RemoveInterfaceFromVirtualNetwork(int32_t netId,const std::string & interfaceName)260 int32_t RouteManager::RemoveInterfaceFromVirtualNetwork(int32_t netId, const std::string &interfaceName)
261 {
262     if (ModifyVirtualNetBasedRules(netId, interfaceName, false) != ROUTEMANAGER_SUCCESS) {
263         return ROUTEMANAGER_ERROR;
264     }
265     return ClearRouteInfo(RTM_GETROUTE, ROUTE_VPN_NETWORK_TABLE);
266 }
267 
ModifyVirtualNetBasedRules(int32_t netId,const std::string & ifaceName,bool add)268 int32_t RouteManager::ModifyVirtualNetBasedRules(int32_t netId, const std::string &ifaceName, bool add)
269 {
270     NETNATIVE_LOGI("ModifyVirtualNetBasedRules,add===%{public}d", add);
271     uint32_t table = GetRouteTableFromType(RouteManager::VPN_NETWORK, ifaceName);
272     if (table == RT_TABLE_UNSPEC) {
273         NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error");
274         return ROUTEMANAGER_ERROR;
275     }
276 
277     // If the rule fails to be added, continue to execute the next rule
278     int32_t ret = UpdateVpnOutputToLocalRule(ifaceName, add);
279     ret += UpdateVpnSystemPermissionRule(netId, table, add);
280     ret += UpdateExplicitNetworkRuleWithUid(netId, table, PERMISSION_NONE, UID_ROOT, UID_ROOT, add);
281     return ret;
282 }
283 
UpdateVpnOutputToLocalRule(const std::string & interfaceName,bool add)284 int32_t RouteManager::UpdateVpnOutputToLocalRule(const std::string &interfaceName, bool add)
285 {
286     RuleInfo ruleInfo;
287     ruleInfo.ruleTable = ROUTE_LOCAL_NETWORK_TABLE;
288     ruleInfo.rulePriority = RULE_LEVEL_VPN_OUTPUT_TO_LOCAL;
289     ruleInfo.ruleFwmark = MARK_UNSET;
290     ruleInfo.ruleMask = MARK_UNSET;
291     if (interfaceName.find("vpn") == std::string::npos) {
292         ruleInfo.ruleIif = interfaceName;
293     }
294     ruleInfo.ruleOif = RULEOIF_NULL;
295 
296     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID);
297 }
298 
UpdateVpnSystemPermissionRule(int32_t netId,uint32_t table,bool add)299 int32_t RouteManager::UpdateVpnSystemPermissionRule(int32_t netId, uint32_t table, bool add)
300 {
301     Fwmark fwmark;
302     fwmark.netId = netId;
303     NetworkPermission permission = NetworkPermission::PERMISSION_SYSTEM;
304     fwmark.permission = permission;
305 
306     Fwmark mask;
307     mask.netId = FWMARK_NET_ID_MASK;
308     mask.permission = permission;
309 
310     RuleInfo ruleInfo;
311     ruleInfo.ruleTable = table;
312     ruleInfo.rulePriority = RULE_LEVEL_SECURE_VPN;
313     ruleInfo.ruleFwmark = fwmark.intValue;
314     ruleInfo.ruleMask = mask.intValue;
315     ruleInfo.ruleIif = RULEIIF_NULL;
316     ruleInfo.ruleOif = RULEOIF_NULL;
317 
318     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, INVALID_UID, INVALID_UID);
319 }
320 
AddUsersToVirtualNetwork(int32_t netId,const std::string & interfaceName,const std::vector<NetManagerStandard::UidRange> & uidRanges)321 int32_t RouteManager::AddUsersToVirtualNetwork(int32_t netId, const std::string &interfaceName,
322                                                const std::vector<NetManagerStandard::UidRange> &uidRanges)
323 {
324     return UpdateVirtualNetwork(netId, interfaceName, uidRanges, true);
325 }
326 
RemoveUsersFromVirtualNetwork(int32_t netId,const std::string & interfaceName,const std::vector<NetManagerStandard::UidRange> & uidRanges)327 int32_t RouteManager::RemoveUsersFromVirtualNetwork(int32_t netId, const std::string &interfaceName,
328                                                     const std::vector<NetManagerStandard::UidRange> &uidRanges)
329 {
330     return UpdateVirtualNetwork(netId, interfaceName, uidRanges, false);
331 }
332 
UpdateVirtualNetwork(int32_t netId,const std::string & interfaceName,const std::vector<NetManagerStandard::UidRange> & uidRanges,bool add)333 int32_t RouteManager::UpdateVirtualNetwork(int32_t netId, const std::string &interfaceName,
334                                            const std::vector<NetManagerStandard::UidRange> &uidRanges, bool add)
335 {
336     NETNATIVE_LOGI("UpdateVirtualNetwork, add == %{public}d", add);
337     uint32_t table = GetRouteTableFromType(RouteManager::VPN_NETWORK, interfaceName);
338     if (table == RT_TABLE_UNSPEC) {
339         NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error");
340         return ROUTEMANAGER_ERROR;
341     }
342     int32_t ret = ROUTEMANAGER_SUCCESS;
343     for (auto range : uidRanges) {
344         // If the rule fails to be added, continue to execute the next rule
345         ret += UpdateVpnUidRangeRule(table, range.begin_, range.end_, add);
346         ret += UpdateExplicitNetworkRuleWithUid(netId, table, PERMISSION_NONE, range.begin_, range.end_, add);
347         ret += UpdateOutputInterfaceRulesWithUid(interfaceName, table, PERMISSION_NONE, range.begin_, range.end_, add);
348     }
349     return ret;
350 }
351 
UpdateVnicUidRangesRule(const std::vector<NetManagerStandard::UidRange> & uidRanges,bool add)352 int32_t RouteManager::UpdateVnicUidRangesRule(const std::vector<NetManagerStandard::UidRange> &uidRanges, bool add)
353 {
354     int32_t ret = ROUTEMANAGER_SUCCESS;
355     for (const auto &range : uidRanges) {
356         Fwmark fwmark;
357         Fwmark mask;
358         fwmark.protectedFromVpn = false;
359         mask.protectedFromVpn = false;
360 
361         RuleInfo ruleInfo;
362         ruleInfo.ruleTable = ROUTE_VNIC_TABLE;
363         ruleInfo.rulePriority = RULE_LEVEL_VNIC_NETWORK;
364         ruleInfo.ruleFwmark = fwmark.intValue;
365         ruleInfo.ruleMask = mask.intValue;
366         ruleInfo.ruleIif = RULEIIF_LOOPBACK;
367         ruleInfo.ruleOif = RULEOIF_NULL;
368         ret += UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, range.begin_, range.end_);
369     }
370     return ret;
371 }
372 
UpdateVpnUidRangeRule(uint32_t table,uid_t uidStart,uid_t uidEnd,bool add)373 int32_t RouteManager::UpdateVpnUidRangeRule(uint32_t table, uid_t uidStart, uid_t uidEnd, bool add)
374 {
375     Fwmark fwmark;
376     Fwmark mask;
377     fwmark.protectedFromVpn = false;
378     mask.protectedFromVpn = true;
379 
380     RuleInfo ruleInfo;
381     ruleInfo.ruleTable = table;
382     ruleInfo.rulePriority = RULE_LEVEL_SECURE_VPN;
383     ruleInfo.ruleFwmark = fwmark.intValue;
384     ruleInfo.ruleMask = mask.intValue;
385     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
386     ruleInfo.ruleOif = RULEOIF_NULL;
387     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd);
388 }
389 
UpdateExplicitNetworkRuleWithUid(int32_t netId,uint32_t table,NetworkPermission permission,uid_t uidStart,uid_t uidEnd,bool add)390 int32_t RouteManager::UpdateExplicitNetworkRuleWithUid(int32_t netId, uint32_t table, NetworkPermission permission,
391                                                        uid_t uidStart, uid_t uidEnd, bool add)
392 {
393     NETNATIVE_LOGI("UpdateExplicitNetworkRuleWithUid");
394     Fwmark fwmark;
395     fwmark.netId = netId;
396     fwmark.explicitlySelected = true;
397     fwmark.permission = permission;
398 
399     Fwmark mask;
400     mask.netId = FWMARK_NET_ID_MASK;
401     mask.explicitlySelected = true;
402     mask.permission = permission;
403 
404     RuleInfo ruleInfo;
405     ruleInfo.ruleTable = table;
406     ruleInfo.rulePriority = RULE_LEVEL_EXPLICIT_NETWORK;
407     ruleInfo.ruleFwmark = fwmark.intValue;
408     ruleInfo.ruleMask = mask.intValue;
409     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
410     ruleInfo.ruleOif = RULEOIF_NULL;
411 
412     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd);
413 }
414 
UpdateOutputInterfaceRulesWithUid(const std::string & interface,uint32_t table,NetworkPermission permission,uid_t uidStart,uid_t uidEnd,bool add)415 int32_t RouteManager::UpdateOutputInterfaceRulesWithUid(const std::string &interface, uint32_t table,
416                                                         NetworkPermission permission, uid_t uidStart, uid_t uidEnd,
417                                                         bool add)
418 {
419     NETNATIVE_LOGI("UpdateOutputInterfaceRulesWithUid interface:%{public}s", interface.c_str());
420     Fwmark fwmark;
421     fwmark.permission = permission;
422 
423     Fwmark mask;
424     mask.permission = permission;
425 
426     RuleInfo ruleInfo;
427     ruleInfo.ruleTable = table;
428     ruleInfo.rulePriority = RULE_LEVEL_OUTPUT_IFACE_VPN;
429     ruleInfo.ruleFwmark = fwmark.intValue;
430     ruleInfo.ruleMask = mask.intValue;
431     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
432     ruleInfo.ruleOif = interface;
433 
434     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, uidStart, uidEnd);
435 }
436 
AddInterfaceToLocalNetwork(uint16_t netId,const std::string & interfaceName)437 int32_t RouteManager::AddInterfaceToLocalNetwork(uint16_t netId, const std::string &interfaceName)
438 {
439     NETNATIVE_LOGI("AddInterfaceToLocalNetwork, %{public}s", interfaceName.c_str());
440     if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, ADD_CONTROL)) {
441         NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret);
442         return ret;
443     }
444     std::lock_guard lock(interfaceToTableLock_);
445     interfaceToTable_[interfaceName] = ROUTE_LOCAL_NETWORK_TABLE;
446 
447     return 0;
448 }
449 
RemoveInterfaceFromLocalNetwork(uint16_t netId,const std::string & interfaceName)450 int32_t RouteManager::RemoveInterfaceFromLocalNetwork(uint16_t netId, const std::string &interfaceName)
451 {
452     NETNATIVE_LOGI("RemoveInterfaceFromLocalNetwork");
453     if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, DEL_CONTROL)) {
454         NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret);
455         return ret;
456     }
457     std::lock_guard lock(interfaceToTableLock_);
458     interfaceToTable_.erase(interfaceName);
459 
460     return 0;
461 }
462 
EnableSharing(const std::string & inputInterface,const std::string & outputInterface)463 int32_t RouteManager::EnableSharing(const std::string &inputInterface, const std::string &outputInterface)
464 {
465     return UpdateSharingNetwork(RTM_NEWRULE, inputInterface, outputInterface);
466 }
467 
DisableSharing(const std::string & inputInterface,const std::string & outputInterface)468 int32_t RouteManager::DisableSharing(const std::string &inputInterface, const std::string &outputInterface)
469 {
470     return UpdateSharingNetwork(RTM_DELRULE, inputInterface, outputInterface);
471 }
472 
ReadAddrGw(const std::string & addr,InetAddr * res)473 int32_t RouteManager::ReadAddrGw(const std::string &addr, InetAddr *res)
474 {
475     if (res == nullptr) {
476         return -1;
477     }
478 
479     std::string addressString(addr.c_str());
480     if (strchr(addr.c_str(), ':')) {
481         res->family = AF_INET6;
482         res->bitlen = OUTPUT_MAX;
483     } else {
484         res->family = AF_INET;
485         res->bitlen = BIT_32_LEN;
486     }
487 
488     return inet_pton(res->family, addressString.c_str(), res->data);
489 }
490 
ReadAddr(const std::string & addr,InetAddr * res)491 int32_t RouteManager::ReadAddr(const std::string &addr, InetAddr *res)
492 {
493     if (res == nullptr) {
494         return -EINVAL;
495     }
496 
497     const char *slashStr = strchr(addr.c_str(), '/');
498     if (slashStr == nullptr) {
499         return -EINVAL;
500     }
501 
502     const char *maskLenStr = slashStr + 1;
503     if (*maskLenStr == 0) {
504         return -EINVAL;
505     }
506 
507     char *endptr = nullptr;
508     unsigned templen = strtoul(maskLenStr, &endptr, DECIMAL_DIGITAL);
509     if ((endptr == nullptr) || (templen > BIT_MAX_LEN)) {
510         return -EINVAL;
511     }
512     res->prefixlen = templen;
513 
514     std::string addressString(addr.c_str(), slashStr - addr.c_str());
515     if (strchr(addr.c_str(), ':')) {
516         res->family = AF_INET6;
517         res->bitlen = OUTPUT_MAX;
518     } else {
519         res->family = AF_INET;
520         res->bitlen = BIT_32_LEN;
521     }
522 
523     return inet_pton(res->family, addressString.c_str(), res->data);
524 }
525 
AddClatTunInterface(const std::string & interfaceName,const std::string & dstAddr,const std::string & nxtHop)526 int32_t RouteManager::AddClatTunInterface(const std::string &interfaceName, const std::string &dstAddr,
527                                           const std::string &nxtHop)
528 {
529     NETNATIVE_LOGI("AddClatTunInterface, interfaceName:%{public}s; dstAddr:%{public}s; nxtHop:%{public}s;",
530                    interfaceName.c_str(), dstAddr.c_str(), nxtHop.c_str());
531     if (int32_t ret = AddRoute(RouteManager::INTERFACE, interfaceName, dstAddr, nxtHop)) {
532         NETNATIVE_LOGE("AddRoute err, error is %{public}d", ret);
533         return ret;
534     }
535     return UpdateClatTunInterface(interfaceName, PERMISSION_NONE, ADD_CONTROL);
536 }
537 
RemoveClatTunInterface(const std::string & interfaceName)538 int32_t RouteManager::RemoveClatTunInterface(const std::string &interfaceName)
539 {
540     NETNATIVE_LOGI("RemoveClatTunInterface, interfaceName:%{public}s", interfaceName.c_str());
541     if (int32_t ret = UpdateClatTunInterface(interfaceName, PERMISSION_NONE, DEL_CONTROL)) {
542         NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret);
543         return ret;
544     }
545     if (int32_t ret = ClearRoutes(interfaceName)) {
546         NETNATIVE_LOGE("ClearRoutes err, error is %{public}d", ret);
547         return ret;
548     }
549     if (int32_t ret = ClearSharingRules(interfaceName)) {
550         NETNATIVE_LOGE("ClearSharingRules err, error is %{public}d", ret);
551         return ret;
552     }
553 
554     return 0;
555 }
556 
UpdateClatTunInterface(const std::string & interfaceName,NetworkPermission permission,bool add)557 int32_t RouteManager::UpdateClatTunInterface(const std::string &interfaceName, NetworkPermission permission, bool add)
558 {
559     NETNATIVE_LOGI("UpdateClatTunInterface, interfaceName: %{public}s, permission: %{public}d, add: %{public}d",
560                    interfaceName.c_str(), static_cast<int32_t>(permission), add);
561     uint32_t table = FindTableByInterfacename(interfaceName);
562     if (table == RT_TABLE_UNSPEC) {
563         NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error");
564         return -1;
565     }
566 
567     Fwmark fwmark;
568     fwmark.permission = permission;
569 
570     Fwmark mask;
571     mask.permission = permission;
572 
573     RuleInfo ruleInfo;
574     ruleInfo.ruleTable = table;
575     ruleInfo.rulePriority = RULE_LEVEL_CLAT_TUN;
576     ruleInfo.ruleFwmark = fwmark.intValue;
577     ruleInfo.ruleMask = mask.intValue;
578     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
579     ruleInfo.ruleOif = RULEOIF_NULL;
580 
581     if (int32_t ret = UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo)) {
582         NETNATIVE_LOGE("UpdateRuleInfo failed, err is %{public}d", ret);
583         return ret;
584     }
585 
586     return 0;
587 }
588 
Init()589 int32_t RouteManager::Init()
590 {
591     NETNATIVE_LOGI("Init");
592     // need to call IptablesWrapper's RunCommand function.
593     std::string commandNew;
594     commandNew.append(" -t mangle -N ");
595     commandNew.append(LOCAL_MANGLE_INPUT);
596 
597     std::string commandJump;
598     commandJump.append(" -A INPUT -j ");
599     commandJump.append(LOCAL_MANGLE_INPUT);
600 
601     if (int32_t ret = ClearRules()) {
602         NETNATIVE_LOGE("ClearRules failed, err is %{public}d", ret);
603         return ret;
604     }
605 
606     if (access(NETSYS_ROUTE_INIT_DIR_PATH, F_OK) == 0) {
607         if (int32_t ret = AddLocalNetworkRules()) {
608             NETNATIVE_LOGE("AddLocalNetworkRules failed, err is %{public}d", ret);
609             return ret;
610         }
611     } else {
612         NETNATIVE_LOGI("AddLocalNetworkRules init ok, do not need repeat");
613     }
614 
615     return 0;
616 }
617 
ClearRules()618 int32_t RouteManager::ClearRules()
619 {
620     return ClearRouteInfo(RTM_GETRULE, 0) >= 0 ? 0 : -1;
621 }
622 
ClearRoutes(const std::string & interfaceName,int32_t netId)623 int32_t RouteManager::ClearRoutes(const std::string &interfaceName, int32_t netId)
624 {
625     std::lock_guard lock(RouteManager::interfaceToTableLock_);
626     uint32_t table = FindTableByInterfacename(interfaceName, netId);
627     NETNATIVE_LOGI("ClearRoutes--table==:%{public}d", table);
628     if (table == RT_TABLE_UNSPEC) {
629         return -1;
630     }
631     int32_t ret = ClearRouteInfo(RTM_GETROUTE, table);
632     if (ret == 0 && table != ROUTE_INTERNAL_DEFAULT_TABLE) {
633         interfaceToTable_.erase(interfaceName);
634     }
635 
636     return 0;
637 }
638 
AddLocalNetworkRules()639 int32_t RouteManager::AddLocalNetworkRules()
640 {
641     NETNATIVE_LOGI("AddLocalNetworkRules");
642     if (int32_t ret =
643             UpdateExplicitNetworkRule(LOCAL_NET_ID, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, ADD_CONTROL)) {
644         NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret);
645         return ret;
646     }
647     Fwmark fwmark;
648     fwmark.explicitlySelected = false;
649 
650     Fwmark mask;
651     mask.explicitlySelected = true;
652 
653     RuleInfo ruleInfo;
654     ruleInfo.ruleTable = ROUTE_LOCAL_NETWORK_TABLE;
655     ruleInfo.rulePriority = RULE_LEVEL_LOCAL_NETWORK;
656     ruleInfo.ruleFwmark = fwmark.intValue;
657     ruleInfo.ruleMask = mask.intValue;
658     ruleInfo.ruleIif = RULEIIF_NULL;
659     ruleInfo.ruleOif = RULEOIF_NULL;
660 
661     return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo);
662 }
663 
UpdatePhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission,bool add)664 int32_t RouteManager::UpdatePhysicalNetwork(uint16_t netId, const std::string &interfaceName,
665                                             NetworkPermission permission, bool add)
666 {
667     NETNATIVE_LOGI("UpdatePhysicalNetwork,add===%{public}d", add);
668     uint32_t table = FindTableByInterfacename(interfaceName, netId);
669     if (table == RT_TABLE_UNSPEC) {
670         NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error");
671         return -1;
672     }
673 
674     if (int32_t ret = UpdateExplicitNetworkRule(netId, table, permission, add)) {
675         NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret);
676         return ret;
677     }
678 
679     if (int32_t ret = UpdateOutputInterfaceRules(interfaceName, table, permission, add)) {
680         NETNATIVE_LOGE("UpdateOutputInterfaceRules failed, err is %{public}d", ret);
681         return ret;
682     }
683 
684     return 0;
685 }
686 
UpdateLocalNetwork(uint16_t netId,const std::string & interfaceName,bool add)687 int32_t RouteManager::UpdateLocalNetwork(uint16_t netId, const std::string &interfaceName, bool add)
688 {
689     NETNATIVE_LOGI("UpdateLocalNetwork");
690     return UpdateOutputInterfaceRules(interfaceName, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, add);
691 }
692 
UpdateIncomingPacketMark(uint16_t netId,const std::string & interfaceName,NetworkPermission permission,bool add)693 int32_t RouteManager::UpdateIncomingPacketMark(uint16_t netId, const std::string &interfaceName,
694                                                NetworkPermission permission, bool add)
695 {
696     NETNATIVE_LOGI("UpdateIncomingPacketMark");
697     Fwmark fwmark;
698     fwmark.netId = netId;
699     fwmark.explicitlySelected = true;
700     fwmark.protectedFromVpn = true;
701     fwmark.permission = permission;
702     const uint32_t mask = ~Fwmark::GetUidBillingMask();
703     std::string action = "";
704     if (add) {
705         action = " -A ";
706     } else {
707         action = " -D ";
708     }
709     std::stringstream ss;
710     ss << action << LOCAL_MANGLE_INPUT << " -i " << interfaceName << " -j MARK --set-mark 0x" << std::nouppercase
711        << std::hex << fwmark.intValue << "/0x" << std::nouppercase << std::hex << mask;
712     // need to call IptablesWrapper's RunCommand function.
713 
714     return 0;
715 }
716 
UpdateExplicitNetworkRule(uint16_t netId,uint32_t table,NetworkPermission permission,bool add)717 int32_t RouteManager::UpdateExplicitNetworkRule(uint16_t netId, uint32_t table, NetworkPermission permission, bool add)
718 {
719     NETNATIVE_LOGI("UpdateExplicitNetworkRule");
720     Fwmark fwmark;
721     fwmark.netId = netId;
722     fwmark.explicitlySelected = true;
723     fwmark.permission = permission;
724 
725     Fwmark mask;
726     mask.netId = FWMARK_NET_ID_MASK;
727     mask.explicitlySelected = true;
728     mask.permission = permission;
729 
730     RuleInfo ruleInfo;
731     ruleInfo.ruleTable = table;
732     ruleInfo.rulePriority = RULE_LEVEL_EXPLICIT_NETWORK;
733     ruleInfo.ruleFwmark = fwmark.intValue;
734     ruleInfo.ruleMask = mask.intValue;
735     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
736     ruleInfo.ruleOif = RULEOIF_NULL;
737 
738     if (NetManagerStandard::IsInternalNetId(netId)) {
739         return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo, UID_ALLOW_INTERNAL.first,
740                               UID_ALLOW_INTERNAL.second);
741     }
742     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
743 }
744 
UpdateOutputInterfaceRules(const std::string & interfaceName,uint32_t table,NetworkPermission permission,bool add)745 int32_t RouteManager::UpdateOutputInterfaceRules(const std::string &interfaceName, uint32_t table,
746                                                  NetworkPermission permission, bool add)
747 {
748     NETNATIVE_LOGI("UpdateOutputInterfaceRules");
749     Fwmark fwmark;
750     fwmark.permission = permission;
751 
752     Fwmark mask;
753     mask.permission = permission;
754 
755     RuleInfo ruleInfo;
756     ruleInfo.ruleTable = table;
757     ruleInfo.rulePriority = RULE_LEVEL_OUTPUT_INTERFACE;
758     ruleInfo.ruleFwmark = fwmark.intValue;
759     ruleInfo.ruleMask = mask.intValue;
760     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
761     ruleInfo.ruleOif = interfaceName;
762 
763     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
764 }
765 
UpdateSharingNetwork(uint16_t action,const std::string & inputInterface,const std::string & outputInterface)766 int32_t RouteManager::UpdateSharingNetwork(uint16_t action, const std::string &inputInterface,
767                                            const std::string &outputInterface)
768 {
769     NETNATIVE_LOGI("UpdateSharingNetwork");
770     uint32_t table = FindTableByInterfacename(outputInterface);
771     if (table == RT_TABLE_UNSPEC) {
772         return -1;
773     }
774 
775     RuleInfo ruleInfo;
776     ruleInfo.ruleTable = table;
777     ruleInfo.rulePriority = RULE_LEVEL_SHARING;
778     ruleInfo.ruleFwmark = MARK_UNSET;
779     ruleInfo.ruleMask = MARK_UNSET;
780     ruleInfo.ruleIif = inputInterface;
781     ruleInfo.ruleOif = RULEOIF_NULL;
782 
783     return UpdateRuleInfo(action, FR_ACT_TO_TBL, ruleInfo);
784 }
785 
ClearSharingRules(const std::string & inputInterface)786 int32_t RouteManager::ClearSharingRules(const std::string &inputInterface)
787 {
788     NETNATIVE_LOGI("ClearSharingRules");
789 
790     RuleInfo ruleInfo;
791     ruleInfo.ruleTable = 0;
792     ruleInfo.rulePriority = RULE_LEVEL_SHARING;
793     ruleInfo.ruleFwmark = MARK_UNSET;
794     ruleInfo.ruleMask = MARK_UNSET;
795     ruleInfo.ruleIif = inputInterface;
796     ruleInfo.ruleOif = RULEOIF_NULL;
797 
798     return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
799 }
800 
UpdateRuleInfo(uint32_t action,uint8_t ruleType,RuleInfo ruleInfo,uid_t uidStart,uid_t uidEnd)801 int32_t RouteManager::UpdateRuleInfo(uint32_t action, uint8_t ruleType, RuleInfo ruleInfo, uid_t uidStart, uid_t uidEnd)
802 {
803     NETNATIVE_LOGI("UpdateRuleInfo");
804     if (ruleInfo.rulePriority < 0) {
805         NETNATIVE_LOGE("invalid IP-rule priority %{public}d", ruleInfo.rulePriority);
806         return ROUTEMANAGER_ERROR;
807     }
808 
809     if (ruleInfo.ruleFwmark & ~ruleInfo.ruleMask) {
810         NETNATIVE_LOGE("mask 0x%{public}x does not select all the bits set in fwmark 0x%{public}x", ruleInfo.ruleMask,
811                        ruleInfo.ruleFwmark);
812         return ROUTEMANAGER_ERROR;
813     }
814 
815     if (ruleInfo.ruleTable == RT_TABLE_UNSPEC && ruleType == FR_ACT_TO_TBL && action != RTM_DELRULE) {
816         NETNATIVE_LOGE("RT_TABLE_UNSPEC only allowed when deleting rules");
817         return -ENOTUNIQ;
818     }
819 
820     // The main work is to assemble the structure required for rule.
821     for (const uint8_t family : {AF_INET, AF_INET6}) {
822         if (SendRuleToKernel(action, family, ruleType, ruleInfo, uidStart, uidEnd) < 0) {
823             NETNATIVE_LOGE("Update %{public}s rule info failed, action = %{public}d",
824                            (family == AF_INET) ? "IPv4" : "IPv6", action);
825             return NETMANAGER_ERR_INTERNAL;
826         }
827     }
828     return NETMANAGER_SUCCESS;
829 }
830 
SendRuleToKernel(uint32_t action,uint8_t family,uint8_t ruleType,RuleInfo ruleInfo,uid_t uidStart,uid_t uidEnd)831 int32_t RouteManager::SendRuleToKernel(uint32_t action, uint8_t family, uint8_t ruleType, RuleInfo ruleInfo,
832                                        uid_t uidStart, uid_t uidEnd)
833 {
834     struct fib_rule_hdr msg = {0};
835     msg.action = ruleType;
836     msg.family = family;
837     uint16_t ruleFlag = (action == RTM_NEWRULE) ? NLM_F_CREATE : NLM_F_EXCL;
838     NetlinkMsg nlmsg(ruleFlag, NETLINK_MAX_LEN, getpid());
839     nlmsg.AddRule(action, msg);
840     if (int32_t ret = nlmsg.AddAttr32(FRA_PRIORITY, ruleInfo.rulePriority)) {
841         return ret;
842     }
843     if (ruleInfo.ruleTable != RT_TABLE_UNSPEC) {
844         if (int32_t ret = nlmsg.AddAttr32(FRA_TABLE, ruleInfo.ruleTable)) {
845             return ret;
846         }
847     }
848     if (ruleInfo.ruleMask != 0) {
849         if (int32_t ret = nlmsg.AddAttr32(FRA_FWMARK, ruleInfo.ruleFwmark)) {
850             return ret;
851         }
852         if (int32_t ret = nlmsg.AddAttr32(FRA_FWMASK, ruleInfo.ruleMask)) {
853             return ret;
854         }
855     }
856     if ((uidStart != INVALID_UID) && (uidEnd != INVALID_UID)) {
857         FibRuleUidRange uidRange = {uidStart, uidEnd};
858         if (int32_t ret = nlmsg.AddAttr(FRA_UID_RANGE, &uidRange, sizeof(uidRange))) {
859             NETNATIVE_LOGE("SendRuleToKernel FRA_UID_RANGE is error.");
860             return ret;
861         }
862     }
863     if (ruleInfo.ruleIif != RULEIIF_NULL) {
864         char ruleIifName[IFNAMSIZ] = {0};
865         size_t ruleIifLength = strlcpy(ruleIifName, ruleInfo.ruleIif.c_str(), IFNAMSIZ) + 1;
866         if (int32_t ret = nlmsg.AddAttr(FRA_IIFNAME, ruleIifName, ruleIifLength)) {
867             return ret;
868         }
869     }
870     if (ruleInfo.ruleOif != RULEOIF_NULL) {
871         char ruleOifName[IFNAMSIZ] = {0};
872         size_t ruleOifLength = strlcpy(ruleOifName, ruleInfo.ruleOif.c_str(), IFNAMSIZ) + 1;
873         if (int32_t ret = nlmsg.AddAttr(FRA_OIFNAME, ruleOifName, ruleOifLength)) {
874             return ret;
875         }
876     }
877 
878     return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage());
879 }
880 
UpdateRouteRule(uint16_t action,uint16_t flags,RouteInfo routeInfo)881 int32_t RouteManager::UpdateRouteRule(uint16_t action, uint16_t flags, RouteInfo routeInfo)
882 {
883     NETNATIVE_LOG_D("UpdateRouteRule");
884     RouteInfo routeInfoModify = routeInfo;
885     // The main work is to assemble the structure required for route.
886     struct rtmsg msg;
887     (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
888     msg.rtm_family = AF_INET;
889     msg.rtm_dst_len = BIT_32_LEN;
890     msg.rtm_protocol = RTPROT_STATIC;
891     msg.rtm_scope = RT_SCOPE_UNIVERSE;
892     msg.rtm_type = RTN_UNICAST;
893     msg.rtm_table = RT_TABLE_UNSPEC;
894 
895     uint32_t index = 0;
896     if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "unreachable")) {
897         msg.rtm_type = RTN_UNREACHABLE;
898         routeInfoModify.routeInterfaceName = "";
899         routeInfoModify.routeNextHop = "";
900     } else if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "throw")) {
901         msg.rtm_type = RTN_THROW;
902         routeInfoModify.routeInterfaceName = "";
903         routeInfoModify.routeNextHop = "";
904     } else {
905         index = if_nametoindex(routeInfo.routeInterfaceName.c_str());
906     }
907 
908     int32_t ret = SendRouteToKernel(action, flags, msg, routeInfoModify, index);
909     if (ret < 0) {
910         NETNATIVE_LOGE("SendNetlinkMsgToKernel Error ret = %{public}d", ret);
911         return ret;
912     }
913 
914     return 0;
915 }
916 
SendRouteToKernel(uint16_t action,uint16_t routeFlag,rtmsg msg,RouteInfo routeInfo,uint32_t index)917 int32_t RouteManager::SendRouteToKernel(uint16_t action, uint16_t routeFlag, rtmsg msg, RouteInfo routeInfo,
918                                         uint32_t index)
919 {
920     InetAddr dst;
921     int32_t readAddrResult = ReadAddr(routeInfo.routeDestinationName, &dst);
922     if (readAddrResult != 1) {
923         NETNATIVE_LOGE("dest parse failed:%{public}d", readAddrResult);
924         return -1;
925     }
926     msg.rtm_family = static_cast<uint8_t>(dst.family);
927     msg.rtm_dst_len = static_cast<uint8_t>(dst.prefixlen);
928     if (dst.family == AF_INET) {
929         msg.rtm_scope = RT_SCOPE_LINK;
930     } else if (dst.family == AF_INET6) {
931         msg.rtm_scope = RT_SCOPE_UNIVERSE;
932     }
933 
934     InetAddr gw = {0};
935     if (!routeInfo.routeNextHop.empty() && ReadAddrGw(routeInfo.routeNextHop, &gw) <= 0) {
936         NETNATIVE_LOGE("gw parse failed:%{public}d", readAddrResult);
937         return -1;
938     }
939     if (gw.bitlen != 0) {
940         msg.rtm_scope = RT_SCOPE_UNIVERSE;
941         msg.rtm_family = static_cast<uint8_t>(gw.family);
942     }
943     NetlinkMsg nlmsg(routeFlag, NETLINK_MAX_LEN, getpid());
944     nlmsg.AddRoute(action, msg);
945     if (int32_t ret = nlmsg.AddAttr32(RTA_TABLE, routeInfo.routeTable)) {
946         return ret;
947     }
948     if (int32_t ret = nlmsg.AddAttr(RTA_DST, dst.data, dst.bitlen / BYTE_ALIGNMENT)) {
949         return ret;
950     }
951     if (!routeInfo.routeNextHop.empty()) {
952         if (int32_t ret = nlmsg.AddAttr(RTA_GATEWAY, gw.data, gw.bitlen / BYTE_ALIGNMENT)) {
953             return ret;
954         }
955     }
956     if (!routeInfo.routeInterfaceName.empty()) {
957         NETNATIVE_LOGI("index is :%{public}d", index);
958         if (int32_t ret = nlmsg.AddAttr32(RTA_OIF, index)) {
959             return ret;
960         }
961     }
962 
963     return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage());
964 }
965 
FindTableByInterfacename(const std::string & interfaceName,int32_t netId)966 uint32_t RouteManager::FindTableByInterfacename(const std::string &interfaceName, int32_t netId)
967 {
968     NETNATIVE_LOGI("FindTableByInterfacename netId %{public}d", netId);
969     if (NetManagerStandard::IsInternalNetId(netId)) {
970         return ROUTE_INTERNAL_DEFAULT_TABLE;
971     }
972     auto iter = interfaceToTable_.find(interfaceName);
973     if (iter != interfaceToTable_.end()) {
974         return iter->second;
975     }
976 
977     uint32_t table = if_nametoindex(interfaceName.c_str());
978     if (table == 0) {
979         NETNATIVE_LOGE("RouteManager cannot find interface %{public}s", interfaceName.c_str());
980         return RT_TABLE_UNSPEC;
981     }
982     table += THOUSAND_LEN;
983     interfaceToTable_[interfaceName] = table;
984     return table;
985 }
986 
GetRouteTableFromType(TableType tableType,const std::string & interfaceName)987 uint32_t RouteManager::GetRouteTableFromType(TableType tableType, const std::string &interfaceName)
988 {
989     switch (tableType) {
990         case RouteManager::INTERFACE:
991             return FindTableByInterfacename(interfaceName);
992         case RouteManager::LOCAL_NETWORK:
993             return ROUTE_LOCAL_NETWORK_TABLE;
994         case RouteManager::VPN_NETWORK:
995             return ROUTE_VPN_NETWORK_TABLE;
996         case RouteManager::INTERNAL_DEFAULT:
997             return ROUTE_INTERNAL_DEFAULT_TABLE;
998         default:
999             NETNATIVE_LOGE("tableType [%{tableType}d] is error", tableType);
1000             return RT_TABLE_UNSPEC;
1001     }
1002 }
1003 
SetRouteInfo(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop,RouteInfo & routeInfo)1004 int32_t RouteManager::SetRouteInfo(TableType tableType, const std::string &interfaceName,
1005                                    const std::string &destinationName, const std::string &nextHop, RouteInfo &routeInfo)
1006 {
1007     uint32_t table = GetRouteTableFromType(tableType, interfaceName);
1008     if (table == RT_TABLE_UNSPEC) {
1009         return -1;
1010     }
1011 
1012     routeInfo.routeTable = table;
1013     routeInfo.routeInterfaceName = interfaceName;
1014     routeInfo.routeDestinationName = destinationName;
1015     routeInfo.routeNextHop = nextHop;
1016     return 0;
1017 }
1018 } // namespace nmd
1019 } // namespace OHOS
1020