1/*
2 * Copyright (c) 2022-2024 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 "iptables_wrapper.h"
17
18#include <unistd.h>
19
20#include "datetime_ex.h"
21#include "net_manager_constants.h"
22#include "netmanager_base_common_utils.h"
23#include "netnative_log_wrapper.h"
24
25namespace OHOS {
26namespace nmd {
27using namespace NetManagerStandard;
28namespace {
29constexpr const char *IPATBLES_CMD_PATH = "/system/bin/iptables";
30constexpr const char *IP6TABLES_CMD_PATH = "/system/bin/ip6tables";
31} // namespace
32
33IptablesWrapper::IptablesWrapper()
34{
35    isRunningFlag_ = true;
36    isIptablesSystemAccess_ = access(IPATBLES_CMD_PATH, F_OK) == 0;
37    isIp6tablesSystemAccess_ = access(IP6TABLES_CMD_PATH, F_OK) == 0;
38
39    iptablesWrapperFfrtQueue_ = std::make_shared<ffrt::queue>("IptablesWrapper");
40}
41
42IptablesWrapper::~IptablesWrapper()
43{
44    isRunningFlag_ = false;
45    iptablesWrapperFfrtQueue_.reset();
46}
47
48void IptablesWrapper::ExecuteCommand(const std::string &command)
49{
50    NETNATIVE_LOGI("ExecuteCommand %{public}s", AnonymizeIptablesCommand(command).c_str());
51    if (CommonUtils::ForkExec(command) == NETMANAGER_ERROR) {
52        NETNATIVE_LOGE("run exec faild");
53    }
54}
55
56void IptablesWrapper::ExecuteCommandForRes(const std::string &command)
57{
58    NETNATIVE_LOGI("ExecuteCommandForRes %{public}s", AnonymizeIptablesCommand(command).c_str());
59    if (CommonUtils::ForkExec(command, &result_) == NETMANAGER_ERROR) {
60        NETNATIVE_LOGE("run exec faild");
61    }
62}
63
64int32_t IptablesWrapper::RunCommand(const IpType &ipType, const std::string &command)
65{
66    NETNATIVE_LOGI("IptablesWrapper::RunCommand, ipType:%{public}d", ipType);
67    if (!iptablesWrapperFfrtQueue_) {
68        NETNATIVE_LOGE("FFRT Init Fail");
69        return NETMANAGER_ERROR;
70    }
71
72    if (isIptablesSystemAccess_ && (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6)) {
73        std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
74#if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
75        ExecuteCommand(cmd);
76#else
77        std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
78        iptablesWrapperFfrtQueue_->submit(executeCommand);
79#endif // UNITTEST_FORBID_FFRT
80    }
81
82    if (isIp6tablesSystemAccess_ && (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6)) {
83        std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
84#if UNITTEST_FORBID_FFRT // Forbid FFRT for unittest, which will cause crash in destructor process
85        ExecuteCommand(cmd);
86#else
87        std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
88        iptablesWrapperFfrtQueue_->submit(executeCommand);
89#endif // UNITTEST_FORBID_FFRT
90    }
91
92    return NetManagerStandard::NETMANAGER_SUCCESS;
93}
94
95std::string IptablesWrapper::RunCommandForRes(const IpType &ipType, const std::string &command)
96{
97    NETNATIVE_LOGI("IptablesWrapper::RunCommandForRes, ipType:%{public}d", ipType);
98    if (!iptablesWrapperFfrtQueue_) {
99        NETNATIVE_LOGE("FFRT Init Fail");
100        return result_;
101    }
102
103    if (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6) {
104        std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
105        std::function<void()> executeCommandForRes =
106            std::bind(&IptablesWrapper::ExecuteCommandForRes, shared_from_this(), cmd);
107
108        int64_t start = GetTickCount();
109        ffrt::task_handle RunCommandForResTaskIpv4 = iptablesWrapperFfrtQueue_->submit_h(executeCommandForRes);
110        iptablesWrapperFfrtQueue_->wait(RunCommandForResTaskIpv4);
111        NETNATIVE_LOGI("FFRT cost:%{public}lld ms", static_cast<long long>(GetTickCount() - start));
112    }
113
114    if (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6) {
115        std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
116        std::function<void()> executeCommandForRes =
117            std::bind(&IptablesWrapper::ExecuteCommandForRes, shared_from_this(), cmd);
118
119        int64_t start = GetTickCount();
120        ffrt::task_handle RunCommandForResTaskIpv6 = iptablesWrapperFfrtQueue_->submit_h(executeCommandForRes);
121        iptablesWrapperFfrtQueue_->wait(RunCommandForResTaskIpv6);
122        NETNATIVE_LOGI("FFRT cost:%{public}lld ms", static_cast<long long>(GetTickCount() - start));
123    }
124
125    return result_;
126}
127
128int32_t IptablesWrapper::RunMutipleCommands(const IpType &ipType, const std::vector<std::string> &commands)
129{
130    NETNATIVE_LOG_D("IptablesWrapper::RunMutipleCommands, ipType:%{public}d", ipType);
131    if (!iptablesWrapperFfrtQueue_) {
132        NETNATIVE_LOGE("FFRT Init Fail");
133        return NETMANAGER_ERROR;
134    }
135
136    for (const std::string& command : commands) {
137        if (isIptablesSystemAccess_ && (ipType == IPTYPE_IPV4 || ipType == IPTYPE_IPV4V6)) {
138            std::string cmd = std::string(IPATBLES_CMD_PATH) + " " + command;
139            std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
140            iptablesWrapperFfrtQueue_->submit(executeCommand);
141        }
142
143        if (isIp6tablesSystemAccess_ && (ipType == IPTYPE_IPV6 || ipType == IPTYPE_IPV4V6)) {
144            std::string cmd = std::string(IP6TABLES_CMD_PATH) + " " + command;
145            std::function<void()> executeCommand = std::bind(&IptablesWrapper::ExecuteCommand, shared_from_this(), cmd);
146            iptablesWrapperFfrtQueue_->submit(executeCommand);
147        }
148    }
149
150    return NetManagerStandard::NETMANAGER_SUCCESS;
151}
152} // namespace nmd
153} // namespace OHOS
154