1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include <poll.h>
17094332d3Sopenharmony_ci#include <sys/types.h>
18094332d3Sopenharmony_ci#include <securec.h>
19094332d3Sopenharmony_ci#include <unistd.h>
20094332d3Sopenharmony_ci#include <errno.h>
21094332d3Sopenharmony_ci#include <net/if.h>
22094332d3Sopenharmony_ci#include <linux/nl80211.h>
23094332d3Sopenharmony_ci#include <netlink/genl/ctrl.h>
24094332d3Sopenharmony_ci#include <netlink/genl/genl.h>
25094332d3Sopenharmony_ci#include <netlink/handlers.h>
26094332d3Sopenharmony_ci#include <osal_mem.h>
27094332d3Sopenharmony_ci
28094332d3Sopenharmony_ci#include "hilog/log.h"
29094332d3Sopenharmony_ci#include "../wifi_common_cmd.h"
30094332d3Sopenharmony_ci#include "netlink_adapter.h"
31094332d3Sopenharmony_ci
32094332d3Sopenharmony_ci#define OUI_QCA 0x001374
33094332d3Sopenharmony_ci
34094332d3Sopenharmony_ci#define LISTEN_FD_NUMS 2
35094332d3Sopenharmony_ci#define EVENT_SOCKET_INDEX 0
36094332d3Sopenharmony_ci#define CTRL_SOCKET_INDEX 1
37094332d3Sopenharmony_ci#define CTRL_SOCKET_WRITE_SIDE 0
38094332d3Sopenharmony_ci#define CTRL_SOCKET_READ_SIDE 1
39094332d3Sopenharmony_ci
40094332d3Sopenharmony_ci#define BUFSIZE 1024
41094332d3Sopenharmony_ci#define POLLTIMEOUT 1000
42094332d3Sopenharmony_ci
43094332d3Sopenharmony_cistatic inline uint32_t BitLeftShift(uint8_t x)
44094332d3Sopenharmony_ci{
45094332d3Sopenharmony_ci    return 1U << x;
46094332d3Sopenharmony_ci}
47094332d3Sopenharmony_ci
48094332d3Sopenharmony_ci#define SCAN_QUAL_INVALID      BitLeftShift(0)
49094332d3Sopenharmony_ci#define SCAN_NOISE_INVALID     BitLeftShift(1)
50094332d3Sopenharmony_ci#define SCAN_LEVEL_INVALID     BitLeftShift(2)
51094332d3Sopenharmony_ci#define SCAN_LEVEL_DBM         BitLeftShift(3)
52094332d3Sopenharmony_ci#define SCAN_ASSOCIATED        BitLeftShift(5)
53094332d3Sopenharmony_ci
54094332d3Sopenharmony_ci#define SUCCESS_STATUS 0
55094332d3Sopenharmony_ci#define WLAN_ATTR_SCAN_COOKIE 7
56094332d3Sopenharmony_ci#define WLAN_ATTR_SCAN_STATUS 8
57094332d3Sopenharmony_ci#define WLAN_ATTR_SCAN_MAX 11
58094332d3Sopenharmony_ci#define SCAN_STATUS_MAX 2
59094332d3Sopenharmony_ci#define NL80211_SCAN_DONE 107
60094332d3Sopenharmony_ci#define WLAN_CMD_VDR_COMMON 0xCB
61094332d3Sopenharmony_ci#define DATA_FRAME_MAX_SIZE 1400
62094332d3Sopenharmony_ci
63094332d3Sopenharmony_citypedef struct {
64094332d3Sopenharmony_ci    WifiScanResults *scanResults;
65094332d3Sopenharmony_ci    const char *ifName;
66094332d3Sopenharmony_ci} WifiScanResultArg;
67094332d3Sopenharmony_ci
68094332d3Sopenharmony_cistatic int g_familyId = 0;
69094332d3Sopenharmony_ci
70094332d3Sopenharmony_cistatic int NoSeqCheck(struct nl_msg *msg, void *arg)
71094332d3Sopenharmony_ci{
72094332d3Sopenharmony_ci    (void)msg;
73094332d3Sopenharmony_ci    return NL_OK;
74094332d3Sopenharmony_ci}
75094332d3Sopenharmony_ci
76094332d3Sopenharmony_cistatic void QcaWifiEventScanDoneProcess(const char *ifName, struct nlattr *data, size_t len)
77094332d3Sopenharmony_ci{
78094332d3Sopenharmony_ci    struct nlattr *attr[WLAN_ATTR_SCAN_MAX + 1];
79094332d3Sopenharmony_ci    uint32_t status;
80094332d3Sopenharmony_ci
81094332d3Sopenharmony_ci    if (nla_parse(attr, WLAN_ATTR_SCAN_MAX, data, len, NULL) ||
82094332d3Sopenharmony_ci        attr[WLAN_ATTR_SCAN_STATUS] ||
83094332d3Sopenharmony_ci        !attr[WLAN_ATTR_SCAN_COOKIE]) {
84094332d3Sopenharmony_ci        return;
85094332d3Sopenharmony_ci    }
86094332d3Sopenharmony_ci
87094332d3Sopenharmony_ci    status = nla_get_u8(attr[WLAN_ATTR_SCAN_STATUS]);
88094332d3Sopenharmony_ci    if (status >= SCAN_STATUS_MAX) {
89094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: invalid status",  __FUNCTION__);
90094332d3Sopenharmony_ci        return;
91094332d3Sopenharmony_ci    }
92094332d3Sopenharmony_ci
93094332d3Sopenharmony_ci    WifiEventReport(ifName, WIFI_EVENT_SCAN_DONE, &status);
94094332d3Sopenharmony_ci}
95094332d3Sopenharmony_ci
96094332d3Sopenharmony_cistatic void WifiEventVendorProcess(const char *ifName, struct nlattr **attr)
97094332d3Sopenharmony_ci{
98094332d3Sopenharmony_ci    uint32_t vendorId;
99094332d3Sopenharmony_ci    uint32_t subCmd;
100094332d3Sopenharmony_ci    uint8_t *data = NULL;
101094332d3Sopenharmony_ci    uint32_t len;
102094332d3Sopenharmony_ci
103094332d3Sopenharmony_ci    if (attr[NL80211_ATTR_VENDOR_ID] == NULL) {
104094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: failed to get vendor id", __FUNCTION__);
105094332d3Sopenharmony_ci        return;
106094332d3Sopenharmony_ci    }
107094332d3Sopenharmony_ci    if (attr[NL80211_ATTR_VENDOR_SUBCMD] == NULL) {
108094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: failed to get vendor subcmd", __FUNCTION__);
109094332d3Sopenharmony_ci        return;
110094332d3Sopenharmony_ci    }
111094332d3Sopenharmony_ci
112094332d3Sopenharmony_ci    vendorId = nla_get_u32(attr[NL80211_ATTR_VENDOR_ID]);
113094332d3Sopenharmony_ci    subCmd = nla_get_u32(attr[NL80211_ATTR_VENDOR_SUBCMD]);
114094332d3Sopenharmony_ci    if (vendorId != OUI_QCA || subCmd != NL80211_SCAN_DONE) {
115094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: unsupported vendor event", __FUNCTION__);
116094332d3Sopenharmony_ci        return;
117094332d3Sopenharmony_ci    }
118094332d3Sopenharmony_ci
119094332d3Sopenharmony_ci    if (attr[NL80211_ATTR_VENDOR_DATA] == NULL) {
120094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: get vendor data fail", __FUNCTION__);
121094332d3Sopenharmony_ci        return;
122094332d3Sopenharmony_ci    }
123094332d3Sopenharmony_ci    data = nla_data(attr[NL80211_ATTR_VENDOR_DATA]);
124094332d3Sopenharmony_ci    len = (uint32_t)nla_len(attr[NL80211_ATTR_VENDOR_DATA]);
125094332d3Sopenharmony_ci
126094332d3Sopenharmony_ci    QcaWifiEventScanDoneProcess(ifName, (struct nlattr *)data, len);
127094332d3Sopenharmony_ci}
128094332d3Sopenharmony_ci
129094332d3Sopenharmony_cistatic int32_t GetNlaDataScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
130094332d3Sopenharmony_ci{
131094332d3Sopenharmony_ci    uint8_t *ie;
132094332d3Sopenharmony_ci    uint8_t *beaconIe;
133094332d3Sopenharmony_ci    uint8_t *bssid;
134094332d3Sopenharmony_ci
135094332d3Sopenharmony_ci    (void)len;
136094332d3Sopenharmony_ci    if (attr[NL80211_BSS_INFORMATION_ELEMENTS]) {
137094332d3Sopenharmony_ci        ie = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
138094332d3Sopenharmony_ci        scanResult->ieLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
139094332d3Sopenharmony_ci        if (ie != NULL && scanResult->ieLen != 0) {
140094332d3Sopenharmony_ci            scanResult->ie = OsalMemCalloc(scanResult->ieLen);
141094332d3Sopenharmony_ci            if (scanResult->ie == NULL || memcpy_s(scanResult->ie, scanResult->ieLen, ie, scanResult->ieLen) != EOK) {
142094332d3Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "%s: fill ie data fail", __FUNCTION__);
143094332d3Sopenharmony_ci                return RET_CODE_FAILURE;
144094332d3Sopenharmony_ci            }
145094332d3Sopenharmony_ci        }
146094332d3Sopenharmony_ci    }
147094332d3Sopenharmony_ci    if (attr[NL80211_BSS_BEACON_IES]) {
148094332d3Sopenharmony_ci        beaconIe = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
149094332d3Sopenharmony_ci        scanResult->beaconIeLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
150094332d3Sopenharmony_ci        if (beaconIe != NULL && scanResult->beaconIeLen != 0) {
151094332d3Sopenharmony_ci            scanResult->beaconIe = OsalMemCalloc(scanResult->beaconIeLen);
152094332d3Sopenharmony_ci            if (scanResult->beaconIe == NULL ||
153094332d3Sopenharmony_ci                memcpy_s(scanResult->beaconIe, scanResult->beaconIeLen, beaconIe, scanResult->beaconIeLen) != EOK) {
154094332d3Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "%s: fill beacon ie data fail", __FUNCTION__);
155094332d3Sopenharmony_ci                return RET_CODE_FAILURE;
156094332d3Sopenharmony_ci            }
157094332d3Sopenharmony_ci        }
158094332d3Sopenharmony_ci    }
159094332d3Sopenharmony_ci    if (attr[NL80211_BSS_BSSID]) {
160094332d3Sopenharmony_ci        bssid = nla_data(attr[NL80211_BSS_BSSID]);
161094332d3Sopenharmony_ci        if (bssid != NULL) {
162094332d3Sopenharmony_ci            scanResult->bssid = OsalMemCalloc(ETH_ADDR_LEN);
163094332d3Sopenharmony_ci            if (scanResult->bssid == NULL || memcpy_s(scanResult->bssid, ETH_ADDR_LEN, bssid, ETH_ADDR_LEN) != EOK) {
164094332d3Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "%s: fill bssid fail", __FUNCTION__);
165094332d3Sopenharmony_ci                return RET_CODE_FAILURE;
166094332d3Sopenharmony_ci            }
167094332d3Sopenharmony_ci        }
168094332d3Sopenharmony_ci    }
169094332d3Sopenharmony_ci    return RET_CODE_SUCCESS;
170094332d3Sopenharmony_ci}
171094332d3Sopenharmony_ci
172094332d3Sopenharmony_cistatic int32_t DoGetScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
173094332d3Sopenharmony_ci{
174094332d3Sopenharmony_ci    if (GetNlaDataScanResult(attr, len, scanResult) != RET_CODE_SUCCESS) {
175094332d3Sopenharmony_ci        return RET_CODE_FAILURE;
176094332d3Sopenharmony_ci    }
177094332d3Sopenharmony_ci    if (attr[NL80211_BSS_FREQUENCY]) {
178094332d3Sopenharmony_ci        scanResult->freq = nla_get_u32(attr[NL80211_BSS_FREQUENCY]);
179094332d3Sopenharmony_ci    }
180094332d3Sopenharmony_ci    if (attr[NL80211_BSS_BEACON_INTERVAL]) {
181094332d3Sopenharmony_ci        scanResult->beaconInt = nla_get_u16(attr[NL80211_BSS_BEACON_INTERVAL]);
182094332d3Sopenharmony_ci    }
183094332d3Sopenharmony_ci    if (attr[NL80211_BSS_CAPABILITY]) {
184094332d3Sopenharmony_ci        scanResult->caps = nla_get_u16(attr[NL80211_BSS_CAPABILITY]);
185094332d3Sopenharmony_ci    }
186094332d3Sopenharmony_ci    if (attr[NL80211_BSS_SIGNAL_MBM]) {
187094332d3Sopenharmony_ci         /* mBm to dBm */
188094332d3Sopenharmony_ci        scanResult->level = (int32_t)nla_get_u32(attr[NL80211_BSS_SIGNAL_MBM]) / SIGNAL_LEVEL_CONFFICIENT;
189094332d3Sopenharmony_ci        scanResult->flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
190094332d3Sopenharmony_ci    } else if (attr[NL80211_BSS_SIGNAL_UNSPEC]) {
191094332d3Sopenharmony_ci        scanResult->level = (int32_t)nla_get_u8(attr[NL80211_BSS_SIGNAL_UNSPEC]);
192094332d3Sopenharmony_ci        scanResult->flags |= SCAN_QUAL_INVALID;
193094332d3Sopenharmony_ci    } else {
194094332d3Sopenharmony_ci        scanResult->flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
195094332d3Sopenharmony_ci    }
196094332d3Sopenharmony_ci    if (attr[NL80211_BSS_TSF]) {
197094332d3Sopenharmony_ci        scanResult->tsf = nla_get_u64(attr[NL80211_BSS_TSF]);
198094332d3Sopenharmony_ci    }
199094332d3Sopenharmony_ci    if (attr[NL80211_BSS_BEACON_TSF]) {
200094332d3Sopenharmony_ci        uint64_t tsf = nla_get_u64(attr[NL80211_BSS_BEACON_TSF]);
201094332d3Sopenharmony_ci        if (tsf > scanResult->tsf) {
202094332d3Sopenharmony_ci            scanResult->tsf = tsf;
203094332d3Sopenharmony_ci        }
204094332d3Sopenharmony_ci    }
205094332d3Sopenharmony_ci    if (attr[NL80211_BSS_SEEN_MS_AGO]) {
206094332d3Sopenharmony_ci        scanResult->age = nla_get_u32(attr[NL80211_BSS_SEEN_MS_AGO]);
207094332d3Sopenharmony_ci    }
208094332d3Sopenharmony_ci    return RET_CODE_SUCCESS;
209094332d3Sopenharmony_ci}
210094332d3Sopenharmony_ci
211094332d3Sopenharmony_cistatic int32_t WifiGetScanResultHandler(struct nl_msg *msg, void *arg)
212094332d3Sopenharmony_ci{
213094332d3Sopenharmony_ci    WifiScanResult *scanResult = NULL;
214094332d3Sopenharmony_ci    WifiScanResults *scanResults = NULL;
215094332d3Sopenharmony_ci    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
216094332d3Sopenharmony_ci    WifiScanResultArg *handlerArg = (WifiScanResultArg *)arg;
217094332d3Sopenharmony_ci    struct nlattr *attr[NL80211_ATTR_MAX + 1], *bssAttr[NL80211_BSS_MAX + 1];
218094332d3Sopenharmony_ci    static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
219094332d3Sopenharmony_ci    memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
220094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
221094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
222094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
223094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
224094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
225094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
226094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
227094332d3Sopenharmony_ci    bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
228094332d3Sopenharmony_ci
229094332d3Sopenharmony_ci    if (handlerArg == NULL || handlerArg->scanResults == NULL || handlerArg->ifName == NULL) {
230094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: Invalid param",  __FUNCTION__);
231094332d3Sopenharmony_ci        return NL_SKIP;
232094332d3Sopenharmony_ci    }
233094332d3Sopenharmony_ci    scanResults = handlerArg->scanResults;
234094332d3Sopenharmony_ci    scanResult = &scanResults->scanResult[scanResults->num];
235094332d3Sopenharmony_ci    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
236094332d3Sopenharmony_ci    if (!attr[NL80211_ATTR_BSS]) {
237094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: bss info missing",  __FUNCTION__);
238094332d3Sopenharmony_ci        return NL_SKIP;
239094332d3Sopenharmony_ci    }
240094332d3Sopenharmony_ci    if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
241094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes",  __FUNCTION__);
242094332d3Sopenharmony_ci        return NL_SKIP;
243094332d3Sopenharmony_ci    }
244094332d3Sopenharmony_ci    if (DoGetScanResult(bssAttr, NL80211_BSS_MAX + 1, scanResult) != RET_CODE_SUCCESS) {
245094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: DoGetScanResult fail",  __FUNCTION__);
246094332d3Sopenharmony_ci        FreeScanResult(scanResult);
247094332d3Sopenharmony_ci        return NL_SKIP;
248094332d3Sopenharmony_ci    }
249094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "%{public}s, line:%{public}d num:%{public}u scanResultCapacity:%{public}u", __FUNCTION__,
250094332d3Sopenharmony_ci        __LINE__, scanResults->num, scanResults->scanResultCapacity);
251094332d3Sopenharmony_ci    scanResults->num++;
252094332d3Sopenharmony_ci    if (scanResults->num == scanResults->scanResultCapacity) {
253094332d3Sopenharmony_ci        scanResults->scanResultCapacity += INIT_SCAN_RES_NUM;
254094332d3Sopenharmony_ci        WifiScanResult *newScanResult = NULL;
255094332d3Sopenharmony_ci        newScanResult = (WifiScanResult *)OsalMemCalloc(sizeof(WifiScanResult) * (scanResults->scanResultCapacity));
256094332d3Sopenharmony_ci        if (newScanResult == NULL) {
257094332d3Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "%{public}s: newscanResult is NULL",  __FUNCTION__);
258094332d3Sopenharmony_ci            scanResults->scanResultCapacity -= INIT_SCAN_RES_NUM;
259094332d3Sopenharmony_ci            scanResults->num = 0;
260094332d3Sopenharmony_ci            return NL_SKIP;
261094332d3Sopenharmony_ci        }
262094332d3Sopenharmony_ci        if (memcpy_s((void *)newScanResult, sizeof(WifiScanResult) * (scanResults->scanResultCapacity),
263094332d3Sopenharmony_ci            (void *)scanResults->scanResult, sizeof(WifiScanResult) * (scanResults->num)) != RET_CODE_SUCCESS) {
264094332d3Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s fail",  __FUNCTION__);
265094332d3Sopenharmony_ci        }
266094332d3Sopenharmony_ci        OsalMemFree(scanResults->scanResult);
267094332d3Sopenharmony_ci        scanResults->scanResult = newScanResult;
268094332d3Sopenharmony_ci        newScanResult = NULL;
269094332d3Sopenharmony_ci    }
270094332d3Sopenharmony_ci    return NL_SKIP;
271094332d3Sopenharmony_ci}
272094332d3Sopenharmony_ci
273094332d3Sopenharmony_cistatic void WifiEventScanResultProcess(const char *ifName)
274094332d3Sopenharmony_ci{
275094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
276094332d3Sopenharmony_ci    int32_t ret;
277094332d3Sopenharmony_ci    WifiScanResults scanResults = {0};
278094332d3Sopenharmony_ci    WifiScanResultArg arg;
279094332d3Sopenharmony_ci    uint32_t ifaceId = if_nametoindex(ifName);
280094332d3Sopenharmony_ci    struct nl_msg *msg = nlmsg_alloc();
281094332d3Sopenharmony_ci    if (NULL == msg) {
282094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: msg is NULL.",  __FUNCTION__);
283094332d3Sopenharmony_ci        return;
284094332d3Sopenharmony_ci    }
285094332d3Sopenharmony_ci    if (InitScanResults(&scanResults) != RET_CODE_SUCCESS) {
286094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: InitScanResults failed",  __FUNCTION__);
287094332d3Sopenharmony_ci        return;
288094332d3Sopenharmony_ci    }
289094332d3Sopenharmony_ci    arg.scanResults = &scanResults;
290094332d3Sopenharmony_ci    arg.ifName = ifName;
291094332d3Sopenharmony_ci    genlmsg_put(msg, 0, 0, g_familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
292094332d3Sopenharmony_ci    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
293094332d3Sopenharmony_ci    ret = NetlinkSendCmdSync(msg, WifiGetScanResultHandler, (void *)&arg);
294094332d3Sopenharmony_ci    if (ret != RET_CODE_SUCCESS) {
295094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: send cmd failed",  __FUNCTION__);
296094332d3Sopenharmony_ci    }
297094332d3Sopenharmony_ci    WifiEventReport(ifName, WIFI_EVENT_SCAN_RESULTS, &scanResults);
298094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "%s: scanResults.num = %u", __FUNCTION__, scanResults.num);
299094332d3Sopenharmony_ci    FreeScanResults(&scanResults);
300094332d3Sopenharmony_ci    nlmsg_free(msg);
301094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
302094332d3Sopenharmony_ci}
303094332d3Sopenharmony_ci
304094332d3Sopenharmony_cistatic void WifiEventScanAbortedProcess(const char *ifName)
305094332d3Sopenharmony_ci{
306094332d3Sopenharmony_ci    WifiScanResults scanResults = {0};
307094332d3Sopenharmony_ci
308094332d3Sopenharmony_ci    if (ifName == NULL) {
309094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: ifName is NULL.",  __FUNCTION__);
310094332d3Sopenharmony_ci        return;
311094332d3Sopenharmony_ci    }
312094332d3Sopenharmony_ci    WifiEventReport(ifName, WIFI_EVENT_SCAN_ABORTED, &scanResults);
313094332d3Sopenharmony_ci}
314094332d3Sopenharmony_ci
315094332d3Sopenharmony_cistatic void WifiEventDataFrameProcess(const char *ifName, struct nlattr **attr)
316094332d3Sopenharmony_ci{
317094332d3Sopenharmony_ci    WifiDataFrame dataFrame;
318094332d3Sopenharmony_ci    /* The outer function can ensure that attr is not empty */
319094332d3Sopenharmony_ci    if (ifName == NULL || attr[NL80211_ATTR_FRAME] == NULL) {
320094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%{public}s: ifName is invalid or failed to get frame data", __FUNCTION__);
321094332d3Sopenharmony_ci        return;
322094332d3Sopenharmony_ci    }
323094332d3Sopenharmony_ci
324094332d3Sopenharmony_ci    (void)memset_s(&dataFrame, sizeof(WifiDataFrame), 0, sizeof(WifiDataFrame));
325094332d3Sopenharmony_ci
326094332d3Sopenharmony_ci    dataFrame.data = nla_data(attr[NL80211_ATTR_FRAME]);
327094332d3Sopenharmony_ci    dataFrame.dataLen = (uint32_t)nla_len(attr[NL80211_ATTR_FRAME]);
328094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "%{public}s: receive data frame len %{public}u", __FUNCTION__, dataFrame.dataLen);
329094332d3Sopenharmony_ci    if (dataFrame.dataLen > DATA_FRAME_MAX_SIZE) {
330094332d3Sopenharmony_ci        return;
331094332d3Sopenharmony_ci    }
332094332d3Sopenharmony_ci
333094332d3Sopenharmony_ci    WifiEventReport(ifName, WIFI_EVENT_DATA_FRAME_RECEIVED, &dataFrame);
334094332d3Sopenharmony_ci}
335094332d3Sopenharmony_ci
336094332d3Sopenharmony_cistatic void DoProcessEvent(const char *ifName, int cmd, struct nlattr **attr)
337094332d3Sopenharmony_ci{
338094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s cmd=%{public}d ifName=%{public}s", __FUNCTION__, cmd, ifName);
339094332d3Sopenharmony_ci    switch (cmd) {
340094332d3Sopenharmony_ci        case NL80211_CMD_VENDOR:
341094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_VENDOR");
342094332d3Sopenharmony_ci            WifiEventVendorProcess(ifName, attr);
343094332d3Sopenharmony_ci            break;
344094332d3Sopenharmony_ci        case NL80211_CMD_START_SCHED_SCAN:
345094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_START_SCHED_SCAN");
346094332d3Sopenharmony_ci            break;
347094332d3Sopenharmony_ci        case NL80211_CMD_SCHED_SCAN_RESULTS:
348094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCHED_SCAN_RESULTS");
349094332d3Sopenharmony_ci            WifiEventScanResultProcess(ifName);
350094332d3Sopenharmony_ci            break;
351094332d3Sopenharmony_ci        case NL80211_CMD_SCHED_SCAN_STOPPED:
352094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCHED_SCAN_STOPPED");
353094332d3Sopenharmony_ci            break;
354094332d3Sopenharmony_ci        case NL80211_CMD_NEW_SCAN_RESULTS:
355094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_NEW_SCAN_RESULTS");
356094332d3Sopenharmony_ci            WifiEventScanResultProcess(ifName);
357094332d3Sopenharmony_ci            break;
358094332d3Sopenharmony_ci        case NL80211_CMD_SCAN_ABORTED:
359094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCAN_ABORTED");
360094332d3Sopenharmony_ci            WifiEventScanAbortedProcess(ifName);
361094332d3Sopenharmony_ci            break;
362094332d3Sopenharmony_ci        case NL80211_CMD_TRIGGER_SCAN:
363094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_TRIGGER_SCAN");
364094332d3Sopenharmony_ci            break;
365094332d3Sopenharmony_ci        case NL80211_CMD_FRAME_TX_STATUS:
366094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_FRAME_TX_STATUS");
367094332d3Sopenharmony_ci            WifiEventTxStatus(ifName, attr);
368094332d3Sopenharmony_ci            break;
369094332d3Sopenharmony_ci        case WLAN_CMD_VDR_COMMON:
370094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "receive cmd WLAN_CMD_VDR_COMMON");
371094332d3Sopenharmony_ci            WifiEventDataFrameProcess(ifName, attr);
372094332d3Sopenharmony_ci            break;
373094332d3Sopenharmony_ci        default:
374094332d3Sopenharmony_ci            HILOG_INFO(LOG_CORE, "not supported cmd");
375094332d3Sopenharmony_ci            break;
376094332d3Sopenharmony_ci    }
377094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
378094332d3Sopenharmony_ci}
379094332d3Sopenharmony_ci
380094332d3Sopenharmony_cistatic int32_t ProcessEvent(struct nl_msg *msg, void *arg)
381094332d3Sopenharmony_ci{
382094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
383094332d3Sopenharmony_ci    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
384094332d3Sopenharmony_ci    struct nlattr *attr[NL80211_ATTR_MAX + 1];
385094332d3Sopenharmony_ci    struct NetworkInfoResult networkInfo;
386094332d3Sopenharmony_ci    uint32_t ifidx = -1;
387094332d3Sopenharmony_ci    uint32_t i;
388094332d3Sopenharmony_ci    int ret;
389094332d3Sopenharmony_ci
390094332d3Sopenharmony_ci    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
391094332d3Sopenharmony_ci        genlmsg_attrlen(hdr, 0), NULL);
392094332d3Sopenharmony_ci
393094332d3Sopenharmony_ci    if (attr[NL80211_ATTR_IFINDEX]) {
394094332d3Sopenharmony_ci        ifidx = nla_get_u32(attr[NL80211_ATTR_IFINDEX]);
395094332d3Sopenharmony_ci    }
396094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "ifidx = %{public}d", ifidx);
397094332d3Sopenharmony_ci
398094332d3Sopenharmony_ci    ret = GetUsableNetworkInfo(&networkInfo);
399094332d3Sopenharmony_ci    if (ret != RET_CODE_SUCCESS) {
400094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: get usable network information failed", __FUNCTION__);
401094332d3Sopenharmony_ci        return NL_SKIP;
402094332d3Sopenharmony_ci    }
403094332d3Sopenharmony_ci
404094332d3Sopenharmony_ci    for (i = 0; i < networkInfo.nums; i++) {
405094332d3Sopenharmony_ci        HILOG_DEBUG(LOG_CORE, "name=%{public}s index=%{public}d mode=%{public}s",
406094332d3Sopenharmony_ci            networkInfo.infos[i].name, if_nametoindex(networkInfo.infos[i].name), networkInfo.infos[i].supportMode);
407094332d3Sopenharmony_ci        if (ifidx == if_nametoindex(networkInfo.infos[i].name)) {
408094332d3Sopenharmony_ci            DoProcessEvent(networkInfo.infos[i].name, hdr->cmd, attr);
409094332d3Sopenharmony_ci            return NL_SKIP;
410094332d3Sopenharmony_ci        }
411094332d3Sopenharmony_ci    }
412094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
413094332d3Sopenharmony_ci    return NL_SKIP;
414094332d3Sopenharmony_ci}
415094332d3Sopenharmony_ci
416094332d3Sopenharmony_cistatic struct nl_cb *CreateCb(void)
417094332d3Sopenharmony_ci{
418094332d3Sopenharmony_ci    struct nl_cb *cb;
419094332d3Sopenharmony_ci
420094332d3Sopenharmony_ci    cb = nl_cb_alloc(NL_CB_DEFAULT);
421094332d3Sopenharmony_ci    if (cb == NULL) {
422094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: alloc cb failed", __FUNCTION__);
423094332d3Sopenharmony_ci        return NULL;
424094332d3Sopenharmony_ci    }
425094332d3Sopenharmony_ci
426094332d3Sopenharmony_ci    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, NoSeqCheck, NULL);
427094332d3Sopenharmony_ci    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ProcessEvent, NULL);
428094332d3Sopenharmony_ci
429094332d3Sopenharmony_ci    return cb;
430094332d3Sopenharmony_ci}
431094332d3Sopenharmony_ci
432094332d3Sopenharmony_cistatic int HandleEvent(struct nl_sock *sock)
433094332d3Sopenharmony_ci{
434094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
435094332d3Sopenharmony_ci    int ret;
436094332d3Sopenharmony_ci    struct nl_cb *cb = CreateCb();
437094332d3Sopenharmony_ci    if (cb == NULL) {
438094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%{public}s: Create cb failed", __FUNCTION__);
439094332d3Sopenharmony_ci        return RET_CODE_FAILURE;
440094332d3Sopenharmony_ci    }
441094332d3Sopenharmony_ci
442094332d3Sopenharmony_ci    ret = nl_recvmsgs(sock, cb);
443094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "nl_recvmsgs ret:%{public}d, errno:%{public}d %{public}s", ret, errno, strerror(errno));
444094332d3Sopenharmony_ci    nl_cb_put(cb);
445094332d3Sopenharmony_ci    cb = NULL;
446094332d3Sopenharmony_ci    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
447094332d3Sopenharmony_ci    return ret;
448094332d3Sopenharmony_ci}
449094332d3Sopenharmony_ci
450094332d3Sopenharmony_cistatic int32_t CtrlNoSeqCheck(struct nl_msg *msg, void *arg)
451094332d3Sopenharmony_ci{
452094332d3Sopenharmony_ci    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
453094332d3Sopenharmony_ci    struct nlattr *attr[NL80211_ATTR_MAX + 1];
454094332d3Sopenharmony_ci
455094332d3Sopenharmony_ci    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
456094332d3Sopenharmony_ci        genlmsg_attrlen(hdr, 0), NULL);
457094332d3Sopenharmony_ci
458094332d3Sopenharmony_ci    if (hdr->cmd != NL80211_CMD_FRAME) {
459094332d3Sopenharmony_ci        return NL_OK;
460094332d3Sopenharmony_ci    }
461094332d3Sopenharmony_ci    if (attr[NL80211_ATTR_FRAME] == NULL) {
462094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: failed to get frame data", __FUNCTION__);
463094332d3Sopenharmony_ci        return NL_OK;
464094332d3Sopenharmony_ci    }
465094332d3Sopenharmony_ci
466094332d3Sopenharmony_ci    WifiActionData actionData;
467094332d3Sopenharmony_ci    actionData.data = nla_data(attr[NL80211_ATTR_FRAME]);
468094332d3Sopenharmony_ci    actionData.dataLen = (uint32_t)nla_len(attr[NL80211_ATTR_FRAME]);
469094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "%s: receive data len = %{public}d", __FUNCTION__, actionData.dataLen);
470094332d3Sopenharmony_ci    WifiEventReport("p2p0", WIFI_EVENT_ACTION_RECEIVED, &actionData);
471094332d3Sopenharmony_ci    return NL_OK;
472094332d3Sopenharmony_ci}
473094332d3Sopenharmony_ci
474094332d3Sopenharmony_cistatic int32_t CtrlSocketErrorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
475094332d3Sopenharmony_ci{
476094332d3Sopenharmony_ci    int32_t *ret = (int32_t *)arg;
477094332d3Sopenharmony_ci    *ret = err->error;
478094332d3Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "%s: ctrl sock error ret = %{public}d", __FUNCTION__, *ret);
479094332d3Sopenharmony_ci    return NL_SKIP;
480094332d3Sopenharmony_ci}
481094332d3Sopenharmony_ci
482094332d3Sopenharmony_cistatic int32_t CtrlSocketFinishHandler(struct nl_msg *msg, void *arg)
483094332d3Sopenharmony_ci{
484094332d3Sopenharmony_ci    int32_t *ret = (int32_t *)arg;
485094332d3Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "%s: ctrl sock finish ret = %{public}d", __FUNCTION__, *ret);
486094332d3Sopenharmony_ci    *ret = 0;
487094332d3Sopenharmony_ci    return NL_SKIP;
488094332d3Sopenharmony_ci}
489094332d3Sopenharmony_ci
490094332d3Sopenharmony_cistatic int32_t CtrlSocketAckHandler(struct nl_msg *msg, void *arg)
491094332d3Sopenharmony_ci{
492094332d3Sopenharmony_ci    int32_t *err = (int32_t *)arg;
493094332d3Sopenharmony_ci    HILOG_ERROR(LOG_CORE, "%s: ctrl sock ack ret = %{public}d", __FUNCTION__, *err);
494094332d3Sopenharmony_ci    *err = 0;
495094332d3Sopenharmony_ci    return NL_STOP;
496094332d3Sopenharmony_ci}
497094332d3Sopenharmony_ci
498094332d3Sopenharmony_cistatic int HandleCtrlEvent(struct nl_sock *sock)
499094332d3Sopenharmony_ci{
500094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
501094332d3Sopenharmony_ci    int ret;
502094332d3Sopenharmony_ci    struct nl_cb *cb;
503094332d3Sopenharmony_ci    int error;
504094332d3Sopenharmony_ci
505094332d3Sopenharmony_ci    cb = nl_cb_alloc(NL_CB_DEFAULT);
506094332d3Sopenharmony_ci    if (cb == NULL) {
507094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%{public}s: alloc ctrl cb failed", __FUNCTION__);
508094332d3Sopenharmony_ci        return RET_CODE_FAILURE;
509094332d3Sopenharmony_ci    }
510094332d3Sopenharmony_ci
511094332d3Sopenharmony_ci    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, CtrlNoSeqCheck, NULL);
512094332d3Sopenharmony_ci    nl_cb_err(cb, NL_CB_CUSTOM, CtrlSocketErrorHandler, &error);
513094332d3Sopenharmony_ci    nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, CtrlSocketFinishHandler, &error);
514094332d3Sopenharmony_ci    nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, CtrlSocketAckHandler, &error);
515094332d3Sopenharmony_ci
516094332d3Sopenharmony_ci    ret = nl_recvmsgs(sock, cb);
517094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "nl_recvmsgs ret:%{public}d, errno:%{public}d %{public}s", ret, errno, strerror(errno));
518094332d3Sopenharmony_ci    nl_cb_put(cb);
519094332d3Sopenharmony_ci    cb = NULL;
520094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
521094332d3Sopenharmony_ci    return ret;
522094332d3Sopenharmony_ci}
523094332d3Sopenharmony_ci
524094332d3Sopenharmony_civoid *EventThread(void *para)
525094332d3Sopenharmony_ci{
526094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
527094332d3Sopenharmony_ci    struct nl_sock *eventSock = NULL;
528094332d3Sopenharmony_ci    struct nl_sock *ctrlSock = NULL;
529094332d3Sopenharmony_ci    struct pollfd pollFds[LISTEN_FD_NUMS] = {0};
530094332d3Sopenharmony_ci    struct WifiThreadParam *threadParam = NULL;
531094332d3Sopenharmony_ci    int ret;
532094332d3Sopenharmony_ci    enum ThreadStatus *status = NULL;
533094332d3Sopenharmony_ci
534094332d3Sopenharmony_ci    if (para == NULL) {
535094332d3Sopenharmony_ci        HILOG_ERROR(LOG_CORE, "%s: para is null", __FUNCTION__);
536094332d3Sopenharmony_ci        return NULL;
537094332d3Sopenharmony_ci    } else {
538094332d3Sopenharmony_ci        threadParam = (struct WifiThreadParam *)para;
539094332d3Sopenharmony_ci        eventSock = threadParam->eventSock;
540094332d3Sopenharmony_ci        ctrlSock = threadParam->ctrlSock;
541094332d3Sopenharmony_ci        g_familyId = threadParam->familyId;
542094332d3Sopenharmony_ci        status = threadParam->status;
543094332d3Sopenharmony_ci        *status = THREAD_RUN;
544094332d3Sopenharmony_ci    }
545094332d3Sopenharmony_ci
546094332d3Sopenharmony_ci    pollFds[EVENT_SOCKET_INDEX].fd = nl_socket_get_fd(eventSock);
547094332d3Sopenharmony_ci    pollFds[EVENT_SOCKET_INDEX].events = POLLIN | POLLERR;
548094332d3Sopenharmony_ci    pollFds[CTRL_SOCKET_INDEX].fd = nl_socket_get_fd(ctrlSock);
549094332d3Sopenharmony_ci    pollFds[CTRL_SOCKET_INDEX].events = POLLIN;
550094332d3Sopenharmony_ci
551094332d3Sopenharmony_ci    while (*status == THREAD_RUN) {
552094332d3Sopenharmony_ci        ret = TEMP_FAILURE_RETRY(poll(pollFds, LISTEN_FD_NUMS, POLLTIMEOUT));
553094332d3Sopenharmony_ci        HILOG_DEBUG(LOG_CORE, "EventThread TEMP_FAILURE_RETRY ret:%{public}d status:%{public}d", ret, *status);
554094332d3Sopenharmony_ci        if (ret < 0) {
555094332d3Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "%{public}s: fail poll", __FUNCTION__);
556094332d3Sopenharmony_ci            break;
557094332d3Sopenharmony_ci        } else if ((uint32_t)pollFds[EVENT_SOCKET_INDEX].revents & POLLERR) {
558094332d3Sopenharmony_ci            HILOG_ERROR(LOG_CORE, "%{public}s: event socket get POLLERR event", __FUNCTION__);
559094332d3Sopenharmony_ci            break;
560094332d3Sopenharmony_ci        } else if ((uint32_t)pollFds[EVENT_SOCKET_INDEX].revents & POLLIN) {
561094332d3Sopenharmony_ci            if (HandleEvent(eventSock) != RET_CODE_SUCCESS) {
562094332d3Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "EventThread HandleEvent break");
563094332d3Sopenharmony_ci                break;
564094332d3Sopenharmony_ci            }
565094332d3Sopenharmony_ci        } else if ((uint32_t)pollFds[CTRL_SOCKET_INDEX].revents & POLLIN) {
566094332d3Sopenharmony_ci            if (HandleCtrlEvent(ctrlSock) != RET_CODE_SUCCESS) {
567094332d3Sopenharmony_ci                HILOG_ERROR(LOG_CORE, "EventThread HandleCtrlEvent break");
568094332d3Sopenharmony_ci                break;
569094332d3Sopenharmony_ci            }
570094332d3Sopenharmony_ci        }
571094332d3Sopenharmony_ci    }
572094332d3Sopenharmony_ci
573094332d3Sopenharmony_ci    *status = THREAD_STOP;
574094332d3Sopenharmony_ci    HILOG_INFO(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
575094332d3Sopenharmony_ci    return NULL;
576094332d3Sopenharmony_ci}
577