1 /*
2 * Copyright (c) 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 "sharing_manager.h"
17
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <regex>
21 #include <unistd.h>
22
23 #include "net_manager_constants.h"
24 #include "netmanager_base_common_utils.h"
25 #include "netnative_log_wrapper.h"
26 #include "route_manager.h"
27
28 namespace OHOS {
29 namespace nmd {
30 using namespace NetManagerStandard;
31 namespace {
32 constexpr const char *IPV4_FORWARDING_PROC_FILE = "/proc/sys/net/ipv4/ip_forward";
33 constexpr const char *IPV6_FORWARDING_PROC_FILE = "/proc/sys/net/ipv6/conf/all/forwarding";
34 constexpr const char *IPTABLES_TMP_BAK = "/data/service/el1/public/netmanager/ipfwd.bak";
35
36 constexpr const int MAX_MATCH_SIZE = 4;
37 constexpr const int TWO_LIST_CORRECT_DATA = 2;
38 constexpr const int NEXT_LIST_CORRECT_DATA = 1;
39 constexpr uint32_t NET_TRAFFIC_RESULT_INDEX_OFFSET = 2;
40
41 // commands of create tables
42 constexpr const char *CREATE_TETHERCTRL_NAT_POSTROUTING = "-t nat -N tetherctrl_nat_POSTROUTING";
43 constexpr const char *CREATE_TETHERCTRL_FORWARD = "-t filter -N tetherctrl_FORWARD";
44 constexpr const char *CREATE_TETHERCTRL_COUNTERS = "-t filter -N tetherctrl_counters";
45 constexpr const char *CREATE_TETHERCTRL_MANGLE_FORWARD = "-t mangle -N tetherctrl_mangle_FORWARD";
46
47 // commands of set nat
48 constexpr const char *APPEND_NAT_POSTROUTING = "-t nat -A POSTROUTING -j tetherctrl_nat_POSTROUTING";
49 constexpr const char *APPEND_MANGLE_FORWARD = "-t mangle -A FORWARD -j tetherctrl_mangle_FORWARD";
50 constexpr const char *APPEND_TETHERCTRL_MANGLE_FORWARD =
51 "-t mangle -A tetherctrl_mangle_FORWARD "
52 "-p tcp -m tcp --tcp-flags SYN SYN -j TCPMSS --clamp-mss-to-pmtu";
53 constexpr const char *CLEAR_TETHERCTRL_NAT_POSTROUTING = "-t nat -F tetherctrl_nat_POSTROUTING";
54 constexpr const char *CLEAR_TETHERCTRL_MANGLE_FORWARD = "-t mangle -F tetherctrl_mangle_FORWARD";
55 constexpr const char *DELETE_TETHERCTRL_NAT_POSTROUTING = "-t nat -D POSTROUTING -j tetherctrl_nat_POSTROUTING";
56 constexpr const char *DELETE_TETHERCTRL_MANGLE_FORWARD = "-t mangle -D FORWARD -j tetherctrl_mangle_FORWARD";
57
58 constexpr const char *IPATBLES_RESTORE_CMD_PATH = "/system/bin/iptables-restore";
59 constexpr const char *IPATBLES_SAVE_CMD_PATH = "/system/bin/iptables-save";
60
EnableNatCmd(const std::string & down)61 const std::string EnableNatCmd(const std::string &down)
62 {
63 return "-t nat -A tetherctrl_nat_POSTROUTING -o " + down + " -j MASQUERADE";
64 }
65
66 // commands of set ipfwd, all commands with filter
67 constexpr const char *FORWARD_JUMP_TETHERCTRL_FORWARD = " FORWARD -j tetherctrl_FORWARD";
68 constexpr const char *SET_TETHERCTRL_FORWARD_DROP = " tetherctrl_FORWARD -j DROP";
SetTetherctrlForward1(const std::string & from,const std::string & to)69 const std::string SetTetherctrlForward1(const std::string &from, const std::string &to)
70 {
71 return " tetherctrl_FORWARD -i " + from + " -o " + to +
72 " -m state --state RELATED,ESTABLISHED"
73 " -g tetherctrl_counters";
74 }
75
SetTetherctrlForward2(const std::string & from,const std::string & to)76 const std::string SetTetherctrlForward2(const std::string &from, const std::string &to)
77 {
78 return " tetherctrl_FORWARD -i " + to + " -o " + from + " -m state --state INVALID -j DROP";
79 }
80
SetTetherctrlForward3(const std::string & from,const std::string & to)81 const std::string SetTetherctrlForward3(const std::string &from, const std::string &to)
82 {
83 return " tetherctrl_FORWARD -i " + to + " -o " + from + " -g tetherctrl_counters";
84 }
85
SetTetherctrlCounters1(const std::string & from,const std::string & to)86 const std::string SetTetherctrlCounters1(const std::string &from, const std::string &to)
87 {
88 return " tetherctrl_counters -i " + to + " -o " + from + " -j RETURN";
89 }
90
SetTetherctrlCounters2(const std::string & from,const std::string & to)91 const std::string SetTetherctrlCounters2(const std::string &from, const std::string &to)
92 {
93 return " tetherctrl_counters -i " + from + " -o " + to + " -j RETURN";
94 }
95
WriteToFile(const char * fileName,const char * value)96 bool WriteToFile(const char *fileName, const char *value)
97 {
98 if (fileName == nullptr) {
99 return false;
100 }
101 int fd = open(fileName, O_WRONLY | O_CLOEXEC);
102 if (fd < 0) {
103 NETNATIVE_LOGE("failed to open %{private}s: %{public}s", fileName, strerror(errno));
104 return false;
105 }
106
107 const ssize_t len = strlen(value);
108 if (write(fd, value, len) != len) {
109 NETNATIVE_LOGE("faield to write %{public}s to %{private}s: %{public}s", value, fileName, strerror(errno));
110 close(fd);
111 return false;
112 }
113
114 close(fd);
115 return true;
116 }
117
Rollback()118 void Rollback()
119 {
120 NETNATIVE_LOGE("iptables rollback");
121 std::string rollBak = std::string(IPATBLES_RESTORE_CMD_PATH) + " -T filter < ";
122 rollBak.append(IPTABLES_TMP_BAK);
123 CommonUtils::ForkExec(rollBak);
124 }
125 } // namespace
126
SharingManager()127 SharingManager::SharingManager()
128 {
129 iptablesWrapper_ = DelayedSingleton<IptablesWrapper>::GetInstance();
130 }
131
InitChildChains()132 void SharingManager::InitChildChains()
133 {
134 iptablesWrapper_->RunCommand(IPTYPE_IPV4, CREATE_TETHERCTRL_NAT_POSTROUTING);
135 iptablesWrapper_->RunCommand(IPTYPE_IPV4, CREATE_TETHERCTRL_FORWARD);
136 iptablesWrapper_->RunCommand(IPTYPE_IPV4, CREATE_TETHERCTRL_COUNTERS);
137 iptablesWrapper_->RunCommand(IPTYPE_IPV4, CREATE_TETHERCTRL_MANGLE_FORWARD);
138 inited_ = true;
139 }
140
IpEnableForwarding(const std::string & requestor)141 int32_t SharingManager::IpEnableForwarding(const std::string &requestor)
142 {
143 NETNATIVE_LOG_D("IpEnableForwarding requestor: %{public}s", requestor.c_str());
144 forwardingRequests_.insert(requestor);
145 return SetIpFwdEnable();
146 }
147
IpDisableForwarding(const std::string & requestor)148 int32_t SharingManager::IpDisableForwarding(const std::string &requestor)
149 {
150 NETNATIVE_LOG_D("IpDisableForwarding requestor: %{public}s", requestor.c_str());
151 forwardingRequests_.erase(requestor);
152 return SetIpFwdEnable();
153 }
154
EnableNat(const std::string & downstreamIface,const std::string & upstreamIface)155 int32_t SharingManager::EnableNat(const std::string &downstreamIface, const std::string &upstreamIface)
156 {
157 CheckInited();
158 if (downstreamIface == upstreamIface) {
159 NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", downstreamIface.c_str(),
160 upstreamIface.c_str());
161 return -1;
162 }
163 if (!CommonUtils::CheckIfaceName(upstreamIface)) {
164 NETNATIVE_LOGE("iface name valid check fail: %{public}s", upstreamIface.c_str());
165 return -1;
166 }
167 iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_NAT_POSTROUTING);
168 iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_MANGLE_FORWARD);
169
170 NETNATIVE_LOGI("EnableNat downstreamIface: %{public}s, upstreamIface: %{public}s", downstreamIface.c_str(),
171 upstreamIface.c_str());
172
173 if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, EnableNatCmd(upstreamIface)) !=
174 NetManagerStandard::NETMANAGER_SUCCESS) {
175 NETNATIVE_LOGE("IptablesWrapper run command failed");
176 return -1;
177 }
178
179 if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_TETHERCTRL_MANGLE_FORWARD) !=
180 NetManagerStandard::NETMANAGER_SUCCESS) {
181 NETNATIVE_LOGE("IptablesWrapper run command failed");
182 return -1;
183 }
184 return 0;
185 }
186
DisableNat(const std::string & downstreamIface,const std::string & upstreamIface)187 int32_t SharingManager::DisableNat(const std::string &downstreamIface, const std::string &upstreamIface)
188 {
189 CheckInited();
190 if (downstreamIface == upstreamIface) {
191 NETNATIVE_LOGE("Duplicate interface specified: %{public}s %s", downstreamIface.c_str(),
192 upstreamIface.c_str());
193 return -1;
194 }
195 if (!CommonUtils::CheckIfaceName(upstreamIface)) {
196 NETNATIVE_LOGE("iface name valid check fail: %{public}s", upstreamIface.c_str());
197 return -1;
198 }
199
200 NETNATIVE_LOGI("DisableNat downstreamIface: %{public}s, upstreamIface: %{public}s", downstreamIface.c_str(),
201 upstreamIface.c_str());
202
203 if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, CLEAR_TETHERCTRL_NAT_POSTROUTING) !=
204 NetManagerStandard::NETMANAGER_SUCCESS) {
205 NETNATIVE_LOGE("IptablesWrapper run command failed");
206 return -1;
207 }
208 if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, CLEAR_TETHERCTRL_MANGLE_FORWARD) !=
209 NetManagerStandard::NETMANAGER_SUCCESS) {
210 NETNATIVE_LOGE("IptablesWrapper run command failed");
211 return -1;
212 }
213
214 iptablesWrapper_->RunCommand(IPTYPE_IPV4, DELETE_TETHERCTRL_NAT_POSTROUTING);
215 iptablesWrapper_->RunCommand(IPTYPE_IPV4, DELETE_TETHERCTRL_MANGLE_FORWARD);
216 return 0;
217 }
218
SetIpFwdEnable()219 int32_t SharingManager::SetIpFwdEnable()
220 {
221 bool disable = forwardingRequests_.empty();
222 const char *value = disable ? "0" : "1";
223 bool ipv4Success = WriteToFile(IPV4_FORWARDING_PROC_FILE, value);
224 bool ipv6Success = WriteToFile(IPV6_FORWARDING_PROC_FILE, value);
225 return (ipv4Success && ipv6Success) ? 0 : -1;
226 }
227
IpfwdAddInterfaceForward(const std::string & fromIface,const std::string & toIface)228 int32_t SharingManager::IpfwdAddInterfaceForward(const std::string &fromIface, const std::string &toIface)
229 {
230 CheckInited();
231 if (fromIface == toIface) {
232 NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
233 return -1;
234 }
235 if (!(CommonUtils::CheckIfaceName(fromIface)) || !(CommonUtils::CheckIfaceName(toIface))) {
236 NETNATIVE_LOGE("iface name valid check fail: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
237 return -1;
238 }
239 NETNATIVE_LOGI("IpfwdAddInterfaceForward fromIface: %{public}s, toIface: %{public}s", fromIface.c_str(),
240 toIface.c_str());
241
242 if (interfaceForwards_.empty()) {
243 SetForwardRules(true, FORWARD_JUMP_TETHERCTRL_FORWARD);
244 }
245 int32_t result = 0;
246 std::string saveBak = std::string(IPATBLES_SAVE_CMD_PATH) + " -t filter > ";
247 saveBak.append(IPTABLES_TMP_BAK);
248 CommonUtils::ForkExec(saveBak);
249
250 /*
251 * Add a forward rule, when the status of packets is RELATED,
252 * ESTABLISED and from fromIface to toIface, goto tetherctrl_counters
253 */
254 result = SetForwardRules(true, SetTetherctrlForward1(toIface, fromIface));
255 if (result) {
256 return result;
257 }
258
259 /*
260 * Add a forward rule, when the status is INVALID and from toIface to fromIface, just drop
261 */
262 result = SetForwardRules(true, SetTetherctrlForward2(toIface, fromIface));
263 if (result) {
264 Rollback();
265 return result;
266 }
267
268 /*
269 * Add a forward rule, from toIface to fromIface, goto tetherctrl_counters
270 */
271 result = SetForwardRules(true, SetTetherctrlForward3(toIface, fromIface));
272 if (result) {
273 Rollback();
274 return result;
275 }
276
277 /*
278 * Add a forward rule, drop others
279 */
280 result = SetForwardRules(true, SET_TETHERCTRL_FORWARD_DROP);
281 if (result) {
282 Rollback();
283 return result;
284 }
285
286 /*
287 * Add a forward rule, if from toIface to fromIface return chain of father
288 */
289 result = SetForwardRules(true, SetTetherctrlCounters1(fromIface, toIface));
290 if (result) {
291 Rollback();
292 return result;
293 }
294
295 /*
296 * Add a forward rule, if from fromIface to toIface return chain of father
297 */
298 result = SetForwardRules(true, SetTetherctrlCounters2(fromIface, toIface));
299 if (result) {
300 Rollback();
301 return result;
302 }
303
304 result = RouteManager::EnableSharing(fromIface, toIface);
305 if (result) {
306 Rollback();
307 return result;
308 }
309 interfaceForwards_.insert(fromIface + toIface);
310 return 0;
311 }
312
IpfwdRemoveInterfaceForward(const std::string & fromIface,const std::string & toIface)313 int32_t SharingManager::IpfwdRemoveInterfaceForward(const std::string &fromIface, const std::string &toIface)
314 {
315 CheckInited();
316 if (fromIface == toIface) {
317 NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
318 return -1;
319 }
320 if (!(CommonUtils::CheckIfaceName(fromIface)) || !(CommonUtils::CheckIfaceName(toIface))) {
321 NETNATIVE_LOGE("iface name valid check fail: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
322 return -1;
323 }
324 NETNATIVE_LOGI("IpfwdRemoveInterfaceForward fromIface: %{public}s, toIface: %{public}s", fromIface.c_str(),
325 toIface.c_str());
326
327 SetForwardRules(false, SetTetherctrlForward1(toIface, fromIface));
328 SetForwardRules(false, SetTetherctrlForward2(toIface, fromIface));
329 SetForwardRules(false, SetTetherctrlForward3(toIface, fromIface));
330 SetForwardRules(false, SET_TETHERCTRL_FORWARD_DROP);
331 SetForwardRules(false, SetTetherctrlCounters1(fromIface, toIface));
332 SetForwardRules(false, SetTetherctrlCounters2(fromIface, toIface));
333
334 RouteManager::DisableSharing(fromIface, toIface);
335
336 interfaceForwards_.erase(fromIface + toIface);
337 if (interfaceForwards_.empty()) {
338 SetForwardRules(false, FORWARD_JUMP_TETHERCTRL_FORWARD);
339 }
340
341 return 0;
342 }
343
GetNetworkSharingTraffic(const std::string & downIface,const std::string & upIface,NetworkSharingTraffic & traffic)344 int32_t SharingManager::GetNetworkSharingTraffic(const std::string &downIface, const std::string &upIface,
345 NetworkSharingTraffic &traffic)
346 {
347 const std::string cmds = "-t filter -L tetherctrl_counters -nvx";
348 std::string result = iptablesWrapper_->RunCommandForRes(IPTYPE_IPV4, cmds);
349
350 const std::string num = "(\\d+)";
351 const std::string iface = "([^\\s]+)";
352 const std::string dst = "(0.0.0.0/0|::/0)";
353 const std::string counters = "\\s*" + num + "\\s+" + num + " RETURN all( -- | )" + iface + "\\s+" +
354 iface + "\\s+" + dst + "\\s+" + dst;
355 static const std::regex IP_RE(counters);
356
357 bool isFindTx = false;
358 bool isFindRx = false;
359 const std::vector<std::string> lines = CommonUtils::Split(result, "\n");
360 for (auto line : lines) {
361 std::smatch matches;
362 std::regex_search(line, matches, IP_RE);
363 if (matches.size() < MAX_MATCH_SIZE) {
364 continue;
365 }
366 for (uint32_t i = 0; i < matches.size() - 1; i++) {
367 std::string tempMatch = matches[i];
368 NETNATIVE_LOG_D("GetNetworkSharingTraffic matche[%{public}s]", tempMatch.c_str());
369 if (matches[i] == downIface && matches[i + NEXT_LIST_CORRECT_DATA] == upIface &&
370 ((i - TWO_LIST_CORRECT_DATA) >= 0)) {
371 int64_t send =
372 static_cast<int64_t>(strtoul(matches[i - TWO_LIST_CORRECT_DATA].str().c_str(), nullptr, 0));
373 isFindTx = true;
374 traffic.send = send;
375 traffic.all += send;
376 } else if (matches[i] == upIface && matches[i + NEXT_LIST_CORRECT_DATA] == downIface &&
377 ((i - NET_TRAFFIC_RESULT_INDEX_OFFSET) >= 0)) {
378 int64_t receive =
379 static_cast<int64_t>(strtoul(matches[i - TWO_LIST_CORRECT_DATA].str().c_str(), nullptr, 0));
380 isFindRx = true;
381 traffic.receive = receive;
382 traffic.all += receive;
383 }
384 if (isFindTx && isFindRx) {
385 NETNATIVE_LOG_D("GetNetworkSharingTraffic success total");
386 return NETMANAGER_SUCCESS;
387 }
388 }
389 }
390 NETNATIVE_LOGE("GetNetworkSharingTraffic failed");
391 return NETMANAGER_ERROR;
392 }
393
CheckInited()394 void SharingManager::CheckInited()
395 {
396 std::lock_guard<std::mutex> guard(initedMutex_);
397 if (inited_) {
398 return;
399 }
400 InitChildChains();
401 }
402
SetForwardRules(bool set,const std::string & cmds)403 int32_t SharingManager::SetForwardRules(bool set, const std::string &cmds)
404 {
405 const std::string op = set ? "-A" : "-D";
406
407 if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, "-t filter " + op + cmds) !=
408 NetManagerStandard::NETMANAGER_SUCCESS) {
409 NETNATIVE_LOGE("IptablesWrapper run command failed");
410 return -1;
411 }
412 return 0;
413 }
414 } // namespace nmd
415 } // namespace OHOS
416