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