blob: a51a4449315b6677f88a501f0da2487639d0a060 [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
98#ifndef AP_PREFIX
99#define AP_PREFIX "wifi"
100#endif
101
102#ifndef RADIO_PREFIX
103#define RADIO_PREFIX "wlan"
104#endif
105
106#define MAX_ASSOCIATED_STA_NUM 2007
107
108//Uncomment to enable debug logs
109//#define WIFI_DEBUG
110
111#ifdef WIFI_DEBUG
112#define wifi_dbg_printf printf
113#define WIFI_ENTRY_EXIT_DEBUG printf
114#else
115#define wifi_dbg_printf(format, args...) printf("")
116#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
117#endif
118
119#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
120#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
121#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
122#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
123#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
124#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
125#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
126#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
127#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
128#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
129
130#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
131
132#define BW_FNAME "/nvram/bw_file.txt"
133
134#define PS_MAX_TID 16
135
136static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
137 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
138 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
139 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
140 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
141 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
142 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
143 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
144 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
153};
154
155typedef unsigned long long u64;
156
157/* Enum to define WiFi Bands */
158typedef enum
159{
160 band_invalid = -1,
161 band_2_4 = 0,
162 band_5 = 1,
163 band_6 = 2,
164} wifi_band;
165
166typedef enum {
167 WIFI_MODE_A = 0x01,
168 WIFI_MODE_B = 0x02,
169 WIFI_MODE_G = 0x04,
170 WIFI_MODE_N = 0x08,
171 WIFI_MODE_AC = 0x10,
172 WIFI_MODE_AX = 0x20,
173} wifi_ieee80211_Mode;
174
175#ifdef WIFI_HAL_VERSION_3
176
177// Return number of elements in array
178#ifndef ARRAY_SIZE
179#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
180#endif /* ARRAY_SIZE */
181
182#ifndef ARRAY_AND_SIZE
183#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
184#endif /* ARRAY_AND_SIZE */
185
186#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
187
188typedef struct {
189 int32_t value;
190 int32_t param;
191 intptr_t key;
192 intptr_t data;
193} wifi_secur_list;
194
195static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
196static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
197wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
198wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
199char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
200static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
201
202static wifi_secur_list map_security[] =
203{
204 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
205 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
206 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
207 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
208 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
209 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
210 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
211 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
216};
217
218wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
219{
220 wifi_secur_list *item;
221 int i;
222
223 for (item = list,i = 0;i < list_sz; item++, i++) {
224 if ((int)(item->key) == key) {
225 return item;
226 }
227 }
228
229 return NULL;
230}
231
232char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
233{
234 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
235
236 if (!item) {
237 return "";
238 }
239
240 return (char *)(item->data);
241}
242
243wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
244{
245 wifi_secur_list *item;
246 int i;
247
248 for (item = list,i = 0;i < list_sz; item++, i++) {
249 if (strcmp((char *)(item->data), str) == 0) {
250 return item;
251 }
252 }
253
254 return NULL;
255}
256#endif /* WIFI_HAL_VERSION_3 */
257
258#ifdef HAL_NETLINK_IMPL
259typedef struct {
260 int id;
261 struct nl_sock* socket;
262 struct nl_cb* cb;
263} Netlink;
264
265static int mac_addr_aton(unsigned char *mac_addr, char *arg)
266{
267 unsigned int mac_addr_int[6]={};
268 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);
269 mac_addr[0] = mac_addr_int[0];
270 mac_addr[1] = mac_addr_int[1];
271 mac_addr[2] = mac_addr_int[2];
272 mac_addr[3] = mac_addr_int[3];
273 mac_addr[4] = mac_addr_int[4];
274 mac_addr[5] = mac_addr_int[5];
275 return 0;
276}
277
278static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
279{
280 unsigned int mac_addr_int[6]={};
281 mac_addr_int[0] = arg[0];
282 mac_addr_int[1] = arg[1];
283 mac_addr_int[2] = arg[2];
284 mac_addr_int[3] = arg[3];
285 mac_addr_int[4] = arg[4];
286 mac_addr_int[5] = arg[5];
287 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]);
288 return;
289}
290
291static int ieee80211_frequency_to_channel(int freq)
292{
293 /* see 802.11-2007 17.3.8.3.2 and Annex J */
294 if (freq == 2484)
295 return 14;
296 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
297 else if (freq == 5935)
298 return 2;
299 else if (freq < 2484)
300 return (freq - 2407) / 5;
301 else if (freq >= 4910 && freq <= 4980)
302 return (freq - 4000) / 5;
303 else if (freq < 5950)
304 return (freq - 5000) / 5;
305 else if (freq <= 45000) /* DMG band lower limit */
306 /* see 802.11ax D6.1 27.3.23.2 */
307 return (freq - 5950) / 5;
308 else if (freq >= 58320 && freq <= 70200)
309 return (freq - 56160) / 2160;
310 else
311 return 0;
312}
313
314static int initSock80211(Netlink* nl) {
315 nl->socket = nl_socket_alloc();
316 if (!nl->socket) {
317 fprintf(stderr, "Failing to allocate the sock\n");
318 return -ENOMEM;
319 }
320
321 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
322
323 if (genl_connect(nl->socket)) {
324 fprintf(stderr, "Failed to connect\n");
325 nl_close(nl->socket);
326 nl_socket_free(nl->socket);
327 return -ENOLINK;
328 }
329
330 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
331 if (nl->id< 0) {
332 fprintf(stderr, "interface not found.\n");
333 nl_close(nl->socket);
334 nl_socket_free(nl->socket);
335 return -ENOENT;
336 }
337
338 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
339 if ((!nl->cb)) {
340 fprintf(stderr, "Failed to allocate netlink callback.\n");
341 nl_close(nl->socket);
342 nl_socket_free(nl->socket);
343 return ENOMEM;
344 }
345
346 return nl->id;
347}
348
349static int nlfree(Netlink *nl)
350{
351 nl_cb_put(nl->cb);
352 nl_close(nl->socket);
353 nl_socket_free(nl->socket);
354 return 0;
355}
356
357static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
358 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
359 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
360 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
361};
362
363static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
364};
365
366static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
367};
368
369typedef struct _wifi_channelStats_loc {
370 INT array_size;
371 INT ch_number;
372 BOOL ch_in_pool;
373 INT ch_noise;
374 BOOL ch_radar_noise;
375 INT ch_max_80211_rssi;
376 INT ch_non_80211_noise;
377 INT ch_utilization;
378 ULLONG ch_utilization_total;
379 ULLONG ch_utilization_busy;
380 ULLONG ch_utilization_busy_tx;
381 ULLONG ch_utilization_busy_rx;
382 ULLONG ch_utilization_busy_self;
383 ULLONG ch_utilization_busy_ext;
384} wifi_channelStats_t_loc;
385
386typedef struct wifi_device_info {
387 INT wifi_devIndex;
388 UCHAR wifi_devMacAddress[6];
389 CHAR wifi_devIPAddress[64];
390 BOOL wifi_devAssociatedDeviceAuthentiationState;
391 INT wifi_devSignalStrength;
392 INT wifi_devTxRate;
393 INT wifi_devRxRate;
394} wifi_device_info_t;
395
396#endif
397
398//For 5g Alias Interfaces
399static BOOL priv_flag = TRUE;
400static BOOL pub_flag = TRUE;
401static BOOL Radio_flag = TRUE;
402//wifi_setApBeaconRate(1, beaconRate);
403
404BOOL multiple_set = FALSE;
405
406struct params
407{
408 char * name;
409 char * value;
410};
411
412static int _syscmd(char *cmd, char *retBuf, int retBufSize)
413{
414 FILE *f;
415 char *ptr = retBuf;
416 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
417
418 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
419 if((f = popen(cmd, "r")) == NULL) {
420 fprintf(stderr,"\npopen %s error\n", cmd);
421 return RETURN_ERR;
422 }
423
424 while(!feof(f))
425 {
426 *ptr = 0;
427 if(bufSize>=128) {
428 bufbytes=128;
429 } else {
430 bufbytes=bufSize-1;
431 }
432
433 fgets(ptr,bufbytes,f);
434 readbytes=strlen(ptr);
435
436 if(!readbytes)
437 break;
438
439 bufSize-=readbytes;
440 ptr += readbytes;
441 }
442 cmd_ret = pclose(f);
443 retBuf[retBufSize-1]=0;
444 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
445
446 return cmd_ret >> 8;
447}
448
449INT radio_index_to_phy(int radioIndex)
450{
451 char cmd[128] = {0};
452 char buf[64] = {0};
453 int phyIndex = 0;
454 snprintf(cmd, sizeof(cmd), "ls /tmp | grep wifi%d | cut -d '-' -f1 | tr -d '\n'", radioIndex);
455 _syscmd(cmd, buf, sizeof(buf));
456
457 if (strlen(buf) == 0 || strstr(buf, "phy") == NULL) {
458 fprintf(stderr, "%s: failed to get phy index with: %d\n", __func__, radioIndex);
459 return RETURN_ERR;
460 }
461 sscanf(buf, "phy%d", &phyIndex);
462
463 return phyIndex;
464}
465
466INT wifi_getMaxRadioNumber(INT *max_radio_num)
467{
468 char cmd[64] = {0};
469 char buf[4] = {0};
470
471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
472
473 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
474 _syscmd(cmd, buf, sizeof(buf));
475 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
476
477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
478
479 return RETURN_OK;
480}
481
482wifi_band wifi_index_to_band(int apIndex)
483{
484 char cmd[128] = {0};
485 char buf[64] = {0};
486 int nl80211_band = 0;
487 int i = 0;
488 int phyIndex = 0;
489 int radioIndex = 0;
490 int max_radio_num = 0;
491 wifi_band band = band_invalid;
492
493 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
494
495 wifi_getMaxRadioNumber(&max_radio_num);
496 radioIndex = apIndex % max_radio_num;
497 phyIndex = radio_index_to_phy(radioIndex);
498 while(i < 10){
499 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
500 _syscmd(cmd, buf, sizeof(buf));
501 nl80211_band = strtol(buf, NULL, 10);
502 if (nl80211_band == 1)
503 band = band_2_4;
504 else if (nl80211_band == 2)
505 band = band_5;
506 else if (nl80211_band == 4) // band == 3 is 60GHz
507 band = band_6;
508
509 if(band != band_invalid)
510 break;
511
512 i++;
513 sleep(1);
514 }
515
516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
517 return band;
518}
519
520static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
521{
522 char cmd[MAX_CMD_SIZE]={'\0'};
523 char buf[MAX_BUF_SIZE]={'\0'};
524 int ret = 0;
525
526 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
527 ret = _syscmd(cmd, buf, sizeof(buf));
528 if ((ret != 0) && (strlen(buf) == 0))
529 return -1;
530 snprintf(output, output_size, "%s", buf);
531
532 return 0;
533}
534
535static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
536{
537 char cmd[MAX_CMD_SIZE]={'\0'};
538 char buf[MAX_BUF_SIZE]={'\0'};
539
540 for(int i=0;i<item_count;i++)
541 {
542 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
543 if (strlen(buf) == 0) //Insert
544 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
545 else //Update
546 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
547
548 if(_syscmd(cmd, buf, sizeof(buf)))
549 return -1;
550 }
551
552 return 0;
553}
554
555//For Getting Current Interface Name from corresponding hostapd configuration
556static int wifi_GetInterfaceName(int apIndex, char *interface_name)
557{
558 char config_file[128] = {0};
559
560 if (interface_name == NULL)
561 return RETURN_ERR;
562
563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
564
565 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
566 wifi_hostapdRead(config_file, "interface", interface_name, 16);
567 if (strlen(interface_name) == 0)
568 return RETURN_ERR;
569
570 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
571 return RETURN_OK;
572}
573
574// wifi agent will call this function, do not change the parameter
575void GetInterfaceName(char *interface_name, char *conf_file)
576{
577 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
578 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
580}
581
582static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
583{
584 char interface_name[16] = {0};
585 if (multiple_set == TRUE)
586 return RETURN_OK;
587 char cmd[MAX_CMD_SIZE]="", output[32]="";
588 FILE *fp;
589 int i;
590 //NOTE RELOAD should be done in ApplySSIDSettings
591 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
592 return RETURN_ERR;
593 for(i=0; i<item_count; i++, list++)
594 {
595 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
596 if((fp = popen(cmd, "r"))==NULL)
597 {
598 perror("popen failed");
599 return -1;
600 }
601 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
602 {
603 pclose(fp);
604 perror("fgets failed");
605 return -1;
606 }
607 pclose(fp);
608 }
609 return 0;
610}
611
612static int wifi_reloadAp(int apIndex)
613{
614 char interface_name[16] = {0};
615 if (multiple_set == TRUE)
616 return RETURN_OK;
617 char cmd[MAX_CMD_SIZE]="";
618 char buf[MAX_BUF_SIZE]="";
619
620 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
621 return RETURN_ERR;
622 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
623 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
624 return RETURN_ERR;
625
626 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
627 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
628 return RETURN_ERR;
629
630 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
631 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
632 return RETURN_ERR;
633
634 return RETURN_OK;
635}
636
637INT File_Reading(CHAR *file, char *Value)
638{
639 FILE *fp = NULL;
640 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
641 int count = 0;
642
643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
644 fp = popen(file,"r");
645 if(fp == NULL)
646 return RETURN_ERR;
647
648 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
649 {
650 for(count=0;buf[count]!='\n';count++)
651 copy_buf[count]=buf[count];
652 copy_buf[count]='\0';
653 }
654 strcpy(Value,copy_buf);
655 pclose(fp);
656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
657
658 return RETURN_OK;
659}
660
661void wifi_RestartHostapd_2G()
662{
663 int Public2GApIndex = 4;
664
665 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
666 wifi_setApEnable(Public2GApIndex, FALSE);
667 wifi_setApEnable(Public2GApIndex, TRUE);
668 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
669}
670
671void wifi_RestartHostapd_5G()
672{
673 int Public5GApIndex = 5;
674
675 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
676 wifi_setApEnable(Public5GApIndex, FALSE);
677 wifi_setApEnable(Public5GApIndex, TRUE);
678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
679}
680
681void wifi_RestartPrivateWifi_2G()
682{
683 int PrivateApIndex = 0;
684
685 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
686 wifi_setApEnable(PrivateApIndex, FALSE);
687 wifi_setApEnable(PrivateApIndex, TRUE);
688 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
689}
690
691void wifi_RestartPrivateWifi_5G()
692{
693 int Private5GApIndex = 1;
694
695 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
696 wifi_setApEnable(Private5GApIndex, FALSE);
697 wifi_setApEnable(Private5GApIndex, TRUE);
698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
699}
700
701static int writeBandWidth(int radioIndex,char *bw_value)
702{
703 char buf[MAX_BUF_SIZE];
704 char cmd[MAX_CMD_SIZE];
705
706 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
707 if(_syscmd(cmd, buf, sizeof(buf)))
708 {
709 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
710 _syscmd(cmd, buf, sizeof(buf));
711 return RETURN_OK;
712 }
713
714 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
715 _syscmd(cmd,buf,sizeof(buf));
716 return RETURN_OK;
717}
718
719static int readBandWidth(int radioIndex,char *bw_value)
720{
721 char buf[MAX_BUF_SIZE] = {0};
722 char cmd[MAX_CMD_SIZE] = {0};
723 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
724 _syscmd(cmd,buf,sizeof(buf));
725 if(NULL!=strstr(buf,"20MHz"))
726 {
727 strcpy(bw_value,"20MHz");
728 }
729 else if(NULL!=strstr(buf,"40MHz"))
730 {
731 strcpy(bw_value,"40MHz");
732 }
733 else if(NULL!=strstr(buf,"80MHz"))
734 {
735 strcpy(bw_value,"80MHz");
736 }
737 else
738 {
739 return RETURN_ERR;
740 }
741 return RETURN_OK;
742}
743
744// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
745INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
746{
747 struct params params={'\0'};
748 char config_file[MAX_BUF_SIZE] = {0};
749 char buf[MAX_BUF_SIZE] = {'\0'};
750
751 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
752 // Copy the numeric value
753 if (strlen (beaconRate) >= 5) {
754 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
755 buf[strlen(beaconRate) - 4] = '\0';
756 } else if (strlen(beaconRate) > 0)
757 strcpy(buf, beaconRate);
758 else
759 return RETURN_ERR;
760
761 params.name = "beacon_rate";
762 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
763 if (strncmp(buf, "5.5", 3) == 0) {
764 snprintf(buf, sizeof(buf), "55");
765 params.value = buf;
766 } else {
767 strcat(buf, "0");
768 params.value = buf;
769 }
770
771 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
772 wifi_hostapdWrite(config_file, &params, 1);
773 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
775
776 return RETURN_OK;
777}
778
779INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
780{
781 char config_file[128] = {'\0'};
782 char temp_output[128] = {'\0'};
783 char buf[128] = {'\0'};
784 char cmd[128] = {'\0'};
785 int rate = 0;
786 int phyId = 0;
787
788 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
789 if (NULL == beaconRate)
790 return RETURN_ERR;
791
792 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
793 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
794 phyId = radio_index_to_phy(radioIndex);
795 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
796 if(strlen(buf) > 0) {
797 if (strncmp(buf, "55", 2) == 0)
798 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
799 else {
800 rate = strtol(buf, NULL, 10)/10;
801 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
802 }
803 } else {
804 // config not set, so we would use lowest rate as default
805 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
806 _syscmd(cmd, buf, sizeof(buf));
807 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
808 }
809 strncpy(beaconRate, temp_output, sizeof(temp_output));
810 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
811
812 return RETURN_OK;
813}
814
815INT wifi_setLED(INT radioIndex, BOOL enable)
816{
817 return 0;
818}
819INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
820{
821 return RETURN_OK;
822}
823/**********************************************************************************
824 *
825 * Wifi Subsystem level function prototypes
826 *
827**********************************************************************************/
828//---------------------------------------------------------------------------------------------------
829//Wifi system api
830//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
831INT wifi_getHalVersion(CHAR *output_string) //RDKB
832{
833 if(!output_string)
834 return RETURN_ERR;
835 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
836
837 return RETURN_OK;
838}
839
840
841/* wifi_factoryReset() function */
842/**
843* @description Clears internal variables to implement a factory reset of the Wi-Fi
844* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
845*
846* @param None
847*
848* @return The status of the operation.
849* @retval RETURN_OK if successful.
850* @retval RETURN_ERR if any error is detected
851*
852* @execution Synchronous
853* @sideeffect None
854*
855* @note This function must not suspend and must not invoke any blocking system
856* calls. It should probably just send a message to a driver event handler task.
857*
858*/
859INT wifi_factoryReset()
860{
861 char cmd[128];
862
863 /*delete running hostapd conf files*/
864 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
865 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
866 system(cmd);
867 system("systemctl restart hostapd.service");
868
869 return RETURN_OK;
870}
871
872/* wifi_factoryResetRadios() function */
873/**
874* @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.
875*
876* @param None
877* @return The status of the operation
878* @retval RETURN_OK if successful
879* @retval RETURN_ERR if any error is detected
880*
881* @execution Synchronous
882*
883* @sideeffect None
884*
885* @note This function must not suspend and must not invoke any blocking system
886* calls. It should probably just send a message to a driver event handler task.
887*
888*/
889INT wifi_factoryResetRadios()
890{
891 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
892 return RETURN_OK;
893
894 return RETURN_ERR;
895}
896
897
898/* wifi_factoryResetRadio() function */
899/**
900* @description Restore selected radio parameters without touching access point parameters
901*
902* @param radioIndex - Index of Wi-Fi Radio channel
903*
904* @return The status of the operation.
905* @retval RETURN_OK if successful.
906* @retval RETURN_ERR if any error is detected
907*
908* @execution Synchronous.
909* @sideeffect None.
910*
911* @note This function must not suspend and must not invoke any blocking system
912* calls. It should probably just send a message to a driver event handler task.
913*
914*/
915INT wifi_factoryResetRadio(int radioIndex) //RDKB
916{
917 system("systemctl stop hostapd.service");
918
919 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
920 if(radioIndex == 0)
921 system("rm /nvram/hostapd0.conf");
922 else if(radioIndex == 1)
923 system("rm /nvram/hostapd1.conf");
924 else
925 return RETURN_ERR;
926
927 system("systemctl start hostapd.service");
928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
929 return RETURN_OK;
930}
931
932/* wifi_initRadio() function */
933/**
934* Description: This function call initializes the specified radio.
935* Implementation specifics may dictate the functionality since
936* different hardware implementations may have different initilization requirements.
937* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
938*
939* @return The status of the operation.
940* @retval RETURN_OK if successful.
941* @retval RETURN_ERR if any error is detected
942*
943* @execution Synchronous.
944* @sideeffect None.
945*
946* @note This function must not suspend and must not invoke any blocking system
947* calls. It should probably just send a message to a driver event handler task.
948*
949*/
950INT wifi_initRadio(INT radioIndex)
951{
952 //TODO: Initializes the wifi subsystem (for specified radio)
953 return RETURN_OK;
954}
955void macfilter_init()
956{
957 char count[4]={'\0'};
958 char buf[253]={'\0'};
959 char tmp[19]={'\0'};
960 int dev_count,block,mac_entry=0;
961 char res[4]={'\0'};
962 char acl_file_path[64] = {'\0'};
963 FILE *fp = NULL;
964 int index=0;
965 char iface[10]={'\0'};
966 char config_file[MAX_BUF_SIZE] = {0};
967
968
969 sprintf(acl_file_path,"/tmp/mac_filter.sh");
970
971 fp=fopen(acl_file_path,"w+");
972 if (fp == NULL) {
973 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
974 return RETURN_ERR;
975 }
976 sprintf(buf,"#!/bin/sh \n");
977 fprintf(fp,"%s\n",buf);
978
979 system("chmod 0777 /tmp/mac_filter.sh");
980
981 for(index=0;index<=1;index++)
982 {
983 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
984 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
985 sprintf(buf,"syscfg get %dcountfilter",index);
986 _syscmd(buf,count,sizeof(count));
987 mac_entry=atoi(count);
988
989 sprintf(buf,"syscfg get %dblockall",index);
990 _syscmd(buf,res,sizeof(res));
991 block = atoi(res);
992
993 //Allow only those macs mentioned in ACL
994 if(block==1)
995 {
996 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
997 fprintf(fp,"%s\n",buf);
998 for(dev_count=1;dev_count<=mac_entry;dev_count++)
999 {
1000 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1001 _syscmd(buf,tmp,sizeof(tmp));
1002 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1003 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1004 fprintf(fp,"%s\n",buf);
1005 }
1006 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1007 fprintf(fp,"%s\n",buf);
1008 }
1009
1010 //Block all the macs mentioned in ACL
1011 else if(block==2)
1012 {
1013 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1014 fprintf(fp,"%s\n",buf);
1015
1016 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1017 {
1018 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1019 _syscmd(buf,tmp,sizeof(tmp));
1020 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1021 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1022 fprintf(fp,"%s\n",buf);
1023 }
1024 }
1025 }
1026 fclose(fp);
1027}
1028
1029// Initializes the wifi subsystem (all radios)
1030INT wifi_init() //RDKB
1031{
1032 char interface[MAX_BUF_SIZE]={'\0'};
1033 char bridge_name[MAX_BUF_SIZE]={'\0'};
1034 INT len=0;
1035
1036 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1037 //Not intitializing macfilter for Turris-Omnia Platform for now
1038 //macfilter_init();
1039
1040 system("/usr/sbin/iw reg set US");
1041 // system("systemctl start hostapd.service");
1042 sleep(2);//sleep to wait for hostapd to start
1043
1044 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1045
1046 return RETURN_OK;
1047}
1048
1049/* wifi_reset() function */
1050/**
1051* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1052* Implementation specifics may dictate what is actualy reset since
1053* different hardware implementations may have different requirements.
1054* Parameters : None
1055*
1056* @return The status of the operation.
1057* @retval RETURN_OK if successful.
1058* @retval RETURN_ERR if any error is detected
1059*
1060* @execution Synchronous.
1061* @sideeffect None.
1062*
1063* @note This function must not suspend and must not invoke any blocking system
1064* calls. It should probably just send a message to a driver event handler task.
1065*
1066*/
1067INT wifi_reset()
1068{
1069 //TODO: resets the wifi subsystem, deletes all APs
1070 system("systemctl stop hostapd.service");
1071 sleep(2);
1072 system("systemctl start hostapd.service");
1073 sleep(5);
1074 return RETURN_OK;
1075}
1076
1077/* wifi_down() function */
1078/**
1079* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1080* Implementation specifics may dictate some functionality since
1081* different hardware implementations may have different requirements.
1082*
1083* @param None
1084*
1085* @return The status of the operation
1086* @retval RETURN_OK if successful
1087* @retval RETURN_ERR if any error is detected
1088*
1089* @execution Synchronous
1090* @sideeffect None
1091*
1092* @note This function must not suspend and must not invoke any blocking system
1093* calls. It should probably just send a message to a driver event handler task.
1094*
1095*/
1096INT wifi_down()
1097{
1098 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
1099 system("systemctl stop hostapd.service");
1100 sleep(2);
1101 return RETURN_OK;
1102}
1103
1104
1105/* wifi_createInitialConfigFiles() function */
1106/**
1107* @description This function creates wifi configuration files. The format
1108* and content of these files are implementation dependent. This function call is
1109* used to trigger this task if necessary. Some implementations may not need this
1110* function. If an implementation does not need to create config files the function call can
1111* do nothing and return RETURN_OK.
1112*
1113* @param None
1114*
1115* @return The status of the operation
1116* @retval RETURN_OK if successful
1117* @retval RETURN_ERR if any error is detected
1118*
1119* @execution Synchronous
1120* @sideeffect None
1121*
1122* @note This function must not suspend and must not invoke any blocking system
1123* calls. It should probably just send a message to a driver event handler task.
1124*
1125*/
1126INT wifi_createInitialConfigFiles()
1127{
1128 //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)
1129 return RETURN_OK;
1130}
1131
1132// outputs the country code to a max 64 character string
1133INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1134{
1135 char interface_name[16] = {0};
1136 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1137 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
1138 return RETURN_ERR;
1139
1140 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1141 return RETURN_ERR;
1142 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
1143 _syscmd(cmd, buf, sizeof(buf));
1144 if(strlen(buf) > 0)
1145 snprintf(output_string, 64, "%s", buf);
1146 else
1147 return RETURN_ERR;
1148
1149 return RETURN_OK;
1150}
1151
1152INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1153{
1154 //Set wifi config. Wait for wifi reset to apply
1155 char str[MAX_BUF_SIZE]={'\0'};
1156 char cmd[MAX_CMD_SIZE]={'\0'};
1157 struct params params;
1158 char config_file[MAX_BUF_SIZE] = {0};
1159
1160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1161 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1162 return RETURN_ERR;
1163
1164 if (strlen(CountryCode) == 0)
1165 strcpy(CountryCode, "US");
1166
1167 params.name = "country_code";
1168 params.value = CountryCode;
1169 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1170 int ret = wifi_hostapdWrite(config_file, &params, 1);
1171 if (ret) {
1172 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1173 ,__func__, ret);
1174 }
1175
1176 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1177 if (ret) {
1178 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1179 ,__func__, ret);
1180 }
1181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1182
1183 return RETURN_OK;
1184}
1185
1186INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1187{
1188 char interface_name[16] = {0};
1189 char channel_util_file[64] = {0};
1190 char cmd[128] = {0};
1191 char buf[128] = {0};
1192 char line[128] = {0};
1193 char *param = NULL, *value = NULL;
1194 int read = 0;
1195 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1196 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1197 size_t len = 0;
1198 FILE *f = NULL;
1199
1200 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1201
1202 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1203 return RETURN_ERR;
1204 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1205 _syscmd(cmd, buf, sizeof(buf));
1206 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1207
1208 memset(cmd, 0, sizeof(cmd));
1209 memset(buf, 0, sizeof(buf));
1210 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1211 if ((f = popen(cmd, "r")) == NULL) {
1212 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1213 return RETURN_ERR;
1214 }
1215
1216 read = getline(&line, &len, f);
1217 while (read != -1) {
1218 param = strtok(line, ":\t");
1219 value = strtok(NULL, " ");
1220 if(strstr(param, "frequency") != NULL) {
1221 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1222 }
1223 if(strstr(param, "noise") != NULL) {
1224 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1225 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1226 }
1227 if(strstr(param, "channel active time") != NULL) {
1228 ActiveTime = strtol(value, NULL, 10);
1229 }
1230 if(strstr(param, "channel busy time") != NULL) {
1231 BusyTime = strtol(value, NULL, 10);
1232 }
1233 if(strstr(param, "channel transmit time") != NULL) {
1234 TransmitTime = strtol(value, NULL, 10);
1235 }
1236 read = getline(&line, &len, f);
1237 }
1238 pclose(f);
1239
1240 // The file should store the last active, busy and transmit time
1241 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1242 f = fopen(channel_util_file, "r");
1243 if (f != NULL) {
1244 read = getline(&line, &len, f);
1245 preActiveTime = strtol(line, NULL, 10);
1246 read = getline(&line, &len, f);
1247 preBusyTime = strtol(line, NULL, 10);
1248 read = getline(&line, &len, f);
1249 preTransmitTime = strtol(line, NULL, 10);
1250 fclose(f);
1251 }
1252
1253 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1254 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1255
1256 f = fopen(channel_util_file, "w");
1257 if (f != NULL) {
1258 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1259 fclose(f);
1260 }
1261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1262 return RETURN_OK;
1263}
1264
1265/**********************************************************************************
1266 *
1267 * Wifi radio level function prototypes
1268 *
1269**********************************************************************************/
1270
1271//Get the total number of radios in this wifi subsystem
1272INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1273{
1274 if (NULL == output)
1275 return RETURN_ERR;
1276 *output = MAX_NUM_RADIOS;
1277
1278 return RETURN_OK;
1279}
1280
1281//Get the total number of SSID entries in this wifi subsystem
1282INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1283{
1284 if (NULL == output)
1285 return RETURN_ERR;
1286 *output = MAX_APS;
1287
1288 return RETURN_OK;
1289}
1290
1291//Get the Radio enable config parameter
1292INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1293{
1294 char interface_name[16] = {0};
1295 char buf[128] = {0}, cmd[128] = {0};
1296
1297 if (NULL == output_bool)
1298 return RETURN_ERR;
1299
1300 *output_bool = FALSE;
1301 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1302 return RETURN_ERR;
1303
1304 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1305 return RETURN_ERR;
1306 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1307 _syscmd(cmd, buf, sizeof(buf));
1308
1309 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1310 *output_bool = TRUE;
1311 return RETURN_OK;
1312}
1313
1314INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1315{
1316 char interface_name[16] = {0};
1317 char cmd[MAX_CMD_SIZE] = {0};
1318 char buf[MAX_CMD_SIZE] = {0};
1319 int apIndex, ret;
1320 int max_radio_num = 0;
1321 int phyId = 0;
1322
1323 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1324
1325 phyId = radio_index_to_phy(radioIndex);
1326
1327 wifi_getMaxRadioNumber(&max_radio_num);
1328
1329 if(enable==FALSE)
1330 {
1331 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1332 {
1333 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1334 return RETURN_ERR;
1335
1336 //Detaching %s%d from hostapd daemon
1337 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
1338 _syscmd(cmd, buf, sizeof(buf));
1339 if(strncmp(buf, "OK", 2))
1340 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1341
1342 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1343 _syscmd(cmd, buf, sizeof(buf));
1344 }
1345 }
1346 else
1347 {
1348 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1349 {
1350 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1351 return RETURN_ERR;
1352
1353 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1354 ret = _syscmd(cmd, buf, sizeof(buf));
1355 if ( ret == RETURN_ERR)
1356 {
1357 fprintf(stderr, "VAP interface creation failed\n");
1358 continue;
1359 }
1360 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1361 _syscmd(cmd, buf, sizeof(buf));
1362 if(*buf == '1')
1363 {
1364 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1365 phyId, apIndex);
1366 _syscmd(cmd, buf, sizeof(buf));
1367 if(strncmp(buf, "OK", 2))
1368 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1369 }
1370 }
1371 }
1372
1373 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1374 return RETURN_OK;
1375}
1376
1377//Get the Radio enable status
1378INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1379{
1380 if (NULL == output_bool)
1381 return RETURN_ERR;
1382
1383 return wifi_getRadioEnable(radioIndex, output_bool);
1384}
1385
1386//Get the Radio Interface name from platform, eg "wlan0"
1387INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1388{
1389 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1390 return RETURN_ERR;
1391 return wifi_GetInterfaceName(radioIndex, output_string);
1392}
1393
1394//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1395//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.
1396INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1397{
1398 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1399 // For max bit rate, we should always choose the best MCS
1400 char mode[64] = {0};
1401 char channel_bandwidth_str[64] = {0};
1402 char *tmp = NULL;
1403 UINT mode_map = 0;
1404 UINT num_subcarrier = 0;
1405 UINT code_bits = 0;
1406 float code_rate = 0; // use max code rate
1407 int NSS = 0;
1408 UINT Symbol_duration = 0;
1409 UINT GI_duration = 0;
1410 wifi_band band = band_invalid;
1411 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1412 BOOL enable = FALSE;
1413 float bit_rate = 0;
1414
1415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1416 if (NULL == output_string)
1417 return RETURN_ERR;
1418
1419 wifi_getRadioEnable(radioIndex, &enable);
1420 if (enable == FALSE) {
1421 snprintf(output_string, 64, "0 Mb/s");
1422 return RETURN_OK;
1423 }
1424
1425 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1426 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1427 return RETURN_ERR;
1428 }
1429
1430 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1431 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1432 return RETURN_ERR;
1433 }
1434
1435 if (gi == wifi_guard_interval_3200)
1436 GI_duration = 32;
1437 else if (gi == wifi_guard_interval_1600)
1438 GI_duration = 16;
1439 else if (gi == wifi_guard_interval_800)
1440 GI_duration = 8;
1441 else // auto, 400
1442 GI_duration = 4;
1443
1444 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1445 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1446 return RETURN_ERR;
1447 }
1448
1449 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1450 strcpy(channel_bandwidth_str, "160");
1451
1452 if (mode_map & WIFI_MODE_AX) {
1453 if (strstr(channel_bandwidth_str, "160") != NULL)
1454 num_subcarrier = 1960;
1455 else if (strstr(channel_bandwidth_str, "80") != NULL)
1456 num_subcarrier = 980;
1457 else if (strstr(channel_bandwidth_str, "40") != NULL)
1458 num_subcarrier = 468;
1459 else if (strstr(channel_bandwidth_str, "20") != NULL)
1460 num_subcarrier = 234;
1461 code_bits = 10;
1462 code_rate = (float)5/6;
1463 Symbol_duration = 128;
1464 } else if (mode_map & WIFI_MODE_AC) {
1465 if (strstr(channel_bandwidth_str, "160") != NULL)
1466 num_subcarrier = 468;
1467 else if (strstr(channel_bandwidth_str, "80") != NULL)
1468 num_subcarrier = 234;
1469 else if (strstr(channel_bandwidth_str, "40") != NULL)
1470 num_subcarrier = 108;
1471 else if (strstr(channel_bandwidth_str, "20") != NULL)
1472 num_subcarrier = 52;
1473 code_bits = 8;
1474 code_rate = (float)5/6;
1475 Symbol_duration = 32;
1476 } else if (mode_map & WIFI_MODE_N) {
1477 if (strstr(channel_bandwidth_str, "160") != NULL)
1478 num_subcarrier = 468;
1479 else if (strstr(channel_bandwidth_str, "80") != NULL)
1480 num_subcarrier = 234;
1481 else if (strstr(channel_bandwidth_str, "40") != NULL)
1482 num_subcarrier = 108;
1483 else if (strstr(channel_bandwidth_str, "20") != NULL)
1484 num_subcarrier = 52;
1485 code_bits = 6;
1486 code_rate = (float)3/4;
1487 Symbol_duration = 32;
1488 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1489 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1490 snprintf(output_string, 64, "65 Mb/s");
1491 return RETURN_OK;
1492 } else {
1493 snprintf(output_string, 64, "0 Mb/s");
1494 return RETURN_OK;
1495 }
1496
1497 // Spatial streams
1498 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1499 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1500 return RETURN_ERR;
1501 }
1502
1503 // multiple 10 is to align duration unit (0.1 us)
1504 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1505 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1506
1507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1508
1509 return RETURN_OK;
1510}
1511#if 0
1512INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1513{
1514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1515 char cmd[64];
1516 char buf[1024];
1517 int apIndex;
1518
1519 if (NULL == output_string)
1520 return RETURN_ERR;
1521
1522 apIndex=(radioIndex==0)?0:1;
1523
1524 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
1525 _syscmd(cmd,buf, sizeof(buf));
1526
1527 snprintf(output_string, 64, "%s", buf);
1528 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1529 return RETURN_OK;
1530}
1531#endif
1532
1533
1534//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1535//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.
1536INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1537{
1538 wifi_band band = band_invalid;
1539
1540 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1541 if (NULL == output_string)
1542 return RETURN_ERR;
1543
1544 band = wifi_index_to_band(radioIndex);
1545
1546 memset(output_string, 0, 10);
1547 if (band == band_2_4)
1548 strcpy(output_string, "2.4GHz");
1549 else if (band == band_5)
1550 strcpy(output_string, "5GHz");
1551 else if (band == band_6)
1552 strcpy(output_string, "6GHz");
1553 else
1554 return RETURN_ERR;
1555 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1556
1557 return RETURN_OK;
1558#if 0
1559 char buf[MAX_BUF_SIZE]={'\0'};
1560 char str[MAX_BUF_SIZE]={'\0'};
1561 char cmd[MAX_CMD_SIZE]={'\0'};
1562 char *ch=NULL;
1563 char *ch2=NULL;
1564
1565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1566 if (NULL == output_string)
1567 return RETURN_ERR;
1568
1569
1570 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1571
1572 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1573 {
1574 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1575 return RETURN_ERR;
1576 }
1577 ch=strchr(buf,'\n');
1578 *ch='\0';
1579 ch=strchr(buf,'=');
1580 if(ch==NULL)
1581 return RETURN_ERR;
1582
1583
1584 ch++;
1585
1586 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1587 strcpy(buf,"0");
1588 if(strlen(ch) == 1)
1589 ch=strcat(buf,ch);
1590
1591
1592 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1593
1594 if(_syscmd(cmd,str,64) == RETURN_ERR)
1595 {
1596 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1597 return RETURN_ERR;
1598 }
1599
1600
1601 ch2=strchr(str,'\n');
1602 //replace \n with \0
1603 *ch2='\0';
1604 ch2=strchr(str,'=');
1605 if(ch2==NULL)
1606 {
1607 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1608 return RETURN_ERR;
1609 }
1610 else
1611 wifi_dbg_printf("%s",ch2+1);
1612
1613
1614 ch2++;
1615
1616
1617 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1618
1619 memset(buf,'\0',sizeof(buf));
1620 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1621 {
1622 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1623 return RETURN_ERR;
1624 }
1625 if (strstr(buf,"2.4") != NULL )
1626 strcpy(output_string,"2.4GHz");
1627 else if(strstr(buf,"5.") != NULL )
1628 strcpy(output_string,"5GHz");
1629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1630
1631 return RETURN_OK;
1632#endif
1633}
1634
1635//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1636//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.
1637INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1638{
1639 wifi_band band = band_invalid;
1640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1641 if (NULL == output_string)
1642 return RETURN_ERR;
1643 band = wifi_index_to_band(radioIndex);
1644
1645 if (band == band_2_4)
1646 snprintf(output_string, 64, "2.4GHz");
1647 else if (band == band_5)
1648 snprintf(output_string, 64, "5GHz");
1649 else if (band == band_6)
1650 snprintf(output_string, 64, "6GHz");
1651
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653
1654 return RETURN_OK;
1655#if 0
1656 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1657 char buf[MAX_BUF_SIZE]={'\0'};
1658 char str[MAX_BUF_SIZE]={'\0'};
1659 char cmd[MAX_CMD_SIZE]={'\0'};
1660 char *ch=NULL;
1661 char *ch2=NULL;
1662 char ch1[5]="0";
1663
1664 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1665
1666 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1667 {
1668 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1669 return RETURN_ERR;
1670 }
1671
1672 ch=strchr(buf,'\n');
1673 *ch='\0';
1674 ch=strchr(buf,'=');
1675 if(ch==NULL)
1676 return RETURN_ERR;
1677 ch++;
1678
1679 if(strlen(ch)==1)
1680 {
1681 strcat(ch1,ch);
1682
1683 }
1684 else
1685 {
1686 strcpy(ch1,ch);
1687 }
1688
1689
1690
1691 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1692 if(_syscmd(cmd,str,64) == RETURN_ERR)
1693 {
1694 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1695 return RETURN_ERR;
1696 }
1697
1698
1699 ch2=strchr(str,'\n');
1700 //replace \n with \0
1701 *ch2='\0';
1702 ch2=strchr(str,'=');
1703 if(ch2==NULL)
1704 {
1705 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1706 return RETURN_ERR;
1707 }
1708 else
1709 wifi_dbg_printf("%s",ch2+1);
1710 ch2++;
1711
1712
1713 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1714 memset(buf,'\0',sizeof(buf));
1715 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1716 {
1717 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1718 return RETURN_ERR;
1719 }
1720
1721
1722 if(strstr(buf,"2.4")!=NULL)
1723 {
1724 strcpy(output_string,"2.4GHz");
1725 }
1726 if(strstr(buf,"5.")!=NULL)
1727 {
1728 strcpy(output_string,"5GHz");
1729 }
1730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1731 return RETURN_OK;
1732#endif
1733}
1734
1735//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1736//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.
1737INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1738{
1739 char cmd[128]={0};
1740 char buf[128]={0};
1741 char temp_output[128] = {0};
1742 wifi_band band;
1743 int phyId = 0;
1744
1745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1746 if (NULL == output_string)
1747 return RETURN_ERR;
1748
1749 band = wifi_index_to_band(radioIndex);
1750 if (band == band_2_4) {
1751 strcat(temp_output, "b,g,");
1752 } else if (band == band_5) {
1753 strcat(temp_output, "a,");
1754 }
1755 phyId = radio_index_to_phy(radioIndex);
1756 // ht capabilities
1757 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);
1758 _syscmd(cmd, buf, sizeof(buf));
1759 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
1760 strcat(temp_output, "n,");
1761 }
1762
1763 // vht capabilities
1764 if (band == band_5) {
1765 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
1766 _syscmd(cmd, buf, sizeof(buf));
1767 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
1768 strcat(temp_output, "ac,");
1769 }
1770 }
1771
1772 // he capabilities
1773 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);
1774 _syscmd(cmd, buf, sizeof(buf));
1775 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
1776 strcat(temp_output, "ax,");
1777 }
1778
1779 // Remove the last comma
1780 if (strlen(temp_output) != 0)
1781 temp_output[strlen(temp_output)-1] = '\0';
1782 strncpy(output_string, temp_output, strlen(temp_output));
1783 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1784 return RETURN_OK;
1785}
1786
1787//Get the radio operating mode, and pure mode flag. eg: "ac"
1788//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.
1789INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1790{
1791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1792 if (NULL == output_string)
1793 return RETURN_ERR;
1794
1795 if (radioIndex == 0) {
1796 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1797 *gOnly = FALSE;
1798 *nOnly = TRUE;
1799 *acOnly = FALSE;
1800 } else {
1801 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1802 *gOnly = FALSE;
1803 *nOnly = FALSE;
1804 *acOnly = FALSE;
1805 }
1806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1807
1808 return RETURN_OK;
1809#if 0
1810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1811 char buf[64] = {0};
1812 char config_file[MAX_BUF_SIZE] = {0};
1813
1814 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1815 return RETURN_ERR;
1816
1817 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1818 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1819
1820 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1821 if (strlen(buf) == 0)
1822 {
1823 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1824 return RETURN_ERR;
1825 }
1826 if(strcmp(buf,"g")==0)
1827 {
1828 wifi_dbg_printf("\nG\n");
1829 *gOnly=TRUE;
1830 *nOnly=FALSE;
1831 *acOnly=FALSE;
1832 }
1833 else if(strcmp(buf,"n")==0)
1834 {
1835 wifi_dbg_printf("\nN\n");
1836 *gOnly=FALSE;
1837 *nOnly=TRUE;
1838 *acOnly=FALSE;
1839 }
1840 else if(strcmp(buf,"ac")==0)
1841 {
1842 wifi_dbg_printf("\nac\n");
1843 *gOnly=FALSE;
1844 *nOnly=FALSE;
1845 *acOnly=TRUE;
1846 }
1847 /* hostapd-5G.conf has "a" as hw_mode */
1848 else if(strcmp(buf,"a")==0)
1849 {
1850 wifi_dbg_printf("\na\n");
1851 *gOnly=FALSE;
1852 *nOnly=FALSE;
1853 *acOnly=FALSE;
1854 }
1855 else
1856 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1857
1858 //for a,n mode
1859 if(radioIndex == 1)
1860 {
1861 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1862 if(strcmp(buf,"1")==0)
1863 {
1864 strncpy(output_string, "n", 1);
1865 *nOnly=FALSE;
1866 }
1867 }
1868
1869 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1871 return RETURN_OK;
1872#endif
1873}
1874
1875INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1876{
1877 char cmd[128] = {0};
1878 char buf[64] = {0};
1879 char config_file[64] = {0};
1880 wifi_band band;
1881
1882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1883 if(NULL == output_string || NULL == pureMode)
1884 return RETURN_ERR;
1885
1886 // grep all of the ieee80211 protocol config set to 1
1887 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1888 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1889 _syscmd(cmd, buf, sizeof(buf));
1890
1891 band = wifi_index_to_band(radioIndex);
1892 // puremode is a bit map
1893 *pureMode = 0;
1894 if (band == band_2_4) {
1895 strcat(output_string, "b,g");
1896 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1897 if (strstr(buf, "n") != NULL) {
1898 strcat(output_string, ",n");
1899 *pureMode |= WIFI_MODE_N;
1900 }
1901 if (strstr(buf, "ax") != NULL) {
1902 strcat(output_string, ",ax");
1903 *pureMode |= WIFI_MODE_AX;
1904 }
1905 } else if (band == band_5) {
1906 strcat(output_string, "a");
1907 *pureMode |= WIFI_MODE_A;
1908 if (strstr(buf, "n") != NULL) {
1909 strcat(output_string, ",n");
1910 *pureMode |= WIFI_MODE_N;
1911 }
1912 if (strstr(buf, "ac") != NULL) {
1913 strcat(output_string, ",ac");
1914 *pureMode |= WIFI_MODE_AC;
1915 }
1916 if (strstr(buf, "ax") != NULL) {
1917 strcat(output_string, ",ax");
1918 *pureMode |= WIFI_MODE_AX;
1919 }
1920 } else if (band == band_6) {
1921 if (strstr(buf, "ax") != NULL) {
1922 strcat(output_string, "ax");
1923 *pureMode |= WIFI_MODE_AX;
1924 }
1925 }
1926
1927 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1928 return RETURN_OK;
1929}
1930
1931// Set the radio operating mode, and pure mode flag.
1932INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1933{
1934 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1935 if (strcmp (channelMode,"11A") == 0)
1936 {
1937 writeBandWidth(radioIndex,"20MHz");
1938 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1939 printf("\nChannel Mode is 802.11a (5GHz)\n");
1940 }
1941 else if (strcmp (channelMode,"11NAHT20") == 0)
1942 {
1943 writeBandWidth(radioIndex,"20MHz");
1944 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1945 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1946 }
1947 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1948 {
1949 writeBandWidth(radioIndex,"40MHz");
1950 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1951 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1952 }
1953 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1954 {
1955 writeBandWidth(radioIndex,"40MHz");
1956 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1957 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1958 }
1959 else if (strcmp (channelMode,"11ACVHT20") == 0)
1960 {
1961 writeBandWidth(radioIndex,"20MHz");
1962 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1963 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1964 }
1965 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1966 {
1967 writeBandWidth(radioIndex,"40MHz");
1968 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1969 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1970 }
1971 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1972 {
1973 writeBandWidth(radioIndex,"40MHz");
1974 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1975 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1976 }
1977 else if (strcmp (channelMode,"11ACVHT80") == 0)
1978 {
1979 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1980 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1981 }
1982 else if (strcmp (channelMode,"11ACVHT160") == 0)
1983 {
1984 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1985 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1986 }
1987 else if (strcmp (channelMode,"11B") == 0)
1988 {
1989 writeBandWidth(radioIndex,"20MHz");
1990 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1991 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1992 }
1993 else if (strcmp (channelMode,"11G") == 0)
1994 {
1995 writeBandWidth(radioIndex,"20MHz");
1996 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1997 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1998 }
1999 else if (strcmp (channelMode,"11NGHT20") == 0)
2000 {
2001 writeBandWidth(radioIndex,"20MHz");
2002 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2003 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2004 }
2005 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2006 {
2007 writeBandWidth(radioIndex,"40MHz");
2008 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2009 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2010 }
2011 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2012 {
2013 writeBandWidth(radioIndex,"40MHz");
2014 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2015 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2016 }
2017 else
2018 {
2019 return RETURN_ERR;
2020 }
2021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2022
2023 return RETURN_OK;
2024}
2025
2026// Set the radio operating mode, and pure mode flag.
2027INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2028{
2029 int num_hostapd_support_mode = 3; // n, ac, ax
2030 struct params list[num_hostapd_support_mode];
2031 char config_file[64] = {0};
2032 char bandwidth[16] = {0};
2033 int mode_check_bit = 1 << 3; // n mode
2034
2035
2036 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2037 // Set radio mode
2038 list[0].name = "ieee80211n";
2039 list[1].name = "ieee80211ac";
2040 list[2].name = "ieee80211ax";
2041 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2042
2043 // check the bit map from n to ax, and set hostapd config
2044 if (pureMode & WIFI_MODE_N)
2045 list[0].value = "1";
2046 else
2047 list[0].value = "0";
2048 if (pureMode & WIFI_MODE_AC)
2049 list[1].value = "1";
2050 else
2051 list[1].value = "0";
2052 if (pureMode & WIFI_MODE_AX)
2053 list[2].value = "1";
2054 else
2055 list[2].value = "0";
2056 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2057
2058 if (channelMode == NULL || strlen(channelMode) == 0)
2059 return RETURN_OK;
2060 // Set bandwidth
2061 if (strstr(channelMode, "40") != NULL)
2062 strcpy(bandwidth, "40MHz");
2063 else if (strstr(channelMode, "80") != NULL)
2064 strcpy(bandwidth, "80MHz");
2065 else if (strstr(channelMode, "160") != NULL)
2066 strcpy(bandwidth, "160MHz");
2067 else // 11A, 11B, 11G....
2068 strcpy(bandwidth, "20MHz");
2069
2070 writeBandWidth(radioIndex, bandwidth);
2071 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2072
2073 wifi_reloadAp(radioIndex);
2074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2075
2076 return RETURN_OK;
2077}
2078
2079INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2080
2081 char config_file[64] = {0};
2082 char buf[64] = {0};
2083 struct params params = {0};
2084 wifi_band band = band_invalid;
2085
2086 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2087
2088 band = wifi_index_to_band(radioIndex);
2089
2090 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2091 return RETURN_ERR;
2092 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2093 return RETURN_ERR;
2094 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2095 return RETURN_ERR;
2096
2097 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2098 params.name = "hw_mode";
2099 params.value = hw_mode;
2100 wifi_hostapdWrite(config_file, &params, 1);
2101 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2102
2103 if (band == band_2_4) {
2104 if (strncmp(hw_mode, "b", 1) == 0) {
2105 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2106 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2107 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2108 snprintf(buf, sizeof(buf), "%s", "1,2");
2109 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2110 } else {
2111 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2112
2113 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2114 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2115 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2116 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2117 }
2118 }
2119
2120 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2121 return RETURN_OK;
2122}
2123
2124INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2125{
2126 char config_file[64] = {0};
2127 struct params params = {0};
2128 wifi_band band = band_invalid;
2129
2130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2131
2132 band = wifi_index_to_band(radioIndex);
2133 if (band != band_2_4)
2134 return RETURN_OK;
2135
2136 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2137 params.name = "noscan";
2138 params.value = noscan;
2139 wifi_hostapdWrite(config_file, &params, 1);
2140 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2141
2142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2143 return RETURN_OK;
2144}
2145
2146//Get the list of supported channel. eg: "1-11"
2147//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.
2148INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2149{
2150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2151 if (NULL == output_string)
2152 return RETURN_ERR;
2153 char cmd[256] = {0};
2154 char buf[128] = {0};
2155 BOOL dfs_enable = false;
2156 int phyId = 0;
2157
2158 // Parse possible channel number and separate them with commas.
2159 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2160 phyId = radio_index_to_phy(radioIndex);
2161 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2162 if (dfs_enable)
2163 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);
2164 else
2165 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);
2166
2167 _syscmd(cmd,buf,sizeof(buf));
2168 strncpy(output_string, buf, sizeof(buf));
2169
2170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2171 return RETURN_OK;
2172}
2173
2174//Get the list for used channel. eg: "1,6,9,11"
2175//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.
2176INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2177{
2178 char interface_name[16] = {0};
2179 char cmd[128] = {0};
2180 char buf[128] = {0};
2181 char config_file[64] = {0};
2182 int channel = 0;
2183 int freq = 0;
2184 int bandwidth = 0;
2185 int center_freq = 0;
2186 int center_channel = 0;
2187 int channel_delta = 0;
2188 wifi_band band = band_invalid;
2189
2190 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2191
2192 if (NULL == output_string)
2193 return RETURN_ERR;
2194
2195 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2196 return RETURN_ERR;
2197 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2198 _syscmd(cmd, buf, sizeof(buf));
2199 if (strlen(buf) == 0) {
2200 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2201 return RETURN_ERR;
2202 }
2203 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2204
2205 if (bandwidth == 20) {
2206 snprintf(output_string, 256, "%d", channel);
2207 return RETURN_OK;
2208 }
2209
2210 center_channel = ieee80211_frequency_to_channel(center_freq);
2211
2212 band = wifi_index_to_band(radioIndex);
2213 if (band == band_2_4 && bandwidth == 40) {
2214 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2215 memset(buf, 0, sizeof(buf));
2216 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2217
2218 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2219 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2220 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2221 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2222 } else {
2223 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2224 return RETURN_ERR;
2225 }
2226 } else if (band == band_5 || band == band_6){
2227 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2228 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2229 channel_delta = (bandwidth-20)/10;
2230 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2231 } else
2232 return RETURN_ERR;
2233
2234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2235 return RETURN_OK;
2236}
2237
2238//Get the running channel number
2239INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2240{
2241 char channel_str[16] = {0};
2242 char config_file[128] = {0};
2243
2244 if (output_ulong == NULL)
2245 return RETURN_ERR;
2246
2247 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2248 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2249
2250 *output_ulong = strtoul(channel_str, NULL, 10);
2251
2252 return RETURN_OK;
2253}
2254
2255
2256INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2257{
2258 char cmd[1024] = {0}, buf[5] = {0};
2259 char interface_name[16] = {0};
2260
2261 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2262 if (NULL == output_ulong)
2263 return RETURN_ERR;
2264
2265 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2266 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2267 return RETURN_ERR;
2268 _syscmd(cmd,buf,sizeof(buf));
2269 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2270 if (*output_ulong == 0) {
2271 return RETURN_ERR;
2272 }
2273
2274 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2275 return RETURN_OK;
2276}
2277
2278//Storing the previous channel value
2279INT wifi_storeprevchanval(INT radioIndex)
2280{
2281 char buf[256] = {0};
2282 char output[4]={'\0'};
2283 char config_file[MAX_BUF_SIZE] = {0};
2284 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2285 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2286 if(radioIndex == 0)
2287 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2288 else if(radioIndex == 1)
2289 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2290 system(buf);
2291 Radio_flag = FALSE;
2292 return RETURN_OK;
2293}
2294
2295//Set the running channel number
2296INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2297{
2298 // We only write hostapd config here
2299 char str_channel[8]={0};
2300 char *list_channel;
2301 char config_file[128] = {0};
2302 char possible_channels[256] = {0};
2303 int max_radio_num = 0;
2304 struct params list = {0};
2305
2306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2307
2308 // Check valid
2309 sprintf(str_channel, "%lu", channel);
2310
2311 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2312 list_channel = strtok(possible_channels, ",");
2313 while(true)
2314 {
2315 if(list_channel == NULL) { // input not in the list
2316 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2317 return RETURN_ERR;
2318 }
2319 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2320 break;
2321 list_channel = strtok(NULL, ",");
2322 }
2323
2324 list.name = "channel";
2325 list.value = str_channel;
2326 wifi_getMaxRadioNumber(&max_radio_num);
2327 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2328 {
2329 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2330 wifi_hostapdWrite(config_file, &list, 1);
2331 }
2332
2333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2334 return RETURN_OK;
2335}
2336
2337INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2338{
2339 struct params list[2];
2340 char str_idx[16];
2341 char config_file[64];
2342 int max_num_radios = 0;
2343 wifi_band band = band_invalid;
2344
2345 band = wifi_index_to_band(radioIndex);
2346 if (band == band_2_4)
2347 return RETURN_OK;
2348
2349 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2350 list[0].name = "vht_oper_centr_freq_seg0_idx";
2351 list[0].value = str_idx;
2352 list[1].name = "he_oper_centr_freq_seg0_idx";
2353 list[1].value = str_idx;
2354
2355 wifi_getMaxRadioNumber(&max_num_radios);
2356 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2357 {
2358 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2359 if (band == band_6)
2360 wifi_hostapdWrite(config_file, &list[1], 1);
2361 else
2362 wifi_hostapdWrite(config_file, list, 2);
2363 }
2364
2365 return RETURN_OK;
2366}
2367
2368//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2369//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2370INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2371{
2372 //Set to wifi config only. Wait for wifi reset to apply.
2373 char buf[256] = {0};
2374 char str_channel[256] = {0};
2375 int count = 0;
2376 ULONG Value = 0;
2377 FILE *fp = NULL;
2378 if(enable == TRUE)
2379 {
2380 wifi_setRadioChannel(radioIndex,Value);
2381 }
2382 return RETURN_OK;
2383}
2384
2385INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2386{
2387 if (output_bool == NULL)
2388 return RETURN_ERR;
2389
2390 *output_bool = TRUE;
2391
2392 return RETURN_OK;
2393}
2394
2395INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2396{
2397 if (NULL == output_bool)
2398 return RETURN_ERR;
2399 *output_bool=FALSE;
2400 return RETURN_OK;
2401}
2402
2403INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2404{
2405 if (NULL == output_bool)
2406 return RETURN_ERR;
2407 *output_bool=FALSE;
2408 return RETURN_OK;
2409}
2410
2411INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2412{
2413 //Set to wifi config only. Wait for wifi reset to apply.
2414 return RETURN_OK;
2415}
2416
2417INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2418{
2419 return RETURN_OK;
2420}
2421
2422INT wifi_factoryResetAP(int apIndex)
2423{
2424 char ap_config_file[64] = {0};
2425 char cmd[128] = {0};
2426
2427 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2428
2429 wifi_setApEnable(apIndex, FALSE);
2430 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2431 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2432 wifi_setApEnable(apIndex, TRUE);
2433
2434 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2435
2436 return RETURN_OK;
2437}
2438
2439//To set Band Steering AP group
2440//To-do
2441INT wifi_setBandSteeringApGroup(char *ApGroup)
2442{
2443 return RETURN_OK;
2444}
2445
2446INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2447{
2448 char config_file[128] = {'\0'};
2449 char buf[128] = {'\0'};
2450
2451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2452 if (dtimInterval == NULL)
2453 return RETURN_ERR;
2454
2455 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2456 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2457
2458 if (strlen(buf) == 0) {
2459 *dtimInterval = 2;
2460 } else {
2461 *dtimInterval = strtoul(buf, NULL, 10);
2462 }
2463
2464 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2465 return RETURN_OK;
2466}
2467
2468INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2469{
2470 struct params params={0};
2471 char config_file[MAX_BUF_SIZE] = {'\0'};
2472 char buf[MAX_BUF_SIZE] = {'\0'};
2473
2474 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2475 if (dtimInterval < 1 || dtimInterval > 255) {
2476 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2477 return RETURN_ERR;
2478 }
2479
2480 params.name = "dtim_period";
2481 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2482 params.value = buf;
2483
2484 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2485 wifi_hostapdWrite(config_file, &params, 1);
2486 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2487
2488 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2489 return RETURN_OK;
2490}
2491
2492//Check if the driver support the Dfs
2493INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2494{
2495 wifi_band band = band_invalid;
2496 if (NULL == output_bool)
2497 return RETURN_ERR;
2498 *output_bool=FALSE;
2499
2500 band = wifi_index_to_band(radioIndex);
2501 if (band == band_5)
2502 *output_bool = TRUE;
2503 return RETURN_OK;
2504}
2505
2506//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.
2507//The value of this parameter is a comma seperated list of channel number
2508INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2509{
2510 if (NULL == output_pool)
2511 return RETURN_ERR;
2512 if (radioIndex==1)
2513 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2514 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2515
2516 return RETURN_OK;
2517}
2518
2519INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2520{
2521 //Set to wifi config. And apply instantly.
2522 return RETURN_OK;
2523}
2524
2525INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2526{
2527 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2528 return RETURN_ERR;
2529 *output_interval_seconds=1800;
2530 *output_dwell_milliseconds=40;
2531
2532 return RETURN_OK;
2533}
2534
2535INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2536{
2537 //Set to wifi config. And apply instantly.
2538 return RETURN_OK;
2539}
2540
2541INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2542{
2543 if (output_bool == NULL)
2544 return RETURN_ERR;
2545 *output_bool = true;
2546 return RETURN_OK;
2547}
2548
2549INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2550{
2551 return RETURN_OK;
2552}
2553
2554//Get the Dfs enable status
2555INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2556{
2557 char buf[16] = {0};
2558 FILE *f = NULL;
2559
2560 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2561
2562 if (output_bool == NULL)
2563 return RETURN_ERR;
2564
2565 *output_bool = TRUE; // default
2566 f = fopen(DFS_ENABLE_FILE, "r");
2567 if (f != NULL) {
2568 fgets(buf, 2, f);
2569 if (strncmp(buf, "0", 1) == 0)
2570 *output_bool = FALSE;
2571 fclose(f);
2572 }
2573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2574 return RETURN_OK;
2575}
2576
2577//Set the Dfs enable status
2578INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2579{
2580 char config_file[128] = {0};
2581 FILE *f = NULL;
2582 struct params params={0};
2583
2584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2585
2586 f = fopen(DFS_ENABLE_FILE, "w");
2587 if (f == NULL)
2588 return RETURN_ERR;
2589 fprintf(f, "%d", enable);
2590 fclose(f);
2591
2592 params.name = "acs_exclude_dfs";
2593 params.value = enable?"0":"1";
2594 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2595 wifi_hostapdWrite(config_file, &params, 1);
2596 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2597
2598 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2599
2600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2601 return RETURN_OK;
2602}
2603
2604//Check if the driver support the AutoChannelRefreshPeriod
2605INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2606{
2607 if (NULL == output_bool)
2608 return RETURN_ERR;
2609 *output_bool=FALSE; //not support
2610
2611 return RETURN_OK;
2612}
2613
2614//Get the ACS refresh period in seconds
2615INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2616{
2617 if (NULL == output_ulong)
2618 return RETURN_ERR;
2619 *output_ulong=300;
2620
2621 return RETURN_OK;
2622}
2623
2624//Set the ACS refresh period in seconds
2625INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2626{
2627 return RETURN_ERR;
2628}
2629
2630//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2631//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.
2632INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2633{
2634 char cmd[128] = {0}, buf[64] = {0};
2635 char extchannel[128] = {0};
2636 char interface_name[64] = {0};
2637 int ret = 0, len=0;
2638 BOOL radio_enable = FALSE;
2639 wifi_band band;
2640
2641 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2642
2643 if (NULL == output_string)
2644 return RETURN_ERR;
2645
2646 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2647 return RETURN_ERR;
2648
2649 if (radio_enable != TRUE)
2650 return RETURN_OK;
2651
2652 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2653 return RETURN_ERR;
2654 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
2655 ret = _syscmd(cmd, buf, sizeof(buf));
2656 len = strlen(buf);
2657 if((ret != 0) || (len == 0))
2658 {
2659 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2660 return RETURN_ERR;
2661 }
2662
2663 band = wifi_index_to_band(radioIndex);
2664 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
2665 wifi_getRadioExtChannel(radioIndex, extchannel);
2666 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
2667 snprintf(buf, sizeof(buf), "40");
2668 }
2669 snprintf(output_string, 64, "%sMHz", buf);
2670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2671
2672 return RETURN_OK;
2673}
2674
2675//Set the Operating Channel Bandwidth.
2676INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
2677{
2678 char config_file[128];
2679 char set_value[16];
2680 struct params params[2];
2681 int max_radio_num = 0;
2682
2683 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2684
2685 if(NULL == bandwidth)
2686 return RETURN_ERR;
2687
2688 if(strstr(bandwidth,"160") != NULL)
2689 strcpy(set_value, "2");
2690 else if(strstr(bandwidth,"80") != NULL)
2691 strcpy(set_value, "1");
2692 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2693 strcpy(set_value, "0");
2694 else
2695 {
2696 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
2697 return RETURN_ERR;
2698 }
2699
2700 params[0].name = "vht_oper_chwidth";
2701 params[0].value = set_value;
2702 params[1].name = "he_oper_chwidth";
2703 params[1].value = set_value;
2704
2705 wifi_getMaxRadioNumber(&max_radio_num);
2706 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2707 {
2708 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2709 wifi_hostapdWrite(config_file, params, 2);
2710 }
2711
2712 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2713 return RETURN_OK;
2714}
2715
2716//Getting current radio extension channel
2717INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2718{
2719 CHAR buf[150] = {0};
2720 CHAR cmd[150] = {0};
2721 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2722 _syscmd(cmd, buf, sizeof(buf));
2723 if(NULL != strstr(buf,"HT40+"))
2724 strcpy(Value,"AboveControlChannel");
2725 else if(NULL != strstr(buf,"HT40-"))
2726 strcpy(Value,"BelowControlChannel");
2727 return RETURN_OK;
2728}
2729
2730//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2731//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.
2732INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2733{
2734 char config_file[64] = {0};
2735 char mode_str[16] = {0};
2736 char buf[64] = {0};
2737 wifi_band band;
2738 int channel = 0, centr_channel = 0;
2739 UINT mode_map = 0;
2740
2741 if (output_string == NULL)
2742 return RETURN_ERR;
2743
2744 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
2745
2746 band = wifi_index_to_band(radioIndex);
2747 if (band == band_invalid)
2748 return RETURN_ERR;
2749
2750 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2751
2752 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08002753 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08002754 // 2G band or ac and ax mode is disable, we will check ht_capab
2755 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08002756 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08002757 snprintf(output_string, 64, "Auto");
2758 } else {
2759 // 5G and 6G band with ac or ax mode.
2760 wifi_getRadioChannel(radioIndex, &channel);
2761 if (mode_map&WIFI_MODE_AX)
2762 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2763 else
2764 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
2765 centr_channel = strtol(buf, NULL, 10);
2766 if (centr_channel > channel)
2767 snprintf(output_string, 64, "AboveControlChannel");
2768 else
2769 snprintf(output_string, 64, "BelowControlChannel");
2770 }
2771
2772 return RETURN_OK;
2773}
2774
2775//Set the extension channel.
2776INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2777{
2778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2779 struct params params={0};
2780 char config_file[64] = {0};
2781 char ext_channel[128]={0};
2782 char buf[128] = {0};
2783 char cmd[128] = {0};
2784 int max_radio_num =0, ret = 0, bandwidth = 0;
2785 unsigned long channel = 0, centr_channel = 0;
2786 bool stbcEnable = FALSE;
2787 params.name = "ht_capab";
2788 wifi_band band;
2789
2790 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2791 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
2792 _syscmd(cmd, buf, sizeof(buf));
2793 if (strlen(buf) != 0)
2794 stbcEnable = TRUE;
2795 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
2796 return RETURN_ERR;
2797 bandwidth = strtol(buf, NULL, 10);
2798 // TDK expected to get error with 20MHz
2799 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
2800 return RETURN_ERR;
2801
2802 band = wifi_index_to_band(radioIndex);
2803 if (band == band_invalid)
2804 return RETURN_ERR;
2805
2806 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
2807 return RETURN_ERR;
2808
2809 if (band == band_5) {
2810 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
2811 centr_channel = util_unii_5g_centerfreq(buf, channel);
2812 if (centr_channel == 0)
2813 return RETURN_ERR;
2814 }
2815
2816 if(NULL!= strstr(string,"Above")) {
2817 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
2818 return RETURN_ERR;
2819 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
2820 } else if(NULL!= strstr(string,"Below")) {
2821 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
2822 return RETURN_ERR;
2823 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
2824 } else {
2825 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
2826 }
2827
2828 params.value = ext_channel;
2829
2830 wifi_getMaxRadioNumber(&max_radio_num);
2831 for(int i=0; i<=MAX_APS/max_radio_num; i++)
2832 {
2833 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
2834 wifi_hostapdWrite(config_file, &params, 1);
2835 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
2836 }
2837
2838 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2839 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2840 return RETURN_OK;
2841}
2842
2843//Get the guard interval value. eg "400nsec" or "800nsec"
2844//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.
2845INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2846{
2847 wifi_guard_interval_t GI;
2848
2849 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2850
2851 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
2852 return RETURN_ERR;
2853
2854 if (GI == wifi_guard_interval_400)
2855 strcpy(output_string, "400nsec");
2856 else if (GI == wifi_guard_interval_800)
2857 strcpy(output_string, "800nsec");
2858 else if (GI == wifi_guard_interval_1600)
2859 strcpy(output_string, "1600nsec");
2860 else if (GI == wifi_guard_interval_3200)
2861 strcpy(output_string, "3200nsec");
2862 else
2863 strcpy(output_string, "Auto");
2864
2865 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2866 return RETURN_OK;
2867}
2868
2869//Set the guard interval value.
2870INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2871{
2872 wifi_guard_interval_t GI;
2873 int ret = 0;
2874
2875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2876
2877 if (strcmp(string, "400nsec") == 0)
2878 GI = wifi_guard_interval_400;
2879 else if (strcmp(string , "800nsec") == 0)
2880 GI = wifi_guard_interval_800;
2881 else if (strcmp(string , "1600nsec") == 0)
2882 GI = wifi_guard_interval_1600;
2883 else if (strcmp(string , "3200nsec") == 0)
2884 GI = wifi_guard_interval_3200;
2885 else
2886 GI = wifi_guard_interval_auto;
2887
2888 ret = wifi_setGuardInterval(radioIndex, GI);
2889
2890 if (ret == RETURN_ERR) {
2891 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2892 return RETURN_ERR;
2893 }
2894
2895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2896 return RETURN_OK;
2897}
2898
2899//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2900INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2901{
2902 char buf[32]={0};
2903 char mcs_file[64] = {0};
2904 char cmd[64] = {0};
2905 int mode_bitmap = 0;
2906
2907 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2908 if(output_int == NULL)
2909 return RETURN_ERR;
2910 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2911
2912 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2913 _syscmd(cmd, buf, sizeof(buf));
2914 if (strlen(buf) > 0)
2915 *output_int = strtol(buf, NULL, 10);
2916 else {
2917 // output the max MCS for the current radio mode
2918 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2919 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2920 return RETURN_ERR;
2921 }
2922 if (mode_bitmap & WIFI_MODE_AX) {
2923 *output_int = 11;
2924 } else if (mode_bitmap & WIFI_MODE_AC) {
2925 *output_int = 9;
2926 } else if (mode_bitmap & WIFI_MODE_N) {
2927 *output_int = 7;
2928 }
2929 }
2930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2931
2932 return RETURN_OK;
2933}
2934
2935//Set the Modulation Coding Scheme index
2936INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2937{
2938 // 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).
2939 char config_file[64] = {0};
2940 char set_value[16] = {0};
2941 char mcs_file[32] = {0};
2942 wifi_band band = band_invalid;
2943 struct params set_config = {0};
2944 FILE *f = NULL;
2945
2946 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2947
2948 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2949
2950 // -1 means auto
2951 if (MCS > 15 || MCS < -1) {
2952 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2953 return RETURN_ERR;
2954 }
2955
2956 if (MCS > 9 || MCS == -1)
2957 strcpy(set_value, "2");
2958 else if (MCS > 7)
2959 strcpy(set_value, "1");
2960 else
2961 strcpy(set_value, "0");
2962
2963 set_config.name = "he_basic_mcs_nss_set";
2964 set_config.value = set_value;
2965
2966 wifi_hostapdWrite(config_file, &set_config, 1);
2967 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2968
2969 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2970 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2971 f = fopen(mcs_file, "w");
2972 if (f == NULL) {
2973 fprintf(stderr, "%s: fopen failed\n", __func__);
2974 return RETURN_ERR;
2975 }
2976 fprintf(f, "%d", MCS);
2977 fclose(f);
2978
2979 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2980 return RETURN_OK;
2981}
2982
2983//Get supported Transmit Power list, eg : "0,25,50,75,100"
2984//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.
2985INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2986{
2987 if (NULL == output_list)
2988 return RETURN_ERR;
2989 snprintf(output_list, 64,"0,25,50,75,100");
2990 return RETURN_OK;
2991}
2992
2993//Get current Transmit Power in dBm units.
2994//The transmite power level is in units of full power for this radio.
2995INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2996{
2997 char interface_name[16] = {0};
2998 char cmd[128]={0};
2999 char buf[16]={0};
3000 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3001
3002 if(output_ulong == NULL)
3003 return RETURN_ERR;
3004
3005 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3006 return RETURN_ERR;
3007 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3008 _syscmd(cmd, buf, sizeof(buf));
3009
3010 *output_ulong = strtol(buf, NULL, 10);
3011
3012 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3013 return RETURN_OK;
3014}
3015
3016//Set Transmit Power
3017//The transmite power level is in units of full power for this radio.
3018INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3019{
3020 char interface_name[16] = {0};
3021 char *support;
3022 char cmd[128]={0};
3023 char buf[128]={0};
3024 char txpower_str[64] = {0};
3025 int txpower = 0;
3026 int maximum_tx = 0;
3027 int phyId = 0;
3028
3029 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3030
3031 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3032 return RETURN_ERR;
3033 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
3034 _syscmd(cmd, buf, sizeof(buf));
3035 maximum_tx = strtol(buf, NULL, 10);
3036
3037 // Get the Tx power supported list and check that is the input in the list
3038 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3039 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3040 support = strtok(buf, ",");
3041 while(true)
3042 {
3043 if(support == NULL) { // input not in the list
3044 wifi_dbg_printf("Input value is invalid.\n");
3045 return RETURN_ERR;
3046 }
3047 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3048 break;
3049 }
3050 support = strtok(NULL, ",");
3051 }
3052 txpower = TransmitPower*maximum_tx/100;
3053 phyId = radio_index_to_phy(radioIndex);
3054 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3055 _syscmd(cmd, buf, sizeof(buf));
3056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3057
3058 return RETURN_OK;
3059}
3060
3061//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3062INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3063{
3064 if (NULL == Supported)
3065 return RETURN_ERR;
3066 *Supported = TRUE;
3067
3068 return RETURN_OK;
3069}
3070
3071//Get 80211h feature enable
3072INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3073{
3074 char buf[64]={'\0'};
3075 char config_file[64] = {'\0'};
3076
3077 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3078 if(enable == NULL)
3079 return RETURN_ERR;
3080
3081 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3082 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3083
3084 if (strncmp(buf, "1", 1) == 0)
3085 *enable = TRUE;
3086 else
3087 *enable = FALSE;
3088
3089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3090 return RETURN_OK;
3091}
3092
3093//Set 80211h feature enable
3094INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3095{
3096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3097 struct params params={'\0'};
3098 char config_file[MAX_BUF_SIZE] = {0};
3099
3100 params.name = "ieee80211h";
3101
3102 if (enable) {
3103 params.value = "1";
3104 } else {
3105 params.value = "0";
3106 }
3107
3108 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3109 wifi_hostapdWrite(config_file, &params, 1);
3110
3111 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3113 return RETURN_OK;
3114}
3115
3116//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.
3117INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3118{
3119 if (NULL == output)
3120 return RETURN_ERR;
3121 *output=100;
3122
3123 return RETURN_OK;
3124}
3125
3126//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.
3127INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3128{
3129 if (NULL == output)
3130 return RETURN_ERR;
3131 *output = -99;
3132
3133 return RETURN_OK;
3134}
3135
3136INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3137{
3138 return RETURN_ERR;
3139}
3140
3141
3142//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3143INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3144{
3145 char interface_name[16] = {0};
3146 char cmd[MAX_BUF_SIZE]={'\0'};
3147 char buf[MAX_CMD_SIZE]={'\0'};
3148
3149 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3150 if(output == NULL)
3151 return RETURN_ERR;
3152
3153 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3154 return RETURN_ERR;
3155 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3156 _syscmd(cmd, buf, sizeof(buf));
3157 *output = atoi(buf);
3158
3159 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3160 return RETURN_OK;
3161}
3162
3163INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3164{
3165 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3166 struct params params={'\0'};
3167 char buf[MAX_BUF_SIZE] = {'\0'};
3168 char config_file[MAX_BUF_SIZE] = {'\0'};
3169
3170 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3171 return RETURN_ERR;
3172
3173 params.name = "beacon_int";
3174 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3175 params.value = buf;
3176
3177 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3178 wifi_hostapdWrite(config_file, &params, 1);
3179
3180 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3182 return RETURN_OK;
3183}
3184
3185//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.
3186INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3187{
3188 //TODO: need to revisit below implementation
3189 char *temp;
3190 char temp_output[128] = {0};
3191 char temp_TransmitRates[64] = {0};
3192 char config_file[64] = {0};
3193
3194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3195 if (NULL == output)
3196 return RETURN_ERR;
3197 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3198 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3199
3200 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3201 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3202 } else {
3203 temp = strtok(temp_TransmitRates," ");
3204 while(temp!=NULL)
3205 {
3206 // Convert 100 kbps to Mbps
3207 temp[strlen(temp)-1]=0;
3208 if((temp[0]=='5') && (temp[1]=='\0'))
3209 {
3210 temp="5.5";
3211 }
3212 strcat(temp_output,temp);
3213 temp = strtok(NULL," ");
3214 if(temp!=NULL)
3215 {
3216 strcat(temp_output,",");
3217 }
3218 }
3219 strcpy(output,temp_output);
3220 }
3221 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3222 return RETURN_OK;
3223}
3224
3225INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3226{
3227 char *temp;
3228 char temp1[128];
3229 char temp_output[128];
3230 char temp_TransmitRates[128];
3231 char set[128];
3232 char sub_set[128];
3233 int set_count=0,subset_count=0;
3234 int set_index=0,subset_index=0;
3235 char *token;
3236 int flag=0, i=0;
3237 struct params params={'\0'};
3238 char config_file[MAX_BUF_SIZE] = {0};
3239 wifi_band band = wifi_index_to_band(radioIndex);
3240
3241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3242 if(NULL == TransmitRates)
3243 return RETURN_ERR;
3244 strcpy(sub_set,TransmitRates);
3245
3246 //Allow only supported Data transmit rate to be set
3247 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3248 token = strtok(sub_set,",");
3249 while( token != NULL ) /* split the basic rate to be set, by comma */
3250 {
3251 sub_set[subset_count]=atoi(token);
3252 subset_count++;
3253 token=strtok(NULL,",");
3254 }
3255 token=strtok(set,",");
3256 while(token!=NULL) /* split the supported rate by comma */
3257 {
3258 set[set_count]=atoi(token);
3259 set_count++;
3260 token=strtok(NULL,",");
3261 }
3262 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3263 {
3264 for(set_index=0;set_index < set_count;set_index++)
3265 {
3266 flag=0;
3267 if(sub_set[subset_index]==set[set_index])
3268 break;
3269 else
3270 flag=1; /* No match found */
3271 }
3272 if(flag==1)
3273 return RETURN_ERR; //If value not found return Error
3274 }
3275 strcpy(temp_TransmitRates,TransmitRates);
3276
3277 for(i=0;i<strlen(temp_TransmitRates);i++)
3278 {
3279 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3280 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3281 {
3282 continue;
3283 }
3284 else
3285 {
3286 return RETURN_ERR;
3287 }
3288 }
3289 strcpy(temp_output,"");
3290 temp = strtok(temp_TransmitRates,",");
3291 while(temp!=NULL)
3292 {
3293 strcpy(temp1,temp);
3294 if(band == band_5)
3295 {
3296 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3297 {
3298 return RETURN_ERR;
3299 }
3300 }
3301
3302 if(strcmp(temp,"5.5")==0)
3303 {
3304 strcpy(temp1,"55");
3305 }
3306 else
3307 {
3308 strcat(temp1,"0");
3309 }
3310 strcat(temp_output,temp1);
3311 temp = strtok(NULL,",");
3312 if(temp!=NULL)
3313 {
3314 strcat(temp_output," ");
3315 }
3316 }
3317 strcpy(TransmitRates,temp_output);
3318
3319 params.name= "basic_rates";
3320 params.value =TransmitRates;
3321
3322 wifi_dbg_printf("\n%s:",__func__);
3323 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3324 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3325 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3326 wifi_hostapdWrite(config_file,&params,1);
3327 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3328 return RETURN_OK;
3329}
3330
3331//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3332INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3333{
3334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3335 FILE *fp = NULL;
3336 char path[256] = {0}, output_string[256] = {0};
3337 int count = 0;
3338 char *interface = NULL;
3339
3340 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3341 if (fp == NULL)
3342 {
3343 printf("Failed to run command in Function %s\n", __FUNCTION__);
3344 return RETURN_ERR;
3345 }
3346 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3347 {
3348 interface = strchr(path, '=');
3349
3350 if (interface != NULL)
3351 {
3352 strcpy(output_string, interface + 1);
3353 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3354 interface_name[count] = output_string[count];
3355
3356 interface_name[count] = '\0';
3357 }
3358 }
3359 pclose(fp);
3360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3361 return RETURN_OK;
3362}
3363
3364INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3365{
3366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3367 output_struct->radio_BytesSent = 0;
3368 output_struct->radio_BytesReceived = 0;
3369 output_struct->radio_PacketsSent = 0;
3370 output_struct->radio_PacketsReceived = 0;
3371 output_struct->radio_ErrorsSent = 0;
3372 output_struct->radio_ErrorsReceived = 0;
3373 output_struct->radio_DiscardPacketsSent = 0;
3374 output_struct->radio_DiscardPacketsReceived = 0;
3375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3376 return RETURN_OK;
3377}
3378
3379
3380INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3381{
3382 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3383 CHAR buf[MAX_CMD_SIZE] = {0};
3384 CHAR Value[MAX_BUF_SIZE] = {0};
3385 FILE *fp = NULL;
3386
3387 if (ifname == NULL || strlen(ifname) <= 1)
3388 return RETURN_OK;
3389
3390 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3391 system(buf);
3392
3393 fp = fopen("/tmp/Radio_Stats.txt", "r");
3394 if(fp == NULL)
3395 {
3396 printf("/tmp/Radio_Stats.txt not exists \n");
3397 return RETURN_ERR;
3398 }
3399 fclose(fp);
3400
3401 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3402 File_Reading(buf, Value);
3403 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3404
3405 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3406 File_Reading(buf, Value);
3407 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3408
3409 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3410 File_Reading(buf, Value);
3411 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3412
3413 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3414 File_Reading(buf, Value);
3415 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3416
3417 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3418 File_Reading(buf, Value);
3419 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3420
3421 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3422 File_Reading(buf, Value);
3423 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3424
3425 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3426 File_Reading(buf, Value);
3427 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3428
3429 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3430 File_Reading(buf, Value);
3431 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3432
3433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3434 return RETURN_OK;
3435}
3436
3437INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3438{
3439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3440 CHAR buf[MAX_CMD_SIZE] = {0};
3441 FILE *fp = NULL;
3442 INT count = 0;
3443
3444 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3445 {
3446 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3447 File_Reading(buf, status);
3448 }
3449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3450 return RETURN_OK;
3451}
3452
3453//Get detail radio traffic static info
3454INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3455{
3456
3457#if 0
3458 //ifconfig radio_x
3459 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3460 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3461 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3462 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3463
3464 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3465 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3466 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.
3467 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.
3468
3469 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3470 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].
3471 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3472 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.
3473 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
3474 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
3475 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
3476 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
3477 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
3478
3479 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
3480 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
3481 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
3482 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.
3483
3484 return RETURN_OK;
3485#endif
3486
3487 CHAR interface_name[64] = {0};
3488 BOOL iface_status = FALSE;
3489 wifi_radioTrafficStats2_t radioTrafficStats = {0};
3490
3491 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3492 if (NULL == output_struct)
3493 return RETURN_ERR;
3494
3495 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3496 return RETURN_ERR;
3497
3498 wifi_getApEnable(radioIndex, &iface_status);
3499
3500 if (iface_status == TRUE)
3501 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3502 else
3503 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
3504
3505 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3506 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3507 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3508 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3509 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3510 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3511 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3512 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
3513
3514 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3515 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].
3516 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3517 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.
3518 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
3519 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
3520 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
3521 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
3522 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
3523
3524 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
3525 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
3526 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
3527 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.
3528
3529 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3530
3531 return RETURN_OK;
3532}
3533
3534//Set radio traffic static Measureing rules
3535INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3536{
3537 //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
3538 // Else, save the MeasuringRate and MeasuringInterval for future usage
3539
3540 return RETURN_OK;
3541}
3542
3543//To start or stop RadioTrafficStats
3544INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3545{
3546 //zqiu: If the RadioTrafficStats process running
3547 // if(enable)
3548 // return RETURN_OK.
3549 // else
3550 // Stop RadioTrafficStats process
3551 // Else
3552 // if(enable)
3553 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3554 // else
3555 // return RETURN_OK.
3556
3557 return RETURN_OK;
3558}
3559
3560//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
3561INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3562{
3563 //zqiu: Please ignor signalIndex.
3564 if (NULL == SignalLevel)
3565 return RETURN_ERR;
3566 *SignalLevel=(radioIndex==0)?-19:-19;
3567
3568 return RETURN_OK;
3569}
3570
3571//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3572INT wifi_applyRadioSettings(INT radioIndex)
3573{
3574 return RETURN_OK;
3575}
3576
3577//Get the radio index assocated with this SSID entry
3578INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3579{
3580 if(NULL == radioIndex)
3581 return RETURN_ERR;
3582 int max_radio_num = 0;
3583 wifi_getMaxRadioNumber(&max_radio_num);
3584 *radioIndex = ssidIndex%max_radio_num;
3585 return RETURN_OK;
3586}
3587
3588//Device.WiFi.SSID.{i}.Enable
3589//Get SSID enable configuration parameters (not the SSID enable status)
3590INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3591{
3592 if (NULL == output_bool)
3593 return RETURN_ERR;
3594
3595 return wifi_getApEnable(ssidIndex, output_bool);
3596}
3597
3598//Device.WiFi.SSID.{i}.Enable
3599//Set SSID enable configuration parameters
3600INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3601{
3602 return wifi_setApEnable(ssidIndex, enable);
3603}
3604
3605//Device.WiFi.SSID.{i}.Status
3606//Get the SSID enable status
3607INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3608{
3609 char cmd[MAX_CMD_SIZE]={0};
3610 char buf[MAX_BUF_SIZE]={0};
3611 BOOL output_bool;
3612
3613 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3614 if (NULL == output_string)
3615 return RETURN_ERR;
3616
3617 wifi_getApEnable(ssidIndex,&output_bool);
3618 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3619
3620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3621 return RETURN_OK;
3622}
3623
3624// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3625INT wifi_getSSIDName(INT apIndex, CHAR *output)
3626{
3627 char config_file[MAX_BUF_SIZE] = {0};
3628
3629 if (NULL == output)
3630 return RETURN_ERR;
3631
3632 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3633 wifi_hostapdRead(config_file,"ssid",output,32);
3634
3635 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3636 return RETURN_OK;
3637}
3638
3639// Set a max 32 byte string and sets an internal variable to the SSID name
3640INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3641{
3642 char str[MAX_BUF_SIZE]={'\0'};
3643 char cmd[MAX_CMD_SIZE]={'\0'};
3644 struct params params;
3645 char config_file[MAX_BUF_SIZE] = {0};
3646
3647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3648 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3649 return RETURN_ERR;
3650
3651 params.name = "ssid";
3652 params.value = ssid_string;
3653 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3654 wifi_hostapdWrite(config_file, &params, 1);
3655 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3657
3658 return RETURN_OK;
3659}
3660
3661//Get the BSSID
3662INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3663{
3664 char cmd[MAX_CMD_SIZE]="";
3665
3666 if (NULL == output_string)
3667 return RETURN_ERR;
3668
3669 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3670 {
3671 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
3672 _syscmd(cmd, output_string, 64);
3673 return RETURN_OK;
3674 }
3675 strncpy(output_string, "\0", 1);
3676
3677 return RETURN_ERR;
3678}
3679
3680//Get the MAC address associated with this Wifi SSID
3681INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3682{
3683 wifi_getBaseBSSID(ssidIndex,output_string);
3684 return RETURN_OK;
3685}
3686
3687//Get the basic SSID traffic static info
3688//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3689//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3690INT wifi_applySSIDSettings(INT ssidIndex)
3691{
3692 char interface_name[16] = {0};
3693 BOOL status = false;
3694 char cmd[MAX_CMD_SIZE] = {0};
3695 char buf[MAX_CMD_SIZE] = {0};
3696 int apIndex, ret;
3697 int max_radio_num = 0;
3698 int radioIndex = 0;
3699
3700 wifi_getMaxRadioNumber(&max_radio_num);
3701
3702 radioIndex = ssidIndex % max_radio_num;
3703
3704 wifi_getApEnable(ssidIndex,&status);
3705 // Do not apply when ssid index is disabled
3706 if (status == false)
3707 return RETURN_OK;
3708
3709 /* Doing full remove and add for ssid Index
3710 * Not all hostapd options are supported with reload
3711 * for example macaddr_acl
3712 */
3713 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3714 return RETURN_ERR;
3715
3716 ret = wifi_setApEnable(ssidIndex,true);
3717
3718 /* Workaround for hostapd issue with multiple bss definitions
3719 * when first created interface will be removed
3720 * then all vaps other vaps on same phy are removed
3721 * after calling setApEnable to false readd all enabled vaps */
3722 for(int i=0; i < MAX_APS/max_radio_num; i++) {
3723 apIndex = max_radio_num*i+radioIndex;
3724 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
3725 return RETURN_ERR;
3726 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
3727 _syscmd(cmd, buf, sizeof(buf));
3728 if(*buf == '1')
3729 wifi_setApEnable(apIndex, true);
3730 }
3731
3732 return ret;
3733}
3734
3735struct channels_noise {
3736 int channel;
3737 int noise;
3738};
3739
3740// Return noise array for each channel
3741int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3742{
3743 char interface_name[16] = {0};
3744 FILE *f = NULL;
3745 char cmd[128] = {0};
3746 char line[256] = {0};
3747 size_t len = 0;
3748 ssize_t read = 0;
3749 int tmp = 0, arr_index = -1;
3750
3751 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3752 return RETURN_ERR;
3753 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
3754
3755 if ((f = popen(cmd, "r")) == NULL) {
3756 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3757 return RETURN_ERR;
3758 }
3759
3760 while(fgets(line, sizeof(line), f) != NULL) {
3761 if(arr_index < channels_num){
3762 sscanf(line, "%d", &tmp);
3763 if (tmp > 0) { // channel frequency, the first line must be frequency
3764 arr_index++;
3765 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3766 } else { // noise
3767 channels_noise_arr[arr_index].noise = tmp;
3768 }
3769 }else{
3770 break;
3771 }
3772 }
3773 pclose(f);
3774 return RETURN_OK;
3775}
3776
3777//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3778//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3779INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3780{
3781 int index = -1;
3782 wifi_neighbor_ap2_t *scan_array = NULL;
3783 char cmd[256]={0};
3784 char buf[128]={0};
3785 char file_name[32] = {0};
3786 char filter_SSID[32] = {0};
3787 char line[256] = {0};
3788 char interface_name[16] = {0};
3789 char *ret = NULL;
3790 int freq=0;
3791 FILE *f = NULL;
3792 size_t len=0;
3793 int channels_num = 0;
3794 int vht_channel_width = 0;
3795 int get_noise_ret = RETURN_ERR;
3796 bool filter_enable = false;
3797 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
3798 int phyId = 0;
3799
3800 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
3801
3802 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3803 return RETURN_ERR;
3804
3805 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3806 f = fopen(file_name, "r");
3807 if (f != NULL) {
3808 fgets(filter_SSID, sizeof(file_name), f);
3809 if (strlen(filter_SSID) != 0)
3810 filter_enable = true;
3811 fclose(f);
3812 }
3813
3814 phyId = radio_index_to_phy(radioIndex);
3815 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
3816 _syscmd(cmd, buf, sizeof(buf));
3817 channels_num = strtol(buf, NULL, 10);
3818
3819
3820
3821 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
3822 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
3823 fprintf(stderr, "cmd: %s\n", cmd);
3824 if ((f = popen(cmd, "r")) == NULL) {
3825 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3826 return RETURN_ERR;
3827 }
3828
3829 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3830 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3831
3832 ret = fgets(line, sizeof(line), f);
3833 while (ret != NULL) {
3834 if(strstr(line, "BSS") != NULL) { // new neighbor info
3835 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3836 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3837 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
3838
3839 if (!filter_BSS) {
3840 index++;
3841 wifi_neighbor_ap2_t *tmp;
3842 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3843 if (tmp == NULL) { // no more memory to use
3844 index--;
3845 wifi_dbg_printf("%s: realloc failed\n", __func__);
3846 break;
3847 }
3848 scan_array = tmp;
3849 }
3850 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3851
3852 filter_BSS = false;
3853 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3854 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3855 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3856 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3857 } else if (strstr(line, "freq") != NULL) {
3858 sscanf(line," freq: %d", &freq);
3859 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3860
3861 if (freq >= 2412 && freq <= 2484) {
3862 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3863 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3864 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3865 }
3866 else if (freq >= 5160 && freq <= 5805) {
3867 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3868 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3869 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3870 }
3871
3872 scan_array[index].ap_Noise = 0;
3873 if (get_noise_ret == RETURN_OK) {
3874 for (int i = 0; i < channels_num; i++) {
3875 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3876 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3877 break;
3878 }
3879 }
3880 }
3881 } else if (strstr(line, "beacon interval") != NULL) {
3882 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3883 } else if (strstr(line, "signal") != NULL) {
3884 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3885 } else if (strstr(line,"SSID") != NULL) {
3886 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3887 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3888 filter_BSS = true;
3889 }
3890 } else if (strstr(line, "Supported rates") != NULL) {
3891 char SRate[80] = {0}, *tmp = NULL;
3892 memset(buf, 0, sizeof(buf));
3893 strcpy(SRate, line);
3894 tmp = strtok(SRate, ":");
3895 tmp = strtok(NULL, ":");
3896 strcpy(buf, tmp);
3897 memset(SRate, 0, sizeof(SRate));
3898
3899 tmp = strtok(buf, " \n");
3900 while (tmp != NULL) {
3901 strcat(SRate, tmp);
3902 if (SRate[strlen(SRate) - 1] == '*') {
3903 SRate[strlen(SRate) - 1] = '\0';
3904 }
3905 strcat(SRate, ",");
3906
3907 tmp = strtok(NULL, " \n");
3908 }
3909 SRate[strlen(SRate) - 1] = '\0';
3910 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3911 } else if (strstr(line, "DTIM") != NULL) {
3912 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3913 } else if (strstr(line, "VHT capabilities") != NULL) {
3914 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3915 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3916 } else if (strstr(line, "HT capabilities") != NULL) {
3917 strcat(scan_array[index].ap_SupportedStandards, ",n");
3918 strcpy(scan_array[index].ap_OperatingStandards, "n");
3919 } else if (strstr(line, "VHT operation") != NULL) {
3920 ret = fgets(line, sizeof(line), f);
3921 sscanf(line," * channel width: %d", &vht_channel_width);
3922 if(vht_channel_width == 1) {
3923 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3924 } else {
3925 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3926 }
3927 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3928 continue;
3929 } else if (strstr(line, "HT operation") != NULL) {
3930 ret = fgets(line, sizeof(line), f);
3931 sscanf(line," * secondary channel offset: %s", &buf);
3932 if (!strcmp(buf, "above")) {
3933 //40Mhz +
3934 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3935 }
3936 else if (!strcmp(buf, "below")) {
3937 //40Mhz -
3938 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3939 } else {
3940 //20Mhz
3941 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3942 }
3943 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3944 continue;
3945 } else if (strstr(line, "HE capabilities") != NULL) {
3946 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3947 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3948 ret = fgets(line, sizeof(line), f);
3949 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3950 if (strstr(line, "HE40/2.4GHz") != NULL)
3951 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
3952 else
3953 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
3954 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
3955 if (strstr(line, "HE80/5GHz") != NULL) {
3956 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3957 ret = fgets(line, sizeof(line), f);
3958 } else
3959 continue;
3960 if (strstr(line, "HE160/5GHz") != NULL)
3961 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
3962 }
3963 continue;
3964 } else if (strstr(line, "WPA") != NULL) {
3965 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3966 } else if (strstr(line, "RSN") != NULL) {
3967 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3968 } else if (strstr(line, "Group cipher") != NULL) {
3969 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3970 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3971 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3972 }
3973 }
3974 ret = fgets(line, sizeof(line), f);
3975 }
3976
3977 if (!filter_BSS) {
3978 *output_array_size = index + 1;
3979 } else {
3980 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3981 *output_array_size = index;
3982 }
3983 *neighbor_ap_array = scan_array;
3984 pclose(f);
3985 free(channels_noise_arr);
3986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3987 return RETURN_OK;
3988}
3989
3990//>> Deprecated: used for old RDKB code.
3991INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3992{
3993 INT status = RETURN_ERR;
3994
3995 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3996 output_struct->wifi_PLCPErrorCount = 0;
3997 output_struct->wifi_FCSErrorCount = 0;
3998 output_struct->wifi_InvalidMACCount = 0;
3999 output_struct->wifi_PacketsOtherReceived = 0;
4000 output_struct->wifi_Noise = 0;
4001 status = RETURN_OK;
4002 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4003 return status;
4004}
4005
4006INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4007{
4008 char interface_name[16] = {0};
4009 char cmd[128] = {0};
4010 char buf[1280] = {0};
4011 char *pos = NULL;
4012
4013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4014 if (NULL == output_struct)
4015 return RETURN_ERR;
4016
4017 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4018 return RETURN_ERR;
4019
4020 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4021
4022 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4023 _syscmd(cmd, buf, sizeof(buf));
4024
4025 pos = buf;
4026 if ((pos = strstr(pos, "RX packets:")) == NULL)
4027 return RETURN_ERR;
4028 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4029
4030 if ((pos = strstr(pos, "TX packets:")) == NULL)
4031 return RETURN_ERR;
4032 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4033
4034 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4035 return RETURN_ERR;
4036 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4037
4038 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4039 return RETURN_ERR;
4040 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4041
4042 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4043 _syscmd(cmd, buf, sizeof(buf));
4044 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4045
4046#if 0
4047 //TODO: need to revisit below implementation
4048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4049 char interface_name[MAX_BUF_SIZE] = {0};
4050 char interface_status[MAX_BUF_SIZE] = {0};
4051 char Value[MAX_BUF_SIZE] = {0};
4052 char buf[MAX_CMD_SIZE] = {0};
4053 char cmd[MAX_CMD_SIZE] = {0};
4054 FILE *fp = NULL;
4055
4056 if (NULL == output_struct) {
4057 return RETURN_ERR;
4058 }
4059
4060 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4061
4062 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4063 {
4064 if(apIndex == 0) //private_wifi for 2.4G
4065 {
4066 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4067 }
4068 else if(apIndex == 1) //private_wifi for 5G
4069 {
4070 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4071 }
4072 else if(apIndex == 4) //public_wifi for 2.4G
4073 {
4074 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4075 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4076 {
4077 return RETURN_ERR;
4078 }
4079 if(buf[0] == '#')//tp-link
4080 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4081 else//tenda
4082 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4083 }
4084 else if(apIndex == 5) //public_wifi for 5G
4085 {
4086 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4087 }
4088
4089 GetIfacestatus(interface_name, interface_status);
4090
4091 if(0 != strcmp(interface_status, "1"))
4092 return RETURN_ERR;
4093
4094 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4095 system(cmd);
4096
4097 fp = fopen("/tmp/SSID_Stats.txt", "r");
4098 if(fp == NULL)
4099 {
4100 printf("/tmp/SSID_Stats.txt not exists \n");
4101 return RETURN_ERR;
4102 }
4103 fclose(fp);
4104
4105 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4106 File_Reading(buf, Value);
4107 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4108
4109 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4110 File_Reading(buf, Value);
4111 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4112
4113 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4114 File_Reading(buf, Value);
4115 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4116
4117 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4118 File_Reading(buf, Value);
4119 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4120
4121 /* There is no specific parameter from caller to associate the value wifi_Associations */
4122 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4123 //_syscmd(cmd, buf, sizeof(buf));
4124 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4125 }
4126#endif
4127 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4128 return RETURN_OK;
4129}
4130
4131INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4132{
4133 char interface_name[MAX_BUF_SIZE] = {0};
4134 char interface_status[MAX_BUF_SIZE] = {0};
4135 char Value[MAX_BUF_SIZE] = {0};
4136 char buf[MAX_CMD_SIZE] = {0};
4137 char cmd[MAX_CMD_SIZE] = {0};
4138 FILE *fp = NULL;
4139
4140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4141 if (NULL == output_struct)
4142 return RETURN_ERR;
4143
4144 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4145
4146 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4147 return RETURN_ERR;
4148 GetIfacestatus(interface_name, interface_status);
4149
4150 if(0 != strcmp(interface_status, "1"))
4151 return RETURN_ERR;
4152
4153 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4154 system(cmd);
4155
4156 fp = fopen("/tmp/SSID_Stats.txt", "r");
4157 if(fp == NULL)
4158 {
4159 printf("/tmp/SSID_Stats.txt not exists \n");
4160 return RETURN_ERR;
4161 }
4162 fclose(fp);
4163
4164 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4165 File_Reading(buf, Value);
4166 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4167
4168 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4169 File_Reading(buf, Value);
4170 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4171
4172 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4173 File_Reading(buf, Value);
4174 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4175
4176 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4177 File_Reading(buf, Value);
4178 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4179
4180 output_struct->wifi_UnicastPacketsSent = 0;
4181 output_struct->wifi_UnicastPacketsReceived = 0;
4182 output_struct->wifi_MulticastPacketsSent = 0;
4183 output_struct->wifi_MulticastPacketsReceived = 0;
4184 output_struct->wifi_BroadcastPacketsSent = 0;
4185 output_struct->wifi_BroadcastPacketsRecevied = 0;
4186 output_struct->wifi_UnknownPacketsReceived = 0;
4187
4188 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4189 return RETURN_OK;
4190}
4191
4192INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4193{
4194 INT status = RETURN_ERR;
4195
4196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4197 //Below values should get updated from hal
4198 output_struct->wifi_RetransCount=0;
4199 output_struct->wifi_FailedRetransCount=0;
4200 output_struct->wifi_RetryCount=0;
4201 output_struct->wifi_MultipleRetryCount=0;
4202 output_struct->wifi_ACKFailureCount=0;
4203 output_struct->wifi_AggregatedPacketCount=0;
4204
4205 status = RETURN_OK;
4206 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4207
4208 return status;
4209}
4210
4211INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4212{
4213 INT status = RETURN_ERR;
4214 UINT index;
4215 wifi_neighbor_ap_t *pt=NULL;
4216
4217 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4218 *output_array_size=2;
4219 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4220 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4221 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4222 strcpy(pt->ap_Radio,"");
4223 strcpy(pt->ap_SSID,"");
4224 strcpy(pt->ap_BSSID,"");
4225 strcpy(pt->ap_Mode,"");
4226 pt->ap_Channel=1;
4227 pt->ap_SignalStrength=0;
4228 strcpy(pt->ap_SecurityModeEnabled,"");
4229 strcpy(pt->ap_EncryptionMode,"");
4230 strcpy(pt->ap_OperatingFrequencyBand,"");
4231 strcpy(pt->ap_SupportedStandards,"");
4232 strcpy(pt->ap_OperatingStandards,"");
4233 strcpy(pt->ap_OperatingChannelBandwidth,"");
4234 pt->ap_BeaconPeriod=1;
4235 pt->ap_Noise=0;
4236 strcpy(pt->ap_BasicDataTransferRates,"");
4237 strcpy(pt->ap_SupportedDataTransferRates,"");
4238 pt->ap_DTIMPeriod=1;
4239 pt->ap_ChannelUtilization = 1;
4240 }
4241
4242 status = RETURN_OK;
4243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4244
4245 return status;
4246}
4247
4248//----------------- AP HAL -------------------------------
4249
4250//>> Deprecated: used for old RDKB code.
4251INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4252{
4253 if (NULL == output_ulong || NULL == output_struct)
4254 return RETURN_ERR;
4255 *output_ulong = 0;
4256 *output_struct = NULL;
4257 return RETURN_OK;
4258}
4259
4260#ifdef HAL_NETLINK_IMPL
4261static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4262 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4263 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4264 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4265 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4266 char mac_addr[20];
4267 static int count=0;
4268 int rate=0;
4269
4270 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4271
4272 nla_parse(tb,
4273 NL80211_ATTR_MAX,
4274 genlmsg_attrdata(gnlh, 0),
4275 genlmsg_attrlen(gnlh, 0),
4276 NULL);
4277
4278 if(!tb[NL80211_ATTR_STA_INFO]) {
4279 fprintf(stderr, "sta stats missing!\n");
4280 return NL_SKIP;
4281 }
4282
4283
4284 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4285 fprintf(stderr, "failed to parse nested attributes!\n");
4286 return NL_SKIP;
4287 }
4288
4289 //devIndex starts from 1
4290 if( ++count == out->wifi_devIndex )
4291 {
4292 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4293 //Getting the mac addrress
4294 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4295
4296 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4297 fprintf(stderr, "failed to parse nested rate attributes!");
4298 return NL_SKIP;
4299 }
4300
4301 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4302 if(rinfo[NL80211_RATE_INFO_BITRATE])
4303 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4304 out->wifi_devTxRate = rate/10;
4305 }
4306
4307 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4308 fprintf(stderr, "failed to parse nested rate attributes!");
4309 return NL_SKIP;
4310 }
4311
4312 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4313 if(rinfo[NL80211_RATE_INFO_BITRATE])
4314 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4315 out->wifi_devRxRate = rate/10;
4316 }
4317 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4318 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4319
4320 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4321 count = 0; //starts the count for next cycle
4322 return NL_STOP;
4323 }
4324
4325 return NL_SKIP;
4326
4327}
4328#endif
4329
4330INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4331{
4332#ifdef HAL_NETLINK_IMPL
4333 Netlink nl = {0};
4334 char if_name[10] = {0};
4335 char interface_name[16] = {0};
4336
4337 wifi_device_info_t info = {0};
4338 info.wifi_devIndex = devIndex;
4339
4340 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4341 return RETURN_ERR;
4342
4343 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4344
4345 nl.id = initSock80211(&nl);
4346
4347 if (nl.id < 0) {
4348 fprintf(stderr, "Error initializing netlink \n");
4349 return -1;
4350 }
4351
4352 struct nl_msg* msg = nlmsg_alloc();
4353
4354 if (!msg) {
4355 fprintf(stderr, "Failed to allocate netlink message.\n");
4356 nlfree(&nl);
4357 return -2;
4358 }
4359
4360 genlmsg_put(msg,
4361 NL_AUTO_PORT,
4362 NL_AUTO_SEQ,
4363 nl.id,
4364 0,
4365 NLM_F_DUMP,
4366 NL80211_CMD_GET_STATION,
4367 0);
4368
4369 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4370 nl_send_auto(nl.socket, msg);
4371 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4372 nl_recvmsgs(nl.socket, nl.cb);
4373 nlmsg_free(msg);
4374 nlfree(&nl);
4375
4376 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4377 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4378 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4379 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4380 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4381 return RETURN_OK;
4382#else
4383 //iw utility to retrieve station information
4384#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4385#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4386#define MACFILE "/tmp/wifi_AssoMac.txt"
4387#define TXRATEFILE "/tmp/wifi_txrate.txt"
4388#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4389 FILE *file = NULL;
4390 char if_name[10] = {'\0'};
4391 char pipeCmd[256] = {'\0'};
4392 char line[256] = {0};
4393 char interface_name[16] = {0};
4394 int count = 0, device = 0;
4395
4396 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4397 return RETURN_ERR;
4398
4399 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4400
4401 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4402 file = popen(pipeCmd, "r");
4403
4404 if(file == NULL)
4405 return RETURN_ERR; //popen failed
4406
4407 fgets(line, sizeof line, file);
4408 device = atoi(line);
4409 pclose(file);
4410
4411 if(device == 0)
4412 return RETURN_ERR; //No devices are connected
4413
4414 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4415 system(pipeCmd);
4416
4417 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4418
4419 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4420
4421 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4422
4423 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4424
4425 //devIndex starts from 1, ++count
4426 if((file = fopen(SIGNALFILE, "r")) != NULL )
4427 {
4428 for(count =0;fgets(line, sizeof line, file) != NULL;)
4429 {
4430 if (++count == devIndex)
4431 {
4432 output_struct->wifi_devSignalStrength = atoi(line);
4433 break;
4434 }
4435 }
4436 fclose(file);
4437 }
4438 else
4439 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4440
4441 if((file = fopen(MACFILE, "r")) != NULL )
4442 {
4443 for(count =0;fgets(line, sizeof line, file) != NULL;)
4444 {
4445 if (++count == devIndex)
4446 {
4447 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]);
4448 break;
4449 }
4450 }
4451 fclose(file);
4452 }
4453 else
4454 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4455
4456 if((file = fopen(TXRATEFILE, "r")) != NULL )
4457 {
4458 for(count =0;fgets(line, sizeof line, file) != NULL;)
4459 {
4460 if (++count == devIndex)
4461 {
4462 output_struct->wifi_devTxRate = atoi(line);
4463 break;
4464 }
4465 }
4466 fclose(file);
4467 }
4468 else
4469 fprintf(stderr,"fopen wifi_txrate.txt failed");
4470
4471 if((file = fopen(RXRATEFILE, "r")) != NULL)
4472 {
4473 for(count =0;fgets(line, sizeof line, file) != NULL;)
4474 {
4475 if (++count == devIndex)
4476 {
4477 output_struct->wifi_devRxRate = atoi(line);
4478 break;
4479 }
4480 }
4481 fclose(file);
4482 }
4483 else
4484 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4485
4486 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4487
4488 return RETURN_OK;
4489#endif
4490}
4491
4492INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4493{
4494 if (NULL == device)
4495 return RETURN_ERR;
4496 return RETURN_OK;
4497}
4498//<<
4499
4500
4501//--------------wifi_ap_hal-----------------------------
4502//enables CTS protection for the radio used by this AP
4503INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4504{
4505 //save config and Apply instantly
4506 return RETURN_ERR;
4507}
4508
4509// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4510INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4511{
4512 char config_file[64] = {'\0'};
4513 char buf[64] = {'\0'};
4514 struct params list;
4515
4516 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4517 list.name = "ht_coex";
4518 snprintf(buf, sizeof(buf), "%d", enable);
4519 list.value = buf;
4520
4521 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4522 wifi_hostapdWrite(config_file, &list, 1);
4523 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4524
4525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4526
4527 return RETURN_OK;
4528}
4529
4530//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4531INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4532{
4533 char config_file[MAX_BUF_SIZE] = {'\0'};
4534 char buf[MAX_BUF_SIZE] = {'\0'};
4535 struct params list;
4536
4537 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4538 if (threshold < 256 || threshold > 2346 )
4539 return RETURN_ERR;
4540 list.name = "fragm_threshold";
4541 snprintf(buf, sizeof(buf), "%d", threshold);
4542 list.value = buf;
4543
4544 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4545 wifi_hostapdWrite(config_file, &list, 1);
4546 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4547
4548 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4549
4550 return RETURN_OK;
4551}
4552
4553// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4554INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4555{
4556 char config_file[64] = {'\0'};
4557 char cmd[512] = {'\0'};
4558 char buf[512] = {'\0'};
4559 char stbc_config[16] = {'\0'};
4560 wifi_band band;
4561 int iterator = 0;
4562 BOOL current_stbc = FALSE;
4563 int ant_count = 0;
4564 int ant_bitmap = 0;
4565 struct params list;
4566
4567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4568
4569 band = wifi_index_to_band(radioIndex);
4570 if (band == band_invalid)
4571 return RETURN_ERR;
4572
4573 if (band == band_2_4)
4574 iterator = 1;
4575 else if (band == band_5)
4576 iterator = 2;
4577 else
4578 return RETURN_OK;
4579
4580 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4581 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4582 ant_count += ant_bitmap & 1;
4583
4584 if (ant_count == 1 && STBC_Enable == TRUE) {
4585 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4586 return RETURN_OK;
4587 }
4588
4589 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4590
4591 // set ht and vht config
4592 for (int i = 0; i < iterator; i++) {
4593 memset(stbc_config, 0, sizeof(stbc_config));
4594 memset(cmd, 0, sizeof(cmd));
4595 memset(buf, 0, sizeof(buf));
4596 list.name = (i == 0)?"ht_capab":"vht_capab";
4597 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
4598 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4599 _syscmd(cmd, buf, sizeof(buf));
4600 if (strlen(buf) != 0)
4601 current_stbc = TRUE;
4602 if (current_stbc == STBC_Enable)
4603 continue;
4604
4605 if (STBC_Enable == TRUE) {
4606 // Append the STBC flags in capab config
4607 memset(cmd, 0, sizeof(cmd));
4608 if (i == 0)
4609 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4610 else
4611 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4612 _syscmd(cmd, buf, sizeof(buf));
4613 } else if (STBC_Enable == FALSE) {
4614 // Remove the STBC flags and remain other flags in capab
4615 memset(cmd, 0, sizeof(cmd));
4616 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4617 _syscmd(cmd, buf, sizeof(buf));
4618 memset(cmd, 0, sizeof(cmd));
4619 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4620 _syscmd(cmd, buf, sizeof(buf));
4621 }
4622 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4623 list.value = buf;
4624 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4625 }
4626
4627 wifi_reloadAp(radioIndex);
4628
4629 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4630 return RETURN_OK;
4631}
4632
4633// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4634INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4635{
4636 char cmd[128] = {0};
4637 char buf[128] = {0};
4638 char interface_name[16] = {0};
4639
4640 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4641
4642 if(output_bool == NULL)
4643 return RETURN_ERR;
4644
4645 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4646 return RETURN_ERR;
4647
4648 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4649 _syscmd(cmd, buf, sizeof(buf));
4650
4651 if (strncmp(buf, "1", 1) == 0)
4652 *output_bool = TRUE;
4653 else
4654 *output_bool = FALSE;
4655
4656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4657 return RETURN_OK;
4658}
4659
4660// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4661INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4662{
4663 char config_file[128] = {0};
4664 struct params list = {0};
4665 BOOL enable;
4666
4667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4668
4669 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
4670 return RETURN_ERR;
4671
4672 if (amsduEnable == enable)
4673 return RETURN_OK;
4674
4675 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4676 list.name = "amsdu";
4677 list.value = amsduEnable? "1":"0";
4678 wifi_hostapdWrite(config_file, &list, 1);
4679 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4680 wifi_reloadAp(radioIndex);
4681
4682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4683 return RETURN_OK;
4684}
4685
4686//P2 // outputs the number of Tx streams
4687INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4688{
4689 char buf[8] = {0};
4690 char cmd[128] = {0};
4691 int phyId = 0;
4692
4693 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4694
4695 phyId = radio_index_to_phy(radioIndex);
4696 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
4697 _syscmd(cmd, buf, sizeof(buf));
4698
4699 *output_int = (INT)strtol(buf, NULL, 16);
4700
4701 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4702
4703 return RETURN_OK;
4704}
4705
4706INT fitChainMask(INT radioIndex, int antcount)
4707{
4708 char buf[128] = {0};
4709 char cmd[128] = {0};
4710 char config_file[64] = {0};
4711 wifi_band band;
4712 struct params list[2] = {0};
4713
4714 band = wifi_index_to_band(radioIndex);
4715 if (band == band_invalid)
4716 return RETURN_ERR;
4717
4718 list[0].name = "he_mu_beamformer";
4719 list[1].name = "he_su_beamformer";
4720
4721 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4722 if (antcount == 1) {
4723 // remove config about multiple antennas
4724 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4725 _syscmd(cmd, buf, sizeof(buf));
4726
4727 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
4728 _syscmd(cmd, buf, sizeof(buf));
4729
4730 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
4731 _syscmd(cmd, buf, sizeof(buf));
4732
4733 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
4734 _syscmd(cmd, buf, sizeof(buf));
4735
4736 list[0].value = "0";
4737 list[1].value = "0";
4738 } else {
4739 // 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.
4740 if (band == band_2_4 || band == band_5) {
4741 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4742 _syscmd(cmd, buf, sizeof(buf));
4743 if (strlen(buf) > 0) {
4744 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
4745 _syscmd(cmd, buf, sizeof(buf));
4746 }
4747 }
4748 if (band == band_5) {
4749 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
4750 _syscmd(cmd, buf, sizeof(buf));
4751 if (strlen(buf) > 0) {
4752 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
4753 _syscmd(cmd, buf, sizeof(buf));
4754 }
4755 }
4756
4757 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
4758 _syscmd(cmd, buf, sizeof(buf));
4759 if (strlen(buf) == 0) {
4760 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
4761 _syscmd(cmd, buf, sizeof(buf));
4762 }
4763
4764 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
4765 _syscmd(cmd, buf, sizeof(buf));
4766 if (strlen(buf) == 0) {
4767 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
4768 _syscmd(cmd, buf, sizeof(buf));
4769 }
4770
4771 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
4772 _syscmd(cmd, buf, sizeof(buf));
4773 if (strlen(buf) == 0) {
4774 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
4775 } else {
4776 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
4777 }
4778 _syscmd(cmd, buf, sizeof(buf));
4779
4780 list[0].value = "1";
4781 list[1].value = "1";
4782 }
4783 wifi_hostapdWrite(config_file, list, 2);
4784}
4785
4786//P2 // sets the number of Tx streams to an enviornment variable
4787INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4788{
4789 char cmd[128] = {0};
4790 char buf[128] = {0};
4791 int phyId = 0;
4792 int cur_mask = 0;
4793 int antcount = 0;
4794 wifi_band band;
4795
4796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4797
4798 if (numStreams <= 0) {
4799 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
4800 return RETURN_ERR;
4801 }
4802
4803 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
4804 if (cur_mask == numStreams)
4805 return RETURN_OK;
4806
4807 wifi_setRadioEnable(radioIndex, FALSE);
4808
4809 phyId = radio_index_to_phy(radioIndex);
4810 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
4811 _syscmd(cmd, buf, sizeof(buf));
4812
4813 if (strlen(buf) > 0) {
4814 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4815 return RETURN_ERR;
4816 }
4817
4818 // if chain mask changed, we need to make the hostapd config valid.
4819 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
4820 antcount += cur_mask & 1;
4821 }
4822 fitChainMask(radioIndex, antcount);
4823
4824 wifi_setRadioEnable(radioIndex, TRUE);
4825
4826 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4827 return RETURN_OK;
4828}
4829
4830//P2 // outputs the number of Rx streams
4831INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4832{
4833 char buf[8] = {0};
4834 char cmd[128] = {0};
4835 int phyId = 0;
4836
4837 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4838
4839 phyId = radio_index_to_phy(radioIndex);
4840 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
4841 _syscmd(cmd, buf, sizeof(buf));
4842
4843 *output_int = (INT)strtol(buf, NULL, 16);
4844
4845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4846
4847 return RETURN_OK;
4848}
4849
4850//P2 // sets the number of Rx streams to an enviornment variable
4851INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4852{
4853 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4854 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4855 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4856 return RETURN_ERR;
4857 }
4858 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4859 return RETURN_ERR;
4860}
4861
4862//Get radio RDG enable setting
4863INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4864{
4865 if (NULL == output_bool)
4866 return RETURN_ERR;
4867 *output_bool = TRUE;
4868 return RETURN_OK;
4869}
4870
4871//Get radio RDG enable setting
4872INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4873{
4874 if (NULL == output_bool)
4875 return RETURN_ERR;
4876 *output_bool = TRUE;
4877 return RETURN_OK;
4878}
4879
4880//Set radio RDG enable setting
4881INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4882{
4883 return RETURN_ERR;
4884}
4885
4886//Get radio ADDBA enable setting
4887INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4888{
4889 if (NULL == output_bool)
4890 return RETURN_ERR;
4891 *output_bool = TRUE;
4892 return RETURN_OK;
4893}
4894
4895//Set radio ADDBA enable setting
4896INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4897{
4898 return RETURN_ERR;
4899}
4900
4901//Get radio auto block ack enable setting
4902INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4903{
4904 if (NULL == output_bool)
4905 return RETURN_ERR;
4906 *output_bool = TRUE;
4907 return RETURN_OK;
4908}
4909
4910//Set radio auto block ack enable setting
4911INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4912{
4913 return RETURN_ERR;
4914}
4915
4916//Get radio 11n pure mode enable support
4917INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4918{
4919 if (NULL == output_bool)
4920 return RETURN_ERR;
4921 *output_bool = TRUE;
4922 return RETURN_OK;
4923}
4924
4925//Get radio 11n pure mode enable setting
4926INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4927{
4928 if (NULL == output_bool)
4929 return RETURN_ERR;
4930 *output_bool = TRUE;
4931 return RETURN_OK;
4932}
4933
4934//Set radio 11n pure mode enable setting
4935INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4936{
4937 return RETURN_ERR;
4938}
4939
4940//Get radio IGMP snooping enable setting
4941INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4942{
4943 char interface_name[16] = {0};
4944 char cmd[128]={0};
4945 char buf[4]={0};
4946 bool bridge = FALSE, mac80211 = FALSE;
4947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4948
4949 if(output_bool == NULL)
4950 return RETURN_ERR;
4951
4952 *output_bool = FALSE;
4953
4954 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4955 _syscmd(cmd, buf, sizeof(buf));
4956 if (strncmp(buf, "1", 1) == 0)
4957 bridge = TRUE;
4958
4959 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4960 return RETURN_ERR;
4961 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
4962 _syscmd(cmd, buf, sizeof(buf));
4963 if (strncmp(buf, "1", 1) == 0)
4964 mac80211 = TRUE;
4965
4966 if (bridge && mac80211)
4967 *output_bool = TRUE;
4968
4969 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4970 return RETURN_OK;
4971}
4972
4973//Set radio IGMP snooping enable setting
4974INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4975{
4976 char interface_name[16] = {0};
4977 char cmd[128]={0};
4978 char buf[4]={0};
4979 int max_num_radios =0;
4980 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4981
4982 // bridge
4983 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4984 _syscmd(cmd, buf, sizeof(buf));
4985
4986 wifi_getMaxRadioNumber(&max_num_radios);
4987 // mac80211
4988 for (int i = 0; i < max_num_radios; i++) {
4989 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
4990 return RETURN_ERR;
4991 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
4992 _syscmd(cmd, buf, sizeof(buf));
4993 }
4994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4995 return RETURN_OK;
4996}
4997
4998//Get the Reset count of radio
4999INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5000{
5001 if (NULL == output_int)
5002 return RETURN_ERR;
5003 *output_int = (radioIndex==0)? 1: 3;
5004
5005 return RETURN_OK;
5006}
5007
5008
5009//---------------------------------------------------------------------------------------------------
5010//
5011// Additional Wifi AP level APIs used for Access Point devices
5012//
5013//---------------------------------------------------------------------------------------------------
5014
5015// creates a new ap and pushes these parameters to the hardware
5016INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5017{
5018 // Deprecated when use hal version 3, use wifi_createVap() instead.
5019 return RETURN_OK;
5020}
5021
5022// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5023INT wifi_deleteAp(INT apIndex)
5024{
5025 char interface_name[16] = {0};
5026 char buf[1024];
5027 char cmd[128];
5028
5029 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5030 return RETURN_ERR;
5031 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
5032 _syscmd(cmd, buf, sizeof(buf));
5033
5034 wifi_removeApSecVaribles(apIndex);
5035
5036 return RETURN_OK;
5037}
5038
5039// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5040INT wifi_getApName(INT apIndex, CHAR *output_string)
5041{
5042 char interface_name[16] = {0};
5043 if(NULL == output_string)
5044 return RETURN_ERR;
5045
5046 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5047 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
5048 else
5049 snprintf(output_string, 16, "%s", interface_name);
5050 return RETURN_OK;
5051}
5052
5053// Outputs the index number in that corresponds to the SSID string
5054INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5055{
5056 char cmd [128] = {0};
5057 char buf[32] = {0};
5058 char *apIndex_str = NULL;
5059 bool enable = FALSE;
5060
5061 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5062 _syscmd(cmd, buf, sizeof(buf));
5063
5064 if (strlen(buf) != 0) {
5065 apIndex_str = strtok(buf, "\n");
5066 *output_int = strtoul(apIndex_str, NULL, 10);
5067 return RETURN_OK;
5068 }
5069
5070 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5071 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5072 if (apIndex_str) {
5073 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5074 return RETURN_OK;
5075 }
5076 *output_int = -1;
5077 return RETURN_OK;
5078}
5079
5080INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5081{
5082 return wifi_getIndexFromName(inputSsidString, output_int);
5083}
5084
5085// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5086INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5087{
5088 char buf[MAX_BUF_SIZE] = {0};
5089 char cmd[MAX_CMD_SIZE] = {0};
5090 char config_file[MAX_BUF_SIZE] = {0};
5091
5092 if(NULL == output_string)
5093 return RETURN_ERR;
5094
5095 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5096 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5097 if((strcmp(buf,"3")==0))
5098 snprintf(output_string, 32, "WPAand11i");
5099 else if((strcmp(buf,"2")==0))
5100 snprintf(output_string, 32, "11i");
5101 else if((strcmp(buf,"1")==0))
5102 snprintf(output_string, 32, "WPA");
5103 else
5104 snprintf(output_string, 32, "None");
5105
5106 return RETURN_OK;
5107}
5108
5109// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5110INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5111{
5112 char config_file[MAX_BUF_SIZE] = {0};
5113 struct params list;
5114
5115 if (NULL == beaconTypeString)
5116 return RETURN_ERR;
5117 list.name = "wpa";
5118 list.value = "0";
5119
5120 if((strcmp(beaconTypeString,"WPAand11i")==0))
5121 list.value="3";
5122 else if((strcmp(beaconTypeString,"11i")==0))
5123 list.value="2";
5124 else if((strcmp(beaconTypeString,"WPA")==0))
5125 list.value="1";
5126
5127 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5128 wifi_hostapdWrite(config_file, &list, 1);
5129 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5130 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5131 return RETURN_OK;
5132}
5133
5134// sets the beacon interval on the hardware for this AP
5135INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5136{
5137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5138 struct params params={'\0'};
5139 char buf[MAX_BUF_SIZE] = {'\0'};
5140 char config_file[MAX_BUF_SIZE] = {'\0'};
5141
5142 params.name = "beacon_int";
5143 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5144 params.value = buf;
5145
5146 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5147 wifi_hostapdWrite(config_file, &params, 1);
5148
5149 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5151 return RETURN_OK;
5152}
5153
5154INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5155{
5156 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5157 return RETURN_ERR;
5158 return RETURN_OK;
5159}
5160
5161// Get the packet size threshold supported.
5162INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5163{
5164 //save config and apply instantly
5165 if (NULL == output_bool)
5166 return RETURN_ERR;
5167 *output_bool = TRUE;
5168 return RETURN_OK;
5169}
5170
5171// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5172INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5173{
developer72fb0bb2023-01-11 09:46:29 +08005174 char buf[16] = {0};
5175 char config_file[128] = {0};
5176 struct params param = {0};
5177
5178 if (threshold > 65535) {
5179 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5180 return RETURN_ERR;
5181 }
5182
developer23e71282023-01-18 10:25:19 +08005183 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005184 snprintf(buf, sizeof(buf), "%u", threshold);
5185 param.name = "rts_threshold";
5186 param.value = buf;
5187 wifi_hostapdWrite(config_file, &param, 1);
5188 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5189 wifi_reloadAp(apIndex);
5190
5191 return RETURN_OK;
5192}
5193
5194// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5195INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5196{
5197 if (NULL == output_string)
5198 return RETURN_ERR;
5199 snprintf(output_string, 32, "TKIPandAESEncryption");
5200 return RETURN_OK;
5201
5202}
5203
5204// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5205INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5206{
5207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5208 char *param_name = NULL;
5209 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5210
5211 if(NULL == output_string)
5212 return RETURN_ERR;
5213
5214 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5215 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5216
5217 if(strcmp(buf,"0")==0)
5218 {
5219 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5220 snprintf(output_string, 32, "None");
5221 return RETURN_OK;
5222 }
5223 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5224 param_name = "rsn_pairwise";
5225 else if((strcmp(buf,"1")==0))
5226 param_name = "wpa_pairwise";
5227 else
5228 return RETURN_ERR;
5229 memset(output_string,'\0',32);
5230 wifi_hostapdRead(config_file,param_name,output_string,32);
5231 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5232 param_name = "wpa_pairwise";
5233 memset(output_string, '\0', 32);
5234 wifi_hostapdRead(config_file, param_name, output_string, 32);
5235 }
5236 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5237
5238 if(strcmp(output_string,"TKIP") == 0)
5239 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5240 else if(strcmp(output_string,"CCMP") == 0)
5241 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5242 else if(strcmp(output_string,"TKIP CCMP") == 0)
5243 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5244
5245 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5246 return RETURN_OK;
5247}
5248
5249// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5250INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5251{
5252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5253 struct params params={'\0'};
5254 char output_string[32];
5255 char config_file[MAX_BUF_SIZE] = {0};
5256
5257 memset(output_string,'\0',32);
5258 wifi_getApWpaEncryptionMode(apIndex,output_string);
5259
5260 if(strcmp(encMode, "TKIPEncryption") == 0)
5261 params.value = "TKIP";
5262 else if(strcmp(encMode,"AESEncryption") == 0)
5263 params.value = "CCMP";
5264 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5265 params.value = "TKIP CCMP";
5266
5267 if((strcmp(output_string,"WPAand11i")==0))
5268 {
5269 params.name = "wpa_pairwise";
5270 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5271 wifi_hostapdWrite(config_file, &params, 1);
5272 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5273
5274 params.name = "rsn_pairwise";
5275 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5276 wifi_hostapdWrite(config_file, &params, 1);
5277 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5278
5279 return RETURN_OK;
5280 }
5281 else if((strcmp(output_string,"11i")==0))
5282 {
5283 params.name = "rsn_pairwise";
5284 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5285 wifi_hostapdWrite(config_file, &params, 1);
5286 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5287 return RETURN_OK;
5288 }
5289 else if((strcmp(output_string,"WPA")==0))
5290 {
5291 params.name = "wpa_pairwise";
5292 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5293 wifi_hostapdWrite(config_file, &params, 1);
5294 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5295 return RETURN_OK;
5296 }
5297
5298 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5299 return RETURN_OK;
5300}
5301
5302// deletes internal security varable settings for this ap
5303INT wifi_removeApSecVaribles(INT apIndex)
5304{
5305 //TODO: remove the entry in hostapd config file
5306 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5307 //_syscmd(cmd, buf, sizeof(buf));
5308
5309 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5310 //_syscmd(cmd, buf, sizeof(buf));
5311 return RETURN_ERR;
5312}
5313
5314// changes the hardware settings to disable encryption on this ap
5315INT wifi_disableApEncryption(INT apIndex)
5316{
5317 //Apply instantly
5318 return RETURN_ERR;
5319}
5320
5321// set the authorization mode on this ap
5322// mode mapping as: 1: open, 2: shared, 4:auto
5323INT wifi_setApAuthMode(INT apIndex, INT mode)
5324{
5325 struct params params={0};
5326 char config_file[64] = {0};
5327 int ret;
5328
5329 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5330
5331 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5332 params.name = "auth_algs";
5333
5334 if (mode & 1 && mode & 2)
5335 params.value = "3";
5336 else if (mode & 2)
5337 params.value = "2";
5338 else if (mode & 1)
5339 params.value = "1";
5340 else
5341 params.value = "0";
5342
5343 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5344 wifi_hostapdWrite(config_file, &params, 1);
5345 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5346 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5347
5348 return RETURN_OK;
5349}
5350
5351// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5352INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5353{
5354 //save to wifi config, and wait for wifi restart to apply
5355 struct params params={'\0'};
5356 char config_file[MAX_BUF_SIZE] = {0};
5357 int ret;
5358
5359 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5360 if(authMode == NULL)
5361 return RETURN_ERR;
5362
5363 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5364 params.name = "wpa_key_mgmt";
5365
5366 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5367 params.value = "WPA-PSK";
5368 else if(strcmp(authMode,"EAPAuthentication") == 0)
5369 params.value = "WPA-EAP";
5370 else if (strcmp(authMode, "SAEAuthentication") == 0)
5371 params.value = "SAE";
5372 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5373 params.value = "WPA-EAP-SUITE-B-192";
5374 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5375 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08005376 else if (strcmp(authMode, "Enhanced_Open") == 0)
5377 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08005378 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5379 return RETURN_OK; //This is taken careof in beaconType
5380
5381 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5382 ret=wifi_hostapdWrite(config_file,&params,1);
5383 if(!ret)
5384 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5385 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5386
5387 return ret;
5388}
5389
5390// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5391INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5392{
5393 //save to wifi config, and wait for wifi restart to apply
5394 char BeaconType[50] = {0};
5395 char config_file[MAX_BUF_SIZE] = {0};
5396
5397 *authMode = 0;
5398 wifi_getApBeaconType(apIndex,BeaconType);
5399 printf("%s____%s \n",__FUNCTION__,BeaconType);
5400
5401 if(strcmp(BeaconType,"None") == 0)
5402 strcpy(authMode,"None");
5403 else
5404 {
5405 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5406 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5407 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5408 if(strcmp(authMode,"WPA-PSK") == 0)
5409 strcpy(authMode,"SharedAuthentication");
5410 else if(strcmp(authMode,"WPA-EAP") == 0)
5411 strcpy(authMode,"EAPAuthentication");
5412 }
5413
5414 return RETURN_OK;
5415}
5416
5417// Outputs the number of stations associated per AP
5418INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5419{
5420 char interface_name[16] = {0};
5421 char cmd[128]={0};
5422 char buf[128]={0};
5423 BOOL status = false;
5424
5425 if(apIndex > MAX_APS)
5426 return RETURN_ERR;
5427
5428 wifi_getApEnable(apIndex,&status);
5429 if (!status)
5430 return RETURN_OK;
5431
5432 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5433 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5434 return RETURN_ERR;
5435 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
5436 _syscmd(cmd, buf, sizeof(buf));
5437 sscanf(buf,"%lu", output_ulong);
5438
5439 return RETURN_OK;
5440}
5441
5442// manually removes any active wi-fi association with the device specified on this ap
5443INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5444{
5445 char interface_name[16] = {0};
5446 char buf[126]={'\0'};
5447
5448 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5449 return RETURN_ERR;
5450 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
5451 system(buf);
5452
5453 return RETURN_OK;
5454}
5455
5456// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5457INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5458{
5459 if(NULL == output_int)
5460 return RETURN_ERR;
5461 int max_radio_num = 0;
5462 wifi_getMaxRadioNumber(&max_radio_num);
5463 *output_int = apIndex%max_radio_num;
5464 return RETURN_OK;
5465}
5466
5467// sets the radio index for the specific ap
5468INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5469{
5470 //set to config only and wait for wifi reset to apply settings
5471 return RETURN_ERR;
5472}
5473
5474// Get the ACL MAC list per AP
5475INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5476{
5477 char interface_name[16] = {0};
5478 char cmd[MAX_CMD_SIZE]={'\0'};
5479 int ret = 0;
5480
5481 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5482 return RETURN_ERR;
5483 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
5484 ret = _syscmd(cmd,macArray,buf_size);
5485 if (ret != 0)
5486 return RETURN_ERR;
5487
5488 return RETURN_OK;
5489}
5490
5491INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5492{
5493 char interface_name[16] = {0};
5494 char cmd[MAX_CMD_SIZE]={'\0'};
5495 int ret = 0;
5496
5497 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5498 return RETURN_ERR;
5499 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
5500 ret = _syscmd(cmd,macArray,buf_size);
5501 if (ret != 0)
5502 return RETURN_ERR;
5503
5504 return RETURN_OK;
5505}
5506
5507
5508// Get the list of stations associated per AP
5509INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5510{
5511 char interface_name[16] = {0};
5512 char cmd[128];
5513
5514 if(apIndex > 3) //Currently supporting apIndex upto 3
5515 return RETURN_ERR;
5516 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5517 return RETURN_ERR;
5518 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5519 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
5520 _syscmd(cmd, macArray, buf_size);
5521
5522 return RETURN_OK;
5523}
5524
5525// adds the mac address to the filter list
5526//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5527INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5528{
5529 char cmd[MAX_CMD_SIZE]={'\0'};
5530 char buf[MAX_BUF_SIZE]={'\0'};
5531
5532#if 0
5533 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
5534 if(_syscmd(cmd,buf,sizeof(buf)))
5535 return RETURN_ERR;
5536#endif
5537 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5538 if(_syscmd(cmd,buf,sizeof(buf)))
5539 return RETURN_ERR;
5540
5541 return RETURN_OK;
5542}
5543
5544// deletes the mac address from the filter list
5545//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5546INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5547{
5548 char cmd[MAX_CMD_SIZE]={'\0'};
5549 char buf[MAX_BUF_SIZE]={'\0'};
5550
5551#if 0
5552 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
5553 if(_syscmd(cmd,buf,sizeof(buf)))
5554 return RETURN_ERR;
5555
5556#endif
5557 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5558 if(_syscmd(cmd,buf,sizeof(buf)))
5559 return RETURN_ERR;
5560
5561 return RETURN_OK;
5562}
5563
5564// outputs the number of devices in the filter list
5565INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5566{
5567 char cmd[MAX_BUF_SIZE]={0};
5568 char buf[MAX_CMD_SIZE]={0};
5569
5570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5571 if(output_uint == NULL)
5572 return RETURN_ERR;
5573
5574 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5575 _syscmd(cmd, buf, sizeof(buf));
5576
5577 *output_uint = atoi(buf);
5578
5579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5580 return RETURN_OK;
5581}
5582
5583INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5584{
5585 char cmd[128]={'\0'};
5586 char buf[128]={'\0'};
5587
5588 if(strcmp(action,"DENY")==0)
5589 {
5590 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5591 system(buf);
5592 return RETURN_OK;
5593 }
5594
5595 if(strcmp(action,"ALLOW")==0)
5596 {
5597 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5598 system(buf);
5599 return RETURN_OK;
5600 }
5601
5602 return RETURN_ERR;
5603
5604}
5605
5606// enable kick for devices on acl black list
5607INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5608{
5609 char aclArray[512] = {0}, *acl = NULL;
5610 char assocArray[512] = {0}, *asso = NULL;
5611
5612 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
5613 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5614
5615 // if there are no devices connected there is nothing to do
5616 if (strlen(assocArray) < 17)
5617 return RETURN_OK;
5618
5619 if (enable == TRUE)
5620 {
5621 //kick off the MAC which is in ACL array (deny list)
5622 acl = strtok(aclArray, "\r\n");
5623 while (acl != NULL) {
5624 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5625 wifi_kickApAssociatedDevice(apIndex, acl);
5626
5627 acl = strtok(NULL, "\r\n");
5628 }
5629 wifi_setApMacAddressControlMode(apIndex, 2);
5630 }
5631 else
5632 {
5633 wifi_setApMacAddressControlMode(apIndex, 0);
5634 }
5635
5636#if 0
5637 //TODO: need to revisit below implementation
5638 char aclArray[512]={0}, *acl=NULL;
5639 char assocArray[512]={0}, *asso=NULL;
5640 char buf[256]={'\0'};
5641 char action[10]={'\0'};
5642 FILE *fr=NULL;
5643 char interface[10]={'\0'};
5644 char config_file[MAX_BUF_SIZE] = {0};
5645
5646 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5647 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5648 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5649 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5650
5651 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5652 system(buf);
5653 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5654 system(buf);
5655 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5656 system(buf);
5657 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5658 system(buf);
5659 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5660 system(buf);
5661
5662 if ( enable == TRUE )
5663 {
5664 int device_count=0;
5665 strcpy(action,"DENY");
5666 //kick off the MAC which is in ACL array (deny list)
5667 acl = strtok (aclArray,",");
5668 while (acl != NULL) {
5669 if(strlen(acl)>=17)
5670 {
5671 apply_rules(apIndex, acl,action,interface);
5672 device_count++;
5673 //Register mac to be blocked ,in syscfg.db persistent storage
5674 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5675 system(buf);
5676 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5677 system(buf);
5678 system("syscfg commit");
5679
5680 wifi_kickApAssociatedDevice(apIndex, acl);
5681 }
5682 acl = strtok (NULL, ",");
5683 }
5684 }
5685 else
5686 {
5687 int device_count=0;
5688 char cmdmac[20]={'\0'};
5689 strcpy(action,"ALLOW");
5690 //kick off the MAC which is not in ACL array (allow list)
5691 acl = strtok (aclArray,",");
5692 while (acl != NULL) {
5693 if(strlen(acl)>=17)
5694 {
5695 apply_rules(apIndex, acl,action,interface);
5696 device_count++;
5697 //Register mac to be Allowed ,in syscfg.db persistent storage
5698 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5699 system(buf);
5700 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5701 system(buf);
5702 sprintf(cmdmac,"%s",acl);
5703 }
5704 acl = strtok (NULL, ",");
5705 }
5706 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5707 system(buf);
5708
5709 //Disconnect the mac which is not in ACL
5710 asso = strtok (assocArray,",");
5711 while (asso != NULL) {
5712 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5713 wifi_kickApAssociatedDevice(apIndex, asso);
5714 asso = strtok (NULL, ",");
5715 }
5716 }
5717#endif
5718 return RETURN_OK;
5719}
5720
5721INT wifi_setPreferPrivateConnection(BOOL enable)
5722{
5723 return RETURN_OK;
5724}
5725
5726// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5727INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5728{
5729 char interface_name[16] = {0};
5730 int items = 1;
5731 struct params list[2];
5732 char buf[MAX_BUF_SIZE] = {0};
5733 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
5734 char deny_file[MAX_BUF_SIZE] = {0};
5735
5736 list[0].name = "macaddr_acl";
5737
5738 if (filterMode == 0) {
5739 sprintf(buf, "%d", 0);
5740 list[0].value = buf;
5741
5742 char cmd[128], rtn[128];
5743 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5744 return RETURN_ERR;
5745 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
5746 _syscmd(cmd, rtn, sizeof(rtn));
5747 memset(cmd,0,sizeof(cmd));
5748 // Delete deny_mac_file in hostapd configuration
5749 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5750 _syscmd(cmd, rtn, sizeof(rtn));
5751 }
5752 else if (filterMode == 1) {
5753 sprintf(buf, "%d", filterMode);
5754 list[0].value = buf;
5755 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5756 list[1].name = "accept_mac_file";
5757 list[1].value = acl_file;
5758 items = 2;
5759 } else if (filterMode == 2) {
5760 //TODO: deny_mac_file
5761 sprintf(buf, "%d", 0);
5762 list[0].value = buf;
5763 list[1].name = "deny_mac_file";
5764 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5765 list[1].value = deny_file;
5766 items = 2;
5767 } else {
5768 return RETURN_ERR;
5769 }
5770
5771 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5772 wifi_hostapdWrite(config_file, list, items);
5773
5774 return RETURN_OK;
5775
5776#if 0
5777 if(apIndex==0 || apIndex==1)
5778 {
5779 //set the filtermode
5780 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5781 system(buf);
5782 system("syscfg commit");
5783
5784 if(filterMode==0)
5785 {
5786 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5787 system(buf);
5788 return RETURN_OK;
5789 }
5790 }
5791 return RETURN_OK;
5792#endif
5793}
5794
5795// 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.
5796INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5797{
5798 return RETURN_ERR;
5799}
5800
5801// gets the vlan ID for this ap from an internal enviornment variable
5802INT wifi_getApVlanID(INT apIndex, INT *output_int)
5803{
5804 if(apIndex==0)
5805 {
5806 *output_int=100;
5807 return RETURN_OK;
5808 }
5809
5810 return RETURN_ERR;
5811}
5812
5813// sets the vlan ID for this ap to an internal enviornment variable
5814INT wifi_setApVlanID(INT apIndex, INT vlanId)
5815{
5816 //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)
5817 return RETURN_ERR;
5818}
5819
5820// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5821INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5822{
5823 snprintf(bridgeName, 32, "brlan0");
5824 snprintf(IP, 32, "10.0.0.1");
5825 snprintf(subnet, 32, "255.255.255.0");
5826
5827 return RETURN_OK;
5828}
5829
5830//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5831INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5832{
5833 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5834 return RETURN_ERR;
5835}
5836
5837// reset the vlan configuration for this ap
5838INT wifi_resetApVlanCfg(INT apIndex)
5839{
5840 char original_config_file[64] = {0};
5841 char current_config_file[64] = {0};
5842 char buf[64] = {0};
5843 char cmd[64] = {0};
5844 char vlan_file[64] = {0};
5845 char vlan_tagged_interface[16] = {0};
5846 char vlan_bridge[16] = {0};
5847 char vlan_naming[16] = {0};
5848 struct params list[4] = {0};
5849 wifi_band band;
5850
5851 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5852
5853 band = wifi_index_to_band(apIndex);
5854 if (band == band_2_4)
5855 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5856 else if (band == band_5)
5857 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5858 else if (band == band_6)
5859 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5860
5861 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5862
5863 if (strlen(vlan_file) == 0)
5864 strcpy(vlan_file, VLAN_FILE);
5865
5866 // The file should exist or this vap would not work.
5867 if (access(vlan_file, F_OK) != 0) {
5868 sprintf(cmd, "touch %s", vlan_file);
5869 _syscmd(cmd, buf, sizeof(buf));
5870 }
5871 list[0].name = "vlan_file";
5872 list[0].value = vlan_file;
5873
5874 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5875 list[1].name = "vlan_tagged_interface";
5876 list[1].value = vlan_tagged_interface;
5877
5878 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5879 list[2].name = "vlan_bridge";
5880 list[2].value = vlan_bridge;
5881
5882 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5883 list[3].name = "vlan_naming";
5884 list[3].value = vlan_naming;
5885
5886 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5887 wifi_hostapdWrite(current_config_file, list, 4);
5888 //Reapply vlan settings
5889 // wifi_pushBridgeInfo(apIndex);
5890
5891 // restart this ap
5892 wifi_setApEnable(apIndex, FALSE);
5893 wifi_setApEnable(apIndex, TRUE);
5894
5895 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5896
5897 return RETURN_OK;
5898}
5899
5900// 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.
5901INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5902{
5903 return RETURN_ERR;
5904}
5905
5906// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5907INT wifi_startHostApd()
5908{
5909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5910 system("systemctl start hostapd.service");
5911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5912 return RETURN_OK;
5913 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5914}
5915
5916// stops hostapd
5917INT wifi_stopHostApd()
5918{
5919 char cmd[128] = {0};
5920 char buf[128] = {0};
5921
5922 sprintf(cmd,"systemctl stop hostapd");
5923 _syscmd(cmd, buf, sizeof(buf));
5924
5925 return RETURN_OK;
5926}
5927
5928// restart hostapd dummy function
5929INT wifi_restartHostApd()
5930{
5931 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5932 system("systemctl restart hostapd-global");
5933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5934
5935 return RETURN_OK;
5936}
5937
5938static int align_hostapd_config(int index)
5939{
5940 ULONG lval;
5941 wifi_getRadioChannel(index%2, &lval);
5942 wifi_setRadioChannel(index%2, lval);
5943 return RETURN_OK;
5944}
5945
5946// sets the AP enable status variable for the specified ap.
5947INT wifi_setApEnable(INT apIndex, BOOL enable)
5948{
5949 char interface_name[16] = {0};
5950 char config_file[MAX_BUF_SIZE] = {0};
5951 char cmd[MAX_CMD_SIZE] = {0};
5952 char buf[MAX_BUF_SIZE] = {0};
5953 BOOL status;
5954 int max_radio_num = 0;
5955 int phyId = 0;
5956
5957 wifi_getApEnable(apIndex,&status);
5958
5959 wifi_getMaxRadioNumber(&max_radio_num);
5960 if (enable == status)
5961 return RETURN_OK;
5962
5963 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5964 return RETURN_ERR;
5965
5966 if (enable == TRUE) {
5967 int radioIndex = apIndex % max_radio_num;
5968 phyId = radio_index_to_phy(radioIndex);
5969 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5970 //Hostapd will bring up this interface
5971 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
5972 _syscmd(cmd, buf, sizeof(buf));
developer23e71282023-01-18 10:25:19 +08005973 sprintf(cmd, "iw %s del", interface_name);
5974 _syscmd(cmd, buf, sizeof(buf));
5975 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
5976 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08005977 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
5978 _syscmd(cmd, buf, sizeof(buf));
5979 }
5980 else {
5981 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
5982 _syscmd(cmd, buf, sizeof(buf));
5983 sprintf(cmd, "ip link set %s down", interface_name);
5984 _syscmd(cmd, buf, sizeof(buf));
5985 }
5986 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
5987 interface_name, interface_name, enable, VAP_STATUS_FILE);
5988 _syscmd(cmd, buf, sizeof(buf));
5989 //Wait for wifi up/down to apply
5990 return RETURN_OK;
5991}
5992
5993// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5994INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5995{
5996 char interface_name[16] = {0};
5997 char cmd[MAX_CMD_SIZE] = {'\0'};
5998 char buf[MAX_BUF_SIZE] = {'\0'};
5999
6000 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6001 return RETURN_ERR;
6002
6003 *output_bool = 0;
6004
6005 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6006 {
6007 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6008 *output_bool = FALSE;
6009 return RETURN_OK;
6010 }
6011 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6012 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6013 }
6014
6015 return RETURN_OK;
6016}
6017
6018// Outputs the AP "Enabled" "Disabled" status from driver
6019INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6020{
6021 char cmd[128] = {0};
6022 char buf[128] = {0};
6023 BOOL output_bool;
6024
6025 if ( NULL == output_string)
6026 return RETURN_ERR;
6027 wifi_getApEnable(apIndex,&output_bool);
6028
6029 if(output_bool == 1)
6030 snprintf(output_string, 32, "Up");
6031 else
6032 snprintf(output_string, 32, "Disable");
6033
6034 return RETURN_OK;
6035}
6036
6037//Indicates whether or not beacons include the SSID name.
6038// outputs a 1 if SSID on the AP is enabled, else outputs 0
6039INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6040{
6041 //get the running status
6042 char config_file[MAX_BUF_SIZE] = {0};
6043 char buf[16] = {0};
6044
6045 if (!output)
6046 return RETURN_ERR;
6047
6048 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6049 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6050 // default is enable
6051 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6052 *output = TRUE;
6053
6054 return RETURN_OK;
6055}
6056
6057// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6058INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6059{
6060 //store the config, apply instantly
6061 char config_file[MAX_BUF_SIZE] = {0};
6062 struct params list;
6063
6064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6065 list.name = "ignore_broadcast_ssid";
6066 list.value = enable?"0":"1";
6067
6068 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6069 wifi_hostapdWrite(config_file, &list, 1);
6070 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6071 //TODO: call hostapd_cli for dynamic_config_control
6072 wifi_reloadAp(apIndex);
6073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6074
6075 return RETURN_OK;
6076}
6077
6078//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6079INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6080{
6081 //get the running status
6082 if(!output_uint)
6083 return RETURN_ERR;
6084 *output_uint=16;
6085 return RETURN_OK;
6086}
6087
6088INT wifi_setApRetryLimit(INT apIndex, UINT number)
6089{
6090 //apply instantly
6091 return RETURN_ERR;
6092}
6093
6094//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6095INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6096{
6097 if(!output)
6098 return RETURN_ERR;
6099 *output=TRUE;
6100 return RETURN_OK;
6101}
6102
6103//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6104INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6105{
6106 //get the running status from driver
6107 char cmd[128] = {0};
6108 char buf[128] = {0};
6109 int max_radio_num = 0, radioIndex = 0;
6110 int phyId = 0;
6111
6112 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6113
6114 wifi_getMaxRadioNumber(&max_radio_num);
6115 radioIndex = apIndex % max_radio_num;
6116 phyId = radio_index_to_phy(radioIndex);
6117 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6118 _syscmd(cmd,buf, sizeof(buf));
6119
6120 if (strlen(buf) > 0)
6121 *output = true;
6122
6123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6124
6125 return RETURN_OK;
6126}
6127
6128//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6129INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6130{
6131 //get the running status from driver
6132 if(!output)
6133 return RETURN_ERR;
6134
6135 char config_file[MAX_BUF_SIZE] = {0};
6136 char buf[16] = {0};
6137
6138 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6139 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6140 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6141 *output = TRUE;
6142 else
6143 *output = FALSE;
6144
6145 return RETURN_OK;
6146}
6147
6148// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6149INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6150{
6151 //Save config and apply instantly.
6152 char config_file[MAX_BUF_SIZE] = {0};
6153 struct params list;
6154
6155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6156 list.name = "wmm_enabled";
6157 list.value = enable?"1":"0";
6158
6159 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6160 wifi_hostapdWrite(config_file, &list, 1);
6161 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6162 wifi_reloadAp(apIndex);
6163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6164
6165 return RETURN_OK;
6166}
6167
6168//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.
6169INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6170{
6171 //get the running status from driver
6172 if(!output)
6173 return RETURN_ERR;
6174
6175 char config_file[128] = {0};
6176 char buf[16] = {0};
6177
6178 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6179 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6180 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6181 *output = TRUE;
6182 else
6183 *output = FALSE;
6184
6185 return RETURN_OK;
6186}
6187
6188// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6189INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6190{
6191 //save config and apply instantly.
6192 char config_file[MAX_BUF_SIZE] = {0};
6193 struct params list;
6194
6195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6196 list.name = "uapsd_advertisement_enabled";
6197 list.value = enable?"1":"0";
6198
6199 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6200 wifi_hostapdWrite(config_file, &list, 1);
6201 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6202 wifi_reloadAp(apIndex);
6203 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6204
6205 return RETURN_OK;
6206}
6207
6208// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6209INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6210{
6211 char interface_name[16] = {0};
6212 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6213 char cmd[128] = {0};
6214 char buf[128] = {0};
6215 char ack_filepath[128] = {0};
6216 uint16_t bitmap = 0;
6217 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6218 FILE *f = NULL;
6219
6220 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6221
6222 // Get current setting
6223 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6224 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6225 _syscmd(cmd, buf, sizeof(buf));
6226 if (strlen(buf) > 0)
6227 bitmap = strtoul(buf, NULL, 10);
6228
6229 bitmap = strtoul(buf, NULL, 10);
6230
6231 if (ackPolicy == TRUE) { // True, unset this class
6232 bitmap &= ~class_map[class];
6233 } else { // False, set this class
6234 bitmap |= class_map[class];
6235 }
6236
6237 f = fopen(ack_filepath, "w");
6238 if (f == NULL) {
6239 fprintf(stderr, "%s: fopen failed\n", __func__);
6240 return RETURN_ERR;
6241 }
6242 fprintf(f, "%hu", bitmap);
6243 fclose(f);
6244
6245 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6246 return RETURN_ERR;
6247 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6248 _syscmd(cmd, buf, sizeof(buf));
6249
6250 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6251 return RETURN_OK;
6252}
6253
6254//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.
6255INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6256{
6257 //get the running status from driver
6258 if(!output_uint)
6259 return RETURN_ERR;
6260
6261 char output[16]={'\0'};
6262 char config_file[MAX_BUF_SIZE] = {0};
6263
6264 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6265 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6266 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6267 else {
6268 int device_num = atoi(output);
6269 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6270 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6271 return RETURN_ERR;
6272 }
6273 else {
6274 *output_uint = device_num;
6275 }
6276 }
6277
6278 return RETURN_OK;
6279}
6280
6281INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6282{
6283 //store to wifi config, apply instantly
6284 char str[MAX_BUF_SIZE]={'\0'};
6285 char cmd[MAX_CMD_SIZE]={'\0'};
6286 struct params params;
6287 char config_file[MAX_BUF_SIZE] = {0};
6288
6289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6290 if (number > MAX_ASSOCIATED_STA_NUM) {
6291 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6292 return RETURN_ERR;
6293 }
6294 sprintf(str, "%d", number);
6295 params.name = "max_num_sta";
6296 params.value = str;
6297
6298 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6299 int ret = wifi_hostapdWrite(config_file, &params, 1);
6300 if (ret) {
6301 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6302 ,__func__, ret);
6303 }
6304
6305 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6306 if (ret) {
6307 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6308 ,__func__, ret);
6309 }
6310 wifi_reloadAp(apIndex);
6311 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6312
6313 return RETURN_OK;
6314}
6315
6316//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.
6317INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6318{
6319 //get the current threshold
6320 if(!output_uint)
6321 return RETURN_ERR;
6322 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6323 if (*output_uint == 0)
6324 *output_uint = 50;
6325 return RETURN_OK;
6326}
6327
6328INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6329{
6330 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6331 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6332 return RETURN_OK;
6333 return RETURN_ERR;
6334}
6335
6336//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.
6337INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6338{
6339 if(!output_uint)
6340 return RETURN_ERR;
6341 *output_uint = 3;
6342 return RETURN_OK;
6343}
6344
6345//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6346INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6347{
6348 if(!output_uint)
6349 return RETURN_ERR;
6350 *output_uint = 3;
6351 return RETURN_OK;
6352}
6353
6354//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.
6355INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6356{
6357 if(!output_in_seconds)
6358 return RETURN_ERR;
6359 *output_in_seconds = 0;
6360 return RETURN_OK;
6361}
6362
6363//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
6364INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6365{
6366 if(!output || apIndex>=MAX_APS)
6367 return RETURN_ERR;
6368 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6369 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6370 return RETURN_OK;
6371}
6372
6373//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6374INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6375{
6376 char config_file[128] = {0};
6377 char wpa[16] = {0};
6378 char key_mgmt[64] = {0};
6379 char buf[16] = {0};
6380 if (!output)
6381 return RETURN_ERR;
6382
6383 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6384 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6385
6386 strcpy(output, "None");//Copying "None" to output string for default case
6387 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6388 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6389 if (!strcmp(wpa, "1"))
6390 snprintf(output, 32, "WPA-Personal");
6391 else if (!strcmp(wpa, "2"))
6392 snprintf(output, 32, "WPA2-Personal");
6393 else if (!strcmp(wpa, "3"))
6394 snprintf(output, 32, "WPA-WPA2-Personal");
6395
6396 } else if (strstr(key_mgmt, "WPA-EAP")) {
6397 if (!strcmp(wpa, "1"))
6398 snprintf(output, 32, "WPA-Enterprise");
6399 else if (!strcmp(wpa, "2"))
6400 snprintf(output, 32, "WPA2-Enterprise");
6401 else if (!strcmp(wpa, "3"))
6402 snprintf(output, 32, "WPA-WPA2-Enterprise");
6403 } else if (strstr(key_mgmt, "SAE")) {
6404 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6405 snprintf(output, 32, "WPA3-Personal");
6406 else
6407 snprintf(output, 32, "WPA3-Personal-Transition");
6408 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6409 snprintf(output, 32, "WPA3-Enterprise");
6410 }
6411
6412 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6413 return RETURN_OK;
6414#if 0
6415 //TODO: need to revisit below implementation
6416 char securityType[32], authMode[32];
6417 int enterpriseMode=0;
6418
6419 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6420 if(!output)
6421 return RETURN_ERR;
6422
6423 wifi_getApBeaconType(apIndex, securityType);
6424 strcpy(output,"None");//By default, copying "None" to output string
6425 if (strncmp(securityType,"None", strlen("None")) == 0)
6426 return RETURN_OK;
6427
6428 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6429 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6430
6431 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6432 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6433 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6434 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6435 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6436 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6437 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6438
6439 return RETURN_OK;
6440#endif
6441}
6442
6443INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6444{
6445 char securityType[32];
6446 char authMode[32];
6447
6448 //store settings and wait for wifi up to apply
6449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6450 if(!encMode)
6451 return RETURN_ERR;
6452
6453 if (strcmp(encMode, "None")==0)
6454 {
6455 strcpy(securityType,"None");
6456 strcpy(authMode,"None");
6457 }
6458 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6459 {
6460 strcpy(securityType,"WPAand11i");
6461 strcpy(authMode,"PSKAuthentication");
6462 }
6463 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6464 {
6465 strcpy(securityType,"WPAand11i");
6466 strcpy(authMode,"EAPAuthentication");
6467 }
6468 else if (strcmp(encMode, "WPA-Personal")==0)
6469 {
6470 strcpy(securityType,"WPA");
6471 strcpy(authMode,"PSKAuthentication");
6472 }
6473 else if (strcmp(encMode, "WPA-Enterprise")==0)
6474 {
6475 strcpy(securityType,"WPA");
6476 strcpy(authMode,"EAPAuthentication");
6477 }
6478 else if (strcmp(encMode, "WPA2-Personal")==0)
6479 {
6480 strcpy(securityType,"11i");
6481 strcpy(authMode,"PSKAuthentication");
6482 }
6483 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6484 {
6485 strcpy(securityType,"11i");
6486 strcpy(authMode,"EAPAuthentication");
6487 }
6488 else if (strcmp(encMode, "WPA3-Personal") == 0)
6489 {
6490 strcpy(securityType,"11i");
6491 strcpy(authMode,"SAEAuthentication");
6492 }
6493 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6494 {
6495 strcpy(securityType, "11i");
6496 strcpy(authMode, "PSK-SAEAuthentication");
6497 }
6498 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6499 {
6500 strcpy(securityType,"11i");
6501 strcpy(authMode,"EAP_192-bit_Authentication");
6502 }
developer3086e2f2023-01-17 09:40:01 +08006503 else if (strcmp(encMode, "OWE") == 0)
6504 {
6505 strcpy(securityType,"11i");
6506 strcpy(authMode,"Enhanced_Open");
6507 }
developer72fb0bb2023-01-11 09:46:29 +08006508 else
6509 {
6510 strcpy(securityType,"None");
6511 strcpy(authMode,"None");
6512 }
6513 wifi_setApBeaconType(apIndex, securityType);
6514 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6516
6517 return RETURN_OK;
6518}
6519
6520
6521//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6522// output_string must be pre-allocated as 64 character string by caller
6523// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6524INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6525{
6526 char buf[16] = {0};
6527 char config_file[MAX_BUF_SIZE] = {0};
6528
6529 if(output_string==NULL)
6530 return RETURN_ERR;
6531
6532 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6533 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6534
6535 if(strcmp(buf,"0")==0)
6536 {
6537 printf("wpa_mode is %s ......... \n",buf);
6538 return RETURN_ERR;
6539 }
6540
6541 wifi_dbg_printf("\nFunc=%s\n",__func__);
6542 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6543 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6544 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6545
6546 return RETURN_OK;
6547}
6548
6549// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6550// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6551INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6552{
6553 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6554 struct params params={'\0'};
6555 int ret;
6556 char config_file[MAX_BUF_SIZE] = {0};
6557
6558 if(NULL == preSharedKey)
6559 return RETURN_ERR;
6560
6561 params.name = "wpa_passphrase";
6562
6563 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6564 {
6565 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6566 return RETURN_ERR;
6567 }
6568 params.value = preSharedKey;
6569 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6570 ret = wifi_hostapdWrite(config_file, &params, 1);
6571 if(!ret)
6572 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6573 return ret;
6574 //TODO: call hostapd_cli for dynamic_config_control
6575}
6576
6577//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6578// outputs the passphrase, maximum 63 characters
6579INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6580{
6581 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6582
6583 wifi_dbg_printf("\nFunc=%s\n",__func__);
6584 if (NULL == output_string)
6585 return RETURN_ERR;
6586
6587 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6588 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6589 if(strcmp(buf,"0")==0)
6590 {
6591 printf("wpa_mode is %s ......... \n",buf);
6592 return RETURN_ERR;
6593 }
6594
6595 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6596 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6597
6598 return RETURN_OK;
6599}
6600
6601// sets the passphrase enviornment variable, max 63 characters
6602INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6603{
6604 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6605 struct params params={'\0'};
6606 char config_file[MAX_BUF_SIZE] = {0};
6607 int ret;
6608
6609 if(NULL == passPhrase)
6610 return RETURN_ERR;
6611
6612 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6613 {
6614 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6615 return RETURN_ERR;
6616 }
6617 params.name = "wpa_passphrase";
6618 params.value = passPhrase;
6619 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6620 ret=wifi_hostapdWrite(config_file,&params,1);
6621 if(!ret)
6622 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6623
6624 return ret;
6625}
6626
6627//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.
6628INT wifi_setApSecurityReset(INT apIndex)
6629{
6630 char original_config_file[64] = {0};
6631 char current_config_file[64] = {0};
6632 char buf[64] = {0};
6633 char cmd[64] = {0};
6634 char wpa[4] = {0};
6635 char wpa_psk[64] = {0};
6636 char wpa_passphrase[64] = {0};
6637 char wpa_psk_file[128] = {0};
6638 char wpa_key_mgmt[64] = {0};
6639 char wpa_pairwise[32] = {0};
6640 wifi_band band;
6641 struct params list[6];
6642
6643 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6644
6645 band = wifi_index_to_band(apIndex);
6646 if (band == band_2_4)
6647 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6648 else if (band == band_5)
6649 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6650 else if (band == band_6)
6651 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6652 else
6653 return RETURN_ERR;
6654
6655 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6656 list[0].name = "wpa";
6657 list[0].value = wpa;
6658
6659 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6660 list[1].name = "wpa_psk";
6661 list[1].value = wpa_psk;
6662
6663 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6664 list[2].name = "wpa_passphrase";
6665 list[2].value = wpa_passphrase;
6666
6667 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6668
6669 if (strlen(wpa_psk_file) == 0)
6670 strcpy(wpa_psk_file, PSK_FILE);
6671
6672 if (access(wpa_psk_file, F_OK) != 0) {
6673 sprintf(cmd, "touch %s", wpa_psk_file);
6674 _syscmd(cmd, buf, sizeof(buf));
6675 }
6676 list[3].name = "wpa_psk_file";
6677 list[3].value = wpa_psk_file;
6678
6679 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6680 list[4].name = "wpa_key_mgmt";
6681 list[4].value = wpa_key_mgmt;
6682
6683 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6684 list[5].name = "wpa_pairwise";
6685 list[5].value = wpa_pairwise;
6686
6687 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6688 wifi_hostapdWrite(current_config_file, list, 6);
6689
6690 wifi_setApEnable(apIndex, FALSE);
6691 wifi_setApEnable(apIndex, TRUE);
6692
6693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6694 return RETURN_OK;
6695}
6696
6697//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).
6698INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6699{
6700 char config_file[64] = {0};
6701 char buf[64] = {0};
6702 char cmd[256] = {0};
6703
6704 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6705
6706 if(!IP_output || !Port_output || !RadiusSecret_output)
6707 return RETURN_ERR;
6708
6709 // Read the first matched config
6710 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6711 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6712 _syscmd(cmd, buf, sizeof(buf));
6713 strncpy(IP_output, buf, 64);
6714
6715 memset(buf, 0, sizeof(buf));
6716 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6717 _syscmd(cmd, buf, sizeof(buf));
6718 *Port_output = atoi(buf);
6719
6720 memset(buf, 0, sizeof(buf));
6721 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6722 _syscmd(cmd, buf, sizeof(buf));
6723 strncpy(RadiusSecret_output, buf, 64);
6724
6725 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6726 return RETURN_OK;
6727}
6728
6729INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6730{
6731 char config_file[64] = {0};
6732 char port_str[8] = {0};
6733 char cmd[256] = {0};
6734 char buf[128] = {0};
6735
6736 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6737
6738 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6739
6740 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6741 _syscmd(cmd, buf, sizeof(buf));
6742 memset(cmd, 0, sizeof(cmd));
6743
6744 snprintf(port_str, sizeof(port_str), "%d", port);
6745 if (strlen(buf) == 0)
6746 // Append
6747 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6748 "auth_server_addr=%s\\n"
6749 "auth_server_port=%s\\n"
6750 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6751 else {
6752 // Delete the three lines setting after the "# radius 1" comment
6753 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6754 _syscmd(cmd, buf, sizeof(buf));
6755 memset(cmd, 0, sizeof(cmd));
6756 // Use "# radius 1" comment to find the location to insert the radius setting
6757 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6758 "# radius 1\\n"
6759 "auth_server_addr=%s\\n"
6760 "auth_server_port=%s\\n"
6761 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6762 }
6763 if(_syscmd(cmd, buf, sizeof(buf))) {
6764 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6765 return RETURN_ERR;
6766 }
6767
6768 wifi_reloadAp(apIndex);
6769 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6770 return RETURN_OK;
6771}
6772
6773INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6774{
6775 char config_file[64] = {0};
6776 char buf[64] = {0};
6777 char cmd[256] = {0};
6778
6779 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6780
6781 if(!IP_output || !Port_output || !RadiusSecret_output)
6782 return RETURN_ERR;
6783
6784 // Read the second matched config
6785 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6786 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6787 _syscmd(cmd, buf, sizeof(buf));
6788 strncpy(IP_output, buf, 64);
6789
6790 memset(buf, 0, sizeof(buf));
6791 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6792 _syscmd(cmd, buf, sizeof(buf));
6793 *Port_output = atoi(buf);
6794
6795 memset(buf, 0, sizeof(buf));
6796 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6797 _syscmd(cmd, buf, sizeof(buf));
6798 strncpy(RadiusSecret_output, buf, 64);
6799
6800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6801 return RETURN_OK;
6802}
6803
6804INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6805{
6806 char config_file[64] = {0};
6807 char port_str[8] = {0};
6808 char cmd[256] = {0};
6809 char buf[128] = {0};
6810
6811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6812
6813 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6814
6815 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6816 _syscmd(cmd, buf, sizeof(buf));
6817 memset(cmd, 0, sizeof(cmd));
6818
6819 snprintf(port_str, sizeof(port_str), "%d", port);
6820 if (strlen(buf) == 0)
6821 // Append
6822 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6823 "auth_server_addr=%s\\n"
6824 "auth_server_port=%s\\n"
6825 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6826 else {
6827 // Delete the three lines setting after the "# radius 2" comment
6828 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6829 _syscmd(cmd, buf, sizeof(buf));
6830 memset(cmd, 0, sizeof(cmd));
6831 // Use "# radius 2" comment to find the location to insert the radius setting
6832 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6833 "# radius 2\\n"
6834 "auth_server_addr=%s\\n"
6835 "auth_server_port=%s\\n"
6836 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6837 }
6838 if(_syscmd(cmd, buf, sizeof(buf))) {
6839 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6840 return RETURN_ERR;
6841 }
6842
6843 wifi_reloadAp(apIndex);
6844 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6845 return RETURN_OK;
6846}
6847
6848//RadiusSettings
6849INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6850{
6851 if(!output)
6852 return RETURN_ERR;
6853
6854 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6855 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6856 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6857 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6858 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6859 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.
6860 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6861 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6862 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6863 //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.
6864
6865 return RETURN_OK;
6866}
6867
6868INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6869{
6870 //store the paramters, and apply instantly
6871 return RETURN_ERR;
6872}
6873
6874//Device.WiFi.AccessPoint.{i}.WPS.Enable
6875//Enables or disables WPS functionality for this access point.
6876// outputs the WPS enable state of this ap in output_bool
6877INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6878{
6879 char interface_name[16] = {0};
6880 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6881 if(!output_bool)
6882 return RETURN_ERR;
6883 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6884 return RETURN_ERR;
6885 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
6886 _syscmd(cmd, buf, sizeof(buf));
6887 if(strstr(buf, "configured"))
6888 *output_bool=TRUE;
6889 else
6890 *output_bool=FALSE;
6891
6892 return RETURN_OK;
6893}
6894
6895//Device.WiFi.AccessPoint.{i}.WPS.Enable
6896// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6897INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6898{
6899 char config_file[MAX_BUF_SIZE] = {0};
6900 struct params params;
6901
6902 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6903 //store the paramters, and wait for wifi up to apply
6904 params.name = "wps_state";
6905 params.value = enable ? "2":"0";
6906
6907 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6908 wifi_hostapdWrite(config_file, &params, 1);
6909 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6910 wifi_reloadAp(apIndex);
6911
6912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6913 return RETURN_OK;
6914}
6915
6916//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
6917INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6918{
6919 if(!output)
6920 return RETURN_ERR;
6921 snprintf(output, 128, "PushButton,PIN");
6922 return RETURN_OK;
6923}
6924
6925//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6926//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.
6927// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6928INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6929{
6930 if(!output)
6931 return RETURN_ERR;
6932 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6933
6934 return RETURN_OK;
6935}
6936
6937//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6938// 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
6939INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6940{
6941 //apply instantly. No setting need to be stored.
6942 char methods[MAX_BUF_SIZE], *token, *next_token;
6943 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6944 struct params params;
6945
6946 if(!methodString)
6947 return RETURN_ERR;
6948 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6949 //store the paramters, and wait for wifi up to apply
6950
6951 snprintf(methods, sizeof(methods), "%s", methodString);
6952 for(token=methods; *token; token=next_token)
6953 {
6954 strtok_r(token, ",", &next_token);
6955 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6956 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6957 else if(*token=='E')
6958 {
6959 if(!strcmp(methods, "Ethernet"))
6960 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6961 else if(!strcmp(methods, "ExternalNFCToken"))
6962 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6963 else
6964 printf("%s: Unknown WpsConfigMethod\n", __func__);
6965 }
6966 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6967 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6968 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6969 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6970 else if(*token=='P' )
6971 {
6972 if(!strcmp(token, "PushButton"))
6973 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6974 else if(!strcmp(token, "PIN"))
6975 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6976 else
6977 printf("%s: Unknown WpsConfigMethod\n", __func__);
6978 }
6979 else
6980 printf("%s: Unknown WpsConfigMethod\n", __func__);
6981 }
6982 params.name = "config_methods";
6983 params.value = config_methods;
6984 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6985 wifi_hostapdWrite(config_file, &params, 1);
6986 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6987 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6988
6989 return RETURN_OK;
6990}
6991
6992// outputs the pin value, ulong_pin must be allocated by the caller
6993INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6994{
6995 char buf[MAX_BUF_SIZE] = {0};
6996 char cmd[MAX_CMD_SIZE] = {0};
6997
6998 if(!output_ulong)
6999 return RETURN_ERR;
7000 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7001 _syscmd(cmd, buf, sizeof(buf));
7002 if(strlen(buf) > 0)
7003 *output_ulong=strtoul(buf, NULL, 10);
7004
7005 return RETURN_OK;
7006}
7007
7008// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7009INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7010{
7011 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7012 char ap_pin[16] = {0};
7013 char buf[MAX_BUF_SIZE] = {0};
7014 char config_file[MAX_BUF_SIZE] = {0};
7015 ULONG prev_pin = 0;
7016 struct params params;
7017
7018 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7019 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7020 params.name = "ap_pin";
7021 params.value = ap_pin;
7022 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7023 wifi_hostapdWrite(config_file, &params, 1);
7024 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7025 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7026
7027 return RETURN_OK;
7028}
7029
7030// Output string is either Not configured or Configured, max 32 characters
7031INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7032{
7033 char interface_name[16] = {0};
7034 char cmd[MAX_CMD_SIZE];
7035 char buf[MAX_BUF_SIZE]={0};
7036
7037 if(!output_string)
7038 return RETURN_ERR;
7039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7040 snprintf(output_string, 32, "Not configured");
7041 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7042 return RETURN_ERR;
7043 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7044 _syscmd(cmd, buf, sizeof(buf));
7045
7046 if(!strncmp(buf, "configured", 10))
7047 snprintf(output_string, 32, "Configured");
7048 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7049
7050 return RETURN_OK;
7051}
7052
7053// sets the WPS pin for this AP
7054INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7055{
7056 char interface_name[16] = {0};
7057 char cmd[MAX_CMD_SIZE];
7058 char buf[MAX_BUF_SIZE]={0};
7059 BOOL enable;
7060
7061 wifi_getApEnable(apIndex, &enable);
7062 if (!enable)
7063 return RETURN_ERR;
7064 wifi_getApWpsEnable(apIndex, &enable);
7065 if (!enable)
7066 return RETURN_ERR;
7067
7068 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7069 return RETURN_ERR;
7070 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7071 _syscmd(cmd, buf, sizeof(buf));
7072 if((strstr(buf, "OK"))!=NULL)
7073 return RETURN_OK;
7074
7075 return RETURN_ERR;
7076}
7077
7078// This function is called when the WPS push button has been pressed for this AP
7079INT wifi_setApWpsButtonPush(INT apIndex)
7080{
7081 char cmd[MAX_CMD_SIZE];
7082 char buf[MAX_BUF_SIZE]={0};
7083 char interface_name[16] = {0};
7084 BOOL enable=FALSE;
7085
7086 wifi_getApEnable(apIndex, &enable);
7087 if (!enable)
7088 return RETURN_ERR;
7089
7090 wifi_getApWpsEnable(apIndex, &enable);
7091 if (!enable)
7092 return RETURN_ERR;
7093
7094 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7095 return RETURN_ERR;
7096
7097 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7098 _syscmd(cmd, buf, sizeof(buf));
7099
7100 if((strstr(buf, "OK"))!=NULL)
7101 return RETURN_OK;
7102 return RETURN_ERR;
7103}
7104
7105// cancels WPS mode for this AP
7106INT wifi_cancelApWPS(INT apIndex)
7107{
7108 char interface_name[16] = {0};
7109 char cmd[MAX_CMD_SIZE];
7110 char buf[MAX_BUF_SIZE]={0};
7111
7112 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7113 return RETURN_ERR;
7114 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7115 _syscmd(cmd,buf, sizeof(buf));
7116
7117 if((strstr(buf, "OK"))!=NULL)
7118 return RETURN_OK;
7119 return RETURN_ERR;
7120}
7121
7122//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7123//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7124INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7125{
7126 char interface_name[16] = {0};
7127 FILE *f = NULL;
7128 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7129 char cmd[256] = {0}, buf[2048] = {0};
7130 char *param = NULL, *value = NULL, *line=NULL;
7131 size_t len = 0;
7132 ssize_t nread = 0;
7133 wifi_associated_dev_t *dev=NULL;
7134
7135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7136 *associated_dev_array = NULL;
7137 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7138 return RETURN_ERR;
7139 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7140 _syscmd(cmd,buf,sizeof(buf));
7141 *output_array_size = atoi(buf);
7142
7143 if (*output_array_size <= 0)
7144 return RETURN_OK;
7145
7146 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7147 *associated_dev_array = dev;
7148 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7149 _syscmd(cmd,buf,sizeof(buf));
7150 f = fopen("/tmp/connected_devices.txt", "r");
7151 if (f==NULL)
7152 {
7153 *output_array_size=0;
7154 return RETURN_ERR;
7155 }
7156 while ((getline(&line, &len, f)) != -1)
7157 {
7158 param = strtok(line,"=");
7159 value = strtok(NULL,"=");
7160
7161 if( strcmp("flags",param) == 0 )
7162 {
7163 value[strlen(value)-1]='\0';
7164 if(strstr (value,"AUTHORIZED") != NULL )
7165 {
7166 dev[auth_temp].cli_AuthenticationState = 1;
7167 dev[auth_temp].cli_Active = 1;
7168 auth_temp++;
7169 read_flag=1;
7170 }
7171 }
7172 if(read_flag==1)
7173 {
7174 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7175 {
7176 value[strlen(value)-1]='\0';
7177 sscanf(value, "%x:%x:%x:%x:%x:%x",
7178 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7179 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7180 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7181 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7182 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7183 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7184 mac_temp++;
7185 read_flag=0;
7186 }
7187 }
7188 }
7189 *output_array_size = auth_temp;
7190 auth_temp=0;
7191 mac_temp=0;
7192 free(line);
7193 fclose(f);
7194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7195 return RETURN_OK;
7196}
7197
7198#define MACADDRESS_SIZE 6
7199
7200INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7201{
7202 FILE *fp = NULL;
7203 char str[MAX_BUF_SIZE] = {0};
7204 int wificlientindex = 0 ;
7205 int count = 0;
7206 int signalstrength = 0;
7207 int arr[MACADDRESS_SIZE] = {0};
7208 unsigned char mac[MACADDRESS_SIZE] = {0};
7209 UINT wifi_count = 0;
7210 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7211 char pipeCmd[MAX_CMD_SIZE] = {0};
7212
7213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7214 *output_array_size = 0;
7215 *associated_dev_array = NULL;
7216
7217 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7218 fp = popen(pipeCmd, "r");
7219 if (fp == NULL)
7220 {
7221 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7222 return RETURN_ERR;
7223 }
7224
7225 /* Read the output a line at a time - output it. */
7226 fgets(str, sizeof(str)-1, fp);
7227 wifi_count = (unsigned int) atoi ( str );
7228 *output_array_size = wifi_count;
7229 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7230 pclose(fp);
7231
7232 if(wifi_count == 0)
7233 {
7234 return RETURN_OK;
7235 }
7236 else
7237 {
7238 wifi_associated_dev3_t* temp = NULL;
7239 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7240 if(temp == NULL)
7241 {
7242 printf("Error Statement. Insufficient memory \n");
7243 return RETURN_ERR;
7244 }
7245
7246 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7247 system(pipeCmd);
7248 memset(pipeCmd,0,sizeof(pipeCmd));
7249 if(apIndex == 0)
7250 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7251 else if(apIndex == 1)
7252 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7253 system(pipeCmd);
7254
7255 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7256 if(fp == NULL)
7257 {
7258 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7259 free(temp);
7260 return RETURN_ERR;
7261 }
7262 fclose(fp);
7263
7264 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7265 fp = popen(pipeCmd, "r");
7266 if(fp)
7267 {
7268 for(count =0 ; count < wifi_count; count++)
7269 {
7270 fgets(str, MAX_BUF_SIZE, fp);
7271 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7272 {
7273 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7274 {
7275 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7276
7277 }
7278 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7279 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]);
7280 }
7281 temp[count].cli_AuthenticationState = 1; //TODO
7282 temp[count].cli_Active = 1; //TODO
7283 }
7284 pclose(fp);
7285 }
7286
7287 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7288 fp = popen(pipeCmd, "r");
7289 if(fp)
7290 {
7291 pclose(fp);
7292 }
7293 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7294 if(fp)
7295 {
7296 for(count =0 ; count < wifi_count ;count++)
7297 {
7298 fgets(str, MAX_BUF_SIZE, fp);
7299 signalstrength = atoi(str);
7300 temp[count].cli_SignalStrength = signalstrength;
7301 temp[count].cli_RSSI = signalstrength;
7302 temp[count].cli_SNR = signalstrength + 95;
7303 }
7304 pclose(fp);
7305 }
7306
7307
7308 if((apIndex == 0) || (apIndex == 4))
7309 {
7310 for(count =0 ; count < wifi_count ;count++)
7311 {
7312 strcpy(temp[count].cli_OperatingStandard,"g");
7313 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7314 }
7315
7316 //BytesSent
7317 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7318 fp = popen(pipeCmd, "r");
7319 if(fp)
7320 {
7321 pclose(fp);
7322 }
7323 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7324 if(fp)
7325 {
7326 for (count = 0; count < wifi_count; count++)
7327 {
7328 fgets(str, MAX_BUF_SIZE, fp);
7329 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7330 }
7331 pclose(fp);
7332 }
7333
7334 //BytesReceived
7335 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7336 fp = popen(pipeCmd, "r");
7337 if (fp)
7338 {
7339 pclose(fp);
7340 }
7341 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7342 if (fp)
7343 {
7344 for (count = 0; count < wifi_count; count++)
7345 {
7346 fgets(str, MAX_BUF_SIZE, fp);
7347 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7348 }
7349 pclose(fp);
7350 }
7351
7352 //PacketsSent
7353 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7354 fp = popen(pipeCmd, "r");
7355 if (fp)
7356 {
7357 pclose(fp);
7358 }
7359
7360 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7361 if (fp)
7362 {
7363 for (count = 0; count < wifi_count; count++)
7364 {
7365 fgets(str, MAX_BUF_SIZE, fp);
7366 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7367 }
7368 pclose(fp);
7369 }
7370
7371 //PacketsReceived
7372 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7373 fp = popen(pipeCmd, "r");
7374 if (fp)
7375 {
7376 pclose(fp);
7377 }
7378 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7379 if (fp)
7380 {
7381 for (count = 0; count < wifi_count; count++)
7382 {
7383 fgets(str, MAX_BUF_SIZE, fp);
7384 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7385 }
7386 pclose(fp);
7387 }
7388
7389 //ErrorsSent
7390 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7391 fp = popen(pipeCmd, "r");
7392 if (fp)
7393 {
7394 pclose(fp);
7395 }
7396 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7397 if (fp)
7398 {
7399 for (count = 0; count < wifi_count; count++)
7400 {
7401 fgets(str, MAX_BUF_SIZE, fp);
7402 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7403 }
7404 pclose(fp);
7405 }
7406
7407 //ErrorsSent
7408 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7409 fp = popen(pipeCmd, "r");
7410 if (fp)
7411 {
7412 pclose(fp);
7413 }
7414 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7415 if (fp)
7416 {
7417 for (count = 0; count < wifi_count; count++)
7418 {
7419 fgets(str, MAX_BUF_SIZE, fp);
7420 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7421 }
7422 pclose(fp);
7423 }
7424
7425 //LastDataDownlinkRate
7426 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7427 fp = popen(pipeCmd, "r");
7428 if (fp)
7429 {
7430 pclose(fp);
7431 }
7432 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7433 if (fp)
7434 {
7435 for (count = 0; count < wifi_count; count++)
7436 {
7437 fgets(str, MAX_BUF_SIZE, fp);
7438 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7439 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7440 }
7441 pclose(fp);
7442 }
7443
7444 //LastDataUplinkRate
7445 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7446 fp = popen(pipeCmd, "r");
7447 if (fp)
7448 {
7449 pclose(fp);
7450 }
7451 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7452 if (fp)
7453 {
7454 for (count = 0; count < wifi_count; count++)
7455 {
7456 fgets(str, MAX_BUF_SIZE, fp);
7457 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7458 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7459 }
7460 pclose(fp);
7461 }
7462
7463 }
7464 else if ((apIndex == 1) || (apIndex == 5))
7465 {
7466 for (count = 0; count < wifi_count; count++)
7467 {
7468 strcpy(temp[count].cli_OperatingStandard, "a");
7469 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7470 temp[count].cli_BytesSent = 0;
7471 temp[count].cli_BytesReceived = 0;
7472 temp[count].cli_LastDataUplinkRate = 0;
7473 temp[count].cli_LastDataDownlinkRate = 0;
7474 temp[count].cli_PacketsSent = 0;
7475 temp[count].cli_PacketsReceived = 0;
7476 temp[count].cli_ErrorsSent = 0;
7477 }
7478 }
7479
7480 for (count = 0; count < wifi_count; count++)
7481 {
7482 temp[count].cli_Retransmissions = 0;
7483 temp[count].cli_DataFramesSentAck = 0;
7484 temp[count].cli_DataFramesSentNoAck = 0;
7485 temp[count].cli_MinRSSI = 0;
7486 temp[count].cli_MaxRSSI = 0;
7487 strncpy(temp[count].cli_InterferenceSources, "", 64);
7488 memset(temp[count].cli_IPAddress, 0, 64);
7489 temp[count].cli_RetransCount = 0;
7490 temp[count].cli_FailedRetransCount = 0;
7491 temp[count].cli_RetryCount = 0;
7492 temp[count].cli_MultipleRetryCount = 0;
7493 }
7494 *associated_dev_array = temp;
7495 }
7496 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7497 return RETURN_OK;
7498}
7499
7500int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7501{
7502 FILE *fp = NULL;
7503 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7504 char cmd[MAX_CMD_SIZE];
7505 int count = 0;
7506
7507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7508 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7509 fp = popen(cmd,"r");
7510 if(fp == NULL)
7511 {
7512 printf("Failed to run command in Function %s\n",__FUNCTION__);
7513 return 0;
7514 }
7515 if(fgets(path, sizeof(path)-1, fp) != NULL)
7516 {
7517 for(count=0;path[count]!='\n';count++)
7518 status[count]=path[count];
7519 status[count]='\0';
7520 }
7521 strcpy(wifi_status,status);
7522 pclose(fp);
7523 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7524 return RETURN_OK;
7525}
7526
7527/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7528struct hostapd_sta_param {
7529 char key[50];
7530 char value[100];
7531}
7532
7533static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7534 int i = 0;
7535
7536 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7537 if (strncmp(params[i].key,key,50) == 0){
7538 return &params[i].value;
7539 }
7540 i++;
7541 }
7542 return NULL;
7543
7544} */
7545
7546static unsigned int count_occurences(const char *buf, const char *word)
7547{
7548 unsigned int n = 0;
7549 char *ptr = strstr(buf, word);
7550
7551 while (ptr++) {
7552 n++;
7553 ptr = strstr(ptr, word);
7554 }
7555
7556 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7557 return n;
7558}
7559
7560static const char *get_line_from_str_buf(const char *buf, char *line)
7561{
7562 int i;
7563 int n = strlen(buf);
7564
7565 for (i = 0; i < n; i++) {
7566 line[i] = buf[i];
7567 if (buf[i] == '\n') {
7568 line[i] = '\0';
7569 return &buf[i + 1];
7570 }
7571 }
7572
7573 return NULL;
7574}
7575
7576INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7577{
7578 unsigned int assoc_cnt = 0;
7579 char interface_name[50] = {0};
7580 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7581 char cmd[MAX_CMD_SIZE] = {'\0'};
7582 char line[256] = {'\0'};
7583 int i = 0;
7584 int ret = 0;
7585 const char *ptr = NULL;
7586 char *key = NULL;
7587 char *val = NULL;
7588 wifi_associated_dev3_t *temp = NULL;
7589 int rssi;
7590
7591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7592
7593 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7594 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7595 return RETURN_ERR;
7596 }
7597
7598 // Example filtered output of 'iw dev' command:
7599 // Station 0a:69:72:10:d2:fa (on wifi0)
7600 // signal avg:-67 [-71, -71] dBm
7601 // Station 28:c2:1f:25:5f:99 (on wifi0)
7602 // signal avg:-67 [-71, -70] dBm
7603 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7604 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7605 return RETURN_ERR;
7606 }
7607
7608 ret = _syscmd(cmd, buf, sizeof(buf));
7609 if (ret == RETURN_ERR) {
7610 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7611 return RETURN_ERR;
7612 }
7613
7614 *output_array_size = count_occurences(buf, "Station");
7615 if (*output_array_size == 0) return RETURN_OK;
7616
7617 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7618 if (temp == NULL) {
7619 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7620 return RETURN_ERR;
7621 }
7622 *associated_dev_array = temp;
7623
7624 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7625 ptr = get_line_from_str_buf(buf, line);
7626 i = -1;
7627 while (ptr) {
7628 if (strstr(line, "Station")) {
7629 i++;
7630 key = strtok(line, " ");
7631 val = strtok(NULL, " ");
7632 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7633 &temp[i].cli_MACAddress[0],
7634 &temp[i].cli_MACAddress[1],
7635 &temp[i].cli_MACAddress[2],
7636 &temp[i].cli_MACAddress[3],
7637 &temp[i].cli_MACAddress[4],
7638 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7639 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7640 free(*associated_dev_array);
7641 return RETURN_ERR;
7642 }
7643 }
7644 else if (i < 0) {
7645 ptr = get_line_from_str_buf(ptr, line);
7646 continue; // We didn't detect 'station' entry yet
7647 }
7648 else if (strstr(line, "signal avg")) {
7649 key = strtok(line, ":");
7650 val = strtok(NULL, " ");
7651 if (sscanf(val, "%d", &rssi) <= 0 ) {
7652 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7653 free(*associated_dev_array);
7654 return RETURN_ERR;
7655 }
7656 temp[i].cli_RSSI = rssi;
7657 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7658 }
7659 // Here other fields can be parsed if added to filter of 'iw dev' command
7660
7661 ptr = get_line_from_str_buf(ptr, line);
7662 };
7663
7664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7665
7666 return RETURN_OK;
7667}
7668
7669#if 0
7670//To-do
7671INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7672{
7673 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7674
7675 //Using different approach to get required WiFi Parameters from system available commands
7676#if 0
7677 FILE *f;
7678 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7679 char cmd[256], buf[2048];
7680 char *param , *value, *line=NULL;
7681 size_t len = 0;
7682 ssize_t nread;
7683 wifi_associated_dev3_t *dev=NULL;
7684 *associated_dev_array = NULL;
7685 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7686 _syscmd(cmd,buf,sizeof(buf));
7687 *output_array_size = atoi(buf);
7688
7689 if (*output_array_size <= 0)
7690 return RETURN_OK;
7691
7692 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7693 *associated_dev_array = dev;
7694 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
7695 _syscmd(cmd,buf,sizeof(buf));
7696 f = fopen("/tmp/connected_devices.txt", "r");
7697 if (f==NULL)
7698 {
7699 *output_array_size=0;
7700 return RETURN_ERR;
7701 }
7702 while ((nread = getline(&line, &len, f)) != -1)
7703 {
7704 param = strtok(line,"=");
7705 value = strtok(NULL,"=");
7706
7707 if( strcmp("flags",param) == 0 )
7708 {
7709 value[strlen(value)-1]='\0';
7710 if(strstr (value,"AUTHORIZED") != NULL )
7711 {
7712 dev[auth_temp].cli_AuthenticationState = 1;
7713 dev[auth_temp].cli_Active = 1;
7714 auth_temp++;
7715 read_flag=1;
7716 }
7717 }
7718 if(read_flag==1)
7719 {
7720 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7721 {
7722 value[strlen(value)-1]='\0';
7723 sscanf(value, "%x:%x:%x:%x:%x:%x",
7724 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7725 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7726 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7727 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7728 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7729 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7730
7731 }
7732 else if( strcmp("rx_packets",param) == 0 )
7733 {
7734 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7735 }
7736
7737 else if( strcmp("tx_packets",param) == 0 )
7738 {
7739 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7740 }
7741
7742 else if( strcmp("rx_bytes",param) == 0 )
7743 {
7744 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7745 }
7746
7747 else if( strcmp("tx_bytes",param) == 0 )
7748 {
7749 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7750 mac_temp++;
7751 read_flag=0;
7752 }
7753 }
7754 }
7755
7756 *output_array_size = auth_temp;
7757 auth_temp=0;
7758 mac_temp=0;
7759 free(line);
7760 fclose(f);
7761#endif
7762 char interface_name[MAX_BUF_SIZE] = {0};
7763 char wifi_status[MAX_BUF_SIZE] = {0};
7764 char hostapdconf[MAX_BUF_SIZE] = {0};
7765
7766 wifi_associated_dev3_t *dev_array = NULL;
7767 ULONG wifi_count = 0;
7768
7769 *associated_dev_array = NULL;
7770 *output_array_size = 0;
7771
7772 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7773 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7774 {
7775 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7776
7777 wifi_GetInterfaceName(interface_name, hostapdconf);
7778
7779 if(strlen(interface_name) > 1)
7780 {
7781 wifihal_interfacestatus(wifi_status,interface_name);
7782 if(strcmp(wifi_status,"RUNNING") == 0)
7783 {
7784 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7785
7786 *associated_dev_array = dev_array;
7787 *output_array_size = wifi_count;
7788 }
7789 else
7790 {
7791 *associated_dev_array = NULL;
7792 }
7793 }
7794 }
7795
7796 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7797 return RETURN_OK;
7798}
7799#endif
7800
7801/* getIPAddress function */
7802/**
7803* @description Returning IpAddress of the Matched String
7804*
7805* @param
7806* @str Having MacAddress
7807* @ipaddr Having ipaddr
7808* @return The status of the operation
7809* @retval RETURN_OK if successful
7810* @retval RETURN_ERR if any error is detected
7811*
7812*/
7813
7814INT getIPAddress(char *str,char *ipaddr)
7815{
7816 FILE *fp = NULL;
7817 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7818 int LeaseTime = 0,ret = 0;
7819 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7820 {
7821 return RETURN_ERR;
7822 }
7823
7824 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7825 {
7826 /*
7827 Sample:sss
7828 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7829 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7830 */
7831 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7832 &(LeaseTime),
7833 phyAddr,
7834 ipAddr,
7835 hostName
7836 );
7837 if(ret != 4)
7838 continue;
7839 if(strcmp(str,phyAddr) == 0)
7840 strcpy(ipaddr,ipAddr);
7841 }
7842 fclose(fp);
7843 return RETURN_OK;
7844}
7845
7846/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7847/**
7848* @description Returning Inactive wireless connected clients informations
7849*
7850* @param
7851* @filename Holding private_wifi 2g/5g content files
7852* @associated_dev_array Having inactiv wireless clients informations
7853* @output_array_size Returning Inactive wireless counts
7854* @return The status of the operation
7855* @retval RETURN_OK if successful
7856* @retval RETURN_ERR if any error is detected
7857*
7858*/
7859
7860INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7861{
7862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7863 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7864 FILE *fp = NULL;
7865 int arr[MACADDRESS_SIZE] = {0};
7866 unsigned char mac[MACADDRESS_SIZE] = {0};
7867 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7868 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7869 fp = popen(buf,"r");
7870 if(fp == NULL)
7871 return RETURN_ERR;
7872 else
7873 {
7874 fgets(path,sizeof(path),fp);
7875 maccount = atoi(path);
7876 }
7877 pclose(fp);
7878 *output_array_size = maccount;
7879 wifi_associated_dev3_t* temp = NULL;
7880 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7881 *associated_dev_array = temp;
7882 if(temp == NULL)
7883 {
7884 printf("Error Statement. Insufficient memory \n");
7885 return RETURN_ERR;
7886 }
7887 memset(buf,0,sizeof(buf));
7888 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7889 fp = popen(buf,"r");
7890 if (fp == NULL) {
7891 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
7892 return RETURN_ERR;
7893 }
7894 for(count = 0; count < maccount ; count++)
7895 {
7896 fgets(path,sizeof(path),fp);
7897 for(i = 0; path[i]!='\n';i++)
7898 str[i]=path[i];
7899 str[i]='\0';
7900 getIPAddress(str,ipaddr);
7901 memset(buf,0,sizeof(buf));
7902 if(strlen(ipaddr) > 0)
7903 {
7904 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7905 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7906 {
7907 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7908 {
7909 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7910 {
7911 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7912
7913 }
7914 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7915 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]);
7916 }
7917 temp[count].cli_AuthenticationState = 0; //TODO
7918 temp[count].cli_Active = 0; //TODO
7919 temp[count].cli_SignalStrength = 0;
7920 }
7921 else //Active wireless clients info
7922 {
7923 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7924 {
7925 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7926 {
7927 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7928
7929 }
7930 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7931 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]);
7932 }
7933 temp[count].cli_Active = 1;
7934 }
7935 }
7936 memset(ipaddr,0,sizeof(ipaddr));
7937 }
7938 pclose(fp);
7939 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7940 return RETURN_OK;
7941}
7942//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7943//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7944//To get Band Steering Capability
7945INT wifi_getBandSteeringCapability(BOOL *support)
7946{
7947 *support = FALSE;
7948 return RETURN_OK;
7949}
7950
7951
7952//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7953//To get Band Steering enable status
7954INT wifi_getBandSteeringEnable(BOOL *enable)
7955{
7956 *enable = FALSE;
7957 return RETURN_OK;
7958}
7959
7960//To turn on/off Band steering
7961INT wifi_setBandSteeringEnable(BOOL enable)
7962{
7963 return RETURN_OK;
7964}
7965
7966//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7967//To get Band Steering AP group
7968INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7969{
7970 if (NULL == output_ApGroup)
7971 return RETURN_ERR;
7972
7973 strcpy(output_ApGroup, "1,2");
7974 return RETURN_OK;
7975}
7976
7977//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7978//to set and read the band steering BandUtilizationThreshold parameters
7979INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7980{
7981 return RETURN_ERR;
7982}
7983
7984INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7985{
7986 return RETURN_ERR;
7987}
7988
7989//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7990//to set and read the band steering RSSIThreshold parameters
7991INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7992{
7993 return RETURN_ERR;
7994}
7995
7996INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7997{
7998 return RETURN_ERR;
7999}
8000
8001
8002//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8003//to set and read the band steering physical modulation rate threshold parameters
8004INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8005{
8006 //If chip is not support, return -1
8007 return RETURN_ERR;
8008}
8009
8010INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8011{
8012 //If chip is not support, return -1
8013 return RETURN_ERR;
8014}
8015
8016//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8017//to set and read the inactivity time (in seconds) for steering under overload condition
8018INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8019{
8020 return RETURN_ERR;
8021}
8022
8023INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8024{
8025 return RETURN_ERR;
8026}
8027
8028//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8029//to set and read the inactivity time (in seconds) for steering under Idle condition
8030INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8031{
8032 return RETURN_ERR;
8033}
8034
8035INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8036{
8037 return RETURN_ERR;
8038}
8039
8040//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8041//pClientMAC[64]
8042//pSourceSSIDIndex[64]
8043//pDestSSIDIndex[64]
8044//pSteeringReason[256]
8045INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8046{
8047 //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
8048 *pSteeringTime=time(NULL);
8049 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8050 return RETURN_OK;
8051}
8052
8053INT wifi_ifConfigDown(INT apIndex)
8054{
8055 INT status = RETURN_OK;
8056 char cmd[64];
8057
8058 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8059 printf("%s: %s\n", __func__, cmd);
8060 system(cmd);
8061
8062 return status;
8063}
8064
8065INT wifi_ifConfigUp(INT apIndex)
8066{
8067 char interface_name[16] = {0};
8068 char cmd[128];
8069 char buf[1024];
8070
8071 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8072 return RETURN_ERR;
8073 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8074 _syscmd(cmd, buf, sizeof(buf));
8075 return 0;
8076}
8077
8078//>> Deprecated. Replace with wifi_applyRadioSettings
8079INT wifi_pushBridgeInfo(INT apIndex)
8080{
8081 char interface_name[16] = {0};
8082 char ip[32] = {0};
8083 char subnet[32] = {0};
8084 char bridge[32] = {0};
8085 int vlanId = 0;
8086 char cmd[128] = {0};
8087 char buf[1024] = {0};
8088
8089 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8090 wifi_getApVlanID(apIndex,&vlanId);
8091
8092 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8093 return RETURN_ERR;
8094 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8095 _syscmd(cmd,buf, sizeof(buf));
8096
8097 return 0;
8098}
8099
8100INT wifi_pushChannel(INT radioIndex, UINT channel)
8101{
8102 char interface_name[16] = {0};
8103 char cmd[128];
8104 char buf[1024];
8105 int apIndex;
8106
8107 apIndex=(radioIndex==0)?0:1;
8108 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8109 return RETURN_ERR;
8110 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8111 _syscmd(cmd,buf, sizeof(buf));
8112
8113 return 0;
8114}
8115
8116INT wifi_pushChannelMode(INT radioIndex)
8117{
8118 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8119 return RETURN_ERR;
8120}
8121
8122INT wifi_pushDefaultValues(INT radioIndex)
8123{
8124 //Apply Comcast specified default radio settings instantly
8125 //AMPDU=1
8126 //AMPDUFrames=32
8127 //AMPDULim=50000
8128 //txqueuelen=1000
8129
8130 return RETURN_ERR;
8131}
8132
8133INT wifi_pushTxChainMask(INT radioIndex)
8134{
8135 //Apply default TxChainMask instantly
8136 return RETURN_ERR;
8137}
8138
8139INT wifi_pushRxChainMask(INT radioIndex)
8140{
8141 //Apply default RxChainMask instantly
8142 return RETURN_ERR;
8143}
8144
8145INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8146{
8147 INT status;
8148
8149 status = wifi_setSSIDName(apIndex,ssid);
8150 wifi_setApEnable(apIndex,FALSE);
8151 wifi_setApEnable(apIndex,TRUE);
8152
8153 return status;
8154}
8155
8156INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8157{
8158 //Apply default Ssid Advertisement instantly
8159 return RETURN_ERR;
8160}
8161
8162INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8163{
8164 INT status = RETURN_ERR;
8165 *output = 0;
8166 return RETURN_ERR;
8167}
8168
8169INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8170{
8171 return RETURN_OK;
8172}
8173
8174INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8175{
8176 return RETURN_OK;
8177}
8178
8179//To-do
8180INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8181{
8182 char output[16]={'\0'};
8183 char config_file[MAX_BUF_SIZE] = {0};
8184
8185 if (!output_string)
8186 return RETURN_ERR;
8187
8188 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8189 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8190
8191 if (strlen(output) == 0)
8192 snprintf(output_string, 64, "Disabled");
8193 else if (strncmp(output, "0", 1) == 0)
8194 snprintf(output_string, 64, "Disabled");
8195 else if (strncmp(output, "1", 1) == 0)
8196 snprintf(output_string, 64, "Optional");
8197 else if (strncmp(output, "2", 1) == 0)
8198 snprintf(output_string, 64, "Required");
8199 else {
8200 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8201 return RETURN_ERR;
8202 }
8203
8204 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8205 return RETURN_OK;
8206}
8207INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8208{
8209 char str[MAX_BUF_SIZE]={'\0'};
8210 char cmd[MAX_CMD_SIZE]={'\0'};
8211 struct params params;
8212 char config_file[MAX_BUF_SIZE] = {0};
8213
8214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8215 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8216 return RETURN_ERR;
8217
8218 params.name = "ieee80211w";
8219 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8220 params.value = "0";
8221 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8222 params.value = "1";
8223 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8224 params.value = "2";
8225 else{
8226 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8227 return RETURN_ERR;
8228 }
8229 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8230 wifi_hostapdWrite(config_file, &params, 1);
8231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8232 return RETURN_OK;
8233}
8234INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8235{
8236 char output[16]={'\0'};
8237 char config_file[MAX_BUF_SIZE] = {0};
8238
8239 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8240 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8241 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8242
8243 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8244 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8245
8246 return RETURN_OK;
8247}
8248
8249INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8250{
8251 return RETURN_OK;
8252}
8253
8254INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8255{
8256 return RETURN_OK;
8257}
8258
8259INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8260{
8261 return RETURN_OK;
8262}
8263
8264INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8265{
8266 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8267 char config_file[MAX_BUF_SIZE] = {0};
8268
8269 if (NULL == output)
8270 return RETURN_ERR;
8271 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8272 wifi_hostapdRead(config_file,"hw_mode",output,64);
8273
8274 if(strcmp(output,"b")==0)
8275 sprintf(output, "%s", "1,2,5.5,11");
8276 else if (strcmp(output,"a")==0)
8277 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8278 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8279 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8280
8281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8282 return RETURN_OK;
8283}
8284
8285INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8286{
8287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8288 char *temp;
8289 char temp_output[128];
8290 char temp_TransmitRates[128];
8291 char config_file[MAX_BUF_SIZE] = {0};
8292
8293 if (NULL == output)
8294 return RETURN_ERR;
8295
8296 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8297 wifi_hostapdRead(config_file,"supported_rates",output,64);
8298
8299 if (strlen(output) == 0) {
8300 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8301 return RETURN_OK;
8302 }
8303 strcpy(temp_TransmitRates,output);
8304 strcpy(temp_output,"");
8305 temp = strtok(temp_TransmitRates," ");
8306 while(temp!=NULL)
8307 {
8308 temp[strlen(temp)-1]=0;
8309 if((temp[0]=='5') && (temp[1]=='\0'))
8310 {
8311 temp="5.5";
8312 }
8313 strcat(temp_output,temp);
8314 temp = strtok(NULL," ");
8315 if(temp!=NULL)
8316 {
8317 strcat(temp_output,",");
8318 }
8319 }
8320 strcpy(output,temp_output);
8321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8322
8323 return RETURN_OK;
8324}
8325
8326INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8327{
8328 return RETURN_OK;
8329}
8330
8331
8332INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8333{
8334 int i=0;
8335 char *temp;
8336 char temp1[128] = {0};
8337 char temp_output[128] = {0};
8338 char temp_TransmitRates[128] = {0};
8339 struct params params={'\0'};
8340 char config_file[MAX_BUF_SIZE] = {0};
8341 wifi_band band = wifi_index_to_band(wlanIndex);
8342
8343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8344 if(NULL == output)
8345 return RETURN_ERR;
8346 strcpy(temp_TransmitRates,output);
8347
8348 for(i=0;i<strlen(temp_TransmitRates);i++)
8349 {
8350 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8351 {
8352 continue;
8353 }
8354 else
8355 {
8356 return RETURN_ERR;
8357 }
8358 }
8359 strcpy(temp_output,"");
8360 temp = strtok(temp_TransmitRates,",");
8361 while(temp!=NULL)
8362 {
8363 strcpy(temp1,temp);
8364 if(band == band_5)
8365 {
8366 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8367 {
8368 return RETURN_ERR;
8369 }
8370 }
8371
8372 if(strcmp(temp,"5.5")==0)
8373 {
8374 strcpy(temp1,"55");
8375 }
8376 else
8377 {
8378 strcat(temp1,"0");
8379 }
8380 strcat(temp_output,temp1);
8381 temp = strtok(NULL,",");
8382 if(temp!=NULL)
8383 {
8384 strcat(temp_output," ");
8385 }
8386 }
8387 strcpy(output,temp_output);
8388
8389 params.name = "supported_rates";
8390 params.value = output;
8391
8392 wifi_dbg_printf("\n%s:",__func__);
8393 wifi_dbg_printf("params.value=%s\n",params.value);
8394 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8395 wifi_hostapdWrite(config_file,&params,1);
8396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8397
8398 return RETURN_OK;
8399}
8400
8401
8402static char *sncopy(char *dst, int dst_sz, const char *src)
8403{
8404 if (src && dst && dst_sz > 0) {
8405 strncpy(dst, src, dst_sz);
8406 dst[dst_sz - 1] = '\0';
8407 }
8408 return dst;
8409}
8410
8411static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8412{
8413 if (0 == strcmp(ht_mode, "HT40") ||
8414 0 == strcmp(ht_mode, "HT80") ||
8415 0 == strcmp(ht_mode, "HT160")) {
8416 switch (channel) {
8417 case 1 ... 7:
8418 case 36:
8419 case 44:
8420 case 52:
8421 case 60:
8422 case 100:
8423 case 108:
8424 case 116:
8425 case 124:
8426 case 132:
8427 case 140:
8428 case 149:
8429 case 157:
8430 return 1;
8431 case 8 ... 13:
8432 case 40:
8433 case 48:
8434 case 56:
8435 case 64:
8436 case 104:
8437 case 112:
8438 case 120:
8439 case 128:
8440 case 136:
8441 case 144:
8442 case 153:
8443 case 161:
8444 return -1;
8445 default:
8446 return -EINVAL;
8447 }
8448 }
8449
8450 return -EINVAL;
8451}
8452
8453static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8454{
8455 int idx = channel%8;
8456 if (0 == strcmp(ht_mode, "HT40") ||
8457 0 == strcmp(ht_mode, "HT80") ||
8458 0 == strcmp(ht_mode, "HT160")) {
8459 switch (idx) {
8460 case 1:
8461 return 1;
8462 case 5:
8463 return -1;
8464 default:
8465 return -EINVAL;
8466 }
8467 }
8468
8469 return -EINVAL;
8470}
8471static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8472{
8473 if (NULL == hw_mode) return;
8474
8475 if (0 == strcmp(hw_mode, "ac"))
8476 sncopy(bw_mode, bw_mode_len, "ht vht");
8477
8478 if (0 == strcmp(hw_mode, "n"))
8479 sncopy(bw_mode, bw_mode_len, "ht");
8480
8481 return;
8482}
8483
8484static int util_chan_to_freq(int chan)
8485{
8486 if (chan == 14)
8487 return 2484;
8488 else if (chan < 14)
8489 return 2407 + chan * 5;
8490 else if (chan >= 182 && chan <= 196)
8491 return 4000 + chan * 5;
8492 else
8493 return 5000 + chan * 5;
8494 return 0;
8495}
8496
8497static int util_6G_chan_to_freq(int chan)
8498{
8499 if (chan)
8500 return 5950 + chan * 5;
8501 else
8502 return 0;
8503
8504}
8505const int *util_unii_5g_chan2list(int chan, int width)
8506{
8507 static const int lists[] = {
8508 // <width>, <chan1>, <chan2>..., 0,
8509 20, 36, 0,
8510 20, 40, 0,
8511 20, 44, 0,
8512 20, 48, 0,
8513 20, 52, 0,
8514 20, 56, 0,
8515 20, 60, 0,
8516 20, 64, 0,
8517 20, 100, 0,
8518 20, 104, 0,
8519 20, 108, 0,
8520 20, 112, 0,
8521 20, 116, 0,
8522 20, 120, 0,
8523 20, 124, 0,
8524 20, 128, 0,
8525 20, 132, 0,
8526 20, 136, 0,
8527 20, 140, 0,
8528 20, 144, 0,
8529 20, 149, 0,
8530 20, 153, 0,
8531 20, 157, 0,
8532 20, 161, 0,
8533 20, 165, 0,
8534 40, 36, 40, 0,
8535 40, 44, 48, 0,
8536 40, 52, 56, 0,
8537 40, 60, 64, 0,
8538 40, 100, 104, 0,
8539 40, 108, 112, 0,
8540 40, 116, 120, 0,
8541 40, 124, 128, 0,
8542 40, 132, 136, 0,
8543 40, 140, 144, 0,
8544 40, 149, 153, 0,
8545 40, 157, 161, 0,
8546 80, 36, 40, 44, 48, 0,
8547 80, 52, 56, 60, 64, 0,
8548 80, 100, 104, 108, 112, 0,
8549 80, 116, 120, 124, 128, 0,
8550 80, 132, 136, 140, 144, 0,
8551 80, 149, 153, 157, 161, 0,
8552 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8553 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8554 -1 // final delimiter
8555 };
8556 const int *start;
8557 const int *p;
8558
8559 for (p = lists; *p != -1; p++) {
8560 if (*p == width) {
8561 for (start = ++p; *p != 0; p++) {
8562 if (*p == chan)
8563 return start;
8564 }
8565 }
8566 // move to the end of channel list of given width
8567 while (*p != 0) {
8568 p++;
8569 }
8570 }
8571
8572 return NULL;
8573}
8574
8575static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8576{
8577 if (NULL == ht_mode)
8578 return 0;
8579
8580 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8581 const int *chans = util_unii_5g_chan2list(channel, width);
8582 int sum = 0;
8583 int cnt = 0;
8584
8585 if (NULL == chans)
8586 return 0;
8587
8588 while (*chans) {
8589 sum += *chans;
8590 cnt++;
8591 chans++;
8592 }
8593 if (cnt == 0)
8594 return 0;
8595 return sum / cnt;
8596}
8597
8598static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8599{
8600 if (NULL == ht_mode)
8601 return 0;
8602
8603 int width = strtol((ht_mode + 2), NULL, 10);
8604
8605 int idx = 0 ;
8606 int centerchan = 0;
8607 int chan_ofs = 1;
8608
8609 if (width == 40){
8610 idx = ((channel/4) + chan_ofs)%2;
8611 switch (idx) {
8612 case 0:
8613 centerchan = (channel - 2);
8614 break;
8615 case 1:
8616 centerchan = (channel + 2);
8617 break;
8618 default:
8619 return -EINVAL;
8620 }
8621 }else if (width == 80){
8622 idx = ((channel/4) + chan_ofs)%4;
8623 switch (idx) {
8624 case 0:
8625 centerchan = (channel - 6);
8626 break;
8627 case 1:
8628 centerchan = (channel + 6);
8629 break;
8630 case 2:
8631 centerchan = (channel + 2);
8632 break;
8633 case 3:
8634 centerchan = (channel - 2);
8635 break;
8636 default:
8637 return -EINVAL;
8638 }
8639 }else if (width == 160){
8640 switch (channel) {
8641 case 1 ... 29:
8642 centerchan = 15;
8643 break;
8644 case 33 ... 61:
8645 centerchan = 47;
8646 break;
8647 case 65 ... 93:
8648 centerchan = 79;
8649 break;
8650 case 97 ... 125:
8651 centerchan = 111;
8652 break;
8653 case 129 ... 157:
8654 centerchan = 143;
8655 break;
8656 case 161 ... 189:
8657 centerchan = 175;
8658 break;
8659 case 193 ... 221:
8660 centerchan = 207;
8661 break;
8662 default:
8663 return -EINVAL;
8664 }
8665 }
8666 return centerchan;
8667}
8668static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8669{
8670 BOOL onlyG, onlyN, onlyA;
8671 CHAR tmp[64];
8672 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8673 if (ret == RETURN_OK) {
8674 sncopy(hw_mode, hw_mode_size, tmp);
8675 }
8676 return ret;
8677}
8678
8679INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8680{
8681 // Sample commands:
8682 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8683 // hostapd_cli -i wifi0 chan_switch 30 2437
8684 char cmd[MAX_CMD_SIZE] = {0};
8685 char buf[MAX_BUF_SIZE] = {0};
8686 int freq = 0, ret = 0;
8687 char center_freq1_str[32] = ""; // center_freq1=%d
8688 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8689 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8690 char hw_mode[16] = ""; // n|ac
8691 char bw_mode[16] = ""; // ht|ht vht
8692 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8693 char interface_name[16] = {0};
8694 int sec_chan_offset;
8695 int width;
8696 char config_file[64] = {0};
8697 BOOL stbcEnable = FALSE;
8698 char *ext_str = "None";
8699 wifi_band band = band_invalid;
8700 int center_chan = 0;
8701 int center_freq1 = 0;
8702
8703 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
8704
8705 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8706 return RETURN_ERR;
8707
8708 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8709
8710 band = wifi_index_to_band(radioIndex);
8711
8712 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8713
8714 // Get radio mode HT20|HT40|HT80 etc.
8715 if (channel){
8716 if (band == band_6){
8717 freq = util_6G_chan_to_freq(channel);
8718 }else{
8719 freq = util_chan_to_freq(channel);
8720 }
8721 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8722
8723 // Provide bandwith if specified
8724 if (channel_width_MHz > 20) {
8725 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8726 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8727 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8728
8729 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8730 }else if (channel_width_MHz == 20){
8731 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
8732 }
8733
8734
8735 if (channel_width_MHz > 20) {
8736 if (band == band_6){
8737 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
8738 if(center_chan){
8739 center_freq1 = util_6G_chan_to_freq(center_chan);
8740 }
8741 }else{
8742 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8743 if(center_chan){
8744 center_freq1 = util_chan_to_freq(center_chan);
8745 }
8746 }
8747
8748 if (center_freq1)
8749 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8750
8751 }
8752
8753 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8754 if (band == band_6){
8755 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
8756 }else{
8757 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8758 }
8759 if (sec_chan_offset != -EINVAL)
8760 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8761
8762 // Only the first AP, other are hanging on the same radio
8763 int apIndex = radioIndex;
8764 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
8765 interface_name, csa_beacon_count, freq,
8766 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8767 wifi_dbg_printf("execute: '%s'\n", cmd);
8768 ret = _syscmd(cmd, buf, sizeof(buf));
8769 wifi_reloadAp(radioIndex);
8770
8771 ret = wifi_setRadioChannel(radioIndex, channel);
8772 if (ret != RETURN_OK) {
8773 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
8774 return RETURN_ERR;
8775 }
8776
8777 if (sec_chan_offset == 1) ext_str = "Above";
8778 else if (sec_chan_offset == -1) ext_str = "Below";
8779
8780 wifi_setRadioCenterChannel(radioIndex, center_chan);
8781
8782 } else {
8783 if (channel_width_MHz > 20)
8784 ext_str = "Above";
8785 }
8786
8787 wifi_setRadioExtChannel(radioIndex, ext_str);
8788
8789 char mhz_str[16];
8790 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8791 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8792
8793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8794
8795 return RETURN_OK;
8796}
8797
8798INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8799{
8800 int index = -1;
8801 wifi_neighbor_ap2_t *scan_array = NULL;
8802 char cmd[256]={0};
8803 char buf[128]={0};
8804 char file_name[32] = {0};
8805 char filter_SSID[32] = {0};
8806 char line[256] = {0};
8807 char interface_name[16] = {0};
8808 char *ret = NULL;
8809 int freq=0;
8810 FILE *f = NULL;
8811 size_t len=0;
8812 int channels_num = 0;
8813 int vht_channel_width = 0;
8814 int get_noise_ret = RETURN_ERR;
8815 bool filter_enable = false;
8816 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
8817 int phyId = 0;
8818
8819 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
8820
8821 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8822 f = fopen(file_name, "r");
8823 if (f != NULL) {
8824 fgets(filter_SSID, sizeof(file_name), f);
8825 if (strlen(filter_SSID) != 0)
8826 filter_enable = true;
8827 fclose(f);
8828 }
8829
8830 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
8831 return RETURN_ERR;
8832
8833 phyId = radio_index_to_phy(radio_index);
8834
8835 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
8836 _syscmd(cmd, buf, sizeof(buf));
8837 channels_num = strtol(buf, NULL, 10);
8838
8839 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8840 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
8841 fprintf(stderr, "cmd: %s\n", cmd);
8842 if ((f = popen(cmd, "r")) == NULL) {
8843 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8844 return RETURN_ERR;
8845 }
8846
8847 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8848 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8849
8850 ret = fgets(line, sizeof(line), f);
8851 while (ret != NULL) {
8852 if(strstr(line, "BSS") != NULL) { // new neighbor info
8853 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8854 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8855 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8856
8857 if (!filter_BSS) {
8858 index++;
8859 wifi_neighbor_ap2_t *tmp;
8860 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8861 if (tmp == NULL) { // no more memory to use
8862 index--;
8863 wifi_dbg_printf("%s: realloc failed\n", __func__);
8864 break;
8865 }
8866 scan_array = tmp;
8867 }
8868 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8869
8870 filter_BSS = false;
8871 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8872 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8873 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8874 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8875 } else if (strstr(line, "freq") != NULL) {
8876 sscanf(line," freq: %d", &freq);
8877 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
8878
8879 if (freq >= 2412 && freq <= 2484) {
8880 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8881 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8882 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8883 }
8884 else if (freq >= 5160 && freq <= 5805) {
8885 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8886 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8887 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8888 }
8889
8890 scan_array[index].ap_Noise = 0;
8891 if (get_noise_ret == RETURN_OK) {
8892 for (int i = 0; i < channels_num; i++) {
8893 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8894 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8895 break;
8896 }
8897 }
8898 }
8899 } else if (strstr(line, "beacon interval") != NULL) {
8900 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8901 } else if (strstr(line, "signal") != NULL) {
8902 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8903 } else if (strstr(line,"SSID") != NULL) {
8904 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8905 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8906 filter_BSS = true;
8907 }
8908 } else if (strstr(line, "Supported rates") != NULL) {
8909 char SRate[80] = {0}, *tmp = NULL;
8910 memset(buf, 0, sizeof(buf));
8911 strcpy(SRate, line);
8912 tmp = strtok(SRate, ":");
8913 tmp = strtok(NULL, ":");
8914 strcpy(buf, tmp);
8915 memset(SRate, 0, sizeof(SRate));
8916
8917 tmp = strtok(buf, " \n");
8918 while (tmp != NULL) {
8919 strcat(SRate, tmp);
8920 if (SRate[strlen(SRate) - 1] == '*') {
8921 SRate[strlen(SRate) - 1] = '\0';
8922 }
8923 strcat(SRate, ",");
8924
8925 tmp = strtok(NULL, " \n");
8926 }
8927 SRate[strlen(SRate) - 1] = '\0';
8928 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8929 } else if (strstr(line, "DTIM") != NULL) {
8930 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8931 } else if (strstr(line, "VHT capabilities") != NULL) {
8932 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8933 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8934 } else if (strstr(line, "HT capabilities") != NULL) {
8935 strcat(scan_array[index].ap_SupportedStandards, ",n");
8936 strcpy(scan_array[index].ap_OperatingStandards, "n");
8937 } else if (strstr(line, "VHT operation") != NULL) {
8938 ret = fgets(line, sizeof(line), f);
8939 sscanf(line," * channel width: %d", &vht_channel_width);
8940 if(vht_channel_width == 1) {
8941 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8942 } else {
8943 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8944 }
8945 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8946 continue;
8947 } else if (strstr(line, "HT operation") != NULL) {
8948 ret = fgets(line, sizeof(line), f);
8949 sscanf(line," * secondary channel offset: %s", &buf);
8950 if (!strcmp(buf, "above")) {
8951 //40Mhz +
8952 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
8953 }
8954 else if (!strcmp(buf, "below")) {
8955 //40Mhz -
8956 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8957 } else {
8958 //20Mhz
8959 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
8960 }
8961 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8962 continue;
8963 } else if (strstr(line, "HE capabilities") != NULL) {
8964 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8965 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8966 ret = fgets(line, sizeof(line), f);
8967 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8968 if (strstr(line, "HE40/2.4GHz") != NULL)
8969 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8970 else
8971 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8972 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8973 if (strstr(line, "HE80/5GHz") != NULL) {
8974 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8975 ret = fgets(line, sizeof(line), f);
8976 } else
8977 continue;
8978 if (strstr(line, "HE160/5GHz") != NULL)
8979 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
8980 }
8981 continue;
8982 } else if (strstr(line, "WPA") != NULL) {
8983 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8984 } else if (strstr(line, "RSN") != NULL) {
8985 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8986 } else if (strstr(line, "Group cipher") != NULL) {
8987 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8988 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8989 strcpy(scan_array[index].ap_EncryptionMode, "AES");
8990 }
8991 }
8992 ret = fgets(line, sizeof(line), f);
8993 }
8994
8995 if (!filter_BSS) {
8996 *output_array_size = index + 1;
8997 } else {
8998 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8999 *output_array_size = index;
9000 }
9001 *neighbor_ap_array = scan_array;
9002 pclose(f);
9003 free(channels_noise_arr);
9004 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9005 return RETURN_OK;
9006}
9007
9008INT wifi_getApAssociatedDeviceStats(
9009 INT apIndex,
9010 mac_address_t *clientMacAddress,
9011 wifi_associated_dev_stats_t *associated_dev_stats,
9012 u64 *handle)
9013{
9014 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9015 char interface_name[50] = {0};
9016 char cmd[1024] = {0};
9017 char mac_str[18] = {0};
9018 char *key = NULL;
9019 char *val = NULL;
9020 FILE *f = NULL;
9021 char *line = NULL;
9022 size_t len = 0;
9023
9024 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9025 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9026 return RETURN_ERR;
9027 }
9028
9029 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9030 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9031 if((f = popen(cmd, "r")) == NULL) {
9032 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9033 return RETURN_ERR;
9034 }
9035
9036 while ((getline(&line, &len, f)) != -1) {
9037 key = strtok(line,":");
9038 val = strtok(NULL,":");
9039
9040 if(!strncmp(key,"rx bytes",8))
9041 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9042 if(!strncmp(key,"tx bytes",8))
9043 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9044 if(!strncmp(key,"rx packets",10))
9045 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9046 if(!strncmp(key,"tx packets",10))
9047 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9048 if(!strncmp(key,"tx retries",10))
9049 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9050 if(!strncmp(key,"tx failed",9))
9051 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9052 if(!strncmp(key,"rx drop misc",13))
9053 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9054 if(!strncmp(key,"rx bitrate",10)) {
9055 val = strtok(val, " ");
9056 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9057 }
9058 if(!strncmp(key,"tx bitrate",10)) {
9059 val = strtok(val, " ");
9060 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9061 }
9062 }
9063 free(line);
9064 pclose(f);
9065 return RETURN_OK;
9066}
9067
9068INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9069{
9070 char interface_name[16] = {0};
9071 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9072
9073 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9074 if (NULL == output_string)
9075 return RETURN_ERR;
9076
9077 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9078 return RETURN_ERR;
9079 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
9080 _syscmd(cmd, buf, sizeof(buf));
9081
9082 //size of SSID name restricted to value less than 32 bytes
9083 snprintf(output_string, 32, "%s", buf);
9084 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9085
9086 return RETURN_OK;
9087}
9088
9089INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9090{
9091 //char cmd[MAX_CMD_SIZE] = {0};
9092 char config_file[MAX_BUF_SIZE] = {0};
9093 char buf[32] = {0};
9094
9095 if (!output_filterMode)
9096 return RETURN_ERR;
9097
9098 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9099 //_syscmd(cmd, buf, sizeof(buf));
9100 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9101 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9102 if(strlen(buf) == 0) {
9103 *output_filterMode = 0;
9104 }
9105 else {
9106 int macaddr_acl_mode = strtol(buf, NULL, 10);
9107 if (macaddr_acl_mode == 1) {
9108 *output_filterMode = 1;
9109 } else if (macaddr_acl_mode == 0) {
9110 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9111 if (strlen(buf) == 0) {
9112 *output_filterMode = 0;
9113 } else {
9114 *output_filterMode = 2;
9115 }
9116 } else {
9117 return RETURN_ERR;
9118 }
9119 }
9120
9121 return RETURN_OK;
9122}
9123
9124INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9125{
9126 FILE *fp = NULL;
9127 char str[MAX_BUF_SIZE] = {0};
9128 int wificlientindex = 0 ;
9129 int count = 0;
9130 int signalstrength = 0;
9131 int arr[MACADDRESS_SIZE] = {0};
9132 unsigned char mac[MACADDRESS_SIZE] = {0};
9133 UINT wifi_count = 0;
9134 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9135 char pipeCmd[MAX_CMD_SIZE] = {0};
9136
9137 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9138 *output_array_size = 0;
9139 *associated_dev_array = NULL;
9140 char interface_name[50] = {0};
9141
9142 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9143 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9144 return RETURN_ERR;
9145 }
9146
9147 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9148 fp = popen(pipeCmd, "r");
9149 if (fp == NULL)
9150 {
9151 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9152 return RETURN_ERR;
9153 }
9154
9155 /* Read the output a line at a time - output it. */
9156 fgets(str, sizeof(str)-1, fp);
9157 wifi_count = (unsigned int) atoi ( str );
9158 *output_array_size = wifi_count;
9159 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9160 pclose(fp);
9161
9162 if(wifi_count == 0)
9163 {
9164 return RETURN_OK;
9165 }
9166 else
9167 {
9168 wifi_associated_dev2_t* temp = NULL;
9169 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9170 *associated_dev_array = temp;
9171 if(temp == NULL)
9172 {
9173 printf("Error Statement. Insufficient memory \n");
9174 return RETURN_ERR;
9175 }
9176
9177 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9178 system(pipeCmd);
9179
9180 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9181 if(fp == NULL)
9182 {
9183 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9184 return RETURN_ERR;
9185 }
9186 fclose(fp);
9187
9188 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9189 fp = popen(pipeCmd, "r");
9190 if(fp)
9191 {
9192 for(count =0 ; count < wifi_count; count++)
9193 {
9194 fgets(str, MAX_BUF_SIZE, fp);
9195 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9196 {
9197 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9198 {
9199 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9200
9201 }
9202 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9203 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]);
9204 }
9205 temp[count].cli_AuthenticationState = 1; //TODO
9206 temp[count].cli_Active = 1; //TODO
9207 }
9208 pclose(fp);
9209 }
9210
9211 //Updating RSSI per client
9212 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9213 fp = popen(pipeCmd, "r");
9214 if(fp)
9215 {
9216 pclose(fp);
9217 }
9218 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9219 if(fp)
9220 {
9221 for(count =0 ; count < wifi_count ;count++)
9222 {
9223 fgets(str, MAX_BUF_SIZE, fp);
9224 signalstrength = atoi(str);
9225 temp[count].cli_RSSI = signalstrength;
9226 }
9227 pclose(fp);
9228 }
9229
9230
9231 //LastDataDownlinkRate
9232 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9233 fp = popen(pipeCmd, "r");
9234 if (fp)
9235 {
9236 pclose(fp);
9237 }
9238 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9239 if (fp)
9240 {
9241 for (count = 0; count < wifi_count; count++)
9242 {
9243 fgets(str, MAX_BUF_SIZE, fp);
9244 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9245 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9246 }
9247 pclose(fp);
9248 }
9249
9250 //LastDataUplinkRate
9251 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9252 fp = popen(pipeCmd, "r");
9253 if (fp)
9254 {
9255 pclose(fp);
9256 }
9257 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9258 if (fp)
9259 {
9260 for (count = 0; count < wifi_count; count++)
9261 {
9262 fgets(str, MAX_BUF_SIZE, fp);
9263 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9264 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9265 }
9266 pclose(fp);
9267 }
9268 }
9269 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9270 return RETURN_OK;
9271
9272}
9273
9274INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9275{
9276#if 0
9277 /*char buf[1024] = {0};
9278 sprintf(cmd, "ifconfig %s ", interface_name);
9279 _syscmd(cmd, buf, sizeof(buf));*/
9280
9281 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9282 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9283 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9284 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9285
9286 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.
9287 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].
9288 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].
9289 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].
9290 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9291 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9292
9293 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9294 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9295 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9296 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.
9297 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.
9298 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.
9299 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.
9300 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.
9301 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.
9302 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.
9303 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9304#endif
9305
9306 FILE *fp = NULL;
9307 char interface_name[50] = {0};
9308 char pipeCmd[128] = {0};
9309 char str[256] = {0};
9310 wifi_ssidTrafficStats2_t *out = output_struct;
9311
9312 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9313 if (!output_struct)
9314 return RETURN_ERR;
9315
9316 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9317 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9318 return RETURN_ERR;
9319 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9320
9321 fp = popen(pipeCmd, "r");
9322 if (fp == NULL) {
9323 fprintf(stderr, "%s: popen failed\n", __func__);
9324 return RETURN_ERR;
9325 }
9326 fgets(str, sizeof(str), fp);
9327 pclose(fp);
9328
9329 if (strlen(str) == 0) // interface not exist
9330 return RETURN_OK;
9331
9332 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9333 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9334
9335 memset(str, 0, sizeof(str));
9336 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9337 fp = popen(pipeCmd, "r");
9338 if (fp == NULL) {
9339 fprintf(stderr, "%s: popen failed\n", __func__);
9340 return RETURN_ERR;
9341 }
9342 fgets(str, sizeof(str), fp);
9343
9344 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9345 &out->ssid_BroadcastPacketsSent);
9346 pclose(fp);
9347
9348 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9349 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9350
9351 // Not supported
9352 output_struct->ssid_RetransCount = 0;
9353 output_struct->ssid_FailedRetransCount = 0;
9354 output_struct->ssid_RetryCount = 0;
9355 output_struct->ssid_MultipleRetryCount = 0;
9356 output_struct->ssid_ACKFailureCount = 0;
9357 output_struct->ssid_AggregatedPacketCount = 0;
9358
9359 return RETURN_OK;
9360}
9361
9362//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).
9363INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9364{
9365 char output_val[16]={'\0'};
9366 char config_file[MAX_BUF_SIZE] = {0};
9367
9368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9369 if (!output)
9370 return RETURN_ERR;
9371 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9372 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9373
9374 if( strcmp(output_val,"1") == 0 )
9375 *output = TRUE;
9376 else
9377 *output = FALSE;
9378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9379
9380 return RETURN_OK;
9381}
9382
9383INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9384{
9385 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9386 char str[MAX_BUF_SIZE]={'\0'};
9387 char string[MAX_BUF_SIZE]={'\0'};
9388 char cmd[MAX_CMD_SIZE]={'\0'};
9389 char *ch;
9390 char config_file[MAX_BUF_SIZE] = {0};
9391 struct params params;
9392
9393 if(enable == TRUE)
9394 strcpy(string,"1");
9395 else
9396 strcpy(string,"0");
9397
9398 params.name = "ap_isolate";
9399 params.value = string;
9400
9401 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9402 wifi_hostapdWrite(config_file,&params,1);
9403 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9404
9405 return RETURN_OK;
9406}
9407
9408INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9409{
9410 if (NULL == output_dBm)
9411 return RETURN_ERR;
9412
9413 *output_dBm = 0;
9414 return RETURN_OK;
9415}
9416
9417INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9418{
9419 return RETURN_OK;
9420}
9421INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9422{
9423 return RETURN_OK;
9424}
9425INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9426{
9427 return RETURN_OK;
9428}
9429INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9430{
9431 return RETURN_OK;
9432}
9433INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9434{
9435 return RETURN_OK;
9436}
9437INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9438{
9439 char config_file[MAX_BUF_SIZE] = {0};
9440 struct params list;
9441
9442 list.name = "bss_transition";
9443 list.value = activate?"1":"0";
9444 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9445 wifi_hostapdWrite(config_file, &list, 1);
9446
9447 return RETURN_OK;
9448}
9449wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9450
9451void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9452{
9453 return;
9454}
9455
9456INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9457{
9458 // TODO Implement me!
9459 return RETURN_OK;
9460}
9461
9462INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9463{
9464 char file_name[128] = {0};
9465 char buf[128] = {0};
9466 FILE *f = NULL;
9467 int max_num_radios = 0;
9468
9469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9470
9471 wifi_getMaxRadioNumber(&max_num_radios);
9472 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9473 for (int index = 0; index < max_num_radios; index++) {
9474 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9475 f = fopen(file_name, "w");
9476 if (f == NULL)
9477 return RETURN_ERR;
9478 // For mode == 0 is to disable filter, just don't write to the file.
9479 if (mode)
9480 fprintf(f, "%s", essid);
9481
9482 fclose(f);
9483 }
9484 } else { // special case, need to set AP's SSID as filter for each radio.
9485 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9486 f = fopen(file_name, "w");
9487 if (f == NULL)
9488 return RETURN_ERR;
9489
9490 // For mode == 0 is to disable filter, just don't write to the file.
9491 if (mode)
9492 fprintf(f, "%s", essid);
9493
9494 fclose(f);
9495 }
9496
9497 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9498 return RETURN_OK;
9499}
9500
9501INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9502{
9503 // TODO Implement me!
9504 //Apply wifi_pushRadioChannel() instantly
9505 return RETURN_ERR;
9506}
9507
9508INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9509{
9510 // TODO Implement me!
9511 return RETURN_OK;
9512}
9513
9514#ifdef HAL_NETLINK_IMPL
9515static int tidStats_callback(struct nl_msg *msg, void *arg) {
9516 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9517 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9518 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9519 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9520 int rem , tid_index = 0;
9521
9522 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9523 wifi_associated_dev_tid_entry_t *stats_entry;
9524
9525 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9526 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9527 };
9528 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9529 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9530 };
9531
9532 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9533 genlmsg_attrlen(gnlh, 0), NULL);
9534
9535
9536 if (!tb[NL80211_ATTR_STA_INFO]) {
9537 fprintf(stderr, "station stats missing!\n");
9538 return NL_SKIP;
9539 }
9540
9541 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9542 tb[NL80211_ATTR_STA_INFO],
9543 stats_policy)) {
9544 fprintf(stderr, "failed to parse nested attributes!\n");
9545 return NL_SKIP;
9546 }
9547
9548 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9549 {
9550 stats_entry = &out->tid_array[tid_index];
9551
9552 stats_entry->tid = tid_index;
9553 stats_entry->ac = _tid_ac_index_get[tid_index];
9554
9555 if(sinfo[NL80211_STA_INFO_TID_STATS])
9556 {
9557 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9558 printf("failed to parse nested stats attributes!");
9559 return NL_SKIP;
9560 }
9561 }
9562 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9563 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9564
9565 if(tid_index < (PS_MAX_TID - 1))
9566 tid_index++;
9567 }
9568 //ToDo: sum_time_ms, ewma_time_ms
9569 return NL_SKIP;
9570}
9571#endif
9572
9573INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9574{
9575#ifdef HAL_NETLINK_IMPL
9576 Netlink nl;
9577 char if_name[10];
9578 char interface_name[16] = {0};
9579
9580 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9581 return RETURN_ERR;
9582
9583 snprintf(if_name, sizeof(if_name), "%s", interface_name);
9584
9585 nl.id = initSock80211(&nl);
9586
9587 if (nl.id < 0) {
9588 fprintf(stderr, "Error initializing netlink \n");
9589 return -1;
9590 }
9591
9592 struct nl_msg* msg = nlmsg_alloc();
9593
9594 if (!msg) {
9595 fprintf(stderr, "Failed to allocate netlink message.\n");
9596 nlfree(&nl);
9597 return -2;
9598 }
9599
9600 genlmsg_put(msg,
9601 NL_AUTO_PORT,
9602 NL_AUTO_SEQ,
9603 nl.id,
9604 0,
9605 0,
9606 NL80211_CMD_GET_STATION,
9607 0);
9608
9609 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9610 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9611 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9612 nl_send_auto(nl.socket, msg);
9613 nl_recvmsgs(nl.socket, nl.cb);
9614 nlmsg_free(msg);
9615 nlfree(&nl);
9616 return RETURN_OK;
9617#else
9618//iw implementation
9619#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9620#define TOTAL_MAX_LINES 50
9621
9622 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9623 char if_name[32] = {0};
9624 FILE *fp=NULL;
9625 char pipeCmd[1024]= {'\0'};
9626 int lines,tid_index=0;
9627 char mac_addr[20] = {'\0'};
9628
9629 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9630 return RETURN_ERR;
9631
9632 wifi_associated_dev_tid_entry_t *stats_entry;
9633
9634 strcpy(mac_addr,clientMacAddress);
9635
9636 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9637 fp= popen(pipeCmd,"r");
9638 if(fp == NULL)
9639 {
9640 perror("popen for station dump failed\n");
9641 return RETURN_ERR;
9642 }
9643 pclose(fp);
9644
9645 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9646 fp=popen(pipeCmd,"r");
9647 if(fp == NULL)
9648 {
9649 perror("popen for grep station failed\n");
9650 return RETURN_ERR;
9651 }
9652 else if(fgets(buf,sizeof(buf),fp) != NULL)
9653 lines=atoi(buf);
9654 else
9655 {
9656 pclose(fp);
9657 fprintf(stderr,"No devices are connected \n");
9658 return RETURN_ERR;
9659 }
9660 pclose(fp);
9661
9662 if(lines == 1)
9663 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9664
9665 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9666 {
9667 stats_entry = &tid_stats->tid_array[tid_index];
9668 stats_entry->tid = tid_index;
9669
9670 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);
9671
9672 fp=popen(pipeCmd,"r");
9673 if(fp ==NULL)
9674 {
9675 perror("Failed to read from tid file \n");
9676 return RETURN_ERR;
9677 }
9678 else if(fgets(buf,sizeof(buf),fp) != NULL)
9679 stats_entry->num_msdus = atol(buf);
9680
9681 pclose(fp);
9682 stats_entry->ac = _tid_ac_index_get[tid_index];
9683// TODO:
9684// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9685// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9686 }
9687 return RETURN_OK;
9688#endif
9689}
9690
9691
9692INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9693{
9694 char interface_name[16] = {0};
9695 char cmd[128]={0};
9696 char buf[128]={0};
9697 int freq = 0;
9698
9699 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9700
9701 // full mode is used to scan all channels.
9702 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9703 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9704 ieee80211_channel_to_frequency(chan_list[0], &freq);
9705
9706 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9707 return RETURN_ERR;
9708
9709 if (freq)
9710 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
9711 else
9712 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
9713
9714 _syscmd(cmd, buf, sizeof(buf));
9715 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9716
9717 return RETURN_OK;
9718}
9719
9720
9721INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9722{
9723 // TODO Implement me!
9724 return RETURN_ERR;
9725}
9726
9727INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9728{
9729 // TODO Implement me!
9730 return RETURN_ERR;
9731}
9732
9733INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9734{
9735 // TODO Implement me!
9736 return RETURN_ERR;
9737}
9738
9739INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9740{
9741 // TODO Implement me!
9742 return RETURN_ERR;
9743}
9744
9745INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9746{
9747 // TODO Implement me!
9748 return RETURN_ERR;
9749}
9750
9751INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9752{
9753 // TODO Implement me!
9754 return RETURN_ERR;
9755}
9756
9757INT wifi_steering_eventUnregister(void)
9758{
9759 // TODO Implement me!
9760 return RETURN_ERR;
9761}
9762
9763INT wifi_delApAclDevices(INT apIndex)
9764{
9765#if 0
9766 char cmd[MAX_BUF_SIZE] = {0};
9767 char buf[MAX_BUF_SIZE] = {0};
9768
9769 /* Not reset proof solution */
9770 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
9771 if(_syscmd(cmd,buf,sizeof(buf)))
9772 return RETURN_ERR;
9773#endif
9774 char cmd[MAX_CMD_SIZE]={0};
9775 char buf[MAX_BUF_SIZE]={0};
9776
9777 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9778 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9779 if(_syscmd(cmd, buf, sizeof(buf)))
9780 return RETURN_ERR;
9781 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9782
9783 return RETURN_OK;
9784}
9785
9786#ifdef HAL_NETLINK_IMPL
9787static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9788 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9789 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9790 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9791 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9792 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9793 char mac_addr[20],dev[20];
9794
9795 nla_parse(tb,
9796 NL80211_ATTR_MAX,
9797 genlmsg_attrdata(gnlh, 0),
9798 genlmsg_attrlen(gnlh, 0),
9799 NULL);
9800
9801 if(!tb[NL80211_ATTR_STA_INFO]) {
9802 fprintf(stderr, "sta stats missing!\n");
9803 return NL_SKIP;
9804 }
9805
9806 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9807 fprintf(stderr, "failed to parse nested attributes!\n");
9808 return NL_SKIP;
9809 }
9810 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9811
9812 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9813
9814 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9815 fprintf(stderr, "failed to parse nested rate attributes!");
9816 return NL_SKIP;
9817 }
9818
9819 if(sinfo[NL80211_STA_INFO_TID_STATS])
9820 {
9821 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9822 printf("failed to parse nested stats attributes!");
9823 return NL_SKIP;
9824 }
9825 }
9826
9827 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9828 {
9829 printf("Type is VHT\n");
9830 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9831 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9832
9833 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9834 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9835 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9836 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9837 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9838 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9839 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9840 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9841 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9842 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9843 }
9844 else
9845 {
9846 printf(" OFDM or CCK \n");
9847 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9848 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9849 }
9850
9851 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9852 if(rinfo[NL80211_RATE_INFO_MCS])
9853 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9854 }
9855 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9856 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9857 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9858 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9859
9860 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9861 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9862
9863 if (sinfo[NL80211_STA_INFO_SIGNAL])
9864 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9865 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9866 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9867 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9868 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9869 //rssi_array need to be filled
9870 return NL_SKIP;
9871}
9872#endif
9873
9874INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9875{
9876#ifdef HAL_NETLINK_IMPL
9877 Netlink nl;
9878 char if_name[32];
9879 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9880 return RETURN_ERR;
9881
9882 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9883
9884 if (*output_array_size <= 0)
9885 return RETURN_OK;
9886
9887 nl.id = initSock80211(&nl);
9888
9889 if (nl.id < 0) {
9890 fprintf(stderr, "Error initializing netlink \n");
9891 return 0;
9892 }
9893
9894 struct nl_msg* msg = nlmsg_alloc();
9895
9896 if (!msg) {
9897 fprintf(stderr, "Failed to allocate netlink message.\n");
9898 nlfree(&nl);
9899 return 0;
9900 }
9901
9902 genlmsg_put(msg,
9903 NL_AUTO_PORT,
9904 NL_AUTO_SEQ,
9905 nl.id,
9906 0,
9907 0,
9908 NL80211_CMD_GET_STATION,
9909 0);
9910
9911 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9912 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9913 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9914 nl_send_auto(nl.socket, msg);
9915 nl_recvmsgs(nl.socket, nl.cb);
9916 nlmsg_free(msg);
9917 nlfree(&nl);
9918 return RETURN_OK;
9919#else
9920 //TODO Implement me
9921 return RETURN_OK;
9922#endif
9923}
9924
9925#ifdef HAL_NETLINK_IMPL
9926static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9927 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9928 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9929 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9930 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9931 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9932 char mac_addr[20],dev[20];
9933
9934 nla_parse(tb,
9935 NL80211_ATTR_MAX,
9936 genlmsg_attrdata(gnlh, 0),
9937 genlmsg_attrlen(gnlh, 0),
9938 NULL);
9939
9940 if(!tb[NL80211_ATTR_STA_INFO]) {
9941 fprintf(stderr, "sta stats missing!\n");
9942 return NL_SKIP;
9943 }
9944
9945 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9946 fprintf(stderr, "failed to parse nested attributes!\n");
9947 return NL_SKIP;
9948 }
9949
9950 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9951
9952 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9953
9954 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9955 fprintf(stderr, "failed to parse nested rate attributes!");
9956 return NL_SKIP;
9957 }
9958
9959 if(sinfo[NL80211_STA_INFO_TID_STATS])
9960 {
9961 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9962 printf("failed to parse nested stats attributes!");
9963 return NL_SKIP;
9964 }
9965 }
9966 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9967 {
9968 printf("Type is VHT\n");
9969 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9970 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9971
9972 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9973 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9974 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9975 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9976 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9977 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9978 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9979 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9980 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9981 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9982 }
9983 else
9984 {
9985 printf(" OFDM or CCK \n");
9986 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9987 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9988 }
9989
9990 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9991 if(rinfo[NL80211_RATE_INFO_MCS])
9992 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9993 }
9994
9995 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9996 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9997 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9998 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9999
10000 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10001 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10002 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10003
10004 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10005 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10006
10007 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10008 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10009
10010 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10011 ((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]);
10012
10013 return NL_SKIP;
10014}
10015#endif
10016
10017INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10018{
10019#ifdef HAL_NETLINK_IMPL
10020 Netlink nl;
10021 char if_name[10];
10022 char interface_name[16] = {0};
10023 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10024 return RETURN_ERR;
10025
10026 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10027
10028 if (*output_array_size <= 0)
10029 return RETURN_OK;
10030
10031 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10032
10033 nl.id = initSock80211(&nl);
10034
10035 if(nl.id < 0) {
10036 fprintf(stderr, "Error initializing netlink \n");
10037 return 0;
10038 }
10039
10040 struct nl_msg* msg = nlmsg_alloc();
10041
10042 if(!msg) {
10043 fprintf(stderr, "Failed to allocate netlink message.\n");
10044 nlfree(&nl);
10045 return 0;
10046 }
10047
10048 genlmsg_put(msg,
10049 NL_AUTO_PORT,
10050 NL_AUTO_SEQ,
10051 nl.id,
10052 0,
10053 0,
10054 NL80211_CMD_GET_STATION,
10055 0);
10056
10057 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10058 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10059 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10060 nl_send_auto(nl.socket, msg);
10061 nl_recvmsgs(nl.socket, nl.cb);
10062 nlmsg_free(msg);
10063 nlfree(&nl);
10064 return RETURN_OK;
10065#else
10066 //TODO Implement me
10067 return RETURN_OK;
10068#endif
10069}
10070
10071INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10072{
10073 // TODO Implement me!
10074 char buf[MAX_BUF_SIZE] = {0};
10075 char config_file[MAX_BUF_SIZE] = {0};
10076
10077 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10078 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10079 *activate = (strncmp("1",buf,1) == 0);
10080
10081 return RETURN_OK;
10082}
10083
10084INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10085{
10086 char config_file[MAX_BUF_SIZE] = {0};
10087 struct params list;
10088
10089 list.name = "rrm_neighbor_report";
10090 list.value = activate?"1":"0";
10091 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10092 wifi_hostapdWrite(config_file, &list, 1);
10093
10094 return RETURN_OK;
10095}
10096
10097INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10098{
10099 char buf[32] = {0};
10100 char config_file[MAX_BUF_SIZE] = {0};
10101
10102 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10103 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10104 *activate = (strncmp("1",buf,1) == 0);
10105
10106 return RETURN_OK;
10107}
10108#undef HAL_NETLINK_IMPL
10109#ifdef HAL_NETLINK_IMPL
10110static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10111 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10112 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10113 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10114 char dev[20];
10115 int freq =0 ;
10116 static int i=0;
10117
10118 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10119
10120 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10121 };
10122
10123 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10124
10125 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10126
10127 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10128 fprintf(stderr, "survey data missing!\n");
10129 return NL_SKIP;
10130 }
10131
10132 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10133 {
10134 fprintf(stderr, "failed to parse nested attributes!\n");
10135 return NL_SKIP;
10136 }
10137
10138
10139 if(out[0].array_size == 1 )
10140 {
10141 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10142 {
10143 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10144 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10145 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10146
10147 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10148 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10149 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10150 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10151 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10152 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10153 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10154 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10155 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10156 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10157 if (sinfo[NL80211_SURVEY_INFO_TIME])
10158 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10159 return NL_STOP;
10160 }
10161 }
10162 else
10163 {
10164 if ( i <= out[0].array_size )
10165 {
10166 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10167 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10168 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10169
10170 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10171 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10172 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10173 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10174 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10175 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10176 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10177 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10178 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10179 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10180 if (sinfo[NL80211_SURVEY_INFO_TIME])
10181 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10182 }
10183 }
10184
10185 i++;
10186 return NL_SKIP;
10187}
10188#endif
10189
10190static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10191{
10192 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10193 FILE *fp;
10194
10195 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10196 {
10197 printf("Creating Frequency-Channel Map\n");
10198 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10199 }
10200 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10201 if((fp = popen(command, "r")))
10202 {
10203 fgets(output, sizeof(output), fp);
10204 *freqMHz = atoi(output);
10205 pclose(fp);
10206 }
10207
10208 return 0;
10209}
10210
10211static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10212{
10213 int freqMHz = -1;
10214 char cmd[MAX_CMD_SIZE] = {'\0'};
10215 char interface_name[16] = {0};
10216
10217 ieee80211_channel_to_frequency(channel, &freqMHz);
10218 if (freqMHz == -1) {
10219 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10220 return -1;
10221 }
10222
10223 wifi_GetInterfaceName(radioIndex, interface_name);
10224 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10225 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10226 radioIndex, freqMHz);
10227 return -1;
10228 }
10229
10230 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10231 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10232 return -1;
10233 }
10234
10235 return 0;
10236}
10237
10238static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10239{
10240 const char *ptr = buf;
10241 char *key = NULL;
10242 char *val = NULL;
10243 char line[256] = { '\0' };
10244
10245 while (ptr = get_line_from_str_buf(ptr, line)) {
10246 if (strstr(line, "Frequency")) continue;
10247
10248 key = strtok(line, ":");
10249 val = strtok(NULL, " ");
10250 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10251
10252 if (!strcmp(key, "noise")) {
10253 sscanf(val, "%d", &stats->ch_noise);
10254 if (stats->ch_noise == 0) {
10255 // Workaround for missing noise information.
10256 // Assume -95 for 2.4G and -103 for 5G
10257 if (radioIndex == 0) stats->ch_noise = -95;
10258 if (radioIndex == 1) stats->ch_noise = -103;
10259 }
10260 }
10261 else if (!strcmp(key, "channel active time")) {
10262 sscanf(val, "%llu", &stats->ch_utilization_total);
10263 }
10264 else if (!strcmp(key, "channel busy time")) {
10265 sscanf(val, "%llu", &stats->ch_utilization_busy);
10266 }
10267 else if (!strcmp(key, "channel receive time")) {
10268 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10269 }
10270 else if (!strcmp(key, "channel transmit time")) {
10271 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10272 }
10273 };
10274
10275 return 0;
10276}
10277
10278INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10279{
10280 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10281#ifdef HAL_NETLINK_IMPL
10282 Netlink nl;
10283 wifi_channelStats_t_loc local[array_size];
10284 char if_name[32];
10285
10286 local[0].array_size = array_size;
10287
10288 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10289 return RETURN_ERR;
10290
10291 nl.id = initSock80211(&nl);
10292
10293 if (nl.id < 0) {
10294 fprintf(stderr, "Error initializing netlink \n");
10295 return -1;
10296 }
10297
10298 struct nl_msg* msg = nlmsg_alloc();
10299
10300 if (!msg) {
10301 fprintf(stderr, "Failed to allocate netlink message.\n");
10302 nlfree(&nl);
10303 return -2;
10304 }
10305
10306 genlmsg_put(msg,
10307 NL_AUTO_PORT,
10308 NL_AUTO_SEQ,
10309 nl.id,
10310 0,
10311 NLM_F_DUMP,
10312 NL80211_CMD_GET_SURVEY,
10313 0);
10314
10315 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10316 nl_send_auto(nl.socket, msg);
10317 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10318 nl_recvmsgs(nl.socket, nl.cb);
10319 nlmsg_free(msg);
10320 nlfree(&nl);
10321 //Copying the Values
10322 for(int i=0;i<array_size;i++)
10323 {
10324 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10325 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10326 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10327 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10328 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10329 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10330 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10331 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10332 }
10333#else
10334 ULONG channel = 0;
10335 int i;
10336 int number_of_channels = array_size;
10337 char buf[512];
10338 INT ret;
10339 wifi_channelStats_t tmp_stats;
10340
10341 if (number_of_channels == 0) {
10342 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10343 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10344 return RETURN_ERR;
10345 }
10346 number_of_channels = 1;
10347 input_output_channelStats_array[0].ch_number = channel;
10348 }
10349
10350 for (i = 0; i < number_of_channels; i++) {
10351
10352 input_output_channelStats_array[i].ch_noise = 0;
10353 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10354 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10355 input_output_channelStats_array[i].ch_utilization_busy = 0;
10356 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10357 input_output_channelStats_array[i].ch_utilization_total = 0;
10358
10359 memset(buf, 0, sizeof(buf));
10360 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10361 return RETURN_ERR;
10362 }
10363 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10364 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10365 return RETURN_ERR;
10366 }
10367
10368 // XXX: fake missing 'self' counter which is not available in iw survey output
10369 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10370 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10371
10372 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10373 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10374 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10375 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10376 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10377
10378 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",
10379 __func__,
10380 input_output_channelStats_array[i].ch_number,
10381 input_output_channelStats_array[i].ch_noise,
10382 input_output_channelStats_array[i].ch_utilization_total,
10383 input_output_channelStats_array[i].ch_utilization_busy,
10384 input_output_channelStats_array[i].ch_utilization_busy_rx,
10385 input_output_channelStats_array[i].ch_utilization_busy_tx,
10386 input_output_channelStats_array[i].ch_utilization_busy_self,
10387 input_output_channelStats_array[i].ch_utilization_busy_ext);
10388 }
10389#endif
10390 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10391 return RETURN_OK;
10392}
10393#define HAL_NETLINK_IMPL
10394
10395/* Hostapd events */
10396
10397#ifndef container_of
10398#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10399#define container_of(ptr, type, member) \
10400 ((type *)((char *)ptr - offset_of(type, member)))
10401#endif /* container_of */
10402
10403struct ctrl {
10404 char sockpath[128];
10405 char sockdir[128];
10406 char bss[IFNAMSIZ];
10407 char reply[4096];
10408 int ssid_index;
10409 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10410 void (*overrun)(struct ctrl *ctrl);
10411 struct wpa_ctrl *wpa;
10412 unsigned int ovfl;
10413 size_t reply_len;
10414 int initialized;
10415 ev_timer retry;
10416 ev_timer watchdog;
10417 ev_stat stat;
10418 ev_io io;
10419};
10420static wifi_newApAssociatedDevice_callback clients_connect_cb;
10421static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10422static struct ctrl wpa_ctrl[MAX_APS];
10423static int initialized;
10424
10425static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10426{
10427 char cbuf[256] = {};
10428 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10429 struct cmsghdr *cmsg;
10430 unsigned int ovfl = ctrl->ovfl;
10431 unsigned int drop;
10432
10433 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10434 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10435 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10436 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10437
10438 drop = ovfl - ctrl->ovfl;
10439 ctrl->ovfl = ovfl;
10440
10441 return drop;
10442}
10443
10444static void ctrl_close(struct ctrl *ctrl)
10445{
10446 if (ctrl->io.cb)
10447 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10448 if (ctrl->retry.cb)
10449 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10450 if (!ctrl->wpa)
10451 return;
10452
10453 wpa_ctrl_detach(ctrl->wpa);
10454 wpa_ctrl_close(ctrl->wpa);
10455 ctrl->wpa = NULL;
10456 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10457}
10458
10459static void ctrl_process(struct ctrl *ctrl)
10460{
10461 const char *str;
10462 int drops;
10463 int level;
10464 int err;
10465
10466 /* Example events:
10467 *
10468 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10469 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10470 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10471 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10472 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10473 */
10474 if (!(str = index(ctrl->reply, '>')))
10475 return;
10476 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10477 return;
10478
10479 str++;
10480
10481 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10482 if (!(str = index(ctrl->reply, ' ')))
10483 return;
10484 wifi_associated_dev_t sta;
10485 memset(&sta, 0, sizeof(sta));
10486
10487 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10488 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10489 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10490
10491 sta.cli_Active=true;
10492
10493 (clients_connect_cb)(ctrl->ssid_index, &sta);
10494 goto handled;
10495 }
10496
10497 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10498 if (!(str = index(ctrl->reply, ' ')))
10499 return;
10500
10501 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10502 goto handled;
10503 }
10504
10505 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10506 printf("CTRL_WPA: handle TERMINATING event\n");
10507 goto retry;
10508 }
10509
10510 if (strncmp("AP-DISABLED", str, 11) == 0) {
10511 printf("CTRL_WPA: handle AP-DISABLED\n");
10512 goto retry;
10513 }
10514
10515 printf("Event not supported!!\n");
10516
10517handled:
10518
10519 if ((drops = ctrl_get_drops(ctrl))) {
10520 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10521 if (ctrl->overrun)
10522 ctrl->overrun(ctrl);
10523 }
10524
10525 return;
10526
10527retry:
10528 printf("WPA_CTRL: closing\n");
10529 ctrl_close(ctrl);
10530 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10531 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10532}
10533
10534static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10535{
10536 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10537 int err;
10538
10539 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10540 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10541 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10542 ctrl->reply[ctrl->reply_len] = 0;
10543 if (err < 0) {
10544 if (errno == EAGAIN || errno == EWOULDBLOCK)
10545 return;
10546 ctrl_close(ctrl);
10547 ev_timer_again(EV_A_ &ctrl->retry);
10548 return;
10549 }
10550
10551 ctrl_process(ctrl);
10552}
10553
10554static int ctrl_open(struct ctrl *ctrl)
10555{
10556 int fd;
10557
10558 if (ctrl->wpa)
10559 return 0;
10560
10561 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10562 if (!ctrl->wpa)
10563 goto err;
10564
10565 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10566 goto err_close;
10567
10568 fd = wpa_ctrl_get_fd(ctrl->wpa);
10569 if (fd < 0)
10570 goto err_detach;
10571
10572 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10573 goto err_detach;
10574
10575 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10576 ev_io_start(EV_DEFAULT_ &ctrl->io);
10577
10578 return 0;
10579
10580err_detach:
10581 wpa_ctrl_detach(ctrl->wpa);
10582err_close:
10583 wpa_ctrl_close(ctrl->wpa);
10584err:
10585 ctrl->wpa = NULL;
10586 return -1;
10587}
10588
10589static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10590{
10591 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10592
10593 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10594 ctrl_open(ctrl);
10595}
10596
10597static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10598{
10599 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10600
10601 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10602 if (ctrl_open(ctrl) == 0) {
10603 printf("WPA_CTRL: retry successful\n");
10604 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10605 }
10606}
10607
10608int ctrl_enable(struct ctrl *ctrl)
10609{
10610 if (ctrl->wpa)
10611 return 0;
10612
10613 if (!ctrl->stat.cb) {
10614 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10615 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10616 }
10617
10618 if (!ctrl->retry.cb) {
10619 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10620 }
10621
10622 return ctrl_open(ctrl);
10623}
10624
10625static void
10626ctrl_msg_cb(char *buf, size_t len)
10627{
10628 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10629
10630 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10631 ctrl_process(ctrl);
10632}
10633
10634static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10635{
10636 int err;
10637
10638 if (!ctrl->wpa)
10639 return -1;
10640 if (*reply_len < 2)
10641 return -1;
10642
10643 (*reply_len)--;
10644 ctrl->reply_len = sizeof(ctrl->reply);
10645 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10646 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10647 if (err < 0)
10648 return err;
10649
10650 if (ctrl->reply_len > *reply_len)
10651 ctrl->reply_len = *reply_len;
10652
10653 *reply_len = ctrl->reply_len;
10654 memcpy(reply, ctrl->reply, *reply_len);
10655 reply[*reply_len - 1] = 0;
10656 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10657 return 0;
10658}
10659
10660static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10661{
10662 const char *pong = "PONG";
10663 const char *ping = "PING";
10664 char reply[1024];
10665 size_t len = sizeof(reply);
10666 int err;
10667 ULONG s, snum;
10668 INT ret;
10669 BOOL status;
10670
10671 printf("WPA_CTRL: watchdog cb\n");
10672
10673 ret = wifi_getSSIDNumberOfEntries(&snum);
10674 if (ret != RETURN_OK) {
10675 printf("%s: failed to get SSID count", __func__);
10676 return;
10677 }
10678
10679 if (snum > MAX_APS) {
10680 printf("more ssid than supported! %lu\n", snum);
10681 return;
10682 }
10683
10684 for (s = 0; s < snum; s++) {
10685 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10686 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
10687 continue;
10688 }
10689 if (status == false) continue;
10690
10691 memset(reply, 0, sizeof(reply));
10692 len = sizeof(reply);
10693 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10694 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10695 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10696 continue;
10697
10698 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10699 ctrl_close(&wpa_ctrl[s]);
10700 printf("WPA_CTRL: ev_timer_again %lu\n", s);
10701 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10702 }
10703}
10704
10705static int init_wpa()
10706{
10707 int ret = 0, i = 0;
10708 ULONG s, snum;
10709
10710 ret = wifi_getSSIDNumberOfEntries(&snum);
10711 if (ret != RETURN_OK) {
10712 printf("%s: failed to get SSID count", __func__);
10713 return RETURN_ERR;
10714 }
10715
10716 if (snum > MAX_APS) {
10717 printf("more ssid than supported! %lu\n", snum);
10718 return RETURN_ERR;
10719 }
10720
10721 for (s = 0; s < snum; s++) {
10722 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10723 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10724 wpa_ctrl[s].ssid_index = s;
10725 ctrl_enable(&wpa_ctrl[s]);
10726 }
10727
10728 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10729 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10730
10731 initialized = 1;
10732 printf("WPA_CTRL: initialized\n");
10733
10734 return RETURN_OK;
10735}
10736
10737void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10738{
10739 clients_connect_cb = callback_proc;
10740 if (!initialized)
10741 init_wpa();
10742}
10743
10744void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10745{
10746 clients_disconnect_cb = callback_proc;
10747 if (!initialized)
10748 init_wpa();
10749}
10750
10751INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10752{
10753 // TODO Implement me!
10754 return RETURN_ERR;
10755}
10756
10757INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10758{
10759 // TODO Implement me!
10760 return RETURN_ERR;
10761}
10762
10763INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10764{
10765 int i;
10766 char cmd[256];
10767 char channel_numbers_buf[256];
10768 char dfs_state_buf[256];
10769 char line[256];
10770 const char *ptr;
10771
10772 memset(cmd, 0, sizeof(cmd));
10773 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10774 memset(line, 0, sizeof(line));
10775 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10776 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10777
10778 if (radioIndex == 0) { // 2.4G - all allowed
10779 if (outputMapSize < 11) {
10780 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10781 return RETURN_ERR;
10782 }
10783
10784 for (i = 0; i < 11; i++) {
10785 outputMap[i].ch_number = i + 1;
10786 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10787 }
10788
10789 return RETURN_OK;
10790 }
10791
10792 if (radioIndex == 1) { // 5G
10793// Example output of iw list:
10794//
10795// Frequencies:
10796// * 5180 MHz [36] (17.0 dBm)
10797// * 5200 MHz [40] (17.0 dBm)
10798// * 5220 MHz [44] (17.0 dBm)
10799// * 5240 MHz [48] (17.0 dBm)
10800// * 5260 MHz [52] (23.0 dBm) (radar detection)
10801// DFS state: usable (for 78930 sec)
10802// DFS CAC time: 60000 ms
10803// * 5280 MHz [56] (23.0 dBm) (radar detection)
10804// DFS state: usable (for 78930 sec)
10805// DFS CAC time: 60000 ms
10806// * 5300 MHz [60] (23.0 dBm) (radar detection)
10807// DFS state: usable (for 78930 sec)
10808// DFS CAC time: 60000 ms
10809// * 5320 MHz [64] (23.0 dBm) (radar detection)
10810// DFS state: usable (for 78930 sec)
10811// DFS CAC time: 60000 ms
10812// * 5500 MHz [100] (disabled)
10813// * 5520 MHz [104] (disabled)
10814// * 5540 MHz [108] (disabled)
10815// * 5560 MHz [112] (disabled)
10816//
10817// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10818 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10819 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10820 return RETURN_ERR;
10821 }
10822
10823 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10824 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10825 return RETURN_ERR;
10826 }
10827
10828 ptr = channel_numbers_buf;
10829 i = 0;
10830 while (ptr = get_line_from_str_buf(ptr, line)) {
10831 if (i >= outputMapSize) {
10832 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10833 return RETURN_ERR;
10834 }
10835 sscanf(line, "%d", &outputMap[i].ch_number);
10836
10837 memset(cmd, 0, sizeof(cmd));
10838 // Below command should fetch string for DFS state (usable, available or unavailable)
10839 // Example line: "DFS state: usable (for 78930 sec)"
10840 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) {
10841 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10842 return RETURN_ERR;
10843 }
10844
10845 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10846 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10847 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10848 return RETURN_ERR;
10849 }
10850
10851 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10852
10853 if (!strcmp(dfs_state_buf, "usable")) {
10854 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10855 } else if (!strcmp(dfs_state_buf, "available")) {
10856 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10857 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10858 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10859 } else {
10860 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10861 }
10862 i++;
10863 }
10864
10865 return RETURN_OK;
10866 }
10867
10868 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10869 return RETURN_ERR;
10870}
10871
10872INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10873{
10874 // TODO Implement me!
10875 return RETURN_ERR;
10876}
10877
10878INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10879{
10880 return RETURN_OK;
10881}
10882
10883INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10884{
10885 // TODO Implement me!
10886 return RETURN_ERR;
10887}
10888
10889INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10890{
10891 // TODO API refrence Implementaion is present on RPI hal
10892 return RETURN_ERR;
10893}
10894
10895INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10896{
10897 char interface_name[16] = {0};
10898 char cmd[128]={'\0'};
10899 char buf[128]={'\0'};
10900 char *support;
10901 int maximum_tx = 0, current_tx = 0;
10902
10903 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10904 if(txpwr_pcntg == NULL)
10905 return RETURN_ERR;
10906
10907 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10908 return RETURN_ERR;
10909
10910 // Get the maximum tx power of the device
10911 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
10912 _syscmd(cmd, buf, sizeof(buf));
10913 maximum_tx = strtol(buf, NULL, 10);
10914
10915 // Get the current tx power
10916 memset(cmd, 0, sizeof(cmd));
10917 memset(buf, 0, sizeof(buf));
10918 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
10919 _syscmd(cmd, buf, sizeof(buf));
10920 current_tx = strtol(buf, NULL, 10);
10921
10922 // Get the power supported list and find the current power percentage in supported list
10923 memset(buf, 0, sizeof(buf));
10924 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10925 support = strtok(buf, ",");
10926 while(true)
10927 {
10928 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10929 *txpwr_pcntg = 100;
10930 wifi_dbg_printf("current power is not in supported list\n");
10931 return RETURN_OK;
10932 }
10933 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10934 if (tmp == current_tx) {
10935 *txpwr_pcntg = strtol(support, NULL, 10);
10936 break;
10937 }
10938 support = strtok(NULL, ",");
10939 }
10940 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10941 return RETURN_OK;
10942}
10943
10944INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10945{
10946 // TODO precac feature.
10947 struct params params = {0};
10948 char config_file[128] = {0};
10949
10950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10951
10952 params.name = "enable_background_radar";
10953 params.value = enable?"1":"0";
10954 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10955 wifi_hostapdWrite(config_file, &params, 1);
10956 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10957
10958 /* TODO precac feature */
10959
10960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10961 return RETURN_OK;
10962}
10963
10964INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10965{
10966 char config_file[128] = {0};
10967 char buf[64] = {0};
10968
10969 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10970 if (NULL == enable || NULL == precac)
10971 return RETURN_ERR;
10972
10973 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10974 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10975 if (strncmp(enable, "1", 1) == 0)
10976 *enable = true;
10977 else
10978 *enable = false;
10979
10980 /* TODO precac feature */
10981
10982 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10983 return RETURN_OK;
10984}
10985
10986INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10987{
10988 *supported = TRUE;
10989 return RETURN_OK;
10990}
10991
10992INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10993{
10994 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10995 struct params params = {0};
10996 char config_file[64] = {0};
10997 char buf[64] = {0};
10998 unsigned int set_mu_type = 0;
10999 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11000
11001 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11002 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11003
11004 if (strlen(buf) > 0)
11005 set_mu_type = strtol(buf, NULL, 10);
11006
11007 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11008 set_mu_type &= ~0x05; // unset bit 0, 2
11009 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11010 set_mu_type |= 0x01;
11011 set_mu_type &= ~0x04;
11012 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11013 set_mu_type &= ~0x01;
11014 set_mu_type |= 0x04;
11015 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11016 set_mu_type |= 0x05; // set bit 0, 2
11017 }
11018
11019 params.name = "hemu_onoff";
11020 sprintf(buf, "%u", set_mu_type);
11021 params.value = buf;
11022 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11023 wifi_hostapdWrite(config_file, &params, 1);
11024 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11025
11026 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11027 return RETURN_OK;
11028}
11029
11030INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11031{
11032 struct params params={0};
11033 char config_file[64] = {0};
11034 char buf[64] = {0};
11035 unsigned int get_mu_type = 0;
11036
11037 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11038
11039 if (mu_type == NULL)
11040 return RETURN_ERR;
11041
11042 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11043 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11044 get_mu_type = strtol(buf, NULL, 10);
11045
11046 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11047 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11048 else if (get_mu_type & 0x04)
11049 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11050 else if (get_mu_type & 0x01)
11051 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11052 else
11053 *mu_type = WIFI_DL_MU_TYPE_NONE;
11054
11055 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11056 return RETURN_OK;
11057}
11058
11059INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11060{
11061 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11062 struct params params={0};
11063 char config_file[64] = {0};
11064 char buf[64] = {0};
11065 unsigned int set_mu_type = 0;
11066 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11067
11068 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11069 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11070
11071 if (strlen(buf) > 0)
11072 set_mu_type = strtol(buf, NULL, 10);
11073
11074 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11075 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11076 set_mu_type &= ~0x0a;
11077 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11078 set_mu_type |= 0x02;
11079 set_mu_type &= ~0x08;
11080 }
11081
11082 params.name = "hemu_onoff";
11083 sprintf(buf, "%u", set_mu_type);
11084 params.value = buf;
11085 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11086 wifi_hostapdWrite(config_file, &params, 1);
11087 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11088
11089 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11090 return RETURN_OK;
11091}
11092
11093INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11094{
11095 struct params params={0};
11096 char config_file[64] = {0};
11097 char buf[64] = {0};
11098 unsigned int get_mu_type = 0;
11099
11100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11101
11102 if (mu_type == NULL)
11103 return RETURN_ERR;
11104
11105 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11106 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11107
11108 get_mu_type = strtol(buf, NULL, 10);
11109 if (get_mu_type & 0x02)
11110 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11111 else
11112 *mu_type = WIFI_DL_MU_TYPE_NONE;
11113
11114 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11115 return RETURN_OK;
11116}
11117
11118
11119INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11120{
11121 char cmd[128] = {0};
11122 char buf[256] = {0};
11123 char config_file[64] = {0};
11124 char GI[8] = {0};
11125 int mode_map = 0;
11126 FILE *f = NULL;
11127 wifi_band band = band_invalid;
11128
11129 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11130
11131 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11132 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11133 return RETURN_ERR;
11134 }
11135
11136 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11137 band = wifi_index_to_band(radio_index);
11138
11139 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11140 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11141 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11142 _syscmd(cmd, buf, sizeof(buf));
11143 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11144 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11145 if (strstr(buf, "[SHORT-GI-") == NULL) {
11146 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11147 _syscmd(cmd, buf, sizeof(buf));
11148 }
11149 if (band == band_5) {
11150 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11151 if (strstr(buf, "[SHORT-GI-") == NULL) {
11152 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11153 _syscmd(cmd, buf, sizeof(buf));
11154 }
11155 }
11156 }
11157 wifi_reloadAp(radio_index);
11158
11159 if (guard_interval == wifi_guard_interval_400)
11160 strcpy(GI, "0.4");
11161 else if (guard_interval == wifi_guard_interval_800)
11162 strcpy(GI, "0.8");
11163 else if (guard_interval == wifi_guard_interval_1600)
11164 strcpy(GI, "1.6");
11165 else if (guard_interval == wifi_guard_interval_3200)
11166 strcpy(GI, "3.2");
11167 else if (guard_interval == wifi_guard_interval_auto)
11168 strcpy(GI, "auto");
11169 // Record GI for get GI function
11170 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11171 f = fopen(buf, "w");
11172 if (f == NULL)
11173 return RETURN_ERR;
11174 fprintf(f, "%s", GI);
11175 fclose(f);
11176 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11177 return RETURN_OK;
11178}
11179
11180INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11181{
11182 char buf[32] = {0};
11183 char cmd[64] = {0};
11184
11185 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11186
11187 if (guard_interval == NULL)
11188 return RETURN_ERR;
11189
11190 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11191 _syscmd(cmd, buf, sizeof(buf));
11192
11193 if (strncmp(buf, "0.4", 3) == 0)
11194 *guard_interval = wifi_guard_interval_400;
11195 else if (strncmp(buf, "0.8", 3) == 0)
11196 *guard_interval = wifi_guard_interval_800;
11197 else if (strncmp(buf, "1.6", 3) == 0)
11198 *guard_interval = wifi_guard_interval_1600;
11199 else if (strncmp(buf, "3.2", 3) == 0)
11200 *guard_interval = wifi_guard_interval_3200;
11201 else
11202 *guard_interval = wifi_guard_interval_auto;
11203
11204 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11205 return RETURN_OK;
11206}
11207
11208INT wifi_setBSSColor(INT radio_index, UCHAR color)
11209{
11210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11211 struct params params = {0};
11212 char config_file[128] = {0};
11213 char bss_color[4] ={0};
11214
11215 params.name = "he_bss_color";
11216 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11217 params.value = bss_color;
11218 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11219 wifi_hostapdWrite(config_file, &params, 1);
11220 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11221
11222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11223 return RETURN_OK;
11224}
11225
11226INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11227{
11228 char config_file[128] = {0};
11229 char buf[64] = {0};
11230 char temp_output[128] = {'\0'};
11231
11232 wifi_dbg_printf("\nFunc=%s\n", __func__);
11233 if (NULL == color)
11234 return RETURN_ERR;
11235
11236 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11237 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11238
11239 if(strlen(buf) > 0) {
11240 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11241 } else {
11242 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11243 }
11244
11245 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11246 wifi_dbg_printf("\noutput_string=%s\n", color);
11247
11248 return RETURN_OK;
11249}
11250
11251/* multi-psk support */
11252INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11253{
11254 char cmd[256];
11255 char interface_name[16] = {0};
11256
11257 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11258 return RETURN_ERR;
11259
11260 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11261 interface_name,
11262 mac[0],
11263 mac[1],
11264 mac[2],
11265 mac[3],
11266 mac[4],
11267 mac[5]
11268 );
11269 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11270 _syscmd(cmd, key->wifi_keyId, 64);
11271
11272
11273 return RETURN_OK;
11274}
11275
11276INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11277{
11278 char interface_name[16] = {0};
11279 FILE *fd = NULL;
11280 char fname[100];
11281 char cmd[128] = {0};
11282 char out[64] = {0};
11283 wifi_key_multi_psk_t * key = NULL;
11284 if(keysNumber < 0)
11285 return RETURN_ERR;
11286
11287 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11288 fd = fopen(fname, "w");
11289 if (!fd) {
11290 return RETURN_ERR;
11291 }
11292 key= (wifi_key_multi_psk_t *) keys;
11293 for(int i=0; i<keysNumber; ++i, key++) {
11294 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11295 }
11296 fclose(fd);
11297
11298 //reload file
11299 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11300 return RETURN_ERR;
11301 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11302 _syscmd(cmd, out, 64);
11303 return RETURN_OK;
11304}
11305
11306INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11307{
11308 FILE *fd = NULL;
11309 char fname[100];
11310 char * line = NULL;
11311 char * pos = NULL;
11312 size_t len = 0;
11313 ssize_t read = 0;
11314 INT ret = RETURN_OK;
11315 wifi_key_multi_psk_t *keys_it = NULL;
11316
11317 if (keysNumber < 1) {
11318 return RETURN_ERR;
11319 }
11320
11321 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11322 fd = fopen(fname, "r");
11323 if (!fd) {
11324 return RETURN_ERR;
11325 }
11326
11327 if (keys == NULL) {
11328 ret = RETURN_ERR;
11329 goto close;
11330 }
11331
11332 keys_it = keys;
11333 while ((read = getline(&line, &len, fd)) != -1) {
11334 //Strip trailing new line if present
11335 if (read > 0 && line[read-1] == '\n') {
11336 line[read-1] = '\0';
11337 }
11338
11339 if(strcmp(line,"keyid=")) {
11340 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11341 if (!(pos = index(line, ' '))) {
11342 ret = RETURN_ERR;
11343 goto close;
11344 }
11345 pos++;
11346 //Here should be 00:00:00:00:00:00
11347 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11348 printf("Not supported MAC: %s\n", pos);
11349 }
11350 if (!(pos = index(pos, ' '))) {
11351 ret = RETURN_ERR;
11352 goto close;
11353 }
11354 pos++;
11355
11356 //The rest is PSK
11357 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11358 keys_it++;
11359
11360 if(--keysNumber <= 0)
11361 break;
11362 }
11363 }
11364
11365close:
11366 free(line);
11367 fclose(fd);
11368 return ret;
11369}
11370/* end of multi-psk support */
11371
11372INT wifi_setNeighborReports(UINT apIndex,
11373 UINT numNeighborReports,
11374 wifi_NeighborReport_t *neighborReports)
11375{
11376 char cmd[256] = { 0 };
11377 char hex_bssid[13] = { 0 };
11378 char bssid[18] = { 0 };
11379 char nr[256] = { 0 };
11380 char ssid[256];
11381 char hex_ssid[256];
11382 char interface_name[16] = {0};
11383 INT ret;
11384
11385 /*rmeove all neighbors*/
11386 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11387 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11388 return RETURN_ERR;
11389 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);
11390 system(cmd);
11391
11392 for(unsigned int i = 0; i < numNeighborReports; i++)
11393 {
11394 memset(ssid, 0, sizeof(ssid));
11395 ret = wifi_getSSIDName(apIndex, ssid);
11396 if (ret != RETURN_OK)
11397 return RETURN_ERR;
11398
11399 memset(hex_ssid, 0, sizeof(hex_ssid));
11400 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11401 sprintf(hex_ssid + k,"%02x", ssid[j]);
11402
11403 snprintf(hex_bssid, sizeof(hex_bssid),
11404 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11405 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11406 snprintf(bssid, sizeof(bssid),
11407 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11408 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11409
11410 snprintf(nr, sizeof(nr),
11411 "%s" // bssid
11412 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11413 "%02hhx" // operclass
11414 "%02hhx" // channel
11415 "%02hhx", // phy_mode
11416 hex_bssid,
11417 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11418 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11419 neighborReports[i].opClass,
11420 neighborReports[i].channel,
11421 neighborReports[i].phyTable);
11422
11423 snprintf(cmd, sizeof(cmd),
11424 "hostapd_cli set_neighbor "
11425 "%s " // bssid
11426 "ssid=%s " // ssid
11427 "nr=%s " // nr
11428 "-i %s",
11429 bssid,hex_ssid,nr, interface_name);
11430
11431 if (WEXITSTATUS(system(cmd)) != 0)
11432 {
11433 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11434 }
11435 }
11436
11437 return RETURN_OK;
11438}
11439
11440INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11441{
11442 return RETURN_OK;
11443}
11444
11445#ifdef _WIFI_HAL_TEST_
11446int main(int argc,char **argv)
11447{
11448 int index;
11449 INT ret=0;
11450 char buf[1024]="";
11451
11452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11453 if(argc<3)
11454 {
11455 if(argc==2)
11456 {
11457 if(!strcmp(argv[1], "init"))
11458 return wifi_init();
11459 if(!strcmp(argv[1], "reset"))
11460 return wifi_reset();
11461 if(!strcmp(argv[1], "wifi_getHalVersion"))
11462 {
11463 char buffer[64];
11464 if(wifi_getHalVersion(buffer)==RETURN_OK)
11465 printf("Version: %s\n", buffer);
11466 else
11467 printf("Error in wifi_getHalVersion\n");
11468 return RETURN_OK;
11469 }
11470 }
11471 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11472 exit(-1);
11473 }
11474
11475 index = atoi(argv[2]);
11476 if(strstr(argv[1], "wifi_getApName")!=NULL)
11477 {
11478 wifi_getApName(index,buf);
11479 printf("Ap name is %s \n",buf);
11480 return 0;
11481 }
11482 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11483 {
11484 BOOL b = FALSE;
11485 BOOL *output_bool = &b;
11486 wifi_getRadioAutoChannelEnable(index,output_bool);
11487 printf("Channel enabled = %d \n",b);
11488 return 0;
11489 }
11490 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11491 {
11492 wifi_getApWpaEncryptionMode(index,buf);
11493 printf("encryption enabled = %s\n",buf);
11494 return 0;
11495 }
11496 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11497 {
11498 BOOL b = FALSE;
11499 BOOL *output_bool = &b;
11500 wifi_getApSsidAdvertisementEnable(index,output_bool);
11501 printf("advertisment enabled = %d\n",b);
11502 return 0;
11503 }
11504 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11505 {
11506 if(argc <= 3 )
11507 {
11508 printf("Insufficient arguments \n");
11509 exit(-1);
11510 }
11511
11512 char sta[20] = {'\0'};
11513 ULLONG handle= 0;
11514 strcpy(sta,argv[3]);
11515 mac_address_t st;
11516 mac_addr_aton(st,sta);
11517
11518 wifi_associated_dev_tid_stats_t tid_stats;
11519 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11520 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11521 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);
11522 }
11523
11524 if(strstr(argv[1], "getApEnable")!=NULL) {
11525 BOOL enable;
11526 ret=wifi_getApEnable(index, &enable);
11527 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11528 }
11529 else if(strstr(argv[1], "setApEnable")!=NULL) {
11530 BOOL enable = atoi(argv[3]);
11531 ret=wifi_setApEnable(index, enable);
11532 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11533 }
11534 else if(strstr(argv[1], "getApStatus")!=NULL) {
11535 char status[64];
11536 ret=wifi_getApStatus(index, status);
11537 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11538 }
11539 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11540 {
11541 wifi_getSSIDNameStatus(index,buf);
11542 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11543 return 0;
11544 }
11545 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11546 wifi_ssidTrafficStats2_t stats={0};
11547 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11548 printf("%s %d: returns %d\n", argv[1], index, ret);
11549 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11550 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11551 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11552 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11553 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11554 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11555 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11556 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11557 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11558 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11559 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11560 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11561 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11562 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11563 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11564 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11565 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11566 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11567 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11568 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11569 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11570 }
11571 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11572 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11573 UINT array_size=0;
11574 UINT i=0;
11575 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11576 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11577 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11578 printf(" neighbor %d:\n", i);
11579 printf(" ap_SSID =%s\n", pt->ap_SSID);
11580 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11581 printf(" ap_Mode =%s\n", pt->ap_Mode);
11582 printf(" ap_Channel =%d\n", pt->ap_Channel);
11583 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11584 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11585 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11586 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11587 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11588 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11589 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11590 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11591 printf(" ap_Noise =%d\n", pt->ap_Noise);
11592 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11593 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11594 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11595 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11596 }
11597 if(neighbor_ap_array)
11598 free(neighbor_ap_array); //make sure to free the list
11599 }
11600 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11601 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11602 UINT array_size=0;
11603 UINT i=0;
11604 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11605 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11606 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11607 printf(" associated_dev %d:\n", i);
11608 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11609 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11610 printf(" cli_SNR =%d\n", pt->cli_SNR);
11611 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11612 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11613 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11614 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11615 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11616 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11617 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11618 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11619 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11620 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11621 }
11622 if(associated_dev_array)
11623 free(associated_dev_array); //make sure to free the list
11624 }
11625
11626 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11627 {
11628#define MAX_ARRAY_SIZE 64
11629 int i, array_size;
11630 char *p, *ch_str;
11631 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11632
11633 if(argc != 5)
11634 {
11635 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11636 exit(-1);
11637 }
11638 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11639
11640 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11641 {
11642 strtok_r(ch_str, ",", &p);
11643 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11644 }
11645 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11646 if(!array_size)
11647 array_size=1;//Need to print current channel statistics
11648 for(i=0; i<array_size; i++)
11649 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11650 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11651 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11652 input_output_channelStats_array[i].ch_number,\
11653 input_output_channelStats_array[i].ch_noise,\
11654 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11655 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11656 input_output_channelStats_array[i].ch_utilization_busy,\
11657 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11658 input_output_channelStats_array[i].ch_utilization_total);
11659 }
11660
11661 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11662 {
11663 if(argc <= 3 )
11664 {
11665 printf("Insufficient arguments \n");
11666 exit(-1);
11667 }
11668 char mac_addr[20] = {'\0'};
11669 wifi_device_t output_struct;
11670 int dev_index = atoi(argv[3]);
11671
11672 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11673 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11674 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);
11675 }
11676
11677 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11678 {
11679 if (argc <= 3)
11680 {
11681 printf("Insufficient arguments\n");
11682 exit(-1);
11683 }
11684 char args[256];
11685 wifi_NeighborReport_t *neighborReports;
11686
11687 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11688 if (!neighborReports)
11689 {
11690 printf("Failed to allocate memory");
11691 exit(-1);
11692 }
11693
11694 for (int i = 3; i < argc; ++i)
11695 {
11696 char *val;
11697 int j = 0;
11698 memset(args, 0, sizeof(args));
11699 strncpy(args, argv[i], sizeof(args));
11700 val = strtok(args, ";");
11701 while (val != NULL)
11702 {
11703 if (j == 0)
11704 {
11705 mac_addr_aton(neighborReports[i - 3].bssid, val);
11706 } else if (j == 1)
11707 {
11708 neighborReports[i - 3].info = strtol(val, NULL, 16);
11709 } else if (j == 2)
11710 {
11711 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11712 } else if (j == 3)
11713 {
11714 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11715 } else if (j == 4)
11716 {
11717 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11718 } else {
11719 printf("Insufficient arguments]n\n");
11720 exit(-1);
11721 }
11722 val = strtok(NULL, ";");
11723 j++;
11724 }
11725 }
11726
11727 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11728 if (ret != RETURN_OK)
11729 {
11730 printf("wifi_setNeighborReports ret = %d", ret);
11731 exit(-1);
11732 }
11733 }
11734 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11735 {
11736 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11737 printf("%s.\n", buf);
11738 else
11739 printf("Error returned\n");
11740 }
11741 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11742 {
11743 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11744 printf("%s.\n", buf);
11745 else
11746 printf("Error returned\n");
11747 }
11748 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11749 {
11750 if (argc <= 2)
11751 {
11752 printf("Insufficient arguments\n");
11753 exit(-1);
11754 }
11755 char buf[64]= {'\0'};
11756 wifi_getRadioOperatingChannelBandwidth(index,buf);
11757 printf("Current bandwidth is %s \n",buf);
11758 return 0;
11759 }
11760 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11761 {
11762 if (argc <= 5)
11763 {
11764 printf("Insufficient arguments\n");
11765 exit(-1);
11766 }
11767 UINT channel = atoi(argv[3]);
11768 UINT width = atoi(argv[4]);
11769 UINT beacon = atoi(argv[5]);
11770 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11771 printf("Result = %d", ret);
11772 }
11773
11774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11775 return 0;
11776}
11777
11778#endif
11779
11780#ifdef WIFI_HAL_VERSION_3
11781
11782INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11783{
11784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11785 if (bitMap & WIFI_BITRATE_1MBPS)
11786 strcat(BasicRate, "1,");
11787 if (bitMap & WIFI_BITRATE_2MBPS)
11788 strcat(BasicRate, "2,");
11789 if (bitMap & WIFI_BITRATE_5_5MBPS)
11790 strcat(BasicRate, "5.5,");
11791 if (bitMap & WIFI_BITRATE_6MBPS)
11792 strcat(BasicRate, "6,");
11793 if (bitMap & WIFI_BITRATE_9MBPS)
11794 strcat(BasicRate, "9,");
11795 if (bitMap & WIFI_BITRATE_11MBPS)
11796 strcat(BasicRate, "11,");
11797 if (bitMap & WIFI_BITRATE_12MBPS)
11798 strcat(BasicRate, "12,");
11799 if (bitMap & WIFI_BITRATE_18MBPS)
11800 strcat(BasicRate, "18,");
11801 if (bitMap & WIFI_BITRATE_24MBPS)
11802 strcat(BasicRate, "24,");
11803 if (bitMap & WIFI_BITRATE_36MBPS)
11804 strcat(BasicRate, "36,");
11805 if (bitMap & WIFI_BITRATE_48MBPS)
11806 strcat(BasicRate, "48,");
11807 if (bitMap & WIFI_BITRATE_54MBPS)
11808 strcat(BasicRate, "54,");
11809 if (strlen(BasicRate) != 0) // remove last comma
11810 BasicRate[strlen(BasicRate) - 1] = '\0';
11811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11812 return RETURN_OK;
11813}
11814
11815INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11816{
11817 UINT BitMap = 0;
11818 char *rate;
11819
11820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11821 rate = strtok(BasicRatesList, ",");
11822 while(rate != NULL)
11823 {
11824 if (strcmp(rate, "1") == 0)
11825 BitMap |= WIFI_BITRATE_1MBPS;
11826 else if (strcmp(rate, "2") == 0)
11827 BitMap |= WIFI_BITRATE_2MBPS;
11828 else if (strcmp(rate, "5.5") == 0)
11829 BitMap |= WIFI_BITRATE_5_5MBPS;
11830 else if (strcmp(rate, "6") == 0)
11831 BitMap |= WIFI_BITRATE_6MBPS;
11832 else if (strcmp(rate, "9") == 0)
11833 BitMap |= WIFI_BITRATE_9MBPS;
11834 else if (strcmp(rate, "11") == 0)
11835 BitMap |= WIFI_BITRATE_11MBPS;
11836 else if (strcmp(rate, "12") == 0)
11837 BitMap |= WIFI_BITRATE_12MBPS;
11838 else if (strcmp(rate, "18") == 0)
11839 BitMap |= WIFI_BITRATE_18MBPS;
11840 else if (strcmp(rate, "24") == 0)
11841 BitMap |= WIFI_BITRATE_24MBPS;
11842 else if (strcmp(rate, "36") == 0)
11843 BitMap |= WIFI_BITRATE_36MBPS;
11844 else if (strcmp(rate, "48") == 0)
11845 BitMap |= WIFI_BITRATE_48MBPS;
11846 else if (strcmp(rate, "54") == 0)
11847 BitMap |= WIFI_BITRATE_54MBPS;
11848 rate = strtok(NULL, ",");
11849 }
11850 *basicRateBitMap = BitMap;
11851 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11852 return RETURN_OK;
11853}
11854
11855// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
11856INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11857{
11858 char buf[128] = {0};
11859 char cmd[128] = {0};
11860 char config_file[64] = {0};
11861 int bandwidth;
11862 int set_mode = 0;
11863 wifi_radio_operationParam_t current_param;
11864
11865 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11866
11867 multiple_set = TRUE;
11868 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11869 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11870 return RETURN_ERR;
11871 }
11872 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11873 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11874 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11875 return RETURN_ERR;
11876 }
11877 }
11878
11879 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11880 bandwidth = 20;
11881 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11882 bandwidth = 40;
11883 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11884 bandwidth = 80;
11885 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11886 bandwidth = 160;
11887 if (operationParam->autoChannelEnabled){
11888 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11889 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11890 return RETURN_ERR;
11891 }
11892 }else{
11893 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11894 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11895 return RETURN_ERR;
11896 }
11897 }
11898
11899 if (current_param.variant != operationParam->variant) {
11900 // Two different definition bit map, so need to check every bit.
11901 if (operationParam->variant & WIFI_80211_VARIANT_A)
11902 set_mode |= WIFI_MODE_A;
11903 if (operationParam->variant & WIFI_80211_VARIANT_B)
11904 set_mode |= WIFI_MODE_B;
11905 if (operationParam->variant & WIFI_80211_VARIANT_G)
11906 set_mode |= WIFI_MODE_G;
11907 if (operationParam->variant & WIFI_80211_VARIANT_N)
11908 set_mode |= WIFI_MODE_N;
11909 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11910 set_mode |= WIFI_MODE_AC;
11911 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11912 set_mode |= WIFI_MODE_AX;
11913 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11914 memset(buf, 0, sizeof(buf));
11915 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11916 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11917 return RETURN_ERR;
11918 }
11919 }
11920 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11921 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11922 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11923 return RETURN_ERR;
11924 }
11925 }
11926 if (current_param.beaconInterval != operationParam->beaconInterval) {
11927 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11928 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11929 return RETURN_ERR;
11930 }
11931 }
11932 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11933 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11934 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11935 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11936 return RETURN_ERR;
11937 }
11938 }
11939 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11940 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11941 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11942 return RETURN_ERR;
11943 }
11944 }
11945 if (current_param.guardInterval != operationParam->guardInterval) {
11946 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11947 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11948 return RETURN_ERR;
11949 }
11950 }
11951 if (current_param.transmitPower != operationParam->transmitPower) {
11952 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11953 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11954 return RETURN_ERR;
11955 }
11956 }
11957 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11958 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11959 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11960 return RETURN_ERR;
11961 }
11962 }
11963 if (current_param.obssCoex != operationParam->obssCoex) {
11964 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11965 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11966 return RETURN_ERR;
11967 }
11968 }
11969 if (current_param.stbcEnable != operationParam->stbcEnable) {
11970 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11971 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11972 return RETURN_ERR;
11973 }
11974 }
11975 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11976 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11977 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11978 return RETURN_ERR;
11979 }
11980 }
11981
11982 // if enable is true, then restart the radio
11983 wifi_setRadioEnable(index, FALSE);
11984 if (operationParam->enable == TRUE)
11985 wifi_setRadioEnable(index, TRUE);
11986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11987
11988 return RETURN_OK;
11989}
11990
11991INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11992{
11993 char band[64] = {0};
11994 char buf[256] = {0};
11995 char config_file[64] = {0};
11996 char cmd[128] = {0};
11997 int ret = RETURN_ERR;
11998 int mode = 0;
11999 ULONG channel = 0;
12000 BOOL enabled = FALSE;
12001
12002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12003 printf("Entering %s index = %d\n", __func__, (int)index);
12004
12005 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12006 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12007 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12008 {
12009 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12010 return RETURN_ERR;
12011 }
12012 operationParam->enable = enabled;
12013
12014 memset(band, 0, sizeof(band));
12015 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12016 {
12017 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12018 return RETURN_ERR;
12019 }
12020
12021 if (!strcmp(band, "2.4GHz"))
12022 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12023 else if (!strcmp(band, "5GHz"))
12024 operationParam->band = WIFI_FREQUENCY_5_BAND;
12025 else if (!strcmp(band, "6GHz"))
12026 operationParam->band = WIFI_FREQUENCY_6_BAND;
12027 else
12028 {
12029 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12030 band);
12031 }
12032
12033 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12034 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12035 operationParam->channel = 0;
12036 operationParam->autoChannelEnabled = TRUE;
12037 } else {
12038 operationParam->channel = strtol(buf, NULL, 10);
12039 operationParam->autoChannelEnabled = FALSE;
12040 }
12041
12042 memset(buf, 0, sizeof(buf));
12043 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12044 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12045 return RETURN_ERR;
12046 }
12047 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12048 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12049 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12050 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12051 else
12052 {
12053 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12054 return false;
12055 }
12056
12057 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12058 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12059 return RETURN_ERR;
12060 }
12061 // Two different definition bit map, so need to check every bit.
12062 if (mode & WIFI_MODE_A)
12063 operationParam->variant |= WIFI_80211_VARIANT_A;
12064 if (mode & WIFI_MODE_B)
12065 operationParam->variant |= WIFI_80211_VARIANT_B;
12066 if (mode & WIFI_MODE_G)
12067 operationParam->variant |= WIFI_80211_VARIANT_G;
12068 if (mode & WIFI_MODE_N)
12069 operationParam->variant |= WIFI_80211_VARIANT_N;
12070 if (mode & WIFI_MODE_AC)
12071 operationParam->variant |= WIFI_80211_VARIANT_AC;
12072 if (mode & WIFI_MODE_AX)
12073 operationParam->variant |= WIFI_80211_VARIANT_AX;
12074 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12075 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12076 return RETURN_ERR;
12077 }
12078 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12079 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12080 return RETURN_ERR;
12081 }
12082 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12083 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12084 return RETURN_ERR;
12085 }
12086
12087 memset(buf, 0, sizeof(buf));
12088 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12089 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12090 return RETURN_ERR;
12091 }
12092 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12093
12094 memset(buf, 0, sizeof(buf));
12095 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12096 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12097 return RETURN_ERR;
12098 }
12099 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12100
12101 memset(buf, 0, sizeof(buf));
12102 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12103 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12104
12105 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12106 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12107 return RETURN_ERR;
12108 }
12109 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12110 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12111 return RETURN_ERR;
12112 }
12113
12114 memset(buf, 0, sizeof(buf));
12115 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12116 if (strcmp(buf, "-1") == 0) {
12117 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12118 operationParam->ctsProtection = FALSE;
12119 } else {
12120 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12121 operationParam->ctsProtection = TRUE;
12122 }
12123
12124 memset(buf, 0, sizeof(buf));
12125 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12126 if (strcmp(buf, "0") == 0)
12127 operationParam->obssCoex = FALSE;
12128 else
12129 operationParam->obssCoex = TRUE;
12130
12131 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12132 _syscmd(cmd, buf, sizeof(buf));
12133 if (strlen(buf) != 0)
12134 operationParam->stbcEnable = TRUE;
12135 else
12136 operationParam->stbcEnable = FALSE;
12137
12138 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12139 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12140 return RETURN_ERR;
12141 }
12142
12143 // Below value is hardcoded
12144
12145 operationParam->numSecondaryChannels = 0;
12146 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12147 operationParam->channelSecondary[i] = 0;
12148 }
12149 operationParam->csa_beacon_count = 15;
12150 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12151
12152 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12153 return RETURN_OK;
12154}
12155
12156static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12157{
12158 int max_radio_num = 0;
12159
12160 wifi_getMaxRadioNumber(&max_radio_num);
12161 if (radioIndex >= max_radio_num) {
12162 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12163 return RETURN_ERR;
12164 }
12165
12166 return (arrayIndex * max_radio_num) + radioIndex;
12167}
12168
12169wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12170 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12171 return WIFI_BITRATE_1MBPS;
12172 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12173 return WIFI_BITRATE_2MBPS;
12174 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12175 return WIFI_BITRATE_5_5MBPS;
12176 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12177 return WIFI_BITRATE_6MBPS;
12178 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12179 return WIFI_BITRATE_9MBPS;
12180 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12181 return WIFI_BITRATE_11MBPS;
12182 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12183 return WIFI_BITRATE_12MBPS;
12184 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12185 return WIFI_BITRATE_18MBPS;
12186 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12187 return WIFI_BITRATE_24MBPS;
12188 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12189 return WIFI_BITRATE_36MBPS;
12190 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12191 return WIFI_BITRATE_48MBPS;
12192 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12193 return WIFI_BITRATE_54MBPS;
12194 return WIFI_BITRATE_DEFAULT;
12195}
12196
12197INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12198{
12199 if (beacon == WIFI_BITRATE_1MBPS)
12200 strcpy(beacon_str, "1Mbps");
12201 else if (beacon == WIFI_BITRATE_2MBPS)
12202 strcpy(beacon_str, "2Mbps");
12203 else if (beacon == WIFI_BITRATE_5_5MBPS)
12204 strcpy(beacon_str, "5.5Mbps");
12205 else if (beacon == WIFI_BITRATE_6MBPS)
12206 strcpy(beacon_str, "6Mbps");
12207 else if (beacon == WIFI_BITRATE_9MBPS)
12208 strcpy(beacon_str, "9Mbps");
12209 else if (beacon == WIFI_BITRATE_11MBPS)
12210 strcpy(beacon_str, "11Mbps");
12211 else if (beacon == WIFI_BITRATE_12MBPS)
12212 strcpy(beacon_str, "12Mbps");
12213 else if (beacon == WIFI_BITRATE_18MBPS)
12214 strcpy(beacon_str, "18Mbps");
12215 else if (beacon == WIFI_BITRATE_24MBPS)
12216 strcpy(beacon_str, "24Mbps");
12217 else if (beacon == WIFI_BITRATE_36MBPS)
12218 strcpy(beacon_str, "36Mbps");
12219 else if (beacon == WIFI_BITRATE_48MBPS)
12220 strcpy(beacon_str, "48Mbps");
12221 else if (beacon == WIFI_BITRATE_54MBPS)
12222 strcpy(beacon_str, "54Mbps");
12223 return RETURN_OK;
12224}
12225
12226INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12227{
12228 INT mode = 0;
12229 INT ret = -1;
12230 INT output = 0;
12231 int i = 0;
12232 int vap_index = 0;
12233 BOOL enabled = FALSE;
12234 char buf[256] = {0};
12235 wifi_vap_security_t security = {0};
12236 map->num_vaps = 5; // Hardcoded
12237
12238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12239 printf("Entering %s index = %d\n", __func__, (int)index);
12240
12241 for (i = 0; i < 5; i++)
12242 {
12243 map->vap_array[i].radio_index = index;
12244
12245 vap_index = array_index_to_vap_index(index, i);
12246 if (vap_index < 0)
12247 return RETURN_ERR;
12248
12249 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12250
12251 map->vap_array[i].vap_index = vap_index;
12252
12253 memset(buf, 0, sizeof(buf));
12254 ret = wifi_getApName(vap_index, buf);
12255 if (ret != RETURN_OK) {
12256 printf("%s: wifi_getApName return error\n", __func__);
12257 return RETURN_ERR;
12258 }
12259 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12260
12261 memset(buf, 0, sizeof(buf));
12262 ret = wifi_getSSIDName(vap_index, buf);
12263 if (ret != RETURN_OK) {
12264 printf("%s: wifi_getSSIDName return error\n", __func__);
12265 return RETURN_ERR;
12266 }
12267 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12268
12269 ret = wifi_getSSIDEnable(vap_index, &enabled);
12270 if (ret != RETURN_OK) {
12271 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12272 return RETURN_ERR;
12273 }
12274 map->vap_array[i].u.bss_info.enabled = enabled;
12275
12276 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12277 if (ret != RETURN_OK) {
12278 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12279 return RETURN_ERR;
12280 }
12281 map->vap_array[i].u.bss_info.showSsid = enabled;
12282
12283 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12284 if (ret != RETURN_OK) {
12285 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12286 return RETURN_ERR;
12287 }
12288 map->vap_array[i].u.bss_info.isolation = enabled;
12289
12290 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12291 if (ret != RETURN_OK) {
12292 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12293 return RETURN_ERR;
12294 }
12295 map->vap_array[i].u.bss_info.bssMaxSta = output;
12296
12297 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12298 if (ret != RETURN_OK) {
12299 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12300 return RETURN_ERR;
12301 }
12302 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12303
12304 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12305 if (ret != RETURN_OK) {
12306 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12307 return RETURN_ERR;
12308 }
12309 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12310
12311 ret = wifi_getApSecurity(vap_index, &security);
12312 if (ret != RETURN_OK) {
12313 printf("%s: wifi_getApSecurity return error\n", __func__);
12314 return RETURN_ERR;
12315 }
12316 map->vap_array[i].u.bss_info.security = security;
12317
12318 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12319 if (ret != RETURN_OK) {
12320 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12321 return RETURN_ERR;
12322 }
12323 if (mode == 0)
12324 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12325 else
12326 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12327 if (mode == 1)
12328 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12329 else if (mode == 2)
12330 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12331
12332 ret = wifi_getApWmmEnable(vap_index, &enabled);
12333 if (ret != RETURN_OK) {
12334 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12335 return RETURN_ERR;
12336 }
12337 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12338
12339 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12340 if (ret != RETURN_OK) {
12341 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12342 return RETURN_ERR;
12343 }
12344 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12345
12346 memset(buf, 0, sizeof(buf));
12347 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12348 if (ret != RETURN_OK) {
12349 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12350 return RETURN_ERR;
12351 }
12352 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12353
12354 memset(buf, 0, sizeof(buf));
12355 ret = wifi_getBaseBSSID(vap_index, buf);
12356 if (ret != RETURN_OK) {
12357 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12358 return RETURN_ERR;
12359 }
12360 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12361 &map->vap_array[i].u.bss_info.bssid[0],
12362 &map->vap_array[i].u.bss_info.bssid[1],
12363 &map->vap_array[i].u.bss_info.bssid[2],
12364 &map->vap_array[i].u.bss_info.bssid[3],
12365 &map->vap_array[i].u.bss_info.bssid[4],
12366 &map->vap_array[i].u.bss_info.bssid[5]);
12367 // 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]);
12368
12369 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12370 if (ret != RETURN_OK) {
12371 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12372 return RETURN_ERR;
12373 }
12374 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12375
12376 // TODO: wps, noack
12377 }
12378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12379 return RETURN_OK;
12380}
12381
12382void checkVapStatus(int apIndex, bool *enable)
12383{
12384 char if_name[16] = {0};
12385 char cmd[128] = {0};
12386 char buf[128] = {0};
12387
12388 *enable = FALSE;
12389 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12390 return;
12391
12392 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12393 _syscmd(cmd, buf, sizeof(buf));
12394 if (strlen(buf) > 0)
12395 *enable = TRUE;
12396 return;
12397}
12398
12399static int prepareInterface(UINT apIndex, char *new_interface)
12400{
12401 char cur_interface[16] = {0};
12402 char config_file[128] = {0};
12403 char cmd[128] = {0};
12404 char buf[16] = {0};
12405 int max_radio_num = 0;
12406 int radioIndex = -1;
12407 int phyIndex = -1;
12408
12409 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12410 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12411
12412 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12413 wifi_getMaxRadioNumber(&max_radio_num);
12414 radioIndex = apIndex % max_radio_num;
12415 phyIndex = radio_index_to_phy(radioIndex);
12416 // disable and del old interface, then add new interface
12417 wifi_setApEnable(apIndex, FALSE);
12418 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12419 _syscmd(cmd, buf, sizeof(buf));
12420 }
12421 // update the vap status file
12422 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12423 _syscmd(cmd, buf, sizeof(buf));
12424 return RETURN_OK;
12425}
12426
12427INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12428{
12429 char interface_name[16] = {0};
12430 unsigned int i;
12431 wifi_vap_info_t *vap_info = NULL;
12432 int acl_mode;
12433 int ret = 0;
12434 char *sec_str = NULL;
12435 char buf[256] = {0};
12436 char cmd[128] = {0};
12437 char config_file[64] = {0};
12438 char bssid[32] = {0};
12439 char psk_file[64] = {0};
12440 bool enable = FALSE;
12441
12442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12443 printf("Entering %s index = %d\n", __func__, (int)index);
12444 for (i = 0; i < map->num_vaps; i++)
12445 {
12446 multiple_set = TRUE;
12447 vap_info = &map->vap_array[i];
12448
12449 // Check vap status file to enable multiple ap if the system boot.
12450 checkVapStatus(vap_info->vap_index, &enable);
12451 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
12452 continue;
12453
12454 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12455
12456 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12457 enable = FALSE;
12458
12459 // multi-ap first up need to copy current radio config
12460 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
12461 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12462 _syscmd(cmd, buf, sizeof(buf));
12463 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12464 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12465 } else {
12466 // Check whether the interface name is valid or this ap change it.
12467 int apIndex = -1;
12468 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12469 if (apIndex != -1 && apIndex != vap_info->vap_index)
12470 continue;
12471 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12472 }
12473
12474 struct params params[3];
12475 params[0].name = "interface";
12476 params[0].value = vap_info->vap_name;
12477 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12478 params[1].name = "bssid";
12479 params[1].value = bssid;
12480 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
12481 params[2].name = "wpa_psk_file";
12482 params[2].value = psk_file;
12483
12484 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12485 wifi_hostapdWrite(config_file, params, 3);
12486
12487 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12488 _syscmd(cmd, buf, sizeof(buf));
12489
12490 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12491 if (ret != RETURN_OK) {
12492 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12493 return RETURN_ERR;
12494 }
12495
12496 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12497 if (ret != RETURN_OK) {
12498 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12499 return RETURN_ERR;
12500 }
12501
12502 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12503 if (ret != RETURN_OK) {
12504 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12505 return RETURN_ERR;
12506 }
12507
12508 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12509 if (ret != RETURN_OK) {
12510 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12511 return RETURN_ERR;
12512 }
12513
12514 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12515 if (ret != RETURN_OK) {
12516 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12517 return RETURN_ERR;
12518 }
12519
12520 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12521 if (ret != RETURN_OK) {
12522 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12523 return RETURN_ERR;
12524 }
12525
12526 if (vap_info->u.bss_info.mac_filter_enable == false){
12527 acl_mode = 0;
12528 }else {
12529 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
12530 acl_mode = 2;
12531 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12532 _syscmd(cmd, buf, sizeof(buf));
12533 }else{
12534 acl_mode = 1;
12535 }
12536 }
12537
12538 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12539 if (ret != RETURN_OK) {
12540 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12541 return RETURN_ERR;
12542 }
12543
12544 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12545 if (ret != RETURN_OK) {
12546 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12547 return RETURN_ERR;
12548 }
12549
12550 memset(buf, 0, sizeof(buf));
12551 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12552 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12553 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12554 if (ret != RETURN_OK) {
12555 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12556 return RETURN_ERR;
12557 }
12558
12559 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12560 if (ret != RETURN_OK) {
12561 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12562 return RETURN_ERR;
12563 }
12564
developer72fb0bb2023-01-11 09:46:29 +080012565 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12566 if (ret != RETURN_OK) {
12567 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12568 return RETURN_ERR;
12569 }
12570
developer23e71282023-01-18 10:25:19 +080012571 wifi_setApEnable(vap_info->vap_index, FALSE);
12572 wifi_setApEnable(vap_info->vap_index, TRUE);
12573 multiple_set = FALSE;
12574
12575 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080012576 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12577 if (ret != RETURN_OK) {
12578 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12579 return RETURN_ERR;
12580 }
12581
12582 // TODO mgmtPowerControl, interworking, wps
12583 }
12584 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12585 return RETURN_OK;
12586}
12587
12588int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12589{
12590 char *token, *next;
12591 const char s[2] = ",";
12592 int count =0;
12593
12594 /* get the first token */
12595 token = strtok_r(pchannels, s, &next);
12596
12597 /* walk through other tokens */
12598 while( token != NULL && count < MAX_CHANNELS) {
12599 chlistptr->channels_list[count++] = atoi(token);
12600 token = strtok_r(NULL, s, &next);
12601 }
12602
12603 return count;
12604}
12605
12606static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12607{
12608 INT status;
12609 wifi_channels_list_t *chlistp;
12610 CHAR output_string[64];
12611 CHAR pchannels[128];
12612 CHAR interface_name[16] = {0};
12613 wifi_band band;
12614
12615 if(rcap == NULL)
12616 {
12617 return RETURN_ERR;
12618 }
12619
12620 rcap->numSupportedFreqBand = 1;
12621 band = wifi_index_to_band(radioIndex);
12622
12623 if (band == band_2_4)
12624 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12625 else if (band == band_5)
12626 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12627 else if (band == band_6)
12628 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
12629
12630 chlistp = &(rcap->channel_list[0]);
12631 memset(pchannels, 0, sizeof(pchannels));
12632
12633 /* possible number of radio channels */
12634 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12635 {
12636 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12637 }
12638 /* Number of channels and list*/
12639 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12640
12641 /* autoChannelSupported */
12642 /* always ON with wifi_getRadioAutoChannelSupported */
12643 rcap->autoChannelSupported = TRUE;
12644
12645 /* DCSSupported */
12646 /* always ON with wifi_getRadioDCSSupported */
12647 rcap->DCSSupported = TRUE;
12648
12649 /* zeroDFSSupported - TBD */
12650 rcap->zeroDFSSupported = FALSE;
12651
12652 /* Supported Country List*/
12653 memset(output_string, 0, sizeof(output_string));
12654 status = wifi_getRadioCountryCode(radioIndex, output_string);
12655 if( status != 0 ) {
12656 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12657 return RETURN_ERR;
12658 } else {
12659 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12660 }
12661 if(!strcmp(output_string,"US")){
12662 rcap->countrySupported[0] = wifi_countrycode_US;
12663 rcap->countrySupported[1] = wifi_countrycode_CA;
12664 } else if (!strcmp(output_string,"CA")) {
12665 rcap->countrySupported[0] = wifi_countrycode_CA;
12666 rcap->countrySupported[1] = wifi_countrycode_US;
12667 } else {
12668 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12669 }
12670
12671 rcap->numcountrySupported = 2;
12672
12673 /* csi */
12674 rcap->csi.maxDevices = 8;
12675 rcap->csi.soudingFrameSupported = TRUE;
12676
12677 wifi_GetInterfaceName(radioIndex, interface_name);
12678 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
12679
12680 /* channelWidth - all supported bandwidths */
12681 int i=0;
12682 rcap->channelWidth[i] = 0;
12683 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12684 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12685 WIFI_CHANNELBANDWIDTH_40MHZ);
12686
12687 }
12688 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
12689 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
12690 WIFI_CHANNELBANDWIDTH_40MHZ |
12691 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
12692 }
12693
12694
12695 /* mode - all supported variants */
12696 // rcap->mode[i] = WIFI_80211_VARIANT_H;
12697 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
12698 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
12699 }
12700 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
12701 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
12702 }
12703 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
12704 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
12705 }
12706 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
12707 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
12708
12709 /* supportedBitRate - all supported bitrates */
12710 rcap->supportedBitRate[i] = 0;
12711 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
12712 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12713 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
12714 }
12715 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
12716 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
12717 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
12718 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
12719 }
12720
12721
12722 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
12723 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
12724 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
12725 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
12726 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
12727 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
12728 rcap->cipherSupported = 0;
12729 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
12730 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
12731
12732 return RETURN_OK;
12733}
12734
12735INT wifi_getHalCapability(wifi_hal_capability_t *cap)
12736{
12737 INT status = 0, radioIndex = 0;
12738 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
12739 int iter = 0;
12740 unsigned int j = 0;
12741 int max_num_radios;
12742 wifi_interface_name_idex_map_t *iface_info = NULL;
12743
12744 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12745
12746 memset(cap, 0, sizeof(wifi_hal_capability_t));
12747
12748 /* version */
12749 cap->version.major = WIFI_HAL_MAJOR_VERSION;
12750 cap->version.minor = WIFI_HAL_MINOR_VERSION;
12751
12752 /* number of radios platform property */
12753 wifi_getMaxRadioNumber(&max_num_radios);
12754 cap->wifi_prop.numRadios = max_num_radios;
12755
12756 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
12757 {
12758 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
12759 if (status != 0) {
12760 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
12761 return RETURN_ERR;
12762 }
12763
12764 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
12765 {
12766 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
12767 {
12768 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
12769 return RETURN_ERR;
12770 }
12771 iface_info = &cap->wifi_prop.interface_map[iter];
12772 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
12773 iface_info->rdk_radio_index = radioIndex;
12774 memset(output, 0, sizeof(output));
12775 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
12776 {
12777 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
12778 }
12779 // TODO: bridge name
12780 // TODO: vlan id
12781 // TODO: primary
12782 iface_info->index = array_index_to_vap_index(radioIndex, j);
12783 memset(output, 0, sizeof(output));
12784 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
12785 {
12786 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
12787 }
12788 iter++;
12789 }
12790 }
12791
12792 cap->BandSteeringSupported = FALSE;
12793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12794 return RETURN_OK;
12795}
12796
12797INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
12798{
12799 struct params h_config={0};
12800 char config_file[64] = {0};
12801
12802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12803
12804 h_config.name = "okc";
12805 h_config.value = okc_enable?"1":"0";
12806
12807 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12808 wifi_hostapdWrite(config_file, &h_config, 1);
12809 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12810
12811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12812 return RETURN_OK;
12813}
12814
12815INT wifi_setSAEMFP(int ap_index, BOOL enable)
12816{
12817 struct params h_config={0};
12818 char config_file[64] = {0};
12819 char buf[128] = {0};
12820
12821 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12822
12823 h_config.name = "sae_require_mfp";
12824 h_config.value = enable?"1":"0";
12825
12826 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12827 wifi_hostapdWrite(config_file, &h_config, 1);
12828 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12829
12830 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12831 return RETURN_OK;
12832}
12833
12834INT wifi_setSAEpwe(int ap_index, int sae_pwe)
12835{
12836 struct params h_config={0};
12837 char config_file[64] = {0};
12838 char buf[128] = {0};
12839
12840 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12841
12842 h_config.name = "sae_pwe";
12843 snprintf(buf, sizeof(buf), "%d", sae_pwe);
12844 h_config.value = buf;
12845
12846 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12847 wifi_hostapdWrite(config_file, &h_config, 1);
12848 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12849
12850 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12851 return RETURN_OK;
12852}
12853
12854INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
12855{
12856 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
12857 struct params h_config={0};
12858 char config_file[64] = {0};
12859
12860 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
12861
12862 h_config.name = "wpa_disable_eapol_key_retries";
12863 h_config.value = disable_EAPOL_retries?"1":"0";
12864
12865 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
12866 wifi_hostapdWrite(config_file, &h_config, 1);
12867 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
12868
12869 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
12870 return RETURN_OK;
12871}
12872
12873INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
12874{
12875 char buf[128] = {0};
12876 char config_file[128] = {0};
12877 char password[64] = {0};
12878 char mfp[32] = {0};
12879 char wpa_mode[32] = {0};
12880 BOOL okc_enable = FALSE;
12881 BOOL sae_MFP = FALSE;
12882 BOOL disable_EAPOL_retries = TRUE;
12883 int sae_pwe = 0;
12884 struct params params = {0};
12885 wifi_band band = band_invalid;
12886
12887 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12888
12889 multiple_set = TRUE;
12890 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12891 if (security->mode == wifi_security_mode_none) {
12892 strcpy(wpa_mode, "None");
12893 } else if (security->mode == wifi_security_mode_wpa_personal)
12894 strcpy(wpa_mode, "WPA-Personal");
12895 else if (security->mode == wifi_security_mode_wpa2_personal)
12896 strcpy(wpa_mode, "WPA2-Personal");
12897 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12898 strcpy(wpa_mode, "WPA-WPA2-Personal");
12899 else if (security->mode == wifi_security_mode_wpa_enterprise)
12900 strcpy(wpa_mode, "WPA-Enterprise");
12901 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12902 strcpy(wpa_mode, "WPA2-Enterprise");
12903 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12904 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12905 else if (security->mode == wifi_security_mode_wpa3_personal) {
12906 strcpy(wpa_mode, "WPA3-Personal");
12907 okc_enable = TRUE;
12908 sae_MFP = TRUE;
12909 sae_pwe = 2;
12910 disable_EAPOL_retries = FALSE;
12911 } else if (security->mode == wifi_security_mode_wpa3_transition) {
12912 strcpy(wpa_mode, "WPA3-Personal-Transition");
12913 okc_enable = TRUE;
12914 sae_MFP = TRUE;
12915 sae_pwe = 2;
12916 disable_EAPOL_retries = FALSE;
12917 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
12918 strcpy(wpa_mode, "WPA3-Enterprise");
12919 sae_MFP = TRUE;
12920 sae_pwe = 2;
12921 disable_EAPOL_retries = FALSE;
developer3086e2f2023-01-17 09:40:01 +080012922 } else if (security->mode == wifi_security_mode_owe) {
12923 strcpy(wpa_mode, "OWE");
12924 sae_MFP = TRUE;
12925 sae_pwe = 2;
12926 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080012927 }
12928
12929 band = wifi_index_to_band(ap_index);
12930 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
12931 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
12932 return RETURN_ERR;
12933 }
12934
12935 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12936 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
12937 wifi_setSAEMFP(ap_index, sae_MFP);
12938 wifi_setSAEpwe(ap_index, sae_pwe);
12939 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
12940
developer23e71282023-01-18 10:25:19 +080012941 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer72fb0bb2023-01-11 09:46:29 +080012942 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
12943 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
12944 password[63] = '\0';
12945 wifi_setApSecurityKeyPassphrase(ap_index, password);
12946 }
12947 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
12948 params.name = "sae_password";
12949 params.value = security->u.key.key;
12950 wifi_hostapdWrite(config_file, &params, 1);
12951 }
12952 }
12953
12954 if (security->mode != wifi_security_mode_none) {
12955 memset(&params, 0, sizeof(params));
12956 params.name = "wpa_pairwise";
12957 if (security->encr == wifi_encryption_tkip)
12958 params.value = "TKIP";
12959 else if (security->encr == wifi_encryption_aes)
12960 params.value = "CCMP";
12961 else if (security->encr == wifi_encryption_aes_tkip)
12962 params.value = "TKIP CCMP";
12963 wifi_hostapdWrite(config_file, &params, 1);
12964 }
12965
12966 if (security->mfp == wifi_mfp_cfg_disabled)
12967 strcpy(mfp, "Disabled");
12968 else if (security->mfp == wifi_mfp_cfg_optional)
12969 strcpy(mfp, "Optional");
12970 else if (security->mfp == wifi_mfp_cfg_required)
12971 strcpy(mfp, "Required");
12972 wifi_setApSecurityMFPConfig(ap_index, mfp);
12973
12974 memset(&params, 0, sizeof(params));
12975 params.name = "transition_disable";
12976 if (security->wpa3_transition_disable == TRUE)
12977 params.value = "0x01";
12978 else
12979 params.value = "0x00";
12980 wifi_hostapdWrite(config_file, &params, 1);
12981
12982 memset(&params, 0, sizeof(params));
12983 params.name = "wpa_group_rekey";
12984 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12985 params.value = buf;
12986 wifi_hostapdWrite(config_file, &params, 1);
12987
12988 memset(&params, 0, sizeof(params));
12989 params.name = "wpa_strict_rekey";
12990 params.value = security->strict_rekey?"1":"0";
12991 wifi_hostapdWrite(config_file, &params, 1);
12992
12993 memset(&params, 0, sizeof(params));
12994 params.name = "wpa_pairwise_update_count";
12995 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12996 params.value = buf;
12997 wifi_hostapdWrite(config_file, &params, 1);
12998
12999 memset(&params, 0, sizeof(params));
13000 params.name = "disable_pmksa_caching";
13001 params.value = security->disable_pmksa_caching?"1":"0";
13002 wifi_hostapdWrite(config_file, &params, 1);
13003
developer23e71282023-01-18 10:25:19 +080013004 if (multiple_set == FALSE) {
13005 wifi_setApEnable(ap_index, FALSE);
13006 wifi_setApEnable(ap_index, TRUE);
13007 }
developer72fb0bb2023-01-11 09:46:29 +080013008
13009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13010
13011 return RETURN_OK;
13012}
13013
13014INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13015{
13016 char buf[256] = {0};
13017 char config_file[128] = {0};
13018 int disable = 0;
13019 // struct params params = {0};
13020
13021 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13022 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13023 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13024 security->mode = wifi_security_mode_none;
13025 if (strlen(buf) != 0) {
13026 if (!strcmp(buf, "WPA-Personal"))
13027 security->mode = wifi_security_mode_wpa_personal;
13028 else if (!strcmp(buf, "WPA2-Personal"))
13029 security->mode = wifi_security_mode_wpa2_personal;
13030 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13031 security->mode = wifi_security_mode_wpa_wpa2_personal;
13032 else if (!strcmp(buf, "WPA-Enterprise"))
13033 security->mode = wifi_security_mode_wpa_enterprise;
13034 else if (!strcmp(buf, "WPA2-Enterprise"))
13035 security->mode = wifi_security_mode_wpa2_enterprise;
13036 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13037 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13038 else if (!strcmp(buf, "WPA3-Personal"))
13039 security->mode = wifi_security_mode_wpa3_personal;
13040 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13041 security->mode = wifi_security_mode_wpa3_transition;
13042 else if (!strcmp(buf, "WPA3-Enterprise"))
13043 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013044 else if (!strcmp(buf, "OWE"))
13045 security->mode = wifi_security_mode_owe;
developer72fb0bb2023-01-11 09:46:29 +080013046 }
13047
13048 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13049 if (security->mode == wifi_security_mode_none)
13050 security->encr = wifi_encryption_none;
13051 else {
13052 if (strcmp(buf, "TKIP") == 0)
13053 security->encr = wifi_encryption_tkip;
13054 else if (strcmp(buf, "CCMP") == 0)
13055 security->encr = wifi_encryption_aes;
13056 else
13057 security->encr = wifi_encryption_aes_tkip;
13058 }
13059
13060 if (security->mode != wifi_encryption_none) {
13061 memset(buf, 0, sizeof(buf));
13062 // wpa3 can use one or both configs as password, so we check sae_password first.
13063 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13064 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13065 security->u.key.type = wifi_security_key_type_sae;
13066 } else {
13067 security->u.key.type = wifi_security_key_type_psk;
13068 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13069 }
13070 strncpy(security->u.key.key, buf, sizeof(buf));
13071 security->u.key.key[255] = '\0';
13072 }
13073
13074 memset(buf, 0, sizeof(buf));
13075 wifi_getApSecurityMFPConfig(ap_index, buf);
13076 if (strcmp(buf, "Disabled") == 0)
13077 security->mfp = wifi_mfp_cfg_disabled;
13078 else if (strcmp(buf, "Optional") == 0)
13079 security->mfp = wifi_mfp_cfg_optional;
13080 else if (strcmp(buf, "Required") == 0)
13081 security->mfp = wifi_mfp_cfg_required;
13082
13083 memset(buf, 0, sizeof(buf));
13084 security->wpa3_transition_disable = FALSE;
13085 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13086 disable = strtol(buf, NULL, 16);
13087 if (disable != 0)
13088 security->wpa3_transition_disable = TRUE;
13089
13090 memset(buf, 0, sizeof(buf));
13091 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13092 if (strlen(buf) == 0)
13093 security->rekey_interval = 86400;
13094 else
13095 security->rekey_interval = strtol(buf, NULL, 10);
13096
13097 memset(buf, 0, sizeof(buf));
13098 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13099 if (strlen(buf) == 0)
13100 security->strict_rekey = 1;
13101 else
13102 security->strict_rekey = strtol(buf, NULL, 10);
13103
13104 memset(buf, 0, sizeof(buf));
13105 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13106 if (strlen(buf) == 0)
13107 security->eapol_key_retries = 4;
13108 else
13109 security->eapol_key_retries = strtol(buf, NULL, 10);
13110
13111 memset(buf, 0, sizeof(buf));
13112 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13113 if (strlen(buf) == 0)
13114 security->disable_pmksa_caching = FALSE;
13115 else
13116 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13117
13118 /* TODO
13119 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13120 */
13121 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13122 security->eap_identity_req_timeout = 0;
13123 security->eap_identity_req_retries = 0;
13124 security->eap_req_timeout = 0;
13125 security->eap_req_retries = 0;
13126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13127 return RETURN_OK;
13128}
13129
13130#endif /* WIFI_HAL_VERSION_3 */
13131
13132#ifdef WIFI_HAL_VERSION_3_PHASE2
13133INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13134{
13135 char interface_name[16] = {0};
13136 char cmd[128] = {0};
13137 char buf[128] = {0};
13138 char *mac_addr = NULL;
13139 BOOL status = FALSE;
13140 size_t len = 0;
13141
13142 if(ap_index > MAX_APS)
13143 return RETURN_ERR;
13144
13145 *output_numDevices = 0;
13146 wifi_getApEnable(ap_index, &status);
13147 if (status == FALSE)
13148 return RETURN_OK;
13149
13150 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13151 return RETURN_ERR;
13152 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13153 _syscmd(cmd, buf, sizeof(buf));
13154
13155 mac_addr = strtok(buf, "\n");
13156 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13157 *output_numDevices = i + 1;
13158 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13159 addr_ptr = output_deviceMacAddressArray[i];
13160 mac_addr_aton(addr_ptr, mac_addr);
13161 mac_addr = strtok(NULL, "\n");
13162 }
13163
13164 return RETURN_OK;
13165}
13166#else
13167INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13168{
13169 char interface_name[16] = {0};
13170 char cmd[128];
13171 BOOL status = false;
13172
13173 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13174 return RETURN_ERR;
13175
13176 output_buf[0] = '\0';
13177
13178 wifi_getApEnable(ap_index,&status);
13179 if (!status)
13180 return RETURN_OK;
13181
13182 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13183 return RETURN_ERR;
13184 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13185 _syscmd(cmd, output_buf, output_buf_size);
13186
13187 return RETURN_OK;
13188}
13189#endif
13190
13191INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13192{
13193 char output[16]={'\0'};
13194 char config_file[MAX_BUF_SIZE] = {0};
13195
13196 if (!enable)
13197 return RETURN_ERR;
13198
13199 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13200 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13201
13202 if (strlen(output) == 0)
13203 *enable = FALSE;
13204 else if (strncmp(output, "1", 1) == 0)
13205 *enable = TRUE;
13206 else
13207 *enable = FALSE;
13208
13209 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13210 return RETURN_OK;
13211}
13212
13213INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13214{
13215 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13216 return RETURN_ERR;
13217 *output_enable=TRUE;
13218 return RETURN_OK;
13219}
13220
13221INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13222{
13223 char cmd[128] = {0};
13224 char buf[128] = {0};
13225 char line[128] = {0};
13226 size_t len = 0;
13227 FILE *f = NULL;
13228 int index = 0;
13229 int exp = 0;
13230 int mantissa = 0;
13231 int duration = 0;
13232 int radio_index = 0;
13233 int max_radio_num = 0;
13234 uint twt_wake_interval = 0;
13235 int phyId = 0;
13236 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13237
13238 wifi_getMaxRadioNumber(&max_radio_num);
13239
13240 radio_index = ap_index % max_radio_num;
13241
13242 phyId = radio_index_to_phy(radio_index);
13243 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13244 _syscmd(cmd, buf, sizeof(buf));
13245 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13246 if (*numSessionReturned > maxNumberSessions)
13247 *numSessionReturned = maxNumberSessions;
13248 else if (*numSessionReturned < 1) {
13249 *numSessionReturned = 0;
13250 return RETURN_OK;
13251 }
13252
13253 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13254 if ((f = popen(cmd, "r")) == NULL) {
13255 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13256 return RETURN_ERR;
13257 }
13258
13259 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13260 while((fgets(line, sizeof(line), f)) != NULL) {
13261 char *tmp = NULL;
13262 strcpy(buf, line);
13263 tmp = strtok(buf, " ");
13264 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13265 tmp = strtok(NULL, " ");
13266 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13267 tmp = strtok(NULL, " ");
13268 if (strstr(tmp, "t")) {
13269 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13270 }
13271 if (strstr(tmp, "a")) {
13272 twtSessions[index].twtParameters.operation.announced = TRUE;
13273 }
13274 tmp = strtok(NULL, " ");
13275 exp = strtol(tmp, NULL, 10);
13276 tmp = strtok(NULL, " ");
13277 mantissa = strtol(tmp, NULL, 10);
13278 tmp = strtok(NULL, " ");
13279 duration = strtol(tmp, NULL, 10);
13280
13281 // only implicit supported
13282 twtSessions[index].twtParameters.operation.implicit = TRUE;
13283 // only individual agreement supported
13284 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13285
13286 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13287 twt_wake_interval = mantissa * (1 << exp);
13288 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13289 // Overflow handling
13290 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13291 } else {
13292 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13293 }
13294 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13295 index++;
13296 }
13297
13298 pclose(f);
13299 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13300 return RETURN_OK;
13301}