• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
27 #include "hilog/log.h"
28 #include "../wifi_common_cmd.h"
29 #include "netlink_adapter.h"
30 
31 #define OUI_QCA 0x001374
32 
33 #define LISTEN_FD_NUMS 2
34 #define EVENT_SOCKET_INDEX 0
35 #define CTRL_SOCKET_INDEX 1
36 #define CTRL_SOCKET_WRITE_SIDE 0
37 #define CTRL_SOCKET_READ_SIDE 1
38 
39 #define BUFSIZE 1024
40 #define POLLTIMEOUT 1000
41 #define SIGNALLEVELCONFFICIENT 100
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 static int g_familyId = 0;
62 
HandleCtrlEvent(int fd)63 static int HandleCtrlEvent(int fd)
64 {
65     int ret;
66     char buf[BUFSIZE];
67 
68     ret = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)));
69     if (ret < 0) {
70         HILOG_ERROR(LOG_CORE, "%s: Read after POLL returned %d, error no = %d (%s)",
71             __FUNCTION__, ret, errno, strerror(errno));
72     }
73 
74     return ret;
75 }
76 
NoSeqCheck(struct nl_msg * msg,void * arg)77 static int NoSeqCheck(struct nl_msg *msg, void *arg)
78 {
79     (void)msg;
80     return NL_OK;
81 }
82 
QcaWifiEventScanDoneProcess(const char * ifName,struct nlattr * data,size_t len)83 static void QcaWifiEventScanDoneProcess(const char *ifName, struct nlattr *data, size_t len)
84 {
85     struct nlattr *attr[WLAN_ATTR_SCAN_MAX + 1];
86     uint32_t status;
87 
88     if (nla_parse(attr, WLAN_ATTR_SCAN_MAX, data, len, NULL) ||
89         attr[WLAN_ATTR_SCAN_STATUS] ||
90         !attr[WLAN_ATTR_SCAN_COOKIE]) {
91         return;
92     }
93 
94     status = nla_get_u8(attr[WLAN_ATTR_SCAN_STATUS]);
95     if (status >= SCAN_STATUS_MAX) {
96         HILOG_ERROR(LOG_CORE, "%s: invalid status", __func__);
97         return;
98     }
99 
100     WifiEventReport(ifName, WIFI_EVENT_SCAN_DONE, &status);
101 }
102 
WifiEventVendorProcess(const char * ifName,struct nlattr ** attr)103 static void WifiEventVendorProcess(const char *ifName, struct nlattr **attr)
104 {
105     uint32_t vendor_id;
106     uint32_t subcmd;
107     uint8_t *data = NULL;
108     uint32_t len;
109 
110     if (attr[NL80211_ATTR_VENDOR_ID] == NULL) {
111         HILOG_ERROR(LOG_CORE, "%s: failed to get vendor id", __FUNCTION__);
112         return;
113     }
114     if (attr[NL80211_ATTR_VENDOR_SUBCMD] == NULL) {
115         HILOG_ERROR(LOG_CORE, "%s: failed to get vendor subcmd", __FUNCTION__);
116         return;
117     }
118 
119     vendor_id = nla_get_u32(attr[NL80211_ATTR_VENDOR_ID]);
120     subcmd = nla_get_u32(attr[NL80211_ATTR_VENDOR_SUBCMD]);
121     if (vendor_id != OUI_QCA || subcmd != NL80211_SCAN_DONE) {
122         HILOG_ERROR(LOG_CORE, "%s: unsupported vendor event", __FUNCTION__);
123         return;
124     }
125 
126     if (attr[NL80211_ATTR_VENDOR_DATA] == NULL) {
127         HILOG_ERROR(LOG_CORE, "%s: get vendor data fail", __FUNCTION__);
128         return;
129     }
130     data = nla_data(attr[NL80211_ATTR_VENDOR_DATA]);
131     len = nla_len(attr[NL80211_ATTR_VENDOR_DATA]);
132 
133     QcaWifiEventScanDoneProcess(ifName, (struct nlattr *)data, len);
134 }
135 
DoGetScanResult(struct nlattr * attr[],int len,WifiScanResult * scanResult)136 static void DoGetScanResult(struct nlattr *attr[], int len, WifiScanResult *scanResult)
137 {
138     if (attr[NL80211_BSS_INFORMATION_ELEMENTS]) {
139         scanResult->ie = nla_data(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
140         scanResult->ieLen = (uint32_t)nla_len(attr[NL80211_BSS_INFORMATION_ELEMENTS]);
141     }
142     if (attr[NL80211_BSS_BEACON_IES]) {
143         scanResult->beaconIe = nla_data(attr[NL80211_BSS_BEACON_IES]);
144         scanResult->beaconIeLen = (uint32_t)nla_len(attr[NL80211_BSS_BEACON_IES]);
145     }
146     if (attr[NL80211_BSS_BSSID]) {
147         scanResult->bssid = nla_data(attr[NL80211_BSS_BSSID]);
148     }
149     if (attr[NL80211_BSS_FREQUENCY]) {
150         scanResult->freq = nla_get_u32(attr[NL80211_BSS_FREQUENCY]);
151     }
152     if (attr[NL80211_BSS_BEACON_INTERVAL]) {
153         scanResult->beaconInt = nla_get_u16(attr[NL80211_BSS_BEACON_INTERVAL]);
154     }
155     if (attr[NL80211_BSS_CAPABILITY]) {
156         scanResult->caps = nla_get_u16(attr[NL80211_BSS_CAPABILITY]);
157     }
158     if (attr[NL80211_BSS_SIGNAL_MBM]) {
159          /* mBm to dBm */
160         scanResult->level = (int32_t)nla_get_u32(attr[NL80211_BSS_SIGNAL_MBM]) / SIGNALLEVELCONFFICIENT;
161         scanResult->flags |= SCAN_LEVEL_DBM | SCAN_QUAL_INVALID;
162     } else if (attr[NL80211_BSS_SIGNAL_UNSPEC]) {
163         scanResult->level = (int32_t)nla_get_u8(attr[NL80211_BSS_SIGNAL_UNSPEC]);
164         scanResult->flags |= SCAN_QUAL_INVALID;
165     } else {
166         scanResult->flags |= SCAN_LEVEL_INVALID | SCAN_QUAL_INVALID;
167     }
168     if (attr[NL80211_BSS_SEEN_MS_AGO]) {
169         scanResult->age = nla_get_u32(attr[NL80211_BSS_SEEN_MS_AGO]);
170     }
171 }
172 
WifiGetScanResultHandler(struct nl_msg * msg,void * arg)173 static int32_t WifiGetScanResultHandler(struct nl_msg *msg, void *arg)
174 {
175     WifiScanResult scanResult = {0};
176     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
177     const char *ifName = (const char *)arg;
178     struct nlattr *attr[NL80211_ATTR_MAX + 1], *bssAttr[NL80211_BSS_MAX + 1];
179     static struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
180     memset_s(bssPolicy, sizeof(bssPolicy), 0, sizeof(bssPolicy));
181     bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
182     bssPolicy[NL80211_BSS_TSF].type = NLA_U64;
183     bssPolicy[NL80211_BSS_BEACON_INTERVAL].type = NLA_U16;
184     bssPolicy[NL80211_BSS_CAPABILITY].type = NLA_U16;
185     bssPolicy[NL80211_BSS_SIGNAL_MBM].type = NLA_U32;
186     bssPolicy[NL80211_BSS_SIGNAL_UNSPEC].type = NLA_U8;
187     bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
188     bssPolicy[NL80211_BSS_SEEN_MS_AGO].type = NLA_U32;
189 
190     if (ifName == NULL) {
191         HILOG_ERROR(LOG_CORE, "%s: ifName is null", __func__);
192         return NL_SKIP;
193     }
194 
195     nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
196     if (!attr[NL80211_ATTR_BSS]) {
197         HILOG_ERROR(LOG_CORE, "%s: bss info missing", __func__);
198         return NL_SKIP;
199     }
200     if (nla_parse_nested(bssAttr, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy)) {
201         HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes", __func__);
202         return NL_SKIP;
203     }
204 
205     DoGetScanResult(bssAttr, NL80211_BSS_MAX + 1, &scanResult);
206 
207     WifiEventReport(ifName, WIFI_EVENT_SCAN_RESULT, &scanResult);
208     return NL_SKIP;
209 }
210 
WifiEventScanResultProcess(const char * ifName)211 static void WifiEventScanResultProcess(const char *ifName)
212 {
213     int32_t ret;
214     uint32_t ifaceId = if_nametoindex(ifName);
215     struct nl_msg *msg = nlmsg_alloc();
216 
217     genlmsg_put(msg, 0, 0, g_familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0);
218     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
219     ret = NetlinkSendCmdSync(msg, WifiGetScanResultHandler, (void *)ifName);
220     if (ret != RET_CODE_SUCCESS) {
221         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __func__);
222     }
223 
224     nlmsg_free(msg);
225 }
226 
DoProcessEvent(const char * ifName,int cmd,struct nlattr ** attr)227 static void DoProcessEvent(const char *ifName, int cmd, struct nlattr **attr)
228 {
229     switch (cmd) {
230         case NL80211_CMD_VENDOR:
231             WifiEventVendorProcess(ifName, attr);
232             break;
233         case NL80211_CMD_NEW_SCAN_RESULTS:
234             WifiEventScanResultProcess(ifName);
235             break;
236         default:
237             HILOG_INFO(LOG_CORE, "%s: not supported cmd, cmd = %d", __FUNCTION__, cmd);
238             break;
239     }
240 }
241 
ProcessEvent(struct nl_msg * msg,void * arg)242 static int32_t ProcessEvent(struct nl_msg *msg, void *arg)
243 {
244     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
245     struct nlattr *attr[NL80211_ATTR_MAX + 1];
246     struct NetworkInfoResult networkInfo;
247     uint32_t ifidx = -1;
248     uint32_t i;
249     int ret;
250 
251     nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0),
252         genlmsg_attrlen(hdr, 0), NULL);
253 
254     if (attr[NL80211_ATTR_IFINDEX]) {
255         ifidx = nla_get_u32(attr[NL80211_ATTR_IFINDEX]);
256     }
257 
258     ret = GetUsableNetworkInfo(&networkInfo);
259     if (ret != RET_CODE_SUCCESS) {
260         HILOG_ERROR(LOG_CORE, "%s: get usable network information failed", __FUNCTION__);
261         return NL_SKIP;
262     }
263 
264     for (i = 0; i < networkInfo.nums; i++) {
265         if (ifidx == if_nametoindex(networkInfo.infos[i].name)) {
266             DoProcessEvent(networkInfo.infos[i].name, hdr->cmd, attr);
267             return NL_SKIP;
268         }
269     }
270 
271     return NL_SKIP;
272 }
273 
CreateCb(void)274 static struct nl_cb *CreateCb(void)
275 {
276     struct nl_cb *cb;
277 
278     cb = nl_cb_alloc(NL_CB_DEFAULT);
279     if (cb == NULL) {
280         HILOG_ERROR(LOG_CORE, "%s: alloc cb failed", __FUNCTION__);
281         return NULL;
282     }
283 
284     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, NoSeqCheck, NULL);
285     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ProcessEvent, NULL);
286 
287     return cb;
288 }
289 
HandleEvent(struct nl_sock * sock)290 static int HandleEvent(struct nl_sock *sock)
291 {
292     int ret;
293     struct nl_cb *cb = CreateCb();
294     if (cb == NULL) {
295         HILOG_ERROR(LOG_CORE, "%s: Create cb failed", __FUNCTION__);
296         return RET_CODE_FAILURE;
297     }
298 
299     ret = nl_recvmsgs(sock, cb);
300 
301     nl_cb_put(cb);
302     cb = NULL;
303     return ret;
304 }
305 
EventThread(void * para)306 void *EventThread(void *para)
307 {
308     struct nl_sock *eventSock = NULL;
309     struct pollfd pollFds[LISTEN_FD_NUMS] = {0};
310     struct WifiThreadParam *threadParam = NULL;
311     int ctrlSocks[2];
312     int ret;
313     enum ThreadStatus *status = NULL;
314 
315     if (para == NULL) {
316         HILOG_ERROR(LOG_CORE, "%s: para is null", __FUNCTION__);
317         return NULL;
318     } else {
319         threadParam = (struct WifiThreadParam *)para;
320         eventSock = threadParam->eventSock;
321         g_familyId = threadParam->familyId;
322         status = threadParam->status;
323         *status = THREAD_RUN;
324     }
325 
326     pollFds[EVENT_SOCKET_INDEX].fd = nl_socket_get_fd(eventSock);
327     pollFds[EVENT_SOCKET_INDEX].events = POLLIN | POLLERR;
328 
329     ret = socketpair(AF_UNIX, SOCK_STREAM, 0, ctrlSocks);
330     if (ret != 0) {
331         HILOG_ERROR(LOG_CORE, "%s: fail socketpair", __FUNCTION__);
332         *status = THREAD_STOP;
333         return NULL;
334     }
335     pollFds[CTRL_SOCKET_INDEX].fd = ctrlSocks[CTRL_SOCKET_READ_SIDE];
336     pollFds[CTRL_SOCKET_INDEX].events = POLLIN | POLLERR;
337 
338     while (*status == THREAD_RUN) {
339         ret = TEMP_FAILURE_RETRY(poll(pollFds, LISTEN_FD_NUMS, POLLTIMEOUT));
340         if (ret < 0) {
341             HILOG_ERROR(LOG_CORE, "%s: fail poll", __FUNCTION__);
342             break;
343         } else if (pollFds[EVENT_SOCKET_INDEX].revents & POLLERR) {
344             HILOG_ERROR(LOG_CORE, "%s: event socket get POLLERR event", __FUNCTION__);
345             break;
346         } else if (pollFds[EVENT_SOCKET_INDEX].revents & POLLIN) {
347             if (HandleEvent(eventSock) != RET_CODE_SUCCESS) {
348                 break;
349             }
350         } else if (pollFds[CTRL_SOCKET_INDEX].revents & POLLERR) {
351             HILOG_ERROR(LOG_CORE, "%s: ctrl socket get POLLERR event", __FUNCTION__);
352             break;
353         } else if (pollFds[CTRL_SOCKET_INDEX].revents & POLLIN) {
354             if (HandleCtrlEvent(pollFds[CTRL_SOCKET_INDEX].fd) != RET_CODE_SUCCESS) {
355                 break;
356             }
357         }
358     }
359 
360     close(pollFds[CTRL_SOCKET_INDEX].fd);
361     *status = THREAD_STOP;
362     return NULL;
363 }
364