1/*
2 * Copyright (C) 2021-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 "dhcp_controller.h"
17
18#include "dhcp_result_parcel.h"
19#include "netnative_log_wrapper.h"
20#include "netmanager_base_common_utils.h"
21#include <securec.h>
22
23namespace OHOS {
24namespace nmd {
25static constexpr const char *DEFAULT_STR_SUBNET = "255.255.255.0";
26static constexpr const char *DEFAULT_STR_STARTIP = ".3";
27static constexpr const char *DEFAULT_STR_ENDIP = ".254";
28DhcpController *DhcpController::DhcpControllerResultNotify::dhcpController_ = nullptr;
29
30DhcpController::DhcpControllerResultNotify::DhcpControllerResultNotify() {}
31
32DhcpController::DhcpControllerResultNotify::~DhcpControllerResultNotify() {}
33
34void DhcpController::DhcpControllerResultNotify::SetDhcpController(DhcpController *dhcpController)
35{
36    dhcpController_ = dhcpController;
37}
38
39void DhcpController::DhcpControllerResultNotify::OnSuccess(int status, const char *ifname,
40                                                           DhcpResult *result)
41{
42    if (ifname == nullptr || result == nullptr) {
43        NETNATIVE_LOGE("ifname or result is nullptr!");
44        return;
45    }
46    NETNATIVE_LOGI(
47        "Enter DhcpController::DhcpControllerResultNotify::OnSuccess "
48        "ifname=[%{public}s], iptype=[%{public}d], strYourCli=[%{public}s], "
49        "strServer=[%{public}s], strSubnet=[%{public}s], strDns1=[%{public}s], "
50        "strDns2=[%{public}s] strRouter1=[%{public}s] strRouter2=[%{public}s]",
51        ifname, result->iptype, result->strOptClientId,
52        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptServerId).c_str(),
53        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptSubnet).c_str(),
54        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptDns1).c_str(),
55        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptDns2).c_str(),
56        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptRouter1).c_str(),
57        NetManagerStandard::CommonUtils::ToAnonymousIp(result->strOptRouter2).c_str());
58    dhcpController_->Process(ifname, result);
59}
60
61void DhcpController::DhcpControllerResultNotify::OnFailed(int status, const char *ifname,
62                                                          const char *reason)
63{
64    NETNATIVE_LOGE("Enter DhcpController::DhcpControllerResultNotify::OnFailed");
65}
66
67DhcpController::DhcpController()
68{
69    dhcpResultNotify_ = std::make_unique<DhcpControllerResultNotify>();
70}
71
72DhcpController::~DhcpController() {}
73
74int32_t DhcpController::RegisterNotifyCallback(sptr<OHOS::NetsysNative::INotifyCallback> &callback)
75{
76    NETNATIVE_LOGI("DhcpController RegisterNotifyCallback");
77    callback_ = callback;
78    return 0;
79}
80
81void DhcpController::StartClient(const std::string &iface, bool bIpv6)
82{
83    clientEvent.OnIpSuccessChanged = DhcpControllerResultNotify::OnSuccess;
84    clientEvent.OnIpFailChanged = DhcpControllerResultNotify::OnFailed;
85    dhcpResultNotify_->SetDhcpController(this);
86    if (RegisterDhcpClientCallBack(iface.c_str(), &clientEvent) != DHCP_SUCCESS) {
87        NETNATIVE_LOGE("RegisterDhcpClientCallBack failed.");
88        return;
89    }
90
91    NETNATIVE_LOGI("DhcpController StartDhcpClient iface[%{public}s] ipv6[%{public}d]", iface.c_str(), bIpv6);
92    if (StartDhcpClient(iface.c_str(), bIpv6) != DHCP_SUCCESS) {
93        NETNATIVE_LOGE("Start dhcp client failed");
94    }
95}
96
97void DhcpController::StopClient(const std::string &iface, bool bIpv6)
98{
99    NETNATIVE_LOGI("DhcpController StopDhcpClient iface[%{public}s] ipv6[%{public}d]", iface.c_str(), bIpv6);
100    if (StopDhcpClient(iface.c_str(), bIpv6) != DHCP_SUCCESS) {
101        NETNATIVE_LOGE("Stop dhcp client failed");
102    }
103}
104
105void DhcpController::Process(const std::string &iface, DhcpResult *result)
106{
107    NETNATIVE_LOGI("DhcpController Process");
108    sptr<OHOS::NetsysNative::DhcpResultParcel> ptr = new (std::nothrow) OHOS::NetsysNative::DhcpResultParcel();
109    if (ptr == nullptr) {
110        return;
111    }
112    ptr->iface_ = iface;
113    ptr->ipAddr_ = result->strOptClientId;
114    ptr->gateWay_ = result->strOptServerId;
115    ptr->subNet_ = result->strOptSubnet;
116    ptr->route1_ = result->strOptRouter1;
117    ptr->route2_ = result->strOptRouter2;
118    ptr->dns1_ = result->strOptDns1;
119    ptr->dns2_ = result->strOptDns2;
120    NETNATIVE_LOGI("DhcpController Process iface[%{public}s]", iface.c_str());
121    callback_->OnDhcpSuccess(ptr);
122}
123
124bool DhcpController::StartDhcpService(const std::string &iface, const std::string &ipv4addr)
125{
126    constexpr int32_t IP_V4 = 0;
127    std::string ipAddr = ipv4addr;
128    std::string::size_type pos = ipAddr.rfind(".");
129    if (pos == std::string::npos) {
130        return false;
131    }
132
133    std::string ipHead = ipAddr.substr(0, pos);
134    std::string strStartip = ipHead + DEFAULT_STR_STARTIP;
135    std::string strEndip = ipHead + DEFAULT_STR_ENDIP;
136    std::string strSubnet = DEFAULT_STR_SUBNET;
137
138    DhcpRange range;
139    range.iptype = IP_V4;
140    if (strcpy_s(range.strTagName, DHCP_MAX_FILE_BYTES, iface.c_str()) != 0) {
141        NETNATIVE_LOGE("strcpy_s strTagName failed!");
142        return false;
143    }
144
145    if (strcpy_s(range.strStartip, INET_ADDRSTRLEN, strStartip.c_str()) != 0) {
146        NETNATIVE_LOGE("strcpy_s strStartip failed!");
147        return false;
148    }
149
150    if (strcpy_s(range.strEndip, INET_ADDRSTRLEN, strEndip.c_str()) != 0) {
151        NETNATIVE_LOGE("strcpy_s strEndip failed!");
152        return false;
153    }
154
155    if (strcpy_s(range.strSubnet, INET_ADDRSTRLEN, strSubnet.c_str()) != 0) {
156        NETNATIVE_LOGE("strcpy_s strSubnet failed!");
157        return false;
158    }
159
160    if (SetDhcpRange(iface.c_str(), &range) != DHCP_SUCCESS) {
161        NETNATIVE_LOGE("SetDhcpRange failed!");
162        return false;
163    }
164    NETNATIVE_LOGI(
165        "Set dhcp range : ifaceName[%{public}s] TagName[%{public}s] start ip[%{public}s] end ip[%{public}s]",
166        iface.c_str(), range.strTagName, range.strStartip, range.strEndip);
167    if (StartDhcpServer(iface.c_str()) != DHCP_SUCCESS) {
168        NETNATIVE_LOGE("Start dhcp server failed!, iface:[%{public}s]", iface.c_str());
169        return false;
170    }
171    return true;
172}
173
174bool DhcpController::StopDhcpService(const std::string &iface)
175{
176    if (RemoveAllDhcpRange(iface.c_str()) != DHCP_SUCCESS) {
177        NETNATIVE_LOGE("failed to remove [%{public}s] dhcp range.", iface.c_str());
178    }
179
180    if (StopDhcpServer(iface.c_str()) != DHCP_SUCCESS) {
181        NETNATIVE_LOGE("Stop dhcp server failed!");
182        return false;
183    }
184    NETNATIVE_LOGI("StopDhcpService ifaceName[%{public}s]", iface.c_str());
185    return true;
186}
187} // namespace nmd
188} // namespace OHOS
189