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