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