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 #include "wifi_ap_nat_manager.h"
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <cerrno>
20 #include <cstdlib>
21 #include <cstring>
22 #include <fstream>
23 #include <vector>
24 #include "network_interface.h"
25 #include "if_config.h"
26 #include "wifi_logger.h"
27
28 DEFINE_WIFILOG_HOTSPOT_LABEL("WifiApNatManager");
29
30
31 namespace OHOS {
32 namespace Wifi {
33 const std::string SYSTEM_COMMAND_IP = "/system/bin/ip";
34 const std::string SYSTEM_COMMAND_IPTABLES = "/system/bin/iptables";
35 const std::string SYSTEM_COMMAND_IP6TABLES = "/system/bin/ip6tables";
36 const std::string IP_V4_FORWARDING_CONFIG_FILE = "/proc/sys/net/ipv4/ip_forward";
37 const std::string IP_V6_FORWARDING_CONFIG_FILE = "/proc/sys/net/ipv6/conf/all/forwarding";
38
EnableInterfaceNat(bool enable,std::string inInterfaceName,std::string outInterfaceName) const39 bool WifiApNatManager::EnableInterfaceNat(bool enable, std::string inInterfaceName, std::string outInterfaceName) const
40 {
41 WIFI_LOGI("EnableInterfaceNat enable [%{public}s], inInterfaceName [%{private}s] outInterfaceName "
42 "[%{private}s].",
43 enable ? "true" : "false",
44 inInterfaceName.c_str(),
45 outInterfaceName.c_str());
46
47 if (!NetworkInterface::IsValidInterfaceName(inInterfaceName) ||
48 !NetworkInterface::IsValidInterfaceName(outInterfaceName)) {
49 WIFI_LOGE("Invalid interface name.");
50 return false;
51 }
52
53 if (inInterfaceName == outInterfaceName) {
54 WIFI_LOGI("Duplicate interface no need NAT.");
55 return false;
56 }
57
58 if (!SetForwarding(enable)) {
59 WIFI_LOGE("SetForwarding failed.");
60 return false;
61 }
62
63 if (!SetInterfaceRoute(enable)) {
64 WIFI_LOGE("SetInterfaceRoute failed.");
65 return false;
66 }
67
68 if (!SetInterfaceNat(enable, outInterfaceName)) {
69 WIFI_LOGE("SetInterfaceNat failed.");
70 return false;
71 }
72
73 return true;
74 }
75
SetForwarding(bool enable) const76 bool WifiApNatManager::SetForwarding(bool enable) const
77 {
78 WIFI_LOGI("SetForwarding enable = %{public}s.", ((enable) ? "true" : "false"));
79
80 bool bResult = true;
81 const std::string content = enable ? "1" : "0";
82 bResult = bResult && WriteDataToFile(IP_V4_FORWARDING_CONFIG_FILE, content);
83 bResult = bResult && WriteDataToFile(IP_V6_FORWARDING_CONFIG_FILE, content);
84 return bResult;
85 }
86
SetInterfaceRoute(bool enable) const87 bool WifiApNatManager::SetInterfaceRoute(bool enable) const
88 {
89 const std::string natRouteTable = "10";
90 std::vector<std::string> ipRouteCmd;
91
92 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
93 ipRouteCmd.push_back("rule");
94 ipRouteCmd.push_back(enable ? "add" : "del");
95 ipRouteCmd.push_back("fwmark");
96 ipRouteCmd.push_back("0x0/0xffff");
97 ipRouteCmd.push_back("lookup");
98 ipRouteCmd.push_back("254");
99 ipRouteCmd.push_back("prio");
100 ipRouteCmd.push_back("18000");
101 IfConfig::GetInstance().ExecCommand(ipRouteCmd);
102
103 /* Refresh the cache */
104 ipRouteCmd.clear();
105 ipRouteCmd.push_back(SYSTEM_COMMAND_IP);
106 ipRouteCmd.push_back("route");
107 ipRouteCmd.push_back("flush");
108 ipRouteCmd.push_back("cache");
109 IfConfig::GetInstance().ExecCommand(ipRouteCmd);
110
111 return true;
112 }
113
SetInterfaceNat(bool enable,const std::string & outInterfaceName) const114 bool WifiApNatManager::SetInterfaceNat(bool enable, const std::string &outInterfaceName) const
115 {
116 std::vector<std::string> iptablesCmd;
117
118 /* Clearing the Firewalls */
119 iptablesCmd.push_back(SYSTEM_COMMAND_IPTABLES);
120 iptablesCmd.push_back("-F");
121 IfConfig::GetInstance().ExecCommand(iptablesCmd);
122
123 /* iptable forward ACCEPT */
124 iptablesCmd.clear();
125 iptablesCmd.push_back(SYSTEM_COMMAND_IPTABLES);
126 iptablesCmd.push_back("-P");
127 iptablesCmd.push_back("FORWARD");
128 iptablesCmd.push_back(enable ? "ACCEPT" : "DROP");
129 IfConfig::GetInstance().ExecCommand(iptablesCmd);
130
131 /* Setting NAT Rules */
132 iptablesCmd.clear();
133 iptablesCmd.push_back(SYSTEM_COMMAND_IPTABLES);
134 iptablesCmd.push_back("-t");
135 iptablesCmd.push_back("nat");
136 iptablesCmd.push_back(enable ? "-A" : "-D");
137 iptablesCmd.push_back("POSTROUTING");
138 iptablesCmd.push_back("-o");
139 iptablesCmd.push_back(outInterfaceName);
140 iptablesCmd.push_back("-j");
141 iptablesCmd.push_back("MASQUERADE");
142 IfConfig::GetInstance().ExecCommand(iptablesCmd);
143
144 return true;
145 }
146
WriteDataToFile(const std::string & fileName,const std::string & content) const147 bool WifiApNatManager::WriteDataToFile(const std::string &fileName, const std::string &content) const
148 {
149 std::ofstream outf(fileName, std::ios::out);
150 if (!outf) {
151 WIFI_LOGE("write content [%{public}s] to file [%{public}s] failed. error: %{public}d.",
152 content.c_str(), fileName.c_str(), errno);
153 return false;
154 }
155 outf.write(content.c_str(), content.length());
156 outf.close();
157 return true;
158 }
159 } // namespace Wifi
160 } // namespace OHOS