1 /*
2 * Copyright (C) 2021 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 #include "block_connect_service.h"
16
17 namespace OHOS {
18 namespace Wifi {
19 DEFINE_WIFILOG_LABEL("BlockConnectService");
20 constexpr int FREQUENT_DISCONNECT_COUNT = 5;
21 constexpr int64_t FREQUENT_DISCONNECT_TIME_INTERVAL_MAX = 10 * 60 * 1000 * 1000;
22 constexpr int64_t FREQUENT_DISCONNECT_TIME_INTERVAL_MID = 1 * 60 * 1000 * 1000;
23 constexpr int64_t FREQUENT_DISCONNECT_TIME_INTERVAL_MIN = 0.5 * 60 * 1000 * 1000;
24
GetInstance()25 BlockConnectService &BlockConnectService::GetInstance()
26 {
27 static BlockConnectService gStaBlockConnectService;
28 return gStaBlockConnectService;
29 }
30
BlockConnectService()31 BlockConnectService::BlockConnectService()
32 {
33 // Initialize any necessary variables or data structures
34 blockConnectPolicies = {
35 {DisabledReason::DISABLED_ASSOCIATION_REJECTION,
36 DisablePolicy(5 * 60 * 1000 * 1000, 3, WifiDeviceConfigStatus::DISABLED)},
37 {DisabledReason::DISABLED_AUTHENTICATION_FAILURE,
38 DisablePolicy(5 * 60 * 1000 * 1000, 3, WifiDeviceConfigStatus::DISABLED)},
39 {DisabledReason::DISABLED_DHCP_FAILURE,
40 DisablePolicy(5 * 60 * 1000 * 1000, 2, WifiDeviceConfigStatus::DISABLED)},
41 {DisabledReason::DISABLED_NO_INTERNET_TEMPORARY,
42 DisablePolicy(5 * 60 * 1000 * 1000, 1, WifiDeviceConfigStatus::DISABLED)},
43 {DisabledReason::DISABLED_AUTHENTICATION_NO_CREDENTIALS,
44 DisablePolicy(-1, 3, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
45 {DisabledReason::DISABLED_NO_INTERNET_PERMANENT,
46 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
47 {DisabledReason::DISABLED_BY_WIFI_MANAGER,
48 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
49 {DisabledReason::DISABLED_BY_WRONG_PASSWORD,
50 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
51 {DisabledReason::DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
52 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
53 {DisabledReason::DISABLED_AUTHENTICATION_PRIVATE_EAP_ERROR,
54 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
55 {DisabledReason::DISABLED_NETWORK_NOT_FOUND,
56 DisablePolicy(5 * 60 * 1000 * 1000, 2, WifiDeviceConfigStatus::DISABLED)},
57 {DisabledReason::DISABLED_CONSECUTIVE_FAILURES,
58 DisablePolicy(5 * 60 * 1000 * 1000, 1, WifiDeviceConfigStatus::DISABLED)},
59 {DisabledReason::DISABLED_BY_SYSTEM,
60 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
61 {DisabledReason::DISABLED_EAP_AKA_FAILURE,
62 DisablePolicy(-1, 1, WifiDeviceConfigStatus::PERMEMANTLY_DISABLED)},
63 {DisabledReason::DISABLED_DISASSOC_REASON,
64 DisablePolicy(5 * 60 * 1000 * 1000, 5, WifiDeviceConfigStatus::DISABLED)},
65 };
66
67 validReasons = {
68 static_cast<int>(DisconnectDetailReason::UNSPECIFIED),
69 static_cast<int>(DisconnectDetailReason::PREV_AUTH_NOT_VALID),
70 static_cast<int>(DisconnectDetailReason::DISASSOC_DUE_TO_INACTIVITY),
71 static_cast<int>(DisconnectDetailReason::DISASSOC_AP_BUSY),
72 static_cast<int>(DisconnectDetailReason::DISASSOC_STA_HAS_LEFT),
73 static_cast<int>(DisconnectDetailReason::DISASSOC_IEEE_802_1X_AUTH_FAILED),
74 static_cast<int>(DisconnectDetailReason::DISASSOC_LOW_ACK)
75 };
76
77 mLastConnectedApInfo = {"", -1, 0};
78 }
79
80 // Destructor
~BlockConnectService()81 BlockConnectService::~BlockConnectService()
82 {
83 // Clean up any resources
84 blockConnectPolicies.clear();
85 }
86
Exit()87 void BlockConnectService::Exit()
88 {
89 // Implement the logic to exit the service
90 // Clean up any resources
91 blockConnectPolicies.clear();
92 mLastConnectedApInfo = {"", -1, 0};
93 }
94
95 // Method to check if auto connect is enabled for a given WifiDeviceConfig
ShouldAutoConnect(const WifiDeviceConfig & config)96 bool BlockConnectService::ShouldAutoConnect(const WifiDeviceConfig &config)
97 {
98 // Return true if auto connect is enabled, false otherwise
99 WIFI_LOGD("ENTER shouldAutoConnect %{public}d",
100 config.networkSelectionStatus.status == WifiDeviceConfigStatus::ENABLED);
101 return config.networkSelectionStatus.status == WifiDeviceConfigStatus::ENABLED;
102 }
103
104 // Update the selection status of all saved networks and check if disabled networks have expired
UpdateAllNetworkSelectStatus()105 bool BlockConnectService::UpdateAllNetworkSelectStatus()
106 {
107 WIFI_LOGD("ENTER updateAllNetworkSelectStatus");
108 // Implement the logic to update the selection status of all saved networks
109 // and check if disabled networks have expired
110 // Return true if successful, false otherwise
111 int64_t timestamp = GetElapsedMicrosecondsSinceBoot();
112 std::vector<WifiDeviceConfig> results;
113 if (WifiSettings::GetInstance().GetDeviceConfig(results) != 0) {
114 WIFI_LOGE("Failed to get device config");
115 return false;
116 }
117 for (auto &config : results) {
118 if (config.networkSelectionStatus.status == WifiDeviceConfigStatus::ENABLED) {
119 continue;
120 }
121 DisablePolicy policy = CalculateDisablePolicy(config.networkSelectionStatus.networkSelectionDisableReason);
122 if (policy.disableStatus == WifiDeviceConfigStatus::PERMEMANTLY_DISABLED) {
123 LogDisabledConfig(config);
124 continue;
125 }
126 if (policy.disableStatus == WifiDeviceConfigStatus::ENABLED ||
127 timestamp - config.networkSelectionStatus.networkDisableTimeStamp >= policy.disableTime) {
128 config.networkSelectionStatus.status = WifiDeviceConfigStatus::ENABLED;
129 config.networkSelectionStatus.networkSelectionDisableReason = DisabledReason::DISABLED_NONE;
130 config.networkSelectionStatus.networkDisableTimeStamp = -1;
131 config.networkSelectionStatus.networkDisableCount = 0;
132 WifiSettings::GetInstance().AddDeviceConfig(config);
133 }
134 LogDisabledConfig(config);
135 }
136 return true;
137 }
138
139 // Enable the selection status of a target network
EnableNetworkSelectStatus(int targetNetworkId)140 bool BlockConnectService::EnableNetworkSelectStatus(int targetNetworkId)
141 {
142 WIFI_LOGD("ENTER EnableNetworkSelectStatus");
143 // Implement the logic to enable the selection status of a target network
144 // Return true if successful, false otherwise
145 WifiDeviceConfig targetNetwork;
146 if (WifiSettings::GetInstance().GetDeviceConfig(targetNetworkId, targetNetwork)) {
147 WIFI_LOGE("Failed to get device config %{public}d", targetNetworkId);
148 return false;
149 }
150 targetNetwork.networkSelectionStatus.status = WifiDeviceConfigStatus::ENABLED;
151 targetNetwork.networkSelectionStatus.networkSelectionDisableReason = DisabledReason::DISABLED_NONE;
152 targetNetwork.networkSelectionStatus.networkDisableTimeStamp = -1;
153 targetNetwork.networkSelectionStatus.networkDisableCount = 0;
154 WifiSettings::GetInstance().AddDeviceConfig(targetNetwork);
155 WIFI_LOGI("EnableNetworkSelectStatus %{public}d %{public}s enabled",
156 targetNetworkId, SsidAnonymize(targetNetwork.ssid).c_str());
157 return true;
158 }
159
CalculateDisablePolicy(DisabledReason disableReason)160 DisablePolicy BlockConnectService::CalculateDisablePolicy(DisabledReason disableReason)
161 {
162 // Implement the logic to calculate the disable reason based on the disconnect reason
163 // Return the disable reason
164 std::map<DisabledReason, DisablePolicy>::iterator it = blockConnectPolicies.find(disableReason);
165 if (it == blockConnectPolicies.end()) {
166 return DisablePolicy(-1, 0, WifiDeviceConfigStatus::ENABLED);
167 }
168 return it->second;
169 }
170
171 // Clear the blocklist information of a target network with reason for wpa_supplicant disconnection
UpdateNetworkSelectStatus(int targetNetworkId,DisabledReason disableReason,int wpaReason)172 bool BlockConnectService::UpdateNetworkSelectStatus(int targetNetworkId, DisabledReason disableReason, int wpaReason)
173 {
174 // Implement the logic to clear the blocklist information of a target network
175 // Return true if successful, false otherwise
176 WIFI_LOGD("ENTER updateNetworkSelectStatus");
177 if (disableReason == DisabledReason::DISABLED_DISASSOC_REASON) {
178 if (std::find(validReasons.begin(), validReasons.end(), wpaReason) == validReasons.end()) {
179 return false;
180 }
181 }
182 return UpdateNetworkSelectStatus(targetNetworkId, disableReason);
183 }
184
185 // Clear the blocklist information of a target network
UpdateNetworkSelectStatus(int targetNetworkId,DisabledReason disableReason)186 bool BlockConnectService::UpdateNetworkSelectStatus(int targetNetworkId, DisabledReason disableReason)
187 {
188 // Implement the logic to clear the blocklist information of a target network
189 // Return true if successful, false otherwise
190 WIFI_LOGD("ENTER updateNetworkSelectStatus");
191 WifiDeviceConfig targetNetwork;
192 int64_t timestamp = GetElapsedMicrosecondsSinceBoot();
193 if (WifiSettings::GetInstance().GetDeviceConfig(targetNetworkId, targetNetwork)) {
194 WIFI_LOGE("Failed to get device config %{public}d", targetNetworkId);
195 return false;
196 }
197 DisablePolicy disablePolicy = CalculateDisablePolicy(disableReason);
198 if (disablePolicy.disableStatus == WifiDeviceConfigStatus::ENABLED) {
199 targetNetwork.networkSelectionStatus.status = WifiDeviceConfigStatus::ENABLED;
200 targetNetwork.networkSelectionStatus.networkSelectionDisableReason = disableReason;
201 targetNetwork.networkSelectionStatus.networkDisableTimeStamp = -1;
202 targetNetwork.networkSelectionStatus.networkDisableCount = 0;
203 return true;
204 }
205 if (targetNetwork.networkSelectionStatus.networkSelectionDisableReason == disableReason) {
206 targetNetwork.networkSelectionStatus.networkDisableCount++;
207 } else {
208 targetNetwork.networkSelectionStatus.networkDisableCount = 1;
209 targetNetwork.networkSelectionStatus.networkSelectionDisableReason = disableReason;
210 }
211
212 if (targetNetwork.networkSelectionStatus.networkDisableCount >= disablePolicy.disableCount) {
213 targetNetwork.networkSelectionStatus.status = disablePolicy.disableStatus;
214 targetNetwork.networkSelectionStatus.networkSelectionDisableReason = disableReason;
215 targetNetwork.networkSelectionStatus.networkDisableTimeStamp = timestamp;
216 }
217 WifiSettings::GetInstance().AddDeviceConfig(targetNetwork);
218 WIFI_LOGI("updateNetworkSelectStatus networkId %{public}d %{public}s %{public}d",
219 targetNetworkId, SsidAnonymize(targetNetwork.ssid).c_str(), disableReason);
220 return true;
221 }
222
223 // Check if the given BSSID has frequent disconnects with the last connected network
IsFrequentDisconnect(std::string bssid,int wpaReason)224 bool BlockConnectService::IsFrequentDisconnect(std::string bssid, int wpaReason)
225 {
226 // Implement the logic to check if the given BSSID has frequent disconnects
227 // with the last connected network
228 // Return true if frequent disconnects, false otherwise
229 int64_t timestamp = GetElapsedMicrosecondsSinceBoot();
230 int64_t time_duration = timestamp - mLastConnectedApInfo.lastDisconnectTimestamp;
231 WIFI_LOGD("ENTER isFrequentDisconnect %{public}" PRId64" %{public}s", time_duration, MacAnonymize(bssid).c_str());
232 WIFI_LOGD("mLastConnectedApInfo alreadyConnectedCount %{public}d", mLastConnectedApInfo.alreadyConnectedCount);
233 mLastConnectedApInfo.lastDisconnectTimestamp = timestamp;
234 if (mLastConnectedApInfo.bssid != bssid) {
235 mLastConnectedApInfo.bssid = bssid;
236 mLastConnectedApInfo.alreadyConnectedCount = 1;
237 return false;
238 }
239
240 if (time_duration > FREQUENT_DISCONNECT_TIME_INTERVAL_MAX) {
241 mLastConnectedApInfo.bssid = bssid;
242 mLastConnectedApInfo.alreadyConnectedCount = 1;
243 return false;
244 }
245 if (wpaReason == static_cast<int>(DisconnectDetailReason::DEAUTH_STA_IS_LEFING) ||
246 wpaReason == static_cast<int>(DisconnectDetailReason::DISASSOC_STA_HAS_LEFT)) {
247 if (time_duration < FREQUENT_DISCONNECT_TIME_INTERVAL_MIN) {
248 WIFI_LOGD("isFrequentDisconnect case min %{public}s %{public}d duration %{public}" PRId64,
249 MacAnonymize(bssid).c_str(), wpaReason, time_duration);
250 mLastConnectedApInfo.alreadyConnectedCount++;
251 }
252 } else if (time_duration < FREQUENT_DISCONNECT_TIME_INTERVAL_MID) {
253 WIFI_LOGD("isFrequentDisconnect case mid %{public}s %{public}d duration %{public}" PRId64,
254 MacAnonymize(bssid).c_str(), wpaReason, time_duration);
255 mLastConnectedApInfo.alreadyConnectedCount++;
256 }
257 if (mLastConnectedApInfo.alreadyConnectedCount >= FREQUENT_DISCONNECT_COUNT) {
258 WIFI_LOGI("isFrequentDisconnect %{public}s %{public}d count %{public}d",
259 MacAnonymize(bssid).c_str(), wpaReason, mLastConnectedApInfo.alreadyConnectedCount);
260 return true;
261 }
262 return false;
263 }
264
265 // Check if the given targetNetworkId is blocked due to wrong password
IsWrongPassword(int targetNetworkId)266 bool BlockConnectService::IsWrongPassword(int targetNetworkId)
267 {
268 // Implement the logic to check if the given targetNetworkId is blocked due to wrong password
269 // Return true if blocked due to wrong password, false otherwise
270 WifiDeviceConfig targetNetwork;
271 if (WifiSettings::GetInstance().GetDeviceConfig(targetNetworkId, targetNetwork)) {
272 WIFI_LOGE("Failed to get device config %{public}d", targetNetworkId);
273 return false;
274 }
275
276 if (targetNetwork.numAssociation == 0) {
277 return true;
278 }
279 return false;
280 }
281
EnableAllNetworksByEnteringSettings(std::vector<DisabledReason> enableReasons)282 void BlockConnectService::EnableAllNetworksByEnteringSettings(std::vector<DisabledReason> enableReasons)
283 {
284 WIFI_LOGI("ENTER EnableAllNetworksByEnteringSettings");
285 std::vector<WifiDeviceConfig> results;
286 if (WifiSettings::GetInstance().GetDeviceConfig(results) != 0) {
287 WIFI_LOGE("Failed to get device config");
288 return;
289 }
290 for (auto &config : results) {
291 if (config.networkSelectionStatus.status == WifiDeviceConfigStatus::ENABLED) {
292 continue;
293 }
294 if (std::find(enableReasons.begin(), enableReasons.end(),
295 config.networkSelectionStatus.networkSelectionDisableReason) != enableReasons.end()) {
296 config.networkSelectionStatus.status = WifiDeviceConfigStatus::ENABLED;
297 config.networkSelectionStatus.networkSelectionDisableReason = DisabledReason::DISABLED_NONE;
298 config.networkSelectionStatus.networkDisableTimeStamp = -1;
299 config.networkSelectionStatus.networkDisableCount = 0;
300 WifiSettings::GetInstance().AddDeviceConfig(config);
301 }
302 }
303 }
304
OnReceiveSettingsEnterEvent(bool isEnter)305 void BlockConnectService::OnReceiveSettingsEnterEvent(bool isEnter)
306 {
307 WIFI_LOGI("ENTER OnReceiveSettingsEnterEvent %{public}d", static_cast<int>(isEnter));
308 if (isEnter) {
309 std::vector<DisabledReason> enableReasons = {
310 DisabledReason::DISABLED_AUTHENTICATION_FAILURE,
311 DisabledReason::DISABLED_ASSOCIATION_REJECTION,
312 DisabledReason::DISABLED_DHCP_FAILURE,
313 DisabledReason::DISABLED_CONSECUTIVE_FAILURES,
314 };
315 EnableAllNetworksByEnteringSettings(enableReasons);
316 }
317 }
318
LogDisabledConfig(const WifiDeviceConfig & config)319 void BlockConnectService::LogDisabledConfig(const WifiDeviceConfig &config)
320 {
321 if (config.networkSelectionStatus.status == WifiDeviceConfigStatus::ENABLED) {
322 WIFI_LOGD("%{public}s config is ENABLED", SsidAnonymize(config.ssid).c_str());
323 return;
324 }
325 if (config.networkSelectionStatus.status == WifiDeviceConfigStatus::DISABLED) {
326 WIFI_LOGI("%{public}s config is DISABLED due to reason: %{public}d",
327 SsidAnonymize(config.ssid).c_str(), config.networkSelectionStatus.networkSelectionDisableReason);
328 return;
329 }
330 if (config.networkSelectionStatus.status == WifiDeviceConfigStatus::PERMEMANTLY_DISABLED) {
331 WIFI_LOGI("%{public}s networkId :%{public}d config is PERMEMANTLY DISABLED due to reason: %{public}d",
332 SsidAnonymize(config.ssid).c_str(), config.networkId,
333 config.networkSelectionStatus.networkSelectionDisableReason);
334 return;
335 }
336 }
337 }
338 }