blob: d43065d8d57679fb5d4d344d2b4092e9e1da11a4 [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>
57#include<net/if.h>
58#endif
59
60#include <ev.h>
61#include <wpa_ctrl.h>
62#include <errno.h>
63#include <time.h>
64#define MAC_ALEN 6
65
66#define MAX_BUF_SIZE 256
67#define MAX_CMD_SIZE 256
68#define IF_NAME_SIZE 16
69#define CONFIG_PREFIX "/nvram/hostapd"
70#define ACL_PREFIX "/nvram/hostapd-acl"
71#define DENY_PREFIX "/nvram/hostapd-deny"
72//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
73#define SOCK_PREFIX "/var/run/hostapd/wifi"
74#define VAP_STATUS_FILE "/nvram/vap-status"
75#define ESSID_FILE "/tmp/essid"
76#define GUARD_INTERVAL_FILE "/nvram/guard-interval"
77#define CHANNEL_STATS_FILE "/tmp/channel_stats"
78#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
79#define VLAN_FILE "/nvram/hostapd.vlan"
80#define PSK_FILE "/nvram/hostapd"
81#define MCS_FILE "/tmp/MCS"
82#define NOACK_MAP_FILE "/tmp/NoAckMap"
83
84#define BRIDGE_NAME "brlan0"
85
86/*
87 MAX_APS - Number of all AP available in system
88 2x Home AP
89 2x Backhaul AP
90 2x Guest AP
91 2x Secure Onboard AP
92 2x Service AP
93
94*/
95
96
97#define MAX_APS MAX_NUM_RADIOS*5
developer7e4a2a62023-04-06 19:56:03 +080098
99#define PREFIX_WIFI2G "ra"
100#define PREFIX_WIFI5G "rai"
101#define PREFIX_WIFI6G "rax"
developer72fb0bb2023-01-11 09:46:29 +0800102
103#ifndef RADIO_PREFIX
104#define RADIO_PREFIX "wlan"
105#endif
106
107#define MAX_ASSOCIATED_STA_NUM 2007
108
109//Uncomment to enable debug logs
110//#define WIFI_DEBUG
111
112#ifdef WIFI_DEBUG
113#define wifi_dbg_printf printf
114#define WIFI_ENTRY_EXIT_DEBUG printf
115#else
116#define wifi_dbg_printf(format, args...) printf("")
117#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
118#endif
119
120#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
121#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
122#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
123#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
124#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
125#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
126#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
127#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
128#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
129#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
130
131#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
132
133#define BW_FNAME "/nvram/bw_file.txt"
134
135#define PS_MAX_TID 16
136
developer96b38512023-02-22 11:17:45 +0800137#define MAX_CARD_INDEX 3
138
developer72fb0bb2023-01-11 09:46:29 +0800139static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
141 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
142 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
143 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
144 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
145 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
146 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
147 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
150 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
151 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
153 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
155 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
156};
157
158typedef unsigned long long u64;
159
160/* Enum to define WiFi Bands */
161typedef enum
162{
163 band_invalid = -1,
164 band_2_4 = 0,
165 band_5 = 1,
166 band_6 = 2,
167} wifi_band;
168
developer17038e62023-03-02 14:43:43 +0800169char* wifi_band_str[] = {
170 "2G",
171 "5G",
172 "6G",
173};
174
developer72fb0bb2023-01-11 09:46:29 +0800175typedef enum {
176 WIFI_MODE_A = 0x01,
177 WIFI_MODE_B = 0x02,
178 WIFI_MODE_G = 0x04,
179 WIFI_MODE_N = 0x08,
180 WIFI_MODE_AC = 0x10,
181 WIFI_MODE_AX = 0x20,
182} wifi_ieee80211_Mode;
183
184#ifdef WIFI_HAL_VERSION_3
185
186// Return number of elements in array
187#ifndef ARRAY_SIZE
188#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
189#endif /* ARRAY_SIZE */
190
191#ifndef ARRAY_AND_SIZE
192#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
193#endif /* ARRAY_AND_SIZE */
194
195#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
196
197typedef struct {
198 int32_t value;
199 int32_t param;
200 intptr_t key;
201 intptr_t data;
202} wifi_secur_list;
203
204static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
205static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
206wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
207wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
208char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
209static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
210
211static wifi_secur_list map_security[] =
212{
213 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
214 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
215 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
220 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
221 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
222 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
223 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
224 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
225};
226
227wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
228{
229 wifi_secur_list *item;
230 int i;
231
232 for (item = list,i = 0;i < list_sz; item++, i++) {
233 if ((int)(item->key) == key) {
234 return item;
235 }
236 }
237
238 return NULL;
239}
240
241char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
242{
243 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
244
245 if (!item) {
246 return "";
247 }
248
249 return (char *)(item->data);
250}
251
252wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
253{
254 wifi_secur_list *item;
255 int i;
256
257 for (item = list,i = 0;i < list_sz; item++, i++) {
258 if (strcmp((char *)(item->data), str) == 0) {
259 return item;
260 }
261 }
262
263 return NULL;
264}
265#endif /* WIFI_HAL_VERSION_3 */
266
developer96b38512023-02-22 11:17:45 +0800267
268static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800269char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
270char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
271#define MAX_SSID_LEN 64
272char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
developer745f0bd2023-03-06 14:32:53 +0800273int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800274
275static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
276static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
277
developer96b38512023-02-22 11:17:45 +0800278
279static int
280get_value(const char *conf_file, const char *param, char *value, int len)
281{
282 FILE *fp;
283 int ret = -1;
284 int param_len = strlen(param);
285 int buf_len;
286 char buf[256];
287
288 fp = fopen(conf_file, "r");
289 if (!fp) {
290 return -1;
291 }
292
293 while (fgets(buf, sizeof(buf), fp)) {
294 buf_len = strlen(buf);
295 if (buf[buf_len - 1] == '\n') {
296 buf_len--;
297 buf[buf_len] = '\0';
298 }
299 if ((buf_len > param_len) &&
300 (strncmp(buf, param, param_len) == 0) &&
301 (buf[param_len] == '=')) {
302
303 if (buf_len == (param_len + 1)) {
304 value[0] = '\0';
305 ret = 0;
306 } else {
307 ret = snprintf(value, len, "%s", buf + (param_len + 1));
308 }
309 fclose(fp);
310 return ret;
311 }
312 }
313 fclose(fp);
314 return -1;
315}
316
317static int
318get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
319{
320 char buf[256];
321 int ret;
322 char *save_ptr = NULL;
323 char *tok = NULL;
324
325 ret = get_value(conf_file, param, buf, sizeof(buf));
326 if (ret < 0)
327 return ret;
328
329 tok = strtok_r(buf, ";", &save_ptr);
330 do {
331 if (idx == 0 || tok == NULL)
332 break;
333 else
334 idx--;
335
336 tok = strtok_r(NULL, ";", &save_ptr);
337 } while (tok != NULL);
338
339 if (tok) {
340 ret = snprintf(value, len, "%s", tok);
341 } else {
342 ret = 0;
343 value[0] = '\0';
344 }
345
346 return ret;
347}
348
349
developer72fb0bb2023-01-11 09:46:29 +0800350#ifdef HAL_NETLINK_IMPL
351typedef struct {
352 int id;
353 struct nl_sock* socket;
354 struct nl_cb* cb;
355} Netlink;
356
357static int mac_addr_aton(unsigned char *mac_addr, char *arg)
358{
359 unsigned int mac_addr_int[6]={};
360 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);
361 mac_addr[0] = mac_addr_int[0];
362 mac_addr[1] = mac_addr_int[1];
363 mac_addr[2] = mac_addr_int[2];
364 mac_addr[3] = mac_addr_int[3];
365 mac_addr[4] = mac_addr_int[4];
366 mac_addr[5] = mac_addr_int[5];
367 return 0;
368}
369
370static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
371{
372 unsigned int mac_addr_int[6]={};
373 mac_addr_int[0] = arg[0];
374 mac_addr_int[1] = arg[1];
375 mac_addr_int[2] = arg[2];
376 mac_addr_int[3] = arg[3];
377 mac_addr_int[4] = arg[4];
378 mac_addr_int[5] = arg[5];
379 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]);
380 return;
381}
382
383static int ieee80211_frequency_to_channel(int freq)
384{
385 /* see 802.11-2007 17.3.8.3.2 and Annex J */
386 if (freq == 2484)
387 return 14;
388 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
389 else if (freq == 5935)
390 return 2;
391 else if (freq < 2484)
392 return (freq - 2407) / 5;
393 else if (freq >= 4910 && freq <= 4980)
394 return (freq - 4000) / 5;
395 else if (freq < 5950)
396 return (freq - 5000) / 5;
397 else if (freq <= 45000) /* DMG band lower limit */
398 /* see 802.11ax D6.1 27.3.23.2 */
399 return (freq - 5950) / 5;
400 else if (freq >= 58320 && freq <= 70200)
401 return (freq - 56160) / 2160;
402 else
403 return 0;
404}
405
406static int initSock80211(Netlink* nl) {
407 nl->socket = nl_socket_alloc();
408 if (!nl->socket) {
409 fprintf(stderr, "Failing to allocate the sock\n");
410 return -ENOMEM;
411 }
412
413 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
414
415 if (genl_connect(nl->socket)) {
416 fprintf(stderr, "Failed to connect\n");
417 nl_close(nl->socket);
418 nl_socket_free(nl->socket);
419 return -ENOLINK;
420 }
421
422 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
423 if (nl->id< 0) {
424 fprintf(stderr, "interface not found.\n");
425 nl_close(nl->socket);
426 nl_socket_free(nl->socket);
427 return -ENOENT;
428 }
429
430 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
431 if ((!nl->cb)) {
432 fprintf(stderr, "Failed to allocate netlink callback.\n");
433 nl_close(nl->socket);
434 nl_socket_free(nl->socket);
435 return ENOMEM;
436 }
437
438 return nl->id;
439}
440
441static int nlfree(Netlink *nl)
442{
443 nl_cb_put(nl->cb);
444 nl_close(nl->socket);
445 nl_socket_free(nl->socket);
446 return 0;
447}
448
449static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
450 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
451 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
452 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
453};
454
455static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
456};
457
458static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
459};
460
461typedef struct _wifi_channelStats_loc {
462 INT array_size;
463 INT ch_number;
464 BOOL ch_in_pool;
465 INT ch_noise;
466 BOOL ch_radar_noise;
467 INT ch_max_80211_rssi;
468 INT ch_non_80211_noise;
469 INT ch_utilization;
470 ULLONG ch_utilization_total;
471 ULLONG ch_utilization_busy;
472 ULLONG ch_utilization_busy_tx;
473 ULLONG ch_utilization_busy_rx;
474 ULLONG ch_utilization_busy_self;
475 ULLONG ch_utilization_busy_ext;
476} wifi_channelStats_t_loc;
477
478typedef struct wifi_device_info {
479 INT wifi_devIndex;
480 UCHAR wifi_devMacAddress[6];
481 CHAR wifi_devIPAddress[64];
482 BOOL wifi_devAssociatedDeviceAuthentiationState;
483 INT wifi_devSignalStrength;
484 INT wifi_devTxRate;
485 INT wifi_devRxRate;
486} wifi_device_info_t;
487
488#endif
489
490//For 5g Alias Interfaces
491static BOOL priv_flag = TRUE;
492static BOOL pub_flag = TRUE;
493static BOOL Radio_flag = TRUE;
494//wifi_setApBeaconRate(1, beaconRate);
495
496BOOL multiple_set = FALSE;
497
498struct params
499{
500 char * name;
501 char * value;
502};
503
504static int _syscmd(char *cmd, char *retBuf, int retBufSize)
505{
506 FILE *f;
507 char *ptr = retBuf;
508 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
509
510 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
511 if((f = popen(cmd, "r")) == NULL) {
512 fprintf(stderr,"\npopen %s error\n", cmd);
513 return RETURN_ERR;
514 }
515
516 while(!feof(f))
517 {
518 *ptr = 0;
519 if(bufSize>=128) {
520 bufbytes=128;
521 } else {
522 bufbytes=bufSize-1;
523 }
524
525 fgets(ptr,bufbytes,f);
526 readbytes=strlen(ptr);
527
528 if(!readbytes)
529 break;
530
531 bufSize-=readbytes;
532 ptr += readbytes;
533 }
534 cmd_ret = pclose(f);
535 retBuf[retBufSize-1]=0;
536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
537
538 return cmd_ret >> 8;
539}
540
541INT radio_index_to_phy(int radioIndex)
542{
developer17038e62023-03-02 14:43:43 +0800543 /* TODO */
544 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800545}
546
547INT wifi_getMaxRadioNumber(INT *max_radio_num)
548{
549 char cmd[64] = {0};
550 char buf[4] = {0};
551
552 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
553
554 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
555 _syscmd(cmd, buf, sizeof(buf));
556 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
557
558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
559
560 return RETURN_OK;
561}
562
developer17038e62023-03-02 14:43:43 +0800563wifi_band radio_index_to_band(int radioIndex)
564{
developer745f0bd2023-03-06 14:32:53 +0800565 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800566}
567
developer72fb0bb2023-01-11 09:46:29 +0800568wifi_band wifi_index_to_band(int apIndex)
569{
570 char cmd[128] = {0};
571 char buf[64] = {0};
572 int nl80211_band = 0;
573 int i = 0;
574 int phyIndex = 0;
575 int radioIndex = 0;
576 int max_radio_num = 0;
577 wifi_band band = band_invalid;
578
579 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
580
581 wifi_getMaxRadioNumber(&max_radio_num);
582 radioIndex = apIndex % max_radio_num;
583 phyIndex = radio_index_to_phy(radioIndex);
584 while(i < 10){
585 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
586 _syscmd(cmd, buf, sizeof(buf));
587 nl80211_band = strtol(buf, NULL, 10);
588 if (nl80211_band == 1)
589 band = band_2_4;
590 else if (nl80211_band == 2)
591 band = band_5;
592 else if (nl80211_band == 4) // band == 3 is 60GHz
593 band = band_6;
594
595 if(band != band_invalid)
596 break;
developer69b61b02023-03-07 17:17:44 +0800597
developer72fb0bb2023-01-11 09:46:29 +0800598 i++;
599 sleep(1);
600 }
601
602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
603 return band;
604}
605
606static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
607{
developer7e4a2a62023-04-06 19:56:03 +0800608 char cmd[MAX_CMD_SIZE] = {0};
609 char buf[MAX_BUF_SIZE] = {0};
610 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +0800611
developer7e4a2a62023-04-06 19:56:03 +0800612 ret = snprintf(cmd, MAX_CMD_SIZE, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"",
613 conf_file, param);
developer72fb0bb2023-01-11 09:46:29 +0800614
developer7e4a2a62023-04-06 19:56:03 +0800615 if (ret < 0) {
616 printf("%s: snprintf error!", __func__);
617 return -1;
618 }
619
620 ret = _syscmd(cmd, buf, sizeof(buf));
621 if ((ret != 0) && (strlen(buf) == 0)) {
622 printf("%s: _syscmd error!", __func__);
623 return -1;
624 }
625
626 snprintf(output, output_size, "%s", buf);
627
628 return 0;
developer72fb0bb2023-01-11 09:46:29 +0800629}
630
631static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
632{
developer7e4a2a62023-04-06 19:56:03 +0800633 char cmd[MAX_CMD_SIZE] = {0};
634 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +0800635
developer7e4a2a62023-04-06 19:56:03 +0800636 for (int i = 0; i < item_count; i++) {
developer72fb0bb2023-01-11 09:46:29 +0800637 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
developer7e4a2a62023-04-06 19:56:03 +0800638 if (strlen(buf) == 0) /*no such item, insert it*/
developer72fb0bb2023-01-11 09:46:29 +0800639 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800640 else /*find the item, update it*/
developer72fb0bb2023-01-11 09:46:29 +0800641 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer7e4a2a62023-04-06 19:56:03 +0800642
developer72fb0bb2023-01-11 09:46:29 +0800643 if(_syscmd(cmd, buf, sizeof(buf)))
644 return -1;
645 }
646
647 return 0;
648}
649
650//For Getting Current Interface Name from corresponding hostapd configuration
651static int wifi_GetInterfaceName(int apIndex, char *interface_name)
652{
653 char config_file[128] = {0};
654
655 if (interface_name == NULL)
656 return RETURN_ERR;
657
658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
659
660 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
661 wifi_hostapdRead(config_file, "interface", interface_name, 16);
662 if (strlen(interface_name) == 0)
663 return RETURN_ERR;
664
665 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
666 return RETURN_OK;
667}
668
developer72fb0bb2023-01-11 09:46:29 +0800669
670static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
671{
672 char interface_name[16] = {0};
673 if (multiple_set == TRUE)
674 return RETURN_OK;
675 char cmd[MAX_CMD_SIZE]="", output[32]="";
676 FILE *fp;
677 int i;
678 //NOTE RELOAD should be done in ApplySSIDSettings
679 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
680 return RETURN_ERR;
681 for(i=0; i<item_count; i++, list++)
682 {
683 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
684 if((fp = popen(cmd, "r"))==NULL)
685 {
686 perror("popen failed");
687 return -1;
688 }
689 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
690 {
691 pclose(fp);
692 perror("fgets failed");
693 return -1;
694 }
695 pclose(fp);
696 }
697 return 0;
698}
699
developer7e4a2a62023-04-06 19:56:03 +0800700static int wifi_quick_reload_ap(int apIndex)
701{
702 char interface_name[IF_NAME_SIZE] = {0};
703 char cmd[MAX_CMD_SIZE] = {0};
704 char buf[MAX_BUF_SIZE] = {0};
705
706 if (multiple_set == TRUE)
707 return RETURN_OK;
708
709 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
710 return RETURN_ERR;
711
712 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
713 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
714 return RETURN_ERR;
715
716 return RETURN_OK;
717}
718
developer72fb0bb2023-01-11 09:46:29 +0800719static int wifi_reloadAp(int apIndex)
720{
721 char interface_name[16] = {0};
722 if (multiple_set == TRUE)
723 return RETURN_OK;
724 char cmd[MAX_CMD_SIZE]="";
725 char buf[MAX_BUF_SIZE]="";
726
727 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
728 return RETURN_ERR;
729 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
730 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
731 return RETURN_ERR;
732
733 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
734 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
735 return RETURN_ERR;
736
737 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
738 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
739 return RETURN_ERR;
740
741 return RETURN_OK;
742}
743
744INT File_Reading(CHAR *file, char *Value)
745{
746 FILE *fp = NULL;
747 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
748 int count = 0;
749
750 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
751 fp = popen(file,"r");
752 if(fp == NULL)
753 return RETURN_ERR;
754
755 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
756 {
757 for(count=0;buf[count]!='\n';count++)
758 copy_buf[count]=buf[count];
759 copy_buf[count]='\0';
760 }
761 strcpy(Value,copy_buf);
762 pclose(fp);
763 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
764
765 return RETURN_OK;
766}
767
768void wifi_RestartHostapd_2G()
769{
770 int Public2GApIndex = 4;
771
772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
773 wifi_setApEnable(Public2GApIndex, FALSE);
774 wifi_setApEnable(Public2GApIndex, TRUE);
775 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
776}
777
778void wifi_RestartHostapd_5G()
779{
780 int Public5GApIndex = 5;
781
782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
783 wifi_setApEnable(Public5GApIndex, FALSE);
784 wifi_setApEnable(Public5GApIndex, TRUE);
785 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
786}
787
788void wifi_RestartPrivateWifi_2G()
789{
790 int PrivateApIndex = 0;
791
792 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
793 wifi_setApEnable(PrivateApIndex, FALSE);
794 wifi_setApEnable(PrivateApIndex, TRUE);
795 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
796}
797
798void wifi_RestartPrivateWifi_5G()
799{
800 int Private5GApIndex = 1;
801
802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
803 wifi_setApEnable(Private5GApIndex, FALSE);
804 wifi_setApEnable(Private5GApIndex, TRUE);
805 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
806}
807
808static int writeBandWidth(int radioIndex,char *bw_value)
809{
810 char buf[MAX_BUF_SIZE];
811 char cmd[MAX_CMD_SIZE];
812
813 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
814 if(_syscmd(cmd, buf, sizeof(buf)))
815 {
816 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
817 _syscmd(cmd, buf, sizeof(buf));
818 return RETURN_OK;
819 }
820
821 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
822 _syscmd(cmd,buf,sizeof(buf));
823 return RETURN_OK;
824}
825
826static int readBandWidth(int radioIndex,char *bw_value)
827{
828 char buf[MAX_BUF_SIZE] = {0};
829 char cmd[MAX_CMD_SIZE] = {0};
830 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
831 _syscmd(cmd,buf,sizeof(buf));
832 if(NULL!=strstr(buf,"20MHz"))
833 {
834 strcpy(bw_value,"20MHz");
835 }
836 else if(NULL!=strstr(buf,"40MHz"))
837 {
838 strcpy(bw_value,"40MHz");
839 }
840 else if(NULL!=strstr(buf,"80MHz"))
841 {
842 strcpy(bw_value,"80MHz");
843 }
844 else
845 {
846 return RETURN_ERR;
847 }
848 return RETURN_OK;
849}
850
851// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
852INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
853{
854 struct params params={'\0'};
855 char config_file[MAX_BUF_SIZE] = {0};
856 char buf[MAX_BUF_SIZE] = {'\0'};
857
858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
859 // Copy the numeric value
860 if (strlen (beaconRate) >= 5) {
861 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
862 buf[strlen(beaconRate) - 4] = '\0';
863 } else if (strlen(beaconRate) > 0)
864 strcpy(buf, beaconRate);
865 else
866 return RETURN_ERR;
867
868 params.name = "beacon_rate";
869 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
870 if (strncmp(buf, "5.5", 3) == 0) {
871 snprintf(buf, sizeof(buf), "55");
872 params.value = buf;
873 } else {
874 strcat(buf, "0");
875 params.value = buf;
876 }
877
878 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
879 wifi_hostapdWrite(config_file, &params, 1);
880 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
881 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
882
883 return RETURN_OK;
884}
885
886INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
887{
888 char config_file[128] = {'\0'};
889 char temp_output[128] = {'\0'};
890 char buf[128] = {'\0'};
891 char cmd[128] = {'\0'};
892 int rate = 0;
893 int phyId = 0;
894
895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
896 if (NULL == beaconRate)
897 return RETURN_ERR;
898
899 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
900 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
901 phyId = radio_index_to_phy(radioIndex);
902 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
903 if(strlen(buf) > 0) {
904 if (strncmp(buf, "55", 2) == 0)
905 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
906 else {
907 rate = strtol(buf, NULL, 10)/10;
908 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
909 }
910 } else {
911 // config not set, so we would use lowest rate as default
912 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
913 _syscmd(cmd, buf, sizeof(buf));
914 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
915 }
916 strncpy(beaconRate, temp_output, sizeof(temp_output));
917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
918
919 return RETURN_OK;
920}
921
922INT wifi_setLED(INT radioIndex, BOOL enable)
923{
924 return 0;
925}
926INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
927{
928 return RETURN_OK;
929}
930/**********************************************************************************
931 *
developer69b61b02023-03-07 17:17:44 +0800932 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +0800933 *
934**********************************************************************************/
935//---------------------------------------------------------------------------------------------------
936//Wifi system api
937//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 +0800938INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +0800939{
940 if(!output_string)
941 return RETURN_ERR;
942 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
943
944 return RETURN_OK;
945}
946
947
948/* wifi_factoryReset() function */
949/**
developer69b61b02023-03-07 17:17:44 +0800950* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +0800951* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
952*
953* @param None
954*
955* @return The status of the operation.
956* @retval RETURN_OK if successful.
957* @retval RETURN_ERR if any error is detected
958*
959* @execution Synchronous
960* @sideeffect None
961*
962* @note This function must not suspend and must not invoke any blocking system
963* calls. It should probably just send a message to a driver event handler task.
964*
965*/
966INT wifi_factoryReset()
967{
968 char cmd[128];
969
970 /*delete running hostapd conf files*/
971 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
972 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
973 system(cmd);
974 system("systemctl restart hostapd.service");
975
976 return RETURN_OK;
977}
978
979/* wifi_factoryResetRadios() function */
980/**
981* @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.
982*
983* @param None
984* @return The status of the operation
985* @retval RETURN_OK if successful
986* @retval RETURN_ERR if any error is detected
987*
988* @execution Synchronous
989*
990* @sideeffect None
991*
992* @note This function must not suspend and must not invoke any blocking system
993* calls. It should probably just send a message to a driver event handler task.
994*
995*/
996INT wifi_factoryResetRadios()
997{
998 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
999 return RETURN_OK;
1000
1001 return RETURN_ERR;
1002}
1003
1004
1005/* wifi_factoryResetRadio() function */
1006/**
1007* @description Restore selected radio parameters without touching access point parameters
1008*
1009* @param radioIndex - Index of Wi-Fi Radio channel
1010*
1011* @return The status of the operation.
1012* @retval RETURN_OK if successful.
1013* @retval RETURN_ERR if any error is detected
1014*
1015* @execution Synchronous.
1016* @sideeffect None.
1017*
1018* @note This function must not suspend and must not invoke any blocking system
1019* calls. It should probably just send a message to a driver event handler task.
1020*
1021*/
1022INT wifi_factoryResetRadio(int radioIndex) //RDKB
1023{
1024 system("systemctl stop hostapd.service");
1025
1026 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1027 if(radioIndex == 0)
1028 system("rm /nvram/hostapd0.conf");
1029 else if(radioIndex == 1)
1030 system("rm /nvram/hostapd1.conf");
1031 else
1032 return RETURN_ERR;
1033
1034 system("systemctl start hostapd.service");
1035 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1036 return RETURN_OK;
1037}
1038
1039/* wifi_initRadio() function */
1040/**
1041* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001042* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001043* different hardware implementations may have different initilization requirements.
1044* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1045*
1046* @return The status of the operation.
1047* @retval RETURN_OK if successful.
1048* @retval RETURN_ERR if any error is detected
1049*
1050* @execution Synchronous.
1051* @sideeffect None.
1052*
1053* @note This function must not suspend and must not invoke any blocking system
1054* calls. It should probably just send a message to a driver event handler task.
1055*
1056*/
1057INT wifi_initRadio(INT radioIndex)
1058{
1059 //TODO: Initializes the wifi subsystem (for specified radio)
1060 return RETURN_OK;
1061}
1062void macfilter_init()
1063{
1064 char count[4]={'\0'};
1065 char buf[253]={'\0'};
1066 char tmp[19]={'\0'};
1067 int dev_count,block,mac_entry=0;
1068 char res[4]={'\0'};
1069 char acl_file_path[64] = {'\0'};
1070 FILE *fp = NULL;
1071 int index=0;
1072 char iface[10]={'\0'};
1073 char config_file[MAX_BUF_SIZE] = {0};
1074
1075
1076 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1077
1078 fp=fopen(acl_file_path,"w+");
1079 if (fp == NULL) {
1080 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001081 return;
developer72fb0bb2023-01-11 09:46:29 +08001082 }
1083 sprintf(buf,"#!/bin/sh \n");
1084 fprintf(fp,"%s\n",buf);
1085
1086 system("chmod 0777 /tmp/mac_filter.sh");
1087
1088 for(index=0;index<=1;index++)
1089 {
1090 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1091 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1092 sprintf(buf,"syscfg get %dcountfilter",index);
1093 _syscmd(buf,count,sizeof(count));
1094 mac_entry=atoi(count);
1095
1096 sprintf(buf,"syscfg get %dblockall",index);
1097 _syscmd(buf,res,sizeof(res));
1098 block = atoi(res);
1099
1100 //Allow only those macs mentioned in ACL
1101 if(block==1)
1102 {
1103 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1104 fprintf(fp,"%s\n",buf);
1105 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1106 {
1107 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1108 _syscmd(buf,tmp,sizeof(tmp));
1109 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1110 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1111 fprintf(fp,"%s\n",buf);
1112 }
1113 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1114 fprintf(fp,"%s\n",buf);
1115 }
1116
1117 //Block all the macs mentioned in ACL
1118 else if(block==2)
1119 {
1120 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1121 fprintf(fp,"%s\n",buf);
1122
1123 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1124 {
1125 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1126 _syscmd(buf,tmp,sizeof(tmp));
1127 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1128 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1129 fprintf(fp,"%s\n",buf);
1130 }
1131 }
1132 }
1133 fclose(fp);
1134}
1135
developer17038e62023-03-02 14:43:43 +08001136
1137static void
1138wifi_ParseProfile(void)
1139{
1140 int i;
1141 int max_radio_num = 0;
1142 int card_idx;
1143 int band_idx;
1144 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001145 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001146 char buf[MAX_BUF_SIZE] = {0};
1147 char chip_name[12];
1148 char card_profile[MAX_BUF_SIZE] = {0};
1149 char band_profile[MAX_BUF_SIZE] = {0};
1150 FILE* fp;
1151
1152 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1153
1154 memset(main_prefix, 0, sizeof(main_prefix));
1155 memset(ext_prefix, 0, sizeof(ext_prefix));
1156 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001157 for (i = 0; i < MAX_NUM_RADIOS; i++)
1158 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001159
1160 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1161 /* LOG */
1162 return;
1163 }
1164
1165 for (card_idx = 0; card_idx < 3; card_idx++) {
1166 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1167 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1168 break;
1169 }
1170 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1171 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1172 break;
1173 }
1174 for (band_idx = 0; band_idx < 3; band_idx++) {
1175 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1176 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1177 /* LOG */
1178 break;
1179 }
1180
1181 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1182 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1183 /* LOG */
1184 }
1185
1186 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1187 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1188 /* LOG */
1189 }
1190
1191 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1192 /* LOG */
1193 }
developer745f0bd2023-03-06 14:32:53 +08001194 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1195 /* LOG */
1196 }
1197
1198 wireless_mode = atoi(buf);
1199 switch (wireless_mode) {
1200 case 22:
1201 case 16:
1202 case 6:
1203 case 4:
1204 case 1:
1205 radio_band[phy_idx] = band_2_4;
1206 break;
1207 case 23:
1208 case 17:
1209 case 14:
1210 case 11:
1211 case 2:
1212 radio_band[phy_idx] = band_5;
1213 break;
1214 case 24:
1215 case 18:
1216 radio_band[phy_idx] = band_6;
1217 break;
1218 }
developer17038e62023-03-02 14:43:43 +08001219 phy_idx++;
1220 }
1221 }
1222
1223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1224}
1225
1226static void
1227wifi_PrepareDefaultHostapdConfigs(void)
1228{
developer0132ed92023-03-21 13:48:53 +08001229 int radio_idx;
1230 int bss_idx;
1231 int ap_idx;
1232 int band_idx;
1233 char buf[MAX_BUF_SIZE] = {0};
1234 char config_file[MAX_BUF_SIZE] = {0};
1235 char ssid[MAX_BUF_SIZE] = {0};
1236 char interface[32] = {0};
1237 char ret_buf[MAX_BUF_SIZE] = {0};
1238 char psk_file[64] = {0};
1239 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001240
developer0132ed92023-03-21 13:48:53 +08001241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1243 band_idx = radio_index_to_band(radio_idx);
1244 if (band_idx < 0) {
1245 break;
1246 }
1247 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1248 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1249
1250 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1251 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
1252 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001253
developer0132ed92023-03-21 13:48:53 +08001254 if (bss_idx == 0) {
1255 snprintf(ssid, sizeof(ssid), "%s", default_ssid[radio_idx]);
1256 snprintf(interface, sizeof(interface), "%s", main_prefix[radio_idx]);
1257 } else {
1258 snprintf(ssid, sizeof(ssid), "%s_%d", default_ssid[radio_idx], bss_idx);
1259 snprintf(interface, sizeof(interface), "%s%d", ext_prefix[radio_idx], bss_idx);
1260 }
developer17038e62023-03-02 14:43:43 +08001261
developer0132ed92023-03-21 13:48:53 +08001262 /* fix wpa_psk_file path */
1263 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001264
developer0132ed92023-03-21 13:48:53 +08001265 params[0].name = "ssid";
1266 params[0].value = ssid;
1267 params[1].name = "interface";
1268 params[1].value = interface;
1269 params[2].name = "wpa_psk_file";
1270 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001271
developer0132ed92023-03-21 13:48:53 +08001272 wifi_hostapdWrite(config_file, params, 3);
1273 }
1274 }
1275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001276}
1277
1278static void
1279wifiBringUpInterfacesForRadio(int radio_idx)
1280{
developer0132ed92023-03-21 13:48:53 +08001281 int bss_idx;
1282 int ap_idx;
1283 int band_idx;
1284 char cmd[MAX_CMD_SIZE] = {0};
1285 char config_file[MAX_BUF_SIZE] = {0};
1286 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001287 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001288
1289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001290
developered997d32023-04-18 22:45:39 +08001291 bss_idx = 0;
1292 /*TBD: we need refine setup flow and mbss flow*/
1293// for (bss_idx = 0; bss_idx < 5; bss_idx++) {
developer0132ed92023-03-21 13:48:53 +08001294 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1295
1296 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1297 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1298
1299 memset(cmd, 0, MAX_CMD_SIZE);
1300 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001301
developer0132ed92023-03-21 13:48:53 +08001302 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1303 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1304 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001305
1306 wifi_GetInterfaceName(ap_idx, inf_name);
1307
1308 memset(cmd, 0, MAX_CMD_SIZE);
1309 memset(ret_buf, 0, MAX_BUF_SIZE);
1310
1311 /* fix vap-status file */
1312 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1313 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developered997d32023-04-18 22:45:39 +08001314// }
1315
1316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001317}
1318
1319static void
1320wifi_BringUpInterfaces(void)
1321{
1322 int radio_idx;
1323 int bss_idx;
1324 int ap_idx;
1325 int band_idx;
1326 char cmd[MAX_BUF_SIZE] = {0};
1327 char config_file[MAX_BUF_SIZE] = {0};
1328 char ret_buf[MAX_BUF_SIZE]={'\0'};
1329
1330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1331 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1332 band_idx = radio_index_to_band(radio_idx);
1333 if (band_idx < 0) {
1334 break;
1335 }
1336 wifiBringUpInterfacesForRadio(radio_idx);
1337 }
1338 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1339}
1340
1341static void
1342wifi_BringDownInterfacesForRadio(int radio_idx)
1343{
1344 int bss_idx;
1345 int ap_idx;
1346 int band_idx;
1347 char cmd[MAX_BUF_SIZE] = {0};
1348 char config_file[MAX_BUF_SIZE] = {0};
1349 char ret_buf[MAX_BUF_SIZE]={'\0'};
1350
1351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001352
developer8a3bbbf2023-03-15 17:47:23 +08001353 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1354 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1355
1356
developer17038e62023-03-02 14:43:43 +08001357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1358}
1359
1360
1361static void
1362wifi_BringDownInterfaces(void)
1363{
1364 int radio_idx;
1365 int bss_idx;
1366 int ap_idx;
1367 int band_idx;
1368 char cmd[MAX_BUF_SIZE] = {0};
1369 char config_file[MAX_BUF_SIZE] = {0};
1370 char ret_buf[MAX_BUF_SIZE]={'\0'};
1371
1372 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1373 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1374 band_idx = radio_index_to_band(radio_idx);
1375 if (band_idx < 0) {
1376 break;
1377 }
1378 wifi_BringDownInterfacesForRadio(radio_idx);
1379 }
1380 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1381}
1382
developer8a3bbbf2023-03-15 17:47:23 +08001383static void wifi_vap_status_reset()
1384{
1385 char cmd[MAX_CMD_SIZE] = {0};
1386 char ret_buf[MAX_BUF_SIZE] = {0};
1387 char radio_idx = 0;
1388 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001389
developer8a3bbbf2023-03-15 17:47:23 +08001390 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1391 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1392 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1393 } else {
1394 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1395 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1396 }
1397
1398 memset(cmd, 0, MAX_CMD_SIZE);
1399 memset(ret_buf, 0, MAX_BUF_SIZE);
1400
1401 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1402 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1403 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1404 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1405 }
1406
1407}
developer17038e62023-03-02 14:43:43 +08001408
developer72fb0bb2023-01-11 09:46:29 +08001409// Initializes the wifi subsystem (all radios)
1410INT wifi_init() //RDKB
1411{
developer96b38512023-02-22 11:17:45 +08001412 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1413 //Not intitializing macfilter for Turris-Omnia Platform for now
1414 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001415 wifi_ParseProfile();
1416 wifi_PrepareDefaultHostapdConfigs();
1417 //system("/usr/sbin/iw reg set US");
1418 system("systemctl start hostapd.service");
1419 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001420
1421 wifi_vap_status_reset();
1422
developer17038e62023-03-02 14:43:43 +08001423 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001424
developer96b38512023-02-22 11:17:45 +08001425
1426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001427
1428 return RETURN_OK;
1429}
1430
1431/* wifi_reset() function */
1432/**
1433* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001434* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001435* different hardware implementations may have different requirements.
1436* Parameters : None
1437*
1438* @return The status of the operation.
1439* @retval RETURN_OK if successful.
1440* @retval RETURN_ERR if any error is detected
1441*
1442* @execution Synchronous.
1443* @sideeffect None.
1444*
1445* @note This function must not suspend and must not invoke any blocking system
1446* calls. It should probably just send a message to a driver event handler task.
1447*
1448*/
1449INT wifi_reset()
1450{
developer17038e62023-03-02 14:43:43 +08001451
1452 wifi_BringDownInterfaces();
1453 sleep(2);
1454
developer96b38512023-02-22 11:17:45 +08001455 //TODO: resets the wifi subsystem, deletes all APs
1456 system("systemctl stop hostapd.service");
1457 sleep(2);
developer17038e62023-03-02 14:43:43 +08001458
developer96b38512023-02-22 11:17:45 +08001459 system("systemctl start hostapd.service");
1460 sleep(5);
developer17038e62023-03-02 14:43:43 +08001461
1462 wifi_PrepareDefaultHostapdConfigs();
1463 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001464
1465 wifi_vap_status_reset();
1466
developer17038e62023-03-02 14:43:43 +08001467 wifi_BringUpInterfaces();
1468
developer72fb0bb2023-01-11 09:46:29 +08001469 return RETURN_OK;
1470}
1471
1472/* wifi_down() function */
1473/**
1474* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001475* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001476* different hardware implementations may have different requirements.
1477*
1478* @param None
1479*
1480* @return The status of the operation
1481* @retval RETURN_OK if successful
1482* @retval RETURN_ERR if any error is detected
1483*
1484* @execution Synchronous
1485* @sideeffect None
1486*
1487* @note This function must not suspend and must not invoke any blocking system
1488* calls. It should probably just send a message to a driver event handler task.
1489*
1490*/
1491INT wifi_down()
1492{
developer96b38512023-02-22 11:17:45 +08001493 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001494 wifi_BringDownInterfaces();
1495 sleep(2);
1496
developer96b38512023-02-22 11:17:45 +08001497 system("systemctl stop hostapd.service");
1498 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001499 return RETURN_OK;
1500}
1501
1502
1503/* wifi_createInitialConfigFiles() function */
1504/**
1505* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001506* and content of these files are implementation dependent. This function call is
1507* used to trigger this task if necessary. Some implementations may not need this
1508* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001509* do nothing and return RETURN_OK.
1510*
1511* @param None
1512*
1513* @return The status of the operation
1514* @retval RETURN_OK if successful
1515* @retval RETURN_ERR if any error is detected
1516*
1517* @execution Synchronous
1518* @sideeffect None
1519*
1520* @note This function must not suspend and must not invoke any blocking system
1521* calls. It should probably just send a message to a driver event handler task.
1522*
1523*/
1524INT wifi_createInitialConfigFiles()
1525{
1526 //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)
1527 return RETURN_OK;
1528}
1529
developer7e4a2a62023-04-06 19:56:03 +08001530/* outputs the country code to a max 64 character string */
developer72fb0bb2023-01-11 09:46:29 +08001531INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1532{
developer7e4a2a62023-04-06 19:56:03 +08001533 char interface_name[IF_NAME_SIZE] = {0};
1534 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
developer72fb0bb2023-01-11 09:46:29 +08001535
developer7e4a2a62023-04-06 19:56:03 +08001536 if (!output_string || (radioIndex >= MAX_NUM_RADIOS)) {
1537 printf("%s: input para error!!!\n", __func__);
1538 return RETURN_ERR;
1539 }
developer72fb0bb2023-01-11 09:46:29 +08001540
developer7e4a2a62023-04-06 19:56:03 +08001541 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK) {
1542 printf("%s: get inf_name error!!!\n", __func__);
1543 return RETURN_ERR;
1544 }
1545
1546 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i %s status driver | grep country | cut -d '=' -f2 | tr -d '\\n'",
1547 interface_name);
1548 _syscmd(cmd, buf, sizeof(buf));
1549
1550 if(strlen(buf))
1551 snprintf(output_string, 64, "%s", buf);
1552 else
1553 return RETURN_ERR;
1554
1555 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001556}
1557
1558INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1559{
developer7e4a2a62023-04-06 19:56:03 +08001560 /*Set wifi config. Wait for wifi reset to apply*/
1561 char str[MAX_BUF_SIZE] = {0};
1562 char cmd[MAX_CMD_SIZE] = {0};
1563 struct params params;
1564 char config_file[MAX_BUF_SIZE] = {0};
1565 int ret = 0;
developer72fb0bb2023-01-11 09:46:29 +08001566
developer7e4a2a62023-04-06 19:56:03 +08001567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001568
developer7e4a2a62023-04-06 19:56:03 +08001569 if(NULL == CountryCode || strlen(CountryCode) >= 32 ) {
1570 printf("%s: input para error!!!\n", __func__);
1571 return RETURN_ERR;
1572 }
developer72fb0bb2023-01-11 09:46:29 +08001573
developer7e4a2a62023-04-06 19:56:03 +08001574 if (!strlen(CountryCode))
1575 strncpy(CountryCode, "US", sizeof("US")); /*default set the code to US*/
developer72fb0bb2023-01-11 09:46:29 +08001576
developer7e4a2a62023-04-06 19:56:03 +08001577 params.name = "country_code";
1578 params.value = CountryCode;
developer72fb0bb2023-01-11 09:46:29 +08001579
developer7e4a2a62023-04-06 19:56:03 +08001580 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1581 ret = wifi_hostapdWrite(config_file, &params, 1);
1582
1583 if (ret) {
1584 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n",
1585 __func__, ret);
1586 }
1587
1588 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1589
1590 if (ret) {
1591 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n",
1592 __func__, ret);
1593 }
1594
1595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
1596
1597 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08001598}
1599
1600INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1601{
1602 char interface_name[16] = {0};
1603 char channel_util_file[64] = {0};
1604 char cmd[128] = {0};
1605 char buf[128] = {0};
1606 char line[128] = {0};
1607 char *param = NULL, *value = NULL;
1608 int read = 0;
1609 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1610 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1611 size_t len = 0;
1612 FILE *f = NULL;
1613
1614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1615
1616 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1617 return RETURN_ERR;
1618 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1619 _syscmd(cmd, buf, sizeof(buf));
1620 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1621
1622 memset(cmd, 0, sizeof(cmd));
1623 memset(buf, 0, sizeof(buf));
1624 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1625 if ((f = popen(cmd, "r")) == NULL) {
1626 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1627 return RETURN_ERR;
1628 }
1629
1630 read = getline(&line, &len, f);
1631 while (read != -1) {
1632 param = strtok(line, ":\t");
1633 value = strtok(NULL, " ");
1634 if(strstr(param, "frequency") != NULL) {
1635 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1636 }
1637 if(strstr(param, "noise") != NULL) {
1638 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1639 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1640 }
1641 if(strstr(param, "channel active time") != NULL) {
1642 ActiveTime = strtol(value, NULL, 10);
1643 }
1644 if(strstr(param, "channel busy time") != NULL) {
1645 BusyTime = strtol(value, NULL, 10);
1646 }
1647 if(strstr(param, "channel transmit time") != NULL) {
1648 TransmitTime = strtol(value, NULL, 10);
1649 }
1650 read = getline(&line, &len, f);
1651 }
1652 pclose(f);
1653
1654 // The file should store the last active, busy and transmit time
1655 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1656 f = fopen(channel_util_file, "r");
1657 if (f != NULL) {
1658 read = getline(&line, &len, f);
1659 preActiveTime = strtol(line, NULL, 10);
1660 read = getline(&line, &len, f);
1661 preBusyTime = strtol(line, NULL, 10);
1662 read = getline(&line, &len, f);
1663 preTransmitTime = strtol(line, NULL, 10);
1664 fclose(f);
1665 }
1666
1667 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1668 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1669
1670 f = fopen(channel_util_file, "w");
1671 if (f != NULL) {
1672 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1673 fclose(f);
1674 }
1675 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1676 return RETURN_OK;
1677}
1678
1679/**********************************************************************************
1680 *
1681 * Wifi radio level function prototypes
1682 *
1683**********************************************************************************/
1684
1685//Get the total number of radios in this wifi subsystem
1686INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1687{
1688 if (NULL == output)
1689 return RETURN_ERR;
1690 *output = MAX_NUM_RADIOS;
1691
1692 return RETURN_OK;
1693}
1694
developer69b61b02023-03-07 17:17:44 +08001695//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08001696INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1697{
1698 if (NULL == output)
1699 return RETURN_ERR;
1700 *output = MAX_APS;
1701
1702 return RETURN_OK;
1703}
1704
1705//Get the Radio enable config parameter
1706INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1707{
1708 char interface_name[16] = {0};
1709 char buf[128] = {0}, cmd[128] = {0};
1710
1711 if (NULL == output_bool)
1712 return RETURN_ERR;
1713
1714 *output_bool = FALSE;
1715 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1716 return RETURN_ERR;
1717
1718 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1719 return RETURN_ERR;
1720 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1721 _syscmd(cmd, buf, sizeof(buf));
1722
1723 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1724 *output_bool = TRUE;
1725 return RETURN_OK;
1726}
1727
1728INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1729{
1730 char interface_name[16] = {0};
1731 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001732 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001733 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08001734 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08001735 int phyId = 0;
1736
1737 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1738
1739 phyId = radio_index_to_phy(radioIndex);
1740
1741 wifi_getMaxRadioNumber(&max_radio_num);
1742
developer8a3bbbf2023-03-15 17:47:23 +08001743 if(enable == FALSE) {
1744 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s DISABLE", main_prefix[radioIndex]);
1745 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08001746
developer8a3bbbf2023-03-15 17:47:23 +08001747 } else {
developer72fb0bb2023-01-11 09:46:29 +08001748
developer8a3bbbf2023-03-15 17:47:23 +08001749 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s ENABLE", main_prefix[radioIndex]);
1750 _syscmd(cmd, buf, sizeof(buf));
1751
1752 /*start from bss1 not main bss */
1753 for(apIndex = (radioIndex + max_radio_num); apIndex < MAX_APS; apIndex += max_radio_num) {
1754
developer72fb0bb2023-01-11 09:46:29 +08001755 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1756 return RETURN_ERR;
1757
developer8a3bbbf2023-03-15 17:47:23 +08001758 memset(cmd, 0, MAX_CMD_SIZE);
1759 memset(buf, 0, MAX_BUF_SIZE);
1760
developer72fb0bb2023-01-11 09:46:29 +08001761 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1762 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001763
1764 if(*buf == '1') {
1765
1766 memset(cmd, 0, MAX_CMD_SIZE);
1767 memset(buf, 0, MAX_BUF_SIZE);
1768
developer72fb0bb2023-01-11 09:46:29 +08001769 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1770 phyId, apIndex);
1771 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001772
developer72fb0bb2023-01-11 09:46:29 +08001773 }
1774 }
developer7e4a2a62023-04-06 19:56:03 +08001775
developer72fb0bb2023-01-11 09:46:29 +08001776 }
1777
1778 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1779 return RETURN_OK;
1780}
1781
1782//Get the Radio enable status
1783INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1784{
1785 if (NULL == output_bool)
1786 return RETURN_ERR;
1787
1788 return wifi_getRadioEnable(radioIndex, output_bool);
1789}
1790
1791//Get the Radio Interface name from platform, eg "wlan0"
1792INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1793{
1794 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1795 return RETURN_ERR;
1796 return wifi_GetInterfaceName(radioIndex, output_string);
1797}
1798
1799//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1800//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.
1801INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1802{
1803 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1804 // For max bit rate, we should always choose the best MCS
1805 char mode[64] = {0};
1806 char channel_bandwidth_str[64] = {0};
1807 char *tmp = NULL;
1808 UINT mode_map = 0;
1809 UINT num_subcarrier = 0;
1810 UINT code_bits = 0;
1811 float code_rate = 0; // use max code rate
1812 int NSS = 0;
1813 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08001814 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08001815 wifi_band band = band_invalid;
1816 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1817 BOOL enable = FALSE;
1818 float bit_rate = 0;
1819
1820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1821 if (NULL == output_string)
1822 return RETURN_ERR;
1823
1824 wifi_getRadioEnable(radioIndex, &enable);
1825 if (enable == FALSE) {
1826 snprintf(output_string, 64, "0 Mb/s");
1827 return RETURN_OK;
1828 }
1829
1830 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1831 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1832 return RETURN_ERR;
1833 }
1834
1835 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1836 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1837 return RETURN_ERR;
1838 }
1839
1840 if (gi == wifi_guard_interval_3200)
1841 GI_duration = 32;
1842 else if (gi == wifi_guard_interval_1600)
1843 GI_duration = 16;
1844 else if (gi == wifi_guard_interval_800)
1845 GI_duration = 8;
1846 else // auto, 400
1847 GI_duration = 4;
1848
1849 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1850 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1851 return RETURN_ERR;
1852 }
1853
1854 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1855 strcpy(channel_bandwidth_str, "160");
1856
1857 if (mode_map & WIFI_MODE_AX) {
1858 if (strstr(channel_bandwidth_str, "160") != NULL)
1859 num_subcarrier = 1960;
1860 else if (strstr(channel_bandwidth_str, "80") != NULL)
1861 num_subcarrier = 980;
1862 else if (strstr(channel_bandwidth_str, "40") != NULL)
1863 num_subcarrier = 468;
1864 else if (strstr(channel_bandwidth_str, "20") != NULL)
1865 num_subcarrier = 234;
1866 code_bits = 10;
1867 code_rate = (float)5/6;
1868 Symbol_duration = 128;
1869 } else if (mode_map & WIFI_MODE_AC) {
1870 if (strstr(channel_bandwidth_str, "160") != NULL)
1871 num_subcarrier = 468;
1872 else if (strstr(channel_bandwidth_str, "80") != NULL)
1873 num_subcarrier = 234;
1874 else if (strstr(channel_bandwidth_str, "40") != NULL)
1875 num_subcarrier = 108;
1876 else if (strstr(channel_bandwidth_str, "20") != NULL)
1877 num_subcarrier = 52;
1878 code_bits = 8;
1879 code_rate = (float)5/6;
1880 Symbol_duration = 32;
1881 } else if (mode_map & WIFI_MODE_N) {
1882 if (strstr(channel_bandwidth_str, "160") != NULL)
1883 num_subcarrier = 468;
1884 else if (strstr(channel_bandwidth_str, "80") != NULL)
1885 num_subcarrier = 234;
1886 else if (strstr(channel_bandwidth_str, "40") != NULL)
1887 num_subcarrier = 108;
1888 else if (strstr(channel_bandwidth_str, "20") != NULL)
1889 num_subcarrier = 52;
1890 code_bits = 6;
1891 code_rate = (float)3/4;
1892 Symbol_duration = 32;
1893 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1894 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1895 snprintf(output_string, 64, "65 Mb/s");
1896 return RETURN_OK;
1897 } else {
1898 snprintf(output_string, 64, "0 Mb/s");
1899 return RETURN_OK;
1900 }
1901
1902 // Spatial streams
1903 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1904 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1905 return RETURN_ERR;
1906 }
1907
1908 // multiple 10 is to align duration unit (0.1 us)
1909 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1910 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1911
1912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1913
1914 return RETURN_OK;
1915}
1916#if 0
1917INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1918{
1919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1920 char cmd[64];
1921 char buf[1024];
1922 int apIndex;
1923
developer69b61b02023-03-07 17:17:44 +08001924 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08001925 return RETURN_ERR;
1926
1927 apIndex=(radioIndex==0)?0:1;
1928
1929 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
1930 _syscmd(cmd,buf, sizeof(buf));
1931
1932 snprintf(output_string, 64, "%s", buf);
1933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1934 return RETURN_OK;
1935}
1936#endif
1937
1938
1939//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1940//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.
1941INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1942{
1943 wifi_band band = band_invalid;
1944
1945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1946 if (NULL == output_string)
1947 return RETURN_ERR;
1948
1949 band = wifi_index_to_band(radioIndex);
1950
1951 memset(output_string, 0, 10);
1952 if (band == band_2_4)
1953 strcpy(output_string, "2.4GHz");
1954 else if (band == band_5)
1955 strcpy(output_string, "5GHz");
1956 else if (band == band_6)
1957 strcpy(output_string, "6GHz");
1958 else
1959 return RETURN_ERR;
1960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1961
1962 return RETURN_OK;
1963#if 0
1964 char buf[MAX_BUF_SIZE]={'\0'};
1965 char str[MAX_BUF_SIZE]={'\0'};
1966 char cmd[MAX_CMD_SIZE]={'\0'};
1967 char *ch=NULL;
1968 char *ch2=NULL;
1969
1970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1971 if (NULL == output_string)
1972 return RETURN_ERR;
1973
1974
1975 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1976
1977 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1978 {
1979 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1980 return RETURN_ERR;
1981 }
1982 ch=strchr(buf,'\n');
1983 *ch='\0';
1984 ch=strchr(buf,'=');
1985 if(ch==NULL)
1986 return RETURN_ERR;
1987
1988
1989 ch++;
1990
1991 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1992 strcpy(buf,"0");
1993 if(strlen(ch) == 1)
1994 ch=strcat(buf,ch);
1995
1996
1997 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1998
1999 if(_syscmd(cmd,str,64) == RETURN_ERR)
2000 {
2001 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2002 return RETURN_ERR;
2003 }
2004
2005
2006 ch2=strchr(str,'\n');
2007 //replace \n with \0
2008 *ch2='\0';
2009 ch2=strchr(str,'=');
2010 if(ch2==NULL)
2011 {
2012 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2013 return RETURN_ERR;
2014 }
2015 else
2016 wifi_dbg_printf("%s",ch2+1);
2017
2018
2019 ch2++;
2020
2021
2022 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
2023
2024 memset(buf,'\0',sizeof(buf));
2025 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2026 {
2027 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2028 return RETURN_ERR;
2029 }
2030 if (strstr(buf,"2.4") != NULL )
2031 strcpy(output_string,"2.4GHz");
2032 else if(strstr(buf,"5.") != NULL )
2033 strcpy(output_string,"5GHz");
2034 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2035
2036 return RETURN_OK;
2037#endif
2038}
2039
2040//Get the frequency band at which the radio is operating, eg: "2.4GHz"
2041//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.
2042INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
2043{
2044 wifi_band band = band_invalid;
2045 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2046 if (NULL == output_string)
2047 return RETURN_ERR;
2048 band = wifi_index_to_band(radioIndex);
2049
developer69b61b02023-03-07 17:17:44 +08002050 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002051 snprintf(output_string, 64, "2.4GHz");
2052 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002053 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002054 else if (band == band_6)
2055 snprintf(output_string, 64, "6GHz");
2056
2057 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2058
2059 return RETURN_OK;
2060#if 0
2061 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2062 char buf[MAX_BUF_SIZE]={'\0'};
2063 char str[MAX_BUF_SIZE]={'\0'};
2064 char cmd[MAX_CMD_SIZE]={'\0'};
2065 char *ch=NULL;
2066 char *ch2=NULL;
2067 char ch1[5]="0";
2068
2069 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2070
2071 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2072 {
2073 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2074 return RETURN_ERR;
2075 }
2076
2077 ch=strchr(buf,'\n');
2078 *ch='\0';
2079 ch=strchr(buf,'=');
2080 if(ch==NULL)
2081 return RETURN_ERR;
2082 ch++;
2083
2084 if(strlen(ch)==1)
2085 {
2086 strcat(ch1,ch);
2087
2088 }
2089 else
2090 {
2091 strcpy(ch1,ch);
2092 }
2093
2094
2095
2096 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2097 if(_syscmd(cmd,str,64) == RETURN_ERR)
2098 {
2099 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2100 return RETURN_ERR;
2101 }
2102
2103
2104 ch2=strchr(str,'\n');
2105 //replace \n with \0
2106 *ch2='\0';
2107 ch2=strchr(str,'=');
2108 if(ch2==NULL)
2109 {
2110 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2111 return RETURN_ERR;
2112 }
2113 else
2114 wifi_dbg_printf("%s",ch2+1);
2115 ch2++;
2116
2117
2118 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2119 memset(buf,'\0',sizeof(buf));
2120 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2121 {
2122 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2123 return RETURN_ERR;
2124 }
2125
2126
2127 if(strstr(buf,"2.4")!=NULL)
2128 {
2129 strcpy(output_string,"2.4GHz");
2130 }
2131 if(strstr(buf,"5.")!=NULL)
2132 {
2133 strcpy(output_string,"5GHz");
2134 }
2135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2136 return RETURN_OK;
2137#endif
2138}
2139
2140//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2141//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.
2142INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2143{
2144 char cmd[128]={0};
2145 char buf[128]={0};
2146 char temp_output[128] = {0};
2147 wifi_band band;
2148 int phyId = 0;
2149
2150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002151 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002152 return RETURN_ERR;
2153
2154 band = wifi_index_to_band(radioIndex);
2155 if (band == band_2_4) {
2156 strcat(temp_output, "b,g,");
2157 } else if (band == band_5) {
2158 strcat(temp_output, "a,");
2159 }
2160 phyId = radio_index_to_phy(radioIndex);
2161 // ht capabilities
2162 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);
2163 _syscmd(cmd, buf, sizeof(buf));
2164 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2165 strcat(temp_output, "n,");
2166 }
2167
2168 // vht capabilities
2169 if (band == band_5) {
2170 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2171 _syscmd(cmd, buf, sizeof(buf));
2172 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2173 strcat(temp_output, "ac,");
2174 }
2175 }
2176
2177 // he capabilities
2178 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);
2179 _syscmd(cmd, buf, sizeof(buf));
2180 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2181 strcat(temp_output, "ax,");
2182 }
2183
2184 // Remove the last comma
2185 if (strlen(temp_output) != 0)
2186 temp_output[strlen(temp_output)-1] = '\0';
2187 strncpy(output_string, temp_output, strlen(temp_output));
2188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2189 return RETURN_OK;
2190}
2191
2192//Get the radio operating mode, and pure mode flag. eg: "ac"
2193//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.
2194INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2195{
2196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2197 if (NULL == output_string)
2198 return RETURN_ERR;
2199
2200 if (radioIndex == 0) {
2201 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2202 *gOnly = FALSE;
2203 *nOnly = TRUE;
2204 *acOnly = FALSE;
2205 } else {
2206 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2207 *gOnly = FALSE;
2208 *nOnly = FALSE;
2209 *acOnly = FALSE;
2210 }
2211 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2212
2213 return RETURN_OK;
2214#if 0
2215 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2216 char buf[64] = {0};
2217 char config_file[MAX_BUF_SIZE] = {0};
2218
developer69b61b02023-03-07 17:17:44 +08002219 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002220 return RETURN_ERR;
2221
2222 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2223 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2224
2225 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002226 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002227 {
2228 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2229 return RETURN_ERR;
2230 }
2231 if(strcmp(buf,"g")==0)
2232 {
2233 wifi_dbg_printf("\nG\n");
2234 *gOnly=TRUE;
2235 *nOnly=FALSE;
2236 *acOnly=FALSE;
2237 }
2238 else if(strcmp(buf,"n")==0)
2239 {
2240 wifi_dbg_printf("\nN\n");
2241 *gOnly=FALSE;
2242 *nOnly=TRUE;
2243 *acOnly=FALSE;
2244 }
2245 else if(strcmp(buf,"ac")==0)
2246 {
2247 wifi_dbg_printf("\nac\n");
2248 *gOnly=FALSE;
2249 *nOnly=FALSE;
2250 *acOnly=TRUE;
2251 }
2252 /* hostapd-5G.conf has "a" as hw_mode */
2253 else if(strcmp(buf,"a")==0)
2254 {
2255 wifi_dbg_printf("\na\n");
2256 *gOnly=FALSE;
2257 *nOnly=FALSE;
2258 *acOnly=FALSE;
2259 }
2260 else
2261 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2262
2263 //for a,n mode
2264 if(radioIndex == 1)
2265 {
2266 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2267 if(strcmp(buf,"1")==0)
2268 {
2269 strncpy(output_string, "n", 1);
2270 *nOnly=FALSE;
2271 }
2272 }
2273
2274 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2276 return RETURN_OK;
2277#endif
2278}
2279
2280INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2281{
2282 char cmd[128] = {0};
2283 char buf[64] = {0};
2284 char config_file[64] = {0};
2285 wifi_band band;
2286
2287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2288 if(NULL == output_string || NULL == pureMode)
2289 return RETURN_ERR;
2290
2291 // grep all of the ieee80211 protocol config set to 1
2292 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2293 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
2294 _syscmd(cmd, buf, sizeof(buf));
2295
2296 band = wifi_index_to_band(radioIndex);
2297 // puremode is a bit map
2298 *pureMode = 0;
2299 if (band == band_2_4) {
2300 strcat(output_string, "b,g");
2301 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
2302 if (strstr(buf, "n") != NULL) {
2303 strcat(output_string, ",n");
2304 *pureMode |= WIFI_MODE_N;
2305 }
2306 if (strstr(buf, "ax") != NULL) {
2307 strcat(output_string, ",ax");
2308 *pureMode |= WIFI_MODE_AX;
2309 }
2310 } else if (band == band_5) {
2311 strcat(output_string, "a");
2312 *pureMode |= WIFI_MODE_A;
2313 if (strstr(buf, "n") != NULL) {
2314 strcat(output_string, ",n");
2315 *pureMode |= WIFI_MODE_N;
2316 }
2317 if (strstr(buf, "ac") != NULL) {
2318 strcat(output_string, ",ac");
2319 *pureMode |= WIFI_MODE_AC;
2320 }
2321 if (strstr(buf, "ax") != NULL) {
2322 strcat(output_string, ",ax");
2323 *pureMode |= WIFI_MODE_AX;
2324 }
2325 } else if (band == band_6) {
2326 if (strstr(buf, "ax") != NULL) {
2327 strcat(output_string, "ax");
2328 *pureMode |= WIFI_MODE_AX;
2329 }
2330 }
2331
2332 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2333 return RETURN_OK;
2334}
2335
2336// Set the radio operating mode, and pure mode flag.
2337INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2338{
developer69b61b02023-03-07 17:17:44 +08002339 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002340 if (strcmp (channelMode,"11A") == 0)
2341 {
2342 writeBandWidth(radioIndex,"20MHz");
2343 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2344 printf("\nChannel Mode is 802.11a (5GHz)\n");
2345 }
2346 else if (strcmp (channelMode,"11NAHT20") == 0)
2347 {
2348 writeBandWidth(radioIndex,"20MHz");
2349 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2350 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2351 }
2352 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2353 {
2354 writeBandWidth(radioIndex,"40MHz");
2355 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2356 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2357 }
2358 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2359 {
2360 writeBandWidth(radioIndex,"40MHz");
2361 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2362 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2363 }
2364 else if (strcmp (channelMode,"11ACVHT20") == 0)
2365 {
2366 writeBandWidth(radioIndex,"20MHz");
2367 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2368 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2369 }
2370 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2371 {
2372 writeBandWidth(radioIndex,"40MHz");
2373 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2374 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2375 }
2376 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2377 {
2378 writeBandWidth(radioIndex,"40MHz");
2379 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2380 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2381 }
2382 else if (strcmp (channelMode,"11ACVHT80") == 0)
2383 {
2384 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2385 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2386 }
2387 else if (strcmp (channelMode,"11ACVHT160") == 0)
2388 {
2389 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2390 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002391 }
developer72fb0bb2023-01-11 09:46:29 +08002392 else if (strcmp (channelMode,"11B") == 0)
2393 {
2394 writeBandWidth(radioIndex,"20MHz");
2395 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2396 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2397 }
2398 else if (strcmp (channelMode,"11G") == 0)
2399 {
2400 writeBandWidth(radioIndex,"20MHz");
2401 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2402 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2403 }
2404 else if (strcmp (channelMode,"11NGHT20") == 0)
2405 {
2406 writeBandWidth(radioIndex,"20MHz");
2407 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2408 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2409 }
2410 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2411 {
2412 writeBandWidth(radioIndex,"40MHz");
2413 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2414 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2415 }
2416 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2417 {
2418 writeBandWidth(radioIndex,"40MHz");
2419 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2420 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2421 }
developer69b61b02023-03-07 17:17:44 +08002422 else
developer72fb0bb2023-01-11 09:46:29 +08002423 {
2424 return RETURN_ERR;
2425 }
2426 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2427
2428 return RETURN_OK;
2429}
2430
2431// Set the radio operating mode, and pure mode flag.
2432INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2433{
2434 int num_hostapd_support_mode = 3; // n, ac, ax
2435 struct params list[num_hostapd_support_mode];
2436 char config_file[64] = {0};
2437 char bandwidth[16] = {0};
2438 int mode_check_bit = 1 << 3; // n mode
developer69b61b02023-03-07 17:17:44 +08002439
developer72fb0bb2023-01-11 09:46:29 +08002440
2441 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2442 // Set radio mode
2443 list[0].name = "ieee80211n";
2444 list[1].name = "ieee80211ac";
2445 list[2].name = "ieee80211ax";
2446 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2447
2448 // check the bit map from n to ax, and set hostapd config
2449 if (pureMode & WIFI_MODE_N)
2450 list[0].value = "1";
2451 else
2452 list[0].value = "0";
2453 if (pureMode & WIFI_MODE_AC)
2454 list[1].value = "1";
2455 else
2456 list[1].value = "0";
2457 if (pureMode & WIFI_MODE_AX)
2458 list[2].value = "1";
2459 else
2460 list[2].value = "0";
2461 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2462
2463 if (channelMode == NULL || strlen(channelMode) == 0)
2464 return RETURN_OK;
2465 // Set bandwidth
2466 if (strstr(channelMode, "40") != NULL)
2467 strcpy(bandwidth, "40MHz");
2468 else if (strstr(channelMode, "80") != NULL)
2469 strcpy(bandwidth, "80MHz");
2470 else if (strstr(channelMode, "160") != NULL)
2471 strcpy(bandwidth, "160MHz");
2472 else // 11A, 11B, 11G....
2473 strcpy(bandwidth, "20MHz");
2474
2475 writeBandWidth(radioIndex, bandwidth);
2476 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2477
2478 wifi_reloadAp(radioIndex);
2479 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2480
2481 return RETURN_OK;
2482}
2483
2484INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2485
2486 char config_file[64] = {0};
2487 char buf[64] = {0};
2488 struct params params = {0};
2489 wifi_band band = band_invalid;
2490
2491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2492
2493 band = wifi_index_to_band(radioIndex);
2494
2495 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2496 return RETURN_ERR;
2497 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2498 return RETURN_ERR;
2499 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2500 return RETURN_ERR;
2501
2502 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2503 params.name = "hw_mode";
2504 params.value = hw_mode;
2505 wifi_hostapdWrite(config_file, &params, 1);
2506 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2507
2508 if (band == band_2_4) {
2509 if (strncmp(hw_mode, "b", 1) == 0) {
2510 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2511 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2512 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2513 snprintf(buf, sizeof(buf), "%s", "1,2");
2514 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2515 } else {
2516 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2517
2518 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2519 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2520 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2521 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2522 }
2523 }
2524
2525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2526 return RETURN_OK;
2527}
2528
2529INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2530{
2531 char config_file[64] = {0};
2532 struct params params = {0};
2533 wifi_band band = band_invalid;
2534
2535 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2536
2537 band = wifi_index_to_band(radioIndex);
2538 if (band != band_2_4)
2539 return RETURN_OK;
2540
2541 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2542 params.name = "noscan";
2543 params.value = noscan;
2544 wifi_hostapdWrite(config_file, &params, 1);
2545 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2546
2547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2548 return RETURN_OK;
2549}
2550
2551//Get the list of supported channel. eg: "1-11"
2552//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.
2553INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2554{
2555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002556 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002557 return RETURN_ERR;
2558 char cmd[256] = {0};
2559 char buf[128] = {0};
2560 BOOL dfs_enable = false;
2561 int phyId = 0;
2562
2563 // Parse possible channel number and separate them with commas.
2564 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2565 phyId = radio_index_to_phy(radioIndex);
2566 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2567 if (dfs_enable)
2568 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 +08002569 else
developer72fb0bb2023-01-11 09:46:29 +08002570 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);
2571
2572 _syscmd(cmd,buf,sizeof(buf));
2573 strncpy(output_string, buf, sizeof(buf));
2574
2575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2576 return RETURN_OK;
2577}
2578
2579//Get the list for used channel. eg: "1,6,9,11"
2580//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.
2581INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2582{
2583 char interface_name[16] = {0};
2584 char cmd[128] = {0};
2585 char buf[128] = {0};
2586 char config_file[64] = {0};
2587 int channel = 0;
2588 int freq = 0;
2589 int bandwidth = 0;
2590 int center_freq = 0;
2591 int center_channel = 0;
2592 int channel_delta = 0;
2593 wifi_band band = band_invalid;
2594
2595 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2596
2597 if (NULL == output_string)
2598 return RETURN_ERR;
2599
2600 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2601 return RETURN_ERR;
2602 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2603 _syscmd(cmd, buf, sizeof(buf));
2604 if (strlen(buf) == 0) {
2605 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2606 return RETURN_ERR;
2607 }
2608 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2609
2610 if (bandwidth == 20) {
2611 snprintf(output_string, 256, "%d", channel);
2612 return RETURN_OK;
2613 }
2614
2615 center_channel = ieee80211_frequency_to_channel(center_freq);
2616
2617 band = wifi_index_to_band(radioIndex);
2618 if (band == band_2_4 && bandwidth == 40) {
2619 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2620 memset(buf, 0, sizeof(buf));
2621 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2622
2623 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2624 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2625 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2626 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2627 } else {
2628 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2629 return RETURN_ERR;
2630 }
2631 } else if (band == band_5 || band == band_6){
2632 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2633 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2634 channel_delta = (bandwidth-20)/10;
2635 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2636 } else
2637 return RETURN_ERR;
2638
2639 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2640 return RETURN_OK;
2641}
2642
developer69b61b02023-03-07 17:17:44 +08002643//Get the running channel number
developer72fb0bb2023-01-11 09:46:29 +08002644INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2645{
2646 char channel_str[16] = {0};
2647 char config_file[128] = {0};
2648
2649 if (output_ulong == NULL)
2650 return RETURN_ERR;
2651
2652 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2653 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2654
2655 *output_ulong = strtoul(channel_str, NULL, 10);
2656
2657 return RETURN_OK;
2658}
2659
2660
2661INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2662{
2663 char cmd[1024] = {0}, buf[5] = {0};
2664 char interface_name[16] = {0};
2665
2666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2667 if (NULL == output_ulong)
2668 return RETURN_ERR;
2669
2670 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2671 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2672 return RETURN_ERR;
2673 _syscmd(cmd,buf,sizeof(buf));
2674 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2675 if (*output_ulong == 0) {
2676 return RETURN_ERR;
2677 }
2678
2679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2680 return RETURN_OK;
2681}
2682
2683//Storing the previous channel value
2684INT wifi_storeprevchanval(INT radioIndex)
2685{
2686 char buf[256] = {0};
2687 char output[4]={'\0'};
2688 char config_file[MAX_BUF_SIZE] = {0};
2689 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2690 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2691 if(radioIndex == 0)
2692 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2693 else if(radioIndex == 1)
2694 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2695 system(buf);
2696 Radio_flag = FALSE;
2697 return RETURN_OK;
2698}
2699
2700//Set the running channel number
2701INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2702{
2703 // We only write hostapd config here
2704 char str_channel[8]={0};
2705 char *list_channel;
2706 char config_file[128] = {0};
2707 char possible_channels[256] = {0};
2708 int max_radio_num = 0;
2709 struct params list = {0};
2710
2711 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2712
2713 // Check valid
2714 sprintf(str_channel, "%lu", channel);
2715
2716 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2717 list_channel = strtok(possible_channels, ",");
2718 while(true)
2719 {
2720 if(list_channel == NULL) { // input not in the list
2721 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2722 return RETURN_ERR;
2723 }
2724 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2725 break;
2726 list_channel = strtok(NULL, ",");
2727 }
2728
2729 list.name = "channel";
2730 list.value = str_channel;
2731 wifi_getMaxRadioNumber(&max_radio_num);
2732 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2733 {
2734 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2735 wifi_hostapdWrite(config_file, &list, 1);
2736 }
2737
2738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2739 return RETURN_OK;
2740}
2741
2742INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2743{
2744 struct params list[2];
2745 char str_idx[16];
2746 char config_file[64];
2747 int max_num_radios = 0;
2748 wifi_band band = band_invalid;
2749
2750 band = wifi_index_to_band(radioIndex);
2751 if (band == band_2_4)
2752 return RETURN_OK;
2753
2754 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2755 list[0].name = "vht_oper_centr_freq_seg0_idx";
2756 list[0].value = str_idx;
2757 list[1].name = "he_oper_centr_freq_seg0_idx";
2758 list[1].value = str_idx;
2759
2760 wifi_getMaxRadioNumber(&max_num_radios);
2761 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2762 {
2763 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2764 if (band == band_6)
2765 wifi_hostapdWrite(config_file, &list[1], 1);
2766 else
2767 wifi_hostapdWrite(config_file, list, 2);
2768 }
2769
2770 return RETURN_OK;
2771}
2772
2773//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2774//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2775INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2776{
2777 //Set to wifi config only. Wait for wifi reset to apply.
2778 char buf[256] = {0};
2779 char str_channel[256] = {0};
2780 int count = 0;
2781 ULONG Value = 0;
2782 FILE *fp = NULL;
2783 if(enable == TRUE)
2784 {
2785 wifi_setRadioChannel(radioIndex,Value);
2786 }
2787 return RETURN_OK;
2788}
2789
2790INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2791{
2792 if (output_bool == NULL)
2793 return RETURN_ERR;
2794
2795 *output_bool = TRUE;
2796
2797 return RETURN_OK;
2798}
2799
2800INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2801{
developer69b61b02023-03-07 17:17:44 +08002802 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002803 return RETURN_ERR;
2804 *output_bool=FALSE;
2805 return RETURN_OK;
2806}
2807
2808INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2809{
developer69b61b02023-03-07 17:17:44 +08002810 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002811 return RETURN_ERR;
2812 *output_bool=FALSE;
2813 return RETURN_OK;
2814}
2815
2816INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2817{
2818 //Set to wifi config only. Wait for wifi reset to apply.
2819 return RETURN_OK;
2820}
2821
2822INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2823{
2824 return RETURN_OK;
2825}
2826
2827INT wifi_factoryResetAP(int apIndex)
2828{
2829 char ap_config_file[64] = {0};
2830 char cmd[128] = {0};
2831
2832 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2833
2834 wifi_setApEnable(apIndex, FALSE);
2835 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2836 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2837 wifi_setApEnable(apIndex, TRUE);
2838
2839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2840
2841 return RETURN_OK;
2842}
2843
2844//To set Band Steering AP group
2845//To-do
2846INT wifi_setBandSteeringApGroup(char *ApGroup)
2847{
2848 return RETURN_OK;
2849}
2850
2851INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2852{
2853 char config_file[128] = {'\0'};
2854 char buf[128] = {'\0'};
2855
2856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2857 if (dtimInterval == NULL)
2858 return RETURN_ERR;
2859
2860 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2861 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2862
2863 if (strlen(buf) == 0) {
2864 *dtimInterval = 2;
2865 } else {
2866 *dtimInterval = strtoul(buf, NULL, 10);
2867 }
2868
2869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2870 return RETURN_OK;
2871}
2872
2873INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2874{
2875 struct params params={0};
2876 char config_file[MAX_BUF_SIZE] = {'\0'};
2877 char buf[MAX_BUF_SIZE] = {'\0'};
2878
2879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2880 if (dtimInterval < 1 || dtimInterval > 255) {
2881 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2882 return RETURN_ERR;
2883 }
developer69b61b02023-03-07 17:17:44 +08002884
developer72fb0bb2023-01-11 09:46:29 +08002885 params.name = "dtim_period";
2886 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2887 params.value = buf;
2888
2889 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2890 wifi_hostapdWrite(config_file, &params, 1);
2891 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2892
2893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2894 return RETURN_OK;
2895}
2896
2897//Check if the driver support the Dfs
2898INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2899{
2900 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08002901 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002902 return RETURN_ERR;
2903 *output_bool=FALSE;
2904
2905 band = wifi_index_to_band(radioIndex);
2906 if (band == band_5)
2907 *output_bool = TRUE;
2908 return RETURN_OK;
2909}
2910
2911//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.
2912//The value of this parameter is a comma seperated list of channel number
2913INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2914{
developer69b61b02023-03-07 17:17:44 +08002915 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08002916 return RETURN_ERR;
2917 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08002918 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08002919 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2920
2921 return RETURN_OK;
2922}
2923
2924INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2925{
2926 //Set to wifi config. And apply instantly.
2927 return RETURN_OK;
2928}
2929
2930INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2931{
developer69b61b02023-03-07 17:17:44 +08002932 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08002933 return RETURN_ERR;
2934 *output_interval_seconds=1800;
2935 *output_dwell_milliseconds=40;
2936
2937 return RETURN_OK;
2938}
2939
2940INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2941{
2942 //Set to wifi config. And apply instantly.
2943 return RETURN_OK;
2944}
2945
2946INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2947{
2948 if (output_bool == NULL)
2949 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08002950 *output_bool = true;
2951 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002952}
2953
2954INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2955{
2956 return RETURN_OK;
2957}
2958
2959//Get the Dfs enable status
2960INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2961{
2962 char buf[16] = {0};
2963 FILE *f = NULL;
2964
2965 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2966
2967 if (output_bool == NULL)
2968 return RETURN_ERR;
2969
2970 *output_bool = TRUE; // default
2971 f = fopen(DFS_ENABLE_FILE, "r");
2972 if (f != NULL) {
2973 fgets(buf, 2, f);
2974 if (strncmp(buf, "0", 1) == 0)
2975 *output_bool = FALSE;
2976 fclose(f);
2977 }
2978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2979 return RETURN_OK;
2980}
2981
2982//Set the Dfs enable status
2983INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2984{
2985 char config_file[128] = {0};
2986 FILE *f = NULL;
2987 struct params params={0};
2988
2989 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2990
2991 f = fopen(DFS_ENABLE_FILE, "w");
2992 if (f == NULL)
2993 return RETURN_ERR;
2994 fprintf(f, "%d", enable);
2995 fclose(f);
2996
2997 params.name = "acs_exclude_dfs";
2998 params.value = enable?"0":"1";
2999 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3000 wifi_hostapdWrite(config_file, &params, 1);
3001 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3002
3003 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
3004
3005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3006 return RETURN_OK;
3007}
3008
3009//Check if the driver support the AutoChannelRefreshPeriod
3010INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
3011{
developer69b61b02023-03-07 17:17:44 +08003012 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003013 return RETURN_ERR;
3014 *output_bool=FALSE; //not support
3015
3016 return RETURN_OK;
3017}
3018
3019//Get the ACS refresh period in seconds
3020INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
3021{
developer69b61b02023-03-07 17:17:44 +08003022 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08003023 return RETURN_ERR;
3024 *output_ulong=300;
3025
3026 return RETURN_OK;
3027}
3028
3029//Set the ACS refresh period in seconds
3030INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
3031{
3032 return RETURN_ERR;
3033}
3034
3035//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
3036//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.
3037INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
3038{
developer8666b312023-03-24 14:05:31 +08003039 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08003040 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08003041 char interface_name[64] = {0};
3042 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08003043 BOOL radio_enable = FALSE;
3044 wifi_band band;
3045
3046 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3047
3048 if (NULL == output_string)
3049 return RETURN_ERR;
3050
3051 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
3052 return RETURN_ERR;
3053
3054 if (radio_enable != TRUE)
3055 return RETURN_OK;
3056
developer8666b312023-03-24 14:05:31 +08003057 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3058 return RETURN_ERR;
3059 /*IW command get BW320 to do*/
3060 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3061 ret = _syscmd(cmd, buf, sizeof(buf));
3062 len = strlen(buf);
3063 if((ret != 0) || (len == 0))
3064 {
3065 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3066 return RETURN_ERR;
3067 }
3068
developer72fb0bb2023-01-11 09:46:29 +08003069 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003070 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003071 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003072 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3073 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003074 }
developer8666b312023-03-24 14:05:31 +08003075 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003076 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3077
3078 return RETURN_OK;
3079}
developer72fb0bb2023-01-11 09:46:29 +08003080//Set the Operating Channel Bandwidth.
3081INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3082{
3083 char config_file[128];
3084 char set_value[16];
3085 struct params params[2];
3086 int max_radio_num = 0;
3087
3088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3089
3090 if(NULL == bandwidth)
3091 return RETURN_ERR;
3092
3093 if(strstr(bandwidth,"160") != NULL)
3094 strcpy(set_value, "2");
3095 else if(strstr(bandwidth,"80") != NULL)
3096 strcpy(set_value, "1");
3097 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
3098 strcpy(set_value, "0");
3099 else
3100 {
3101 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3102 return RETURN_ERR;
3103 }
3104
3105 params[0].name = "vht_oper_chwidth";
3106 params[0].value = set_value;
3107 params[1].name = "he_oper_chwidth";
3108 params[1].value = set_value;
3109
3110 wifi_getMaxRadioNumber(&max_radio_num);
3111 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3112 {
3113 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3114 wifi_hostapdWrite(config_file, params, 2);
3115 }
3116
3117 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3118 return RETURN_OK;
3119}
3120
3121//Getting current radio extension channel
3122INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3123{
3124 CHAR buf[150] = {0};
3125 CHAR cmd[150] = {0};
3126 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
3127 _syscmd(cmd, buf, sizeof(buf));
3128 if(NULL != strstr(buf,"HT40+"))
3129 strcpy(Value,"AboveControlChannel");
3130 else if(NULL != strstr(buf,"HT40-"))
3131 strcpy(Value,"BelowControlChannel");
3132 return RETURN_OK;
3133}
3134
3135//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3136//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.
3137INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3138{
3139 char config_file[64] = {0};
3140 char mode_str[16] = {0};
3141 char buf[64] = {0};
3142 wifi_band band;
3143 int channel = 0, centr_channel = 0;
3144 UINT mode_map = 0;
3145
3146 if (output_string == NULL)
3147 return RETURN_ERR;
3148
3149 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3150
3151 band = wifi_index_to_band(radioIndex);
3152 if (band == band_invalid)
3153 return RETURN_ERR;
3154
3155 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3156
3157 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003158 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08003159 // 2G band or ac and ax mode is disable, we will check ht_capab
3160 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08003161 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003162 snprintf(output_string, 64, "Auto");
3163 } else {
3164 // 5G and 6G band with ac or ax mode.
3165 wifi_getRadioChannel(radioIndex, &channel);
3166 if (mode_map&WIFI_MODE_AX)
3167 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3168 else
3169 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3170 centr_channel = strtol(buf, NULL, 10);
3171 if (centr_channel > channel)
3172 snprintf(output_string, 64, "AboveControlChannel");
3173 else
3174 snprintf(output_string, 64, "BelowControlChannel");
3175 }
3176
3177 return RETURN_OK;
3178}
3179
3180//Set the extension channel.
3181INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003182{
developer72fb0bb2023-01-11 09:46:29 +08003183 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3184 struct params params={0};
3185 char config_file[64] = {0};
3186 char ext_channel[128]={0};
3187 char buf[128] = {0};
3188 char cmd[128] = {0};
3189 int max_radio_num =0, ret = 0, bandwidth = 0;
3190 unsigned long channel = 0, centr_channel = 0;
3191 bool stbcEnable = FALSE;
3192 params.name = "ht_capab";
3193 wifi_band band;
3194
3195 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3196 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3197 _syscmd(cmd, buf, sizeof(buf));
3198 if (strlen(buf) != 0)
3199 stbcEnable = TRUE;
3200 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3201 return RETURN_ERR;
3202 bandwidth = strtol(buf, NULL, 10);
3203 // TDK expected to get error with 20MHz
3204 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3205 return RETURN_ERR;
3206
3207 band = wifi_index_to_band(radioIndex);
3208 if (band == band_invalid)
3209 return RETURN_ERR;
3210
3211 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3212 return RETURN_ERR;
3213
3214 if (band == band_5) {
3215 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3216 centr_channel = util_unii_5g_centerfreq(buf, channel);
3217 if (centr_channel == 0)
3218 return RETURN_ERR;
3219 }
3220
3221 if(NULL!= strstr(string,"Above")) {
3222 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3223 return RETURN_ERR;
3224 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
3225 } else if(NULL!= strstr(string,"Below")) {
3226 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3227 return RETURN_ERR;
3228 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
3229 } else {
3230 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
3231 }
3232
3233 params.value = ext_channel;
3234
3235 wifi_getMaxRadioNumber(&max_radio_num);
3236 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3237 {
3238 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
3239 wifi_hostapdWrite(config_file, &params, 1);
3240 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3241 }
3242
3243 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3245 return RETURN_OK;
3246}
3247
3248//Get the guard interval value. eg "400nsec" or "800nsec"
3249//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.
3250INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3251{
3252 wifi_guard_interval_t GI;
3253
3254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3255
3256 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3257 return RETURN_ERR;
3258
3259 if (GI == wifi_guard_interval_400)
3260 strcpy(output_string, "400nsec");
3261 else if (GI == wifi_guard_interval_800)
3262 strcpy(output_string, "800nsec");
3263 else if (GI == wifi_guard_interval_1600)
3264 strcpy(output_string, "1600nsec");
3265 else if (GI == wifi_guard_interval_3200)
3266 strcpy(output_string, "3200nsec");
3267 else
3268 strcpy(output_string, "Auto");
3269
3270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3271 return RETURN_OK;
3272}
3273
3274//Set the guard interval value.
3275INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3276{
3277 wifi_guard_interval_t GI;
3278 int ret = 0;
3279
3280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3281
3282 if (strcmp(string, "400nsec") == 0)
3283 GI = wifi_guard_interval_400;
3284 else if (strcmp(string , "800nsec") == 0)
3285 GI = wifi_guard_interval_800;
3286 else if (strcmp(string , "1600nsec") == 0)
3287 GI = wifi_guard_interval_1600;
3288 else if (strcmp(string , "3200nsec") == 0)
3289 GI = wifi_guard_interval_3200;
3290 else
3291 GI = wifi_guard_interval_auto;
3292
3293 ret = wifi_setGuardInterval(radioIndex, GI);
3294
3295 if (ret == RETURN_ERR) {
3296 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3297 return RETURN_ERR;
3298 }
3299
3300 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3301 return RETURN_OK;
3302}
3303
3304//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3305INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3306{
3307 char buf[32]={0};
3308 char mcs_file[64] = {0};
3309 char cmd[64] = {0};
3310 int mode_bitmap = 0;
3311
3312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3313 if(output_int == NULL)
3314 return RETURN_ERR;
3315 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3316
3317 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3318 _syscmd(cmd, buf, sizeof(buf));
3319 if (strlen(buf) > 0)
3320 *output_int = strtol(buf, NULL, 10);
3321 else {
3322 // output the max MCS for the current radio mode
3323 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3324 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3325 return RETURN_ERR;
3326 }
3327 if (mode_bitmap & WIFI_MODE_AX) {
3328 *output_int = 11;
3329 } else if (mode_bitmap & WIFI_MODE_AC) {
3330 *output_int = 9;
3331 } else if (mode_bitmap & WIFI_MODE_N) {
3332 *output_int = 7;
3333 }
3334 }
3335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3336
3337 return RETURN_OK;
3338}
3339
3340//Set the Modulation Coding Scheme index
3341INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3342{
3343 // Only HE mode can specify MCS capability. We don't support MCS in HT mode, because that would be ambiguous (MCS code 8~11 refer to 2 NSS in HT but 1 NSS in HE adn VHT).
3344 char config_file[64] = {0};
3345 char set_value[16] = {0};
3346 char mcs_file[32] = {0};
3347 wifi_band band = band_invalid;
3348 struct params set_config = {0};
3349 FILE *f = NULL;
3350
3351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3352
3353 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3354
3355 // -1 means auto
3356 if (MCS > 15 || MCS < -1) {
3357 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3358 return RETURN_ERR;
3359 }
3360
3361 if (MCS > 9 || MCS == -1)
3362 strcpy(set_value, "2");
3363 else if (MCS > 7)
3364 strcpy(set_value, "1");
3365 else
3366 strcpy(set_value, "0");
3367
3368 set_config.name = "he_basic_mcs_nss_set";
3369 set_config.value = set_value;
3370
3371 wifi_hostapdWrite(config_file, &set_config, 1);
3372 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3373
3374 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3375 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3376 f = fopen(mcs_file, "w");
3377 if (f == NULL) {
3378 fprintf(stderr, "%s: fopen failed\n", __func__);
3379 return RETURN_ERR;
3380 }
3381 fprintf(f, "%d", MCS);
3382 fclose(f);
3383
3384 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3385 return RETURN_OK;
3386}
3387
3388//Get supported Transmit Power list, eg : "0,25,50,75,100"
3389//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.
3390INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3391{
3392 if (NULL == output_list)
3393 return RETURN_ERR;
3394 snprintf(output_list, 64,"0,25,50,75,100");
3395 return RETURN_OK;
3396}
3397
3398//Get current Transmit Power in dBm units.
3399//The transmite power level is in units of full power for this radio.
3400INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3401{
3402 char interface_name[16] = {0};
3403 char cmd[128]={0};
3404 char buf[16]={0};
3405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3406
3407 if(output_ulong == NULL)
3408 return RETURN_ERR;
3409
3410 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3411 return RETURN_ERR;
3412 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3413 _syscmd(cmd, buf, sizeof(buf));
3414
3415 *output_ulong = strtol(buf, NULL, 10);
3416
3417 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3418 return RETURN_OK;
3419}
3420
3421//Set Transmit Power
3422//The transmite power level is in units of full power for this radio.
3423INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3424{
3425 char interface_name[16] = {0};
3426 char *support;
3427 char cmd[128]={0};
3428 char buf[128]={0};
3429 char txpower_str[64] = {0};
3430 int txpower = 0;
3431 int maximum_tx = 0;
3432 int phyId = 0;
3433
3434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3435
3436 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3437 return RETURN_ERR;
3438 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
3439 _syscmd(cmd, buf, sizeof(buf));
3440 maximum_tx = strtol(buf, NULL, 10);
3441
3442 // Get the Tx power supported list and check that is the input in the list
3443 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3444 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3445 support = strtok(buf, ",");
3446 while(true)
3447 {
3448 if(support == NULL) { // input not in the list
3449 wifi_dbg_printf("Input value is invalid.\n");
3450 return RETURN_ERR;
3451 }
3452 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3453 break;
3454 }
3455 support = strtok(NULL, ",");
3456 }
3457 txpower = TransmitPower*maximum_tx/100;
3458 phyId = radio_index_to_phy(radioIndex);
3459 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3460 _syscmd(cmd, buf, sizeof(buf));
3461 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3462
3463 return RETURN_OK;
3464}
3465
3466//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3467INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3468{
developer69b61b02023-03-07 17:17:44 +08003469 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08003470 return RETURN_ERR;
3471 *Supported = TRUE;
3472
3473 return RETURN_OK;
3474}
3475
3476//Get 80211h feature enable
3477INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3478{
3479 char buf[64]={'\0'};
3480 char config_file[64] = {'\0'};
3481
3482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3483 if(enable == NULL)
3484 return RETURN_ERR;
3485
3486 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3487 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3488
3489 if (strncmp(buf, "1", 1) == 0)
3490 *enable = TRUE;
3491 else
3492 *enable = FALSE;
3493
3494 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3495 return RETURN_OK;
3496}
3497
3498//Set 80211h feature enable
3499INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3500{
3501 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3502 struct params params={'\0'};
3503 char config_file[MAX_BUF_SIZE] = {0};
3504
3505 params.name = "ieee80211h";
3506
3507 if (enable) {
3508 params.value = "1";
3509 } else {
3510 params.value = "0";
3511 }
3512
3513 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3514 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003515
developer72fb0bb2023-01-11 09:46:29 +08003516 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3517 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3518 return RETURN_OK;
3519}
3520
3521//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.
3522INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3523{
3524 if (NULL == output)
3525 return RETURN_ERR;
3526 *output=100;
3527
3528 return RETURN_OK;
3529}
3530
3531//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.
3532INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3533{
3534 if (NULL == output)
3535 return RETURN_ERR;
3536 *output = -99;
3537
3538 return RETURN_OK;
3539}
3540
3541INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3542{
3543 return RETURN_ERR;
3544}
3545
3546
3547//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3548INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3549{
3550 char interface_name[16] = {0};
3551 char cmd[MAX_BUF_SIZE]={'\0'};
3552 char buf[MAX_CMD_SIZE]={'\0'};
3553
3554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3555 if(output == NULL)
3556 return RETURN_ERR;
3557
3558 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3559 return RETURN_ERR;
3560 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3561 _syscmd(cmd, buf, sizeof(buf));
3562 *output = atoi(buf);
3563
3564 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3565 return RETURN_OK;
3566}
developer69b61b02023-03-07 17:17:44 +08003567
developer72fb0bb2023-01-11 09:46:29 +08003568INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3569{
3570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3571 struct params params={'\0'};
3572 char buf[MAX_BUF_SIZE] = {'\0'};
3573 char config_file[MAX_BUF_SIZE] = {'\0'};
3574
3575 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3576 return RETURN_ERR;
3577
3578 params.name = "beacon_int";
3579 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3580 params.value = buf;
3581
3582 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3583 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003584
developer72fb0bb2023-01-11 09:46:29 +08003585 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3586 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3587 return RETURN_OK;
3588}
3589
3590//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.
3591INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3592{
3593 //TODO: need to revisit below implementation
3594 char *temp;
3595 char temp_output[128] = {0};
3596 char temp_TransmitRates[64] = {0};
3597 char config_file[64] = {0};
3598
3599 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3600 if (NULL == output)
3601 return RETURN_ERR;
3602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3603 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08003604
developer72fb0bb2023-01-11 09:46:29 +08003605 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3606 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3607 } else {
3608 temp = strtok(temp_TransmitRates," ");
3609 while(temp!=NULL)
3610 {
3611 // Convert 100 kbps to Mbps
3612 temp[strlen(temp)-1]=0;
3613 if((temp[0]=='5') && (temp[1]=='\0'))
3614 {
3615 temp="5.5";
3616 }
3617 strcat(temp_output,temp);
3618 temp = strtok(NULL," ");
3619 if(temp!=NULL)
3620 {
3621 strcat(temp_output,",");
3622 }
3623 }
3624 strcpy(output,temp_output);
3625 }
3626 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3627 return RETURN_OK;
3628}
3629
3630INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3631{
3632 char *temp;
3633 char temp1[128];
3634 char temp_output[128];
3635 char temp_TransmitRates[128];
3636 char set[128];
3637 char sub_set[128];
3638 int set_count=0,subset_count=0;
3639 int set_index=0,subset_index=0;
3640 char *token;
3641 int flag=0, i=0;
3642 struct params params={'\0'};
3643 char config_file[MAX_BUF_SIZE] = {0};
3644 wifi_band band = wifi_index_to_band(radioIndex);
3645
3646 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3647 if(NULL == TransmitRates)
3648 return RETURN_ERR;
3649 strcpy(sub_set,TransmitRates);
3650
3651 //Allow only supported Data transmit rate to be set
3652 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3653 token = strtok(sub_set,",");
3654 while( token != NULL ) /* split the basic rate to be set, by comma */
3655 {
3656 sub_set[subset_count]=atoi(token);
3657 subset_count++;
3658 token=strtok(NULL,",");
3659 }
3660 token=strtok(set,",");
3661 while(token!=NULL) /* split the supported rate by comma */
3662 {
3663 set[set_count]=atoi(token);
3664 set_count++;
3665 token=strtok(NULL,",");
3666 }
3667 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3668 {
3669 for(set_index=0;set_index < set_count;set_index++)
3670 {
3671 flag=0;
3672 if(sub_set[subset_index]==set[set_index])
3673 break;
3674 else
3675 flag=1; /* No match found */
3676 }
3677 if(flag==1)
3678 return RETURN_ERR; //If value not found return Error
3679 }
3680 strcpy(temp_TransmitRates,TransmitRates);
3681
3682 for(i=0;i<strlen(temp_TransmitRates);i++)
3683 {
3684 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3685 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3686 {
3687 continue;
3688 }
3689 else
3690 {
3691 return RETURN_ERR;
3692 }
3693 }
3694 strcpy(temp_output,"");
3695 temp = strtok(temp_TransmitRates,",");
3696 while(temp!=NULL)
3697 {
3698 strcpy(temp1,temp);
3699 if(band == band_5)
3700 {
3701 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3702 {
3703 return RETURN_ERR;
3704 }
3705 }
3706
3707 if(strcmp(temp,"5.5")==0)
3708 {
3709 strcpy(temp1,"55");
3710 }
3711 else
3712 {
3713 strcat(temp1,"0");
3714 }
3715 strcat(temp_output,temp1);
3716 temp = strtok(NULL,",");
3717 if(temp!=NULL)
3718 {
3719 strcat(temp_output," ");
3720 }
3721 }
3722 strcpy(TransmitRates,temp_output);
3723
3724 params.name= "basic_rates";
3725 params.value =TransmitRates;
3726
3727 wifi_dbg_printf("\n%s:",__func__);
3728 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3729 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3730 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3731 wifi_hostapdWrite(config_file,&params,1);
3732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3733 return RETURN_OK;
3734}
3735
3736//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3737INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3738{
3739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3740 FILE *fp = NULL;
3741 char path[256] = {0}, output_string[256] = {0};
3742 int count = 0;
3743 char *interface = NULL;
3744
3745 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3746 if (fp == NULL)
3747 {
3748 printf("Failed to run command in Function %s\n", __FUNCTION__);
3749 return RETURN_ERR;
3750 }
3751 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3752 {
3753 interface = strchr(path, '=');
3754
3755 if (interface != NULL)
3756 {
3757 strcpy(output_string, interface + 1);
3758 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3759 interface_name[count] = output_string[count];
3760
3761 interface_name[count] = '\0';
3762 }
3763 }
3764 pclose(fp);
3765 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3766 return RETURN_OK;
3767}
3768
3769INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3770{
3771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3772 output_struct->radio_BytesSent = 0;
3773 output_struct->radio_BytesReceived = 0;
3774 output_struct->radio_PacketsSent = 0;
3775 output_struct->radio_PacketsReceived = 0;
3776 output_struct->radio_ErrorsSent = 0;
3777 output_struct->radio_ErrorsReceived = 0;
3778 output_struct->radio_DiscardPacketsSent = 0;
3779 output_struct->radio_DiscardPacketsReceived = 0;
3780 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3781 return RETURN_OK;
3782}
3783
3784
3785INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3786{
3787 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3788 CHAR buf[MAX_CMD_SIZE] = {0};
3789 CHAR Value[MAX_BUF_SIZE] = {0};
3790 FILE *fp = NULL;
3791
3792 if (ifname == NULL || strlen(ifname) <= 1)
3793 return RETURN_OK;
3794
3795 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3796 system(buf);
3797
3798 fp = fopen("/tmp/Radio_Stats.txt", "r");
3799 if(fp == NULL)
3800 {
3801 printf("/tmp/Radio_Stats.txt not exists \n");
3802 return RETURN_ERR;
3803 }
3804 fclose(fp);
3805
3806 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3807 File_Reading(buf, Value);
3808 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3809
3810 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3811 File_Reading(buf, Value);
3812 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3813
3814 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3815 File_Reading(buf, Value);
3816 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3817
3818 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3819 File_Reading(buf, Value);
3820 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3821
3822 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3823 File_Reading(buf, Value);
3824 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3825
3826 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3827 File_Reading(buf, Value);
3828 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3829
3830 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3831 File_Reading(buf, Value);
3832 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3833
3834 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3835 File_Reading(buf, Value);
3836 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3837
3838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3839 return RETURN_OK;
3840}
3841
3842INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3843{
developer7e4a2a62023-04-06 19:56:03 +08003844 CHAR buf[MAX_CMD_SIZE] = {0};
3845 INT count = 0;
developer72fb0bb2023-01-11 09:46:29 +08003846
developer7e4a2a62023-04-06 19:56:03 +08003847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3848
3849 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL) {
3850 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3851 File_Reading(buf, status);
3852 }
3853
3854 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3855 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08003856}
3857
3858//Get detail radio traffic static info
3859INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3860{
3861
developer69b61b02023-03-07 17:17:44 +08003862#if 0
3863 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08003864 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3865 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3866 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3867 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3868
3869 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3870 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3871 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.
3872 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.
3873
developer69b61b02023-03-07 17:17:44 +08003874 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 +08003875 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].
3876 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3877 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.
3878 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
3879 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
3880 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
3881 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
3882 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
3883
3884 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
3885 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
3886 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
3887 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.
3888
3889 return RETURN_OK;
3890#endif
3891
3892 CHAR interface_name[64] = {0};
3893 BOOL iface_status = FALSE;
3894 wifi_radioTrafficStats2_t radioTrafficStats = {0};
3895
3896 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3897 if (NULL == output_struct)
3898 return RETURN_ERR;
3899
3900 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3901 return RETURN_ERR;
3902
3903 wifi_getApEnable(radioIndex, &iface_status);
3904
3905 if (iface_status == TRUE)
3906 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3907 else
3908 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
3909
3910 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3911 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3912 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3913 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3914 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3915 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3916 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3917 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
3918
3919 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3920 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].
3921 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3922 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.
3923 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
3924 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
3925 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
3926 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
3927 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
3928
3929 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
3930 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
3931 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
3932 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.
3933
3934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3935
3936 return RETURN_OK;
3937}
3938
3939//Set radio traffic static Measureing rules
3940INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3941{
3942 //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
3943 // Else, save the MeasuringRate and MeasuringInterval for future usage
3944
3945 return RETURN_OK;
3946}
3947
3948//To start or stop RadioTrafficStats
3949INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3950{
3951 //zqiu: If the RadioTrafficStats process running
3952 // if(enable)
3953 // return RETURN_OK.
3954 // else
3955 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08003956 // Else
developer72fb0bb2023-01-11 09:46:29 +08003957 // if(enable)
3958 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3959 // else
3960 // return RETURN_OK.
3961
3962 return RETURN_OK;
3963}
3964
3965//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
3966INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3967{
3968 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08003969 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08003970 return RETURN_ERR;
3971 *SignalLevel=(radioIndex==0)?-19:-19;
3972
3973 return RETURN_OK;
3974}
3975
3976//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3977INT wifi_applyRadioSettings(INT radioIndex)
3978{
3979 return RETURN_OK;
3980}
3981
3982//Get the radio index assocated with this SSID entry
3983INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3984{
3985 if(NULL == radioIndex)
3986 return RETURN_ERR;
3987 int max_radio_num = 0;
3988 wifi_getMaxRadioNumber(&max_radio_num);
3989 *radioIndex = ssidIndex%max_radio_num;
3990 return RETURN_OK;
3991}
3992
3993//Device.WiFi.SSID.{i}.Enable
3994//Get SSID enable configuration parameters (not the SSID enable status)
3995INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3996{
developer69b61b02023-03-07 17:17:44 +08003997 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003998 return RETURN_ERR;
3999
4000 return wifi_getApEnable(ssidIndex, output_bool);
4001}
4002
4003//Device.WiFi.SSID.{i}.Enable
4004//Set SSID enable configuration parameters
4005INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
4006{
4007 return wifi_setApEnable(ssidIndex, enable);
4008}
4009
4010//Device.WiFi.SSID.{i}.Status
4011//Get the SSID enable status
4012INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
4013{
4014 char cmd[MAX_CMD_SIZE]={0};
4015 char buf[MAX_BUF_SIZE]={0};
4016 BOOL output_bool;
4017
4018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4019 if (NULL == output_string)
4020 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08004021
developer72fb0bb2023-01-11 09:46:29 +08004022 wifi_getApEnable(ssidIndex,&output_bool);
4023 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
4024
4025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4026 return RETURN_OK;
4027}
4028
4029// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
4030INT wifi_getSSIDName(INT apIndex, CHAR *output)
4031{
4032 char config_file[MAX_BUF_SIZE] = {0};
4033
developer69b61b02023-03-07 17:17:44 +08004034 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08004035 return RETURN_ERR;
4036
4037 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4038 wifi_hostapdRead(config_file,"ssid",output,32);
4039
4040 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
4041 return RETURN_OK;
4042}
4043
developer69b61b02023-03-07 17:17:44 +08004044// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08004045INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
4046{
4047 char str[MAX_BUF_SIZE]={'\0'};
4048 char cmd[MAX_CMD_SIZE]={'\0'};
4049 struct params params;
4050 char config_file[MAX_BUF_SIZE] = {0};
4051
4052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4053 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4054 return RETURN_ERR;
4055
4056 params.name = "ssid";
4057 params.value = ssid_string;
4058 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4059 wifi_hostapdWrite(config_file, &params, 1);
4060 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4061 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4062
4063 return RETURN_OK;
4064}
4065
4066//Get the BSSID
4067INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4068{
developer7e4a2a62023-04-06 19:56:03 +08004069 char cmd[MAX_CMD_SIZE] = {0};
4070 char inf_name[IF_NAME_SIZE] = {0};
4071 char conf_file[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08004072
developer7e4a2a62023-04-06 19:56:03 +08004073 if (!output_string)
developer72fb0bb2023-01-11 09:46:29 +08004074 return RETURN_ERR;
4075
developer7e4a2a62023-04-06 19:56:03 +08004076 wifi_GetInterfaceName(ssidIndex, inf_name);
4077
4078 if(ssidIndex >= 0 && ssidIndex < MAX_APS) {
4079 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 +08004080 _syscmd(cmd, output_string, 64);
developer7e4a2a62023-04-06 19:56:03 +08004081 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08004082 }
developer7e4a2a62023-04-06 19:56:03 +08004083
developer72fb0bb2023-01-11 09:46:29 +08004084 strncpy(output_string, "\0", 1);
4085
4086 return RETURN_ERR;
4087}
4088
4089//Get the MAC address associated with this Wifi SSID
4090INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4091{
4092 wifi_getBaseBSSID(ssidIndex,output_string);
4093 return RETURN_OK;
4094}
4095
4096//Get the basic SSID traffic static info
4097//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4098//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4099INT wifi_applySSIDSettings(INT ssidIndex)
4100{
4101 char interface_name[16] = {0};
4102 BOOL status = false;
4103 char cmd[MAX_CMD_SIZE] = {0};
4104 char buf[MAX_CMD_SIZE] = {0};
4105 int apIndex, ret;
4106 int max_radio_num = 0;
4107 int radioIndex = 0;
4108
4109 wifi_getMaxRadioNumber(&max_radio_num);
4110
4111 radioIndex = ssidIndex % max_radio_num;
4112
4113 wifi_getApEnable(ssidIndex,&status);
4114 // Do not apply when ssid index is disabled
4115 if (status == false)
4116 return RETURN_OK;
4117
4118 /* Doing full remove and add for ssid Index
4119 * Not all hostapd options are supported with reload
4120 * for example macaddr_acl
4121 */
4122 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4123 return RETURN_ERR;
4124
4125 ret = wifi_setApEnable(ssidIndex,true);
4126
4127 /* Workaround for hostapd issue with multiple bss definitions
4128 * when first created interface will be removed
4129 * then all vaps other vaps on same phy are removed
4130 * after calling setApEnable to false readd all enabled vaps */
4131 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4132 apIndex = max_radio_num*i+radioIndex;
4133 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4134 return RETURN_ERR;
4135 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4136 _syscmd(cmd, buf, sizeof(buf));
4137 if(*buf == '1')
4138 wifi_setApEnable(apIndex, true);
4139 }
4140
4141 return ret;
4142}
4143
4144struct channels_noise {
4145 int channel;
4146 int noise;
4147};
4148
4149// Return noise array for each channel
4150int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4151{
4152 char interface_name[16] = {0};
4153 FILE *f = NULL;
4154 char cmd[128] = {0};
4155 char line[256] = {0};
4156 size_t len = 0;
4157 ssize_t read = 0;
4158 int tmp = 0, arr_index = -1;
4159
4160 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4161 return RETURN_ERR;
4162 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4163
4164 if ((f = popen(cmd, "r")) == NULL) {
4165 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4166 return RETURN_ERR;
4167 }
developer69b61b02023-03-07 17:17:44 +08004168
developer72fb0bb2023-01-11 09:46:29 +08004169 while(fgets(line, sizeof(line), f) != NULL) {
4170 if(arr_index < channels_num){
4171 sscanf(line, "%d", &tmp);
4172 if (tmp > 0) { // channel frequency, the first line must be frequency
4173 arr_index++;
4174 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4175 } else { // noise
4176 channels_noise_arr[arr_index].noise = tmp;
4177 }
4178 }else{
4179 break;
4180 }
4181 }
4182 pclose(f);
4183 return RETURN_OK;
4184}
4185
4186//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4187//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004188INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004189{
4190 int index = -1;
4191 wifi_neighbor_ap2_t *scan_array = NULL;
4192 char cmd[256]={0};
4193 char buf[128]={0};
4194 char file_name[32] = {0};
4195 char filter_SSID[32] = {0};
4196 char line[256] = {0};
4197 char interface_name[16] = {0};
4198 char *ret = NULL;
4199 int freq=0;
4200 FILE *f = NULL;
4201 size_t len=0;
4202 int channels_num = 0;
4203 int vht_channel_width = 0;
4204 int get_noise_ret = RETURN_ERR;
4205 bool filter_enable = false;
4206 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4207 int phyId = 0;
4208
4209 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4210
4211 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4212 return RETURN_ERR;
4213
4214 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4215 f = fopen(file_name, "r");
4216 if (f != NULL) {
4217 fgets(filter_SSID, sizeof(file_name), f);
4218 if (strlen(filter_SSID) != 0)
4219 filter_enable = true;
4220 fclose(f);
4221 }
4222
4223 phyId = radio_index_to_phy(radioIndex);
4224 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4225 _syscmd(cmd, buf, sizeof(buf));
4226 channels_num = strtol(buf, NULL, 10);
4227
4228
4229
4230 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4231 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4232 fprintf(stderr, "cmd: %s\n", cmd);
4233 if ((f = popen(cmd, "r")) == NULL) {
4234 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4235 return RETURN_ERR;
4236 }
developer69b61b02023-03-07 17:17:44 +08004237
developer72fb0bb2023-01-11 09:46:29 +08004238 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4239 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004240
developer72fb0bb2023-01-11 09:46:29 +08004241 ret = fgets(line, sizeof(line), f);
4242 while (ret != NULL) {
4243 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004244 // 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 +08004245 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4246 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4247
4248 if (!filter_BSS) {
4249 index++;
4250 wifi_neighbor_ap2_t *tmp;
4251 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4252 if (tmp == NULL) { // no more memory to use
4253 index--;
4254 wifi_dbg_printf("%s: realloc failed\n", __func__);
4255 break;
4256 }
4257 scan_array = tmp;
4258 }
4259 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4260
4261 filter_BSS = false;
4262 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4263 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4264 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4265 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4266 } else if (strstr(line, "freq") != NULL) {
4267 sscanf(line," freq: %d", &freq);
4268 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4269
4270 if (freq >= 2412 && freq <= 2484) {
4271 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4272 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4273 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4274 }
4275 else if (freq >= 5160 && freq <= 5805) {
4276 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4277 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4278 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4279 }
4280
4281 scan_array[index].ap_Noise = 0;
4282 if (get_noise_ret == RETURN_OK) {
4283 for (int i = 0; i < channels_num; i++) {
4284 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4285 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4286 break;
4287 }
4288 }
4289 }
4290 } else if (strstr(line, "beacon interval") != NULL) {
4291 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4292 } else if (strstr(line, "signal") != NULL) {
4293 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4294 } else if (strstr(line,"SSID") != NULL) {
4295 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4296 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4297 filter_BSS = true;
4298 }
4299 } else if (strstr(line, "Supported rates") != NULL) {
4300 char SRate[80] = {0}, *tmp = NULL;
4301 memset(buf, 0, sizeof(buf));
4302 strcpy(SRate, line);
4303 tmp = strtok(SRate, ":");
4304 tmp = strtok(NULL, ":");
4305 strcpy(buf, tmp);
4306 memset(SRate, 0, sizeof(SRate));
4307
4308 tmp = strtok(buf, " \n");
4309 while (tmp != NULL) {
4310 strcat(SRate, tmp);
4311 if (SRate[strlen(SRate) - 1] == '*') {
4312 SRate[strlen(SRate) - 1] = '\0';
4313 }
4314 strcat(SRate, ",");
4315
4316 tmp = strtok(NULL, " \n");
4317 }
4318 SRate[strlen(SRate) - 1] = '\0';
4319 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4320 } else if (strstr(line, "DTIM") != NULL) {
4321 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4322 } else if (strstr(line, "VHT capabilities") != NULL) {
4323 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4324 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4325 } else if (strstr(line, "HT capabilities") != NULL) {
4326 strcat(scan_array[index].ap_SupportedStandards, ",n");
4327 strcpy(scan_array[index].ap_OperatingStandards, "n");
4328 } else if (strstr(line, "VHT operation") != NULL) {
4329 ret = fgets(line, sizeof(line), f);
4330 sscanf(line," * channel width: %d", &vht_channel_width);
4331 if(vht_channel_width == 1) {
4332 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4333 } else {
4334 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4335 }
4336 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4337 continue;
4338 } else if (strstr(line, "HT operation") != NULL) {
4339 ret = fgets(line, sizeof(line), f);
4340 sscanf(line," * secondary channel offset: %s", &buf);
4341 if (!strcmp(buf, "above")) {
4342 //40Mhz +
4343 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4344 }
4345 else if (!strcmp(buf, "below")) {
4346 //40Mhz -
4347 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4348 } else {
4349 //20Mhz
4350 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4351 }
4352 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4353 continue;
4354 } else if (strstr(line, "HE capabilities") != NULL) {
4355 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4356 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4357 ret = fgets(line, sizeof(line), f);
4358 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4359 if (strstr(line, "HE40/2.4GHz") != NULL)
4360 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4361 else
4362 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4363 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4364 if (strstr(line, "HE80/5GHz") != NULL) {
4365 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4366 ret = fgets(line, sizeof(line), f);
4367 } else
4368 continue;
4369 if (strstr(line, "HE160/5GHz") != NULL)
4370 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4371 }
4372 continue;
4373 } else if (strstr(line, "WPA") != NULL) {
4374 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4375 } else if (strstr(line, "RSN") != NULL) {
4376 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4377 } else if (strstr(line, "Group cipher") != NULL) {
4378 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4379 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4380 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4381 }
4382 }
4383 ret = fgets(line, sizeof(line), f);
4384 }
4385
4386 if (!filter_BSS) {
4387 *output_array_size = index + 1;
4388 } else {
4389 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4390 *output_array_size = index;
4391 }
4392 *neighbor_ap_array = scan_array;
4393 pclose(f);
4394 free(channels_noise_arr);
4395 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4396 return RETURN_OK;
4397}
4398
4399//>> Deprecated: used for old RDKB code.
4400INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4401{
4402 INT status = RETURN_ERR;
4403
4404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4405 output_struct->wifi_PLCPErrorCount = 0;
4406 output_struct->wifi_FCSErrorCount = 0;
4407 output_struct->wifi_InvalidMACCount = 0;
4408 output_struct->wifi_PacketsOtherReceived = 0;
4409 output_struct->wifi_Noise = 0;
4410 status = RETURN_OK;
4411 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4412 return status;
4413}
4414
4415INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4416{
4417 char interface_name[16] = {0};
4418 char cmd[128] = {0};
4419 char buf[1280] = {0};
4420 char *pos = NULL;
4421
4422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4423 if (NULL == output_struct)
4424 return RETURN_ERR;
4425
4426 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4427 return RETURN_ERR;
4428
4429 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4430
4431 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4432 _syscmd(cmd, buf, sizeof(buf));
4433
4434 pos = buf;
4435 if ((pos = strstr(pos, "RX packets:")) == NULL)
4436 return RETURN_ERR;
4437 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4438
4439 if ((pos = strstr(pos, "TX packets:")) == NULL)
4440 return RETURN_ERR;
4441 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4442
4443 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4444 return RETURN_ERR;
4445 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4446
4447 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4448 return RETURN_ERR;
4449 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4450
4451 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4452 _syscmd(cmd, buf, sizeof(buf));
4453 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4454
4455#if 0
4456 //TODO: need to revisit below implementation
4457 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4458 char interface_name[MAX_BUF_SIZE] = {0};
4459 char interface_status[MAX_BUF_SIZE] = {0};
4460 char Value[MAX_BUF_SIZE] = {0};
4461 char buf[MAX_CMD_SIZE] = {0};
4462 char cmd[MAX_CMD_SIZE] = {0};
4463 FILE *fp = NULL;
4464
4465 if (NULL == output_struct) {
4466 return RETURN_ERR;
4467 }
4468
4469 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4470
4471 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4472 {
4473 if(apIndex == 0) //private_wifi for 2.4G
4474 {
4475 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4476 }
4477 else if(apIndex == 1) //private_wifi for 5G
4478 {
4479 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4480 }
4481 else if(apIndex == 4) //public_wifi for 2.4G
4482 {
4483 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4484 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4485 {
4486 return RETURN_ERR;
4487 }
4488 if(buf[0] == '#')//tp-link
4489 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4490 else//tenda
4491 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4492 }
4493 else if(apIndex == 5) //public_wifi for 5G
4494 {
4495 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4496 }
4497
4498 GetIfacestatus(interface_name, interface_status);
4499
4500 if(0 != strcmp(interface_status, "1"))
4501 return RETURN_ERR;
4502
4503 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4504 system(cmd);
4505
4506 fp = fopen("/tmp/SSID_Stats.txt", "r");
4507 if(fp == NULL)
4508 {
4509 printf("/tmp/SSID_Stats.txt not exists \n");
4510 return RETURN_ERR;
4511 }
4512 fclose(fp);
4513
4514 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4515 File_Reading(buf, Value);
4516 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4517
4518 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4519 File_Reading(buf, Value);
4520 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4521
4522 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4523 File_Reading(buf, Value);
4524 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4525
4526 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4527 File_Reading(buf, Value);
4528 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4529
4530 /* There is no specific parameter from caller to associate the value wifi_Associations */
4531 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4532 //_syscmd(cmd, buf, sizeof(buf));
4533 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4534 }
4535#endif
4536 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4537 return RETURN_OK;
4538}
4539
4540INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4541{
4542 char interface_name[MAX_BUF_SIZE] = {0};
4543 char interface_status[MAX_BUF_SIZE] = {0};
4544 char Value[MAX_BUF_SIZE] = {0};
4545 char buf[MAX_CMD_SIZE] = {0};
4546 char cmd[MAX_CMD_SIZE] = {0};
4547 FILE *fp = NULL;
4548
4549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4550 if (NULL == output_struct)
4551 return RETURN_ERR;
4552
4553 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4554
4555 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4556 return RETURN_ERR;
4557 GetIfacestatus(interface_name, interface_status);
4558
4559 if(0 != strcmp(interface_status, "1"))
4560 return RETURN_ERR;
4561
4562 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4563 system(cmd);
4564
4565 fp = fopen("/tmp/SSID_Stats.txt", "r");
4566 if(fp == NULL)
4567 {
4568 printf("/tmp/SSID_Stats.txt not exists \n");
4569 return RETURN_ERR;
4570 }
4571 fclose(fp);
4572
4573 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4574 File_Reading(buf, Value);
4575 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4576
4577 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4578 File_Reading(buf, Value);
4579 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4580
4581 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4582 File_Reading(buf, Value);
4583 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4584
4585 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4586 File_Reading(buf, Value);
4587 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4588
4589 output_struct->wifi_UnicastPacketsSent = 0;
4590 output_struct->wifi_UnicastPacketsReceived = 0;
4591 output_struct->wifi_MulticastPacketsSent = 0;
4592 output_struct->wifi_MulticastPacketsReceived = 0;
4593 output_struct->wifi_BroadcastPacketsSent = 0;
4594 output_struct->wifi_BroadcastPacketsRecevied = 0;
4595 output_struct->wifi_UnknownPacketsReceived = 0;
4596
4597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4598 return RETURN_OK;
4599}
4600
4601INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4602{
4603 INT status = RETURN_ERR;
4604
4605 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4606 //Below values should get updated from hal
4607 output_struct->wifi_RetransCount=0;
4608 output_struct->wifi_FailedRetransCount=0;
4609 output_struct->wifi_RetryCount=0;
4610 output_struct->wifi_MultipleRetryCount=0;
4611 output_struct->wifi_ACKFailureCount=0;
4612 output_struct->wifi_AggregatedPacketCount=0;
4613
4614 status = RETURN_OK;
4615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4616
4617 return status;
4618}
4619
4620INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4621{
4622 INT status = RETURN_ERR;
4623 UINT index;
4624 wifi_neighbor_ap_t *pt=NULL;
4625
4626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4627 *output_array_size=2;
4628 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4629 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4630 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4631 strcpy(pt->ap_Radio,"");
4632 strcpy(pt->ap_SSID,"");
4633 strcpy(pt->ap_BSSID,"");
4634 strcpy(pt->ap_Mode,"");
4635 pt->ap_Channel=1;
4636 pt->ap_SignalStrength=0;
4637 strcpy(pt->ap_SecurityModeEnabled,"");
4638 strcpy(pt->ap_EncryptionMode,"");
4639 strcpy(pt->ap_OperatingFrequencyBand,"");
4640 strcpy(pt->ap_SupportedStandards,"");
4641 strcpy(pt->ap_OperatingStandards,"");
4642 strcpy(pt->ap_OperatingChannelBandwidth,"");
4643 pt->ap_BeaconPeriod=1;
4644 pt->ap_Noise=0;
4645 strcpy(pt->ap_BasicDataTransferRates,"");
4646 strcpy(pt->ap_SupportedDataTransferRates,"");
4647 pt->ap_DTIMPeriod=1;
4648 pt->ap_ChannelUtilization = 1;
4649 }
4650
4651 status = RETURN_OK;
4652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4653
4654 return status;
4655}
4656
4657//----------------- AP HAL -------------------------------
4658
4659//>> Deprecated: used for old RDKB code.
4660INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4661{
4662 if (NULL == output_ulong || NULL == output_struct)
4663 return RETURN_ERR;
4664 *output_ulong = 0;
4665 *output_struct = NULL;
4666 return RETURN_OK;
4667}
4668
4669#ifdef HAL_NETLINK_IMPL
4670static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4671 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4672 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4673 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4674 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4675 char mac_addr[20];
4676 static int count=0;
4677 int rate=0;
4678
4679 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4680
4681 nla_parse(tb,
4682 NL80211_ATTR_MAX,
4683 genlmsg_attrdata(gnlh, 0),
4684 genlmsg_attrlen(gnlh, 0),
4685 NULL);
4686
4687 if(!tb[NL80211_ATTR_STA_INFO]) {
4688 fprintf(stderr, "sta stats missing!\n");
4689 return NL_SKIP;
4690 }
4691
4692
4693 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4694 fprintf(stderr, "failed to parse nested attributes!\n");
4695 return NL_SKIP;
4696 }
4697
4698 //devIndex starts from 1
4699 if( ++count == out->wifi_devIndex )
4700 {
4701 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4702 //Getting the mac addrress
4703 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4704
4705 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4706 fprintf(stderr, "failed to parse nested rate attributes!");
4707 return NL_SKIP;
4708 }
4709
4710 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4711 if(rinfo[NL80211_RATE_INFO_BITRATE])
4712 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4713 out->wifi_devTxRate = rate/10;
4714 }
4715
4716 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4717 fprintf(stderr, "failed to parse nested rate attributes!");
4718 return NL_SKIP;
4719 }
4720
4721 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4722 if(rinfo[NL80211_RATE_INFO_BITRATE])
4723 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4724 out->wifi_devRxRate = rate/10;
4725 }
4726 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4727 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4728
4729 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4730 count = 0; //starts the count for next cycle
4731 return NL_STOP;
4732 }
4733
4734 return NL_SKIP;
4735
4736}
4737#endif
4738
4739INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4740{
4741#ifdef HAL_NETLINK_IMPL
4742 Netlink nl = {0};
4743 char if_name[10] = {0};
4744 char interface_name[16] = {0};
4745
4746 wifi_device_info_t info = {0};
4747 info.wifi_devIndex = devIndex;
4748
4749 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4750 return RETURN_ERR;
4751
4752 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4753
4754 nl.id = initSock80211(&nl);
4755
4756 if (nl.id < 0) {
4757 fprintf(stderr, "Error initializing netlink \n");
4758 return -1;
4759 }
4760
4761 struct nl_msg* msg = nlmsg_alloc();
4762
4763 if (!msg) {
4764 fprintf(stderr, "Failed to allocate netlink message.\n");
4765 nlfree(&nl);
4766 return -2;
4767 }
4768
4769 genlmsg_put(msg,
4770 NL_AUTO_PORT,
4771 NL_AUTO_SEQ,
4772 nl.id,
4773 0,
4774 NLM_F_DUMP,
4775 NL80211_CMD_GET_STATION,
4776 0);
4777
4778 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4779 nl_send_auto(nl.socket, msg);
4780 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4781 nl_recvmsgs(nl.socket, nl.cb);
4782 nlmsg_free(msg);
4783 nlfree(&nl);
4784
4785 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4786 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4787 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4788 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4789 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4790 return RETURN_OK;
4791#else
4792 //iw utility to retrieve station information
4793#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4794#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4795#define MACFILE "/tmp/wifi_AssoMac.txt"
4796#define TXRATEFILE "/tmp/wifi_txrate.txt"
4797#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4798 FILE *file = NULL;
4799 char if_name[10] = {'\0'};
4800 char pipeCmd[256] = {'\0'};
4801 char line[256] = {0};
4802 char interface_name[16] = {0};
4803 int count = 0, device = 0;
4804
4805 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4806 return RETURN_ERR;
4807
4808 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4809
4810 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4811 file = popen(pipeCmd, "r");
4812
4813 if(file == NULL)
4814 return RETURN_ERR; //popen failed
4815
4816 fgets(line, sizeof line, file);
4817 device = atoi(line);
4818 pclose(file);
4819
4820 if(device == 0)
4821 return RETURN_ERR; //No devices are connected
4822
4823 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4824 system(pipeCmd);
4825
4826 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4827
4828 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4829
4830 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4831
4832 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4833
4834 //devIndex starts from 1, ++count
4835 if((file = fopen(SIGNALFILE, "r")) != NULL )
4836 {
4837 for(count =0;fgets(line, sizeof line, file) != NULL;)
4838 {
4839 if (++count == devIndex)
4840 {
4841 output_struct->wifi_devSignalStrength = atoi(line);
4842 break;
4843 }
4844 }
4845 fclose(file);
4846 }
4847 else
4848 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4849
4850 if((file = fopen(MACFILE, "r")) != NULL )
4851 {
4852 for(count =0;fgets(line, sizeof line, file) != NULL;)
4853 {
4854 if (++count == devIndex)
4855 {
4856 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]);
4857 break;
4858 }
4859 }
4860 fclose(file);
4861 }
4862 else
4863 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4864
4865 if((file = fopen(TXRATEFILE, "r")) != NULL )
4866 {
4867 for(count =0;fgets(line, sizeof line, file) != NULL;)
4868 {
4869 if (++count == devIndex)
4870 {
4871 output_struct->wifi_devTxRate = atoi(line);
4872 break;
4873 }
4874 }
4875 fclose(file);
4876 }
4877 else
4878 fprintf(stderr,"fopen wifi_txrate.txt failed");
4879
4880 if((file = fopen(RXRATEFILE, "r")) != NULL)
4881 {
4882 for(count =0;fgets(line, sizeof line, file) != NULL;)
4883 {
4884 if (++count == devIndex)
4885 {
4886 output_struct->wifi_devRxRate = atoi(line);
4887 break;
4888 }
4889 }
4890 fclose(file);
4891 }
4892 else
4893 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4894
4895 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4896
4897 return RETURN_OK;
4898#endif
4899}
4900
4901INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4902{
4903 if (NULL == device)
4904 return RETURN_ERR;
4905 return RETURN_OK;
4906}
4907//<<
4908
4909
4910//--------------wifi_ap_hal-----------------------------
4911//enables CTS protection for the radio used by this AP
4912INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4913{
4914 //save config and Apply instantly
4915 return RETURN_ERR;
4916}
4917
4918// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4919INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4920{
4921 char config_file[64] = {'\0'};
4922 char buf[64] = {'\0'};
4923 struct params list;
4924
4925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4926 list.name = "ht_coex";
4927 snprintf(buf, sizeof(buf), "%d", enable);
4928 list.value = buf;
4929
4930 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4931 wifi_hostapdWrite(config_file, &list, 1);
4932 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4933
4934 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4935
4936 return RETURN_OK;
4937}
4938
4939//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4940INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4941{
4942 char config_file[MAX_BUF_SIZE] = {'\0'};
4943 char buf[MAX_BUF_SIZE] = {'\0'};
4944 struct params list;
4945
4946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4947 if (threshold < 256 || threshold > 2346 )
4948 return RETURN_ERR;
4949 list.name = "fragm_threshold";
4950 snprintf(buf, sizeof(buf), "%d", threshold);
4951 list.value = buf;
4952
4953 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4954 wifi_hostapdWrite(config_file, &list, 1);
4955 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4956
4957 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4958
4959 return RETURN_OK;
4960}
4961
4962// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4963INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4964{
4965 char config_file[64] = {'\0'};
4966 char cmd[512] = {'\0'};
4967 char buf[512] = {'\0'};
4968 char stbc_config[16] = {'\0'};
4969 wifi_band band;
4970 int iterator = 0;
4971 BOOL current_stbc = FALSE;
4972 int ant_count = 0;
4973 int ant_bitmap = 0;
4974 struct params list;
4975
4976 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4977
4978 band = wifi_index_to_band(radioIndex);
4979 if (band == band_invalid)
4980 return RETURN_ERR;
4981
4982 if (band == band_2_4)
4983 iterator = 1;
4984 else if (band == band_5)
4985 iterator = 2;
4986 else
4987 return RETURN_OK;
4988
4989 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4990 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4991 ant_count += ant_bitmap & 1;
4992
4993 if (ant_count == 1 && STBC_Enable == TRUE) {
4994 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4995 return RETURN_OK;
4996 }
4997
4998 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4999
5000 // set ht and vht config
5001 for (int i = 0; i < iterator; i++) {
5002 memset(stbc_config, 0, sizeof(stbc_config));
5003 memset(cmd, 0, sizeof(cmd));
5004 memset(buf, 0, sizeof(buf));
5005 list.name = (i == 0)?"ht_capab":"vht_capab";
5006 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
5007 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
5008 _syscmd(cmd, buf, sizeof(buf));
5009 if (strlen(buf) != 0)
5010 current_stbc = TRUE;
5011 if (current_stbc == STBC_Enable)
5012 continue;
5013
5014 if (STBC_Enable == TRUE) {
5015 // Append the STBC flags in capab config
5016 memset(cmd, 0, sizeof(cmd));
5017 if (i == 0)
5018 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
5019 else
5020 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
5021 _syscmd(cmd, buf, sizeof(buf));
5022 } else if (STBC_Enable == FALSE) {
5023 // Remove the STBC flags and remain other flags in capab
5024 memset(cmd, 0, sizeof(cmd));
5025 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5026 _syscmd(cmd, buf, sizeof(buf));
5027 memset(cmd, 0, sizeof(cmd));
5028 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
5029 _syscmd(cmd, buf, sizeof(buf));
5030 }
5031 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
5032 list.value = buf;
5033 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5034 }
5035
5036 wifi_reloadAp(radioIndex);
5037
5038 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5039 return RETURN_OK;
5040}
5041
5042// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
5043INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
5044{
5045 char cmd[128] = {0};
5046 char buf[128] = {0};
5047 char interface_name[16] = {0};
5048
5049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5050
5051 if(output_bool == NULL)
5052 return RETURN_ERR;
5053
5054 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5055 return RETURN_ERR;
5056
5057 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
5058 _syscmd(cmd, buf, sizeof(buf));
5059
5060 if (strncmp(buf, "1", 1) == 0)
5061 *output_bool = TRUE;
5062 else
5063 *output_bool = FALSE;
5064
5065 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5066 return RETURN_OK;
5067}
5068
5069// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5070INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5071{
5072 char config_file[128] = {0};
5073 struct params list = {0};
5074 BOOL enable;
5075
5076 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5077
5078 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
5079 return RETURN_ERR;
5080
5081 if (amsduEnable == enable)
5082 return RETURN_OK;
5083
5084 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5085 list.name = "amsdu";
5086 list.value = amsduEnable? "1":"0";
5087 wifi_hostapdWrite(config_file, &list, 1);
5088 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5089 wifi_reloadAp(radioIndex);
5090
5091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5092 return RETURN_OK;
5093}
5094
5095//P2 // outputs the number of Tx streams
5096INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5097{
5098 char buf[8] = {0};
5099 char cmd[128] = {0};
5100 int phyId = 0;
5101
5102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5103
5104 phyId = radio_index_to_phy(radioIndex);
5105 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5106 _syscmd(cmd, buf, sizeof(buf));
5107
5108 *output_int = (INT)strtol(buf, NULL, 16);
5109
5110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5111
5112 return RETURN_OK;
5113}
5114
5115INT fitChainMask(INT radioIndex, int antcount)
5116{
5117 char buf[128] = {0};
5118 char cmd[128] = {0};
5119 char config_file[64] = {0};
5120 wifi_band band;
5121 struct params list[2] = {0};
5122
5123 band = wifi_index_to_band(radioIndex);
5124 if (band == band_invalid)
5125 return RETURN_ERR;
5126
5127 list[0].name = "he_mu_beamformer";
5128 list[1].name = "he_su_beamformer";
5129
5130 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5131 if (antcount == 1) {
5132 // remove config about multiple antennas
5133 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5134 _syscmd(cmd, buf, sizeof(buf));
5135
5136 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5137 _syscmd(cmd, buf, sizeof(buf));
5138
5139 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5140 _syscmd(cmd, buf, sizeof(buf));
5141
5142 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5143 _syscmd(cmd, buf, sizeof(buf));
5144
5145 list[0].value = "0";
5146 list[1].value = "0";
5147 } else {
5148 // 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.
5149 if (band == band_2_4 || band == band_5) {
5150 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5151 _syscmd(cmd, buf, sizeof(buf));
5152 if (strlen(buf) > 0) {
5153 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5154 _syscmd(cmd, buf, sizeof(buf));
5155 }
5156 }
5157 if (band == band_5) {
5158 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5159 _syscmd(cmd, buf, sizeof(buf));
5160 if (strlen(buf) > 0) {
5161 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5162 _syscmd(cmd, buf, sizeof(buf));
5163 }
5164 }
5165
5166 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5167 _syscmd(cmd, buf, sizeof(buf));
5168 if (strlen(buf) == 0) {
5169 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5170 _syscmd(cmd, buf, sizeof(buf));
5171 }
5172
5173 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5174 _syscmd(cmd, buf, sizeof(buf));
5175 if (strlen(buf) == 0) {
5176 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5177 _syscmd(cmd, buf, sizeof(buf));
5178 }
5179
5180 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5181 _syscmd(cmd, buf, sizeof(buf));
5182 if (strlen(buf) == 0) {
5183 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5184 } else {
5185 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5186 }
5187 _syscmd(cmd, buf, sizeof(buf));
5188
5189 list[0].value = "1";
5190 list[1].value = "1";
5191 }
5192 wifi_hostapdWrite(config_file, list, 2);
5193}
5194
5195//P2 // sets the number of Tx streams to an enviornment variable
5196INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5197{
5198 char cmd[128] = {0};
5199 char buf[128] = {0};
5200 int phyId = 0;
5201 int cur_mask = 0;
5202 int antcount = 0;
5203 wifi_band band;
5204
5205 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5206
5207 if (numStreams <= 0) {
5208 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5209 return RETURN_ERR;
5210 }
5211
5212 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5213 if (cur_mask == numStreams)
5214 return RETURN_OK;
5215
5216 wifi_setRadioEnable(radioIndex, FALSE);
5217
5218 phyId = radio_index_to_phy(radioIndex);
5219 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
5220 _syscmd(cmd, buf, sizeof(buf));
5221
5222 if (strlen(buf) > 0) {
5223 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5224 return RETURN_ERR;
5225 }
5226
5227 // if chain mask changed, we need to make the hostapd config valid.
5228 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5229 antcount += cur_mask & 1;
5230 }
5231 fitChainMask(radioIndex, antcount);
5232
5233 wifi_setRadioEnable(radioIndex, TRUE);
5234
5235 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5236 return RETURN_OK;
5237}
5238
5239//P2 // outputs the number of Rx streams
5240INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5241{
5242 char buf[8] = {0};
5243 char cmd[128] = {0};
5244 int phyId = 0;
5245
5246 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5247
5248 phyId = radio_index_to_phy(radioIndex);
5249 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5250 _syscmd(cmd, buf, sizeof(buf));
5251
5252 *output_int = (INT)strtol(buf, NULL, 16);
5253
5254 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5255
5256 return RETURN_OK;
5257}
5258
5259//P2 // sets the number of Rx streams to an enviornment variable
5260INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5261{
5262 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5263 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5264 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5265 return RETURN_ERR;
5266 }
5267 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5268 return RETURN_ERR;
5269}
5270
5271//Get radio RDG enable setting
5272INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5273{
5274 if (NULL == output_bool)
5275 return RETURN_ERR;
5276 *output_bool = TRUE;
5277 return RETURN_OK;
5278}
5279
5280//Get radio RDG enable setting
5281INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5282{
5283 if (NULL == output_bool)
5284 return RETURN_ERR;
5285 *output_bool = TRUE;
5286 return RETURN_OK;
5287}
5288
5289//Set radio RDG enable setting
5290INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5291{
5292 return RETURN_ERR;
5293}
5294
5295//Get radio ADDBA enable setting
5296INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5297{
5298 if (NULL == output_bool)
5299 return RETURN_ERR;
5300 *output_bool = TRUE;
5301 return RETURN_OK;
5302}
5303
5304//Set radio ADDBA enable setting
5305INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5306{
5307 return RETURN_ERR;
5308}
5309
5310//Get radio auto block ack enable setting
5311INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5312{
5313 if (NULL == output_bool)
5314 return RETURN_ERR;
5315 *output_bool = TRUE;
5316 return RETURN_OK;
5317}
5318
5319//Set radio auto block ack enable setting
5320INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5321{
5322 return RETURN_ERR;
5323}
5324
5325//Get radio 11n pure mode enable support
5326INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5327{
5328 if (NULL == output_bool)
5329 return RETURN_ERR;
5330 *output_bool = TRUE;
5331 return RETURN_OK;
5332}
5333
5334//Get radio 11n pure mode enable setting
5335INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5336{
5337 if (NULL == output_bool)
5338 return RETURN_ERR;
5339 *output_bool = TRUE;
5340 return RETURN_OK;
5341}
5342
5343//Set radio 11n pure mode enable setting
5344INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5345{
5346 return RETURN_ERR;
5347}
5348
5349//Get radio IGMP snooping enable setting
5350INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5351{
5352 char interface_name[16] = {0};
5353 char cmd[128]={0};
5354 char buf[4]={0};
5355 bool bridge = FALSE, mac80211 = FALSE;
5356 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5357
5358 if(output_bool == NULL)
5359 return RETURN_ERR;
5360
5361 *output_bool = FALSE;
5362
5363 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5364 _syscmd(cmd, buf, sizeof(buf));
5365 if (strncmp(buf, "1", 1) == 0)
5366 bridge = TRUE;
5367
5368 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5369 return RETURN_ERR;
5370 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5371 _syscmd(cmd, buf, sizeof(buf));
5372 if (strncmp(buf, "1", 1) == 0)
5373 mac80211 = TRUE;
5374
5375 if (bridge && mac80211)
5376 *output_bool = TRUE;
5377
5378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5379 return RETURN_OK;
5380}
5381
5382//Set radio IGMP snooping enable setting
5383INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5384{
5385 char interface_name[16] = {0};
5386 char cmd[128]={0};
5387 char buf[4]={0};
5388 int max_num_radios =0;
5389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5390
5391 // bridge
5392 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5393 _syscmd(cmd, buf, sizeof(buf));
5394
5395 wifi_getMaxRadioNumber(&max_num_radios);
5396 // mac80211
5397 for (int i = 0; i < max_num_radios; i++) {
5398 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5399 return RETURN_ERR;
5400 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5401 _syscmd(cmd, buf, sizeof(buf));
5402 }
5403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5404 return RETURN_OK;
5405}
5406
5407//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08005408INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08005409{
developer69b61b02023-03-07 17:17:44 +08005410 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08005411 return RETURN_ERR;
5412 *output_int = (radioIndex==0)? 1: 3;
5413
5414 return RETURN_OK;
5415}
5416
5417
5418//---------------------------------------------------------------------------------------------------
5419//
5420// Additional Wifi AP level APIs used for Access Point devices
5421//
5422//---------------------------------------------------------------------------------------------------
5423
5424// creates a new ap and pushes these parameters to the hardware
5425INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5426{
5427 // Deprecated when use hal version 3, use wifi_createVap() instead.
5428 return RETURN_OK;
5429}
5430
5431// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5432INT wifi_deleteAp(INT apIndex)
5433{
developer7e4a2a62023-04-06 19:56:03 +08005434 char interface_name[16] = {0};
5435 char buf[MAX_BUF_SIZE];
5436 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08005437
developer7e4a2a62023-04-06 19:56:03 +08005438 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5439 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08005440
developer7e4a2a62023-04-06 19:56:03 +08005441 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
5442 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005443
developer7e4a2a62023-04-06 19:56:03 +08005444 wifi_removeApSecVaribles(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005445
developer7e4a2a62023-04-06 19:56:03 +08005446 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005447}
5448
5449// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5450INT wifi_getApName(INT apIndex, CHAR *output_string)
5451{
developer7e4a2a62023-04-06 19:56:03 +08005452 char interface_name[IF_NAME_SIZE] = {0};
5453 char radio_idx = 0;
5454 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005455
developer7e4a2a62023-04-06 19:56:03 +08005456 if(!output_string)
5457 return RETURN_ERR;
5458
5459 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
5460 vap_index_to_array_index(apIndex, &radio_idx, &bss_idx);
5461
5462 snprintf(output_string, IF_NAME_SIZE, "%s%d", ext_prefix[radio_idx], bss_idx); // For wifiagent generating data model.
5463 } else
5464 snprintf(output_string, IF_NAME_SIZE, "%s", interface_name);
5465
5466 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005467}
5468
5469// Outputs the index number in that corresponds to the SSID string
5470INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5471{
developer7e4a2a62023-04-06 19:56:03 +08005472 char cmd [128] = {0};
5473 char buf[32] = {0};
5474 char ap_idx = 0;
5475 char *apIndex_str = NULL;
5476 char radio_idx = 0;
5477 char bss_idx = 0;
developer72fb0bb2023-01-11 09:46:29 +08005478
developer7e4a2a62023-04-06 19:56:03 +08005479 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'",
5480 inputSsidString);
5481 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005482
developer7e4a2a62023-04-06 19:56:03 +08005483 if (strlen(buf)) {
5484 apIndex_str = strtok(buf, "\n");
5485 *output_int = strtoul(apIndex_str, NULL, 10);
5486 return RETURN_OK;
5487 }
developer72fb0bb2023-01-11 09:46:29 +08005488
developer7e4a2a62023-04-06 19:56:03 +08005489 /* If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.*/
5490 if (strstr(inputSsidString, PREFIX_WIFI6G)) {
5491 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI6G));
5492 radio_idx = 2;
5493 } else if (strstr(inputSsidString, PREFIX_WIFI5G)) {
5494 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI5G));
5495 radio_idx = 1;
5496 } else if (strstr(inputSsidString, PREFIX_WIFI2G)) {
5497 bss_idx = atoi(inputSsidString + strlen(PREFIX_WIFI2G));
5498 radio_idx = 0;
5499 } else {
5500 printf("%s: hostapd conf not find, unknow inf(%s), return ERROR!!!(%d).\n",
5501 __func__, inputSsidString, ap_idx);
5502 *output_int = -1;
5503 return RETURN_ERR;
5504 }
5505
5506 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
5507
5508 if (ap_idx >= 0 && ap_idx < MAX_VAP) {
5509 printf("%s: hostapd conf not find, inf(%s), use inf idx(%d).\n",
5510 __func__, inputSsidString, ap_idx);
5511 *output_int = ap_idx;
5512 return RETURN_OK;
5513 }
5514
5515 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005516}
5517
5518INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5519{
5520 return wifi_getIndexFromName(inputSsidString, output_int);
5521}
5522
5523// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5524INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5525{
5526 char buf[MAX_BUF_SIZE] = {0};
5527 char cmd[MAX_CMD_SIZE] = {0};
5528 char config_file[MAX_BUF_SIZE] = {0};
5529
5530 if(NULL == output_string)
5531 return RETURN_ERR;
5532
5533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5534 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5535 if((strcmp(buf,"3")==0))
5536 snprintf(output_string, 32, "WPAand11i");
5537 else if((strcmp(buf,"2")==0))
5538 snprintf(output_string, 32, "11i");
5539 else if((strcmp(buf,"1")==0))
5540 snprintf(output_string, 32, "WPA");
5541 else
5542 snprintf(output_string, 32, "None");
5543
5544 return RETURN_OK;
5545}
5546
5547// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5548INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5549{
5550 char config_file[MAX_BUF_SIZE] = {0};
5551 struct params list;
5552
5553 if (NULL == beaconTypeString)
5554 return RETURN_ERR;
5555 list.name = "wpa";
5556 list.value = "0";
5557
5558 if((strcmp(beaconTypeString,"WPAand11i")==0))
5559 list.value="3";
5560 else if((strcmp(beaconTypeString,"11i")==0))
5561 list.value="2";
5562 else if((strcmp(beaconTypeString,"WPA")==0))
5563 list.value="1";
5564
5565 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5566 wifi_hostapdWrite(config_file, &list, 1);
5567 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5568 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5569 return RETURN_OK;
5570}
5571
5572// sets the beacon interval on the hardware for this AP
5573INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5574{
5575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5576 struct params params={'\0'};
5577 char buf[MAX_BUF_SIZE] = {'\0'};
5578 char config_file[MAX_BUF_SIZE] = {'\0'};
5579
5580 params.name = "beacon_int";
5581 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5582 params.value = buf;
5583
5584 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5585 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08005586
developer72fb0bb2023-01-11 09:46:29 +08005587 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5588 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5589 return RETURN_OK;
5590}
5591
5592INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5593{
5594 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5595 return RETURN_ERR;
5596 return RETURN_OK;
5597}
5598
5599// Get the packet size threshold supported.
5600INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5601{
5602 //save config and apply instantly
5603 if (NULL == output_bool)
5604 return RETURN_ERR;
5605 *output_bool = TRUE;
5606 return RETURN_OK;
5607}
5608
5609// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5610INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5611{
developer72fb0bb2023-01-11 09:46:29 +08005612 char buf[16] = {0};
5613 char config_file[128] = {0};
5614 struct params param = {0};
5615
5616 if (threshold > 65535) {
5617 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5618 return RETURN_ERR;
5619 }
5620
developer23e71282023-01-18 10:25:19 +08005621 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005622 snprintf(buf, sizeof(buf), "%u", threshold);
5623 param.name = "rts_threshold";
5624 param.value = buf;
5625 wifi_hostapdWrite(config_file, &param, 1);
5626 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5627 wifi_reloadAp(apIndex);
5628
5629 return RETURN_OK;
5630}
5631
5632// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5633INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5634{
5635 if (NULL == output_string)
5636 return RETURN_ERR;
5637 snprintf(output_string, 32, "TKIPandAESEncryption");
5638 return RETURN_OK;
5639
5640}
5641
5642// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5643INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5644{
5645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5646 char *param_name = NULL;
5647 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5648
5649 if(NULL == output_string)
5650 return RETURN_ERR;
5651
5652 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5653 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5654
5655 if(strcmp(buf,"0")==0)
5656 {
5657 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5658 snprintf(output_string, 32, "None");
5659 return RETURN_OK;
5660 }
5661 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5662 param_name = "rsn_pairwise";
5663 else if((strcmp(buf,"1")==0))
5664 param_name = "wpa_pairwise";
5665 else
5666 return RETURN_ERR;
5667 memset(output_string,'\0',32);
5668 wifi_hostapdRead(config_file,param_name,output_string,32);
5669 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5670 param_name = "wpa_pairwise";
5671 memset(output_string, '\0', 32);
5672 wifi_hostapdRead(config_file, param_name, output_string, 32);
5673 }
5674 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5675
5676 if(strcmp(output_string,"TKIP") == 0)
5677 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5678 else if(strcmp(output_string,"CCMP") == 0)
5679 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5680 else if(strcmp(output_string,"TKIP CCMP") == 0)
5681 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5682
5683 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5684 return RETURN_OK;
5685}
5686
5687// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5688INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5689{
5690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5691 struct params params={'\0'};
5692 char output_string[32];
5693 char config_file[MAX_BUF_SIZE] = {0};
5694
5695 memset(output_string,'\0',32);
5696 wifi_getApWpaEncryptionMode(apIndex,output_string);
5697
5698 if(strcmp(encMode, "TKIPEncryption") == 0)
5699 params.value = "TKIP";
5700 else if(strcmp(encMode,"AESEncryption") == 0)
5701 params.value = "CCMP";
5702 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5703 params.value = "TKIP CCMP";
5704
5705 if((strcmp(output_string,"WPAand11i")==0))
5706 {
5707 params.name = "wpa_pairwise";
5708 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5709 wifi_hostapdWrite(config_file, &params, 1);
5710 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5711
5712 params.name = "rsn_pairwise";
5713 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5714 wifi_hostapdWrite(config_file, &params, 1);
5715 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5716
5717 return RETURN_OK;
5718 }
5719 else if((strcmp(output_string,"11i")==0))
5720 {
5721 params.name = "rsn_pairwise";
5722 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5723 wifi_hostapdWrite(config_file, &params, 1);
5724 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5725 return RETURN_OK;
5726 }
5727 else if((strcmp(output_string,"WPA")==0))
5728 {
5729 params.name = "wpa_pairwise";
5730 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5731 wifi_hostapdWrite(config_file, &params, 1);
5732 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5733 return RETURN_OK;
5734 }
5735
5736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5737 return RETURN_OK;
5738}
5739
5740// deletes internal security varable settings for this ap
5741INT wifi_removeApSecVaribles(INT apIndex)
5742{
5743 //TODO: remove the entry in hostapd config file
5744 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5745 //_syscmd(cmd, buf, sizeof(buf));
5746
5747 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5748 //_syscmd(cmd, buf, sizeof(buf));
5749 return RETURN_ERR;
5750}
5751
5752// changes the hardware settings to disable encryption on this ap
5753INT wifi_disableApEncryption(INT apIndex)
5754{
5755 //Apply instantly
5756 return RETURN_ERR;
5757}
5758
5759// set the authorization mode on this ap
5760// mode mapping as: 1: open, 2: shared, 4:auto
5761INT wifi_setApAuthMode(INT apIndex, INT mode)
5762{
5763 struct params params={0};
5764 char config_file[64] = {0};
5765 int ret;
5766
5767 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5768
5769 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5770 params.name = "auth_algs";
5771
5772 if (mode & 1 && mode & 2)
5773 params.value = "3";
5774 else if (mode & 2)
5775 params.value = "2";
5776 else if (mode & 1)
5777 params.value = "1";
5778 else
5779 params.value = "0";
5780
5781 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5782 wifi_hostapdWrite(config_file, &params, 1);
5783 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5785
5786 return RETURN_OK;
5787}
5788
5789// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5790INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5791{
5792 //save to wifi config, and wait for wifi restart to apply
5793 struct params params={'\0'};
5794 char config_file[MAX_BUF_SIZE] = {0};
5795 int ret;
5796
5797 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5798 if(authMode == NULL)
5799 return RETURN_ERR;
5800
5801 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5802 params.name = "wpa_key_mgmt";
5803
5804 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5805 params.value = "WPA-PSK";
5806 else if(strcmp(authMode,"EAPAuthentication") == 0)
5807 params.value = "WPA-EAP";
5808 else if (strcmp(authMode, "SAEAuthentication") == 0)
5809 params.value = "SAE";
5810 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5811 params.value = "WPA-EAP-SUITE-B-192";
5812 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5813 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08005814 else if (strcmp(authMode, "Enhanced_Open") == 0)
5815 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08005816 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5817 return RETURN_OK; //This is taken careof in beaconType
5818
5819 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5820 ret=wifi_hostapdWrite(config_file,&params,1);
5821 if(!ret)
5822 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5823 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5824
5825 return ret;
5826}
5827
5828// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5829INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5830{
5831 //save to wifi config, and wait for wifi restart to apply
5832 char BeaconType[50] = {0};
5833 char config_file[MAX_BUF_SIZE] = {0};
5834
5835 *authMode = 0;
5836 wifi_getApBeaconType(apIndex,BeaconType);
5837 printf("%s____%s \n",__FUNCTION__,BeaconType);
5838
5839 if(strcmp(BeaconType,"None") == 0)
5840 strcpy(authMode,"None");
5841 else
5842 {
5843 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5844 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5845 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5846 if(strcmp(authMode,"WPA-PSK") == 0)
5847 strcpy(authMode,"SharedAuthentication");
5848 else if(strcmp(authMode,"WPA-EAP") == 0)
5849 strcpy(authMode,"EAPAuthentication");
5850 }
5851
5852 return RETURN_OK;
5853}
5854
5855// Outputs the number of stations associated per AP
5856INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5857{
5858 char interface_name[16] = {0};
5859 char cmd[128]={0};
5860 char buf[128]={0};
5861 BOOL status = false;
5862
5863 if(apIndex > MAX_APS)
5864 return RETURN_ERR;
5865
5866 wifi_getApEnable(apIndex,&status);
5867 if (!status)
5868 return RETURN_OK;
5869
5870 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5871 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5872 return RETURN_ERR;
5873 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
5874 _syscmd(cmd, buf, sizeof(buf));
5875 sscanf(buf,"%lu", output_ulong);
5876
5877 return RETURN_OK;
5878}
5879
5880// manually removes any active wi-fi association with the device specified on this ap
5881INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5882{
developer7e4a2a62023-04-06 19:56:03 +08005883 char inf_name[16] = {0};
5884 char cmd[MAX_CMD_SIZE] = {0};
5885 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005886
developer7e4a2a62023-04-06 19:56:03 +08005887 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
developer72fb0bb2023-01-11 09:46:29 +08005888 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08005889
5890 snprintf(cmd, sizeof(cmd),"hostapd_cli -i %s disassociate %s", inf_name, client_mac);
5891 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005892
5893 return RETURN_OK;
5894}
5895
5896// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5897INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5898{
developer7e4a2a62023-04-06 19:56:03 +08005899 int max_radio_num = 0;
5900
5901 if(NULL == output_int)
5902 return RETURN_ERR;
5903
5904 wifi_getMaxRadioNumber(&max_radio_num);
5905 *output_int = apIndex % max_radio_num;
5906
5907 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005908}
5909
5910// sets the radio index for the specific ap
5911INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5912{
5913 //set to config only and wait for wifi reset to apply settings
5914 return RETURN_ERR;
5915}
5916
5917// Get the ACL MAC list per AP
5918INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5919{
developer7e4a2a62023-04-06 19:56:03 +08005920 char cmd[MAX_CMD_SIZE] = {0};
5921 char buf[MAX_BUF_SIZE] = {0};
5922 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005923
developer7e4a2a62023-04-06 19:56:03 +08005924 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
5925 return RETURN_ERR;
5926
5927 /* mwctl acl del sta */
5928 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep ':'", inf_name);
5929 _syscmd(cmd, buf, sizeof(buf));
5930
5931 memcpy(macArray, buf, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08005932
5933 return RETURN_OK;
5934}
5935
5936INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5937{
developer72fb0bb2023-01-11 09:46:29 +08005938
developer7e4a2a62023-04-06 19:56:03 +08005939 wifi_getApAclDevices(apIndex, macArray, buf_size);
developer72fb0bb2023-01-11 09:46:29 +08005940
5941 return RETURN_OK;
5942}
5943
5944
5945// Get the list of stations associated per AP
5946INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5947{
developer7e4a2a62023-04-06 19:56:03 +08005948 char interface_name[IF_NAME_SIZE] = {0};
5949 char cmd[MAX_CMD_SIZE];
developer72fb0bb2023-01-11 09:46:29 +08005950
developer7e4a2a62023-04-06 19:56:03 +08005951 if(apIndex > 3) //Currently supporting apIndex upto 3
5952 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005953
developer7e4a2a62023-04-06 19:56:03 +08005954 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5955 return RETURN_ERR;
5956
5957 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s list_sta", interface_name);
5958 _syscmd(cmd, macArray, buf_size);
5959 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08005960}
5961
5962// adds the mac address to the filter list
5963//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5964INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5965{
developer7e4a2a62023-04-06 19:56:03 +08005966 char cmd[MAX_CMD_SIZE] = {0};
5967 char buf[MAX_BUF_SIZE] = {0};
5968 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005969
developer7e4a2a62023-04-06 19:56:03 +08005970 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
5971 return RETURN_ERR;
5972
5973 if (!DeviceMacAddress)
5974 return RETURN_ERR;
5975
5976 /* mwctl acl add sta */
5977 snprintf(cmd, sizeof(cmd), "mwctl %s acl add=%s", inf_name, DeviceMacAddress);
5978 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005979
5980 return RETURN_OK;
5981}
5982
5983// deletes the mac address from the filter list
5984//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5985INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5986{
developer7e4a2a62023-04-06 19:56:03 +08005987 char cmd[MAX_CMD_SIZE] = {0};
5988 char buf[MAX_BUF_SIZE] = {0};
5989 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08005990
developer7e4a2a62023-04-06 19:56:03 +08005991 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
5992 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08005993
developer7e4a2a62023-04-06 19:56:03 +08005994 if (!DeviceMacAddress)
5995 return RETURN_ERR;
5996
5997 /* mwctl acl del sta */
5998 snprintf(cmd, sizeof(cmd), "mwctl %s acl del=%s", inf_name, DeviceMacAddress);
5999 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006000
6001 return RETURN_OK;
6002}
6003
6004// outputs the number of devices in the filter list
6005INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
6006{
developer7e4a2a62023-04-06 19:56:03 +08006007 char cmd[MAX_CMD_SIZE] = {0};
6008 char buf[MAX_BUF_SIZE] = {0};
6009 char inf_name[IF_NAME_SIZE] = {0};
6010 char sta_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08006011
developer72fb0bb2023-01-11 09:46:29 +08006012 if(output_uint == NULL)
6013 return RETURN_ERR;
6014
developer7e4a2a62023-04-06 19:56:03 +08006015 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6016 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006017
developer7e4a2a62023-04-06 19:56:03 +08006018 /* mwctl acl get sta num */
6019 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | wc -l | tr -d '\\n'", inf_name);
6020 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006021
developer7e4a2a62023-04-06 19:56:03 +08006022 if (atoi(buf) > 1)
6023 *output_uint = atoi(buf) - 1; /*except the line of acl_policy*/
6024 else {
6025 *output_uint = 0;
6026 printf("%s: acl get wrong return content!!!\n", __func__);
6027 }
6028
6029 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006030}
6031
6032INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
6033{
6034 char cmd[128]={'\0'};
6035 char buf[128]={'\0'};
6036
6037 if(strcmp(action,"DENY")==0)
6038 {
6039 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
6040 system(buf);
6041 return RETURN_OK;
6042 }
6043
6044 if(strcmp(action,"ALLOW")==0)
6045 {
6046 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
6047 system(buf);
6048 return RETURN_OK;
6049 }
6050
6051 return RETURN_ERR;
6052
6053}
6054
6055// enable kick for devices on acl black list
6056INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
6057{
6058 char aclArray[512] = {0}, *acl = NULL;
6059 char assocArray[512] = {0}, *asso = NULL;
6060
6061 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
6062 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
6063
developer7e4a2a62023-04-06 19:56:03 +08006064 /* if there are no devices connected there is nothing to do */
developer72fb0bb2023-01-11 09:46:29 +08006065 if (strlen(assocArray) < 17)
6066 return RETURN_OK;
6067
developer7e4a2a62023-04-06 19:56:03 +08006068 if (enable == TRUE) {
6069 /* kick off the MAC which is in ACL array (deny list) */
6070 acl = strtok(aclArray, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006071 while (acl != NULL) {
6072 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
6073 wifi_kickApAssociatedDevice(apIndex, acl);
6074
developer7e4a2a62023-04-06 19:56:03 +08006075 acl = strtok(NULL, "\n");
developer72fb0bb2023-01-11 09:46:29 +08006076 }
6077 wifi_setApMacAddressControlMode(apIndex, 2);
developer7e4a2a62023-04-06 19:56:03 +08006078 } else
developer72fb0bb2023-01-11 09:46:29 +08006079 wifi_setApMacAddressControlMode(apIndex, 0);
developer72fb0bb2023-01-11 09:46:29 +08006080
developer72fb0bb2023-01-11 09:46:29 +08006081 return RETURN_OK;
6082}
6083
6084INT wifi_setPreferPrivateConnection(BOOL enable)
6085{
6086 return RETURN_OK;
6087}
6088
6089// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6090INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6091{
developer7e4a2a62023-04-06 19:56:03 +08006092 char inf_name[IF_NAME_SIZE] = {0};
6093 char cmd[MAX_CMD_SIZE] = {0};
6094 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006095
developer7e4a2a62023-04-06 19:56:03 +08006096 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
6097 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006098
developer7e4a2a62023-04-06 19:56:03 +08006099 /*mwctl set acl policy*/
6100 snprintf(cmd, sizeof(cmd), "mwctl %s acl policy=%d", inf_name, filterMode);
6101 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006102
developer7e4a2a62023-04-06 19:56:03 +08006103 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006104}
6105
6106// 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.
6107INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6108{
6109 return RETURN_ERR;
6110}
6111
6112// gets the vlan ID for this ap from an internal enviornment variable
6113INT wifi_getApVlanID(INT apIndex, INT *output_int)
6114{
6115 if(apIndex==0)
6116 {
6117 *output_int=100;
6118 return RETURN_OK;
6119 }
6120
6121 return RETURN_ERR;
6122}
6123
6124// sets the vlan ID for this ap to an internal enviornment variable
6125INT wifi_setApVlanID(INT apIndex, INT vlanId)
6126{
6127 //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)
6128 return RETURN_ERR;
6129}
6130
6131// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6132INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6133{
6134 snprintf(bridgeName, 32, "brlan0");
6135 snprintf(IP, 32, "10.0.0.1");
6136 snprintf(subnet, 32, "255.255.255.0");
6137
6138 return RETURN_OK;
6139}
6140
6141//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6142INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6143{
6144 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6145 return RETURN_ERR;
6146}
6147
6148// reset the vlan configuration for this ap
6149INT wifi_resetApVlanCfg(INT apIndex)
6150{
6151 char original_config_file[64] = {0};
6152 char current_config_file[64] = {0};
6153 char buf[64] = {0};
6154 char cmd[64] = {0};
6155 char vlan_file[64] = {0};
6156 char vlan_tagged_interface[16] = {0};
6157 char vlan_bridge[16] = {0};
6158 char vlan_naming[16] = {0};
6159 struct params list[4] = {0};
6160 wifi_band band;
6161
6162 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6163
6164 band = wifi_index_to_band(apIndex);
6165 if (band == band_2_4)
6166 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6167 else if (band == band_5)
6168 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6169 else if (band == band_6)
6170 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6171
6172 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6173
6174 if (strlen(vlan_file) == 0)
6175 strcpy(vlan_file, VLAN_FILE);
6176
6177 // The file should exist or this vap would not work.
6178 if (access(vlan_file, F_OK) != 0) {
6179 sprintf(cmd, "touch %s", vlan_file);
6180 _syscmd(cmd, buf, sizeof(buf));
6181 }
6182 list[0].name = "vlan_file";
6183 list[0].value = vlan_file;
6184
6185 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6186 list[1].name = "vlan_tagged_interface";
6187 list[1].value = vlan_tagged_interface;
6188
6189 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6190 list[2].name = "vlan_bridge";
6191 list[2].value = vlan_bridge;
6192
6193 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6194 list[3].name = "vlan_naming";
6195 list[3].value = vlan_naming;
6196
6197 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6198 wifi_hostapdWrite(current_config_file, list, 4);
6199 //Reapply vlan settings
6200 // wifi_pushBridgeInfo(apIndex);
6201
6202 // restart this ap
6203 wifi_setApEnable(apIndex, FALSE);
6204 wifi_setApEnable(apIndex, TRUE);
6205
6206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6207
6208 return RETURN_OK;
6209}
6210
6211// 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.
6212INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6213{
6214 return RETURN_ERR;
6215}
6216
6217// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6218INT wifi_startHostApd()
6219{
6220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6221 system("systemctl start hostapd.service");
6222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6223 return RETURN_OK;
6224 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6225}
6226
6227// stops hostapd
developer69b61b02023-03-07 17:17:44 +08006228INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08006229{
6230 char cmd[128] = {0};
6231 char buf[128] = {0};
6232
6233 sprintf(cmd,"systemctl stop hostapd");
6234 _syscmd(cmd, buf, sizeof(buf));
6235
6236 return RETURN_OK;
6237}
6238
6239// restart hostapd dummy function
6240INT wifi_restartHostApd()
6241{
6242 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6243 system("systemctl restart hostapd-global");
6244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6245
6246 return RETURN_OK;
6247}
6248
6249static int align_hostapd_config(int index)
6250{
6251 ULONG lval;
6252 wifi_getRadioChannel(index%2, &lval);
6253 wifi_setRadioChannel(index%2, lval);
6254 return RETURN_OK;
6255}
6256
6257// sets the AP enable status variable for the specified ap.
6258INT wifi_setApEnable(INT apIndex, BOOL enable)
6259{
developer7e4a2a62023-04-06 19:56:03 +08006260 char interface_name[16] = {0};
6261 char config_file[MAX_BUF_SIZE] = {0};
6262 char cmd[MAX_CMD_SIZE] = {0};
6263 char buf[MAX_BUF_SIZE] = {0};
6264 BOOL status;
6265 int max_radio_num = 0;
6266 int phyId = 0;
developer72fb0bb2023-01-11 09:46:29 +08006267
developer7e4a2a62023-04-06 19:56:03 +08006268 wifi_getApEnable(apIndex, &status);
developer72fb0bb2023-01-11 09:46:29 +08006269
developer7e4a2a62023-04-06 19:56:03 +08006270 wifi_getMaxRadioNumber(&max_radio_num);
6271 if (enable == status)
6272 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006273
developer7e4a2a62023-04-06 19:56:03 +08006274 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6275 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006276
developer7e4a2a62023-04-06 19:56:03 +08006277 if (enable == TRUE) {
6278 int radioIndex = apIndex % max_radio_num;
6279 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08006280
developer7e4a2a62023-04-06 19:56:03 +08006281 snprintf(config_file, MAX_BUF_SIZE, "%s%d.conf", CONFIG_PREFIX, apIndex);
6282 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6283 _syscmd(cmd, buf, sizeof(buf));
6284 } else {
6285 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw REMOVE %s", interface_name);
6286 _syscmd(cmd, buf, sizeof(buf));
6287 }
6288 snprintf(cmd, MAX_CMD_SIZE, "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6289 interface_name, interface_name, enable, VAP_STATUS_FILE);
6290 _syscmd(cmd, buf, sizeof(buf));
6291 //Wait for wifi up/down to apply
6292 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006293}
6294
6295// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6296INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6297{
developer7e4a2a62023-04-06 19:56:03 +08006298 char interface_name[IF_NAME_SIZE] = {0};
6299 char cmd[MAX_CMD_SIZE] = {0};
6300 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08006301
developer7e4a2a62023-04-06 19:56:03 +08006302 if ((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6303 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +08006304
developer7e4a2a62023-04-06 19:56:03 +08006305 *output_bool = 0;
developer72fb0bb2023-01-11 09:46:29 +08006306
developer7e4a2a62023-04-06 19:56:03 +08006307 if ((apIndex >= 0) && (apIndex < MAX_APS)) {
6308 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6309 *output_bool = FALSE;
6310 return RETURN_OK;
6311 }
6312 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6313 *output_bool = _syscmd(cmd, buf, sizeof(buf)) ? 0 : 1;
6314 }
developer72fb0bb2023-01-11 09:46:29 +08006315
developer7e4a2a62023-04-06 19:56:03 +08006316 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006317}
6318
developer69b61b02023-03-07 17:17:44 +08006319// Outputs the AP "Enabled" "Disabled" status from driver
6320INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08006321{
developer7e4a2a62023-04-06 19:56:03 +08006322 char cmd[128] = {0};
6323 char buf[128] = {0};
6324 BOOL output_bool;
developer72fb0bb2023-01-11 09:46:29 +08006325
developer7e4a2a62023-04-06 19:56:03 +08006326 if (!output_string) {
6327 printf("%s: null pointer!", __func__);
6328 return RETURN_ERR;
6329 }
developer72fb0bb2023-01-11 09:46:29 +08006330
developer7e4a2a62023-04-06 19:56:03 +08006331 wifi_getApEnable(apIndex, &output_bool);
developer72fb0bb2023-01-11 09:46:29 +08006332
developer7e4a2a62023-04-06 19:56:03 +08006333 if(output_bool == 1)
6334 snprintf(output_string, 32, "Up");
6335 else
6336 snprintf(output_string, 32, "Disable");
6337
6338 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08006339}
6340
6341//Indicates whether or not beacons include the SSID name.
6342// outputs a 1 if SSID on the AP is enabled, else outputs 0
6343INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6344{
6345 //get the running status
6346 char config_file[MAX_BUF_SIZE] = {0};
6347 char buf[16] = {0};
6348
6349 if (!output)
6350 return RETURN_ERR;
6351
6352 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6353 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6354 // default is enable
6355 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6356 *output = TRUE;
6357
6358 return RETURN_OK;
6359}
6360
6361// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6362INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6363{
6364 //store the config, apply instantly
6365 char config_file[MAX_BUF_SIZE] = {0};
6366 struct params list;
6367
6368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6369 list.name = "ignore_broadcast_ssid";
6370 list.value = enable?"0":"1";
6371
6372 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6373 wifi_hostapdWrite(config_file, &list, 1);
6374 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6375 //TODO: call hostapd_cli for dynamic_config_control
6376 wifi_reloadAp(apIndex);
6377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6378
6379 return RETURN_OK;
6380}
6381
6382//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6383INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6384{
6385 //get the running status
6386 if(!output_uint)
6387 return RETURN_ERR;
6388 *output_uint=16;
6389 return RETURN_OK;
6390}
6391
6392INT wifi_setApRetryLimit(INT apIndex, UINT number)
6393{
6394 //apply instantly
6395 return RETURN_ERR;
6396}
6397
6398//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6399INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6400{
6401 if(!output)
6402 return RETURN_ERR;
6403 *output=TRUE;
6404 return RETURN_OK;
6405}
6406
6407//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6408INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6409{
6410 //get the running status from driver
6411 char cmd[128] = {0};
6412 char buf[128] = {0};
6413 int max_radio_num = 0, radioIndex = 0;
6414 int phyId = 0;
6415
6416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6417
6418 wifi_getMaxRadioNumber(&max_radio_num);
6419 radioIndex = apIndex % max_radio_num;
6420 phyId = radio_index_to_phy(radioIndex);
6421 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6422 _syscmd(cmd,buf, sizeof(buf));
6423
6424 if (strlen(buf) > 0)
6425 *output = true;
6426
6427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6428
6429 return RETURN_OK;
6430}
6431
6432//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6433INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6434{
6435 //get the running status from driver
6436 if(!output)
6437 return RETURN_ERR;
6438
6439 char config_file[MAX_BUF_SIZE] = {0};
6440 char buf[16] = {0};
6441
6442 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6443 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6444 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6445 *output = TRUE;
6446 else
6447 *output = FALSE;
6448
6449 return RETURN_OK;
6450}
6451
6452// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6453INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6454{
6455 //Save config and apply instantly.
6456 char config_file[MAX_BUF_SIZE] = {0};
6457 struct params list;
6458
6459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6460 list.name = "wmm_enabled";
6461 list.value = enable?"1":"0";
6462
6463 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6464 wifi_hostapdWrite(config_file, &list, 1);
6465 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6466 wifi_reloadAp(apIndex);
6467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6468
6469 return RETURN_OK;
6470}
6471
6472//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.
6473INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6474{
6475 //get the running status from driver
6476 if(!output)
6477 return RETURN_ERR;
6478
6479 char config_file[128] = {0};
6480 char buf[16] = {0};
6481
6482 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6483 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6484 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6485 *output = TRUE;
6486 else
6487 *output = FALSE;
6488
6489 return RETURN_OK;
6490}
6491
6492// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6493INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6494{
6495 //save config and apply instantly.
6496 char config_file[MAX_BUF_SIZE] = {0};
6497 struct params list;
6498
6499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6500 list.name = "uapsd_advertisement_enabled";
6501 list.value = enable?"1":"0";
6502
6503 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6504 wifi_hostapdWrite(config_file, &list, 1);
6505 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6506 wifi_reloadAp(apIndex);
6507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6508
6509 return RETURN_OK;
6510}
6511
6512// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6513INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6514{
6515 char interface_name[16] = {0};
6516 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6517 char cmd[128] = {0};
6518 char buf[128] = {0};
6519 char ack_filepath[128] = {0};
6520 uint16_t bitmap = 0;
6521 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6522 FILE *f = NULL;
6523
6524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6525
6526 // Get current setting
6527 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6528 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6529 _syscmd(cmd, buf, sizeof(buf));
6530 if (strlen(buf) > 0)
6531 bitmap = strtoul(buf, NULL, 10);
6532
6533 bitmap = strtoul(buf, NULL, 10);
6534
6535 if (ackPolicy == TRUE) { // True, unset this class
6536 bitmap &= ~class_map[class];
6537 } else { // False, set this class
6538 bitmap |= class_map[class];
6539 }
6540
6541 f = fopen(ack_filepath, "w");
6542 if (f == NULL) {
6543 fprintf(stderr, "%s: fopen failed\n", __func__);
6544 return RETURN_ERR;
6545 }
6546 fprintf(f, "%hu", bitmap);
6547 fclose(f);
6548
6549 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6550 return RETURN_ERR;
6551 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6552 _syscmd(cmd, buf, sizeof(buf));
6553
6554 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6555 return RETURN_OK;
6556}
6557
6558//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.
6559INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6560{
6561 //get the running status from driver
6562 if(!output_uint)
6563 return RETURN_ERR;
6564
6565 char output[16]={'\0'};
6566 char config_file[MAX_BUF_SIZE] = {0};
6567
6568 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6569 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6570 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6571 else {
6572 int device_num = atoi(output);
6573 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6574 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6575 return RETURN_ERR;
6576 }
6577 else {
6578 *output_uint = device_num;
6579 }
6580 }
6581
6582 return RETURN_OK;
6583}
6584
6585INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6586{
6587 //store to wifi config, apply instantly
6588 char str[MAX_BUF_SIZE]={'\0'};
6589 char cmd[MAX_CMD_SIZE]={'\0'};
6590 struct params params;
6591 char config_file[MAX_BUF_SIZE] = {0};
6592
6593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6594 if (number > MAX_ASSOCIATED_STA_NUM) {
6595 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6596 return RETURN_ERR;
6597 }
6598 sprintf(str, "%d", number);
6599 params.name = "max_num_sta";
6600 params.value = str;
6601
6602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6603 int ret = wifi_hostapdWrite(config_file, &params, 1);
6604 if (ret) {
6605 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6606 ,__func__, ret);
6607 }
6608
6609 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6610 if (ret) {
6611 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6612 ,__func__, ret);
6613 }
6614 wifi_reloadAp(apIndex);
6615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6616
6617 return RETURN_OK;
6618}
6619
6620//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.
6621INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6622{
6623 //get the current threshold
6624 if(!output_uint)
6625 return RETURN_ERR;
6626 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6627 if (*output_uint == 0)
6628 *output_uint = 50;
6629 return RETURN_OK;
6630}
6631
6632INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6633{
6634 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6635 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6636 return RETURN_OK;
6637 return RETURN_ERR;
6638}
6639
6640//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.
6641INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6642{
6643 if(!output_uint)
6644 return RETURN_ERR;
6645 *output_uint = 3;
6646 return RETURN_OK;
6647}
6648
6649//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6650INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6651{
6652 if(!output_uint)
6653 return RETURN_ERR;
6654 *output_uint = 3;
6655 return RETURN_OK;
6656}
6657
6658//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.
6659INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6660{
6661 if(!output_in_seconds)
6662 return RETURN_ERR;
6663 *output_in_seconds = 0;
6664 return RETURN_OK;
6665}
6666
6667//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
6668INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6669{
6670 if(!output || apIndex>=MAX_APS)
6671 return RETURN_ERR;
6672 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6673 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6674 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006675}
developer72fb0bb2023-01-11 09:46:29 +08006676
6677//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6678INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6679{
6680 char config_file[128] = {0};
6681 char wpa[16] = {0};
6682 char key_mgmt[64] = {0};
6683 char buf[16] = {0};
6684 if (!output)
6685 return RETURN_ERR;
6686
6687 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6688 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6689
6690 strcpy(output, "None");//Copying "None" to output string for default case
6691 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6692 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6693 if (!strcmp(wpa, "1"))
6694 snprintf(output, 32, "WPA-Personal");
6695 else if (!strcmp(wpa, "2"))
6696 snprintf(output, 32, "WPA2-Personal");
6697 else if (!strcmp(wpa, "3"))
6698 snprintf(output, 32, "WPA-WPA2-Personal");
6699
6700 } else if (strstr(key_mgmt, "WPA-EAP")) {
6701 if (!strcmp(wpa, "1"))
6702 snprintf(output, 32, "WPA-Enterprise");
6703 else if (!strcmp(wpa, "2"))
6704 snprintf(output, 32, "WPA2-Enterprise");
6705 else if (!strcmp(wpa, "3"))
6706 snprintf(output, 32, "WPA-WPA2-Enterprise");
6707 } else if (strstr(key_mgmt, "SAE")) {
6708 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6709 snprintf(output, 32, "WPA3-Personal");
6710 else
6711 snprintf(output, 32, "WPA3-Personal-Transition");
6712 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6713 snprintf(output, 32, "WPA3-Enterprise");
6714 }
6715
6716 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6717 return RETURN_OK;
6718#if 0
6719 //TODO: need to revisit below implementation
6720 char securityType[32], authMode[32];
6721 int enterpriseMode=0;
6722
6723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6724 if(!output)
6725 return RETURN_ERR;
6726
6727 wifi_getApBeaconType(apIndex, securityType);
6728 strcpy(output,"None");//By default, copying "None" to output string
6729 if (strncmp(securityType,"None", strlen("None")) == 0)
6730 return RETURN_OK;
6731
6732 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6733 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6734
6735 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6736 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6737 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6738 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6739 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6740 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6742
6743 return RETURN_OK;
6744#endif
6745}
developer69b61b02023-03-07 17:17:44 +08006746
developer72fb0bb2023-01-11 09:46:29 +08006747INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6748{
6749 char securityType[32];
6750 char authMode[32];
6751
6752 //store settings and wait for wifi up to apply
6753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6754 if(!encMode)
6755 return RETURN_ERR;
6756
6757 if (strcmp(encMode, "None")==0)
6758 {
6759 strcpy(securityType,"None");
6760 strcpy(authMode,"None");
6761 }
6762 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6763 {
6764 strcpy(securityType,"WPAand11i");
6765 strcpy(authMode,"PSKAuthentication");
6766 }
6767 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6768 {
6769 strcpy(securityType,"WPAand11i");
6770 strcpy(authMode,"EAPAuthentication");
6771 }
6772 else if (strcmp(encMode, "WPA-Personal")==0)
6773 {
6774 strcpy(securityType,"WPA");
6775 strcpy(authMode,"PSKAuthentication");
6776 }
6777 else if (strcmp(encMode, "WPA-Enterprise")==0)
6778 {
6779 strcpy(securityType,"WPA");
6780 strcpy(authMode,"EAPAuthentication");
6781 }
6782 else if (strcmp(encMode, "WPA2-Personal")==0)
6783 {
6784 strcpy(securityType,"11i");
6785 strcpy(authMode,"PSKAuthentication");
6786 }
6787 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6788 {
6789 strcpy(securityType,"11i");
6790 strcpy(authMode,"EAPAuthentication");
6791 }
6792 else if (strcmp(encMode, "WPA3-Personal") == 0)
6793 {
6794 strcpy(securityType,"11i");
6795 strcpy(authMode,"SAEAuthentication");
6796 }
6797 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6798 {
6799 strcpy(securityType, "11i");
6800 strcpy(authMode, "PSK-SAEAuthentication");
6801 }
6802 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6803 {
6804 strcpy(securityType,"11i");
6805 strcpy(authMode,"EAP_192-bit_Authentication");
6806 }
developer3086e2f2023-01-17 09:40:01 +08006807 else if (strcmp(encMode, "OWE") == 0)
6808 {
6809 strcpy(securityType,"11i");
6810 strcpy(authMode,"Enhanced_Open");
6811 }
developer72fb0bb2023-01-11 09:46:29 +08006812 else
6813 {
6814 strcpy(securityType,"None");
6815 strcpy(authMode,"None");
6816 }
6817 wifi_setApBeaconType(apIndex, securityType);
6818 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6820
6821 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006822}
developer72fb0bb2023-01-11 09:46:29 +08006823
6824
6825//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6826// output_string must be pre-allocated as 64 character string by caller
6827// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6828INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6829{
6830 char buf[16] = {0};
6831 char config_file[MAX_BUF_SIZE] = {0};
6832
6833 if(output_string==NULL)
6834 return RETURN_ERR;
6835
6836 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6837 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6838
6839 if(strcmp(buf,"0")==0)
6840 {
6841 printf("wpa_mode is %s ......... \n",buf);
6842 return RETURN_ERR;
6843 }
6844
6845 wifi_dbg_printf("\nFunc=%s\n",__func__);
6846 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6847 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6848 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6849
6850 return RETURN_OK;
6851}
6852
6853// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6854// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6855INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6856{
6857 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6858 struct params params={'\0'};
6859 int ret;
6860 char config_file[MAX_BUF_SIZE] = {0};
6861
6862 if(NULL == preSharedKey)
6863 return RETURN_ERR;
6864
6865 params.name = "wpa_passphrase";
6866
6867 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6868 {
6869 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6870 return RETURN_ERR;
6871 }
6872 params.value = preSharedKey;
6873 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6874 ret = wifi_hostapdWrite(config_file, &params, 1);
6875 if(!ret)
6876 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6877 return ret;
6878 //TODO: call hostapd_cli for dynamic_config_control
6879}
6880
6881//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6882// outputs the passphrase, maximum 63 characters
6883INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6884{
6885 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6886
6887 wifi_dbg_printf("\nFunc=%s\n",__func__);
6888 if (NULL == output_string)
6889 return RETURN_ERR;
6890
6891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6892 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6893 if(strcmp(buf,"0")==0)
6894 {
6895 printf("wpa_mode is %s ......... \n",buf);
6896 return RETURN_ERR;
6897 }
6898
6899 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6900 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6901
6902 return RETURN_OK;
6903}
6904
6905// sets the passphrase enviornment variable, max 63 characters
6906INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6907{
6908 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6909 struct params params={'\0'};
6910 char config_file[MAX_BUF_SIZE] = {0};
6911 int ret;
6912
6913 if(NULL == passPhrase)
6914 return RETURN_ERR;
6915
6916 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6917 {
6918 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6919 return RETURN_ERR;
6920 }
6921 params.name = "wpa_passphrase";
6922 params.value = passPhrase;
6923 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6924 ret=wifi_hostapdWrite(config_file,&params,1);
6925 if(!ret)
6926 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6927
6928 return ret;
6929}
6930
6931//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.
6932INT wifi_setApSecurityReset(INT apIndex)
6933{
6934 char original_config_file[64] = {0};
6935 char current_config_file[64] = {0};
6936 char buf[64] = {0};
6937 char cmd[64] = {0};
6938 char wpa[4] = {0};
6939 char wpa_psk[64] = {0};
6940 char wpa_passphrase[64] = {0};
6941 char wpa_psk_file[128] = {0};
6942 char wpa_key_mgmt[64] = {0};
6943 char wpa_pairwise[32] = {0};
6944 wifi_band band;
6945 struct params list[6];
6946
6947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6948
6949 band = wifi_index_to_band(apIndex);
6950 if (band == band_2_4)
6951 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6952 else if (band == band_5)
6953 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6954 else if (band == band_6)
6955 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6956 else
6957 return RETURN_ERR;
6958
6959 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6960 list[0].name = "wpa";
6961 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08006962
developer72fb0bb2023-01-11 09:46:29 +08006963 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6964 list[1].name = "wpa_psk";
6965 list[1].value = wpa_psk;
6966
6967 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6968 list[2].name = "wpa_passphrase";
6969 list[2].value = wpa_passphrase;
6970
6971 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6972
6973 if (strlen(wpa_psk_file) == 0)
6974 strcpy(wpa_psk_file, PSK_FILE);
6975
6976 if (access(wpa_psk_file, F_OK) != 0) {
6977 sprintf(cmd, "touch %s", wpa_psk_file);
6978 _syscmd(cmd, buf, sizeof(buf));
6979 }
6980 list[3].name = "wpa_psk_file";
6981 list[3].value = wpa_psk_file;
6982
6983 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6984 list[4].name = "wpa_key_mgmt";
6985 list[4].value = wpa_key_mgmt;
6986
6987 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6988 list[5].name = "wpa_pairwise";
6989 list[5].value = wpa_pairwise;
6990
6991 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6992 wifi_hostapdWrite(current_config_file, list, 6);
6993
6994 wifi_setApEnable(apIndex, FALSE);
6995 wifi_setApEnable(apIndex, TRUE);
6996
6997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6998 return RETURN_OK;
6999}
7000
7001//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).
7002INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7003{
7004 char config_file[64] = {0};
7005 char buf[64] = {0};
7006 char cmd[256] = {0};
7007
7008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7009
7010 if(!IP_output || !Port_output || !RadiusSecret_output)
7011 return RETURN_ERR;
7012
7013 // Read the first matched config
7014 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7015 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7016 _syscmd(cmd, buf, sizeof(buf));
7017 strncpy(IP_output, buf, 64);
7018
7019 memset(buf, 0, sizeof(buf));
7020 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7021 _syscmd(cmd, buf, sizeof(buf));
7022 *Port_output = atoi(buf);
7023
7024 memset(buf, 0, sizeof(buf));
7025 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7026 _syscmd(cmd, buf, sizeof(buf));
7027 strncpy(RadiusSecret_output, buf, 64);
7028
7029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7030 return RETURN_OK;
7031}
7032
7033INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7034{
7035 char config_file[64] = {0};
7036 char port_str[8] = {0};
7037 char cmd[256] = {0};
7038 char buf[128] = {0};
7039
7040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7041
7042 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7043
7044 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7045 _syscmd(cmd, buf, sizeof(buf));
7046 memset(cmd, 0, sizeof(cmd));
7047
7048 snprintf(port_str, sizeof(port_str), "%d", port);
7049 if (strlen(buf) == 0)
7050 // Append
7051 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7052 "auth_server_addr=%s\\n"
7053 "auth_server_port=%s\\n"
7054 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7055 else {
7056 // Delete the three lines setting after the "# radius 1" comment
7057 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7058 _syscmd(cmd, buf, sizeof(buf));
7059 memset(cmd, 0, sizeof(cmd));
7060 // Use "# radius 1" comment to find the location to insert the radius setting
7061 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7062 "# radius 1\\n"
7063 "auth_server_addr=%s\\n"
7064 "auth_server_port=%s\\n"
7065 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7066 }
7067 if(_syscmd(cmd, buf, sizeof(buf))) {
7068 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7069 return RETURN_ERR;
7070 }
7071
7072 wifi_reloadAp(apIndex);
7073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7074 return RETURN_OK;
7075}
7076
7077INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7078{
7079 char config_file[64] = {0};
7080 char buf[64] = {0};
7081 char cmd[256] = {0};
7082
7083 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7084
7085 if(!IP_output || !Port_output || !RadiusSecret_output)
7086 return RETURN_ERR;
7087
7088 // Read the second matched config
7089 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7090 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7091 _syscmd(cmd, buf, sizeof(buf));
7092 strncpy(IP_output, buf, 64);
7093
7094 memset(buf, 0, sizeof(buf));
7095 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7096 _syscmd(cmd, buf, sizeof(buf));
7097 *Port_output = atoi(buf);
7098
7099 memset(buf, 0, sizeof(buf));
7100 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7101 _syscmd(cmd, buf, sizeof(buf));
7102 strncpy(RadiusSecret_output, buf, 64);
7103
7104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7105 return RETURN_OK;
7106}
7107
7108INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7109{
7110 char config_file[64] = {0};
7111 char port_str[8] = {0};
7112 char cmd[256] = {0};
7113 char buf[128] = {0};
7114
7115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7116
7117 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7118
7119 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7120 _syscmd(cmd, buf, sizeof(buf));
7121 memset(cmd, 0, sizeof(cmd));
7122
7123 snprintf(port_str, sizeof(port_str), "%d", port);
7124 if (strlen(buf) == 0)
7125 // Append
7126 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7127 "auth_server_addr=%s\\n"
7128 "auth_server_port=%s\\n"
7129 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7130 else {
7131 // Delete the three lines setting after the "# radius 2" comment
7132 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7133 _syscmd(cmd, buf, sizeof(buf));
7134 memset(cmd, 0, sizeof(cmd));
7135 // Use "# radius 2" comment to find the location to insert the radius setting
7136 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7137 "# radius 2\\n"
7138 "auth_server_addr=%s\\n"
7139 "auth_server_port=%s\\n"
7140 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7141 }
7142 if(_syscmd(cmd, buf, sizeof(buf))) {
7143 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7144 return RETURN_ERR;
7145 }
7146
7147 wifi_reloadAp(apIndex);
7148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7149 return RETURN_OK;
7150}
7151
7152//RadiusSettings
7153INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7154{
7155 if(!output)
7156 return RETURN_ERR;
7157
7158 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08007159 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7160 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7161 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7162 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 +08007163 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 +08007164 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7165 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7166 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 +08007167 //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.
7168
7169 return RETURN_OK;
7170}
7171
7172INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7173{
7174 //store the paramters, and apply instantly
7175 return RETURN_ERR;
7176}
7177
7178//Device.WiFi.AccessPoint.{i}.WPS.Enable
7179//Enables or disables WPS functionality for this access point.
7180// outputs the WPS enable state of this ap in output_bool
7181INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7182{
7183 char interface_name[16] = {0};
7184 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7185 if(!output_bool)
7186 return RETURN_ERR;
7187 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7188 return RETURN_ERR;
7189 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7190 _syscmd(cmd, buf, sizeof(buf));
7191 if(strstr(buf, "configured"))
7192 *output_bool=TRUE;
7193 else
7194 *output_bool=FALSE;
7195
7196 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007197}
developer72fb0bb2023-01-11 09:46:29 +08007198
7199//Device.WiFi.AccessPoint.{i}.WPS.Enable
7200// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7201INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7202{
7203 char config_file[MAX_BUF_SIZE] = {0};
7204 struct params params;
7205
7206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7207 //store the paramters, and wait for wifi up to apply
7208 params.name = "wps_state";
7209 params.value = enable ? "2":"0";
7210
7211 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7212 wifi_hostapdWrite(config_file, &params, 1);
7213 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7214 wifi_reloadAp(apIndex);
7215
7216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7217 return RETURN_OK;
7218}
7219
7220//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
7221INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7222{
7223 if(!output)
7224 return RETURN_ERR;
7225 snprintf(output, 128, "PushButton,PIN");
7226 return RETURN_OK;
7227}
7228
7229//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7230//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.
7231// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7232INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7233{
7234 if(!output)
7235 return RETURN_ERR;
7236 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7237
7238 return RETURN_OK;
7239}
7240
7241//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7242// 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
7243INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7244{
7245 //apply instantly. No setting need to be stored.
7246 char methods[MAX_BUF_SIZE], *token, *next_token;
7247 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7248 struct params params;
7249
7250 if(!methodString)
7251 return RETURN_ERR;
7252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7253 //store the paramters, and wait for wifi up to apply
7254
7255 snprintf(methods, sizeof(methods), "%s", methodString);
7256 for(token=methods; *token; token=next_token)
7257 {
7258 strtok_r(token, ",", &next_token);
7259 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7260 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7261 else if(*token=='E')
7262 {
7263 if(!strcmp(methods, "Ethernet"))
7264 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7265 else if(!strcmp(methods, "ExternalNFCToken"))
7266 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7267 else
7268 printf("%s: Unknown WpsConfigMethod\n", __func__);
7269 }
7270 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7271 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7272 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7273 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7274 else if(*token=='P' )
7275 {
7276 if(!strcmp(token, "PushButton"))
7277 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7278 else if(!strcmp(token, "PIN"))
7279 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7280 else
7281 printf("%s: Unknown WpsConfigMethod\n", __func__);
7282 }
7283 else
7284 printf("%s: Unknown WpsConfigMethod\n", __func__);
7285 }
7286 params.name = "config_methods";
7287 params.value = config_methods;
7288 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7289 wifi_hostapdWrite(config_file, &params, 1);
7290 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7292
7293 return RETURN_OK;
7294}
7295
7296// outputs the pin value, ulong_pin must be allocated by the caller
7297INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7298{
7299 char buf[MAX_BUF_SIZE] = {0};
7300 char cmd[MAX_CMD_SIZE] = {0};
7301
7302 if(!output_ulong)
7303 return RETURN_ERR;
7304 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7305 _syscmd(cmd, buf, sizeof(buf));
7306 if(strlen(buf) > 0)
7307 *output_ulong=strtoul(buf, NULL, 10);
7308
7309 return RETURN_OK;
7310}
7311
7312// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7313INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7314{
7315 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7316 char ap_pin[16] = {0};
7317 char buf[MAX_BUF_SIZE] = {0};
7318 char config_file[MAX_BUF_SIZE] = {0};
7319 ULONG prev_pin = 0;
7320 struct params params;
7321
7322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7323 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7324 params.name = "ap_pin";
7325 params.value = ap_pin;
7326 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7327 wifi_hostapdWrite(config_file, &params, 1);
7328 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7330
7331 return RETURN_OK;
7332}
7333
7334// Output string is either Not configured or Configured, max 32 characters
7335INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7336{
7337 char interface_name[16] = {0};
7338 char cmd[MAX_CMD_SIZE];
7339 char buf[MAX_BUF_SIZE]={0};
7340
7341 if(!output_string)
7342 return RETURN_ERR;
7343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7344 snprintf(output_string, 32, "Not configured");
7345 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7346 return RETURN_ERR;
7347 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7348 _syscmd(cmd, buf, sizeof(buf));
7349
7350 if(!strncmp(buf, "configured", 10))
7351 snprintf(output_string, 32, "Configured");
7352 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7353
7354 return RETURN_OK;
7355}
7356
7357// sets the WPS pin for this AP
7358INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7359{
7360 char interface_name[16] = {0};
7361 char cmd[MAX_CMD_SIZE];
7362 char buf[MAX_BUF_SIZE]={0};
7363 BOOL enable;
7364
7365 wifi_getApEnable(apIndex, &enable);
7366 if (!enable)
7367 return RETURN_ERR;
7368 wifi_getApWpsEnable(apIndex, &enable);
7369 if (!enable)
7370 return RETURN_ERR;
7371
7372 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7373 return RETURN_ERR;
7374 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7375 _syscmd(cmd, buf, sizeof(buf));
7376 if((strstr(buf, "OK"))!=NULL)
7377 return RETURN_OK;
7378
7379 return RETURN_ERR;
7380}
7381
7382// This function is called when the WPS push button has been pressed for this AP
7383INT wifi_setApWpsButtonPush(INT apIndex)
7384{
7385 char cmd[MAX_CMD_SIZE];
7386 char buf[MAX_BUF_SIZE]={0};
7387 char interface_name[16] = {0};
7388 BOOL enable=FALSE;
7389
7390 wifi_getApEnable(apIndex, &enable);
7391 if (!enable)
7392 return RETURN_ERR;
7393
7394 wifi_getApWpsEnable(apIndex, &enable);
7395 if (!enable)
7396 return RETURN_ERR;
7397
7398 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7399 return RETURN_ERR;
7400
7401 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7402 _syscmd(cmd, buf, sizeof(buf));
7403
7404 if((strstr(buf, "OK"))!=NULL)
7405 return RETURN_OK;
7406 return RETURN_ERR;
7407}
7408
7409// cancels WPS mode for this AP
7410INT wifi_cancelApWPS(INT apIndex)
7411{
7412 char interface_name[16] = {0};
7413 char cmd[MAX_CMD_SIZE];
7414 char buf[MAX_BUF_SIZE]={0};
7415
7416 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7417 return RETURN_ERR;
7418 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7419 _syscmd(cmd,buf, sizeof(buf));
7420
7421 if((strstr(buf, "OK"))!=NULL)
7422 return RETURN_OK;
7423 return RETURN_ERR;
7424}
7425
7426//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7427//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7428INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7429{
7430 char interface_name[16] = {0};
7431 FILE *f = NULL;
7432 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7433 char cmd[256] = {0}, buf[2048] = {0};
7434 char *param = NULL, *value = NULL, *line=NULL;
7435 size_t len = 0;
7436 ssize_t nread = 0;
7437 wifi_associated_dev_t *dev=NULL;
7438
7439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7440 *associated_dev_array = NULL;
7441 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7442 return RETURN_ERR;
7443 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7444 _syscmd(cmd,buf,sizeof(buf));
7445 *output_array_size = atoi(buf);
7446
7447 if (*output_array_size <= 0)
7448 return RETURN_OK;
7449
7450 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7451 *associated_dev_array = dev;
7452 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7453 _syscmd(cmd,buf,sizeof(buf));
7454 f = fopen("/tmp/connected_devices.txt", "r");
7455 if (f==NULL)
7456 {
7457 *output_array_size=0;
7458 return RETURN_ERR;
7459 }
7460 while ((getline(&line, &len, f)) != -1)
7461 {
7462 param = strtok(line,"=");
7463 value = strtok(NULL,"=");
7464
7465 if( strcmp("flags",param) == 0 )
7466 {
7467 value[strlen(value)-1]='\0';
7468 if(strstr (value,"AUTHORIZED") != NULL )
7469 {
7470 dev[auth_temp].cli_AuthenticationState = 1;
7471 dev[auth_temp].cli_Active = 1;
7472 auth_temp++;
7473 read_flag=1;
7474 }
7475 }
7476 if(read_flag==1)
7477 {
7478 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7479 {
7480 value[strlen(value)-1]='\0';
7481 sscanf(value, "%x:%x:%x:%x:%x:%x",
7482 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7483 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7484 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7485 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7486 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7487 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7488 mac_temp++;
7489 read_flag=0;
7490 }
7491 }
7492 }
7493 *output_array_size = auth_temp;
7494 auth_temp=0;
7495 mac_temp=0;
7496 free(line);
7497 fclose(f);
7498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7499 return RETURN_OK;
7500}
7501
7502#define MACADDRESS_SIZE 6
7503
7504INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7505{
7506 FILE *fp = NULL;
7507 char str[MAX_BUF_SIZE] = {0};
7508 int wificlientindex = 0 ;
7509 int count = 0;
7510 int signalstrength = 0;
7511 int arr[MACADDRESS_SIZE] = {0};
7512 unsigned char mac[MACADDRESS_SIZE] = {0};
7513 UINT wifi_count = 0;
7514 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7515 char pipeCmd[MAX_CMD_SIZE] = {0};
7516
7517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7518 *output_array_size = 0;
7519 *associated_dev_array = NULL;
7520
7521 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7522 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08007523 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08007524 {
7525 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7526 return RETURN_ERR;
7527 }
7528
7529 /* Read the output a line at a time - output it. */
7530 fgets(str, sizeof(str)-1, fp);
7531 wifi_count = (unsigned int) atoi ( str );
7532 *output_array_size = wifi_count;
7533 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7534 pclose(fp);
7535
7536 if(wifi_count == 0)
7537 {
7538 return RETURN_OK;
7539 }
7540 else
7541 {
7542 wifi_associated_dev3_t* temp = NULL;
7543 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7544 if(temp == NULL)
7545 {
7546 printf("Error Statement. Insufficient memory \n");
7547 return RETURN_ERR;
7548 }
7549
7550 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7551 system(pipeCmd);
7552 memset(pipeCmd,0,sizeof(pipeCmd));
7553 if(apIndex == 0)
7554 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7555 else if(apIndex == 1)
7556 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7557 system(pipeCmd);
7558
7559 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7560 if(fp == NULL)
7561 {
7562 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7563 free(temp);
7564 return RETURN_ERR;
7565 }
7566 fclose(fp);
7567
7568 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7569 fp = popen(pipeCmd, "r");
7570 if(fp)
7571 {
7572 for(count =0 ; count < wifi_count; count++)
7573 {
7574 fgets(str, MAX_BUF_SIZE, fp);
7575 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7576 {
7577 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7578 {
7579 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7580
7581 }
7582 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7583 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]);
7584 }
7585 temp[count].cli_AuthenticationState = 1; //TODO
7586 temp[count].cli_Active = 1; //TODO
7587 }
7588 pclose(fp);
7589 }
7590
7591 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7592 fp = popen(pipeCmd, "r");
7593 if(fp)
developer69b61b02023-03-07 17:17:44 +08007594 {
developer72fb0bb2023-01-11 09:46:29 +08007595 pclose(fp);
7596 }
7597 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7598 if(fp)
7599 {
7600 for(count =0 ; count < wifi_count ;count++)
7601 {
7602 fgets(str, MAX_BUF_SIZE, fp);
7603 signalstrength = atoi(str);
7604 temp[count].cli_SignalStrength = signalstrength;
7605 temp[count].cli_RSSI = signalstrength;
7606 temp[count].cli_SNR = signalstrength + 95;
7607 }
7608 pclose(fp);
7609 }
7610
7611
7612 if((apIndex == 0) || (apIndex == 4))
7613 {
7614 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08007615 {
developer72fb0bb2023-01-11 09:46:29 +08007616 strcpy(temp[count].cli_OperatingStandard,"g");
7617 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7618 }
7619
7620 //BytesSent
7621 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7622 fp = popen(pipeCmd, "r");
7623 if(fp)
developer69b61b02023-03-07 17:17:44 +08007624 {
developer72fb0bb2023-01-11 09:46:29 +08007625 pclose(fp);
7626 }
7627 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7628 if(fp)
7629 {
7630 for (count = 0; count < wifi_count; count++)
7631 {
7632 fgets(str, MAX_BUF_SIZE, fp);
7633 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7634 }
7635 pclose(fp);
7636 }
7637
7638 //BytesReceived
7639 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7640 fp = popen(pipeCmd, "r");
7641 if (fp)
7642 {
7643 pclose(fp);
7644 }
7645 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7646 if (fp)
7647 {
7648 for (count = 0; count < wifi_count; count++)
7649 {
7650 fgets(str, MAX_BUF_SIZE, fp);
7651 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7652 }
7653 pclose(fp);
7654 }
7655
7656 //PacketsSent
7657 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7658 fp = popen(pipeCmd, "r");
7659 if (fp)
7660 {
7661 pclose(fp);
7662 }
7663
7664 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7665 if (fp)
7666 {
7667 for (count = 0; count < wifi_count; count++)
7668 {
7669 fgets(str, MAX_BUF_SIZE, fp);
7670 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7671 }
7672 pclose(fp);
7673 }
7674
7675 //PacketsReceived
7676 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7677 fp = popen(pipeCmd, "r");
7678 if (fp)
7679 {
7680 pclose(fp);
7681 }
7682 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7683 if (fp)
7684 {
7685 for (count = 0; count < wifi_count; count++)
7686 {
7687 fgets(str, MAX_BUF_SIZE, fp);
7688 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7689 }
7690 pclose(fp);
7691 }
7692
7693 //ErrorsSent
7694 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7695 fp = popen(pipeCmd, "r");
7696 if (fp)
7697 {
7698 pclose(fp);
7699 }
7700 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7701 if (fp)
7702 {
7703 for (count = 0; count < wifi_count; count++)
7704 {
7705 fgets(str, MAX_BUF_SIZE, fp);
7706 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7707 }
7708 pclose(fp);
7709 }
7710
7711 //ErrorsSent
7712 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7713 fp = popen(pipeCmd, "r");
7714 if (fp)
7715 {
7716 pclose(fp);
7717 }
7718 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7719 if (fp)
7720 {
7721 for (count = 0; count < wifi_count; count++)
7722 {
7723 fgets(str, MAX_BUF_SIZE, fp);
7724 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7725 }
7726 pclose(fp);
7727 }
7728
7729 //LastDataDownlinkRate
7730 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7731 fp = popen(pipeCmd, "r");
7732 if (fp)
7733 {
7734 pclose(fp);
7735 }
7736 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7737 if (fp)
7738 {
7739 for (count = 0; count < wifi_count; count++)
7740 {
7741 fgets(str, MAX_BUF_SIZE, fp);
7742 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7743 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7744 }
7745 pclose(fp);
7746 }
7747
7748 //LastDataUplinkRate
7749 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7750 fp = popen(pipeCmd, "r");
7751 if (fp)
7752 {
7753 pclose(fp);
7754 }
7755 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7756 if (fp)
7757 {
7758 for (count = 0; count < wifi_count; count++)
7759 {
7760 fgets(str, MAX_BUF_SIZE, fp);
7761 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7762 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7763 }
7764 pclose(fp);
7765 }
7766
7767 }
7768 else if ((apIndex == 1) || (apIndex == 5))
7769 {
7770 for (count = 0; count < wifi_count; count++)
7771 {
7772 strcpy(temp[count].cli_OperatingStandard, "a");
7773 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7774 temp[count].cli_BytesSent = 0;
7775 temp[count].cli_BytesReceived = 0;
7776 temp[count].cli_LastDataUplinkRate = 0;
7777 temp[count].cli_LastDataDownlinkRate = 0;
7778 temp[count].cli_PacketsSent = 0;
7779 temp[count].cli_PacketsReceived = 0;
7780 temp[count].cli_ErrorsSent = 0;
7781 }
7782 }
7783
7784 for (count = 0; count < wifi_count; count++)
7785 {
7786 temp[count].cli_Retransmissions = 0;
7787 temp[count].cli_DataFramesSentAck = 0;
7788 temp[count].cli_DataFramesSentNoAck = 0;
7789 temp[count].cli_MinRSSI = 0;
7790 temp[count].cli_MaxRSSI = 0;
7791 strncpy(temp[count].cli_InterferenceSources, "", 64);
7792 memset(temp[count].cli_IPAddress, 0, 64);
7793 temp[count].cli_RetransCount = 0;
7794 temp[count].cli_FailedRetransCount = 0;
7795 temp[count].cli_RetryCount = 0;
7796 temp[count].cli_MultipleRetryCount = 0;
7797 }
7798 *associated_dev_array = temp;
7799 }
7800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7801 return RETURN_OK;
7802}
7803
developer7e4a2a62023-04-06 19:56:03 +08007804int wifihal_interfacestatus(CHAR *wifi_status, CHAR *interface_name)
developer72fb0bb2023-01-11 09:46:29 +08007805{
developer7e4a2a62023-04-06 19:56:03 +08007806 char cmd[MAX_CMD_SIZE] = {0};
7807 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08007808
developer7e4a2a62023-04-06 19:56:03 +08007809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
7810
7811 snprintf(cmd, MAX_CMD_SIZE, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4 | tr -d '\\n'",
7812 interface_name);
7813 _syscmd(cmd, buf, MAX_BUF_SIZE);
7814
7815 strcpy(wifi_status, buf); /* TBD: check wifi_status mem lenth and replace with strcpy later */
7816
7817 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08007818 return RETURN_OK;
7819}
7820
7821/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7822struct hostapd_sta_param {
7823 char key[50];
7824 char value[100];
7825}
7826
7827static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7828 int i = 0;
7829
7830 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7831 if (strncmp(params[i].key,key,50) == 0){
7832 return &params[i].value;
7833 }
7834 i++;
7835 }
7836 return NULL;
7837
7838} */
7839
7840static unsigned int count_occurences(const char *buf, const char *word)
7841{
7842 unsigned int n = 0;
7843 char *ptr = strstr(buf, word);
7844
7845 while (ptr++) {
7846 n++;
7847 ptr = strstr(ptr, word);
7848 }
7849
7850 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7851 return n;
7852}
7853
7854static const char *get_line_from_str_buf(const char *buf, char *line)
7855{
7856 int i;
7857 int n = strlen(buf);
7858
7859 for (i = 0; i < n; i++) {
7860 line[i] = buf[i];
7861 if (buf[i] == '\n') {
7862 line[i] = '\0';
7863 return &buf[i + 1];
7864 }
7865 }
7866
7867 return NULL;
7868}
7869
7870INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7871{
7872 unsigned int assoc_cnt = 0;
7873 char interface_name[50] = {0};
7874 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7875 char cmd[MAX_CMD_SIZE] = {'\0'};
7876 char line[256] = {'\0'};
7877 int i = 0;
7878 int ret = 0;
7879 const char *ptr = NULL;
7880 char *key = NULL;
7881 char *val = NULL;
7882 wifi_associated_dev3_t *temp = NULL;
7883 int rssi;
7884
7885 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7886
7887 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7888 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7889 return RETURN_ERR;
7890 }
7891
7892 // Example filtered output of 'iw dev' command:
7893 // Station 0a:69:72:10:d2:fa (on wifi0)
7894 // signal avg:-67 [-71, -71] dBm
7895 // Station 28:c2:1f:25:5f:99 (on wifi0)
7896 // signal avg:-67 [-71, -70] dBm
7897 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7898 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7899 return RETURN_ERR;
7900 }
7901
7902 ret = _syscmd(cmd, buf, sizeof(buf));
7903 if (ret == RETURN_ERR) {
7904 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7905 return RETURN_ERR;
7906 }
7907
7908 *output_array_size = count_occurences(buf, "Station");
7909 if (*output_array_size == 0) return RETURN_OK;
7910
7911 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7912 if (temp == NULL) {
7913 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7914 return RETURN_ERR;
7915 }
7916 *associated_dev_array = temp;
7917
7918 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7919 ptr = get_line_from_str_buf(buf, line);
7920 i = -1;
7921 while (ptr) {
7922 if (strstr(line, "Station")) {
7923 i++;
7924 key = strtok(line, " ");
7925 val = strtok(NULL, " ");
7926 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7927 &temp[i].cli_MACAddress[0],
7928 &temp[i].cli_MACAddress[1],
7929 &temp[i].cli_MACAddress[2],
7930 &temp[i].cli_MACAddress[3],
7931 &temp[i].cli_MACAddress[4],
7932 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7933 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7934 free(*associated_dev_array);
7935 return RETURN_ERR;
7936 }
7937 }
7938 else if (i < 0) {
7939 ptr = get_line_from_str_buf(ptr, line);
7940 continue; // We didn't detect 'station' entry yet
7941 }
7942 else if (strstr(line, "signal avg")) {
7943 key = strtok(line, ":");
7944 val = strtok(NULL, " ");
7945 if (sscanf(val, "%d", &rssi) <= 0 ) {
7946 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7947 free(*associated_dev_array);
7948 return RETURN_ERR;
7949 }
7950 temp[i].cli_RSSI = rssi;
7951 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7952 }
7953 // Here other fields can be parsed if added to filter of 'iw dev' command
7954
7955 ptr = get_line_from_str_buf(ptr, line);
7956 };
7957
7958 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7959
7960 return RETURN_OK;
7961}
7962
7963#if 0
7964//To-do
7965INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7966{
7967 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7968
7969 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08007970#if 0
developer72fb0bb2023-01-11 09:46:29 +08007971 FILE *f;
7972 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7973 char cmd[256], buf[2048];
7974 char *param , *value, *line=NULL;
7975 size_t len = 0;
7976 ssize_t nread;
7977 wifi_associated_dev3_t *dev=NULL;
7978 *associated_dev_array = NULL;
7979 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7980 _syscmd(cmd,buf,sizeof(buf));
7981 *output_array_size = atoi(buf);
7982
7983 if (*output_array_size <= 0)
7984 return RETURN_OK;
7985
7986 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7987 *associated_dev_array = dev;
7988 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
7989 _syscmd(cmd,buf,sizeof(buf));
7990 f = fopen("/tmp/connected_devices.txt", "r");
7991 if (f==NULL)
7992 {
7993 *output_array_size=0;
7994 return RETURN_ERR;
7995 }
7996 while ((nread = getline(&line, &len, f)) != -1)
7997 {
7998 param = strtok(line,"=");
7999 value = strtok(NULL,"=");
8000
8001 if( strcmp("flags",param) == 0 )
8002 {
8003 value[strlen(value)-1]='\0';
8004 if(strstr (value,"AUTHORIZED") != NULL )
8005 {
8006 dev[auth_temp].cli_AuthenticationState = 1;
8007 dev[auth_temp].cli_Active = 1;
8008 auth_temp++;
8009 read_flag=1;
8010 }
8011 }
8012 if(read_flag==1)
8013 {
8014 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8015 {
8016 value[strlen(value)-1]='\0';
8017 sscanf(value, "%x:%x:%x:%x:%x:%x",
8018 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8019 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8020 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8021 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8022 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8023 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8024
8025 }
8026 else if( strcmp("rx_packets",param) == 0 )
8027 {
8028 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8029 }
8030
8031 else if( strcmp("tx_packets",param) == 0 )
8032 {
developer69b61b02023-03-07 17:17:44 +08008033 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08008034 }
8035
8036 else if( strcmp("rx_bytes",param) == 0 )
8037 {
8038 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8039 }
8040
8041 else if( strcmp("tx_bytes",param) == 0 )
8042 {
developer69b61b02023-03-07 17:17:44 +08008043 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08008044 mac_temp++;
8045 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08008046 }
developer72fb0bb2023-01-11 09:46:29 +08008047 }
8048 }
8049
8050 *output_array_size = auth_temp;
8051 auth_temp=0;
8052 mac_temp=0;
8053 free(line);
8054 fclose(f);
8055#endif
8056 char interface_name[MAX_BUF_SIZE] = {0};
8057 char wifi_status[MAX_BUF_SIZE] = {0};
8058 char hostapdconf[MAX_BUF_SIZE] = {0};
8059
8060 wifi_associated_dev3_t *dev_array = NULL;
8061 ULONG wifi_count = 0;
8062
8063 *associated_dev_array = NULL;
8064 *output_array_size = 0;
8065
8066 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8067 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8068 {
8069 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8070
8071 wifi_GetInterfaceName(interface_name, hostapdconf);
8072
8073 if(strlen(interface_name) > 1)
8074 {
8075 wifihal_interfacestatus(wifi_status,interface_name);
8076 if(strcmp(wifi_status,"RUNNING") == 0)
8077 {
8078 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8079
8080 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08008081 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08008082 }
8083 else
8084 {
8085 *associated_dev_array = NULL;
8086 }
8087 }
8088 }
8089
8090 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8091 return RETURN_OK;
8092}
8093#endif
8094
8095/* getIPAddress function */
8096/**
8097* @description Returning IpAddress of the Matched String
8098*
developer69b61b02023-03-07 17:17:44 +08008099* @param
developer72fb0bb2023-01-11 09:46:29 +08008100* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08008101* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08008102* @return The status of the operation
8103* @retval RETURN_OK if successful
8104* @retval RETURN_ERR if any error is detected
8105*
8106*/
8107
8108INT getIPAddress(char *str,char *ipaddr)
8109{
8110 FILE *fp = NULL;
8111 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8112 int LeaseTime = 0,ret = 0;
8113 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8114 {
8115 return RETURN_ERR;
8116 }
8117
8118 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8119 {
8120 /*
8121 Sample:sss
8122 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8123 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8124 */
8125 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8126 &(LeaseTime),
8127 phyAddr,
8128 ipAddr,
8129 hostName
8130 );
8131 if(ret != 4)
8132 continue;
8133 if(strcmp(str,phyAddr) == 0)
8134 strcpy(ipaddr,ipAddr);
8135 }
8136 fclose(fp);
8137 return RETURN_OK;
8138}
8139
8140/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8141/**
8142* @description Returning Inactive wireless connected clients informations
8143*
developer69b61b02023-03-07 17:17:44 +08008144* @param
developer72fb0bb2023-01-11 09:46:29 +08008145* @filename Holding private_wifi 2g/5g content files
8146* @associated_dev_array Having inactiv wireless clients informations
8147* @output_array_size Returning Inactive wireless counts
8148* @return The status of the operation
8149* @retval RETURN_OK if successful
8150* @retval RETURN_ERR if any error is detected
8151*
8152*/
8153
8154INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8155{
8156 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8157 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8158 FILE *fp = NULL;
8159 int arr[MACADDRESS_SIZE] = {0};
8160 unsigned char mac[MACADDRESS_SIZE] = {0};
8161 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8162 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8163 fp = popen(buf,"r");
8164 if(fp == NULL)
8165 return RETURN_ERR;
8166 else
8167 {
8168 fgets(path,sizeof(path),fp);
8169 maccount = atoi(path);
8170 }
8171 pclose(fp);
8172 *output_array_size = maccount;
8173 wifi_associated_dev3_t* temp = NULL;
8174 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8175 *associated_dev_array = temp;
8176 if(temp == NULL)
8177 {
8178 printf("Error Statement. Insufficient memory \n");
8179 return RETURN_ERR;
8180 }
8181 memset(buf,0,sizeof(buf));
8182 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8183 fp = popen(buf,"r");
8184 if (fp == NULL) {
8185 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8186 return RETURN_ERR;
8187 }
8188 for(count = 0; count < maccount ; count++)
8189 {
8190 fgets(path,sizeof(path),fp);
8191 for(i = 0; path[i]!='\n';i++)
8192 str[i]=path[i];
8193 str[i]='\0';
8194 getIPAddress(str,ipaddr);
8195 memset(buf,0,sizeof(buf));
8196 if(strlen(ipaddr) > 0)
8197 {
8198 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8199 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8200 {
8201 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8202 {
8203 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8204 {
8205 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8206
8207 }
8208 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8209 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]);
8210 }
8211 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08008212 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08008213 temp[count].cli_SignalStrength = 0;
8214 }
8215 else //Active wireless clients info
8216 {
8217 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8218 {
8219 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8220 {
8221 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8222
8223 }
8224 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8225 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]);
8226 }
8227 temp[count].cli_Active = 1;
8228 }
8229 }
8230 memset(ipaddr,0,sizeof(ipaddr));
8231 }
8232 pclose(fp);
8233 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8234 return RETURN_OK;
8235}
8236//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8237//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8238//To get Band Steering Capability
8239INT wifi_getBandSteeringCapability(BOOL *support)
8240{
8241 *support = FALSE;
8242 return RETURN_OK;
8243}
8244
8245
8246//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8247//To get Band Steering enable status
8248INT wifi_getBandSteeringEnable(BOOL *enable)
8249{
8250 *enable = FALSE;
8251 return RETURN_OK;
8252}
8253
8254//To turn on/off Band steering
8255INT wifi_setBandSteeringEnable(BOOL enable)
8256{
8257 return RETURN_OK;
8258}
8259
8260//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8261//To get Band Steering AP group
8262INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8263{
8264 if (NULL == output_ApGroup)
8265 return RETURN_ERR;
8266
8267 strcpy(output_ApGroup, "1,2");
8268 return RETURN_OK;
8269}
8270
8271//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8272//to set and read the band steering BandUtilizationThreshold parameters
8273INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8274{
8275 return RETURN_ERR;
8276}
8277
8278INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8279{
8280 return RETURN_ERR;
8281}
8282
8283//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8284//to set and read the band steering RSSIThreshold parameters
8285INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8286{
8287 return RETURN_ERR;
8288}
8289
8290INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8291{
8292 return RETURN_ERR;
8293}
8294
8295
8296//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8297//to set and read the band steering physical modulation rate threshold parameters
8298INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8299{
8300 //If chip is not support, return -1
8301 return RETURN_ERR;
8302}
8303
8304INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8305{
8306 //If chip is not support, return -1
8307 return RETURN_ERR;
8308}
8309
8310//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8311//to set and read the inactivity time (in seconds) for steering under overload condition
8312INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8313{
8314 return RETURN_ERR;
8315}
8316
8317INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8318{
8319 return RETURN_ERR;
8320}
8321
8322//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8323//to set and read the inactivity time (in seconds) for steering under Idle condition
8324INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8325{
8326 return RETURN_ERR;
8327}
8328
8329INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8330{
8331 return RETURN_ERR;
8332}
8333
8334//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8335//pClientMAC[64]
8336//pSourceSSIDIndex[64]
8337//pDestSSIDIndex[64]
8338//pSteeringReason[256]
8339INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8340{
8341 //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
8342 *pSteeringTime=time(NULL);
8343 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8344 return RETURN_OK;
8345}
8346
8347INT wifi_ifConfigDown(INT apIndex)
8348{
8349 INT status = RETURN_OK;
8350 char cmd[64];
8351
8352 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8353 printf("%s: %s\n", __func__, cmd);
8354 system(cmd);
8355
8356 return status;
8357}
8358
8359INT wifi_ifConfigUp(INT apIndex)
8360{
8361 char interface_name[16] = {0};
8362 char cmd[128];
8363 char buf[1024];
8364
8365 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8366 return RETURN_ERR;
8367 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8368 _syscmd(cmd, buf, sizeof(buf));
8369 return 0;
8370}
8371
8372//>> Deprecated. Replace with wifi_applyRadioSettings
8373INT wifi_pushBridgeInfo(INT apIndex)
8374{
8375 char interface_name[16] = {0};
8376 char ip[32] = {0};
8377 char subnet[32] = {0};
8378 char bridge[32] = {0};
8379 int vlanId = 0;
8380 char cmd[128] = {0};
8381 char buf[1024] = {0};
8382
8383 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8384 wifi_getApVlanID(apIndex,&vlanId);
8385
8386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8387 return RETURN_ERR;
8388 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8389 _syscmd(cmd,buf, sizeof(buf));
8390
8391 return 0;
8392}
8393
8394INT wifi_pushChannel(INT radioIndex, UINT channel)
8395{
8396 char interface_name[16] = {0};
8397 char cmd[128];
8398 char buf[1024];
8399 int apIndex;
8400
developer69b61b02023-03-07 17:17:44 +08008401 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08008402 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8403 return RETURN_ERR;
8404 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8405 _syscmd(cmd,buf, sizeof(buf));
8406
8407 return 0;
8408}
8409
8410INT wifi_pushChannelMode(INT radioIndex)
8411{
8412 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8413 return RETURN_ERR;
8414}
8415
8416INT wifi_pushDefaultValues(INT radioIndex)
8417{
8418 //Apply Comcast specified default radio settings instantly
8419 //AMPDU=1
8420 //AMPDUFrames=32
8421 //AMPDULim=50000
8422 //txqueuelen=1000
8423
8424 return RETURN_ERR;
8425}
8426
8427INT wifi_pushTxChainMask(INT radioIndex)
8428{
8429 //Apply default TxChainMask instantly
8430 return RETURN_ERR;
8431}
8432
8433INT wifi_pushRxChainMask(INT radioIndex)
8434{
8435 //Apply default RxChainMask instantly
8436 return RETURN_ERR;
8437}
8438
8439INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8440{
developer7e4a2a62023-04-06 19:56:03 +08008441 INT status;
developer72fb0bb2023-01-11 09:46:29 +08008442
developer7e4a2a62023-04-06 19:56:03 +08008443 status = wifi_setSSIDName(apIndex, ssid);
8444 wifi_quick_reload_ap(apIndex);
developer72fb0bb2023-01-11 09:46:29 +08008445
developer7e4a2a62023-04-06 19:56:03 +08008446 return status;
developer72fb0bb2023-01-11 09:46:29 +08008447}
8448
8449INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8450{
8451 //Apply default Ssid Advertisement instantly
8452 return RETURN_ERR;
8453}
8454
8455INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8456{
8457 INT status = RETURN_ERR;
8458 *output = 0;
8459 return RETURN_ERR;
8460}
8461
8462INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8463{
8464 return RETURN_OK;
8465}
8466
8467INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8468{
8469 return RETURN_OK;
8470}
8471
8472//To-do
8473INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8474{
8475 char output[16]={'\0'};
8476 char config_file[MAX_BUF_SIZE] = {0};
8477
8478 if (!output_string)
8479 return RETURN_ERR;
8480
8481 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8482 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8483
8484 if (strlen(output) == 0)
8485 snprintf(output_string, 64, "Disabled");
8486 else if (strncmp(output, "0", 1) == 0)
8487 snprintf(output_string, 64, "Disabled");
8488 else if (strncmp(output, "1", 1) == 0)
8489 snprintf(output_string, 64, "Optional");
8490 else if (strncmp(output, "2", 1) == 0)
8491 snprintf(output_string, 64, "Required");
8492 else {
8493 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8494 return RETURN_ERR;
8495 }
8496
8497 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8498 return RETURN_OK;
8499}
8500INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8501{
8502 char str[MAX_BUF_SIZE]={'\0'};
8503 char cmd[MAX_CMD_SIZE]={'\0'};
8504 struct params params;
8505 char config_file[MAX_BUF_SIZE] = {0};
8506
8507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8508 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8509 return RETURN_ERR;
8510
8511 params.name = "ieee80211w";
8512 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8513 params.value = "0";
8514 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8515 params.value = "1";
8516 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8517 params.value = "2";
8518 else{
8519 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8520 return RETURN_ERR;
8521 }
8522 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8523 wifi_hostapdWrite(config_file, &params, 1);
8524 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8525 return RETURN_OK;
8526}
8527INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8528{
8529 char output[16]={'\0'};
8530 char config_file[MAX_BUF_SIZE] = {0};
8531
8532 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8533 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8534 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8535
8536 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8537 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8538
8539 return RETURN_OK;
8540}
8541
8542INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8543{
8544 return RETURN_OK;
8545}
8546
8547INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8548{
8549 return RETURN_OK;
8550}
8551
8552INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8553{
8554 return RETURN_OK;
8555}
8556
8557INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8558{
8559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8560 char config_file[MAX_BUF_SIZE] = {0};
8561
8562 if (NULL == output)
8563 return RETURN_ERR;
8564 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8565 wifi_hostapdRead(config_file,"hw_mode",output,64);
8566
8567 if(strcmp(output,"b")==0)
8568 sprintf(output, "%s", "1,2,5.5,11");
8569 else if (strcmp(output,"a")==0)
8570 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8571 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8572 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8573
8574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8575 return RETURN_OK;
8576}
8577
8578INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8579{
8580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8581 char *temp;
8582 char temp_output[128];
8583 char temp_TransmitRates[128];
8584 char config_file[MAX_BUF_SIZE] = {0};
8585
8586 if (NULL == output)
8587 return RETURN_ERR;
8588
8589 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8590 wifi_hostapdRead(config_file,"supported_rates",output,64);
8591
8592 if (strlen(output) == 0) {
8593 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8594 return RETURN_OK;
8595 }
8596 strcpy(temp_TransmitRates,output);
8597 strcpy(temp_output,"");
8598 temp = strtok(temp_TransmitRates," ");
8599 while(temp!=NULL)
8600 {
8601 temp[strlen(temp)-1]=0;
8602 if((temp[0]=='5') && (temp[1]=='\0'))
8603 {
8604 temp="5.5";
8605 }
8606 strcat(temp_output,temp);
8607 temp = strtok(NULL," ");
8608 if(temp!=NULL)
8609 {
8610 strcat(temp_output,",");
8611 }
8612 }
8613 strcpy(output,temp_output);
8614 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8615
8616 return RETURN_OK;
8617}
8618
8619INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8620{
8621 return RETURN_OK;
8622}
8623
8624
8625INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8626{
8627 int i=0;
8628 char *temp;
8629 char temp1[128] = {0};
8630 char temp_output[128] = {0};
8631 char temp_TransmitRates[128] = {0};
8632 struct params params={'\0'};
8633 char config_file[MAX_BUF_SIZE] = {0};
8634 wifi_band band = wifi_index_to_band(wlanIndex);
8635
8636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8637 if(NULL == output)
8638 return RETURN_ERR;
8639 strcpy(temp_TransmitRates,output);
8640
8641 for(i=0;i<strlen(temp_TransmitRates);i++)
8642 {
8643 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8644 {
8645 continue;
8646 }
8647 else
8648 {
8649 return RETURN_ERR;
8650 }
8651 }
8652 strcpy(temp_output,"");
8653 temp = strtok(temp_TransmitRates,",");
8654 while(temp!=NULL)
8655 {
8656 strcpy(temp1,temp);
8657 if(band == band_5)
8658 {
8659 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8660 {
8661 return RETURN_ERR;
8662 }
8663 }
8664
8665 if(strcmp(temp,"5.5")==0)
8666 {
8667 strcpy(temp1,"55");
8668 }
8669 else
8670 {
8671 strcat(temp1,"0");
8672 }
8673 strcat(temp_output,temp1);
8674 temp = strtok(NULL,",");
8675 if(temp!=NULL)
8676 {
8677 strcat(temp_output," ");
8678 }
8679 }
8680 strcpy(output,temp_output);
8681
8682 params.name = "supported_rates";
8683 params.value = output;
8684
8685 wifi_dbg_printf("\n%s:",__func__);
8686 wifi_dbg_printf("params.value=%s\n",params.value);
8687 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8688 wifi_hostapdWrite(config_file,&params,1);
8689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8690
8691 return RETURN_OK;
8692}
8693
8694
8695static char *sncopy(char *dst, int dst_sz, const char *src)
8696{
8697 if (src && dst && dst_sz > 0) {
8698 strncpy(dst, src, dst_sz);
8699 dst[dst_sz - 1] = '\0';
8700 }
8701 return dst;
8702}
8703
8704static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8705{
8706 if (0 == strcmp(ht_mode, "HT40") ||
8707 0 == strcmp(ht_mode, "HT80") ||
8708 0 == strcmp(ht_mode, "HT160")) {
8709 switch (channel) {
8710 case 1 ... 7:
8711 case 36:
8712 case 44:
8713 case 52:
8714 case 60:
8715 case 100:
8716 case 108:
8717 case 116:
8718 case 124:
8719 case 132:
8720 case 140:
8721 case 149:
8722 case 157:
8723 return 1;
8724 case 8 ... 13:
8725 case 40:
8726 case 48:
8727 case 56:
8728 case 64:
8729 case 104:
8730 case 112:
8731 case 120:
8732 case 128:
8733 case 136:
8734 case 144:
8735 case 153:
8736 case 161:
8737 return -1;
8738 default:
8739 return -EINVAL;
8740 }
8741 }
8742
8743 return -EINVAL;
8744}
8745
8746static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8747{
8748 int idx = channel%8;
8749 if (0 == strcmp(ht_mode, "HT40") ||
8750 0 == strcmp(ht_mode, "HT80") ||
8751 0 == strcmp(ht_mode, "HT160")) {
8752 switch (idx) {
8753 case 1:
8754 return 1;
8755 case 5:
8756 return -1;
8757 default:
8758 return -EINVAL;
8759 }
8760 }
8761
8762 return -EINVAL;
8763}
8764static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8765{
8766 if (NULL == hw_mode) return;
8767
8768 if (0 == strcmp(hw_mode, "ac"))
8769 sncopy(bw_mode, bw_mode_len, "ht vht");
8770
8771 if (0 == strcmp(hw_mode, "n"))
8772 sncopy(bw_mode, bw_mode_len, "ht");
8773
8774 return;
8775}
8776
8777static int util_chan_to_freq(int chan)
8778{
8779 if (chan == 14)
8780 return 2484;
8781 else if (chan < 14)
8782 return 2407 + chan * 5;
8783 else if (chan >= 182 && chan <= 196)
8784 return 4000 + chan * 5;
8785 else
8786 return 5000 + chan * 5;
8787 return 0;
8788}
8789
8790static int util_6G_chan_to_freq(int chan)
8791{
8792 if (chan)
8793 return 5950 + chan * 5;
8794 else
8795 return 0;
developer69b61b02023-03-07 17:17:44 +08008796
developer72fb0bb2023-01-11 09:46:29 +08008797}
8798const int *util_unii_5g_chan2list(int chan, int width)
8799{
8800 static const int lists[] = {
8801 // <width>, <chan1>, <chan2>..., 0,
8802 20, 36, 0,
8803 20, 40, 0,
8804 20, 44, 0,
8805 20, 48, 0,
8806 20, 52, 0,
8807 20, 56, 0,
8808 20, 60, 0,
8809 20, 64, 0,
8810 20, 100, 0,
8811 20, 104, 0,
8812 20, 108, 0,
8813 20, 112, 0,
8814 20, 116, 0,
8815 20, 120, 0,
8816 20, 124, 0,
8817 20, 128, 0,
8818 20, 132, 0,
8819 20, 136, 0,
8820 20, 140, 0,
8821 20, 144, 0,
8822 20, 149, 0,
8823 20, 153, 0,
8824 20, 157, 0,
8825 20, 161, 0,
8826 20, 165, 0,
8827 40, 36, 40, 0,
8828 40, 44, 48, 0,
8829 40, 52, 56, 0,
8830 40, 60, 64, 0,
8831 40, 100, 104, 0,
8832 40, 108, 112, 0,
8833 40, 116, 120, 0,
8834 40, 124, 128, 0,
8835 40, 132, 136, 0,
8836 40, 140, 144, 0,
8837 40, 149, 153, 0,
8838 40, 157, 161, 0,
8839 80, 36, 40, 44, 48, 0,
8840 80, 52, 56, 60, 64, 0,
8841 80, 100, 104, 108, 112, 0,
8842 80, 116, 120, 124, 128, 0,
8843 80, 132, 136, 140, 144, 0,
8844 80, 149, 153, 157, 161, 0,
8845 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8846 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8847 -1 // final delimiter
8848 };
8849 const int *start;
8850 const int *p;
8851
8852 for (p = lists; *p != -1; p++) {
8853 if (*p == width) {
8854 for (start = ++p; *p != 0; p++) {
8855 if (*p == chan)
8856 return start;
8857 }
8858 }
8859 // move to the end of channel list of given width
8860 while (*p != 0) {
8861 p++;
8862 }
8863 }
8864
8865 return NULL;
8866}
8867
8868static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8869{
8870 if (NULL == ht_mode)
8871 return 0;
8872
8873 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8874 const int *chans = util_unii_5g_chan2list(channel, width);
8875 int sum = 0;
8876 int cnt = 0;
8877
8878 if (NULL == chans)
8879 return 0;
8880
8881 while (*chans) {
8882 sum += *chans;
8883 cnt++;
8884 chans++;
8885 }
8886 if (cnt == 0)
8887 return 0;
8888 return sum / cnt;
8889}
8890
8891static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8892{
8893 if (NULL == ht_mode)
8894 return 0;
8895
8896 int width = strtol((ht_mode + 2), NULL, 10);
8897
8898 int idx = 0 ;
8899 int centerchan = 0;
8900 int chan_ofs = 1;
8901
8902 if (width == 40){
8903 idx = ((channel/4) + chan_ofs)%2;
8904 switch (idx) {
8905 case 0:
8906 centerchan = (channel - 2);
8907 break;
8908 case 1:
8909 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08008910 break;
developer72fb0bb2023-01-11 09:46:29 +08008911 default:
8912 return -EINVAL;
8913 }
8914 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08008915 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08008916 switch (idx) {
8917 case 0:
8918 centerchan = (channel - 6);
8919 break;
8920 case 1:
8921 centerchan = (channel + 6);
8922 break;
8923 case 2:
8924 centerchan = (channel + 2);
8925 break;
8926 case 3:
8927 centerchan = (channel - 2);
8928 break;
8929 default:
8930 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08008931 }
developer72fb0bb2023-01-11 09:46:29 +08008932 }else if (width == 160){
8933 switch (channel) {
8934 case 1 ... 29:
8935 centerchan = 15;
8936 break;
8937 case 33 ... 61:
8938 centerchan = 47;
8939 break;
8940 case 65 ... 93:
8941 centerchan = 79;
8942 break;
8943 case 97 ... 125:
8944 centerchan = 111;
8945 break;
8946 case 129 ... 157:
8947 centerchan = 143;
8948 break;
8949 case 161 ... 189:
8950 centerchan = 175;
8951 break;
8952 case 193 ... 221:
8953 centerchan = 207;
8954 break;
8955 default:
8956 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08008957 }
developer72fb0bb2023-01-11 09:46:29 +08008958 }
8959 return centerchan;
8960}
8961static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8962{
8963 BOOL onlyG, onlyN, onlyA;
8964 CHAR tmp[64];
8965 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8966 if (ret == RETURN_OK) {
8967 sncopy(hw_mode, hw_mode_size, tmp);
8968 }
8969 return ret;
8970}
8971
8972INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8973{
8974 // Sample commands:
8975 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8976 // hostapd_cli -i wifi0 chan_switch 30 2437
8977 char cmd[MAX_CMD_SIZE] = {0};
8978 char buf[MAX_BUF_SIZE] = {0};
8979 int freq = 0, ret = 0;
8980 char center_freq1_str[32] = ""; // center_freq1=%d
8981 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8982 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8983 char hw_mode[16] = ""; // n|ac
8984 char bw_mode[16] = ""; // ht|ht vht
8985 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8986 char interface_name[16] = {0};
8987 int sec_chan_offset;
8988 int width;
8989 char config_file[64] = {0};
8990 BOOL stbcEnable = FALSE;
8991 char *ext_str = "None";
8992 wifi_band band = band_invalid;
8993 int center_chan = 0;
8994 int center_freq1 = 0;
8995
8996 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
8997
8998 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8999 return RETURN_ERR;
9000
9001 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9002
9003 band = wifi_index_to_band(radioIndex);
9004
9005 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9006
9007 // Get radio mode HT20|HT40|HT80 etc.
9008 if (channel){
9009 if (band == band_6){
9010 freq = util_6G_chan_to_freq(channel);
9011 }else{
9012 freq = util_chan_to_freq(channel);
9013 }
9014 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9015
9016 // Provide bandwith if specified
9017 if (channel_width_MHz > 20) {
9018 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9019 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9020 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9021
9022 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9023 }else if (channel_width_MHz == 20){
9024 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9025 }
9026
9027
9028 if (channel_width_MHz > 20) {
9029 if (band == band_6){
9030 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9031 if(center_chan){
9032 center_freq1 = util_6G_chan_to_freq(center_chan);
9033 }
9034 }else{
9035 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9036 if(center_chan){
9037 center_freq1 = util_chan_to_freq(center_chan);
9038 }
9039 }
developer69b61b02023-03-07 17:17:44 +08009040
developer72fb0bb2023-01-11 09:46:29 +08009041 if (center_freq1)
9042 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +08009043
developer72fb0bb2023-01-11 09:46:29 +08009044 }
9045
9046 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9047 if (band == band_6){
9048 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9049 }else{
9050 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9051 }
9052 if (sec_chan_offset != -EINVAL)
9053 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9054
9055 // Only the first AP, other are hanging on the same radio
9056 int apIndex = radioIndex;
9057 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9058 interface_name, csa_beacon_count, freq,
9059 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9060 wifi_dbg_printf("execute: '%s'\n", cmd);
9061 ret = _syscmd(cmd, buf, sizeof(buf));
9062 wifi_reloadAp(radioIndex);
9063
9064 ret = wifi_setRadioChannel(radioIndex, channel);
9065 if (ret != RETURN_OK) {
9066 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9067 return RETURN_ERR;
9068 }
9069
9070 if (sec_chan_offset == 1) ext_str = "Above";
9071 else if (sec_chan_offset == -1) ext_str = "Below";
9072
9073 wifi_setRadioCenterChannel(radioIndex, center_chan);
9074
9075 } else {
9076 if (channel_width_MHz > 20)
9077 ext_str = "Above";
9078 }
9079
9080 wifi_setRadioExtChannel(radioIndex, ext_str);
9081
9082 char mhz_str[16];
9083 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9084 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9085
9086 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9087
9088 return RETURN_OK;
9089}
9090
9091INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9092{
9093 int index = -1;
9094 wifi_neighbor_ap2_t *scan_array = NULL;
9095 char cmd[256]={0};
9096 char buf[128]={0};
9097 char file_name[32] = {0};
9098 char filter_SSID[32] = {0};
9099 char line[256] = {0};
9100 char interface_name[16] = {0};
9101 char *ret = NULL;
9102 int freq=0;
9103 FILE *f = NULL;
9104 size_t len=0;
9105 int channels_num = 0;
9106 int vht_channel_width = 0;
9107 int get_noise_ret = RETURN_ERR;
9108 bool filter_enable = false;
9109 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9110 int phyId = 0;
9111
9112 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9113
9114 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9115 f = fopen(file_name, "r");
9116 if (f != NULL) {
9117 fgets(filter_SSID, sizeof(file_name), f);
9118 if (strlen(filter_SSID) != 0)
9119 filter_enable = true;
9120 fclose(f);
9121 }
9122
9123 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9124 return RETURN_ERR;
9125
9126 phyId = radio_index_to_phy(radio_index);
9127
9128 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9129 _syscmd(cmd, buf, sizeof(buf));
9130 channels_num = strtol(buf, NULL, 10);
9131
9132 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9133 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9134 fprintf(stderr, "cmd: %s\n", cmd);
9135 if ((f = popen(cmd, "r")) == NULL) {
9136 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9137 return RETURN_ERR;
9138 }
developer69b61b02023-03-07 17:17:44 +08009139
developer72fb0bb2023-01-11 09:46:29 +08009140 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9141 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08009142
developer72fb0bb2023-01-11 09:46:29 +08009143 ret = fgets(line, sizeof(line), f);
9144 while (ret != NULL) {
9145 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08009146 // 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 +08009147 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9148 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9149
9150 if (!filter_BSS) {
9151 index++;
9152 wifi_neighbor_ap2_t *tmp;
9153 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9154 if (tmp == NULL) { // no more memory to use
9155 index--;
9156 wifi_dbg_printf("%s: realloc failed\n", __func__);
9157 break;
9158 }
9159 scan_array = tmp;
9160 }
9161 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9162
9163 filter_BSS = false;
9164 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9165 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9166 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9167 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9168 } else if (strstr(line, "freq") != NULL) {
9169 sscanf(line," freq: %d", &freq);
9170 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9171
9172 if (freq >= 2412 && freq <= 2484) {
9173 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9174 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9175 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9176 }
9177 else if (freq >= 5160 && freq <= 5805) {
9178 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9179 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9180 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9181 }
9182
9183 scan_array[index].ap_Noise = 0;
9184 if (get_noise_ret == RETURN_OK) {
9185 for (int i = 0; i < channels_num; i++) {
9186 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9187 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9188 break;
9189 }
9190 }
9191 }
9192 } else if (strstr(line, "beacon interval") != NULL) {
9193 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9194 } else if (strstr(line, "signal") != NULL) {
9195 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9196 } else if (strstr(line,"SSID") != NULL) {
9197 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9198 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9199 filter_BSS = true;
9200 }
9201 } else if (strstr(line, "Supported rates") != NULL) {
9202 char SRate[80] = {0}, *tmp = NULL;
9203 memset(buf, 0, sizeof(buf));
9204 strcpy(SRate, line);
9205 tmp = strtok(SRate, ":");
9206 tmp = strtok(NULL, ":");
9207 strcpy(buf, tmp);
9208 memset(SRate, 0, sizeof(SRate));
9209
9210 tmp = strtok(buf, " \n");
9211 while (tmp != NULL) {
9212 strcat(SRate, tmp);
9213 if (SRate[strlen(SRate) - 1] == '*') {
9214 SRate[strlen(SRate) - 1] = '\0';
9215 }
9216 strcat(SRate, ",");
9217
9218 tmp = strtok(NULL, " \n");
9219 }
9220 SRate[strlen(SRate) - 1] = '\0';
9221 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9222 } else if (strstr(line, "DTIM") != NULL) {
9223 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9224 } else if (strstr(line, "VHT capabilities") != NULL) {
9225 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9226 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9227 } else if (strstr(line, "HT capabilities") != NULL) {
9228 strcat(scan_array[index].ap_SupportedStandards, ",n");
9229 strcpy(scan_array[index].ap_OperatingStandards, "n");
9230 } else if (strstr(line, "VHT operation") != NULL) {
9231 ret = fgets(line, sizeof(line), f);
9232 sscanf(line," * channel width: %d", &vht_channel_width);
9233 if(vht_channel_width == 1) {
9234 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9235 } else {
9236 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9237 }
9238 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9239 continue;
9240 } else if (strstr(line, "HT operation") != NULL) {
9241 ret = fgets(line, sizeof(line), f);
9242 sscanf(line," * secondary channel offset: %s", &buf);
9243 if (!strcmp(buf, "above")) {
9244 //40Mhz +
9245 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9246 }
9247 else if (!strcmp(buf, "below")) {
9248 //40Mhz -
9249 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9250 } else {
9251 //20Mhz
9252 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9253 }
9254 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9255 continue;
9256 } else if (strstr(line, "HE capabilities") != NULL) {
9257 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9258 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9259 ret = fgets(line, sizeof(line), f);
9260 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9261 if (strstr(line, "HE40/2.4GHz") != NULL)
9262 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9263 else
9264 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9265 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9266 if (strstr(line, "HE80/5GHz") != NULL) {
9267 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9268 ret = fgets(line, sizeof(line), f);
9269 } else
9270 continue;
9271 if (strstr(line, "HE160/5GHz") != NULL)
9272 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9273 }
9274 continue;
9275 } else if (strstr(line, "WPA") != NULL) {
9276 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9277 } else if (strstr(line, "RSN") != NULL) {
9278 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9279 } else if (strstr(line, "Group cipher") != NULL) {
9280 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9281 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9282 strcpy(scan_array[index].ap_EncryptionMode, "AES");
9283 }
9284 }
9285 ret = fgets(line, sizeof(line), f);
9286 }
9287
9288 if (!filter_BSS) {
9289 *output_array_size = index + 1;
9290 } else {
9291 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9292 *output_array_size = index;
9293 }
9294 *neighbor_ap_array = scan_array;
9295 pclose(f);
9296 free(channels_noise_arr);
9297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9298 return RETURN_OK;
9299}
9300
9301INT wifi_getApAssociatedDeviceStats(
9302 INT apIndex,
9303 mac_address_t *clientMacAddress,
9304 wifi_associated_dev_stats_t *associated_dev_stats,
9305 u64 *handle)
9306{
9307 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9308 char interface_name[50] = {0};
9309 char cmd[1024] = {0};
9310 char mac_str[18] = {0};
9311 char *key = NULL;
9312 char *val = NULL;
9313 FILE *f = NULL;
9314 char *line = NULL;
9315 size_t len = 0;
9316
9317 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9318 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9319 return RETURN_ERR;
9320 }
9321
9322 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9323 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9324 if((f = popen(cmd, "r")) == NULL) {
9325 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9326 return RETURN_ERR;
9327 }
9328
9329 while ((getline(&line, &len, f)) != -1) {
9330 key = strtok(line,":");
9331 val = strtok(NULL,":");
9332
9333 if(!strncmp(key,"rx bytes",8))
9334 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9335 if(!strncmp(key,"tx bytes",8))
9336 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9337 if(!strncmp(key,"rx packets",10))
9338 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9339 if(!strncmp(key,"tx packets",10))
9340 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9341 if(!strncmp(key,"tx retries",10))
9342 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9343 if(!strncmp(key,"tx failed",9))
9344 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9345 if(!strncmp(key,"rx drop misc",13))
9346 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9347 if(!strncmp(key,"rx bitrate",10)) {
9348 val = strtok(val, " ");
9349 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9350 }
9351 if(!strncmp(key,"tx bitrate",10)) {
9352 val = strtok(val, " ");
9353 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9354 }
9355 }
9356 free(line);
9357 pclose(f);
9358 return RETURN_OK;
9359}
9360
9361INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9362{
developer7e4a2a62023-04-06 19:56:03 +08009363 char interface_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08009364 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9365
developer7e4a2a62023-04-06 19:56:03 +08009366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9367
developer72fb0bb2023-01-11 09:46:29 +08009368 if (NULL == output_string)
9369 return RETURN_ERR;
9370
9371 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9372 return RETURN_ERR;
developer7e4a2a62023-04-06 19:56:03 +08009373
9374 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 +08009375 _syscmd(cmd, buf, sizeof(buf));
9376
9377 //size of SSID name restricted to value less than 32 bytes
9378 snprintf(output_string, 32, "%s", buf);
developer7e4a2a62023-04-06 19:56:03 +08009379 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n", __func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08009380
9381 return RETURN_OK;
9382}
9383
9384INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9385{
developer7e4a2a62023-04-06 19:56:03 +08009386 char cmd[MAX_CMD_SIZE] = {0};
9387 char buf[MAX_BUF_SIZE] = {0};
9388 char inf_name[IF_NAME_SIZE] = {0};
9389 char policy = 0;
developer72fb0bb2023-01-11 09:46:29 +08009390
9391 if (!output_filterMode)
9392 return RETURN_ERR;
9393
developer7e4a2a62023-04-06 19:56:03 +08009394 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
9395 return RETURN_ERR;
9396
9397 /* mwctl get acl policy */
9398 snprintf(cmd, sizeof(cmd), "mwctl %s acl show_all | grep policy | cut -d '=' -f2 | tr -d '\\n'", inf_name);
9399 _syscmd(cmd, buf, sizeof(buf));
9400
9401
9402 policy = atoi(buf);
9403
9404 if (policy < 0 || policy > 2) {
9405 printf("%s:get wrong acl policy!!!\n", __func__);
9406 *output_filterMode = 0;
9407 return RETURN_ERR;
9408 } else
9409 *output_filterMode = policy;
9410
developer72fb0bb2023-01-11 09:46:29 +08009411
9412 return RETURN_OK;
9413}
9414
9415INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9416{
9417 FILE *fp = NULL;
9418 char str[MAX_BUF_SIZE] = {0};
9419 int wificlientindex = 0 ;
9420 int count = 0;
9421 int signalstrength = 0;
9422 int arr[MACADDRESS_SIZE] = {0};
9423 unsigned char mac[MACADDRESS_SIZE] = {0};
9424 UINT wifi_count = 0;
9425 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9426 char pipeCmd[MAX_CMD_SIZE] = {0};
9427
9428 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9429 *output_array_size = 0;
9430 *associated_dev_array = NULL;
9431 char interface_name[50] = {0};
9432
9433 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9434 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9435 return RETURN_ERR;
9436 }
9437
9438 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9439 fp = popen(pipeCmd, "r");
9440 if (fp == NULL)
9441 {
9442 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9443 return RETURN_ERR;
9444 }
9445
9446 /* Read the output a line at a time - output it. */
9447 fgets(str, sizeof(str)-1, fp);
9448 wifi_count = (unsigned int) atoi ( str );
9449 *output_array_size = wifi_count;
9450 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9451 pclose(fp);
9452
9453 if(wifi_count == 0)
9454 {
9455 return RETURN_OK;
9456 }
9457 else
9458 {
9459 wifi_associated_dev2_t* temp = NULL;
9460 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9461 *associated_dev_array = temp;
9462 if(temp == NULL)
9463 {
9464 printf("Error Statement. Insufficient memory \n");
9465 return RETURN_ERR;
9466 }
9467
9468 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9469 system(pipeCmd);
9470
9471 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9472 if(fp == NULL)
9473 {
9474 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9475 return RETURN_ERR;
9476 }
9477 fclose(fp);
9478
9479 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9480 fp = popen(pipeCmd, "r");
9481 if(fp)
9482 {
9483 for(count =0 ; count < wifi_count; count++)
9484 {
9485 fgets(str, MAX_BUF_SIZE, fp);
9486 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9487 {
9488 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9489 {
9490 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9491
9492 }
9493 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9494 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]);
9495 }
9496 temp[count].cli_AuthenticationState = 1; //TODO
9497 temp[count].cli_Active = 1; //TODO
9498 }
9499 pclose(fp);
9500 }
9501
9502 //Updating RSSI per client
9503 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9504 fp = popen(pipeCmd, "r");
9505 if(fp)
9506 {
9507 pclose(fp);
9508 }
9509 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9510 if(fp)
9511 {
9512 for(count =0 ; count < wifi_count ;count++)
9513 {
9514 fgets(str, MAX_BUF_SIZE, fp);
9515 signalstrength = atoi(str);
9516 temp[count].cli_RSSI = signalstrength;
9517 }
9518 pclose(fp);
9519 }
9520
9521
9522 //LastDataDownlinkRate
9523 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9524 fp = popen(pipeCmd, "r");
9525 if (fp)
9526 {
9527 pclose(fp);
9528 }
9529 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9530 if (fp)
9531 {
9532 for (count = 0; count < wifi_count; count++)
9533 {
9534 fgets(str, MAX_BUF_SIZE, fp);
9535 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9536 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9537 }
9538 pclose(fp);
9539 }
9540
9541 //LastDataUplinkRate
9542 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9543 fp = popen(pipeCmd, "r");
9544 if (fp)
9545 {
9546 pclose(fp);
9547 }
9548 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9549 if (fp)
9550 {
9551 for (count = 0; count < wifi_count; count++)
9552 {
9553 fgets(str, MAX_BUF_SIZE, fp);
9554 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9555 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9556 }
9557 pclose(fp);
9558 }
9559 }
9560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9561 return RETURN_OK;
9562
9563}
9564
9565INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9566{
9567#if 0
9568 /*char buf[1024] = {0};
9569 sprintf(cmd, "ifconfig %s ", interface_name);
9570 _syscmd(cmd, buf, sizeof(buf));*/
9571
9572 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9573 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9574 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9575 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9576
9577 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.
9578 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].
9579 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].
9580 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].
9581 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9582 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9583
9584 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9585 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9586 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9587 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.
9588 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.
9589 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.
9590 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.
9591 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.
9592 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.
9593 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.
9594 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9595#endif
9596
9597 FILE *fp = NULL;
9598 char interface_name[50] = {0};
9599 char pipeCmd[128] = {0};
9600 char str[256] = {0};
9601 wifi_ssidTrafficStats2_t *out = output_struct;
9602
9603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9604 if (!output_struct)
9605 return RETURN_ERR;
9606
9607 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9608 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9609 return RETURN_ERR;
9610 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9611
9612 fp = popen(pipeCmd, "r");
9613 if (fp == NULL) {
9614 fprintf(stderr, "%s: popen failed\n", __func__);
9615 return RETURN_ERR;
9616 }
9617 fgets(str, sizeof(str), fp);
9618 pclose(fp);
9619
9620 if (strlen(str) == 0) // interface not exist
9621 return RETURN_OK;
9622
9623 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9624 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9625
9626 memset(str, 0, sizeof(str));
9627 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9628 fp = popen(pipeCmd, "r");
9629 if (fp == NULL) {
9630 fprintf(stderr, "%s: popen failed\n", __func__);
9631 return RETURN_ERR;
9632 }
9633 fgets(str, sizeof(str), fp);
9634
9635 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9636 &out->ssid_BroadcastPacketsSent);
9637 pclose(fp);
9638
9639 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9640 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9641
9642 // Not supported
9643 output_struct->ssid_RetransCount = 0;
9644 output_struct->ssid_FailedRetransCount = 0;
9645 output_struct->ssid_RetryCount = 0;
9646 output_struct->ssid_MultipleRetryCount = 0;
9647 output_struct->ssid_ACKFailureCount = 0;
9648 output_struct->ssid_AggregatedPacketCount = 0;
9649
9650 return RETURN_OK;
9651}
9652
9653//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).
9654INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9655{
9656 char output_val[16]={'\0'};
9657 char config_file[MAX_BUF_SIZE] = {0};
9658
9659 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9660 if (!output)
9661 return RETURN_ERR;
9662 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9663 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9664
9665 if( strcmp(output_val,"1") == 0 )
9666 *output = TRUE;
9667 else
9668 *output = FALSE;
9669 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9670
9671 return RETURN_OK;
9672}
9673
9674INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9675{
9676 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9677 char str[MAX_BUF_SIZE]={'\0'};
9678 char string[MAX_BUF_SIZE]={'\0'};
9679 char cmd[MAX_CMD_SIZE]={'\0'};
9680 char *ch;
9681 char config_file[MAX_BUF_SIZE] = {0};
9682 struct params params;
9683
9684 if(enable == TRUE)
9685 strcpy(string,"1");
9686 else
9687 strcpy(string,"0");
9688
9689 params.name = "ap_isolate";
9690 params.value = string;
9691
9692 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9693 wifi_hostapdWrite(config_file,&params,1);
9694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9695
9696 return RETURN_OK;
9697}
9698
9699INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9700{
9701 if (NULL == output_dBm)
9702 return RETURN_ERR;
9703
9704 *output_dBm = 0;
9705 return RETURN_OK;
9706}
9707
9708INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9709{
9710 return RETURN_OK;
9711}
9712INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9713{
9714 return RETURN_OK;
9715}
9716INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9717{
9718 return RETURN_OK;
9719}
9720INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9721{
9722 return RETURN_OK;
9723}
9724INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9725{
9726 return RETURN_OK;
9727}
9728INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9729{
9730 char config_file[MAX_BUF_SIZE] = {0};
9731 struct params list;
9732
9733 list.name = "bss_transition";
9734 list.value = activate?"1":"0";
9735 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9736 wifi_hostapdWrite(config_file, &list, 1);
9737
9738 return RETURN_OK;
9739}
9740wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9741
9742void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9743{
9744 return;
9745}
9746
9747INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9748{
9749 // TODO Implement me!
9750 return RETURN_OK;
9751}
9752
9753INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9754{
9755 char file_name[128] = {0};
9756 char buf[128] = {0};
9757 FILE *f = NULL;
9758 int max_num_radios = 0;
9759
9760 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9761
9762 wifi_getMaxRadioNumber(&max_num_radios);
9763 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9764 for (int index = 0; index < max_num_radios; index++) {
9765 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9766 f = fopen(file_name, "w");
9767 if (f == NULL)
9768 return RETURN_ERR;
9769 // For mode == 0 is to disable filter, just don't write to the file.
9770 if (mode)
9771 fprintf(f, "%s", essid);
9772
9773 fclose(f);
9774 }
9775 } else { // special case, need to set AP's SSID as filter for each radio.
9776 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9777 f = fopen(file_name, "w");
9778 if (f == NULL)
9779 return RETURN_ERR;
9780
9781 // For mode == 0 is to disable filter, just don't write to the file.
9782 if (mode)
9783 fprintf(f, "%s", essid);
9784
9785 fclose(f);
9786 }
9787
9788 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9789 return RETURN_OK;
9790}
9791
9792INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9793{
9794 // TODO Implement me!
9795 //Apply wifi_pushRadioChannel() instantly
9796 return RETURN_ERR;
9797}
9798
9799INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9800{
9801 // TODO Implement me!
9802 return RETURN_OK;
9803}
9804
9805#ifdef HAL_NETLINK_IMPL
9806static int tidStats_callback(struct nl_msg *msg, void *arg) {
9807 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9808 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9809 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9810 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9811 int rem , tid_index = 0;
9812
9813 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9814 wifi_associated_dev_tid_entry_t *stats_entry;
9815
9816 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9817 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9818 };
9819 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9820 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9821 };
9822
9823 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9824 genlmsg_attrlen(gnlh, 0), NULL);
9825
9826
9827 if (!tb[NL80211_ATTR_STA_INFO]) {
9828 fprintf(stderr, "station stats missing!\n");
9829 return NL_SKIP;
9830 }
9831
9832 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9833 tb[NL80211_ATTR_STA_INFO],
9834 stats_policy)) {
9835 fprintf(stderr, "failed to parse nested attributes!\n");
9836 return NL_SKIP;
9837 }
9838
9839 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9840 {
9841 stats_entry = &out->tid_array[tid_index];
9842
9843 stats_entry->tid = tid_index;
9844 stats_entry->ac = _tid_ac_index_get[tid_index];
9845
9846 if(sinfo[NL80211_STA_INFO_TID_STATS])
9847 {
9848 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9849 printf("failed to parse nested stats attributes!");
9850 return NL_SKIP;
9851 }
9852 }
9853 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9854 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9855
9856 if(tid_index < (PS_MAX_TID - 1))
9857 tid_index++;
9858 }
9859 //ToDo: sum_time_ms, ewma_time_ms
9860 return NL_SKIP;
9861}
9862#endif
9863
9864INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9865{
9866#ifdef HAL_NETLINK_IMPL
9867 Netlink nl;
9868 char if_name[10];
9869 char interface_name[16] = {0};
9870
9871 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9872 return RETURN_ERR;
9873
9874 snprintf(if_name, sizeof(if_name), "%s", interface_name);
9875
9876 nl.id = initSock80211(&nl);
9877
9878 if (nl.id < 0) {
9879 fprintf(stderr, "Error initializing netlink \n");
9880 return -1;
9881 }
9882
9883 struct nl_msg* msg = nlmsg_alloc();
9884
9885 if (!msg) {
9886 fprintf(stderr, "Failed to allocate netlink message.\n");
9887 nlfree(&nl);
9888 return -2;
9889 }
9890
9891 genlmsg_put(msg,
9892 NL_AUTO_PORT,
9893 NL_AUTO_SEQ,
9894 nl.id,
9895 0,
9896 0,
9897 NL80211_CMD_GET_STATION,
9898 0);
9899
9900 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9901 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9902 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9903 nl_send_auto(nl.socket, msg);
9904 nl_recvmsgs(nl.socket, nl.cb);
9905 nlmsg_free(msg);
9906 nlfree(&nl);
9907 return RETURN_OK;
9908#else
9909//iw implementation
9910#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9911#define TOTAL_MAX_LINES 50
9912
9913 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9914 char if_name[32] = {0};
9915 FILE *fp=NULL;
9916 char pipeCmd[1024]= {'\0'};
9917 int lines,tid_index=0;
9918 char mac_addr[20] = {'\0'};
9919
9920 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9921 return RETURN_ERR;
9922
9923 wifi_associated_dev_tid_entry_t *stats_entry;
9924
9925 strcpy(mac_addr,clientMacAddress);
9926
9927 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9928 fp= popen(pipeCmd,"r");
9929 if(fp == NULL)
9930 {
9931 perror("popen for station dump failed\n");
9932 return RETURN_ERR;
9933 }
9934 pclose(fp);
9935
9936 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9937 fp=popen(pipeCmd,"r");
9938 if(fp == NULL)
9939 {
9940 perror("popen for grep station failed\n");
9941 return RETURN_ERR;
9942 }
9943 else if(fgets(buf,sizeof(buf),fp) != NULL)
9944 lines=atoi(buf);
9945 else
9946 {
9947 pclose(fp);
9948 fprintf(stderr,"No devices are connected \n");
9949 return RETURN_ERR;
9950 }
9951 pclose(fp);
9952
9953 if(lines == 1)
9954 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9955
9956 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9957 {
9958 stats_entry = &tid_stats->tid_array[tid_index];
9959 stats_entry->tid = tid_index;
9960
9961 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);
9962
9963 fp=popen(pipeCmd,"r");
9964 if(fp ==NULL)
9965 {
9966 perror("Failed to read from tid file \n");
9967 return RETURN_ERR;
9968 }
9969 else if(fgets(buf,sizeof(buf),fp) != NULL)
9970 stats_entry->num_msdus = atol(buf);
9971
9972 pclose(fp);
9973 stats_entry->ac = _tid_ac_index_get[tid_index];
9974// TODO:
9975// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9976// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9977 }
9978 return RETURN_OK;
9979#endif
9980}
9981
9982
9983INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9984{
9985 char interface_name[16] = {0};
9986 char cmd[128]={0};
9987 char buf[128]={0};
9988 int freq = 0;
9989
9990 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9991
9992 // full mode is used to scan all channels.
9993 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9994 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9995 ieee80211_channel_to_frequency(chan_list[0], &freq);
9996
9997 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9998 return RETURN_ERR;
9999
10000 if (freq)
10001 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10002 else
10003 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10004
10005 _syscmd(cmd, buf, sizeof(buf));
10006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10007
10008 return RETURN_OK;
10009}
10010
10011
10012INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10013{
10014 // TODO Implement me!
10015 return RETURN_ERR;
10016}
10017
10018INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10019{
10020 // TODO Implement me!
10021 return RETURN_ERR;
10022}
10023
10024INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10025{
10026 // TODO Implement me!
10027 return RETURN_ERR;
10028}
10029
10030INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10031{
10032 // TODO Implement me!
10033 return RETURN_ERR;
10034}
10035
10036INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10037{
10038 // TODO Implement me!
10039 return RETURN_ERR;
10040}
10041
10042INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10043{
10044 // TODO Implement me!
10045 return RETURN_ERR;
10046}
10047
10048INT wifi_steering_eventUnregister(void)
10049{
10050 // TODO Implement me!
10051 return RETURN_ERR;
10052}
10053
10054INT wifi_delApAclDevices(INT apIndex)
10055{
developer7e4a2a62023-04-06 19:56:03 +080010056 char cmd[MAX_CMD_SIZE] = {0};
10057 char buf[MAX_BUF_SIZE] = {0};
10058 char inf_name[IF_NAME_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080010059
developer7e4a2a62023-04-06 19:56:03 +080010060 if (wifi_GetInterfaceName(apIndex, inf_name) != RETURN_OK)
10061 return RETURN_ERR;
developer72fb0bb2023-01-11 09:46:29 +080010062
developer7e4a2a62023-04-06 19:56:03 +080010063 /* mwctl acl clear all stas */
10064 snprintf(cmd, sizeof(cmd), "mwctl %s acl clear_all", inf_name);
10065 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080010066
10067 return RETURN_OK;
10068}
10069
10070#ifdef HAL_NETLINK_IMPL
10071static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10072 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10073 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10074 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10075 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10076 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10077 char mac_addr[20],dev[20];
10078
10079 nla_parse(tb,
10080 NL80211_ATTR_MAX,
10081 genlmsg_attrdata(gnlh, 0),
10082 genlmsg_attrlen(gnlh, 0),
10083 NULL);
10084
10085 if(!tb[NL80211_ATTR_STA_INFO]) {
10086 fprintf(stderr, "sta stats missing!\n");
10087 return NL_SKIP;
10088 }
10089
10090 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10091 fprintf(stderr, "failed to parse nested attributes!\n");
10092 return NL_SKIP;
10093 }
10094 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10095
10096 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10097
10098 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10099 fprintf(stderr, "failed to parse nested rate attributes!");
10100 return NL_SKIP;
10101 }
10102
10103 if(sinfo[NL80211_STA_INFO_TID_STATS])
10104 {
10105 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10106 printf("failed to parse nested stats attributes!");
10107 return NL_SKIP;
10108 }
10109 }
10110
10111 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10112 {
10113 printf("Type is VHT\n");
10114 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10115 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10116
10117 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10118 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10119 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10120 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10121 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10122 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10123 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10124 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10125 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10126 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10127 }
10128 else
10129 {
10130 printf(" OFDM or CCK \n");
10131 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10132 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10133 }
10134
10135 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10136 if(rinfo[NL80211_RATE_INFO_MCS])
10137 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10138 }
10139 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10140 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10141 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10142 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10143
10144 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10145 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10146
10147 if (sinfo[NL80211_STA_INFO_SIGNAL])
10148 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10149 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10150 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10151 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10152 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10153 //rssi_array need to be filled
10154 return NL_SKIP;
10155}
10156#endif
10157
10158INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10159{
10160#ifdef HAL_NETLINK_IMPL
10161 Netlink nl;
10162 char if_name[32];
10163 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10164 return RETURN_ERR;
10165
10166 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10167
10168 if (*output_array_size <= 0)
10169 return RETURN_OK;
10170
10171 nl.id = initSock80211(&nl);
10172
10173 if (nl.id < 0) {
10174 fprintf(stderr, "Error initializing netlink \n");
10175 return 0;
10176 }
10177
10178 struct nl_msg* msg = nlmsg_alloc();
10179
10180 if (!msg) {
10181 fprintf(stderr, "Failed to allocate netlink message.\n");
10182 nlfree(&nl);
10183 return 0;
10184 }
10185
10186 genlmsg_put(msg,
10187 NL_AUTO_PORT,
10188 NL_AUTO_SEQ,
10189 nl.id,
10190 0,
10191 0,
10192 NL80211_CMD_GET_STATION,
10193 0);
10194
10195 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10196 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10197 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10198 nl_send_auto(nl.socket, msg);
10199 nl_recvmsgs(nl.socket, nl.cb);
10200 nlmsg_free(msg);
10201 nlfree(&nl);
10202 return RETURN_OK;
10203#else
10204 //TODO Implement me
10205 return RETURN_OK;
10206#endif
10207}
10208
10209#ifdef HAL_NETLINK_IMPL
10210static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10211 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10212 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10213 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10214 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10215 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10216 char mac_addr[20],dev[20];
10217
10218 nla_parse(tb,
10219 NL80211_ATTR_MAX,
10220 genlmsg_attrdata(gnlh, 0),
10221 genlmsg_attrlen(gnlh, 0),
10222 NULL);
10223
10224 if(!tb[NL80211_ATTR_STA_INFO]) {
10225 fprintf(stderr, "sta stats missing!\n");
10226 return NL_SKIP;
10227 }
10228
10229 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10230 fprintf(stderr, "failed to parse nested attributes!\n");
10231 return NL_SKIP;
10232 }
10233
10234 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10235
10236 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10237
10238 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10239 fprintf(stderr, "failed to parse nested rate attributes!");
10240 return NL_SKIP;
10241 }
10242
10243 if(sinfo[NL80211_STA_INFO_TID_STATS])
10244 {
10245 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10246 printf("failed to parse nested stats attributes!");
10247 return NL_SKIP;
10248 }
10249 }
10250 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10251 {
10252 printf("Type is VHT\n");
10253 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10254 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10255
10256 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10257 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10258 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10259 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10260 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10261 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10262 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10263 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10264 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10265 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10266 }
10267 else
10268 {
10269 printf(" OFDM or CCK \n");
10270 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10271 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10272 }
10273
10274 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10275 if(rinfo[NL80211_RATE_INFO_MCS])
10276 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10277 }
10278
10279 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10280 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10281 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10282 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10283
10284 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10286 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10287
10288 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10289 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10290
10291 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10292 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10293
10294 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10295 ((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]);
10296
10297 return NL_SKIP;
10298}
10299#endif
10300
10301INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10302{
10303#ifdef HAL_NETLINK_IMPL
10304 Netlink nl;
10305 char if_name[10];
10306 char interface_name[16] = {0};
10307 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10308 return RETURN_ERR;
10309
10310 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10311
10312 if (*output_array_size <= 0)
10313 return RETURN_OK;
10314
10315 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10316
10317 nl.id = initSock80211(&nl);
10318
10319 if(nl.id < 0) {
10320 fprintf(stderr, "Error initializing netlink \n");
10321 return 0;
10322 }
10323
10324 struct nl_msg* msg = nlmsg_alloc();
10325
10326 if(!msg) {
10327 fprintf(stderr, "Failed to allocate netlink message.\n");
10328 nlfree(&nl);
10329 return 0;
10330 }
10331
10332 genlmsg_put(msg,
10333 NL_AUTO_PORT,
10334 NL_AUTO_SEQ,
10335 nl.id,
10336 0,
10337 0,
10338 NL80211_CMD_GET_STATION,
10339 0);
10340
10341 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10342 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10343 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10344 nl_send_auto(nl.socket, msg);
10345 nl_recvmsgs(nl.socket, nl.cb);
10346 nlmsg_free(msg);
10347 nlfree(&nl);
10348 return RETURN_OK;
10349#else
10350 //TODO Implement me
10351 return RETURN_OK;
10352#endif
10353}
10354
10355INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10356{
10357 // TODO Implement me!
10358 char buf[MAX_BUF_SIZE] = {0};
10359 char config_file[MAX_BUF_SIZE] = {0};
10360
10361 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10362 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10363 *activate = (strncmp("1",buf,1) == 0);
10364
10365 return RETURN_OK;
10366}
10367
10368INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10369{
10370 char config_file[MAX_BUF_SIZE] = {0};
10371 struct params list;
10372
10373 list.name = "rrm_neighbor_report";
10374 list.value = activate?"1":"0";
10375 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10376 wifi_hostapdWrite(config_file, &list, 1);
10377
10378 return RETURN_OK;
10379}
10380
10381INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10382{
10383 char buf[32] = {0};
10384 char config_file[MAX_BUF_SIZE] = {0};
10385
10386 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10387 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10388 *activate = (strncmp("1",buf,1) == 0);
10389
10390 return RETURN_OK;
10391}
10392#undef HAL_NETLINK_IMPL
10393#ifdef HAL_NETLINK_IMPL
10394static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10395 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10396 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10397 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10398 char dev[20];
10399 int freq =0 ;
10400 static int i=0;
10401
10402 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10403
10404 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10405 };
10406
10407 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10408
10409 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10410
10411 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10412 fprintf(stderr, "survey data missing!\n");
10413 return NL_SKIP;
10414 }
10415
10416 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10417 {
10418 fprintf(stderr, "failed to parse nested attributes!\n");
10419 return NL_SKIP;
10420 }
10421
10422
10423 if(out[0].array_size == 1 )
10424 {
10425 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10426 {
10427 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10428 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10429 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10430
10431 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10432 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10433 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10434 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10435 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10436 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10437 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10438 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10439 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10440 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10441 if (sinfo[NL80211_SURVEY_INFO_TIME])
10442 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10443 return NL_STOP;
10444 }
10445 }
10446 else
10447 {
10448 if ( i <= out[0].array_size )
10449 {
10450 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10451 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10452 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10453
10454 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10455 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10456 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10457 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10458 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10459 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10460 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10461 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10462 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10463 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10464 if (sinfo[NL80211_SURVEY_INFO_TIME])
10465 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10466 }
10467 }
10468
10469 i++;
10470 return NL_SKIP;
10471}
10472#endif
10473
10474static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10475{
10476 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10477 FILE *fp;
10478
10479 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10480 {
10481 printf("Creating Frequency-Channel Map\n");
10482 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10483 }
10484 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10485 if((fp = popen(command, "r")))
10486 {
10487 fgets(output, sizeof(output), fp);
10488 *freqMHz = atoi(output);
10489 pclose(fp);
10490 }
10491
10492 return 0;
10493}
10494
10495static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10496{
10497 int freqMHz = -1;
10498 char cmd[MAX_CMD_SIZE] = {'\0'};
10499 char interface_name[16] = {0};
10500
10501 ieee80211_channel_to_frequency(channel, &freqMHz);
10502 if (freqMHz == -1) {
10503 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10504 return -1;
10505 }
10506
10507 wifi_GetInterfaceName(radioIndex, interface_name);
10508 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10509 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10510 radioIndex, freqMHz);
10511 return -1;
10512 }
10513
10514 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10515 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10516 return -1;
10517 }
10518
10519 return 0;
10520}
10521
10522static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10523{
10524 const char *ptr = buf;
10525 char *key = NULL;
10526 char *val = NULL;
10527 char line[256] = { '\0' };
10528
10529 while (ptr = get_line_from_str_buf(ptr, line)) {
10530 if (strstr(line, "Frequency")) continue;
10531
10532 key = strtok(line, ":");
10533 val = strtok(NULL, " ");
10534 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10535
10536 if (!strcmp(key, "noise")) {
10537 sscanf(val, "%d", &stats->ch_noise);
10538 if (stats->ch_noise == 0) {
10539 // Workaround for missing noise information.
10540 // Assume -95 for 2.4G and -103 for 5G
10541 if (radioIndex == 0) stats->ch_noise = -95;
10542 if (radioIndex == 1) stats->ch_noise = -103;
10543 }
10544 }
10545 else if (!strcmp(key, "channel active time")) {
10546 sscanf(val, "%llu", &stats->ch_utilization_total);
10547 }
10548 else if (!strcmp(key, "channel busy time")) {
10549 sscanf(val, "%llu", &stats->ch_utilization_busy);
10550 }
10551 else if (!strcmp(key, "channel receive time")) {
10552 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10553 }
10554 else if (!strcmp(key, "channel transmit time")) {
10555 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10556 }
10557 };
10558
10559 return 0;
10560}
10561
10562INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10563{
10564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10565#ifdef HAL_NETLINK_IMPL
10566 Netlink nl;
10567 wifi_channelStats_t_loc local[array_size];
10568 char if_name[32];
10569
10570 local[0].array_size = array_size;
10571
10572 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10573 return RETURN_ERR;
10574
10575 nl.id = initSock80211(&nl);
10576
10577 if (nl.id < 0) {
10578 fprintf(stderr, "Error initializing netlink \n");
10579 return -1;
10580 }
10581
10582 struct nl_msg* msg = nlmsg_alloc();
10583
10584 if (!msg) {
10585 fprintf(stderr, "Failed to allocate netlink message.\n");
10586 nlfree(&nl);
10587 return -2;
10588 }
10589
10590 genlmsg_put(msg,
10591 NL_AUTO_PORT,
10592 NL_AUTO_SEQ,
10593 nl.id,
10594 0,
10595 NLM_F_DUMP,
10596 NL80211_CMD_GET_SURVEY,
10597 0);
10598
10599 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10600 nl_send_auto(nl.socket, msg);
10601 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10602 nl_recvmsgs(nl.socket, nl.cb);
10603 nlmsg_free(msg);
10604 nlfree(&nl);
10605 //Copying the Values
10606 for(int i=0;i<array_size;i++)
10607 {
10608 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10609 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10610 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10611 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10612 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10613 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10614 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10615 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10616 }
10617#else
10618 ULONG channel = 0;
10619 int i;
10620 int number_of_channels = array_size;
10621 char buf[512];
10622 INT ret;
10623 wifi_channelStats_t tmp_stats;
10624
10625 if (number_of_channels == 0) {
10626 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10627 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10628 return RETURN_ERR;
10629 }
10630 number_of_channels = 1;
10631 input_output_channelStats_array[0].ch_number = channel;
10632 }
10633
10634 for (i = 0; i < number_of_channels; i++) {
10635
10636 input_output_channelStats_array[i].ch_noise = 0;
10637 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10638 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10639 input_output_channelStats_array[i].ch_utilization_busy = 0;
10640 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10641 input_output_channelStats_array[i].ch_utilization_total = 0;
10642
10643 memset(buf, 0, sizeof(buf));
10644 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10645 return RETURN_ERR;
10646 }
10647 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10648 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10649 return RETURN_ERR;
10650 }
10651
10652 // XXX: fake missing 'self' counter which is not available in iw survey output
10653 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10654 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10655
10656 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10657 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10658 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10659 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10660 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10661
10662 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",
10663 __func__,
10664 input_output_channelStats_array[i].ch_number,
10665 input_output_channelStats_array[i].ch_noise,
10666 input_output_channelStats_array[i].ch_utilization_total,
10667 input_output_channelStats_array[i].ch_utilization_busy,
10668 input_output_channelStats_array[i].ch_utilization_busy_rx,
10669 input_output_channelStats_array[i].ch_utilization_busy_tx,
10670 input_output_channelStats_array[i].ch_utilization_busy_self,
10671 input_output_channelStats_array[i].ch_utilization_busy_ext);
10672 }
10673#endif
10674 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10675 return RETURN_OK;
10676}
10677#define HAL_NETLINK_IMPL
10678
10679/* Hostapd events */
10680
10681#ifndef container_of
10682#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10683#define container_of(ptr, type, member) \
10684 ((type *)((char *)ptr - offset_of(type, member)))
10685#endif /* container_of */
10686
10687struct ctrl {
10688 char sockpath[128];
10689 char sockdir[128];
10690 char bss[IFNAMSIZ];
10691 char reply[4096];
10692 int ssid_index;
10693 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10694 void (*overrun)(struct ctrl *ctrl);
10695 struct wpa_ctrl *wpa;
10696 unsigned int ovfl;
10697 size_t reply_len;
10698 int initialized;
10699 ev_timer retry;
10700 ev_timer watchdog;
10701 ev_stat stat;
10702 ev_io io;
10703};
10704static wifi_newApAssociatedDevice_callback clients_connect_cb;
10705static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10706static struct ctrl wpa_ctrl[MAX_APS];
10707static int initialized;
10708
10709static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10710{
10711 char cbuf[256] = {};
10712 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10713 struct cmsghdr *cmsg;
10714 unsigned int ovfl = ctrl->ovfl;
10715 unsigned int drop;
10716
10717 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10718 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10719 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10720 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10721
10722 drop = ovfl - ctrl->ovfl;
10723 ctrl->ovfl = ovfl;
10724
10725 return drop;
10726}
10727
10728static void ctrl_close(struct ctrl *ctrl)
10729{
10730 if (ctrl->io.cb)
10731 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10732 if (ctrl->retry.cb)
10733 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10734 if (!ctrl->wpa)
10735 return;
10736
10737 wpa_ctrl_detach(ctrl->wpa);
10738 wpa_ctrl_close(ctrl->wpa);
10739 ctrl->wpa = NULL;
10740 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10741}
10742
10743static void ctrl_process(struct ctrl *ctrl)
10744{
10745 const char *str;
10746 int drops;
10747 int level;
10748 int err;
10749
10750 /* Example events:
10751 *
10752 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10753 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10754 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10755 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10756 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10757 */
10758 if (!(str = index(ctrl->reply, '>')))
10759 return;
10760 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10761 return;
10762
10763 str++;
10764
10765 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10766 if (!(str = index(ctrl->reply, ' ')))
10767 return;
10768 wifi_associated_dev_t sta;
10769 memset(&sta, 0, sizeof(sta));
10770
10771 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10772 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10773 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10774
10775 sta.cli_Active=true;
10776
10777 (clients_connect_cb)(ctrl->ssid_index, &sta);
10778 goto handled;
10779 }
10780
10781 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10782 if (!(str = index(ctrl->reply, ' ')))
10783 return;
10784
10785 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10786 goto handled;
10787 }
10788
10789 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10790 printf("CTRL_WPA: handle TERMINATING event\n");
10791 goto retry;
10792 }
10793
10794 if (strncmp("AP-DISABLED", str, 11) == 0) {
10795 printf("CTRL_WPA: handle AP-DISABLED\n");
10796 goto retry;
10797 }
10798
10799 printf("Event not supported!!\n");
10800
10801handled:
10802
10803 if ((drops = ctrl_get_drops(ctrl))) {
10804 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10805 if (ctrl->overrun)
10806 ctrl->overrun(ctrl);
10807 }
10808
10809 return;
10810
10811retry:
10812 printf("WPA_CTRL: closing\n");
10813 ctrl_close(ctrl);
10814 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10815 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10816}
10817
10818static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10819{
10820 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10821 int err;
10822
10823 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10824 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10825 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10826 ctrl->reply[ctrl->reply_len] = 0;
10827 if (err < 0) {
10828 if (errno == EAGAIN || errno == EWOULDBLOCK)
10829 return;
10830 ctrl_close(ctrl);
10831 ev_timer_again(EV_A_ &ctrl->retry);
10832 return;
10833 }
10834
10835 ctrl_process(ctrl);
10836}
10837
10838static int ctrl_open(struct ctrl *ctrl)
10839{
10840 int fd;
10841
10842 if (ctrl->wpa)
10843 return 0;
10844
10845 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10846 if (!ctrl->wpa)
10847 goto err;
10848
10849 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10850 goto err_close;
10851
10852 fd = wpa_ctrl_get_fd(ctrl->wpa);
10853 if (fd < 0)
10854 goto err_detach;
10855
10856 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10857 goto err_detach;
10858
10859 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10860 ev_io_start(EV_DEFAULT_ &ctrl->io);
10861
10862 return 0;
10863
10864err_detach:
10865 wpa_ctrl_detach(ctrl->wpa);
10866err_close:
10867 wpa_ctrl_close(ctrl->wpa);
10868err:
10869 ctrl->wpa = NULL;
10870 return -1;
10871}
10872
10873static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10874{
10875 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10876
10877 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10878 ctrl_open(ctrl);
10879}
10880
10881static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10882{
10883 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10884
10885 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10886 if (ctrl_open(ctrl) == 0) {
10887 printf("WPA_CTRL: retry successful\n");
10888 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10889 }
10890}
10891
10892int ctrl_enable(struct ctrl *ctrl)
10893{
10894 if (ctrl->wpa)
10895 return 0;
10896
10897 if (!ctrl->stat.cb) {
10898 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10899 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10900 }
10901
10902 if (!ctrl->retry.cb) {
10903 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10904 }
10905
10906 return ctrl_open(ctrl);
10907}
10908
10909static void
10910ctrl_msg_cb(char *buf, size_t len)
10911{
10912 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10913
10914 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10915 ctrl_process(ctrl);
10916}
10917
10918static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10919{
10920 int err;
10921
10922 if (!ctrl->wpa)
10923 return -1;
10924 if (*reply_len < 2)
10925 return -1;
10926
10927 (*reply_len)--;
10928 ctrl->reply_len = sizeof(ctrl->reply);
10929 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10930 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10931 if (err < 0)
10932 return err;
10933
10934 if (ctrl->reply_len > *reply_len)
10935 ctrl->reply_len = *reply_len;
10936
10937 *reply_len = ctrl->reply_len;
10938 memcpy(reply, ctrl->reply, *reply_len);
10939 reply[*reply_len - 1] = 0;
10940 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10941 return 0;
10942}
10943
10944static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10945{
10946 const char *pong = "PONG";
10947 const char *ping = "PING";
10948 char reply[1024];
10949 size_t len = sizeof(reply);
10950 int err;
10951 ULONG s, snum;
10952 INT ret;
10953 BOOL status;
10954
10955 printf("WPA_CTRL: watchdog cb\n");
10956
10957 ret = wifi_getSSIDNumberOfEntries(&snum);
10958 if (ret != RETURN_OK) {
10959 printf("%s: failed to get SSID count", __func__);
10960 return;
10961 }
10962
10963 if (snum > MAX_APS) {
10964 printf("more ssid than supported! %lu\n", snum);
10965 return;
10966 }
10967
10968 for (s = 0; s < snum; s++) {
10969 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10970 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
10971 continue;
10972 }
10973 if (status == false) continue;
10974
10975 memset(reply, 0, sizeof(reply));
10976 len = sizeof(reply);
10977 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10978 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10979 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10980 continue;
10981
10982 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10983 ctrl_close(&wpa_ctrl[s]);
10984 printf("WPA_CTRL: ev_timer_again %lu\n", s);
10985 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10986 }
10987}
10988
10989static int init_wpa()
10990{
10991 int ret = 0, i = 0;
10992 ULONG s, snum;
10993
10994 ret = wifi_getSSIDNumberOfEntries(&snum);
10995 if (ret != RETURN_OK) {
10996 printf("%s: failed to get SSID count", __func__);
10997 return RETURN_ERR;
10998 }
10999
11000 if (snum > MAX_APS) {
11001 printf("more ssid than supported! %lu\n", snum);
11002 return RETURN_ERR;
11003 }
11004
11005 for (s = 0; s < snum; s++) {
11006 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11007 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11008 wpa_ctrl[s].ssid_index = s;
11009 ctrl_enable(&wpa_ctrl[s]);
11010 }
11011
11012 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11013 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11014
11015 initialized = 1;
11016 printf("WPA_CTRL: initialized\n");
11017
11018 return RETURN_OK;
11019}
11020
11021void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11022{
11023 clients_connect_cb = callback_proc;
11024 if (!initialized)
11025 init_wpa();
11026}
11027
11028void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11029{
11030 clients_disconnect_cb = callback_proc;
11031 if (!initialized)
11032 init_wpa();
11033}
11034
11035INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11036{
11037 // TODO Implement me!
11038 return RETURN_ERR;
11039}
11040
11041INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11042{
11043 // TODO Implement me!
11044 return RETURN_ERR;
11045}
11046
11047INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11048{
11049 int i;
11050 char cmd[256];
11051 char channel_numbers_buf[256];
11052 char dfs_state_buf[256];
11053 char line[256];
11054 const char *ptr;
11055
11056 memset(cmd, 0, sizeof(cmd));
11057 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
11058 memset(line, 0, sizeof(line));
11059 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11060 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
11061
11062 if (radioIndex == 0) { // 2.4G - all allowed
11063 if (outputMapSize < 11) {
11064 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
11065 return RETURN_ERR;
11066 }
11067
11068 for (i = 0; i < 11; i++) {
11069 outputMap[i].ch_number = i + 1;
11070 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11071 }
11072
11073 return RETURN_OK;
11074 }
11075
11076 if (radioIndex == 1) { // 5G
11077// Example output of iw list:
11078//
11079// Frequencies:
11080// * 5180 MHz [36] (17.0 dBm)
11081// * 5200 MHz [40] (17.0 dBm)
11082// * 5220 MHz [44] (17.0 dBm)
11083// * 5240 MHz [48] (17.0 dBm)
11084// * 5260 MHz [52] (23.0 dBm) (radar detection)
11085// DFS state: usable (for 78930 sec)
11086// DFS CAC time: 60000 ms
11087// * 5280 MHz [56] (23.0 dBm) (radar detection)
11088// DFS state: usable (for 78930 sec)
11089// DFS CAC time: 60000 ms
11090// * 5300 MHz [60] (23.0 dBm) (radar detection)
11091// DFS state: usable (for 78930 sec)
11092// DFS CAC time: 60000 ms
11093// * 5320 MHz [64] (23.0 dBm) (radar detection)
11094// DFS state: usable (for 78930 sec)
11095// DFS CAC time: 60000 ms
11096// * 5500 MHz [100] (disabled)
11097// * 5520 MHz [104] (disabled)
11098// * 5540 MHz [108] (disabled)
11099// * 5560 MHz [112] (disabled)
11100//
11101// Below command should fetch channel numbers of each enabled channel in 5GHz band:
11102 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
11103 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
11104 return RETURN_ERR;
11105 }
11106
11107 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11108 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11109 return RETURN_ERR;
11110 }
11111
11112 ptr = channel_numbers_buf;
11113 i = 0;
11114 while (ptr = get_line_from_str_buf(ptr, line)) {
11115 if (i >= outputMapSize) {
11116 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11117 return RETURN_ERR;
11118 }
11119 sscanf(line, "%d", &outputMap[i].ch_number);
11120
11121 memset(cmd, 0, sizeof(cmd));
11122 // Below command should fetch string for DFS state (usable, available or unavailable)
11123 // Example line: "DFS state: usable (for 78930 sec)"
11124 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) {
11125 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
11126 return RETURN_ERR;
11127 }
11128
11129 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11130 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
11131 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11132 return RETURN_ERR;
11133 }
11134
11135 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
11136
11137 if (!strcmp(dfs_state_buf, "usable")) {
11138 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11139 } else if (!strcmp(dfs_state_buf, "available")) {
11140 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11141 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11142 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11143 } else {
11144 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11145 }
11146 i++;
11147 }
11148
11149 return RETURN_OK;
11150 }
11151
11152 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11153 return RETURN_ERR;
11154}
11155
11156INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11157{
11158 // TODO Implement me!
11159 return RETURN_ERR;
11160}
11161
11162INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11163{
11164 return RETURN_OK;
11165}
11166
11167INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11168{
11169 // TODO Implement me!
11170 return RETURN_ERR;
11171}
11172
11173INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11174{
11175 // TODO API refrence Implementaion is present on RPI hal
11176 return RETURN_ERR;
11177}
11178
11179INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11180{
11181 char interface_name[16] = {0};
11182 char cmd[128]={'\0'};
11183 char buf[128]={'\0'};
11184 char *support;
11185 int maximum_tx = 0, current_tx = 0;
11186
11187 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11188 if(txpwr_pcntg == NULL)
11189 return RETURN_ERR;
11190
11191 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11192 return RETURN_ERR;
11193
11194 // Get the maximum tx power of the device
11195 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11196 _syscmd(cmd, buf, sizeof(buf));
11197 maximum_tx = strtol(buf, NULL, 10);
11198
11199 // Get the current tx power
11200 memset(cmd, 0, sizeof(cmd));
11201 memset(buf, 0, sizeof(buf));
11202 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11203 _syscmd(cmd, buf, sizeof(buf));
11204 current_tx = strtol(buf, NULL, 10);
11205
11206 // Get the power supported list and find the current power percentage in supported list
11207 memset(buf, 0, sizeof(buf));
11208 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11209 support = strtok(buf, ",");
11210 while(true)
11211 {
11212 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11213 *txpwr_pcntg = 100;
11214 wifi_dbg_printf("current power is not in supported list\n");
11215 return RETURN_OK;
11216 }
11217 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11218 if (tmp == current_tx) {
11219 *txpwr_pcntg = strtol(support, NULL, 10);
11220 break;
11221 }
11222 support = strtok(NULL, ",");
11223 }
11224 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11225 return RETURN_OK;
11226}
11227
11228INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11229{
11230 // TODO precac feature.
11231 struct params params = {0};
11232 char config_file[128] = {0};
11233
11234 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11235
11236 params.name = "enable_background_radar";
11237 params.value = enable?"1":"0";
11238 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11239 wifi_hostapdWrite(config_file, &params, 1);
11240 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11241
11242 /* TODO precac feature */
11243
11244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11245 return RETURN_OK;
11246}
11247
11248INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11249{
11250 char config_file[128] = {0};
11251 char buf[64] = {0};
11252
11253 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11254 if (NULL == enable || NULL == precac)
11255 return RETURN_ERR;
11256
11257 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11258 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11259 if (strncmp(enable, "1", 1) == 0)
11260 *enable = true;
11261 else
11262 *enable = false;
11263
11264 /* TODO precac feature */
11265
11266 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11267 return RETURN_OK;
11268}
11269
11270INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11271{
11272 *supported = TRUE;
11273 return RETURN_OK;
11274}
11275
11276INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11277{
11278 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11279 struct params params = {0};
11280 char config_file[64] = {0};
11281 char buf[64] = {0};
11282 unsigned int set_mu_type = 0;
11283 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11284
11285 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11286 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11287
11288 if (strlen(buf) > 0)
11289 set_mu_type = strtol(buf, NULL, 10);
11290
11291 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11292 set_mu_type &= ~0x05; // unset bit 0, 2
11293 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11294 set_mu_type |= 0x01;
11295 set_mu_type &= ~0x04;
11296 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11297 set_mu_type &= ~0x01;
11298 set_mu_type |= 0x04;
11299 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11300 set_mu_type |= 0x05; // set bit 0, 2
11301 }
11302
11303 params.name = "hemu_onoff";
11304 sprintf(buf, "%u", set_mu_type);
11305 params.value = buf;
11306 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11307 wifi_hostapdWrite(config_file, &params, 1);
11308 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11309
11310 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11311 return RETURN_OK;
11312}
11313
11314INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11315{
11316 struct params params={0};
11317 char config_file[64] = {0};
11318 char buf[64] = {0};
11319 unsigned int get_mu_type = 0;
11320
11321 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11322
11323 if (mu_type == NULL)
11324 return RETURN_ERR;
11325
11326 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11327 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11328 get_mu_type = strtol(buf, NULL, 10);
11329
11330 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11331 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11332 else if (get_mu_type & 0x04)
11333 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11334 else if (get_mu_type & 0x01)
11335 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11336 else
11337 *mu_type = WIFI_DL_MU_TYPE_NONE;
11338
11339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11340 return RETURN_OK;
11341}
11342
11343INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11344{
11345 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11346 struct params params={0};
11347 char config_file[64] = {0};
11348 char buf[64] = {0};
11349 unsigned int set_mu_type = 0;
11350 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11351
11352 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11353 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11354
11355 if (strlen(buf) > 0)
11356 set_mu_type = strtol(buf, NULL, 10);
11357
11358 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11359 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11360 set_mu_type &= ~0x0a;
11361 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11362 set_mu_type |= 0x02;
11363 set_mu_type &= ~0x08;
11364 }
11365
11366 params.name = "hemu_onoff";
11367 sprintf(buf, "%u", set_mu_type);
11368 params.value = buf;
11369 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11370 wifi_hostapdWrite(config_file, &params, 1);
11371 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11372
11373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11374 return RETURN_OK;
11375}
11376
11377INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11378{
11379 struct params params={0};
11380 char config_file[64] = {0};
11381 char buf[64] = {0};
11382 unsigned int get_mu_type = 0;
11383
11384 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11385
11386 if (mu_type == NULL)
11387 return RETURN_ERR;
11388
11389 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11390 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11391
11392 get_mu_type = strtol(buf, NULL, 10);
11393 if (get_mu_type & 0x02)
11394 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11395 else
11396 *mu_type = WIFI_DL_MU_TYPE_NONE;
11397
11398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11399 return RETURN_OK;
11400}
11401
11402
11403INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11404{
11405 char cmd[128] = {0};
11406 char buf[256] = {0};
11407 char config_file[64] = {0};
11408 char GI[8] = {0};
11409 int mode_map = 0;
11410 FILE *f = NULL;
11411 wifi_band band = band_invalid;
11412
11413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11414
11415 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11416 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11417 return RETURN_ERR;
11418 }
11419
11420 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11421 band = wifi_index_to_band(radio_index);
11422
11423 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11424 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11425 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11426 _syscmd(cmd, buf, sizeof(buf));
11427 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11428 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11429 if (strstr(buf, "[SHORT-GI-") == NULL) {
11430 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11431 _syscmd(cmd, buf, sizeof(buf));
11432 }
11433 if (band == band_5) {
11434 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11435 if (strstr(buf, "[SHORT-GI-") == NULL) {
11436 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11437 _syscmd(cmd, buf, sizeof(buf));
11438 }
11439 }
11440 }
11441 wifi_reloadAp(radio_index);
11442
11443 if (guard_interval == wifi_guard_interval_400)
11444 strcpy(GI, "0.4");
11445 else if (guard_interval == wifi_guard_interval_800)
11446 strcpy(GI, "0.8");
11447 else if (guard_interval == wifi_guard_interval_1600)
11448 strcpy(GI, "1.6");
11449 else if (guard_interval == wifi_guard_interval_3200)
11450 strcpy(GI, "3.2");
11451 else if (guard_interval == wifi_guard_interval_auto)
11452 strcpy(GI, "auto");
11453 // Record GI for get GI function
11454 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11455 f = fopen(buf, "w");
11456 if (f == NULL)
11457 return RETURN_ERR;
11458 fprintf(f, "%s", GI);
11459 fclose(f);
11460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11461 return RETURN_OK;
11462}
11463
11464INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11465{
11466 char buf[32] = {0};
11467 char cmd[64] = {0};
11468
11469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11470
11471 if (guard_interval == NULL)
11472 return RETURN_ERR;
11473
11474 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11475 _syscmd(cmd, buf, sizeof(buf));
11476
11477 if (strncmp(buf, "0.4", 3) == 0)
11478 *guard_interval = wifi_guard_interval_400;
11479 else if (strncmp(buf, "0.8", 3) == 0)
11480 *guard_interval = wifi_guard_interval_800;
11481 else if (strncmp(buf, "1.6", 3) == 0)
11482 *guard_interval = wifi_guard_interval_1600;
11483 else if (strncmp(buf, "3.2", 3) == 0)
11484 *guard_interval = wifi_guard_interval_3200;
11485 else
11486 *guard_interval = wifi_guard_interval_auto;
11487
11488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11489 return RETURN_OK;
11490}
11491
11492INT wifi_setBSSColor(INT radio_index, UCHAR color)
11493{
11494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11495 struct params params = {0};
11496 char config_file[128] = {0};
11497 char bss_color[4] ={0};
11498
11499 params.name = "he_bss_color";
11500 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11501 params.value = bss_color;
11502 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11503 wifi_hostapdWrite(config_file, &params, 1);
11504 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer69b61b02023-03-07 17:17:44 +080011505
developer72fb0bb2023-01-11 09:46:29 +080011506 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11507 return RETURN_OK;
11508}
11509
11510INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11511{
11512 char config_file[128] = {0};
11513 char buf[64] = {0};
11514 char temp_output[128] = {'\0'};
11515
11516 wifi_dbg_printf("\nFunc=%s\n", __func__);
11517 if (NULL == color)
11518 return RETURN_ERR;
11519
11520 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11521 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11522
11523 if(strlen(buf) > 0) {
11524 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11525 } else {
11526 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11527 }
11528
11529 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11530 wifi_dbg_printf("\noutput_string=%s\n", color);
11531
11532 return RETURN_OK;
11533}
11534
11535/* multi-psk support */
11536INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11537{
11538 char cmd[256];
11539 char interface_name[16] = {0};
11540
11541 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11542 return RETURN_ERR;
11543
11544 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11545 interface_name,
11546 mac[0],
11547 mac[1],
11548 mac[2],
11549 mac[3],
11550 mac[4],
11551 mac[5]
11552 );
11553 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11554 _syscmd(cmd, key->wifi_keyId, 64);
11555
11556
11557 return RETURN_OK;
11558}
11559
11560INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11561{
11562 char interface_name[16] = {0};
11563 FILE *fd = NULL;
11564 char fname[100];
11565 char cmd[128] = {0};
11566 char out[64] = {0};
11567 wifi_key_multi_psk_t * key = NULL;
11568 if(keysNumber < 0)
11569 return RETURN_ERR;
11570
11571 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11572 fd = fopen(fname, "w");
11573 if (!fd) {
11574 return RETURN_ERR;
11575 }
11576 key= (wifi_key_multi_psk_t *) keys;
11577 for(int i=0; i<keysNumber; ++i, key++) {
11578 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11579 }
11580 fclose(fd);
11581
11582 //reload file
11583 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11584 return RETURN_ERR;
11585 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11586 _syscmd(cmd, out, 64);
11587 return RETURN_OK;
11588}
11589
11590INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11591{
11592 FILE *fd = NULL;
11593 char fname[100];
11594 char * line = NULL;
11595 char * pos = NULL;
11596 size_t len = 0;
11597 ssize_t read = 0;
11598 INT ret = RETURN_OK;
11599 wifi_key_multi_psk_t *keys_it = NULL;
11600
11601 if (keysNumber < 1) {
11602 return RETURN_ERR;
11603 }
11604
11605 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11606 fd = fopen(fname, "r");
11607 if (!fd) {
11608 return RETURN_ERR;
11609 }
11610
11611 if (keys == NULL) {
11612 ret = RETURN_ERR;
11613 goto close;
11614 }
11615
11616 keys_it = keys;
11617 while ((read = getline(&line, &len, fd)) != -1) {
11618 //Strip trailing new line if present
11619 if (read > 0 && line[read-1] == '\n') {
11620 line[read-1] = '\0';
11621 }
11622
11623 if(strcmp(line,"keyid=")) {
11624 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11625 if (!(pos = index(line, ' '))) {
11626 ret = RETURN_ERR;
11627 goto close;
11628 }
11629 pos++;
11630 //Here should be 00:00:00:00:00:00
11631 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11632 printf("Not supported MAC: %s\n", pos);
11633 }
11634 if (!(pos = index(pos, ' '))) {
11635 ret = RETURN_ERR;
11636 goto close;
11637 }
11638 pos++;
11639
11640 //The rest is PSK
11641 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11642 keys_it++;
11643
11644 if(--keysNumber <= 0)
11645 break;
11646 }
11647 }
11648
11649close:
11650 free(line);
11651 fclose(fd);
11652 return ret;
11653}
11654/* end of multi-psk support */
11655
11656INT wifi_setNeighborReports(UINT apIndex,
11657 UINT numNeighborReports,
11658 wifi_NeighborReport_t *neighborReports)
11659{
11660 char cmd[256] = { 0 };
11661 char hex_bssid[13] = { 0 };
11662 char bssid[18] = { 0 };
11663 char nr[256] = { 0 };
11664 char ssid[256];
11665 char hex_ssid[256];
11666 char interface_name[16] = {0};
11667 INT ret;
11668
11669 /*rmeove all neighbors*/
11670 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11671 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11672 return RETURN_ERR;
11673 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);
11674 system(cmd);
11675
11676 for(unsigned int i = 0; i < numNeighborReports; i++)
11677 {
11678 memset(ssid, 0, sizeof(ssid));
11679 ret = wifi_getSSIDName(apIndex, ssid);
11680 if (ret != RETURN_OK)
11681 return RETURN_ERR;
11682
11683 memset(hex_ssid, 0, sizeof(hex_ssid));
11684 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11685 sprintf(hex_ssid + k,"%02x", ssid[j]);
11686
11687 snprintf(hex_bssid, sizeof(hex_bssid),
11688 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11689 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11690 snprintf(bssid, sizeof(bssid),
11691 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11692 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11693
11694 snprintf(nr, sizeof(nr),
11695 "%s" // bssid
11696 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11697 "%02hhx" // operclass
11698 "%02hhx" // channel
11699 "%02hhx", // phy_mode
11700 hex_bssid,
11701 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11702 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11703 neighborReports[i].opClass,
11704 neighborReports[i].channel,
11705 neighborReports[i].phyTable);
11706
11707 snprintf(cmd, sizeof(cmd),
11708 "hostapd_cli set_neighbor "
11709 "%s " // bssid
11710 "ssid=%s " // ssid
11711 "nr=%s " // nr
11712 "-i %s",
11713 bssid,hex_ssid,nr, interface_name);
11714
11715 if (WEXITSTATUS(system(cmd)) != 0)
11716 {
11717 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11718 }
11719 }
11720
11721 return RETURN_OK;
11722}
11723
11724INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11725{
11726 return RETURN_OK;
11727}
11728
11729#ifdef _WIFI_HAL_TEST_
11730int main(int argc,char **argv)
11731{
11732 int index;
11733 INT ret=0;
11734 char buf[1024]="";
11735
11736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11737 if(argc<3)
11738 {
11739 if(argc==2)
11740 {
11741 if(!strcmp(argv[1], "init"))
11742 return wifi_init();
11743 if(!strcmp(argv[1], "reset"))
11744 return wifi_reset();
11745 if(!strcmp(argv[1], "wifi_getHalVersion"))
11746 {
11747 char buffer[64];
11748 if(wifi_getHalVersion(buffer)==RETURN_OK)
11749 printf("Version: %s\n", buffer);
11750 else
11751 printf("Error in wifi_getHalVersion\n");
11752 return RETURN_OK;
11753 }
11754 }
11755 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11756 exit(-1);
11757 }
11758
11759 index = atoi(argv[2]);
11760 if(strstr(argv[1], "wifi_getApName")!=NULL)
11761 {
11762 wifi_getApName(index,buf);
11763 printf("Ap name is %s \n",buf);
11764 return 0;
11765 }
11766 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11767 {
11768 BOOL b = FALSE;
11769 BOOL *output_bool = &b;
11770 wifi_getRadioAutoChannelEnable(index,output_bool);
11771 printf("Channel enabled = %d \n",b);
11772 return 0;
11773 }
11774 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11775 {
11776 wifi_getApWpaEncryptionMode(index,buf);
11777 printf("encryption enabled = %s\n",buf);
11778 return 0;
11779 }
11780 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11781 {
11782 BOOL b = FALSE;
11783 BOOL *output_bool = &b;
11784 wifi_getApSsidAdvertisementEnable(index,output_bool);
11785 printf("advertisment enabled = %d\n",b);
11786 return 0;
11787 }
11788 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11789 {
11790 if(argc <= 3 )
11791 {
11792 printf("Insufficient arguments \n");
11793 exit(-1);
11794 }
11795
11796 char sta[20] = {'\0'};
11797 ULLONG handle= 0;
11798 strcpy(sta,argv[3]);
11799 mac_address_t st;
11800 mac_addr_aton(st,sta);
11801
11802 wifi_associated_dev_tid_stats_t tid_stats;
11803 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11804 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11805 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);
11806 }
11807
11808 if(strstr(argv[1], "getApEnable")!=NULL) {
11809 BOOL enable;
11810 ret=wifi_getApEnable(index, &enable);
11811 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11812 }
11813 else if(strstr(argv[1], "setApEnable")!=NULL) {
11814 BOOL enable = atoi(argv[3]);
11815 ret=wifi_setApEnable(index, enable);
11816 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11817 }
11818 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080011819 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080011820 ret=wifi_getApStatus(index, status);
11821 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11822 }
11823 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11824 {
11825 wifi_getSSIDNameStatus(index,buf);
11826 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11827 return 0;
11828 }
11829 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11830 wifi_ssidTrafficStats2_t stats={0};
11831 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11832 printf("%s %d: returns %d\n", argv[1], index, ret);
11833 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11834 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11835 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11836 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11837 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11838 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11839 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11840 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11841 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11842 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11843 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11844 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11845 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11846 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11847 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11848 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11849 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11850 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11851 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11852 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11853 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11854 }
11855 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11856 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11857 UINT array_size=0;
11858 UINT i=0;
11859 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11860 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080011861 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080011862 printf(" neighbor %d:\n", i);
11863 printf(" ap_SSID =%s\n", pt->ap_SSID);
11864 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11865 printf(" ap_Mode =%s\n", pt->ap_Mode);
11866 printf(" ap_Channel =%d\n", pt->ap_Channel);
11867 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11868 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11869 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11870 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11871 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11872 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11873 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11874 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11875 printf(" ap_Noise =%d\n", pt->ap_Noise);
11876 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11877 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11878 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080011879 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080011880 }
11881 if(neighbor_ap_array)
11882 free(neighbor_ap_array); //make sure to free the list
11883 }
11884 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11885 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11886 UINT array_size=0;
11887 UINT i=0;
11888 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11889 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080011890 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080011891 printf(" associated_dev %d:\n", i);
11892 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11893 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11894 printf(" cli_SNR =%d\n", pt->cli_SNR);
11895 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11896 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11897 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11898 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11899 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11900 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11901 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11902 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11903 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11904 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11905 }
11906 if(associated_dev_array)
11907 free(associated_dev_array); //make sure to free the list
11908 }
11909
11910 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11911 {
11912#define MAX_ARRAY_SIZE 64
11913 int i, array_size;
11914 char *p, *ch_str;
11915 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11916
11917 if(argc != 5)
11918 {
11919 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11920 exit(-1);
11921 }
11922 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11923
11924 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11925 {
11926 strtok_r(ch_str, ",", &p);
11927 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11928 }
11929 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11930 if(!array_size)
11931 array_size=1;//Need to print current channel statistics
11932 for(i=0; i<array_size; i++)
11933 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11934 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11935 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11936 input_output_channelStats_array[i].ch_number,\
11937 input_output_channelStats_array[i].ch_noise,\
11938 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11939 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11940 input_output_channelStats_array[i].ch_utilization_busy,\
11941 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11942 input_output_channelStats_array[i].ch_utilization_total);
11943 }
11944
11945 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11946 {
11947 if(argc <= 3 )
11948 {
11949 printf("Insufficient arguments \n");
11950 exit(-1);
11951 }
11952 char mac_addr[20] = {'\0'};
11953 wifi_device_t output_struct;
11954 int dev_index = atoi(argv[3]);
11955
11956 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11957 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11958 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);
11959 }
11960
11961 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11962 {
11963 if (argc <= 3)
11964 {
11965 printf("Insufficient arguments\n");
11966 exit(-1);
11967 }
11968 char args[256];
11969 wifi_NeighborReport_t *neighborReports;
11970
11971 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11972 if (!neighborReports)
11973 {
11974 printf("Failed to allocate memory");
11975 exit(-1);
11976 }
11977
11978 for (int i = 3; i < argc; ++i)
11979 {
11980 char *val;
11981 int j = 0;
11982 memset(args, 0, sizeof(args));
11983 strncpy(args, argv[i], sizeof(args));
11984 val = strtok(args, ";");
11985 while (val != NULL)
11986 {
11987 if (j == 0)
11988 {
11989 mac_addr_aton(neighborReports[i - 3].bssid, val);
11990 } else if (j == 1)
11991 {
11992 neighborReports[i - 3].info = strtol(val, NULL, 16);
11993 } else if (j == 2)
11994 {
11995 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11996 } else if (j == 3)
11997 {
11998 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11999 } else if (j == 4)
12000 {
12001 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12002 } else {
12003 printf("Insufficient arguments]n\n");
12004 exit(-1);
12005 }
12006 val = strtok(NULL, ";");
12007 j++;
12008 }
12009 }
12010
12011 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12012 if (ret != RETURN_OK)
12013 {
12014 printf("wifi_setNeighborReports ret = %d", ret);
12015 exit(-1);
12016 }
12017 }
12018 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12019 {
12020 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12021 printf("%s.\n", buf);
12022 else
12023 printf("Error returned\n");
12024 }
12025 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12026 {
12027 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12028 printf("%s.\n", buf);
12029 else
12030 printf("Error returned\n");
12031 }
12032 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12033 {
12034 if (argc <= 2)
12035 {
12036 printf("Insufficient arguments\n");
12037 exit(-1);
12038 }
12039 char buf[64]= {'\0'};
12040 wifi_getRadioOperatingChannelBandwidth(index,buf);
12041 printf("Current bandwidth is %s \n",buf);
12042 return 0;
12043 }
12044 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12045 {
12046 if (argc <= 5)
12047 {
12048 printf("Insufficient arguments\n");
12049 exit(-1);
12050 }
12051 UINT channel = atoi(argv[3]);
12052 UINT width = atoi(argv[4]);
12053 UINT beacon = atoi(argv[5]);
12054 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12055 printf("Result = %d", ret);
12056 }
12057
12058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12059 return 0;
12060}
12061
12062#endif
12063
12064#ifdef WIFI_HAL_VERSION_3
12065
12066INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12067{
12068 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12069 if (bitMap & WIFI_BITRATE_1MBPS)
12070 strcat(BasicRate, "1,");
12071 if (bitMap & WIFI_BITRATE_2MBPS)
12072 strcat(BasicRate, "2,");
12073 if (bitMap & WIFI_BITRATE_5_5MBPS)
12074 strcat(BasicRate, "5.5,");
12075 if (bitMap & WIFI_BITRATE_6MBPS)
12076 strcat(BasicRate, "6,");
12077 if (bitMap & WIFI_BITRATE_9MBPS)
12078 strcat(BasicRate, "9,");
12079 if (bitMap & WIFI_BITRATE_11MBPS)
12080 strcat(BasicRate, "11,");
12081 if (bitMap & WIFI_BITRATE_12MBPS)
12082 strcat(BasicRate, "12,");
12083 if (bitMap & WIFI_BITRATE_18MBPS)
12084 strcat(BasicRate, "18,");
12085 if (bitMap & WIFI_BITRATE_24MBPS)
12086 strcat(BasicRate, "24,");
12087 if (bitMap & WIFI_BITRATE_36MBPS)
12088 strcat(BasicRate, "36,");
12089 if (bitMap & WIFI_BITRATE_48MBPS)
12090 strcat(BasicRate, "48,");
12091 if (bitMap & WIFI_BITRATE_54MBPS)
12092 strcat(BasicRate, "54,");
12093 if (strlen(BasicRate) != 0) // remove last comma
12094 BasicRate[strlen(BasicRate) - 1] = '\0';
12095 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12096 return RETURN_OK;
12097}
12098
12099INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12100{
12101 UINT BitMap = 0;
12102 char *rate;
12103
12104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12105 rate = strtok(BasicRatesList, ",");
12106 while(rate != NULL)
12107 {
12108 if (strcmp(rate, "1") == 0)
12109 BitMap |= WIFI_BITRATE_1MBPS;
12110 else if (strcmp(rate, "2") == 0)
12111 BitMap |= WIFI_BITRATE_2MBPS;
12112 else if (strcmp(rate, "5.5") == 0)
12113 BitMap |= WIFI_BITRATE_5_5MBPS;
12114 else if (strcmp(rate, "6") == 0)
12115 BitMap |= WIFI_BITRATE_6MBPS;
12116 else if (strcmp(rate, "9") == 0)
12117 BitMap |= WIFI_BITRATE_9MBPS;
12118 else if (strcmp(rate, "11") == 0)
12119 BitMap |= WIFI_BITRATE_11MBPS;
12120 else if (strcmp(rate, "12") == 0)
12121 BitMap |= WIFI_BITRATE_12MBPS;
12122 else if (strcmp(rate, "18") == 0)
12123 BitMap |= WIFI_BITRATE_18MBPS;
12124 else if (strcmp(rate, "24") == 0)
12125 BitMap |= WIFI_BITRATE_24MBPS;
12126 else if (strcmp(rate, "36") == 0)
12127 BitMap |= WIFI_BITRATE_36MBPS;
12128 else if (strcmp(rate, "48") == 0)
12129 BitMap |= WIFI_BITRATE_48MBPS;
12130 else if (strcmp(rate, "54") == 0)
12131 BitMap |= WIFI_BITRATE_54MBPS;
12132 rate = strtok(NULL, ",");
12133 }
12134 *basicRateBitMap = BitMap;
12135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12136 return RETURN_OK;
12137}
12138
12139// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
12140INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12141{
12142 char buf[128] = {0};
12143 char cmd[128] = {0};
12144 char config_file[64] = {0};
12145 int bandwidth;
12146 int set_mode = 0;
12147 wifi_radio_operationParam_t current_param;
12148
12149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12150
12151 multiple_set = TRUE;
12152 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12153 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12154 return RETURN_ERR;
12155 }
12156 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12157 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12158 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12159 return RETURN_ERR;
12160 }
12161 }
12162
12163 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12164 bandwidth = 20;
12165 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12166 bandwidth = 40;
12167 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12168 bandwidth = 80;
12169 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12170 bandwidth = 160;
12171 if (operationParam->autoChannelEnabled){
12172 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12173 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12174 return RETURN_ERR;
12175 }
developer69b61b02023-03-07 17:17:44 +080012176 }else{
developer72fb0bb2023-01-11 09:46:29 +080012177 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12178 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12179 return RETURN_ERR;
12180 }
12181 }
12182
12183 if (current_param.variant != operationParam->variant) {
12184 // Two different definition bit map, so need to check every bit.
12185 if (operationParam->variant & WIFI_80211_VARIANT_A)
12186 set_mode |= WIFI_MODE_A;
12187 if (operationParam->variant & WIFI_80211_VARIANT_B)
12188 set_mode |= WIFI_MODE_B;
12189 if (operationParam->variant & WIFI_80211_VARIANT_G)
12190 set_mode |= WIFI_MODE_G;
12191 if (operationParam->variant & WIFI_80211_VARIANT_N)
12192 set_mode |= WIFI_MODE_N;
12193 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12194 set_mode |= WIFI_MODE_AC;
12195 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12196 set_mode |= WIFI_MODE_AX;
12197 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12198 memset(buf, 0, sizeof(buf));
12199 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12200 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12201 return RETURN_ERR;
12202 }
12203 }
12204 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12205 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12206 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12207 return RETURN_ERR;
12208 }
12209 }
12210 if (current_param.beaconInterval != operationParam->beaconInterval) {
12211 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12212 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12213 return RETURN_ERR;
12214 }
12215 }
12216 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12217 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12218 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12219 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12220 return RETURN_ERR;
12221 }
12222 }
12223 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12224 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12225 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12226 return RETURN_ERR;
12227 }
12228 }
12229 if (current_param.guardInterval != operationParam->guardInterval) {
12230 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12231 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12232 return RETURN_ERR;
12233 }
12234 }
12235 if (current_param.transmitPower != operationParam->transmitPower) {
12236 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12237 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12238 return RETURN_ERR;
12239 }
12240 }
12241 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12242 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12243 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12244 return RETURN_ERR;
12245 }
12246 }
12247 if (current_param.obssCoex != operationParam->obssCoex) {
12248 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12249 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12250 return RETURN_ERR;
12251 }
12252 }
12253 if (current_param.stbcEnable != operationParam->stbcEnable) {
12254 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12255 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12256 return RETURN_ERR;
12257 }
12258 }
12259 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12260 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12261 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12262 return RETURN_ERR;
12263 }
12264 }
12265
12266 // if enable is true, then restart the radio
12267 wifi_setRadioEnable(index, FALSE);
12268 if (operationParam->enable == TRUE)
12269 wifi_setRadioEnable(index, TRUE);
12270 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12271
12272 return RETURN_OK;
12273}
12274
12275INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12276{
12277 char band[64] = {0};
12278 char buf[256] = {0};
12279 char config_file[64] = {0};
12280 char cmd[128] = {0};
12281 int ret = RETURN_ERR;
12282 int mode = 0;
12283 ULONG channel = 0;
12284 BOOL enabled = FALSE;
12285
12286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12287 printf("Entering %s index = %d\n", __func__, (int)index);
12288
12289 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12290 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12291 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12292 {
12293 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12294 return RETURN_ERR;
12295 }
12296 operationParam->enable = enabled;
12297
12298 memset(band, 0, sizeof(band));
12299 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12300 {
12301 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12302 return RETURN_ERR;
12303 }
12304
12305 if (!strcmp(band, "2.4GHz"))
12306 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12307 else if (!strcmp(band, "5GHz"))
12308 operationParam->band = WIFI_FREQUENCY_5_BAND;
12309 else if (!strcmp(band, "6GHz"))
12310 operationParam->band = WIFI_FREQUENCY_6_BAND;
12311 else
12312 {
12313 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12314 band);
12315 }
12316
12317 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12318 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12319 operationParam->channel = 0;
12320 operationParam->autoChannelEnabled = TRUE;
12321 } else {
12322 operationParam->channel = strtol(buf, NULL, 10);
12323 operationParam->autoChannelEnabled = FALSE;
12324 }
12325
12326 memset(buf, 0, sizeof(buf));
12327 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12328 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12329 return RETURN_ERR;
12330 }
12331 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12332 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12333 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12334 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12335 else
12336 {
12337 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12338 return false;
12339 }
12340
12341 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12342 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12343 return RETURN_ERR;
12344 }
12345 // Two different definition bit map, so need to check every bit.
12346 if (mode & WIFI_MODE_A)
12347 operationParam->variant |= WIFI_80211_VARIANT_A;
12348 if (mode & WIFI_MODE_B)
12349 operationParam->variant |= WIFI_80211_VARIANT_B;
12350 if (mode & WIFI_MODE_G)
12351 operationParam->variant |= WIFI_80211_VARIANT_G;
12352 if (mode & WIFI_MODE_N)
12353 operationParam->variant |= WIFI_80211_VARIANT_N;
12354 if (mode & WIFI_MODE_AC)
12355 operationParam->variant |= WIFI_80211_VARIANT_AC;
12356 if (mode & WIFI_MODE_AX)
12357 operationParam->variant |= WIFI_80211_VARIANT_AX;
12358 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12359 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12360 return RETURN_ERR;
12361 }
12362 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12363 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12364 return RETURN_ERR;
12365 }
12366 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12367 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12368 return RETURN_ERR;
12369 }
12370
12371 memset(buf, 0, sizeof(buf));
12372 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12373 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12374 return RETURN_ERR;
12375 }
12376 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12377
12378 memset(buf, 0, sizeof(buf));
12379 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12380 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12381 return RETURN_ERR;
12382 }
12383 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12384
12385 memset(buf, 0, sizeof(buf));
12386 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12387 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12388
12389 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12390 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12391 return RETURN_ERR;
12392 }
12393 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12394 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12395 return RETURN_ERR;
12396 }
12397
12398 memset(buf, 0, sizeof(buf));
12399 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12400 if (strcmp(buf, "-1") == 0) {
12401 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12402 operationParam->ctsProtection = FALSE;
12403 } else {
12404 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12405 operationParam->ctsProtection = TRUE;
12406 }
12407
12408 memset(buf, 0, sizeof(buf));
12409 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12410 if (strcmp(buf, "0") == 0)
12411 operationParam->obssCoex = FALSE;
12412 else
12413 operationParam->obssCoex = TRUE;
12414
12415 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12416 _syscmd(cmd, buf, sizeof(buf));
12417 if (strlen(buf) != 0)
12418 operationParam->stbcEnable = TRUE;
12419 else
12420 operationParam->stbcEnable = FALSE;
12421
12422 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12423 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12424 return RETURN_ERR;
12425 }
12426
12427 // Below value is hardcoded
12428
12429 operationParam->numSecondaryChannels = 0;
12430 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12431 operationParam->channelSecondary[i] = 0;
12432 }
12433 operationParam->csa_beacon_count = 15;
12434 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12435
12436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12437 return RETURN_OK;
12438}
12439
12440static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12441{
12442 int max_radio_num = 0;
12443
12444 wifi_getMaxRadioNumber(&max_radio_num);
12445 if (radioIndex >= max_radio_num) {
12446 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12447 return RETURN_ERR;
12448 }
12449
12450 return (arrayIndex * max_radio_num) + radioIndex;
12451}
12452
developer96b38512023-02-22 11:17:45 +080012453static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
12454{
12455 int max_radio_num = 0;
12456
12457 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
12458 return -1;
12459
12460 wifi_getMaxRadioNumber(&max_radio_num);
12461
12462 (*radioIndex) = vapIndex % max_radio_num;
12463 (*arrayIndex) = vapIndex / max_radio_num;
12464
12465 return 0;
12466}
12467
12468
developer72fb0bb2023-01-11 09:46:29 +080012469wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12470 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12471 return WIFI_BITRATE_1MBPS;
12472 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12473 return WIFI_BITRATE_2MBPS;
12474 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12475 return WIFI_BITRATE_5_5MBPS;
12476 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12477 return WIFI_BITRATE_6MBPS;
12478 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12479 return WIFI_BITRATE_9MBPS;
12480 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12481 return WIFI_BITRATE_11MBPS;
12482 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12483 return WIFI_BITRATE_12MBPS;
12484 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12485 return WIFI_BITRATE_18MBPS;
12486 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12487 return WIFI_BITRATE_24MBPS;
12488 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12489 return WIFI_BITRATE_36MBPS;
12490 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12491 return WIFI_BITRATE_48MBPS;
12492 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12493 return WIFI_BITRATE_54MBPS;
12494 return WIFI_BITRATE_DEFAULT;
12495}
12496
12497INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12498{
12499 if (beacon == WIFI_BITRATE_1MBPS)
12500 strcpy(beacon_str, "1Mbps");
12501 else if (beacon == WIFI_BITRATE_2MBPS)
12502 strcpy(beacon_str, "2Mbps");
12503 else if (beacon == WIFI_BITRATE_5_5MBPS)
12504 strcpy(beacon_str, "5.5Mbps");
12505 else if (beacon == WIFI_BITRATE_6MBPS)
12506 strcpy(beacon_str, "6Mbps");
12507 else if (beacon == WIFI_BITRATE_9MBPS)
12508 strcpy(beacon_str, "9Mbps");
12509 else if (beacon == WIFI_BITRATE_11MBPS)
12510 strcpy(beacon_str, "11Mbps");
12511 else if (beacon == WIFI_BITRATE_12MBPS)
12512 strcpy(beacon_str, "12Mbps");
12513 else if (beacon == WIFI_BITRATE_18MBPS)
12514 strcpy(beacon_str, "18Mbps");
12515 else if (beacon == WIFI_BITRATE_24MBPS)
12516 strcpy(beacon_str, "24Mbps");
12517 else if (beacon == WIFI_BITRATE_36MBPS)
12518 strcpy(beacon_str, "36Mbps");
12519 else if (beacon == WIFI_BITRATE_48MBPS)
12520 strcpy(beacon_str, "48Mbps");
12521 else if (beacon == WIFI_BITRATE_54MBPS)
12522 strcpy(beacon_str, "54Mbps");
12523 return RETURN_OK;
12524}
12525
12526INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12527{
12528 INT mode = 0;
12529 INT ret = -1;
12530 INT output = 0;
12531 int i = 0;
12532 int vap_index = 0;
12533 BOOL enabled = FALSE;
12534 char buf[256] = {0};
12535 wifi_vap_security_t security = {0};
12536 map->num_vaps = 5; // Hardcoded
12537
12538 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12539 printf("Entering %s index = %d\n", __func__, (int)index);
12540
12541 for (i = 0; i < 5; i++)
12542 {
12543 map->vap_array[i].radio_index = index;
12544
12545 vap_index = array_index_to_vap_index(index, i);
12546 if (vap_index < 0)
12547 return RETURN_ERR;
12548
12549 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12550
12551 map->vap_array[i].vap_index = vap_index;
12552
12553 memset(buf, 0, sizeof(buf));
12554 ret = wifi_getApName(vap_index, buf);
12555 if (ret != RETURN_OK) {
12556 printf("%s: wifi_getApName return error\n", __func__);
12557 return RETURN_ERR;
12558 }
12559 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12560
12561 memset(buf, 0, sizeof(buf));
12562 ret = wifi_getSSIDName(vap_index, buf);
12563 if (ret != RETURN_OK) {
12564 printf("%s: wifi_getSSIDName return error\n", __func__);
12565 return RETURN_ERR;
12566 }
12567 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12568
12569 ret = wifi_getSSIDEnable(vap_index, &enabled);
12570 if (ret != RETURN_OK) {
12571 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12572 return RETURN_ERR;
12573 }
12574 map->vap_array[i].u.bss_info.enabled = enabled;
12575
12576 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12577 if (ret != RETURN_OK) {
12578 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12579 return RETURN_ERR;
12580 }
12581 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080012582
developer72fb0bb2023-01-11 09:46:29 +080012583 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12584 if (ret != RETURN_OK) {
12585 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12586 return RETURN_ERR;
12587 }
12588 map->vap_array[i].u.bss_info.isolation = enabled;
12589
12590 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12591 if (ret != RETURN_OK) {
12592 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12593 return RETURN_ERR;
12594 }
12595 map->vap_array[i].u.bss_info.bssMaxSta = output;
12596
12597 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12598 if (ret != RETURN_OK) {
12599 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12600 return RETURN_ERR;
12601 }
12602 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12603
12604 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12605 if (ret != RETURN_OK) {
12606 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12607 return RETURN_ERR;
12608 }
12609 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12610
12611 ret = wifi_getApSecurity(vap_index, &security);
12612 if (ret != RETURN_OK) {
12613 printf("%s: wifi_getApSecurity return error\n", __func__);
12614 return RETURN_ERR;
12615 }
12616 map->vap_array[i].u.bss_info.security = security;
12617
12618 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12619 if (ret != RETURN_OK) {
12620 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12621 return RETURN_ERR;
12622 }
developer69b61b02023-03-07 17:17:44 +080012623 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080012624 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080012625 else
developer72fb0bb2023-01-11 09:46:29 +080012626 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080012627 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080012628 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080012629 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080012630 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12631
12632 ret = wifi_getApWmmEnable(vap_index, &enabled);
12633 if (ret != RETURN_OK) {
12634 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12635 return RETURN_ERR;
12636 }
12637 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12638
12639 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12640 if (ret != RETURN_OK) {
12641 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12642 return RETURN_ERR;
12643 }
12644 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12645
12646 memset(buf, 0, sizeof(buf));
12647 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12648 if (ret != RETURN_OK) {
12649 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12650 return RETURN_ERR;
12651 }
12652 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12653
12654 memset(buf, 0, sizeof(buf));
12655 ret = wifi_getBaseBSSID(vap_index, buf);
12656 if (ret != RETURN_OK) {
12657 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12658 return RETURN_ERR;
12659 }
12660 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12661 &map->vap_array[i].u.bss_info.bssid[0],
12662 &map->vap_array[i].u.bss_info.bssid[1],
12663 &map->vap_array[i].u.bss_info.bssid[2],
12664 &map->vap_array[i].u.bss_info.bssid[3],
12665 &map->vap_array[i].u.bss_info.bssid[4],
12666 &map->vap_array[i].u.bss_info.bssid[5]);
12667 // 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]);
12668
12669 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12670 if (ret != RETURN_OK) {
12671 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12672 return RETURN_ERR;
12673 }
12674 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12675
12676 // TODO: wps, noack
12677 }
12678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12679 return RETURN_OK;
12680}
12681
12682void checkVapStatus(int apIndex, bool *enable)
12683{
12684 char if_name[16] = {0};
12685 char cmd[128] = {0};
12686 char buf[128] = {0};
12687
12688 *enable = FALSE;
12689 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12690 return;
12691
12692 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12693 _syscmd(cmd, buf, sizeof(buf));
12694 if (strlen(buf) > 0)
12695 *enable = TRUE;
12696 return;
12697}
12698
12699static int prepareInterface(UINT apIndex, char *new_interface)
12700{
12701 char cur_interface[16] = {0};
12702 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080012703 char cmd[MAX_CMD_SIZE] = {0};
12704 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012705 int max_radio_num = 0;
12706 int radioIndex = -1;
12707 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080012708 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080012709
12710 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12711 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12712
12713 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080012714 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080012715 radioIndex = apIndex % max_radio_num;
12716 phyIndex = radio_index_to_phy(radioIndex);
12717 // disable and del old interface, then add new interface
12718 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080012719
12720 params.name = "interface";
12721 params.value = new_interface;
12722 wifi_hostapdWrite(config_file, &params, 1);
12723
12724 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
12725 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080012726 }
developer8a3bbbf2023-03-15 17:47:23 +080012727
developer72fb0bb2023-01-11 09:46:29 +080012728 // update the vap status file
12729 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12730 _syscmd(cmd, buf, sizeof(buf));
12731 return RETURN_OK;
12732}
12733
12734INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12735{
12736 char interface_name[16] = {0};
12737 unsigned int i;
12738 wifi_vap_info_t *vap_info = NULL;
12739 int acl_mode;
12740 int ret = 0;
12741 char *sec_str = NULL;
12742 char buf[256] = {0};
12743 char cmd[128] = {0};
12744 char config_file[64] = {0};
12745 char bssid[32] = {0};
12746 char psk_file[64] = {0};
12747 bool enable = FALSE;
12748
12749 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12750 printf("Entering %s index = %d\n", __func__, (int)index);
12751 for (i = 0; i < map->num_vaps; i++)
12752 {
12753 multiple_set = TRUE;
12754 vap_info = &map->vap_array[i];
12755
12756 // Check vap status file to enable multiple ap if the system boot.
12757 checkVapStatus(vap_info->vap_index, &enable);
12758 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
12759 continue;
12760
12761 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12762
12763 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12764 enable = FALSE;
12765
12766 // multi-ap first up need to copy current radio config
12767 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
12768 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12769 _syscmd(cmd, buf, sizeof(buf));
12770 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12771 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12772 } else {
12773 // Check whether the interface name is valid or this ap change it.
12774 int apIndex = -1;
12775 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12776 if (apIndex != -1 && apIndex != vap_info->vap_index)
12777 continue;
12778 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12779 }
12780
12781 struct params params[3];
12782 params[0].name = "interface";
12783 params[0].value = vap_info->vap_name;
12784 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12785 params[1].name = "bssid";
12786 params[1].value = bssid;
12787 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
12788 params[2].name = "wpa_psk_file";
12789 params[2].value = psk_file;
12790
12791 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12792 wifi_hostapdWrite(config_file, params, 3);
12793
12794 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12795 _syscmd(cmd, buf, sizeof(buf));
12796
12797 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12798 if (ret != RETURN_OK) {
12799 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12800 return RETURN_ERR;
12801 }
12802
12803 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12804 if (ret != RETURN_OK) {
12805 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12806 return RETURN_ERR;
12807 }
12808
12809 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12810 if (ret != RETURN_OK) {
12811 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12812 return RETURN_ERR;
12813 }
12814
12815 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12816 if (ret != RETURN_OK) {
12817 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12818 return RETURN_ERR;
12819 }
12820
12821 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12822 if (ret != RETURN_OK) {
12823 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12824 return RETURN_ERR;
12825 }
12826
12827 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12828 if (ret != RETURN_OK) {
12829 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12830 return RETURN_ERR;
12831 }
12832
12833 if (vap_info->u.bss_info.mac_filter_enable == false){
12834 acl_mode = 0;
12835 }else {
12836 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
12837 acl_mode = 2;
12838 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12839 _syscmd(cmd, buf, sizeof(buf));
12840 }else{
12841 acl_mode = 1;
12842 }
12843 }
12844
12845 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12846 if (ret != RETURN_OK) {
12847 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12848 return RETURN_ERR;
12849 }
12850
12851 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12852 if (ret != RETURN_OK) {
12853 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12854 return RETURN_ERR;
12855 }
12856
developered997d32023-04-18 22:45:39 +080012857 /*TBD: we need refine beacon rate setting flow*/
12858 //memset(buf, 0, sizeof(buf));
12859 //beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
developer72fb0bb2023-01-11 09:46:29 +080012860 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
developered997d32023-04-18 22:45:39 +080012861 //ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12862 //if (ret != RETURN_OK) {
12863 // fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12864 // return RETURN_ERR;
12865 //}
developer72fb0bb2023-01-11 09:46:29 +080012866
12867 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12868 if (ret != RETURN_OK) {
12869 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12870 return RETURN_ERR;
12871 }
12872
developer72fb0bb2023-01-11 09:46:29 +080012873 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12874 if (ret != RETURN_OK) {
12875 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12876 return RETURN_ERR;
12877 }
12878
developer23e71282023-01-18 10:25:19 +080012879 wifi_setApEnable(vap_info->vap_index, FALSE);
12880 wifi_setApEnable(vap_info->vap_index, TRUE);
12881 multiple_set = FALSE;
12882
12883 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080012884 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12885 if (ret != RETURN_OK) {
12886 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12887 return RETURN_ERR;
12888 }
12889
12890 // TODO mgmtPowerControl, interworking, wps
12891 }
12892 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12893 return RETURN_OK;
12894}
12895
12896int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12897{
12898 char *token, *next;
12899 const char s[2] = ",";
12900 int count =0;
12901
12902 /* get the first token */
12903 token = strtok_r(pchannels, s, &next);
12904
12905 /* walk through other tokens */
12906 while( token != NULL && count < MAX_CHANNELS) {
12907 chlistptr->channels_list[count++] = atoi(token);
12908 token = strtok_r(NULL, s, &next);
12909 }
12910
12911 return count;
12912}
12913
12914static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12915{
12916 INT status;
12917 wifi_channels_list_t *chlistp;
12918 CHAR output_string[64];
12919 CHAR pchannels[128];
12920 CHAR interface_name[16] = {0};
12921 wifi_band band;
12922
12923 if(rcap == NULL)
12924 {
12925 return RETURN_ERR;
12926 }
12927
12928 rcap->numSupportedFreqBand = 1;
12929 band = wifi_index_to_band(radioIndex);
12930
12931 if (band == band_2_4)
12932 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12933 else if (band == band_5)
12934 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12935 else if (band == band_6)
12936 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
12937
12938 chlistp = &(rcap->channel_list[0]);
12939 memset(pchannels, 0, sizeof(pchannels));
12940
12941 /* possible number of radio channels */
12942 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12943 {
12944 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12945 }
12946 /* Number of channels and list*/
12947 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12948
12949 /* autoChannelSupported */
12950 /* always ON with wifi_getRadioAutoChannelSupported */
12951 rcap->autoChannelSupported = TRUE;
12952
12953 /* DCSSupported */
12954 /* always ON with wifi_getRadioDCSSupported */
12955 rcap->DCSSupported = TRUE;
12956
12957 /* zeroDFSSupported - TBD */
12958 rcap->zeroDFSSupported = FALSE;
12959
12960 /* Supported Country List*/
12961 memset(output_string, 0, sizeof(output_string));
12962 status = wifi_getRadioCountryCode(radioIndex, output_string);
12963 if( status != 0 ) {
12964 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12965 return RETURN_ERR;
12966 } else {
12967 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12968 }
12969 if(!strcmp(output_string,"US")){
12970 rcap->countrySupported[0] = wifi_countrycode_US;
12971 rcap->countrySupported[1] = wifi_countrycode_CA;
12972 } else if (!strcmp(output_string,"CA")) {
12973 rcap->countrySupported[0] = wifi_countrycode_CA;
12974 rcap->countrySupported[1] = wifi_countrycode_US;
12975 } else {
12976 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12977 }
12978
12979 rcap->numcountrySupported = 2;
12980
12981 /* csi */
12982 rcap->csi.maxDevices = 8;
12983 rcap->csi.soudingFrameSupported = TRUE;
12984
12985 wifi_GetInterfaceName(radioIndex, interface_name);
12986 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
12987
12988 /* channelWidth - all supported bandwidths */
12989 int i=0;
12990 rcap->channelWidth[i] = 0;
12991 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12992 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12993 WIFI_CHANNELBANDWIDTH_40MHZ);
12994
12995 }
12996 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
12997 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12998 WIFI_CHANNELBANDWIDTH_40MHZ |
12999 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13000 }
13001
13002
13003 /* mode - all supported variants */
13004 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13005 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13006 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13007 }
13008 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13009 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13010 }
13011 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13012 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13013 }
13014 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13015 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13016
13017 /* supportedBitRate - all supported bitrates */
13018 rcap->supportedBitRate[i] = 0;
13019 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13020 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13021 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13022 }
13023 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13024 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13025 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13026 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13027 }
13028
13029
13030 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13031 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13032 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13033 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13034 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13035 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13036 rcap->cipherSupported = 0;
13037 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13038 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13039
13040 return RETURN_OK;
13041}
13042
13043INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13044{
13045 INT status = 0, radioIndex = 0;
13046 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13047 int iter = 0;
13048 unsigned int j = 0;
13049 int max_num_radios;
13050 wifi_interface_name_idex_map_t *iface_info = NULL;
13051
13052 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13053
13054 memset(cap, 0, sizeof(wifi_hal_capability_t));
13055
13056 /* version */
13057 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13058 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13059
13060 /* number of radios platform property */
13061 wifi_getMaxRadioNumber(&max_num_radios);
13062 cap->wifi_prop.numRadios = max_num_radios;
13063
13064 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13065 {
13066 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13067 if (status != 0) {
13068 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13069 return RETURN_ERR;
13070 }
13071
13072 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13073 {
13074 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13075 {
13076 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13077 return RETURN_ERR;
13078 }
13079 iface_info = &cap->wifi_prop.interface_map[iter];
13080 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13081 iface_info->rdk_radio_index = radioIndex;
13082 memset(output, 0, sizeof(output));
13083 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13084 {
13085 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13086 }
13087 // TODO: bridge name
13088 // TODO: vlan id
13089 // TODO: primary
13090 iface_info->index = array_index_to_vap_index(radioIndex, j);
13091 memset(output, 0, sizeof(output));
13092 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13093 {
13094 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13095 }
13096 iter++;
13097 }
13098 }
13099
13100 cap->BandSteeringSupported = FALSE;
13101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13102 return RETURN_OK;
13103}
13104
13105INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13106{
13107 struct params h_config={0};
13108 char config_file[64] = {0};
13109
13110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13111
13112 h_config.name = "okc";
13113 h_config.value = okc_enable?"1":"0";
13114
13115 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13116 wifi_hostapdWrite(config_file, &h_config, 1);
13117 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13118
13119 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13120 return RETURN_OK;
13121}
13122
13123INT wifi_setSAEMFP(int ap_index, BOOL enable)
13124{
13125 struct params h_config={0};
13126 char config_file[64] = {0};
13127 char buf[128] = {0};
13128
13129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13130
13131 h_config.name = "sae_require_mfp";
13132 h_config.value = enable?"1":"0";
13133
13134 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13135 wifi_hostapdWrite(config_file, &h_config, 1);
13136 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13137
13138 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13139 return RETURN_OK;
13140}
13141
13142INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13143{
13144 struct params h_config={0};
13145 char config_file[64] = {0};
13146 char buf[128] = {0};
13147
13148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13149
13150 h_config.name = "sae_pwe";
13151 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13152 h_config.value = buf;
13153
13154 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13155 wifi_hostapdWrite(config_file, &h_config, 1);
13156 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13157
13158 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13159 return RETURN_OK;
13160}
13161
13162INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13163{
13164 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13165 struct params h_config={0};
13166 char config_file[64] = {0};
13167
13168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13169
13170 h_config.name = "wpa_disable_eapol_key_retries";
13171 h_config.value = disable_EAPOL_retries?"1":"0";
13172
13173 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13174 wifi_hostapdWrite(config_file, &h_config, 1);
13175 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13176
13177 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13178 return RETURN_OK;
13179}
13180
13181INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13182{
13183 char buf[128] = {0};
13184 char config_file[128] = {0};
13185 char password[64] = {0};
13186 char mfp[32] = {0};
13187 char wpa_mode[32] = {0};
13188 BOOL okc_enable = FALSE;
13189 BOOL sae_MFP = FALSE;
13190 BOOL disable_EAPOL_retries = TRUE;
13191 int sae_pwe = 0;
13192 struct params params = {0};
13193 wifi_band band = band_invalid;
13194
13195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13196
13197 multiple_set = TRUE;
13198 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13199 if (security->mode == wifi_security_mode_none) {
13200 strcpy(wpa_mode, "None");
13201 } else if (security->mode == wifi_security_mode_wpa_personal)
13202 strcpy(wpa_mode, "WPA-Personal");
13203 else if (security->mode == wifi_security_mode_wpa2_personal)
13204 strcpy(wpa_mode, "WPA2-Personal");
13205 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13206 strcpy(wpa_mode, "WPA-WPA2-Personal");
13207 else if (security->mode == wifi_security_mode_wpa_enterprise)
13208 strcpy(wpa_mode, "WPA-Enterprise");
13209 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13210 strcpy(wpa_mode, "WPA2-Enterprise");
13211 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13212 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
13213 else if (security->mode == wifi_security_mode_wpa3_personal) {
13214 strcpy(wpa_mode, "WPA3-Personal");
13215 okc_enable = TRUE;
13216 sae_MFP = TRUE;
13217 sae_pwe = 2;
13218 disable_EAPOL_retries = FALSE;
13219 } else if (security->mode == wifi_security_mode_wpa3_transition) {
13220 strcpy(wpa_mode, "WPA3-Personal-Transition");
13221 okc_enable = TRUE;
13222 sae_MFP = TRUE;
13223 sae_pwe = 2;
13224 disable_EAPOL_retries = FALSE;
13225 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
13226 strcpy(wpa_mode, "WPA3-Enterprise");
13227 sae_MFP = TRUE;
13228 sae_pwe = 2;
13229 disable_EAPOL_retries = FALSE;
developer3086e2f2023-01-17 09:40:01 +080013230 } else if (security->mode == wifi_security_mode_owe) {
13231 strcpy(wpa_mode, "OWE");
13232 sae_MFP = TRUE;
13233 sae_pwe = 2;
13234 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013235 }
13236
13237 band = wifi_index_to_band(ap_index);
13238 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13239 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13240 return RETURN_ERR;
13241 }
13242
13243 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
13244 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
13245 wifi_setSAEMFP(ap_index, sae_MFP);
13246 wifi_setSAEpwe(ap_index, sae_pwe);
13247 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
13248
developer23e71282023-01-18 10:25:19 +080013249 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer72fb0bb2023-01-11 09:46:29 +080013250 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
13251 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
13252 password[63] = '\0';
13253 wifi_setApSecurityKeyPassphrase(ap_index, password);
13254 }
13255 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13256 params.name = "sae_password";
13257 params.value = security->u.key.key;
13258 wifi_hostapdWrite(config_file, &params, 1);
13259 }
13260 }
13261
13262 if (security->mode != wifi_security_mode_none) {
13263 memset(&params, 0, sizeof(params));
13264 params.name = "wpa_pairwise";
13265 if (security->encr == wifi_encryption_tkip)
13266 params.value = "TKIP";
13267 else if (security->encr == wifi_encryption_aes)
13268 params.value = "CCMP";
13269 else if (security->encr == wifi_encryption_aes_tkip)
13270 params.value = "TKIP CCMP";
13271 wifi_hostapdWrite(config_file, &params, 1);
13272 }
13273
13274 if (security->mfp == wifi_mfp_cfg_disabled)
13275 strcpy(mfp, "Disabled");
13276 else if (security->mfp == wifi_mfp_cfg_optional)
13277 strcpy(mfp, "Optional");
13278 else if (security->mfp == wifi_mfp_cfg_required)
13279 strcpy(mfp, "Required");
13280 wifi_setApSecurityMFPConfig(ap_index, mfp);
13281
13282 memset(&params, 0, sizeof(params));
13283 params.name = "transition_disable";
13284 if (security->wpa3_transition_disable == TRUE)
13285 params.value = "0x01";
13286 else
13287 params.value = "0x00";
13288 wifi_hostapdWrite(config_file, &params, 1);
13289
13290 memset(&params, 0, sizeof(params));
13291 params.name = "wpa_group_rekey";
13292 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13293 params.value = buf;
13294 wifi_hostapdWrite(config_file, &params, 1);
13295
13296 memset(&params, 0, sizeof(params));
13297 params.name = "wpa_strict_rekey";
13298 params.value = security->strict_rekey?"1":"0";
13299 wifi_hostapdWrite(config_file, &params, 1);
13300
13301 memset(&params, 0, sizeof(params));
13302 params.name = "wpa_pairwise_update_count";
13303 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13304 params.value = buf;
13305 wifi_hostapdWrite(config_file, &params, 1);
13306
13307 memset(&params, 0, sizeof(params));
13308 params.name = "disable_pmksa_caching";
13309 params.value = security->disable_pmksa_caching?"1":"0";
13310 wifi_hostapdWrite(config_file, &params, 1);
13311
developer23e71282023-01-18 10:25:19 +080013312 if (multiple_set == FALSE) {
13313 wifi_setApEnable(ap_index, FALSE);
13314 wifi_setApEnable(ap_index, TRUE);
13315 }
developer72fb0bb2023-01-11 09:46:29 +080013316
13317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13318
13319 return RETURN_OK;
13320}
13321
13322INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13323{
13324 char buf[256] = {0};
13325 char config_file[128] = {0};
13326 int disable = 0;
13327 // struct params params = {0};
13328
13329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13330 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13331 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13332 security->mode = wifi_security_mode_none;
13333 if (strlen(buf) != 0) {
13334 if (!strcmp(buf, "WPA-Personal"))
13335 security->mode = wifi_security_mode_wpa_personal;
13336 else if (!strcmp(buf, "WPA2-Personal"))
13337 security->mode = wifi_security_mode_wpa2_personal;
13338 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13339 security->mode = wifi_security_mode_wpa_wpa2_personal;
13340 else if (!strcmp(buf, "WPA-Enterprise"))
13341 security->mode = wifi_security_mode_wpa_enterprise;
13342 else if (!strcmp(buf, "WPA2-Enterprise"))
13343 security->mode = wifi_security_mode_wpa2_enterprise;
13344 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13345 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13346 else if (!strcmp(buf, "WPA3-Personal"))
13347 security->mode = wifi_security_mode_wpa3_personal;
13348 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13349 security->mode = wifi_security_mode_wpa3_transition;
13350 else if (!strcmp(buf, "WPA3-Enterprise"))
13351 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013352 else if (!strcmp(buf, "OWE"))
13353 security->mode = wifi_security_mode_owe;
developer72fb0bb2023-01-11 09:46:29 +080013354 }
13355
13356 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13357 if (security->mode == wifi_security_mode_none)
13358 security->encr = wifi_encryption_none;
13359 else {
13360 if (strcmp(buf, "TKIP") == 0)
13361 security->encr = wifi_encryption_tkip;
13362 else if (strcmp(buf, "CCMP") == 0)
13363 security->encr = wifi_encryption_aes;
13364 else
13365 security->encr = wifi_encryption_aes_tkip;
13366 }
13367
13368 if (security->mode != wifi_encryption_none) {
13369 memset(buf, 0, sizeof(buf));
13370 // wpa3 can use one or both configs as password, so we check sae_password first.
13371 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13372 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13373 security->u.key.type = wifi_security_key_type_sae;
13374 } else {
13375 security->u.key.type = wifi_security_key_type_psk;
13376 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13377 }
13378 strncpy(security->u.key.key, buf, sizeof(buf));
13379 security->u.key.key[255] = '\0';
13380 }
13381
13382 memset(buf, 0, sizeof(buf));
13383 wifi_getApSecurityMFPConfig(ap_index, buf);
13384 if (strcmp(buf, "Disabled") == 0)
13385 security->mfp = wifi_mfp_cfg_disabled;
13386 else if (strcmp(buf, "Optional") == 0)
13387 security->mfp = wifi_mfp_cfg_optional;
13388 else if (strcmp(buf, "Required") == 0)
13389 security->mfp = wifi_mfp_cfg_required;
13390
13391 memset(buf, 0, sizeof(buf));
13392 security->wpa3_transition_disable = FALSE;
13393 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13394 disable = strtol(buf, NULL, 16);
13395 if (disable != 0)
13396 security->wpa3_transition_disable = TRUE;
13397
13398 memset(buf, 0, sizeof(buf));
13399 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13400 if (strlen(buf) == 0)
13401 security->rekey_interval = 86400;
13402 else
13403 security->rekey_interval = strtol(buf, NULL, 10);
13404
13405 memset(buf, 0, sizeof(buf));
13406 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13407 if (strlen(buf) == 0)
13408 security->strict_rekey = 1;
13409 else
13410 security->strict_rekey = strtol(buf, NULL, 10);
13411
13412 memset(buf, 0, sizeof(buf));
13413 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13414 if (strlen(buf) == 0)
13415 security->eapol_key_retries = 4;
13416 else
13417 security->eapol_key_retries = strtol(buf, NULL, 10);
13418
13419 memset(buf, 0, sizeof(buf));
13420 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13421 if (strlen(buf) == 0)
13422 security->disable_pmksa_caching = FALSE;
13423 else
13424 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13425
13426 /* TODO
13427 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13428 */
13429 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13430 security->eap_identity_req_timeout = 0;
13431 security->eap_identity_req_retries = 0;
13432 security->eap_req_timeout = 0;
13433 security->eap_req_retries = 0;
13434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13435 return RETURN_OK;
13436}
13437
13438#endif /* WIFI_HAL_VERSION_3 */
13439
13440#ifdef WIFI_HAL_VERSION_3_PHASE2
13441INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13442{
13443 char interface_name[16] = {0};
13444 char cmd[128] = {0};
13445 char buf[128] = {0};
13446 char *mac_addr = NULL;
13447 BOOL status = FALSE;
13448 size_t len = 0;
13449
13450 if(ap_index > MAX_APS)
13451 return RETURN_ERR;
13452
13453 *output_numDevices = 0;
13454 wifi_getApEnable(ap_index, &status);
13455 if (status == FALSE)
13456 return RETURN_OK;
13457
13458 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13459 return RETURN_ERR;
13460 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13461 _syscmd(cmd, buf, sizeof(buf));
13462
13463 mac_addr = strtok(buf, "\n");
13464 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13465 *output_numDevices = i + 1;
13466 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13467 addr_ptr = output_deviceMacAddressArray[i];
13468 mac_addr_aton(addr_ptr, mac_addr);
13469 mac_addr = strtok(NULL, "\n");
13470 }
13471
13472 return RETURN_OK;
13473}
13474#else
13475INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13476{
13477 char interface_name[16] = {0};
13478 char cmd[128];
13479 BOOL status = false;
13480
13481 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13482 return RETURN_ERR;
13483
13484 output_buf[0] = '\0';
13485
13486 wifi_getApEnable(ap_index,&status);
13487 if (!status)
13488 return RETURN_OK;
13489
13490 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13491 return RETURN_ERR;
13492 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13493 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080013494
developer72fb0bb2023-01-11 09:46:29 +080013495 return RETURN_OK;
13496}
13497#endif
13498
13499INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13500{
13501 char output[16]={'\0'};
13502 char config_file[MAX_BUF_SIZE] = {0};
13503
13504 if (!enable)
13505 return RETURN_ERR;
13506
13507 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13508 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13509
13510 if (strlen(output) == 0)
13511 *enable = FALSE;
13512 else if (strncmp(output, "1", 1) == 0)
13513 *enable = TRUE;
13514 else
13515 *enable = FALSE;
13516
13517 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13518 return RETURN_OK;
13519}
13520
13521INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13522{
13523 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13524 return RETURN_ERR;
13525 *output_enable=TRUE;
13526 return RETURN_OK;
13527}
13528
13529INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13530{
13531 char cmd[128] = {0};
13532 char buf[128] = {0};
13533 char line[128] = {0};
13534 size_t len = 0;
13535 FILE *f = NULL;
13536 int index = 0;
13537 int exp = 0;
13538 int mantissa = 0;
13539 int duration = 0;
13540 int radio_index = 0;
13541 int max_radio_num = 0;
13542 uint twt_wake_interval = 0;
13543 int phyId = 0;
13544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13545
13546 wifi_getMaxRadioNumber(&max_radio_num);
13547
13548 radio_index = ap_index % max_radio_num;
13549
13550 phyId = radio_index_to_phy(radio_index);
13551 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13552 _syscmd(cmd, buf, sizeof(buf));
13553 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13554 if (*numSessionReturned > maxNumberSessions)
13555 *numSessionReturned = maxNumberSessions;
13556 else if (*numSessionReturned < 1) {
13557 *numSessionReturned = 0;
13558 return RETURN_OK;
13559 }
13560
13561 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13562 if ((f = popen(cmd, "r")) == NULL) {
13563 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13564 return RETURN_ERR;
13565 }
13566
13567 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13568 while((fgets(line, sizeof(line), f)) != NULL) {
13569 char *tmp = NULL;
13570 strcpy(buf, line);
13571 tmp = strtok(buf, " ");
13572 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13573 tmp = strtok(NULL, " ");
13574 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13575 tmp = strtok(NULL, " ");
13576 if (strstr(tmp, "t")) {
13577 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13578 }
13579 if (strstr(tmp, "a")) {
13580 twtSessions[index].twtParameters.operation.announced = TRUE;
13581 }
13582 tmp = strtok(NULL, " ");
13583 exp = strtol(tmp, NULL, 10);
13584 tmp = strtok(NULL, " ");
13585 mantissa = strtol(tmp, NULL, 10);
13586 tmp = strtok(NULL, " ");
13587 duration = strtol(tmp, NULL, 10);
13588
13589 // only implicit supported
13590 twtSessions[index].twtParameters.operation.implicit = TRUE;
13591 // only individual agreement supported
13592 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13593
13594 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13595 twt_wake_interval = mantissa * (1 << exp);
13596 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13597 // Overflow handling
13598 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13599 } else {
13600 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13601 }
13602 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13603 index++;
13604 }
13605
13606 pclose(f);
13607 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13608 return RETURN_OK;
13609}