1 /*
2 * Copyright (C) 2021-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 <arpa/inet.h>
17 #include <cstring>
18 #include <fcntl.h>
19 #include <fstream>
20 #include <future>
21 #include <list>
22 #include <memory>
23 #include <netdb.h>
24 #include <regex>
25 #include <securec.h>
26 #include <sys/socket.h>
27 #include <thread>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <string>
31
32 #include "net_monitor.h"
33 #include "dns_config_client.h"
34 #include "event_report.h"
35 #include "fwmark_client.h"
36 #include "netmanager_base_common_utils.h"
37 #include "netsys_controller.h"
38 #include "net_http_proxy_tracker.h"
39 #include "net_mgr_log_wrapper.h"
40 #include "net_manager_constants.h"
41 #include "tiny_count_down_latch.h"
42
43 namespace OHOS {
44 namespace NetManagerStandard {
45 namespace {
46 constexpr int32_t INIT_DETECTION_DELAY_MS = 1 * 1000;
47 constexpr int32_t MAX_FAILED_DETECTION_DELAY_MS = 10 * 60 * 1000;
48 constexpr int32_t PRIMARY_DETECTION_RESULT_WAIT_MS = 3 * 1000;
49 constexpr int32_t ALL_DETECTION_RESULT_WAIT_MS = 10 * 1000;
50 constexpr int32_t CAPTIVE_PORTAL_DETECTION_DELAY_MS = 15 * 1000;
51 constexpr int32_t DOUBLE = 2;
52 constexpr int32_t SIM_PORTAL_CODE = 302;
53 constexpr int32_t ONE_URL_DETECT_NUM = 2;
54 constexpr int32_t ALL_DETECT_THREAD_NUM = 4;
55 constexpr const char NEW_LINE_STR = '\n';
56 constexpr const char* URL_CFG_FILE = "/system/etc/netdetectionurl.conf";
57 constexpr const char* DETECT_CFG_FILE = "/system/etc/detectionconfig.conf";
58 constexpr const char *SETTINGS_DATASHARE_URI =
59 "datashare:///com.ohos.settingsdata/entry/settingsdata/SETTINGSDATA?Proxy=true";
60 constexpr const char *SETTINGS_DATA_EXT_URI = "datashare:///com.ohos.settingsdata.DataAbility";
61 const std::string HTTP_URL_HEADER = "HttpProbeUrl:";
62 const std::string HTTPS_URL_HEADER = "HttpsProbeUrl:";
63 const std::string FALLBACK_HTTP_URL_HEADER = "FallbackHttpProbeUrl:";
64 const std::string FALLBACK_HTTPS_URL_HEADER = "FallbackHttpsProbeUrl:";
65 const std::string ADD_RANDOM_CFG_PREFIX = "AddSuffix:";
66 const std::string ADD_RANDOM_CFG_VALUE = "true";
67 } // namespace
NetDetectThread(const std::shared_ptr<NetMonitor> &netMonitor)68 static void NetDetectThread(const std::shared_ptr<NetMonitor> &netMonitor)
69 {
70 if (netMonitor == nullptr) {
71 NETMGR_LOG_E("netMonitor is nullptr");
72 return;
73 }
74 while (netMonitor->IsDetecting()) {
75 netMonitor->Detection();
76 }
77 }
78
NetMonitor(uint32_t netId, NetBearType bearType, const NetLinkInfo &netLinkInfo, const std::weak_ptr<INetMonitorCallback> &callback)79 NetMonitor::NetMonitor(uint32_t netId, NetBearType bearType, const NetLinkInfo &netLinkInfo,
80 const std::weak_ptr<INetMonitorCallback> &callback)
81 : netId_(netId), netLinkInfo_(netLinkInfo), netMonitorCallback_(callback)
82 {
83 netBearType_ = bearType;
84 LoadGlobalHttpProxy();
85 GetDetectUrlConfig();
86 GetHttpProbeUrlFromConfig();
87 }
88
Start()89 void NetMonitor::Start()
90 {
91 NETMGR_LOG_D("Start net[%{public}d] monitor in", netId_);
92 if (isDetecting_) {
93 NETMGR_LOG_W("Net[%{public}d] monitor is detecting, no need to start", netId_);
94 return;
95 }
96 isDetecting_ = true;
97 std::shared_ptr<NetMonitor> netMonitor = shared_from_this();
98 std::thread t([netMonitor] { return NetDetectThread(netMonitor); });
99 std::string threadName = "netDetect";
100 pthread_setname_np(t.native_handle(), threadName.c_str());
101 t.detach();
102 }
103
Stop()104 void NetMonitor::Stop()
105 {
106 NETMGR_LOG_I("Stop net[%{public}d] monitor in", netId_);
107 isDetecting_ = false;
108 detectionCond_.notify_all();
109 NETMGR_LOG_D("Stop net[%{public}d] monitor out", netId_);
110 }
111
IsDetecting()112 bool NetMonitor::IsDetecting()
113 {
114 return isDetecting_.load();
115 }
116
ProcessDetection(NetHttpProbeResult& probeResult, NetDetectionStatus& result)117 void NetMonitor::ProcessDetection(NetHttpProbeResult& probeResult, NetDetectionStatus& result)
118 {
119 if (probeResult.IsSuccessful()) {
120 NETMGR_LOG_I("Net[%{public}d] probe success", netId_);
121 isDetecting_ = false;
122 needDetectionWithoutProxy_ = true;
123 result = VERIFICATION_STATE;
124 } else if (probeResult.GetCode() == SIM_PORTAL_CODE && netBearType_ == BEARER_CELLULAR) {
125 NETMGR_LOG_E("Net[%{public}d] probe failed with 302 response on Cell", netId_);
126 detectionDelay_ = MAX_FAILED_DETECTION_DELAY_MS;
127 result = CAPTIVE_PORTAL_STATE;
128 } else if (probeResult.IsNeedPortal()) {
129 NETMGR_LOG_W("Net[%{public}d] need portal", netId_);
130 detectionDelay_ = CAPTIVE_PORTAL_DETECTION_DELAY_MS;
131 result = CAPTIVE_PORTAL_STATE;
132 } else {
133 NETMGR_LOG_E("Net[%{public}d] probe failed", netId_);
134 detectionDelay_ *= DOUBLE;
135 if (detectionDelay_ == 0) {
136 detectionDelay_ = INIT_DETECTION_DELAY_MS;
137 } else if (detectionDelay_ >= MAX_FAILED_DETECTION_DELAY_MS) {
138 detectionDelay_ = MAX_FAILED_DETECTION_DELAY_MS;
139 }
140 NETMGR_LOG_I("Net probe failed detectionDelay time [%{public}d]", detectionDelay_);
141 result = INVALID_DETECTION_STATE;
142 }
143 auto monitorCallback = netMonitorCallback_.lock();
144 if (monitorCallback) {
145 monitorCallback->OnHandleNetMonitorResult(result, probeResult.GetRedirectUrl());
146 }
147 struct EventInfo eventInfo = {.monitorStatus = static_cast<int32_t>(result)};
148 EventReport::SendMonitorBehaviorEvent(eventInfo);
149 if (isDetecting_) {
150 std::unique_lock<std::mutex> locker(detectionMtx_);
151 detectionCond_.wait_for(locker, std::chrono::milliseconds(detectionDelay_));
152 }
153 }
154
Detection()155 void NetMonitor::Detection()
156 {
157 NetHttpProbeResult probeResult = SendProbe();
158 if (isDetecting_) {
159 NetDetectionStatus result = UNKNOWN_STATE;
160 ProcessDetection(probeResult, result);
161 }
162 }
163
SendProbe()164 NetHttpProbeResult NetMonitor::SendProbe()
165 {
166 NETMGR_LOG_I("start net detection");
167 std::lock_guard<std::mutex> monitorLocker(probeMtx_);
168 std::shared_ptr<TinyCountDownLatch> latch = std::make_shared<TinyCountDownLatch>(ONE_URL_DETECT_NUM);
169 std::shared_ptr<TinyCountDownLatch> latchAll = std::make_shared<TinyCountDownLatch>(ALL_DETECT_THREAD_NUM);
170 std::shared_ptr<ProbeThread> primaryHttpThread = std::make_shared<ProbeThread>(
171 netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP, httpUrl_, httpsUrl_);
172 std::shared_ptr<ProbeThread> primaryHttpsThread = std::make_shared<ProbeThread>(
173 netId_, netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS, httpUrl_, httpsUrl_);
174 {
175 std::lock_guard<std::mutex> proxyLocker(proxyMtx_);
176 primaryHttpThread->UpdateGlobalHttpProxy(globalHttpProxy_);
177 primaryHttpsThread->UpdateGlobalHttpProxy(globalHttpProxy_);
178 }
179 primaryHttpThread->Start();
180 primaryHttpsThread->Start();
181
182 latch->Await(std::chrono::milliseconds(PRIMARY_DETECTION_RESULT_WAIT_MS));
183 NetHttpProbeResult httpProbeResult = GetThreadDetectResult(primaryHttpThread, ProbeType::PROBE_HTTP);
184 NetHttpProbeResult httpsProbeResult = GetThreadDetectResult(primaryHttpsThread, ProbeType::PROBE_HTTPS);
185 if (httpProbeResult.IsNeedPortal()) {
186 NETMGR_LOG_I("http detect result: portal");
187 return httpProbeResult;
188 }
189 if (httpsProbeResult.IsSuccessful()) {
190 NETMGR_LOG_I("https detect result: success");
191 return httpsProbeResult;
192 }
193 NETMGR_LOG_I("backup url detection start");
194 std::shared_ptr<ProbeThread> fallbackHttpThread = std::make_shared<ProbeThread>(netId_,
195 netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTP, fallbackHttpUrl_, fallbackHttpsUrl_);
196 std::shared_ptr<ProbeThread> fallbackHttpsThread = std::make_shared<ProbeThread>(netId_,
197 netBearType_, netLinkInfo_, latch, latchAll, ProbeType::PROBE_HTTPS, fallbackHttpUrl_, fallbackHttpsUrl_);
198 fallbackHttpThread->ProbeWithoutGlobalHttpProxy();
199 fallbackHttpsThread->ProbeWithoutGlobalHttpProxy();
200 fallbackHttpThread->Start();
201 fallbackHttpsThread->Start();
202 latchAll->Await(std::chrono::milliseconds(ALL_DETECTION_RESULT_WAIT_MS));
203 httpProbeResult = GetThreadDetectResult(primaryHttpThread, ProbeType::PROBE_HTTP);
204 httpsProbeResult = GetThreadDetectResult(primaryHttpsThread, ProbeType::PROBE_HTTPS);
205 NetHttpProbeResult fallbackHttpProbeResult = GetThreadDetectResult(fallbackHttpThread, ProbeType::PROBE_HTTP);
206 NetHttpProbeResult fallbackHttpsProbeResult = GetThreadDetectResult(fallbackHttpsThread, ProbeType::PROBE_HTTPS);
207 return ProcessThreadDetectResult(httpProbeResult, httpsProbeResult, fallbackHttpProbeResult,
208 fallbackHttpsProbeResult);
209 }
210
GetThreadDetectResult(std::shared_ptr<ProbeThread>& probeThread, ProbeType probeType)211 NetHttpProbeResult NetMonitor::GetThreadDetectResult(std::shared_ptr<ProbeThread>& probeThread, ProbeType probeType)
212 {
213 NetHttpProbeResult result;
214 if (!probeThread->IsDetecting()) {
215 if (probeType == ProbeType::PROBE_HTTP) {
216 return probeThread->GetHttpProbeResult();
217 } else {
218 return probeThread->GetHttpsProbeResult();
219 }
220 }
221 return result;
222 }
223
ProcessThreadDetectResult(NetHttpProbeResult& httpProbeResult, NetHttpProbeResult& httpsProbeResult, NetHttpProbeResult& fallbackHttpProbeResult, NetHttpProbeResult& fallbackHttpsProbeResult)224 NetHttpProbeResult NetMonitor::ProcessThreadDetectResult(NetHttpProbeResult& httpProbeResult,
225 NetHttpProbeResult& httpsProbeResult, NetHttpProbeResult& fallbackHttpProbeResult,
226 NetHttpProbeResult& fallbackHttpsProbeResult)
227 {
228 if (httpProbeResult.IsNeedPortal()) {
229 NETMGR_LOG_I("primary http detect result: portal");
230 return httpProbeResult;
231 }
232 if (fallbackHttpProbeResult.IsNeedPortal()) {
233 NETMGR_LOG_I("fallback http detect result: portal");
234 return fallbackHttpProbeResult;
235 }
236 if (httpsProbeResult.IsSuccessful()) {
237 NETMGR_LOG_I("primary https detect result: success");
238 return httpsProbeResult;
239 }
240 if (fallbackHttpsProbeResult.IsSuccessful()) {
241 NETMGR_LOG_I("fallback https detect result: success");
242 return fallbackHttpsProbeResult;
243 }
244 if (httpProbeResult.IsSuccessful() && fallbackHttpProbeResult.IsSuccessful()) {
245 NETMGR_LOG_I("both primary http and fallback http detect result success");
246 return httpProbeResult;
247 }
248 return httpsProbeResult;
249 }
250
LoadGlobalHttpProxy()251 void NetMonitor::LoadGlobalHttpProxy()
252 {
253 if (!CheckIfSettingsDataReady()) {
254 NETMGR_LOG_E("data_share is not ready");
255 return;
256 }
257 NetHttpProxyTracker httpProxyTracker;
258 httpProxyTracker.ReadFromSettingsData(globalHttpProxy_);
259 }
260
UpdateGlobalHttpProxy(const HttpProxy &httpProxy)261 void NetMonitor::UpdateGlobalHttpProxy(const HttpProxy &httpProxy)
262 {
263 std::unique_lock<std::mutex> proxyLocker(proxyMtx_);
264 globalHttpProxy_ = httpProxy;
265 }
266
GetHttpProbeUrlFromConfig()267 void NetMonitor::GetHttpProbeUrlFromConfig()
268 {
269 if (!std::filesystem::exists(URL_CFG_FILE)) {
270 NETMGR_LOG_E("File not exist (%{public}s)", URL_CFG_FILE);
271 return;
272 }
273
274 std::ifstream file(URL_CFG_FILE);
275 if (!file.is_open()) {
276 NETMGR_LOG_E("Open file failed (%{public}s)", strerror(errno));
277 return;
278 }
279
280 std::ostringstream oss;
281 oss << file.rdbuf();
282 std::string content = oss.str();
283 auto pos = content.find(HTTP_URL_HEADER);
284 if (pos != std::string::npos) {
285 pos += HTTP_URL_HEADER.length();
286 httpUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
287 if (isNeedSuffix_) {
288 uint64_t ranNum = CommonUtils::GenRandomNumber();
289 httpUrl_ = httpUrl_ + std::string("_") + std::to_string(ranNum);
290 }
291 }
292
293 pos = content.find(HTTPS_URL_HEADER);
294 if (pos != std::string::npos) {
295 pos += HTTPS_URL_HEADER.length();
296 httpsUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
297 }
298
299 pos = content.find(FALLBACK_HTTP_URL_HEADER);
300 if (pos != std::string::npos) {
301 pos += FALLBACK_HTTP_URL_HEADER.length();
302 fallbackHttpUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
303 }
304
305 pos = content.find(FALLBACK_HTTPS_URL_HEADER);
306 if (pos != std::string::npos) {
307 pos += FALLBACK_HTTPS_URL_HEADER.length();
308 fallbackHttpsUrl_ = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
309 }
310 NETMGR_LOG_D("Get net detection http url:[%{public}s], https url:[%{public}s], fallback http url:[%{public}s],"
311 " fallback https url:[%{public}s]", httpUrl_.c_str(), httpsUrl_.c_str(), fallbackHttpUrl_.c_str(),
312 fallbackHttpsUrl_.c_str());
313 }
314
GetDetectUrlConfig()315 void NetMonitor::GetDetectUrlConfig()
316 {
317 if (!std::filesystem::exists(DETECT_CFG_FILE)) {
318 NETMGR_LOG_E("File not exist (%{public}s)", DETECT_CFG_FILE);
319 return;
320 }
321
322 std::ifstream file(DETECT_CFG_FILE);
323 if (!file.is_open()) {
324 NETMGR_LOG_E("Open file failed (%{public}s)", strerror(errno));
325 return;
326 }
327 std::ostringstream oss;
328 oss << file.rdbuf();
329 std::string content = oss.str();
330 auto pos = content.find(ADD_RANDOM_CFG_PREFIX);
331 if (pos != std::string::npos) {
332 pos += ADD_RANDOM_CFG_PREFIX.length();
333 std::string value = content.substr(pos, content.find(NEW_LINE_STR, pos) - pos);
334 value = CommonUtils::Trim(value);
335 isNeedSuffix_ = value.compare(ADD_RANDOM_CFG_VALUE) == 0;
336 }
337 NETMGR_LOG_I("is need add suffix (%{public}d)", isNeedSuffix_);
338 }
339
CheckIfSettingsDataReady()340 bool NetMonitor::CheckIfSettingsDataReady()
341 {
342 if (isDataShareReady_) {
343 return true;
344 }
345 sptr<ISystemAbilityManager> saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
346 if (saManager == nullptr) {
347 NETMGR_LOG_E("GetSystemAbilityManager failed.");
348 return false;
349 }
350 sptr<IRemoteObject> dataShareSa = saManager->GetSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID);
351 if (dataShareSa == nullptr) {
352 NETMGR_LOG_E("Get dataShare SA Failed.");
353 return false;
354 }
355 sptr<IRemoteObject> remoteObj = saManager->GetSystemAbility(COMM_NET_CONN_MANAGER_SYS_ABILITY_ID);
356 if (remoteObj == nullptr) {
357 NETMGR_LOG_E("NetDataShareHelperUtils GetSystemAbility Service Failed.");
358 return false;
359 }
360 std::pair<int, std::shared_ptr<DataShare::DataShareHelper>> ret =
361 DataShare::DataShareHelper::Create(remoteObj, SETTINGS_DATASHARE_URI, SETTINGS_DATA_EXT_URI);
362 NETMGR_LOG_I("create data_share helper, ret=%{public}d", ret.first);
363 if (ret.first == DataShare::E_OK) {
364 NETMGR_LOG_I("create data_share helper success");
365 auto helper = ret.second;
366 if (helper != nullptr) {
367 bool releaseRet = helper->Release();
368 NETMGR_LOG_I("release data_share helper, releaseRet=%{public}d", releaseRet);
369 }
370 isDataShareReady_ = true;
371 return true;
372 } else if (ret.first == DataShare::E_DATA_SHARE_NOT_READY) {
373 NETMGR_LOG_E("create data_share helper failed");
374 isDataShareReady_ = false;
375 return false;
376 }
377 NETMGR_LOG_E("data_share unknown.");
378 return true;
379 }
380 } // namespace NetManagerStandard
381 } // namespace OHOS
382