• 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 "securec.h"
38 
39 #include "route_manager.h"
40 
41 using namespace OHOS::NetManagerStandard::CommonUtils;
42 namespace OHOS {
43 namespace nmd {
44 namespace {
45 constexpr int32_t RULE_LEVEL_EXPLICIT_NETWORK = 11000;
46 constexpr int32_t RULE_LEVEL_OUTPUT_INTERFACE = 12000;
47 constexpr int32_t RULE_LEVEL_LOCAL_NETWORK = 13000;
48 constexpr int32_t RULE_LEVEL_SHARING = 14000;
49 constexpr int32_t RULE_LEVEL_DEFAULT = 16000;
50 constexpr uint32_t ROUTE_VPN_NETWORK_TABLE = 98;
51 constexpr uint32_t ROUTE_LOCAL_NETWORK_TABLE = 99;
52 constexpr uint32_t OUTPUT_MAX = 128;
53 constexpr uint32_t BIT_32_LEN = 32;
54 constexpr uint32_t BIT_MAX_LEN = 255;
55 constexpr uint32_t DECIMAL_DIGITAL = 10;
56 constexpr uint32_t BYTE_ALIGNMENT = 8;
57 constexpr uint32_t THOUSAND_LEN = 100;
58 constexpr uint16_t LOCAL_NET_ID = 99;
59 constexpr uint16_t NETID_UNSET = 0;
60 constexpr uint32_t MARK_UNSET = 0;
61 constexpr bool ADD_CONTROL = true;
62 constexpr bool DEL_CONTROL = false;
63 const std::string RULEIIF_LOOPBACK = "lo";
64 const std::string RULEIIF_NULL = "";
65 const std::string RULEOIF_NULL = "";
66 const std::string LOCAL_MANGLE_INPUT = "routectrl_mangle_INPUT";
67 constexpr const char *NETSYS_ROUTE_INIT_DIR_PATH = "/data/service/el1/public/netmanager/route";
68 } // namespace
69 
70 std::mutex RouteManager::interfaceToTableLock_;
71 std::map<std::string, uint32_t> RouteManager::interfaceToTable_;
72 
RouteManager()73 RouteManager::RouteManager()
74 {
75     Init();
76 }
77 
AddRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)78 int32_t RouteManager::AddRoute(TableType tableType, const std::string &interfaceName,
79                                const std::string &destinationName, const std::string &nextHop)
80 {
81     NETNATIVE_LOGI("Entry RouteManager::AddRoute,interfaceName:%{public}s,destination:%{public}s, nextHop:%{public}s",
82                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
83     uint32_t table = GetRouteTableFromType(tableType, interfaceName);
84     if (table == RT_TABLE_UNSPEC) {
85         return -1;
86     }
87 
88     // This is a user-defined structure used to integrate the information required for setting up routes.
89     RouteInfo routeInfo;
90     routeInfo.routeTable = table;
91     routeInfo.routeInterfaceName = interfaceName;
92     routeInfo.routeDestinationName = destinationName;
93     routeInfo.routeNextHop = nextHop;
94     return UpdateRouteRule(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, routeInfo);
95 }
96 
RemoveRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)97 int32_t RouteManager::RemoveRoute(TableType tableType, const std::string &interfaceName,
98                                   const std::string &destinationName, const std::string &nextHop)
99 {
100     NETNATIVE_LOGI("Entry RouteManager::RemoveRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s",
101                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
102     uint32_t table = GetRouteTableFromType(tableType, interfaceName);
103     if (table == RT_TABLE_UNSPEC) {
104         return -1;
105     }
106 
107     RouteInfo routeInfo;
108     routeInfo.routeTable = table;
109     routeInfo.routeInterfaceName = interfaceName;
110     routeInfo.routeDestinationName = destinationName;
111     routeInfo.routeNextHop = nextHop;
112     return UpdateRouteRule(RTM_DELROUTE, NLM_F_EXCL, routeInfo);
113 }
114 
UpdateRoute(TableType tableType,const std::string & interfaceName,const std::string & destinationName,const std::string & nextHop)115 int32_t RouteManager::UpdateRoute(TableType tableType, const std::string &interfaceName,
116                                   const std::string &destinationName, const std::string &nextHop)
117 {
118     NETNATIVE_LOGI("Entry RouteManager::UpdateRoute,interfaceName:%{public}s,destination:%{public}s,nextHop:%{public}s",
119                    interfaceName.c_str(), ToAnonymousIp(destinationName).c_str(), ToAnonymousIp(nextHop).c_str());
120     uint32_t table = GetRouteTableFromType(tableType, interfaceName);
121     if (table == RT_TABLE_UNSPEC) {
122         return -1;
123     }
124 
125     RouteInfo routeInfo;
126     routeInfo.routeTable = table;
127     routeInfo.routeInterfaceName = interfaceName;
128     routeInfo.routeDestinationName = destinationName;
129     routeInfo.routeNextHop = nextHop;
130     return UpdateRouteRule(RTM_NEWROUTE, NLM_F_REPLACE, routeInfo);
131 }
132 
AddInterfaceToDefaultNetwork(const std::string & interfaceName,NetworkPermission permission)133 int32_t RouteManager::AddInterfaceToDefaultNetwork(const std::string &interfaceName, NetworkPermission permission)
134 {
135     NETNATIVE_LOGI("AddInterfaceToDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(),
136                    permission);
137     uint32_t table = FindTableByInterfacename(interfaceName);
138     if (table == RT_TABLE_UNSPEC) {
139         return -1;
140     }
141     Fwmark fwmark;
142     fwmark.netId = NETID_UNSET;
143     fwmark.permission = permission;
144 
145     Fwmark mask;
146     mask.netId = FWMARK_NET_ID_MASK;
147     mask.permission = permission;
148 
149     // This is a user-defined structure used to integrate the information required for setting up rules.
150     RuleInfo ruleInfo;
151     ruleInfo.ruleTable = table;
152     ruleInfo.rulePriority = RULE_LEVEL_DEFAULT;
153     ruleInfo.ruleFwmark = fwmark.intValue;
154     ruleInfo.ruleMask = mask.intValue;
155     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
156     ruleInfo.ruleOif = RULEOIF_NULL;
157     return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo);
158 }
159 
RemoveInterfaceFromDefaultNetwork(const std::string & interfaceName,NetworkPermission permission)160 int32_t RouteManager::RemoveInterfaceFromDefaultNetwork(const std::string &interfaceName, NetworkPermission permission)
161 {
162     NETNATIVE_LOGI("RemoveInterfaceFromDefaultNetwork, %{public}s;permission:%{public}d;", interfaceName.c_str(),
163                    permission);
164     uint32_t table = FindTableByInterfacename(interfaceName);
165     if (table == RT_TABLE_UNSPEC) {
166         return -1;
167     }
168 
169     Fwmark fwmark;
170     fwmark.netId = NETID_UNSET;
171     fwmark.permission = permission;
172 
173     Fwmark mask;
174     mask.netId = FWMARK_NET_ID_MASK;
175     mask.permission = permission;
176 
177     RuleInfo ruleInfo;
178     ruleInfo.ruleTable = table;
179     ruleInfo.rulePriority = RULE_LEVEL_DEFAULT;
180     ruleInfo.ruleFwmark = fwmark.intValue;
181     ruleInfo.ruleMask = mask.intValue;
182     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
183     ruleInfo.ruleOif = RULEOIF_NULL;
184     return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
185 }
186 
AddInterfaceToPhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission)187 int32_t RouteManager::AddInterfaceToPhysicalNetwork(uint16_t netId, const std::string &interfaceName,
188                                                     NetworkPermission permission)
189 {
190     NETNATIVE_LOGI("AddInterfaceToPhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;",
191                    netId, interfaceName.c_str(), permission);
192     return UpdatePhysicalNetwork(netId, interfaceName, permission, ADD_CONTROL);
193 }
194 
RemoveInterfaceFromPhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission)195 int32_t RouteManager::RemoveInterfaceFromPhysicalNetwork(uint16_t netId, const std::string &interfaceName,
196                                                          NetworkPermission permission)
197 {
198     NETNATIVE_LOGI("RemoveInterfacePhysicalNetwork, netId:%{public}d;interfaceName:%{public}s;permission:%{public}d;",
199                    netId, interfaceName.c_str(), permission);
200     if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, permission, DEL_CONTROL)) {
201         NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret);
202         return ret;
203     }
204     if (int32_t ret = ClearRoutes(interfaceName)) {
205         NETNATIVE_LOGE("ClearRoutes err, error is %{public}d", ret);
206         return ret;
207     }
208     if (int32_t ret = ClearSharingRules(interfaceName)) {
209         NETNATIVE_LOGE("ClearSharingRules err, error is %{public}d", ret);
210         return ret;
211     }
212 
213     return 0;
214 }
215 
ModifyPhysicalNetworkPermission(uint16_t netId,const std::string & interfaceName,NetworkPermission oldPermission,NetworkPermission newPermission)216 int32_t RouteManager::ModifyPhysicalNetworkPermission(uint16_t netId, const std::string &interfaceName,
217                                                       NetworkPermission oldPermission, NetworkPermission newPermission)
218 {
219     NETNATIVE_LOGI("Entry RouteManager::ModifyPhysicalNetworkPermission, %{public}s", interfaceName.c_str());
220     if (int32_t ret = UpdatePhysicalNetwork(netId, interfaceName, newPermission, ADD_CONTROL)) {
221         NETNATIVE_LOGE("UpdatePhysicalNetwork err, error is %{public}d", ret);
222         return ret;
223     }
224 
225     return UpdatePhysicalNetwork(netId, interfaceName, newPermission, DEL_CONTROL);
226 }
227 
AddInterfaceToLocalNetwork(uint16_t netId,const std::string & interfaceName)228 int32_t RouteManager::AddInterfaceToLocalNetwork(uint16_t netId, const std::string &interfaceName)
229 {
230     NETNATIVE_LOGI("Entry RouteManager::AddInterfaceToLocalNetwork, %{public}s", interfaceName.c_str());
231     if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, ADD_CONTROL)) {
232         NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret);
233         return ret;
234     }
235     std::lock_guard lock(interfaceToTableLock_);
236     interfaceToTable_[interfaceName] = ROUTE_LOCAL_NETWORK_TABLE;
237 
238     return 0;
239 }
240 
RemoveInterfaceFromLocalNetwork(uint16_t netId,const std::string & interfaceName)241 int32_t RouteManager::RemoveInterfaceFromLocalNetwork(uint16_t netId, const std::string &interfaceName)
242 {
243     NETNATIVE_LOGI("Entry RouteManager::RemoveInterfaceFromLocalNetwork");
244     if (int32_t ret = UpdateLocalNetwork(netId, interfaceName, DEL_CONTROL)) {
245         NETNATIVE_LOGE("UpdateLocalNetwork err, error is %{public}d", ret);
246         return ret;
247     }
248     std::lock_guard lock(interfaceToTableLock_);
249     interfaceToTable_.erase(interfaceName);
250 
251     return 0;
252 }
253 
EnableSharing(const std::string & inputInterface,const std::string & outputInterface)254 int32_t RouteManager::EnableSharing(const std::string &inputInterface, const std::string &outputInterface)
255 {
256     return UpdateSharingNetwork(RTM_NEWRULE, inputInterface, outputInterface);
257 }
258 
DisableSharing(const std::string & inputInterface,const std::string & outputInterface)259 int32_t RouteManager::DisableSharing(const std::string &inputInterface, const std::string &outputInterface)
260 {
261     return UpdateSharingNetwork(RTM_DELRULE, inputInterface, outputInterface);
262 }
263 
ReadAddrGw(const std::string & addr,InetAddr * res)264 int32_t RouteManager::ReadAddrGw(const std::string &addr, InetAddr *res)
265 {
266     if (res == nullptr) {
267         return -1;
268     }
269 
270     std::string addressString(addr.c_str());
271     if (strchr(addr.c_str(), ':')) {
272         res->family = AF_INET6;
273         res->bitlen = OUTPUT_MAX;
274     } else {
275         res->family = AF_INET;
276         res->bitlen = BIT_32_LEN;
277     }
278 
279     return inet_pton(res->family, addressString.c_str(), res->data);
280 }
281 
ReadAddr(const std::string & addr,InetAddr * res)282 int32_t RouteManager::ReadAddr(const std::string &addr, InetAddr *res)
283 {
284     if (res == nullptr) {
285         return -EINVAL;
286     }
287 
288     const char *slashStr = strchr(addr.c_str(), '/');
289     if (slashStr == nullptr) {
290         return -EINVAL;
291     }
292 
293     const char *maskLenStr = slashStr + 1;
294     if (*maskLenStr == 0) {
295         return -EINVAL;
296     }
297 
298     char *endptr = nullptr;
299     unsigned templen = strtoul(maskLenStr, &endptr, DECIMAL_DIGITAL);
300     if ((endptr == nullptr) || (templen > BIT_MAX_LEN)) {
301         return -EINVAL;
302     }
303     res->prefixlen = templen;
304 
305     std::string addressString(addr.c_str(), slashStr - addr.c_str());
306     if (strchr(addr.c_str(), ':')) {
307         res->family = AF_INET6;
308         res->bitlen = OUTPUT_MAX;
309     } else {
310         res->family = AF_INET;
311         res->bitlen = BIT_32_LEN;
312     }
313 
314     return inet_pton(res->family, addressString.c_str(), res->data);
315 }
316 
Init()317 int32_t RouteManager::Init()
318 {
319     NETNATIVE_LOGI("Entry RouteManager::Init");
320     // need to call IptablesWrapper's RunCommand function.
321     std::string commandNew;
322     commandNew.append(" -t mangle -N ");
323     commandNew.append(LOCAL_MANGLE_INPUT);
324 
325     std::string commandJump;
326     commandJump.append(" -A INPUT -j ");
327     commandJump.append(LOCAL_MANGLE_INPUT);
328 
329     if (int32_t ret = ClearRules()) {
330         NETNATIVE_LOGE("ClearRules failed, err is %{public}d", ret);
331         return ret;
332     }
333 
334     if (access(NETSYS_ROUTE_INIT_DIR_PATH, F_OK) == 0) {
335         if (int32_t ret = AddLocalNetworkRules()) {
336             NETNATIVE_LOGE("AddLocalNetworkRules failed, err is %{public}d", ret);
337             return ret;
338         }
339     } else {
340         NETNATIVE_LOGI("AddLocalNetworkRules init ok, do not need repeat");
341     }
342 
343     return 0;
344 }
345 
ClearRules()346 int32_t RouteManager::ClearRules()
347 {
348     return ClearRouteInfo(RTM_GETRULE, 0) >= 0 ? 0 : -1;
349 }
350 
ClearRoutes(const std::string & interfaceName)351 int32_t RouteManager::ClearRoutes(const std::string &interfaceName)
352 {
353     std::lock_guard lock(RouteManager::interfaceToTableLock_);
354     uint32_t table = FindTableByInterfacename(interfaceName);
355     NETNATIVE_LOGI("RouteManager::ClearRoutes--table==:%{public}d", table);
356     if (table == RT_TABLE_UNSPEC) {
357         return -1;
358     }
359     int32_t ret = ClearRouteInfo(RTM_GETROUTE, table);
360     if (ret == 0) {
361         interfaceToTable_.erase(interfaceName);
362     }
363 
364     return 0;
365 }
366 
AddLocalNetworkRules()367 int32_t RouteManager::AddLocalNetworkRules()
368 {
369     NETNATIVE_LOGI("Entry RouteManager::AddLocalNetworkRules");
370     if (int32_t ret =
371             UpdateExplicitNetworkRule(LOCAL_NET_ID, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, ADD_CONTROL)) {
372         NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret);
373         return ret;
374     }
375     Fwmark fwmark;
376     fwmark.explicitlySelected = false;
377 
378     Fwmark mask;
379     mask.explicitlySelected = true;
380 
381     RuleInfo ruleInfo;
382     ruleInfo.ruleTable = ROUTE_LOCAL_NETWORK_TABLE;
383     ruleInfo.rulePriority = RULE_LEVEL_LOCAL_NETWORK;
384     ruleInfo.ruleFwmark = fwmark.intValue;
385     ruleInfo.ruleMask = mask.intValue;
386     ruleInfo.ruleIif = RULEIIF_NULL;
387     ruleInfo.ruleOif = RULEOIF_NULL;
388 
389     return UpdateRuleInfo(RTM_NEWRULE, FR_ACT_TO_TBL, ruleInfo);
390 }
391 
UpdatePhysicalNetwork(uint16_t netId,const std::string & interfaceName,NetworkPermission permission,bool add)392 int32_t RouteManager::UpdatePhysicalNetwork(uint16_t netId, const std::string &interfaceName,
393                                             NetworkPermission permission, bool add)
394 {
395     NETNATIVE_LOGI("Entry RouteManager::UpdatePhysicalNetwork,add===%{public}d", add);
396     uint32_t table = FindTableByInterfacename(interfaceName);
397     if (table == RT_TABLE_UNSPEC) {
398         NETNATIVE_LOGE("table == RT_TABLE_UNSPEC, this is error");
399         return -1;
400     }
401 
402     if (int32_t ret = UpdateExplicitNetworkRule(netId, table, permission, add)) {
403         NETNATIVE_LOGE("UpdateExplicitNetworkRule failed, err is %{public}d", ret);
404         return ret;
405     }
406 
407     if (int32_t ret = UpdateOutputInterfaceRules(interfaceName, table, permission, add)) {
408         NETNATIVE_LOGE("UpdateOutputInterfaceRules failed, err is %{public}d", ret);
409         return ret;
410     }
411 
412     return 0;
413 }
414 
UpdateLocalNetwork(uint16_t netId,const std::string & interfaceName,bool add)415 int32_t RouteManager::UpdateLocalNetwork(uint16_t netId, const std::string &interfaceName, bool add)
416 {
417     NETNATIVE_LOGI("Entry RouteManager::UpdateLocalNetwork");
418     return UpdateOutputInterfaceRules(interfaceName, ROUTE_LOCAL_NETWORK_TABLE, PERMISSION_NONE, add);
419 }
420 
UpdateIncomingPacketMark(uint16_t netId,const std::string & interfaceName,NetworkPermission permission,bool add)421 int32_t RouteManager::UpdateIncomingPacketMark(uint16_t netId, const std::string &interfaceName,
422                                                NetworkPermission permission, bool add)
423 {
424     NETNATIVE_LOGI("Entry RouteManager::UpdateIncomingPacketMark");
425     Fwmark fwmark;
426     fwmark.netId = netId;
427     fwmark.explicitlySelected = true;
428     fwmark.protectedFromVpn = true;
429     fwmark.permission = permission;
430     const uint32_t mask = ~Fwmark::GetUidBillingMask();
431     std::string command = "";
432     std::string action = "";
433     if (add) {
434         action = " -A ";
435     } else {
436         action = " -D ";
437     }
438     std::stringstream ss;
439     ss << action << LOCAL_MANGLE_INPUT << " -i " << interfaceName << " -j MARK --set-mark 0x" << std::nouppercase
440        << std::hex << fwmark.intValue << "/0x" << std::nouppercase << std::hex << mask;
441     command = ss.str();
442     // need to call IptablesWrapper's RunCommand function.
443 
444     return 0;
445 }
446 
UpdateExplicitNetworkRule(uint16_t netId,uint32_t table,NetworkPermission permission,bool add)447 int32_t RouteManager::UpdateExplicitNetworkRule(uint16_t netId, uint32_t table, NetworkPermission permission, bool add)
448 {
449     NETNATIVE_LOGI("Entry RouteManager::UpdateExplicitNetworkRule");
450     Fwmark fwmark;
451     fwmark.netId = netId;
452     fwmark.explicitlySelected = true;
453     fwmark.permission = permission;
454 
455     Fwmark mask;
456     mask.netId = FWMARK_NET_ID_MASK;
457     mask.explicitlySelected = true;
458     mask.permission = permission;
459 
460     RuleInfo ruleInfo;
461     ruleInfo.ruleTable = table;
462     ruleInfo.rulePriority = RULE_LEVEL_EXPLICIT_NETWORK;
463     ruleInfo.ruleFwmark = fwmark.intValue;
464     ruleInfo.ruleMask = mask.intValue;
465     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
466     ruleInfo.ruleOif = RULEOIF_NULL;
467 
468     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
469 }
470 
UpdateOutputInterfaceRules(const std::string & interfaceName,uint32_t table,NetworkPermission permission,bool add)471 int32_t RouteManager::UpdateOutputInterfaceRules(const std::string &interfaceName, uint32_t table,
472                                                  NetworkPermission permission, bool add)
473 {
474     NETNATIVE_LOGI("Entry RouteManager::UpdateOutputInterfaceRules");
475     Fwmark fwmark;
476     fwmark.permission = permission;
477 
478     Fwmark mask;
479     mask.permission = permission;
480 
481     RuleInfo ruleInfo;
482     ruleInfo.ruleTable = table;
483     ruleInfo.rulePriority = RULE_LEVEL_OUTPUT_INTERFACE;
484     ruleInfo.ruleFwmark = fwmark.intValue;
485     ruleInfo.ruleMask = mask.intValue;
486     ruleInfo.ruleIif = RULEIIF_LOOPBACK;
487     ruleInfo.ruleOif = interfaceName;
488 
489     return UpdateRuleInfo(add ? RTM_NEWRULE : RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
490 }
491 
UpdateSharingNetwork(uint16_t action,const std::string & inputInterface,const std::string & outputInterface)492 int32_t RouteManager::UpdateSharingNetwork(uint16_t action, const std::string &inputInterface,
493                                            const std::string &outputInterface)
494 {
495     NETNATIVE_LOGI("Entry RouteManager::UpdateSharingNetwork");
496     uint32_t table = FindTableByInterfacename(outputInterface);
497     if (table == RT_TABLE_UNSPEC) {
498         return -1;
499     }
500 
501     RuleInfo ruleInfo;
502     ruleInfo.ruleTable = table;
503     ruleInfo.rulePriority = RULE_LEVEL_SHARING;
504     ruleInfo.ruleFwmark = MARK_UNSET;
505     ruleInfo.ruleMask = MARK_UNSET;
506     ruleInfo.ruleIif = inputInterface;
507     ruleInfo.ruleOif = RULEOIF_NULL;
508 
509     return UpdateRuleInfo(action, FR_ACT_TO_TBL, ruleInfo);
510 }
511 
ClearSharingRules(const std::string & inputInterface)512 int32_t RouteManager::ClearSharingRules(const std::string &inputInterface)
513 {
514     NETNATIVE_LOGI("Entry RouteManager::ClearSharingRules");
515 
516     RuleInfo ruleInfo;
517     ruleInfo.ruleTable = 0;
518     ruleInfo.rulePriority = RULE_LEVEL_SHARING;
519     ruleInfo.ruleFwmark = MARK_UNSET;
520     ruleInfo.ruleMask = MARK_UNSET;
521     ruleInfo.ruleIif = inputInterface;
522     ruleInfo.ruleOif = RULEOIF_NULL;
523 
524     return UpdateRuleInfo(RTM_DELRULE, FR_ACT_TO_TBL, ruleInfo);
525 }
526 
UpdateRuleInfo(uint32_t action,uint8_t ruleType,RuleInfo ruleInfo)527 int32_t RouteManager::UpdateRuleInfo(uint32_t action, uint8_t ruleType, RuleInfo ruleInfo)
528 {
529     NETNATIVE_LOGI("Entry RouteManager::UpdateRuleInfo");
530     if (ruleInfo.rulePriority < 0) {
531         NETNATIVE_LOGE("invalid IP-rule priority %{public}d", ruleInfo.rulePriority);
532         return -1;
533     }
534 
535     if (ruleInfo.ruleFwmark & ~ruleInfo.ruleMask) {
536         NETNATIVE_LOGE("mask 0x%{public}x does not select all the bits set in fwmark 0x%{public}x", ruleInfo.ruleMask,
537                        ruleInfo.ruleFwmark);
538         return -1;
539     }
540 
541     if (ruleInfo.ruleTable == RT_TABLE_UNSPEC && ruleType == FR_ACT_TO_TBL && action != RTM_DELRULE) {
542         NETNATIVE_LOGE("RT_TABLE_UNSPEC only allowed when deleting rules");
543         return -ENOTUNIQ;
544     }
545 
546     // The main work is to assemble the structure required for rule.
547     uint16_t ruleFlag = NLM_F_EXCL;
548     if (action == RTM_NEWRULE) {
549         ruleFlag = NLM_F_CREATE;
550     }
551 
552     int32_t ret = SendRuleToKernel(action, ruleFlag, ruleType, ruleInfo);
553     if (ret < 0) {
554         NETNATIVE_LOGE("SendNetlinkMsgToKernel Error, ret = %{public}d", ret);
555         return ret;
556     }
557 
558     return 0;
559 }
560 
SendRuleToKernel(uint32_t action,uint16_t ruleFlag,uint8_t ruleType,RuleInfo ruleInfo)561 int32_t RouteManager::SendRuleToKernel(uint32_t action, uint16_t ruleFlag, uint8_t ruleType, RuleInfo ruleInfo)
562 {
563     struct fib_rule_hdr msg = {0};
564     msg.action = ruleType;
565     msg.family = AF_INET;
566     NetlinkMsg nlmsg(ruleFlag, NETLINK_MAX_LEN, getpid());
567     nlmsg.AddRule(action, msg);
568     if (int32_t ret = nlmsg.AddAttr32(FRA_PRIORITY, ruleInfo.rulePriority)) {
569         return ret;
570     }
571     if (ruleInfo.ruleTable != RT_TABLE_UNSPEC) {
572         if (int32_t ret = nlmsg.AddAttr32(FRA_TABLE, ruleInfo.ruleTable)) {
573             return ret;
574         }
575     }
576     if (ruleInfo.ruleMask != 0) {
577         if (int32_t ret = nlmsg.AddAttr32(FRA_FWMARK, ruleInfo.ruleFwmark)) {
578             return ret;
579         }
580         if (int32_t ret = nlmsg.AddAttr32(FRA_FWMASK, ruleInfo.ruleMask)) {
581             return ret;
582         }
583     }
584     if (ruleInfo.ruleIif != RULEIIF_NULL) {
585         char ruleIifName[IFNAMSIZ] = {0};
586         size_t ruleIifLength = strlcpy(ruleIifName, ruleInfo.ruleIif.c_str(), IFNAMSIZ) + 1;
587         if (int32_t ret = nlmsg.AddAttr(FRA_IIFNAME, ruleIifName, ruleIifLength)) {
588             return ret;
589         }
590     }
591     if (ruleInfo.ruleOif != RULEOIF_NULL) {
592         char ruleOifName[IFNAMSIZ] = {0};
593         size_t ruleOifLength = strlcpy(ruleOifName, ruleInfo.ruleOif.c_str(), IFNAMSIZ) + 1;
594         if (int32_t ret = nlmsg.AddAttr(FRA_OIFNAME, ruleOifName, ruleOifLength)) {
595             return ret;
596         }
597     }
598 
599     return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage());
600 }
601 
UpdateRouteRule(uint16_t action,uint16_t flags,RouteInfo routeInfo)602 int32_t RouteManager::UpdateRouteRule(uint16_t action, uint16_t flags, RouteInfo routeInfo)
603 {
604     NETNATIVE_LOGI("Entry RouteManager::UpdateRouteRule");
605     RouteInfo routeInfoModify = routeInfo;
606     // The main work is to assemble the structure required for route.
607     struct rtmsg msg;
608     (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
609     msg.rtm_family = AF_INET;
610     msg.rtm_dst_len = BIT_32_LEN;
611     msg.rtm_protocol = RTPROT_STATIC;
612     msg.rtm_scope = RT_SCOPE_UNIVERSE;
613     msg.rtm_type = RTN_UNICAST;
614     msg.rtm_table = RT_TABLE_UNSPEC;
615 
616     uint32_t index = 0;
617     if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "unreachable")) {
618         msg.rtm_type = RTN_UNREACHABLE;
619         routeInfoModify.routeInterfaceName = nullptr;
620         routeInfoModify.routeNextHop = nullptr;
621     } else if (!routeInfo.routeNextHop.empty() && !strcmp(routeInfo.routeNextHop.c_str(), "throw")) {
622         msg.rtm_type = RTN_THROW;
623         routeInfoModify.routeInterfaceName = nullptr;
624         routeInfoModify.routeNextHop = nullptr;
625     } else {
626         index = if_nametoindex(routeInfo.routeInterfaceName.c_str());
627     }
628 
629     int32_t ret = SendRouteToKernel(action, flags, msg, routeInfoModify, index);
630     if (ret < 0) {
631         NETNATIVE_LOGE("SendNetlinkMsgToKernel Error ret = %{public}d", ret);
632         return ret;
633     }
634 
635     return 0;
636 }
637 
SendRouteToKernel(uint16_t action,uint16_t routeFlag,rtmsg msg,RouteInfo routeInfo,uint32_t index)638 int32_t RouteManager::SendRouteToKernel(uint16_t action, uint16_t routeFlag, rtmsg msg, RouteInfo routeInfo,
639                                         uint32_t index)
640 {
641     InetAddr dst;
642     int32_t readAddrResult = ReadAddr(routeInfo.routeDestinationName, &dst);
643     if (readAddrResult != 1) {
644         NETNATIVE_LOGE("dest parse failed:%{public}d", readAddrResult);
645         return -1;
646     }
647     msg.rtm_family = static_cast<uint8_t>(dst.family);
648     msg.rtm_dst_len = static_cast<uint8_t>(dst.prefixlen);
649     if (dst.family == AF_INET) {
650         msg.rtm_scope = RT_SCOPE_LINK;
651     } else if (dst.family == AF_INET6) {
652         msg.rtm_scope = RT_SCOPE_UNIVERSE;
653     }
654 
655     InetAddr gw = {0};
656     if (!routeInfo.routeNextHop.empty() && ReadAddrGw(routeInfo.routeNextHop, &gw) <= 0) {
657         NETNATIVE_LOGE("gw parse failed:%{public}d", readAddrResult);
658         return -1;
659     }
660     if (gw.bitlen != 0) {
661         msg.rtm_scope = RT_SCOPE_UNIVERSE;
662         msg.rtm_family = static_cast<uint8_t>(gw.family);
663     }
664     NetlinkMsg nlmsg(routeFlag, NETLINK_MAX_LEN, getpid());
665     nlmsg.AddRoute(action, msg);
666     if (int32_t ret = nlmsg.AddAttr32(RTA_TABLE, routeInfo.routeTable)) {
667         return ret;
668     }
669     if (int32_t ret = nlmsg.AddAttr(RTA_DST, dst.data, dst.bitlen / BYTE_ALIGNMENT)) {
670         return ret;
671     }
672     if (!routeInfo.routeNextHop.empty()) {
673         if (int32_t ret = nlmsg.AddAttr(RTA_GATEWAY, gw.data, gw.bitlen / BYTE_ALIGNMENT)) {
674             return ret;
675         }
676     }
677     if (!routeInfo.routeInterfaceName.empty()) {
678         NETNATIVE_LOGI("index is :%{public}d", index);
679         if (int32_t ret = nlmsg.AddAttr32(RTA_OIF, index)) {
680             return ret;
681         }
682     }
683 
684     return SendNetlinkMsgToKernel(nlmsg.GetNetLinkMessage());
685 }
686 
FindTableByInterfacename(const std::string & interfaceName)687 uint32_t RouteManager::FindTableByInterfacename(const std::string &interfaceName)
688 {
689     auto iter = interfaceToTable_.find(interfaceName);
690     if (iter != interfaceToTable_.end()) {
691         return iter->second;
692     }
693 
694     uint32_t table = if_nametoindex(interfaceName.c_str());
695     if (table == 0) {
696         NETNATIVE_LOGE("RouteManager cannot find interface %{public}s", interfaceName.c_str());
697         return RT_TABLE_UNSPEC;
698     }
699     table += THOUSAND_LEN;
700     interfaceToTable_[interfaceName] = table;
701     return table;
702 }
703 
GetRouteTableFromType(TableType tableType,const std::string & interfaceName)704 uint32_t RouteManager::GetRouteTableFromType(TableType tableType, const std::string &interfaceName)
705 {
706     uint32_t table;
707     if (tableType == RouteManager::INTERFACE) {
708         table = FindTableByInterfacename(interfaceName);
709     } else if (tableType == RouteManager::LOCAL_NETWORK) {
710         table = ROUTE_LOCAL_NETWORK_TABLE;
711     } else if (tableType == RouteManager::VPN_NETWORK) {
712         table = ROUTE_VPN_NETWORK_TABLE;
713     } else {
714         table = 0;
715         NETNATIVE_LOGE("tableType is error");
716     }
717     return table;
718 }
719 } // namespace nmd
720 } // namespace OHOS
721