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