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