• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BitLeftShift(uint8_t x)43 static 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 
61 typedef struct {
62     WifiScanResults *scanResults;
63     const char *ifName;
64 } WifiScanResultArg;
65 
66 static int g_familyId = 0;
67 
HandleCtrlEvent(int fd)68 static int HandleCtrlEvent(int fd)
69 {
70     int ret;
71     char buf[BUFSIZE];
72 
73     ret = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
74     if (ret < 0) {
75         HILOG_ERROR(LOG_CORE, "%s: Read after POLL returned %d, error no = %d (%s)",
76             __FUNCTION__, ret, errno, strerror(errno));
77     }
78 
79     return ret;
80 }
81 
NoSeqCheck(struct nl_msg * msg,void * arg)82 static int NoSeqCheck(struct nl_msg *msg, void *arg)
83 {
84     (void)msg;
85     return NL_OK;
86 }
87 
QcaWifiEventScanDoneProcess(const char * ifName,struct nlattr * data,size_t len)88 static void QcaWifiEventScanDoneProcess(const char *ifName, struct nlattr *data, size_t len)
89 {
90     struct nlattr *attr[WLAN_ATTR_SCAN_MAX + 1];
91     uint32_t status;
92 
93     if (nla_parse(attr, WLAN_ATTR_SCAN_MAX, data, len, NULL) ||
94         attr[WLAN_ATTR_SCAN_STATUS] ||
95         !attr[WLAN_ATTR_SCAN_COOKIE]) {
96         return;
97     }
98 
99     status = nla_get_u8(attr[WLAN_ATTR_SCAN_STATUS]);
100     if (status >= SCAN_STATUS_MAX) {
101         HILOG_ERROR(LOG_CORE, "%s: invalid status", __func__);
102         return;
103     }
104 
105     WifiEventReport(ifName, WIFI_EVENT_SCAN_DONE, &status);
106 }
107 
WifiEventVendorProcess(const char * ifName,struct nlattr ** attr)108 static void WifiEventVendorProcess(const char *ifName, struct nlattr **attr)
109 {
110     uint32_t vendorId;
111     uint32_t subCmd;
112     uint8_t *data = NULL;
113     uint32_t len;
114 
115     if (attr[NL80211_ATTR_VENDOR_ID] == NULL) {
116         HILOG_ERROR(LOG_CORE, "%s: failed to get vendor id", __FUNCTION__);
117         return;
118     }
119     if (attr[NL80211_ATTR_VENDOR_SUBCMD] == NULL) {
120         HILOG_ERROR(LOG_CORE, "%s: failed to get vendor subcmd", __FUNCTION__);
121         return;
122     }
123 
124     vendorId = nla_get_u32(attr[NL80211_ATTR_VENDOR_ID]);
125     subCmd = nla_get_u32(attr[NL80211_ATTR_VENDOR_SUBCMD]);
126     if (vendorId != OUI_QCA || subCmd != NL80211_SCAN_DONE) {
127         HILOG_ERROR(LOG_CORE, "%s: unsupported vendor event", __FUNCTION__);
128         return;
129     }
130 
131     if (attr[NL80211_ATTR_VENDOR_DATA] == NULL) {
132         HILOG_ERROR(LOG_CORE, "%s: get vendor data fail", __FUNCTION__);
133         return;
134     }
135     data = nla_data(attr[NL80211_ATTR_VENDOR_DATA]);
136     len = nla_len(attr[NL80211_ATTR_VENDOR_DATA]);
137 
138     QcaWifiEventScanDoneProcess(ifName, (struct nlattr *)data, len);
139 }
140 
GetNlaDataScanResult(struct nlattr * attr[],int len,WifiScanResult * scanResult)141 static int32_t GetNlaDataScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
142 {
143     uint8_t *ie;
144     uint8_t *beaconIe;
145     uint8_t *bssid;
146 
147     (void)len;
148     if (attr[NL80211_BSS_INFORMATION_ELEMENTS]) {
149         ie = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
150         scanResult->ieLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
151         if (ie != NULL && scanResult->ieLen != 0) {
152             scanResult->ie = OsalMemCalloc(scanResult->ieLen);
153             if (scanResult->ie == NULL || memcpy_s(scanResult->ie, scanResult->ieLen, ie, scanResult->ieLen) != EOK) {
154                 HILOG_ERROR(LOG_CORE, "%s: fill ie data fail", __FUNCTION__);
155                 return RET_CODE_FAILURE;
156             }
157         }
158     }
159     if (attr[NL80211_BSS_BEACON_IES]) {
160         beaconIe = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
161         scanResult->beaconIeLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
162         if (beaconIe != NULL && scanResult->beaconIeLen != 0) {
163             scanResult->beaconIe = OsalMemCalloc(scanResult->beaconIeLen);
164             if (scanResult->beaconIe == NULL ||
165                 memcpy_s(scanResult->beaconIe, scanResult->beaconIeLen, beaconIe, scanResult->beaconIeLen) != EOK) {
166                 HILOG_ERROR(LOG_CORE, "%s: fill beacon ie data fail", __FUNCTION__);
167                 return RET_CODE_FAILURE;
168             }
169         }
170     }
171     if (attr[NL80211_BSS_BSSID]) {
172         bssid = nla_data(attr[NL80211_BSS_BSSID]);
173         if (bssid != NULL) {
174             scanResult->bssid = OsalMemCalloc(ETH_ADDR_LEN);
175             if (scanResult->bssid == NULL || memcpy_s(scanResult->bssid, ETH_ADDR_LEN, bssid, ETH_ADDR_LEN) != EOK) {
176                 HILOG_ERROR(LOG_CORE, "%s: fill bssid fail", __FUNCTION__);
177                 return RET_CODE_FAILURE;
178             }
179         }
180     }
181     return RET_CODE_SUCCESS;
182 }
183 
DoGetScanResult(struct nlattr * attr[],int len,WifiScanResult * scanResult)184 static int32_t DoGetScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
185 {
186     if (GetNlaDataScanResult(attr, len, scanResult) != RET_CODE_SUCCESS) {
187         return RET_CODE_FAILURE;
188     }
189     if (attr[NL80211_BSS_FREQUENCY]) {
190         scanResult->freq = nla_get_u32(attr[NL80211_BSS_FREQUENCY]);
191     }
192     if (attr[NL80211_BSS_BEACON_INTERVAL]) {
193         scanResult->beaconInt = nla_get_u16(attr[NL80211_BSS_BEACON_INTERVAL]);
194     }
195     if (attr[NL80211_BSS_CAPABILITY]) {
196         scanResult->caps = nla_get_u16(attr[NL80211_BSS_CAPABILITY]);
197     }
198     if (attr[NL80211_BSS_SIGNAL_MBM]) {
199          /* mBm to dBm */
200         scanResult->level = (int32_t)nla_get_u32(attr[NL80211_BSS_SIGNAL_MBM]) / SIGNAL_LEVEL_CONFFICIENT;
201         scanResult->flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
202     } else if (attr[NL80211_BSS_SIGNAL_UNSPEC]) {
203         scanResult->level = (int32_t)nla_get_u8(attr[NL80211_BSS_SIGNAL_UNSPEC]);
204         scanResult->flags |= SCAN_QUAL_INVALID;
205     } else {
206         scanResult->flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
207     }
208     if (attr[NL80211_BSS_TSF]) {
209         scanResult->tsf = nla_get_u64(attr[NL80211_BSS_TSF]);
210     }
211     if (attr[NL80211_BSS_BEACON_TSF]) {
212         uint64_t tsf = nla_get_u64(attr[NL80211_BSS_BEACON_TSF]);
213         if (tsf > scanResult->tsf) {
214             scanResult->tsf = tsf;
215         }
216     }
217     if (attr[NL80211_BSS_SEEN_MS_AGO]) {
218         scanResult->age = nla_get_u32(attr[NL80211_BSS_SEEN_MS_AGO]);
219     }
220     return RET_CODE_SUCCESS;
221 }
222 
WifiGetScanResultHandler(struct nl_msg * msg,void * arg)223 static int32_t WifiGetScanResultHandler(struct nl_msg *msg, void *arg)
224 {
225     WifiScanResult *scanResult = NULL;
226     WifiScanResults *scanResults = NULL;
227     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
228     WifiScanResultArg *handlerArg = (WifiScanResultArg *)arg;
229     struct nlattr *attr[NL80211_ATTR_MAX + 1], *bssAttr[NL80211_BSS_MAX + 1];
230     static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
231     memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
232     bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
233     bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
234     bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
235     bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
236     bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
237     bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
238     bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
239     bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
240 
241     if (handlerArg == NULL || handlerArg->scanResults == NULL ||
242         handlerArg->scanResults->num >= MAX_SCAN_RES_NUM || handlerArg->ifName == NULL) {
243         HILOG_ERROR(LOG_CORE, "%s: Invalid param", __func__);
244         return NL_SKIP;
245     }
246     scanResults = handlerArg->scanResults;
247     scanResult = &scanResults->scanResult[scanResults->num];
248     nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
249     if (!attr[NL80211_ATTR_BSS]) {
250         HILOG_ERROR(LOG_CORE, "%s: bss info missing", __func__);
251         return NL_SKIP;
252     }
253     if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
254         HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes", __func__);
255         return NL_SKIP;
256     }
257     if (DoGetScanResult(bssAttr, NL80211_BSS_MAX + 1, scanResult) != RET_CODE_SUCCESS) {
258         HILOG_ERROR(LOG_CORE, "%s: DoGetScanResult fail", __func__);
259         FreeScanResult(scanResult);
260         return NL_SKIP;
261     }
262     WifiEventReport(handlerArg->ifName, WIFI_EVENT_SCAN_RESULT, scanResult);
263     scanResults->num++;
264     if (scanResults->num == MAX_SCAN_RES_NUM) {
265         WifiEventReport(handlerArg->ifName, WIFI_EVENT_SCAN_RESULTS, scanResults);
266         FreeScanResults(scanResults);
267         (void)memset_s(scanResults, sizeof(WifiScanResults), 0, sizeof(WifiScanResults));
268     }
269     return NL_SKIP;
270 }
271 
WifiEventScanResultProcess(const char * ifName)272 static void WifiEventScanResultProcess(const char *ifName)
273 {
274     int32_t ret;
275     WifiScanResults scanResults = {0};
276     WifiScanResultArg arg;
277     uint32_t ifaceId = if_nametoindex(ifName);
278     struct nl_msg *msg = nlmsg_alloc();
279 
280     arg.scanResults = &scanResults;
281     arg.ifName = ifName;
282     genlmsg_put(msg, 0, 0, g_familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
283     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
284     ret = NetlinkSendCmdSync(msg, WifiGetScanResultHandler, (void *)&arg);
285     if (ret != RET_CODE_SUCCESS) {
286         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __func__);
287     }
288     if (scanResults.num != 0) {
289         WifiEventReport(ifName, WIFI_EVENT_SCAN_RESULTS, &scanResults);
290     }
291     FreeScanResults(&scanResults);
292     nlmsg_free(msg);
293 }
294 
WifiEventScanAbortedProcess(const char * ifName)295 static void WifiEventScanAbortedProcess(const char *ifName)
296 {
297     WifiScanResults scanResults = {0};
298 
299     if (ifName == NULL) {
300         HILOG_ERROR(LOG_CORE, "%s: ifName is NULL.", __func__);
301         return;
302     }
303     WifiEventReport(ifName, WIFI_EVENT_SCAN_ABORTED, &scanResults);
304 }
305 
DoProcessEvent(const char * ifName,int cmd,struct nlattr ** attr)306 static void DoProcessEvent(const char *ifName, int cmd, struct nlattr **attr)
307 {
308     switch (cmd) {
309         case NL80211_CMD_VENDOR:
310             WifiEventVendorProcess(ifName, attr);
311             break;
312         case NL80211_CMD_START_SCHED_SCAN:
313             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_START_SCHED_SCAN, cmd = %d", __FUNCTION__, cmd);
314             break;
315         case NL80211_CMD_SCHED_SCAN_RESULTS:
316             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_SCHED_SCAN_RESULTS, cmd = %d", __FUNCTION__, cmd);
317             WifiEventScanResultProcess(ifName);
318             break;
319         case NL80211_CMD_SCHED_SCAN_STOPPED:
320             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_SCHED_SCAN_STOPPED, cmd = %d", __FUNCTION__, cmd);
321             break;
322         case NL80211_CMD_NEW_SCAN_RESULTS:
323             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_NEW_SCAN_RESULTS, cmd = %d", __FUNCTION__, cmd);
324             WifiEventScanResultProcess(ifName);
325             break;
326         case NL80211_CMD_SCAN_ABORTED:
327             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_SCAN_ABORTED, cmd = %d", __FUNCTION__, cmd);
328             WifiEventScanAbortedProcess(ifName);
329             break;
330         case NL80211_CMD_TRIGGER_SCAN:
331             HILOG_INFO(LOG_CORE, "%s: receive cmd NL80211_CMD_TRIGGER_SCAN, cmd = %d", __FUNCTION__, cmd);
332             break;
333         default:
334             HILOG_INFO(LOG_CORE, "%s: not supported cmd, cmd = %d", __FUNCTION__, cmd);
335             break;
336     }
337 }
338 
ProcessEvent(struct nl_msg * msg,void * arg)339 static int32_t ProcessEvent(struct nl_msg *msg, void *arg)
340 {
341     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
342     struct nlattr *attr[NL80211_ATTR_MAX + 1];
343     struct NetworkInfoResult networkInfo;
344     uint32_t ifidx = -1;
345     uint32_t i;
346     int ret;
347 
348     nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
349         genlmsg_attrlen(hdr, 0), NULL);
350 
351     if (attr[NL80211_ATTR_IFINDEX]) {
352         ifidx = nla_get_u32(attr[NL80211_ATTR_IFINDEX]);
353     }
354 
355     ret = GetUsableNetworkInfo(&networkInfo);
356     if (ret != RET_CODE_SUCCESS) {
357         HILOG_ERROR(LOG_CORE, "%s: get usable network information failed", __FUNCTION__);
358         return NL_SKIP;
359     }
360 
361     for (i = 0; i < networkInfo.nums; i++) {
362         if (ifidx == if_nametoindex(networkInfo.infos[i].name)) {
363             DoProcessEvent(networkInfo.infos[i].name, hdr->cmd, attr);
364             return NL_SKIP;
365         }
366     }
367 
368     return NL_SKIP;
369 }
370 
CreateCb(void)371 static struct nl_cb *CreateCb(void)
372 {
373     struct nl_cb *cb;
374 
375     cb = nl_cb_alloc(NL_CB_DEFAULT);
376     if (cb == NULL) {
377         HILOG_ERROR(LOG_CORE, "%s: alloc cb failed", __FUNCTION__);
378         return NULL;
379     }
380 
381     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, NoSeqCheck, NULL);
382     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ProcessEvent, NULL);
383 
384     return cb;
385 }
386 
HandleEvent(struct nl_sock * sock)387 static int HandleEvent(struct nl_sock *sock)
388 {
389     int ret;
390     struct nl_cb *cb = CreateCb();
391     if (cb == NULL) {
392         HILOG_ERROR(LOG_CORE, "%s: Create cb failed", __FUNCTION__);
393         return RET_CODE_FAILURE;
394     }
395 
396     ret = nl_recvmsgs(sock, cb);
397 
398     nl_cb_put(cb);
399     cb = NULL;
400     return ret;
401 }
402 
EventThread(void * para)403 void *EventThread(void *para)
404 {
405     struct nl_sock *eventSock = NULL;
406     struct pollfd pollFds[LISTEN_FD_NUMS] = {0};
407     struct WifiThreadParam *threadParam = NULL;
408     int ctrlSocks[2];
409     int ret;
410     enum ThreadStatus *status = NULL;
411 
412     if (para == NULL) {
413         HILOG_ERROR(LOG_CORE, "%s: para is null", __FUNCTION__);
414         return NULL;
415     } else {
416         threadParam = (struct WifiThreadParam *)para;
417         eventSock = threadParam->eventSock;
418         g_familyId = threadParam->familyId;
419         status = threadParam->status;
420         *status = THREAD_RUN;
421     }
422 
423     pollFds[EVENT_SOCKET_INDEX].fd = nl_socket_get_fd(eventSock);
424     pollFds[EVENT_SOCKET_INDEX].events = POLLIN | POLLERR;
425 
426     ret = socketpair(AF_UNIX, SOCK_STREAM, 0, ctrlSocks);
427     if (ret != 0) {
428         HILOG_ERROR(LOG_CORE, "%s: fail socketpair", __FUNCTION__);
429         *status = THREAD_STOP;
430         return NULL;
431     }
432     pollFds[CTRL_SOCKET_INDEX].fd = ctrlSocks[CTRL_SOCKET_READ_SIDE];
433     pollFds[CTRL_SOCKET_INDEX].events = POLLIN | POLLERR;
434 
435     while (*status == THREAD_RUN) {
436         ret = TEMP_FAILURE_RETRY(poll(pollFds, LISTEN_FD_NUMS, POLLTIMEOUT));
437         if (ret < 0) {
438             HILOG_ERROR(LOG_CORE, "%s: fail poll", __FUNCTION__);
439             break;
440         } else if (pollFds[EVENT_SOCKET_INDEX].revents & POLLERR) {
441             HILOG_ERROR(LOG_CORE, "%s: event socket get POLLERR event", __FUNCTION__);
442             break;
443         } else if (pollFds[EVENT_SOCKET_INDEX].revents & POLLIN) {
444             if (HandleEvent(eventSock) != RET_CODE_SUCCESS) {
445                 break;
446             }
447         } else if (pollFds[CTRL_SOCKET_INDEX].revents & POLLERR) {
448             HILOG_ERROR(LOG_CORE, "%s: ctrl socket get POLLERR event", __FUNCTION__);
449             break;
450         } else if (pollFds[CTRL_SOCKET_INDEX].revents & POLLIN) {
451             if (HandleCtrlEvent(pollFds[CTRL_SOCKET_INDEX].fd) != RET_CODE_SUCCESS) {
452                 break;
453             }
454         }
455     }
456 
457     close(pollFds[CTRL_SOCKET_INDEX].fd);
458     *status = THREAD_STOP;
459     return NULL;
460 }
461