• 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 #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