blob: 9050d2ed97e9ce4c70dbdef1116e6fcce0441535 [file] [log] [blame]
developer72fb0bb2023-01-11 09:46:29 +08001/*
2 * If not stated otherwise in this file or this component's LICENSE file the
3 * following copyright and licenses apply:
4 *
5 * Copyright 2019 RDK Management
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18*/
19
20/*
21* Material from the TR181 data model is Copyright (c) 2010-2017, Broadband Forum
22* Licensed under the BSD-3 license
23*/
24
25/*
26* This file includes material that is Copyright (c) 2020, Plume Design Inc.
27* Licensed under the BSD-3 license
28*/
29
30/* Code in rxStatsInfo_callback and other callbacks is credited as follows:
31Copyright (c) 2007, 2008 Johannes Berg
32Copyright (c) 2007 Andy Lutomirski
33Copyright (c) 2007 Mike Kershaw
34Copyright (c) 2008-2009 Luis R. Rodriguez
35Licensed under the ISC license
36*/
37#define MTK_IMPL
38#define HAL_NETLINK_IMPL
39#define _GNU_SOURCE /* needed for strcasestr */
40
41#include <stdio.h>
42#include <stdlib.h>
43#include <unistd.h>
44#include <string.h>
45#include <fcntl.h>
46#include <stdbool.h>
47#include "wifi_hal.h"
48
49#ifdef HAL_NETLINK_IMPL
50#include <errno.h>
51#include <netlink/attr.h>
52#include <netlink/netlink.h>
53#include <netlink/genl/genl.h>
54#include <netlink/genl/family.h>
55#include <netlink/genl/ctrl.h>
56#include <linux/nl80211.h>
developer8dd72532023-05-17 19:58:35 +080057#include <net/if.h>
58#include <unl.h>
59#include "mtk_vendor_nl80211.h"
developer72fb0bb2023-01-11 09:46:29 +080060#endif
61
62#include <ev.h>
63#include <wpa_ctrl.h>
64#include <errno.h>
65#include <time.h>
66#define MAC_ALEN 6
67
68#define MAX_BUF_SIZE 256
69#define MAX_CMD_SIZE 256
70#define IF_NAME_SIZE 16
71#define CONFIG_PREFIX "/nvram/hostapd"
72#define ACL_PREFIX "/nvram/hostapd-acl"
73#define DENY_PREFIX "/nvram/hostapd-deny"
74//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
75#define SOCK_PREFIX "/var/run/hostapd/wifi"
76#define VAP_STATUS_FILE "/nvram/vap-status"
77#define ESSID_FILE "/tmp/essid"
78#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
79#define CHANNEL_STATS_FILE "/tmp/channel_stats"
80#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
81#define VLAN_FILE "/nvram/hostapd.vlan"
82#define PSK_FILE "/nvram/hostapd"
83#define MCS_FILE "/tmp/MCS"
developera1255e42023-05-13 17:45:02 +080084#define POWER_PERCENTAGE "/tmp/POWER"
85#define MGMT_POWER_CTRL "/tmp/mgmt_power_ctrl"
86/*LOGAN_DAT_FILE: may be different on customer's platform.*/
87#define LOGAN_DAT_FILE "/etc/wireless/mediatek/mt7990.b"
88
developer72fb0bb2023-01-11 09:46:29 +080089#define NOACK_MAP_FILE "/tmp/NoAckMap"
developerf6a87542023-05-16 15:47:28 +080090
developer72fb0bb2023-01-11 09:46:29 +080091#define BRIDGE_NAME "brlan0"
developerd1824452023-05-18 12:30:04 +080092#define BASE_PHY_INDEX 1
93#define BASE_RADIO_INDEX 0
developer72fb0bb2023-01-11 09:46:29 +080094
95/*
96 MAX_APS - Number of all AP available in system
97 2x Home AP
98 2x Backhaul AP
99 2x Guest AP
100 2x Secure Onboard AP
101 2x Service AP
102
103*/
104
105
106#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +0800107
108#define PREFIX_WIFI2G "ra"
109#define PREFIX_WIFI5G "rai"
110#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800111
developer47cc27a2023-05-17 23:09:58 +0800112#define PREFIX_SSID_2G "RDKB_2G"
113#define PREFIX_SSID_5G "RDKB_5G"
114#define PREFIX_SSID_6G "RDKB_6G"
115
developer72fb0bb2023-01-11 09:46:29 +0800116#ifndef RADIO_PREFIX
117#define RADIO_PREFIX "wlan"
118#endif
119
120#define MAX_ASSOCIATED_STA_NUM 2007
121
122//Uncomment to enable debug logs
123//#define WIFI_DEBUG
developer49b17232023-05-19 16:35:19 +0800124enum {
125 DEBUG_OFF = 0,
126 DEBUG_ERROR = 1,
127 DEBUG_WARN = 2,
128 DEBUG_NOTICE = 3,
129 DEBUG_INFO = 4
130};
131int wifi_debug_level = DEBUG_NOTICE;
132#define wifi_debug(level, fmt, args...) \
133{ \
134 if (level <= wifi_debug_level) \
135 { \
136 printf("[%s][%d]"fmt"\n", __func__, __LINE__, ##args); \
137 } \
138}
developer72fb0bb2023-01-11 09:46:29 +0800139
140#ifdef WIFI_DEBUG
141#define wifi_dbg_printf printf
142#define WIFI_ENTRY_EXIT_DEBUG printf
143#else
144#define wifi_dbg_printf(format, args...) printf("")
145#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
146#endif
147
148#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
149#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
150#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
151#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
152#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
153#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
154#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
155#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
156#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
157#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
158
159#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
160
161#define BW_FNAME "/nvram/bw_file.txt"
162
163#define PS_MAX_TID 16
164
developer96b38512023-02-22 11:17:45 +0800165#define MAX_CARD_INDEX 3
166
developer72fb0bb2023-01-11 09:46:29 +0800167static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
168 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
169 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
170 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
171 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
172 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
173 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
174 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
175 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
176 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
177 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
178 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
179 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
180 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
181 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
182 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
183 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
184};
185
186typedef unsigned long long u64;
187
188/* Enum to define WiFi Bands */
189typedef enum
190{
191 band_invalid = -1,
192 band_2_4 = 0,
193 band_5 = 1,
194 band_6 = 2,
195} wifi_band;
196
developer17038e62023-03-02 14:43:43 +0800197char* wifi_band_str[] = {
198 "2G",
199 "5G",
200 "6G",
201};
202
developer72fb0bb2023-01-11 09:46:29 +0800203typedef enum {
204 WIFI_MODE_A = 0x01,
205 WIFI_MODE_B = 0x02,
206 WIFI_MODE_G = 0x04,
207 WIFI_MODE_N = 0x08,
208 WIFI_MODE_AC = 0x10,
209 WIFI_MODE_AX = 0x20,
developera1255e42023-05-13 17:45:02 +0800210 WIFI_MODE_BE = 0x40,
developer72fb0bb2023-01-11 09:46:29 +0800211} wifi_ieee80211_Mode;
212
developerd1824452023-05-18 12:30:04 +0800213typedef enum ht_config_bw{
214 HT_BW_20,
215 HT_BW_40,
216};
217
218typedef enum vht_config_bw{
219 VHT_BW_2040,
220 VHT_BW_80,
221 VHT_BW_160,
222 VHT_BW_8080,
223};
224
225typedef enum eht_config_bw{
226 EHT_BW_20,
227 EHT_BW_40,
228 EHT_BW_80,
229 EHT_BW_160,
230 EHT_BW_320,
231};
232
developer72fb0bb2023-01-11 09:46:29 +0800233#ifdef WIFI_HAL_VERSION_3
234
235// Return number of elements in array
236#ifndef ARRAY_SIZE
237#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
238#endif /* ARRAY_SIZE */
239
240#ifndef ARRAY_AND_SIZE
241#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
242#endif /* ARRAY_AND_SIZE */
243
244#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
245
246typedef struct {
247 int32_t value;
248 int32_t param;
249 intptr_t key;
250 intptr_t data;
251} wifi_secur_list;
252
253static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
254static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
255wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
256wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
257char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
258static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer47cc27a2023-05-17 23:09:58 +0800259static void wifi_PrepareDefaultHostapdConfigs(void);
260static void wifi_psk_file_reset();
261
developer49b17232023-05-19 16:35:19 +0800262/*type define the nl80211 call back func*/
263typedef int (*mtk_nl80211_cb) (struct nl_msg *, void *);
264
265/**
266*struct mtk_nl80211_param
267* init mtk nl80211 using parameters
268* @sub_cmd: the cmd define in the mtk_vendor_nl80211.h.
269* @if_type: now only support the NL80211_ATTR_IFINDEX/NL80211_ATTR_WIPHY.
270* @if_idx: the index should match the interface or wiphy.
271* Note: NA
272**/
273struct mtk_nl80211_param {
274 unsigned int sub_cmd;
275 int if_type;
276 int if_idx;
277};
278
279/**
developer121a8e72023-05-22 09:19:39 +0800280*struct mtk_nl80211_cb_data
281* init mtk nl80211 call back parameters
282* @out_buf: store the mtk vendor output msg for wifi hal buffer.
283* @out_len: the output buffer length.
284* Note: NA
285**/
286struct mtk_nl80211_cb_data {
287 char * out_buf;
288 unsigned int out_len;
289};
290
291/**
developer49b17232023-05-19 16:35:19 +0800292*mtk_nl80211_init
293* init mtk nl80211 netlink and init the vendor msg common part.
294* @nl: netlink, just init it.
295* @msg: netlink message will alloc it.
296* the msg send success/fails is not free by app
297* only the nla_put etc api fails should use nlmsg_free.
298* @msg_data: vendor data msg attr pointer.
299* @param: init using interface and sub_cmd parameter.
300*
301*init the netlink context and mtk netlink vendor msg.
302*
303*return:
304* 0: success
305* other: fail
306**/
307
308int mtk_nl80211_init(struct unl *nl, struct nl_msg **msg,
309 struct nlattr **msg_data, struct mtk_nl80211_param *param) {
310 /*sanity check here*/
311 if (!nl || !param) {
312 (void)fprintf(stderr,
313 "[%s][%d]:nl(0x%lx) or param(0x%lx) is null, error!\n",
314 __func__, __LINE__, nl, param);
315 return -1;
316 }
317 /*if_type check*/
318 if ( param->if_type != NL80211_ATTR_IFINDEX && param->if_type != NL80211_ATTR_WIPHY) {
319 (void)fprintf(stderr,
320 "[%s][%d]:if_type(0x%x) is not supported, only 0x%x and 0x%x supported.\n",
321 __func__, __LINE__, param->if_type, NL80211_ATTR_IFINDEX, NL80211_ATTR_WIPHY);
322 return -1;
323 }
324 /*init the nl*/
325 if (unl_genl_init(nl, "nl80211") < 0) {
326 (void)fprintf(stderr, "[%s][%d]::Failed to connect to nl80211\n",
327 __func__, __LINE__);
328 return -1;
329 }
330 /*init the msg*/
331 *msg = unl_genl_msg(nl, NL80211_CMD_VENDOR, false);
332
333 if (nla_put_u32(*msg, param->if_type, param->if_idx) ||
334 nla_put_u32(*msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
335 nla_put_u32(*msg, NL80211_ATTR_VENDOR_SUBCMD, param->sub_cmd)) {
336 (void)fprintf(stderr,
337 "[%s][%d]:Nla put error: if_type: 0x%x, if_idx: 0x%x, sub_cmd: 0x%x\n",
338 __func__, __LINE__, param->if_type, param->if_idx, param->sub_cmd);
339 goto err;
340 }
341
342 *msg_data = nla_nest_start(*msg, NL80211_ATTR_VENDOR_DATA);
343 if (!*msg_data) {
344 (void)fprintf(stderr, "[%s][%d]:Nla put NL80211_ATTR_VENDOR_DATA start error\n",
345 __func__, __LINE__);
346 goto err;
347 }
348
349 return 0;
350err:
351
352 nlmsg_free(*msg);
353 unl_free(nl);
354 return -1;
355}
356
357/**
358*mtk_nl80211_send
359* set the vendor cmd call back and sent the vendor msg.
360* @nl: netlink.
361* @msg: netlink message.
362* @msg_data: vendor data msg attr pointer.
363* @handler: if the msg have call back shoud add the call back func
364* the event msg will handle by the call back func(exp:get cmd)
365* other set it as NULL(exp:set cmd).
366* @arg:call back func arg parameter.
367*add end of the netlink msg, set the call back and send msg
368*
369*return:
370* 0: success
371* other: fail
372**/
373int mtk_nl80211_send(struct unl *nl, struct nl_msg *msg,
374 struct nlattr *msg_data, mtk_nl80211_cb handler, void *arg) {
375 int ret = 0;
376 /*sanity check*/
377 if (!nl || !msg || !msg_data) {
378 (void)fprintf(stderr,
379 "[%s][%d]:nl(0x%lx),msg(0x%lx) or msg_data(0x%lx) is null, error!\n",
380 __func__, __LINE__, nl, msg, msg_data);
381 return -1;
382 }
383 /*end the msg attr of vendor data*/
384 nla_nest_end(msg, msg_data);
385 /*send the msg and set call back */
386 ret = unl_genl_request(nl, msg, handler, arg);
387 if (ret)
388 (void)fprintf(stderr, "send nl80211 cmd fails\n");
389 return ret;
390}
391
392/**
393*mtk_nl80211_deint
394* deinit the netlink and the nl80211 vendor msg.
395* @nl: netlink.
396*
397*free deinit the netlink and the nl80211 vendor msg.
398*
399*return:
400* 0: success
401**/
402
403int mtk_nl80211_deint(struct unl *nl) {
404 unl_free(nl);
405 return 0;
406}
407
developer72fb0bb2023-01-11 09:46:29 +0800408
409static wifi_secur_list map_security[] =
410{
411 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
412 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
413 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
414 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
415 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
416 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
417 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
418 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
419 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
420 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
421 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
422 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
423};
424
425wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
426{
427 wifi_secur_list *item;
428 int i;
429
430 for (item = list,i = 0;i < list_sz; item++, i++) {
431 if ((int)(item->key) == key) {
432 return item;
433 }
434 }
435
436 return NULL;
437}
438
439char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
440{
441 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
442
443 if (!item) {
444 return "";
445 }
446
447 return (char *)(item->data);
448}
449
450wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
451{
452 wifi_secur_list *item;
453 int i;
454
455 for (item = list,i = 0;i < list_sz; item++, i++) {
456 if (strcmp((char *)(item->data), str) == 0) {
457 return item;
458 }
459 }
460
461 return NULL;
462}
463#endif /* WIFI_HAL_VERSION_3 */
464
developer96b38512023-02-22 11:17:45 +0800465
466static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800467char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
468char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
469#define MAX_SSID_LEN 64
470char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800471int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800472
473static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
474static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
475
developer96b38512023-02-22 11:17:45 +0800476
477static int
478get_value(const char *conf_file, const char *param, char *value, int len)
479{
480 FILE *fp;
481 int ret = -1;
482 int param_len = strlen(param);
483 int buf_len;
484 char buf[256];
485
486 fp = fopen(conf_file, "r");
487 if (!fp) {
488 return -1;
489 }
490
491 while (fgets(buf, sizeof(buf), fp)) {
492 buf_len = strlen(buf);
493 if (buf[buf_len - 1] == '\n') {
494 buf_len--;
495 buf[buf_len] = '\0';
496 }
497 if ((buf_len > param_len) &&
498 (strncmp(buf, param, param_len) == 0) &&
499 (buf[param_len] == '=')) {
500
501 if (buf_len == (param_len + 1)) {
502 value[0] = '\0';
503 ret = 0;
504 } else {
505 ret = snprintf(value, len, "%s", buf + (param_len + 1));
506 }
507 fclose(fp);
508 return ret;
509 }
510 }
511 fclose(fp);
512 return -1;
513}
514
515static int
516get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
517{
518 char buf[256];
519 int ret;
520 char *save_ptr = NULL;
521 char *tok = NULL;
522
523 ret = get_value(conf_file, param, buf, sizeof(buf));
524 if (ret < 0)
525 return ret;
526
527 tok = strtok_r(buf, ";", &save_ptr);
528 do {
529 if (idx == 0 || tok == NULL)
530 break;
531 else
532 idx--;
533
534 tok = strtok_r(NULL, ";", &save_ptr);
535 } while (tok != NULL);
536
537 if (tok) {
538 ret = snprintf(value, len, "%s", tok);
539 } else {
540 ret = 0;
541 value[0] = '\0';
542 }
543
544 return ret;
545}
546
547
developer72fb0bb2023-01-11 09:46:29 +0800548#ifdef HAL_NETLINK_IMPL
549typedef struct {
550 int id;
551 struct nl_sock* socket;
552 struct nl_cb* cb;
553} Netlink;
554
555static int mac_addr_aton(unsigned char *mac_addr, char *arg)
556{
557 unsigned int mac_addr_int[6]={};
558 sscanf(arg, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
559 mac_addr[0] = mac_addr_int[0];
560 mac_addr[1] = mac_addr_int[1];
561 mac_addr[2] = mac_addr_int[2];
562 mac_addr[3] = mac_addr_int[3];
563 mac_addr[4] = mac_addr_int[4];
564 mac_addr[5] = mac_addr_int[5];
565 return 0;
566}
567
568static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
569{
570 unsigned int mac_addr_int[6]={};
571 mac_addr_int[0] = arg[0];
572 mac_addr_int[1] = arg[1];
573 mac_addr_int[2] = arg[2];
574 mac_addr_int[3] = arg[3];
575 mac_addr_int[4] = arg[4];
576 mac_addr_int[5] = arg[5];
577 snprintf(mac_addr, 20, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
578 return;
579}
580
581static int ieee80211_frequency_to_channel(int freq)
582{
583 /* see 802.11-2007 17.3.8.3.2 and Annex J */
584 if (freq == 2484)
585 return 14;
586 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
587 else if (freq == 5935)
588 return 2;
589 else if (freq < 2484)
590 return (freq - 2407) / 5;
591 else if (freq >= 4910 && freq <= 4980)
592 return (freq - 4000) / 5;
593 else if (freq < 5950)
594 return (freq - 5000) / 5;
595 else if (freq <= 45000) /* DMG band lower limit */
596 /* see 802.11ax D6.1 27.3.23.2 */
597 return (freq - 5950) / 5;
598 else if (freq >= 58320 && freq <= 70200)
599 return (freq - 56160) / 2160;
600 else
601 return 0;
602}
603
604static int initSock80211(Netlink* nl) {
605 nl->socket = nl_socket_alloc();
606 if (!nl->socket) {
607 fprintf(stderr, "Failing to allocate the sock\n");
608 return -ENOMEM;
609 }
610
611 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
612
613 if (genl_connect(nl->socket)) {
614 fprintf(stderr, "Failed to connect\n");
615 nl_close(nl->socket);
616 nl_socket_free(nl->socket);
617 return -ENOLINK;
618 }
619
620 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
621 if (nl->id< 0) {
622 fprintf(stderr, "interface not found.\n");
623 nl_close(nl->socket);
624 nl_socket_free(nl->socket);
625 return -ENOENT;
626 }
627
628 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
629 if ((!nl->cb)) {
630 fprintf(stderr, "Failed to allocate netlink callback.\n");
631 nl_close(nl->socket);
632 nl_socket_free(nl->socket);
633 return ENOMEM;
634 }
635
636 return nl->id;
637}
638
639static int nlfree(Netlink *nl)
640{
641 nl_cb_put(nl->cb);
642 nl_close(nl->socket);
643 nl_socket_free(nl->socket);
644 return 0;
645}
646
647static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
648 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
649 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
650 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
651};
652
653static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
654};
655
656static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
657};
658
659typedef struct _wifi_channelStats_loc {
660 INT array_size;
661 INT ch_number;
662 BOOL ch_in_pool;
663 INT ch_noise;
664 BOOL ch_radar_noise;
665 INT ch_max_80211_rssi;
666 INT ch_non_80211_noise;
667 INT ch_utilization;
668 ULLONG ch_utilization_total;
669 ULLONG ch_utilization_busy;
670 ULLONG ch_utilization_busy_tx;
671 ULLONG ch_utilization_busy_rx;
672 ULLONG ch_utilization_busy_self;
673 ULLONG ch_utilization_busy_ext;
674} wifi_channelStats_t_loc;
675
676typedef struct wifi_device_info {
677 INT wifi_devIndex;
678 UCHAR wifi_devMacAddress[6];
679 CHAR wifi_devIPAddress[64];
680 BOOL wifi_devAssociatedDeviceAuthentiationState;
681 INT wifi_devSignalStrength;
682 INT wifi_devTxRate;
683 INT wifi_devRxRate;
684} wifi_device_info_t;
685
686#endif
687
688//For 5g Alias Interfaces
689static BOOL priv_flag = TRUE;
690static BOOL pub_flag = TRUE;
691static BOOL Radio_flag = TRUE;
692//wifi_setApBeaconRate(1, beaconRate);
693
694BOOL multiple_set = FALSE;
695
696struct params
697{
698 char * name;
699 char * value;
700};
701
702static int _syscmd(char *cmd, char *retBuf, int retBufSize)
703{
704 FILE *f;
705 char *ptr = retBuf;
706 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
707
708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
709 if((f = popen(cmd, "r")) == NULL) {
710 fprintf(stderr,"\npopen %s error\n", cmd);
711 return RETURN_ERR;
712 }
713
714 while(!feof(f))
715 {
716 *ptr = 0;
717 if(bufSize>=128) {
718 bufbytes=128;
719 } else {
720 bufbytes=bufSize-1;
721 }
722
723 fgets(ptr,bufbytes,f);
724 readbytes=strlen(ptr);
725
726 if(!readbytes)
727 break;
728
729 bufSize-=readbytes;
730 ptr += readbytes;
731 }
732 cmd_ret = pclose(f);
733 retBuf[retBufSize-1]=0;
734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
735
736 return cmd_ret >> 8;
737}
738
739INT radio_index_to_phy(int radioIndex)
740{
developer17038e62023-03-02 14:43:43 +0800741 /* TODO */
742 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800743}
744
745INT wifi_getMaxRadioNumber(INT *max_radio_num)
746{
747 char cmd[64] = {0};
748 char buf[4] = {0};
749
750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
751
752 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
753 _syscmd(cmd, buf, sizeof(buf));
754 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
755
756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
757
758 return RETURN_OK;
759}
760
developer17038e62023-03-02 14:43:43 +0800761wifi_band radio_index_to_band(int radioIndex)
762{
developer745f0bd2023-03-06 14:32:53 +0800763 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800764}
765
developer72fb0bb2023-01-11 09:46:29 +0800766wifi_band wifi_index_to_band(int apIndex)
767{
768 char cmd[128] = {0};
769 char buf[64] = {0};
770 int nl80211_band = 0;
771 int i = 0;
772 int phyIndex = 0;
773 int radioIndex = 0;
774 int max_radio_num = 0;
775 wifi_band band = band_invalid;
776
777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
778
779 wifi_getMaxRadioNumber(&max_radio_num);
780 radioIndex = apIndex % max_radio_num;
781 phyIndex = radio_index_to_phy(radioIndex);
782 while(i < 10){
783 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
784 _syscmd(cmd, buf, sizeof(buf));
785 nl80211_band = strtol(buf, NULL, 10);
786 if (nl80211_band == 1)
787 band = band_2_4;
788 else if (nl80211_band == 2)
789 band = band_5;
790 else if (nl80211_band == 4) // band == 3 is 60GHz
791 band = band_6;
792
793 if(band != band_invalid)
794 break;
developer69b61b02023-03-07 17:17:44 +0800795
developer72fb0bb2023-01-11 09:46:29 +0800796 i++;
797 sleep(1);
798 }
799
800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
801 return band;
802}
803
804static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
805{
developer7e4a2a62023-04-06 19:56:03 +0800806 char cmd[MAX_CMD_SIZE] = {0};
807 char buf[MAX_BUF_SIZE] = {0};
808 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800809
developer7e4a2a62023-04-06 19:56:03 +0800810 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
811 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800812
developer7e4a2a62023-04-06 19:56:03 +0800813 if (ret < 0) {
814 printf("%s: snprintf error!", __func__);
815 return -1;
816 }
817
818 ret = _syscmd(cmd, buf, sizeof(buf));
819 if ((ret != 0) && (strlen(buf) == 0)) {
820 printf("%s: _syscmd error!", __func__);
821 return -1;
822 }
823
824 snprintf(output, output_size, "%s", buf);
825
826 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800827}
828
829static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
830{
developer7e4a2a62023-04-06 19:56:03 +0800831 char cmd[MAX_CMD_SIZE] = {0};
832 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800833
developer7e4a2a62023-04-06 19:56:03 +0800834 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800835 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800836 if (strlen(buf) == 0) /*no such item, insert it*/
developera1255e42023-05-13 17:45:02 +0800837 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800838 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800839 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developera1255e42023-05-13 17:45:02 +0800840
developer72fb0bb2023-01-11 09:46:29 +0800841 if(_syscmd(cmd, buf, sizeof(buf)))
842 return -1;
843 }
844
developera1255e42023-05-13 17:45:02 +0800845 return 0;
846}
847static int wifi_datfileRead(char *conf_file, char *param, char *output, int output_size)
848{
849 char cmd[MAX_CMD_SIZE] = {0};
850 char buf[MAX_BUF_SIZE] = {0};
851 int ret = 0;
852
853 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
854 conf_file, param);
855
856 if (ret < 0) {
857 printf("%s: snprintf error!", __func__);
858 return -1;
859 }
860
861 ret = _syscmd(cmd, buf, sizeof(buf));
862 if ((ret != 0) && (strlen(buf) == 0)) {
863 printf("%s: _syscmd error!", __func__);
864 return -1;
865 }
866
867 snprintf(output, output_size, "%s", buf);
868
developer72fb0bb2023-01-11 09:46:29 +0800869 return 0;
870}
871
developera1255e42023-05-13 17:45:02 +0800872static int wifi_datfileWrite(char *conf_file, struct params *list, int item_count)
873{
874 char cmd[MAX_CMD_SIZE] = {0};
875 char buf[MAX_BUF_SIZE] = {0};
876
877 for (int i = 0; i < item_count; i++) {
878 wifi_datfileRead(conf_file, list[i].name, buf, sizeof(buf));
879 if (strlen(buf) == 0) /*no such item, insert it*/
880 snprintf(cmd, sizeof(cmd), "sed -i -e '$a %s=%s' %s", list[i].name, list[i].value, conf_file);
881 else /*find the item, update it*/
882 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
883
884 if(_syscmd(cmd, buf, sizeof(buf)))
885 return -1;
886 }
887
888 return 0;
889}
890
developer72fb0bb2023-01-11 09:46:29 +0800891//For Getting Current Interface Name from corresponding hostapd configuration
892static int wifi_GetInterfaceName(int apIndex, char *interface_name)
893{
894 char config_file[128] = {0};
895
896 if (interface_name == NULL)
897 return RETURN_ERR;
898
899 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
900
901 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
902 wifi_hostapdRead(config_file, "interface", interface_name, 16);
903 if (strlen(interface_name) == 0)
904 return RETURN_ERR;
905
906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
907 return RETURN_OK;
908}
909
developera1255e42023-05-13 17:45:02 +0800910static UCHAR get_bssnum_byindex(INT radio_index, UCHAR *bss_cnt)
911{
912 char interface_name[IF_NAME_SIZE] = {0};
913 char cmd[MAX_BUF_SIZE]={'\0'};
914 char buf[MAX_CMD_SIZE]={'\0'};
915 UCHAR channel = 0;
916
917 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
918 return RETURN_ERR;
919 /*interface name to channel number*/
920 snprintf(cmd, sizeof(cmd), "iw dev %s info | grep -i 'channel' | cut -d ' ' -f2", interface_name);
921 _syscmd(cmd, buf, sizeof(buf));
922 channel = atoi(buf);
923 WIFI_ENTRY_EXIT_DEBUG("%s:channel=%d\n", __func__, channel);
924 /*count dev number with the same channel*/
925 snprintf(cmd, sizeof(cmd), "iw dev | grep -i 'channel %d' | wc -l", channel);
926 _syscmd(cmd, buf, sizeof(buf));
927 *bss_cnt = atoi(buf) - 1;/*1 for apcli interface*/
928 WIFI_ENTRY_EXIT_DEBUG("%s:bss_cnt=%d\n", __func__, *bss_cnt);
929 return RETURN_OK;
930}
developer72fb0bb2023-01-11 09:46:29 +0800931
developerd1824452023-05-18 12:30:04 +0800932/* index: radio index or phy index
933 phy: true-> base phy command
934 false-> base radio command */
935static int wifi_mwctlSet(int index, struct params *mwctl, bool phy)
936{
937 char cmd[MAX_CMD_SIZE]={'\0'};
938 char buf[MAX_BUF_SIZE]={'\0'};
939 char interface_name[16] = {0};
940
941 if (phy == TRUE)
942 snprintf(cmd, sizeof(cmd), "mwctl phy phy%d set %s%s", index, mwctl->name, mwctl->value);
943 else {
944 if (wifi_GetInterfaceName(index, interface_name) != RETURN_OK)
945 return RETURN_ERR;
946 snprintf(cmd, sizeof(cmd), "mwctl %s set %s%s", interface_name, mwctl->name, mwctl->value);
947 }
948 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
949 return RETURN_ERR;
950
951 return RETURN_OK;
952}
953
developer72fb0bb2023-01-11 09:46:29 +0800954static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
955{
956 char interface_name[16] = {0};
957 if (multiple_set == TRUE)
958 return RETURN_OK;
959 char cmd[MAX_CMD_SIZE]="", output[32]="";
960 FILE *fp;
961 int i;
962 //NOTE RELOAD should be done in ApplySSIDSettings
963 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
964 return RETURN_ERR;
965 for(i=0; i<item_count; i++, list++)
966 {
developerf6a87542023-05-16 15:47:28 +0800967 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
developer72fb0bb2023-01-11 09:46:29 +0800968 if((fp = popen(cmd, "r"))==NULL)
969 {
970 perror("popen failed");
971 return -1;
972 }
973 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
974 {
975 pclose(fp);
976 perror("fgets failed");
977 return -1;
978 }
979 pclose(fp);
980 }
981 return 0;
982}
983
developer7e4a2a62023-04-06 19:56:03 +0800984static int wifi_quick_reload_ap(int apIndex)
985{
986 char interface_name[IF_NAME_SIZE] = {0};
987 char cmd[MAX_CMD_SIZE] = {0};
988 char buf[MAX_BUF_SIZE] = {0};
989
990 if (multiple_set == TRUE)
991 return RETURN_OK;
992
993 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
994 return RETURN_ERR;
995
996 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
997 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
998 return RETURN_ERR;
999
1000 return RETURN_OK;
1001}
1002
developer72fb0bb2023-01-11 09:46:29 +08001003static int wifi_reloadAp(int apIndex)
1004{
1005 char interface_name[16] = {0};
1006 if (multiple_set == TRUE)
1007 return RETURN_OK;
1008 char cmd[MAX_CMD_SIZE]="";
1009 char buf[MAX_BUF_SIZE]="";
1010
1011 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1012 return RETURN_ERR;
1013 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
1014 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1015 return RETURN_ERR;
1016
1017 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
1018 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1019 return RETURN_ERR;
1020
1021 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
1022 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
1023 return RETURN_ERR;
1024
1025 return RETURN_OK;
1026}
1027
1028INT File_Reading(CHAR *file, char *Value)
1029{
1030 FILE *fp = NULL;
1031 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
1032 int count = 0;
1033
1034 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1035 fp = popen(file,"r");
1036 if(fp == NULL)
1037 return RETURN_ERR;
1038
1039 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
1040 {
1041 for(count=0;buf[count]!='\n';count++)
1042 copy_buf[count]=buf[count];
1043 copy_buf[count]='\0';
1044 }
1045 strcpy(Value,copy_buf);
1046 pclose(fp);
1047 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1048
1049 return RETURN_OK;
1050}
1051
1052void wifi_RestartHostapd_2G()
1053{
1054 int Public2GApIndex = 4;
1055
1056 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1057 wifi_setApEnable(Public2GApIndex, FALSE);
1058 wifi_setApEnable(Public2GApIndex, TRUE);
1059 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1060}
1061
1062void wifi_RestartHostapd_5G()
1063{
1064 int Public5GApIndex = 5;
1065
1066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1067 wifi_setApEnable(Public5GApIndex, FALSE);
1068 wifi_setApEnable(Public5GApIndex, TRUE);
1069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1070}
1071
1072void wifi_RestartPrivateWifi_2G()
1073{
1074 int PrivateApIndex = 0;
1075
1076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1077 wifi_setApEnable(PrivateApIndex, FALSE);
1078 wifi_setApEnable(PrivateApIndex, TRUE);
1079 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1080}
1081
1082void wifi_RestartPrivateWifi_5G()
1083{
1084 int Private5GApIndex = 1;
1085
1086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1087 wifi_setApEnable(Private5GApIndex, FALSE);
1088 wifi_setApEnable(Private5GApIndex, TRUE);
1089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1090}
1091
1092static int writeBandWidth(int radioIndex,char *bw_value)
1093{
1094 char buf[MAX_BUF_SIZE];
1095 char cmd[MAX_CMD_SIZE];
1096
1097 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
1098 if(_syscmd(cmd, buf, sizeof(buf)))
1099 {
1100 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
1101 _syscmd(cmd, buf, sizeof(buf));
1102 return RETURN_OK;
1103 }
1104
1105 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
1106 _syscmd(cmd,buf,sizeof(buf));
1107 return RETURN_OK;
1108}
1109
1110static int readBandWidth(int radioIndex,char *bw_value)
1111{
1112 char buf[MAX_BUF_SIZE] = {0};
1113 char cmd[MAX_CMD_SIZE] = {0};
1114 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
1115 _syscmd(cmd,buf,sizeof(buf));
1116 if(NULL!=strstr(buf,"20MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001117 strcpy(bw_value,"20MHz");
developer72fb0bb2023-01-11 09:46:29 +08001118 else if(NULL!=strstr(buf,"40MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001119 strcpy(bw_value,"40MHz");
developer72fb0bb2023-01-11 09:46:29 +08001120 else if(NULL!=strstr(buf,"80MHz"))
developer72fb0bb2023-01-11 09:46:29 +08001121 strcpy(bw_value,"80MHz");
developerd1824452023-05-18 12:30:04 +08001122 else if(NULL!=strstr(buf,"160MHz"))
1123 strcpy(bw_value,"160MHz");
1124 else if(NULL!=strstr(buf,"320MHz"))
1125 strcpy(bw_value,"320MHz");
developer72fb0bb2023-01-11 09:46:29 +08001126 else
developer72fb0bb2023-01-11 09:46:29 +08001127 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08001128 return RETURN_OK;
1129}
1130
1131// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
1132INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
1133{
1134 struct params params={'\0'};
1135 char config_file[MAX_BUF_SIZE] = {0};
1136 char buf[MAX_BUF_SIZE] = {'\0'};
1137
1138 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1139 // Copy the numeric value
1140 if (strlen (beaconRate) >= 5) {
1141 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
1142 buf[strlen(beaconRate) - 4] = '\0';
1143 } else if (strlen(beaconRate) > 0)
1144 strcpy(buf, beaconRate);
1145 else
1146 return RETURN_ERR;
1147
1148 params.name = "beacon_rate";
1149 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
1150 if (strncmp(buf, "5.5", 3) == 0) {
1151 snprintf(buf, sizeof(buf), "55");
1152 params.value = buf;
1153 } else {
1154 strcat(buf, "0");
1155 params.value = buf;
1156 }
1157
1158 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1159 wifi_hostapdWrite(config_file, &params, 1);
1160 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1161 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1162
1163 return RETURN_OK;
1164}
1165
1166INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
1167{
1168 char config_file[128] = {'\0'};
1169 char temp_output[128] = {'\0'};
1170 char buf[128] = {'\0'};
1171 char cmd[128] = {'\0'};
1172 int rate = 0;
1173 int phyId = 0;
1174
1175 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1176 if (NULL == beaconRate)
1177 return RETURN_ERR;
1178
1179 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1180 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
1181 phyId = radio_index_to_phy(radioIndex);
1182 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
1183 if(strlen(buf) > 0) {
1184 if (strncmp(buf, "55", 2) == 0)
1185 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
1186 else {
1187 rate = strtol(buf, NULL, 10)/10;
1188 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
1189 }
1190 } else {
1191 // config not set, so we would use lowest rate as default
1192 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
1193 _syscmd(cmd, buf, sizeof(buf));
1194 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
1195 }
1196 strncpy(beaconRate, temp_output, sizeof(temp_output));
1197 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1198
1199 return RETURN_OK;
1200}
1201
1202INT wifi_setLED(INT radioIndex, BOOL enable)
1203{
1204 return 0;
1205}
1206INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
1207{
1208 return RETURN_OK;
1209}
1210/**********************************************************************************
1211 *
developer69b61b02023-03-07 17:17:44 +08001212 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +08001213 *
1214**********************************************************************************/
1215//---------------------------------------------------------------------------------------------------
1216//Wifi system api
1217//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
developer69b61b02023-03-07 17:17:44 +08001218INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08001219{
1220 if(!output_string)
1221 return RETURN_ERR;
1222 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
1223
1224 return RETURN_OK;
1225}
1226
1227
1228/* wifi_factoryReset() function */
1229/**
developer69b61b02023-03-07 17:17:44 +08001230* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +08001231* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1232*
1233* @param None
1234*
1235* @return The status of the operation.
1236* @retval RETURN_OK if successful.
1237* @retval RETURN_ERR if any error is detected
1238*
1239* @execution Synchronous
1240* @sideeffect None
1241*
1242* @note This function must not suspend and must not invoke any blocking system
1243* calls. It should probably just send a message to a driver event handler task.
1244*
1245*/
1246INT wifi_factoryReset()
1247{
developer47cc27a2023-05-17 23:09:58 +08001248 char cmd[MAX_CMD_SIZE] = {0};
1249 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001250
developer47cc27a2023-05-17 23:09:58 +08001251 /*delete running hostapd conf files*/
1252 wifi_dbg_printf("\n[%s]: deleting hostapd conf file.", __func__);
1253 snprintf(cmd, MAX_CMD_SIZE, "rm -rf /nvram/*.conf");
1254 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001255
developer47cc27a2023-05-17 23:09:58 +08001256 wifi_PrepareDefaultHostapdConfigs();
1257 wifi_psk_file_reset();
1258
1259 memset(cmd, 0, MAX_CMD_SIZE);
1260 memset(buf, 0, MAX_BUF_SIZE);
1261
1262 snprintf(cmd, MAX_CMD_SIZE, "systemctl restart hostapd.service");
1263 _syscmd(cmd, buf, sizeof(buf));
1264
1265 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001266}
1267
1268/* wifi_factoryResetRadios() function */
1269/**
1270* @description Restore all radio parameters without touching access point parameters. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
1271*
1272* @param None
1273* @return The status of the operation
1274* @retval RETURN_OK if successful
1275* @retval RETURN_ERR if any error is detected
1276*
1277* @execution Synchronous
1278*
1279* @sideeffect None
1280*
1281* @note This function must not suspend and must not invoke any blocking system
1282* calls. It should probably just send a message to a driver event handler task.
1283*
1284*/
1285INT wifi_factoryResetRadios()
1286{
1287 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
1288 return RETURN_OK;
1289
1290 return RETURN_ERR;
1291}
1292
1293
1294/* wifi_factoryResetRadio() function */
1295/**
1296* @description Restore selected radio parameters without touching access point parameters
1297*
1298* @param radioIndex - Index of Wi-Fi Radio channel
1299*
1300* @return The status of the operation.
1301* @retval RETURN_OK if successful.
1302* @retval RETURN_ERR if any error is detected
1303*
1304* @execution Synchronous.
1305* @sideeffect None.
1306*
1307* @note This function must not suspend and must not invoke any blocking system
1308* calls. It should probably just send a message to a driver event handler task.
1309*
1310*/
1311INT wifi_factoryResetRadio(int radioIndex) //RDKB
1312{
developer47cc27a2023-05-17 23:09:58 +08001313 char cmd[MAX_CMD_SIZE] = {0};
1314 char buf[MAX_BUF_SIZE] = {0};
1315 char vap_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08001316
developer47cc27a2023-05-17 23:09:58 +08001317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001318
developer47cc27a2023-05-17 23:09:58 +08001319 snprintf(cmd, MAX_CMD_SIZE, "systemctl stop hostapd.service");
1320 _syscmd(cmd, buf, sizeof(buf));
1321
1322 memset(cmd, 0, MAX_CMD_SIZE);
1323 memset(buf, 0, MAX_BUF_SIZE);
1324
1325 for (vap_idx = radioIndex; vap_idx < MAX_APS; vap_idx += MAX_NUM_RADIOS)
1326 wifi_factoryResetAP(vap_idx);
1327
1328 snprintf(cmd, MAX_CMD_SIZE, "systemctl start hostapd.service");
1329 _syscmd(cmd, buf, sizeof(buf));
1330
1331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1332 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001333}
1334
1335/* wifi_initRadio() function */
1336/**
1337* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001338* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001339* different hardware implementations may have different initilization requirements.
1340* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1341*
1342* @return The status of the operation.
1343* @retval RETURN_OK if successful.
1344* @retval RETURN_ERR if any error is detected
1345*
1346* @execution Synchronous.
1347* @sideeffect None.
1348*
1349* @note This function must not suspend and must not invoke any blocking system
1350* calls. It should probably just send a message to a driver event handler task.
1351*
1352*/
1353INT wifi_initRadio(INT radioIndex)
1354{
1355 //TODO: Initializes the wifi subsystem (for specified radio)
1356 return RETURN_OK;
1357}
1358void macfilter_init()
1359{
1360 char count[4]={'\0'};
1361 char buf[253]={'\0'};
1362 char tmp[19]={'\0'};
1363 int dev_count,block,mac_entry=0;
1364 char res[4]={'\0'};
1365 char acl_file_path[64] = {'\0'};
1366 FILE *fp = NULL;
1367 int index=0;
1368 char iface[10]={'\0'};
1369 char config_file[MAX_BUF_SIZE] = {0};
1370
1371
1372 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1373
1374 fp=fopen(acl_file_path,"w+");
1375 if (fp == NULL) {
1376 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001377 return;
developer72fb0bb2023-01-11 09:46:29 +08001378 }
1379 sprintf(buf,"#!/bin/sh \n");
1380 fprintf(fp,"%s\n",buf);
1381
1382 system("chmod 0777 /tmp/mac_filter.sh");
1383
1384 for(index=0;index<=1;index++)
1385 {
1386 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1387 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1388 sprintf(buf,"syscfg get %dcountfilter",index);
1389 _syscmd(buf,count,sizeof(count));
1390 mac_entry=atoi(count);
1391
1392 sprintf(buf,"syscfg get %dblockall",index);
1393 _syscmd(buf,res,sizeof(res));
1394 block = atoi(res);
1395
1396 //Allow only those macs mentioned in ACL
1397 if(block==1)
1398 {
1399 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1400 fprintf(fp,"%s\n",buf);
1401 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1402 {
1403 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1404 _syscmd(buf,tmp,sizeof(tmp));
1405 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1406 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1407 fprintf(fp,"%s\n",buf);
1408 }
1409 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1410 fprintf(fp,"%s\n",buf);
1411 }
1412
1413 //Block all the macs mentioned in ACL
1414 else if(block==2)
1415 {
1416 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1417 fprintf(fp,"%s\n",buf);
1418
1419 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1420 {
1421 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1422 _syscmd(buf,tmp,sizeof(tmp));
1423 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1424 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1425 fprintf(fp,"%s\n",buf);
1426 }
1427 }
1428 }
1429 fclose(fp);
1430}
1431
developer17038e62023-03-02 14:43:43 +08001432
1433static void
1434wifi_ParseProfile(void)
1435{
1436 int i;
1437 int max_radio_num = 0;
1438 int card_idx;
1439 int band_idx;
1440 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001441 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001442 char buf[MAX_BUF_SIZE] = {0};
1443 char chip_name[12];
1444 char card_profile[MAX_BUF_SIZE] = {0};
1445 char band_profile[MAX_BUF_SIZE] = {0};
1446 FILE* fp;
1447
1448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1449
1450 memset(main_prefix, 0, sizeof(main_prefix));
1451 memset(ext_prefix, 0, sizeof(ext_prefix));
1452 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001453 for (i = 0; i < MAX_NUM_RADIOS; i++)
1454 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001455
1456 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1457 /* LOG */
1458 return;
1459 }
1460
1461 for (card_idx = 0; card_idx < 3; card_idx++) {
1462 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1463 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1464 break;
1465 }
1466 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1467 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1468 break;
1469 }
1470 for (band_idx = 0; band_idx < 3; band_idx++) {
1471 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1472 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1473 /* LOG */
1474 break;
1475 }
1476
1477 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1478 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1479 /* LOG */
1480 }
1481
1482 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1483 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1484 /* LOG */
1485 }
1486
1487 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1488 /* LOG */
1489 }
developer745f0bd2023-03-06 14:32:53 +08001490 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1491 /* LOG */
1492 }
1493
1494 wireless_mode = atoi(buf);
1495 switch (wireless_mode) {
1496 case 22:
1497 case 16:
1498 case 6:
1499 case 4:
1500 case 1:
1501 radio_band[phy_idx] = band_2_4;
1502 break;
1503 case 23:
1504 case 17:
1505 case 14:
1506 case 11:
1507 case 2:
1508 radio_band[phy_idx] = band_5;
1509 break;
1510 case 24:
1511 case 18:
1512 radio_band[phy_idx] = band_6;
1513 break;
1514 }
developer17038e62023-03-02 14:43:43 +08001515 phy_idx++;
1516 }
1517 }
1518
1519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1520}
1521
1522static void
1523wifi_PrepareDefaultHostapdConfigs(void)
1524{
developer0132ed92023-03-21 13:48:53 +08001525 int radio_idx;
1526 int bss_idx;
1527 int ap_idx;
developer0132ed92023-03-21 13:48:53 +08001528 char buf[MAX_BUF_SIZE] = {0};
1529 char config_file[MAX_BUF_SIZE] = {0};
1530 char ssid[MAX_BUF_SIZE] = {0};
1531 char interface[32] = {0};
1532 char ret_buf[MAX_BUF_SIZE] = {0};
1533 char psk_file[64] = {0};
1534 struct params params[3];
developer47cc27a2023-05-17 23:09:58 +08001535 char *band_str[3] = {"2G", "5G", "6G"};
developer17038e62023-03-02 14:43:43 +08001536
developer0132ed92023-03-21 13:48:53 +08001537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1538 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001539
developer0132ed92023-03-21 13:48:53 +08001540 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer47cc27a2023-05-17 23:09:58 +08001541 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
developer0132ed92023-03-21 13:48:53 +08001542
developer47cc27a2023-05-17 23:09:58 +08001543 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1544 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], config_file);
1545 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001546
developer47cc27a2023-05-17 23:09:58 +08001547 if (radio_idx == band_2_4) {
1548 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
1549 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
1550 } else if (radio_idx == band_5) {
1551 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
1552 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
1553 } else if (radio_idx == band_6) {
1554 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
1555 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
1556 }
developer17038e62023-03-02 14:43:43 +08001557
developer47cc27a2023-05-17 23:09:58 +08001558 /* fix wpa_psk_file path */
1559 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001560
developer47cc27a2023-05-17 23:09:58 +08001561 params[0].name = "ssid";
1562 params[0].value = ssid;
1563 params[1].name = "interface";
1564 params[1].value = interface;
1565 params[2].name = "wpa_psk_file";
1566 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001567
developer47cc27a2023-05-17 23:09:58 +08001568 wifi_hostapdWrite(config_file, params, 3);
developer0132ed92023-03-21 13:48:53 +08001569 }
1570 }
1571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001572}
1573
1574static void
1575wifiBringUpInterfacesForRadio(int radio_idx)
1576{
developer0132ed92023-03-21 13:48:53 +08001577 int bss_idx;
1578 int ap_idx;
1579 int band_idx;
1580 char cmd[MAX_CMD_SIZE] = {0};
1581 char config_file[MAX_BUF_SIZE] = {0};
1582 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001583 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001584
1585 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001586
developered997d32023-04-18 22:45:39 +08001587 bss_idx = 0;
1588 /*TBD: we need refine setup flow and mbss flow*/
1589// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001590 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1591
1592 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1593 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1594
1595 memset(cmd, 0, MAX_CMD_SIZE);
1596 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001597
developer0132ed92023-03-21 13:48:53 +08001598 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1599 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1600 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001601
1602 wifi_GetInterfaceName(ap_idx, inf_name);
1603
1604 memset(cmd, 0, MAX_CMD_SIZE);
1605 memset(ret_buf, 0, MAX_BUF_SIZE);
1606
1607 /* fix vap-status file */
1608 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1609 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001610// }
1611
1612 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001613}
1614
1615static void
1616wifi_BringUpInterfaces(void)
1617{
1618 int radio_idx;
1619 int bss_idx;
1620 int ap_idx;
1621 int band_idx;
1622 char cmd[MAX_BUF_SIZE] = {0};
1623 char config_file[MAX_BUF_SIZE] = {0};
1624 char ret_buf[MAX_BUF_SIZE]={'\0'};
1625
1626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1627 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1628 band_idx = radio_index_to_band(radio_idx);
1629 if (band_idx < 0) {
1630 break;
1631 }
1632 wifiBringUpInterfacesForRadio(radio_idx);
1633 }
1634 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1635}
1636
1637static void
1638wifi_BringDownInterfacesForRadio(int radio_idx)
1639{
1640 int bss_idx;
1641 int ap_idx;
1642 int band_idx;
1643 char cmd[MAX_BUF_SIZE] = {0};
1644 char config_file[MAX_BUF_SIZE] = {0};
1645 char ret_buf[MAX_BUF_SIZE]={'\0'};
1646
1647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001648
developer8a3bbbf2023-03-15 17:47:23 +08001649 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1650 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1651
1652
developer17038e62023-03-02 14:43:43 +08001653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1654}
1655
1656
1657static void
1658wifi_BringDownInterfaces(void)
1659{
1660 int radio_idx;
1661 int bss_idx;
1662 int ap_idx;
1663 int band_idx;
1664 char cmd[MAX_BUF_SIZE] = {0};
1665 char config_file[MAX_BUF_SIZE] = {0};
1666 char ret_buf[MAX_BUF_SIZE]={'\0'};
1667
1668 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1669 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1670 band_idx = radio_index_to_band(radio_idx);
1671 if (band_idx < 0) {
1672 break;
1673 }
1674 wifi_BringDownInterfacesForRadio(radio_idx);
1675 }
1676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1677}
1678
developer47cc27a2023-05-17 23:09:58 +08001679static void wifi_psk_file_reset()
1680{
1681 char cmd[MAX_CMD_SIZE] = {0};
1682 char ret_buf[MAX_BUF_SIZE] = {0};
1683 char psk_file[MAX_CMD_SIZE]= {0};
1684 char vap_idx = 0;
1685
1686 for (vap_idx = 0; vap_idx < MAX_APS; vap_idx++) {
1687 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, vap_idx);
1688
1689 if (access(psk_file, F_OK) != 0) {
1690 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
1691 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1692 } else {
1693 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
1694 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1695 }
1696 }
1697}
1698
developer8a3bbbf2023-03-15 17:47:23 +08001699static void wifi_vap_status_reset()
1700{
1701 char cmd[MAX_CMD_SIZE] = {0};
1702 char ret_buf[MAX_BUF_SIZE] = {0};
1703 char radio_idx = 0;
1704 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001705
developer8a3bbbf2023-03-15 17:47:23 +08001706 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1707 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1708 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1709 } else {
1710 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1711 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1712 }
1713
1714 memset(cmd, 0, MAX_CMD_SIZE);
1715 memset(ret_buf, 0, MAX_BUF_SIZE);
1716
1717 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1718 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1719 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1720 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1721 }
1722
1723}
developer17038e62023-03-02 14:43:43 +08001724
developer72fb0bb2023-01-11 09:46:29 +08001725// Initializes the wifi subsystem (all radios)
1726INT wifi_init() //RDKB
1727{
developer96b38512023-02-22 11:17:45 +08001728 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1729 //Not intitializing macfilter for Turris-Omnia Platform for now
1730 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001731 wifi_ParseProfile();
1732 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001733 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001734 //system("/usr/sbin/iw reg set US");
1735 system("systemctl start hostapd.service");
1736 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001737
1738 wifi_vap_status_reset();
1739
developer17038e62023-03-02 14:43:43 +08001740 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001741
developer96b38512023-02-22 11:17:45 +08001742
1743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001744
1745 return RETURN_OK;
1746}
1747
1748/* wifi_reset() function */
1749/**
1750* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001751* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001752* different hardware implementations may have different requirements.
1753* Parameters : None
1754*
1755* @return The status of the operation.
1756* @retval RETURN_OK if successful.
1757* @retval RETURN_ERR if any error is detected
1758*
1759* @execution Synchronous.
1760* @sideeffect None.
1761*
1762* @note This function must not suspend and must not invoke any blocking system
1763* calls. It should probably just send a message to a driver event handler task.
1764*
1765*/
1766INT wifi_reset()
1767{
developer17038e62023-03-02 14:43:43 +08001768
1769 wifi_BringDownInterfaces();
1770 sleep(2);
1771
developer96b38512023-02-22 11:17:45 +08001772 //TODO: resets the wifi subsystem, deletes all APs
1773 system("systemctl stop hostapd.service");
1774 sleep(2);
developer17038e62023-03-02 14:43:43 +08001775
developer96b38512023-02-22 11:17:45 +08001776 system("systemctl start hostapd.service");
1777 sleep(5);
developer17038e62023-03-02 14:43:43 +08001778
1779 wifi_PrepareDefaultHostapdConfigs();
developer47cc27a2023-05-17 23:09:58 +08001780 wifi_psk_file_reset();
developer17038e62023-03-02 14:43:43 +08001781 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001782
1783 wifi_vap_status_reset();
1784
developer17038e62023-03-02 14:43:43 +08001785 wifi_BringUpInterfaces();
1786
developer72fb0bb2023-01-11 09:46:29 +08001787 return RETURN_OK;
1788}
1789
1790/* wifi_down() function */
1791/**
1792* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001793* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001794* different hardware implementations may have different requirements.
1795*
1796* @param None
1797*
1798* @return The status of the operation
1799* @retval RETURN_OK if successful
1800* @retval RETURN_ERR if any error is detected
1801*
1802* @execution Synchronous
1803* @sideeffect None
1804*
1805* @note This function must not suspend and must not invoke any blocking system
1806* calls. It should probably just send a message to a driver event handler task.
1807*
1808*/
1809INT wifi_down()
1810{
developer96b38512023-02-22 11:17:45 +08001811 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001812 wifi_BringDownInterfaces();
1813 sleep(2);
1814
developer96b38512023-02-22 11:17:45 +08001815 system("systemctl stop hostapd.service");
1816 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001817 return RETURN_OK;
1818}
1819
1820
1821/* wifi_createInitialConfigFiles() function */
1822/**
1823* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001824* and content of these files are implementation dependent. This function call is
1825* used to trigger this task if necessary. Some implementations may not need this
1826* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001827* do nothing and return RETURN_OK.
1828*
1829* @param None
1830*
1831* @return The status of the operation
1832* @retval RETURN_OK if successful
1833* @retval RETURN_ERR if any error is detected
1834*
1835* @execution Synchronous
1836* @sideeffect None
1837*
1838* @note This function must not suspend and must not invoke any blocking system
1839* calls. It should probably just send a message to a driver event handler task.
1840*
1841*/
1842INT wifi_createInitialConfigFiles()
1843{
1844 //TODO: creates initial implementation dependent configuration files that are later used for variable storage. Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
1845 return RETURN_OK;
1846}
1847
developer7e4a2a62023-04-06 19:56:03 +08001848/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001849INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1850{
developer7e4a2a62023-04-06 19:56:03 +08001851 char interface_name[IF_NAME_SIZE] = {0};
1852 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001853
developer7e4a2a62023-04-06 19:56:03 +08001854 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
1855 printf("%s: input para error!!!\n", __func__);
1856 return RETURN_ERR;
1857 }
developer72fb0bb2023-01-11 09:46:29 +08001858
developer7e4a2a62023-04-06 19:56:03 +08001859 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1860 printf("%s: get inf_name error!!!\n", __func__);
1861 return RETURN_ERR;
1862 }
1863
1864 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1865 interface_name);
1866 _syscmd(cmd, buf, sizeof(buf));
1867
1868 if(strlen(buf))
1869 snprintf(output_string, 64, "%s", buf);
1870 else
1871 return RETURN_ERR;
1872
1873 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001874}
1875
1876INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1877{
developer7e4a2a62023-04-06 19:56:03 +08001878 /*Set wifi config. Wait for wifi reset to apply*/
1879 char str[MAX_BUF_SIZE] = {0};
1880 char cmd[MAX_CMD_SIZE] = {0};
1881 struct params params;
1882 char config_file[MAX_BUF_SIZE] = {0};
1883 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001884
developer7e4a2a62023-04-06 19:56:03 +08001885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001886
developer7e4a2a62023-04-06 19:56:03 +08001887 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1888 printf("%s: input para error!!!\n", __func__);
1889 return RETURN_ERR;
1890 }
developer72fb0bb2023-01-11 09:46:29 +08001891
developer7e4a2a62023-04-06 19:56:03 +08001892 if (!strlen(CountryCode))
1893 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001894
developer7e4a2a62023-04-06 19:56:03 +08001895 params.name = "country_code";
1896 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001897
developer7e4a2a62023-04-06 19:56:03 +08001898 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1899 ret = wifi_hostapdWrite(config_file, &params, 1);
1900
1901 if (ret) {
1902 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1903 __func__, ret);
1904 }
1905
1906 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1907
1908 if (ret) {
1909 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1910 __func__, ret);
1911 }
1912
1913 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1914
1915 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001916}
1917
1918INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1919{
1920 char interface_name[16] = {0};
1921 char channel_util_file[64] = {0};
1922 char cmd[128] = {0};
1923 char buf[128] = {0};
1924 char line[128] = {0};
1925 char *param = NULL, *value = NULL;
1926 int read = 0;
1927 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1928 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1929 size_t len = 0;
1930 FILE *f = NULL;
1931
1932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1933
1934 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1935 return RETURN_ERR;
1936 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1937 _syscmd(cmd, buf, sizeof(buf));
1938 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1939
1940 memset(cmd, 0, sizeof(cmd));
1941 memset(buf, 0, sizeof(buf));
1942 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1943 if ((f = popen(cmd, "r")) == NULL) {
1944 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1945 return RETURN_ERR;
1946 }
1947
1948 read = getline(&line, &len, f);
1949 while (read != -1) {
1950 param = strtok(line, ":\t");
1951 value = strtok(NULL, " ");
1952 if(strstr(param, "frequency") != NULL) {
1953 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1954 }
1955 if(strstr(param, "noise") != NULL) {
1956 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1957 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1958 }
1959 if(strstr(param, "channel active time") != NULL) {
1960 ActiveTime = strtol(value, NULL, 10);
1961 }
1962 if(strstr(param, "channel busy time") != NULL) {
1963 BusyTime = strtol(value, NULL, 10);
1964 }
1965 if(strstr(param, "channel transmit time") != NULL) {
1966 TransmitTime = strtol(value, NULL, 10);
1967 }
1968 read = getline(&line, &len, f);
1969 }
1970 pclose(f);
1971
1972 // The file should store the last active, busy and transmit time
1973 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1974 f = fopen(channel_util_file, "r");
1975 if (f != NULL) {
1976 read = getline(&line, &len, f);
1977 preActiveTime = strtol(line, NULL, 10);
1978 read = getline(&line, &len, f);
1979 preBusyTime = strtol(line, NULL, 10);
1980 read = getline(&line, &len, f);
1981 preTransmitTime = strtol(line, NULL, 10);
1982 fclose(f);
1983 }
1984
1985 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1986 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1987
1988 f = fopen(channel_util_file, "w");
1989 if (f != NULL) {
1990 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1991 fclose(f);
1992 }
1993 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1994 return RETURN_OK;
1995}
1996
1997/**********************************************************************************
1998 *
1999 * Wifi radio level function prototypes
2000 *
2001**********************************************************************************/
2002
2003//Get the total number of radios in this wifi subsystem
2004INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
2005{
2006 if (NULL == output)
2007 return RETURN_ERR;
2008 *output = MAX_NUM_RADIOS;
2009
2010 return RETURN_OK;
2011}
2012
developer69b61b02023-03-07 17:17:44 +08002013//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08002014INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
2015{
2016 if (NULL == output)
2017 return RETURN_ERR;
2018 *output = MAX_APS;
2019
2020 return RETURN_OK;
2021}
2022
2023//Get the Radio enable config parameter
2024INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
2025{
2026 char interface_name[16] = {0};
2027 char buf[128] = {0}, cmd[128] = {0};
2028
2029 if (NULL == output_bool)
2030 return RETURN_ERR;
2031
2032 *output_bool = FALSE;
2033 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
2034 return RETURN_ERR;
2035
2036 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2037 return RETURN_ERR;
2038 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
2039 _syscmd(cmd, buf, sizeof(buf));
2040
2041 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
2042 *output_bool = TRUE;
2043 return RETURN_OK;
2044}
2045
developere82c0ca2023-05-10 16:25:35 +08002046typedef long time_t;
2047static time_t radio_up_time[MAX_NUM_RADIOS];
2048
developer72fb0bb2023-01-11 09:46:29 +08002049INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
2050{
2051 char interface_name[16] = {0};
2052 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08002053 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002054 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08002055 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08002056 int phyId = 0;
2057
2058 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2059
2060 phyId = radio_index_to_phy(radioIndex);
2061
2062 wifi_getMaxRadioNumber(&max_radio_num);
2063
developer8a3bbbf2023-03-15 17:47:23 +08002064 if(enable == FALSE) {
developer47cc27a2023-05-17 23:09:58 +08002065
2066 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2067 return RETURN_ERR;
2068
2069 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002070 _syscmd(cmd, buf, sizeof(buf));
developere82c0ca2023-05-10 16:25:35 +08002071 if(strncmp(buf, "OK", 2))
2072 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
developer8a3bbbf2023-03-15 17:47:23 +08002073 } else {
developere82c0ca2023-05-10 16:25:35 +08002074 for (apIndex = radioIndex; apIndex < MAX_APS; apIndex += max_radio_num) {
developer72fb0bb2023-01-11 09:46:29 +08002075 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
2076 return RETURN_ERR;
2077
developer8a3bbbf2023-03-15 17:47:23 +08002078 memset(cmd, 0, MAX_CMD_SIZE);
2079 memset(buf, 0, MAX_BUF_SIZE);
2080
developer72fb0bb2023-01-11 09:46:29 +08002081 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
2082 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002083
2084 if(*buf == '1') {
2085
2086 memset(cmd, 0, MAX_CMD_SIZE);
2087 memset(buf, 0, MAX_BUF_SIZE);
2088
developer72fb0bb2023-01-11 09:46:29 +08002089 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
2090 phyId, apIndex);
2091 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08002092
developer72fb0bb2023-01-11 09:46:29 +08002093 }
2094 }
developere82c0ca2023-05-10 16:25:35 +08002095 time(&radio_up_time[radioIndex]);
developer72fb0bb2023-01-11 09:46:29 +08002096 }
2097
2098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2099 return RETURN_OK;
2100}
2101
2102//Get the Radio enable status
2103INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
2104{
2105 if (NULL == output_bool)
2106 return RETURN_ERR;
2107
2108 return wifi_getRadioEnable(radioIndex, output_bool);
2109}
2110
2111//Get the Radio Interface name from platform, eg "wlan0"
2112INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
2113{
2114 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
2115 return RETURN_ERR;
2116 return wifi_GetInterfaceName(radioIndex, output_string);
2117}
2118
2119//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
2120//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2121INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2122{
2123 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
2124 // For max bit rate, we should always choose the best MCS
2125 char mode[64] = {0};
2126 char channel_bandwidth_str[64] = {0};
2127 char *tmp = NULL;
2128 UINT mode_map = 0;
2129 UINT num_subcarrier = 0;
2130 UINT code_bits = 0;
2131 float code_rate = 0; // use max code rate
2132 int NSS = 0;
2133 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08002134 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08002135 wifi_band band = band_invalid;
2136 wifi_guard_interval_t gi = wifi_guard_interval_auto;
2137 BOOL enable = FALSE;
2138 float bit_rate = 0;
developera1255e42023-05-13 17:45:02 +08002139 int ant_bitmap = 0;
developer72fb0bb2023-01-11 09:46:29 +08002140
2141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2142 if (NULL == output_string)
2143 return RETURN_ERR;
2144
2145 wifi_getRadioEnable(radioIndex, &enable);
2146 if (enable == FALSE) {
2147 snprintf(output_string, 64, "0 Mb/s");
2148 return RETURN_OK;
2149 }
2150
2151 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
2152 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
2153 return RETURN_ERR;
2154 }
2155
2156 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
2157 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
2158 return RETURN_ERR;
2159 }
2160
2161 if (gi == wifi_guard_interval_3200)
2162 GI_duration = 32;
2163 else if (gi == wifi_guard_interval_1600)
2164 GI_duration = 16;
2165 else if (gi == wifi_guard_interval_800)
2166 GI_duration = 8;
2167 else // auto, 400
2168 GI_duration = 4;
2169
2170 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
2171 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
2172 return RETURN_ERR;
2173 }
2174
2175 if (strstr(channel_bandwidth_str, "80+80") != NULL)
2176 strcpy(channel_bandwidth_str, "160");
2177
2178 if (mode_map & WIFI_MODE_AX) {
2179 if (strstr(channel_bandwidth_str, "160") != NULL)
2180 num_subcarrier = 1960;
2181 else if (strstr(channel_bandwidth_str, "80") != NULL)
2182 num_subcarrier = 980;
2183 else if (strstr(channel_bandwidth_str, "40") != NULL)
2184 num_subcarrier = 468;
2185 else if (strstr(channel_bandwidth_str, "20") != NULL)
2186 num_subcarrier = 234;
2187 code_bits = 10;
2188 code_rate = (float)5/6;
2189 Symbol_duration = 128;
developera1255e42023-05-13 17:45:02 +08002190 GI_duration = 8;/*HE no GI 400ns*/
developer72fb0bb2023-01-11 09:46:29 +08002191 } else if (mode_map & WIFI_MODE_AC) {
2192 if (strstr(channel_bandwidth_str, "160") != NULL)
2193 num_subcarrier = 468;
2194 else if (strstr(channel_bandwidth_str, "80") != NULL)
2195 num_subcarrier = 234;
2196 else if (strstr(channel_bandwidth_str, "40") != NULL)
2197 num_subcarrier = 108;
2198 else if (strstr(channel_bandwidth_str, "20") != NULL)
2199 num_subcarrier = 52;
2200 code_bits = 8;
2201 code_rate = (float)5/6;
2202 Symbol_duration = 32;
2203 } else if (mode_map & WIFI_MODE_N) {
2204 if (strstr(channel_bandwidth_str, "160") != NULL)
2205 num_subcarrier = 468;
2206 else if (strstr(channel_bandwidth_str, "80") != NULL)
2207 num_subcarrier = 234;
2208 else if (strstr(channel_bandwidth_str, "40") != NULL)
2209 num_subcarrier = 108;
2210 else if (strstr(channel_bandwidth_str, "20") != NULL)
2211 num_subcarrier = 52;
2212 code_bits = 6;
2213 code_rate = (float)3/4;
2214 Symbol_duration = 32;
2215 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
2216 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
2217 snprintf(output_string, 64, "65 Mb/s");
2218 return RETURN_OK;
2219 } else {
2220 snprintf(output_string, 64, "0 Mb/s");
2221 return RETURN_OK;
2222 }
2223
2224 // Spatial streams
developera1255e42023-05-13 17:45:02 +08002225 if (wifi_getRadioTxChainMask(radioIndex, &ant_bitmap) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +08002226 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
2227 return RETURN_ERR;
2228 }
developera1255e42023-05-13 17:45:02 +08002229 for (; ant_bitmap > 0; ant_bitmap >>= 1)
2230 NSS += ant_bitmap & 1;
developer72fb0bb2023-01-11 09:46:29 +08002231
2232 // multiple 10 is to align duration unit (0.1 us)
2233 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
2234 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
developera1255e42023-05-13 17:45:02 +08002235 WIFI_ENTRY_EXIT_DEBUG("%s:num_subcarrier=%d, code_bits=%d, code_rate=%.3f, nss=%d, symbol time=%u, %.1f Mb/s\n",
2236 __func__, num_subcarrier, code_bits, code_rate, NSS, Symbol_duration + GI_duration, bit_rate);
developer72fb0bb2023-01-11 09:46:29 +08002237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2238
2239 return RETURN_OK;
2240}
2241#if 0
2242INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
2243{
2244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2245 char cmd[64];
2246 char buf[1024];
2247 int apIndex;
2248
developer69b61b02023-03-07 17:17:44 +08002249 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002250 return RETURN_ERR;
2251
2252 apIndex=(radioIndex==0)?0:1;
2253
2254 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
2255 _syscmd(cmd,buf, sizeof(buf));
2256
2257 snprintf(output_string, 64, "%s", buf);
2258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2259 return RETURN_OK;
2260}
2261#endif
2262
2263
2264//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
2265//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2266INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
2267{
2268 wifi_band band = band_invalid;
2269
2270 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2271 if (NULL == output_string)
2272 return RETURN_ERR;
2273
2274 band = wifi_index_to_band(radioIndex);
2275
2276 memset(output_string, 0, 10);
2277 if (band == band_2_4)
2278 strcpy(output_string, "2.4GHz");
2279 else if (band == band_5)
2280 strcpy(output_string, "5GHz");
2281 else if (band == band_6)
2282 strcpy(output_string, "6GHz");
2283 else
2284 return RETURN_ERR;
2285 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2286
2287 return RETURN_OK;
2288#if 0
2289 char buf[MAX_BUF_SIZE]={'\0'};
2290 char str[MAX_BUF_SIZE]={'\0'};
2291 char cmd[MAX_CMD_SIZE]={'\0'};
2292 char *ch=NULL;
2293 char *ch2=NULL;
2294
2295 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2296 if (NULL == output_string)
2297 return RETURN_ERR;
2298
2299
2300 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2301
2302 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2303 {
2304 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2305 return RETURN_ERR;
2306 }
2307 ch=strchr(buf,'\n');
2308 *ch='\0';
2309 ch=strchr(buf,'=');
2310 if(ch==NULL)
2311 return RETURN_ERR;
2312
2313
2314 ch++;
2315
2316 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
2317 strcpy(buf,"0");
2318 if(strlen(ch) == 1)
2319 ch=strcat(buf,ch);
2320
2321
2322 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2323
2324 if(_syscmd(cmd,str,64) == RETURN_ERR)
2325 {
2326 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2327 return RETURN_ERR;
2328 }
2329
2330
2331 ch2=strchr(str,'\n');
2332 //replace \n with \0
2333 *ch2='\0';
2334 ch2=strchr(str,'=');
2335 if(ch2==NULL)
2336 {
2337 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2338 return RETURN_ERR;
2339 }
2340 else
2341 wifi_dbg_printf("%s",ch2+1);
2342
2343
2344 ch2++;
2345
2346
2347 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2348
2349 memset(buf,'\0',sizeof(buf));
2350 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2351 {
2352 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2353 return RETURN_ERR;
2354 }
2355 if (strstr(buf,"2.4") != NULL )
2356 strcpy(output_string,"2.4GHz");
2357 else if(strstr(buf,"5.") != NULL )
2358 strcpy(output_string,"5GHz");
2359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2360
2361 return RETURN_OK;
2362#endif
2363}
2364
2365//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2366//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2367INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2368{
2369 wifi_band band = band_invalid;
2370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2371 if (NULL == output_string)
2372 return RETURN_ERR;
2373 band = wifi_index_to_band(radioIndex);
2374
developer69b61b02023-03-07 17:17:44 +08002375 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002376 snprintf(output_string, 64, "2.4GHz");
2377 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002378 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002379 else if (band == band_6)
2380 snprintf(output_string, 64, "6GHz");
2381
2382 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2383
2384 return RETURN_OK;
2385#if 0
2386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2387 char buf[MAX_BUF_SIZE]={'\0'};
2388 char str[MAX_BUF_SIZE]={'\0'};
2389 char cmd[MAX_CMD_SIZE]={'\0'};
2390 char *ch=NULL;
2391 char *ch2=NULL;
2392 char ch1[5]="0";
2393
2394 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2395
2396 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2397 {
2398 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2399 return RETURN_ERR;
2400 }
2401
2402 ch=strchr(buf,'\n');
2403 *ch='\0';
2404 ch=strchr(buf,'=');
2405 if(ch==NULL)
2406 return RETURN_ERR;
2407 ch++;
2408
2409 if(strlen(ch)==1)
2410 {
2411 strcat(ch1,ch);
2412
2413 }
2414 else
2415 {
2416 strcpy(ch1,ch);
2417 }
2418
2419
2420
2421 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2422 if(_syscmd(cmd,str,64) == RETURN_ERR)
2423 {
2424 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2425 return RETURN_ERR;
2426 }
2427
2428
2429 ch2=strchr(str,'\n');
2430 //replace \n with \0
2431 *ch2='\0';
2432 ch2=strchr(str,'=');
2433 if(ch2==NULL)
2434 {
2435 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2436 return RETURN_ERR;
2437 }
2438 else
2439 wifi_dbg_printf("%s",ch2+1);
2440 ch2++;
2441
2442
2443 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2444 memset(buf,'\0',sizeof(buf));
2445 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2446 {
2447 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2448 return RETURN_ERR;
2449 }
2450
2451
2452 if(strstr(buf,"2.4")!=NULL)
2453 {
2454 strcpy(output_string,"2.4GHz");
2455 }
2456 if(strstr(buf,"5.")!=NULL)
2457 {
2458 strcpy(output_string,"5GHz");
2459 }
2460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2461 return RETURN_OK;
2462#endif
2463}
2464
2465//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2466//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2467INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2468{
2469 char cmd[128]={0};
2470 char buf[128]={0};
2471 char temp_output[128] = {0};
2472 wifi_band band;
2473 int phyId = 0;
2474
2475 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002476 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002477 return RETURN_ERR;
2478
2479 band = wifi_index_to_band(radioIndex);
2480 if (band == band_2_4) {
2481 strcat(temp_output, "b,g,");
2482 } else if (band == band_5) {
2483 strcat(temp_output, "a,");
2484 }
2485 phyId = radio_index_to_phy(radioIndex);
2486 // ht capabilities
2487 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", phyId);
2488 _syscmd(cmd, buf, sizeof(buf));
2489 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2490 strcat(temp_output, "n,");
2491 }
2492
2493 // vht capabilities
2494 if (band == band_5) {
2495 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2496 _syscmd(cmd, buf, sizeof(buf));
2497 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2498 strcat(temp_output, "ac,");
2499 }
2500 }
2501
2502 // he capabilities
2503 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'HE MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
2504 _syscmd(cmd, buf, sizeof(buf));
2505 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2506 strcat(temp_output, "ax,");
2507 }
2508
developere82c0ca2023-05-10 16:25:35 +08002509 // eht capabilities
2510 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'EHT MAC Capabilities' | head -n 2 | tail -n 1 | cut -d '(' -f2 | cut -c1-6 | tr -d '\\n'", phyId);
2511 _syscmd(cmd, buf, sizeof(buf));
2512 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2513 strcat(temp_output, "be,");
2514 }
2515
developer72fb0bb2023-01-11 09:46:29 +08002516 // Remove the last comma
2517 if (strlen(temp_output) != 0)
2518 temp_output[strlen(temp_output)-1] = '\0';
2519 strncpy(output_string, temp_output, strlen(temp_output));
2520 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2521 return RETURN_OK;
2522}
2523
2524//Get the radio operating mode, and pure mode flag. eg: "ac"
2525//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
2526INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2527{
2528 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2529 if (NULL == output_string)
2530 return RETURN_ERR;
2531
2532 if (radioIndex == 0) {
2533 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2534 *gOnly = FALSE;
2535 *nOnly = TRUE;
2536 *acOnly = FALSE;
2537 } else {
2538 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2539 *gOnly = FALSE;
2540 *nOnly = FALSE;
2541 *acOnly = FALSE;
2542 }
2543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2544
2545 return RETURN_OK;
2546#if 0
2547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2548 char buf[64] = {0};
2549 char config_file[MAX_BUF_SIZE] = {0};
2550
developer69b61b02023-03-07 17:17:44 +08002551 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002552 return RETURN_ERR;
2553
2554 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2555 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2556
2557 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002558 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002559 {
2560 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2561 return RETURN_ERR;
2562 }
2563 if(strcmp(buf,"g")==0)
2564 {
2565 wifi_dbg_printf("\nG\n");
2566 *gOnly=TRUE;
2567 *nOnly=FALSE;
2568 *acOnly=FALSE;
2569 }
2570 else if(strcmp(buf,"n")==0)
2571 {
2572 wifi_dbg_printf("\nN\n");
2573 *gOnly=FALSE;
2574 *nOnly=TRUE;
2575 *acOnly=FALSE;
2576 }
2577 else if(strcmp(buf,"ac")==0)
2578 {
2579 wifi_dbg_printf("\nac\n");
2580 *gOnly=FALSE;
2581 *nOnly=FALSE;
2582 *acOnly=TRUE;
2583 }
2584 /* hostapd-5G.conf has "a" as hw_mode */
2585 else if(strcmp(buf,"a")==0)
2586 {
2587 wifi_dbg_printf("\na\n");
2588 *gOnly=FALSE;
2589 *nOnly=FALSE;
2590 *acOnly=FALSE;
2591 }
2592 else
2593 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2594
2595 //for a,n mode
2596 if(radioIndex == 1)
2597 {
2598 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2599 if(strcmp(buf,"1")==0)
2600 {
2601 strncpy(output_string, "n", 1);
2602 *nOnly=FALSE;
2603 }
2604 }
2605
2606 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2608 return RETURN_OK;
2609#endif
2610}
2611
developer0f10c772023-05-16 21:43:39 +08002612enum WIFI_MODE {
2613 WMODE_INVALID = 0,
2614 WMODE_A = 1 << 0,
2615 WMODE_B = 1 << 1,
2616 WMODE_G = 1 << 2,
2617 WMODE_GN = 1 << 3,
2618 WMODE_AN = 1 << 4,
2619 WMODE_AC = 1 << 5,
2620 WMODE_AX_24G = 1 << 6,
2621 WMODE_AX_5G = 1 << 7,
2622 WMODE_AX_6G = 1 << 8,
2623 WMODE_BE_24G = 1 << 9,
2624 WMODE_BE_5G = 1 << 10,
2625 WMODE_BE_6G = 1 << 11,
2626 /*
2627 * total types of supported wireless mode,
2628 * add this value once yow add new type
2629 */
2630 WMODE_COMP = 12,
2631};
2632
2633#define RADIO_MODE_LEN 32
developer72fb0bb2023-01-11 09:46:29 +08002634INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2635{
developer0f10c772023-05-16 21:43:39 +08002636 char cmd[MAX_CMD_SIZE] = {0};
2637 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002638 wifi_band band;
developer0f10c772023-05-16 21:43:39 +08002639 unsigned int phymode;
2640 unsigned char radio_mode_tem_len;
2641 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002642
2643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2644 if(NULL == output_string || NULL == pureMode)
2645 return RETURN_ERR;
2646
developer0f10c772023-05-16 21:43:39 +08002647 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2648 return RETURN_ERR;
2649
2650 snprintf(cmd, sizeof(cmd), "mwctl %s dump radio_info | grep 'phymode' | cut -d ' ' -f2", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08002651 _syscmd(cmd, buf, sizeof(buf));
2652
developer0f10c772023-05-16 21:43:39 +08002653 phymode = strtoul(buf, NULL, 10);
2654 band = wifi_index_to_band(radioIndex);
2655
2656 // puremode is a bit map
developer72fb0bb2023-01-11 09:46:29 +08002657 *pureMode = 0;
developer0f10c772023-05-16 21:43:39 +08002658 memset(output_string, 0, RADIO_MODE_LEN);
2659
2660 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2661
2662 switch (band) {
2663 case band_2_4:
2664 if (phymode & WMODE_B) {
2665 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "b,");
2666 *pureMode |= WIFI_MODE_B;
2667 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2668 }
2669 if (phymode & WMODE_G) {
2670 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "g,");
2671 *pureMode |= WIFI_MODE_G;
2672 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2673 }
2674 if (phymode & WMODE_GN) {
2675 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2676 *pureMode |= WIFI_MODE_N;
2677 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2678 }
2679 if (phymode & WMODE_AX_24G) {
2680 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2681 *pureMode |= WIFI_MODE_AX;
2682 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2683 }
2684 if (phymode & WMODE_BE_24G) {
2685 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2686 *pureMode |= WIFI_MODE_BE;
2687 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2688 }
2689 break;
2690 case band_5:
2691 if (phymode & WMODE_A) {
2692 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "a,");
2693 *pureMode |= WIFI_MODE_A;
2694 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2695 }
2696 if (phymode & WMODE_AN) {
2697 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "n,");
2698 *pureMode |= WIFI_MODE_N;
2699 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2700 }
2701 if (phymode & WMODE_AC) {
2702 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ac,");
2703 *pureMode |= WIFI_MODE_AC;
2704 }
2705 if (phymode & WMODE_AX_5G) {
2706 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2707 *pureMode |= WIFI_MODE_AX;
2708 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2709 }
2710 if (phymode & WMODE_BE_5G) {
2711 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2712 *pureMode |= WIFI_MODE_BE;
2713 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2714 }
2715 break;
2716 case band_6:
2717 if (phymode & WMODE_AX_6G) {
2718 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "ax,");
2719 *pureMode |= WIFI_MODE_AX;
2720 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2721 }
2722 if (phymode & WMODE_BE_6G) {
2723 snprintf(output_string + strlen(output_string), radio_mode_tem_len, "%s", "be,");
2724 *pureMode |= WIFI_MODE_BE;
2725 radio_mode_tem_len = RADIO_MODE_LEN - strlen(output_string);
2726 }
2727 break;
2728 default:
2729 fprintf(stderr, "%s band_idx invalid\n", __func__);
2730 break;
2731 }
2732
2733 /* Remove the last comma */
2734 if (strlen(output_string) != 0)
2735 output_string[strlen(output_string)-1] = '\0';
developer72fb0bb2023-01-11 09:46:29 +08002736
2737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2738 return RETURN_OK;
2739}
2740
2741// Set the radio operating mode, and pure mode flag.
2742INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2743{
developer69b61b02023-03-07 17:17:44 +08002744 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002745 if (strcmp (channelMode,"11A") == 0)
2746 {
2747 writeBandWidth(radioIndex,"20MHz");
2748 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2749 printf("\nChannel Mode is 802.11a (5GHz)\n");
2750 }
2751 else if (strcmp (channelMode,"11NAHT20") == 0)
2752 {
2753 writeBandWidth(radioIndex,"20MHz");
2754 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2755 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2756 }
2757 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2758 {
2759 writeBandWidth(radioIndex,"40MHz");
2760 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2761 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2762 }
2763 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2764 {
2765 writeBandWidth(radioIndex,"40MHz");
2766 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2767 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2768 }
2769 else if (strcmp (channelMode,"11ACVHT20") == 0)
2770 {
2771 writeBandWidth(radioIndex,"20MHz");
2772 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2773 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2774 }
2775 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2776 {
2777 writeBandWidth(radioIndex,"40MHz");
2778 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2779 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2780 }
2781 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2782 {
2783 writeBandWidth(radioIndex,"40MHz");
2784 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2785 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2786 }
2787 else if (strcmp (channelMode,"11ACVHT80") == 0)
2788 {
2789 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2790 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2791 }
2792 else if (strcmp (channelMode,"11ACVHT160") == 0)
2793 {
2794 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2795 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002796 }
developer72fb0bb2023-01-11 09:46:29 +08002797 else if (strcmp (channelMode,"11B") == 0)
2798 {
2799 writeBandWidth(radioIndex,"20MHz");
2800 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2801 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2802 }
2803 else if (strcmp (channelMode,"11G") == 0)
2804 {
2805 writeBandWidth(radioIndex,"20MHz");
2806 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2807 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2808 }
2809 else if (strcmp (channelMode,"11NGHT20") == 0)
2810 {
2811 writeBandWidth(radioIndex,"20MHz");
2812 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2813 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2814 }
2815 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2816 {
2817 writeBandWidth(radioIndex,"40MHz");
2818 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2819 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2820 }
2821 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2822 {
2823 writeBandWidth(radioIndex,"40MHz");
2824 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2825 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2826 }
developer69b61b02023-03-07 17:17:44 +08002827 else
developer72fb0bb2023-01-11 09:46:29 +08002828 {
2829 return RETURN_ERR;
2830 }
2831 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2832
2833 return RETURN_OK;
2834}
2835
developer0f10c772023-05-16 21:43:39 +08002836typedef enum _RT_802_11_PHY_MODE {
2837 PHY_11BG_MIXED = 0,
2838 PHY_11B = 1,
2839 PHY_11A = 2,
2840 PHY_11ABG_MIXED = 3,
2841 PHY_11G = 4,
2842 PHY_11ABGN_MIXED = 5, /* both band 5 */
2843 PHY_11N_2_4G = 6, /* 11n-only with 2.4G band 6 */
2844 PHY_11GN_MIXED = 7, /* 2.4G band 7 */
2845 PHY_11AN_MIXED = 8, /* 5G band 8 */
2846 PHY_11BGN_MIXED = 9, /* if check 802.11b. 9 */
2847 PHY_11AGN_MIXED = 10, /* if check 802.11b. 10 */
2848 PHY_11N_5G = 11, /* 11n-only with 5G band 11 */
2849 PHY_11VHT_N_ABG_MIXED = 12, /* 12 -> AC/A/AN/B/G/GN mixed */
2850 PHY_11VHT_N_AG_MIXED = 13, /* 13 -> AC/A/AN/G/GN mixed */
2851 PHY_11VHT_N_A_MIXED = 14, /* 14 -> AC/AN/A mixed in 5G band */
2852 PHY_11VHT_N_MIXED = 15, /* 15 -> AC/AN mixed in 5G band */
2853 PHY_11AX_24G = 16,
2854 PHY_11AX_5G = 17,
2855 PHY_11AX_6G = 18,
2856 PHY_11AX_24G_6G = 19,
2857 PHY_11AX_5G_6G = 20,
2858 PHY_11AX_24G_5G_6G = 21,
2859 PHY_11BE_24G = 22,
2860 PHY_11BE_5G = 23,
2861 PHY_11BE_6G = 24,
2862 PHY_11BE_24G_6G = 25,
2863 PHY_11BE_5G_6G = 26,
2864 PHY_11BE_24G_5G_6G = 27,
2865 PHY_MODE_MAX,
2866} RT_802_11_PHY_MODE;
2867
2868unsigned int puremode_to_wireless_mode(INT radioIndex, UINT pureMode)
2869{
2870 int band_idx = 0;
2871 unsigned int wireless_mode = PHY_MODE_MAX;
2872
2873 band_idx = radio_index_to_band(radioIndex);
2874
2875 switch (band_idx) {
2876 case band_2_4:
2877 if (pureMode == (WIFI_MODE_G | WIFI_MODE_N))
2878 wireless_mode = PHY_11GN_MIXED;
2879 if (pureMode == (WIFI_MODE_B | WIFI_MODE_G | WIFI_MODE_N))
2880 wireless_mode = PHY_11BGN_MIXED;
2881 if (pureMode & WIFI_MODE_AX)
2882 wireless_mode = PHY_11AX_24G;
2883 if (pureMode & WIFI_MODE_BE)
2884 wireless_mode = PHY_11BE_24G;
2885 break;
2886 case band_5:
2887 if (pureMode == WIFI_MODE_N)
2888 wireless_mode = PHY_11N_5G;
2889 if ((pureMode == WIFI_MODE_AC) || (pureMode == (WIFI_MODE_N | WIFI_MODE_AC)))
2890 wireless_mode = PHY_11VHT_N_MIXED;
2891 if (pureMode == (WIFI_MODE_A | WIFI_MODE_N | WIFI_MODE_AC))
2892 wireless_mode = PHY_11VHT_N_A_MIXED;
2893 if (pureMode & WIFI_MODE_AX)
2894 wireless_mode = PHY_11AX_5G;
2895 if (pureMode & WIFI_MODE_BE)
2896 wireless_mode = PHY_11BE_5G;
2897 break;
2898 case band_6:
2899 if (pureMode & WIFI_MODE_AX)
2900 wireless_mode = PHY_11AX_6G;
2901 if (pureMode & WIFI_MODE_BE)
2902 wireless_mode = PHY_11BE_6G;
2903 break;
2904 default:
2905 fprintf(stderr, "%s band_idx invalid\n", __func__);
2906 break;
2907 }
2908
2909 return wireless_mode;
2910}
2911
developer72fb0bb2023-01-11 09:46:29 +08002912// Set the radio operating mode, and pure mode flag.
2913INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2914{
developer0f10c772023-05-16 21:43:39 +08002915 unsigned int wireless_mode = PHY_MODE_MAX;
developer69b61b02023-03-07 17:17:44 +08002916
developer0f10c772023-05-16 21:43:39 +08002917 char interface_name[IF_NAME_SIZE] = {0};
2918 char cmd[MAX_CMD_SIZE] = {0};
2919 char buf[MAX_BUF_SIZE] = {0};
2920 int i;
developer72fb0bb2023-01-11 09:46:29 +08002921
developer0f10c772023-05-16 21:43:39 +08002922 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002923
developer0f10c772023-05-16 21:43:39 +08002924 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
developer72fb0bb2023-01-11 09:46:29 +08002925
developer0f10c772023-05-16 21:43:39 +08002926 if (wireless_mode == PHY_MODE_MAX) {
2927 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2928 return RETURN_ERR;
2929 }
developer72fb0bb2023-01-11 09:46:29 +08002930
developer0f10c772023-05-16 21:43:39 +08002931 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2932 return RETURN_ERR;
2933 snprintf(cmd, sizeof(cmd), "mwctl %s set phymode %d", interface_name, wireless_mode);
2934 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08002935
developer0f10c772023-05-16 21:43:39 +08002936 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2937
2938 return RETURN_OK;
2939}
2940
2941INT wifi_setRadioMode_by_dat(INT radioIndex, UINT pureMode)
2942{
2943 unsigned int wireless_mode = PHY_MODE_MAX;
2944 char interface_name[IF_NAME_SIZE] = {0};
2945 char cmd[MAX_CMD_SIZE] = {0};
2946 char buf[MAX_BUF_SIZE] = {0};
2947 int i;
2948 char dat_file[MAX_BUF_SIZE] = {0};
2949 struct params params={0};
2950
2951 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, pureMode, __LINE__);
2952
2953 wireless_mode = puremode_to_wireless_mode(radioIndex, pureMode);
2954
2955 if (wireless_mode == PHY_MODE_MAX) {
2956 fprintf(stderr, "%s wireless_mode invalid pureMode = %x\n", __func__, pureMode);
2957 return RETURN_ERR;
2958 }
2959
2960 params.name = "WirelessMode";
2961 snprintf(buf, sizeof(buf), "%d", wireless_mode);
2962 params.value = buf;
2963
2964 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
2965 wifi_datfileWrite(dat_file, &params, 1);
2966
developer72fb0bb2023-01-11 09:46:29 +08002967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2968
2969 return RETURN_OK;
2970}
2971
2972INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2973
2974 char config_file[64] = {0};
2975 char buf[64] = {0};
2976 struct params params = {0};
2977 wifi_band band = band_invalid;
2978
2979 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2980
2981 band = wifi_index_to_band(radioIndex);
2982
2983 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2984 return RETURN_ERR;
2985 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2986 return RETURN_ERR;
2987 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2988 return RETURN_ERR;
2989
2990 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2991 params.name = "hw_mode";
2992 params.value = hw_mode;
2993 wifi_hostapdWrite(config_file, &params, 1);
2994 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2995
2996 if (band == band_2_4) {
2997 if (strncmp(hw_mode, "b", 1) == 0) {
2998 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2999 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
3000 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3001 snprintf(buf, sizeof(buf), "%s", "1,2");
3002 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3003 } else {
3004 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
3005
3006 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
3007 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
3008 snprintf(buf, sizeof(buf), "%s", "6,12,24");
3009 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
3010 }
3011 }
3012
3013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3014 return RETURN_OK;
3015}
3016
3017INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
3018{
3019 char config_file[64] = {0};
3020 struct params params = {0};
3021 wifi_band band = band_invalid;
3022
3023 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3024
3025 band = wifi_index_to_band(radioIndex);
3026 if (band != band_2_4)
3027 return RETURN_OK;
3028
3029 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3030 params.name = "noscan";
3031 params.value = noscan;
3032 wifi_hostapdWrite(config_file, &params, 1);
3033 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3034
3035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3036 return RETURN_OK;
3037}
3038
3039//Get the list of supported channel. eg: "1-11"
3040//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3041INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
3042{
3043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08003044 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08003045 return RETURN_ERR;
3046 char cmd[256] = {0};
3047 char buf[128] = {0};
3048 BOOL dfs_enable = false;
3049 int phyId = 0;
3050
3051 // Parse possible channel number and separate them with commas.
3052 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
3053 phyId = radio_index_to_phy(radioIndex);
3054 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
3055 if (dfs_enable)
3056 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer69b61b02023-03-07 17:17:44 +08003057 else
developer72fb0bb2023-01-11 09:46:29 +08003058 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar\\|no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
3059
3060 _syscmd(cmd,buf,sizeof(buf));
3061 strncpy(output_string, buf, sizeof(buf));
3062
3063 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3064 return RETURN_OK;
3065}
developerd1824452023-05-18 12:30:04 +08003066//Getting current radio extension channel
3067INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3068{
3069 CHAR buf[150] = {0};
3070 CHAR cmd[150] = {0};
3071
3072 wifi_datfileRead(file, "HT_EXTCHA", buf, sizeof(buf));
3073 if (strncmp(buf, "0", 1) == 0) //bewlow
3074 strcpy(Value,"BelowControlChannel");
3075 if(strncmp(buf, "1", 1) == 0) //above
3076 strcpy(Value,"AboveControlChannel");
3077 return RETURN_OK;
3078}
developerf6a87542023-05-16 15:47:28 +08003079
developer72fb0bb2023-01-11 09:46:29 +08003080//Get the list for used channel. eg: "1,6,9,11"
3081//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3082INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
3083{
3084 char interface_name[16] = {0};
3085 char cmd[128] = {0};
3086 char buf[128] = {0};
3087 char config_file[64] = {0};
3088 int channel = 0;
3089 int freq = 0;
3090 int bandwidth = 0;
3091 int center_freq = 0;
3092 int center_channel = 0;
3093 int channel_delta = 0;
3094 wifi_band band = band_invalid;
3095
3096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3097
3098 if (NULL == output_string)
3099 return RETURN_ERR;
3100
3101 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3102 return RETURN_ERR;
3103 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
3104 _syscmd(cmd, buf, sizeof(buf));
3105 if (strlen(buf) == 0) {
3106 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
3107 return RETURN_ERR;
3108 }
3109 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
3110
3111 if (bandwidth == 20) {
3112 snprintf(output_string, 256, "%d", channel);
3113 return RETURN_OK;
3114 }
3115
3116 center_channel = ieee80211_frequency_to_channel(center_freq);
3117
3118 band = wifi_index_to_band(radioIndex);
3119 if (band == band_2_4 && bandwidth == 40) {
developerd1824452023-05-18 12:30:04 +08003120 sprintf(config_file, "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08003121 memset(buf, 0, sizeof(buf));
3122 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
3123
3124 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
3125 snprintf(output_string, 256, "%d,%d", channel, channel+4);
3126 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
3127 snprintf(output_string, 256, "%d,%d", channel-4, channel);
3128 } else {
3129 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
3130 return RETURN_ERR;
3131 }
3132 } else if (band == band_5 || band == band_6){
3133 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
developerd1824452023-05-18 12:30:04 +08003134 // example: bandwidth 80: center is 42 (5210), channels are "36,40,44,48" (5170-5250). The delta should be 6.
developer72fb0bb2023-01-11 09:46:29 +08003135 channel_delta = (bandwidth-20)/10;
developerd1824452023-05-18 12:30:04 +08003136 memset(output_string, 0, 256);
3137 for (int i = center_channel-channel_delta; i <= center_channel+channel_delta; i+=4) {
3138 // If i is not the last channel, we add a comma.
3139 snprintf(buf, sizeof(buf), "%d%s", i, i==center_channel+channel_delta?"":",");
3140 strncat(output_string, buf, strlen(buf));
3141 }
developer72fb0bb2023-01-11 09:46:29 +08003142 } else
3143 return RETURN_ERR;
3144
3145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3146 return RETURN_OK;
3147}
3148
developer69b61b02023-03-07 17:17:44 +08003149//Get the running channel number
developerd1824452023-05-18 12:30:04 +08003150INT wifi_getRadioChannel(INT radioIndex, ULONG *output_ulong) //RDKB
developer72fb0bb2023-01-11 09:46:29 +08003151{
3152 char channel_str[16] = {0};
3153 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003154 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003155
3156 if (output_ulong == NULL)
3157 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003158 band = wifi_index_to_band(radioIndex);
3159 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3160 wifi_datfileRead(config_file, "Channel", channel_str, sizeof(channel_str));
developer72fb0bb2023-01-11 09:46:29 +08003161
3162 *output_ulong = strtoul(channel_str, NULL, 10);
3163
3164 return RETURN_OK;
3165}
3166
3167
3168INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
3169{
3170 char cmd[1024] = {0}, buf[5] = {0};
3171 char interface_name[16] = {0};
3172
3173 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3174 if (NULL == output_ulong)
3175 return RETURN_ERR;
3176
3177 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
3178 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
3179 return RETURN_ERR;
3180 _syscmd(cmd,buf,sizeof(buf));
3181 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
3182 if (*output_ulong == 0) {
3183 return RETURN_ERR;
3184 }
3185
3186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3187 return RETURN_OK;
3188}
3189
3190//Storing the previous channel value
3191INT wifi_storeprevchanval(INT radioIndex)
3192{
3193 char buf[256] = {0};
3194 char output[4]={'\0'};
3195 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08003196 wifi_band band = band_invalid;
3197
3198 band = wifi_index_to_band(radioIndex);
3199 if (band == band_invalid) {
3200 return RETURN_ERR;
3201 wifi_dbg_printf("[%s]: Invalid radio index", __func__);
3202 }
3203 snprintf(config_file, sizeof(config_file), "%s%d.dat",LOGAN_DAT_FILE, band);
3204 wifi_datfileRead(config_file, "Channel", output, sizeof(output));
3205
3206 if(band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08003207 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003208 else if(band == band_5)
developer72fb0bb2023-01-11 09:46:29 +08003209 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
developerd1824452023-05-18 12:30:04 +08003210 else
3211 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval6G_AutoChannelEnable");
developer72fb0bb2023-01-11 09:46:29 +08003212 system(buf);
3213 Radio_flag = FALSE;
3214 return RETURN_OK;
3215}
3216
3217//Set the running channel number
3218INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
3219{
3220 // We only write hostapd config here
3221 char str_channel[8]={0};
3222 char *list_channel;
3223 char config_file[128] = {0};
3224 char possible_channels[256] = {0};
developerd1824452023-05-18 12:30:04 +08003225 char config_file_dat[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003226 int max_radio_num = 0;
3227 struct params list = {0};
developerd1824452023-05-18 12:30:04 +08003228 struct params dat = {0};
3229 struct params acs = {0};
3230 wifi_band band = band_invalid;
3231 bool acs_channel = false;
developer72fb0bb2023-01-11 09:46:29 +08003232
3233 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3234
developerd1824452023-05-18 12:30:04 +08003235 if (channel == 0)
3236 acs_channel = true;
developer72fb0bb2023-01-11 09:46:29 +08003237 // Check valid
3238 sprintf(str_channel, "%lu", channel);
3239
developerd1824452023-05-18 12:30:04 +08003240
developer72fb0bb2023-01-11 09:46:29 +08003241 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
3242 list_channel = strtok(possible_channels, ",");
3243 while(true)
3244 {
3245 if(list_channel == NULL) { // input not in the list
3246 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
3247 return RETURN_ERR;
3248 }
3249 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
3250 break;
3251 list_channel = strtok(NULL, ",");
3252 }
developerd1824452023-05-18 12:30:04 +08003253 /*
developer72fb0bb2023-01-11 09:46:29 +08003254 list.name = "channel";
3255 list.value = str_channel;
3256 wifi_getMaxRadioNumber(&max_radio_num);
3257 for(int i=0; i<=MAX_APS/max_radio_num;i++)
3258 {
3259 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3260 wifi_hostapdWrite(config_file, &list, 1);
3261 }
developerd1824452023-05-18 12:30:04 +08003262 */
3263 dat.name = "Channel";
3264 dat.value = str_channel;
3265 band = wifi_index_to_band(radioIndex);
3266 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3267 wifi_datfileWrite(config_file_dat, &dat, 1);
3268 if (acs_channel == true) {
3269 acs.name = "AutoChannelSelect";
3270 acs.value = "3";
3271 } else {
3272 acs.name = "AutoChannelSelect";
3273 acs.value = "0";
3274 }
3275 wifi_datfileWrite(config_file_dat, &acs, 1);
developerc0772e62023-05-18 15:10:48 +08003276 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003277 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3278 return RETURN_OK;
3279}
3280
3281INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
3282{
3283 struct params list[2];
3284 char str_idx[16];
3285 char config_file[64];
3286 int max_num_radios = 0;
3287 wifi_band band = band_invalid;
3288
3289 band = wifi_index_to_band(radioIndex);
3290 if (band == band_2_4)
3291 return RETURN_OK;
3292
3293 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
3294 list[0].name = "vht_oper_centr_freq_seg0_idx";
3295 list[0].value = str_idx;
3296 list[1].name = "he_oper_centr_freq_seg0_idx";
3297 list[1].value = str_idx;
3298
3299 wifi_getMaxRadioNumber(&max_num_radios);
3300 for(int i=0; i<=MAX_APS/max_num_radios; i++)
3301 {
3302 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
3303 if (band == band_6)
3304 wifi_hostapdWrite(config_file, &list[1], 1);
3305 else
3306 wifi_hostapdWrite(config_file, list, 2);
3307 }
3308
3309 return RETURN_OK;
3310}
3311
3312//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
3313//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
3314INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
3315{
3316 //Set to wifi config only. Wait for wifi reset to apply.
3317 char buf[256] = {0};
3318 char str_channel[256] = {0};
3319 int count = 0;
3320 ULONG Value = 0;
3321 FILE *fp = NULL;
3322 if(enable == TRUE)
3323 {
3324 wifi_setRadioChannel(radioIndex,Value);
3325 }
3326 return RETURN_OK;
3327}
3328
3329INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
3330{
3331 if (output_bool == NULL)
3332 return RETURN_ERR;
3333
3334 *output_bool = TRUE;
3335
3336 return RETURN_OK;
3337}
3338
3339INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
3340{
developer69b61b02023-03-07 17:17:44 +08003341 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003342 return RETURN_ERR;
3343 *output_bool=FALSE;
3344 return RETURN_OK;
3345}
3346
3347INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
3348{
developer69b61b02023-03-07 17:17:44 +08003349 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003350 return RETURN_ERR;
3351 *output_bool=FALSE;
3352 return RETURN_OK;
3353}
3354
3355INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
3356{
3357 //Set to wifi config only. Wait for wifi reset to apply.
3358 return RETURN_OK;
3359}
3360
3361INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
3362{
3363 return RETURN_OK;
3364}
3365
3366INT wifi_factoryResetAP(int apIndex)
3367{
developer47cc27a2023-05-17 23:09:58 +08003368 char ap_config_file[MAX_CMD_SIZE] = {0};
3369 char cmd[MAX_CMD_SIZE] = {0};
3370 char ret_buf[MAX_BUF_SIZE] = {0};
3371 int radio_idx = 0;
3372 int bss_idx = 0;
3373 char ssid[32] = {0};
3374 char interface[IF_NAME_SIZE] = {0};
3375 char psk_file[MAX_CMD_SIZE] = {0};
3376 struct params params[3] = {0};
3377 char *band_str[3] = {"2G", "5G", "6G"};
developer72fb0bb2023-01-11 09:46:29 +08003378
3379 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3380
developer47cc27a2023-05-17 23:09:58 +08003381 /*del old config file*/
3382 snprintf(ap_config_file, MAX_CMD_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
3383 snprintf(cmd, MAX_CMD_SIZE, "rm %s", ap_config_file);
3384 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003385
developer47cc27a2023-05-17 23:09:58 +08003386 memset(cmd, 0, sizeof(cmd));
3387 memset(ret_buf, 0, sizeof(ret_buf));
developer72fb0bb2023-01-11 09:46:29 +08003388
developer47cc27a2023-05-17 23:09:58 +08003389 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
3390
3391 /*prepare new config file*/
3392 snprintf(cmd, sizeof(cmd), "cp /etc/hostapd-%s.conf %s", band_str[radio_idx], ap_config_file);
3393 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3394
3395 if (radio_idx == band_2_4) {
3396 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_2G, bss_idx);
3397 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI2G, bss_idx);
3398 } else if (radio_idx == band_5) {
3399 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_5G, bss_idx);
3400 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI5G, bss_idx);
3401 } else if (radio_idx == band_6) {
3402 snprintf(ssid, sizeof(ssid), "%s_%d", PREFIX_SSID_6G, bss_idx);
3403 snprintf(interface, sizeof(interface), "%s%d", PREFIX_WIFI6G, bss_idx);
3404 }
3405
3406 /* fix wpa_psk_file path */
3407 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", apIndex);
3408
3409 params[0].name = "ssid";
3410 params[0].value = ssid;
3411 params[1].name = "interface";
3412 params[1].value = interface;
3413 params[2].name = "wpa_psk_file";
3414 params[2].value = psk_file;
3415
3416 wifi_hostapdWrite(ap_config_file, params, 3);
3417
3418 /*clear psk file*/
3419 memset(cmd, 0, sizeof(cmd));
3420 memset(ret_buf, 0, sizeof(ret_buf));
3421
3422 snprintf(psk_file, sizeof(psk_file), "%s%d.psk", PSK_FILE, apIndex);
3423
3424 if (access(psk_file, F_OK) != 0) {
3425 snprintf(cmd, MAX_CMD_SIZE, "touch %s", psk_file);
3426 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3427 } else {
3428 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", psk_file);
3429 _syscmd(cmd, ret_buf, sizeof(ret_buf));
3430 }
3431
3432 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3433
3434 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003435}
3436
3437//To set Band Steering AP group
3438//To-do
3439INT wifi_setBandSteeringApGroup(char *ApGroup)
3440{
3441 return RETURN_OK;
3442}
3443
3444INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
3445{
3446 char config_file[128] = {'\0'};
3447 char buf[128] = {'\0'};
3448
3449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3450 if (dtimInterval == NULL)
3451 return RETURN_ERR;
3452
3453 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer885b56c2023-05-22 15:02:46 +08003454 wifi_hostapdRead(config_file, "dtim_period", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08003455
3456 if (strlen(buf) == 0) {
3457 *dtimInterval = 2;
3458 } else {
3459 *dtimInterval = strtoul(buf, NULL, 10);
3460 }
3461
3462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3463 return RETURN_OK;
3464}
3465
3466INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
3467{
3468 struct params params={0};
3469 char config_file[MAX_BUF_SIZE] = {'\0'};
3470 char buf[MAX_BUF_SIZE] = {'\0'};
3471
3472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3473 if (dtimInterval < 1 || dtimInterval > 255) {
3474 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
3475 return RETURN_ERR;
3476 }
developer69b61b02023-03-07 17:17:44 +08003477
developer72fb0bb2023-01-11 09:46:29 +08003478 params.name = "dtim_period";
3479 snprintf(buf, sizeof(buf), "%d", dtimInterval);
3480 params.value = buf;
3481
3482 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
3483 wifi_hostapdWrite(config_file, &params, 1);
3484 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3485
3486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3487 return RETURN_OK;
3488}
3489
3490//Check if the driver support the Dfs
3491INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
3492{
3493 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08003494 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003495 return RETURN_ERR;
3496 *output_bool=FALSE;
3497
3498 band = wifi_index_to_band(radioIndex);
3499 if (band == band_5)
3500 *output_bool = TRUE;
3501 return RETURN_OK;
3502}
3503
3504//The output_string is a max length 256 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3505//The value of this parameter is a comma seperated list of channel number
3506INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
3507{
developer69b61b02023-03-07 17:17:44 +08003508 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08003509 return RETURN_ERR;
3510 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08003511 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08003512 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
3513
3514 return RETURN_OK;
3515}
3516
3517INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
3518{
3519 //Set to wifi config. And apply instantly.
3520 return RETURN_OK;
3521}
3522
3523INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
3524{
developer69b61b02023-03-07 17:17:44 +08003525 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08003526 return RETURN_ERR;
3527 *output_interval_seconds=1800;
3528 *output_dwell_milliseconds=40;
3529
3530 return RETURN_OK;
3531}
3532
3533INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
3534{
3535 //Set to wifi config. And apply instantly.
3536 return RETURN_OK;
3537}
3538
3539INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
3540{
3541 if (output_bool == NULL)
3542 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003543 *output_bool = true;
3544 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003545}
3546
3547INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
3548{
3549 return RETURN_OK;
3550}
3551
3552//Get the Dfs enable status
3553INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
3554{
3555 char buf[16] = {0};
3556 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003557 char config_file_dat[128] = {0};
3558 char dfs_key[16] = "DfsEnable";
3559 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003560
3561 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3562
3563 if (output_bool == NULL)
3564 return RETURN_ERR;
developerf6a87542023-05-16 15:47:28 +08003565 *output_bool = TRUE; // default
developerd1824452023-05-18 12:30:04 +08003566 band = wifi_index_to_band(radioIndex);
3567 snprintf(config_file_dat, sizeof(config_file_dat), "%s%d.dat", LOGAN_DAT_FILE, band);
3568
3569 wifi_datfileRead(config_file_dat, dfs_key, buf, sizeof(buf));
3570
3571 if (strncmp(buf, "0", 1) == 0)
3572 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08003573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3574 return RETURN_OK;
3575}
3576
3577//Set the Dfs enable status
3578INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
3579{
3580 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +08003581 char config_dat_file[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003582 FILE *f = NULL;
developerd1824452023-05-18 12:30:04 +08003583 struct params dat = {0};
3584 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003585
3586 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3587
3588 f = fopen(DFS_ENABLE_FILE, "w");
3589 if (f == NULL)
3590 return RETURN_ERR;
3591 fprintf(f, "%d", enable);
3592 fclose(f);
3593
developer72fb0bb2023-01-11 09:46:29 +08003594 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3595
developerd1824452023-05-18 12:30:04 +08003596 dat.name = "DfsEnable";
3597 dat.value = enable?"0":"1";
3598 band = wifi_index_to_band(radioIndex);
3599 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3600 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08003601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3602 return RETURN_OK;
3603}
3604
3605//Check if the driver support the AutoChannelRefreshPeriod
3606INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3607{
developer69b61b02023-03-07 17:17:44 +08003608 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003609 return RETURN_ERR;
3610 *output_bool=FALSE; //not support
3611
3612 return RETURN_OK;
3613}
3614
3615//Get the ACS refresh period in seconds
3616INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3617{
developer69b61b02023-03-07 17:17:44 +08003618 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003619 return RETURN_ERR;
3620 *output_ulong=300;
3621
3622 return RETURN_OK;
3623}
3624
3625//Set the ACS refresh period in seconds
3626INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3627{
3628 return RETURN_ERR;
3629}
3630
3631//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3632//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3633INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3634{
developer8666b312023-03-24 14:05:31 +08003635 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003636 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003637 char interface_name[64] = {0};
3638 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003639 BOOL radio_enable = FALSE;
3640 wifi_band band;
3641
3642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3643
developerd1824452023-05-18 12:30:04 +08003644 if (NULL == output_string) {
3645 WIFI_ENTRY_EXIT_DEBUG("output_string is nuill %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003646 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003647 }
3648 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR) {
3649 WIFI_ENTRY_EXIT_DEBUG("wifi_getRadioEnable failed %s: %d \n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003650 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003651 }
3652 if (radio_enable != TRUE) {
3653 WIFI_ENTRY_EXIT_DEBUG("Radio %d is not enable failed %s: %d \n", radioIndex, __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08003654 return RETURN_OK;
developerd1824452023-05-18 12:30:04 +08003655 }
developer8666b312023-03-24 14:05:31 +08003656 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3657 return RETURN_ERR;
3658 /*IW command get BW320 to do*/
developerd1824452023-05-18 12:30:04 +08003659
developer8666b312023-03-24 14:05:31 +08003660 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3661 ret = _syscmd(cmd, buf, sizeof(buf));
3662 len = strlen(buf);
3663 if((ret != 0) || (len == 0))
3664 {
3665 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3666 return RETURN_ERR;
3667 }
3668
developer72fb0bb2023-01-11 09:46:29 +08003669 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003670 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003671 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003672 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3673 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003674 }
developer8666b312023-03-24 14:05:31 +08003675 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003676 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3677
3678 return RETURN_OK;
3679}
developer72fb0bb2023-01-11 09:46:29 +08003680//Set the Operating Channel Bandwidth.
3681INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3682{
3683 char config_file[128];
developerd1824452023-05-18 12:30:04 +08003684 char ht_value[16];
3685 char vht_value[16];
3686 char eht_value[16];
3687 struct params dat[3];
3688 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08003689
3690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3691
3692 if(NULL == bandwidth)
3693 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003694 band = wifi_index_to_band(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08003695
developerd1824452023-05-18 12:30:04 +08003696 if(strstr(bandwidth,"320") != NULL) {
3697 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3698 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3699 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_320);
3700 } else if(strstr(bandwidth,"160") != NULL) {
3701 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3702 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_160);
3703 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_160);
3704 } else if(strstr(bandwidth,"80") != NULL) {
3705 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3706 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_80);
3707 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_80);
3708 } else if(strstr(bandwidth,"40") != NULL) {
3709 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_40);
3710 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3711 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_40);
3712 } else if(strstr(bandwidth,"20") != NULL) {
3713 snprintf(ht_value, sizeof(ht_value), "%d", HT_BW_20);
3714 snprintf(vht_value, sizeof(vht_value), "%d", VHT_BW_2040);
3715 snprintf(eht_value, sizeof(eht_value), "%d", EHT_BW_20);
3716 } else {
developer72fb0bb2023-01-11 09:46:29 +08003717 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3718 return RETURN_ERR;
3719 }
3720
developerd1824452023-05-18 12:30:04 +08003721 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3722 dat[0].name = "HT_BW";
3723 dat[0].value = ht_value;
3724 dat[1].name = "VHT_BW";
3725 dat[1].value = vht_value;
3726 dat[2].name = "EHT_ApBw";
3727 dat[2].value = eht_value;
3728 wifi_datfileWrite(config_file, dat, 3);
developer72fb0bb2023-01-11 09:46:29 +08003729
3730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3731 return RETURN_OK;
3732}
3733
developer72fb0bb2023-01-11 09:46:29 +08003734//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3735//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3736INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3737{
3738 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003739 char config_dat_file[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003740 char mode_str[16] = {0};
3741 char buf[64] = {0};
developerd1824452023-05-18 12:30:04 +08003742 char cmd[MAX_CMD_SIZE] = {0};
3743 char interface_name[64] = {0};
3744 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003745 wifi_band band;
developerd1824452023-05-18 12:30:04 +08003746 ULONG channel = 0;
3747 int centr_channel = 0;
developer72fb0bb2023-01-11 09:46:29 +08003748 UINT mode_map = 0;
developerd1824452023-05-18 12:30:04 +08003749 int freq=0;
developer72fb0bb2023-01-11 09:46:29 +08003750
3751 if (output_string == NULL)
3752 return RETURN_ERR;
3753
3754 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3755
3756 band = wifi_index_to_band(radioIndex);
3757 if (band == band_invalid)
3758 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003759 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3760 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08003761
3762 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3763
3764 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003765 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developerd1824452023-05-18 12:30:04 +08003766 // 2G band or ac and ax mode is disable, we will check HT_EXTCHA
3767 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3768 wifi_halgetRadioExtChannel(config_dat_file, output_string);
developer23e71282023-01-18 10:25:19 +08003769 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003770 snprintf(output_string, 64, "Auto");
3771 } else {
3772 // 5G and 6G band with ac or ax mode.
3773 wifi_getRadioChannel(radioIndex, &channel);
developerd1824452023-05-18 12:30:04 +08003774 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'center1' | cut -d ' ' -f9 | tr -d '\\n'", interface_name);
3775
3776 ret = _syscmd(cmd, buf, sizeof(buf));
3777 len = strlen(buf);
3778 if((ret != 0) || (len == 0))
3779 {
3780 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3781 return RETURN_ERR;
3782 }
3783 sscanf(buf, "%d", &freq);
3784 centr_channel = ieee80211_frequency_to_channel(freq);
3785 if (centr_channel > (int)channel)
developer72fb0bb2023-01-11 09:46:29 +08003786 snprintf(output_string, 64, "AboveControlChannel");
3787 else
3788 snprintf(output_string, 64, "BelowControlChannel");
3789 }
3790
3791 return RETURN_OK;
3792}
3793
3794//Set the extension channel.
3795INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003796{
developer72fb0bb2023-01-11 09:46:29 +08003797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3798 struct params params={0};
3799 char config_file[64] = {0};
developerd1824452023-05-18 12:30:04 +08003800 char config_dat_file[64] = {0};
3801 char ext_channel[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003802 char buf[128] = {0};
3803 char cmd[128] = {0};
3804 int max_radio_num =0, ret = 0, bandwidth = 0;
3805 unsigned long channel = 0, centr_channel = 0;
3806 bool stbcEnable = FALSE;
3807 params.name = "ht_capab";
3808 wifi_band band;
3809
3810 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3811 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3812 _syscmd(cmd, buf, sizeof(buf));
3813 if (strlen(buf) != 0)
3814 stbcEnable = TRUE;
3815 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3816 return RETURN_ERR;
3817 bandwidth = strtol(buf, NULL, 10);
3818 // TDK expected to get error with 20MHz
3819 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3820 return RETURN_ERR;
3821
3822 band = wifi_index_to_band(radioIndex);
3823 if (band == band_invalid)
3824 return RETURN_ERR;
3825
3826 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3827 return RETURN_ERR;
3828
3829 if (band == band_5) {
3830 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3831 centr_channel = util_unii_5g_centerfreq(buf, channel);
3832 if (centr_channel == 0)
3833 return RETURN_ERR;
3834 }
3835
3836 if(NULL!= strstr(string,"Above")) {
3837 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3838 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003839 snprintf(ext_channel, sizeof(ext_channel), "Above");
developer72fb0bb2023-01-11 09:46:29 +08003840 } else if(NULL!= strstr(string,"Below")) {
3841 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3842 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +08003843 snprintf(ext_channel, sizeof(ext_channel), "Above");
3844 } else
3845 printf("%s: invalid EXT_CHA:%s\n", __func__, string);
developer72fb0bb2023-01-11 09:46:29 +08003846
developerd1824452023-05-18 12:30:04 +08003847 params.name = "HT_EXTCHA";
developer72fb0bb2023-01-11 09:46:29 +08003848 params.value = ext_channel;
3849
developerd1824452023-05-18 12:30:04 +08003850 snprintf (config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
3851 wifi_datfileWrite(config_dat_file, &params, 1);
3852
developer72fb0bb2023-01-11 09:46:29 +08003853 wifi_getMaxRadioNumber(&max_radio_num);
3854 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3855 {
3856 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
developer72fb0bb2023-01-11 09:46:29 +08003857 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3858 }
3859
3860 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3862 return RETURN_OK;
3863}
3864
3865//Get the guard interval value. eg "400nsec" or "800nsec"
3866//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
3867INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3868{
3869 wifi_guard_interval_t GI;
3870
3871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3872
3873 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3874 return RETURN_ERR;
3875
3876 if (GI == wifi_guard_interval_400)
3877 strcpy(output_string, "400nsec");
3878 else if (GI == wifi_guard_interval_800)
3879 strcpy(output_string, "800nsec");
3880 else if (GI == wifi_guard_interval_1600)
3881 strcpy(output_string, "1600nsec");
3882 else if (GI == wifi_guard_interval_3200)
3883 strcpy(output_string, "3200nsec");
3884 else
3885 strcpy(output_string, "Auto");
3886
3887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3888 return RETURN_OK;
3889}
3890
3891//Set the guard interval value.
3892INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3893{
3894 wifi_guard_interval_t GI;
3895 int ret = 0;
3896
3897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3898
3899 if (strcmp(string, "400nsec") == 0)
3900 GI = wifi_guard_interval_400;
3901 else if (strcmp(string , "800nsec") == 0)
3902 GI = wifi_guard_interval_800;
3903 else if (strcmp(string , "1600nsec") == 0)
3904 GI = wifi_guard_interval_1600;
3905 else if (strcmp(string , "3200nsec") == 0)
3906 GI = wifi_guard_interval_3200;
3907 else
3908 GI = wifi_guard_interval_auto;
3909
3910 ret = wifi_setGuardInterval(radioIndex, GI);
3911
3912 if (ret == RETURN_ERR) {
3913 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3914 return RETURN_ERR;
3915 }
3916
3917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3918 return RETURN_OK;
3919}
3920
3921//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3922INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3923{
3924 char buf[32]={0};
3925 char mcs_file[64] = {0};
3926 char cmd[64] = {0};
3927 int mode_bitmap = 0;
3928
3929 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3930 if(output_int == NULL)
3931 return RETURN_ERR;
3932 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3933
3934 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3935 _syscmd(cmd, buf, sizeof(buf));
3936 if (strlen(buf) > 0)
3937 *output_int = strtol(buf, NULL, 10);
3938 else {
3939 // output the max MCS for the current radio mode
3940 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3941 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3942 return RETURN_ERR;
3943 }
3944 if (mode_bitmap & WIFI_MODE_AX) {
3945 *output_int = 11;
3946 } else if (mode_bitmap & WIFI_MODE_AC) {
3947 *output_int = 9;
3948 } else if (mode_bitmap & WIFI_MODE_N) {
3949 *output_int = 7;
3950 }
3951 }
3952 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3953
3954 return RETURN_OK;
3955}
3956
3957//Set the Modulation Coding Scheme index
3958INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3959{
developera1255e42023-05-13 17:45:02 +08003960 /*Only HE mode can specify MCS capability. We don't support MCS in HT mode,
3961 because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).*/
developer72fb0bb2023-01-11 09:46:29 +08003962 char config_file[64] = {0};
3963 char set_value[16] = {0};
3964 char mcs_file[32] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003965 struct params set_config = {0};
3966 FILE *f = NULL;
developera1255e42023-05-13 17:45:02 +08003967 INT nss = 0;
3968 int ant_bitmap = 0;
3969 unsigned short cal_value = 0;
3970 UCHAR tval = 0, i = 0;
developer72fb0bb2023-01-11 09:46:29 +08003971
3972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3973
3974 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3975
3976 // -1 means auto
3977 if (MCS > 15 || MCS < -1) {
3978 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3979 return RETURN_ERR;
3980 }
developera1255e42023-05-13 17:45:02 +08003981 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);/*nss is a bit map value,1111*/
3982 for(; ant_bitmap > 0; ant_bitmap >>= 1)
3983 nss += 1;
3984 //printf("%s:nss = %d\n", __func__, nss);
3985 /*16-bit combination of 2-bit values of Max HE-MCS For 1..8 SS;each 2-bit value have following meaning:
3986 0 = HE-MCS 0-7, 1 = HE-MCS 0-9, 2 = HE-MCS 0-11, 3 = not supported*/
developer72fb0bb2023-01-11 09:46:29 +08003987 if (MCS > 9 || MCS == -1)
developera1255e42023-05-13 17:45:02 +08003988 tval = 2;/*one stream value*/
developer72fb0bb2023-01-11 09:46:29 +08003989 else if (MCS > 7)
developera1255e42023-05-13 17:45:02 +08003990 tval = 1;
developer72fb0bb2023-01-11 09:46:29 +08003991 else
developera1255e42023-05-13 17:45:02 +08003992 tval = 0;
3993 for (i = 0; i < nss; i++)
3994 cal_value |= (tval << (2*i));
3995 snprintf(set_value, sizeof(set_value), "%x", cal_value);
3996 WIFI_ENTRY_EXIT_DEBUG("%s:set=%s, cal=%x\n", __func__, set_value, cal_value);
3997 set_config.name = "he_basic_mcs_nss_set";/*He capability in beacon or response*/
developer72fb0bb2023-01-11 09:46:29 +08003998 set_config.value = set_value;
3999
4000 wifi_hostapdWrite(config_file, &set_config, 1);
4001 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
4002
4003 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
4004 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
4005 f = fopen(mcs_file, "w");
4006 if (f == NULL) {
4007 fprintf(stderr, "%s: fopen failed\n", __func__);
4008 return RETURN_ERR;
4009 }
4010 fprintf(f, "%d", MCS);
4011 fclose(f);
4012
4013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4014 return RETURN_OK;
4015}
4016
4017//Get supported Transmit Power list, eg : "0,25,50,75,100"
4018//The output_list is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
4019INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
4020{
4021 if (NULL == output_list)
4022 return RETURN_ERR;
4023 snprintf(output_list, 64,"0,25,50,75,100");
4024 return RETURN_OK;
4025}
4026
4027//Get current Transmit Power in dBm units.
4028//The transmite power level is in units of full power for this radio.
4029INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
4030{
4031 char interface_name[16] = {0};
4032 char cmd[128]={0};
4033 char buf[16]={0};
developera1255e42023-05-13 17:45:02 +08004034 char pwr_file[128]={0};
4035
developer72fb0bb2023-01-11 09:46:29 +08004036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4037
4038 if(output_ulong == NULL)
4039 return RETURN_ERR;
4040
4041 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4042 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004043/*
developer72fb0bb2023-01-11 09:46:29 +08004044 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
4045 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004046 *output_ulong = strtol(buf, NULL, 10);
developera1255e42023-05-13 17:45:02 +08004047*/
4048 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4049 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", pwr_file);
4050 _syscmd(cmd, buf, sizeof(buf));
4051 if (strlen(buf) > 0)
4052 *output_ulong = strtol(buf, NULL, 10);
4053 else
4054 *output_ulong = 100;
developer72fb0bb2023-01-11 09:46:29 +08004055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4056 return RETURN_OK;
4057}
4058
4059//Set Transmit Power
4060//The transmite power level is in units of full power for this radio.
4061INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
4062{
4063 char interface_name[16] = {0};
4064 char *support;
4065 char cmd[128]={0};
4066 char buf[128]={0};
4067 char txpower_str[64] = {0};
developera1255e42023-05-13 17:45:02 +08004068 char pwr_file[128]={0};
4069 FILE *f = NULL;
developer72fb0bb2023-01-11 09:46:29 +08004070
4071 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4072
4073 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4074 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +08004075 // Get the Tx power supported list and check that is the input in the list
4076 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4077 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4078 support = strtok(buf, ",");
4079 while(true)
4080 {
4081 if(support == NULL) { // input not in the list
4082 wifi_dbg_printf("Input value is invalid.\n");
4083 return RETURN_ERR;
4084 }
4085 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4086 break;
4087 }
4088 support = strtok(NULL, ",");
4089 }
4090 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PercentageCtrl=1\n", interface_name);
4091 _syscmd(cmd, buf, sizeof(buf));
4092 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr PowerDropCtrl=%lu\n", interface_name, TransmitPower);
4093 _syscmd(cmd, buf, sizeof(buf));
4094 snprintf(pwr_file, sizeof(pwr_file), "%s%d.txt", POWER_PERCENTAGE, radioIndex);
4095 f = fopen(pwr_file, "w");
4096 if (f == NULL) {
4097 fprintf(stderr, "%s: fopen failed\n", __func__);
4098 return RETURN_ERR;
4099 }
4100 fprintf(f, "%d", TransmitPower);
4101 fclose(f);
4102/* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08004103 _syscmd(cmd, buf, sizeof(buf));
4104 maximum_tx = strtol(buf, NULL, 10);
4105
4106 // Get the Tx power supported list and check that is the input in the list
4107 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
4108 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
4109 support = strtok(buf, ",");
4110 while(true)
4111 {
4112 if(support == NULL) { // input not in the list
4113 wifi_dbg_printf("Input value is invalid.\n");
4114 return RETURN_ERR;
4115 }
4116 if (strncmp(txpower_str, support, strlen(support)) == 0) {
4117 break;
4118 }
4119 support = strtok(NULL, ",");
4120 }
4121 txpower = TransmitPower*maximum_tx/100;
4122 phyId = radio_index_to_phy(radioIndex);
4123 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
4124 _syscmd(cmd, buf, sizeof(buf));
4125 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera1255e42023-05-13 17:45:02 +08004126*/
4127 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004128}
4129
4130//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
4131INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
4132{
developer69b61b02023-03-07 17:17:44 +08004133 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08004134 return RETURN_ERR;
4135 *Supported = TRUE;
4136
4137 return RETURN_OK;
4138}
4139
4140//Get 80211h feature enable
4141INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
4142{
4143 char buf[64]={'\0'};
4144 char config_file[64] = {'\0'};
4145
4146 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4147 if(enable == NULL)
4148 return RETURN_ERR;
4149
4150 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08004151 /* wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf)); */
4152 wifi_datfileRead(config_file, "IEEE80211H", buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08004153
4154 if (strncmp(buf, "1", 1) == 0)
4155 *enable = TRUE;
4156 else
4157 *enable = FALSE;
4158
4159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4160 return RETURN_OK;
4161}
4162
4163//Set 80211h feature enable
4164INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
4165{
4166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4167 struct params params={'\0'};
developerd1824452023-05-18 12:30:04 +08004168 struct params dat={0};
developer72fb0bb2023-01-11 09:46:29 +08004169 char config_file[MAX_BUF_SIZE] = {0};
developerd1824452023-05-18 12:30:04 +08004170 char config_dat_file[MAX_BUF_SIZE] = {0};
4171 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08004172
4173 params.name = "ieee80211h";
4174
4175 if (enable) {
4176 params.value = "1";
4177 } else {
4178 params.value = "0";
4179 }
4180
developerd1824452023-05-18 12:30:04 +08004181 dat.name = "IEEE80211H";
4182 dat.value = params.value;
4183
4184 band = wifi_index_to_band(radioIndex);
4185 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4186 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer69b61b02023-03-07 17:17:44 +08004187
developerd1824452023-05-18 12:30:04 +08004188 wifi_hostapdWrite(config_file, &params, 1);
4189 wifi_datfileWrite(config_dat_file, &dat, 1);
developer72fb0bb2023-01-11 09:46:29 +08004190 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4191 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4192 return RETURN_OK;
4193}
4194
4195//Indicates the Carrier Sense ranges supported by the radio. It is measured in dBm. Refer section A.2.3.2 of CableLabs Wi-Fi MGMT Specification.
4196INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
4197{
4198 if (NULL == output)
4199 return RETURN_ERR;
4200 *output=100;
4201
4202 return RETURN_OK;
4203}
4204
4205//The RSSI signal level at which CS/CCA detects a busy condition. This attribute enables APs to increase minimum sensitivity to avoid detecting busy condition from multiple/weak Wi-Fi sources in dense Wi-Fi environments. It is measured in dBm. Refer section A.2.3.2 of CableLabs Wi-Fi MGMT Specification.
4206INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
4207{
4208 if (NULL == output)
4209 return RETURN_ERR;
4210 *output = -99;
4211
4212 return RETURN_OK;
4213}
4214
4215INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
4216{
4217 return RETURN_ERR;
4218}
4219
4220
4221//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
4222INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
4223{
4224 char interface_name[16] = {0};
4225 char cmd[MAX_BUF_SIZE]={'\0'};
4226 char buf[MAX_CMD_SIZE]={'\0'};
4227
4228 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4229 if(output == NULL)
4230 return RETURN_ERR;
4231
4232 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4233 return RETURN_ERR;
4234 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
4235 _syscmd(cmd, buf, sizeof(buf));
4236 *output = atoi(buf);
4237
4238 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4239 return RETURN_OK;
4240}
developer69b61b02023-03-07 17:17:44 +08004241
developer72fb0bb2023-01-11 09:46:29 +08004242INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
4243{
4244 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4245 struct params params={'\0'};
4246 char buf[MAX_BUF_SIZE] = {'\0'};
4247 char config_file[MAX_BUF_SIZE] = {'\0'};
4248
4249 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
4250 return RETURN_ERR;
4251
4252 params.name = "beacon_int";
4253 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
4254 params.value = buf;
4255
4256 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
4257 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08004258
developer72fb0bb2023-01-11 09:46:29 +08004259 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
4260 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4261 return RETURN_OK;
4262}
4263
4264//Comma-separated list of strings. The set of data rates, in Mbps, that have to be supported by all stations that desire to join this BSS. The stations have to be able to receive and transmit at each of the data rates listed inBasicDataTransmitRates. For example, a value of "1,2", indicates that stations support 1 Mbps and 2 Mbps. Most control packets use a data rate in BasicDataTransmitRates.
4265INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
4266{
4267 //TODO: need to revisit below implementation
4268 char *temp;
4269 char temp_output[128] = {0};
4270 char temp_TransmitRates[64] = {0};
4271 char config_file[64] = {0};
4272
4273 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4274 if (NULL == output)
4275 return RETURN_ERR;
4276 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4277 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08004278
developer72fb0bb2023-01-11 09:46:29 +08004279 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
4280 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
4281 } else {
4282 temp = strtok(temp_TransmitRates," ");
4283 while(temp!=NULL)
4284 {
4285 // Convert 100 kbps to Mbps
4286 temp[strlen(temp)-1]=0;
4287 if((temp[0]=='5') && (temp[1]=='\0'))
4288 {
4289 temp="5.5";
4290 }
4291 strcat(temp_output,temp);
4292 temp = strtok(NULL," ");
4293 if(temp!=NULL)
4294 {
4295 strcat(temp_output,",");
4296 }
4297 }
4298 strcpy(output,temp_output);
4299 }
4300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4301 return RETURN_OK;
4302}
4303
4304INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
4305{
4306 char *temp;
4307 char temp1[128];
4308 char temp_output[128];
4309 char temp_TransmitRates[128];
4310 char set[128];
4311 char sub_set[128];
4312 int set_count=0,subset_count=0;
4313 int set_index=0,subset_index=0;
4314 char *token;
4315 int flag=0, i=0;
4316 struct params params={'\0'};
4317 char config_file[MAX_BUF_SIZE] = {0};
4318 wifi_band band = wifi_index_to_band(radioIndex);
4319
4320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4321 if(NULL == TransmitRates)
4322 return RETURN_ERR;
4323 strcpy(sub_set,TransmitRates);
4324
4325 //Allow only supported Data transmit rate to be set
4326 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
4327 token = strtok(sub_set,",");
4328 while( token != NULL ) /* split the basic rate to be set, by comma */
4329 {
4330 sub_set[subset_count]=atoi(token);
4331 subset_count++;
4332 token=strtok(NULL,",");
4333 }
4334 token=strtok(set,",");
4335 while(token!=NULL) /* split the supported rate by comma */
4336 {
4337 set[set_count]=atoi(token);
4338 set_count++;
4339 token=strtok(NULL,",");
4340 }
4341 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
4342 {
4343 for(set_index=0;set_index < set_count;set_index++)
4344 {
4345 flag=0;
4346 if(sub_set[subset_index]==set[set_index])
4347 break;
4348 else
4349 flag=1; /* No match found */
4350 }
4351 if(flag==1)
4352 return RETURN_ERR; //If value not found return Error
4353 }
4354 strcpy(temp_TransmitRates,TransmitRates);
4355
4356 for(i=0;i<strlen(temp_TransmitRates);i++)
4357 {
4358 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
4359 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
4360 {
4361 continue;
4362 }
4363 else
4364 {
4365 return RETURN_ERR;
4366 }
4367 }
4368 strcpy(temp_output,"");
4369 temp = strtok(temp_TransmitRates,",");
4370 while(temp!=NULL)
4371 {
4372 strcpy(temp1,temp);
4373 if(band == band_5)
4374 {
4375 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
4376 {
4377 return RETURN_ERR;
4378 }
4379 }
4380
4381 if(strcmp(temp,"5.5")==0)
4382 {
4383 strcpy(temp1,"55");
4384 }
4385 else
4386 {
4387 strcat(temp1,"0");
4388 }
4389 strcat(temp_output,temp1);
4390 temp = strtok(NULL,",");
4391 if(temp!=NULL)
4392 {
4393 strcat(temp_output," ");
4394 }
4395 }
4396 strcpy(TransmitRates,temp_output);
4397
4398 params.name= "basic_rates";
4399 params.value =TransmitRates;
4400
4401 wifi_dbg_printf("\n%s:",__func__);
4402 wifi_dbg_printf("\nparams.value=%s\n",params.value);
4403 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
4404 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
4405 wifi_hostapdWrite(config_file,&params,1);
4406 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4407 return RETURN_OK;
4408}
4409
4410//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
4411INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
4412{
4413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4414 FILE *fp = NULL;
4415 char path[256] = {0}, output_string[256] = {0};
4416 int count = 0;
4417 char *interface = NULL;
4418
4419 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
4420 if (fp == NULL)
4421 {
4422 printf("Failed to run command in Function %s\n", __FUNCTION__);
4423 return RETURN_ERR;
4424 }
4425 if (fgets(path, sizeof(path) - 1, fp) != NULL)
4426 {
4427 interface = strchr(path, '=');
4428
4429 if (interface != NULL)
4430 {
4431 strcpy(output_string, interface + 1);
4432 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
4433 interface_name[count] = output_string[count];
4434
4435 interface_name[count] = '\0';
4436 }
4437 }
4438 pclose(fp);
4439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4440 return RETURN_OK;
4441}
4442
4443INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
4444{
4445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4446 output_struct->radio_BytesSent = 0;
4447 output_struct->radio_BytesReceived = 0;
4448 output_struct->radio_PacketsSent = 0;
4449 output_struct->radio_PacketsReceived = 0;
4450 output_struct->radio_ErrorsSent = 0;
4451 output_struct->radio_ErrorsReceived = 0;
4452 output_struct->radio_DiscardPacketsSent = 0;
4453 output_struct->radio_DiscardPacketsReceived = 0;
4454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4455 return RETURN_OK;
4456}
4457
4458
4459INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
4460{
4461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4462 CHAR buf[MAX_CMD_SIZE] = {0};
4463 CHAR Value[MAX_BUF_SIZE] = {0};
4464 FILE *fp = NULL;
4465
4466 if (ifname == NULL || strlen(ifname) <= 1)
4467 return RETURN_OK;
4468
4469 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
4470 system(buf);
4471
4472 fp = fopen("/tmp/Radio_Stats.txt", "r");
4473 if(fp == NULL)
4474 {
4475 printf("/tmp/Radio_Stats.txt not exists \n");
4476 return RETURN_ERR;
4477 }
4478 fclose(fp);
4479
4480 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4481 File_Reading(buf, Value);
4482 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
4483
4484 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4485 File_Reading(buf, Value);
4486 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
4487
4488 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4489 File_Reading(buf, Value);
4490 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
4491
4492 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4493 File_Reading(buf, Value);
4494 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
4495
4496 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4497 File_Reading(buf, Value);
4498 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
4499
4500 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4501 File_Reading(buf, Value);
4502 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
4503
4504 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4505 File_Reading(buf, Value);
4506 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
4507
4508 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4509 File_Reading(buf, Value);
4510 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
4511
4512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4513 return RETURN_OK;
4514}
4515
4516INT GetIfacestatus(CHAR *interface_name, CHAR *status)
4517{
developer7e4a2a62023-04-06 19:56:03 +08004518 CHAR buf[MAX_CMD_SIZE] = {0};
4519 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08004520
developer7e4a2a62023-04-06 19:56:03 +08004521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4522
4523 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
4524 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
4525 File_Reading(buf, status);
4526 }
4527
4528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4529 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004530}
4531
4532//Get detail radio traffic static info
4533INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
4534{
4535
developer69b61b02023-03-07 17:17:44 +08004536#if 0
4537 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08004538 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
4539 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
4540 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
4541 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
4542
4543 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
4544 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
4545 output_struct->radio_DiscardPacketsSent=0; //The total number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space.
4546 output_struct->radio_DiscardPacketsReceived=0; //The total number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being delivered. One possible reason for discarding such a packet could be to free up buffer space.
4547
developer69b61b02023-03-07 17:17:44 +08004548 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
developer72fb0bb2023-01-11 09:46:29 +08004549 output_struct->radio_FCSErrorCount=0; //The number of packets that were received with a detected FCS error. This parameter is based on dot11FCSErrorCount from [Annex C/802.11-2012].
4550 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
4551 output_struct->radio_PacketsOtherReceived=0; //The number of packets that were received, but which were destined for a MAC address that is not associated with this interface.
4552 output_struct->radio_NoiseFloor=-99; //The noise floor for this radio channel where a recoverable signal can be obtained. Expressed as a signed integer in the range (-110:0). Measurement should capture all energy (in dBm) from sources other than Wi-Fi devices as well as interference from Wi-Fi devices too weak to be decoded. Measured in dBm
4553 output_struct->radio_ChannelUtilization=35; //Percentage of time the channel was occupied by the radios own activity (Activity Factor) or the activity of other radios. Channel utilization MUST cover all user traffic, management traffic, and time the radio was unavailable for CSMA activities, including DIFS intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4554 output_struct->radio_ActivityFactor=2; //Percentage of time that the radio was transmitting or receiving Wi-Fi packets to/from associated clients. Activity factor MUST include all traffic that deals with communication between the radio and clients associated to the radio as well as management overhead for the radio, including NAV timers, beacons, probe responses,time for receiving devices to send an ACK, SIFC intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4555 output_struct->radio_CarrierSenseThreshold_Exceeded=20; //Percentage of time that the radio was unable to transmit or receive Wi-Fi packets to/from associated clients due to energy detection (ED) on the channel or clear channel assessment (CCA). The metric is calculated and updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4556 output_struct->radio_RetransmissionMetirc=0; //Percentage of packets that had to be re-transmitted. Multiple re-transmissions of the same packet count as one. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in percentage
4557
4558 output_struct->radio_MaximumNoiseFloorOnChannel=-1; //Maximum Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4559 output_struct->radio_MinimumNoiseFloorOnChannel=-1; //Minimum Noise on the channel. The metric is updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4560 output_struct->radio_MedianNoiseFloorOnChannel=-1; //Median Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4561 output_struct->radio_StatisticsStartTime=0; //The date and time at which the collection of the current set of statistics started. This time must be updated whenever the radio statistics are reset.
4562
4563 return RETURN_OK;
4564#endif
4565
4566 CHAR interface_name[64] = {0};
4567 BOOL iface_status = FALSE;
4568 wifi_radioTrafficStats2_t radioTrafficStats = {0};
4569
4570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
4571 if (NULL == output_struct)
4572 return RETURN_ERR;
4573
4574 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4575 return RETURN_ERR;
4576
4577 wifi_getApEnable(radioIndex, &iface_status);
4578
4579 if (iface_status == TRUE)
4580 wifi_halGetIfStats(interface_name, &radioTrafficStats);
4581 else
4582 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
4583
4584 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
4585 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
4586 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
4587 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
4588 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
4589 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
4590 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
4591 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
4592
4593 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
4594 output_struct->radio_FCSErrorCount = 0; //The number of packets that were received with a detected FCS error. This parameter is based on dot11FCSErrorCount from [Annex C/802.11-2012].
4595 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
4596 output_struct->radio_PacketsOtherReceived = 0; //The number of packets that were received, but which were destined for a MAC address that is not associated with this interface.
4597 output_struct->radio_NoiseFloor = -99; //The noise floor for this radio channel where a recoverable signal can be obtained. Expressed as a signed integer in the range (-110:0). Measurement should capture all energy (in dBm) from sources other than Wi-Fi devices as well as interference from Wi-Fi devices too weak to be decoded. Measured in dBm
4598 output_struct->radio_ChannelUtilization = 35; //Percentage of time the channel was occupied by the radio\92s own activity (Activity Factor) or the activity of other radios. Channel utilization MUST cover all user traffic, management traffic, and time the radio was unavailable for CSMA activities, including DIFS intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4599 output_struct->radio_ActivityFactor = 2; //Percentage of time that the radio was transmitting or receiving Wi-Fi packets to/from associated clients. Activity factor MUST include all traffic that deals with communication between the radio and clients associated to the radio as well as management overhead for the radio, including NAV timers, beacons, probe responses,time for receiving devices to send an ACK, SIFC intervals, etc. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4600 output_struct->radio_CarrierSenseThreshold_Exceeded = 20; //Percentage of time that the radio was unable to transmit or receive Wi-Fi packets to/from associated clients due to energy detection (ED) on the channel or clear channel assessment (CCA). The metric is calculated and updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in Percentage
4601 output_struct->radio_RetransmissionMetirc = 0; //Percentage of packets that had to be re-transmitted. Multiple re-transmissions of the same packet count as one. The metric is calculated and updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected from the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in percentage
4602
4603 output_struct->radio_MaximumNoiseFloorOnChannel = -1; //Maximum Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4604 output_struct->radio_MinimumNoiseFloorOnChannel = -1; //Minimum Noise on the channel. The metric is updated in this Parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4605 output_struct->radio_MedianNoiseFloorOnChannel = -1; //Median Noise on the channel during the measuring interval. The metric is updated in this parameter at the end of the interval defined by "Radio Statistics Measuring Interval". The calculation of this metric MUST only use the data collected in the just completed interval. If this metric is queried before it has been updated with an initial calculation, it MUST return -1. Units in dBm
4606 output_struct->radio_StatisticsStartTime = 0; //The date and time at which the collection of the current set of statistics started. This time must be updated whenever the radio statistics are reset.
4607
4608 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
4609
4610 return RETURN_OK;
4611}
4612
4613//Set radio traffic static Measureing rules
4614INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
4615{
4616 //zqiu: If the RadioTrafficStats process running, and the new value is different from old value, the process needs to be reset. The Statistics date, such as MaximumNoiseFloorOnChannel, MinimumNoiseFloorOnChannel and MedianNoiseFloorOnChannel need to be reset. And the "StatisticsStartTime" must be reset to the current time. Units in Seconds
4617 // Else, save the MeasuringRate and MeasuringInterval for future usage
4618
4619 return RETURN_OK;
4620}
4621
4622//To start or stop RadioTrafficStats
4623INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
4624{
4625 //zqiu: If the RadioTrafficStats process running
4626 // if(enable)
4627 // return RETURN_OK.
4628 // else
4629 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08004630 // Else
developer72fb0bb2023-01-11 09:46:29 +08004631 // if(enable)
4632 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
4633 // else
4634 // return RETURN_OK.
4635
4636 return RETURN_OK;
4637}
4638
4639//Clients associated with the AP over a specific interval. The histogram MUST have a range from -110to 0 dBm and MUST be divided in bins of 3 dBM, with bins aligning on the -110 dBm end of the range. Received signal levels equal to or greater than the smaller boundary of a bin and less than the larger boundary are included in the respective bin. The bin associated with the client?s current received signal level MUST be incremented when a client associates with the AP. Additionally, the respective bins associated with each connected client?s current received signal level MUST be incremented at the interval defined by "Radio Statistics Measuring Rate". The histogram?s bins MUST NOT be incremented at any other time. The histogram data collected during the interval MUST be published to the parameter only at the end of the interval defined by "Radio Statistics Measuring Interval". The underlying histogram data MUST be cleared at the start of each interval defined by "Radio Statistics Measuring Interval?. If any of the parameter's representing this histogram is queried before the histogram has been updated with an initial set of data, it MUST return -1. Units dBm
4640INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
4641{
4642 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08004643 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08004644 return RETURN_ERR;
developer47cc27a2023-05-17 23:09:58 +08004645
developer72fb0bb2023-01-11 09:46:29 +08004646 *SignalLevel=(radioIndex==0)?-19:-19;
4647
4648 return RETURN_OK;
4649}
4650
4651//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4652INT wifi_applyRadioSettings(INT radioIndex)
4653{
4654 return RETURN_OK;
4655}
4656
4657//Get the radio index assocated with this SSID entry
4658INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
4659{
4660 if(NULL == radioIndex)
4661 return RETURN_ERR;
4662 int max_radio_num = 0;
4663 wifi_getMaxRadioNumber(&max_radio_num);
4664 *radioIndex = ssidIndex%max_radio_num;
4665 return RETURN_OK;
4666}
4667
4668//Device.WiFi.SSID.{i}.Enable
4669//Get SSID enable configuration parameters (not the SSID enable status)
4670INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
4671{
developer69b61b02023-03-07 17:17:44 +08004672 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08004673 return RETURN_ERR;
4674
4675 return wifi_getApEnable(ssidIndex, output_bool);
4676}
4677
4678//Device.WiFi.SSID.{i}.Enable
4679//Set SSID enable configuration parameters
4680INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4681{
4682 return wifi_setApEnable(ssidIndex, enable);
4683}
4684
4685//Device.WiFi.SSID.{i}.Status
4686//Get the SSID enable status
4687INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4688{
4689 char cmd[MAX_CMD_SIZE]={0};
4690 char buf[MAX_BUF_SIZE]={0};
4691 BOOL output_bool;
4692
4693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4694 if (NULL == output_string)
4695 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004696
developer72fb0bb2023-01-11 09:46:29 +08004697 wifi_getApEnable(ssidIndex,&output_bool);
4698 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4699
4700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4701 return RETURN_OK;
4702}
4703
4704// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4705INT wifi_getSSIDName(INT apIndex, CHAR *output)
4706{
4707 char config_file[MAX_BUF_SIZE] = {0};
4708
developer69b61b02023-03-07 17:17:44 +08004709 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004710 return RETURN_ERR;
4711
4712 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4713 wifi_hostapdRead(config_file,"ssid",output,32);
4714
4715 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4716 return RETURN_OK;
4717}
4718
developer69b61b02023-03-07 17:17:44 +08004719// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004720INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4721{
4722 char str[MAX_BUF_SIZE]={'\0'};
4723 char cmd[MAX_CMD_SIZE]={'\0'};
4724 struct params params;
4725 char config_file[MAX_BUF_SIZE] = {0};
4726
4727 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4728 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4729 return RETURN_ERR;
4730
4731 params.name = "ssid";
4732 params.value = ssid_string;
4733 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4734 wifi_hostapdWrite(config_file, &params, 1);
4735 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4737
4738 return RETURN_OK;
4739}
4740
4741//Get the BSSID
4742INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4743{
developer7e4a2a62023-04-06 19:56:03 +08004744 char cmd[MAX_CMD_SIZE] = {0};
4745 char inf_name[IF_NAME_SIZE] = {0};
4746 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004747
developer7e4a2a62023-04-06 19:56:03 +08004748 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004749 return RETURN_ERR;
4750
developer47cc27a2023-05-17 23:09:58 +08004751 if (wifi_GetInterfaceName(ssidIndex, inf_name) != RETURN_OK)
4752 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08004753
4754 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4755 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep bssid | cut -d '=' -f2 | tr -d '\\n'", inf_name);
developer72fb0bb2023-01-11 09:46:29 +08004756 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004757 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004758 }
developer7e4a2a62023-04-06 19:56:03 +08004759
developer72fb0bb2023-01-11 09:46:29 +08004760 strncpy(output_string, "\0", 1);
4761
4762 return RETURN_ERR;
4763}
4764
4765//Get the MAC address associated with this Wifi SSID
4766INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4767{
4768 wifi_getBaseBSSID(ssidIndex,output_string);
4769 return RETURN_OK;
4770}
4771
4772//Get the basic SSID traffic static info
4773//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4774//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4775INT wifi_applySSIDSettings(INT ssidIndex)
4776{
4777 char interface_name[16] = {0};
4778 BOOL status = false;
4779 char cmd[MAX_CMD_SIZE] = {0};
4780 char buf[MAX_CMD_SIZE] = {0};
4781 int apIndex, ret;
4782 int max_radio_num = 0;
4783 int radioIndex = 0;
4784
4785 wifi_getMaxRadioNumber(&max_radio_num);
4786
4787 radioIndex = ssidIndex % max_radio_num;
4788
4789 wifi_getApEnable(ssidIndex,&status);
4790 // Do not apply when ssid index is disabled
4791 if (status == false)
4792 return RETURN_OK;
4793
4794 /* Doing full remove and add for ssid Index
4795 * Not all hostapd options are supported with reload
4796 * for example macaddr_acl
4797 */
4798 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4799 return RETURN_ERR;
4800
4801 ret = wifi_setApEnable(ssidIndex,true);
4802
4803 /* Workaround for hostapd issue with multiple bss definitions
4804 * when first created interface will be removed
4805 * then all vaps other vaps on same phy are removed
4806 * after calling setApEnable to false readd all enabled vaps */
4807 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4808 apIndex = max_radio_num*i+radioIndex;
4809 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4810 return RETURN_ERR;
4811 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4812 _syscmd(cmd, buf, sizeof(buf));
4813 if(*buf == '1')
4814 wifi_setApEnable(apIndex, true);
4815 }
4816
4817 return ret;
4818}
4819
4820struct channels_noise {
4821 int channel;
4822 int noise;
4823};
4824
4825// Return noise array for each channel
4826int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4827{
4828 char interface_name[16] = {0};
4829 FILE *f = NULL;
4830 char cmd[128] = {0};
4831 char line[256] = {0};
4832 size_t len = 0;
4833 ssize_t read = 0;
4834 int tmp = 0, arr_index = -1;
4835
4836 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4837 return RETURN_ERR;
4838 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4839
4840 if ((f = popen(cmd, "r")) == NULL) {
4841 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4842 return RETURN_ERR;
4843 }
developer69b61b02023-03-07 17:17:44 +08004844
developer72fb0bb2023-01-11 09:46:29 +08004845 while(fgets(line, sizeof(line), f) != NULL) {
4846 if(arr_index < channels_num){
4847 sscanf(line, "%d", &tmp);
4848 if (tmp > 0) { // channel frequency, the first line must be frequency
4849 arr_index++;
4850 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4851 } else { // noise
4852 channels_noise_arr[arr_index].noise = tmp;
4853 }
4854 }else{
4855 break;
4856 }
4857 }
4858 pclose(f);
4859 return RETURN_OK;
4860}
4861
4862//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4863//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004864INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004865{
4866 int index = -1;
4867 wifi_neighbor_ap2_t *scan_array = NULL;
4868 char cmd[256]={0};
4869 char buf[128]={0};
4870 char file_name[32] = {0};
4871 char filter_SSID[32] = {0};
4872 char line[256] = {0};
4873 char interface_name[16] = {0};
4874 char *ret = NULL;
4875 int freq=0;
4876 FILE *f = NULL;
4877 size_t len=0;
4878 int channels_num = 0;
4879 int vht_channel_width = 0;
4880 int get_noise_ret = RETURN_ERR;
4881 bool filter_enable = false;
4882 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4883 int phyId = 0;
4884
4885 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4886
4887 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4888 return RETURN_ERR;
4889
4890 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4891 f = fopen(file_name, "r");
4892 if (f != NULL) {
4893 fgets(filter_SSID, sizeof(file_name), f);
4894 if (strlen(filter_SSID) != 0)
4895 filter_enable = true;
4896 fclose(f);
4897 }
4898
4899 phyId = radio_index_to_phy(radioIndex);
4900 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4901 _syscmd(cmd, buf, sizeof(buf));
4902 channels_num = strtol(buf, NULL, 10);
4903
4904
4905
4906 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4907 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4908 fprintf(stderr, "cmd: %s\n", cmd);
4909 if ((f = popen(cmd, "r")) == NULL) {
4910 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4911 return RETURN_ERR;
4912 }
developer69b61b02023-03-07 17:17:44 +08004913
developer72fb0bb2023-01-11 09:46:29 +08004914 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4915 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004916
developer72fb0bb2023-01-11 09:46:29 +08004917 ret = fgets(line, sizeof(line), f);
4918 while (ret != NULL) {
4919 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004920 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08004921 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4922 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4923
4924 if (!filter_BSS) {
4925 index++;
4926 wifi_neighbor_ap2_t *tmp;
4927 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4928 if (tmp == NULL) { // no more memory to use
4929 index--;
4930 wifi_dbg_printf("%s: realloc failed\n", __func__);
4931 break;
4932 }
4933 scan_array = tmp;
4934 }
4935 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4936
4937 filter_BSS = false;
4938 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4939 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4940 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4941 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4942 } else if (strstr(line, "freq") != NULL) {
4943 sscanf(line," freq: %d", &freq);
4944 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4945
4946 if (freq >= 2412 && freq <= 2484) {
4947 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4948 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4949 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4950 }
4951 else if (freq >= 5160 && freq <= 5805) {
4952 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4953 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4954 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4955 }
4956
4957 scan_array[index].ap_Noise = 0;
4958 if (get_noise_ret == RETURN_OK) {
4959 for (int i = 0; i < channels_num; i++) {
4960 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4961 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4962 break;
4963 }
4964 }
4965 }
4966 } else if (strstr(line, "beacon interval") != NULL) {
4967 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4968 } else if (strstr(line, "signal") != NULL) {
4969 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4970 } else if (strstr(line,"SSID") != NULL) {
4971 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4972 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4973 filter_BSS = true;
4974 }
4975 } else if (strstr(line, "Supported rates") != NULL) {
4976 char SRate[80] = {0}, *tmp = NULL;
4977 memset(buf, 0, sizeof(buf));
4978 strcpy(SRate, line);
4979 tmp = strtok(SRate, ":");
4980 tmp = strtok(NULL, ":");
4981 strcpy(buf, tmp);
4982 memset(SRate, 0, sizeof(SRate));
4983
4984 tmp = strtok(buf, " \n");
4985 while (tmp != NULL) {
4986 strcat(SRate, tmp);
4987 if (SRate[strlen(SRate) - 1] == '*') {
4988 SRate[strlen(SRate) - 1] = '\0';
4989 }
4990 strcat(SRate, ",");
4991
4992 tmp = strtok(NULL, " \n");
4993 }
4994 SRate[strlen(SRate) - 1] = '\0';
4995 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4996 } else if (strstr(line, "DTIM") != NULL) {
4997 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4998 } else if (strstr(line, "VHT capabilities") != NULL) {
4999 strcat(scan_array[index].ap_SupportedStandards, ",ac");
5000 strcpy(scan_array[index].ap_OperatingStandards, "ac");
5001 } else if (strstr(line, "HT capabilities") != NULL) {
5002 strcat(scan_array[index].ap_SupportedStandards, ",n");
5003 strcpy(scan_array[index].ap_OperatingStandards, "n");
5004 } else if (strstr(line, "VHT operation") != NULL) {
5005 ret = fgets(line, sizeof(line), f);
5006 sscanf(line," * channel width: %d", &vht_channel_width);
5007 if(vht_channel_width == 1) {
5008 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
5009 } else {
5010 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
5011 }
5012 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5013 continue;
5014 } else if (strstr(line, "HT operation") != NULL) {
5015 ret = fgets(line, sizeof(line), f);
5016 sscanf(line," * secondary channel offset: %s", &buf);
5017 if (!strcmp(buf, "above")) {
5018 //40Mhz +
5019 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
5020 }
5021 else if (!strcmp(buf, "below")) {
5022 //40Mhz -
5023 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
5024 } else {
5025 //20Mhz
5026 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
5027 }
5028 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
5029 continue;
5030 } else if (strstr(line, "HE capabilities") != NULL) {
5031 strcat(scan_array[index].ap_SupportedStandards, ",ax");
5032 strcpy(scan_array[index].ap_OperatingStandards, "ax");
5033 ret = fgets(line, sizeof(line), f);
5034 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
5035 if (strstr(line, "HE40/2.4GHz") != NULL)
5036 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
5037 else
5038 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
5039 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
5040 if (strstr(line, "HE80/5GHz") != NULL) {
5041 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
5042 ret = fgets(line, sizeof(line), f);
5043 } else
5044 continue;
5045 if (strstr(line, "HE160/5GHz") != NULL)
5046 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
5047 }
5048 continue;
5049 } else if (strstr(line, "WPA") != NULL) {
5050 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
5051 } else if (strstr(line, "RSN") != NULL) {
5052 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
5053 } else if (strstr(line, "Group cipher") != NULL) {
5054 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
5055 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
5056 strcpy(scan_array[index].ap_EncryptionMode, "AES");
5057 }
5058 }
5059 ret = fgets(line, sizeof(line), f);
5060 }
5061
5062 if (!filter_BSS) {
5063 *output_array_size = index + 1;
5064 } else {
5065 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
5066 *output_array_size = index;
5067 }
5068 *neighbor_ap_array = scan_array;
5069 pclose(f);
5070 free(channels_noise_arr);
5071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5072 return RETURN_OK;
5073}
5074
5075//>> Deprecated: used for old RDKB code.
5076INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
5077{
5078 INT status = RETURN_ERR;
5079
5080 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5081 output_struct->wifi_PLCPErrorCount = 0;
5082 output_struct->wifi_FCSErrorCount = 0;
5083 output_struct->wifi_InvalidMACCount = 0;
5084 output_struct->wifi_PacketsOtherReceived = 0;
5085 output_struct->wifi_Noise = 0;
5086 status = RETURN_OK;
5087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5088 return status;
5089}
5090
5091INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
5092{
5093 char interface_name[16] = {0};
5094 char cmd[128] = {0};
5095 char buf[1280] = {0};
5096 char *pos = NULL;
5097
5098 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5099 if (NULL == output_struct)
5100 return RETURN_ERR;
5101
5102 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5103 return RETURN_ERR;
5104
5105 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5106
5107 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
5108 _syscmd(cmd, buf, sizeof(buf));
5109
5110 pos = buf;
5111 if ((pos = strstr(pos, "RX packets:")) == NULL)
5112 return RETURN_ERR;
5113 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
5114
5115 if ((pos = strstr(pos, "TX packets:")) == NULL)
5116 return RETURN_ERR;
5117 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
5118
5119 if ((pos = strstr(pos, "RX bytes:")) == NULL)
5120 return RETURN_ERR;
5121 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
5122
5123 if ((pos = strstr(pos, "TX bytes:")) == NULL)
5124 return RETURN_ERR;
5125 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
5126
5127 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
5128 _syscmd(cmd, buf, sizeof(buf));
5129 sscanf(buf, "%lu", &output_struct->wifi_Associations);
5130
5131#if 0
5132 //TODO: need to revisit below implementation
5133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5134 char interface_name[MAX_BUF_SIZE] = {0};
5135 char interface_status[MAX_BUF_SIZE] = {0};
5136 char Value[MAX_BUF_SIZE] = {0};
5137 char buf[MAX_CMD_SIZE] = {0};
5138 char cmd[MAX_CMD_SIZE] = {0};
5139 FILE *fp = NULL;
5140
5141 if (NULL == output_struct) {
5142 return RETURN_ERR;
5143 }
5144
5145 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
5146
5147 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
5148 {
5149 if(apIndex == 0) //private_wifi for 2.4G
5150 {
5151 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
5152 }
5153 else if(apIndex == 1) //private_wifi for 5G
5154 {
5155 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
5156 }
5157 else if(apIndex == 4) //public_wifi for 2.4G
5158 {
5159 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
5160 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
5161 {
5162 return RETURN_ERR;
5163 }
5164 if(buf[0] == '#')//tp-link
5165 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5166 else//tenda
5167 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
5168 }
5169 else if(apIndex == 5) //public_wifi for 5G
5170 {
5171 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5172 }
5173
5174 GetIfacestatus(interface_name, interface_status);
5175
5176 if(0 != strcmp(interface_status, "1"))
5177 return RETURN_ERR;
5178
5179 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5180 system(cmd);
5181
5182 fp = fopen("/tmp/SSID_Stats.txt", "r");
5183 if(fp == NULL)
5184 {
5185 printf("/tmp/SSID_Stats.txt not exists \n");
5186 return RETURN_ERR;
5187 }
5188 fclose(fp);
5189
5190 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5191 File_Reading(buf, Value);
5192 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
5193
5194 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5195 File_Reading(buf, Value);
5196 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
5197
5198 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
5199 File_Reading(buf, Value);
5200 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
5201
5202 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5203 File_Reading(buf, Value);
5204 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
5205
5206 /* There is no specific parameter from caller to associate the value wifi_Associations */
5207 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
5208 //_syscmd(cmd, buf, sizeof(buf));
5209 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
5210 }
5211#endif
5212 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5213 return RETURN_OK;
5214}
5215
5216INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
5217{
5218 char interface_name[MAX_BUF_SIZE] = {0};
5219 char interface_status[MAX_BUF_SIZE] = {0};
5220 char Value[MAX_BUF_SIZE] = {0};
5221 char buf[MAX_CMD_SIZE] = {0};
5222 char cmd[MAX_CMD_SIZE] = {0};
5223 FILE *fp = NULL;
5224
5225 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5226 if (NULL == output_struct)
5227 return RETURN_ERR;
5228
5229 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
5230
5231 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
5232 return RETURN_ERR;
5233 GetIfacestatus(interface_name, interface_status);
5234
5235 if(0 != strcmp(interface_status, "1"))
5236 return RETURN_ERR;
5237
5238 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
5239 system(cmd);
5240
5241 fp = fopen("/tmp/SSID_Stats.txt", "r");
5242 if(fp == NULL)
5243 {
5244 printf("/tmp/SSID_Stats.txt not exists \n");
5245 return RETURN_ERR;
5246 }
5247 fclose(fp);
5248
5249 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5250 File_Reading(buf, Value);
5251 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
5252
5253 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
5254 File_Reading(buf, Value);
5255 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
5256
5257 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5258 File_Reading(buf, Value);
5259 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
5260
5261 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
5262 File_Reading(buf, Value);
5263 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
5264
5265 output_struct->wifi_UnicastPacketsSent = 0;
5266 output_struct->wifi_UnicastPacketsReceived = 0;
5267 output_struct->wifi_MulticastPacketsSent = 0;
5268 output_struct->wifi_MulticastPacketsReceived = 0;
5269 output_struct->wifi_BroadcastPacketsSent = 0;
5270 output_struct->wifi_BroadcastPacketsRecevied = 0;
5271 output_struct->wifi_UnknownPacketsReceived = 0;
5272
5273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5274 return RETURN_OK;
5275}
5276
5277INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
5278{
5279 INT status = RETURN_ERR;
5280
5281 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5282 //Below values should get updated from hal
5283 output_struct->wifi_RetransCount=0;
5284 output_struct->wifi_FailedRetransCount=0;
5285 output_struct->wifi_RetryCount=0;
5286 output_struct->wifi_MultipleRetryCount=0;
5287 output_struct->wifi_ACKFailureCount=0;
5288 output_struct->wifi_AggregatedPacketCount=0;
5289
5290 status = RETURN_OK;
5291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5292
5293 return status;
5294}
5295
5296INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
5297{
5298 INT status = RETURN_ERR;
5299 UINT index;
5300 wifi_neighbor_ap_t *pt=NULL;
5301
5302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5303 *output_array_size=2;
5304 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
5305 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
5306 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
5307 strcpy(pt->ap_Radio,"");
5308 strcpy(pt->ap_SSID,"");
5309 strcpy(pt->ap_BSSID,"");
5310 strcpy(pt->ap_Mode,"");
5311 pt->ap_Channel=1;
5312 pt->ap_SignalStrength=0;
5313 strcpy(pt->ap_SecurityModeEnabled,"");
5314 strcpy(pt->ap_EncryptionMode,"");
5315 strcpy(pt->ap_OperatingFrequencyBand,"");
5316 strcpy(pt->ap_SupportedStandards,"");
5317 strcpy(pt->ap_OperatingStandards,"");
5318 strcpy(pt->ap_OperatingChannelBandwidth,"");
5319 pt->ap_BeaconPeriod=1;
5320 pt->ap_Noise=0;
5321 strcpy(pt->ap_BasicDataTransferRates,"");
5322 strcpy(pt->ap_SupportedDataTransferRates,"");
5323 pt->ap_DTIMPeriod=1;
5324 pt->ap_ChannelUtilization = 1;
5325 }
5326
5327 status = RETURN_OK;
5328 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5329
5330 return status;
5331}
5332
5333//----------------- AP HAL -------------------------------
5334
5335//>> Deprecated: used for old RDKB code.
5336INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
5337{
5338 if (NULL == output_ulong || NULL == output_struct)
5339 return RETURN_ERR;
5340 *output_ulong = 0;
5341 *output_struct = NULL;
5342 return RETURN_OK;
5343}
5344
5345#ifdef HAL_NETLINK_IMPL
5346static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
5347 struct nlattr *tb[NL80211_ATTR_MAX + 1];
5348 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
5349 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
5350 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
5351 char mac_addr[20];
5352 static int count=0;
5353 int rate=0;
5354
5355 wifi_device_info_t *out = (wifi_device_info_t*)arg;
5356
5357 nla_parse(tb,
5358 NL80211_ATTR_MAX,
5359 genlmsg_attrdata(gnlh, 0),
5360 genlmsg_attrlen(gnlh, 0),
5361 NULL);
5362
5363 if(!tb[NL80211_ATTR_STA_INFO]) {
5364 fprintf(stderr, "sta stats missing!\n");
5365 return NL_SKIP;
5366 }
5367
5368
5369 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
5370 fprintf(stderr, "failed to parse nested attributes!\n");
5371 return NL_SKIP;
5372 }
5373
5374 //devIndex starts from 1
5375 if( ++count == out->wifi_devIndex )
5376 {
5377 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
5378 //Getting the mac addrress
5379 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
5380
5381 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
5382 fprintf(stderr, "failed to parse nested rate attributes!");
5383 return NL_SKIP;
5384 }
5385
5386 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
5387 if(rinfo[NL80211_RATE_INFO_BITRATE])
5388 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5389 out->wifi_devTxRate = rate/10;
5390 }
5391
5392 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
5393 fprintf(stderr, "failed to parse nested rate attributes!");
5394 return NL_SKIP;
5395 }
5396
5397 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
5398 if(rinfo[NL80211_RATE_INFO_BITRATE])
5399 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
5400 out->wifi_devRxRate = rate/10;
5401 }
5402 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
5403 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
5404
5405 out->wifi_devAssociatedDeviceAuthentiationState = 1;
5406 count = 0; //starts the count for next cycle
5407 return NL_STOP;
5408 }
5409
5410 return NL_SKIP;
5411
5412}
5413#endif
5414
5415INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
5416{
5417#ifdef HAL_NETLINK_IMPL
5418 Netlink nl = {0};
5419 char if_name[10] = {0};
5420 char interface_name[16] = {0};
5421
5422 wifi_device_info_t info = {0};
5423 info.wifi_devIndex = devIndex;
5424
5425 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5426 return RETURN_ERR;
5427
5428 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5429
5430 nl.id = initSock80211(&nl);
5431
5432 if (nl.id < 0) {
5433 fprintf(stderr, "Error initializing netlink \n");
5434 return -1;
5435 }
5436
5437 struct nl_msg* msg = nlmsg_alloc();
5438
5439 if (!msg) {
5440 fprintf(stderr, "Failed to allocate netlink message.\n");
5441 nlfree(&nl);
5442 return -2;
5443 }
5444
5445 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +08005446 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +08005447 NL_AUTO_SEQ,
5448 nl.id,
5449 0,
5450 NLM_F_DUMP,
5451 NL80211_CMD_GET_STATION,
5452 0);
5453
5454 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +08005455 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +08005456 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
5457 nl_recvmsgs(nl.socket, nl.cb);
5458 nlmsg_free(msg);
5459 nlfree(&nl);
5460
5461 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
5462 output_struct->wifi_devRxRate = info.wifi_devRxRate;
5463 output_struct->wifi_devTxRate = info.wifi_devTxRate;
5464 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
5465 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
5466 return RETURN_OK;
5467#else
5468 //iw utility to retrieve station information
5469#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
5470#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
5471#define MACFILE "/tmp/wifi_AssoMac.txt"
5472#define TXRATEFILE "/tmp/wifi_txrate.txt"
5473#define RXRATEFILE "/tmp/wifi_rxrate.txt"
5474 FILE *file = NULL;
5475 char if_name[10] = {'\0'};
5476 char pipeCmd[256] = {'\0'};
5477 char line[256] = {0};
5478 char interface_name[16] = {0};
5479 int count = 0, device = 0;
5480
5481 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5482 return RETURN_ERR;
5483
5484 snprintf(if_name,sizeof(if_name),"%s", interface_name);
5485
5486 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
5487 file = popen(pipeCmd, "r");
5488
5489 if(file == NULL)
5490 return RETURN_ERR; //popen failed
5491
5492 fgets(line, sizeof line, file);
5493 device = atoi(line);
5494 pclose(file);
5495
5496 if(device == 0)
5497 return RETURN_ERR; //No devices are connected
5498
5499 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
5500 system(pipeCmd);
5501
5502 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
5503
5504 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
5505
5506 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
5507
5508 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
5509
5510 //devIndex starts from 1, ++count
5511 if((file = fopen(SIGNALFILE, "r")) != NULL )
5512 {
5513 for(count =0;fgets(line, sizeof line, file) != NULL;)
5514 {
5515 if (++count == devIndex)
5516 {
5517 output_struct->wifi_devSignalStrength = atoi(line);
5518 break;
5519 }
5520 }
5521 fclose(file);
5522 }
5523 else
5524 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
5525
5526 if((file = fopen(MACFILE, "r")) != NULL )
5527 {
5528 for(count =0;fgets(line, sizeof line, file) != NULL;)
5529 {
5530 if (++count == devIndex)
5531 {
5532 sscanf(line, "%02x:%02x:%02x:%02x:%02x:%02x",&output_struct->wifi_devMacAddress[0],&output_struct->wifi_devMacAddress[1],&output_struct->wifi_devMacAddress[2],&output_struct->wifi_devMacAddress[3],&output_struct->wifi_devMacAddress[4],&output_struct->wifi_devMacAddress[5]);
5533 break;
5534 }
5535 }
5536 fclose(file);
5537 }
5538 else
5539 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
5540
5541 if((file = fopen(TXRATEFILE, "r")) != NULL )
5542 {
5543 for(count =0;fgets(line, sizeof line, file) != NULL;)
5544 {
5545 if (++count == devIndex)
5546 {
5547 output_struct->wifi_devTxRate = atoi(line);
5548 break;
5549 }
5550 }
5551 fclose(file);
5552 }
5553 else
5554 fprintf(stderr,"fopen wifi_txrate.txt failed");
5555
5556 if((file = fopen(RXRATEFILE, "r")) != NULL)
5557 {
5558 for(count =0;fgets(line, sizeof line, file) != NULL;)
5559 {
5560 if (++count == devIndex)
5561 {
5562 output_struct->wifi_devRxRate = atoi(line);
5563 break;
5564 }
5565 }
5566 fclose(file);
5567 }
5568 else
5569 fprintf(stderr,"fopen wifi_rxrate.txt failed");
5570
5571 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
5572
5573 return RETURN_OK;
5574#endif
5575}
5576
5577INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
5578{
5579 if (NULL == device)
5580 return RETURN_ERR;
5581 return RETURN_OK;
5582}
5583//<<
5584
5585
5586//--------------wifi_ap_hal-----------------------------
5587//enables CTS protection for the radio used by this AP
5588INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
5589{
5590 //save config and Apply instantly
5591 return RETURN_ERR;
5592}
5593
5594// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
5595INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
5596{
5597 char config_file[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005598 char config_dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005599 char buf[64] = {'\0'};
developerd1824452023-05-18 12:30:04 +08005600 struct params list = {0};
5601 struct params dat = {0};
5602 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005603
5604 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5605 list.name = "ht_coex";
5606 snprintf(buf, sizeof(buf), "%d", enable);
5607 list.value = buf;
5608
developerd1824452023-05-18 12:30:04 +08005609 dat.name = "HT_BSSCoexistence";
5610 dat.value = buf;
5611
5612 band = wifi_index_to_band(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005613 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developerd1824452023-05-18 12:30:04 +08005614 snprintf(config_dat_file, sizeof(config_dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
developer72fb0bb2023-01-11 09:46:29 +08005615 wifi_hostapdWrite(config_file, &list, 1);
developerd1824452023-05-18 12:30:04 +08005616 wifi_datfileWrite(config_dat_file, &list, 1);
developer72fb0bb2023-01-11 09:46:29 +08005617 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5618
5619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5620
5621 return RETURN_OK;
5622}
5623
5624//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
5625INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
5626{
5627 char config_file[MAX_BUF_SIZE] = {'\0'};
5628 char buf[MAX_BUF_SIZE] = {'\0'};
5629 struct params list;
5630
5631 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5632 if (threshold < 256 || threshold > 2346 )
5633 return RETURN_ERR;
5634 list.name = "fragm_threshold";
5635 snprintf(buf, sizeof(buf), "%d", threshold);
5636 list.value = buf;
5637
5638 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
5639 wifi_hostapdWrite(config_file, &list, 1);
5640 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5641
5642 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5643
5644 return RETURN_OK;
5645}
5646
5647// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
5648INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
5649{
5650 char config_file[64] = {'\0'};
5651 char cmd[512] = {'\0'};
5652 char buf[512] = {'\0'};
5653 char stbc_config[16] = {'\0'};
5654 wifi_band band;
5655 int iterator = 0;
5656 BOOL current_stbc = FALSE;
5657 int ant_count = 0;
5658 int ant_bitmap = 0;
5659 struct params list;
developera1255e42023-05-13 17:45:02 +08005660 char dat_file[64] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005661
5662 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5663
5664 band = wifi_index_to_band(radioIndex);
5665 if (band == band_invalid)
5666 return RETURN_ERR;
5667
5668 if (band == band_2_4)
5669 iterator = 1;
developera1255e42023-05-13 17:45:02 +08005670 else if ((band == band_5) || (band == band_6))
developer72fb0bb2023-01-11 09:46:29 +08005671 iterator = 2;
5672 else
5673 return RETURN_OK;
5674
5675 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
5676 for (; ant_bitmap > 0; ant_bitmap >>= 1)
5677 ant_count += ant_bitmap & 1;
5678
5679 if (ant_count == 1 && STBC_Enable == TRUE) {
5680 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
5681 return RETURN_OK;
5682 }
5683
5684 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5685
5686 // set ht and vht config
5687 for (int i = 0; i < iterator; i++) {
5688 memset(stbc_config, 0, sizeof(stbc_config));
5689 memset(cmd, 0, sizeof(cmd));
5690 memset(buf, 0, sizeof(buf));
5691 list.name = (i == 0)?"ht_capab":"vht_capab";
5692 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5693 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5694 _syscmd(cmd, buf, sizeof(buf));
5695 if (strlen(buf) != 0)
5696 current_stbc = TRUE;
5697 if (current_stbc == STBC_Enable)
5698 continue;
5699
5700 if (STBC_Enable == TRUE) {
5701 // Append the STBC flags in capab config
5702 memset(cmd, 0, sizeof(cmd));
5703 if (i == 0)
5704 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5705 else
5706 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5707 _syscmd(cmd, buf, sizeof(buf));
5708 } else if (STBC_Enable == FALSE) {
5709 // Remove the STBC flags and remain other flags in capab
5710 memset(cmd, 0, sizeof(cmd));
5711 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5712 _syscmd(cmd, buf, sizeof(buf));
5713 memset(cmd, 0, sizeof(cmd));
5714 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5715 _syscmd(cmd, buf, sizeof(buf));
5716 }
5717 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5718 list.value = buf;
5719 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5720 }
developera1255e42023-05-13 17:45:02 +08005721 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5722 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_STBC=.*/HT_STBC=%d/g' %s", STBC_Enable, dat_file);
5723 _syscmd(cmd, buf, sizeof(buf));
5724 if ((band == band_5) || (band == band_6)) {
5725 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^VHT_STBC=.*/VHT_STBC=%d/g' %s", STBC_Enable, dat_file);
5726 _syscmd(cmd, buf, sizeof(buf));
5727 }
5728 /*wifi_reloadAp(radioIndex);
5729 the caller do this.*/
developer72fb0bb2023-01-11 09:46:29 +08005730
5731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5732 return RETURN_OK;
5733}
5734
5735// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5736INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5737{
developer2c22d832023-05-18 17:46:26 +08005738 char dat_file[128] = {0};
5739 BOOL enable;
5740 wifi_band band;
5741 char amdus_buff[8] = {'\0'};
developer72fb0bb2023-01-11 09:46:29 +08005742
developer2c22d832023-05-18 17:46:26 +08005743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005744
developer2c22d832023-05-18 17:46:26 +08005745 band = wifi_index_to_band(radioIndex);
5746 if (band == band_invalid) {
5747 printf("%s:Band Error\n", __func__);
5748 return RETURN_ERR;
5749 }
5750 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5751 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
5752 if (strncmp(amdus_buff, "1", 1) == 0)
developer72fb0bb2023-01-11 09:46:29 +08005753 *output_bool = TRUE;
developer2c22d832023-05-18 17:46:26 +08005754 else
5755 *output_bool = FALSE;
developer72fb0bb2023-01-11 09:46:29 +08005756
developer2c22d832023-05-18 17:46:26 +08005757 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5758
5759 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005760}
5761
5762// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5763INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5764{
developer2c22d832023-05-18 17:46:26 +08005765 char dat_file[128] = {0};
5766 BOOL enable;
5767 wifi_band band;
5768 char amdus_buff[8] = {'\0'};
5769 struct params params = {0};
developer72fb0bb2023-01-11 09:46:29 +08005770
developer2c22d832023-05-18 17:46:26 +08005771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005772
developer2c22d832023-05-18 17:46:26 +08005773 band = wifi_index_to_band(radioIndex);
5774 if (band == band_invalid) {
5775 printf("%s:Band Error\n", __func__);
5776 return RETURN_ERR;
5777 }
5778 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5779 wifi_datfileRead(dat_file, "HT_AMSDU", amdus_buff, sizeof(amdus_buff));
5780 if (strncmp(amdus_buff, "1", 1) == 0)
5781 enable = TRUE;
5782 else
5783 enable = FALSE;
5784 if (amsduEnable == enable)
5785 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005786
developer2c22d832023-05-18 17:46:26 +08005787 params.name = "HT_AMSDU";
5788 if (amsduEnable)
5789 params.value = "1";
5790 else
5791 params.value = "0";
5792 wifi_datfileWrite(dat_file, &params, 1);
5793 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +08005794
developer2c22d832023-05-18 17:46:26 +08005795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08005796
developer72fb0bb2023-01-11 09:46:29 +08005797 return RETURN_OK;
5798}
5799
5800//P2 // outputs the number of Tx streams
5801INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5802{
5803 char buf[8] = {0};
5804 char cmd[128] = {0};
5805 int phyId = 0;
5806
5807 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5808
5809 phyId = radio_index_to_phy(radioIndex);
5810 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5811 _syscmd(cmd, buf, sizeof(buf));
5812
5813 *output_int = (INT)strtol(buf, NULL, 16);
5814
5815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5816
5817 return RETURN_OK;
5818}
5819
5820INT fitChainMask(INT radioIndex, int antcount)
5821{
5822 char buf[128] = {0};
5823 char cmd[128] = {0};
5824 char config_file[64] = {0};
5825 wifi_band band;
5826 struct params list[2] = {0};
5827
5828 band = wifi_index_to_band(radioIndex);
5829 if (band == band_invalid)
5830 return RETURN_ERR;
5831
5832 list[0].name = "he_mu_beamformer";
5833 list[1].name = "he_su_beamformer";
5834
5835 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5836 if (antcount == 1) {
5837 // remove config about multiple antennas
5838 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5839 _syscmd(cmd, buf, sizeof(buf));
5840
5841 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5842 _syscmd(cmd, buf, sizeof(buf));
5843
5844 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5845 _syscmd(cmd, buf, sizeof(buf));
5846
5847 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5848 _syscmd(cmd, buf, sizeof(buf));
5849
5850 list[0].value = "0";
5851 list[1].value = "0";
5852 } else {
5853 // If we only set RX STBC means STBC is enable and TX STBC is disable when last time set one antenna. so we need to add it back.
5854 if (band == band_2_4 || band == band_5) {
5855 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5856 _syscmd(cmd, buf, sizeof(buf));
5857 if (strlen(buf) > 0) {
5858 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5859 _syscmd(cmd, buf, sizeof(buf));
5860 }
5861 }
5862 if (band == band_5) {
5863 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5864 _syscmd(cmd, buf, sizeof(buf));
5865 if (strlen(buf) > 0) {
5866 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5867 _syscmd(cmd, buf, sizeof(buf));
5868 }
5869 }
5870
5871 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5872 _syscmd(cmd, buf, sizeof(buf));
5873 if (strlen(buf) == 0) {
5874 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5875 _syscmd(cmd, buf, sizeof(buf));
5876 }
5877
5878 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5879 _syscmd(cmd, buf, sizeof(buf));
5880 if (strlen(buf) == 0) {
5881 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5882 _syscmd(cmd, buf, sizeof(buf));
5883 }
5884
5885 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5886 _syscmd(cmd, buf, sizeof(buf));
5887 if (strlen(buf) == 0) {
5888 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5889 } else {
5890 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5891 }
5892 _syscmd(cmd, buf, sizeof(buf));
5893
5894 list[0].value = "1";
5895 list[1].value = "1";
5896 }
5897 wifi_hostapdWrite(config_file, list, 2);
5898}
5899
5900//P2 // sets the number of Tx streams to an enviornment variable
5901INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5902{
5903 char cmd[128] = {0};
5904 char buf[128] = {0};
5905 int phyId = 0;
5906 int cur_mask = 0;
developera1255e42023-05-13 17:45:02 +08005907 int antcountmsk = 0;
5908 INT cur_nss = 0;
5909 UCHAR dat_file[64] = {0};
5910 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +08005911
5912 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5913
5914 if (numStreams <= 0) {
5915 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5916 return RETURN_ERR;
5917 }
5918
developera1255e42023-05-13 17:45:02 +08005919 wifi_getRadioTxChainMask(radioIndex, &cur_mask);//this is mask value
5920 for(; cur_mask > 0; cur_mask >>= 1)//convert to number of streams.
5921 cur_nss += 1;
5922 WIFI_ENTRY_EXIT_DEBUG("%s:cur_nss=%d, new_nss=%d\n", __func__, cur_nss, numStreams);
5923 if (cur_nss == numStreams)
developer72fb0bb2023-01-11 09:46:29 +08005924 return RETURN_OK;
5925
5926 wifi_setRadioEnable(radioIndex, FALSE);
5927
5928 phyId = radio_index_to_phy(radioIndex);
developera1255e42023-05-13 17:45:02 +08005929 //iw need mask value.
5930 for (;numStreams > 0; numStreams--)
5931 antcountmsk |= 0x1 << (numStreams - 1);
5932 snprintf(cmd, sizeof(cmd), "iw phy%d set antenna 0x%x 2>&1", phyId, antcountmsk);
developer72fb0bb2023-01-11 09:46:29 +08005933 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005934 if (strlen(buf) > 0) {
5935 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5936 return RETURN_ERR;
5937 }
developera1255e42023-05-13 17:45:02 +08005938 band = wifi_index_to_band(radioIndex);
5939 if (band == band_invalid) {
5940 printf("%s:Band Error\n", __func__);
5941 return RETURN_ERR;
5942 }
5943 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
5944 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_TxStream=.*/HT_TxStream=%d/g' %s", numStreams, dat_file);
5945 _syscmd(cmd, buf, sizeof(buf));
5946 if (strlen(buf) > 0) {
5947 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5948 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005949 }
developera1255e42023-05-13 17:45:02 +08005950 snprintf(cmd, sizeof(cmd), "sed -r -i 's/^HT_RxStream=.*/HT_RxStream=%d/g' %s", numStreams, dat_file);
5951 _syscmd(cmd, buf, sizeof(buf));
5952 if (strlen(buf) > 0) {
5953 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5954 return RETURN_ERR;
5955 }
5956 fitChainMask(radioIndex, numStreams);
developer72fb0bb2023-01-11 09:46:29 +08005957 wifi_setRadioEnable(radioIndex, TRUE);
5958
5959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5960 return RETURN_OK;
5961}
5962
5963//P2 // outputs the number of Rx streams
5964INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5965{
5966 char buf[8] = {0};
5967 char cmd[128] = {0};
5968 int phyId = 0;
5969
5970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5971
5972 phyId = radio_index_to_phy(radioIndex);
5973 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5974 _syscmd(cmd, buf, sizeof(buf));
5975
5976 *output_int = (INT)strtol(buf, NULL, 16);
5977
5978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5979
5980 return RETURN_OK;
5981}
5982
5983//P2 // sets the number of Rx streams to an enviornment variable
5984INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5985{
5986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5987 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5988 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5989 return RETURN_ERR;
5990 }
5991 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5992 return RETURN_ERR;
5993}
5994
5995//Get radio RDG enable setting
5996INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5997{
developer47cc27a2023-05-17 23:09:58 +08005998 if (NULL == output_bool)
5999 return RETURN_ERR;
6000
6001 *output_bool = TRUE;
6002 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006003}
6004
6005//Get radio RDG enable setting
6006INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
6007{
developer47cc27a2023-05-17 23:09:58 +08006008 char cmd[MAX_CMD_SIZE] = {0};
6009 char buf[MAX_BUF_SIZE] = {0};
6010 char rdg_status[2] = {0};
6011 char dat_file[MAX_CMD_SIZE] = {0};
6012 struct params params = {0};
6013
6014 if (NULL == output_bool)
6015 return RETURN_ERR;
6016
6017 /*prepare dat file path*/
6018 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6019
6020 wifi_datfileRead(dat_file, "HT_RDG", rdg_status, sizeof(rdg_status));
6021 if (!strncmp(rdg_status, "1", sizeof(rdg_status)))
6022 *output_bool = TRUE;
6023 else
6024 *output_bool = FALSE;
6025
6026 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006027}
6028
6029//Set radio RDG enable setting
6030INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
6031{
developer47cc27a2023-05-17 23:09:58 +08006032 char cmd[MAX_CMD_SIZE] = {0};
6033 char buf[MAX_BUF_SIZE] = {0};
6034 char dat_file[MAX_CMD_SIZE] = {0};
6035 struct params params = {0};
6036
6037 /*prepare dat file path*/
6038 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, radioIndex);
6039
6040 params.name = "HT_RDG";
6041
6042 if (enable) {
6043 params.value = "1";
6044 } else {
6045 params.value = "0";
6046 }
6047
6048 wifi_datfileWrite(dat_file, &params, 1);
6049
6050 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006051}
6052
6053//Get radio ADDBA enable setting
6054INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
6055{
6056 if (NULL == output_bool)
6057 return RETURN_ERR;
6058 *output_bool = TRUE;
6059 return RETURN_OK;
6060}
6061
6062//Set radio ADDBA enable setting
6063INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
6064{
6065 return RETURN_ERR;
6066}
6067
6068//Get radio auto block ack enable setting
6069INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
6070{
6071 if (NULL == output_bool)
6072 return RETURN_ERR;
6073 *output_bool = TRUE;
6074 return RETURN_OK;
6075}
6076
6077//Set radio auto block ack enable setting
6078INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
6079{
6080 return RETURN_ERR;
6081}
6082
6083//Get radio 11n pure mode enable support
6084INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
6085{
6086 if (NULL == output_bool)
6087 return RETURN_ERR;
6088 *output_bool = TRUE;
6089 return RETURN_OK;
6090}
6091
6092//Get radio 11n pure mode enable setting
6093INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
6094{
6095 if (NULL == output_bool)
6096 return RETURN_ERR;
6097 *output_bool = TRUE;
6098 return RETURN_OK;
6099}
6100
6101//Set radio 11n pure mode enable setting
6102INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
6103{
6104 return RETURN_ERR;
6105}
6106
6107//Get radio IGMP snooping enable setting
6108INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
6109{
6110 char interface_name[16] = {0};
6111 char cmd[128]={0};
6112 char buf[4]={0};
6113 bool bridge = FALSE, mac80211 = FALSE;
6114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6115
6116 if(output_bool == NULL)
6117 return RETURN_ERR;
6118
6119 *output_bool = FALSE;
6120
6121 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
6122 _syscmd(cmd, buf, sizeof(buf));
6123 if (strncmp(buf, "1", 1) == 0)
6124 bridge = TRUE;
6125
6126 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
6127 return RETURN_ERR;
6128 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
6129 _syscmd(cmd, buf, sizeof(buf));
6130 if (strncmp(buf, "1", 1) == 0)
6131 mac80211 = TRUE;
6132
6133 if (bridge && mac80211)
6134 *output_bool = TRUE;
6135
6136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6137 return RETURN_OK;
6138}
6139
6140//Set radio IGMP snooping enable setting
6141INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
6142{
6143 char interface_name[16] = {0};
6144 char cmd[128]={0};
6145 char buf[4]={0};
6146 int max_num_radios =0;
6147 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6148
6149 // bridge
6150 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
6151 _syscmd(cmd, buf, sizeof(buf));
6152
6153 wifi_getMaxRadioNumber(&max_num_radios);
6154 // mac80211
6155 for (int i = 0; i < max_num_radios; i++) {
6156 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
6157 return RETURN_ERR;
6158 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
6159 _syscmd(cmd, buf, sizeof(buf));
6160 }
6161 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6162 return RETURN_OK;
6163}
6164
6165//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08006166INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08006167{
developer69b61b02023-03-07 17:17:44 +08006168 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08006169 return RETURN_ERR;
6170 *output_int = (radioIndex==0)? 1: 3;
6171
6172 return RETURN_OK;
6173}
6174
6175
6176//---------------------------------------------------------------------------------------------------
6177//
6178// Additional Wifi AP level APIs used for Access Point devices
6179//
6180//---------------------------------------------------------------------------------------------------
6181
6182// creates a new ap and pushes these parameters to the hardware
6183INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
6184{
6185 // Deprecated when use hal version 3, use wifi_createVap() instead.
6186 return RETURN_OK;
6187}
6188
6189// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
6190INT wifi_deleteAp(INT apIndex)
6191{
developer7e4a2a62023-04-06 19:56:03 +08006192 char interface_name[16] = {0};
6193 char buf[MAX_BUF_SIZE];
6194 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006195
developer7e4a2a62023-04-06 19:56:03 +08006196 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6197 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08006198
developer7e4a2a62023-04-06 19:56:03 +08006199 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6200 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006201
developer7e4a2a62023-04-06 19:56:03 +08006202 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006203
developer7e4a2a62023-04-06 19:56:03 +08006204 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006205}
6206
6207// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
6208INT wifi_getApName(INT apIndex, CHAR *output_string)
6209{
developer7e4a2a62023-04-06 19:56:03 +08006210 char interface_name[IF_NAME_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08006211 int radio_idx = 0;
6212 int bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006213
developer7e4a2a62023-04-06 19:56:03 +08006214 if(!output_string)
6215 return RETURN_ERR;
6216
6217 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6218 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
6219
6220 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
6221 } else
6222 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
6223
6224 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006225}
6226
6227// Outputs the index number in that corresponds to the SSID string
6228INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
6229{
developer7e4a2a62023-04-06 19:56:03 +08006230 char cmd [128] = {0};
6231 char buf[32] = {0};
6232 char ap_idx = 0;
6233 char *apIndex_str = NULL;
6234 char radio_idx = 0;
6235 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08006236
developer7e4a2a62023-04-06 19:56:03 +08006237 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
6238 inputSsidString);
6239 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006240
developer7e4a2a62023-04-06 19:56:03 +08006241 if (strlen(buf)) {
6242 apIndex_str = strtok(buf, "\n");
6243 *output_int = strtoul(apIndex_str, NULL, 10);
6244 return RETURN_OK;
6245 }
developer72fb0bb2023-01-11 09:46:29 +08006246
developer7e4a2a62023-04-06 19:56:03 +08006247 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
6248 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
6249 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
6250 radio_idx = 2;
6251 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
6252 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
6253 radio_idx = 1;
6254 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
6255 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
6256 radio_idx = 0;
6257 } else {
6258 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
6259 __func__, inputSsidString, ap_idx);
6260 *output_int = -1;
6261 return RETURN_ERR;
6262 }
6263
6264 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
6265
6266 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
6267 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
6268 __func__, inputSsidString, ap_idx);
6269 *output_int = ap_idx;
6270 return RETURN_OK;
6271 }
6272
6273 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006274}
6275
6276INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
6277{
6278 return wifi_getIndexFromName(inputSsidString, output_int);
6279}
6280
6281// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
6282INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
6283{
6284 char buf[MAX_BUF_SIZE] = {0};
6285 char cmd[MAX_CMD_SIZE] = {0};
6286 char config_file[MAX_BUF_SIZE] = {0};
6287
6288 if(NULL == output_string)
6289 return RETURN_ERR;
6290
6291 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6292 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
6293 if((strcmp(buf,"3")==0))
6294 snprintf(output_string, 32, "WPAand11i");
6295 else if((strcmp(buf,"2")==0))
6296 snprintf(output_string, 32, "11i");
6297 else if((strcmp(buf,"1")==0))
6298 snprintf(output_string, 32, "WPA");
6299 else
6300 snprintf(output_string, 32, "None");
6301
6302 return RETURN_OK;
6303}
6304
6305// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
6306INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
6307{
6308 char config_file[MAX_BUF_SIZE] = {0};
6309 struct params list;
6310
6311 if (NULL == beaconTypeString)
6312 return RETURN_ERR;
6313 list.name = "wpa";
6314 list.value = "0";
6315
6316 if((strcmp(beaconTypeString,"WPAand11i")==0))
6317 list.value="3";
6318 else if((strcmp(beaconTypeString,"11i")==0))
6319 list.value="2";
6320 else if((strcmp(beaconTypeString,"WPA")==0))
6321 list.value="1";
6322
6323 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6324 wifi_hostapdWrite(config_file, &list, 1);
6325 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6326 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6327 return RETURN_OK;
6328}
6329
6330// sets the beacon interval on the hardware for this AP
6331INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
6332{
6333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6334 struct params params={'\0'};
6335 char buf[MAX_BUF_SIZE] = {'\0'};
6336 char config_file[MAX_BUF_SIZE] = {'\0'};
6337
6338 params.name = "beacon_int";
6339 snprintf(buf, sizeof(buf), "%u", beaconInterval);
6340 params.value = buf;
6341
6342 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6343 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08006344
developer72fb0bb2023-01-11 09:46:29 +08006345 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6347 return RETURN_OK;
6348}
6349
6350INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
6351{
6352 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
6353 return RETURN_ERR;
6354 return RETURN_OK;
6355}
6356
6357// Get the packet size threshold supported.
6358INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
6359{
6360 //save config and apply instantly
6361 if (NULL == output_bool)
6362 return RETURN_ERR;
6363 *output_bool = TRUE;
6364 return RETURN_OK;
6365}
6366
6367// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
6368INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
6369{
developer72fb0bb2023-01-11 09:46:29 +08006370 char buf[16] = {0};
6371 char config_file[128] = {0};
6372 struct params param = {0};
6373
6374 if (threshold > 65535) {
6375 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
6376 return RETURN_ERR;
6377 }
6378
developer23e71282023-01-18 10:25:19 +08006379 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006380 snprintf(buf, sizeof(buf), "%u", threshold);
6381 param.name = "rts_threshold";
6382 param.value = buf;
6383 wifi_hostapdWrite(config_file, &param, 1);
6384 wifi_hostapdProcessUpdate(apIndex, &param, 1);
6385 wifi_reloadAp(apIndex);
6386
6387 return RETURN_OK;
6388}
6389
6390// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6391INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
6392{
6393 if (NULL == output_string)
6394 return RETURN_ERR;
6395 snprintf(output_string, 32, "TKIPandAESEncryption");
6396 return RETURN_OK;
6397
6398}
6399
6400// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6401INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
6402{
6403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6404 char *param_name = NULL;
6405 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
6406
6407 if(NULL == output_string)
6408 return RETURN_ERR;
6409
6410 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6411 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6412
6413 if(strcmp(buf,"0")==0)
6414 {
6415 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
6416 snprintf(output_string, 32, "None");
6417 return RETURN_OK;
6418 }
6419 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
6420 param_name = "rsn_pairwise";
6421 else if((strcmp(buf,"1")==0))
6422 param_name = "wpa_pairwise";
6423 else
6424 return RETURN_ERR;
6425 memset(output_string,'\0',32);
6426 wifi_hostapdRead(config_file,param_name,output_string,32);
6427 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
6428 param_name = "wpa_pairwise";
6429 memset(output_string, '\0', 32);
6430 wifi_hostapdRead(config_file, param_name, output_string, 32);
6431 }
6432 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
6433
developere5750452023-05-15 16:46:42 +08006434 if(strcmp(output_string,"TKIP CCMP") == 0)
6435 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
6436 else if(strcmp(output_string,"TKIP") == 0)
developer72fb0bb2023-01-11 09:46:29 +08006437 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
6438 else if(strcmp(output_string,"CCMP") == 0)
6439 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
developer72fb0bb2023-01-11 09:46:29 +08006440
6441 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6442 return RETURN_OK;
6443}
6444
6445// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
6446INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
6447{
6448 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6449 struct params params={'\0'};
6450 char output_string[32];
6451 char config_file[MAX_BUF_SIZE] = {0};
6452
6453 memset(output_string,'\0',32);
developere5750452023-05-15 16:46:42 +08006454 wifi_getApBeaconType(apIndex,output_string);
developer72fb0bb2023-01-11 09:46:29 +08006455
6456 if(strcmp(encMode, "TKIPEncryption") == 0)
6457 params.value = "TKIP";
6458 else if(strcmp(encMode,"AESEncryption") == 0)
6459 params.value = "CCMP";
6460 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
6461 params.value = "TKIP CCMP";
6462
6463 if((strcmp(output_string,"WPAand11i")==0))
6464 {
6465 params.name = "wpa_pairwise";
6466 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6467 wifi_hostapdWrite(config_file, &params, 1);
6468 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6469
6470 params.name = "rsn_pairwise";
6471 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6472 wifi_hostapdWrite(config_file, &params, 1);
6473 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6474
6475 return RETURN_OK;
6476 }
6477 else if((strcmp(output_string,"11i")==0))
6478 {
6479 params.name = "rsn_pairwise";
6480 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6481 wifi_hostapdWrite(config_file, &params, 1);
6482 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6483 return RETURN_OK;
6484 }
6485 else if((strcmp(output_string,"WPA")==0))
6486 {
6487 params.name = "wpa_pairwise";
6488 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6489 wifi_hostapdWrite(config_file, &params, 1);
6490 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6491 return RETURN_OK;
6492 }
6493
6494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6495 return RETURN_OK;
6496}
6497
6498// deletes internal security varable settings for this ap
6499INT wifi_removeApSecVaribles(INT apIndex)
6500{
6501 //TODO: remove the entry in hostapd config file
6502 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
6503 //_syscmd(cmd, buf, sizeof(buf));
6504
6505 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
6506 //_syscmd(cmd, buf, sizeof(buf));
6507 return RETURN_ERR;
6508}
6509
6510// changes the hardware settings to disable encryption on this ap
6511INT wifi_disableApEncryption(INT apIndex)
6512{
6513 //Apply instantly
6514 return RETURN_ERR;
6515}
6516
6517// set the authorization mode on this ap
6518// mode mapping as: 1: open, 2: shared, 4:auto
6519INT wifi_setApAuthMode(INT apIndex, INT mode)
6520{
6521 struct params params={0};
6522 char config_file[64] = {0};
6523 int ret;
6524
6525 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6526
6527 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
6528 params.name = "auth_algs";
6529
developere5750452023-05-15 16:46:42 +08006530 if ((mode & 1 && mode & 2) || mode & 4)
developer72fb0bb2023-01-11 09:46:29 +08006531 params.value = "3";
6532 else if (mode & 2)
6533 params.value = "2";
6534 else if (mode & 1)
6535 params.value = "1";
6536 else
6537 params.value = "0";
6538
6539 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6540 wifi_hostapdWrite(config_file, &params, 1);
6541 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08006542 wifi_reloadAp(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6544
6545 return RETURN_OK;
6546}
6547
6548// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6549INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6550{
6551 //save to wifi config, and wait for wifi restart to apply
6552 struct params params={'\0'};
6553 char config_file[MAX_BUF_SIZE] = {0};
6554 int ret;
6555
6556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6557 if(authMode == NULL)
6558 return RETURN_ERR;
6559
6560 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
6561 params.name = "wpa_key_mgmt";
6562
6563 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
6564 params.value = "WPA-PSK";
6565 else if(strcmp(authMode,"EAPAuthentication") == 0)
6566 params.value = "WPA-EAP";
6567 else if (strcmp(authMode, "SAEAuthentication") == 0)
6568 params.value = "SAE";
6569 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
6570 params.value = "WPA-EAP-SUITE-B-192";
6571 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
6572 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08006573 else if (strcmp(authMode, "Enhanced_Open") == 0)
6574 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08006575 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
6576 return RETURN_OK; //This is taken careof in beaconType
6577
6578 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6579 ret=wifi_hostapdWrite(config_file,&params,1);
6580 if(!ret)
6581 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
6582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6583
6584 return ret;
6585}
6586
6587// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
6588INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
6589{
6590 //save to wifi config, and wait for wifi restart to apply
6591 char BeaconType[50] = {0};
6592 char config_file[MAX_BUF_SIZE] = {0};
6593
6594 *authMode = 0;
6595 wifi_getApBeaconType(apIndex,BeaconType);
6596 printf("%s____%s \n",__FUNCTION__,BeaconType);
6597
6598 if(strcmp(BeaconType,"None") == 0)
6599 strcpy(authMode,"None");
6600 else
6601 {
6602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6603 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
6604 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
6605 if(strcmp(authMode,"WPA-PSK") == 0)
6606 strcpy(authMode,"SharedAuthentication");
6607 else if(strcmp(authMode,"WPA-EAP") == 0)
6608 strcpy(authMode,"EAPAuthentication");
6609 }
6610
6611 return RETURN_OK;
6612}
6613
6614// Outputs the number of stations associated per AP
6615INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
6616{
6617 char interface_name[16] = {0};
6618 char cmd[128]={0};
6619 char buf[128]={0};
6620 BOOL status = false;
6621
6622 if(apIndex > MAX_APS)
6623 return RETURN_ERR;
6624
6625 wifi_getApEnable(apIndex,&status);
6626 if (!status)
6627 return RETURN_OK;
6628
6629 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
6630 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6631 return RETURN_ERR;
6632 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
6633 _syscmd(cmd, buf, sizeof(buf));
6634 sscanf(buf,"%lu", output_ulong);
6635
6636 return RETURN_OK;
6637}
6638
6639// manually removes any active wi-fi association with the device specified on this ap
6640INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
6641{
developer7e4a2a62023-04-06 19:56:03 +08006642 char inf_name[16] = {0};
6643 char cmd[MAX_CMD_SIZE] = {0};
6644 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006645
developer7e4a2a62023-04-06 19:56:03 +08006646 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08006647 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006648
6649 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
6650 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006651
6652 return RETURN_OK;
6653}
6654
6655// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
6656INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
6657{
developer7e4a2a62023-04-06 19:56:03 +08006658 int max_radio_num = 0;
6659
6660 if(NULL == output_int)
6661 return RETURN_ERR;
6662
6663 wifi_getMaxRadioNumber(&max_radio_num);
6664 *output_int = apIndex % max_radio_num;
6665
6666 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006667}
6668
6669// sets the radio index for the specific ap
6670INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
6671{
6672 //set to config only and wait for wifi reset to apply settings
6673 return RETURN_ERR;
6674}
6675
developer121a8e72023-05-22 09:19:39 +08006676
6677#define MAX_ACL_DUMP_LEN 4096
6678int mtk_acl_list_dump_callback(struct nl_msg *msg, void *cb)
6679{
6680 struct nlattr *tb[NL80211_ATTR_MAX + 1];
6681 struct nlattr *vndr_tb[MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX + 1];
6682 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6683 char *show_str = NULL;
6684 int err = 0, skip_len = 0;
6685 unsigned short acl_result_len = 0;
6686 struct mtk_nl80211_cb_data *cb_data = cb;
6687
6688 if (!msg || !cb_data) {
6689 wifi_debug(DEBUG_ERROR, "msg(0x%lx) or cb_data(0x%lx) is null,error.", msg, cb_data);
6690 return NL_SKIP;
6691 }
6692
6693 err = nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
6694 genlmsg_attrlen(gnlh, 0), NULL);
6695 if (err < 0) {
6696 wifi_debug(DEBUG_ERROR, "nla_parse acl list nl80211 msg fails,error.");
6697 return NL_SKIP;
6698 }
6699
6700 if (tb[NL80211_ATTR_VENDOR_DATA]) {
6701 err = nla_parse_nested(vndr_tb, MTK_NL80211_VENDOR_AP_ACL_ATTR_MAX,
6702 tb[NL80211_ATTR_VENDOR_DATA], NULL);
6703 if (err < 0)
6704 return NL_SKIP;
6705 if (vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]) {
6706 acl_result_len = nla_len(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
6707 show_str = nla_data(vndr_tb[MTK_NL80211_VENDOR_ATTR_ACL_LIST_INFO]);
6708 if (acl_result_len > MAX_ACL_DUMP_LEN) {
6709 wifi_debug(DEBUG_ERROR,"the scan result len is invalid !!!\n");
6710 return NL_SKIP;
6711 } else if (*(show_str + acl_result_len - 1) != '\0') {
6712 wifi_debug(DEBUG_INFO, "the result string is not ended with right terminator, handle it!!!\n");
6713 *(show_str + acl_result_len - 1) = '\0';
6714 }
6715 wifi_debug(DEBUG_INFO, "driver msg:%s\n", show_str);
6716 /*skip the first line: 'policy=1\n' len check*/
6717 skip_len = (strchr(show_str, '\n')+1 - show_str);
6718 if (cb_data->out_len < acl_result_len-skip_len) {
6719 wifi_debug(DEBUG_ERROR, "output buffer is not enough! error.\n");
6720 return NL_SKIP;
6721 }
6722 memset(cb_data->out_buf, 0, cb_data->out_len);
6723 /*skip the first line: 'policy=1\n' to find the acl mac addrs*/
6724 memmove(cb_data->out_buf, strchr(show_str, '\n')+1, acl_result_len-skip_len);
6725 wifi_debug(DEBUG_INFO, "out buff:%s", cb_data->out_buf);
6726 } else
6727 wifi_debug(DEBUG_ERROR, "no acl result attr\n");
6728 } else
6729 wifi_debug(DEBUG_ERROR, "no any acl result from driver\n");
6730 return NL_OK;
6731}
developer72fb0bb2023-01-11 09:46:29 +08006732// Get the ACL MAC list per AP
6733INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6734{
developer7e4a2a62023-04-06 19:56:03 +08006735 char inf_name[IF_NAME_SIZE] = {0};
developer121a8e72023-05-22 09:19:39 +08006736 struct mtk_nl80211_param params;
6737 unsigned int if_idx = 0;
6738 int ret = -1;
6739 struct unl unl_ins;
6740 struct nl_msg *msg = NULL;
6741 struct nlattr * msg_data = NULL;
6742 struct mtk_nl80211_param param;
6743 struct mtk_nl80211_cb_data cb_data;
developer72fb0bb2023-01-11 09:46:29 +08006744
developer7e4a2a62023-04-06 19:56:03 +08006745 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6746 return RETURN_ERR;
6747
developer121a8e72023-05-22 09:19:39 +08006748 if_idx = if_nametoindex(inf_name);
6749 if (!if_idx) {
6750 wifi_debug(DEBUG_ERROR,"can't finde ifname(%s) index,ERROR", inf_name);
6751 return RETURN_ERR;
6752 }
6753 /*init mtk nl80211 vendor cmd*/
6754 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
6755 param.if_type = NL80211_ATTR_IFINDEX;
6756 param.if_idx = if_idx;
6757
6758 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6759 if (ret) {
6760 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
6761 return RETURN_ERR;
6762 }
developer7e4a2a62023-04-06 19:56:03 +08006763
developer121a8e72023-05-22 09:19:39 +08006764 /*add mtk vendor cmd data*/
6765 if (nla_put_flag(msg, MTK_NL80211_VENDOR_ATTR_ACL_SHOW_ALL)) {
6766 printf("Nla put ACL_SHOW_ALL attribute error\n");
6767 nlmsg_free(msg);
6768 goto err;
6769 }
developer72fb0bb2023-01-11 09:46:29 +08006770
developer121a8e72023-05-22 09:19:39 +08006771 /*send mtk nl80211 vendor msg*/
6772 cb_data.out_buf = macArray;
6773 cb_data.out_len = buf_size;
6774
6775 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, mtk_acl_list_dump_callback, &cb_data);
6776 if (ret) {
6777 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
6778 goto err;
6779 }
6780 /*deinit mtk nl80211 vendor msg*/
6781 mtk_nl80211_deint(&unl_ins);
6782 wifi_debug(DEBUG_NOTICE,"send cmd success, get macArray:%s", macArray);
developer72fb0bb2023-01-11 09:46:29 +08006783 return RETURN_OK;
developer121a8e72023-05-22 09:19:39 +08006784err:
6785 mtk_nl80211_deint(&unl_ins);
6786 wifi_debug(DEBUG_ERROR,"send cmd fails");
6787 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006788}
6789
6790INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
6791{
developer72fb0bb2023-01-11 09:46:29 +08006792
developer7e4a2a62023-04-06 19:56:03 +08006793 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08006794
6795 return RETURN_OK;
6796}
6797
6798
6799// Get the list of stations associated per AP
6800INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
6801{
developer7e4a2a62023-04-06 19:56:03 +08006802 char interface_name[IF_NAME_SIZE] = {0};
6803 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08006804
developer7e4a2a62023-04-06 19:56:03 +08006805 if(apIndex > 3) //Currently supporting apIndex upto 3
6806 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006807
developer7e4a2a62023-04-06 19:56:03 +08006808 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6809 return RETURN_ERR;
6810
6811 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
6812 _syscmd(cmd, macArray, buf_size);
6813 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006814}
6815
developer8dd72532023-05-17 19:58:35 +08006816int hex2num(char c)
6817{
6818 if (c >= '0' && c <= '9')
6819 return c - '0';
6820 if (c >= 'a' && c <= 'f')
6821 return c - 'a' + 10;
6822 if (c >= 'A' && c <= 'F')
6823 return c - 'A' + 10;
6824 return -1;
6825}
6826
6827/**
6828 * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
6829 * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
6830 * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
6831 * Returns: Characters used (> 0) on success, -1 on failure
6832 */
6833int hwaddr_aton2(const char *txt, unsigned char *addr)
6834{
6835 int i;
6836 const char *pos = txt;
6837
6838 for (i = 0; i < 6; i++) {
6839 int a, b;
6840
6841 while (*pos == ':' || *pos == '.' || *pos == '-')
6842 pos++;
6843
6844 a = hex2num(*pos++);
6845 if (a < 0)
6846 return -1;
6847 b = hex2num(*pos++);
6848 if (b < 0)
6849 return -1;
6850 *addr++ = (a << 4) | b;
6851 }
6852
6853 return pos - txt;
6854}
6855
developer72fb0bb2023-01-11 09:46:29 +08006856// adds the mac address to the filter list
6857//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6858INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6859{
developer7e4a2a62023-04-06 19:56:03 +08006860 char cmd[MAX_CMD_SIZE] = {0};
6861 char buf[MAX_BUF_SIZE] = {0};
6862 char inf_name[IF_NAME_SIZE] = {0};
developer8dd72532023-05-17 19:58:35 +08006863 int if_idx, ret = 0;
developer49b17232023-05-19 16:35:19 +08006864 struct nl_msg *msg = NULL;
6865 struct nlattr * msg_data = NULL;
6866 struct mtk_nl80211_param param;
developer8dd72532023-05-17 19:58:35 +08006867 unsigned char mac[ETH_ALEN] = {0x00, 0x0c, 0x43, 0x11, 0x22, 0x33};
6868 struct unl unl_ins;
developer7e4a2a62023-04-06 19:56:03 +08006869 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6870 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08006871 if (!DeviceMacAddress)
6872 return RETURN_ERR;
developer8dd72532023-05-17 19:58:35 +08006873 if (hwaddr_aton2(DeviceMacAddress, mac) < 0) {
6874 printf("error device mac address=%s\n", DeviceMacAddress);
6875 return RETURN_ERR;
6876 }
developer72fb0bb2023-01-11 09:46:29 +08006877
developer8dd72532023-05-17 19:58:35 +08006878 if_idx = if_nametoindex(inf_name);
developer49b17232023-05-19 16:35:19 +08006879 /*init mtk nl80211 vendor cmd*/
6880 param.sub_cmd = MTK_NL80211_VENDOR_SUBCMD_SET_ACL;
6881 param.if_type = NL80211_ATTR_IFINDEX;
6882 param.if_idx = if_idx;
6883 ret = mtk_nl80211_init(&unl_ins, &msg, &msg_data, &param);
6884 if (ret) {
6885 wifi_debug(DEBUG_ERROR, "init mtk 80211 netlink and msg fails\n");
developer8dd72532023-05-17 19:58:35 +08006886 return RETURN_ERR;
6887 }
developer49b17232023-05-19 16:35:19 +08006888 /*add mtk vendor cmd data*/
6889 if (nla_put(msg, MTK_NL80211_VENDOR_ATTR_ACL_ADD_MAC, ETH_ALEN, mac)) {
6890 printf("Nla put attribute error\n");
developer8dd72532023-05-17 19:58:35 +08006891 nlmsg_free(msg);
6892 goto err;
6893 }
6894
developer49b17232023-05-19 16:35:19 +08006895 /*send mtk nl80211 vendor msg*/
6896 ret = mtk_nl80211_send(&unl_ins, msg, msg_data, NULL, NULL);
6897 if (ret) {
6898 wifi_debug(DEBUG_ERROR, "send mtk nl80211 vender msg fails\n");
developer8dd72532023-05-17 19:58:35 +08006899 goto err;
6900 }
developer49b17232023-05-19 16:35:19 +08006901 /*deinit mtk nl80211 vendor msg*/
6902 mtk_nl80211_deint(&unl_ins);
6903 wifi_debug(DEBUG_NOTICE, "set cmd success.\n");
developer8dd72532023-05-17 19:58:35 +08006904 return RETURN_OK;
6905err:
developer49b17232023-05-19 16:35:19 +08006906 mtk_nl80211_deint(&unl_ins);
6907 wifi_debug(DEBUG_ERROR, "set cmd fails.\n");
developer8dd72532023-05-17 19:58:35 +08006908 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006909}
6910
6911// deletes the mac address from the filter list
6912//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
6913INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
6914{
developer7e4a2a62023-04-06 19:56:03 +08006915 char cmd[MAX_CMD_SIZE] = {0};
6916 char buf[MAX_BUF_SIZE] = {0};
6917 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006918
developer7e4a2a62023-04-06 19:56:03 +08006919 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6920 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006921
developer7e4a2a62023-04-06 19:56:03 +08006922 if (!DeviceMacAddress)
6923 return RETURN_ERR;
6924
6925 /* mwctl acl del sta */
6926 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
6927 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006928
6929 return RETURN_OK;
6930}
6931
6932// outputs the number of devices in the filter list
6933INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6934{
developer7e4a2a62023-04-06 19:56:03 +08006935 char cmd[MAX_CMD_SIZE] = {0};
6936 char buf[MAX_BUF_SIZE] = {0};
6937 char inf_name[IF_NAME_SIZE] = {0};
6938 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006939
developer72fb0bb2023-01-11 09:46:29 +08006940 if(output_uint == NULL)
6941 return RETURN_ERR;
6942
developer7e4a2a62023-04-06 19:56:03 +08006943 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6944 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006945
developer7e4a2a62023-04-06 19:56:03 +08006946 /* mwctl acl get sta num */
6947 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6948 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006949
developer7e4a2a62023-04-06 19:56:03 +08006950 if (atoi(buf) > 1)
6951 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6952 else {
6953 *output_uint = 0;
6954 printf("%s: acl get wrong return content!!!\n", __func__);
6955 }
6956
6957 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006958}
6959
6960INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6961{
6962 char cmd[128]={'\0'};
6963 char buf[128]={'\0'};
6964
6965 if(strcmp(action,"DENY")==0)
6966 {
6967 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6968 system(buf);
6969 return RETURN_OK;
6970 }
6971
6972 if(strcmp(action,"ALLOW")==0)
6973 {
6974 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6975 system(buf);
6976 return RETURN_OK;
6977 }
6978
6979 return RETURN_ERR;
6980
6981}
6982
6983// enable kick for devices on acl black list
6984INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6985{
developer47cc27a2023-05-17 23:09:58 +08006986 char aclArray[MAX_BUF_SIZE] = {0}, *acl = NULL;
6987 char assocArray[MAX_BUF_SIZE] = {0}, *asso = NULL;
developer72fb0bb2023-01-11 09:46:29 +08006988
6989 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
6990 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
6991
developer7e4a2a62023-04-06 19:56:03 +08006992 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08006993 if (strlen(assocArray) < 17)
6994 return RETURN_OK;
6995
developer7e4a2a62023-04-06 19:56:03 +08006996 if (enable == TRUE) {
6997 /* kick off the MAC which is in ACL array (deny list) */
6998 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006999 while (acl != NULL) {
7000 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
7001 wifi_kickApAssociatedDevice(apIndex, acl);
7002
developer7e4a2a62023-04-06 19:56:03 +08007003 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08007004 }
7005 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08007006 } else
developer72fb0bb2023-01-11 09:46:29 +08007007 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08007008
developer72fb0bb2023-01-11 09:46:29 +08007009 return RETURN_OK;
7010}
7011
7012INT wifi_setPreferPrivateConnection(BOOL enable)
7013{
7014 return RETURN_OK;
7015}
7016
7017// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
7018INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
7019{
developer7e4a2a62023-04-06 19:56:03 +08007020 char inf_name[IF_NAME_SIZE] = {0};
7021 char cmd[MAX_CMD_SIZE] = {0};
7022 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007023
developer7e4a2a62023-04-06 19:56:03 +08007024 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
7025 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007026
developer7e4a2a62023-04-06 19:56:03 +08007027 /*mwctl set acl policy*/
7028 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
7029 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007030
developer7e4a2a62023-04-06 19:56:03 +08007031 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007032}
7033
7034// enables internal gateway VLAN mode. In this mode a Vlan tag is added to upstream (received) data packets before exiting the Wifi driver. VLAN tags in downstream data are stripped from data packets before transmission. Default is FALSE.
7035INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
7036{
7037 return RETURN_ERR;
7038}
7039
7040// gets the vlan ID for this ap from an internal enviornment variable
7041INT wifi_getApVlanID(INT apIndex, INT *output_int)
7042{
7043 if(apIndex==0)
7044 {
7045 *output_int=100;
7046 return RETURN_OK;
7047 }
7048
7049 return RETURN_ERR;
7050}
7051
7052// sets the vlan ID for this ap to an internal enviornment variable
7053INT wifi_setApVlanID(INT apIndex, INT vlanId)
7054{
7055 //save the vlanID to config and wait for wifi reset to apply (wifi up module would read this parameters and tag the AP with vlan id)
7056 return RETURN_ERR;
7057}
7058
7059// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
7060INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7061{
7062 snprintf(bridgeName, 32, "brlan0");
7063 snprintf(IP, 32, "10.0.0.1");
7064 snprintf(subnet, 32, "255.255.255.0");
7065
7066 return RETURN_OK;
7067}
7068
7069//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
7070INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
7071{
7072 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
7073 return RETURN_ERR;
7074}
7075
7076// reset the vlan configuration for this ap
7077INT wifi_resetApVlanCfg(INT apIndex)
7078{
7079 char original_config_file[64] = {0};
7080 char current_config_file[64] = {0};
7081 char buf[64] = {0};
7082 char cmd[64] = {0};
7083 char vlan_file[64] = {0};
7084 char vlan_tagged_interface[16] = {0};
7085 char vlan_bridge[16] = {0};
7086 char vlan_naming[16] = {0};
7087 struct params list[4] = {0};
7088 wifi_band band;
developera1255e42023-05-13 17:45:02 +08007089 char interface_name[16] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007090
7091 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007092 band = wifi_index_to_band(apIndex);
7093 if (band == band_2_4)
developera1255e42023-05-13 17:45:02 +08007094 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-2G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007095 else if (band == band_5)
developera1255e42023-05-13 17:45:02 +08007096 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-5G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007097 else if (band == band_6)
developera1255e42023-05-13 17:45:02 +08007098 snprintf(original_config_file, sizeof(original_config_file), "/etc/hostapd-6G.conf");
developer72fb0bb2023-01-11 09:46:29 +08007099
7100 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
7101
7102 if (strlen(vlan_file) == 0)
7103 strcpy(vlan_file, VLAN_FILE);
7104
7105 // The file should exist or this vap would not work.
7106 if (access(vlan_file, F_OK) != 0) {
developera1255e42023-05-13 17:45:02 +08007107 snprintf(cmd, sizeof(cmd), "touch %s", vlan_file);
developer72fb0bb2023-01-11 09:46:29 +08007108 _syscmd(cmd, buf, sizeof(buf));
7109 }
7110 list[0].name = "vlan_file";
7111 list[0].value = vlan_file;
7112
7113 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
7114 list[1].name = "vlan_tagged_interface";
7115 list[1].value = vlan_tagged_interface;
7116
7117 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
7118 list[2].name = "vlan_bridge";
7119 list[2].value = vlan_bridge;
7120
7121 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
7122 list[3].name = "vlan_naming";
7123 list[3].value = vlan_naming;
7124
developera1255e42023-05-13 17:45:02 +08007125 snprintf(current_config_file, sizeof(current_config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007126 wifi_hostapdWrite(current_config_file, list, 4);
7127 //Reapply vlan settings
7128 // wifi_pushBridgeInfo(apIndex);
7129
7130 // restart this ap
7131 wifi_setApEnable(apIndex, FALSE);
7132 wifi_setApEnable(apIndex, TRUE);
developera1255e42023-05-13 17:45:02 +08007133 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7134 return RETURN_ERR;
7135 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_tag 0\n", interface_name);
7136 _syscmd(cmd, buf, sizeof(buf));
7137 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_priority 0\n", interface_name);
7138 _syscmd(cmd, buf, sizeof(buf));
7139 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_id 0\n", interface_name);
7140 _syscmd(cmd, buf, sizeof(buf));
7141 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_en 0\n", interface_name);
7142 _syscmd(cmd, buf, sizeof(buf));
7143 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 0:4\n", interface_name);
7144 _syscmd(cmd, buf, sizeof(buf));
7145 snprintf(cmd, sizeof(cmd), "mwctl dev %s set vlan_policy 1:0\n", interface_name);
7146 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08007147 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7148
7149 return RETURN_OK;
7150}
7151
7152// creates configuration variables needed for WPA/WPS. These variables are implementation dependent and in some implementations these variables are used by hostapd when it is started. Specific variables that are needed are dependent on the hostapd implementation. These variables are set by WPA/WPS security functions in this wifi HAL. If not needed for a particular implementation this function may simply return no error.
7153INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
7154{
7155 return RETURN_ERR;
7156}
7157
7158// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
7159INT wifi_startHostApd()
7160{
7161 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7162 system("systemctl start hostapd.service");
7163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7164 return RETURN_OK;
7165 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
7166}
7167
7168// stops hostapd
developer69b61b02023-03-07 17:17:44 +08007169INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08007170{
7171 char cmd[128] = {0};
7172 char buf[128] = {0};
7173
7174 sprintf(cmd,"systemctl stop hostapd");
7175 _syscmd(cmd, buf, sizeof(buf));
7176
7177 return RETURN_OK;
7178}
7179
7180// restart hostapd dummy function
7181INT wifi_restartHostApd()
7182{
7183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7184 system("systemctl restart hostapd-global");
7185 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7186
7187 return RETURN_OK;
7188}
7189
7190static int align_hostapd_config(int index)
7191{
7192 ULONG lval;
7193 wifi_getRadioChannel(index%2, &lval);
7194 wifi_setRadioChannel(index%2, lval);
7195 return RETURN_OK;
7196}
7197
7198// sets the AP enable status variable for the specified ap.
7199INT wifi_setApEnable(INT apIndex, BOOL enable)
7200{
developer7e4a2a62023-04-06 19:56:03 +08007201 char interface_name[16] = {0};
7202 char config_file[MAX_BUF_SIZE] = {0};
7203 char cmd[MAX_CMD_SIZE] = {0};
7204 char buf[MAX_BUF_SIZE] = {0};
developer47cc27a2023-05-17 23:09:58 +08007205 BOOL status = FALSE;
developer7e4a2a62023-04-06 19:56:03 +08007206 int max_radio_num = 0;
7207 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08007208
developer7e4a2a62023-04-06 19:56:03 +08007209 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08007210
developer7e4a2a62023-04-06 19:56:03 +08007211 wifi_getMaxRadioNumber(&max_radio_num);
7212 if (enable == status)
7213 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007214
developer7e4a2a62023-04-06 19:56:03 +08007215 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7216 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007217
developer7e4a2a62023-04-06 19:56:03 +08007218 if (enable == TRUE) {
7219 int radioIndex = apIndex % max_radio_num;
7220 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08007221
developer7e4a2a62023-04-06 19:56:03 +08007222 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
7223 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
7224 _syscmd(cmd, buf, sizeof(buf));
7225 } else {
7226 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
7227 _syscmd(cmd, buf, sizeof(buf));
7228 }
7229 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
7230 interface_name, interface_name, enable, VAP_STATUS_FILE);
7231 _syscmd(cmd, buf, sizeof(buf));
7232 //Wait for wifi up/down to apply
7233 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007234}
7235
7236// Outputs the setting of the internal variable that is set by wifi_setApEnable().
7237INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
7238{
developer7e4a2a62023-04-06 19:56:03 +08007239 char interface_name[IF_NAME_SIZE] = {0};
7240 char cmd[MAX_CMD_SIZE] = {0};
7241 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007242
developer7e4a2a62023-04-06 19:56:03 +08007243 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
7244 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007245
developer7e4a2a62023-04-06 19:56:03 +08007246 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08007247
developer7e4a2a62023-04-06 19:56:03 +08007248 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
7249 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
7250 *output_bool = FALSE;
7251 return RETURN_OK;
7252 }
7253 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
7254 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
7255 }
developer72fb0bb2023-01-11 09:46:29 +08007256
developer7e4a2a62023-04-06 19:56:03 +08007257 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007258}
7259
developer69b61b02023-03-07 17:17:44 +08007260// Outputs the AP "Enabled" "Disabled" status from driver
7261INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08007262{
developer7e4a2a62023-04-06 19:56:03 +08007263 char cmd[128] = {0};
7264 char buf[128] = {0};
7265 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08007266
developer7e4a2a62023-04-06 19:56:03 +08007267 if (!output_string) {
7268 printf("%s: null pointer!", __func__);
7269 return RETURN_ERR;
7270 }
developer72fb0bb2023-01-11 09:46:29 +08007271
developer7e4a2a62023-04-06 19:56:03 +08007272 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08007273
developer7e4a2a62023-04-06 19:56:03 +08007274 if(output_bool == 1)
7275 snprintf(output_string, 32, "Up");
7276 else
7277 snprintf(output_string, 32, "Disable");
7278
7279 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007280}
7281
7282//Indicates whether or not beacons include the SSID name.
7283// outputs a 1 if SSID on the AP is enabled, else outputs 0
7284INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
7285{
7286 //get the running status
7287 char config_file[MAX_BUF_SIZE] = {0};
7288 char buf[16] = {0};
7289
7290 if (!output)
7291 return RETURN_ERR;
7292
7293 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7294 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
7295 // default is enable
7296 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
7297 *output = TRUE;
7298
7299 return RETURN_OK;
7300}
7301
7302// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
7303INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
7304{
7305 //store the config, apply instantly
7306 char config_file[MAX_BUF_SIZE] = {0};
7307 struct params list;
7308
7309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7310 list.name = "ignore_broadcast_ssid";
7311 list.value = enable?"0":"1";
7312
7313 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7314 wifi_hostapdWrite(config_file, &list, 1);
7315 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7316 //TODO: call hostapd_cli for dynamic_config_control
7317 wifi_reloadAp(apIndex);
7318 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7319
7320 return RETURN_OK;
7321}
7322
7323//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
7324INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
7325{
developer47cc27a2023-05-17 23:09:58 +08007326 /* get the running status */
7327 if(!output_uint)
7328 return RETURN_ERR;
7329
7330 *output_uint = 15;
7331 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08007332}
7333
developer47cc27a2023-05-17 23:09:58 +08007334/*Do not support AP retry limit fix*/
developer72fb0bb2023-01-11 09:46:29 +08007335INT wifi_setApRetryLimit(INT apIndex, UINT number)
7336{
developer47cc27a2023-05-17 23:09:58 +08007337 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08007338}
7339
7340//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
7341INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
7342{
7343 if(!output)
7344 return RETURN_ERR;
7345 *output=TRUE;
7346 return RETURN_OK;
7347}
7348
7349//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
7350INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
7351{
7352 //get the running status from driver
7353 char cmd[128] = {0};
7354 char buf[128] = {0};
7355 int max_radio_num = 0, radioIndex = 0;
7356 int phyId = 0;
7357
7358 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7359
7360 wifi_getMaxRadioNumber(&max_radio_num);
7361 radioIndex = apIndex % max_radio_num;
7362 phyId = radio_index_to_phy(radioIndex);
7363 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
7364 _syscmd(cmd,buf, sizeof(buf));
7365
7366 if (strlen(buf) > 0)
7367 *output = true;
7368
7369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7370
7371 return RETURN_OK;
7372}
7373
7374//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
7375INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
7376{
7377 //get the running status from driver
7378 if(!output)
7379 return RETURN_ERR;
7380
7381 char config_file[MAX_BUF_SIZE] = {0};
7382 char buf[16] = {0};
7383
7384 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7385 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
7386 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
7387 *output = TRUE;
7388 else
7389 *output = FALSE;
7390
7391 return RETURN_OK;
7392}
7393
7394// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
7395INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
7396{
7397 //Save config and apply instantly.
7398 char config_file[MAX_BUF_SIZE] = {0};
7399 struct params list;
7400
7401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7402 list.name = "wmm_enabled";
7403 list.value = enable?"1":"0";
7404
7405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7406 wifi_hostapdWrite(config_file, &list, 1);
7407 wifi_hostapdProcessUpdate(apIndex, &list, 1);
7408 wifi_reloadAp(apIndex);
7409 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7410
7411 return RETURN_OK;
7412}
7413
7414//Whether U-APSD support is currently enabled. When enabled, this is indicated in beacon frames. Note: U-APSD can only be enabled if WMM is also enabled.
7415INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
7416{
7417 //get the running status from driver
7418 if(!output)
7419 return RETURN_ERR;
7420
7421 char config_file[128] = {0};
7422 char buf[16] = {0};
7423
7424 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7425 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
7426 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
7427 *output = TRUE;
7428 else
7429 *output = FALSE;
7430
7431 return RETURN_OK;
7432}
7433
7434// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
7435INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
7436{
7437 //save config and apply instantly.
7438 char config_file[MAX_BUF_SIZE] = {0};
7439 struct params list;
7440
7441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7442 list.name = "uapsd_advertisement_enabled";
7443 list.value = enable?"1":"0";
7444
7445 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7446 wifi_hostapdWrite(config_file, &list, 1);
7447 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developere82c0ca2023-05-10 16:25:35 +08007448 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08007449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7450
7451 return RETURN_OK;
7452}
7453
7454// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
7455INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
7456{
7457 char interface_name[16] = {0};
7458 // assume class 0->BE, 1->BK, 2->VI, 3->VO
7459 char cmd[128] = {0};
7460 char buf[128] = {0};
7461 char ack_filepath[128] = {0};
7462 uint16_t bitmap = 0;
7463 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
7464 FILE *f = NULL;
7465
7466 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7467
7468 // Get current setting
7469 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
7470 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
7471 _syscmd(cmd, buf, sizeof(buf));
7472 if (strlen(buf) > 0)
7473 bitmap = strtoul(buf, NULL, 10);
7474
7475 bitmap = strtoul(buf, NULL, 10);
7476
7477 if (ackPolicy == TRUE) { // True, unset this class
7478 bitmap &= ~class_map[class];
7479 } else { // False, set this class
7480 bitmap |= class_map[class];
7481 }
7482
7483 f = fopen(ack_filepath, "w");
7484 if (f == NULL) {
7485 fprintf(stderr, "%s: fopen failed\n", __func__);
7486 return RETURN_ERR;
7487 }
7488 fprintf(f, "%hu", bitmap);
7489 fclose(f);
7490
7491 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7492 return RETURN_ERR;
7493 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
7494 _syscmd(cmd, buf, sizeof(buf));
7495
7496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
7497 return RETURN_OK;
7498}
7499
7500//The maximum number of devices that can simultaneously be connected to the access point. A value of 0 means that there is no specific limit.
7501INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
7502{
7503 //get the running status from driver
7504 if(!output_uint)
7505 return RETURN_ERR;
7506
7507 char output[16]={'\0'};
7508 char config_file[MAX_BUF_SIZE] = {0};
7509
7510 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7511 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
7512 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
7513 else {
7514 int device_num = atoi(output);
7515 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
7516 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
7517 return RETURN_ERR;
7518 }
7519 else {
7520 *output_uint = device_num;
7521 }
7522 }
7523
7524 return RETURN_OK;
7525}
7526
7527INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
7528{
7529 //store to wifi config, apply instantly
7530 char str[MAX_BUF_SIZE]={'\0'};
7531 char cmd[MAX_CMD_SIZE]={'\0'};
7532 struct params params;
7533 char config_file[MAX_BUF_SIZE] = {0};
7534
7535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7536 if (number > MAX_ASSOCIATED_STA_NUM) {
7537 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
7538 return RETURN_ERR;
7539 }
7540 sprintf(str, "%d", number);
7541 params.name = "max_num_sta";
7542 params.value = str;
7543
7544 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
7545 int ret = wifi_hostapdWrite(config_file, &params, 1);
7546 if (ret) {
7547 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
7548 ,__func__, ret);
7549 }
7550
7551 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
7552 if (ret) {
7553 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
7554 ,__func__, ret);
7555 }
7556 wifi_reloadAp(apIndex);
7557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7558
7559 return RETURN_OK;
7560}
7561
7562//The HighWatermarkThreshold value that is lesser than or equal to MaxAssociatedDevices. Setting this parameter does not actually limit the number of clients that can associate with this access point as that is controlled by MaxAssociatedDevices. MaxAssociatedDevices or 50. The default value of this parameter should be equal to MaxAssociatedDevices. In case MaxAssociatedDevices is 0 (zero), the default value of this parameter should be 50. A value of 0 means that there is no specific limit and Watermark calculation algorithm should be turned off.
7563INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
7564{
7565 //get the current threshold
7566 if(!output_uint)
7567 return RETURN_ERR;
7568 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
7569 if (*output_uint == 0)
7570 *output_uint = 50;
7571 return RETURN_OK;
7572}
7573
7574INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
7575{
7576 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
7577 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
7578 return RETURN_OK;
7579 return RETURN_ERR;
7580}
7581
7582//Number of times the current total number of associated device has reached the HighWatermarkThreshold value. This calculation can be based on the parameter AssociatedDeviceNumberOfEntries as well. Implementation specifics about this parameter are left to the product group and the device vendors. It can be updated whenever there is a new client association request to the access point.
7583INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
7584{
7585 if(!output_uint)
7586 return RETURN_ERR;
7587 *output_uint = 3;
7588 return RETURN_OK;
7589}
7590
7591//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
7592INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
7593{
7594 if(!output_uint)
7595 return RETURN_ERR;
7596 *output_uint = 3;
7597 return RETURN_OK;
7598}
7599
7600//Date and Time at which the maximum number of associated devices ever associated with the access point concurrenlty since the last reset of the device or WiFi module (or in short when was X_COMCAST-COM_AssociatedDevicesHighWatermark updated). This dateTime value is in UTC.
7601INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
7602{
7603 if(!output_in_seconds)
7604 return RETURN_ERR;
7605 *output_in_seconds = 0;
7606 return RETURN_OK;
7607}
7608
7609//Comma-separated list of strings. Indicates which security modes this AccessPoint instance is capable of supporting. Each list item is an enumeration of: None,WEP-64,WEP-128,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise
7610INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
7611{
7612 if(!output || apIndex>=MAX_APS)
7613 return RETURN_ERR;
7614 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
7615 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
7616 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007617}
developer72fb0bb2023-01-11 09:46:29 +08007618
7619//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
7620INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
7621{
7622 char config_file[128] = {0};
7623 char wpa[16] = {0};
7624 char key_mgmt[64] = {0};
7625 char buf[16] = {0};
7626 if (!output)
7627 return RETURN_ERR;
7628
7629 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7630 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
7631
7632 strcpy(output, "None");//Copying "None" to output string for default case
7633 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
7634 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
7635 if (!strcmp(wpa, "1"))
7636 snprintf(output, 32, "WPA-Personal");
7637 else if (!strcmp(wpa, "2"))
7638 snprintf(output, 32, "WPA2-Personal");
7639 else if (!strcmp(wpa, "3"))
7640 snprintf(output, 32, "WPA-WPA2-Personal");
7641
developere5750452023-05-15 16:46:42 +08007642 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
7643 snprintf(output, 32, "WPA3-Enterprise");
developer72fb0bb2023-01-11 09:46:29 +08007644 } else if (strstr(key_mgmt, "WPA-EAP")) {
7645 if (!strcmp(wpa, "1"))
7646 snprintf(output, 32, "WPA-Enterprise");
7647 else if (!strcmp(wpa, "2"))
7648 snprintf(output, 32, "WPA2-Enterprise");
7649 else if (!strcmp(wpa, "3"))
7650 snprintf(output, 32, "WPA-WPA2-Enterprise");
7651 } else if (strstr(key_mgmt, "SAE")) {
7652 if (strstr(key_mgmt, "WPA-PSK") == NULL)
7653 snprintf(output, 32, "WPA3-Personal");
7654 else
7655 snprintf(output, 32, "WPA3-Personal-Transition");
developer72fb0bb2023-01-11 09:46:29 +08007656 }
7657
7658 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
7659 return RETURN_OK;
7660#if 0
7661 //TODO: need to revisit below implementation
7662 char securityType[32], authMode[32];
7663 int enterpriseMode=0;
7664
7665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7666 if(!output)
7667 return RETURN_ERR;
7668
7669 wifi_getApBeaconType(apIndex, securityType);
7670 strcpy(output,"None");//By default, copying "None" to output string
7671 if (strncmp(securityType,"None", strlen("None")) == 0)
7672 return RETURN_OK;
7673
7674 wifi_getApBasicAuthenticationMode(apIndex, authMode);
7675 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
7676
7677 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
7678 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
7679 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
7680 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
7681 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
7682 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
7683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7684
7685 return RETURN_OK;
7686#endif
7687}
developer69b61b02023-03-07 17:17:44 +08007688
developer72fb0bb2023-01-11 09:46:29 +08007689INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
7690{
7691 char securityType[32];
7692 char authMode[32];
7693
7694 //store settings and wait for wifi up to apply
7695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7696 if(!encMode)
7697 return RETURN_ERR;
7698
7699 if (strcmp(encMode, "None")==0)
7700 {
7701 strcpy(securityType,"None");
7702 strcpy(authMode,"None");
7703 }
7704 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
7705 {
7706 strcpy(securityType,"WPAand11i");
7707 strcpy(authMode,"PSKAuthentication");
7708 }
7709 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
7710 {
7711 strcpy(securityType,"WPAand11i");
7712 strcpy(authMode,"EAPAuthentication");
7713 }
7714 else if (strcmp(encMode, "WPA-Personal")==0)
7715 {
7716 strcpy(securityType,"WPA");
7717 strcpy(authMode,"PSKAuthentication");
7718 }
7719 else if (strcmp(encMode, "WPA-Enterprise")==0)
7720 {
7721 strcpy(securityType,"WPA");
7722 strcpy(authMode,"EAPAuthentication");
7723 }
7724 else if (strcmp(encMode, "WPA2-Personal")==0)
7725 {
7726 strcpy(securityType,"11i");
7727 strcpy(authMode,"PSKAuthentication");
7728 }
7729 else if (strcmp(encMode, "WPA2-Enterprise")==0)
7730 {
7731 strcpy(securityType,"11i");
7732 strcpy(authMode,"EAPAuthentication");
7733 }
7734 else if (strcmp(encMode, "WPA3-Personal") == 0)
7735 {
7736 strcpy(securityType,"11i");
7737 strcpy(authMode,"SAEAuthentication");
7738 }
7739 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
7740 {
7741 strcpy(securityType, "11i");
7742 strcpy(authMode, "PSK-SAEAuthentication");
7743 }
7744 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
7745 {
7746 strcpy(securityType,"11i");
7747 strcpy(authMode,"EAP_192-bit_Authentication");
7748 }
developer3086e2f2023-01-17 09:40:01 +08007749 else if (strcmp(encMode, "OWE") == 0)
7750 {
7751 strcpy(securityType,"11i");
7752 strcpy(authMode,"Enhanced_Open");
7753 }
developer72fb0bb2023-01-11 09:46:29 +08007754 else
7755 {
7756 strcpy(securityType,"None");
7757 strcpy(authMode,"None");
7758 }
7759 wifi_setApBeaconType(apIndex, securityType);
7760 wifi_setApBasicAuthenticationMode(apIndex, authMode);
7761 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7762
7763 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007764}
developer72fb0bb2023-01-11 09:46:29 +08007765
7766
7767//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
7768// output_string must be pre-allocated as 64 character string by caller
7769// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7770INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
7771{
7772 char buf[16] = {0};
7773 char config_file[MAX_BUF_SIZE] = {0};
7774
7775 if(output_string==NULL)
7776 return RETURN_ERR;
7777
7778 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7779 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7780
7781 if(strcmp(buf,"0")==0)
7782 {
7783 printf("wpa_mode is %s ......... \n",buf);
7784 return RETURN_ERR;
7785 }
7786
7787 wifi_dbg_printf("\nFunc=%s\n",__func__);
7788 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
developere5750452023-05-15 16:46:42 +08007789 wifi_hostapdRead(config_file,"wpa_psk",output_string,65);
developer72fb0bb2023-01-11 09:46:29 +08007790 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7791
7792 return RETURN_OK;
7793}
7794
7795// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
7796// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
7797INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
7798{
7799 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7800 struct params params={'\0'};
7801 int ret;
7802 char config_file[MAX_BUF_SIZE] = {0};
7803
7804 if(NULL == preSharedKey)
7805 return RETURN_ERR;
7806
developere5750452023-05-15 16:46:42 +08007807 params.name = "wpa_psk";
developer72fb0bb2023-01-11 09:46:29 +08007808
developere5750452023-05-15 16:46:42 +08007809 if(strlen(preSharedKey) != 64)
developer72fb0bb2023-01-11 09:46:29 +08007810 {
developere5750452023-05-15 16:46:42 +08007811 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 64 chars\n");
developer72fb0bb2023-01-11 09:46:29 +08007812 return RETURN_ERR;
7813 }
7814 params.value = preSharedKey;
7815 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7816 ret = wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +08007817 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007818 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007819 wifi_reloadAp(apIndex);
7820 }
developer72fb0bb2023-01-11 09:46:29 +08007821 return ret;
7822 //TODO: call hostapd_cli for dynamic_config_control
7823}
7824
7825//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
7826// outputs the passphrase, maximum 63 characters
7827INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
7828{
7829 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
7830
7831 wifi_dbg_printf("\nFunc=%s\n",__func__);
7832 if (NULL == output_string)
7833 return RETURN_ERR;
7834
7835 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7836 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
7837 if(strcmp(buf,"0")==0)
7838 {
7839 printf("wpa_mode is %s ......... \n",buf);
7840 return RETURN_ERR;
7841 }
7842
7843 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
7844 wifi_dbg_printf("\noutput_string=%s\n",output_string);
7845
7846 return RETURN_OK;
7847}
7848
7849// sets the passphrase enviornment variable, max 63 characters
7850INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
7851{
7852 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
7853 struct params params={'\0'};
7854 char config_file[MAX_BUF_SIZE] = {0};
7855 int ret;
7856
7857 if(NULL == passPhrase)
7858 return RETURN_ERR;
7859
7860 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
7861 {
7862 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
7863 return RETURN_ERR;
7864 }
7865 params.name = "wpa_passphrase";
7866 params.value = passPhrase;
7867 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
7868 ret=wifi_hostapdWrite(config_file,&params,1);
developere5750452023-05-15 16:46:42 +08007869 if(!ret) {
developer72fb0bb2023-01-11 09:46:29 +08007870 wifi_hostapdProcessUpdate(apIndex, &params, 1);
developere5750452023-05-15 16:46:42 +08007871 wifi_reloadAp(apIndex);
7872 }
developer72fb0bb2023-01-11 09:46:29 +08007873
7874 return ret;
7875}
7876
7877//When set to true, this AccessPoint instance's WiFi security settings are reset to their factory default values. The affected settings include ModeEnabled, WEPKey, PreSharedKey and KeyPassphrase.
7878INT wifi_setApSecurityReset(INT apIndex)
7879{
7880 char original_config_file[64] = {0};
7881 char current_config_file[64] = {0};
7882 char buf[64] = {0};
7883 char cmd[64] = {0};
7884 char wpa[4] = {0};
7885 char wpa_psk[64] = {0};
7886 char wpa_passphrase[64] = {0};
7887 char wpa_psk_file[128] = {0};
7888 char wpa_key_mgmt[64] = {0};
7889 char wpa_pairwise[32] = {0};
7890 wifi_band band;
7891 struct params list[6];
7892
7893 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7894
7895 band = wifi_index_to_band(apIndex);
7896 if (band == band_2_4)
7897 sprintf(original_config_file, "/etc/hostapd-2G.conf");
7898 else if (band == band_5)
7899 sprintf(original_config_file, "/etc/hostapd-5G.conf");
7900 else if (band == band_6)
7901 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7902 else
7903 return RETURN_ERR;
7904
7905 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7906 list[0].name = "wpa";
7907 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007908
developer72fb0bb2023-01-11 09:46:29 +08007909 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7910 list[1].name = "wpa_psk";
7911 list[1].value = wpa_psk;
7912
7913 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7914 list[2].name = "wpa_passphrase";
7915 list[2].value = wpa_passphrase;
7916
7917 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7918
7919 if (strlen(wpa_psk_file) == 0)
7920 strcpy(wpa_psk_file, PSK_FILE);
7921
7922 if (access(wpa_psk_file, F_OK) != 0) {
7923 sprintf(cmd, "touch %s", wpa_psk_file);
7924 _syscmd(cmd, buf, sizeof(buf));
7925 }
7926 list[3].name = "wpa_psk_file";
7927 list[3].value = wpa_psk_file;
7928
7929 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7930 list[4].name = "wpa_key_mgmt";
7931 list[4].value = wpa_key_mgmt;
7932
7933 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7934 list[5].name = "wpa_pairwise";
7935 list[5].value = wpa_pairwise;
7936
7937 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7938 wifi_hostapdWrite(current_config_file, list, 6);
7939
7940 wifi_setApEnable(apIndex, FALSE);
7941 wifi_setApEnable(apIndex, TRUE);
7942
7943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7944 return RETURN_OK;
7945}
7946
7947//The IP Address and port number of the RADIUS server used for WLAN security. RadiusServerIPAddr is only applicable when ModeEnabled is an Enterprise type (i.e. WPA-Enterprise, WPA2-Enterprise or WPA-WPA2-Enterprise).
7948INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7949{
7950 char config_file[64] = {0};
7951 char buf[64] = {0};
7952 char cmd[256] = {0};
7953
7954 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7955
7956 if(!IP_output || !Port_output || !RadiusSecret_output)
7957 return RETURN_ERR;
7958
7959 // Read the first matched config
7960 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7961 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7962 _syscmd(cmd, buf, sizeof(buf));
7963 strncpy(IP_output, buf, 64);
7964
7965 memset(buf, 0, sizeof(buf));
7966 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7967 _syscmd(cmd, buf, sizeof(buf));
7968 *Port_output = atoi(buf);
7969
7970 memset(buf, 0, sizeof(buf));
7971 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7972 _syscmd(cmd, buf, sizeof(buf));
7973 strncpy(RadiusSecret_output, buf, 64);
7974
7975 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7976 return RETURN_OK;
7977}
7978
7979INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7980{
7981 char config_file[64] = {0};
7982 char port_str[8] = {0};
7983 char cmd[256] = {0};
7984 char buf[128] = {0};
7985
7986 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7987
developere5750452023-05-15 16:46:42 +08007988 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
7989 return RETURN_ERR;
7990
7991 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
7992 return RETURN_ERR;
7993
developer72fb0bb2023-01-11 09:46:29 +08007994 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7995
7996 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7997 _syscmd(cmd, buf, sizeof(buf));
7998 memset(cmd, 0, sizeof(cmd));
7999
8000 snprintf(port_str, sizeof(port_str), "%d", port);
8001 if (strlen(buf) == 0)
8002 // Append
8003 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
8004 "auth_server_addr=%s\\n"
8005 "auth_server_port=%s\\n"
8006 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
8007 else {
8008 // Delete the three lines setting after the "# radius 1" comment
8009 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
8010 _syscmd(cmd, buf, sizeof(buf));
8011 memset(cmd, 0, sizeof(cmd));
8012 // Use "# radius 1" comment to find the location to insert the radius setting
8013 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
8014 "# radius 1\\n"
8015 "auth_server_addr=%s\\n"
8016 "auth_server_port=%s\\n"
8017 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
8018 }
8019 if(_syscmd(cmd, buf, sizeof(buf))) {
8020 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
8021 return RETURN_ERR;
8022 }
8023
8024 wifi_reloadAp(apIndex);
8025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8026 return RETURN_OK;
8027}
8028
8029INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
8030{
8031 char config_file[64] = {0};
8032 char buf[64] = {0};
8033 char cmd[256] = {0};
8034
8035 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8036
8037 if(!IP_output || !Port_output || !RadiusSecret_output)
8038 return RETURN_ERR;
8039
8040 // Read the second matched config
8041 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8042 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8043 _syscmd(cmd, buf, sizeof(buf));
8044 strncpy(IP_output, buf, 64);
8045
8046 memset(buf, 0, sizeof(buf));
8047 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8048 _syscmd(cmd, buf, sizeof(buf));
8049 *Port_output = atoi(buf);
8050
8051 memset(buf, 0, sizeof(buf));
8052 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
8053 _syscmd(cmd, buf, sizeof(buf));
8054 strncpy(RadiusSecret_output, buf, 64);
8055
8056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8057 return RETURN_OK;
8058}
8059
8060INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
8061{
8062 char config_file[64] = {0};
8063 char port_str[8] = {0};
8064 char cmd[256] = {0};
8065 char buf[128] = {0};
8066
8067 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8068
developere5750452023-05-15 16:46:42 +08008069 if (wifi_getApSecurityModeEnabled(apIndex, buf) != RETURN_OK)
8070 return RETURN_ERR;
8071
8072 if (strstr(buf, "Enterprise") == NULL) // non Enterprise mode sould not set radius server info
8073 return RETURN_ERR;
8074
developer72fb0bb2023-01-11 09:46:29 +08008075 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8076
8077 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
8078 _syscmd(cmd, buf, sizeof(buf));
8079 memset(cmd, 0, sizeof(cmd));
8080
8081 snprintf(port_str, sizeof(port_str), "%d", port);
8082 if (strlen(buf) == 0)
8083 // Append
8084 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
8085 "auth_server_addr=%s\\n"
8086 "auth_server_port=%s\\n"
8087 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
8088 else {
8089 // Delete the three lines setting after the "# radius 2" comment
8090 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
8091 _syscmd(cmd, buf, sizeof(buf));
8092 memset(cmd, 0, sizeof(cmd));
8093 // Use "# radius 2" comment to find the location to insert the radius setting
8094 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
8095 "# radius 2\\n"
8096 "auth_server_addr=%s\\n"
8097 "auth_server_port=%s\\n"
8098 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
8099 }
8100 if(_syscmd(cmd, buf, sizeof(buf))) {
8101 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
8102 return RETURN_ERR;
8103 }
8104
8105 wifi_reloadAp(apIndex);
8106 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8107 return RETURN_OK;
8108}
8109
8110//RadiusSettings
8111INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
8112{
8113 if(!output)
8114 return RETURN_ERR;
8115
8116 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08008117 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
8118 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
8119 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
8120 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
developer72fb0bb2023-01-11 09:46:29 +08008121 output->MaxAuthenticationAttempts = 3; //Indicates the # of time, a client can attempt to login with incorrect credentials. When this limit is reached, the client is blacklisted and not allowed to attempt loging into the network. Settings this parameter to 0 (zero) disables the blacklisting feature.
developer69b61b02023-03-07 17:17:44 +08008122 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
8123 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
8124 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
developer72fb0bb2023-01-11 09:46:29 +08008125 //snprintf(output->RadiusSecret, 64, "12345678"); //The secret used for handshaking with the RADIUS server [RFC2865]. When read, this parameter returns an empty string, regardless of the actual value.
8126
8127 return RETURN_OK;
8128}
8129
8130INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
8131{
8132 //store the paramters, and apply instantly
8133 return RETURN_ERR;
8134}
8135
8136//Device.WiFi.AccessPoint.{i}.WPS.Enable
8137//Enables or disables WPS functionality for this access point.
8138// outputs the WPS enable state of this ap in output_bool
8139INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
8140{
8141 char interface_name[16] = {0};
8142 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
8143 if(!output_bool)
8144 return RETURN_ERR;
8145 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8146 return RETURN_ERR;
8147 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
8148 _syscmd(cmd, buf, sizeof(buf));
8149 if(strstr(buf, "configured"))
8150 *output_bool=TRUE;
8151 else
8152 *output_bool=FALSE;
8153
8154 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08008155}
developer72fb0bb2023-01-11 09:46:29 +08008156
8157//Device.WiFi.AccessPoint.{i}.WPS.Enable
8158// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
8159INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
8160{
8161 char config_file[MAX_BUF_SIZE] = {0};
developere5750452023-05-15 16:46:42 +08008162 char buf[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008163 struct params params;
8164
8165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8166 //store the paramters, and wait for wifi up to apply
8167 params.name = "wps_state";
developere5750452023-05-15 16:46:42 +08008168 if (enable == TRUE) {
8169 wifi_getApBeaconType(apIndex, buf);
8170 if (strncmp(buf, "None", 4) == 0) // If ap didn't set encryption
8171 params.value = "1";
8172 else // If ap set encryption
8173 params.value = "2";
8174 } else {
8175 params.value = "0";
8176 }
developer72fb0bb2023-01-11 09:46:29 +08008177
8178 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8179 wifi_hostapdWrite(config_file, &params, 1);
8180 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8181 wifi_reloadAp(apIndex);
8182
8183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8184 return RETURN_OK;
8185}
8186
8187//Comma-separated list of strings. Indicates WPS configuration methods supported by the device. Each list item is an enumeration of: USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
8188INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
8189{
8190 if(!output)
8191 return RETURN_ERR;
8192 snprintf(output, 128, "PushButton,PIN");
8193 return RETURN_OK;
8194}
8195
8196//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
8197//Comma-separated list of strings. Each list item MUST be a member of the list reported by the ConfigMethodsSupported parameter. Indicates WPS configuration methods enabled on the device.
8198// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
8199INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
8200{
8201 if(!output)
8202 return RETURN_ERR;
8203 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
8204
8205 return RETURN_OK;
8206}
8207
8208//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
8209// sets an enviornment variable that specifies the WPS configuration method(s). methodString is a comma separated list of methods USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
8210INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
8211{
8212 //apply instantly. No setting need to be stored.
8213 char methods[MAX_BUF_SIZE], *token, *next_token;
8214 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
8215 struct params params;
8216
8217 if(!methodString)
8218 return RETURN_ERR;
8219 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8220 //store the paramters, and wait for wifi up to apply
8221
8222 snprintf(methods, sizeof(methods), "%s", methodString);
8223 for(token=methods; *token; token=next_token)
8224 {
8225 strtok_r(token, ",", &next_token);
8226 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
8227 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
8228 else if(*token=='E')
8229 {
8230 if(!strcmp(methods, "Ethernet"))
8231 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
8232 else if(!strcmp(methods, "ExternalNFCToken"))
8233 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
8234 else
8235 printf("%s: Unknown WpsConfigMethod\n", __func__);
8236 }
8237 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
8238 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
8239 else if(*token=='N' && !strcmp(token, "NFCInterface"))
8240 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
8241 else if(*token=='P' )
8242 {
8243 if(!strcmp(token, "PushButton"))
developere5750452023-05-15 16:46:42 +08008244 snprintf(config_methods, sizeof(config_methods), "%s ", "push_button");
developer72fb0bb2023-01-11 09:46:29 +08008245 else if(!strcmp(token, "PIN"))
8246 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
8247 else
8248 printf("%s: Unknown WpsConfigMethod\n", __func__);
8249 }
8250 else
8251 printf("%s: Unknown WpsConfigMethod\n", __func__);
8252 }
8253 params.name = "config_methods";
8254 params.value = config_methods;
8255 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8256 wifi_hostapdWrite(config_file, &params, 1);
8257 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8258 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8259
8260 return RETURN_OK;
8261}
8262
8263// outputs the pin value, ulong_pin must be allocated by the caller
8264INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
8265{
8266 char buf[MAX_BUF_SIZE] = {0};
8267 char cmd[MAX_CMD_SIZE] = {0};
8268
8269 if(!output_ulong)
8270 return RETURN_ERR;
8271 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
8272 _syscmd(cmd, buf, sizeof(buf));
8273 if(strlen(buf) > 0)
8274 *output_ulong=strtoul(buf, NULL, 10);
8275
8276 return RETURN_OK;
8277}
8278
8279// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
8280INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
8281{
8282 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
8283 char ap_pin[16] = {0};
8284 char buf[MAX_BUF_SIZE] = {0};
8285 char config_file[MAX_BUF_SIZE] = {0};
8286 ULONG prev_pin = 0;
8287 struct params params;
8288
8289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8290 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
8291 params.name = "ap_pin";
8292 params.value = ap_pin;
8293 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
8294 wifi_hostapdWrite(config_file, &params, 1);
8295 wifi_hostapdProcessUpdate(apIndex, &params, 1);
8296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8297
8298 return RETURN_OK;
8299}
8300
8301// Output string is either Not configured or Configured, max 32 characters
8302INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
8303{
8304 char interface_name[16] = {0};
8305 char cmd[MAX_CMD_SIZE];
8306 char buf[MAX_BUF_SIZE]={0};
8307
8308 if(!output_string)
8309 return RETURN_ERR;
8310 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8311 snprintf(output_string, 32, "Not configured");
8312 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8313 return RETURN_ERR;
8314 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
8315 _syscmd(cmd, buf, sizeof(buf));
8316
8317 if(!strncmp(buf, "configured", 10))
8318 snprintf(output_string, 32, "Configured");
8319 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8320
8321 return RETURN_OK;
8322}
8323
8324// sets the WPS pin for this AP
8325INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
8326{
8327 char interface_name[16] = {0};
8328 char cmd[MAX_CMD_SIZE];
8329 char buf[MAX_BUF_SIZE]={0};
8330 BOOL enable;
8331
8332 wifi_getApEnable(apIndex, &enable);
8333 if (!enable)
8334 return RETURN_ERR;
8335 wifi_getApWpsEnable(apIndex, &enable);
8336 if (!enable)
8337 return RETURN_ERR;
8338
8339 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8340 return RETURN_ERR;
8341 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
8342 _syscmd(cmd, buf, sizeof(buf));
8343 if((strstr(buf, "OK"))!=NULL)
8344 return RETURN_OK;
8345
8346 return RETURN_ERR;
8347}
8348
8349// This function is called when the WPS push button has been pressed for this AP
8350INT wifi_setApWpsButtonPush(INT apIndex)
8351{
8352 char cmd[MAX_CMD_SIZE];
8353 char buf[MAX_BUF_SIZE]={0};
8354 char interface_name[16] = {0};
8355 BOOL enable=FALSE;
8356
8357 wifi_getApEnable(apIndex, &enable);
8358 if (!enable)
8359 return RETURN_ERR;
8360
8361 wifi_getApWpsEnable(apIndex, &enable);
8362 if (!enable)
8363 return RETURN_ERR;
8364
8365 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8366 return RETURN_ERR;
8367
8368 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
8369 _syscmd(cmd, buf, sizeof(buf));
8370
8371 if((strstr(buf, "OK"))!=NULL)
8372 return RETURN_OK;
8373 return RETURN_ERR;
8374}
8375
8376// cancels WPS mode for this AP
8377INT wifi_cancelApWPS(INT apIndex)
8378{
8379 char interface_name[16] = {0};
8380 char cmd[MAX_CMD_SIZE];
8381 char buf[MAX_BUF_SIZE]={0};
8382
8383 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8384 return RETURN_ERR;
8385 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
8386 _syscmd(cmd,buf, sizeof(buf));
8387
8388 if((strstr(buf, "OK"))!=NULL)
8389 return RETURN_OK;
8390 return RETURN_ERR;
8391}
8392
8393//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
8394//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
8395INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
8396{
8397 char interface_name[16] = {0};
8398 FILE *f = NULL;
8399 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8400 char cmd[256] = {0}, buf[2048] = {0};
8401 char *param = NULL, *value = NULL, *line=NULL;
8402 size_t len = 0;
8403 ssize_t nread = 0;
8404 wifi_associated_dev_t *dev=NULL;
8405
8406 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8407 *associated_dev_array = NULL;
8408 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8409 return RETURN_ERR;
8410 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8411 _syscmd(cmd,buf,sizeof(buf));
8412 *output_array_size = atoi(buf);
8413
8414 if (*output_array_size <= 0)
8415 return RETURN_OK;
8416
8417 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
8418 *associated_dev_array = dev;
8419 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
8420 _syscmd(cmd,buf,sizeof(buf));
8421 f = fopen("/tmp/connected_devices.txt", "r");
8422 if (f==NULL)
8423 {
8424 *output_array_size=0;
8425 return RETURN_ERR;
8426 }
8427 while ((getline(&line, &len, f)) != -1)
8428 {
8429 param = strtok(line,"=");
8430 value = strtok(NULL,"=");
8431
8432 if( strcmp("flags",param) == 0 )
8433 {
8434 value[strlen(value)-1]='\0';
8435 if(strstr (value,"AUTHORIZED") != NULL )
8436 {
8437 dev[auth_temp].cli_AuthenticationState = 1;
8438 dev[auth_temp].cli_Active = 1;
8439 auth_temp++;
8440 read_flag=1;
8441 }
8442 }
8443 if(read_flag==1)
8444 {
8445 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8446 {
8447 value[strlen(value)-1]='\0';
8448 sscanf(value, "%x:%x:%x:%x:%x:%x",
8449 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8450 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8451 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8452 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8453 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8454 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8455 mac_temp++;
8456 read_flag=0;
8457 }
8458 }
8459 }
8460 *output_array_size = auth_temp;
8461 auth_temp=0;
8462 mac_temp=0;
8463 free(line);
8464 fclose(f);
8465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8466 return RETURN_OK;
8467}
8468
8469#define MACADDRESS_SIZE 6
8470
8471INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8472{
8473 FILE *fp = NULL;
8474 char str[MAX_BUF_SIZE] = {0};
8475 int wificlientindex = 0 ;
8476 int count = 0;
8477 int signalstrength = 0;
8478 int arr[MACADDRESS_SIZE] = {0};
8479 unsigned char mac[MACADDRESS_SIZE] = {0};
8480 UINT wifi_count = 0;
8481 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8482 char pipeCmd[MAX_CMD_SIZE] = {0};
8483
8484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8485 *output_array_size = 0;
8486 *associated_dev_array = NULL;
8487
8488 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8489 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08008490 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08008491 {
8492 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8493 return RETURN_ERR;
8494 }
8495
8496 /* Read the output a line at a time - output it. */
8497 fgets(str, sizeof(str)-1, fp);
8498 wifi_count = (unsigned int) atoi ( str );
8499 *output_array_size = wifi_count;
8500 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8501 pclose(fp);
8502
8503 if(wifi_count == 0)
8504 {
8505 return RETURN_OK;
8506 }
8507 else
8508 {
8509 wifi_associated_dev3_t* temp = NULL;
8510 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
8511 if(temp == NULL)
8512 {
8513 printf("Error Statement. Insufficient memory \n");
8514 return RETURN_ERR;
8515 }
8516
8517 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8518 system(pipeCmd);
8519 memset(pipeCmd,0,sizeof(pipeCmd));
8520 if(apIndex == 0)
8521 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
8522 else if(apIndex == 1)
8523 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
8524 system(pipeCmd);
8525
8526 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8527 if(fp == NULL)
8528 {
8529 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8530 free(temp);
8531 return RETURN_ERR;
8532 }
8533 fclose(fp);
8534
8535 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
8536 fp = popen(pipeCmd, "r");
8537 if(fp)
8538 {
8539 for(count =0 ; count < wifi_count; count++)
8540 {
8541 fgets(str, MAX_BUF_SIZE, fp);
8542 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8543 {
8544 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8545 {
8546 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8547
8548 }
8549 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8550 printf("MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
8551 }
8552 temp[count].cli_AuthenticationState = 1; //TODO
8553 temp[count].cli_Active = 1; //TODO
8554 }
8555 pclose(fp);
8556 }
8557
8558 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
8559 fp = popen(pipeCmd, "r");
8560 if(fp)
developer69b61b02023-03-07 17:17:44 +08008561 {
developer72fb0bb2023-01-11 09:46:29 +08008562 pclose(fp);
8563 }
8564 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8565 if(fp)
8566 {
8567 for(count =0 ; count < wifi_count ;count++)
8568 {
8569 fgets(str, MAX_BUF_SIZE, fp);
8570 signalstrength = atoi(str);
8571 temp[count].cli_SignalStrength = signalstrength;
8572 temp[count].cli_RSSI = signalstrength;
8573 temp[count].cli_SNR = signalstrength + 95;
8574 }
8575 pclose(fp);
8576 }
8577
8578
8579 if((apIndex == 0) || (apIndex == 4))
8580 {
8581 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08008582 {
developer72fb0bb2023-01-11 09:46:29 +08008583 strcpy(temp[count].cli_OperatingStandard,"g");
8584 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
8585 }
8586
8587 //BytesSent
8588 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
8589 fp = popen(pipeCmd, "r");
8590 if(fp)
developer69b61b02023-03-07 17:17:44 +08008591 {
developer72fb0bb2023-01-11 09:46:29 +08008592 pclose(fp);
8593 }
8594 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
8595 if(fp)
8596 {
8597 for (count = 0; count < wifi_count; count++)
8598 {
8599 fgets(str, MAX_BUF_SIZE, fp);
8600 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
8601 }
8602 pclose(fp);
8603 }
8604
8605 //BytesReceived
8606 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
8607 fp = popen(pipeCmd, "r");
8608 if (fp)
8609 {
8610 pclose(fp);
8611 }
8612 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
8613 if (fp)
8614 {
8615 for (count = 0; count < wifi_count; count++)
8616 {
8617 fgets(str, MAX_BUF_SIZE, fp);
8618 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
8619 }
8620 pclose(fp);
8621 }
8622
8623 //PacketsSent
8624 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
8625 fp = popen(pipeCmd, "r");
8626 if (fp)
8627 {
8628 pclose(fp);
8629 }
8630
8631 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
8632 if (fp)
8633 {
8634 for (count = 0; count < wifi_count; count++)
8635 {
8636 fgets(str, MAX_BUF_SIZE, fp);
8637 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
8638 }
8639 pclose(fp);
8640 }
8641
8642 //PacketsReceived
8643 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
8644 fp = popen(pipeCmd, "r");
8645 if (fp)
8646 {
8647 pclose(fp);
8648 }
8649 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
8650 if (fp)
8651 {
8652 for (count = 0; count < wifi_count; count++)
8653 {
8654 fgets(str, MAX_BUF_SIZE, fp);
8655 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
8656 }
8657 pclose(fp);
8658 }
8659
8660 //ErrorsSent
8661 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8662 fp = popen(pipeCmd, "r");
8663 if (fp)
8664 {
8665 pclose(fp);
8666 }
8667 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8668 if (fp)
8669 {
8670 for (count = 0; count < wifi_count; count++)
8671 {
8672 fgets(str, MAX_BUF_SIZE, fp);
8673 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8674 }
8675 pclose(fp);
8676 }
8677
8678 //ErrorsSent
8679 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
8680 fp = popen(pipeCmd, "r");
8681 if (fp)
8682 {
8683 pclose(fp);
8684 }
8685 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
8686 if (fp)
8687 {
8688 for (count = 0; count < wifi_count; count++)
8689 {
8690 fgets(str, MAX_BUF_SIZE, fp);
8691 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
8692 }
8693 pclose(fp);
8694 }
8695
8696 //LastDataDownlinkRate
8697 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
8698 fp = popen(pipeCmd, "r");
8699 if (fp)
8700 {
8701 pclose(fp);
8702 }
8703 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8704 if (fp)
8705 {
8706 for (count = 0; count < wifi_count; count++)
8707 {
8708 fgets(str, MAX_BUF_SIZE, fp);
8709 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8710 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8711 }
8712 pclose(fp);
8713 }
8714
8715 //LastDataUplinkRate
8716 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
8717 fp = popen(pipeCmd, "r");
8718 if (fp)
8719 {
8720 pclose(fp);
8721 }
8722 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8723 if (fp)
8724 {
8725 for (count = 0; count < wifi_count; count++)
8726 {
8727 fgets(str, MAX_BUF_SIZE, fp);
8728 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8729 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8730 }
8731 pclose(fp);
8732 }
8733
8734 }
8735 else if ((apIndex == 1) || (apIndex == 5))
8736 {
8737 for (count = 0; count < wifi_count; count++)
8738 {
8739 strcpy(temp[count].cli_OperatingStandard, "a");
8740 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
8741 temp[count].cli_BytesSent = 0;
8742 temp[count].cli_BytesReceived = 0;
8743 temp[count].cli_LastDataUplinkRate = 0;
8744 temp[count].cli_LastDataDownlinkRate = 0;
8745 temp[count].cli_PacketsSent = 0;
8746 temp[count].cli_PacketsReceived = 0;
8747 temp[count].cli_ErrorsSent = 0;
8748 }
8749 }
8750
8751 for (count = 0; count < wifi_count; count++)
8752 {
8753 temp[count].cli_Retransmissions = 0;
8754 temp[count].cli_DataFramesSentAck = 0;
8755 temp[count].cli_DataFramesSentNoAck = 0;
8756 temp[count].cli_MinRSSI = 0;
8757 temp[count].cli_MaxRSSI = 0;
8758 strncpy(temp[count].cli_InterferenceSources, "", 64);
8759 memset(temp[count].cli_IPAddress, 0, 64);
8760 temp[count].cli_RetransCount = 0;
8761 temp[count].cli_FailedRetransCount = 0;
8762 temp[count].cli_RetryCount = 0;
8763 temp[count].cli_MultipleRetryCount = 0;
8764 }
8765 *associated_dev_array = temp;
8766 }
8767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8768 return RETURN_OK;
8769}
8770
developer7e4a2a62023-04-06 19:56:03 +08008771int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08008772{
developer7e4a2a62023-04-06 19:56:03 +08008773 char cmd[MAX_CMD_SIZE] = {0};
8774 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08008775
developer7e4a2a62023-04-06 19:56:03 +08008776 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
8777
8778 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
8779 interface_name);
8780 _syscmd(cmd, buf, MAX_BUF_SIZE);
8781
8782 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
8783
8784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08008785 return RETURN_OK;
8786}
8787
8788/* #define HOSTAPD_STA_PARAM_ENTRIES 29
8789struct hostapd_sta_param {
8790 char key[50];
8791 char value[100];
8792}
8793
8794static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
8795 int i = 0;
8796
8797 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
8798 if (strncmp(params[i].key,key,50) == 0){
8799 return &params[i].value;
8800 }
8801 i++;
8802 }
8803 return NULL;
8804
8805} */
8806
8807static unsigned int count_occurences(const char *buf, const char *word)
8808{
8809 unsigned int n = 0;
8810 char *ptr = strstr(buf, word);
8811
8812 while (ptr++) {
8813 n++;
8814 ptr = strstr(ptr, word);
8815 }
8816
8817 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
8818 return n;
8819}
8820
8821static const char *get_line_from_str_buf(const char *buf, char *line)
8822{
8823 int i;
8824 int n = strlen(buf);
8825
8826 for (i = 0; i < n; i++) {
8827 line[i] = buf[i];
8828 if (buf[i] == '\n') {
8829 line[i] = '\0';
8830 return &buf[i + 1];
8831 }
8832 }
8833
8834 return NULL;
8835}
8836
8837INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8838{
8839 unsigned int assoc_cnt = 0;
8840 char interface_name[50] = {0};
8841 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
8842 char cmd[MAX_CMD_SIZE] = {'\0'};
8843 char line[256] = {'\0'};
8844 int i = 0;
8845 int ret = 0;
8846 const char *ptr = NULL;
8847 char *key = NULL;
8848 char *val = NULL;
8849 wifi_associated_dev3_t *temp = NULL;
8850 int rssi;
8851
8852 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8853
8854 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8855 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8856 return RETURN_ERR;
8857 }
8858
8859 // Example filtered output of 'iw dev' command:
8860 // Station 0a:69:72:10:d2:fa (on wifi0)
8861 // signal avg:-67 [-71, -71] dBm
8862 // Station 28:c2:1f:25:5f:99 (on wifi0)
8863 // signal avg:-67 [-71, -70] dBm
8864 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
8865 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
8866 return RETURN_ERR;
8867 }
8868
8869 ret = _syscmd(cmd, buf, sizeof(buf));
8870 if (ret == RETURN_ERR) {
8871 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
8872 return RETURN_ERR;
8873 }
8874
8875 *output_array_size = count_occurences(buf, "Station");
8876 if (*output_array_size == 0) return RETURN_OK;
8877
8878 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
8879 if (temp == NULL) {
8880 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
8881 return RETURN_ERR;
8882 }
8883 *associated_dev_array = temp;
8884
8885 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
8886 ptr = get_line_from_str_buf(buf, line);
8887 i = -1;
8888 while (ptr) {
8889 if (strstr(line, "Station")) {
8890 i++;
8891 key = strtok(line, " ");
8892 val = strtok(NULL, " ");
8893 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
8894 &temp[i].cli_MACAddress[0],
8895 &temp[i].cli_MACAddress[1],
8896 &temp[i].cli_MACAddress[2],
8897 &temp[i].cli_MACAddress[3],
8898 &temp[i].cli_MACAddress[4],
8899 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
8900 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
8901 free(*associated_dev_array);
8902 return RETURN_ERR;
8903 }
8904 }
8905 else if (i < 0) {
8906 ptr = get_line_from_str_buf(ptr, line);
8907 continue; // We didn't detect 'station' entry yet
8908 }
8909 else if (strstr(line, "signal avg")) {
8910 key = strtok(line, ":");
8911 val = strtok(NULL, " ");
8912 if (sscanf(val, "%d", &rssi) <= 0 ) {
8913 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8914 free(*associated_dev_array);
8915 return RETURN_ERR;
8916 }
8917 temp[i].cli_RSSI = rssi;
8918 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8919 }
8920 // Here other fields can be parsed if added to filter of 'iw dev' command
8921
8922 ptr = get_line_from_str_buf(ptr, line);
8923 };
8924
8925 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8926
8927 return RETURN_OK;
8928}
8929
8930#if 0
8931//To-do
8932INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8933{
8934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8935
8936 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008937#if 0
developer72fb0bb2023-01-11 09:46:29 +08008938 FILE *f;
8939 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8940 char cmd[256], buf[2048];
8941 char *param , *value, *line=NULL;
8942 size_t len = 0;
8943 ssize_t nread;
8944 wifi_associated_dev3_t *dev=NULL;
8945 *associated_dev_array = NULL;
8946 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8947 _syscmd(cmd,buf,sizeof(buf));
8948 *output_array_size = atoi(buf);
8949
8950 if (*output_array_size <= 0)
8951 return RETURN_OK;
8952
8953 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8954 *associated_dev_array = dev;
8955 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8956 _syscmd(cmd,buf,sizeof(buf));
8957 f = fopen("/tmp/connected_devices.txt", "r");
8958 if (f==NULL)
8959 {
8960 *output_array_size=0;
8961 return RETURN_ERR;
8962 }
8963 while ((nread = getline(&line, &len, f)) != -1)
8964 {
8965 param = strtok(line,"=");
8966 value = strtok(NULL,"=");
8967
8968 if( strcmp("flags",param) == 0 )
8969 {
8970 value[strlen(value)-1]='\0';
8971 if(strstr (value,"AUTHORIZED") != NULL )
8972 {
8973 dev[auth_temp].cli_AuthenticationState = 1;
8974 dev[auth_temp].cli_Active = 1;
8975 auth_temp++;
8976 read_flag=1;
8977 }
8978 }
8979 if(read_flag==1)
8980 {
8981 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8982 {
8983 value[strlen(value)-1]='\0';
8984 sscanf(value, "%x:%x:%x:%x:%x:%x",
8985 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8986 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8987 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8988 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8989 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8990 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8991
8992 }
8993 else if( strcmp("rx_packets",param) == 0 )
8994 {
8995 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8996 }
8997
8998 else if( strcmp("tx_packets",param) == 0 )
8999 {
developer69b61b02023-03-07 17:17:44 +08009000 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08009001 }
9002
9003 else if( strcmp("rx_bytes",param) == 0 )
9004 {
9005 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
9006 }
9007
9008 else if( strcmp("tx_bytes",param) == 0 )
9009 {
developer69b61b02023-03-07 17:17:44 +08009010 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08009011 mac_temp++;
9012 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08009013 }
developer72fb0bb2023-01-11 09:46:29 +08009014 }
9015 }
9016
9017 *output_array_size = auth_temp;
9018 auth_temp=0;
9019 mac_temp=0;
9020 free(line);
9021 fclose(f);
9022#endif
9023 char interface_name[MAX_BUF_SIZE] = {0};
9024 char wifi_status[MAX_BUF_SIZE] = {0};
9025 char hostapdconf[MAX_BUF_SIZE] = {0};
9026
9027 wifi_associated_dev3_t *dev_array = NULL;
9028 ULONG wifi_count = 0;
9029
9030 *associated_dev_array = NULL;
9031 *output_array_size = 0;
9032
9033 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
9034 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
9035 {
9036 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
9037
9038 wifi_GetInterfaceName(interface_name, hostapdconf);
9039
9040 if(strlen(interface_name) > 1)
9041 {
9042 wifihal_interfacestatus(wifi_status,interface_name);
9043 if(strcmp(wifi_status,"RUNNING") == 0)
9044 {
9045 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
9046
9047 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08009048 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08009049 }
9050 else
9051 {
9052 *associated_dev_array = NULL;
9053 }
9054 }
9055 }
9056
9057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9058 return RETURN_OK;
9059}
9060#endif
9061
9062/* getIPAddress function */
9063/**
9064* @description Returning IpAddress of the Matched String
9065*
developer69b61b02023-03-07 17:17:44 +08009066* @param
developer72fb0bb2023-01-11 09:46:29 +08009067* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08009068* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08009069* @return The status of the operation
9070* @retval RETURN_OK if successful
9071* @retval RETURN_ERR if any error is detected
9072*
9073*/
9074
9075INT getIPAddress(char *str,char *ipaddr)
9076{
9077 FILE *fp = NULL;
9078 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
9079 int LeaseTime = 0,ret = 0;
9080 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
9081 {
9082 return RETURN_ERR;
9083 }
9084
9085 while ( fgets(buf, sizeof(buf), fp)!= NULL )
9086 {
9087 /*
9088 Sample:sss
9089 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
9090 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
9091 */
9092 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
9093 &(LeaseTime),
9094 phyAddr,
9095 ipAddr,
9096 hostName
9097 );
9098 if(ret != 4)
9099 continue;
9100 if(strcmp(str,phyAddr) == 0)
9101 strcpy(ipaddr,ipAddr);
9102 }
9103 fclose(fp);
9104 return RETURN_OK;
9105}
9106
9107/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
9108/**
9109* @description Returning Inactive wireless connected clients informations
9110*
developer69b61b02023-03-07 17:17:44 +08009111* @param
developer72fb0bb2023-01-11 09:46:29 +08009112* @filename Holding private_wifi 2g/5g content files
9113* @associated_dev_array Having inactiv wireless clients informations
9114* @output_array_size Returning Inactive wireless counts
9115* @return The status of the operation
9116* @retval RETURN_OK if successful
9117* @retval RETURN_ERR if any error is detected
9118*
9119*/
9120
9121INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
9122{
9123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9124 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
9125 FILE *fp = NULL;
9126 int arr[MACADDRESS_SIZE] = {0};
9127 unsigned char mac[MACADDRESS_SIZE] = {0};
9128 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
9129 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
9130 fp = popen(buf,"r");
9131 if(fp == NULL)
9132 return RETURN_ERR;
9133 else
9134 {
9135 fgets(path,sizeof(path),fp);
9136 maccount = atoi(path);
9137 }
9138 pclose(fp);
9139 *output_array_size = maccount;
9140 wifi_associated_dev3_t* temp = NULL;
9141 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
9142 *associated_dev_array = temp;
9143 if(temp == NULL)
9144 {
9145 printf("Error Statement. Insufficient memory \n");
9146 return RETURN_ERR;
9147 }
9148 memset(buf,0,sizeof(buf));
9149 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
9150 fp = popen(buf,"r");
9151 if (fp == NULL) {
9152 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
9153 return RETURN_ERR;
9154 }
9155 for(count = 0; count < maccount ; count++)
9156 {
9157 fgets(path,sizeof(path),fp);
9158 for(i = 0; path[i]!='\n';i++)
9159 str[i]=path[i];
9160 str[i]='\0';
9161 getIPAddress(str,ipaddr);
9162 memset(buf,0,sizeof(buf));
9163 if(strlen(ipaddr) > 0)
9164 {
9165 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
9166 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
9167 {
9168 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9169 {
9170 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9171 {
9172 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9173
9174 }
9175 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9176 fprintf(stderr,"%sMAC %d = %X:%X:%X:%X:%X:%X \n", __FUNCTION__,count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
9177 }
9178 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08009179 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08009180 temp[count].cli_SignalStrength = 0;
9181 }
9182 else //Active wireless clients info
9183 {
9184 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9185 {
9186 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9187 {
9188 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9189
9190 }
9191 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9192 fprintf(stderr,"%sMAC %d = %X:%X:%X:%X:%X:%X \n", __FUNCTION__,count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
9193 }
9194 temp[count].cli_Active = 1;
9195 }
9196 }
9197 memset(ipaddr,0,sizeof(ipaddr));
9198 }
9199 pclose(fp);
9200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9201 return RETURN_OK;
9202}
9203//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
9204//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
9205//To get Band Steering Capability
9206INT wifi_getBandSteeringCapability(BOOL *support)
9207{
9208 *support = FALSE;
9209 return RETURN_OK;
9210}
9211
9212
9213//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
9214//To get Band Steering enable status
9215INT wifi_getBandSteeringEnable(BOOL *enable)
9216{
9217 *enable = FALSE;
9218 return RETURN_OK;
9219}
9220
9221//To turn on/off Band steering
9222INT wifi_setBandSteeringEnable(BOOL enable)
9223{
9224 return RETURN_OK;
9225}
9226
9227//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
9228//To get Band Steering AP group
9229INT wifi_getBandSteeringApGroup(char *output_ApGroup)
9230{
9231 if (NULL == output_ApGroup)
9232 return RETURN_ERR;
9233
9234 strcpy(output_ApGroup, "1,2");
9235 return RETURN_OK;
9236}
9237
9238//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
9239//to set and read the band steering BandUtilizationThreshold parameters
9240INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
9241{
9242 return RETURN_ERR;
9243}
9244
9245INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
9246{
9247 return RETURN_ERR;
9248}
9249
9250//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
9251//to set and read the band steering RSSIThreshold parameters
9252INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
9253{
9254 return RETURN_ERR;
9255}
9256
9257INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
9258{
9259 return RETURN_ERR;
9260}
9261
9262
9263//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
9264//to set and read the band steering physical modulation rate threshold parameters
9265INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
9266{
9267 //If chip is not support, return -1
9268 return RETURN_ERR;
9269}
9270
9271INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
9272{
9273 //If chip is not support, return -1
9274 return RETURN_ERR;
9275}
9276
9277//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
9278//to set and read the inactivity time (in seconds) for steering under overload condition
9279INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
9280{
9281 return RETURN_ERR;
9282}
9283
9284INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
9285{
9286 return RETURN_ERR;
9287}
9288
9289//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
9290//to set and read the inactivity time (in seconds) for steering under Idle condition
9291INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
9292{
9293 return RETURN_ERR;
9294}
9295
9296INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
9297{
9298 return RETURN_ERR;
9299}
9300
9301//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
9302//pClientMAC[64]
9303//pSourceSSIDIndex[64]
9304//pDestSSIDIndex[64]
9305//pSteeringReason[256]
9306INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
9307{
9308 //if no steering or redord_index is out of boundary, return -1. pSteeringTime returns the UTC time in seconds. pClientMAC is pre allocated as 64bytes. pSteeringReason returns the predefined steering trigger reason
9309 *pSteeringTime=time(NULL);
9310 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
9311 return RETURN_OK;
9312}
9313
9314INT wifi_ifConfigDown(INT apIndex)
9315{
9316 INT status = RETURN_OK;
9317 char cmd[64];
9318
9319 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
9320 printf("%s: %s\n", __func__, cmd);
9321 system(cmd);
9322
9323 return status;
9324}
9325
9326INT wifi_ifConfigUp(INT apIndex)
9327{
9328 char interface_name[16] = {0};
9329 char cmd[128];
9330 char buf[1024];
9331
9332 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9333 return RETURN_ERR;
9334 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
9335 _syscmd(cmd, buf, sizeof(buf));
9336 return 0;
9337}
9338
9339//>> Deprecated. Replace with wifi_applyRadioSettings
9340INT wifi_pushBridgeInfo(INT apIndex)
9341{
9342 char interface_name[16] = {0};
9343 char ip[32] = {0};
9344 char subnet[32] = {0};
9345 char bridge[32] = {0};
9346 int vlanId = 0;
9347 char cmd[128] = {0};
9348 char buf[1024] = {0};
9349
9350 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
9351 wifi_getApVlanID(apIndex,&vlanId);
9352
9353 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9354 return RETURN_ERR;
9355 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
9356 _syscmd(cmd,buf, sizeof(buf));
9357
9358 return 0;
9359}
9360
9361INT wifi_pushChannel(INT radioIndex, UINT channel)
9362{
9363 char interface_name[16] = {0};
9364 char cmd[128];
9365 char buf[1024];
9366 int apIndex;
9367
developer69b61b02023-03-07 17:17:44 +08009368 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08009369 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9370 return RETURN_ERR;
9371 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
9372 _syscmd(cmd,buf, sizeof(buf));
9373
9374 return 0;
9375}
9376
9377INT wifi_pushChannelMode(INT radioIndex)
9378{
9379 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
9380 return RETURN_ERR;
9381}
9382
9383INT wifi_pushDefaultValues(INT radioIndex)
9384{
9385 //Apply Comcast specified default radio settings instantly
9386 //AMPDU=1
9387 //AMPDUFrames=32
9388 //AMPDULim=50000
9389 //txqueuelen=1000
9390
9391 return RETURN_ERR;
9392}
9393
9394INT wifi_pushTxChainMask(INT radioIndex)
9395{
9396 //Apply default TxChainMask instantly
9397 return RETURN_ERR;
9398}
9399
9400INT wifi_pushRxChainMask(INT radioIndex)
9401{
9402 //Apply default RxChainMask instantly
9403 return RETURN_ERR;
9404}
9405
9406INT wifi_pushSSID(INT apIndex, CHAR *ssid)
9407{
developer7e4a2a62023-04-06 19:56:03 +08009408 INT status;
developer72fb0bb2023-01-11 09:46:29 +08009409
developer7e4a2a62023-04-06 19:56:03 +08009410 status = wifi_setSSIDName(apIndex, ssid);
9411 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08009412
developer7e4a2a62023-04-06 19:56:03 +08009413 return status;
developer72fb0bb2023-01-11 09:46:29 +08009414}
9415
9416INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
9417{
9418 //Apply default Ssid Advertisement instantly
9419 return RETURN_ERR;
9420}
9421
9422INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
9423{
developere82c0ca2023-05-10 16:25:35 +08009424 time_t now;
9425
9426 time(&now);
9427 if (now > radio_up_time[radioIndex])
9428 *output = now - radio_up_time[radioIndex];
9429 else {
9430 *output = 0;
9431 return RETURN_ERR;
9432 }
9433
9434 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08009435}
9436
9437INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
9438{
9439 return RETURN_OK;
9440}
9441
9442INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
9443{
9444 return RETURN_OK;
9445}
9446
9447//To-do
9448INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
9449{
9450 char output[16]={'\0'};
9451 char config_file[MAX_BUF_SIZE] = {0};
9452
9453 if (!output_string)
9454 return RETURN_ERR;
9455
9456 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9457 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
9458
9459 if (strlen(output) == 0)
9460 snprintf(output_string, 64, "Disabled");
9461 else if (strncmp(output, "0", 1) == 0)
9462 snprintf(output_string, 64, "Disabled");
9463 else if (strncmp(output, "1", 1) == 0)
9464 snprintf(output_string, 64, "Optional");
9465 else if (strncmp(output, "2", 1) == 0)
9466 snprintf(output_string, 64, "Required");
9467 else {
9468 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
9469 return RETURN_ERR;
9470 }
9471
9472 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
9473 return RETURN_OK;
9474}
9475INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
9476{
9477 char str[MAX_BUF_SIZE]={'\0'};
9478 char cmd[MAX_CMD_SIZE]={'\0'};
9479 struct params params;
9480 char config_file[MAX_BUF_SIZE] = {0};
9481
9482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9483 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
9484 return RETURN_ERR;
9485
9486 params.name = "ieee80211w";
9487 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
9488 params.value = "0";
9489 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
9490 params.value = "1";
9491 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
9492 params.value = "2";
9493 else{
9494 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
9495 return RETURN_ERR;
9496 }
9497 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9498 wifi_hostapdWrite(config_file, &params, 1);
9499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
9500 return RETURN_OK;
9501}
9502INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
9503{
9504 char output[16]={'\0'};
9505 char config_file[MAX_BUF_SIZE] = {0};
9506
9507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerc0772e62023-05-18 15:10:48 +08009508 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developerd1824452023-05-18 12:30:04 +08009509 wifi_datfileRead(config_file, "Channel" , output, sizeof(output));
developer72fb0bb2023-01-11 09:46:29 +08009510
9511 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
9512 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9513
9514 return RETURN_OK;
9515}
9516
9517INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
9518{
9519 return RETURN_OK;
9520}
9521
9522INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
9523{
9524 return RETURN_OK;
9525}
9526
9527INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
9528{
9529 return RETURN_OK;
9530}
9531
9532INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9533{
9534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9535 char config_file[MAX_BUF_SIZE] = {0};
9536
9537 if (NULL == output)
9538 return RETURN_ERR;
9539 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9540 wifi_hostapdRead(config_file,"hw_mode",output,64);
9541
9542 if(strcmp(output,"b")==0)
9543 sprintf(output, "%s", "1,2,5.5,11");
9544 else if (strcmp(output,"a")==0)
9545 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
9546 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
9547 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
9548
9549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9550 return RETURN_OK;
9551}
9552
9553INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9554{
9555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9556 char *temp;
9557 char temp_output[128];
9558 char temp_TransmitRates[128];
9559 char config_file[MAX_BUF_SIZE] = {0};
9560
9561 if (NULL == output)
9562 return RETURN_ERR;
9563
9564 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9565 wifi_hostapdRead(config_file,"supported_rates",output,64);
9566
9567 if (strlen(output) == 0) {
9568 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
9569 return RETURN_OK;
9570 }
9571 strcpy(temp_TransmitRates,output);
9572 strcpy(temp_output,"");
9573 temp = strtok(temp_TransmitRates," ");
9574 while(temp!=NULL)
9575 {
9576 temp[strlen(temp)-1]=0;
9577 if((temp[0]=='5') && (temp[1]=='\0'))
9578 {
9579 temp="5.5";
9580 }
9581 strcat(temp_output,temp);
9582 temp = strtok(NULL," ");
9583 if(temp!=NULL)
9584 {
9585 strcat(temp_output,",");
9586 }
9587 }
9588 strcpy(output,temp_output);
9589 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9590
9591 return RETURN_OK;
9592}
9593
9594INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
9595{
9596 return RETURN_OK;
9597}
9598
9599
9600INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
9601{
9602 int i=0;
9603 char *temp;
9604 char temp1[128] = {0};
9605 char temp_output[128] = {0};
9606 char temp_TransmitRates[128] = {0};
9607 struct params params={'\0'};
9608 char config_file[MAX_BUF_SIZE] = {0};
9609 wifi_band band = wifi_index_to_band(wlanIndex);
9610
9611 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9612 if(NULL == output)
9613 return RETURN_ERR;
9614 strcpy(temp_TransmitRates,output);
9615
9616 for(i=0;i<strlen(temp_TransmitRates);i++)
9617 {
9618 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
9619 {
9620 continue;
9621 }
9622 else
9623 {
9624 return RETURN_ERR;
9625 }
9626 }
9627 strcpy(temp_output,"");
9628 temp = strtok(temp_TransmitRates,",");
9629 while(temp!=NULL)
9630 {
9631 strcpy(temp1,temp);
9632 if(band == band_5)
9633 {
9634 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
9635 {
9636 return RETURN_ERR;
9637 }
9638 }
9639
9640 if(strcmp(temp,"5.5")==0)
9641 {
9642 strcpy(temp1,"55");
9643 }
9644 else
9645 {
9646 strcat(temp1,"0");
9647 }
9648 strcat(temp_output,temp1);
9649 temp = strtok(NULL,",");
9650 if(temp!=NULL)
9651 {
9652 strcat(temp_output," ");
9653 }
9654 }
9655 strcpy(output,temp_output);
9656
9657 params.name = "supported_rates";
9658 params.value = output;
9659
9660 wifi_dbg_printf("\n%s:",__func__);
9661 wifi_dbg_printf("params.value=%s\n",params.value);
9662 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
9663 wifi_hostapdWrite(config_file,&params,1);
9664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9665
9666 return RETURN_OK;
9667}
9668
9669
9670static char *sncopy(char *dst, int dst_sz, const char *src)
9671{
9672 if (src && dst && dst_sz > 0) {
9673 strncpy(dst, src, dst_sz);
9674 dst[dst_sz - 1] = '\0';
9675 }
9676 return dst;
9677}
9678
9679static int util_get_sec_chan_offset(int channel, const char* ht_mode)
9680{
9681 if (0 == strcmp(ht_mode, "HT40") ||
9682 0 == strcmp(ht_mode, "HT80") ||
9683 0 == strcmp(ht_mode, "HT160")) {
9684 switch (channel) {
9685 case 1 ... 7:
9686 case 36:
9687 case 44:
9688 case 52:
9689 case 60:
9690 case 100:
9691 case 108:
9692 case 116:
9693 case 124:
9694 case 132:
9695 case 140:
9696 case 149:
9697 case 157:
9698 return 1;
9699 case 8 ... 13:
9700 case 40:
9701 case 48:
9702 case 56:
9703 case 64:
9704 case 104:
9705 case 112:
9706 case 120:
9707 case 128:
9708 case 136:
9709 case 144:
9710 case 153:
9711 case 161:
9712 return -1;
9713 default:
9714 return -EINVAL;
9715 }
9716 }
9717
9718 return -EINVAL;
9719}
9720
9721static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
9722{
9723 int idx = channel%8;
9724 if (0 == strcmp(ht_mode, "HT40") ||
9725 0 == strcmp(ht_mode, "HT80") ||
9726 0 == strcmp(ht_mode, "HT160")) {
9727 switch (idx) {
9728 case 1:
9729 return 1;
9730 case 5:
9731 return -1;
9732 default:
9733 return -EINVAL;
9734 }
9735 }
9736
9737 return -EINVAL;
9738}
9739static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
9740{
9741 if (NULL == hw_mode) return;
9742
9743 if (0 == strcmp(hw_mode, "ac"))
9744 sncopy(bw_mode, bw_mode_len, "ht vht");
9745
9746 if (0 == strcmp(hw_mode, "n"))
9747 sncopy(bw_mode, bw_mode_len, "ht");
9748
9749 return;
9750}
9751
9752static int util_chan_to_freq(int chan)
9753{
9754 if (chan == 14)
9755 return 2484;
9756 else if (chan < 14)
9757 return 2407 + chan * 5;
9758 else if (chan >= 182 && chan <= 196)
9759 return 4000 + chan * 5;
9760 else
9761 return 5000 + chan * 5;
9762 return 0;
9763}
9764
9765static int util_6G_chan_to_freq(int chan)
9766{
9767 if (chan)
9768 return 5950 + chan * 5;
9769 else
9770 return 0;
developer69b61b02023-03-07 17:17:44 +08009771
developer72fb0bb2023-01-11 09:46:29 +08009772}
9773const int *util_unii_5g_chan2list(int chan, int width)
9774{
9775 static const int lists[] = {
9776 // <width>, <chan1>, <chan2>..., 0,
9777 20, 36, 0,
9778 20, 40, 0,
9779 20, 44, 0,
9780 20, 48, 0,
9781 20, 52, 0,
9782 20, 56, 0,
9783 20, 60, 0,
9784 20, 64, 0,
9785 20, 100, 0,
9786 20, 104, 0,
9787 20, 108, 0,
9788 20, 112, 0,
9789 20, 116, 0,
9790 20, 120, 0,
9791 20, 124, 0,
9792 20, 128, 0,
9793 20, 132, 0,
9794 20, 136, 0,
9795 20, 140, 0,
9796 20, 144, 0,
9797 20, 149, 0,
9798 20, 153, 0,
9799 20, 157, 0,
9800 20, 161, 0,
9801 20, 165, 0,
9802 40, 36, 40, 0,
9803 40, 44, 48, 0,
9804 40, 52, 56, 0,
9805 40, 60, 64, 0,
9806 40, 100, 104, 0,
9807 40, 108, 112, 0,
9808 40, 116, 120, 0,
9809 40, 124, 128, 0,
9810 40, 132, 136, 0,
9811 40, 140, 144, 0,
9812 40, 149, 153, 0,
9813 40, 157, 161, 0,
9814 80, 36, 40, 44, 48, 0,
9815 80, 52, 56, 60, 64, 0,
9816 80, 100, 104, 108, 112, 0,
9817 80, 116, 120, 124, 128, 0,
9818 80, 132, 136, 140, 144, 0,
9819 80, 149, 153, 157, 161, 0,
9820 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
9821 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
9822 -1 // final delimiter
9823 };
9824 const int *start;
9825 const int *p;
9826
9827 for (p = lists; *p != -1; p++) {
9828 if (*p == width) {
9829 for (start = ++p; *p != 0; p++) {
9830 if (*p == chan)
9831 return start;
9832 }
9833 }
9834 // move to the end of channel list of given width
9835 while (*p != 0) {
9836 p++;
9837 }
9838 }
9839
9840 return NULL;
9841}
9842
9843static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
9844{
9845 if (NULL == ht_mode)
9846 return 0;
9847
9848 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
9849 const int *chans = util_unii_5g_chan2list(channel, width);
9850 int sum = 0;
9851 int cnt = 0;
9852
9853 if (NULL == chans)
9854 return 0;
9855
9856 while (*chans) {
9857 sum += *chans;
9858 cnt++;
9859 chans++;
9860 }
9861 if (cnt == 0)
9862 return 0;
9863 return sum / cnt;
9864}
9865
9866static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
9867{
9868 if (NULL == ht_mode)
9869 return 0;
9870
9871 int width = strtol((ht_mode + 2), NULL, 10);
9872
9873 int idx = 0 ;
9874 int centerchan = 0;
9875 int chan_ofs = 1;
9876
9877 if (width == 40){
9878 idx = ((channel/4) + chan_ofs)%2;
9879 switch (idx) {
9880 case 0:
9881 centerchan = (channel - 2);
9882 break;
9883 case 1:
9884 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08009885 break;
developer72fb0bb2023-01-11 09:46:29 +08009886 default:
9887 return -EINVAL;
9888 }
9889 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08009890 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08009891 switch (idx) {
9892 case 0:
9893 centerchan = (channel - 6);
9894 break;
9895 case 1:
9896 centerchan = (channel + 6);
9897 break;
9898 case 2:
9899 centerchan = (channel + 2);
9900 break;
9901 case 3:
9902 centerchan = (channel - 2);
9903 break;
9904 default:
9905 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009906 }
developer72fb0bb2023-01-11 09:46:29 +08009907 }else if (width == 160){
9908 switch (channel) {
9909 case 1 ... 29:
9910 centerchan = 15;
9911 break;
9912 case 33 ... 61:
9913 centerchan = 47;
9914 break;
9915 case 65 ... 93:
9916 centerchan = 79;
9917 break;
9918 case 97 ... 125:
9919 centerchan = 111;
9920 break;
9921 case 129 ... 157:
9922 centerchan = 143;
9923 break;
9924 case 161 ... 189:
9925 centerchan = 175;
9926 break;
9927 case 193 ... 221:
9928 centerchan = 207;
9929 break;
9930 default:
9931 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009932 }
developer72fb0bb2023-01-11 09:46:29 +08009933 }
9934 return centerchan;
9935}
9936static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9937{
9938 BOOL onlyG, onlyN, onlyA;
9939 CHAR tmp[64];
9940 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9941 if (ret == RETURN_OK) {
9942 sncopy(hw_mode, hw_mode_size, tmp);
9943 }
9944 return ret;
9945}
9946
9947INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9948{
9949 // Sample commands:
9950 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9951 // hostapd_cli -i wifi0 chan_switch 30 2437
9952 char cmd[MAX_CMD_SIZE] = {0};
9953 char buf[MAX_BUF_SIZE] = {0};
9954 int freq = 0, ret = 0;
9955 char center_freq1_str[32] = ""; // center_freq1=%d
9956 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9957 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9958 char hw_mode[16] = ""; // n|ac
9959 char bw_mode[16] = ""; // ht|ht vht
9960 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9961 char interface_name[16] = {0};
9962 int sec_chan_offset;
9963 int width;
9964 char config_file[64] = {0};
9965 BOOL stbcEnable = FALSE;
9966 char *ext_str = "None";
9967 wifi_band band = band_invalid;
9968 int center_chan = 0;
9969 int center_freq1 = 0;
developerd1824452023-05-18 12:30:04 +08009970 struct params mwctl = {0};
9971 char str_channel[8]={0};
developer72fb0bb2023-01-11 09:46:29 +08009972
9973 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9974
9975 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9976 return RETURN_ERR;
9977
9978 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9979
9980 band = wifi_index_to_band(radioIndex);
9981
9982 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9983
9984 // Get radio mode HT20|HT40|HT80 etc.
9985 if (channel){
9986 if (band == band_6){
9987 freq = util_6G_chan_to_freq(channel);
9988 }else{
9989 freq = util_chan_to_freq(channel);
9990 }
9991 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9992
9993 // Provide bandwith if specified
9994 if (channel_width_MHz > 20) {
9995 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9996 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9997 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9998
9999 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
10000 }else if (channel_width_MHz == 20){
10001 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
10002 }
10003
10004
10005 if (channel_width_MHz > 20) {
10006 if (band == band_6){
10007 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
10008 if(center_chan){
10009 center_freq1 = util_6G_chan_to_freq(center_chan);
10010 }
10011 }else{
10012 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
10013 if(center_chan){
10014 center_freq1 = util_chan_to_freq(center_chan);
10015 }
10016 }
developer69b61b02023-03-07 17:17:44 +080010017
developer72fb0bb2023-01-11 09:46:29 +080010018 if (center_freq1)
10019 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +080010020
developer72fb0bb2023-01-11 09:46:29 +080010021 }
10022
10023 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
10024 if (band == band_6){
10025 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
10026 }else{
10027 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
10028 }
10029 if (sec_chan_offset != -EINVAL)
10030 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
10031
10032 // Only the first AP, other are hanging on the same radio
10033 int apIndex = radioIndex;
developerd1824452023-05-18 12:30:04 +080010034 /* snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
developer72fb0bb2023-01-11 09:46:29 +080010035 interface_name, csa_beacon_count, freq,
developerd1824452023-05-18 12:30:04 +080010036 sec_chan_offset_str, center_freq1_str, opt_chan_info_str); */
10037 snprintf(str_channel, sizeof(str_channel), "%d", channel);
10038 mwctl.name = "channel num=";
10039 mwctl.value = str_channel;
10040 ret = wifi_mwctlSet(radioIndex, &mwctl, BASE_PHY_INDEX);
10041 if (ret != RETURN_OK) {
10042 fprintf(stderr, "%s: wifi_mwctlSet return error.\n", __func__);
10043 return RETURN_ERR;
10044 }
10045 /* wifi_dbg_printf("execute: '%s'\n", cmd);
developerf6a87542023-05-16 15:47:28 +080010046 ret = _syscmd(cmd, buf, sizeof(buf));
developerd1824452023-05-18 12:30:04 +080010047 wifi_reloadAp(radioIndex); */
developer72fb0bb2023-01-11 09:46:29 +080010048
10049 ret = wifi_setRadioChannel(radioIndex, channel);
10050 if (ret != RETURN_OK) {
10051 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
10052 return RETURN_ERR;
10053 }
10054
10055 if (sec_chan_offset == 1) ext_str = "Above";
10056 else if (sec_chan_offset == -1) ext_str = "Below";
10057
developerd1824452023-05-18 12:30:04 +080010058 /*wifi_setRadioCenterChannel(radioIndex, center_chan); */
developer72fb0bb2023-01-11 09:46:29 +080010059
10060 } else {
10061 if (channel_width_MHz > 20)
10062 ext_str = "Above";
10063 }
10064
10065 wifi_setRadioExtChannel(radioIndex, ext_str);
10066
10067 char mhz_str[16];
10068 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
10069 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
10070
10071 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10072
10073 return RETURN_OK;
10074}
10075
10076INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
10077{
10078 int index = -1;
10079 wifi_neighbor_ap2_t *scan_array = NULL;
10080 char cmd[256]={0};
10081 char buf[128]={0};
10082 char file_name[32] = {0};
10083 char filter_SSID[32] = {0};
10084 char line[256] = {0};
10085 char interface_name[16] = {0};
10086 char *ret = NULL;
10087 int freq=0;
10088 FILE *f = NULL;
10089 size_t len=0;
10090 int channels_num = 0;
10091 int vht_channel_width = 0;
10092 int get_noise_ret = RETURN_ERR;
10093 bool filter_enable = false;
10094 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
10095 int phyId = 0;
10096
10097 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
10098
10099 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
10100 f = fopen(file_name, "r");
10101 if (f != NULL) {
10102 fgets(filter_SSID, sizeof(file_name), f);
10103 if (strlen(filter_SSID) != 0)
10104 filter_enable = true;
10105 fclose(f);
10106 }
10107
10108 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
10109 return RETURN_ERR;
10110
10111 phyId = radio_index_to_phy(radio_index);
10112
10113 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
10114 _syscmd(cmd, buf, sizeof(buf));
10115 channels_num = strtol(buf, NULL, 10);
10116
10117 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
10118 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
10119 fprintf(stderr, "cmd: %s\n", cmd);
10120 if ((f = popen(cmd, "r")) == NULL) {
10121 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
10122 return RETURN_ERR;
10123 }
developer69b61b02023-03-07 17:17:44 +080010124
developer72fb0bb2023-01-11 09:46:29 +080010125 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
10126 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +080010127
developer72fb0bb2023-01-11 09:46:29 +080010128 ret = fgets(line, sizeof(line), f);
10129 while (ret != NULL) {
10130 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +080010131 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +080010132 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
10133 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
10134
10135 if (!filter_BSS) {
10136 index++;
10137 wifi_neighbor_ap2_t *tmp;
10138 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
10139 if (tmp == NULL) { // no more memory to use
10140 index--;
10141 wifi_dbg_printf("%s: realloc failed\n", __func__);
10142 break;
10143 }
10144 scan_array = tmp;
10145 }
10146 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
10147
10148 filter_BSS = false;
10149 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
10150 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
10151 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
10152 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
10153 } else if (strstr(line, "freq") != NULL) {
10154 sscanf(line," freq: %d", &freq);
10155 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
10156
10157 if (freq >= 2412 && freq <= 2484) {
10158 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
10159 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
10160 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
10161 }
10162 else if (freq >= 5160 && freq <= 5805) {
10163 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
10164 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
10165 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
10166 }
10167
10168 scan_array[index].ap_Noise = 0;
10169 if (get_noise_ret == RETURN_OK) {
10170 for (int i = 0; i < channels_num; i++) {
10171 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
10172 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
10173 break;
10174 }
10175 }
10176 }
10177 } else if (strstr(line, "beacon interval") != NULL) {
10178 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
10179 } else if (strstr(line, "signal") != NULL) {
10180 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
10181 } else if (strstr(line,"SSID") != NULL) {
10182 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
10183 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
10184 filter_BSS = true;
10185 }
10186 } else if (strstr(line, "Supported rates") != NULL) {
10187 char SRate[80] = {0}, *tmp = NULL;
10188 memset(buf, 0, sizeof(buf));
10189 strcpy(SRate, line);
10190 tmp = strtok(SRate, ":");
10191 tmp = strtok(NULL, ":");
10192 strcpy(buf, tmp);
10193 memset(SRate, 0, sizeof(SRate));
10194
10195 tmp = strtok(buf, " \n");
10196 while (tmp != NULL) {
10197 strcat(SRate, tmp);
10198 if (SRate[strlen(SRate) - 1] == '*') {
10199 SRate[strlen(SRate) - 1] = '\0';
10200 }
10201 strcat(SRate, ",");
10202
10203 tmp = strtok(NULL, " \n");
10204 }
10205 SRate[strlen(SRate) - 1] = '\0';
10206 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
10207 } else if (strstr(line, "DTIM") != NULL) {
10208 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
10209 } else if (strstr(line, "VHT capabilities") != NULL) {
10210 strcat(scan_array[index].ap_SupportedStandards, ",ac");
10211 strcpy(scan_array[index].ap_OperatingStandards, "ac");
10212 } else if (strstr(line, "HT capabilities") != NULL) {
10213 strcat(scan_array[index].ap_SupportedStandards, ",n");
10214 strcpy(scan_array[index].ap_OperatingStandards, "n");
10215 } else if (strstr(line, "VHT operation") != NULL) {
10216 ret = fgets(line, sizeof(line), f);
10217 sscanf(line," * channel width: %d", &vht_channel_width);
10218 if(vht_channel_width == 1) {
10219 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
10220 } else {
10221 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
10222 }
10223 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
10224 continue;
10225 } else if (strstr(line, "HT operation") != NULL) {
10226 ret = fgets(line, sizeof(line), f);
10227 sscanf(line," * secondary channel offset: %s", &buf);
10228 if (!strcmp(buf, "above")) {
10229 //40Mhz +
10230 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
10231 }
10232 else if (!strcmp(buf, "below")) {
10233 //40Mhz -
10234 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
10235 } else {
10236 //20Mhz
10237 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
10238 }
10239 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
10240 continue;
10241 } else if (strstr(line, "HE capabilities") != NULL) {
10242 strcat(scan_array[index].ap_SupportedStandards, ",ax");
10243 strcpy(scan_array[index].ap_OperatingStandards, "ax");
10244 ret = fgets(line, sizeof(line), f);
10245 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
10246 if (strstr(line, "HE40/2.4GHz") != NULL)
10247 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
10248 else
10249 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
10250 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
10251 if (strstr(line, "HE80/5GHz") != NULL) {
10252 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
10253 ret = fgets(line, sizeof(line), f);
10254 } else
10255 continue;
10256 if (strstr(line, "HE160/5GHz") != NULL)
10257 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
10258 }
10259 continue;
10260 } else if (strstr(line, "WPA") != NULL) {
10261 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
10262 } else if (strstr(line, "RSN") != NULL) {
10263 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
10264 } else if (strstr(line, "Group cipher") != NULL) {
10265 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
10266 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
10267 strcpy(scan_array[index].ap_EncryptionMode, "AES");
10268 }
10269 }
10270 ret = fgets(line, sizeof(line), f);
10271 }
10272
10273 if (!filter_BSS) {
10274 *output_array_size = index + 1;
10275 } else {
10276 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
10277 *output_array_size = index;
10278 }
10279 *neighbor_ap_array = scan_array;
10280 pclose(f);
10281 free(channels_noise_arr);
10282 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10283 return RETURN_OK;
10284}
10285
10286INT wifi_getApAssociatedDeviceStats(
10287 INT apIndex,
10288 mac_address_t *clientMacAddress,
10289 wifi_associated_dev_stats_t *associated_dev_stats,
10290 u64 *handle)
10291{
10292 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
10293 char interface_name[50] = {0};
10294 char cmd[1024] = {0};
10295 char mac_str[18] = {0};
10296 char *key = NULL;
10297 char *val = NULL;
10298 FILE *f = NULL;
10299 char *line = NULL;
10300 size_t len = 0;
10301
10302 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10303 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10304 return RETURN_ERR;
10305 }
10306
10307 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
10308 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
10309 if((f = popen(cmd, "r")) == NULL) {
10310 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
10311 return RETURN_ERR;
10312 }
10313
10314 while ((getline(&line, &len, f)) != -1) {
10315 key = strtok(line,":");
10316 val = strtok(NULL,":");
10317
10318 if(!strncmp(key,"rx bytes",8))
10319 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
10320 if(!strncmp(key,"tx bytes",8))
10321 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
10322 if(!strncmp(key,"rx packets",10))
10323 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10324 if(!strncmp(key,"tx packets",10))
10325 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
10326 if(!strncmp(key,"tx retries",10))
10327 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
10328 if(!strncmp(key,"tx failed",9))
10329 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
10330 if(!strncmp(key,"rx drop misc",13))
10331 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
10332 if(!strncmp(key,"rx bitrate",10)) {
10333 val = strtok(val, " ");
10334 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
10335 }
10336 if(!strncmp(key,"tx bitrate",10)) {
10337 val = strtok(val, " ");
10338 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
10339 }
10340 }
10341 free(line);
10342 pclose(f);
10343 return RETURN_OK;
10344}
10345
10346INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
10347{
developer7e4a2a62023-04-06 19:56:03 +080010348 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010349 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
10350
developer7e4a2a62023-04-06 19:56:03 +080010351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10352
developer72fb0bb2023-01-11 09:46:29 +080010353 if (NULL == output_string)
10354 return RETURN_ERR;
10355
10356 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10357 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +080010358
10359 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\\n'", interface_name);
developer72fb0bb2023-01-11 09:46:29 +080010360 _syscmd(cmd, buf, sizeof(buf));
10361
10362 //size of SSID name restricted to value less than 32 bytes
10363 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +080010364 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +080010365
10366 return RETURN_OK;
10367}
10368
10369INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
10370{
developer7e4a2a62023-04-06 19:56:03 +080010371 char cmd[MAX_CMD_SIZE] = {0};
10372 char buf[MAX_BUF_SIZE] = {0};
10373 char inf_name[IF_NAME_SIZE] = {0};
10374 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +080010375
10376 if (!output_filterMode)
10377 return RETURN_ERR;
10378
developer7e4a2a62023-04-06 19:56:03 +080010379 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10380 return RETURN_ERR;
10381
10382 /* mwctl get acl policy */
10383 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
10384 _syscmd(cmd, buf, sizeof(buf));
10385
10386
10387 policy = atoi(buf);
10388
10389 if (policy < 0 || policy > 2) {
10390 printf("%s:get wrong acl policy!!!\n", __func__);
10391 *output_filterMode = 0;
10392 return RETURN_ERR;
10393 } else
10394 *output_filterMode = policy;
10395
developer72fb0bb2023-01-11 09:46:29 +080010396
10397 return RETURN_OK;
10398}
10399
10400INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
10401{
10402 FILE *fp = NULL;
10403 char str[MAX_BUF_SIZE] = {0};
10404 int wificlientindex = 0 ;
10405 int count = 0;
10406 int signalstrength = 0;
10407 int arr[MACADDRESS_SIZE] = {0};
10408 unsigned char mac[MACADDRESS_SIZE] = {0};
10409 UINT wifi_count = 0;
10410 char virtual_interface_name[MAX_BUF_SIZE] = {0};
10411 char pipeCmd[MAX_CMD_SIZE] = {0};
10412
10413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10414 *output_array_size = 0;
10415 *associated_dev_array = NULL;
10416 char interface_name[50] = {0};
10417
10418 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
10419 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
10420 return RETURN_ERR;
10421 }
10422
10423 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
10424 fp = popen(pipeCmd, "r");
10425 if (fp == NULL)
10426 {
10427 printf("Failed to run command inside function %s\n",__FUNCTION__ );
10428 return RETURN_ERR;
10429 }
10430
10431 /* Read the output a line at a time - output it. */
10432 fgets(str, sizeof(str)-1, fp);
10433 wifi_count = (unsigned int) atoi ( str );
10434 *output_array_size = wifi_count;
10435 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
10436 pclose(fp);
10437
10438 if(wifi_count == 0)
10439 {
10440 return RETURN_OK;
10441 }
10442 else
10443 {
10444 wifi_associated_dev2_t* temp = NULL;
10445 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
10446 *associated_dev_array = temp;
10447 if(temp == NULL)
10448 {
10449 printf("Error Statement. Insufficient memory \n");
10450 return RETURN_ERR;
10451 }
10452
10453 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
10454 system(pipeCmd);
10455
10456 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
10457 if(fp == NULL)
10458 {
10459 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
10460 return RETURN_ERR;
10461 }
10462 fclose(fp);
10463
10464 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
10465 fp = popen(pipeCmd, "r");
10466 if(fp)
10467 {
10468 for(count =0 ; count < wifi_count; count++)
10469 {
10470 fgets(str, MAX_BUF_SIZE, fp);
10471 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
10472 {
10473 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
10474 {
10475 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
10476
10477 }
10478 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
10479 wifi_dbg_printf("MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
10480 }
10481 temp[count].cli_AuthenticationState = 1; //TODO
10482 temp[count].cli_Active = 1; //TODO
10483 }
10484 pclose(fp);
10485 }
10486
10487 //Updating RSSI per client
10488 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
10489 fp = popen(pipeCmd, "r");
10490 if(fp)
10491 {
10492 pclose(fp);
10493 }
10494 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
10495 if(fp)
10496 {
10497 for(count =0 ; count < wifi_count ;count++)
10498 {
10499 fgets(str, MAX_BUF_SIZE, fp);
10500 signalstrength = atoi(str);
10501 temp[count].cli_RSSI = signalstrength;
10502 }
10503 pclose(fp);
10504 }
10505
10506
10507 //LastDataDownlinkRate
10508 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
10509 fp = popen(pipeCmd, "r");
10510 if (fp)
10511 {
10512 pclose(fp);
10513 }
10514 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
10515 if (fp)
10516 {
10517 for (count = 0; count < wifi_count; count++)
10518 {
10519 fgets(str, MAX_BUF_SIZE, fp);
10520 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
10521 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
10522 }
10523 pclose(fp);
10524 }
10525
10526 //LastDataUplinkRate
10527 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
10528 fp = popen(pipeCmd, "r");
10529 if (fp)
10530 {
10531 pclose(fp);
10532 }
10533 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
10534 if (fp)
10535 {
10536 for (count = 0; count < wifi_count; count++)
10537 {
10538 fgets(str, MAX_BUF_SIZE, fp);
10539 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
10540 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
10541 }
10542 pclose(fp);
10543 }
10544 }
10545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10546 return RETURN_OK;
10547
10548}
10549
10550INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
10551{
10552#if 0
10553 /*char buf[1024] = {0};
10554 sprintf(cmd, "ifconfig %s ", interface_name);
10555 _syscmd(cmd, buf, sizeof(buf));*/
10556
10557 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
10558 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
10559 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
10560 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
10561
10562 output_struct->ssid_RetransCount = 0; //The total number of transmitted packets which were retransmissions. Two retransmissions of the same packet results in this counter incrementing by two.
10563 output_struct->ssid_FailedRetransCount = 0; //The number of packets that were not transmitted successfully due to the number of retransmission attempts exceeding an 802.11 retry limit. This parameter is based on dot11FailedCount from [802.11-2012].
10564 output_struct->ssid_RetryCount = 0; //The number of packets that were successfully transmitted after one or more retransmissions. This parameter is based on dot11RetryCount from [802.11-2012].
10565 output_struct->ssid_MultipleRetryCount = 0; //The number of packets that were successfully transmitted after more than one retransmission. This parameter is based on dot11MultipleRetryCount from [802.11-2012].
10566 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
10567 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
10568
10569 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
10570 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10571 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
10572 output_struct->ssid_UnicastPacketsReceived = 2; //The total number of received packets, delivered by this layer to a higher layer, which were not addressed to a multicast or broadcast address at this layer.
10573 output_struct->ssid_DiscardedPacketsSent = 1; //The total number of outbound packets which were chosen to be discarded even though no errors had been detected to prevent their being transmitted. One possible reason for discarding such a packet could be to free up buffer space.
10574 output_struct->ssid_DiscardedPacketsReceived = 1; //The total number of inbound packets which were chosen to be discarded even though no errors had been detected to prevent their being delivered. One possible reason for discarding such a packet could be to free up buffer space.
10575 output_struct->ssid_MulticastPacketsSent = 10; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a multicast address at this layer, including those that were discarded or not sent.
10576 output_struct->ssid_MulticastPacketsReceived = 0; //The total number of received packets, delivered by this layer to a higher layer, which were addressed to a multicast address at this layer.
10577 output_struct->ssid_BroadcastPacketsSent = 0; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a broadcast address at this layer, including those that were discarded or not sent.
10578 output_struct->ssid_BroadcastPacketsRecevied = 1; //The total number of packets that higher-level protocols requested for transmission and which were addressed to a broadcast address at this layer, including those that were discarded or not sent.
10579 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
10580#endif
10581
10582 FILE *fp = NULL;
10583 char interface_name[50] = {0};
10584 char pipeCmd[128] = {0};
10585 char str[256] = {0};
10586 wifi_ssidTrafficStats2_t *out = output_struct;
10587
10588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
10589 if (!output_struct)
10590 return RETURN_ERR;
10591
10592 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
10593 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
10594 return RETURN_ERR;
10595 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
10596
10597 fp = popen(pipeCmd, "r");
10598 if (fp == NULL) {
10599 fprintf(stderr, "%s: popen failed\n", __func__);
10600 return RETURN_ERR;
10601 }
10602 fgets(str, sizeof(str), fp);
10603 pclose(fp);
10604
10605 if (strlen(str) == 0) // interface not exist
10606 return RETURN_OK;
10607
10608 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
10609 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
10610
10611 memset(str, 0, sizeof(str));
10612 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
10613 fp = popen(pipeCmd, "r");
10614 if (fp == NULL) {
10615 fprintf(stderr, "%s: popen failed\n", __func__);
10616 return RETURN_ERR;
10617 }
10618 fgets(str, sizeof(str), fp);
10619
10620 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
10621 &out->ssid_BroadcastPacketsSent);
10622 pclose(fp);
10623
10624 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
10625 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
10626
10627 // Not supported
10628 output_struct->ssid_RetransCount = 0;
10629 output_struct->ssid_FailedRetransCount = 0;
10630 output_struct->ssid_RetryCount = 0;
10631 output_struct->ssid_MultipleRetryCount = 0;
10632 output_struct->ssid_ACKFailureCount = 0;
10633 output_struct->ssid_AggregatedPacketCount = 0;
10634
10635 return RETURN_OK;
10636}
10637
10638//Enables or disables device isolation. A value of true means that the devices connected to the Access Point are isolated from all other devices within the home network (as is typically the case for a Wireless Hotspot).
10639INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
10640{
10641 char output_val[16]={'\0'};
10642 char config_file[MAX_BUF_SIZE] = {0};
10643
10644 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10645 if (!output)
10646 return RETURN_ERR;
10647 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10648 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
10649
10650 if( strcmp(output_val,"1") == 0 )
10651 *output = TRUE;
10652 else
10653 *output = FALSE;
10654 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10655
10656 return RETURN_OK;
10657}
10658
10659INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
10660{
10661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10662 char str[MAX_BUF_SIZE]={'\0'};
10663 char string[MAX_BUF_SIZE]={'\0'};
10664 char cmd[MAX_CMD_SIZE]={'\0'};
10665 char *ch;
10666 char config_file[MAX_BUF_SIZE] = {0};
10667 struct params params;
10668
10669 if(enable == TRUE)
10670 strcpy(string,"1");
10671 else
10672 strcpy(string,"0");
10673
10674 params.name = "ap_isolate";
10675 params.value = string;
10676
10677 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10678 wifi_hostapdWrite(config_file,&params,1);
10679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10680
10681 return RETURN_OK;
10682}
10683
10684INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
10685{
developera1255e42023-05-13 17:45:02 +080010686 char mgmtpwr_file[32] = {0};
10687 char cmd[64] = {0};
10688 char buf[32]={0};
10689
developer72fb0bb2023-01-11 09:46:29 +080010690 if (NULL == output_dBm)
10691 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080010692 snprintf(mgmtpwr_file, sizeof(mgmtpwr_file), "%s%d.txt", MGMT_POWER_CTRL, apIndex);
10693 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mgmtpwr_file);
10694 _syscmd(cmd, buf, sizeof(buf));
10695 if (strlen(buf) > 0)
10696 *output_dBm = strtol(buf, NULL, 10);
10697 else
10698 *output_dBm = 23;
developer72fb0bb2023-01-11 09:46:29 +080010699 return RETURN_OK;
10700}
10701
10702INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
10703{
developera1255e42023-05-13 17:45:02 +080010704 char interface_name[16] = {0};
10705 char cmd[128]={0};
10706 char buf[128]={0};
10707 char mgmt_pwr_file[128]={0};
10708 FILE *f = NULL;
10709
10710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10711
10712 if (wifi_GetInterfaceName(wlanIndex, interface_name) != RETURN_OK)
10713 return RETURN_ERR;
10714 snprintf(cmd, sizeof(cmd), "mwctl dev %s set pwr mgmt_frame_pwr=%d", interface_name, dBm);
10715 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR) {
10716 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10717 return RETURN_ERR;
10718 }
10719 snprintf(mgmt_pwr_file, sizeof(mgmt_pwr_file), "%s%d.txt", MGMT_POWER_CTRL, wlanIndex);
10720 f = fopen(mgmt_pwr_file, "w");
10721 if (f == NULL) {
10722 fprintf(stderr, "%s: fopen failed\n", __func__);
10723 return RETURN_ERR;
10724 }
10725 fprintf(f, "%d", dBm);
10726 fclose(f);
developer72fb0bb2023-01-11 09:46:29 +080010727 return RETURN_OK;
10728}
10729INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
10730{
10731 return RETURN_OK;
10732}
10733INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
10734{
10735 return RETURN_OK;
10736}
10737INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
10738{
10739 return RETURN_OK;
10740}
10741INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
10742{
10743 return RETURN_OK;
10744}
10745INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
10746{
10747 char config_file[MAX_BUF_SIZE] = {0};
10748 struct params list;
10749
10750 list.name = "bss_transition";
10751 list.value = activate?"1":"0";
10752 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
10753 wifi_hostapdWrite(config_file, &list, 1);
10754
10755 return RETURN_OK;
10756}
10757wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
10758
10759void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
10760{
10761 return;
10762}
10763
10764INT wifi_setApCsaDeauth(INT apIndex, INT mode)
10765{
10766 // TODO Implement me!
10767 return RETURN_OK;
10768}
10769
10770INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
10771{
10772 char file_name[128] = {0};
10773 char buf[128] = {0};
10774 FILE *f = NULL;
10775 int max_num_radios = 0;
10776
10777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10778
10779 wifi_getMaxRadioNumber(&max_num_radios);
10780 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
10781 for (int index = 0; index < max_num_radios; index++) {
10782 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
10783 f = fopen(file_name, "w");
10784 if (f == NULL)
10785 return RETURN_ERR;
10786 // For mode == 0 is to disable filter, just don't write to the file.
10787 if (mode)
10788 fprintf(f, "%s", essid);
10789
10790 fclose(f);
10791 }
10792 } else { // special case, need to set AP's SSID as filter for each radio.
10793 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
10794 f = fopen(file_name, "w");
10795 if (f == NULL)
10796 return RETURN_ERR;
10797
10798 // For mode == 0 is to disable filter, just don't write to the file.
10799 if (mode)
10800 fprintf(f, "%s", essid);
10801
10802 fclose(f);
10803 }
10804
10805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10806 return RETURN_OK;
10807}
10808
10809INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
10810{
10811 // TODO Implement me!
10812 //Apply wifi_pushRadioChannel() instantly
10813 return RETURN_ERR;
10814}
10815
10816INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
10817{
10818 // TODO Implement me!
10819 return RETURN_OK;
10820}
10821
10822#ifdef HAL_NETLINK_IMPL
10823static int tidStats_callback(struct nl_msg *msg, void *arg) {
10824 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10825 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10826 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10827 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
10828 int rem , tid_index = 0;
10829
10830 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
10831 wifi_associated_dev_tid_entry_t *stats_entry;
10832
10833 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
10834 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
10835 };
10836 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
10837 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
10838 };
10839
10840 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
10841 genlmsg_attrlen(gnlh, 0), NULL);
10842
10843
10844 if (!tb[NL80211_ATTR_STA_INFO]) {
10845 fprintf(stderr, "station stats missing!\n");
10846 return NL_SKIP;
10847 }
10848
10849 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
10850 tb[NL80211_ATTR_STA_INFO],
10851 stats_policy)) {
10852 fprintf(stderr, "failed to parse nested attributes!\n");
10853 return NL_SKIP;
10854 }
10855
developer386281b2023-05-20 15:43:13 +080010856 if (sinfo[NL80211_STA_INFO_TID_STATS]) {
10857 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
10858 {
10859 stats_entry = &out->tid_array[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080010860
developer386281b2023-05-20 15:43:13 +080010861 stats_entry->tid = tid_index;
10862 stats_entry->ac = _tid_ac_index_get[tid_index];
developer72fb0bb2023-01-11 09:46:29 +080010863
developer386281b2023-05-20 15:43:13 +080010864 if(sinfo[NL80211_STA_INFO_TID_STATS])
10865 {
10866 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
10867 printf("failed to parse nested stats attributes!");
10868 return NL_SKIP;
10869 }
developer72fb0bb2023-01-11 09:46:29 +080010870 }
developer386281b2023-05-20 15:43:13 +080010871 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10872 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
developer72fb0bb2023-01-11 09:46:29 +080010873
developer386281b2023-05-20 15:43:13 +080010874 if(tid_index < (PS_MAX_TID - 1))
10875 tid_index++;
10876 }
developer72fb0bb2023-01-11 09:46:29 +080010877 }
10878 //ToDo: sum_time_ms, ewma_time_ms
10879 return NL_SKIP;
10880}
10881#endif
10882
10883INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
10884{
10885#ifdef HAL_NETLINK_IMPL
10886 Netlink nl;
10887 char if_name[10];
10888 char interface_name[16] = {0};
10889
10890 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10891 return RETURN_ERR;
10892
10893 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10894
10895 nl.id = initSock80211(&nl);
10896
10897 if (nl.id < 0) {
10898 fprintf(stderr, "Error initializing netlink \n");
10899 return -1;
10900 }
10901
10902 struct nl_msg* msg = nlmsg_alloc();
10903
10904 if (!msg) {
10905 fprintf(stderr, "Failed to allocate netlink message.\n");
10906 nlfree(&nl);
10907 return -2;
10908 }
10909
10910 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080010911 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080010912 NL_AUTO_SEQ,
10913 nl.id,
10914 0,
10915 0,
10916 NL80211_CMD_GET_STATION,
10917 0);
10918
10919 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10920 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10921 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
developer8dd72532023-05-17 19:58:35 +080010922 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080010923 nl_recvmsgs(nl.socket, nl.cb);
10924 nlmsg_free(msg);
10925 nlfree(&nl);
10926 return RETURN_OK;
10927#else
10928//iw implementation
10929#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
10930#define TOTAL_MAX_LINES 50
10931
10932 char buf[256] = {'\0'}; /* or other suitable maximum line size */
10933 char if_name[32] = {0};
10934 FILE *fp=NULL;
10935 char pipeCmd[1024]= {'\0'};
10936 int lines,tid_index=0;
10937 char mac_addr[20] = {'\0'};
10938
10939 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10940 return RETURN_ERR;
10941
10942 wifi_associated_dev_tid_entry_t *stats_entry;
10943
10944 strcpy(mac_addr,clientMacAddress);
10945
10946 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
10947 fp= popen(pipeCmd,"r");
10948 if(fp == NULL)
10949 {
10950 perror("popen for station dump failed\n");
10951 return RETURN_ERR;
10952 }
10953 pclose(fp);
10954
10955 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
10956 fp=popen(pipeCmd,"r");
10957 if(fp == NULL)
10958 {
10959 perror("popen for grep station failed\n");
10960 return RETURN_ERR;
10961 }
10962 else if(fgets(buf,sizeof(buf),fp) != NULL)
10963 lines=atoi(buf);
10964 else
10965 {
10966 pclose(fp);
10967 fprintf(stderr,"No devices are connected \n");
10968 return RETURN_ERR;
10969 }
10970 pclose(fp);
10971
10972 if(lines == 1)
10973 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10974
10975 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10976 {
10977 stats_entry = &tid_stats->tid_array[tid_index];
10978 stats_entry->tid = tid_index;
10979
10980 snprintf(pipeCmd, sizeof(pipeCmd),"cat "TID_STATS_FILE" | awk '/%s/ {for(i=0; i<=%d; i++) {getline; print}}' | grep -F -A%d 'MSDU' | awk '{print $3}' | tail -1",mac_addr,lines,tid_index+2);
10981
10982 fp=popen(pipeCmd,"r");
10983 if(fp ==NULL)
10984 {
10985 perror("Failed to read from tid file \n");
10986 return RETURN_ERR;
10987 }
10988 else if(fgets(buf,sizeof(buf),fp) != NULL)
10989 stats_entry->num_msdus = atol(buf);
10990
10991 pclose(fp);
10992 stats_entry->ac = _tid_ac_index_get[tid_index];
10993// TODO:
10994// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10995// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10996 }
10997 return RETURN_OK;
10998#endif
10999}
11000
11001
11002INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
11003{
11004 char interface_name[16] = {0};
11005 char cmd[128]={0};
11006 char buf[128]={0};
11007 int freq = 0;
11008
11009 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11010
11011 // full mode is used to scan all channels.
11012 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
11013 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
11014 ieee80211_channel_to_frequency(chan_list[0], &freq);
11015
11016 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11017 return RETURN_ERR;
11018
11019 if (freq)
11020 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
11021 else
11022 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
11023
11024 _syscmd(cmd, buf, sizeof(buf));
11025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11026
11027 return RETURN_OK;
11028}
11029
11030
11031INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
11032{
11033 // TODO Implement me!
11034 return RETURN_ERR;
11035}
11036
11037INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
11038{
11039 // TODO Implement me!
11040 return RETURN_ERR;
11041}
11042
11043INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
11044{
11045 // TODO Implement me!
11046 return RETURN_ERR;
11047}
11048
11049INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
11050{
11051 // TODO Implement me!
11052 return RETURN_ERR;
11053}
11054
11055INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
11056{
11057 // TODO Implement me!
11058 return RETURN_ERR;
11059}
11060
11061INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
11062{
11063 // TODO Implement me!
11064 return RETURN_ERR;
11065}
11066
11067INT wifi_steering_eventUnregister(void)
11068{
11069 // TODO Implement me!
11070 return RETURN_ERR;
11071}
11072
11073INT wifi_delApAclDevices(INT apIndex)
11074{
developer7e4a2a62023-04-06 19:56:03 +080011075 char cmd[MAX_CMD_SIZE] = {0};
11076 char buf[MAX_BUF_SIZE] = {0};
11077 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080011078
developer7e4a2a62023-04-06 19:56:03 +080011079 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
11080 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080011081
developer7e4a2a62023-04-06 19:56:03 +080011082 /* mwctl acl clear all stas */
11083 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
11084 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080011085
11086 return RETURN_OK;
11087}
11088
11089#ifdef HAL_NETLINK_IMPL
11090static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
11091 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11092 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11093 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11094 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
11095 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
11096 char mac_addr[20],dev[20];
11097
11098 nla_parse(tb,
11099 NL80211_ATTR_MAX,
11100 genlmsg_attrdata(gnlh, 0),
11101 genlmsg_attrlen(gnlh, 0),
11102 NULL);
11103
11104 if(!tb[NL80211_ATTR_STA_INFO]) {
11105 fprintf(stderr, "sta stats missing!\n");
11106 return NL_SKIP;
11107 }
11108
11109 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
11110 fprintf(stderr, "failed to parse nested attributes!\n");
11111 return NL_SKIP;
11112 }
11113 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
11114
11115 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11116
developer386281b2023-05-20 15:43:13 +080011117 if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
11118 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
11119 fprintf(stderr, "failed to parse nested rate attributes!");
11120 return NL_SKIP;
11121 }
developer72fb0bb2023-01-11 09:46:29 +080011122 }
11123
11124 if(sinfo[NL80211_STA_INFO_TID_STATS])
11125 {
11126 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
11127 printf("failed to parse nested stats attributes!");
11128 return NL_SKIP;
11129 }
11130 }
11131
11132 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
11133 {
11134 printf("Type is VHT\n");
11135 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
11136 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
11137
11138 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
11139 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
11140 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
11141 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11142 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
11143 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11144 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
11145 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
11146 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
11147 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
11148 }
11149 else
11150 {
11151 printf(" OFDM or CCK \n");
11152 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
11153 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
11154 }
11155
11156 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
11157 if(rinfo[NL80211_RATE_INFO_MCS])
11158 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
11159 }
11160 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
11161 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
11162 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
11163 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
11164
11165 if(stats_info[NL80211_TID_STATS_RX_MSDU])
11166 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
11167
11168 if (sinfo[NL80211_STA_INFO_SIGNAL])
11169 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
11170 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
11171 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
11172 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
11173 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
11174 //rssi_array need to be filled
11175 return NL_SKIP;
11176}
11177#endif
11178
11179INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
11180{
11181#ifdef HAL_NETLINK_IMPL
11182 Netlink nl;
11183 char if_name[32];
11184 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11185 return RETURN_ERR;
11186
11187 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
11188
11189 if (*output_array_size <= 0)
11190 return RETURN_OK;
11191
11192 nl.id = initSock80211(&nl);
11193
11194 if (nl.id < 0) {
11195 fprintf(stderr, "Error initializing netlink \n");
11196 return 0;
11197 }
11198
11199 struct nl_msg* msg = nlmsg_alloc();
11200
11201 if (!msg) {
11202 fprintf(stderr, "Failed to allocate netlink message.\n");
11203 nlfree(&nl);
11204 return 0;
11205 }
11206
11207 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011208 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011209 NL_AUTO_SEQ,
11210 nl.id,
11211 0,
11212 0,
11213 NL80211_CMD_GET_STATION,
11214 0);
11215
11216 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
11217 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11218 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080011219 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011220 nl_recvmsgs(nl.socket, nl.cb);
11221 nlmsg_free(msg);
11222 nlfree(&nl);
11223 return RETURN_OK;
11224#else
11225 //TODO Implement me
11226 return RETURN_OK;
11227#endif
11228}
11229
11230#ifdef HAL_NETLINK_IMPL
11231static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
11232 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11233 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11234 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
11235 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
11236 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
11237 char mac_addr[20],dev[20];
11238
11239 nla_parse(tb,
11240 NL80211_ATTR_MAX,
11241 genlmsg_attrdata(gnlh, 0),
11242 genlmsg_attrlen(gnlh, 0),
11243 NULL);
11244
11245 if(!tb[NL80211_ATTR_STA_INFO]) {
11246 fprintf(stderr, "sta stats missing!\n");
11247 return NL_SKIP;
11248 }
11249
11250 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
11251 fprintf(stderr, "failed to parse nested attributes!\n");
11252 return NL_SKIP;
11253 }
11254
11255 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
11256
11257 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11258
developer386281b2023-05-20 15:43:13 +080011259 if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
11260 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
11261 fprintf(stderr, "failed to parse nested rate attributes!");
11262 return NL_SKIP;
11263 }
developer72fb0bb2023-01-11 09:46:29 +080011264 }
11265
11266 if(sinfo[NL80211_STA_INFO_TID_STATS])
11267 {
11268 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
11269 printf("failed to parse nested stats attributes!");
11270 return NL_SKIP;
11271 }
11272 }
11273 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
11274 {
11275 printf("Type is VHT\n");
11276 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
11277 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
11278
11279 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
11280 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
11281 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
11282 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11283 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
11284 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11285 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
11286 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
11287 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
11288 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11289 }
11290 else
11291 {
11292 printf(" OFDM or CCK \n");
11293 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
11294 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
11295 }
11296
11297 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
11298 if(rinfo[NL80211_RATE_INFO_MCS])
11299 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
11300 }
11301
11302 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
11303 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
11304 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
11305 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
11306
11307 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
11308 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11309 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
11310
11311 if(stats_info[NL80211_TID_STATS_TX_MSDU])
11312 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
11313
11314 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
11315 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
11316
11317 if(sinfo[NL80211_STA_INFO_TX_FAILED])
11318 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->attempts = nla_get_u32(sinfo[NL80211_STA_INFO_TX_PACKETS]) + nla_get_u32(sinfo[NL80211_STA_INFO_TX_FAILED]);
11319
11320 return NL_SKIP;
11321}
11322#endif
11323
11324INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
11325{
11326#ifdef HAL_NETLINK_IMPL
11327 Netlink nl;
11328 char if_name[10];
11329 char interface_name[16] = {0};
11330 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
11331 return RETURN_ERR;
11332
11333 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
11334
11335 if (*output_array_size <= 0)
11336 return RETURN_OK;
11337
11338 snprintf(if_name, sizeof(if_name), "%s", interface_name);
11339
11340 nl.id = initSock80211(&nl);
11341
11342 if(nl.id < 0) {
11343 fprintf(stderr, "Error initializing netlink \n");
11344 return 0;
11345 }
11346
11347 struct nl_msg* msg = nlmsg_alloc();
11348
11349 if(!msg) {
11350 fprintf(stderr, "Failed to allocate netlink message.\n");
11351 nlfree(&nl);
11352 return 0;
11353 }
11354
11355 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011356 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011357 NL_AUTO_SEQ,
11358 nl.id,
11359 0,
11360 0,
11361 NL80211_CMD_GET_STATION,
11362 0);
11363
11364 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
11365 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
11366 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
developer8dd72532023-05-17 19:58:35 +080011367 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011368 nl_recvmsgs(nl.socket, nl.cb);
11369 nlmsg_free(msg);
11370 nlfree(&nl);
11371 return RETURN_OK;
11372#else
11373 //TODO Implement me
11374 return RETURN_OK;
11375#endif
11376}
11377
11378INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
11379{
11380 // TODO Implement me!
11381 char buf[MAX_BUF_SIZE] = {0};
11382 char config_file[MAX_BUF_SIZE] = {0};
11383
11384 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
11385 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
11386 *activate = (strncmp("1",buf,1) == 0);
11387
11388 return RETURN_OK;
11389}
11390
11391INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
11392{
11393 char config_file[MAX_BUF_SIZE] = {0};
11394 struct params list;
11395
11396 list.name = "rrm_neighbor_report";
11397 list.value = activate?"1":"0";
11398 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11399 wifi_hostapdWrite(config_file, &list, 1);
11400
11401 return RETURN_OK;
11402}
11403
11404INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
11405{
11406 char buf[32] = {0};
11407 char config_file[MAX_BUF_SIZE] = {0};
11408
11409 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
11410 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
11411 *activate = (strncmp("1",buf,1) == 0);
11412
11413 return RETURN_OK;
11414}
11415#undef HAL_NETLINK_IMPL
11416#ifdef HAL_NETLINK_IMPL
11417static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
11418 struct nlattr *tb[NL80211_ATTR_MAX + 1];
11419 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
11420 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
11421 char dev[20];
11422 int freq =0 ;
11423 static int i=0;
11424
11425 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
11426
11427 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
11428 };
11429
11430 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
11431
11432 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
11433
11434 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
11435 fprintf(stderr, "survey data missing!\n");
11436 return NL_SKIP;
11437 }
11438
11439 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
11440 {
11441 fprintf(stderr, "failed to parse nested attributes!\n");
11442 return NL_SKIP;
11443 }
11444
11445
11446 if(out[0].array_size == 1 )
11447 {
11448 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
11449 {
11450 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11451 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11452 out[0].ch_number = ieee80211_frequency_to_channel(freq);
11453
11454 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11455 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11456 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11457 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11458 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11459 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11460 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11461 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11462 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11463 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11464 if (sinfo[NL80211_SURVEY_INFO_TIME])
11465 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11466 return NL_STOP;
11467 }
11468 }
11469 else
11470 {
11471 if ( i <= out[0].array_size )
11472 {
11473 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
11474 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
11475 out[i].ch_number = ieee80211_frequency_to_channel(freq);
11476
11477 if (sinfo[NL80211_SURVEY_INFO_NOISE])
11478 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
11479 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
11480 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
11481 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
11482 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
11483 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
11484 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
11485 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
11486 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
11487 if (sinfo[NL80211_SURVEY_INFO_TIME])
11488 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
11489 }
11490 }
11491
11492 i++;
11493 return NL_SKIP;
11494}
11495#endif
11496
11497static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
11498{
11499 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
11500 FILE *fp;
11501
11502 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
11503 {
11504 printf("Creating Frequency-Channel Map\n");
11505 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
11506 }
11507 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
11508 if((fp = popen(command, "r")))
11509 {
11510 fgets(output, sizeof(output), fp);
11511 *freqMHz = atoi(output);
11512 pclose(fp);
11513 }
11514
11515 return 0;
11516}
11517
11518static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
11519{
11520 int freqMHz = -1;
11521 char cmd[MAX_CMD_SIZE] = {'\0'};
11522 char interface_name[16] = {0};
11523
11524 ieee80211_channel_to_frequency(channel, &freqMHz);
11525 if (freqMHz == -1) {
11526 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
11527 return -1;
11528 }
11529
11530 wifi_GetInterfaceName(radioIndex, interface_name);
11531 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
11532 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
11533 radioIndex, freqMHz);
11534 return -1;
11535 }
11536
11537 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
11538 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
11539 return -1;
11540 }
11541
11542 return 0;
11543}
11544
11545static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
11546{
11547 const char *ptr = buf;
11548 char *key = NULL;
11549 char *val = NULL;
11550 char line[256] = { '\0' };
11551
11552 while (ptr = get_line_from_str_buf(ptr, line)) {
11553 if (strstr(line, "Frequency")) continue;
11554
11555 key = strtok(line, ":");
11556 val = strtok(NULL, " ");
11557 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
11558
11559 if (!strcmp(key, "noise")) {
11560 sscanf(val, "%d", &stats->ch_noise);
11561 if (stats->ch_noise == 0) {
11562 // Workaround for missing noise information.
11563 // Assume -95 for 2.4G and -103 for 5G
11564 if (radioIndex == 0) stats->ch_noise = -95;
11565 if (radioIndex == 1) stats->ch_noise = -103;
11566 }
11567 }
11568 else if (!strcmp(key, "channel active time")) {
11569 sscanf(val, "%llu", &stats->ch_utilization_total);
11570 }
11571 else if (!strcmp(key, "channel busy time")) {
11572 sscanf(val, "%llu", &stats->ch_utilization_busy);
11573 }
11574 else if (!strcmp(key, "channel receive time")) {
11575 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
11576 }
11577 else if (!strcmp(key, "channel transmit time")) {
11578 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
11579 }
11580 };
11581
11582 return 0;
11583}
11584
11585INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
11586{
11587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11588#ifdef HAL_NETLINK_IMPL
11589 Netlink nl;
11590 wifi_channelStats_t_loc local[array_size];
11591 char if_name[32];
11592
11593 local[0].array_size = array_size;
11594
11595 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
11596 return RETURN_ERR;
11597
11598 nl.id = initSock80211(&nl);
11599
11600 if (nl.id < 0) {
11601 fprintf(stderr, "Error initializing netlink \n");
11602 return -1;
11603 }
11604
11605 struct nl_msg* msg = nlmsg_alloc();
11606
11607 if (!msg) {
11608 fprintf(stderr, "Failed to allocate netlink message.\n");
11609 nlfree(&nl);
11610 return -2;
11611 }
11612
11613 genlmsg_put(msg,
developer8dd72532023-05-17 19:58:35 +080011614 NL_AUTO_PID,
developer72fb0bb2023-01-11 09:46:29 +080011615 NL_AUTO_SEQ,
11616 nl.id,
11617 0,
11618 NLM_F_DUMP,
11619 NL80211_CMD_GET_SURVEY,
11620 0);
11621
11622 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
developer8dd72532023-05-17 19:58:35 +080011623 nl_send_auto_complete(nl.socket, msg);
developer72fb0bb2023-01-11 09:46:29 +080011624 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
11625 nl_recvmsgs(nl.socket, nl.cb);
11626 nlmsg_free(msg);
11627 nlfree(&nl);
11628 //Copying the Values
11629 for(int i=0;i<array_size;i++)
11630 {
11631 input_output_channelStats_array[i].ch_number = local[i].ch_number;
11632 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
11633 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
11634 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
11635 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
11636 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
11637 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
11638 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
11639 }
11640#else
11641 ULONG channel = 0;
11642 int i;
11643 int number_of_channels = array_size;
11644 char buf[512];
11645 INT ret;
11646 wifi_channelStats_t tmp_stats;
11647
11648 if (number_of_channels == 0) {
11649 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
11650 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
11651 return RETURN_ERR;
11652 }
11653 number_of_channels = 1;
11654 input_output_channelStats_array[0].ch_number = channel;
11655 }
11656
11657 for (i = 0; i < number_of_channels; i++) {
11658
11659 input_output_channelStats_array[i].ch_noise = 0;
11660 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
11661 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
11662 input_output_channelStats_array[i].ch_utilization_busy = 0;
11663 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
11664 input_output_channelStats_array[i].ch_utilization_total = 0;
11665
11666 memset(buf, 0, sizeof(buf));
11667 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
11668 return RETURN_ERR;
11669 }
11670 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
11671 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
11672 return RETURN_ERR;
11673 }
11674
11675 // XXX: fake missing 'self' counter which is not available in iw survey output
11676 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
11677 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
11678
11679 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
11680 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
11681 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
11682 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
11683 input_output_channelStats_array[i].ch_utilization_total *= 1000;
11684
11685 wifi_dbg_printf("%s: ch_number=%d ch_noise=%d total=%llu busy=%llu busy_rx=%llu busy_tx=%llu busy_self=%llu busy_ext=%llu\n",
11686 __func__,
11687 input_output_channelStats_array[i].ch_number,
11688 input_output_channelStats_array[i].ch_noise,
11689 input_output_channelStats_array[i].ch_utilization_total,
11690 input_output_channelStats_array[i].ch_utilization_busy,
11691 input_output_channelStats_array[i].ch_utilization_busy_rx,
11692 input_output_channelStats_array[i].ch_utilization_busy_tx,
11693 input_output_channelStats_array[i].ch_utilization_busy_self,
11694 input_output_channelStats_array[i].ch_utilization_busy_ext);
11695 }
11696#endif
11697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11698 return RETURN_OK;
11699}
11700#define HAL_NETLINK_IMPL
11701
11702/* Hostapd events */
11703
11704#ifndef container_of
11705#define offset_of(st, m) ((size_t)&(((st *)0)->m))
11706#define container_of(ptr, type, member) \
11707 ((type *)((char *)ptr - offset_of(type, member)))
11708#endif /* container_of */
11709
11710struct ctrl {
11711 char sockpath[128];
11712 char sockdir[128];
11713 char bss[IFNAMSIZ];
11714 char reply[4096];
11715 int ssid_index;
11716 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
11717 void (*overrun)(struct ctrl *ctrl);
11718 struct wpa_ctrl *wpa;
11719 unsigned int ovfl;
11720 size_t reply_len;
11721 int initialized;
11722 ev_timer retry;
11723 ev_timer watchdog;
11724 ev_stat stat;
11725 ev_io io;
11726};
11727static wifi_newApAssociatedDevice_callback clients_connect_cb;
11728static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
11729static struct ctrl wpa_ctrl[MAX_APS];
11730static int initialized;
11731
11732static unsigned int ctrl_get_drops(struct ctrl *ctrl)
11733{
11734 char cbuf[256] = {};
11735 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
11736 struct cmsghdr *cmsg;
11737 unsigned int ovfl = ctrl->ovfl;
11738 unsigned int drop;
11739
11740 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
11741 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
11742 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
11743 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
11744
11745 drop = ovfl - ctrl->ovfl;
11746 ctrl->ovfl = ovfl;
11747
11748 return drop;
11749}
11750
11751static void ctrl_close(struct ctrl *ctrl)
11752{
11753 if (ctrl->io.cb)
11754 ev_io_stop(EV_DEFAULT_ &ctrl->io);
11755 if (ctrl->retry.cb)
11756 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11757 if (!ctrl->wpa)
11758 return;
11759
11760 wpa_ctrl_detach(ctrl->wpa);
11761 wpa_ctrl_close(ctrl->wpa);
11762 ctrl->wpa = NULL;
11763 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
11764}
11765
11766static void ctrl_process(struct ctrl *ctrl)
11767{
11768 const char *str;
11769 int drops;
11770 int level;
11771 int err;
11772
11773 /* Example events:
11774 *
11775 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
11776 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
11777 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
11778 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
11779 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
11780 */
11781 if (!(str = index(ctrl->reply, '>')))
11782 return;
11783 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
11784 return;
11785
11786 str++;
11787
11788 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
11789 if (!(str = index(ctrl->reply, ' ')))
11790 return;
11791 wifi_associated_dev_t sta;
11792 memset(&sta, 0, sizeof(sta));
11793
11794 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11795 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
11796 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
11797
11798 sta.cli_Active=true;
11799
11800 (clients_connect_cb)(ctrl->ssid_index, &sta);
11801 goto handled;
11802 }
11803
11804 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
11805 if (!(str = index(ctrl->reply, ' ')))
11806 return;
11807
11808 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
11809 goto handled;
11810 }
11811
11812 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
11813 printf("CTRL_WPA: handle TERMINATING event\n");
11814 goto retry;
11815 }
11816
11817 if (strncmp("AP-DISABLED", str, 11) == 0) {
11818 printf("CTRL_WPA: handle AP-DISABLED\n");
11819 goto retry;
11820 }
11821
11822 printf("Event not supported!!\n");
11823
11824handled:
11825
11826 if ((drops = ctrl_get_drops(ctrl))) {
11827 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
11828 if (ctrl->overrun)
11829 ctrl->overrun(ctrl);
11830 }
11831
11832 return;
11833
11834retry:
11835 printf("WPA_CTRL: closing\n");
11836 ctrl_close(ctrl);
11837 printf("WPA_CTRL: retrying from ctrl prcoess\n");
11838 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
11839}
11840
11841static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
11842{
11843 struct ctrl *ctrl = container_of(io, struct ctrl, io);
11844 int err;
11845
11846 memset(ctrl->reply, 0, sizeof(ctrl->reply));
11847 ctrl->reply_len = sizeof(ctrl->reply) - 1;
11848 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
11849 ctrl->reply[ctrl->reply_len] = 0;
11850 if (err < 0) {
11851 if (errno == EAGAIN || errno == EWOULDBLOCK)
11852 return;
11853 ctrl_close(ctrl);
11854 ev_timer_again(EV_A_ &ctrl->retry);
11855 return;
11856 }
11857
11858 ctrl_process(ctrl);
11859}
11860
11861static int ctrl_open(struct ctrl *ctrl)
11862{
11863 int fd;
11864
11865 if (ctrl->wpa)
11866 return 0;
11867
11868 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
11869 if (!ctrl->wpa)
11870 goto err;
11871
11872 if (wpa_ctrl_attach(ctrl->wpa) < 0)
11873 goto err_close;
11874
11875 fd = wpa_ctrl_get_fd(ctrl->wpa);
11876 if (fd < 0)
11877 goto err_detach;
11878
11879 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
11880 goto err_detach;
11881
11882 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
11883 ev_io_start(EV_DEFAULT_ &ctrl->io);
11884
11885 return 0;
11886
11887err_detach:
11888 wpa_ctrl_detach(ctrl->wpa);
11889err_close:
11890 wpa_ctrl_close(ctrl->wpa);
11891err:
11892 ctrl->wpa = NULL;
11893 return -1;
11894}
11895
11896static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
11897{
11898 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
11899
11900 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
11901 ctrl_open(ctrl);
11902}
11903
11904static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
11905{
11906 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
11907
11908 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
11909 if (ctrl_open(ctrl) == 0) {
11910 printf("WPA_CTRL: retry successful\n");
11911 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
11912 }
11913}
11914
11915int ctrl_enable(struct ctrl *ctrl)
11916{
11917 if (ctrl->wpa)
11918 return 0;
11919
11920 if (!ctrl->stat.cb) {
11921 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
11922 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
11923 }
11924
11925 if (!ctrl->retry.cb) {
11926 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
11927 }
11928
11929 return ctrl_open(ctrl);
11930}
11931
11932static void
11933ctrl_msg_cb(char *buf, size_t len)
11934{
11935 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
11936
11937 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
11938 ctrl_process(ctrl);
11939}
11940
11941static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
11942{
11943 int err;
11944
11945 if (!ctrl->wpa)
11946 return -1;
11947 if (*reply_len < 2)
11948 return -1;
11949
11950 (*reply_len)--;
11951 ctrl->reply_len = sizeof(ctrl->reply);
11952 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
11953 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
11954 if (err < 0)
11955 return err;
11956
11957 if (ctrl->reply_len > *reply_len)
11958 ctrl->reply_len = *reply_len;
11959
11960 *reply_len = ctrl->reply_len;
11961 memcpy(reply, ctrl->reply, *reply_len);
11962 reply[*reply_len - 1] = 0;
11963 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11964 return 0;
11965}
11966
11967static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11968{
11969 const char *pong = "PONG";
11970 const char *ping = "PING";
11971 char reply[1024];
11972 size_t len = sizeof(reply);
11973 int err;
11974 ULONG s, snum;
11975 INT ret;
11976 BOOL status;
11977
11978 printf("WPA_CTRL: watchdog cb\n");
11979
11980 ret = wifi_getSSIDNumberOfEntries(&snum);
11981 if (ret != RETURN_OK) {
11982 printf("%s: failed to get SSID count", __func__);
11983 return;
11984 }
11985
11986 if (snum > MAX_APS) {
11987 printf("more ssid than supported! %lu\n", snum);
11988 return;
11989 }
11990
11991 for (s = 0; s < snum; s++) {
11992 if (wifi_getApEnable(s, &status) != RETURN_OK) {
11993 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
11994 continue;
11995 }
11996 if (status == false) continue;
11997
11998 memset(reply, 0, sizeof(reply));
11999 len = sizeof(reply);
12000 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
12001 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
12002 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
12003 continue;
12004
12005 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
12006 ctrl_close(&wpa_ctrl[s]);
12007 printf("WPA_CTRL: ev_timer_again %lu\n", s);
12008 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
12009 }
12010}
12011
12012static int init_wpa()
12013{
12014 int ret = 0, i = 0;
12015 ULONG s, snum;
12016
12017 ret = wifi_getSSIDNumberOfEntries(&snum);
12018 if (ret != RETURN_OK) {
12019 printf("%s: failed to get SSID count", __func__);
12020 return RETURN_ERR;
12021 }
12022
12023 if (snum > MAX_APS) {
12024 printf("more ssid than supported! %lu\n", snum);
12025 return RETURN_ERR;
12026 }
12027
12028 for (s = 0; s < snum; s++) {
12029 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
12030 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
12031 wpa_ctrl[s].ssid_index = s;
12032 ctrl_enable(&wpa_ctrl[s]);
12033 }
12034
12035 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
12036 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
12037
12038 initialized = 1;
12039 printf("WPA_CTRL: initialized\n");
12040
12041 return RETURN_OK;
12042}
12043
12044void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
12045{
12046 clients_connect_cb = callback_proc;
12047 if (!initialized)
12048 init_wpa();
12049}
12050
12051void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
12052{
12053 clients_disconnect_cb = callback_proc;
12054 if (!initialized)
12055 init_wpa();
12056}
12057
12058INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
12059{
12060 // TODO Implement me!
12061 return RETURN_ERR;
12062}
12063
12064INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
12065{
12066 // TODO Implement me!
12067 return RETURN_ERR;
12068}
12069
12070INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
12071{
12072 int i;
developerd1824452023-05-18 12:30:04 +080012073 int phyId = -1;
12074 char cmd[256] = {0};
12075 char channel_numbers_buf[256] = {0};
12076 char dfs_state_buf[256] = {0};
12077 char line[256] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012078 const char *ptr;
developerd1824452023-05-18 12:30:04 +080012079 BOOL dfs_enable = false;
developer72fb0bb2023-01-11 09:46:29 +080012080
developerd1824452023-05-18 12:30:04 +080012081 memset(outputMap, 0, outputMapSize*sizeof(wifi_channelMap_t)); // all unused entries should be zero
developer72fb0bb2023-01-11 09:46:29 +080012082
developerd1824452023-05-18 12:30:04 +080012083 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
12084 phyId = radio_index_to_phy(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080012085
developerd1824452023-05-18 12:30:04 +080012086 snprintf(cmd, sizeof (cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v '%sno IR\\|5340\\|5480' | awk '{print $4}' | tr -d '[]'", phyId, dfs_enable?"":"radar\\|");
developer72fb0bb2023-01-11 09:46:29 +080012087
developerd1824452023-05-18 12:30:04 +080012088 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
12089 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
12090 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080012091 }
12092
developerd1824452023-05-18 12:30:04 +080012093 ptr = channel_numbers_buf;
12094 i = 0;
12095 while (ptr = get_line_from_str_buf(ptr, line)) {
12096 if (i >= outputMapSize) {
12097 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
12098 return RETURN_ERR;
12099 }
12100 sscanf(line, "%d", &outputMap[i].ch_number);
12101
12102 memset(cmd, 0, sizeof(cmd));
12103 // Below command should fetch string for DFS state (usable, available or unavailable)
12104 // Example line: "DFS state: usable (for 78930 sec)"
12105 if (sprintf(cmd,"iw list | grep -A 2 '\\[%d\\]' | tr -d '\\t' | grep 'DFS state' | awk '{print $3}' | tr -d '\\n'", outputMap[i].ch_number) < 0) {
12106 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
developer72fb0bb2023-01-11 09:46:29 +080012107 return RETURN_ERR;
12108 }
12109
developerd1824452023-05-18 12:30:04 +080012110 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
12111 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
developer72fb0bb2023-01-11 09:46:29 +080012112 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
12113 return RETURN_ERR;
12114 }
12115
developerd1824452023-05-18 12:30:04 +080012116 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
developer59fda4f2023-05-16 15:47:38 +080012117
developerd1824452023-05-18 12:30:04 +080012118 if (!strcmp(dfs_state_buf, "usable")) {
12119 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
12120 } else if (!strcmp(dfs_state_buf, "available")) {
12121 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
12122 } else if (!strcmp(dfs_state_buf, "unavailable")) {
12123 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
12124 } else {
12125 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
developer72fb0bb2023-01-11 09:46:29 +080012126 }
developerd1824452023-05-18 12:30:04 +080012127 i++;
developer59fda4f2023-05-16 15:47:38 +080012128 }
developer40ba1762023-05-13 11:03:49 +080012129
developerd1824452023-05-18 12:30:04 +080012130 return RETURN_OK;
12131
developer72fb0bb2023-01-11 09:46:29 +080012132 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
12133 return RETURN_ERR;
12134}
12135
12136INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
12137{
12138 // TODO Implement me!
12139 return RETURN_ERR;
12140}
12141
12142INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
12143{
12144 return RETURN_OK;
12145}
12146
12147INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
12148{
12149 // TODO Implement me!
12150 return RETURN_ERR;
12151}
12152
12153INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
12154{
12155 // TODO API refrence Implementaion is present on RPI hal
12156 return RETURN_ERR;
12157}
12158
12159INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
12160{
developera1255e42023-05-13 17:45:02 +080012161/*
developer72fb0bb2023-01-11 09:46:29 +080012162 char interface_name[16] = {0};
12163 char cmd[128]={'\0'};
12164 char buf[128]={'\0'};
12165 char *support;
12166 int maximum_tx = 0, current_tx = 0;
developera1255e42023-05-13 17:45:02 +080012167*/ ULONG pwr_percentage = 0;
developer72fb0bb2023-01-11 09:46:29 +080012168
12169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12170 if(txpwr_pcntg == NULL)
12171 return RETURN_ERR;
12172
developera1255e42023-05-13 17:45:02 +080012173 wifi_getRadioTransmitPower(apIndex, &pwr_percentage);
12174 *txpwr_pcntg = pwr_percentage;
12175/* if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +080012176 return RETURN_ERR;
12177
12178 // Get the maximum tx power of the device
12179 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
12180 _syscmd(cmd, buf, sizeof(buf));
12181 maximum_tx = strtol(buf, NULL, 10);
12182
12183 // Get the current tx power
12184 memset(cmd, 0, sizeof(cmd));
12185 memset(buf, 0, sizeof(buf));
12186 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
12187 _syscmd(cmd, buf, sizeof(buf));
12188 current_tx = strtol(buf, NULL, 10);
12189
12190 // Get the power supported list and find the current power percentage in supported list
12191 memset(buf, 0, sizeof(buf));
12192 wifi_getRadioTransmitPowerSupported(apIndex, buf);
12193 support = strtok(buf, ",");
12194 while(true)
12195 {
12196 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
12197 *txpwr_pcntg = 100;
12198 wifi_dbg_printf("current power is not in supported list\n");
12199 return RETURN_OK;
12200 }
12201 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
12202 if (tmp == current_tx) {
12203 *txpwr_pcntg = strtol(support, NULL, 10);
12204 break;
12205 }
12206 support = strtok(NULL, ",");
12207 }
developera1255e42023-05-13 17:45:02 +080012208*/
developer72fb0bb2023-01-11 09:46:29 +080012209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12210 return RETURN_OK;
12211}
12212
12213INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
12214{
12215 // TODO precac feature.
developerd1824452023-05-18 12:30:04 +080012216 struct params params[2] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012217 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080012218 BOOL dfs_enable = false;
12219 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080012220
12221 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developerd1824452023-05-18 12:30:04 +080012222 band = wifi_index_to_band(radioIndex);
12223 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
developer72fb0bb2023-01-11 09:46:29 +080012224
developerd1824452023-05-18 12:30:04 +080012225 if (dfs_enable == false) {
12226 WIFI_ENTRY_EXIT_DEBUG("Please enable DFS firstly!: %s\n", __func__);
12227 return RETURN_ERR;
12228 }
12229 params[0].name = "DfsZeroWaitDefault";
12230 params[0].value = enable?"1":"0";
12231 params[1].name = "DfsDedicatedZeroWait";
12232 params[1].value = enable?"1":"0";
12233 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12234 wifi_datfileWrite(config_file, params, 2);
developerc0772e62023-05-18 15:10:48 +080012235 wifi_reloadAp(radioIndex);
developer72fb0bb2023-01-11 09:46:29 +080012236 /* TODO precac feature */
12237
12238 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12239 return RETURN_OK;
12240}
12241
12242INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
12243{
12244 char config_file[128] = {0};
developerd1824452023-05-18 12:30:04 +080012245 char buf1[32] = {0};
12246 char buf2[32] = {0};
12247 wifi_band band = band_invalid;
developer72fb0bb2023-01-11 09:46:29 +080012248
12249 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12250 if (NULL == enable || NULL == precac)
12251 return RETURN_ERR;
developerd1824452023-05-18 12:30:04 +080012252 band = wifi_index_to_band(radioIndex);
12253 snprintf(config_file, sizeof(config_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12254 wifi_datfileRead(config_file, "DfsZeroWaitDefault", buf1, sizeof(buf1));
12255 wifi_datfileRead(config_file, "DfsDedicatedZeroWait", buf2, sizeof(buf2));
12256 if ((strncmp(buf1, "1", 1) == 0) && (strncmp(buf2, "1", 1) == 0))
developer72fb0bb2023-01-11 09:46:29 +080012257 *enable = true;
12258 else
12259 *enable = false;
12260
12261 /* TODO precac feature */
12262
12263 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12264 return RETURN_OK;
12265}
12266
12267INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
12268{
12269 *supported = TRUE;
12270 return RETURN_OK;
12271}
12272
12273INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
12274{
developera1255e42023-05-13 17:45:02 +080012275 UCHAR dat_file[64] = {0};
12276 wifi_band band = band_invalid;
12277 char cmd[128] = {0};
12278 char buf[256] = {0};
12279 char ofdmabuf[32] = {'\0'};
12280 char mimobuf[32] = {'\0'};
12281 char new_ofdmabuf[32] = {'\0'};
12282 char new_mimobuf[32] = {'\0'};
12283 struct params params[2];
12284 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12285 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12286 UCHAR bss_cnt = 0;
12287 UCHAR val_cnt = 0;
12288 char *token = NULL;
developer72fb0bb2023-01-11 09:46:29 +080012289
developera1255e42023-05-13 17:45:02 +080012290 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12291 if ((mu_type < WIFI_DL_MU_TYPE_NONE)
12292 || (mu_type > WIFI_DL_MU_TYPE_OFDMA_MIMO)) {
12293 printf("%s:mu_type input Error", __func__);
12294 return RETURN_ERR;
12295 }
12296 band = wifi_index_to_band(radio_index);
12297 if (band == band_invalid) {
12298 printf("%s:Band Error\n", __func__);
12299 return RETURN_ERR;
12300 }
12301 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12302 /*get current value in dat file*/
12303 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12304 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
12305 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12306 get_bssnum_byindex(radio_index, &bss_cnt);
12307 val_cnt = 2*bss_cnt - 1;
12308 WIFI_ENTRY_EXIT_DEBUG("bss number: %d\n", bss_cnt);
12309 if ((val_cnt >= sizeof(new_ofdmabuf))
12310 || (val_cnt >= sizeof(new_mimobuf))) {
12311 printf("%s:bss cnt Error", __func__, bss_cnt);
12312 return RETURN_ERR;
12313 }
12314 /*translate set value*/
12315 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
12316 strncpy(new_ofdmabuf, str_zero, val_cnt);
12317 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012318 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
developera1255e42023-05-13 17:45:02 +080012319 strncpy(new_ofdmabuf, str_one, val_cnt);
12320 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012321 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
developera1255e42023-05-13 17:45:02 +080012322 strncpy(new_ofdmabuf, str_zero, val_cnt);
12323 strncpy(new_mimobuf, str_one, val_cnt);
12324 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO) {
12325 strncpy(new_ofdmabuf, str_one, val_cnt);
12326 strncpy(new_mimobuf, str_one, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012327 }
developera1255e42023-05-13 17:45:02 +080012328 WIFI_ENTRY_EXIT_DEBUG("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12329 /*same value, not operation*/
12330 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12331 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12332 printf("%s:Reduntant value\n", __func__);
12333 return RETURN_OK;
12334 }
12335 /*modify dat file to new file*/
12336 params[0].name="MuOfdmaDlEnable";
12337 params[0].value=new_ofdmabuf;
12338 params[1].name="MuMimoDlEnable";
12339 params[1].value=new_mimobuf;
12340 wifi_datfileWrite(dat_file, params, 2);
12341 /*hostapd control restarp ap to take effect on these new value*/
12342 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12344 return RETURN_OK;
12345}
12346
12347INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
12348{
12349 struct params params={0};
12350 char config_file[64] = {0};
12351 char buf[64] = {0};
12352 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012353 UCHAR dat_file[64] = {0};
12354 wifi_band band = band_invalid;
12355 char ofdmabuf[32] = {'\0'};
12356 char mimobuf[32] = {'\0'};
12357 char *token = NULL;
12358 UCHAR ofdma = 0;
12359 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012360
12361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12362
12363 if (mu_type == NULL)
12364 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012365 band = wifi_index_to_band(radio_index);
12366 if (band == band_invalid) {
12367 printf("%s:Band Error\n", __func__);
12368 return RETURN_ERR;
12369 }
12370 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12371 /*get current value in dat file*/
12372 wifi_datfileRead(dat_file, "MuOfdmaDlEnable", ofdmabuf, sizeof(ofdmabuf));
12373 wifi_datfileRead(dat_file, "MuMimoDlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012374
developera1255e42023-05-13 17:45:02 +080012375 token = strtok(ofdmabuf, ";");
12376 ofdma = strtol(token, NULL, 10);
12377 token = strtok(mimobuf, ";");
12378 mimo = strtol(token, NULL, 10);
12379 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d,mimo=%d\n", __func__, ofdma, mimo);
12380 if ((ofdma == 1) && (mimo == 1))
12381 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
12382 else if ((ofdma == 0) && (mimo == 1))
12383 *mu_type = WIFI_DL_MU_TYPE_MIMO;
12384 else if ((ofdma == 1) && (mimo == 0))
12385 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
12386 else
12387 *mu_type = WIFI_DL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012388 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12389 return RETURN_OK;
12390}
12391
12392INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
12393{
12394 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
developera1255e42023-05-13 17:45:02 +080012395 UCHAR dat_file[64] = {0};
12396 wifi_band band = band_invalid;
12397 char cmd[128] = {0};
12398 char buf[256] = {0};
12399 char ofdmabuf[32] = {'\0'};
12400 char mimobuf[32] = {'\0'};
12401 char new_ofdmabuf[32] = {'\0'};
12402 char new_mimobuf[32] = {'\0'};
12403 struct params params[2];
12404 char *str_zero = "0;0;0;0;0;0;0;0;0;0;0;0;0;0;0";/*default 15bss per band.*/
12405 char *str_one = "1;1;1;1;1;1;1;1;1;1;1;1;1;1;1";
12406 UCHAR bss_cnt = 0;
12407 UCHAR val_cnt = 0;
developer72fb0bb2023-01-11 09:46:29 +080012408
developera1255e42023-05-13 17:45:02 +080012409 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12410 band = wifi_index_to_band(radio_index);
12411 if (band == band_invalid) {
12412 printf("%s:Band Error\n", __func__);
12413 return RETURN_ERR;
12414 }
12415 if ((mu_type < WIFI_UL_MU_TYPE_NONE)
12416 || (mu_type > WIFI_UL_MU_TYPE_OFDMA)) {
12417 printf("%s:mu_type input Error\n", __func__);
12418 return RETURN_ERR;
12419 }
12420 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12421 /*get current value in dat file*/
12422 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12423 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
12424 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma-%s, mimo-%s\n", __func__, ofdmabuf, mimobuf);
12425 get_bssnum_byindex(radio_index, &bss_cnt);
12426 val_cnt = 2*bss_cnt - 1;
12427 printf("bssNumber:%d,ValCnt:%d\n", bss_cnt, val_cnt);
12428 if ((val_cnt >= sizeof(new_ofdmabuf))
12429 || (val_cnt >= sizeof(new_mimobuf))) {
12430 printf("%s:bss cnt Error\n", __func__, val_cnt);
12431 return RETURN_ERR;
12432 }
12433 /*translate set value*/
12434 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
12435 strncpy(new_ofdmabuf, str_zero, val_cnt);
12436 strncpy(new_mimobuf, str_zero, val_cnt);
developer72fb0bb2023-01-11 09:46:29 +080012437 }
developera1255e42023-05-13 17:45:02 +080012438 if (mu_type == WIFI_UL_MU_TYPE_OFDMA) {
12439 strncpy(new_ofdmabuf, str_one, val_cnt);
12440 strncpy(new_mimobuf, str_zero, val_cnt);
12441 }
12442 printf("%s:new_ofdmabuf-%s, new_mimobuf-%s\n", __func__, new_ofdmabuf, new_mimobuf);
12443 /*same value, not operation*/
12444 if ((strncmp(new_mimobuf, mimobuf, 1) ==0)
12445 && (strncmp(new_ofdmabuf, ofdmabuf, 1) ==0)) {
12446 printf("%s:Reduntant value\n", __func__);
12447 return RETURN_OK;
12448 }
12449 /*modify dat file to new file*/
12450 params[0].name="MuOfdmaUlEnable";
12451 params[0].value=new_ofdmabuf;
12452 params[1].name="MuMimoUlEnable";
12453 params[1].value=new_mimobuf;
12454 wifi_datfileWrite(dat_file, params, 2);
12455 wifi_reloadAp(radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12457 return RETURN_OK;
12458}
12459
12460INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
12461{
12462 struct params params={0};
12463 char config_file[64] = {0};
12464 char buf[64] = {0};
12465 unsigned int get_mu_type = 0;
developera1255e42023-05-13 17:45:02 +080012466 UCHAR dat_file[64] = {0};
12467 wifi_band band = band_invalid;
12468 char ofdmabuf[32] = {'\0'};
12469 char mimobuf[32] = {'\0'};
12470 char *token = NULL;
12471 UCHAR ofdma = 0;
12472 UCHAR mimo = 0;
developer72fb0bb2023-01-11 09:46:29 +080012473
12474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12475
12476 if (mu_type == NULL)
12477 return RETURN_ERR;
developera1255e42023-05-13 17:45:02 +080012478 band = wifi_index_to_band(radio_index);
12479 if (band == band_invalid) {
12480 printf("%s:Band Error", __func__);
12481 return RETURN_ERR;
12482 }
12483 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12484 /*get current value in dat file*/
12485 wifi_datfileRead(dat_file, "MuOfdmaUlEnable", ofdmabuf, sizeof(ofdmabuf));
12486 wifi_datfileRead(dat_file, "MuMimoUlEnable", mimobuf, sizeof(mimobuf));
developer72fb0bb2023-01-11 09:46:29 +080012487
developera1255e42023-05-13 17:45:02 +080012488 token = strtok(ofdmabuf, ";");
12489 ofdma = strtol(token, NULL, 10);
12490 token = strtok(mimobuf, ";");
12491 mimo = strtol(token, NULL, 10);
12492 WIFI_ENTRY_EXIT_DEBUG("%s:ofdma=%d, mimo=%d\n", __func__, ofdma, mimo);
12493 if ((ofdma == 1) && (mimo == 0))
12494 *mu_type = WIFI_UL_MU_TYPE_OFDMA;
12495 else
12496 *mu_type = WIFI_UL_MU_TYPE_NONE;
developer72fb0bb2023-01-11 09:46:29 +080012497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12498 return RETURN_OK;
12499}
12500
12501
12502INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
12503{
12504 char cmd[128] = {0};
12505 char buf[256] = {0};
12506 char config_file[64] = {0};
12507 char GI[8] = {0};
12508 int mode_map = 0;
12509 FILE *f = NULL;
12510 wifi_band band = band_invalid;
developera1255e42023-05-13 17:45:02 +080012511 char dat_file[64] = {'\0'};
12512 struct params params[3];
developer72fb0bb2023-01-11 09:46:29 +080012513
12514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12515
12516 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
12517 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
12518 return RETURN_ERR;
12519 }
developera1255e42023-05-13 17:45:02 +080012520 /*sanity check*/
12521 if (((guard_interval == wifi_guard_interval_1600)
12522 || (guard_interval == wifi_guard_interval_3200))
12523 && (mode_map & (WIFI_MODE_BE | WIFI_MODE_AX) == 0)) {
12524 wifi_dbg_printf("%s: N/AC Mode not support 1600/3200ns GI\n", __func__);
12525 return RETURN_ERR;
12526 }
developer72fb0bb2023-01-11 09:46:29 +080012527 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
12528 band = wifi_index_to_band(radio_index);
12529
12530 // Hostapd are not supported HE mode GI 1600, 3200 ns.
12531 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
12532 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
12533 _syscmd(cmd, buf, sizeof(buf));
12534 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
12535 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
12536 if (strstr(buf, "[SHORT-GI-") == NULL) {
12537 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
12538 _syscmd(cmd, buf, sizeof(buf));
12539 }
12540 if (band == band_5) {
12541 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
12542 if (strstr(buf, "[SHORT-GI-") == NULL) {
12543 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
12544 _syscmd(cmd, buf, sizeof(buf));
12545 }
12546 }
12547 }
developera1255e42023-05-13 17:45:02 +080012548 /*wifi_reloadAp(radio_index);
12549 caller "wifi_setRadioOperatingParameters" have done this step.
12550 */
12551 snprintf(dat_file, sizeof(dat_file), "%s%d.dat", LOGAN_DAT_FILE, band);
12552 if (guard_interval == wifi_guard_interval_400) {
12553 params[0].name = "HT_GI";
12554 params[0].value = "1";
12555 params[1].name = "VHT_SGI";
12556 params[1].value = "1";
12557 wifi_datfileWrite(dat_file, params, 2);
developer72fb0bb2023-01-11 09:46:29 +080012558 strcpy(GI, "0.4");
developera1255e42023-05-13 17:45:02 +080012559 } else {
12560 params[0].name = "HT_GI";
12561 params[0].value = "0";
12562 params[1].name = "VHT_SGI";
12563 params[1].value = "0";
12564 /*should enable FIXED_HE_GI_SUPPORT in driver*/
12565 params[2].name = "FgiFltf";
12566 if (guard_interval == wifi_guard_interval_800) {
12567 params[2].value = "800";
12568 strcpy(GI, "0.8");
12569 } else if (guard_interval == wifi_guard_interval_1600) {
12570 params[2].value = "1600";
12571 strcpy(GI, "1.6");
12572 } else if (guard_interval == wifi_guard_interval_3200) {
12573 params[2].value = "3200";
12574 strcpy(GI, "3.2");
12575 } else if (guard_interval == wifi_guard_interval_auto) {
12576 params[2].value = "0";
12577 strcpy(GI, "auto");
12578 }
12579 wifi_datfileWrite(dat_file, params, 3);
12580 }
developer72fb0bb2023-01-11 09:46:29 +080012581 // Record GI for get GI function
12582 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
12583 f = fopen(buf, "w");
12584 if (f == NULL)
12585 return RETURN_ERR;
12586 fprintf(f, "%s", GI);
12587 fclose(f);
12588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12589 return RETURN_OK;
12590}
12591
12592INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
12593{
12594 char buf[32] = {0};
12595 char cmd[64] = {0};
12596
12597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12598
12599 if (guard_interval == NULL)
12600 return RETURN_ERR;
12601
developera1255e42023-05-13 17:45:02 +080012602 snprintf(cmd, sizeof(cmd), "cat %s%d.txt 2> /dev/null", GUARD_INTERVAL_FILE, radio_index);
developer72fb0bb2023-01-11 09:46:29 +080012603 _syscmd(cmd, buf, sizeof(buf));
12604
12605 if (strncmp(buf, "0.4", 3) == 0)
12606 *guard_interval = wifi_guard_interval_400;
12607 else if (strncmp(buf, "0.8", 3) == 0)
12608 *guard_interval = wifi_guard_interval_800;
12609 else if (strncmp(buf, "1.6", 3) == 0)
12610 *guard_interval = wifi_guard_interval_1600;
12611 else if (strncmp(buf, "3.2", 3) == 0)
12612 *guard_interval = wifi_guard_interval_3200;
12613 else
12614 *guard_interval = wifi_guard_interval_auto;
12615
12616 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12617 return RETURN_OK;
12618}
12619
12620INT wifi_setBSSColor(INT radio_index, UCHAR color)
12621{
12622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12623 struct params params = {0};
12624 char config_file[128] = {0};
12625 char bss_color[4] ={0};
12626
developera1255e42023-05-13 17:45:02 +080012627 if (color < 1 || color > 63) {
12628 wifi_dbg_printf("color value is err:%d.\n", color);
12629 return RETURN_ERR;
12630 }
developer72fb0bb2023-01-11 09:46:29 +080012631 params.name = "he_bss_color";
12632 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
12633 params.value = bss_color;
12634 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12635 wifi_hostapdWrite(config_file, &params, 1);
developera1255e42023-05-13 17:45:02 +080012636 //wifi_hostapdProcessUpdate(radio_index, &params, 1);
12637 wifi_reloadAp(radio_index);
developer69b61b02023-03-07 17:17:44 +080012638
developer72fb0bb2023-01-11 09:46:29 +080012639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12640 return RETURN_OK;
12641}
12642
12643INT wifi_getBSSColor(INT radio_index, UCHAR *color)
12644{
12645 char config_file[128] = {0};
12646 char buf[64] = {0};
12647 char temp_output[128] = {'\0'};
12648
12649 wifi_dbg_printf("\nFunc=%s\n", __func__);
12650 if (NULL == color)
12651 return RETURN_ERR;
12652
12653 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
12654 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
12655
12656 if(strlen(buf) > 0) {
12657 snprintf(temp_output, sizeof(temp_output), "%s", buf);
12658 } else {
12659 snprintf(temp_output, sizeof(temp_output), "1"); // default value
12660 }
12661
12662 *color = (UCHAR)strtoul(temp_output, NULL, 10);
12663 wifi_dbg_printf("\noutput_string=%s\n", color);
12664
12665 return RETURN_OK;
12666}
12667
12668/* multi-psk support */
12669INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
12670{
12671 char cmd[256];
12672 char interface_name[16] = {0};
12673
12674 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12675 return RETURN_ERR;
12676
12677 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
12678 interface_name,
12679 mac[0],
12680 mac[1],
12681 mac[2],
12682 mac[3],
12683 mac[4],
12684 mac[5]
12685 );
12686 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
12687 _syscmd(cmd, key->wifi_keyId, 64);
12688
12689
12690 return RETURN_OK;
12691}
12692
12693INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12694{
12695 char interface_name[16] = {0};
12696 FILE *fd = NULL;
12697 char fname[100];
12698 char cmd[128] = {0};
12699 char out[64] = {0};
12700 wifi_key_multi_psk_t * key = NULL;
12701 if(keysNumber < 0)
12702 return RETURN_ERR;
12703
12704 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12705 fd = fopen(fname, "w");
12706 if (!fd) {
12707 return RETURN_ERR;
12708 }
12709 key= (wifi_key_multi_psk_t *) keys;
12710 for(int i=0; i<keysNumber; ++i, key++) {
12711 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
12712 }
12713 fclose(fd);
12714
12715 //reload file
12716 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12717 return RETURN_ERR;
12718 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
12719 _syscmd(cmd, out, 64);
12720 return RETURN_OK;
12721}
12722
12723INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
12724{
12725 FILE *fd = NULL;
12726 char fname[100];
12727 char * line = NULL;
12728 char * pos = NULL;
12729 size_t len = 0;
12730 ssize_t read = 0;
12731 INT ret = RETURN_OK;
12732 wifi_key_multi_psk_t *keys_it = NULL;
12733
12734 if (keysNumber < 1) {
12735 return RETURN_ERR;
12736 }
12737
12738 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
12739 fd = fopen(fname, "r");
12740 if (!fd) {
12741 return RETURN_ERR;
12742 }
12743
12744 if (keys == NULL) {
12745 ret = RETURN_ERR;
12746 goto close;
12747 }
12748
12749 keys_it = keys;
12750 while ((read = getline(&line, &len, fd)) != -1) {
12751 //Strip trailing new line if present
12752 if (read > 0 && line[read-1] == '\n') {
12753 line[read-1] = '\0';
12754 }
12755
12756 if(strcmp(line,"keyid=")) {
12757 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
12758 if (!(pos = index(line, ' '))) {
12759 ret = RETURN_ERR;
12760 goto close;
12761 }
12762 pos++;
12763 //Here should be 00:00:00:00:00:00
12764 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
12765 printf("Not supported MAC: %s\n", pos);
12766 }
12767 if (!(pos = index(pos, ' '))) {
12768 ret = RETURN_ERR;
12769 goto close;
12770 }
12771 pos++;
12772
12773 //The rest is PSK
12774 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
12775 keys_it++;
12776
12777 if(--keysNumber <= 0)
12778 break;
12779 }
12780 }
12781
12782close:
12783 free(line);
12784 fclose(fd);
12785 return ret;
12786}
12787/* end of multi-psk support */
12788
12789INT wifi_setNeighborReports(UINT apIndex,
12790 UINT numNeighborReports,
12791 wifi_NeighborReport_t *neighborReports)
12792{
12793 char cmd[256] = { 0 };
12794 char hex_bssid[13] = { 0 };
12795 char bssid[18] = { 0 };
12796 char nr[256] = { 0 };
12797 char ssid[256];
12798 char hex_ssid[256];
12799 char interface_name[16] = {0};
12800 INT ret;
12801
12802 /*rmeove all neighbors*/
12803 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
12804 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
12805 return RETURN_ERR;
12806 sprintf(cmd, "hostapd_cli show_neighbor -i %s | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s",interface_name,interface_name);
12807 system(cmd);
12808
12809 for(unsigned int i = 0; i < numNeighborReports; i++)
12810 {
12811 memset(ssid, 0, sizeof(ssid));
12812 ret = wifi_getSSIDName(apIndex, ssid);
12813 if (ret != RETURN_OK)
12814 return RETURN_ERR;
12815
12816 memset(hex_ssid, 0, sizeof(hex_ssid));
12817 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
12818 sprintf(hex_ssid + k,"%02x", ssid[j]);
12819
12820 snprintf(hex_bssid, sizeof(hex_bssid),
12821 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
12822 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12823 snprintf(bssid, sizeof(bssid),
12824 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
12825 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
12826
12827 snprintf(nr, sizeof(nr),
12828 "%s" // bssid
12829 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
12830 "%02hhx" // operclass
12831 "%02hhx" // channel
12832 "%02hhx", // phy_mode
12833 hex_bssid,
12834 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
12835 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
12836 neighborReports[i].opClass,
12837 neighborReports[i].channel,
12838 neighborReports[i].phyTable);
12839
12840 snprintf(cmd, sizeof(cmd),
12841 "hostapd_cli set_neighbor "
12842 "%s " // bssid
12843 "ssid=%s " // ssid
12844 "nr=%s " // nr
12845 "-i %s",
12846 bssid,hex_ssid,nr, interface_name);
12847
12848 if (WEXITSTATUS(system(cmd)) != 0)
12849 {
12850 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
12851 }
12852 }
12853
12854 return RETURN_OK;
12855}
12856
12857INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
12858{
12859 return RETURN_OK;
12860}
12861
12862#ifdef _WIFI_HAL_TEST_
12863int main(int argc,char **argv)
12864{
12865 int index;
12866 INT ret=0;
12867 char buf[1024]="";
12868
12869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12870 if(argc<3)
12871 {
12872 if(argc==2)
12873 {
12874 if(!strcmp(argv[1], "init"))
12875 return wifi_init();
12876 if(!strcmp(argv[1], "reset"))
12877 return wifi_reset();
12878 if(!strcmp(argv[1], "wifi_getHalVersion"))
12879 {
12880 char buffer[64];
12881 if(wifi_getHalVersion(buffer)==RETURN_OK)
12882 printf("Version: %s\n", buffer);
12883 else
12884 printf("Error in wifi_getHalVersion\n");
12885 return RETURN_OK;
12886 }
12887 }
12888 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
12889 exit(-1);
12890 }
12891
12892 index = atoi(argv[2]);
12893 if(strstr(argv[1], "wifi_getApName")!=NULL)
12894 {
12895 wifi_getApName(index,buf);
12896 printf("Ap name is %s \n",buf);
12897 return 0;
12898 }
developer121a8e72023-05-22 09:19:39 +080012899 if (strstr(argv[1], "wifi_setApAclDevice")!=NULL) {
developer49b17232023-05-19 16:35:19 +080012900 if(argc <= 3 )
12901 {
12902 printf("Insufficient arguments \n");
12903 exit(-1);
12904 }
12905 wifi_addApAclDevice(index, argv[3]);
12906 return 0;
12907 }
developer121a8e72023-05-22 09:19:39 +080012908 if (strstr(argv[1], "wifi_getApAclDevices")!=NULL) {
12909 wifi_getApAclDevices(index, buf, MAX_BUF_SIZE);
12910 return 0;
12911 }
12912
developer0f10c772023-05-16 21:43:39 +080012913 if(strstr(argv[1], "wifi_getRadioMode")!=NULL)
12914 {
12915 int mode = 0;
12916
12917 wifi_getRadioMode(index, buf, &mode);
12918 printf("Ap Radio mode is %s , mode = 0x%x\n", buf, mode);
12919 return 0;
12920 }
developer72fb0bb2023-01-11 09:46:29 +080012921 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
12922 {
12923 BOOL b = FALSE;
12924 BOOL *output_bool = &b;
12925 wifi_getRadioAutoChannelEnable(index,output_bool);
12926 printf("Channel enabled = %d \n",b);
12927 return 0;
12928 }
12929 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
12930 {
12931 wifi_getApWpaEncryptionMode(index,buf);
12932 printf("encryption enabled = %s\n",buf);
12933 return 0;
12934 }
12935 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
12936 {
12937 BOOL b = FALSE;
12938 BOOL *output_bool = &b;
12939 wifi_getApSsidAdvertisementEnable(index,output_bool);
12940 printf("advertisment enabled = %d\n",b);
12941 return 0;
12942 }
12943 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
12944 {
12945 if(argc <= 3 )
12946 {
12947 printf("Insufficient arguments \n");
12948 exit(-1);
12949 }
12950
12951 char sta[20] = {'\0'};
12952 ULLONG handle= 0;
12953 strcpy(sta,argv[3]);
12954 mac_address_t st;
12955 mac_addr_aton(st,sta);
12956
12957 wifi_associated_dev_tid_stats_t tid_stats;
12958 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
12959 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
12960 printf(" tid=%d \t ac=%d \t num_msdus=%lld \n" ,tid_stats.tid_array[tid_index].tid,tid_stats.tid_array[tid_index].ac,tid_stats.tid_array[tid_index].num_msdus);
12961 }
12962
12963 if(strstr(argv[1], "getApEnable")!=NULL) {
12964 BOOL enable;
12965 ret=wifi_getApEnable(index, &enable);
12966 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12967 }
12968 else if(strstr(argv[1], "setApEnable")!=NULL) {
12969 BOOL enable = atoi(argv[3]);
12970 ret=wifi_setApEnable(index, enable);
12971 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
12972 }
12973 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080012974 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080012975 ret=wifi_getApStatus(index, status);
12976 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
12977 }
12978 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
12979 {
12980 wifi_getSSIDNameStatus(index,buf);
12981 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
12982 return 0;
12983 }
12984 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
12985 wifi_ssidTrafficStats2_t stats={0};
12986 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
12987 printf("%s %d: returns %d\n", argv[1], index, ret);
12988 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
12989 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
12990 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
12991 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
12992 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
12993 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
12994 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
12995 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
12996 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
12997 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
12998 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
12999 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
13000 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
13001 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
13002 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
13003 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
13004 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
13005 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
13006 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
13007 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
13008 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
13009 }
13010 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
13011 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
13012 UINT array_size=0;
13013 UINT i=0;
13014 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
13015 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080013016 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080013017 printf(" neighbor %d:\n", i);
13018 printf(" ap_SSID =%s\n", pt->ap_SSID);
13019 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
13020 printf(" ap_Mode =%s\n", pt->ap_Mode);
13021 printf(" ap_Channel =%d\n", pt->ap_Channel);
13022 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
13023 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
13024 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
13025 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
13026 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
13027 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
13028 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
13029 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
13030 printf(" ap_Noise =%d\n", pt->ap_Noise);
13031 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
13032 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
13033 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080013034 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080013035 }
13036 if(neighbor_ap_array)
13037 free(neighbor_ap_array); //make sure to free the list
13038 }
13039 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
13040 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
13041 UINT array_size=0;
13042 UINT i=0;
13043 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
13044 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080013045 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080013046 printf(" associated_dev %d:\n", i);
13047 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
13048 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
13049 printf(" cli_SNR =%d\n", pt->cli_SNR);
13050 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
13051 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
13052 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
13053 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
13054 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
13055 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
13056 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
13057 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
13058 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
13059 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
13060 }
13061 if(associated_dev_array)
13062 free(associated_dev_array); //make sure to free the list
13063 }
13064
13065 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
13066 {
13067#define MAX_ARRAY_SIZE 64
13068 int i, array_size;
13069 char *p, *ch_str;
13070 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
13071
13072 if(argc != 5)
13073 {
13074 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
13075 exit(-1);
13076 }
13077 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
13078
13079 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
13080 {
13081 strtok_r(ch_str, ",", &p);
13082 input_output_channelStats_array[i].ch_number = atoi(ch_str);
13083 }
13084 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
13085 if(!array_size)
13086 array_size=1;//Need to print current channel statistics
13087 for(i=0; i<array_size; i++)
13088 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
13089 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
13090 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
13091 input_output_channelStats_array[i].ch_number,\
13092 input_output_channelStats_array[i].ch_noise,\
13093 input_output_channelStats_array[i].ch_utilization_busy_rx,\
13094 input_output_channelStats_array[i].ch_utilization_busy_tx,\
13095 input_output_channelStats_array[i].ch_utilization_busy,\
13096 input_output_channelStats_array[i].ch_utilization_busy_ext,\
13097 input_output_channelStats_array[i].ch_utilization_total);
13098 }
13099
13100 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
13101 {
13102 if(argc <= 3 )
13103 {
13104 printf("Insufficient arguments \n");
13105 exit(-1);
13106 }
13107 char mac_addr[20] = {'\0'};
13108 wifi_device_t output_struct;
13109 int dev_index = atoi(argv[3]);
13110
13111 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
13112 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
13113 printf("wifi_devMacAddress=%s \t wifi_devAssociatedDeviceAuthentiationState=%d \t, wifi_devSignalStrength=%d \t,wifi_devTxRate=%d \t, wifi_devRxRate =%d \t\n ", mac_addr,output_struct.wifi_devAssociatedDeviceAuthentiationState,output_struct.wifi_devSignalStrength,output_struct.wifi_devTxRate,output_struct.wifi_devRxRate);
13114 }
13115
13116 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
13117 {
13118 if (argc <= 3)
13119 {
13120 printf("Insufficient arguments\n");
13121 exit(-1);
13122 }
13123 char args[256];
13124 wifi_NeighborReport_t *neighborReports;
13125
13126 neighborReports = calloc(argc - 2, sizeof(neighborReports));
13127 if (!neighborReports)
13128 {
13129 printf("Failed to allocate memory");
13130 exit(-1);
13131 }
13132
13133 for (int i = 3; i < argc; ++i)
13134 {
13135 char *val;
13136 int j = 0;
13137 memset(args, 0, sizeof(args));
13138 strncpy(args, argv[i], sizeof(args));
13139 val = strtok(args, ";");
13140 while (val != NULL)
13141 {
13142 if (j == 0)
13143 {
13144 mac_addr_aton(neighborReports[i - 3].bssid, val);
13145 } else if (j == 1)
13146 {
13147 neighborReports[i - 3].info = strtol(val, NULL, 16);
13148 } else if (j == 2)
13149 {
13150 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
13151 } else if (j == 3)
13152 {
13153 neighborReports[i - 3].channel = strtol(val, NULL, 16);
13154 } else if (j == 4)
13155 {
13156 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
13157 } else {
13158 printf("Insufficient arguments]n\n");
13159 exit(-1);
13160 }
13161 val = strtok(NULL, ";");
13162 j++;
13163 }
13164 }
13165
13166 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
13167 if (ret != RETURN_OK)
13168 {
13169 printf("wifi_setNeighborReports ret = %d", ret);
13170 exit(-1);
13171 }
13172 }
13173 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
13174 {
13175 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
13176 printf("%s.\n", buf);
13177 else
13178 printf("Error returned\n");
13179 }
13180 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
13181 {
13182 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
13183 printf("%s.\n", buf);
13184 else
13185 printf("Error returned\n");
13186 }
13187 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
13188 {
13189 if (argc <= 2)
13190 {
13191 printf("Insufficient arguments\n");
13192 exit(-1);
13193 }
13194 char buf[64]= {'\0'};
13195 wifi_getRadioOperatingChannelBandwidth(index,buf);
13196 printf("Current bandwidth is %s \n",buf);
13197 return 0;
13198 }
13199 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
13200 {
13201 if (argc <= 5)
13202 {
13203 printf("Insufficient arguments\n");
13204 exit(-1);
13205 }
13206 UINT channel = atoi(argv[3]);
13207 UINT width = atoi(argv[4]);
13208 UINT beacon = atoi(argv[5]);
13209 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
13210 printf("Result = %d", ret);
13211 }
13212
13213 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13214 return 0;
13215}
13216
13217#endif
13218
13219#ifdef WIFI_HAL_VERSION_3
13220
13221INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
13222{
13223 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13224 if (bitMap & WIFI_BITRATE_1MBPS)
13225 strcat(BasicRate, "1,");
13226 if (bitMap & WIFI_BITRATE_2MBPS)
13227 strcat(BasicRate, "2,");
13228 if (bitMap & WIFI_BITRATE_5_5MBPS)
13229 strcat(BasicRate, "5.5,");
13230 if (bitMap & WIFI_BITRATE_6MBPS)
13231 strcat(BasicRate, "6,");
13232 if (bitMap & WIFI_BITRATE_9MBPS)
13233 strcat(BasicRate, "9,");
13234 if (bitMap & WIFI_BITRATE_11MBPS)
13235 strcat(BasicRate, "11,");
13236 if (bitMap & WIFI_BITRATE_12MBPS)
13237 strcat(BasicRate, "12,");
13238 if (bitMap & WIFI_BITRATE_18MBPS)
13239 strcat(BasicRate, "18,");
13240 if (bitMap & WIFI_BITRATE_24MBPS)
13241 strcat(BasicRate, "24,");
13242 if (bitMap & WIFI_BITRATE_36MBPS)
13243 strcat(BasicRate, "36,");
13244 if (bitMap & WIFI_BITRATE_48MBPS)
13245 strcat(BasicRate, "48,");
13246 if (bitMap & WIFI_BITRATE_54MBPS)
13247 strcat(BasicRate, "54,");
13248 if (strlen(BasicRate) != 0) // remove last comma
13249 BasicRate[strlen(BasicRate) - 1] = '\0';
13250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13251 return RETURN_OK;
13252}
13253
13254INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
13255{
13256 UINT BitMap = 0;
13257 char *rate;
13258
13259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13260 rate = strtok(BasicRatesList, ",");
13261 while(rate != NULL)
13262 {
13263 if (strcmp(rate, "1") == 0)
13264 BitMap |= WIFI_BITRATE_1MBPS;
13265 else if (strcmp(rate, "2") == 0)
13266 BitMap |= WIFI_BITRATE_2MBPS;
13267 else if (strcmp(rate, "5.5") == 0)
13268 BitMap |= WIFI_BITRATE_5_5MBPS;
13269 else if (strcmp(rate, "6") == 0)
13270 BitMap |= WIFI_BITRATE_6MBPS;
13271 else if (strcmp(rate, "9") == 0)
13272 BitMap |= WIFI_BITRATE_9MBPS;
13273 else if (strcmp(rate, "11") == 0)
13274 BitMap |= WIFI_BITRATE_11MBPS;
13275 else if (strcmp(rate, "12") == 0)
13276 BitMap |= WIFI_BITRATE_12MBPS;
13277 else if (strcmp(rate, "18") == 0)
13278 BitMap |= WIFI_BITRATE_18MBPS;
13279 else if (strcmp(rate, "24") == 0)
13280 BitMap |= WIFI_BITRATE_24MBPS;
13281 else if (strcmp(rate, "36") == 0)
13282 BitMap |= WIFI_BITRATE_36MBPS;
13283 else if (strcmp(rate, "48") == 0)
13284 BitMap |= WIFI_BITRATE_48MBPS;
13285 else if (strcmp(rate, "54") == 0)
13286 BitMap |= WIFI_BITRATE_54MBPS;
13287 rate = strtok(NULL, ",");
13288 }
13289 *basicRateBitMap = BitMap;
13290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13291 return RETURN_OK;
13292}
13293
13294// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
13295INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13296{
13297 char buf[128] = {0};
13298 char cmd[128] = {0};
13299 char config_file[64] = {0};
13300 int bandwidth;
13301 int set_mode = 0;
13302 wifi_radio_operationParam_t current_param;
13303
13304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13305
13306 multiple_set = TRUE;
13307 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
13308 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
13309 return RETURN_ERR;
13310 }
13311 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
13312 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
13313 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
13314 return RETURN_ERR;
13315 }
13316 }
13317
13318 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
13319 bandwidth = 20;
13320 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
13321 bandwidth = 40;
13322 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
13323 bandwidth = 80;
13324 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
13325 bandwidth = 160;
13326 if (operationParam->autoChannelEnabled){
13327 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13328 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13329 return RETURN_ERR;
13330 }
developer69b61b02023-03-07 17:17:44 +080013331 }else{
developer72fb0bb2023-01-11 09:46:29 +080013332 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
13333 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
13334 return RETURN_ERR;
13335 }
13336 }
13337
13338 if (current_param.variant != operationParam->variant) {
13339 // Two different definition bit map, so need to check every bit.
13340 if (operationParam->variant & WIFI_80211_VARIANT_A)
13341 set_mode |= WIFI_MODE_A;
13342 if (operationParam->variant & WIFI_80211_VARIANT_B)
13343 set_mode |= WIFI_MODE_B;
13344 if (operationParam->variant & WIFI_80211_VARIANT_G)
13345 set_mode |= WIFI_MODE_G;
13346 if (operationParam->variant & WIFI_80211_VARIANT_N)
13347 set_mode |= WIFI_MODE_N;
13348 if (operationParam->variant & WIFI_80211_VARIANT_AC)
13349 set_mode |= WIFI_MODE_AC;
13350 if (operationParam->variant & WIFI_80211_VARIANT_AX)
13351 set_mode |= WIFI_MODE_AX;
13352 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
13353 memset(buf, 0, sizeof(buf));
developer0f10c772023-05-16 21:43:39 +080013354 if (wifi_setRadioMode_by_dat(index, set_mode) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013355 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
13356 return RETURN_ERR;
13357 }
13358 }
13359 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
13360 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
13361 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
13362 return RETURN_ERR;
13363 }
13364 }
13365 if (current_param.beaconInterval != operationParam->beaconInterval) {
13366 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
13367 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
13368 return RETURN_ERR;
13369 }
13370 }
13371 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
13372 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
13373 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13374 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
13375 return RETURN_ERR;
13376 }
13377 }
13378 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
13379 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
13380 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
13381 return RETURN_ERR;
13382 }
13383 }
13384 if (current_param.guardInterval != operationParam->guardInterval) {
13385 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
13386 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
13387 return RETURN_ERR;
13388 }
13389 }
13390 if (current_param.transmitPower != operationParam->transmitPower) {
13391 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
13392 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
13393 return RETURN_ERR;
13394 }
13395 }
13396 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
13397 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
13398 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
13399 return RETURN_ERR;
13400 }
13401 }
13402 if (current_param.obssCoex != operationParam->obssCoex) {
13403 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
13404 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
13405 return RETURN_ERR;
13406 }
13407 }
13408 if (current_param.stbcEnable != operationParam->stbcEnable) {
13409 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
13410 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
13411 return RETURN_ERR;
13412 }
13413 }
13414 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
13415 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
13416 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
13417 return RETURN_ERR;
13418 }
13419 }
13420
13421 // if enable is true, then restart the radio
13422 wifi_setRadioEnable(index, FALSE);
13423 if (operationParam->enable == TRUE)
13424 wifi_setRadioEnable(index, TRUE);
13425 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13426
13427 return RETURN_OK;
13428}
13429
13430INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
13431{
13432 char band[64] = {0};
13433 char buf[256] = {0};
13434 char config_file[64] = {0};
13435 char cmd[128] = {0};
13436 int ret = RETURN_ERR;
13437 int mode = 0;
13438 ULONG channel = 0;
13439 BOOL enabled = FALSE;
13440
13441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13442 printf("Entering %s index = %d\n", __func__, (int)index);
13443
13444 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
13445 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
13446 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
13447 {
13448 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
13449 return RETURN_ERR;
13450 }
13451 operationParam->enable = enabled;
13452
13453 memset(band, 0, sizeof(band));
13454 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
13455 {
13456 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
13457 return RETURN_ERR;
13458 }
13459
13460 if (!strcmp(band, "2.4GHz"))
13461 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
13462 else if (!strcmp(band, "5GHz"))
13463 operationParam->band = WIFI_FREQUENCY_5_BAND;
13464 else if (!strcmp(band, "6GHz"))
13465 operationParam->band = WIFI_FREQUENCY_6_BAND;
13466 else
13467 {
13468 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
13469 band);
13470 }
13471
13472 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
13473 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
13474 operationParam->channel = 0;
13475 operationParam->autoChannelEnabled = TRUE;
13476 } else {
13477 operationParam->channel = strtol(buf, NULL, 10);
13478 operationParam->autoChannelEnabled = FALSE;
13479 }
13480
13481 memset(buf, 0, sizeof(buf));
13482 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
13483 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
13484 return RETURN_ERR;
13485 }
13486 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
13487 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
13488 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
13489 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
13490 else
13491 {
13492 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
13493 return false;
13494 }
13495
13496 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
13497 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
13498 return RETURN_ERR;
13499 }
13500 // Two different definition bit map, so need to check every bit.
13501 if (mode & WIFI_MODE_A)
13502 operationParam->variant |= WIFI_80211_VARIANT_A;
13503 if (mode & WIFI_MODE_B)
13504 operationParam->variant |= WIFI_80211_VARIANT_B;
13505 if (mode & WIFI_MODE_G)
13506 operationParam->variant |= WIFI_80211_VARIANT_G;
13507 if (mode & WIFI_MODE_N)
13508 operationParam->variant |= WIFI_80211_VARIANT_N;
13509 if (mode & WIFI_MODE_AC)
13510 operationParam->variant |= WIFI_80211_VARIANT_AC;
13511 if (mode & WIFI_MODE_AX)
13512 operationParam->variant |= WIFI_80211_VARIANT_AX;
13513 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
13514 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
13515 return RETURN_ERR;
13516 }
13517 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
13518 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
13519 return RETURN_ERR;
13520 }
13521 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
13522 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
13523 return RETURN_ERR;
13524 }
13525
13526 memset(buf, 0, sizeof(buf));
13527 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
13528 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
13529 return RETURN_ERR;
13530 }
13531 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
13532
13533 memset(buf, 0, sizeof(buf));
13534 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
13535 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
13536 return RETURN_ERR;
13537 }
13538 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
13539
13540 memset(buf, 0, sizeof(buf));
13541 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
13542 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
13543
13544 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
13545 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
13546 return RETURN_ERR;
13547 }
developera1255e42023-05-13 17:45:02 +080013548 if (wifi_getRadioPercentageTransmitPower(index, (ULONG *)&operationParam->transmitPower) != RETURN_OK) {
developer72fb0bb2023-01-11 09:46:29 +080013549 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
13550 return RETURN_ERR;
13551 }
13552
13553 memset(buf, 0, sizeof(buf));
13554 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
13555 if (strcmp(buf, "-1") == 0) {
13556 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
13557 operationParam->ctsProtection = FALSE;
13558 } else {
13559 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
13560 operationParam->ctsProtection = TRUE;
13561 }
13562
13563 memset(buf, 0, sizeof(buf));
13564 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
13565 if (strcmp(buf, "0") == 0)
13566 operationParam->obssCoex = FALSE;
13567 else
13568 operationParam->obssCoex = TRUE;
13569
13570 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
13571 _syscmd(cmd, buf, sizeof(buf));
13572 if (strlen(buf) != 0)
13573 operationParam->stbcEnable = TRUE;
13574 else
13575 operationParam->stbcEnable = FALSE;
13576
13577 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
13578 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
13579 return RETURN_ERR;
13580 }
13581
13582 // Below value is hardcoded
13583
13584 operationParam->numSecondaryChannels = 0;
13585 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
13586 operationParam->channelSecondary[i] = 0;
13587 }
13588 operationParam->csa_beacon_count = 15;
13589 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
13590
13591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13592 return RETURN_OK;
13593}
13594
13595static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
13596{
13597 int max_radio_num = 0;
13598
13599 wifi_getMaxRadioNumber(&max_radio_num);
13600 if (radioIndex >= max_radio_num) {
13601 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
13602 return RETURN_ERR;
13603 }
13604
13605 return (arrayIndex * max_radio_num) + radioIndex;
13606}
13607
developer96b38512023-02-22 11:17:45 +080013608static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
13609{
13610 int max_radio_num = 0;
13611
13612 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
13613 return -1;
13614
13615 wifi_getMaxRadioNumber(&max_radio_num);
13616
13617 (*radioIndex) = vapIndex % max_radio_num;
13618 (*arrayIndex) = vapIndex / max_radio_num;
13619
13620 return 0;
13621}
13622
13623
developer72fb0bb2023-01-11 09:46:29 +080013624wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
13625 if (strncmp(beaconRate, "1Mbps", 5) == 0)
13626 return WIFI_BITRATE_1MBPS;
13627 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
13628 return WIFI_BITRATE_2MBPS;
13629 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
13630 return WIFI_BITRATE_5_5MBPS;
13631 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
13632 return WIFI_BITRATE_6MBPS;
13633 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
13634 return WIFI_BITRATE_9MBPS;
13635 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
13636 return WIFI_BITRATE_11MBPS;
13637 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
13638 return WIFI_BITRATE_12MBPS;
13639 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
13640 return WIFI_BITRATE_18MBPS;
13641 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
13642 return WIFI_BITRATE_24MBPS;
13643 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
13644 return WIFI_BITRATE_36MBPS;
13645 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
13646 return WIFI_BITRATE_48MBPS;
13647 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
13648 return WIFI_BITRATE_54MBPS;
13649 return WIFI_BITRATE_DEFAULT;
13650}
13651
13652INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
13653{
13654 if (beacon == WIFI_BITRATE_1MBPS)
13655 strcpy(beacon_str, "1Mbps");
13656 else if (beacon == WIFI_BITRATE_2MBPS)
13657 strcpy(beacon_str, "2Mbps");
13658 else if (beacon == WIFI_BITRATE_5_5MBPS)
13659 strcpy(beacon_str, "5.5Mbps");
13660 else if (beacon == WIFI_BITRATE_6MBPS)
13661 strcpy(beacon_str, "6Mbps");
13662 else if (beacon == WIFI_BITRATE_9MBPS)
13663 strcpy(beacon_str, "9Mbps");
13664 else if (beacon == WIFI_BITRATE_11MBPS)
13665 strcpy(beacon_str, "11Mbps");
13666 else if (beacon == WIFI_BITRATE_12MBPS)
13667 strcpy(beacon_str, "12Mbps");
13668 else if (beacon == WIFI_BITRATE_18MBPS)
13669 strcpy(beacon_str, "18Mbps");
13670 else if (beacon == WIFI_BITRATE_24MBPS)
13671 strcpy(beacon_str, "24Mbps");
13672 else if (beacon == WIFI_BITRATE_36MBPS)
13673 strcpy(beacon_str, "36Mbps");
13674 else if (beacon == WIFI_BITRATE_48MBPS)
13675 strcpy(beacon_str, "48Mbps");
13676 else if (beacon == WIFI_BITRATE_54MBPS)
13677 strcpy(beacon_str, "54Mbps");
13678 return RETURN_OK;
13679}
13680
13681INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13682{
13683 INT mode = 0;
13684 INT ret = -1;
13685 INT output = 0;
13686 int i = 0;
13687 int vap_index = 0;
13688 BOOL enabled = FALSE;
13689 char buf[256] = {0};
13690 wifi_vap_security_t security = {0};
13691 map->num_vaps = 5; // Hardcoded
13692
13693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13694 printf("Entering %s index = %d\n", __func__, (int)index);
13695
13696 for (i = 0; i < 5; i++)
13697 {
13698 map->vap_array[i].radio_index = index;
13699
13700 vap_index = array_index_to_vap_index(index, i);
13701 if (vap_index < 0)
13702 return RETURN_ERR;
13703
13704 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
13705
13706 map->vap_array[i].vap_index = vap_index;
13707
13708 memset(buf, 0, sizeof(buf));
13709 ret = wifi_getApName(vap_index, buf);
13710 if (ret != RETURN_OK) {
13711 printf("%s: wifi_getApName return error\n", __func__);
13712 return RETURN_ERR;
13713 }
13714 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
13715
13716 memset(buf, 0, sizeof(buf));
13717 ret = wifi_getSSIDName(vap_index, buf);
13718 if (ret != RETURN_OK) {
13719 printf("%s: wifi_getSSIDName return error\n", __func__);
13720 return RETURN_ERR;
13721 }
13722 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
13723
13724 ret = wifi_getSSIDEnable(vap_index, &enabled);
13725 if (ret != RETURN_OK) {
13726 printf("%s: wifi_getSSIDEnable return error\n", __func__);
13727 return RETURN_ERR;
13728 }
13729 map->vap_array[i].u.bss_info.enabled = enabled;
13730
13731 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
13732 if (ret != RETURN_OK) {
13733 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
13734 return RETURN_ERR;
13735 }
13736 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080013737
developer72fb0bb2023-01-11 09:46:29 +080013738 ret = wifi_getApIsolationEnable(vap_index, &enabled);
13739 if (ret != RETURN_OK) {
13740 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
13741 return RETURN_ERR;
13742 }
13743 map->vap_array[i].u.bss_info.isolation = enabled;
13744
13745 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
13746 if (ret != RETURN_OK) {
13747 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
13748 return RETURN_ERR;
13749 }
13750 map->vap_array[i].u.bss_info.bssMaxSta = output;
13751
13752 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
13753 if (ret != RETURN_OK) {
13754 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
13755 return RETURN_ERR;
13756 }
13757 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
13758
13759 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
13760 if (ret != RETURN_OK) {
13761 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
13762 return RETURN_ERR;
13763 }
13764 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
13765
13766 ret = wifi_getApSecurity(vap_index, &security);
13767 if (ret != RETURN_OK) {
13768 printf("%s: wifi_getApSecurity return error\n", __func__);
13769 return RETURN_ERR;
13770 }
13771 map->vap_array[i].u.bss_info.security = security;
13772
13773 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
13774 if (ret != RETURN_OK) {
13775 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
13776 return RETURN_ERR;
13777 }
developer69b61b02023-03-07 17:17:44 +080013778 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080013779 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080013780 else
developer72fb0bb2023-01-11 09:46:29 +080013781 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080013782 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080013783 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080013784 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080013785 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
13786
13787 ret = wifi_getApWmmEnable(vap_index, &enabled);
13788 if (ret != RETURN_OK) {
13789 printf("%s: wifi_getApWmmEnable return error\n", __func__);
13790 return RETURN_ERR;
13791 }
13792 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
13793
13794 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
13795 if (ret != RETURN_OK) {
13796 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
13797 return RETURN_ERR;
13798 }
13799 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
13800
13801 memset(buf, 0, sizeof(buf));
13802 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
13803 if (ret != RETURN_OK) {
13804 printf("%s: wifi_getApBeaconRate return error\n", __func__);
13805 return RETURN_ERR;
13806 }
13807 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
13808
13809 memset(buf, 0, sizeof(buf));
13810 ret = wifi_getBaseBSSID(vap_index, buf);
13811 if (ret != RETURN_OK) {
13812 printf("%s: wifi_getBaseBSSID return error\n", __func__);
13813 return RETURN_ERR;
13814 }
13815 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
13816 &map->vap_array[i].u.bss_info.bssid[0],
13817 &map->vap_array[i].u.bss_info.bssid[1],
13818 &map->vap_array[i].u.bss_info.bssid[2],
13819 &map->vap_array[i].u.bss_info.bssid[3],
13820 &map->vap_array[i].u.bss_info.bssid[4],
13821 &map->vap_array[i].u.bss_info.bssid[5]);
13822 // fprintf(stderr, "%s index %d: mac: %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", __func__, vap_index, map->vap_array[i].u.bss_info.bssid[0], map->vap_array[i].u.bss_info.bssid[1], map->vap_array[i].u.bss_info.bssid[2], map->vap_array[i].u.bss_info.bssid[3], map->vap_array[i].u.bss_info.bssid[4], map->vap_array[i].u.bss_info.bssid[5]);
13823
13824 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
13825 if (ret != RETURN_OK) {
13826 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
13827 return RETURN_ERR;
13828 }
13829 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
13830
13831 // TODO: wps, noack
13832 }
13833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13834 return RETURN_OK;
13835}
13836
developer47cc27a2023-05-17 23:09:58 +080013837void checkVapStatus(int apIndex, BOOL *enable)
developer72fb0bb2023-01-11 09:46:29 +080013838{
13839 char if_name[16] = {0};
13840 char cmd[128] = {0};
13841 char buf[128] = {0};
13842
13843 *enable = FALSE;
13844 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
13845 return;
13846
13847 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
13848 _syscmd(cmd, buf, sizeof(buf));
13849 if (strlen(buf) > 0)
13850 *enable = TRUE;
13851 return;
13852}
13853
13854static int prepareInterface(UINT apIndex, char *new_interface)
13855{
13856 char cur_interface[16] = {0};
13857 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080013858 char cmd[MAX_CMD_SIZE] = {0};
13859 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080013860 int max_radio_num = 0;
13861 int radioIndex = -1;
13862 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080013863 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080013864
13865 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
13866 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
13867
13868 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080013869 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080013870 radioIndex = apIndex % max_radio_num;
13871 phyIndex = radio_index_to_phy(radioIndex);
13872 // disable and del old interface, then add new interface
13873 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080013874
13875 params.name = "interface";
13876 params.value = new_interface;
13877 wifi_hostapdWrite(config_file, &params, 1);
13878
13879 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
13880 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080013881 }
developer8a3bbbf2023-03-15 17:47:23 +080013882
developer72fb0bb2023-01-11 09:46:29 +080013883 // update the vap status file
13884 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
13885 _syscmd(cmd, buf, sizeof(buf));
13886 return RETURN_OK;
13887}
13888
13889INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
13890{
13891 char interface_name[16] = {0};
13892 unsigned int i;
13893 wifi_vap_info_t *vap_info = NULL;
13894 int acl_mode;
13895 int ret = 0;
13896 char *sec_str = NULL;
13897 char buf[256] = {0};
13898 char cmd[128] = {0};
13899 char config_file[64] = {0};
13900 char bssid[32] = {0};
13901 char psk_file[64] = {0};
developer47cc27a2023-05-17 23:09:58 +080013902 BOOL enable = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013903
13904 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13905 printf("Entering %s index = %d\n", __func__, (int)index);
13906 for (i = 0; i < map->num_vaps; i++)
13907 {
13908 multiple_set = TRUE;
13909 vap_info = &map->vap_array[i];
13910
13911 // Check vap status file to enable multiple ap if the system boot.
13912 checkVapStatus(vap_info->vap_index, &enable);
13913 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
13914 continue;
13915
13916 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
13917
13918 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
13919 enable = FALSE;
13920
13921 // multi-ap first up need to copy current radio config
13922 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
13923 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
13924 _syscmd(cmd, buf, sizeof(buf));
13925 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
13926 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
13927 } else {
13928 // Check whether the interface name is valid or this ap change it.
13929 int apIndex = -1;
13930 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
13931 if (apIndex != -1 && apIndex != vap_info->vap_index)
13932 continue;
13933 prepareInterface(vap_info->vap_index, vap_info->vap_name);
13934 }
13935
13936 struct params params[3];
13937 params[0].name = "interface";
13938 params[0].value = vap_info->vap_name;
13939 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
13940 params[1].name = "bssid";
13941 params[1].value = bssid;
13942 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
13943 params[2].name = "wpa_psk_file";
13944 params[2].value = psk_file;
13945
13946 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
13947 wifi_hostapdWrite(config_file, params, 3);
13948
13949 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
13950 _syscmd(cmd, buf, sizeof(buf));
13951
13952 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
13953 if (ret != RETURN_OK) {
13954 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
13955 return RETURN_ERR;
13956 }
13957
13958 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
13959 if (ret != RETURN_OK) {
13960 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
13961 return RETURN_ERR;
13962 }
13963
13964 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
13965 if (ret != RETURN_OK) {
13966 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
13967 return RETURN_ERR;
13968 }
13969
13970 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
13971 if (ret != RETURN_OK) {
13972 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
13973 return RETURN_ERR;
13974 }
13975
13976 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
13977 if (ret != RETURN_OK) {
13978 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
13979 return RETURN_ERR;
13980 }
13981
13982 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
13983 if (ret != RETURN_OK) {
13984 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
13985 return RETURN_ERR;
13986 }
13987
13988 if (vap_info->u.bss_info.mac_filter_enable == false){
13989 acl_mode = 0;
13990 }else {
13991 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
13992 acl_mode = 2;
13993 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
13994 _syscmd(cmd, buf, sizeof(buf));
13995 }else{
13996 acl_mode = 1;
13997 }
13998 }
13999
14000 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
14001 if (ret != RETURN_OK) {
14002 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
14003 return RETURN_ERR;
14004 }
14005
14006 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
14007 if (ret != RETURN_OK) {
14008 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
14009 return RETURN_ERR;
14010 }
14011
developer0f10c772023-05-16 21:43:39 +080014012 memset(buf, 0, sizeof(buf));
14013 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
14014 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
14015 if (ret != RETURN_OK) {
14016 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
14017 return RETURN_ERR;
14018 }
developer72fb0bb2023-01-11 09:46:29 +080014019
14020 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
14021 if (ret != RETURN_OK) {
14022 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
14023 return RETURN_ERR;
14024 }
14025
developer72fb0bb2023-01-11 09:46:29 +080014026 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
14027 if (ret != RETURN_OK) {
14028 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
14029 return RETURN_ERR;
14030 }
14031
developer23e71282023-01-18 10:25:19 +080014032 wifi_setApEnable(vap_info->vap_index, FALSE);
14033 wifi_setApEnable(vap_info->vap_index, TRUE);
14034 multiple_set = FALSE;
14035
14036 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080014037 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
14038 if (ret != RETURN_OK) {
14039 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
14040 return RETURN_ERR;
14041 }
14042
14043 // TODO mgmtPowerControl, interworking, wps
14044 }
14045 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14046 return RETURN_OK;
14047}
14048
14049int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
14050{
14051 char *token, *next;
14052 const char s[2] = ",";
14053 int count =0;
14054
14055 /* get the first token */
14056 token = strtok_r(pchannels, s, &next);
14057
14058 /* walk through other tokens */
14059 while( token != NULL && count < MAX_CHANNELS) {
14060 chlistptr->channels_list[count++] = atoi(token);
14061 token = strtok_r(NULL, s, &next);
14062 }
14063
14064 return count;
14065}
14066
14067static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
14068{
14069 INT status;
14070 wifi_channels_list_t *chlistp;
14071 CHAR output_string[64];
14072 CHAR pchannels[128];
14073 CHAR interface_name[16] = {0};
14074 wifi_band band;
14075
14076 if(rcap == NULL)
14077 {
14078 return RETURN_ERR;
14079 }
14080
14081 rcap->numSupportedFreqBand = 1;
14082 band = wifi_index_to_band(radioIndex);
14083
14084 if (band == band_2_4)
14085 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
14086 else if (band == band_5)
14087 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
14088 else if (band == band_6)
14089 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
14090
14091 chlistp = &(rcap->channel_list[0]);
14092 memset(pchannels, 0, sizeof(pchannels));
14093
14094 /* possible number of radio channels */
14095 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
14096 {
14097 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
14098 }
14099 /* Number of channels and list*/
14100 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
14101
14102 /* autoChannelSupported */
14103 /* always ON with wifi_getRadioAutoChannelSupported */
14104 rcap->autoChannelSupported = TRUE;
14105
14106 /* DCSSupported */
14107 /* always ON with wifi_getRadioDCSSupported */
14108 rcap->DCSSupported = TRUE;
14109
14110 /* zeroDFSSupported - TBD */
14111 rcap->zeroDFSSupported = FALSE;
14112
14113 /* Supported Country List*/
14114 memset(output_string, 0, sizeof(output_string));
14115 status = wifi_getRadioCountryCode(radioIndex, output_string);
14116 if( status != 0 ) {
14117 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
14118 return RETURN_ERR;
14119 } else {
14120 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
14121 }
14122 if(!strcmp(output_string,"US")){
14123 rcap->countrySupported[0] = wifi_countrycode_US;
14124 rcap->countrySupported[1] = wifi_countrycode_CA;
14125 } else if (!strcmp(output_string,"CA")) {
14126 rcap->countrySupported[0] = wifi_countrycode_CA;
14127 rcap->countrySupported[1] = wifi_countrycode_US;
14128 } else {
14129 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
14130 }
14131
14132 rcap->numcountrySupported = 2;
14133
14134 /* csi */
14135 rcap->csi.maxDevices = 8;
14136 rcap->csi.soudingFrameSupported = TRUE;
14137
14138 wifi_GetInterfaceName(radioIndex, interface_name);
14139 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
14140
14141 /* channelWidth - all supported bandwidths */
14142 int i=0;
14143 rcap->channelWidth[i] = 0;
14144 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
14145 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
14146 WIFI_CHANNELBANDWIDTH_40MHZ);
14147
14148 }
14149 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
14150 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
14151 WIFI_CHANNELBANDWIDTH_40MHZ |
14152 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
14153 }
14154
14155
14156 /* mode - all supported variants */
14157 // rcap->mode[i] = WIFI_80211_VARIANT_H;
14158 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
14159 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
14160 }
14161 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
14162 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
14163 }
14164 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
14165 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
14166 }
14167 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
14168 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
14169
14170 /* supportedBitRate - all supported bitrates */
14171 rcap->supportedBitRate[i] = 0;
14172 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
14173 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
14174 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
14175 }
14176 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
14177 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
14178 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
14179 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
14180 }
14181
14182
14183 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
14184 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
14185 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
14186 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
14187 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
14188 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
14189 rcap->cipherSupported = 0;
14190 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
14191 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
14192
14193 return RETURN_OK;
14194}
14195
14196INT wifi_getHalCapability(wifi_hal_capability_t *cap)
14197{
14198 INT status = 0, radioIndex = 0;
14199 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
14200 int iter = 0;
14201 unsigned int j = 0;
14202 int max_num_radios;
14203 wifi_interface_name_idex_map_t *iface_info = NULL;
14204
14205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14206
14207 memset(cap, 0, sizeof(wifi_hal_capability_t));
14208
14209 /* version */
14210 cap->version.major = WIFI_HAL_MAJOR_VERSION;
14211 cap->version.minor = WIFI_HAL_MINOR_VERSION;
14212
14213 /* number of radios platform property */
14214 wifi_getMaxRadioNumber(&max_num_radios);
14215 cap->wifi_prop.numRadios = max_num_radios;
14216
14217 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
14218 {
14219 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
14220 if (status != 0) {
14221 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
14222 return RETURN_ERR;
14223 }
14224
14225 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
14226 {
14227 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
14228 {
14229 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
14230 return RETURN_ERR;
14231 }
14232 iface_info = &cap->wifi_prop.interface_map[iter];
14233 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
14234 iface_info->rdk_radio_index = radioIndex;
14235 memset(output, 0, sizeof(output));
14236 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
14237 {
14238 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
14239 }
14240 // TODO: bridge name
14241 // TODO: vlan id
14242 // TODO: primary
14243 iface_info->index = array_index_to_vap_index(radioIndex, j);
14244 memset(output, 0, sizeof(output));
14245 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
14246 {
14247 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
14248 }
14249 iter++;
14250 }
14251 }
14252
14253 cap->BandSteeringSupported = FALSE;
14254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14255 return RETURN_OK;
14256}
14257
14258INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
14259{
14260 struct params h_config={0};
14261 char config_file[64] = {0};
14262
14263 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14264
14265 h_config.name = "okc";
14266 h_config.value = okc_enable?"1":"0";
14267
14268 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14269 wifi_hostapdWrite(config_file, &h_config, 1);
14270 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14271
14272 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14273 return RETURN_OK;
14274}
14275
14276INT wifi_setSAEMFP(int ap_index, BOOL enable)
14277{
14278 struct params h_config={0};
14279 char config_file[64] = {0};
14280 char buf[128] = {0};
14281
14282 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14283
14284 h_config.name = "sae_require_mfp";
14285 h_config.value = enable?"1":"0";
14286
14287 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14288 wifi_hostapdWrite(config_file, &h_config, 1);
14289 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14290
14291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14292 return RETURN_OK;
14293}
14294
14295INT wifi_setSAEpwe(int ap_index, int sae_pwe)
14296{
14297 struct params h_config={0};
14298 char config_file[64] = {0};
14299 char buf[128] = {0};
14300
14301 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14302
14303 h_config.name = "sae_pwe";
14304 snprintf(buf, sizeof(buf), "%d", sae_pwe);
14305 h_config.value = buf;
14306
14307 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14308 wifi_hostapdWrite(config_file, &h_config, 1);
14309 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14310
14311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14312 return RETURN_OK;
14313}
14314
14315INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
14316{
14317 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
14318 struct params h_config={0};
14319 char config_file[64] = {0};
14320
14321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
14322
14323 h_config.name = "wpa_disable_eapol_key_retries";
14324 h_config.value = disable_EAPOL_retries?"1":"0";
14325
14326 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
14327 wifi_hostapdWrite(config_file, &h_config, 1);
14328 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
14329
14330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
14331 return RETURN_OK;
14332}
14333
14334INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
14335{
14336 char buf[128] = {0};
14337 char config_file[128] = {0};
developere5750452023-05-15 16:46:42 +080014338 char cmd[128] = {0};
developer72fb0bb2023-01-11 09:46:29 +080014339 char password[64] = {0};
14340 char mfp[32] = {0};
14341 char wpa_mode[32] = {0};
14342 BOOL okc_enable = FALSE;
14343 BOOL sae_MFP = FALSE;
14344 BOOL disable_EAPOL_retries = TRUE;
14345 int sae_pwe = 0;
14346 struct params params = {0};
14347 wifi_band band = band_invalid;
14348
14349 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14350
14351 multiple_set = TRUE;
14352 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14353 if (security->mode == wifi_security_mode_none) {
14354 strcpy(wpa_mode, "None");
14355 } else if (security->mode == wifi_security_mode_wpa_personal)
14356 strcpy(wpa_mode, "WPA-Personal");
14357 else if (security->mode == wifi_security_mode_wpa2_personal)
14358 strcpy(wpa_mode, "WPA2-Personal");
14359 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
14360 strcpy(wpa_mode, "WPA-WPA2-Personal");
14361 else if (security->mode == wifi_security_mode_wpa_enterprise)
14362 strcpy(wpa_mode, "WPA-Enterprise");
14363 else if (security->mode == wifi_security_mode_wpa2_enterprise)
14364 strcpy(wpa_mode, "WPA2-Enterprise");
14365 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
14366 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
14367 else if (security->mode == wifi_security_mode_wpa3_personal) {
14368 strcpy(wpa_mode, "WPA3-Personal");
14369 okc_enable = TRUE;
14370 sae_MFP = TRUE;
14371 sae_pwe = 2;
14372 disable_EAPOL_retries = FALSE;
14373 } else if (security->mode == wifi_security_mode_wpa3_transition) {
14374 strcpy(wpa_mode, "WPA3-Personal-Transition");
14375 okc_enable = TRUE;
14376 sae_MFP = TRUE;
14377 sae_pwe = 2;
14378 disable_EAPOL_retries = FALSE;
14379 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
14380 strcpy(wpa_mode, "WPA3-Enterprise");
14381 sae_MFP = TRUE;
14382 sae_pwe = 2;
14383 disable_EAPOL_retries = FALSE;
developerd01e3e82023-04-26 19:10:38 +080014384 } else if (security->mode == wifi_security_mode_enhanced_open) {
developer3086e2f2023-01-17 09:40:01 +080014385 strcpy(wpa_mode, "OWE");
14386 sae_MFP = TRUE;
14387 sae_pwe = 2;
14388 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014389 }
14390
14391 band = wifi_index_to_band(ap_index);
14392 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
14393 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
14394 return RETURN_ERR;
14395 }
14396
14397 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
14398 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
14399 wifi_setSAEMFP(ap_index, sae_MFP);
14400 wifi_setSAEpwe(ap_index, sae_pwe);
14401 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
14402
developerd01e3e82023-04-26 19:10:38 +080014403 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_enhanced_open) {
developere5750452023-05-15 16:46:42 +080014404 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_pass || security->u.key.type == wifi_security_key_type_psk_sae) {
14405 int key_len = strlen(security->u.key.key);
14406 // wpa_psk and wpa_passphrase cann;t use at the same time, the command replace one with the other.
14407 if (key_len == 64) { // set wpa_psk
14408 strncpy(password, security->u.key.key, 64); // 64 characters
14409 password[64] = '\0';
14410 wifi_setApSecurityPreSharedKey(ap_index, password);
14411 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_passphrase=/!p' %s", config_file);
14412 } else if (key_len >= 8 && key_len < 64) { // set wpa_passphrase
14413 strncpy(password, security->u.key.key, 63);
14414 password[63] = '\0';
14415 wifi_setApSecurityKeyPassphrase(ap_index, password);
14416 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^wpa_psk=/!p' %s", config_file);
14417 } else
14418 return RETURN_ERR;
14419 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014420 }
14421 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
14422 params.name = "sae_password";
14423 params.value = security->u.key.key;
14424 wifi_hostapdWrite(config_file, &params, 1);
developere5750452023-05-15 16:46:42 +080014425 } else { // remove sae_password
14426 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^sae_password=/!p' %s", config_file);
14427 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080014428 }
14429 }
14430
14431 if (security->mode != wifi_security_mode_none) {
14432 memset(&params, 0, sizeof(params));
14433 params.name = "wpa_pairwise";
14434 if (security->encr == wifi_encryption_tkip)
14435 params.value = "TKIP";
14436 else if (security->encr == wifi_encryption_aes)
14437 params.value = "CCMP";
14438 else if (security->encr == wifi_encryption_aes_tkip)
14439 params.value = "TKIP CCMP";
14440 wifi_hostapdWrite(config_file, &params, 1);
14441 }
14442
14443 if (security->mfp == wifi_mfp_cfg_disabled)
14444 strcpy(mfp, "Disabled");
14445 else if (security->mfp == wifi_mfp_cfg_optional)
14446 strcpy(mfp, "Optional");
14447 else if (security->mfp == wifi_mfp_cfg_required)
14448 strcpy(mfp, "Required");
14449 wifi_setApSecurityMFPConfig(ap_index, mfp);
14450
14451 memset(&params, 0, sizeof(params));
14452 params.name = "transition_disable";
14453 if (security->wpa3_transition_disable == TRUE)
14454 params.value = "0x01";
14455 else
14456 params.value = "0x00";
14457 wifi_hostapdWrite(config_file, &params, 1);
14458
14459 memset(&params, 0, sizeof(params));
14460 params.name = "wpa_group_rekey";
14461 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
14462 params.value = buf;
14463 wifi_hostapdWrite(config_file, &params, 1);
14464
14465 memset(&params, 0, sizeof(params));
14466 params.name = "wpa_strict_rekey";
14467 params.value = security->strict_rekey?"1":"0";
14468 wifi_hostapdWrite(config_file, &params, 1);
14469
14470 memset(&params, 0, sizeof(params));
14471 params.name = "wpa_pairwise_update_count";
developere5750452023-05-15 16:46:42 +080014472 if (security->eapol_key_retries == 0)
14473 security->eapol_key_retries = 4; // 0 is invalid, set to default value.
developer72fb0bb2023-01-11 09:46:29 +080014474 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
14475 params.value = buf;
14476 wifi_hostapdWrite(config_file, &params, 1);
14477
14478 memset(&params, 0, sizeof(params));
14479 params.name = "disable_pmksa_caching";
14480 params.value = security->disable_pmksa_caching?"1":"0";
14481 wifi_hostapdWrite(config_file, &params, 1);
14482
developer23e71282023-01-18 10:25:19 +080014483 if (multiple_set == FALSE) {
14484 wifi_setApEnable(ap_index, FALSE);
14485 wifi_setApEnable(ap_index, TRUE);
14486 }
developer72fb0bb2023-01-11 09:46:29 +080014487
14488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14489
14490 return RETURN_OK;
14491}
14492
14493INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
14494{
14495 char buf[256] = {0};
14496 char config_file[128] = {0};
14497 int disable = 0;
developere5750452023-05-15 16:46:42 +080014498 bool set_sae = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080014499
14500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14501 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
14502 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
14503 security->mode = wifi_security_mode_none;
14504 if (strlen(buf) != 0) {
14505 if (!strcmp(buf, "WPA-Personal"))
14506 security->mode = wifi_security_mode_wpa_personal;
14507 else if (!strcmp(buf, "WPA2-Personal"))
14508 security->mode = wifi_security_mode_wpa2_personal;
14509 else if (!strcmp(buf, "WPA-WPA2-Personal"))
14510 security->mode = wifi_security_mode_wpa_wpa2_personal;
14511 else if (!strcmp(buf, "WPA-Enterprise"))
14512 security->mode = wifi_security_mode_wpa_enterprise;
14513 else if (!strcmp(buf, "WPA2-Enterprise"))
14514 security->mode = wifi_security_mode_wpa2_enterprise;
14515 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
14516 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
14517 else if (!strcmp(buf, "WPA3-Personal"))
14518 security->mode = wifi_security_mode_wpa3_personal;
14519 else if (!strcmp(buf, "WPA3-Personal-Transition"))
14520 security->mode = wifi_security_mode_wpa3_transition;
14521 else if (!strcmp(buf, "WPA3-Enterprise"))
14522 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080014523 else if (!strcmp(buf, "OWE"))
developerd01e3e82023-04-26 19:10:38 +080014524 security->mode = wifi_security_mode_enhanced_open;
developer72fb0bb2023-01-11 09:46:29 +080014525 }
14526
14527 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
14528 if (security->mode == wifi_security_mode_none)
14529 security->encr = wifi_encryption_none;
14530 else {
14531 if (strcmp(buf, "TKIP") == 0)
14532 security->encr = wifi_encryption_tkip;
14533 else if (strcmp(buf, "CCMP") == 0)
14534 security->encr = wifi_encryption_aes;
14535 else
14536 security->encr = wifi_encryption_aes_tkip;
14537 }
14538
14539 if (security->mode != wifi_encryption_none) {
14540 memset(buf, 0, sizeof(buf));
14541 // wpa3 can use one or both configs as password, so we check sae_password first.
14542 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
developere5750452023-05-15 16:46:42 +080014543 if (strlen(buf) != 0) {
14544 if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
14545 security->u.key.type = wifi_security_key_type_sae;
14546 set_sae = TRUE;
14547 strncpy(security->u.key.key, buf, sizeof(buf));
14548 }
14549 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
14550 if (strlen(buf) != 0){
14551 if (set_sae == TRUE)
14552 security->u.key.type = wifi_security_key_type_psk_sae;
14553 else if (strlen(buf) == 64)
14554 security->u.key.type = wifi_security_key_type_psk;
14555 else
14556 security->u.key.type = wifi_security_key_type_pass;
14557 strncpy(security->u.key.key, buf, sizeof(security->u.key.key));
developer72fb0bb2023-01-11 09:46:29 +080014558 }
developer72fb0bb2023-01-11 09:46:29 +080014559 security->u.key.key[255] = '\0';
14560 }
14561
14562 memset(buf, 0, sizeof(buf));
14563 wifi_getApSecurityMFPConfig(ap_index, buf);
14564 if (strcmp(buf, "Disabled") == 0)
14565 security->mfp = wifi_mfp_cfg_disabled;
14566 else if (strcmp(buf, "Optional") == 0)
14567 security->mfp = wifi_mfp_cfg_optional;
14568 else if (strcmp(buf, "Required") == 0)
14569 security->mfp = wifi_mfp_cfg_required;
14570
14571 memset(buf, 0, sizeof(buf));
14572 security->wpa3_transition_disable = FALSE;
14573 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
14574 disable = strtol(buf, NULL, 16);
14575 if (disable != 0)
14576 security->wpa3_transition_disable = TRUE;
14577
14578 memset(buf, 0, sizeof(buf));
14579 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
14580 if (strlen(buf) == 0)
14581 security->rekey_interval = 86400;
14582 else
14583 security->rekey_interval = strtol(buf, NULL, 10);
14584
14585 memset(buf, 0, sizeof(buf));
14586 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
14587 if (strlen(buf) == 0)
14588 security->strict_rekey = 1;
14589 else
14590 security->strict_rekey = strtol(buf, NULL, 10);
14591
14592 memset(buf, 0, sizeof(buf));
14593 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
14594 if (strlen(buf) == 0)
14595 security->eapol_key_retries = 4;
14596 else
14597 security->eapol_key_retries = strtol(buf, NULL, 10);
14598
14599 memset(buf, 0, sizeof(buf));
14600 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
14601 if (strlen(buf) == 0)
14602 security->disable_pmksa_caching = FALSE;
14603 else
14604 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
14605
14606 /* TODO
14607 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
14608 */
14609 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
14610 security->eap_identity_req_timeout = 0;
14611 security->eap_identity_req_retries = 0;
14612 security->eap_req_timeout = 0;
14613 security->eap_req_retries = 0;
14614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14615 return RETURN_OK;
14616}
14617
14618#endif /* WIFI_HAL_VERSION_3 */
14619
14620#ifdef WIFI_HAL_VERSION_3_PHASE2
14621INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
14622{
14623 char interface_name[16] = {0};
14624 char cmd[128] = {0};
14625 char buf[128] = {0};
14626 char *mac_addr = NULL;
14627 BOOL status = FALSE;
14628 size_t len = 0;
14629
14630 if(ap_index > MAX_APS)
14631 return RETURN_ERR;
14632
14633 *output_numDevices = 0;
14634 wifi_getApEnable(ap_index, &status);
14635 if (status == FALSE)
14636 return RETURN_OK;
14637
14638 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14639 return RETURN_ERR;
14640 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
14641 _syscmd(cmd, buf, sizeof(buf));
14642
14643 mac_addr = strtok(buf, "\n");
14644 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
14645 *output_numDevices = i + 1;
14646 fprintf(stderr, "mac_addr: %s\n", mac_addr);
14647 addr_ptr = output_deviceMacAddressArray[i];
14648 mac_addr_aton(addr_ptr, mac_addr);
14649 mac_addr = strtok(NULL, "\n");
14650 }
14651
14652 return RETURN_OK;
14653}
14654#else
14655INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
14656{
14657 char interface_name[16] = {0};
14658 char cmd[128];
14659 BOOL status = false;
14660
14661 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
14662 return RETURN_ERR;
14663
14664 output_buf[0] = '\0';
14665
14666 wifi_getApEnable(ap_index,&status);
14667 if (!status)
14668 return RETURN_OK;
14669
14670 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
14671 return RETURN_ERR;
14672 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
14673 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080014674
developer72fb0bb2023-01-11 09:46:29 +080014675 return RETURN_OK;
14676}
14677#endif
14678
14679INT wifi_getProxyArp(INT apIndex, BOOL *enable)
14680{
14681 char output[16]={'\0'};
14682 char config_file[MAX_BUF_SIZE] = {0};
14683
14684 if (!enable)
14685 return RETURN_ERR;
14686
14687 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
14688 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
14689
14690 if (strlen(output) == 0)
14691 *enable = FALSE;
14692 else if (strncmp(output, "1", 1) == 0)
14693 *enable = TRUE;
14694 else
14695 *enable = FALSE;
14696
14697 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
14698 return RETURN_OK;
14699}
14700
14701INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
14702{
14703 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
14704 return RETURN_ERR;
14705 *output_enable=TRUE;
14706 return RETURN_OK;
14707}
14708
14709INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
14710{
14711 char cmd[128] = {0};
14712 char buf[128] = {0};
14713 char line[128] = {0};
14714 size_t len = 0;
14715 FILE *f = NULL;
14716 int index = 0;
14717 int exp = 0;
14718 int mantissa = 0;
14719 int duration = 0;
14720 int radio_index = 0;
14721 int max_radio_num = 0;
14722 uint twt_wake_interval = 0;
14723 int phyId = 0;
14724 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
14725
14726 wifi_getMaxRadioNumber(&max_radio_num);
14727
14728 radio_index = ap_index % max_radio_num;
14729
14730 phyId = radio_index_to_phy(radio_index);
14731 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
14732 _syscmd(cmd, buf, sizeof(buf));
14733 *numSessionReturned = strtol(buf, NULL, 10) - 1;
14734 if (*numSessionReturned > maxNumberSessions)
14735 *numSessionReturned = maxNumberSessions;
14736 else if (*numSessionReturned < 1) {
14737 *numSessionReturned = 0;
14738 return RETURN_OK;
14739 }
14740
14741 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
14742 if ((f = popen(cmd, "r")) == NULL) {
14743 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
14744 return RETURN_ERR;
14745 }
14746
14747 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
14748 while((fgets(line, sizeof(line), f)) != NULL) {
14749 char *tmp = NULL;
14750 strcpy(buf, line);
14751 tmp = strtok(buf, " ");
14752 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
14753 tmp = strtok(NULL, " ");
14754 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
14755 tmp = strtok(NULL, " ");
14756 if (strstr(tmp, "t")) {
14757 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
14758 }
14759 if (strstr(tmp, "a")) {
14760 twtSessions[index].twtParameters.operation.announced = TRUE;
14761 }
14762 tmp = strtok(NULL, " ");
14763 exp = strtol(tmp, NULL, 10);
14764 tmp = strtok(NULL, " ");
14765 mantissa = strtol(tmp, NULL, 10);
14766 tmp = strtok(NULL, " ");
14767 duration = strtol(tmp, NULL, 10);
14768
14769 // only implicit supported
14770 twtSessions[index].twtParameters.operation.implicit = TRUE;
14771 // only individual agreement supported
14772 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
14773
14774 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
14775 twt_wake_interval = mantissa * (1 << exp);
14776 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
14777 // Overflow handling
14778 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
14779 } else {
14780 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
14781 }
14782 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
14783 index++;
14784 }
14785
14786 pclose(f);
14787 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
14788 return RETURN_OK;
14789}