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