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 }