• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <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/if_arp.h>
32 #include <linux/netlink.h>
33 #include <linux/nl80211.h>
34 #include <linux/wireless.h>
35 #include <linux/version.h>
36 
37 #include "../wifi_common_cmd.h"
38 #include "hilog/log.h"
39 #include "netlink_adapter.h"
40 
41 #define VENDOR_ID 0x001A11
42 
43 // vendor subcmd
44 #define WIFI_SUBCMD_SET_COUNTRY_CODE   0x100E
45 #define WIFI_SUBCMD_SET_RANDOM_MAC_OUI 0x100C
46 
47 #define WAITFORMUTEX  100000
48 #define WAITFORTHREAD 100000
49 #define RETRIES       30
50 
51 #define STR_WLAN0     "wlan0"
52 #define STR_WLAN1     "wlan1"
53 #define STR_P2P0      "p2p0"
54 #define STR_P2P0_X    "p2p0-"
55 #define NET_DEVICE_INFO_PATH "/sys/class/net"
56 
57 #define PRIMARY_ID_POWER_MODE   0x8bfd
58 #define SECONDARY_ID_POWER_MODE 0x101
59 #define SET_POWER_MODE_SLEEP     "pow_mode sleep"
60 #define SET_POWER_MODE_INIT      "pow_mode init"
61 #define SET_POWER_MODE_THIRD     "pow_mode third"
62 #define GET_POWER_MODE           "get_pow_mode"
63 
64 #define CMD_SET_CLOSE_GO_CAC      "SET_CLOSE_GO_CAC"
65 #define CMD_SET_CHANGE_GO_CHANNEL "CMD_SET_CHANGE_GO_CHANNEL"
66 #define CMD_SET_GO_DETECT_RADAR   "CMD_SET_GO_DETECT_RADAR"
67 #define CMD_SET_DYNAMIC_DBAC_MODE "SET_DYNAMIC_DBAC_MODE"
68 #define CMD_SET_P2P_SCENES        "CMD_SET_P2P_SCENES"
69 #define P2P_BUF_SIZE              64
70 #define MAX_PRIV_CMD_SIZE         4096
71 #define LOW_LITMIT_FREQ_2_4G      2400
72 #define HIGH_LIMIT_FREQ_2_4G      2500
73 #define LOW_LIMIT_FREQ_5G         5100
74 #define HIGH_LIMIT_FREQ_5G        5900
75 
BIT(uint8_t x)76 static inline uint32_t BIT(uint8_t x)
77 {
78     return 1U << x;
79 }
80 #define STA_DRV_DATA_TX_MCS BIT(0)
81 #define STA_DRV_DATA_RX_MCS BIT(1)
82 #define STA_DRV_DATA_TX_VHT_MCS BIT(2)
83 #define STA_DRV_DATA_RX_VHT_MCS BIT(3)
84 #define STA_DRV_DATA_TX_VHT_NSS BIT(4)
85 #define STA_DRV_DATA_RX_VHT_NSS BIT(5)
86 #define STA_DRV_DATA_TX_SHORT_GI BIT(6)
87 #define STA_DRV_DATA_RX_SHORT_GI BIT(7)
88 #define STA_DRV_DATA_LAST_ACK_RSSI BIT(8)
89 
90 #define WLAN_IFACE_LENGTH 4
91 #define P2P_IFACE_LENGTH 3
92 #ifndef KERNEL_VERSION
93 #define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
94 #endif
95 
96 // vendor attr
97 enum AndrWifiAttr {
98 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
99     WIFI_ATTRIBUTE_INVALID,
100 #endif
101     WIFI_ATTRIBUTE_NUM_FEATURE_SET,
102     WIFI_ATTRIBUTE_FEATURE_SET,
103     WIFI_ATTRIBUTE_RANDOM_MAC_OUI,
104     WIFI_ATTRIBUTE_NODFS_SET,
105     WIFI_ATTRIBUTE_COUNTRY
106 };
107 
108 struct FamilyData {
109     const char *group;
110     int32_t id;
111 };
112 
113 struct WifiHalInfo {
114     struct nl_sock *cmdSock;
115     struct nl_sock *eventSock;
116     int32_t familyId;
117 
118     // thread controller info
119     pthread_t thread;
120     enum ThreadStatus status;
121     pthread_mutex_t mutex;
122 };
123 
124 typedef struct {
125     void *buf;
126     uint16_t length;
127     uint16_t flags;
128 } DataPoint;
129 
130 union HwprivReqData {
131     char name[IFNAMSIZ];
132     int32_t mode;
133     DataPoint point;
134 };
135 
136 typedef struct {
137     char interfaceName[IFNAMSIZ];
138     union HwprivReqData data;
139 } HwprivIoctlData;
140 
141 typedef struct {
142 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
143     uint8_t *buf;
144     uint32_t size;
145     uint32_t len;
146 #else
147     uint32_t size;
148     uint32_t len;
149     uint8_t *buf;
150 #endif
151 } WifiPrivCmd;
152 
153 static struct WifiHalInfo g_wifiHalInfo = {0};
154 
OpenNetlinkSocket(void)155 static struct nl_sock *OpenNetlinkSocket(void)
156 {
157     struct nl_sock *sock = NULL;
158 
159     sock = nl_socket_alloc();
160     if (sock == NULL) {
161         HILOG_ERROR(LOG_CORE, "%s: fail to alloc socket", __FUNCTION__);
162         return NULL;
163     }
164 
165     if (nl_connect(sock, NETLINK_GENERIC) != 0) {
166         HILOG_ERROR(LOG_CORE, "%s: fail to connect socket", __FUNCTION__);
167         nl_socket_free(sock);
168         return NULL;
169     }
170     return sock;
171 }
172 
CloseNetlinkSocket(struct nl_sock * sock)173 static void CloseNetlinkSocket(struct nl_sock *sock)
174 {
175     if (sock != NULL) {
176         nl_socket_free(sock);
177     }
178 }
179 
ConnectCmdSocket(void)180 static int32_t ConnectCmdSocket(void)
181 {
182     g_wifiHalInfo.cmdSock = OpenNetlinkSocket();
183     if (g_wifiHalInfo.cmdSock == NULL) {
184         HILOG_ERROR(LOG_CORE, "%s: fail to open cmd socket", __FUNCTION__);
185         return RET_CODE_FAILURE;
186     }
187 
188     nl_socket_disable_seq_check(g_wifiHalInfo.cmdSock);
189     // send find familyId result to Controller
190     g_wifiHalInfo.familyId = genl_ctrl_resolve(g_wifiHalInfo.cmdSock, NL80211_GENL_NAME);
191     if (g_wifiHalInfo.familyId < 0) {
192         HILOG_ERROR(LOG_CORE, "%s: fail to resolve family", __FUNCTION__);
193         CloseNetlinkSocket(g_wifiHalInfo.cmdSock);
194         g_wifiHalInfo.cmdSock = NULL;
195         return RET_CODE_FAILURE;
196     }
197     HILOG_INFO(LOG_CORE, "%s: family id: %d", __FUNCTION__, g_wifiHalInfo.familyId);
198     return RET_CODE_SUCCESS;
199 }
200 
DisconnectCmdSocket(void)201 static void DisconnectCmdSocket(void)
202 {
203     CloseNetlinkSocket(g_wifiHalInfo.cmdSock);
204     g_wifiHalInfo.cmdSock = NULL;
205 }
206 
CmdSocketErrorHandler(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)207 static int32_t CmdSocketErrorHandler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
208 {
209     int32_t *ret = (int32_t *)arg;
210 
211     *ret = err->error;
212     return NL_SKIP;
213 }
214 
CmdSocketFinishHandler(struct nl_msg * msg,void * arg)215 static int32_t CmdSocketFinishHandler(struct nl_msg *msg, void *arg)
216 {
217     int32_t *ret = (int32_t *)arg;
218 
219     *ret = 0;
220     return NL_SKIP;
221 }
222 
CmdSocketAckHandler(struct nl_msg * msg,void * arg)223 static int32_t CmdSocketAckHandler(struct nl_msg *msg, void *arg)
224 {
225     int32_t *err = (int32_t *)arg;
226 
227     *err = 0;
228     return NL_STOP;
229 }
230 
NetlinkSetCallback(const RespHandler handler,int32_t * error,void * data)231 static struct nl_cb *NetlinkSetCallback(const RespHandler handler, int32_t *error, void *data)
232 {
233     struct nl_cb *cb = NULL;
234 
235     cb = nl_cb_alloc(NL_CB_DEFAULT);
236     if (cb == NULL) {
237         HILOG_ERROR(LOG_CORE, "%s: nl_cb_alloc failed", __FUNCTION__);
238         return NULL;
239     }
240     nl_cb_err(cb, NL_CB_CUSTOM, CmdSocketErrorHandler, error);
241     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, CmdSocketFinishHandler, error);
242     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, CmdSocketAckHandler, error);
243     if (handler != NULL) {
244         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handler, data);
245     }
246     return cb;
247 }
248 
PthreadMutexLock(void)249 static int32_t PthreadMutexLock(void)
250 {
251     int32_t rc;
252     int32_t count = 0;
253 
254     while ((rc = pthread_mutex_trylock(&g_wifiHalInfo.mutex)) == EBUSY) {
255         if (count < RETRIES) {
256             HILOG_ERROR(LOG_CORE, "%s: pthread b trylock", __FUNCTION__);
257             count++;
258             usleep(WAITFORMUTEX);
259         } else {
260             HILOG_ERROR(LOG_CORE, "%s: pthread trylock timeout", __FUNCTION__);
261             return RET_CODE_SUCCESS;
262         }
263     }
264     return rc;
265 }
266 
NetlinkSendCmdSync(struct nl_msg * msg,const RespHandler handler,void * data)267 int32_t NetlinkSendCmdSync(struct nl_msg *msg, const RespHandler handler, void *data)
268 {
269     int32_t rc;
270     int32_t error;
271     struct nl_cb *cb = NULL;
272 
273     if (g_wifiHalInfo.cmdSock == NULL) {
274         HILOG_ERROR(LOG_CORE, "%s: sock is null", __FUNCTION__);
275         return RET_CODE_INVALID_PARAM;
276     }
277 
278     if (PthreadMutexLock() != RET_CODE_SUCCESS) {
279         HILOG_ERROR(LOG_CORE, "%s: pthread trylock failed", __FUNCTION__);
280         return RET_CODE_FAILURE;
281     }
282 
283     do {
284         rc = nl_send_auto(g_wifiHalInfo.cmdSock, msg);
285         if (rc < 0) {
286             HILOG_ERROR(LOG_CORE, "%s: nl_send_auto failed", __FUNCTION__);
287             break;
288         }
289         cb = NetlinkSetCallback(handler, &error, data);
290         if (cb == NULL) {
291             HILOG_ERROR(LOG_CORE, "%s: nl_cb_alloc failed", __FUNCTION__);
292             rc = RET_CODE_FAILURE;
293             break;
294         }
295         /* wait for reply */
296         error = 1;
297         while (error > 0) {
298             rc = nl_recvmsgs(g_wifiHalInfo.cmdSock, cb);
299             if (rc < 0) {
300                 HILOG_ERROR(LOG_CORE, "%s: nl_recvmsgs failed: rc = %d, errno = %d, (%s)", __FUNCTION__, rc, errno,
301                     strerror(errno));
302             }
303         }
304         if (error == -NLE_MSGTYPE_NOSUPPORT) {
305             HILOG_ERROR(LOG_CORE, "%s: Netlink message type is not supported", __FUNCTION__);
306             rc = RET_CODE_NOT_SUPPORT;
307         }
308         nl_cb_put(cb);
309     } while (0);
310 
311     pthread_mutex_unlock(&g_wifiHalInfo.mutex);
312     return rc;
313 }
314 
ParseFamilyId(struct nlattr * attr,struct FamilyData * familyData)315 static void ParseFamilyId(struct nlattr *attr, struct FamilyData *familyData)
316 {
317     struct nlattr *tmp = NULL;
318     void *data = NULL;
319     int32_t len;
320     int32_t i;
321 
322     nla_for_each_nested(tmp, attr, i) {
323         struct nlattr *attrMcastGrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
324         data = nla_data(tmp);
325         len = nla_len(tmp);
326         nla_parse(attrMcastGrp, CTRL_ATTR_MCAST_GRP_MAX, data, len, NULL);
327         data = nla_data(attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME]);
328         len = nla_len(attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME]);
329         if (attrMcastGrp[CTRL_ATTR_MCAST_GRP_NAME] && attrMcastGrp[CTRL_ATTR_MCAST_GRP_ID] &&
330             strncmp((char *)data, familyData->group, len) == 0) {
331             familyData->id = (int32_t)nla_get_u32(attrMcastGrp[CTRL_ATTR_MCAST_GRP_ID]);
332         }
333     }
334 }
335 
FamilyIdHandler(struct nl_msg * msg,void * arg)336 static int32_t FamilyIdHandler(struct nl_msg *msg, void *arg)
337 {
338     struct FamilyData *familyData = (struct FamilyData *)arg;
339     struct genlmsghdr *hdr = NULL;
340     struct nlattr *attr[CTRL_ATTR_MAX + 1];
341     void *data = NULL;
342     int32_t len;
343 
344     hdr = nlmsg_data(nlmsg_hdr(msg));
345     if (hdr == NULL) {
346         HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
347         return NL_SKIP;
348     }
349 
350     data = genlmsg_attrdata(hdr, 0);
351     len = genlmsg_attrlen(hdr, 0);
352     nla_parse(attr, CTRL_ATTR_MAX, data, len, NULL);
353     if (!attr[CTRL_ATTR_MCAST_GROUPS]) {
354         return NL_SKIP;
355     }
356 
357     ParseFamilyId(attr[CTRL_ATTR_MCAST_GROUPS], familyData);
358 
359     return NL_SKIP;
360 }
361 
GetMulticastId(const char * family,const char * group)362 static int32_t GetMulticastId(const char *family, const char *group)
363 {
364     struct nl_msg *msg = NULL;
365     int32_t ret;
366     static struct FamilyData familyData;
367     int32_t familyId = genl_ctrl_resolve(g_wifiHalInfo.cmdSock, "nlctrl");
368 
369     familyData.group = group;
370     familyData.id = -ENOENT;
371 
372     msg = nlmsg_alloc();
373     if (msg == NULL) {
374         HILOG_ERROR(LOG_CORE, "%s: nlmsg_alloc failed", __FUNCTION__);
375         return RET_CODE_NOMEM;
376     }
377 
378     if (!genlmsg_put(msg, 0, 0, familyId, 0, 0, CTRL_CMD_GETFAMILY, 0) ||
379         nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, family)) {
380         HILOG_ERROR(LOG_CORE, "%s: put msg failed", __FUNCTION__);
381         nlmsg_free(msg);
382         return RET_CODE_FAILURE;
383     }
384 
385     ret = NetlinkSendCmdSync(msg, FamilyIdHandler, &familyData);
386     if (ret == 0) {
387         ret = familyData.id;
388     }
389     nlmsg_free(msg);
390     return ret;
391 }
392 
NlsockAddMembership(struct nl_sock * sock,const char * group)393 static int32_t NlsockAddMembership(struct nl_sock *sock, const char *group)
394 {
395     int32_t id;
396     int32_t ret;
397 
398     id = GetMulticastId(NL80211_GENL_NAME, group);
399     if (id < 0) {
400         HILOG_ERROR(LOG_CORE, "%s: get multicast id failed", __FUNCTION__);
401         return id;
402     }
403 
404     ret = nl_socket_add_membership(sock, id);
405     if (ret < 0) {
406         HILOG_ERROR(LOG_CORE, "%s: Could not add multicast membership for %d: %d (%s)", __FUNCTION__, id, ret,
407             strerror(-ret));
408         return RET_CODE_FAILURE;
409     }
410 
411     return RET_CODE_SUCCESS;
412 }
413 
ConnectEventSocket(void)414 static int32_t ConnectEventSocket(void)
415 {
416     int32_t ret;
417 
418     g_wifiHalInfo.eventSock = OpenNetlinkSocket();
419     if (g_wifiHalInfo.eventSock == NULL) {
420         HILOG_ERROR(LOG_CORE, "%s: fail to open event socket", __FUNCTION__);
421         return RET_CODE_FAILURE;
422     }
423     do {
424         ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_SCAN);
425         if (ret != RET_CODE_SUCCESS) {
426             HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for scan event failed.", __FUNCTION__);
427             break;
428         }
429         ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_MLME);
430         if (ret != RET_CODE_SUCCESS) {
431             HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for mlme failed.", __FUNCTION__);
432             break;
433         }
434         ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_REG);
435         if (ret != RET_CODE_SUCCESS) {
436             HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for regulatory failed.", __FUNCTION__);
437             break;
438         }
439         ret = NlsockAddMembership(g_wifiHalInfo.eventSock, NL80211_MULTICAST_GROUP_VENDOR);
440         if (ret != RET_CODE_SUCCESS) {
441             HILOG_ERROR(LOG_CORE, "%s: nlsock add membership for vendor failed.", __FUNCTION__);
442             break;
443         }
444         return RET_CODE_SUCCESS;
445     } while (0);
446     CloseNetlinkSocket(g_wifiHalInfo.eventSock);
447     g_wifiHalInfo.eventSock = NULL;
448     return ret;
449 }
450 
DisconnectEventSocket(void)451 void DisconnectEventSocket(void)
452 {
453     CloseNetlinkSocket(g_wifiHalInfo.eventSock);
454     g_wifiHalInfo.eventSock = NULL;
455 }
456 
WifiMsgRegisterEventListener(void)457 static int32_t WifiMsgRegisterEventListener(void)
458 {
459     int32_t rc;
460     int32_t count = 0;
461     struct WifiThreadParam threadParam;
462 
463     threadParam.eventSock = g_wifiHalInfo.eventSock;
464     threadParam.familyId = g_wifiHalInfo.familyId;
465     threadParam.status = &g_wifiHalInfo.status;
466 
467     g_wifiHalInfo.status = THREAD_STARTING;
468     rc = pthread_create(&(g_wifiHalInfo.thread), NULL, EventThread, &threadParam);
469     if (rc != 0) {
470         HILOG_ERROR(LOG_CORE, "%s: failed create event thread", __FUNCTION__);
471         g_wifiHalInfo.status = THREAD_STOP;
472         return RET_CODE_FAILURE;
473     }
474 
475     // waiting for thread start running
476     while (g_wifiHalInfo.status != THREAD_RUN) {
477         HILOG_INFO(LOG_CORE, "%s: waiting for thread start running.", __FUNCTION__);
478         if (count < RETRIES) {
479             count++;
480             usleep(WAITFORTHREAD);
481         } else {
482             HILOG_ERROR(LOG_CORE, "%s: warit for thread running timeout", __FUNCTION__);
483             if (g_wifiHalInfo.status != THREAD_STOP) {
484                 g_wifiHalInfo.status = THREAD_STOP;
485                 pthread_join(g_wifiHalInfo.thread, NULL);
486             }
487             return RET_CODE_FAILURE;
488         }
489     }
490 
491     return RET_CODE_SUCCESS;
492 }
493 
WifiMsgUnregisterEventListener(void)494 static void WifiMsgUnregisterEventListener(void)
495 {
496     g_wifiHalInfo.status = THREAD_STOPPING;
497     pthread_join(g_wifiHalInfo.thread, NULL);
498 }
499 
WifiDriverClientInit(void)500 int32_t WifiDriverClientInit(void)
501 {
502     if (g_wifiHalInfo.cmdSock != NULL) {
503         HILOG_ERROR(LOG_CORE, "%s: already create cmd socket", __FUNCTION__);
504         return RET_CODE_FAILURE;
505     }
506 
507     if (pthread_mutex_init(&g_wifiHalInfo.mutex, NULL) != RET_CODE_SUCCESS) {
508         HILOG_ERROR(LOG_CORE, "%s: init mutex failed.", __FUNCTION__);
509         return RET_CODE_FAILURE;
510     }
511 
512     if (ConnectCmdSocket() != RET_CODE_SUCCESS) {
513         HILOG_ERROR(LOG_CORE, "%s: connect cmd socket failed.", __FUNCTION__);
514         goto err_cmd;
515     }
516 
517     if (ConnectEventSocket() != RET_CODE_SUCCESS) {
518         HILOG_ERROR(LOG_CORE, "%s: connect event socket failed", __FUNCTION__);
519         goto err_event;
520     }
521 
522     if (WifiMsgRegisterEventListener() != RET_CODE_SUCCESS) {
523         HILOG_ERROR(LOG_CORE, "%s: WifiMsgRegisterEventListener failed", __FUNCTION__);
524         goto err_reg;
525     }
526 
527     return RET_CODE_SUCCESS;
528 err_reg:
529     DisconnectEventSocket();
530 err_event:
531     DisconnectCmdSocket();
532 err_cmd:
533     pthread_mutex_destroy(&g_wifiHalInfo.mutex);
534     return RET_CODE_FAILURE;
535 }
536 
WifiDriverClientDeinit(void)537 void WifiDriverClientDeinit(void)
538 {
539     WifiMsgUnregisterEventListener();
540 
541     if (g_wifiHalInfo.cmdSock == NULL) {
542         HILOG_ERROR(LOG_CORE, "%s: cmd socket not inited", __FUNCTION__);
543     } else {
544         DisconnectCmdSocket();
545     }
546 
547     if (g_wifiHalInfo.eventSock == NULL) {
548         HILOG_ERROR(LOG_CORE, "%s: event socket not inited", __FUNCTION__);
549     } else {
550         DisconnectEventSocket();
551     }
552 
553     pthread_mutex_destroy(&g_wifiHalInfo.mutex);
554 }
555 
ParserIsSupportCombo(struct nl_msg * msg,void * arg)556 static int32_t ParserIsSupportCombo(struct nl_msg *msg, void *arg)
557 {
558     struct nlattr *attr[NL80211_ATTR_MAX + 1];
559     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
560     struct nlattr *nlComb = NULL;
561     struct nlattr *attrComb[NUM_NL80211_IFACE_COMB];
562     uint8_t *isSupportCombo = (uint8_t *)arg;
563     int32_t ret, i;
564     static struct nla_policy ifaceCombPolicy[NUM_NL80211_IFACE_COMB];
565     ifaceCombPolicy[NL80211_IFACE_COMB_LIMITS].type = NLA_NESTED;
566     ifaceCombPolicy[NL80211_IFACE_COMB_MAXNUM].type = NLA_U32;
567     ifaceCombPolicy[NL80211_IFACE_COMB_NUM_CHANNELS].type = NLA_U32;
568 
569     // parse all enum nl80211_attrs type
570     ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
571     if (ret != 0) {
572         HILOG_ERROR(LOG_CORE, "%s: nla_parse tb failed", __FUNCTION__);
573         return NL_SKIP;
574     }
575 
576     if (attr[NL80211_ATTR_INTERFACE_COMBINATIONS] != NULL) {
577         nla_for_each_nested(nlComb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], i)
578         {
579             // parse all enum nl80211_if_combination_attrs type
580             ret = nla_parse_nested(attrComb, MAX_NL80211_IFACE_COMB, nlComb, ifaceCombPolicy);
581             if (ret != 0) {
582                 HILOG_ERROR(LOG_CORE, "%s: nla_parse_nested nlComb failed", __FUNCTION__);
583                 return NL_SKIP;
584             }
585             if (!attrComb[NL80211_IFACE_COMB_LIMITS] || !attrComb[NL80211_IFACE_COMB_MAXNUM] ||
586                 !attrComb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
587                 *isSupportCombo = 0;
588             } else {
589                 *isSupportCombo = 1;
590             }
591         }
592     }
593     HILOG_INFO(LOG_CORE, "%s: isSupportCombo is %hhu", __FUNCTION__, *isSupportCombo);
594     return NL_SKIP;
595 }
596 
ParserSupportComboInfo(struct nl_msg * msg,void * arg)597 static int32_t ParserSupportComboInfo(struct nl_msg *msg, void *arg)
598 {
599     (void)arg;
600     struct nlattr *attr[NL80211_ATTR_MAX + 1];
601     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
602     struct nlattr *nlComb = NULL, *nlLimit = NULL, *nlMode = NULL;
603     struct nlattr *attrComb[NUM_NL80211_IFACE_COMB];
604     struct nlattr *attrLimit[NUM_NL80211_IFACE_LIMIT];
605     int32_t ret, i, j, k, type;
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     static struct nla_policy ifaceLimitPolicy[NUM_NL80211_IFACE_LIMIT];
612     ifaceLimitPolicy[NL80211_IFACE_LIMIT_MAX].type = NLA_U32;
613     ifaceLimitPolicy[NL80211_IFACE_LIMIT_TYPES].type = NLA_NESTED;
614 
615     ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
616     if (ret != 0) {
617         HILOG_ERROR(LOG_CORE, "%s: nla_parse tb failed", __FUNCTION__);
618         return NL_SKIP;
619     }
620 
621     if (attr[NL80211_ATTR_INTERFACE_COMBINATIONS] != NULL) {
622         // get each ieee80211_iface_combination
623         nla_for_each_nested(nlComb, attr[NL80211_ATTR_INTERFACE_COMBINATIONS], i)
624         {
625             ret = nla_parse_nested(attrComb, MAX_NL80211_IFACE_COMB, nlComb, ifaceCombPolicy);
626             if (ret != 0) {
627                 HILOG_ERROR(LOG_CORE, "%s: nla_parse_nested nlComb failed", __FUNCTION__);
628                 return NL_SKIP;
629             }
630             if (!attrComb[NL80211_IFACE_COMB_LIMITS] || !attrComb[NL80211_IFACE_COMB_MAXNUM] ||
631                 !attrComb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
632                 return RET_CODE_NOT_SUPPORT;
633             }
634             // parse each ieee80211_iface_limit
635             nla_for_each_nested(nlLimit, attrComb[NL80211_IFACE_COMB_LIMITS], j)
636             {
637                 ret = nla_parse_nested(attrLimit, MAX_NL80211_IFACE_LIMIT, nlLimit, ifaceLimitPolicy);
638                 if (ret || !attrLimit[NL80211_IFACE_LIMIT_TYPES])
639                     return RET_CODE_NOT_SUPPORT; /* broken combination */
640                 // parse each ieee80211_iface_limit's types
641                 nla_for_each_nested(nlMode, attrLimit[NL80211_IFACE_LIMIT_TYPES], k)
642                 {
643                     type = nla_type(nlMode);
644                     if (type > WIFI_IFTYPE_UNSPECIFIED && type < WIFI_IFTYPE_MAX) {
645                         HILOG_INFO(LOG_CORE, "%s: mode: %d", __FUNCTION__, type);
646                     }
647                 }
648                 HILOG_INFO(LOG_CORE, "%s: has parse a attrLimit", __FUNCTION__);
649             }
650         }
651     }
652     return NL_SKIP;
653 }
654 
GetWiphyBands(struct genlmsghdr * hdr)655 static struct nlattr *GetWiphyBands(struct genlmsghdr *hdr)
656 {
657     struct nlattr *attrMsg[NL80211_ATTR_MAX + 1];
658     void *data = genlmsg_attrdata(hdr, 0);
659     int32_t len = genlmsg_attrlen(hdr, 0);
660     nla_parse(attrMsg, NL80211_ATTR_MAX, data, len, NULL);
661     if (!attrMsg[NL80211_ATTR_WIPHY_BANDS]) {
662         HILOG_ERROR(LOG_CORE, "%s: no wiphy bands", __FUNCTION__);
663     }
664     return attrMsg[NL80211_ATTR_WIPHY_BANDS];
665 }
666 
GetCenterFreq(struct nlattr * bands,struct FreqInfoResult * result)667 static void GetCenterFreq(struct nlattr *bands, struct FreqInfoResult *result)
668 {
669     struct nlattr *attrFreq[NL80211_FREQUENCY_ATTR_MAX + 1];
670     struct nlattr *nlFreq = NULL;
671     void *data = NULL;
672     int32_t len;
673     int32_t i;
674     uint32_t freq;
675     static struct nla_policy freqPolicy[NL80211_FREQUENCY_ATTR_MAX + 1];
676     freqPolicy[NL80211_FREQUENCY_ATTR_FREQ].type = NLA_U32;
677     freqPolicy[NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = NLA_U32;
678 
679     // get each ieee80211_channel
680     nla_for_each_nested(nlFreq, bands, i)
681     {
682         data = nla_data(nlFreq);
683         len = nla_len(nlFreq);
684         nla_parse(attrFreq, NL80211_FREQUENCY_ATTR_MAX, data, len, freqPolicy);
685         // get center freq
686         if (attrFreq[NL80211_FREQUENCY_ATTR_FREQ] == NULL) {
687             continue;
688         }
689         freq = nla_get_u32(attrFreq[NL80211_FREQUENCY_ATTR_FREQ]);
690         switch (result->band) {
691             case NL80211_BAND_2GHZ:
692                 if (attrFreq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]) {
693                     if (freq > LOW_LITMIT_FREQ_2_4G && freq < HIGH_LIMIT_FREQ_2_4G) {
694                         result->freqs[result->nums] = freq;
695                         result->txPower[result->nums] = nla_get_u32(attrFreq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER]);
696                         result->nums++;
697                     }
698                 }
699                 break;
700             case NL80211_BAND_5GHZ:
701                 if (freq > LOW_LIMIT_FREQ_5G && freq < HIGH_LIMIT_FREQ_5G) {
702                     result->freqs[result->nums] = freq;
703                     result->nums++;
704                 }
705                 break;
706             default:
707                 break;
708         }
709     }
710 }
711 
ParserValidFreq(struct nl_msg * msg,void * arg)712 static int32_t ParserValidFreq(struct nl_msg *msg, void *arg)
713 {
714     struct FreqInfoResult *result = (struct FreqInfoResult *)arg;
715     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
716     struct nlattr *attrWiphyBands = NULL;
717     struct nlattr *attrBand[NL80211_BAND_ATTR_MAX + 1];
718     struct nlattr *nlBand = NULL;
719     int32_t i;
720     void *data = NULL;
721     int32_t len;
722 
723     attrWiphyBands = GetWiphyBands(hdr);
724     if (attrWiphyBands == NULL) {
725         return NL_SKIP;
726     }
727 
728     // get each ieee80211_supported_band
729     nla_for_each_nested(nlBand, attrWiphyBands, i)
730     {
731         data = nla_data(nlBand);
732         len = nla_len(nlBand);
733         nla_parse(attrBand, NL80211_BAND_ATTR_MAX, data, len, NULL);
734         if (attrBand[NL80211_BAND_ATTR_FREQS] == NULL)
735             continue;
736         GetCenterFreq(attrBand[NL80211_BAND_ATTR_FREQS], result);
737     }
738     return NL_SKIP;
739 }
740 
IsWifiIface(const char * name)741 static bool IsWifiIface(const char *name)
742 {
743     if (strncmp(name, "wlan", WLAN_IFACE_LENGTH) != 0 && strncmp(name, "p2p", P2P_IFACE_LENGTH) != 0) {
744         /* not a wifi interface; ignore it */
745         return false;
746     } else {
747         return true;
748     }
749 }
750 
GetAllIfaceInfo(struct NetworkInfoResult * infoResult)751 static int32_t GetAllIfaceInfo(struct NetworkInfoResult *infoResult)
752 {
753     struct dirent *de;
754     DIR *dir = opendir(NET_DEVICE_INFO_PATH);
755     if (dir == NULL) {
756         return RET_CODE_FAILURE;
757     }
758     infoResult->nums = 0;
759     while ((de = readdir(dir))) {
760         if (de->d_name[0] == '.') {
761             continue;
762         }
763         if (IsWifiIface(de->d_name)) {
764             if (strncpy_s(infoResult->infos[infoResult->nums].name, IFNAMSIZ, de->d_name, sizeof(de->d_name)) != EOK) {
765                 HILOG_ERROR(LOG_CORE, "%s: strncpy_s infoResult->infos failed", __FUNCTION__);
766                 closedir(dir);
767                 return RET_CODE_FAILURE;
768             }
769             infoResult->nums++;
770         }
771     }
772     closedir(dir);
773     if (infoResult->nums == 0) {
774         return RET_CODE_NOT_AVAILABLE;
775     }
776     return RET_CODE_SUCCESS;
777 }
778 
GetUsableNetworkInfo(struct NetworkInfoResult * result)779 int32_t GetUsableNetworkInfo(struct NetworkInfoResult *result)
780 {
781     int32_t ret;
782     uint32_t i;
783 
784     ret = GetAllIfaceInfo(result);
785     if (ret != RET_CODE_SUCCESS) {
786         HILOG_ERROR(LOG_CORE, "%s: GetAllIfaceInfo failed", __FUNCTION__);
787         return ret;
788     }
789 
790     HILOG_INFO(LOG_CORE, "%s: wifi iface num %d", __FUNCTION__, result->nums);
791     for (i = 0; i < result->nums; ++i) {
792         ret = memset_s(result->infos[i].supportMode, sizeof(result->infos[i].supportMode), 0,
793             sizeof(result->infos[i].supportMode));
794         if (ret != EOK) {
795             HILOG_ERROR(LOG_CORE, "%s: memset_s esult->infos failed", __FUNCTION__);
796             return RET_CODE_FAILURE;
797         }
798         if (strncmp(result->infos[i].name, STR_WLAN0, strlen(STR_WLAN0)) == 0) {
799             result->infos[i].supportMode[WIFI_IFTYPE_STATION] = 1;
800             result->infos[i].supportMode[WIFI_IFTYPE_AP] = 1;
801         } else if (strncmp(result->infos[i].name, STR_WLAN1, strlen(STR_WLAN1)) == 0) {
802             result->infos[i].supportMode[WIFI_IFTYPE_STATION] = 1;
803         } else if (strncmp(result->infos[i].name, STR_P2P0, strlen(STR_P2P0)) == 0) {
804             result->infos[i].supportMode[WIFI_IFTYPE_P2P_DEVICE] = 1;
805         } else if (strncmp(result->infos[i].name, STR_P2P0_X, strlen(STR_P2P0_X)) == 0) {
806             result->infos[i].supportMode[WIFI_IFTYPE_P2P_CLIENT] = 1;
807             result->infos[i].supportMode[WIFI_IFTYPE_P2P_GO] = 1;
808         }
809     }
810     return RET_CODE_SUCCESS;
811 }
812 
IsSupportCombo(uint8_t * isSupportCombo)813 int32_t IsSupportCombo(uint8_t *isSupportCombo)
814 {
815     uint32_t ifaceId;
816     struct nl_msg *msg = NULL;
817     struct NetworkInfoResult networkInfo;
818     int32_t ret;
819 
820     ret = GetUsableNetworkInfo(&networkInfo);
821     if (ret != RET_CODE_SUCCESS) {
822         HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
823         return ret;
824     }
825 
826     ifaceId = if_nametoindex(networkInfo.infos[0].name);
827     if (ifaceId == 0) {
828         HILOG_ERROR(LOG_CORE, "%s: get iface id(%u) failed", __FUNCTION__, ifaceId);
829         return RET_CODE_FAILURE;
830     }
831 
832     msg = nlmsg_alloc();
833     if (msg == NULL) {
834         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
835         return RET_CODE_NOMEM;
836     }
837 
838     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
839     nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
840     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
841     ret = NetlinkSendCmdSync(msg, ParserIsSupportCombo, isSupportCombo);
842     if (ret != RET_CODE_SUCCESS) {
843         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
844     }
845     nlmsg_free(msg);
846     return ret;
847 }
848 
GetComboInfo(uint64_t * comboInfo,uint32_t size)849 int32_t GetComboInfo(uint64_t *comboInfo, uint32_t size)
850 {
851     (void)size;
852     uint32_t ifaceId;
853     struct nl_msg *msg = NULL;
854     struct NetworkInfoResult networkInfo;
855     int32_t ret;
856 
857     ret = GetUsableNetworkInfo(&networkInfo);
858     if (ret != RET_CODE_SUCCESS) {
859         HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
860         return ret;
861     }
862 
863     ifaceId = if_nametoindex(networkInfo.infos[0].name);
864     if (ifaceId == 0) {
865         HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
866         return RET_CODE_FAILURE;
867     }
868 
869     msg = nlmsg_alloc();
870     if (msg == NULL) {
871         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
872         return RET_CODE_NOMEM;
873     }
874     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
875     nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
876     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
877     ret = NetlinkSendCmdSync(msg, ParserSupportComboInfo, comboInfo);
878     if (ret != RET_CODE_SUCCESS) {
879         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
880     }
881     nlmsg_free(msg);
882     return ret;
883 }
884 
SetMacAddr(const char * ifName,unsigned char * mac,uint8_t len)885 int32_t SetMacAddr(const char *ifName, unsigned char *mac, uint8_t len)
886 {
887     int32_t fd;
888     int32_t ret;
889     struct ifreq req;
890 
891     if (memset_s(&req, sizeof(req), 0, sizeof(req)) != EOK) {
892         HILOG_ERROR(LOG_CORE, "%s: memset_s req failed", __FUNCTION__);
893         return RET_CODE_FAILURE;
894     }
895     fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
896     if (fd < 0) {
897         HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
898         return RET_CODE_FAILURE;
899     }
900     if (strncpy_s(req.ifr_name, IFNAMSIZ, ifName, strlen(ifName)) != EOK) {
901         HILOG_ERROR(LOG_CORE, "%s: strncpy_s fail", __FUNCTION__);
902         close(fd);
903         return RET_CODE_FAILURE;
904     }
905     req.ifr_addr.sa_family = ARPHRD_ETHER;
906     if (memcpy_s(req.ifr_hwaddr.sa_data, len, mac, len) != EOK) {
907         HILOG_ERROR(LOG_CORE, "%s: memcpy_s req.ifr_hwaddr.sa_data failed", __FUNCTION__);
908         close(fd);
909         return RET_CODE_FAILURE;
910     }
911     ret = ioctl(fd, SIOCSIFHWADDR, &req);
912     if (ret != RET_CODE_SUCCESS) {
913         HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
914         if (errno == EPERM) {
915             ret = RET_CODE_NOT_SUPPORT;
916         } else if (errno == EBUSY) {
917             ret = RET_CODE_DEVICE_BUSY;
918         } else {
919             ret = RET_CODE_FAILURE;
920         }
921     }
922     close(fd);
923     return ret;
924 }
925 
ParserChipId(struct nl_msg * msg,void * arg)926 static int32_t ParserChipId(struct nl_msg *msg, void *arg)
927 {
928     struct genlmsghdr *hdr = nlmsg_data(nlmsg_hdr(msg));
929     struct nlattr *attr[NL80211_ATTR_MAX + 1];
930     uint8_t *chipId = (uint8_t *)arg;
931     uint8_t *getChipId = NULL;
932     int32_t ret;
933 
934     ret = nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
935     if (ret != 0) {
936         HILOG_ERROR(LOG_CORE, "%s: nla_parse failed", __FUNCTION__);
937         return NL_SKIP;
938     }
939 
940     if (attr[NL80211_ATTR_MAX]) {
941         getChipId = nla_data(attr[NL80211_ATTR_MAX]);
942         *chipId = *getChipId;
943     }
944 
945     return NL_SKIP;
946 }
947 
GetDevMacAddr(const char * ifName,int32_t type,uint8_t * mac,uint8_t len)948 int32_t GetDevMacAddr(const char *ifName, int32_t type, uint8_t *mac, uint8_t len)
949 {
950     (void)type;
951     int32_t fd, ret;
952     struct ifreq req;
953 
954     if (memset_s(&req, sizeof(req), 0, sizeof(req)) != EOK) {
955         HILOG_ERROR(LOG_CORE, "%s: memset_s req failed", __FUNCTION__);
956         return RET_CODE_FAILURE;
957     }
958     fd = socket(AF_INET, SOCK_DGRAM, 0);
959     if (fd < 0) {
960         HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
961         return RET_CODE_FAILURE;
962     }
963     req.ifr_addr.sa_family = AF_INET;
964     strncpy_s(req.ifr_name, IFNAMSIZ, ifName, strlen(ifName));
965     ret = ioctl(fd, SIOCGIFHWADDR, &req);
966     if (ret != 0) {
967         HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
968         close(fd);
969         return RET_CODE_FAILURE;
970     }
971     if (memcpy_s(mac, len, (unsigned char *)req.ifr_hwaddr.sa_data, len) != EOK) {
972         HILOG_ERROR(LOG_CORE, "%s: memcpy_s mac failed", __FUNCTION__);
973         ret = RET_CODE_FAILURE;
974     }
975     close(fd);
976     return ret;
977 }
978 
GetValidFreqByBand(const char * ifName,int32_t band,struct FreqInfoResult * result,uint32_t size)979 int32_t GetValidFreqByBand(const char *ifName, int32_t band, struct FreqInfoResult *result, uint32_t size)
980 {
981     uint32_t ifaceId;
982     struct nl_msg *msg = NULL;
983     int32_t ret;
984 
985     if (result == NULL || result->freqs == NULL || result->txPower == NULL) {
986         HILOG_ERROR(LOG_CORE, "%s:  Invalid input parameter", __FUNCTION__);
987         return RET_CODE_INVALID_PARAM;
988     }
989 
990     if (band >= IEEE80211_NUM_BANDS) {
991         HILOG_ERROR(LOG_CORE, "%s:  Invalid input parameter, band = %d", __FUNCTION__, band);
992         return RET_CODE_INVALID_PARAM;
993     }
994 
995     ifaceId = if_nametoindex(ifName);
996     if (ifaceId == 0) {
997         HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
998         return RET_CODE_INVALID_PARAM;
999     }
1000 
1001     msg = nlmsg_alloc();
1002     if (msg == NULL) {
1003         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1004         return RET_CODE_NOMEM;
1005     }
1006 
1007     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
1008     nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
1009     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1010     ret = memset_s(result->freqs, size * sizeof(uint32_t), 0, size * sizeof(uint32_t));
1011     if (ret != EOK) {
1012         HILOG_ERROR(LOG_CORE, "%s: memset_s result->freqs  failed", __FUNCTION__);
1013         nlmsg_free(msg);
1014         return RET_CODE_FAILURE;
1015     }
1016     result->nums = 0;
1017     result->band = band;
1018     ret = NetlinkSendCmdSync(msg, ParserValidFreq, result);
1019     if (ret != RET_CODE_SUCCESS) {
1020         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1021     }
1022     nlmsg_free(msg);
1023     return ret;
1024 }
1025 
SetTxPower(const char * ifName,int32_t power)1026 int32_t SetTxPower(const char *ifName, int32_t power)
1027 {
1028     uint32_t ifaceId;
1029     struct nl_msg *msg = NULL;
1030     int32_t ret;
1031 
1032     ifaceId = if_nametoindex(ifName);
1033     if (ifaceId == 0) {
1034         HILOG_ERROR(LOG_CORE, "%s: get iface id(%d) failed", __FUNCTION__, ifaceId);
1035         return RET_CODE_INVALID_PARAM;
1036     }
1037 
1038     msg = nlmsg_alloc();
1039     if (msg == NULL) {
1040         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1041         return RET_CODE_NOMEM;
1042     }
1043 
1044     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_SET_WIPHY, 0);
1045     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1046     nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, NL80211_TX_POWER_LIMITED);
1047     nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, 100 * power);
1048     ret = NetlinkSendCmdSync(msg, NULL, NULL);
1049     if (ret != RET_CODE_SUCCESS) {
1050         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1051     } else {
1052         HILOG_INFO(LOG_CORE, "%s: send end success", __FUNCTION__);
1053     }
1054     nlmsg_free(msg);
1055     return ret;
1056 }
1057 
GetAssociatedStas(const char * ifName,struct AssocStaInfoResult * result)1058 int32_t GetAssociatedStas(const char *ifName, struct AssocStaInfoResult *result)
1059 {
1060     (void)ifName;
1061     if (memset_s(result, sizeof(struct AssocStaInfoResult), 0, sizeof(struct AssocStaInfoResult)) != EOK) {
1062         HILOG_ERROR(LOG_CORE, "%s: memset_s result failed", __FUNCTION__);
1063         return RET_CODE_FAILURE;
1064     }
1065     return RET_CODE_SUCCESS;
1066 }
1067 
WifiSetCountryCode(const char * ifName,const char * code,uint32_t len)1068 int32_t WifiSetCountryCode(const char *ifName, const char *code, uint32_t len)
1069 {
1070     uint32_t ifaceId = if_nametoindex(ifName);
1071     struct nl_msg *msg = NULL;
1072     struct nlattr *data = NULL;
1073     int32_t ret;
1074 
1075     if (ifaceId == 0) {
1076         HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1077         return RET_CODE_FAILURE;
1078     }
1079 
1080     msg = nlmsg_alloc();
1081     if (msg == NULL) {
1082         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1083         return RET_CODE_NOMEM;
1084     }
1085 
1086     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_VENDOR, 0);
1087     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1088     nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, VENDOR_ID);
1089     nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, WIFI_SUBCMD_SET_COUNTRY_CODE);
1090     data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
1091     if (data == NULL) {
1092         HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1093         nlmsg_free(msg);
1094         return RET_CODE_FAILURE;
1095     }
1096     nla_put(msg, WIFI_ATTRIBUTE_COUNTRY, len, code);
1097     nla_nest_end(msg, data);
1098 
1099     ret = NetlinkSendCmdSync(msg, NULL, NULL);
1100     if (ret != RET_CODE_SUCCESS) {
1101         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1102     }
1103     nlmsg_free(msg);
1104     return ret;
1105 }
1106 
SetScanMacAddr(const char * ifName,uint8_t * scanMac,uint8_t len)1107 int32_t SetScanMacAddr(const char *ifName, uint8_t *scanMac, uint8_t len)
1108 {
1109     int32_t ret;
1110     uint32_t ifaceId = if_nametoindex(ifName);
1111     struct nl_msg *msg = nlmsg_alloc();
1112     struct nlattr *data = NULL;
1113 
1114     if (msg == NULL) {
1115         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1116         return RET_CODE_NOMEM;
1117     }
1118     if (ifaceId == 0) {
1119         HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1120         nlmsg_free(msg);
1121         return RET_CODE_FAILURE;
1122     }
1123     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_VENDOR, 0);
1124     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1125     nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, VENDOR_ID);
1126     nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, WIFI_SUBCMD_SET_RANDOM_MAC_OUI);
1127     data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
1128     if (data == NULL) {
1129         HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1130         nlmsg_free(msg);
1131         return RET_CODE_FAILURE;
1132     }
1133     nla_put(msg, WIFI_ATTRIBUTE_RANDOM_MAC_OUI, len, scanMac);
1134     nla_nest_end(msg, data);
1135     ret = NetlinkSendCmdSync(msg, NULL, NULL);
1136     if (ret != RET_CODE_SUCCESS) {
1137         HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1138     }
1139     nlmsg_free(msg);
1140     return ret;
1141 }
1142 
AcquireChipId(const char * ifName,uint8_t * chipId)1143 int32_t AcquireChipId(const char *ifName, uint8_t *chipId)
1144 {
1145     struct nl_msg *msg = NULL;
1146     uint32_t ifaceId;
1147     int32_t ret;
1148 
1149     if (ifName == NULL || chipId == NULL) {
1150         HILOG_ERROR(LOG_CORE, "%s params is NULL", __FUNCTION__);
1151         return RET_CODE_INVALID_PARAM;
1152     }
1153 
1154     ifaceId = if_nametoindex(ifName);
1155     if (ifaceId == 0) {
1156         HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1157         return RET_CODE_FAILURE;
1158     }
1159 
1160     msg = nlmsg_alloc();
1161     if (msg == NULL) {
1162         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1163         return RET_CODE_NOMEM;
1164     }
1165 
1166     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, NLM_F_DUMP, NL80211_CMD_GET_WIPHY, 0);
1167     nla_put_flag(msg, NL80211_ATTR_SPLIT_WIPHY_DUMP);
1168     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1169 
1170     ret = NetlinkSendCmdSync(msg, ParserChipId, chipId);
1171     if (ret != RET_CODE_SUCCESS) {
1172         HILOG_ERROR(LOG_CORE, "%s: NetlinkSendCmdSync failed.", __FUNCTION__);
1173     }
1174     nlmsg_free(msg);
1175     return ret;
1176 }
1177 
GetIfNamesByChipId(const uint8_t chipId,char ** ifNames,uint32_t * num)1178 int32_t GetIfNamesByChipId(const uint8_t chipId, char **ifNames, uint32_t *num)
1179 {
1180     if (ifNames == NULL || num == NULL) {
1181         HILOG_ERROR(LOG_CORE, "%s params is NULL", __FUNCTION__);
1182         return RET_CODE_INVALID_PARAM;
1183     }
1184 
1185     if (chipId >= MAX_WLAN_DEVICE) {
1186         HILOG_ERROR(LOG_CORE, "%s: chipId = %d", __FUNCTION__, chipId);
1187         return RET_CODE_INVALID_PARAM;
1188     }
1189     *num = 1;
1190     *ifNames = (char *)calloc(*num, IFNAMSIZ);
1191     if (*ifNames == NULL) {
1192         HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1193         return RET_CODE_FAILURE;
1194     }
1195     if (memcpy_s(*ifNames, IFNAMSIZ, "wlan0", IFNAMSIZ) != EOK) {
1196         HILOG_ERROR(LOG_CORE, "%s: memcpy failed", __FUNCTION__);
1197         free(*ifNames);
1198         *ifNames = NULL;
1199         return RET_CODE_FAILURE;
1200     }
1201     return RET_CODE_SUCCESS;
1202 }
1203 
SetResetDriver(const uint8_t chipId,const char * ifName)1204 int32_t SetResetDriver(const uint8_t chipId, const char *ifName)
1205 {
1206     (void)chipId;
1207     (void)ifName;
1208     return RET_CODE_SUCCESS;
1209 }
1210 
NetDeviceInfoHandler(struct nl_msg * msg,void * arg)1211 static int32_t NetDeviceInfoHandler(struct nl_msg *msg, void *arg)
1212 {
1213     struct NetDeviceInfo *info = (struct NetDeviceInfo *)arg;
1214     struct nlattr *attr[NL80211_ATTR_MAX + 1];
1215     struct genlmsghdr *hdr = NULL;
1216     void *data = NULL;
1217     int32_t len;
1218 
1219     hdr = nlmsg_data(nlmsg_hdr(msg));
1220     if (hdr == NULL) {
1221         HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
1222         return NL_SKIP;
1223     }
1224     data = genlmsg_attrdata(hdr, 0);
1225     len = genlmsg_attrlen(hdr, 0);
1226     nla_parse(attr, NL80211_ATTR_MAX, data, len, NULL);
1227     if (attr[NL80211_ATTR_IFTYPE]) {
1228         info->iftype = nla_get_u32(attr[NL80211_ATTR_IFTYPE]);
1229         HILOG_ERROR(LOG_CORE, "%s: %s iftype is %hhu", __FUNCTION__, info->ifName, info->iftype);
1230     }
1231     if (attr[NL80211_ATTR_MAC]) {
1232         if (memcpy_s(info->mac, ETH_ADDR_LEN, nla_data(attr[NL80211_ATTR_MAC]), ETH_ADDR_LEN) != EOK) {
1233             HILOG_ERROR(LOG_CORE, "%s: memcpy_s mac address fail", __FUNCTION__);
1234         }
1235     }
1236 
1237     return NL_SKIP;
1238 }
1239 
GetIftypeAndMac(struct NetDeviceInfo * info)1240 static int32_t GetIftypeAndMac(struct NetDeviceInfo *info)
1241 {
1242     struct nl_msg *msg = nlmsg_alloc();
1243     int32_t ret;
1244 
1245     if (msg == NULL) {
1246         HILOG_ERROR(LOG_CORE, "%s: nlmsg_alloc failed.", __FUNCTION__);
1247         return RET_CODE_FAILURE;
1248     }
1249 
1250     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_INTERFACE, 0);
1251     nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(info->ifName));
1252 
1253     ret = NetlinkSendCmdSync(msg, NetDeviceInfoHandler, info);
1254     if (ret != RET_CODE_SUCCESS) {
1255         HILOG_ERROR(LOG_CORE, "%s: NetlinkSendCmdSync failed.", __FUNCTION__);
1256     }
1257     nlmsg_free(msg);
1258     return ret;
1259 }
1260 
GetNetDeviceInfo(struct NetDeviceInfoResult * netDeviceInfoResult)1261 int32_t GetNetDeviceInfo(struct NetDeviceInfoResult *netDeviceInfoResult)
1262 {
1263     struct NetworkInfoResult networkInfo;
1264     uint32_t i;
1265     int32_t ret;
1266 
1267     ret = GetUsableNetworkInfo(&networkInfo);
1268     if (ret != RET_CODE_SUCCESS) {
1269         HILOG_ERROR(LOG_CORE, "%s: get network info failed", __FUNCTION__);
1270         return ret;
1271     }
1272 
1273     for (i = 0; i < networkInfo.nums && i < MAX_NETDEVICE_COUNT; i++) {
1274         if (memset_s(&netDeviceInfoResult->deviceInfos[i], sizeof(struct NetDeviceInfo), 0,
1275             sizeof(struct NetDeviceInfo)) != EOK) {
1276             HILOG_ERROR(LOG_CORE, "%s: memset_s fail", __FUNCTION__);
1277             return RET_CODE_FAILURE;
1278         }
1279         netDeviceInfoResult->deviceInfos[i].index = i + 1;
1280         if (strncpy_s(netDeviceInfoResult->deviceInfos[i].ifName, IFNAMSIZ,
1281             networkInfo.infos[i].name, IFNAMSIZ) != EOK) {
1282             HILOG_ERROR(LOG_CORE, "%s: strncpy_s fail", __FUNCTION__);
1283             return RET_CODE_FAILURE;
1284         }
1285         ret = GetIftypeAndMac(&netDeviceInfoResult->deviceInfos[i]);
1286         if (ret != RET_CODE_SUCCESS) {
1287             HILOG_ERROR(LOG_CORE, "%s: get iftype and mac failed", __FUNCTION__);
1288             return ret;
1289         }
1290     }
1291 
1292     return RET_CODE_SUCCESS;
1293 }
1294 
CmdScanPutMsg(struct nl_msg * msg,const WifiScan * scan)1295 static int32_t CmdScanPutMsg(struct nl_msg *msg, const WifiScan *scan)
1296 {
1297     struct nlattr *nest = NULL;
1298     int32_t i;
1299 
1300     if (scan->ssids) {
1301         nest = nla_nest_start(msg, NL80211_ATTR_SCAN_SSIDS);
1302         if (nest == NULL) {
1303             HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1304             return RET_CODE_FAILURE;
1305         }
1306         for (i = 0; i < scan->numSsids; i++) {
1307             nla_put(msg, i + 1, scan->ssids->ssidLen, scan->ssids->ssid);
1308         }
1309         nla_nest_end(msg, nest);
1310     }
1311 
1312     if (scan->freqs) {
1313         nest = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
1314         if (nest == NULL) {
1315             HILOG_ERROR(LOG_CORE, "%s: nla_nest_start failed", __FUNCTION__);
1316             return RET_CODE_FAILURE;
1317         }
1318         for (i = 0; i < scan->numFreqs; i++) {
1319             nla_put_u32(msg, i + 1, scan->freqs[i]);
1320         }
1321         nla_nest_end(msg, nest);
1322     }
1323 
1324     if (scan->extraIes) {
1325         nla_put(msg, NL80211_ATTR_IE, scan->extraIesLen, scan->extraIes);
1326     }
1327 
1328     if (scan->bssid) {
1329         nla_put(msg, NL80211_ATTR_MAC, ETH_ADDR_LEN, scan->bssid);
1330     }
1331 
1332     return RET_CODE_SUCCESS;
1333 }
1334 
WifiCmdScan(const char * ifName,WifiScan * scan)1335 int32_t WifiCmdScan(const char *ifName, WifiScan *scan)
1336 {
1337     uint32_t ifaceId = if_nametoindex(ifName);
1338     struct nl_msg *msg = NULL;
1339     int32_t ret;
1340 
1341     if (ifaceId == 0) {
1342         HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1343         return RET_CODE_FAILURE;
1344     }
1345 
1346     msg = nlmsg_alloc();
1347     if (msg == NULL) {
1348         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1349         return RET_CODE_NOMEM;
1350     }
1351 
1352     genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_TRIGGER_SCAN, 0);
1353     nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId);
1354     do {
1355         ret = CmdScanPutMsg(msg, scan);
1356         if (ret != RET_CODE_SUCCESS) {
1357             HILOG_ERROR(LOG_CORE, "%s: put msg failed", __FUNCTION__);
1358             break;
1359         }
1360         ret = NetlinkSendCmdSync(msg, NULL, NULL);
1361         if (ret != RET_CODE_SUCCESS) {
1362             HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1363         }
1364     } while (0);
1365     nlmsg_free(msg);
1366     return ret;
1367 }
1368 
ParsePowerMode(const char * buf,uint16_t len,uint8_t * mode)1369 static int32_t ParsePowerMode(const char *buf, uint16_t len, uint8_t *mode)
1370 {
1371     char *key[WIFI_POWER_MODE_NUM] = {"sleep\n", "third\n", "init\n"};
1372     char *str = "pow_mode = ";
1373     if (buf == NULL || mode == NULL) {
1374         return RET_CODE_INVALID_PARAM;
1375     }
1376     char *pos = strstr(buf, str);
1377     if (pos == NULL) {
1378         HILOG_ERROR(LOG_CORE, "%s: no power mode", __FUNCTION__);
1379         return RET_CODE_FAILURE;
1380     }
1381     pos += strlen(str);
1382     if (!strncmp(pos, key[WIFI_POWER_MODE_SLEEPING], strlen(key[WIFI_POWER_MODE_SLEEPING]))) {
1383         *mode = WIFI_POWER_MODE_SLEEPING;
1384     } else if (!strncmp(pos, key[WIFI_POWER_MODE_GENERAL], strlen(key[WIFI_POWER_MODE_GENERAL]))) {
1385         *mode = WIFI_POWER_MODE_GENERAL;
1386     } else if (!strncmp(pos, key[WIFI_POWER_MODE_THROUGH_WALL], strlen(key[WIFI_POWER_MODE_THROUGH_WALL]))) {
1387         *mode = WIFI_POWER_MODE_THROUGH_WALL;
1388     } else {
1389         HILOG_ERROR(LOG_CORE, "%s: no invalid power mode", __FUNCTION__);
1390         return RET_CODE_FAILURE;
1391     }
1392     return RET_CODE_SUCCESS;
1393 }
1394 
GetCurrentPowerMode(const char * ifName,uint8_t * mode)1395 int32_t GetCurrentPowerMode(const char *ifName, uint8_t *mode)
1396 {
1397     int32_t fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1398     int32_t ret;
1399     HwprivIoctlData ioctlData;
1400 
1401     (void)memset_s(&ioctlData, sizeof(ioctlData), 0, sizeof(ioctlData));
1402     if (fd < 0) {
1403         HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1404         return RET_CODE_FAILURE;
1405     }
1406     do {
1407         if (strcpy_s(ioctlData.interfaceName, IFNAMSIZ, ifName) != EOK) {
1408             HILOG_ERROR(LOG_CORE, "%s: strcpy_s failed", __FUNCTION__);
1409             ret = RET_CODE_FAILURE;
1410             break;
1411         }
1412         ioctlData.data.point.flags = SECONDARY_ID_POWER_MODE;
1413         ioctlData.data.point.length = strlen(GET_POWER_MODE) + 1;
1414         ioctlData.data.point.buf = calloc(ioctlData.data.point.length, sizeof(char));
1415         if (ioctlData.data.point.buf == NULL) {
1416             HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1417             ret = RET_CODE_NOMEM;
1418             break;
1419         }
1420         if (memcpy_s(ioctlData.data.point.buf, ioctlData.data.point.length,
1421             GET_POWER_MODE, strlen(GET_POWER_MODE)) != EOK) {
1422             HILOG_ERROR(LOG_CORE, "%s: memcpy_s failed", __FUNCTION__);
1423             ret = RET_CODE_FAILURE;
1424             break;
1425         }
1426         ret = ioctl(fd, PRIMARY_ID_POWER_MODE, &ioctlData);
1427         if (ret != RET_CODE_SUCCESS) {
1428             HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
1429             if (errno == EOPNOTSUPP) {
1430                 ret = RET_CODE_NOT_SUPPORT;
1431             } else {
1432                 ret = RET_CODE_FAILURE;
1433             }
1434             break;
1435         }
1436         ret = ParsePowerMode(ioctlData.data.point.buf, ioctlData.data.point.length, mode);
1437         if (ret != RET_CODE_SUCCESS) {
1438             HILOG_ERROR(LOG_CORE, "%s: ParsePowerMode failed", __FUNCTION__);
1439             break;
1440         }
1441     } while (0);
1442     if (ioctlData.data.point.buf != NULL) {
1443         free(ioctlData.data.point.buf);
1444         ioctlData.data.point.buf = NULL;
1445     }
1446     close(fd);
1447     return ret;
1448 }
1449 
FillHwprivIoctlData(HwprivIoctlData * ioctlData,uint8_t mode)1450 static int32_t FillHwprivIoctlData(HwprivIoctlData *ioctlData, uint8_t mode)
1451 {
1452     const char *strTable[WIFI_POWER_MODE_NUM] = {SET_POWER_MODE_SLEEP, SET_POWER_MODE_THIRD, SET_POWER_MODE_INIT};
1453     const char *modeStr = strTable[mode];
1454 
1455     ioctlData->data.point.length = strlen(strTable[mode]) + 1;
1456     ioctlData->data.point.buf = calloc(ioctlData->data.point.length, sizeof(char));
1457     if (ioctlData->data.point.buf == NULL) {
1458         HILOG_ERROR(LOG_CORE, "%s: calloc failed", __FUNCTION__);
1459         return RET_CODE_NOMEM;
1460     }
1461     ioctlData->data.point.flags = SECONDARY_ID_POWER_MODE;
1462     if (strncpy_s(ioctlData->data.point.buf, ioctlData->data.point.length, modeStr, strlen(modeStr)) != EOK) {
1463         HILOG_ERROR(LOG_CORE, "%s: strncpy_s failed", __FUNCTION__);
1464         free(ioctlData->data.point.buf);
1465         ioctlData->data.point.buf = NULL;
1466         return RET_CODE_FAILURE;
1467     }
1468 
1469     return RET_CODE_SUCCESS;
1470 }
1471 
SetPowerMode(const char * ifName,uint8_t mode)1472 int32_t SetPowerMode(const char *ifName, uint8_t mode)
1473 {
1474     int32_t fd;
1475     int32_t ret;
1476     HwprivIoctlData ioctlData;
1477 
1478     (void)memset_s(&ioctlData, sizeof(ioctlData), 0, sizeof(ioctlData));
1479     fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
1480     if (fd < 0) {
1481         HILOG_ERROR(LOG_CORE, "%s: open socket failed", __FUNCTION__);
1482         return RET_CODE_FAILURE;
1483     }
1484 
1485     do {
1486         if (strcpy_s(ioctlData.interfaceName, IFNAMSIZ, ifName) != EOK) {
1487             HILOG_ERROR(LOG_CORE, "%s: strcpy_s failed", __FUNCTION__);
1488             ret = RET_CODE_FAILURE;
1489             break;
1490         }
1491         ret = FillHwprivIoctlData(&ioctlData, mode);
1492         if (ret != RET_CODE_SUCCESS) {
1493             break;
1494         }
1495         ret = ioctl(fd, PRIMARY_ID_POWER_MODE, &ioctlData);
1496         if (ret != RET_CODE_SUCCESS) {
1497             HILOG_ERROR(LOG_CORE, "%s: ioctl failed, errno = %d, (%s)", __FUNCTION__, errno, strerror(errno));
1498             if (errno == EOPNOTSUPP) {
1499                 ret = RET_CODE_NOT_SUPPORT;
1500             } else {
1501                 ret = RET_CODE_FAILURE;
1502             }
1503         }
1504     } while (0);
1505 
1506     if (ioctlData.data.point.buf != NULL) {
1507         free(ioctlData.data.point.buf);
1508         ioctlData.data.point.buf = NULL;
1509     }
1510     close(fd);
1511     return ret;
1512 }
1513 
StartChannelMeas(const char * ifName,const struct MeasParam * measParam)1514 int32_t StartChannelMeas(const char *ifName, const struct MeasParam *measParam)
1515 {
1516     (void)ifName;
1517     (void)measParam;
1518     return RET_CODE_NOT_SUPPORT;
1519 }
1520 
GetChannelMeasResult(const char * ifName,struct MeasResult * measResult)1521 int32_t GetChannelMeasResult(const char *ifName, struct MeasResult *measResult)
1522 {
1523     (void)ifName;
1524     (void)measResult;
1525     return RET_CODE_NOT_SUPPORT;
1526 }
1527 
SendCommandToDriver(const char * cmd,uint32_t len,const char * ifName)1528 static int32_t SendCommandToDriver(const char *cmd, uint32_t len, const char *ifName)
1529 {
1530     struct ifreq ifr;
1531     WifiPrivCmd privCmd = {0};
1532     uint8_t buf[MAX_PRIV_CMD_SIZE] = {0};
1533     int32_t ret = RET_CODE_FAILURE;
1534 
1535     if (cmd == NULL) {
1536         HILOG_ERROR(LOG_CORE, "%{public}s: cmd is null", __FUNCTION__);
1537         return RET_CODE_INVALID_PARAM;
1538     }
1539     if (len > MAX_PRIV_CMD_SIZE) {
1540         HILOG_ERROR(LOG_CORE, "%{public}s: Size of command is too large", __FUNCTION__);
1541         return RET_CODE_INVALID_PARAM;
1542     }
1543     if (memset_s(&ifr, sizeof(ifr), 0, sizeof(ifr)) != EOK) {
1544         HILOG_ERROR(LOG_CORE, "%s: memset_s ifr failed", __FUNCTION__);
1545         return RET_CODE_FAILURE;
1546     }
1547     if (memcpy_s(buf, MAX_PRIV_CMD_SIZE, cmd, len) != EOK) {
1548         HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s error", __FUNCTION__);
1549         return RET_CODE_FAILURE;
1550     }
1551     privCmd.buf = buf;
1552     privCmd.size = sizeof(buf);
1553     privCmd.len = len;
1554     ifr.ifr_data = (void *)&privCmd;
1555     if (strcpy_s(ifr.ifr_name, IFNAMSIZ, ifName) != EOK) {
1556         HILOG_ERROR(LOG_CORE, "%s: strcpy_s error", __FUNCTION__);
1557         return RET_CODE_FAILURE;
1558     }
1559     int32_t sock = socket(AF_INET, SOCK_DGRAM, 0);
1560     if (sock < 0) {
1561         HILOG_ERROR(LOG_CORE, "%{public}s: socket failed, errno = %{public}d, (%{public}s)", __FUNCTION__, errno,
1562             strerror(errno));
1563         return ret;
1564     }
1565     do {
1566         ret = ioctl(sock, SIOCDEVPRIVATE + 1, &ifr);
1567         if (ret < 0) {
1568             HILOG_ERROR(LOG_CORE, "%{public}s: ioctl failed, errno = %{public}d, (%{public}s)", __FUNCTION__, errno,
1569                 strerror(errno));
1570             ret = (errno == EOPNOTSUPP) ? RET_CODE_NOT_SUPPORT : RET_CODE_FAILURE;
1571             break;
1572         }
1573         (void)memset_s((void *)cmd, len, 0, len);
1574         if (memcpy_s((void *)cmd, len, privCmd.buf, len - 1) != EOK) {
1575             HILOG_ERROR(LOG_CORE, "%{public}s: memcpy_s error", __FUNCTION__);
1576             ret = RET_CODE_FAILURE;
1577         }
1578     } while (0);
1579 
1580     close(sock);
1581     return ret;
1582 }
1583 
DisableNextCacOnce(const char * ifName)1584 static int32_t DisableNextCacOnce(const char *ifName)
1585 {
1586     char cmdBuf[P2P_BUF_SIZE] = {CMD_SET_CLOSE_GO_CAC};
1587 
1588     return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1589 }
1590 
SetGoChannel(const char * ifName,const int8_t * data,uint32_t len)1591 static int32_t SetGoChannel(const char *ifName, const int8_t *data, uint32_t len)
1592 {
1593     int32_t ret = RET_CODE_FAILURE;
1594     char cmdBuf[P2P_BUF_SIZE] = {0};
1595     uint32_t cmdLen;
1596 
1597     cmdLen = strlen(CMD_SET_CHANGE_GO_CHANNEL);
1598     if ((cmdLen + len) >= P2P_BUF_SIZE) {
1599         HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1600         return ret;
1601     }
1602     ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_CHANGE_GO_CHANNEL, *data);
1603     if (ret < RET_CODE_SUCCESS) {
1604         HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1605         return RET_CODE_FAILURE;
1606     }
1607     return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1608 }
1609 
SetGoDetectRadar(const char * ifName,const int8_t * data,uint32_t len)1610 static int32_t SetGoDetectRadar(const char *ifName, const int8_t *data, uint32_t len)
1611 {
1612     int32_t ret = RET_CODE_FAILURE;
1613     char cmdBuf[P2P_BUF_SIZE] = {0};
1614     uint32_t cmdLen;
1615 
1616     cmdLen = strlen(CMD_SET_GO_DETECT_RADAR);
1617     if ((cmdLen + len) >= P2P_BUF_SIZE) {
1618         HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1619         return ret;
1620     }
1621     ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_GO_DETECT_RADAR, *data);
1622     if (ret < RET_CODE_SUCCESS) {
1623         HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1624         return RET_CODE_FAILURE;
1625     }
1626     return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1627 }
1628 
SetP2pScenes(const char * ifName,const int8_t * data,uint32_t len)1629 static int32_t SetP2pScenes(const char *ifName, const int8_t *data, uint32_t len)
1630 {
1631     int32_t ret = RET_CODE_FAILURE;
1632     char cmdBuf[P2P_BUF_SIZE] = {0};
1633     uint32_t cmdLen;
1634 
1635     cmdLen = strlen(CMD_SET_P2P_SCENES);
1636     if ((cmdLen + len) >= P2P_BUF_SIZE) {
1637         HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1638         return ret;
1639     }
1640     ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_P2P_SCENES, *data);
1641     if (ret < RET_CODE_SUCCESS) {
1642         HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1643         return RET_CODE_FAILURE;
1644     }
1645     return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1646 }
1647 
SetDynamicDbacMode(const char * ifName,const int8_t * data,uint32_t len)1648 static int32_t SetDynamicDbacMode(const char *ifName, const int8_t *data, uint32_t len)
1649 {
1650     int32_t ret = RET_CODE_FAILURE;
1651     char cmdBuf[P2P_BUF_SIZE] = {0};
1652     uint32_t cmdLen;
1653 
1654     cmdLen = strlen(CMD_SET_DYNAMIC_DBAC_MODE);
1655     if ((cmdLen + len) >= P2P_BUF_SIZE) {
1656         HILOG_ERROR(LOG_CORE, "%{public}s: the length of input data is too large", __FUNCTION__);
1657         return ret;
1658     }
1659     ret = snprintf_s(cmdBuf, P2P_BUF_SIZE, P2P_BUF_SIZE - 1, "%s %d", CMD_SET_DYNAMIC_DBAC_MODE, *data);
1660     if (ret < RET_CODE_SUCCESS) {
1661         HILOG_ERROR(LOG_CORE, "%{public}s: ifName: %{public}s, ret = %{public}d", __FUNCTION__, ifName, ret);
1662         return RET_CODE_FAILURE;
1663     }
1664     return SendCommandToDriver(cmdBuf, P2P_BUF_SIZE, ifName);
1665 }
1666 
SetProjectionScreenParam(const char * ifName,const ProjScrnCmdParam * param)1667 int32_t SetProjectionScreenParam(const char *ifName, const ProjScrnCmdParam *param)
1668 {
1669     int32_t ret;
1670 
1671     if (strcmp(ifName, STR_WLAN0) != EOK) {
1672         HILOG_ERROR(LOG_CORE, "%{public}s: %{public}s is not supported", __FUNCTION__, ifName);
1673         return RET_CODE_NOT_SUPPORT;
1674     }
1675     switch (param->cmdId) {
1676         case CMD_CLOSE_GO_CAC:
1677             ret = DisableNextCacOnce(ifName);
1678             break;
1679         case CMD_SET_GO_CSA_CHANNEL:
1680             ret = SetGoChannel(ifName, param->buf, param->bufLen);
1681             break;
1682         case CMD_SET_GO_RADAR_DETECT:
1683             ret = SetGoDetectRadar(ifName, param->buf, param->bufLen);
1684             break;
1685         case CMD_ID_MCC_STA_P2P_QUOTA_TIME:
1686             ret = SetDynamicDbacMode(ifName, param->buf, param->bufLen);
1687             break;
1688         case CMD_ID_CTRL_ROAM_CHANNEL:
1689             ret = SetP2pScenes(ifName, param->buf, param->bufLen);
1690             break;
1691         default:
1692             HILOG_ERROR(LOG_CORE, "%{public}s: Invalid command id", __FUNCTION__);
1693             return RET_CODE_NOT_SUPPORT;
1694     }
1695     if (ret != RET_CODE_SUCCESS) {
1696         HILOG_ERROR(LOG_CORE, "%{public}s: Config projection screen fail, ret = %{public}d", __FUNCTION__, ret);
1697     }
1698     return ret;
1699 }
1700 
SendCmdIoctl(const char * ifName,int32_t cmdId,const int8_t * paramBuf,uint32_t paramBufLen)1701 int32_t SendCmdIoctl(const char *ifName, int32_t cmdId, const int8_t *paramBuf, uint32_t paramBufLen)
1702 {
1703     (void)ifName;
1704     (void)cmdId;
1705     (void)paramBuf;
1706     (void)paramBufLen;
1707     return RET_CODE_NOT_SUPPORT;
1708 }
1709 
ParseStaTxRate(struct nlattr ** stats,uint32_t size,StationInfo * info)1710 static void ParseStaTxRate(struct nlattr **stats, uint32_t size, StationInfo *info)
1711 {
1712     struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
1713     static struct nla_policy ratePolicy[NL80211_RATE_INFO_MAX + 1];
1714 
1715     if (size < NL80211_STA_INFO_MAX + 1) {
1716         HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
1717         return;
1718     }
1719     ratePolicy[NL80211_RATE_INFO_BITRATE].type = NLA_U16;
1720     ratePolicy[NL80211_RATE_INFO_BITRATE32].type = NLA_U32;
1721     ratePolicy[NL80211_RATE_INFO_MCS].type = NLA_U8;
1722     ratePolicy[NL80211_RATE_INFO_VHT_MCS].type = NLA_U8;
1723     ratePolicy[NL80211_RATE_INFO_SHORT_GI].type = NLA_FLAG;
1724     ratePolicy[NL80211_RATE_INFO_VHT_NSS].type = NLA_U8;
1725     if (stats[NL80211_STA_INFO_TX_BITRATE] != NULL &&
1726         nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_TX_BITRATE], ratePolicy) == 0) {
1727         if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
1728             info->txRate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
1729         } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
1730             info->txRate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
1731         }
1732         if (rate[NL80211_RATE_INFO_MCS] != NULL) {
1733             info->txMcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
1734             info->flags |= STA_DRV_DATA_TX_MCS;
1735         }
1736         if (rate[NL80211_RATE_INFO_VHT_MCS] != NULL) {
1737             info->txVhtmcs = nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
1738             info->flags |= STA_DRV_DATA_TX_VHT_MCS;
1739         }
1740         if (rate[NL80211_RATE_INFO_SHORT_GI] != NULL) {
1741             info->flags |= STA_DRV_DATA_TX_SHORT_GI;
1742         }
1743         if (rate[NL80211_RATE_INFO_VHT_NSS] != NULL) {
1744             info->txVhtNss = nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
1745             info->flags |= STA_DRV_DATA_TX_VHT_NSS;
1746         }
1747     }
1748 }
1749 
ParseStaRxRate(struct nlattr ** stats,uint32_t size,StationInfo * info)1750 static void ParseStaRxRate(struct nlattr **stats, uint32_t size, StationInfo *info)
1751 {
1752     struct nlattr *rate[NL80211_RATE_INFO_MAX + 1];
1753     static struct nla_policy ratePolicy[NL80211_RATE_INFO_MAX + 1];
1754 
1755     if (size < NL80211_STA_INFO_MAX + 1) {
1756         HILOG_ERROR(LOG_CORE, "%{public}s: size of stats is not enough", __FUNCTION__);
1757         return;
1758     }
1759     ratePolicy[NL80211_RATE_INFO_BITRATE].type = NLA_U16;
1760     ratePolicy[NL80211_RATE_INFO_BITRATE32].type = NLA_U32;
1761     ratePolicy[NL80211_RATE_INFO_MCS].type = NLA_U8;
1762     ratePolicy[NL80211_RATE_INFO_VHT_MCS].type = NLA_U8;
1763     ratePolicy[NL80211_RATE_INFO_SHORT_GI].type = NLA_FLAG;
1764     ratePolicy[NL80211_RATE_INFO_VHT_NSS].type = NLA_U8;
1765     if (stats[NL80211_STA_INFO_RX_BITRATE] != NULL &&
1766         nla_parse_nested(rate, NL80211_RATE_INFO_MAX, stats[NL80211_STA_INFO_RX_BITRATE], ratePolicy) == 0) {
1767         if (rate[NL80211_RATE_INFO_BITRATE32] != NULL) {
1768             info->rxRate = nla_get_u32(rate[NL80211_RATE_INFO_BITRATE32]);
1769         } else if (rate[NL80211_RATE_INFO_BITRATE] != NULL) {
1770             info->rxRate = nla_get_u16(rate[NL80211_RATE_INFO_BITRATE]);
1771         }
1772         if (rate[NL80211_RATE_INFO_MCS] != NULL) {
1773             info->rxMcs = nla_get_u8(rate[NL80211_RATE_INFO_MCS]);
1774             info->flags |= STA_DRV_DATA_RX_MCS;
1775         }
1776         if (rate[NL80211_RATE_INFO_VHT_MCS] != NULL) {
1777             info->rxVhtmcs = nla_get_u8(rate[NL80211_RATE_INFO_VHT_MCS]);
1778             info->flags |= STA_DRV_DATA_RX_VHT_MCS;
1779         }
1780         if (rate[NL80211_RATE_INFO_SHORT_GI] != NULL) {
1781             info->flags |= STA_DRV_DATA_RX_SHORT_GI;
1782         }
1783         if (rate[NL80211_RATE_INFO_VHT_NSS] != NULL) {
1784             info->rxVhtNss = nla_get_u8(rate[NL80211_RATE_INFO_VHT_NSS]);
1785             info->flags |= STA_DRV_DATA_RX_VHT_NSS;
1786         }
1787     }
1788 }
1789 
ParseStaInfo(struct nlattr ** stats,uint32_t size,StationInfo * info)1790 static void ParseStaInfo(struct nlattr **stats, uint32_t size, StationInfo *info)
1791 {
1792     ParseStaTxRate(stats, size, info);
1793     ParseStaRxRate(stats, size, info);
1794 }
1795 
StationInfoHandler(struct nl_msg * msg,void * arg)1796 static int32_t StationInfoHandler(struct nl_msg *msg, void *arg)
1797 {
1798     StationInfo *info = (StationInfo *)arg;
1799     struct genlmsghdr *hdr = NULL;
1800     struct nlattr *attr[NL80211_ATTR_MAX + 1];
1801     struct nlattr *stats[NL80211_STA_INFO_MAX + 1];
1802     static struct nla_policy statsPolicy[NL80211_STA_INFO_MAX + 1];
1803 
1804     statsPolicy[NL80211_STA_INFO_INACTIVE_TIME].type = NLA_U32;
1805     statsPolicy[NL80211_STA_INFO_RX_BYTES].type = NLA_U32;
1806     statsPolicy[NL80211_STA_INFO_TX_BYTES].type = NLA_U32;
1807     statsPolicy[NL80211_STA_INFO_RX_PACKETS].type = NLA_U32;
1808     statsPolicy[NL80211_STA_INFO_TX_PACKETS].type = NLA_U32;
1809     statsPolicy[NL80211_STA_INFO_TX_FAILED].type = NLA_U32;
1810     statsPolicy[NL80211_STA_INFO_RX_BYTES64].type = NLA_U64;
1811     statsPolicy[NL80211_STA_INFO_TX_BYTES64].type = NLA_U64;
1812     statsPolicy[NL80211_STA_INFO_SIGNAL].type = NLA_U8;
1813     statsPolicy[NL80211_STA_INFO_ACK_SIGNAL].type = NLA_U8;
1814     statsPolicy[NL80211_STA_INFO_RX_DURATION].type = NLA_U64;
1815 
1816     hdr = nlmsg_data(nlmsg_hdr(msg));
1817     if (hdr == NULL) {
1818         HILOG_ERROR(LOG_CORE, "%s: get nlmsg header fail", __FUNCTION__);
1819         return NL_SKIP;
1820     }
1821 
1822     nla_parse(attr, NL80211_ATTR_MAX, genlmsg_attrdata(hdr, 0), genlmsg_attrlen(hdr, 0), NULL);
1823     if (!attr[NL80211_ATTR_STA_INFO]) {
1824         HILOG_ERROR(LOG_CORE, "%s: sta stats missing!", __FUNCTION__);
1825         return NL_SKIP;
1826     }
1827 
1828     if (nla_parse_nested(stats, NL80211_STA_INFO_MAX, attr[NL80211_ATTR_STA_INFO], statsPolicy)) {
1829         HILOG_ERROR(LOG_CORE, "%s: failed to parse nested attributes!", __FUNCTION__);
1830         return NL_SKIP;
1831     }
1832 
1833     ParseStaInfo(stats, NL80211_STA_INFO_MAX + 1, info);
1834     return NL_SKIP;
1835 }
1836 
GetStationInfo(const char * ifName,StationInfo * info,const uint8_t * mac,uint32_t macLen)1837 int32_t GetStationInfo(const char *ifName, StationInfo *info, const uint8_t *mac, uint32_t macLen)
1838 {
1839     uint32_t ifaceId = if_nametoindex(ifName);
1840     struct nl_msg *msg = NULL;
1841     int32_t ret = RET_CODE_FAILURE;
1842 
1843     if (ifaceId == 0) {
1844         HILOG_ERROR(LOG_CORE, "%s: if_nametoindex failed", __FUNCTION__);
1845         return RET_CODE_FAILURE;
1846     }
1847 
1848     msg = nlmsg_alloc();
1849     if (msg == NULL) {
1850         HILOG_ERROR(LOG_CORE, "%s: nlmsg alloc failed", __FUNCTION__);
1851         return RET_CODE_NOMEM;
1852     }
1853     do {
1854         if (!genlmsg_put(msg, 0, 0, g_wifiHalInfo.familyId, 0, 0, NL80211_CMD_GET_STATION, 0)) {
1855             HILOG_ERROR(LOG_CORE, "%s: genlmsg_put faile", __FUNCTION__);
1856             break;
1857         }
1858         if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, ifaceId) != RET_CODE_SUCCESS) {
1859             HILOG_ERROR(LOG_CORE, "%s: nla_put_u32 ifaceId faile", __FUNCTION__);
1860             break;
1861         }
1862         if (nla_put(msg, NL80211_ATTR_MAC, ETH_ADDR_LEN, mac) != RET_CODE_SUCCESS) {
1863             HILOG_ERROR(LOG_CORE, "%s: nla_put mac address faile", __FUNCTION__);
1864             break;
1865         }
1866 
1867         ret = NetlinkSendCmdSync(msg, StationInfoHandler, info);
1868         if (ret != RET_CODE_SUCCESS) {
1869             HILOG_ERROR(LOG_CORE, "%s: send cmd failed", __FUNCTION__);
1870         }
1871     } while (0);
1872     nlmsg_free(msg);
1873     return ret;
1874 }