1/*
2 * Copyright (c) 2022-2023 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 <poll.h>
17#include <sys/types.h>
18#include <securec.h>
19#include <unistd.h>
20#include <errno.h>
21#include <net/if.h>
22#include <linux/nl80211.h>
23#include <netlink/genl/ctrl.h>
24#include <netlink/genl/genl.h>
25#include <netlink/handlers.h>
26#include <osal_mem.h>
27
28#include "hilog/log.h"
29#include "../wifi_common_cmd.h"
30#include "netlink_adapter.h"
31
32#define OUI_QCA 0x001374
33
34#define LISTEN_FD_NUMS 2
35#define EVENT_SOCKET_INDEX 0
36#define CTRL_SOCKET_INDEX 1
37#define CTRL_SOCKET_WRITE_SIDE 0
38#define CTRL_SOCKET_READ_SIDE 1
39
40#define BUFSIZE 1024
41#define POLLTIMEOUT 1000
42
43static inline uint32_t BitLeftShift(uint8_t x)
44{
45    return 1U << x;
46}
47
48#define SCAN_QUAL_INVALID      BitLeftShift(0)
49#define SCAN_NOISE_INVALID     BitLeftShift(1)
50#define SCAN_LEVEL_INVALID     BitLeftShift(2)
51#define SCAN_LEVEL_DBM         BitLeftShift(3)
52#define SCAN_ASSOCIATED        BitLeftShift(5)
53
54#define SUCCESS_STATUS 0
55#define WLAN_ATTR_SCAN_COOKIE 7
56#define WLAN_ATTR_SCAN_STATUS 8
57#define WLAN_ATTR_SCAN_MAX 11
58#define SCAN_STATUS_MAX 2
59#define NL80211_SCAN_DONE 107
60#define WLAN_CMD_VDR_COMMON 0xCB
61#define DATA_FRAME_MAX_SIZE 1400
62
63typedef struct {
64    WifiScanResults *scanResults;
65    const char *ifName;
66} WifiScanResultArg;
67
68static int g_familyId = 0;
69
70static int NoSeqCheck(struct nl_msg *msg, void *arg)
71{
72    (void)msg;
73    return NL_OK;
74}
75
76static void QcaWifiEventScanDoneProcess(const char *ifName, struct nlattr *data, size_t len)
77{
78    struct nlattr *attr[WLAN_ATTR_SCAN_MAX + 1];
79    uint32_t status;
80
81    if (nla_parse(attr, WLAN_ATTR_SCAN_MAX, data, len, NULL) ||
82        attr[WLAN_ATTR_SCAN_STATUS] ||
83        !attr[WLAN_ATTR_SCAN_COOKIE]) {
84        return;
85    }
86
87    status = nla_get_u8(attr[WLAN_ATTR_SCAN_STATUS]);
88    if (status >= SCAN_STATUS_MAX) {
89        HILOG_ERROR(LOG_CORE, "%s: invalid status",  __FUNCTION__);
90        return;
91    }
92
93    WifiEventReport(ifName, WIFI_EVENT_SCAN_DONE, &status);
94}
95
96static void WifiEventVendorProcess(const char *ifName, struct nlattr **attr)
97{
98    uint32_t vendorId;
99    uint32_t subCmd;
100    uint8_t *data = NULL;
101    uint32_t len;
102
103    if (attr[NL80211_ATTR_VENDOR_ID] == NULL) {
104        HILOG_ERROR(LOG_CORE, "%s: failed to get vendor id", __FUNCTION__);
105        return;
106    }
107    if (attr[NL80211_ATTR_VENDOR_SUBCMD] == NULL) {
108        HILOG_ERROR(LOG_CORE, "%s: failed to get vendor subcmd", __FUNCTION__);
109        return;
110    }
111
112    vendorId = nla_get_u32(attr[NL80211_ATTR_VENDOR_ID]);
113    subCmd = nla_get_u32(attr[NL80211_ATTR_VENDOR_SUBCMD]);
114    if (vendorId != OUI_QCA || subCmd != NL80211_SCAN_DONE) {
115        HILOG_ERROR(LOG_CORE, "%s: unsupported vendor event", __FUNCTION__);
116        return;
117    }
118
119    if (attr[NL80211_ATTR_VENDOR_DATA] == NULL) {
120        HILOG_ERROR(LOG_CORE, "%s: get vendor data fail", __FUNCTION__);
121        return;
122    }
123    data = nla_data(attr[NL80211_ATTR_VENDOR_DATA]);
124    len = (uint32_t)nla_len(attr[NL80211_ATTR_VENDOR_DATA]);
125
126    QcaWifiEventScanDoneProcess(ifName, (struct nlattr *)data, len);
127}
128
129static int32_t GetNlaDataScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
130{
131    uint8_t *ie;
132    uint8_t *beaconIe;
133    uint8_t *bssid;
134
135    (void)len;
136    if (attr[NL80211_BSS_INFORMATION_ELEMENTS]) {
137        ie = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
138        scanResult->ieLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
139        if (ie != NULL && scanResult->ieLen != 0) {
140            scanResult->ie = OsalMemCalloc(scanResult->ieLen);
141            if (scanResult->ie == NULL || memcpy_s(scanResult->ie, scanResult->ieLen, ie, scanResult->ieLen) != EOK) {
142                HILOG_ERROR(LOG_CORE, "%s: fill ie data fail", __FUNCTION__);
143                return RET_CODE_FAILURE;
144            }
145        }
146    }
147    if (attr[NL80211_BSS_BEACON_IES]) {
148        beaconIe = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
149        scanResult->beaconIeLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
150        if (beaconIe != NULL && scanResult->beaconIeLen != 0) {
151            scanResult->beaconIe = OsalMemCalloc(scanResult->beaconIeLen);
152            if (scanResult->beaconIe == NULL ||
153                memcpy_s(scanResult->beaconIe, scanResult->beaconIeLen, beaconIe, scanResult->beaconIeLen) != EOK) {
154                HILOG_ERROR(LOG_CORE, "%s: fill beacon ie data fail", __FUNCTION__);
155                return RET_CODE_FAILURE;
156            }
157        }
158    }
159    if (attr[NL80211_BSS_BSSID]) {
160        bssid = nla_data(attr[NL80211_BSS_BSSID]);
161        if (bssid != NULL) {
162            scanResult->bssid = OsalMemCalloc(ETH_ADDR_LEN);
163            if (scanResult->bssid == NULL || memcpy_s(scanResult->bssid, ETH_ADDR_LEN, bssid, ETH_ADDR_LEN) != EOK) {
164                HILOG_ERROR(LOG_CORE, "%s: fill bssid fail", __FUNCTION__);
165                return RET_CODE_FAILURE;
166            }
167        }
168    }
169    return RET_CODE_SUCCESS;
170}
171
172static int32_t DoGetScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
173{
174    if (GetNlaDataScanResult(attr, len, scanResult) != RET_CODE_SUCCESS) {
175        return RET_CODE_FAILURE;
176    }
177    if (attr[NL80211_BSS_FREQUENCY]) {
178        scanResult->freq = nla_get_u32(attr[NL80211_BSS_FREQUENCY]);
179    }
180    if (attr[NL80211_BSS_BEACON_INTERVAL]) {
181        scanResult->beaconInt = nla_get_u16(attr[NL80211_BSS_BEACON_INTERVAL]);
182    }
183    if (attr[NL80211_BSS_CAPABILITY]) {
184        scanResult->caps = nla_get_u16(attr[NL80211_BSS_CAPABILITY]);
185    }
186    if (attr[NL80211_BSS_SIGNAL_MBM]) {
187         /* mBm to dBm */
188        scanResult->level = (int32_t)nla_get_u32(attr[NL80211_BSS_SIGNAL_MBM]) / SIGNAL_LEVEL_CONFFICIENT;
189        scanResult->flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
190    } else if (attr[NL80211_BSS_SIGNAL_UNSPEC]) {
191        scanResult->level = (int32_t)nla_get_u8(attr[NL80211_BSS_SIGNAL_UNSPEC]);
192        scanResult->flags |= SCAN_QUAL_INVALID;
193    } else {
194        scanResult->flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
195    }
196    if (attr[NL80211_BSS_TSF]) {
197        scanResult->tsf = nla_get_u64(attr[NL80211_BSS_TSF]);
198    }
199    if (attr[NL80211_BSS_BEACON_TSF]) {
200        uint64_t tsf = nla_get_u64(attr[NL80211_BSS_BEACON_TSF]);
201        if (tsf > scanResult->tsf) {
202            scanResult->tsf = tsf;
203        }
204    }
205    if (attr[NL80211_BSS_SEEN_MS_AGO]) {
206        scanResult->age = nla_get_u32(attr[NL80211_BSS_SEEN_MS_AGO]);
207    }
208    return RET_CODE_SUCCESS;
209}
210
211static int32_t WifiGetScanResultHandler(struct nl_msg *msg, void *arg)
212{
213    WifiScanResult *scanResult = NULL;
214    WifiScanResults *scanResults = NULL;
215    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
216    WifiScanResultArg *handlerArg = (WifiScanResultArg *)arg;
217    struct nlattr *attr[NL80211_ATTR_MAX + 1], *bssAttr[NL80211_BSS_MAX + 1];
218    static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
219    memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
220    bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
221    bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
222    bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
223    bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
224    bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
225    bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
226    bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
227    bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
228
229    if (handlerArg == NULL || handlerArg->scanResults == NULL || handlerArg->ifName == NULL) {
230        HILOG_ERROR(LOG_CORE, "%s: Invalid param",  __FUNCTION__);
231        return NL_SKIP;
232    }
233    scanResults = handlerArg->scanResults;
234    scanResult = &scanResults->scanResult[scanResults->num];
235    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
236    if (!attr[NL80211_ATTR_BSS]) {
237        HILOG_ERROR(LOG_CORE, "%s: bss info missing",  __FUNCTION__);
238        return NL_SKIP;
239    }
240    if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
241        HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes",  __FUNCTION__);
242        return NL_SKIP;
243    }
244    if (DoGetScanResult(bssAttr, NL80211_BSS_MAX + 1, scanResult) != RET_CODE_SUCCESS) {
245        HILOG_ERROR(LOG_CORE, "%s: DoGetScanResult fail",  __FUNCTION__);
246        FreeScanResult(scanResult);
247        return NL_SKIP;
248    }
249    HILOG_DEBUG(LOG_CORE, "%{public}s, line:%{public}d num:%{public}u scanResultCapacity:%{public}u", __FUNCTION__,
250        __LINE__, scanResults->num, scanResults->scanResultCapacity);
251    scanResults->num++;
252    if (scanResults->num == scanResults->scanResultCapacity) {
253        scanResults->scanResultCapacity += INIT_SCAN_RES_NUM;
254        WifiScanResult *newScanResult = NULL;
255        newScanResult = (WifiScanResult *)OsalMemCalloc(sizeof(WifiScanResult) * (scanResults->scanResultCapacity));
256        if (newScanResult == NULL) {
257            HILOG_ERROR(LOG_CORE, "%{public}s: newscanResult is NULL",  __FUNCTION__);
258            scanResults->scanResultCapacity -= INIT_SCAN_RES_NUM;
259            scanResults->num = 0;
260            return NL_SKIP;
261        }
262        if (memcpy_s((void *)newScanResult, sizeof(WifiScanResult) * (scanResults->scanResultCapacity),
263            (void *)scanResults->scanResult, sizeof(WifiScanResult) * (scanResults->num)) != RET_CODE_SUCCESS) {
264            HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s fail",  __FUNCTION__);
265        }
266        OsalMemFree(scanResults->scanResult);
267        scanResults->scanResult = newScanResult;
268        newScanResult = NULL;
269    }
270    return NL_SKIP;
271}
272
273static void WifiEventScanResultProcess(const char *ifName)
274{
275    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
276    int32_t ret;
277    WifiScanResults scanResults = {0};
278    WifiScanResultArg arg;
279    uint32_t ifaceId = if_nametoindex(ifName);
280    struct nl_msg *msg = nlmsg_alloc();
281    if (NULL == msg) {
282        HILOG_ERROR(LOG_CORE, "%s: msg is NULL.",  __FUNCTION__);
283        return;
284    }
285    if (InitScanResults(&scanResults) != RET_CODE_SUCCESS) {
286        HILOG_ERROR(LOG_CORE, "%s: InitScanResults failed",  __FUNCTION__);
287        return;
288    }
289    arg.scanResults = &scanResults;
290    arg.ifName = ifName;
291    genlmsg_put(msg, 0, 0, g_familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
292    nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
293    ret = NetlinkSendCmdSync(msg, WifiGetScanResultHandler, (void *)&arg);
294    if (ret != RET_CODE_SUCCESS) {
295        HILOG_ERROR(LOG_CORE, "%s: send cmd failed",  __FUNCTION__);
296    }
297    WifiEventReport(ifName, WIFI_EVENT_SCAN_RESULTS, &scanResults);
298    HILOG_INFO(LOG_CORE, "%s: scanResults.num = %u", __FUNCTION__, scanResults.num);
299    FreeScanResults(&scanResults);
300    nlmsg_free(msg);
301    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
302}
303
304static void WifiEventScanAbortedProcess(const char *ifName)
305{
306    WifiScanResults scanResults = {0};
307
308    if (ifName == NULL) {
309        HILOG_ERROR(LOG_CORE, "%s: ifName is NULL.",  __FUNCTION__);
310        return;
311    }
312    WifiEventReport(ifName, WIFI_EVENT_SCAN_ABORTED, &scanResults);
313}
314
315static void WifiEventDataFrameProcess(const char *ifName, struct nlattr **attr)
316{
317    WifiDataFrame dataFrame;
318    /* The outer function can ensure that attr is not empty */
319    if (ifName == NULL || attr[NL80211_ATTR_FRAME] == NULL) {
320        HILOG_ERROR(LOG_CORE, "%{public}s: ifName is invalid or failed to get frame data", __FUNCTION__);
321        return;
322    }
323
324    (void)memset_s(&dataFrame, sizeof(WifiDataFrame), 0, sizeof(WifiDataFrame));
325
326    dataFrame.data = nla_data(attr[NL80211_ATTR_FRAME]);
327    dataFrame.dataLen = (uint32_t)nla_len(attr[NL80211_ATTR_FRAME]);
328    HILOG_INFO(LOG_CORE, "%{public}s: receive data frame len %{public}u", __FUNCTION__, dataFrame.dataLen);
329    if (dataFrame.dataLen > DATA_FRAME_MAX_SIZE) {
330        return;
331    }
332
333    WifiEventReport(ifName, WIFI_EVENT_DATA_FRAME_RECEIVED, &dataFrame);
334}
335
336static void DoProcessEvent(const char *ifName, int cmd, struct nlattr **attr)
337{
338    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s cmd=%{public}d ifName=%{public}s", __FUNCTION__, cmd, ifName);
339    switch (cmd) {
340        case NL80211_CMD_VENDOR:
341            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_VENDOR");
342            WifiEventVendorProcess(ifName, attr);
343            break;
344        case NL80211_CMD_START_SCHED_SCAN:
345            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_START_SCHED_SCAN");
346            break;
347        case NL80211_CMD_SCHED_SCAN_RESULTS:
348            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCHED_SCAN_RESULTS");
349            WifiEventScanResultProcess(ifName);
350            break;
351        case NL80211_CMD_SCHED_SCAN_STOPPED:
352            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCHED_SCAN_STOPPED");
353            break;
354        case NL80211_CMD_NEW_SCAN_RESULTS:
355            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_NEW_SCAN_RESULTS");
356            WifiEventScanResultProcess(ifName);
357            break;
358        case NL80211_CMD_SCAN_ABORTED:
359            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_SCAN_ABORTED");
360            WifiEventScanAbortedProcess(ifName);
361            break;
362        case NL80211_CMD_TRIGGER_SCAN:
363            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_TRIGGER_SCAN");
364            break;
365        case NL80211_CMD_FRAME_TX_STATUS:
366            HILOG_INFO(LOG_CORE, "receive cmd NL80211_CMD_FRAME_TX_STATUS");
367            WifiEventTxStatus(ifName, attr);
368            break;
369        case WLAN_CMD_VDR_COMMON:
370            HILOG_INFO(LOG_CORE, "receive cmd WLAN_CMD_VDR_COMMON");
371            WifiEventDataFrameProcess(ifName, attr);
372            break;
373        default:
374            HILOG_INFO(LOG_CORE, "not supported cmd");
375            break;
376    }
377    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
378}
379
380static int32_t ProcessEvent(struct nl_msg *msg, void *arg)
381{
382    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
383    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
384    struct nlattr *attr[NL80211_ATTR_MAX + 1];
385    struct NetworkInfoResult networkInfo;
386    uint32_t ifidx = -1;
387    uint32_t i;
388    int ret;
389
390    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
391        genlmsg_attrlen(hdr, 0), NULL);
392
393    if (attr[NL80211_ATTR_IFINDEX]) {
394        ifidx = nla_get_u32(attr[NL80211_ATTR_IFINDEX]);
395    }
396    HILOG_INFO(LOG_CORE, "ifidx = %{public}d", ifidx);
397
398    ret = GetUsableNetworkInfo(&networkInfo);
399    if (ret != RET_CODE_SUCCESS) {
400        HILOG_ERROR(LOG_CORE, "%s: get usable network information failed", __FUNCTION__);
401        return NL_SKIP;
402    }
403
404    for (i = 0; i < networkInfo.nums; i++) {
405        HILOG_DEBUG(LOG_CORE, "name=%{public}s index=%{public}d mode=%{public}s",
406            networkInfo.infos[i].name, if_nametoindex(networkInfo.infos[i].name), networkInfo.infos[i].supportMode);
407        if (ifidx == if_nametoindex(networkInfo.infos[i].name)) {
408            DoProcessEvent(networkInfo.infos[i].name, hdr->cmd, attr);
409            return NL_SKIP;
410        }
411    }
412    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
413    return NL_SKIP;
414}
415
416static struct nl_cb *CreateCb(void)
417{
418    struct nl_cb *cb;
419
420    cb = nl_cb_alloc(NL_CB_DEFAULT);
421    if (cb == NULL) {
422        HILOG_ERROR(LOG_CORE, "%s: alloc cb failed", __FUNCTION__);
423        return NULL;
424    }
425
426    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, NoSeqCheck, NULL);
427    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ProcessEvent, NULL);
428
429    return cb;
430}
431
432static int HandleEvent(struct nl_sock *sock)
433{
434    HILOG_DEBUG(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
435    int ret;
436    struct nl_cb *cb = CreateCb();
437    if (cb == NULL) {
438        HILOG_ERROR(LOG_CORE, "%{public}s: Create cb failed", __FUNCTION__);
439        return RET_CODE_FAILURE;
440    }
441
442    ret = nl_recvmsgs(sock, cb);
443    HILOG_INFO(LOG_CORE, "nl_recvmsgs ret:%{public}d, errno:%{public}d %{public}s", ret, errno, strerror(errno));
444    nl_cb_put(cb);
445    cb = NULL;
446    HILOG_DEBUG(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
447    return ret;
448}
449
450static int32_t CtrlNoSeqCheck(struct nl_msg *msg, void *arg)
451{
452    struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
453    struct nlattr *attr[NL80211_ATTR_MAX + 1];
454
455    nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
456        genlmsg_attrlen(hdr, 0), NULL);
457
458    if (hdr->cmd != NL80211_CMD_FRAME) {
459        return NL_OK;
460    }
461    if (attr[NL80211_ATTR_FRAME] == NULL) {
462        HILOG_ERROR(LOG_CORE, "%s: failed to get frame data", __FUNCTION__);
463        return NL_OK;
464    }
465
466    WifiActionData actionData;
467    actionData.data = nla_data(attr[NL80211_ATTR_FRAME]);
468    actionData.dataLen = (uint32_t)nla_len(attr[NL80211_ATTR_FRAME]);
469    HILOG_INFO(LOG_CORE, "%s: receive data len = %{public}d", __FUNCTION__, actionData.dataLen);
470    WifiEventReport("p2p0", WIFI_EVENT_ACTION_RECEIVED, &actionData);
471    return NL_OK;
472}
473
474static int32_t CtrlSocketErrorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
475{
476    int32_t *ret = (int32_t *)arg;
477    *ret = err->error;
478    HILOG_ERROR(LOG_CORE, "%s: ctrl sock error ret = %{public}d", __FUNCTION__, *ret);
479    return NL_SKIP;
480}
481
482static int32_t CtrlSocketFinishHandler(struct nl_msg *msg, void *arg)
483{
484    int32_t *ret = (int32_t *)arg;
485    HILOG_ERROR(LOG_CORE, "%s: ctrl sock finish ret = %{public}d", __FUNCTION__, *ret);
486    *ret = 0;
487    return NL_SKIP;
488}
489
490static int32_t CtrlSocketAckHandler(struct nl_msg *msg, void *arg)
491{
492    int32_t *err = (int32_t *)arg;
493    HILOG_ERROR(LOG_CORE, "%s: ctrl sock ack ret = %{public}d", __FUNCTION__, *err);
494    *err = 0;
495    return NL_STOP;
496}
497
498static int HandleCtrlEvent(struct nl_sock *sock)
499{
500    HILOG_INFO(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
501    int ret;
502    struct nl_cb *cb;
503    int error;
504
505    cb = nl_cb_alloc(NL_CB_DEFAULT);
506    if (cb == NULL) {
507        HILOG_ERROR(LOG_CORE, "%{public}s: alloc ctrl cb failed", __FUNCTION__);
508        return RET_CODE_FAILURE;
509    }
510
511    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, CtrlNoSeqCheck, NULL);
512    nl_cb_err(cb, NL_CB_CUSTOM, CtrlSocketErrorHandler, &error);
513    nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, CtrlSocketFinishHandler, &error);
514    nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, CtrlSocketAckHandler, &error);
515
516    ret = nl_recvmsgs(sock, cb);
517    HILOG_INFO(LOG_CORE, "nl_recvmsgs ret:%{public}d, errno:%{public}d %{public}s", ret, errno, strerror(errno));
518    nl_cb_put(cb);
519    cb = NULL;
520    HILOG_INFO(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
521    return ret;
522}
523
524void *EventThread(void *para)
525{
526    HILOG_INFO(LOG_CORE, "hal enter %{public}s", __FUNCTION__);
527    struct nl_sock *eventSock = NULL;
528    struct nl_sock *ctrlSock = NULL;
529    struct pollfd pollFds[LISTEN_FD_NUMS] = {0};
530    struct WifiThreadParam *threadParam = NULL;
531    int ret;
532    enum ThreadStatus *status = NULL;
533
534    if (para == NULL) {
535        HILOG_ERROR(LOG_CORE, "%s: para is null", __FUNCTION__);
536        return NULL;
537    } else {
538        threadParam = (struct WifiThreadParam *)para;
539        eventSock = threadParam->eventSock;
540        ctrlSock = threadParam->ctrlSock;
541        g_familyId = threadParam->familyId;
542        status = threadParam->status;
543        *status = THREAD_RUN;
544    }
545
546    pollFds[EVENT_SOCKET_INDEX].fd = nl_socket_get_fd(eventSock);
547    pollFds[EVENT_SOCKET_INDEX].events = POLLIN | POLLERR;
548    pollFds[CTRL_SOCKET_INDEX].fd = nl_socket_get_fd(ctrlSock);
549    pollFds[CTRL_SOCKET_INDEX].events = POLLIN;
550
551    while (*status == THREAD_RUN) {
552        ret = TEMP_FAILURE_RETRY(poll(pollFds, LISTEN_FD_NUMS, POLLTIMEOUT));
553        HILOG_DEBUG(LOG_CORE, "EventThread TEMP_FAILURE_RETRY ret:%{public}d status:%{public}d", ret, *status);
554        if (ret < 0) {
555            HILOG_ERROR(LOG_CORE, "%{public}s: fail poll", __FUNCTION__);
556            break;
557        } else if ((uint32_t)pollFds[EVENT_SOCKET_INDEX].revents & POLLERR) {
558            HILOG_ERROR(LOG_CORE, "%{public}s: event socket get POLLERR event", __FUNCTION__);
559            break;
560        } else if ((uint32_t)pollFds[EVENT_SOCKET_INDEX].revents & POLLIN) {
561            if (HandleEvent(eventSock) != RET_CODE_SUCCESS) {
562                HILOG_ERROR(LOG_CORE, "EventThread HandleEvent break");
563                break;
564            }
565        } else if ((uint32_t)pollFds[CTRL_SOCKET_INDEX].revents & POLLIN) {
566            if (HandleCtrlEvent(ctrlSock) != RET_CODE_SUCCESS) {
567                HILOG_ERROR(LOG_CORE, "EventThread HandleCtrlEvent break");
568                break;
569            }
570        }
571    }
572
573    *status = THREAD_STOP;
574    HILOG_INFO(LOG_CORE, "hal exit %{public}s", __FUNCTION__);
575    return NULL;
576}
577