• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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_ = 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     {
145         std::lock_guard<std::mutex> guard(initedMutex_);
146         forwardingRequests_.insert(requestor);
147     }
148     return SetIpFwdEnable();
149 }
150 
IpDisableForwarding(const std::string & requestor)151 int32_t SharingManager::IpDisableForwarding(const std::string &requestor)
152 {
153     NETNATIVE_LOG_D("IpDisableForwarding requestor: %{public}s", requestor.c_str());
154     {
155         std::lock_guard<std::mutex> guard(initedMutex_);
156         forwardingRequests_.erase(requestor);
157     }
158     return SetIpFwdEnable();
159 }
160 
EnableNat(const std::string & downstreamIface,const std::string & upstreamIface)161 int32_t SharingManager::EnableNat(const std::string &downstreamIface, const std::string &upstreamIface)
162 {
163     CheckInited();
164     if (downstreamIface == upstreamIface) {
165         NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", downstreamIface.c_str(),
166                        upstreamIface.c_str());
167         return -1;
168     }
169     if (!CommonUtils::CheckIfaceName(upstreamIface)) {
170         NETNATIVE_LOGE("iface name valid check fail: %{public}s", upstreamIface.c_str());
171         return -1;
172     }
173     iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_NAT_POSTROUTING);
174     iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_MANGLE_FORWARD);
175 
176     NETNATIVE_LOGI("EnableNat downstreamIface: %{public}s, upstreamIface: %{public}s", downstreamIface.c_str(),
177                    upstreamIface.c_str());
178 
179     if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, EnableNatCmd(upstreamIface)) !=
180         NetManagerStandard::NETMANAGER_SUCCESS) {
181         NETNATIVE_LOGE("IptablesWrapper run command failed");
182         return -1;
183     }
184 
185     if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, APPEND_TETHERCTRL_MANGLE_FORWARD) !=
186         NetManagerStandard::NETMANAGER_SUCCESS) {
187         NETNATIVE_LOGE("IptablesWrapper run command failed");
188         return -1;
189     }
190     return 0;
191 }
192 
DisableNat(const std::string & downstreamIface,const std::string & upstreamIface)193 int32_t SharingManager::DisableNat(const std::string &downstreamIface, const std::string &upstreamIface)
194 {
195     CheckInited();
196     if (downstreamIface == upstreamIface) {
197         NETNATIVE_LOGE("Duplicate interface specified: %{public}s %s", downstreamIface.c_str(), upstreamIface.c_str());
198         return -1;
199     }
200     if (!CommonUtils::CheckIfaceName(upstreamIface)) {
201         NETNATIVE_LOGE("iface name valid check fail: %{public}s", upstreamIface.c_str());
202         return -1;
203     }
204 
205     NETNATIVE_LOGI("DisableNat downstreamIface: %{public}s, upstreamIface: %{public}s", downstreamIface.c_str(),
206                    upstreamIface.c_str());
207 
208     if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, CLEAR_TETHERCTRL_NAT_POSTROUTING) !=
209         NetManagerStandard::NETMANAGER_SUCCESS) {
210         NETNATIVE_LOGE("IptablesWrapper run command failed");
211         return -1;
212     }
213     if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, CLEAR_TETHERCTRL_MANGLE_FORWARD) !=
214         NetManagerStandard::NETMANAGER_SUCCESS) {
215         NETNATIVE_LOGE("IptablesWrapper run command failed");
216         return -1;
217     }
218 
219     iptablesWrapper_->RunCommand(IPTYPE_IPV4, DELETE_TETHERCTRL_NAT_POSTROUTING);
220     iptablesWrapper_->RunCommand(IPTYPE_IPV4, DELETE_TETHERCTRL_MANGLE_FORWARD);
221     return 0;
222 }
223 
SetIpFwdEnable()224 int32_t SharingManager::SetIpFwdEnable()
225 {
226     bool disable = forwardingRequests_.empty();
227     const char *value = disable ? "0" : "1";
228     bool ipv4Success = WriteToFile(IPV4_FORWARDING_PROC_FILE, value);
229     bool ipv6Success = WriteToFile(IPV6_FORWARDING_PROC_FILE, value);
230     return (ipv4Success && ipv6Success) ? 0 : -1;
231 }
232 
IpfwdAddInterfaceForward(const std::string & fromIface,const std::string & toIface)233 int32_t SharingManager::IpfwdAddInterfaceForward(const std::string &fromIface, const std::string &toIface)
234 {
235     CheckInited();
236     if (fromIface == toIface) {
237         NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
238         return -1;
239     }
240     if (!(CommonUtils::CheckIfaceName(fromIface)) || !(CommonUtils::CheckIfaceName(toIface))) {
241         NETNATIVE_LOGE("iface name valid check fail: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
242         return -1;
243     }
244     NETNATIVE_LOGI("IpfwdAddInterfaceForward fromIface: %{public}s, toIface: %{public}s", fromIface.c_str(),
245                    toIface.c_str());
246 
247     if (interfaceForwards_.empty()) {
248         SetForwardRules(true, FORWARD_JUMP_TETHERCTRL_FORWARD);
249     }
250     int32_t result = 0;
251     std::string saveBak = std::string(IPATBLES_SAVE_CMD_PATH) + " -t filter > ";
252     saveBak.append(IPTABLES_TMP_BAK);
253     CommonUtils::ForkExec(saveBak);
254 
255     /*
256      * Add a forward rule, when the status of packets is RELATED,
257      * ESTABLISED and from fromIface to toIface, goto tetherctrl_counters
258      */
259     if (SetForwardRules(true, SetTetherctrlForward1(toIface, fromIface))) {
260         return result;
261     }
262 
263     /*
264      * Add a forward rule, when the status is INVALID and from toIface to fromIface, just drop
265      */
266     if (SetForwardRules(true, SetTetherctrlForward2(toIface, fromIface))) {
267         Rollback();
268         return result;
269     }
270 
271     /*
272      * Add a forward rule, from toIface to fromIface, goto tetherctrl_counters
273      */
274     if (SetForwardRules(true, SetTetherctrlForward3(toIface, fromIface))) {
275         Rollback();
276         return result;
277     }
278 
279     /*
280      * Add a forward rule, drop others
281      */
282     if (SetForwardRules(true, SET_TETHERCTRL_FORWARD_DROP)) {
283         Rollback();
284         return result;
285     }
286 
287     /*
288      * Add a forward rule, if from toIface to fromIface return chain of father
289      */
290     if (SetForwardRules(true, SetTetherctrlCounters1(fromIface, toIface))) {
291         Rollback();
292         return result;
293     }
294 
295     /*
296      * Add a forward rule, if from fromIface to toIface return chain of father
297      */
298     if (SetForwardRules(true, SetTetherctrlCounters2(fromIface, toIface))) {
299         Rollback();
300         return result;
301     }
302 
303     if (RouteManager::EnableSharing(fromIface, toIface)) {
304         Rollback();
305         return result;
306     }
307     interfaceForwards_.insert(fromIface + toIface);
308     return 0;
309 }
310 
IpfwdRemoveInterfaceForward(const std::string & fromIface,const std::string & toIface)311 int32_t SharingManager::IpfwdRemoveInterfaceForward(const std::string &fromIface, const std::string &toIface)
312 {
313     CheckInited();
314     if (fromIface == toIface) {
315         NETNATIVE_LOGE("Duplicate interface specified: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
316         return -1;
317     }
318     if (!(CommonUtils::CheckIfaceName(fromIface)) || !(CommonUtils::CheckIfaceName(toIface))) {
319         NETNATIVE_LOGE("iface name valid check fail: %{public}s %{public}s", fromIface.c_str(), toIface.c_str());
320         return -1;
321     }
322     NETNATIVE_LOGI("IpfwdRemoveInterfaceForward fromIface: %{public}s, toIface: %{public}s", fromIface.c_str(),
323                    toIface.c_str());
324 
325     SetForwardRules(false, SetTetherctrlForward1(toIface, fromIface));
326     SetForwardRules(false, SetTetherctrlForward2(toIface, fromIface));
327     SetForwardRules(false, SetTetherctrlForward3(toIface, fromIface));
328     SetForwardRules(false, SET_TETHERCTRL_FORWARD_DROP);
329     SetForwardRules(false, SetTetherctrlCounters1(fromIface, toIface));
330     SetForwardRules(false, SetTetherctrlCounters2(fromIface, toIface));
331 
332     RouteManager::DisableSharing(fromIface, toIface);
333 
334     interfaceForwards_.erase(fromIface + toIface);
335     if (interfaceForwards_.empty()) {
336         SetForwardRules(false, FORWARD_JUMP_TETHERCTRL_FORWARD);
337     }
338 
339     return 0;
340 }
341 
GetNetworkSharingTraffic(const std::string & downIface,const std::string & upIface,NetworkSharingTraffic & traffic)342 int32_t SharingManager::GetNetworkSharingTraffic(const std::string &downIface, const std::string &upIface,
343                                                  NetworkSharingTraffic &traffic)
344 {
345     const std::string cmds = "-t filter -L tetherctrl_counters -nvx";
346     std::string result = iptablesWrapper_->RunCommandForRes(IPTYPE_IPV4, cmds);
347 
348     const std::string num = "(\\d+)";
349     const std::string iface = "([^\\s]+)";
350     const std::string dst = "(0.0.0.0/0|::/0)";
351     const std::string counters = "\\s*" + num + "\\s+" + num + " RETURN     all(  --  |      )" + iface + "\\s+" +
352                                  iface + "\\s+" + dst + "\\s+" + dst;
353     static const std::regex IP_RE(counters);
354 
355     bool isFindTx = false;
356     bool isFindRx = false;
357     const std::vector<std::string> lines = CommonUtils::Split(result, "\n");
358     for (auto line : lines) {
359         std::smatch matches;
360         std::regex_search(line, matches, IP_RE);
361         if (matches.size() < MAX_MATCH_SIZE) {
362             continue;
363         }
364         for (uint32_t i = 0; i < matches.size() - 1; i++) {
365             std::string tempMatch = matches[i];
366             NETNATIVE_LOG_D("GetNetworkSharingTraffic matche[%{public}s]", tempMatch.c_str());
367             if (matches[i] == downIface && matches[i + NEXT_LIST_CORRECT_DATA] == upIface &&
368                 ((i - TWO_LIST_CORRECT_DATA) >= 0)) {
369                 int64_t send =
370                     static_cast<int64_t>(strtoul(matches[i - TWO_LIST_CORRECT_DATA].str().c_str(), nullptr, 0));
371                 isFindTx = true;
372                 traffic.send = send;
373                 traffic.all += send;
374             } else if (matches[i] == upIface && matches[i + NEXT_LIST_CORRECT_DATA] == downIface &&
375                        ((i - NET_TRAFFIC_RESULT_INDEX_OFFSET) >= 0)) {
376                 int64_t receive =
377                     static_cast<int64_t>(strtoul(matches[i - TWO_LIST_CORRECT_DATA].str().c_str(), nullptr, 0));
378                 isFindRx = true;
379                 traffic.receive = receive;
380                 traffic.all += receive;
381             }
382             if (isFindTx && isFindRx) {
383                 NETNATIVE_LOG_D("GetNetworkSharingTraffic success total");
384                 return NETMANAGER_SUCCESS;
385             }
386         }
387     }
388     NETNATIVE_LOGE("GetNetworkSharingTraffic failed");
389     return NETMANAGER_ERROR;
390 }
391 
CheckInited()392 void SharingManager::CheckInited()
393 {
394     std::lock_guard<std::mutex> guard(initedMutex_);
395     if (inited_) {
396         return;
397     }
398     InitChildChains();
399 }
400 
SetForwardRules(bool set,const std::string & cmds)401 int32_t SharingManager::SetForwardRules(bool set, const std::string &cmds)
402 {
403     const std::string op = set ? "-A" : "-D";
404 
405     if (iptablesWrapper_->RunCommand(IPTYPE_IPV4, "-t filter " + op + cmds) != NetManagerStandard::NETMANAGER_SUCCESS) {
406         NETNATIVE_LOGE("IptablesWrapper run command failed");
407         return -1;
408     }
409     return 0;
410 }
411 } // namespace nmd
412 } // namespace OHOS
413