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