1 /*
2  * Copyright (c) 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 "inner_link.h"
17 
18 #include "securec.h"
19 
20 #include "nlohmann/json.hpp"
21 
22 #include "conn_log.h"
23 #include "softbus_adapter_timer.h"
24 
25 #include "channel/auth_negotiate_channel.h"
26 #include "data/link_manager.h"
27 #include "utils/wifi_direct_anonymous.h"
28 #include "wifi_direct_ip_manager.h"
29 
30 namespace OHOS::SoftBus {
InnerLink(const std::string & remoteMac)31 InnerLink::InnerLink(const std::string &remoteMac)
32 {
33     SetRemoteBaseMac(remoteMac);
34 }
35 
InnerLink(LinkType type,const std::string & remoteDeviceId)36 InnerLink::InnerLink(LinkType type, const std::string &remoteDeviceId)
37 {
38     SetLinkType(type);
39     SetRemoteDeviceId(remoteDeviceId);
40 }
41 
~InnerLink()42 InnerLink::~InnerLink()
43 {
44     auto listenerModuleId = GetListenerModule();
45     bool hasAnotherUsed = false;
46     LinkManager::GetInstance().ForEach([&hasAnotherUsed, this](InnerLink &innerLink) {
47         if (innerLink.GetLinkType() == InnerLink::LinkType::P2P && innerLink.GetLocalIpv4() == this->GetLocalIpv4() &&
48             innerLink.GetRemoteDeviceId() != this->GetRemoteDeviceId()) {
49                 hasAnotherUsed = true;
50             }
51         return false;
52     });
53     CONN_LOGI(CONN_WIFI_DIRECT, "hasAnotherUsed=%{public}d", hasAnotherUsed);
54     if (listenerModuleId != UNUSE_BUTT) {
55         CONN_LOGI(CONN_WIFI_DIRECT, "stop auth listening");
56         if (GetLinkType() == LinkType::HML) {
57             AuthNegotiateChannel::StopListening(AUTH_LINK_TYPE_ENHANCED_P2P, listenerModuleId);
58             StopCustomListen(GetLocalCustomPort());
59         } else {
60             if (!hasAnotherUsed) {
61                 AuthNegotiateChannel::StopListening(AUTH_LINK_TYPE_P2P, listenerModuleId);
62             }
63         }
64     }
65     if (!GetLocalIpv4().empty() && !GetRemoteIpv4().empty() && !GetRemoteBaseMac().empty() && !hasAnotherUsed &&
66         !GetLegacyReused()) {
67         CONN_LOGI(CONN_WIFI_DIRECT, "release ip");
68         WifiDirectIpManager::GetInstance().ReleaseIpv4(
69             GetLocalInterface(), Ipv4Info(GetLocalIpv4()), Ipv4Info(GetRemoteIpv4()), GetRemoteBaseMac());
70     }
71 }
72 
GetLinkType() const73 InnerLink::LinkType InnerLink::GetLinkType() const
74 {
75     return Get(InnerLinKey::LINK_TYPE, LinkType::INVALID_TYPE);
76 }
77 
SetLinkType(InnerLink::LinkType type)78 void InnerLink::SetLinkType(InnerLink::LinkType type)
79 {
80     Set(InnerLinKey::LINK_TYPE, type);
81 }
82 
GetState() const83 InnerLink::LinkState InnerLink::GetState() const
84 {
85     return Get(InnerLinKey::STATE, LinkState::INVALID_STATE);
86 }
87 
SetState(LinkState newState)88 void InnerLink::SetState(LinkState newState)
89 {
90     LinkState oldState = GetState();
91     if (oldState != newState) {
92         uint64_t changeTime = SoftBusGetSysTimeMs();
93         Set(InnerLinKey::STATE_CHANGE_TIME, changeTime);
94         Set(InnerLinKey::STATE, newState);
95     }
96 }
97 
GetLocalInterface() const98 std::string InnerLink::GetLocalInterface() const
99 {
100     return Get(InnerLinKey::LOCAL_INTERFACE, std::string(""));
101 }
102 
SetLocalInterface(const std::string & interface)103 void InnerLink::SetLocalInterface(const std::string &interface)
104 {
105     Set(InnerLinKey::LOCAL_INTERFACE, interface);
106 }
107 
GetLocalBaseMac() const108 std::string InnerLink::GetLocalBaseMac() const
109 {
110     return Get(InnerLinKey::LOCAL_BASE_MAC, std::string(""));
111 }
112 
SetLocalBaseMac(const std::string & mac)113 void InnerLink::SetLocalBaseMac(const std::string &mac)
114 {
115     Set(InnerLinKey::LOCAL_BASE_MAC, mac);
116 }
117 
GetLocalDynamicMac() const118 std::string InnerLink::GetLocalDynamicMac() const
119 {
120     return Get(InnerLinKey::LOCAL_DYNAMIC_MAC, std::string(""));
121 }
122 
SetLocalDynamicMac(const std::string & mac)123 void InnerLink::SetLocalDynamicMac(const std::string &mac)
124 {
125     Set(InnerLinKey::LOCAL_DYNAMIC_MAC, mac);
126 }
127 
GetLocalIpv4() const128 std::string InnerLink::GetLocalIpv4() const
129 {
130     return Get(InnerLinKey::LOCAL_IPV4, std::string(""));
131 }
132 
SetLocalIpv4(const std::string & ip)133 void InnerLink::SetLocalIpv4(const std::string &ip)
134 {
135     Set(InnerLinKey::LOCAL_IPV4, ip);
136 }
137 
GetRemoteInterface() const138 std::string InnerLink::GetRemoteInterface() const
139 {
140     return Get(InnerLinKey::REMOTE_INTERFACE, std::string(""));
141 }
142 
SetRemoteInterface(const std::string & interface)143 void InnerLink::SetRemoteInterface(const std::string &interface)
144 {
145     Set(InnerLinKey::REMOTE_INTERFACE, interface);
146 }
147 
GetRemoteBaseMac() const148 std::string InnerLink::GetRemoteBaseMac() const
149 {
150     return Get(InnerLinKey::REMOTE_BASE_MAC, std::string(""));
151 }
152 
SetRemoteBaseMac(const std::string & mac)153 void InnerLink::SetRemoteBaseMac(const std::string &mac)
154 {
155     Set(InnerLinKey::REMOTE_BASE_MAC, mac);
156 }
157 
GetRemoteDynamicMac() const158 std::string InnerLink::GetRemoteDynamicMac() const
159 {
160     return Get(InnerLinKey::REMOTE_DYNAMIC_MAC, std::string(""));
161 }
162 
SetRemoteDynamicMac(const std::string & mac)163 void InnerLink::SetRemoteDynamicMac(const std::string &mac)
164 {
165     Set(InnerLinKey::REMOTE_DYNAMIC_MAC, mac);
166 }
167 
GetRemoteIpv4() const168 std::string InnerLink::GetRemoteIpv4() const
169 {
170     return Get(InnerLinKey::REMOTE_IPV4, std::string(""));
171 }
172 
SetRemoteIpv4(const std::string & ip)173 void InnerLink::SetRemoteIpv4(const std::string &ip)
174 {
175     Set(InnerLinKey::REMOTE_IPV4, ip);
176 }
177 
IsBeingUsedByLocal() const178 bool InnerLink::IsBeingUsedByLocal() const
179 {
180     return !linkIds_.empty();
181 }
182 
IsBeingUsedByRemote() const183 bool InnerLink::IsBeingUsedByRemote() const
184 {
185     return Get(InnerLinKey::IS_BEING_USED_BY_REMOTE, false);
186 }
187 
SetBeingUsedByRemote(bool value)188 void InnerLink::SetBeingUsedByRemote(bool value)
189 {
190     Set(InnerLinKey::IS_BEING_USED_BY_REMOTE, value);
191 }
192 
GetFrequency() const193 int InnerLink::GetFrequency() const
194 {
195     return Get(InnerLinKey::FREQUENCY, -1);
196 }
197 
SetFrequency(int frequency)198 void InnerLink::SetFrequency(int frequency)
199 {
200     Set(InnerLinKey::FREQUENCY, frequency);
201 }
202 
GetRemoteDeviceId() const203 std::string InnerLink::GetRemoteDeviceId() const
204 {
205     return Get(InnerLinKey::REMOTE_DEVICE_ID, std::string(""));
206 }
207 
SetRemoteDeviceId(const std::string & deviceId)208 void InnerLink::SetRemoteDeviceId(const std::string &deviceId)
209 {
210     Set(InnerLinKey::REMOTE_DEVICE_ID, deviceId);
211 }
212 
GetNegotiateChannel() const213 std::shared_ptr<NegotiateChannel> InnerLink::GetNegotiateChannel() const
214 {
215     return channel_;
216 }
217 
SetNegotiateChannel(const std::shared_ptr<NegotiateChannel> & channel)218 void InnerLink::SetNegotiateChannel(const std::shared_ptr<NegotiateChannel> &channel)
219 {
220     channel_ = channel;
221 }
222 
GetLocalPort() const223 int InnerLink::GetLocalPort() const
224 {
225     return Get(InnerLinKey::LOCAL_PORT, -1);
226 }
227 
SetLocalPort(int port)228 void InnerLink::SetLocalPort(int port)
229 {
230     Set(InnerLinKey::LOCAL_PORT, port);
231 }
232 
GetListenerModule() const233 ListenerModule InnerLink::GetListenerModule() const
234 {
235     return Get(InnerLinKey::LISTENER_MODULE_ID, static_cast<ListenerModule>(UNUSE_BUTT));
236 }
237 
SetListenerModule(ListenerModule module)238 void InnerLink::SetListenerModule(ListenerModule module)
239 {
240     Set(InnerLinKey::LISTENER_MODULE_ID, module);
241 }
242 
GetLocalIpv6() const243 std::string InnerLink::GetLocalIpv6() const
244 {
245     return Get(InnerLinKey::LOCAL_IPV6, std::string());
246 }
247 
SetLocalIpv6(const std::string & value)248 void InnerLink::SetLocalIpv6(const std::string &value)
249 {
250     Set(InnerLinKey::LOCAL_IPV6, value);
251 }
252 
GetRemoteIpv6() const253 std::string InnerLink::GetRemoteIpv6() const
254 {
255     return Get(InnerLinKey::REMOTE_IPV6, std::string());
256 }
257 
SetRemoteIpv6(const std::string & value)258 void InnerLink::SetRemoteIpv6(const std::string &value)
259 {
260     Set(InnerLinKey::REMOTE_IPV6, value);
261 }
262 
HasPtk() const263 bool InnerLink::HasPtk() const
264 {
265     return Get(InnerLinKey::HAS_PTK, false);
266 }
267 
SetPtk(bool value)268 void InnerLink::SetPtk(bool value)
269 {
270     Set(InnerLinKey::HAS_PTK, value);
271 }
272 
GetLocalCustomPort() const273 int32_t InnerLink::GetLocalCustomPort() const
274 {
275     return Get(InnerLinKey::LOCAL_CUSTOM_PORT, 0);
276 }
277 
SetLocalCustomPort(int32_t value)278 void InnerLink::SetLocalCustomPort(int32_t value)
279 {
280     Set(InnerLinKey::LOCAL_CUSTOM_PORT, value);
281 }
282 
GetRemoteCustomPort() const283 int32_t InnerLink::GetRemoteCustomPort() const
284 {
285     return Get(InnerLinKey::REMOTE_CUSTOM_PORT, 0);
286 }
287 
StopCustomListen(int32_t localCustomPort)288 void InnerLink::StopCustomListen(int32_t localCustomPort)
289 {
290     CONN_CHECK_AND_RETURN_LOGE(localCustomPort > 0, CONN_WIFI_DIRECT, "loacl custom port is zero");
291     bool hasMoreLocalCustomPort = false;
292     LinkManager::GetInstance().ForEach([&hasMoreLocalCustomPort] (InnerLink &link) {
293         if (link.GetLocalCustomPort() > 0) {
294             hasMoreLocalCustomPort = true;
295             return true;
296         }
297         return false;
298     });
299     if (!hasMoreLocalCustomPort) {
300         CONN_LOGI(CONN_WIFI_DIRECT, "localCustomPort=%{public}d, stop custom listening", localCustomPort);
301         AuthNegotiateChannel::StopCustomListening();
302     }
303 }
304 
SetRemoteCustomPort(int32_t value)305 void InnerLink::SetRemoteCustomPort(int32_t value)
306 {
307     Set(InnerLinKey::REMOTE_CUSTOM_PORT, value);
308 }
309 
GetNewPtkFrame() const310 bool InnerLink::GetNewPtkFrame() const
311 {
312     return Get(InnerLinKey::NEW_PTK_FRAME, false);
313 }
314 
SetNewPtkFrame(bool value)315 void InnerLink::SetNewPtkFrame(bool value)
316 {
317     Set(InnerLinKey::NEW_PTK_FRAME, value);
318 }
319 
GetLegacyReused() const320 bool InnerLink::GetLegacyReused() const
321 {
322     return Get(InnerLinKey::IS_LEGACY_REUSED, false);
323 }
324 
SetLegacyReused(bool value)325 void InnerLink::SetLegacyReused(bool value)
326 {
327     CONN_LOGI(CONN_WIFI_DIRECT, "set legacy reused=%{public}d", value);
328     Set(InnerLinKey::IS_LEGACY_REUSED, value);
329 }
330 
GenerateLink(uint32_t requestId,int pid,WifiDirectLink & link,bool ipv4)331 void InnerLink::GenerateLink(uint32_t requestId, int pid, WifiDirectLink &link, bool ipv4)
332 {
333     link.linkId = LinkManager::GetInstance().AllocateLinkId();
334     AddId(link.linkId, requestId, pid);
335     switch (GetLinkType()) {
336         case LinkType::HML:
337             link.linkType = WIFI_DIRECT_LINK_TYPE_HML;
338             break;
339         case LinkType::P2P:
340             link.linkType = WIFI_DIRECT_LINK_TYPE_P2P;
341             break;
342         default:
343             link.linkType = WIFI_DIRECT_LINK_TYPE_INVALID;
344             break;
345     }
346     std::string localIp;
347     std::string remoteIp;
348     if (ipv4 || GetLocalIpv6().empty()) {
349         localIp = GetLocalIpv4();
350         remoteIp = GetRemoteIpv4();
351     } else {
352         localIp = GetLocalIpv6();
353         remoteIp = GetRemoteIpv6();
354     }
355     if (strcpy_s(link.localIp, IP_STR_MAX_LEN, localIp.c_str()) != EOK) {
356         CONN_LOGI(CONN_WIFI_DIRECT, "local ip cpy failed, link id=%{public}d", link.linkId);
357         // fall-through
358     }
359     if (strcpy_s(link.remoteIp, IP_STR_MAX_LEN, remoteIp.c_str()) != EOK) {
360         CONN_LOGI(CONN_WIFI_DIRECT, "remote ip cpy failed, link id=%{public}d", link.linkId);
361         // fall-through
362     }
363     link.remotePort = GetRemoteCustomPort();
364 }
365 
AddId(int linkId,uint32_t requestId,int pid)366 void InnerLink::AddId(int linkId, uint32_t requestId, int pid)
367 {
368     auto item = std::make_shared<LinkIdStruct>();
369     item->id = linkId;
370     item->requestId = requestId;
371     item->pid = pid;
372     linkIds_[linkId] = item;
373 }
374 
RemoveId(int linkId)375 void InnerLink::RemoveId(int linkId)
376 {
377     if (linkIds_.find(linkId) == linkIds_.end()) {
378         return;
379     }
380     linkIds_.erase(linkId);
381 }
382 
IsContainId(int linkId) const383 bool InnerLink::IsContainId(int linkId) const
384 {
385     return linkIds_.find(linkId) != linkIds_.end();
386 }
387 
GetReference() const388 size_t InnerLink::GetReference() const
389 {
390     return linkIds_.size();
391 }
392 
IsProtected() const393 bool InnerLink::IsProtected() const
394 {
395     LinkState state = Get(InnerLinKey::STATE, LinkState::INVALID_STATE);
396     if (state != LinkState::CONNECTED) {
397         CONN_LOGI(CONN_WIFI_DIRECT, "state=%{public}d", static_cast<int>(state));
398         return false;
399     }
400 
401     uint64_t currentTime = SoftBusGetSysTimeMs();
402     uint64_t changeTime = Get(InnerLinKey::STATE_CHANGE_TIME, uint64_t(0));
403     if (currentTime && currentTime - PROTECT_DURATION_MS < changeTime) {
404         return true;
405     }
406     return false;
407 }
408 
Dump() const409 void InnerLink::Dump() const
410 {
411     nlohmann::json object;
412     object["LINK_TYPE"] = GetLinkType();
413     object["STATE"] = GetState();
414     object["LOCAL_INTERFACE"] = GetLocalInterface();
415     object["LOCAL_BASE_MAC"] = WifiDirectAnonymizeMac(GetLocalBaseMac());
416     object["REMOTE_BASE_MAC"] = WifiDirectAnonymizeMac(GetRemoteBaseMac());
417     object["LOCAL_IPV4"] = WifiDirectAnonymizeIp(GetLocalIpv4());
418     object["REMOTE_IPV4"] = WifiDirectAnonymizeIp(GetRemoteIpv4());
419     object["LOCAL_IPV6"] = WifiDirectAnonymizeIp(GetLocalIpv6());
420     object["REMOTE_IPV6"] = WifiDirectAnonymizeIp(GetRemoteIpv6());
421     object["IS_BEING_USED_BY_LOCAL"] = IsBeingUsedByLocal();
422     object["IS_BEING_USED_BY_REMOTE"] = IsBeingUsedByRemote();
423     object["FREQUENCY"] = GetFrequency();
424     object["REMOTE_DEVICE_ID"] = WifiDirectAnonymizeDeviceId(GetRemoteDeviceId());
425     object["LOCAL_PORT"] = GetLocalPort();
426     object["LISTENER_MODULE_ID"] = GetListenerModule();
427     object["NEGOTIATION_CHANNEL"] = channel_ != nullptr;
428     object["LOCAL_CUSTOM_PORT"] = GetLocalCustomPort();
429     object["REMOTE_CUSTOM_PORT"] = GetRemoteCustomPort();
430 
431     auto linkIdArrayObject = nlohmann::json::array();
432     for (const auto &[key, value] : linkIds_) {
433         nlohmann::json linkIdObject;
434         linkIdObject["LinkId"] = key;
435         linkIdObject["RequestId"] = value->requestId;
436         linkIdObject["Pid"] = value->pid;
437         linkIdArrayObject.push_back(linkIdObject);
438     }
439     object["LINKS"] = linkIdArrayObject;
440     CONN_LOGI(CONN_WIFI_DIRECT, "%{public}s", object.dump().c_str());
441 }
442 } // namespace OHOS::SoftBus
443