1 /*
2 * Copyright (c) 2021-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 <net/if.h>
17 #include <arpa/inet.h>
18 #include <dirent.h>
19 #include <netlink-private/types.h>
20 #include <netlink/genl/ctrl.h>
21 #include <netlink/genl/genl.h>
22 #include <netlink/handlers.h>
23 #include <securec.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <sys/ioctl.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <linux/ethtool.h>
32 #include <linux/if_arp.h>
33 #include <linux/netlink.h>
34 #include <linux/nl80211.h>
35 #include <linux/sockios.h>
36 #include <linux/wireless.h>
37 #include <linux/version.h>
38
39 #include "../wifi_common_cmd.h"
40 #include "hilog/log.h"
41 #include "netlink_adapter.h"
42 #include "hdf_dlist.h"
43
44 #define VENDOR_ID 0x001A11
45
46 // vendor subcmd
47 #define WIFI_SUBCMD_SET_COUNTRY_CODE 0x100E
48 #define WIFI_SUBCMD_SET_RANDOM_MAC_OUI 0x100C
49
50 #define WAITFORMUTEX 100000
51 #define WAITFORTHREAD 100000
52 #define RETRIES 30
53
54 #define STR_WLAN0 "wlan0"
55 #define STR_WLAN1 "wlan1"
56 #define STR_P2P0 "p2p0"
57 #define STR_P2P0_X "p2p0-"
58 #define NET_DEVICE_INFO_PATH "/sys/class/net"
59
60 #define PRIMARY_ID_POWER_MODE 0x8bfd
61 #define SECONDARY_ID_POWER_MODE 0x101
62 #define SET_POWER_MODE_SLEEP "pow_mode sleep"
63 #define SET_POWER_MODE_INIT "pow_mode init"
64 #define SET_POWER_MODE_THIRD "pow_mode third"
65 #define GET_POWER_MODE "get_pow_mode"
66
67 #define CMD_SET_CLOSE_GO_CAC "SET_CLOSE_GO_CAC"
68 #define CMD_SET_CHANGE_GO_CHANNEL "CMD_SET_CHANGE_GO_CHANNEL"
69 #define CMD_SET_GO_DETECT_RADAR "CMD_SET_GO_DETECT_RADAR"
70 #define CMD_SET_DYNAMIC_DBAC_MODE "SET_DYNAMIC_DBAC_MODE"
71 #define CMD_SET_P2P_SCENES "CMD_SET_P2P_SCENES"
72 #define P2P_BUF_SIZE 64
73 #define MAX_PRIV_CMD_SIZE 4096
74 #define LOW_LITMIT_FREQ_2_4G 2400
75 #define HIGH_LIMIT_FREQ_2_4G 2500
76 #define LOW_LIMIT_FREQ_5G 5100
77 #define HIGH_LIMIT_FREQ_5G 5900
78 #define INTERFACE_UP 0x1 /* interface is up */
79 #define MAX_INTERFACE_NAME_SIZE 16
80
BIT(uint8_t x)81 static inline uint32_t BIT(uint8_t x)
82 {
83 return 1U << x;
84 }
85 #define STA_DRV_DATA_TX_MCS BIT(0)
86 #define STA_DRV_DATA_RX_MCS BIT(1)
87 #define STA_DRV_DATA_TX_VHT_MCS BIT(2)
88 #define STA_DRV_DATA_RX_VHT_MCS BIT(3)
89 #define STA_DRV_DATA_TX_VHT_NSS BIT(4)
90 #define STA_DRV_DATA_RX_VHT_NSS BIT(5)
91 #define STA_DRV_DATA_TX_SHORT_GI BIT(6)
92 #define STA_DRV_DATA_RX_SHORT_GI BIT(7)
93 #define STA_DRV_DATA_LAST_ACK_RSSI BIT(8)
94
95 #define WLAN_IFACE_LENGTH 4
96 #define P2P_IFACE_LENGTH 3
97 #ifndef KERNEL_VERSION
98 #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
99 #endif
100
101 // vendor attr
102 enum AndrWifiAttr {
103 #if (defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
104 WIFI_ATTRIBUTE_INVALID,
105 #endif
106 WIFI_ATTRIBUTE_NUM_FEATURE_SET,
107 WIFI_ATTRIBUTE_FEATURE_SET,
108 WIFI_ATTRIBUTE_RANDOM_MAC_OUI,
109 WIFI_ATTRIBUTE_NODFS_SET,
110 WIFI_ATTRIBUTE_COUNTRY
111 };
112
113 struct FamilyData {
114 const char *group;
115 int32_t id;
116 };
117
118 struct WifiHalInfo {
119 struct nl_sock *cmdSock;
120 struct nl_sock *eventSock;
121 int32_t familyId;
122
123 // thread controller info
124 pthread_t thread;
125 enum ThreadStatus status;
126 pthread_mutex_t mutex;
127 };
128
129 typedef struct {
130 void *buf;
131 uint16_t length;
132 uint16_t flags;
133 } DataPoint;
134
135 union HwprivReqData {
136 char name[IFNAMSIZ];
137 int32_t mode;
138 DataPoint point;
139 };
140
141 typedef struct {
142 char interfaceName[IFNAMSIZ];
143 union HwprivReqData data;
144 } HwprivIoctlData;
145
146 typedef struct {
147 #if (defined(LINUX_VERSION_CODE) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
148 uint8_t *buf;
149 uint32_t size;
150 uint32_t len;
151 #else
152 uint32_t size;
153 uint32_t len;
154 uint8_t *buf;
155 #endif
156 } WifiPrivCmd;
157
158 #define SLOW_SCAN_INTERVAL_MULTIPLIER 3
159 #define FAST_SCAN_ITERATIONS 3
160 #define BITNUMS_OF_ONE_BYTE 8
161 #define SCHED_SCAN_PLANS_ATTR_INDEX1 1
162 #define SCHED_SCAN_PLANS_ATTR_INDEX2 2
163 #define MS_PER_SECOND 1000
164
165 typedef struct {
166 uint8_t maxNumScanSsids;
167 uint8_t maxNumSchedScanSsids;
168 uint8_t maxMatchSets;
169 uint32_t maxNumScanPlans;
170 uint32_t maxScanPlanInterval;
171 uint32_t maxScanPlanIterations;
172 } ScanCapabilities;
173
174 typedef struct {
175 bool supportsRandomMacSchedScan;
176 bool supportsLowPowerOneshotScan;
177 bool supportsExtSchedScanRelativeRssi;
178 } WiphyFeatures;
179
180 typedef struct {
181 ScanCapabilities scanCapabilities;
182 WiphyFeatures wiphyFeatures;
183 } WiphyInfo;
184
185 struct SsidListNode {
186 WifiDriverScanSsid ssidInfo;
187 struct DListHead entry;
188 };
189
190 struct FreqListNode {
191 int32_t freq;
192 struct DListHead entry;
193 };
194
195 static struct WifiHalInfo g_wifiHalInfo = {0};
196
OpenNetlinkSocket(void)197 static struct nl_sock *OpenNetlinkSocket(void)
198 {
199 struct nl_sock *sock = NULL;
200
201 sock = nl_socket_alloc();
202 if (sock == NULL) {
203 HILOG_ERROR(LOG_CORE, "%s: fail to alloc socket", __FUNCTION__);
204 return NULL;
205 }
206
207 if (nl_connect(sock, NETLINK_GENERIC) != 0) {
208 HILOG_ERROR(LOG_CORE, "%s: fail to connect socket", __FUNCTION__);
209 nl_socket_free(sock);
210 return NULL;
211 }
212 return sock;
213 }
214
CloseNetlinkSocket(struct nl_sock * sock)215 static void CloseNetlinkSocket(struct nl_sock *sock)
216 {
217 if (sock != NULL) {
218 nl_socket_free(sock);
219 }
220 }
221
ConnectCmdSocket(void)222 static int32_t ConnectCmdSocket(void)
223 {
224 g_wifiHalInfo.cmdSock = OpenNetlinkSocket();
225 if (g_wifiHalInfo.cmdSock == NULL) {
226 HILOG_ERROR(LOG_CORE, "%s: fail to open cmd socket", __FUNCTION__);
227 return RET_CODE_FAILURE;
228 }
229
230 nl_socket_disable_seq_check(g_wifiHalInfo.cmdSock);
231 // send find familyId result to Controller
232 g_wifiHalInfo.familyId = genl_ctrl_resolve(g_wifiHalInfo.cmdSock, NL80211_GENL_NAME);
233 if (g_wifiHalInfo.familyId < 0) {
234 HILOG_ERROR(LOG_CORE, "%s: fail to resolve family", __FUNCTION__);
235 CloseNetlinkSocket(g_wifiHalInfo.cmdSock);
236 g_wifiHalInfo.cmdSock = NULL;
237 return RET_CODE_FAILURE;
238 }
239 HILOG_INFO(LOG_CORE, "%s: family id: %d", __FUNCTION__, g_wifiHalInfo.familyId);
240 return RET_CODE_SUCCESS;
241 }
242
DisconnectCmdSocket(void)243 static void DisconnectCmdSocket(void)
244 {
245 CloseNetlinkSocket(g_wifiHalInfo.cmdSock);
246 g_wifiHalInfo.cmdSock = NULL;
247 }
248
CmdSocketErrorHandler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)249 static int32_t CmdSocketErrorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
250 {
251 int32_t *ret = (int32_t *)arg;
252
253 *ret = err->error;
254 return NL_SKIP;
255 }
256
CmdSocketFinishHandler(struct nl_msg * msg,void * arg)257 static int32_t CmdSocketFinishHandler(struct nl_msg *msg, void *arg)
258 {
259 int32_t *ret = (int32_t *)arg;
260
261 *ret = 0;
262 return NL_SKIP;
263 }
264
CmdSocketAckHandler(struct nl_msg * msg,void * arg)265 static int32_t CmdSocketAckHandler(struct nl_msg *msg, void *arg)
266 {
267 int32_t *err = (int32_t *)arg;
268
269 *err = 0;
270 return NL_STOP;
271 }
272
NetlinkSetCallback(const RespHandler handler,int32_t * error,void * data)273 static struct nl_cb *NetlinkSetCallback(const RespHandler handler, int32_t *error, void *data)
274 {
275 struct nl_cb *cb = NULL;
276
277 cb = nl_cb_alloc(NL_CB_DEFAULT);
278 if (cb == NULL) {
279 HILOG_ERROR(LOG_CORE, "%s: nl_cb_alloc failed", __FUNCTION__);
280 return NULL;
281 }
282 nl_cb_err(cb, NL_CB_CUSTOM, CmdSocketErrorHandler, error);
283 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, CmdSocketFinishHandler, error);
284 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, CmdSocketAckHandler, error);
285 if (handler != NULL) {
286 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, data);
287 }
288 return cb;
289 }
290
PthreadMutexLock(void)291 static int32_t PthreadMutexLock(void)
292 {
293 int32_t rc;
294 int32_t count = 0;
295
296 while ((rc = pthread_mutex_trylock(&g_wifiHalInfo.mutex)) == EBUSY) {
297 if (count < RETRIES) {
298 HILOG_ERROR(LOG_CORE, "%s: pthread b trylock", __FUNCTION__);
299 count++;
300 usleep(WAITFORMUTEX);
301 } else {
302 HILOG_ERROR(LOG_CORE, "%s: pthread trylock timeout", __FUNCTION__);
303 return RET_CODE_SUCCESS;
304 }
305 }
306 return rc;
307 }
308
NetlinkSendCmdSync(struct nl_msg * msg,const RespHandler handler,void * data)309 int32_t NetlinkSendCmdSync(struct nl_msg *msg, const RespHandler handler, void *data)
310 {
311 int32_t rc;
312 int32_t error;
313 struct nl_cb *cb = NULL;
314
315 if (g_wifiHalInfo.cmdSock == NULL) {
316 HILOG_ERROR(LOG_CORE, "%s: sock is null", __FUNCTION__);
317 return RET_CODE_INVALID_PARAM;
318 }
319
320 if (PthreadMutexLock() != RET_CODE_SUCCESS) {
321 HILOG_ERROR(LOG_CORE, "%s: pthread trylock failed", __FUNCTION__);
322 return RET_CODE_FAILURE;
323 }
324
325 do {
326 rc = nl_send_auto(g_wifiHalInfo.cmdSock, msg);
327 if (rc < 0) {
328 HILOG_ERROR(LOG_CORE, "%s: nl_send_auto failed", __FUNCTION__);
329 break;
330 }
331 cb = NetlinkSetCallback(handler, &error, data);
332 if (cb == NULL) {
333 HILOG_ERROR(LOG_CORE, "%s: nl_cb_alloc failed", __FUNCTION__);
334 rc = RET_CODE_FAILURE;
335 break;
336 }
337 /* wait for reply */
338 error = 1;
339 while (error > 0) {
340 rc = nl_recvmsgs(g_wifiHalInfo.cmdSock, cb);
341 if (rc < 0) {
342 HILOG_ERROR(LOG_CORE, "%s: nl_recvmsgs failed: rc = %d, errno = %d, (%s)", __FUNCTION__, rc, errno,
343 strerror(errno));
344 }
345 }
346 if (error == -NLE_MSGTYPE_NOSUPPORT) {
347 HILOG_ERROR(LOG_CORE, "%s: Netlink message type is not supported", __FUNCTION__);
348 rc = RET_CODE_NOT_SUPPORT;
349 }
350 nl_cb_put(cb);
351 } while (0);
352
353 pthread_mutex_unlock(&g_wifiHalInfo.mutex);
354 return rc;
355 }
356
ParseFamilyId(struct nlattr * attr,struct FamilyData * familyData)357 static void ParseFamilyId(struct nlattr *attr, struct FamilyData *familyData)
358 {
359 struct nlattr *tmp = NULL;
360 void *data = NULL;
361 int32_t len;
362 int32_t i;
363
364 nla_for_each_nested(tmp, attr, i) {
365 struct nlattr *attrMcastGrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
366 data = nla_data(tmp);
367 len = nla_len(tmp);
368 nla_parse(attrMcastGrp, CTRL_ATTR_MCAST_GRP_MAX, data, len, NULL);
369 data = nla_data(attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME]);
370 len = nla_len(attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME]);
371 if (attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME] && attrMcastGrp[CTRL_ATTR_MCAST_GRP_ID] &&
372 strncmp((char *)data, familyData->group, len) == 0) {
373 familyData->id = (int32_t)nla_get_u32(attrMcastGrp[CTRL_ATTR_MCAST_GRP_ID]);
374 }
375 }
376 }
377
FamilyIdHandler(struct nl_msg * msg,void * arg)378 static int32_t FamilyIdHandler(struct nl_msg *msg, void *arg)
379 {
380 struct FamilyData *familyData = (struct FamilyData *)arg;
381 struct genlmsghdr *hdr = NULL;
382 struct nlattr *attr[CTRL_ATTR_MAX + 1];
383 void *data = NULL;
384 int32_t len;
385
386 hdr = nlmsg_data(nlmsg_hdr(msg));
387 if (hdr == NULL) {
388 HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
389 return NL_SKIP;
390 }
391
392 data = genlmsg_attrdata(hdr, 0);
393 len = genlmsg_attrlen(hdr, 0);
394 nla_parse(attr, CTRL_ATTR_MAX, data, len, NULL);
395 if (!attr[CTRL_ATTR_MCAST_GROUPS]) {
396 return NL_SKIP;
397 }
398
399 ParseFamilyId(attr[CTRL_ATTR_MCAST_GROUPS], familyData);
400
401 return NL_SKIP;
402 }
403
GetMulticastId(const char * family,const char * group)404 static int32_t GetMulticastId(const char *family, const char *group)
405 {
406 struct nl_msg *msg = NULL;
407 int32_t ret;
408 static struct FamilyData familyData;
409 int32_t familyId = genl_ctrl_resolve(g_wifiHalInfo.cmdSock, "nlctrl");
410
411 familyData.group = group;
412 familyData.id = -ENOENT;
413
414 msg = nlmsg_alloc();
415 if (msg == NULL) {
416 HILOG_ERROR(LOG_CORE, "%s: nlmsg_alloc failed", __FUNCTION__);
417 return RET_CODE_NOMEM;
418 }
419
420 if (!genlmsg_put(msg, 0, 0, familyId, 0, 0, CTRL_CMD_GETFAMILY, 0) ||
421 nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
422 HILOG_ERROR(LOG_CORE, "%s: put msg failed", __FUNCTION__);
423 nlmsg_free(msg);
424 return RET_CODE_FAILURE;
425 }
426
427 ret = NetlinkSendCmdSync(msg, FamilyIdHandler, &familyData);
428 if (ret == 0) {
429 ret = familyData.id;
430 }
431 nlmsg_free(msg);
432 return ret;
433 }
434
NlsockAddMembership(struct nl_sock * sock,const char * group)435 static int32_t NlsockAddMembership(struct nl_sock *sock, const char *group)
436 {
437 int32_t id;
438 int32_t ret;
439
440 id = GetMulticastId(NL80211_GENL_NAME, group);
441 if (id < 0) {
442 HILOG_ERROR(LOG_CORE, "%s: get multicast id failed", __FUNCTION__);
443 return id;
444 }
445
446 ret = nl_socket_add_membership(sock, id);
447 if (ret < 0) {
448 HILOG_ERROR(LOG_CORE, "%s: Could not add multicast membership for %d: %d (%s)", __FUNCTION__, id, ret,
449 strerror(-ret));
450 return RET_CODE_FAILURE;
451 }
452
453 return RET_CODE_SUCCESS;
454 }
455
ConnectEventSocket(void)456 static int32_t ConnectEventSocket(void)
457 {
458 int32_t ret;
459
460 g_wifiHalInfo.eventSock = OpenNetlinkSocket();
461 if (g_wifiHalInfo.eventSock == NULL) {
462 HILOG_ERROR(LOG_CORE, "%s: fail to open event socket", __FUNCTION__);
463 return RET_CODE_FAILURE;
464 }
465 do {
466 ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_SCAN);
467 if (ret != RET_CODE_SUCCESS) {
468 HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for scan event failed.", __FUNCTION__);
469 break;
470 }
471 ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_MLME);
472 if (ret != RET_CODE_SUCCESS) {
473 HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for mlme failed.", __FUNCTION__);
474 break;
475 }
476 ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_REG);
477 if (ret != RET_CODE_SUCCESS) {
478 HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for regulatory failed.", __FUNCTION__);
479 break;
480 }
481 ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_VENDOR);
482 if (ret != RET_CODE_SUCCESS) {
483 HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for vendor failed.", __FUNCTION__);
484 break;
485 }
486 return RET_CODE_SUCCESS;
487 } while (0);
488 CloseNetlinkSocket(g_wifiHalInfo.eventSock);
489 g_wifiHalInfo.eventSock = NULL;
490 return ret;
491 }
492
DisconnectEventSocket(void)493 void DisconnectEventSocket(void)
494 {
495 CloseNetlinkSocket(g_wifiHalInfo.eventSock);
496 g_wifiHalInfo.eventSock = NULL;
497 }
498
WifiMsgRegisterEventListener(void)499 static int32_t WifiMsgRegisterEventListener(void)
500 {
501 int32_t rc;
502 int32_t count = 0;
503 struct WifiThreadParam threadParam;
504
505 threadParam.eventSock = g_wifiHalInfo.eventSock;
506 threadParam.familyId = g_wifiHalInfo.familyId;
507 threadParam.status = &g_wifiHalInfo.status;
508
509 g_wifiHalInfo.status = THREAD_STARTING;
510 rc = pthread_create(&(g_wifiHalInfo.thread), NULL, EventThread, &threadParam);
511 if (rc != 0) {
512 HILOG_ERROR(LOG_CORE, "%s: failed create event thread", __FUNCTION__);
513 g_wifiHalInfo.status = THREAD_STOP;
514 return RET_CODE_FAILURE;
515 }
516
517 // waiting for thread start running
518 while (g_wifiHalInfo.status != THREAD_RUN) {
519 HILOG_INFO(LOG_CORE, "%s: waiting for thread start running.", __FUNCTION__);
520 if (count < RETRIES) {
521 count++;
522 usleep(WAITFORTHREAD);
523 } else {
524 HILOG_ERROR(LOG_CORE, "%s: warit for thread running timeout", __FUNCTION__);
525 if (g_wifiHalInfo.status != THREAD_STOP) {
526 g_wifiHalInfo.status = THREAD_STOP;
527 pthread_join(g_wifiHalInfo.thread, NULL);
528 }
529 return RET_CODE_FAILURE;
530 }
531 }
532
533 return RET_CODE_SUCCESS;
534 }
535
WifiMsgUnregisterEventListener(void)536 static void WifiMsgUnregisterEventListener(void)
537 {
538 g_wifiHalInfo.status = THREAD_STOPPING;
539 pthread_join(g_wifiHalInfo.thread, NULL);
540 }
541
WifiDriverClientInit(void)542 int32_t WifiDriverClientInit(void)
543 {
544 if (g_wifiHalInfo.cmdSock != NULL) {
545 HILOG_ERROR(LOG_CORE, "%s: already create cmd socket", __FUNCTION__);
546 return RET_CODE_FAILURE;
547 }
548
549 if (pthread_mutex_init(&g_wifiHalInfo.mutex, NULL) != RET_CODE_SUCCESS) {
550 HILOG_ERROR(LOG_CORE, "%s: init mutex failed.", __FUNCTION__);
551 return RET_CODE_FAILURE;
552 }
553
554 if (ConnectCmdSocket() != RET_CODE_SUCCESS) {
555 HILOG_ERROR(LOG_CORE, "%s: connect cmd socket failed.", __FUNCTION__);
556 goto err_cmd;
557 }
558
559 if (ConnectEventSocket() != RET_CODE_SUCCESS) {
560 HILOG_ERROR(LOG_CORE, "%s: connect event socket failed", __FUNCTION__);
561 goto err_event;
562 }
563
564 if (WifiMsgRegisterEventListener() != RET_CODE_SUCCESS) {
565 HILOG_ERROR(LOG_CORE, "%s: WifiMsgRegisterEventListener failed", __FUNCTION__);
566 goto err_reg;
567 }
568
569 return RET_CODE_SUCCESS;
570 err_reg:
571 DisconnectEventSocket();
572 err_event:
573 DisconnectCmdSocket();
574 err_cmd:
575 pthread_mutex_destroy(&g_wifiHalInfo.mutex);
576 return RET_CODE_FAILURE;
577 }
578
WifiDriverClientDeinit(void)579 void WifiDriverClientDeinit(void)
580 {
581 WifiMsgUnregisterEventListener();
582
583 if (g_wifiHalInfo.cmdSock == NULL) {
584 HILOG_ERROR(LOG_CORE, "%s: cmd socket not inited", __FUNCTION__);
585 } else {
586 DisconnectCmdSocket();
587 }
588
589 if (g_wifiHalInfo.eventSock == NULL) {
590 HILOG_ERROR(LOG_CORE, "%s: event socket not inited", __FUNCTION__);
591 } else {
592 DisconnectEventSocket();
593 }
594
595 pthread_mutex_destroy(&g_wifiHalInfo.mutex);
596 }
597
ParserIsSupportCombo(struct nl_msg * msg,void * arg)598 static int32_t ParserIsSupportCombo(struct nl_msg *msg, void *arg)
599 {
600 struct nlattr *attr[NL80211_ATTR_MAX + 1];
601 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
602 struct nlattr *nlComb = NULL;
603 struct nlattr *attrComb[NUM_NL80211_IFACE_COMB];
604 uint8_t *isSupportCombo = (uint8_t *)arg;
605 int32_t ret, i;
606 static struct nla_policy ifaceCombPolicy[NUM_NL80211_IFACE_COMB];
607 ifaceCombPolicy[NL80211_IFACE_COMB_LIMITS].type = NLA_NESTED;
608 ifaceCombPolicy[NL80211_IFACE_COMB_MAXNUM].type = NLA_U32;
609 ifaceCombPolicy[NL80211_IFACE_COMB_NUM_CHANNELS].type = NLA_U32;
610
611 // parse all enum nl80211_attrs type
612 ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
613 if (ret != 0) {
614 HILOG_ERROR(LOG_CORE, "%s: nla_parse tb failed", __FUNCTION__);
615 return NL_SKIP;
616 }
617
618 if (attr[NL80211_ATTR_INTERFACE_COMBINATIONS] != NULL) {
619 nla_for_each_nested(nlComb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], i) {
620 // parse all enum nl80211_if_combination_attrs type
621 ret = nla_parse_nested(attrComb, MAX_NL80211_IFACE_COMB, nlComb, ifaceCombPolicy);
622 if (ret != 0) {
623 HILOG_ERROR(LOG_CORE, "%s: nla_parse_nested nlComb failed", __FUNCTION__);
624 return NL_SKIP;
625 }
626 if (!attrComb[NL80211_IFACE_COMB_LIMITS] || !attrComb[NL80211_IFACE_COMB_MAXNUM] ||
627 !attrComb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
628 *isSupportCombo = 0;
629 } else {
630 *isSupportCombo = 1;
631 }
632 }
633 }
634 HILOG_INFO(LOG_CORE, "%s: isSupportCombo is %hhu", __FUNCTION__, *isSupportCombo);
635 return NL_SKIP;
636 }
637
ParserSupportComboInfo(struct nl_msg * msg,void * arg)638 static int32_t ParserSupportComboInfo(struct nl_msg *msg, void *arg)
639 {
640 (void)arg;
641 struct nlattr *attr[NL80211_ATTR_MAX + 1];
642 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
643 struct nlattr *nlComb = NULL, *nlLimit = NULL, *nlMode = NULL;
644 struct nlattr *attrComb[NUM_NL80211_IFACE_COMB];
645 struct nlattr *attrLimit[NUM_NL80211_IFACE_LIMIT];
646 int32_t ret, i, j, k, type;
647 static struct nla_policy ifaceCombPolicy[NUM_NL80211_IFACE_COMB];
648 ifaceCombPolicy[NL80211_IFACE_COMB_LIMITS].type = NLA_NESTED;
649 ifaceCombPolicy[NL80211_IFACE_COMB_MAXNUM].type = NLA_U32;
650 ifaceCombPolicy[NL80211_IFACE_COMB_NUM_CHANNELS].type = NLA_U32;
651
652 static struct nla_policy ifaceLimitPolicy[NUM_NL80211_IFACE_LIMIT];
653 ifaceLimitPolicy[NL80211_IFACE_LIMIT_MAX].type = NLA_U32;
654 ifaceLimitPolicy[NL80211_IFACE_LIMIT_TYPES].type = NLA_NESTED;
655
656 ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
657 if (ret != 0) {
658 HILOG_ERROR(LOG_CORE, "%s: nla_parse tb failed", __FUNCTION__);
659 return NL_SKIP;
660 }
661
662 if (attr[NL80211_ATTR_INTERFACE_COMBINATIONS] != NULL) {
663 // get each ieee80211_iface_combination
664 nla_for_each_nested(nlComb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], i) {
665 ret = nla_parse_nested(attrComb, MAX_NL80211_IFACE_COMB, nlComb, ifaceCombPolicy);
666 if (ret != 0) {
667 HILOG_ERROR(LOG_CORE, "%s: nla_parse_nested nlComb failed", __FUNCTION__);
668 return NL_SKIP;
669 }
670 if (!attrComb[NL80211_IFACE_COMB_LIMITS] || !attrComb[NL80211_IFACE_COMB_MAXNUM] ||
671 !attrComb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
672 return RET_CODE_NOT_SUPPORT;
673 }
674 // parse each ieee80211_iface_limit
675 nla_for_each_nested(nlLimit, attrComb[NL80211_IFACE_COMB_LIMITS], j) {
676 ret = nla_parse_nested(attrLimit, MAX_NL80211_IFACE_LIMIT, nlLimit, ifaceLimitPolicy);
677 if (ret || !attrLimit[NL80211_IFACE_LIMIT_TYPES]) {
678 HILOG_ERROR(LOG_CORE, "%s: iface limit types not supported", __FUNCTION__);
679 return RET_CODE_NOT_SUPPORT; /* broken combination */
680 }
681 // parse each ieee80211_iface_limit's types
682 nla_for_each_nested(nlMode, attrLimit[NL80211_IFACE_LIMIT_TYPES], k) {
683 type = nla_type(nlMode);
684 if (type > WIFI_IFTYPE_UNSPECIFIED && type < WIFI_IFTYPE_MAX) {
685 HILOG_INFO(LOG_CORE, "%s: mode: %d", __FUNCTION__, type);
686 }
687 }
688 HILOG_INFO(LOG_CORE, "%s: has parse a attrLimit", __FUNCTION__);
689 }
690 }
691 }
692 return NL_SKIP;
693 }
694
GetWiphyBands(struct genlmsghdr * hdr)695 static struct nlattr *GetWiphyBands(struct genlmsghdr *hdr)
696 {
697 struct nlattr *attrMsg[NL80211_ATTR_MAX + 1];
698 void *data = genlmsg_attrdata(hdr, 0);
699 int32_t len = genlmsg_attrlen(hdr, 0);
700 nla_parse(attrMsg, NL80211_ATTR_MAX, data, len, NULL);
701 if (!attrMsg[NL80211_ATTR_WIPHY_BANDS]) {
702 HILOG_ERROR(LOG_CORE, "%s: no wiphy bands", __FUNCTION__);
703 }
704 return attrMsg[NL80211_ATTR_WIPHY_BANDS];
705 }
706
GetCenterFreq(struct nlattr * bands,struct FreqInfoResult * result)707 static void GetCenterFreq(struct nlattr *bands, struct FreqInfoResult *result)
708 {
709 struct nlattr *attrFreq[NL80211_FREQUENCY_ATTR_MAX + 1];
710 struct nlattr *nlFreq = NULL;
711 void *data = NULL;
712 int32_t len;
713 int32_t i;
714 uint32_t freq;
715 static struct nla_policy freqPolicy[NL80211_FREQUENCY_ATTR_MAX + 1];
716 freqPolicy[NL80211_FREQUENCY_ATTR_FREQ].type = NLA_U32;
717 freqPolicy[NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = NLA_U32;
718
719 // get each ieee80211_channel
720 nla_for_each_nested(nlFreq, bands, i) {
721 data = nla_data(nlFreq);
722 len = nla_len(nlFreq);
723 nla_parse(attrFreq, NL80211_FREQUENCY_ATTR_MAX, data, len, freqPolicy);
724 // get center freq
725 if (attrFreq[NL80211_FREQUENCY_ATTR_FREQ] == NULL) {
726 continue;
727 }
728 freq = nla_get_u32(attrFreq[NL80211_FREQUENCY_ATTR_FREQ]);
729 switch (result->band) {
730 case NL80211_BAND_2GHZ:
731 if (attrFreq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) {
732 if (freq > LOW_LITMIT_FREQ_2_4G && freq < HIGH_LIMIT_FREQ_2_4G) {
733 result->freqs[result->nums] = freq;
734 result->txPower[result->nums] = nla_get_u32(attrFreq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]);
735 result->nums++;
736 }
737 }
738 break;
739 case NL80211_BAND_5GHZ:
740 if (freq > LOW_LIMIT_FREQ_5G && freq < HIGH_LIMIT_FREQ_5G) {
741 result->freqs[result->nums] = freq;
742 result->nums++;
743 }
744 break;
745 default:
746 break;
747 }
748 }
749 }
750
ParserValidFreq(struct nl_msg * msg,void * arg)751 static int32_t ParserValidFreq(struct nl_msg *msg, void *arg)
752 {
753 struct FreqInfoResult *result = (struct FreqInfoResult *)arg;
754 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
755 struct nlattr *attrWiphyBands = NULL;
756 struct nlattr *attrBand[NL80211_BAND_ATTR_MAX + 1];
757 struct nlattr *nlBand = NULL;
758 int32_t i;
759 void *data = NULL;
760 int32_t len;
761
762 attrWiphyBands = GetWiphyBands(hdr);
763 if (attrWiphyBands == NULL) {
764 return NL_SKIP;
765 }
766
767 // get each ieee80211_supported_band
768 nla_for_each_nested(nlBand, attrWiphyBands, i) {
769 data = nla_data(nlBand);
770 len = nla_len(nlBand);
771 nla_parse(attrBand, NL80211_BAND_ATTR_MAX, data, len, NULL);
772 if (attrBand[NL80211_BAND_ATTR_FREQS] == NULL) {
773 continue;
774 }
775 GetCenterFreq(attrBand[NL80211_BAND_ATTR_FREQS], result);
776 }
777 return NL_SKIP;
778 }
779
IsWifiIface(const char * name)780 static bool IsWifiIface(const char *name)
781 {
782 if (strncmp(name, "wlan", WLAN_IFACE_LENGTH) != 0 && strncmp(name, "p2p", P2P_IFACE_LENGTH) != 0) {
783 /* not a wifi interface; ignore it */
784 return false;
785 } else {
786 return true;
787 }
788 }
789
GetAllIfaceInfo(struct NetworkInfoResult * infoResult)790 static int32_t GetAllIfaceInfo(struct NetworkInfoResult *infoResult)
791 {
792 struct dirent **namelist = NULL;
793 char *ifName = NULL;
794 int32_t num;
795 int32_t i;
796 int32_t ret = RET_CODE_SUCCESS;
797
798 num = scandir(NET_DEVICE_INFO_PATH, &namelist, NULL, alphasort);
799 if (num < 0) {
800 HILOG_ERROR(LOG_CORE, "%s: scandir failed, errno = %d, %s", __FUNCTION__, errno, strerror(errno));
801 return RET_CODE_FAILURE;
802 }
803 infoResult->nums = 0;
804 for (i = 0; i < num; i++) {
805 if (infoResult->nums < MAX_IFACE_NUM && IsWifiIface(namelist[i]->d_name)) {
806 ifName = infoResult->infos[infoResult->nums].name;
807 if (strncpy_s(ifName, IFNAMSIZ, namelist[i]->d_name, strlen(namelist[i]->d_name)) != EOK) {
808 HILOG_ERROR(LOG_CORE, "%s: strncpy_s infoResult->infos failed", __FUNCTION__);
809 ret = RET_CODE_FAILURE;
810 }
811 infoResult->nums++;
812 }
813 free(namelist[i]);
814 }
815 free(namelist);
816 return ret;
817 }
818
GetUsableNetworkInfo(struct NetworkInfoResult * result)819 int32_t GetUsableNetworkInfo(struct NetworkInfoResult *result)
820 {
821 int32_t ret;
822 uint32_t i;
823
824 ret = GetAllIfaceInfo(result);
825 if (ret != RET_CODE_SUCCESS) {
826 HILOG_ERROR(LOG_CORE, "%s: GetAllIfaceInfo failed", __FUNCTION__);
827 return ret;
828 }
829
830 HILOG_INFO(LOG_CORE, "%s: wifi iface num %d", __FUNCTION__, result->nums);
831 for (i = 0; i < result->nums; ++i) {
832 ret = memset_s(result->infos[i].supportMode, sizeof(result->infos[i].supportMode), 0,
833 sizeof(result->infos[i].supportMode));
834 if (ret != EOK) {
835 HILOG_ERROR(LOG_CORE, "%s: memset_s esult->infos failed", __FUNCTION__);
836 return RET_CODE_FAILURE;
837 }
838 if (strncmp(result->infos[i].name, STR_WLAN0, strlen(STR_WLAN0)) == 0) {
839 result->infos[i].supportMode[WIFI_IFTYPE_STATION] = 1;
840 result->infos[i].supportMode[WIFI_IFTYPE_AP] = 1;
841 } else if (strncmp(result->infos[i].name, STR_WLAN1, strlen(STR_WLAN1)) == 0) {
842 result->infos[i].supportMode[WIFI_IFTYPE_STATION] = 1;
843 } else if (strncmp(result->infos[i].name, STR_P2P0, strlen(STR_P2P0)) == 0) {
844 result->infos[i].supportMode[WIFI_IFTYPE_P2P_DEVICE] = 1;
845 } else if (strncmp(result->infos[i].name, STR_P2P0_X, strlen(STR_P2P0_X)) == 0) {
846 result->infos[i].supportMode[WIFI_IFTYPE_P2P_CLIENT] = 1;
847 result->infos[i].supportMode[WIFI_IFTYPE_P2P_GO] = 1;
848 }
849 }
850 return RET_CODE_SUCCESS;
851 }
852
IsSupportCombo(uint8_t * isSupportCombo)853 int32_t IsSupportCombo(uint8_t *isSupportCombo)
854 {
855 uint32_t ifaceId;
856 struct nl_msg *msg = NULL;
857 struct NetworkInfoResult networkInfo;
858 int32_t ret;
859
860 ret = GetUsableNetworkInfo(&networkInfo);
861 if (ret != RET_CODE_SUCCESS) {
862 HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
863 return ret;
864 }
865
866 ifaceId = if_nametoindex(networkInfo.infos[0].name);
867 if (ifaceId == 0) {
868 HILOG_ERROR(LOG_CORE, "%s: get iface id(%u) failed", __FUNCTION__, ifaceId);
869 return RET_CODE_FAILURE;
870 }
871
872 msg = nlmsg_alloc();
873 if (msg == NULL) {
874 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
875 return RET_CODE_NOMEM;
876 }
877
878 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
879 nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
880 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
881 ret = NetlinkSendCmdSync(msg, ParserIsSupportCombo, isSupportCombo);
882 if (ret != RET_CODE_SUCCESS) {
883 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
884 }
885 nlmsg_free(msg);
886 return ret;
887 }
888
GetComboInfo(uint64_t * comboInfo,uint32_t size)889 int32_t GetComboInfo(uint64_t *comboInfo, uint32_t size)
890 {
891 (void)size;
892 uint32_t ifaceId;
893 struct nl_msg *msg = NULL;
894 struct NetworkInfoResult networkInfo;
895 int32_t ret;
896
897 ret = GetUsableNetworkInfo(&networkInfo);
898 if (ret != RET_CODE_SUCCESS) {
899 HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
900 return ret;
901 }
902
903 ifaceId = if_nametoindex(networkInfo.infos[0].name);
904 if (ifaceId == 0) {
905 HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
906 return RET_CODE_FAILURE;
907 }
908
909 msg = nlmsg_alloc();
910 if (msg == NULL) {
911 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
912 return RET_CODE_NOMEM;
913 }
914 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
915 nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
916 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
917 ret = NetlinkSendCmdSync(msg, ParserSupportComboInfo, comboInfo);
918 if (ret != RET_CODE_SUCCESS) {
919 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
920 }
921 nlmsg_free(msg);
922 return ret;
923 }
924
SetMacAddr(const char * ifName,unsigned char * mac,uint8_t len)925 int32_t SetMacAddr(const char *ifName, unsigned char *mac, uint8_t len)
926 {
927 int32_t fd;
928 int32_t ret;
929 struct ifreq req;
930
931 if (memset_s(&req, sizeof(req), 0, sizeof(req)) != EOK) {
932 HILOG_ERROR(LOG_CORE, "%s: memset_s req failed", __FUNCTION__);
933 return RET_CODE_FAILURE;
934 }
935 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
936 if (fd < 0) {
937 HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
938 return RET_CODE_FAILURE;
939 }
940 if (strncpy_s(req.ifr_name, IFNAMSIZ, ifName, strlen(ifName)) != EOK) {
941 HILOG_ERROR(LOG_CORE, "%s: strncpy_s fail", __FUNCTION__);
942 close(fd);
943 return RET_CODE_FAILURE;
944 }
945 req.ifr_addr.sa_family = ARPHRD_ETHER;
946 if (memcpy_s(req.ifr_hwaddr.sa_data, len, mac, len) != EOK) {
947 HILOG_ERROR(LOG_CORE, "%s: memcpy_s req.ifr_hwaddr.sa_data failed", __FUNCTION__);
948 close(fd);
949 return RET_CODE_FAILURE;
950 }
951 ret = ioctl(fd, SIOCSIFHWADDR, &req);
952 if (ret != RET_CODE_SUCCESS) {
953 HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
954 if (errno == EPERM) {
955 ret = RET_CODE_NOT_SUPPORT;
956 } else if (errno == EBUSY) {
957 ret = RET_CODE_DEVICE_BUSY;
958 } else {
959 ret = RET_CODE_FAILURE;
960 }
961 }
962 close(fd);
963 return ret;
964 }
965
ParserChipId(struct nl_msg * msg,void * arg)966 static int32_t ParserChipId(struct nl_msg *msg, void *arg)
967 {
968 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
969 struct nlattr *attr[NL80211_ATTR_MAX + 1];
970 uint8_t *chipId = (uint8_t *)arg;
971 uint8_t *getChipId = NULL;
972 int32_t ret;
973
974 ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
975 if (ret != 0) {
976 HILOG_ERROR(LOG_CORE, "%s: nla_parse failed", __FUNCTION__);
977 return NL_SKIP;
978 }
979
980 if (attr[NL80211_ATTR_MAX]) {
981 getChipId = nla_data(attr[NL80211_ATTR_MAX]);
982 *chipId = *getChipId;
983 }
984
985 return NL_SKIP;
986 }
987
GetDevMacAddr(const char * ifName,int32_t type,uint8_t * mac,uint8_t len)988 int32_t GetDevMacAddr(const char *ifName, int32_t type, uint8_t *mac, uint8_t len)
989 {
990 (void)type;
991 int32_t fd;
992 int32_t ret;
993 struct ifreq req;
994
995 if (memset_s(&req, sizeof(req), 0, sizeof(req)) != EOK) {
996 HILOG_ERROR(LOG_CORE, "%s: memset_s req failed", __FUNCTION__);
997 return RET_CODE_FAILURE;
998 }
999 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1000 if (fd < 0) {
1001 HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1002 return RET_CODE_FAILURE;
1003 }
1004
1005 if (strncpy_s(req.ifr_name, IFNAMSIZ, ifName, strlen(ifName)) != EOK) {
1006 HILOG_ERROR(LOG_CORE, "%s: strncpy_s failed", __FUNCTION__);
1007 close(fd);
1008 return RET_CODE_FAILURE;
1009 }
1010 struct ethtool_perm_addr *epaddr =
1011 (struct ethtool_perm_addr *)malloc(sizeof(struct ethtool_perm_addr) + ETH_ADDR_LEN);
1012 if (epaddr == NULL) {
1013 HILOG_ERROR(LOG_CORE, "%s: malloc failed", __FUNCTION__);
1014 close(fd);
1015 return RET_CODE_FAILURE;
1016 }
1017 epaddr->cmd = ETHTOOL_GPERMADDR;
1018 epaddr->size = ETH_ADDR_LEN;
1019 req.ifr_data = (char*)epaddr;
1020 ret = ioctl(fd, SIOCETHTOOL, &req);
1021 if (ret != 0) {
1022 HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
1023 free(epaddr);
1024 close(fd);
1025 return RET_CODE_FAILURE;
1026 }
1027
1028 if (memcpy_s(mac, len, (unsigned char *)epaddr->data, ETH_ADDR_LEN) != EOK) {
1029 HILOG_ERROR(LOG_CORE, "%s: memcpy_s mac failed", __FUNCTION__);
1030 ret = RET_CODE_FAILURE;
1031 }
1032 free(epaddr);
1033 close(fd);
1034 return ret;
1035 }
1036
GetValidFreqByBand(const char * ifName,int32_t band,struct FreqInfoResult * result,uint32_t size)1037 int32_t GetValidFreqByBand(const char *ifName, int32_t band, struct FreqInfoResult *result, uint32_t size)
1038 {
1039 uint32_t ifaceId;
1040 struct nl_msg *msg = NULL;
1041 int32_t ret;
1042
1043 if (result == NULL || result->freqs == NULL || result->txPower == NULL) {
1044 HILOG_ERROR(LOG_CORE, "%s: Invalid input parameter", __FUNCTION__);
1045 return RET_CODE_INVALID_PARAM;
1046 }
1047
1048 if (band >= IEEE80211_NUM_BANDS) {
1049 HILOG_ERROR(LOG_CORE, "%s: Invalid input parameter, band = %d", __FUNCTION__, band);
1050 return RET_CODE_INVALID_PARAM;
1051 }
1052
1053 ifaceId = if_nametoindex(ifName);
1054 if (ifaceId == 0) {
1055 HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
1056 return RET_CODE_INVALID_PARAM;
1057 }
1058
1059 msg = nlmsg_alloc();
1060 if (msg == NULL) {
1061 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1062 return RET_CODE_NOMEM;
1063 }
1064
1065 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
1066 nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
1067 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1068 ret = memset_s(result->freqs, size * sizeof(uint32_t), 0, size * sizeof(uint32_t));
1069 if (ret != EOK) {
1070 HILOG_ERROR(LOG_CORE, "%s: memset_s result->freqs failed", __FUNCTION__);
1071 nlmsg_free(msg);
1072 return RET_CODE_FAILURE;
1073 }
1074 result->nums = 0;
1075 result->band = band;
1076 ret = NetlinkSendCmdSync(msg, ParserValidFreq, result);
1077 if (ret != RET_CODE_SUCCESS) {
1078 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1079 }
1080 nlmsg_free(msg);
1081 return ret;
1082 }
1083
SetTxPower(const char * ifName,int32_t power)1084 int32_t SetTxPower(const char *ifName, int32_t power)
1085 {
1086 uint32_t ifaceId;
1087 struct nl_msg *msg = NULL;
1088 int32_t ret;
1089
1090 ifaceId = if_nametoindex(ifName);
1091 if (ifaceId == 0) {
1092 HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
1093 return RET_CODE_INVALID_PARAM;
1094 }
1095
1096 msg = nlmsg_alloc();
1097 if (msg == NULL) {
1098 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1099 return RET_CODE_NOMEM;
1100 }
1101
1102 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_SET_WIPHY, 0);
1103 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1104 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, NL80211_TX_POWER_LIMITED);
1105 nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, 100 * power);
1106 ret = NetlinkSendCmdSync(msg, NULL, NULL);
1107 if (ret != RET_CODE_SUCCESS) {
1108 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1109 } else {
1110 HILOG_INFO(LOG_CORE, "%s: send end success", __FUNCTION__);
1111 }
1112 nlmsg_free(msg);
1113 return ret;
1114 }
1115
GetAssociatedStas(const char * ifName,struct AssocStaInfoResult * result)1116 int32_t GetAssociatedStas(const char *ifName, struct AssocStaInfoResult *result)
1117 {
1118 (void)ifName;
1119 if (memset_s(result, sizeof(struct AssocStaInfoResult), 0, sizeof(struct AssocStaInfoResult)) != EOK) {
1120 HILOG_ERROR(LOG_CORE, "%s: memset_s result failed", __FUNCTION__);
1121 return RET_CODE_FAILURE;
1122 }
1123 return RET_CODE_SUCCESS;
1124 }
1125
WifiSetCountryCode(const char * ifName,const char * code,uint32_t len)1126 int32_t WifiSetCountryCode(const char *ifName, const char *code, uint32_t len)
1127 {
1128 uint32_t ifaceId = if_nametoindex(ifName);
1129 struct nl_msg *msg = NULL;
1130 struct nlattr *data = NULL;
1131 int32_t ret;
1132
1133 if (ifaceId == 0) {
1134 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1135 return RET_CODE_FAILURE;
1136 }
1137
1138 msg = nlmsg_alloc();
1139 if (msg == NULL) {
1140 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1141 return RET_CODE_NOMEM;
1142 }
1143
1144 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_VENDOR, 0);
1145 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1146 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, VENDOR_ID);
1147 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, WIFI_SUBCMD_SET_COUNTRY_CODE);
1148 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
1149 if (data == NULL) {
1150 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1151 nlmsg_free(msg);
1152 return RET_CODE_FAILURE;
1153 }
1154 nla_put(msg, WIFI_ATTRIBUTE_COUNTRY, len, code);
1155 nla_nest_end(msg, data);
1156
1157 ret = NetlinkSendCmdSync(msg, NULL, NULL);
1158 if (ret != RET_CODE_SUCCESS) {
1159 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1160 }
1161 nlmsg_free(msg);
1162 return ret;
1163 }
1164
SetScanMacAddr(const char * ifName,uint8_t * scanMac,uint8_t len)1165 int32_t SetScanMacAddr(const char *ifName, uint8_t *scanMac, uint8_t len)
1166 {
1167 int32_t ret;
1168 uint32_t ifaceId = if_nametoindex(ifName);
1169 struct nl_msg *msg = nlmsg_alloc();
1170 struct nlattr *data = NULL;
1171
1172 if (msg == NULL) {
1173 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1174 return RET_CODE_NOMEM;
1175 }
1176 if (ifaceId == 0) {
1177 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1178 nlmsg_free(msg);
1179 return RET_CODE_FAILURE;
1180 }
1181 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_VENDOR, 0);
1182 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1183 nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, VENDOR_ID);
1184 nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, WIFI_SUBCMD_SET_RANDOM_MAC_OUI);
1185 data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
1186 if (data == NULL) {
1187 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1188 nlmsg_free(msg);
1189 return RET_CODE_FAILURE;
1190 }
1191 nla_put(msg, WIFI_ATTRIBUTE_RANDOM_MAC_OUI, len, scanMac);
1192 nla_nest_end(msg, data);
1193 ret = NetlinkSendCmdSync(msg, NULL, NULL);
1194 if (ret != RET_CODE_SUCCESS) {
1195 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1196 }
1197 nlmsg_free(msg);
1198 return ret;
1199 }
1200
AcquireChipId(const char * ifName,uint8_t * chipId)1201 int32_t AcquireChipId(const char *ifName, uint8_t *chipId)
1202 {
1203 struct nl_msg *msg = NULL;
1204 uint32_t ifaceId;
1205 int32_t ret;
1206
1207 if (ifName == NULL || chipId == NULL) {
1208 HILOG_ERROR(LOG_CORE, "%s params is NULL", __FUNCTION__);
1209 return RET_CODE_INVALID_PARAM;
1210 }
1211
1212 ifaceId = if_nametoindex(ifName);
1213 if (ifaceId == 0) {
1214 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1215 return RET_CODE_FAILURE;
1216 }
1217
1218 msg = nlmsg_alloc();
1219 if (msg == NULL) {
1220 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1221 return RET_CODE_NOMEM;
1222 }
1223
1224 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
1225 nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
1226 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1227
1228 ret = NetlinkSendCmdSync(msg, ParserChipId, chipId);
1229 if (ret != RET_CODE_SUCCESS) {
1230 HILOG_ERROR(LOG_CORE, "%s: NetlinkSendCmdSync failed.", __FUNCTION__);
1231 }
1232 nlmsg_free(msg);
1233 return ret;
1234 }
1235
GetIfNamesByChipId(const uint8_t chipId,char ** ifNames,uint32_t * num)1236 int32_t GetIfNamesByChipId(const uint8_t chipId, char **ifNames, uint32_t *num)
1237 {
1238 if (ifNames == NULL || num == NULL) {
1239 HILOG_ERROR(LOG_CORE, "%s params is NULL", __FUNCTION__);
1240 return RET_CODE_INVALID_PARAM;
1241 }
1242
1243 if (chipId >= MAX_WLAN_DEVICE) {
1244 HILOG_ERROR(LOG_CORE, "%s: chipId = %d", __FUNCTION__, chipId);
1245 return RET_CODE_INVALID_PARAM;
1246 }
1247 *num = 1;
1248 *ifNames = (char *)calloc(*num, IFNAMSIZ);
1249 if (*ifNames == NULL) {
1250 HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1251 return RET_CODE_FAILURE;
1252 }
1253 if (memcpy_s(*ifNames, IFNAMSIZ, "wlan0", IFNAMSIZ) != EOK) {
1254 HILOG_ERROR(LOG_CORE, "%s: memcpy failed", __FUNCTION__);
1255 free(*ifNames);
1256 *ifNames = NULL;
1257 return RET_CODE_FAILURE;
1258 }
1259 return RET_CODE_SUCCESS;
1260 }
1261
SetResetDriver(const uint8_t chipId,const char * ifName)1262 int32_t SetResetDriver(const uint8_t chipId, const char *ifName)
1263 {
1264 (void)chipId;
1265 (void)ifName;
1266 return RET_CODE_SUCCESS;
1267 }
1268
NetDeviceInfoHandler(struct nl_msg * msg,void * arg)1269 static int32_t NetDeviceInfoHandler(struct nl_msg *msg, void *arg)
1270 {
1271 struct NetDeviceInfo *info = (struct NetDeviceInfo *)arg;
1272 struct nlattr *attr[NL80211_ATTR_MAX + 1];
1273 struct genlmsghdr *hdr = NULL;
1274 void *data = NULL;
1275 int32_t len;
1276
1277 hdr = nlmsg_data(nlmsg_hdr(msg));
1278 if (hdr == NULL) {
1279 HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
1280 return NL_SKIP;
1281 }
1282 data = genlmsg_attrdata(hdr, 0);
1283 len = genlmsg_attrlen(hdr, 0);
1284 nla_parse(attr, NL80211_ATTR_MAX, data, len, NULL);
1285 if (attr[NL80211_ATTR_IFTYPE]) {
1286 info->iftype = nla_get_u32(attr[NL80211_ATTR_IFTYPE]);
1287 HILOG_ERROR(LOG_CORE, "%s: %s iftype is %hhu", __FUNCTION__, info->ifName, info->iftype);
1288 }
1289 if (attr[NL80211_ATTR_MAC]) {
1290 if (memcpy_s(info->mac, ETH_ADDR_LEN, nla_data(attr[NL80211_ATTR_MAC]), ETH_ADDR_LEN) != EOK) {
1291 HILOG_ERROR(LOG_CORE, "%s: memcpy_s mac address fail", __FUNCTION__);
1292 }
1293 }
1294
1295 return NL_SKIP;
1296 }
1297
GetIftypeAndMac(struct NetDeviceInfo * info)1298 static int32_t GetIftypeAndMac(struct NetDeviceInfo *info)
1299 {
1300 struct nl_msg *msg = nlmsg_alloc();
1301 int32_t ret;
1302
1303 if (msg == NULL) {
1304 HILOG_ERROR(LOG_CORE, "%s: nlmsg_alloc failed.", __FUNCTION__);
1305 return RET_CODE_FAILURE;
1306 }
1307
1308 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_INTERFACE, 0);
1309 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(info->ifName));
1310
1311 ret = NetlinkSendCmdSync(msg, NetDeviceInfoHandler, info);
1312 if (ret != RET_CODE_SUCCESS) {
1313 HILOG_ERROR(LOG_CORE, "%s: NetlinkSendCmdSync failed.", __FUNCTION__);
1314 }
1315 nlmsg_free(msg);
1316 return ret;
1317 }
1318
GetNetDeviceInfo(struct NetDeviceInfoResult * netDeviceInfoResult)1319 int32_t GetNetDeviceInfo(struct NetDeviceInfoResult *netDeviceInfoResult)
1320 {
1321 struct NetworkInfoResult networkInfo;
1322 uint32_t i;
1323 int32_t ret;
1324
1325 ret = GetUsableNetworkInfo(&networkInfo);
1326 if (ret != RET_CODE_SUCCESS) {
1327 HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
1328 return ret;
1329 }
1330
1331 for (i = 0; i < networkInfo.nums && i < MAX_NETDEVICE_COUNT; i++) {
1332 if (memset_s(&netDeviceInfoResult->deviceInfos[i], sizeof(struct NetDeviceInfo), 0,
1333 sizeof(struct NetDeviceInfo)) != EOK) {
1334 HILOG_ERROR(LOG_CORE, "%s: memset_s fail", __FUNCTION__);
1335 return RET_CODE_FAILURE;
1336 }
1337 netDeviceInfoResult->deviceInfos[i].index = i + 1;
1338 if (strncpy_s(netDeviceInfoResult->deviceInfos[i].ifName, IFNAMSIZ,
1339 networkInfo.infos[i].name, IFNAMSIZ) != EOK) {
1340 HILOG_ERROR(LOG_CORE, "%s: strncpy_s fail", __FUNCTION__);
1341 return RET_CODE_FAILURE;
1342 }
1343 ret = GetIftypeAndMac(&netDeviceInfoResult->deviceInfos[i]);
1344 if (ret != RET_CODE_SUCCESS) {
1345 HILOG_ERROR(LOG_CORE, "%s: get iftype and mac failed", __FUNCTION__);
1346 return ret;
1347 }
1348 }
1349
1350 return RET_CODE_SUCCESS;
1351 }
1352
CmdScanPutMsg(struct nl_msg * msg,const WifiScan * scan)1353 static int32_t CmdScanPutMsg(struct nl_msg *msg, const WifiScan *scan)
1354 {
1355 struct nlattr *nest = NULL;
1356 int32_t i;
1357
1358 if (scan->ssids) {
1359 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
1360 if (nest == NULL) {
1361 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1362 return RET_CODE_FAILURE;
1363 }
1364 for (i = 0; i < scan->numSsids; i++) {
1365 nla_put(msg, i + 1, scan->ssids[i].ssidLen, scan->ssids[i].ssid);
1366 }
1367 nla_nest_end(msg, nest);
1368 }
1369
1370 if (scan->freqs) {
1371 nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
1372 if (nest == NULL) {
1373 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1374 return RET_CODE_FAILURE;
1375 }
1376 for (i = 0; i < scan->numFreqs; i++) {
1377 nla_put_u32(msg, i + 1, scan->freqs[i]);
1378 }
1379 nla_nest_end(msg, nest);
1380 }
1381
1382 if (scan->extraIes) {
1383 nla_put(msg, NL80211_ATTR_IE, scan->extraIesLen, scan->extraIes);
1384 }
1385
1386 if (scan->bssid) {
1387 nla_put(msg, NL80211_ATTR_MAC, ETH_ADDR_LEN, scan->bssid);
1388 }
1389
1390 return RET_CODE_SUCCESS;
1391 }
1392
WifiCmdScan(const char * ifName,WifiScan * scan)1393 int32_t WifiCmdScan(const char *ifName, WifiScan *scan)
1394 {
1395 uint32_t ifaceId = if_nametoindex(ifName);
1396 struct nl_msg *msg = NULL;
1397 int32_t ret;
1398
1399 if (ifaceId == 0) {
1400 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1401 return RET_CODE_FAILURE;
1402 }
1403
1404 msg = nlmsg_alloc();
1405 if (msg == NULL) {
1406 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1407 return RET_CODE_NOMEM;
1408 }
1409
1410 genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0);
1411 nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1412 do {
1413 ret = CmdScanPutMsg(msg, scan);
1414 if (ret != RET_CODE_SUCCESS) {
1415 HILOG_ERROR(LOG_CORE, "%s: put msg failed", __FUNCTION__);
1416 break;
1417 }
1418 ret = NetlinkSendCmdSync(msg, NULL, NULL);
1419 if (ret != RET_CODE_SUCCESS) {
1420 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1421 }
1422 } while (0);
1423 nlmsg_free(msg);
1424 return ret;
1425 }
1426
ParsePowerMode(const char * buf,uint16_t len,uint8_t * mode)1427 static int32_t ParsePowerMode(const char *buf, uint16_t len, uint8_t *mode)
1428 {
1429 char *key[WIFI_POWER_MODE_NUM] = {"sleep\n", "third\n", "init\n"};
1430 char *str = "pow_mode = ";
1431 if (buf == NULL || mode == NULL) {
1432 return RET_CODE_INVALID_PARAM;
1433 }
1434 char *pos = strstr(buf, str);
1435 if (pos == NULL) {
1436 HILOG_ERROR(LOG_CORE, "%s: no power mode", __FUNCTION__);
1437 return RET_CODE_FAILURE;
1438 }
1439 pos += strlen(str);
1440 if (!strncmp(pos, key[WIFI_POWER_MODE_SLEEPING], strlen(key[WIFI_POWER_MODE_SLEEPING]))) {
1441 *mode = WIFI_POWER_MODE_SLEEPING;
1442 } else if (!strncmp(pos, key[WIFI_POWER_MODE_GENERAL], strlen(key[WIFI_POWER_MODE_GENERAL]))) {
1443 *mode = WIFI_POWER_MODE_GENERAL;
1444 } else if (!strncmp(pos, key[WIFI_POWER_MODE_THROUGH_WALL], strlen(key[WIFI_POWER_MODE_THROUGH_WALL]))) {
1445 *mode = WIFI_POWER_MODE_THROUGH_WALL;
1446 } else {
1447 HILOG_ERROR(LOG_CORE, "%s: no invalid power mode", __FUNCTION__);
1448 return RET_CODE_FAILURE;
1449 }
1450 return RET_CODE_SUCCESS;
1451 }
1452
GetCurrentPowerMode(const char * ifName,uint8_t * mode)1453 int32_t GetCurrentPowerMode(const char *ifName, uint8_t *mode)
1454 {
1455 int32_t fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1456 int32_t ret;
1457 HwprivIoctlData ioctlData;
1458
1459 (void)memset_s(&ioctlData, sizeof(ioctlData), 0, sizeof(ioctlData));
1460 if (fd < 0) {
1461 HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1462 return RET_CODE_FAILURE;
1463 }
1464 do {
1465 if (strcpy_s(ioctlData.interfaceName, IFNAMSIZ, ifName) != EOK) {
1466 HILOG_ERROR(LOG_CORE, "%s: strcpy_s failed", __FUNCTION__);
1467 ret = RET_CODE_FAILURE;
1468 break;
1469 }
1470 ioctlData.data.point.flags = SECONDARY_ID_POWER_MODE;
1471 ioctlData.data.point.length = strlen(GET_POWER_MODE) + 1;
1472 ioctlData.data.point.buf = calloc(ioctlData.data.point.length, sizeof(char));
1473 if (ioctlData.data.point.buf == NULL) {
1474 HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1475 ret = RET_CODE_NOMEM;
1476 break;
1477 }
1478 if (memcpy_s(ioctlData.data.point.buf, ioctlData.data.point.length,
1479 GET_POWER_MODE, strlen(GET_POWER_MODE)) != EOK) {
1480 HILOG_ERROR(LOG_CORE, "%s: memcpy_s failed", __FUNCTION__);
1481 ret = RET_CODE_FAILURE;
1482 break;
1483 }
1484 ret = ioctl(fd, PRIMARY_ID_POWER_MODE, &ioctlData);
1485 if (ret != RET_CODE_SUCCESS) {
1486 HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
1487 if (errno == EOPNOTSUPP) {
1488 ret = RET_CODE_NOT_SUPPORT;
1489 } else {
1490 ret = RET_CODE_FAILURE;
1491 }
1492 break;
1493 }
1494 ret = ParsePowerMode(ioctlData.data.point.buf, ioctlData.data.point.length, mode);
1495 if (ret != RET_CODE_SUCCESS) {
1496 HILOG_ERROR(LOG_CORE, "%s: ParsePowerMode failed", __FUNCTION__);
1497 break;
1498 }
1499 } while (0);
1500 if (ioctlData.data.point.buf != NULL) {
1501 free(ioctlData.data.point.buf);
1502 ioctlData.data.point.buf = NULL;
1503 }
1504 close(fd);
1505 return ret;
1506 }
1507
FillHwprivIoctlData(HwprivIoctlData * ioctlData,uint8_t mode)1508 static int32_t FillHwprivIoctlData(HwprivIoctlData *ioctlData, uint8_t mode)
1509 {
1510 const char *strTable[WIFI_POWER_MODE_NUM] = {SET_POWER_MODE_SLEEP, SET_POWER_MODE_THIRD, SET_POWER_MODE_INIT};
1511 const char *modeStr = strTable[mode];
1512
1513 ioctlData->data.point.length = strlen(strTable[mode]) + 1;
1514 ioctlData->data.point.buf = calloc(ioctlData->data.point.length, sizeof(char));
1515 if (ioctlData->data.point.buf == NULL) {
1516 HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1517 return RET_CODE_NOMEM;
1518 }
1519 ioctlData->data.point.flags = SECONDARY_ID_POWER_MODE;
1520 if (strncpy_s(ioctlData->data.point.buf, ioctlData->data.point.length, modeStr, strlen(modeStr)) != EOK) {
1521 HILOG_ERROR(LOG_CORE, "%s: strncpy_s failed", __FUNCTION__);
1522 free(ioctlData->data.point.buf);
1523 ioctlData->data.point.buf = NULL;
1524 return RET_CODE_FAILURE;
1525 }
1526
1527 return RET_CODE_SUCCESS;
1528 }
1529
SetPowerMode(const char * ifName,uint8_t mode)1530 int32_t SetPowerMode(const char *ifName, uint8_t mode)
1531 {
1532 int32_t fd;
1533 int32_t ret;
1534 HwprivIoctlData ioctlData;
1535
1536 if (ifName == NULL || mode >= WIFI_POWER_MODE_NUM) {
1537 HILOG_ERROR(LOG_CORE, "%s: Invalid parameter", __FUNCTION__);
1538 return RET_CODE_FAILURE;
1539 }
1540 (void)memset_s(&ioctlData, sizeof(ioctlData), 0, sizeof(ioctlData));
1541 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1542 if (fd < 0) {
1543 HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1544 return RET_CODE_FAILURE;
1545 }
1546
1547 do {
1548 if (strcpy_s(ioctlData.interfaceName, IFNAMSIZ, ifName) != EOK) {
1549 HILOG_ERROR(LOG_CORE, "%s: strcpy_s failed", __FUNCTION__);
1550 ret = RET_CODE_FAILURE;
1551 break;
1552 }
1553 ret = FillHwprivIoctlData(&ioctlData, mode);
1554 if (ret != RET_CODE_SUCCESS) {
1555 break;
1556 }
1557 ret = ioctl(fd, PRIMARY_ID_POWER_MODE, &ioctlData);
1558 if (ret != RET_CODE_SUCCESS) {
1559 HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
1560 if (errno == EOPNOTSUPP) {
1561 ret = RET_CODE_NOT_SUPPORT;
1562 } else {
1563 ret = RET_CODE_FAILURE;
1564 }
1565 }
1566 } while (0);
1567
1568 if (ioctlData.data.point.buf != NULL) {
1569 free(ioctlData.data.point.buf);
1570 ioctlData.data.point.buf = NULL;
1571 }
1572 close(fd);
1573 return ret;
1574 }
1575
StartChannelMeas(const char * ifName,const struct MeasParam * measParam)1576 int32_t StartChannelMeas(const char *ifName, const struct MeasParam *measParam)
1577 {
1578 (void)ifName;
1579 (void)measParam;
1580 return RET_CODE_NOT_SUPPORT;
1581 }
1582
GetChannelMeasResult(const char * ifName,struct MeasResult * measResult)1583 int32_t GetChannelMeasResult(const char *ifName, struct MeasResult *measResult)
1584 {
1585 (void)ifName;
1586 (void)measResult;
1587 return RET_CODE_NOT_SUPPORT;
1588 }
1589
SendCommandToDriver(const char * cmd,uint32_t len,const char * ifName)1590 static int32_t SendCommandToDriver(const char *cmd, uint32_t len, const char *ifName)
1591 {
1592 struct ifreq ifr;
1593 WifiPrivCmd privCmd = {0};
1594 uint8_t buf[MAX_PRIV_CMD_SIZE] = {0};
1595 int32_t ret = RET_CODE_FAILURE;
1596
1597 if (cmd == NULL) {
1598 HILOG_ERROR(LOG_CORE, "%{public}s: cmd is null", __FUNCTION__);
1599 return RET_CODE_INVALID_PARAM;
1600 }
1601 if (len > MAX_PRIV_CMD_SIZE) {
1602 HILOG_ERROR(LOG_CORE, "%{public}s: Size of command is too large", __FUNCTION__);
1603 return RET_CODE_INVALID_PARAM;
1604 }
1605 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
1606 HILOG_ERROR(LOG_CORE, "%s: memset_s ifr failed", __FUNCTION__);
1607 return RET_CODE_FAILURE;
1608 }
1609 if (memcpy_s(buf, MAX_PRIV_CMD_SIZE, cmd, len) != EOK) {
1610 HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s error", __FUNCTION__);
1611 return RET_CODE_FAILURE;
1612 }
1613 privCmd.buf = buf;
1614 privCmd.size = sizeof(buf);
1615 privCmd.len = len;
1616 ifr.ifr_data = (void *)&privCmd;
1617 if (strcpy_s(ifr.ifr_name, IFNAMSIZ, ifName) != EOK) {
1618 HILOG_ERROR(LOG_CORE, "%s: strcpy_s error", __FUNCTION__);
1619 return RET_CODE_FAILURE;
1620 }
1621 int32_t sock = socket(AF_INET, SOCK_DGRAM, 0);
1622 if (sock < 0) {
1623 HILOG_ERROR(LOG_CORE, "%{public}s: socket failed, errno = %{public}d, (%{public}s)", __FUNCTION__, errno,
1624 strerror(errno));
1625 return ret;
1626 }
1627 do {
1628 ret = ioctl(sock, SIOCDEVPRIVATE + 1, &ifr);
1629 if (ret < 0) {
1630 HILOG_ERROR(LOG_CORE, "%{public}s: ioctl failed, errno = %{public}d, (%{public}s)", __FUNCTION__, errno,
1631 strerror(errno));
1632 ret = (errno == EOPNOTSUPP) ? RET_CODE_NOT_SUPPORT : RET_CODE_FAILURE;
1633 break;
1634 }
1635 (void)memset_s((void *)cmd, len, 0, len);
1636 if (memcpy_s((void *)cmd, len, privCmd.buf, len - 1) != EOK) {
1637 HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s error", __FUNCTION__);
1638 ret = RET_CODE_FAILURE;
1639 }
1640 } while (0);
1641
1642 close(sock);
1643 return ret;
1644 }
1645
GetInterfaceState(const char * interfaceName,uint16_t * state)1646 static int32_t GetInterfaceState(const char *interfaceName, uint16_t *state)
1647 {
1648 int32_t ret = RET_CODE_FAILURE;
1649 struct ifreq ifr;
1650 int32_t fd;
1651
1652 if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
1653 HILOG_ERROR(LOG_CORE, "%s: memset_s req failed", __FUNCTION__);
1654 return RET_CODE_FAILURE;
1655 }
1656
1657 fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1658 if (fd < 0) {
1659 HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1660 return RET_CODE_FAILURE;
1661 }
1662 do {
1663 if (strncpy_s(ifr.ifr_name, MAX_INTERFACE_NAME_SIZE, interfaceName, strlen(interfaceName)) != EOK) {
1664 HILOG_ERROR(LOG_CORE, "%s: strncpy_s failed", __FUNCTION__);
1665 break;
1666 }
1667 ret = ioctl(fd, SIOCGIFFLAGS, &ifr);
1668 if (ret < 0) {
1669 HILOG_ERROR(LOG_CORE, "%s:could not read interface state for %s, errno = %d, (%s)", __FUNCTION__,
1670 interfaceName, errno, strerror(errno));
1671 ret = RET_CODE_FAILURE;
1672 break;
1673 }
1674 *state = ifr.ifr_flags;
1675 } while (0);
1676
1677 close(fd);
1678 return ret;
1679 }
1680
DisableNextCacOnce(const char * ifName)1681 static int32_t DisableNextCacOnce(const char *ifName)
1682 {
1683 char cmdBuf[P2P_BUF_SIZE] = {CMD_SET_CLOSE_GO_CAC};
1684
1685 return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1686 }
1687
SetGoChannel(const char * ifName,const int8_t * data,uint32_t len)1688 static int32_t SetGoChannel(const char *ifName, const int8_t *data, uint32_t len)
1689 {
1690 int32_t ret = RET_CODE_FAILURE;
1691 char cmdBuf[P2P_BUF_SIZE] = {0};
1692 uint32_t cmdLen;
1693 uint16_t state;
1694
1695 cmdLen = strlen(CMD_SET_CHANGE_GO_CHANNEL);
1696 if ((cmdLen + len) >= P2P_BUF_SIZE) {
1697 HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1698 return ret;
1699 }
1700 ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_CHANGE_GO_CHANNEL, *data);
1701 if (ret < RET_CODE_SUCCESS) {
1702 HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1703 return RET_CODE_FAILURE;
1704 }
1705 if ((GetInterfaceState(ifName, &state) != RET_CODE_SUCCESS) || (state & INTERFACE_UP) == 0) {
1706 HILOG_ERROR(LOG_CORE, "%{public}s: interface state is not OK.", __FUNCTION__);
1707 return RET_CODE_NETDOWN;
1708 }
1709 return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1710 }
1711
SetGoDetectRadar(const char * ifName,const int8_t * data,uint32_t len)1712 static int32_t SetGoDetectRadar(const char *ifName, const int8_t *data, uint32_t len)
1713 {
1714 int32_t ret = RET_CODE_FAILURE;
1715 char cmdBuf[P2P_BUF_SIZE] = {0};
1716 uint32_t cmdLen;
1717 uint16_t state;
1718
1719 cmdLen = strlen(CMD_SET_GO_DETECT_RADAR);
1720 if ((cmdLen + len) >= P2P_BUF_SIZE) {
1721 HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1722 return ret;
1723 }
1724 ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_GO_DETECT_RADAR, *data);
1725 if (ret < RET_CODE_SUCCESS) {
1726 HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1727 return RET_CODE_FAILURE;
1728 }
1729 if ((GetInterfaceState(ifName, &state) != RET_CODE_SUCCESS) || (state & INTERFACE_UP) == 0) {
1730 HILOG_ERROR(LOG_CORE, "%{public}s: interface state is not OK.", __FUNCTION__);
1731 return RET_CODE_NETDOWN;
1732 }
1733 return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1734 }
1735
SetP2pScenes(const char * ifName,const int8_t * data,uint32_t len)1736 static int32_t SetP2pScenes(const char *ifName, const int8_t *data, uint32_t len)
1737 {
1738 int32_t ret = RET_CODE_FAILURE;
1739 char cmdBuf[P2P_BUF_SIZE] = {0};
1740 uint32_t cmdLen;
1741 uint16_t state;
1742
1743 cmdLen = strlen(CMD_SET_P2P_SCENES);
1744 if ((cmdLen + len) >= P2P_BUF_SIZE) {
1745 HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1746 return ret;
1747 }
1748 ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_P2P_SCENES, *data);
1749 if (ret < RET_CODE_SUCCESS) {
1750 HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1751 return RET_CODE_FAILURE;
1752 }
1753 if ((GetInterfaceState(ifName, &state) != RET_CODE_SUCCESS) || (state & INTERFACE_UP) == 0) {
1754 HILOG_ERROR(LOG_CORE, "%{public}s: interface state is not OK.", __FUNCTION__);
1755 return RET_CODE_NETDOWN;
1756 }
1757 return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1758 }
1759
SetDynamicDbacMode(const char * ifName,const int8_t * data,uint32_t len)1760 static int32_t SetDynamicDbacMode(const char *ifName, const int8_t *data, uint32_t len)
1761 {
1762 int32_t ret = RET_CODE_FAILURE;
1763 char cmdBuf[P2P_BUF_SIZE] = {0};
1764 uint32_t cmdLen;
1765 uint16_t state;
1766
1767 cmdLen = strlen(CMD_SET_DYNAMIC_DBAC_MODE);
1768 if ((cmdLen + len) >= P2P_BUF_SIZE) {
1769 HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1770 return ret;
1771 }
1772 ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_DYNAMIC_DBAC_MODE, *data);
1773 if (ret < RET_CODE_SUCCESS) {
1774 HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1775 return RET_CODE_FAILURE;
1776 }
1777 if ((GetInterfaceState(ifName, &state) != RET_CODE_SUCCESS) || (state & INTERFACE_UP) == 0) {
1778 HILOG_ERROR(LOG_CORE, "%{public}s: interface state is not OK.", __FUNCTION__);
1779 return RET_CODE_NETDOWN;
1780 }
1781 return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1782 }
1783
SetProjectionScreenParam(const char * ifName,const ProjectionScreenParam * param)1784 int32_t SetProjectionScreenParam(const char *ifName, const ProjectionScreenParam *param)
1785 {
1786 int32_t ret;
1787
1788 if (strcmp(ifName, STR_WLAN0) != EOK) {
1789 HILOG_ERROR(LOG_CORE, "%{public}s: %{public}s is not supported", __FUNCTION__, ifName);
1790 return RET_CODE_NOT_SUPPORT;
1791 }
1792 switch (param->cmdId) {
1793 case CMD_CLOSE_GO_CAC:
1794 ret = DisableNextCacOnce(ifName);
1795 break;
1796 case CMD_SET_GO_CSA_CHANNEL:
1797 ret = SetGoChannel(ifName, param->buf, param->bufLen);
1798 break;
1799 case CMD_SET_GO_RADAR_DETECT:
1800 ret = SetGoDetectRadar(ifName, param->buf, param->bufLen);
1801 break;
1802 case CMD_ID_MCC_STA_P2P_QUOTA_TIME:
1803 ret = SetDynamicDbacMode(ifName, param->buf, param->bufLen);
1804 break;
1805 case CMD_ID_CTRL_ROAM_CHANNEL:
1806 ret = SetP2pScenes(ifName, param->buf, param->bufLen);
1807 break;
1808 default:
1809 HILOG_ERROR(LOG_CORE, "%{public}s: Invalid command id", __FUNCTION__);
1810 return RET_CODE_NOT_SUPPORT;
1811 }
1812 if (ret != RET_CODE_SUCCESS) {
1813 HILOG_ERROR(LOG_CORE, "%{public}s: Config projection screen fail, ret = %{public}d", __FUNCTION__, ret);
1814 }
1815 return ret;
1816 }
1817
SendCmdIoctl(const char * ifName,int32_t cmdId,const int8_t * paramBuf,uint32_t paramBufLen)1818 int32_t SendCmdIoctl(const char *ifName, int32_t cmdId, const int8_t *paramBuf, uint32_t paramBufLen)
1819 {
1820 (void)ifName;
1821 (void)cmdId;
1822 (void)paramBuf;
1823 (void)paramBufLen;
1824 return RET_CODE_NOT_SUPPORT;
1825 }
1826
ParseStaTxRate(struct nlattr ** stats,uint32_t size,StationInfo * info)1827 static void ParseStaTxRate(struct nlattr **stats, uint32_t size, StationInfo *info)
1828 {
1829 struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
1830 static struct nla_policy ratePolicy[NL80211_RATE_INFO_MAX + 1];
1831
1832 if (size < NL80211_STA_INFO_MAX + 1) {
1833 HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
1834 return;
1835 }
1836 ratePolicy[NL80211_RATE_INFO_BITRATE].type = NLA_U16;
1837 ratePolicy[NL80211_RATE_INFO_BITRATE32].type = NLA_U32;
1838 ratePolicy[NL80211_RATE_INFO_MCS].type = NLA_U8;
1839 ratePolicy[NL80211_RATE_INFO_VHT_MCS].type = NLA_U8;
1840 ratePolicy[NL80211_RATE_INFO_SHORT_GI].type = NLA_FLAG;
1841 ratePolicy[NL80211_RATE_INFO_VHT_NSS].type = NLA_U8;
1842 if (stats[NL80211_STA_INFO_TX_BITRATE] != NULL &&
1843 nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_TX_BITRATE], ratePolicy) == 0) {
1844 if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
1845 info->txRate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
1846 } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
1847 info->txRate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
1848 }
1849 if (rate[NL80211_RATE_INFO_MCS] != NULL) {
1850 info->txMcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
1851 info->flags |= STA_DRV_DATA_TX_MCS;
1852 }
1853 if (rate[NL80211_RATE_INFO_VHT_MCS] != NULL) {
1854 info->txVhtmcs = nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
1855 info->flags |= STA_DRV_DATA_TX_VHT_MCS;
1856 }
1857 if (rate[NL80211_RATE_INFO_SHORT_GI] != NULL) {
1858 info->flags |= STA_DRV_DATA_TX_SHORT_GI;
1859 }
1860 if (rate[NL80211_RATE_INFO_VHT_NSS] != NULL) {
1861 info->txVhtNss = nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
1862 info->flags |= STA_DRV_DATA_TX_VHT_NSS;
1863 }
1864 }
1865 }
1866
ParseStaRxRate(struct nlattr ** stats,uint32_t size,StationInfo * info)1867 static void ParseStaRxRate(struct nlattr **stats, uint32_t size, StationInfo *info)
1868 {
1869 struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
1870 static struct nla_policy ratePolicy[NL80211_RATE_INFO_MAX + 1];
1871
1872 if (size < NL80211_STA_INFO_MAX + 1) {
1873 HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
1874 return;
1875 }
1876 ratePolicy[NL80211_RATE_INFO_BITRATE].type = NLA_U16;
1877 ratePolicy[NL80211_RATE_INFO_BITRATE32].type = NLA_U32;
1878 ratePolicy[NL80211_RATE_INFO_MCS].type = NLA_U8;
1879 ratePolicy[NL80211_RATE_INFO_VHT_MCS].type = NLA_U8;
1880 ratePolicy[NL80211_RATE_INFO_SHORT_GI].type = NLA_FLAG;
1881 ratePolicy[NL80211_RATE_INFO_VHT_NSS].type = NLA_U8;
1882 if (stats[NL80211_STA_INFO_RX_BITRATE] != NULL &&
1883 nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_RX_BITRATE], ratePolicy) == 0) {
1884 if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
1885 info->rxRate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
1886 } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
1887 info->rxRate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
1888 }
1889 if (rate[NL80211_RATE_INFO_MCS] != NULL) {
1890 info->rxMcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
1891 info->flags |= STA_DRV_DATA_RX_MCS;
1892 }
1893 if (rate[NL80211_RATE_INFO_VHT_MCS] != NULL) {
1894 info->rxVhtmcs = nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
1895 info->flags |= STA_DRV_DATA_RX_VHT_MCS;
1896 }
1897 if (rate[NL80211_RATE_INFO_SHORT_GI] != NULL) {
1898 info->flags |= STA_DRV_DATA_RX_SHORT_GI;
1899 }
1900 if (rate[NL80211_RATE_INFO_VHT_NSS] != NULL) {
1901 info->rxVhtNss = nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
1902 info->flags |= STA_DRV_DATA_RX_VHT_NSS;
1903 }
1904 }
1905 }
1906
ParseStaInfo(struct nlattr ** stats,uint32_t size,StationInfo * info)1907 static void ParseStaInfo(struct nlattr **stats, uint32_t size, StationInfo *info)
1908 {
1909 ParseStaTxRate(stats, size, info);
1910 ParseStaRxRate(stats, size, info);
1911 }
1912
StationInfoHandler(struct nl_msg * msg,void * arg)1913 static int32_t StationInfoHandler(struct nl_msg *msg, void *arg)
1914 {
1915 StationInfo *info = (StationInfo *)arg;
1916 struct genlmsghdr *hdr = NULL;
1917 struct nlattr *attr[NL80211_ATTR_MAX + 1];
1918 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
1919 static struct nla_policy statsPolicy[NL80211_STA_INFO_MAX + 1];
1920
1921 statsPolicy[NL80211_STA_INFO_INACTIVE_TIME].type = NLA_U32;
1922 statsPolicy[NL80211_STA_INFO_RX_BYTES].type = NLA_U32;
1923 statsPolicy[NL80211_STA_INFO_TX_BYTES].type = NLA_U32;
1924 statsPolicy[NL80211_STA_INFO_RX_PACKETS].type = NLA_U32;
1925 statsPolicy[NL80211_STA_INFO_TX_PACKETS].type = NLA_U32;
1926 statsPolicy[NL80211_STA_INFO_TX_FAILED].type = NLA_U32;
1927 statsPolicy[NL80211_STA_INFO_RX_BYTES64].type = NLA_U64;
1928 statsPolicy[NL80211_STA_INFO_TX_BYTES64].type = NLA_U64;
1929 statsPolicy[NL80211_STA_INFO_SIGNAL].type = NLA_U8;
1930 statsPolicy[NL80211_STA_INFO_ACK_SIGNAL].type = NLA_U8;
1931 statsPolicy[NL80211_STA_INFO_RX_DURATION].type = NLA_U64;
1932
1933 hdr = nlmsg_data(nlmsg_hdr(msg));
1934 if (hdr == NULL) {
1935 HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
1936 return NL_SKIP;
1937 }
1938
1939 nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
1940 if (!attr[NL80211_ATTR_STA_INFO]) {
1941 HILOG_ERROR(LOG_CORE, "%s: sta stats missing!", __FUNCTION__);
1942 return NL_SKIP;
1943 }
1944
1945 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, attr[NL80211_ATTR_STA_INFO], statsPolicy)) {
1946 HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes!", __FUNCTION__);
1947 return NL_SKIP;
1948 }
1949
1950 ParseStaInfo(stats, NL80211_STA_INFO_MAX + 1, info);
1951 return NL_SKIP;
1952 }
1953
GetStationInfo(const char * ifName,StationInfo * info,const uint8_t * mac,uint32_t macLen)1954 int32_t GetStationInfo(const char *ifName, StationInfo *info, const uint8_t *mac, uint32_t macLen)
1955 {
1956 uint32_t ifaceId = if_nametoindex(ifName);
1957 struct nl_msg *msg = NULL;
1958 int32_t ret = RET_CODE_FAILURE;
1959
1960 if (ifaceId == 0) {
1961 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1962 return RET_CODE_FAILURE;
1963 }
1964
1965 msg = nlmsg_alloc();
1966 if (msg == NULL) {
1967 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1968 return RET_CODE_NOMEM;
1969 }
1970 do {
1971 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_STATION, 0)) {
1972 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
1973 break;
1974 }
1975 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId) != RET_CODE_SUCCESS) {
1976 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 ifaceId faile", __FUNCTION__);
1977 break;
1978 }
1979 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ADDR_LEN, mac) != RET_CODE_SUCCESS) {
1980 HILOG_ERROR(LOG_CORE, "%s: nla_put mac address faile", __FUNCTION__);
1981 break;
1982 }
1983
1984 ret = NetlinkSendCmdSync(msg, StationInfoHandler, info);
1985 if (ret != RET_CODE_SUCCESS) {
1986 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1987 }
1988 } while (0);
1989 nlmsg_free(msg);
1990 return ret;
1991 }
1992
SetExtFeatureFlag(const uint8_t * extFeatureFlagsBytes,uint32_t extFeatureFlagsLen,uint32_t extFeatureFlag)1993 static bool SetExtFeatureFlag(const uint8_t *extFeatureFlagsBytes, uint32_t extFeatureFlagsLen, uint32_t extFeatureFlag)
1994 {
1995 uint32_t extFeatureFlagBytePos;
1996 uint32_t extFeatureFlagBitPos;
1997
1998 if (extFeatureFlagsBytes == NULL || extFeatureFlagsLen == 0) {
1999 HILOG_ERROR(LOG_CORE, "%s: param is NULL.", __FUNCTION__);
2000 return false;
2001 }
2002 extFeatureFlagBytePos = extFeatureFlag / BITNUMS_OF_ONE_BYTE;
2003 extFeatureFlagBitPos = extFeatureFlag % BITNUMS_OF_ONE_BYTE;
2004 if (extFeatureFlagBytePos >= extFeatureFlagsLen) {
2005 return false;
2006 }
2007 return extFeatureFlagsBytes[extFeatureFlagBytePos] & (1U << extFeatureFlagBitPos);
2008 }
2009
GetWiphyInfoHandler(struct nl_msg * msg,void * arg)2010 static int32_t GetWiphyInfoHandler(struct nl_msg *msg, void *arg)
2011 {
2012 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
2013 struct nlattr *attr[NL80211_ATTR_MAX + 1];
2014 WiphyInfo *wiphyInfo = (WiphyInfo *)arg;
2015 uint32_t featureFlags = 0;
2016 uint8_t *extFeatureFlagsBytes = NULL;
2017 uint32_t extFeatureFlagsLen = 0;
2018
2019 if (hdr == NULL) {
2020 HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
2021 return NL_SKIP;
2022 }
2023 nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
2024 if (attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS] != NULL) {
2025 wiphyInfo->scanCapabilities.maxNumScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCAN_SSIDS]);
2026 }
2027 if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS] != NULL) {
2028 wiphyInfo->scanCapabilities.maxNumSchedScanSsids = nla_get_u8(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS]);
2029 }
2030 if (attr[NL80211_ATTR_MAX_MATCH_SETS] != NULL) {
2031 wiphyInfo->scanCapabilities.maxMatchSets = nla_get_u8(attr[NL80211_ATTR_MAX_MATCH_SETS]);
2032 }
2033 if (attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS] != NULL) {
2034 wiphyInfo->scanCapabilities.maxNumScanPlans = nla_get_u32(attr[NL80211_ATTR_MAX_NUM_SCHED_SCAN_PLANS]);
2035 }
2036 if (attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL] != NULL) {
2037 wiphyInfo->scanCapabilities.maxScanPlanInterval = nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_INTERVAL]);
2038 }
2039 if (attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS] != NULL) {
2040 wiphyInfo->scanCapabilities.maxScanPlanIterations = nla_get_u32(attr[NL80211_ATTR_MAX_SCAN_PLAN_ITERATIONS]);
2041 }
2042 if (attr[NL80211_ATTR_FEATURE_FLAGS] != NULL) {
2043 featureFlags = nla_get_u32(attr[NL80211_ATTR_FEATURE_FLAGS]);
2044 }
2045 wiphyInfo->wiphyFeatures.supportsRandomMacSchedScan = featureFlags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
2046 if (attr[NL80211_ATTR_EXT_FEATURES] != NULL) {
2047 extFeatureFlagsBytes = nla_data(attr[NL80211_ATTR_EXT_FEATURES]);
2048 extFeatureFlagsLen = nla_len(attr[NL80211_ATTR_EXT_FEATURES]);
2049 wiphyInfo->wiphyFeatures.supportsLowPowerOneshotScan =
2050 SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
2051 wiphyInfo->wiphyFeatures.supportsExtSchedScanRelativeRssi =
2052 SetExtFeatureFlag(extFeatureFlagsBytes, extFeatureFlagsLen, NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI);
2053 }
2054 return NL_SKIP;
2055 }
2056
GetWiphyInfo(const uint32_t wiphyIndex,WiphyInfo * wiphyInfo)2057 static int32_t GetWiphyInfo(const uint32_t wiphyIndex, WiphyInfo *wiphyInfo)
2058 {
2059 struct nl_msg *msg = NULL;
2060 int32_t ret = RET_CODE_FAILURE;
2061
2062 if (wiphyInfo == NULL) {
2063 HILOG_ERROR(LOG_CORE, "%s: param is NULL.", __FUNCTION__);
2064 return RET_CODE_INVALID_PARAM;
2065 }
2066 msg = nlmsg_alloc();
2067 if (msg == NULL) {
2068 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2069 return RET_CODE_NOMEM;
2070 }
2071 do {
2072 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_WIPHY, 0)) {
2073 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2074 break;
2075 }
2076 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, wiphyIndex) != RET_CODE_SUCCESS) {
2077 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 wiphyIndex failed.", __FUNCTION__);
2078 break;
2079 }
2080 ret = NetlinkSendCmdSync(msg, GetWiphyInfoHandler, wiphyInfo);
2081 if (ret != RET_CODE_SUCCESS) {
2082 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2083 }
2084 } while (0);
2085 nlmsg_free(msg);
2086 return ret;
2087 }
2088
GetWiphyIndexHandler(struct nl_msg * msg,void * arg)2089 static int32_t GetWiphyIndexHandler(struct nl_msg *msg, void *arg)
2090 {
2091 struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
2092 struct nlattr *attr[NL80211_ATTR_MAX + 1];
2093 uint32_t *wiphyIndex = (uint32_t *)arg;
2094
2095 if (hdr == NULL) {
2096 HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
2097 return NL_SKIP;
2098 }
2099 nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
2100 if (!attr[NL80211_ATTR_WIPHY]) {
2101 HILOG_ERROR(LOG_CORE, "%s: wiphy info missing!", __FUNCTION__);
2102 return NL_SKIP;
2103 }
2104 *wiphyIndex = nla_get_u32(attr[NL80211_ATTR_WIPHY]);
2105 return NL_SKIP;
2106 }
2107
GetWiphyIndex(const char * ifName,uint32_t * wiphyIndex)2108 static int32_t GetWiphyIndex(const char *ifName, uint32_t *wiphyIndex)
2109 {
2110 struct nl_msg *msg = NULL;
2111 uint32_t interfaceId;
2112 int32_t ret = RET_CODE_FAILURE;
2113
2114 if (ifName == NULL || wiphyIndex == NULL) {
2115 HILOG_ERROR(LOG_CORE, "%s: param is NULL.", __FUNCTION__);
2116 return RET_CODE_INVALID_PARAM;
2117 }
2118 interfaceId = if_nametoindex(ifName);
2119 if (interfaceId == 0) {
2120 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
2121 return RET_CODE_FAILURE;
2122 }
2123 msg = nlmsg_alloc();
2124 if (msg == NULL) {
2125 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2126 return RET_CODE_NOMEM;
2127 }
2128 do {
2129 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0)) {
2130 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2131 break;
2132 }
2133 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, interfaceId) != RET_CODE_SUCCESS) {
2134 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId failed.", __FUNCTION__);
2135 break;
2136 }
2137 ret = NetlinkSendCmdSync(msg, GetWiphyIndexHandler, wiphyIndex);
2138 if (ret != RET_CODE_SUCCESS) {
2139 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2140 }
2141 } while (0);
2142 nlmsg_free(msg);
2143 return ret;
2144 }
2145
ProcessMatchSsidToMsg(struct nl_msg * msg,const WiphyInfo * wiphyInfo,const WifiPnoSettings * pnoSettings)2146 static int32_t ProcessMatchSsidToMsg(struct nl_msg *msg, const WiphyInfo *wiphyInfo, const WifiPnoSettings *pnoSettings)
2147 {
2148 struct nlattr *nestedMatchSsid = NULL;
2149 struct nlattr *nest = NULL;
2150 uint8_t matchSsidsCount = 0;
2151
2152 nestedMatchSsid = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
2153 if (nestedMatchSsid == NULL) {
2154 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed.", __FUNCTION__);
2155 return RET_CODE_FAILURE;
2156 }
2157 for (uint32_t i = 0; i < pnoSettings->pnoNetworksLen; i++) {
2158 if (matchSsidsCount + 1 > wiphyInfo->scanCapabilities.maxMatchSets) {
2159 break;
2160 }
2161 nest = nla_nest_start(msg, i);
2162 if (nest == NULL) {
2163 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed.", __FUNCTION__);
2164 return RET_CODE_FAILURE;
2165 }
2166 nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID, pnoSettings->pnoNetworks[i].ssid.ssidLen,
2167 pnoSettings->pnoNetworks[i].ssid.ssid);
2168 nla_put_u32(msg, NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, pnoSettings->min5gRssi);
2169 nla_nest_end(msg, nest);
2170 matchSsidsCount++;
2171 }
2172 nla_nest_end(msg, nestedMatchSsid);
2173 return RET_CODE_SUCCESS;
2174 }
2175
ClearSsidsList(struct DListHead * ssidsList)2176 static void ClearSsidsList(struct DListHead *ssidsList)
2177 {
2178 struct SsidListNode *ssidListNode = NULL;
2179 struct SsidListNode *tmp = NULL;
2180
2181 DLIST_FOR_EACH_ENTRY_SAFE(ssidListNode, tmp, ssidsList, struct SsidListNode, entry) {
2182 DListRemove(&ssidListNode->entry);
2183 free(ssidListNode);
2184 ssidListNode = NULL;
2185 }
2186 DListHeadInit(ssidsList);
2187 }
2188
ProcessSsidToMsg(struct nl_msg * msg,const WiphyInfo * wiphyInfo,const WifiPnoSettings * pnoSettings)2189 static int32_t ProcessSsidToMsg(struct nl_msg *msg, const WiphyInfo *wiphyInfo, const WifiPnoSettings *pnoSettings)
2190 {
2191 uint8_t scanSsidsCount = 0;
2192 struct SsidListNode *ssidListNode = NULL;
2193 struct nlattr *nestedSsid = NULL;
2194 uint32_t index = 0;
2195 struct DListHead scanSsids = {0};
2196
2197 DListHeadInit(&scanSsids);
2198 for (uint32_t i = 0; i < pnoSettings->pnoNetworksLen; i++) {
2199 if (!(pnoSettings->pnoNetworks[i].isHidden)) {
2200 continue;
2201 }
2202 if (scanSsidsCount + 1 > wiphyInfo->scanCapabilities.maxNumSchedScanSsids) {
2203 break;
2204 }
2205 struct SsidListNode *ssidNode = (struct SsidListNode *)malloc(sizeof(struct SsidListNode));
2206 if (ssidNode == NULL) {
2207 HILOG_ERROR(LOG_CORE, "%s: malloc failed.", __FUNCTION__);
2208 ClearSsidsList(&scanSsids);
2209 return RET_CODE_FAILURE;
2210 }
2211 (void)memset_s(ssidNode, sizeof(struct SsidListNode), 0, sizeof(struct SsidListNode));
2212 ssidNode->ssidInfo.ssidLen = pnoSettings->pnoNetworks[i].ssid.ssidLen;
2213 if (memcpy_s(ssidNode->ssidInfo.ssid, MAX_SSID_LEN, pnoSettings->pnoNetworks[i].ssid.ssid,
2214 pnoSettings->pnoNetworks[i].ssid.ssidLen) != EOK) {
2215 HILOG_ERROR(LOG_CORE, "%s: memcpy_s failed.", __FUNCTION__);
2216 ClearSsidsList(&scanSsids);
2217 return RET_CODE_FAILURE;
2218 }
2219 DListInsertTail(&ssidNode->entry, &scanSsids);
2220 scanSsidsCount++;
2221 }
2222 if (!DListIsEmpty(&scanSsids)) {
2223 nestedSsid = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
2224 if (nestedSsid == NULL) {
2225 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed.", __FUNCTION__);
2226 ClearSsidsList(&scanSsids);
2227 return RET_CODE_FAILURE;
2228 }
2229 DLIST_FOR_EACH_ENTRY(ssidListNode, &scanSsids, struct SsidListNode, entry) {
2230 nla_put(msg, index, ssidListNode->ssidInfo.ssidLen, ssidListNode->ssidInfo.ssid);
2231 index++;
2232 }
2233 nla_nest_end(msg, nestedSsid);
2234 }
2235 ClearSsidsList(&scanSsids);
2236 return RET_CODE_SUCCESS;
2237 }
2238
ProcessScanPlanToMsg(struct nl_msg * msg,const WiphyInfo * wiphyInfo,const WifiPnoSettings * pnoSettings)2239 static int32_t ProcessScanPlanToMsg(struct nl_msg *msg, const WiphyInfo *wiphyInfo, const WifiPnoSettings *pnoSettings)
2240 {
2241 struct nlattr *nestedPlan = NULL;
2242 struct nlattr *plan = NULL;
2243
2244 bool supportNumScanPlans = (wiphyInfo->scanCapabilities.maxNumScanPlans >= 2);
2245 bool supportScanPlanInterval = (wiphyInfo->scanCapabilities.maxScanPlanInterval * MS_PER_SECOND >=
2246 (uint32_t)pnoSettings->scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
2247 bool supportScanPlanIterations = (wiphyInfo->scanCapabilities.maxScanPlanIterations >= FAST_SCAN_ITERATIONS);
2248
2249 if (supportNumScanPlans && supportScanPlanInterval && supportScanPlanIterations) {
2250 nestedPlan = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_PLANS);
2251 if (nestedPlan == NULL) {
2252 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed.", __FUNCTION__);
2253 return RET_CODE_FAILURE;
2254 }
2255 plan = nla_nest_start(msg, SCHED_SCAN_PLANS_ATTR_INDEX1);
2256 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, pnoSettings->scanIntervalMs);
2257 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_ITERATIONS, pnoSettings->scanIterations);
2258 nla_nest_end(msg, plan);
2259 plan = nla_nest_start(msg, SCHED_SCAN_PLANS_ATTR_INDEX2);
2260 nla_put_u32(msg, NL80211_SCHED_SCAN_PLAN_INTERVAL, pnoSettings->scanIntervalMs * SLOW_SCAN_INTERVAL_MULTIPLIER);
2261 nla_nest_end(msg, plan);
2262 nla_nest_end(msg, nestedPlan);
2263 } else {
2264 nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, pnoSettings->scanIntervalMs * MS_PER_SECOND);
2265 }
2266 return RET_CODE_SUCCESS;
2267 }
2268
ClearFreqsList(struct DListHead * freqsList)2269 static void ClearFreqsList(struct DListHead *freqsList)
2270 {
2271 struct FreqListNode *freqListNode = NULL;
2272 struct FreqListNode *tmp = NULL;
2273
2274 DLIST_FOR_EACH_ENTRY_SAFE(freqListNode, tmp, freqsList, struct FreqListNode, entry) {
2275 DListRemove(&freqListNode->entry);
2276 free(freqListNode);
2277 freqListNode = NULL;
2278 }
2279 DListHeadInit(freqsList);
2280 }
2281
InsertFreqToList(int32_t freq,struct DListHead * scanFreqs)2282 static int32_t InsertFreqToList(int32_t freq, struct DListHead *scanFreqs)
2283 {
2284 bool isFreqExist = false;
2285 struct FreqListNode *freqListNode = NULL;
2286
2287 DLIST_FOR_EACH_ENTRY(freqListNode, scanFreqs, struct FreqListNode, entry) {
2288 if (freqListNode == NULL) {
2289 HILOG_ERROR(LOG_CORE, "%s: freqListNode is NULL.", __FUNCTION__);
2290 return RET_CODE_FAILURE;
2291 }
2292 if (freqListNode->freq == freq) {
2293 isFreqExist = true;
2294 break;
2295 }
2296 }
2297 if (!isFreqExist) {
2298 struct FreqListNode *freqNode = (struct FreqListNode *)malloc(sizeof(struct FreqListNode));
2299 if (freqNode == NULL) {
2300 HILOG_ERROR(LOG_CORE, "%s: malloc failed.", __FUNCTION__);
2301 return RET_CODE_FAILURE;
2302 }
2303 (void)memset_s(freqNode, sizeof(struct FreqListNode), 0, sizeof(struct FreqListNode));
2304 freqNode->freq = freq;
2305 DListInsertTail(&freqNode->entry, scanFreqs);
2306 }
2307 return RET_CODE_SUCCESS;
2308 }
2309
ProcessFreqToMsg(struct nl_msg * msg,const WifiPnoSettings * pnoSettings)2310 static int32_t ProcessFreqToMsg(struct nl_msg *msg, const WifiPnoSettings *pnoSettings)
2311 {
2312 struct FreqListNode *freqListNode = NULL;
2313 struct DListHead scanFreqs = {0};
2314 struct nlattr *nestedFreq = NULL;
2315 uint32_t index = 0;
2316
2317 DListHeadInit(&scanFreqs);
2318 for (uint32_t i = 0; i < pnoSettings->pnoNetworksLen; i++) {
2319 for (uint32_t j = 0; j < pnoSettings->pnoNetworks[i].freqsLen; j++) {
2320 if (InsertFreqToList(pnoSettings->pnoNetworks[i].freqs[j], &scanFreqs) != RET_CODE_SUCCESS) {
2321 HILOG_ERROR(LOG_CORE, "%s: InsertFreqToList failed.", __FUNCTION__);
2322 ClearFreqsList(&scanFreqs);
2323 return RET_CODE_FAILURE;
2324 }
2325 }
2326 }
2327 if (!DListIsEmpty(&scanFreqs)) {
2328 nestedFreq = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
2329 if (nestedFreq == NULL) {
2330 HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed.", __FUNCTION__);
2331 ClearFreqsList(&scanFreqs);
2332 return RET_CODE_FAILURE;
2333 }
2334 DLIST_FOR_EACH_ENTRY(freqListNode, &scanFreqs, struct FreqListNode, entry) {
2335 nla_put_s32(msg, index, freqListNode->freq);
2336 index++;
2337 }
2338 nla_nest_end(msg, nestedFreq);
2339 }
2340 ClearFreqsList(&scanFreqs);
2341 return RET_CODE_SUCCESS;
2342 }
2343
ProcessReqflagsToMsg(struct nl_msg * msg,const WiphyInfo * wiphyInfo,const WifiPnoSettings * pnoSettings)2344 static int32_t ProcessReqflagsToMsg(struct nl_msg *msg, const WiphyInfo *wiphyInfo, const WifiPnoSettings *pnoSettings)
2345 {
2346 uint32_t scanFlag = 0;
2347
2348 if (wiphyInfo->wiphyFeatures.supportsExtSchedScanRelativeRssi) {
2349 struct nl80211_bss_select_rssi_adjust rssiAdjust;
2350 (void)memset_s(&rssiAdjust, sizeof(rssiAdjust), 0, sizeof(rssiAdjust));
2351 rssiAdjust.band = NL80211_BAND_2GHZ;
2352 rssiAdjust.delta = pnoSettings->min2gRssi - pnoSettings->min5gRssi;
2353 nla_put(msg, NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST, sizeof(rssiAdjust), &rssiAdjust);
2354 }
2355 if (wiphyInfo->wiphyFeatures.supportsRandomMacSchedScan) {
2356 scanFlag |= NL80211_SCAN_FLAG_RANDOM_ADDR;
2357 }
2358 if (wiphyInfo->wiphyFeatures.supportsLowPowerOneshotScan) {
2359 scanFlag |= NL80211_SCAN_FLAG_LOW_POWER;
2360 }
2361 if (scanFlag != 0) {
2362 nla_put_u32(msg, NL80211_ATTR_SCAN_FLAGS, scanFlag);
2363 }
2364 return RET_CODE_SUCCESS;
2365 }
2366
ConvertSetsToNetlinkmsg(struct nl_msg * msg,const char * ifName,const WifiPnoSettings * pnoSettings)2367 static int32_t ConvertSetsToNetlinkmsg(struct nl_msg *msg, const char *ifName, const WifiPnoSettings *pnoSettings)
2368 {
2369 int32_t ret;
2370 uint32_t wiphyIndex;
2371 WiphyInfo wiphyInfo;
2372
2373 (void)memset_s(&wiphyInfo, sizeof(wiphyInfo), 0, sizeof(wiphyInfo));
2374 ret = GetWiphyIndex(ifName, &wiphyIndex);
2375 if (ret != RET_CODE_SUCCESS) {
2376 HILOG_ERROR(LOG_CORE, "%s: GetWiphyIndex failed", __FUNCTION__);
2377 return RET_CODE_FAILURE;
2378 }
2379 ret = GetWiphyInfo(wiphyIndex, &wiphyInfo);
2380 if (ret != RET_CODE_SUCCESS) {
2381 HILOG_ERROR(LOG_CORE, "%s: GetWiphyInfo failed", __FUNCTION__);
2382 return RET_CODE_FAILURE;
2383 }
2384 if (ProcessMatchSsidToMsg(msg, &wiphyInfo, pnoSettings) != RET_CODE_SUCCESS ||
2385 ProcessSsidToMsg(msg, &wiphyInfo, pnoSettings) != RET_CODE_SUCCESS ||
2386 ProcessScanPlanToMsg(msg, &wiphyInfo, pnoSettings) != RET_CODE_SUCCESS ||
2387 ProcessReqflagsToMsg(msg, &wiphyInfo, pnoSettings) != RET_CODE_SUCCESS ||
2388 ProcessFreqToMsg(msg, pnoSettings) != RET_CODE_SUCCESS) {
2389 HILOG_ERROR(LOG_CORE, "%s: Fill parameters to netlink failed.", __FUNCTION__);
2390 return RET_CODE_FAILURE;
2391 }
2392 return RET_CODE_SUCCESS;
2393 }
2394
WifiStartPnoScan(const char * ifName,const WifiPnoSettings * pnoSettings)2395 int32_t WifiStartPnoScan(const char *ifName, const WifiPnoSettings *pnoSettings)
2396 {
2397 uint32_t interfaceId;
2398 struct nl_msg *msg = NULL;
2399 int32_t ret = RET_CODE_FAILURE;
2400
2401 interfaceId = if_nametoindex(ifName);
2402 if (interfaceId == 0) {
2403 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
2404 return RET_CODE_FAILURE;
2405 }
2406 msg = nlmsg_alloc();
2407 if (msg == NULL) {
2408 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2409 return RET_CODE_NOMEM;
2410 }
2411 do {
2412 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_ACK, NL80211_CMD_START_SCHED_SCAN, 0)) {
2413 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2414 break;
2415 }
2416 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, interfaceId) != RET_CODE_SUCCESS) {
2417 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId failed.", __FUNCTION__);
2418 break;
2419 }
2420 if (ConvertSetsToNetlinkmsg(msg, ifName, pnoSettings) != RET_CODE_SUCCESS) {
2421 HILOG_ERROR(LOG_CORE, "%s: ConvertSetsToNetlinkmsg failed.", __FUNCTION__);
2422 break;
2423 }
2424 ret = NetlinkSendCmdSync(msg, NULL, NULL);
2425 if (ret != RET_CODE_SUCCESS) {
2426 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2427 }
2428 } while (0);
2429 nlmsg_free(msg);
2430 return ret;
2431 }
2432
WifiStopPnoScan(const char * ifName)2433 int32_t WifiStopPnoScan(const char *ifName)
2434 {
2435 uint32_t interfaceId;
2436 struct nl_msg *msg = NULL;
2437 int32_t ret = RET_CODE_FAILURE;
2438
2439 interfaceId = if_nametoindex(ifName);
2440 if (interfaceId == 0) {
2441 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
2442 return RET_CODE_FAILURE;
2443 }
2444 msg = nlmsg_alloc();
2445 if (msg == NULL) {
2446 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2447 return RET_CODE_NOMEM;
2448 }
2449 do {
2450 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_ACK, NL80211_CMD_STOP_SCHED_SCAN, 0)) {
2451 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2452 break;
2453 }
2454 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, interfaceId) != RET_CODE_SUCCESS) {
2455 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId failed.", __FUNCTION__);
2456 break;
2457 }
2458 ret = NetlinkSendCmdSync(msg, NULL, NULL);
2459 if (ret != RET_CODE_SUCCESS) {
2460 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2461 }
2462 } while (0);
2463 nlmsg_free(msg);
2464 return ret;
2465 }
2466
GetAssociatedInfoHandler(struct nl_msg * msg,void * arg)2467 static int32_t GetAssociatedInfoHandler(struct nl_msg *msg, void *arg)
2468 {
2469 struct nlattr *attr[NL80211_ATTR_MAX + 1];
2470 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2471 struct nlattr *bss[NL80211_BSS_MAX + 1];
2472 uint32_t status;
2473 AssociatedInfo *associatedInfo = (AssociatedInfo *)arg;
2474 struct nla_policy bssPolicy[NL80211_BSS_MAX + 1];
2475 bssPolicy[NL80211_BSS_BSSID].type = NLA_UNSPEC;
2476 bssPolicy[NL80211_BSS_FREQUENCY].type = NLA_U32;
2477 bssPolicy[NL80211_BSS_STATUS].type = NLA_U32;
2478
2479 nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
2480 if (!attr[NL80211_ATTR_BSS]) {
2481 HILOG_ERROR(LOG_CORE, "%s: BSS info missing!", __FUNCTION__);
2482 return NL_SKIP;
2483 }
2484 if (nla_parse_nested(bss, NL80211_BSS_MAX, attr[NL80211_ATTR_BSS], bssPolicy) < 0 ||
2485 bss[NL80211_BSS_STATUS] == NULL) {
2486 HILOG_ERROR(LOG_CORE, "%s: BSS attr or status missing!", __FUNCTION__);
2487 return NL_SKIP;
2488 }
2489 status = nla_get_u32(bss[NL80211_BSS_STATUS]);
2490 if (status == BSS_STATUS_ASSOCIATED && bss[NL80211_BSS_FREQUENCY]) {
2491 associatedInfo->associatedFreq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
2492 }
2493 if (status == BSS_STATUS_ASSOCIATED && bss[NL80211_BSS_BSSID]) {
2494 if (memcpy_s(associatedInfo->associatedBssid, ETH_ADDR_LEN,
2495 nla_data(bss[NL80211_BSS_BSSID]), ETH_ADDR_LEN) != EOK) {
2496 HILOG_ERROR(LOG_CORE, "%s: memcpy_s failed!", __FUNCTION__);
2497 return NL_SKIP;
2498 }
2499 }
2500 return NL_SKIP;
2501 }
2502
WifiGetAssociatedInfo(const char * ifName,AssociatedInfo * associatedInfo)2503 static int32_t WifiGetAssociatedInfo(const char *ifName, AssociatedInfo *associatedInfo)
2504 {
2505 struct nl_msg *msg = NULL;
2506 uint32_t interfaceId;
2507 int32_t ret = RET_CODE_FAILURE;
2508
2509 interfaceId = if_nametoindex(ifName);
2510 if (interfaceId == 0) {
2511 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
2512 return RET_CODE_FAILURE;
2513 }
2514 msg = nlmsg_alloc();
2515 if (msg == NULL) {
2516 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2517 return RET_CODE_NOMEM;
2518 }
2519 do {
2520 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_SCAN, 0)) {
2521 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2522 break;
2523 }
2524 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, interfaceId) != RET_CODE_SUCCESS) {
2525 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId faile", __FUNCTION__);
2526 break;
2527 }
2528 ret = NetlinkSendCmdSync(msg, GetAssociatedInfoHandler, associatedInfo);
2529 if (ret != RET_CODE_SUCCESS) {
2530 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2531 }
2532 } while (0);
2533 nlmsg_free(msg);
2534 return ret;
2535 }
2536
FillSignalExt(struct nlattr ** stats,uint32_t size,struct SignalResult * signalResult)2537 static void FillSignalExt(struct nlattr **stats, uint32_t size, struct SignalResult *signalResult)
2538 {
2539 if (size < NL80211_STA_INFO_MAX + 1) {
2540 HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
2541 return;
2542 }
2543
2544 if (stats[NL80211_STA_INFO_NOISE] != NULL) {
2545 signalResult->currentNoise = nla_get_s32(stats[NL80211_STA_INFO_NOISE]);
2546 }
2547 if (stats[NL80211_STA_INFO_SNR] != NULL) {
2548 signalResult->currentSnr = nla_get_s32(stats[NL80211_STA_INFO_SNR]);
2549 }
2550 if (stats[NL80211_STA_INFO_CNAHLOAD] != NULL) {
2551 signalResult->currentChload = nla_get_s32(stats[NL80211_STA_INFO_CNAHLOAD]);
2552 }
2553 if (stats[NL80211_STA_INFO_UL_DELAY] != NULL) {
2554 signalResult->currentUlDelay = nla_get_s32(stats[NL80211_STA_INFO_UL_DELAY]);
2555 }
2556 }
2557
FillSignalRate(struct nlattr ** stats,uint32_t size,struct SignalResult * signalResult)2558 static void FillSignalRate(struct nlattr **stats, uint32_t size, struct SignalResult *signalResult)
2559 {
2560 struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
2561 struct nla_policy ratePolicy[NL80211_RATE_INFO_MAX + 1];
2562 ratePolicy[NL80211_RATE_INFO_BITRATE].type = NLA_U16;
2563 ratePolicy[NL80211_RATE_INFO_BITRATE32].type = NLA_U32;
2564
2565 if (size < NL80211_STA_INFO_MAX + 1) {
2566 HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
2567 return;
2568 }
2569 if (stats[NL80211_STA_INFO_RX_BITRATE] != NULL &&
2570 nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_RX_BITRATE], ratePolicy) == 0) {
2571 if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
2572 signalResult->rxBitrate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
2573 } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
2574 signalResult->rxBitrate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
2575 }
2576 }
2577 if (stats[NL80211_STA_INFO_TX_BITRATE] != NULL &&
2578 nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_TX_BITRATE], ratePolicy) == 0) {
2579 if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
2580 signalResult->txBitrate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
2581 } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
2582 signalResult->txBitrate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
2583 }
2584 }
2585 }
2586
SignalInfoHandler(struct nl_msg * msg,void * arg)2587 static int32_t SignalInfoHandler(struct nl_msg *msg, void *arg)
2588 {
2589 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
2590 struct nlattr *attr[NL80211_ATTR_MAX + 1];
2591 struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
2592 struct nla_policy statsPolicy[NL80211_STA_INFO_MAX + 1];
2593 struct SignalResult *signalResult = (struct SignalResult *)arg;
2594 statsPolicy[NL80211_STA_INFO_SIGNAL].type = NLA_S8;
2595 statsPolicy[NL80211_STA_INFO_RX_BYTES].type = NLA_U32;
2596 statsPolicy[NL80211_STA_INFO_TX_BYTES].type = NLA_U32;
2597 statsPolicy[NL80211_STA_INFO_RX_PACKETS].type = NLA_U32;
2598 statsPolicy[NL80211_STA_INFO_TX_PACKETS].type = NLA_U32;
2599 statsPolicy[NL80211_STA_INFO_TX_FAILED].type = NLA_U32;
2600 statsPolicy[NL80211_STA_INFO_NOISE].type = NLA_S32;
2601 statsPolicy[NL80211_STA_INFO_SNR].type = NLA_S32;
2602 statsPolicy[NL80211_STA_INFO_CNAHLOAD].type = NLA_S32;
2603 statsPolicy[NL80211_STA_INFO_UL_DELAY].type = NLA_S32;
2604
2605 nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
2606 if (!attr[NL80211_ATTR_STA_INFO]) {
2607 HILOG_ERROR(LOG_CORE, "%s: sta stats missing!", __FUNCTION__);
2608 return NL_SKIP;
2609 }
2610 if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, attr[NL80211_ATTR_STA_INFO], statsPolicy) < 0) {
2611 HILOG_ERROR(LOG_CORE, "%s: nla_parse_nested NL80211_ATTR_STA_INFO failed!", __FUNCTION__);
2612 return NL_SKIP;
2613 }
2614 if (stats[NL80211_STA_INFO_SIGNAL] != NULL) {
2615 signalResult->currentRssi = nla_get_s8(stats[NL80211_STA_INFO_SIGNAL]);
2616 }
2617 if (stats[NL80211_STA_INFO_TX_BYTES] != NULL) {
2618 signalResult->currentTxBytes = nla_get_u32(stats[NL80211_STA_INFO_TX_BYTES]);
2619 }
2620 if (stats[NL80211_STA_INFO_RX_BYTES] != NULL) {
2621 signalResult->currentRxBytes = nla_get_u32(stats[NL80211_STA_INFO_RX_BYTES]);
2622 }
2623 if (stats[NL80211_STA_INFO_TX_PACKETS] != NULL) {
2624 signalResult->currentTxPackets = nla_get_u32(stats[NL80211_STA_INFO_TX_PACKETS]);
2625 }
2626 if (stats[NL80211_STA_INFO_RX_PACKETS] != NULL) {
2627 signalResult->currentRxPackets = nla_get_u32(stats[NL80211_STA_INFO_RX_PACKETS]);
2628 }
2629 if (stats[NL80211_STA_INFO_TX_FAILED] != NULL) {
2630 signalResult->currentTxFailed = nla_get_u32(stats[NL80211_STA_INFO_TX_FAILED]);
2631 }
2632 FillSignalExt(stats, NL80211_STA_INFO_MAX + 1, signalResult);
2633 FillSignalRate(stats, NL80211_STA_INFO_MAX + 1, signalResult);
2634
2635 return NL_SKIP;
2636 }
2637
WifiGetSignalPollInfo(const char * ifName,struct SignalResult * signalResult)2638 int32_t WifiGetSignalPollInfo(const char *ifName, struct SignalResult *signalResult)
2639 {
2640 struct nl_msg *msg = NULL;
2641 uint32_t interfaceId;
2642 int32_t ret = RET_CODE_FAILURE;
2643 AssociatedInfo associatedInfo;
2644 (void)memset_s(&associatedInfo, sizeof(associatedInfo), 0, sizeof(associatedInfo));
2645
2646 if (ifName == NULL || signalResult == NULL) {
2647 HILOG_ERROR(LOG_CORE, "%s: param is NULL.", __FUNCTION__);
2648 return RET_CODE_FAILURE;
2649 }
2650 interfaceId = if_nametoindex(ifName);
2651 if (interfaceId == 0) {
2652 HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
2653 return RET_CODE_FAILURE;
2654 }
2655 if (WifiGetAssociatedInfo(ifName, &associatedInfo) != RET_CODE_SUCCESS) {
2656 HILOG_ERROR(LOG_CORE, "%s: WifiGetAssociatedInfo failed", __FUNCTION__);
2657 return RET_CODE_FAILURE;
2658 }
2659 signalResult->associatedFreq = associatedInfo.associatedFreq;
2660 msg = nlmsg_alloc();
2661 if (msg == NULL) {
2662 HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
2663 return RET_CODE_NOMEM;
2664 }
2665 do {
2666 if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_STATION, 0)) {
2667 HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
2668 break;
2669 }
2670 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, interfaceId) != RET_CODE_SUCCESS) {
2671 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId faile", __FUNCTION__);
2672 break;
2673 }
2674 if (nla_put(msg, NL80211_ATTR_MAC, ETH_ADDR_LEN, associatedInfo.associatedBssid) != RET_CODE_SUCCESS) {
2675 HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 interfaceId faile", __FUNCTION__);
2676 break;
2677 }
2678 ret = NetlinkSendCmdSync(msg, SignalInfoHandler, signalResult);
2679 if (ret != RET_CODE_SUCCESS) {
2680 HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
2681 }
2682 } while (0);
2683 nlmsg_free(msg);
2684 return ret;
2685 }
2686