• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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