blob: a99a986020521241499ef09de14b9c34b5edb902 [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
developer96b38512023-02-22 11:17:45 +0800136#define MAX_CARD_INDEX 3
137
developer72fb0bb2023-01-11 09:46:29 +0800138static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
139 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
140 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
141 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
142 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
143 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
144 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
145 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
146 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
148 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
149 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
150 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
151 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
152 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
153 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
154 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
155};
156
157typedef unsigned long long u64;
158
159/* Enum to define WiFi Bands */
160typedef enum
161{
162 band_invalid = -1,
163 band_2_4 = 0,
164 band_5 = 1,
165 band_6 = 2,
166} wifi_band;
167
developer17038e62023-03-02 14:43:43 +0800168char* wifi_band_str[] = {
169 "2G",
170 "5G",
171 "6G",
172};
173
developer72fb0bb2023-01-11 09:46:29 +0800174typedef enum {
175 WIFI_MODE_A = 0x01,
176 WIFI_MODE_B = 0x02,
177 WIFI_MODE_G = 0x04,
178 WIFI_MODE_N = 0x08,
179 WIFI_MODE_AC = 0x10,
180 WIFI_MODE_AX = 0x20,
181} wifi_ieee80211_Mode;
182
183#ifdef WIFI_HAL_VERSION_3
184
185// Return number of elements in array
186#ifndef ARRAY_SIZE
187#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
188#endif /* ARRAY_SIZE */
189
190#ifndef ARRAY_AND_SIZE
191#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
192#endif /* ARRAY_AND_SIZE */
193
194#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
195
196typedef struct {
197 int32_t value;
198 int32_t param;
199 intptr_t key;
200 intptr_t data;
201} wifi_secur_list;
202
203static int util_unii_5g_centerfreq(const char *ht_mode, int channel);
204static int util_unii_6g_centerfreq(const char *ht_mode, int channel);
205wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
206wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
207char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
208static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
209
210static wifi_secur_list map_security[] =
211{
212 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
213 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
214 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
219 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
220 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise"),
221 WIFI_ITEM_STR(wifi_security_mode_wpa3_personal, "WPA3-Personal"),
222 WIFI_ITEM_STR(wifi_security_mode_wpa3_transition, "WPA3-Personal-Transition"),
223 WIFI_ITEM_STR(wifi_security_mode_wpa3_enterprise, "WPA3-Enterprise")
224};
225
226wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
227{
228 wifi_secur_list *item;
229 int i;
230
231 for (item = list,i = 0;i < list_sz; item++, i++) {
232 if ((int)(item->key) == key) {
233 return item;
234 }
235 }
236
237 return NULL;
238}
239
240char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
241{
242 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
243
244 if (!item) {
245 return "";
246 }
247
248 return (char *)(item->data);
249}
250
251wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
252{
253 wifi_secur_list *item;
254 int i;
255
256 for (item = list,i = 0;i < list_sz; item++, i++) {
257 if (strcmp((char *)(item->data), str) == 0) {
258 return item;
259 }
260 }
261
262 return NULL;
263}
264#endif /* WIFI_HAL_VERSION_3 */
265
developer96b38512023-02-22 11:17:45 +0800266
267static char l1profile[32] = "/etc/wireless/l1profile.dat";
developer17038e62023-03-02 14:43:43 +0800268char main_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
269char ext_prefix[MAX_NUM_RADIOS][IFNAMSIZ];
270#define MAX_SSID_LEN 64
271char default_ssid[MAX_NUM_RADIOS][MAX_SSID_LEN];;
272
273static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
274static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
275
developer96b38512023-02-22 11:17:45 +0800276
277static int
278get_value(const char *conf_file, const char *param, char *value, int len)
279{
280 FILE *fp;
281 int ret = -1;
282 int param_len = strlen(param);
283 int buf_len;
284 char buf[256];
285
286 fp = fopen(conf_file, "r");
287 if (!fp) {
288 return -1;
289 }
290
291 while (fgets(buf, sizeof(buf), fp)) {
292 buf_len = strlen(buf);
293 if (buf[buf_len - 1] == '\n') {
294 buf_len--;
295 buf[buf_len] = '\0';
296 }
297 if ((buf_len > param_len) &&
298 (strncmp(buf, param, param_len) == 0) &&
299 (buf[param_len] == '=')) {
300
301 if (buf_len == (param_len + 1)) {
302 value[0] = '\0';
303 ret = 0;
304 } else {
305 ret = snprintf(value, len, "%s", buf + (param_len + 1));
306 }
307 fclose(fp);
308 return ret;
309 }
310 }
311 fclose(fp);
312 return -1;
313}
314
315static int
316get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
317{
318 char buf[256];
319 int ret;
320 char *save_ptr = NULL;
321 char *tok = NULL;
322
323 ret = get_value(conf_file, param, buf, sizeof(buf));
324 if (ret < 0)
325 return ret;
326
327 tok = strtok_r(buf, ";", &save_ptr);
328 do {
329 if (idx == 0 || tok == NULL)
330 break;
331 else
332 idx--;
333
334 tok = strtok_r(NULL, ";", &save_ptr);
335 } while (tok != NULL);
336
337 if (tok) {
338 ret = snprintf(value, len, "%s", tok);
339 } else {
340 ret = 0;
341 value[0] = '\0';
342 }
343
344 return ret;
345}
346
347
developer72fb0bb2023-01-11 09:46:29 +0800348#ifdef HAL_NETLINK_IMPL
349typedef struct {
350 int id;
351 struct nl_sock* socket;
352 struct nl_cb* cb;
353} Netlink;
354
355static int mac_addr_aton(unsigned char *mac_addr, char *arg)
356{
357 unsigned int mac_addr_int[6]={};
358 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);
359 mac_addr[0] = mac_addr_int[0];
360 mac_addr[1] = mac_addr_int[1];
361 mac_addr[2] = mac_addr_int[2];
362 mac_addr[3] = mac_addr_int[3];
363 mac_addr[4] = mac_addr_int[4];
364 mac_addr[5] = mac_addr_int[5];
365 return 0;
366}
367
368static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
369{
370 unsigned int mac_addr_int[6]={};
371 mac_addr_int[0] = arg[0];
372 mac_addr_int[1] = arg[1];
373 mac_addr_int[2] = arg[2];
374 mac_addr_int[3] = arg[3];
375 mac_addr_int[4] = arg[4];
376 mac_addr_int[5] = arg[5];
377 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]);
378 return;
379}
380
381static int ieee80211_frequency_to_channel(int freq)
382{
383 /* see 802.11-2007 17.3.8.3.2 and Annex J */
384 if (freq == 2484)
385 return 14;
386 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
387 else if (freq == 5935)
388 return 2;
389 else if (freq < 2484)
390 return (freq - 2407) / 5;
391 else if (freq >= 4910 && freq <= 4980)
392 return (freq - 4000) / 5;
393 else if (freq < 5950)
394 return (freq - 5000) / 5;
395 else if (freq <= 45000) /* DMG band lower limit */
396 /* see 802.11ax D6.1 27.3.23.2 */
397 return (freq - 5950) / 5;
398 else if (freq >= 58320 && freq <= 70200)
399 return (freq - 56160) / 2160;
400 else
401 return 0;
402}
403
404static int initSock80211(Netlink* nl) {
405 nl->socket = nl_socket_alloc();
406 if (!nl->socket) {
407 fprintf(stderr, "Failing to allocate the sock\n");
408 return -ENOMEM;
409 }
410
411 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
412
413 if (genl_connect(nl->socket)) {
414 fprintf(stderr, "Failed to connect\n");
415 nl_close(nl->socket);
416 nl_socket_free(nl->socket);
417 return -ENOLINK;
418 }
419
420 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
421 if (nl->id< 0) {
422 fprintf(stderr, "interface not found.\n");
423 nl_close(nl->socket);
424 nl_socket_free(nl->socket);
425 return -ENOENT;
426 }
427
428 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
429 if ((!nl->cb)) {
430 fprintf(stderr, "Failed to allocate netlink callback.\n");
431 nl_close(nl->socket);
432 nl_socket_free(nl->socket);
433 return ENOMEM;
434 }
435
436 return nl->id;
437}
438
439static int nlfree(Netlink *nl)
440{
441 nl_cb_put(nl->cb);
442 nl_close(nl->socket);
443 nl_socket_free(nl->socket);
444 return 0;
445}
446
447static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
448 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
449 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
450 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
451};
452
453static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
454};
455
456static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
457};
458
459typedef struct _wifi_channelStats_loc {
460 INT array_size;
461 INT ch_number;
462 BOOL ch_in_pool;
463 INT ch_noise;
464 BOOL ch_radar_noise;
465 INT ch_max_80211_rssi;
466 INT ch_non_80211_noise;
467 INT ch_utilization;
468 ULLONG ch_utilization_total;
469 ULLONG ch_utilization_busy;
470 ULLONG ch_utilization_busy_tx;
471 ULLONG ch_utilization_busy_rx;
472 ULLONG ch_utilization_busy_self;
473 ULLONG ch_utilization_busy_ext;
474} wifi_channelStats_t_loc;
475
476typedef struct wifi_device_info {
477 INT wifi_devIndex;
478 UCHAR wifi_devMacAddress[6];
479 CHAR wifi_devIPAddress[64];
480 BOOL wifi_devAssociatedDeviceAuthentiationState;
481 INT wifi_devSignalStrength;
482 INT wifi_devTxRate;
483 INT wifi_devRxRate;
484} wifi_device_info_t;
485
486#endif
487
488//For 5g Alias Interfaces
489static BOOL priv_flag = TRUE;
490static BOOL pub_flag = TRUE;
491static BOOL Radio_flag = TRUE;
492//wifi_setApBeaconRate(1, beaconRate);
493
494BOOL multiple_set = FALSE;
495
496struct params
497{
498 char * name;
499 char * value;
500};
501
502static int _syscmd(char *cmd, char *retBuf, int retBufSize)
503{
504 FILE *f;
505 char *ptr = retBuf;
506 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
507
508 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
509 if((f = popen(cmd, "r")) == NULL) {
510 fprintf(stderr,"\npopen %s error\n", cmd);
511 return RETURN_ERR;
512 }
513
514 while(!feof(f))
515 {
516 *ptr = 0;
517 if(bufSize>=128) {
518 bufbytes=128;
519 } else {
520 bufbytes=bufSize-1;
521 }
522
523 fgets(ptr,bufbytes,f);
524 readbytes=strlen(ptr);
525
526 if(!readbytes)
527 break;
528
529 bufSize-=readbytes;
530 ptr += readbytes;
531 }
532 cmd_ret = pclose(f);
533 retBuf[retBufSize-1]=0;
534 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
535
536 return cmd_ret >> 8;
537}
538
539INT radio_index_to_phy(int radioIndex)
540{
developer17038e62023-03-02 14:43:43 +0800541 /* TODO */
542 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800543}
544
545INT wifi_getMaxRadioNumber(INT *max_radio_num)
546{
547 char cmd[64] = {0};
548 char buf[4] = {0};
549
550 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
551
552 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
553 _syscmd(cmd, buf, sizeof(buf));
554 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
555
556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
557
558 return RETURN_OK;
559}
560
developer17038e62023-03-02 14:43:43 +0800561wifi_band radio_index_to_band(int radioIndex)
562{
563 char cmd[128] = {0};
564 char buf[64] = {0};
565 int nl80211_band = 0;
566 int i = 0;
567 int phyIndex = 0;
568 int max_radio_num = 0;
569 wifi_band band = band_invalid;
570
571 phyIndex = radio_index_to_phy(radioIndex);
572 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
573 _syscmd(cmd, buf, sizeof(buf));
574 nl80211_band = strtol(buf, NULL, 10);
575 if (nl80211_band == 1)
576 return band_2_4;
577 else if (nl80211_band == 2)
578 return band_5;
579 else if (nl80211_band == 4) // band == 3 is 60GHz
580 return band_6;
581 else
582 return band_invalid;
583}
584
developer72fb0bb2023-01-11 09:46:29 +0800585wifi_band wifi_index_to_band(int apIndex)
586{
587 char cmd[128] = {0};
588 char buf[64] = {0};
589 int nl80211_band = 0;
590 int i = 0;
591 int phyIndex = 0;
592 int radioIndex = 0;
593 int max_radio_num = 0;
594 wifi_band band = band_invalid;
595
596 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
597
598 wifi_getMaxRadioNumber(&max_radio_num);
599 radioIndex = apIndex % max_radio_num;
600 phyIndex = radio_index_to_phy(radioIndex);
601 while(i < 10){
602 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
603 _syscmd(cmd, buf, sizeof(buf));
604 nl80211_band = strtol(buf, NULL, 10);
605 if (nl80211_band == 1)
606 band = band_2_4;
607 else if (nl80211_band == 2)
608 band = band_5;
609 else if (nl80211_band == 4) // band == 3 is 60GHz
610 band = band_6;
611
612 if(band != band_invalid)
613 break;
614
615 i++;
616 sleep(1);
617 }
618
619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
620 return band;
621}
622
623static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
624{
625 char cmd[MAX_CMD_SIZE]={'\0'};
626 char buf[MAX_BUF_SIZE]={'\0'};
627 int ret = 0;
628
629 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
630 ret = _syscmd(cmd, buf, sizeof(buf));
631 if ((ret != 0) && (strlen(buf) == 0))
632 return -1;
633 snprintf(output, output_size, "%s", buf);
634
635 return 0;
636}
637
638static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
639{
640 char cmd[MAX_CMD_SIZE]={'\0'};
641 char buf[MAX_BUF_SIZE]={'\0'};
642
643 for(int i=0;i<item_count;i++)
644 {
645 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
646 if (strlen(buf) == 0) //Insert
647 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
648 else //Update
649 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
650
651 if(_syscmd(cmd, buf, sizeof(buf)))
652 return -1;
653 }
654
655 return 0;
656}
657
658//For Getting Current Interface Name from corresponding hostapd configuration
659static int wifi_GetInterfaceName(int apIndex, char *interface_name)
660{
661 char config_file[128] = {0};
662
663 if (interface_name == NULL)
664 return RETURN_ERR;
665
666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
667
668 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
669 wifi_hostapdRead(config_file, "interface", interface_name, 16);
670 if (strlen(interface_name) == 0)
671 return RETURN_ERR;
672
673 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
674 return RETURN_OK;
675}
676
developer72fb0bb2023-01-11 09:46:29 +0800677
678static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
679{
680 char interface_name[16] = {0};
681 if (multiple_set == TRUE)
682 return RETURN_OK;
683 char cmd[MAX_CMD_SIZE]="", output[32]="";
684 FILE *fp;
685 int i;
686 //NOTE RELOAD should be done in ApplySSIDSettings
687 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
688 return RETURN_ERR;
689 for(i=0; i<item_count; i++, list++)
690 {
691 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
692 if((fp = popen(cmd, "r"))==NULL)
693 {
694 perror("popen failed");
695 return -1;
696 }
697 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
698 {
699 pclose(fp);
700 perror("fgets failed");
701 return -1;
702 }
703 pclose(fp);
704 }
705 return 0;
706}
707
708static int wifi_reloadAp(int apIndex)
709{
710 char interface_name[16] = {0};
711 if (multiple_set == TRUE)
712 return RETURN_OK;
713 char cmd[MAX_CMD_SIZE]="";
714 char buf[MAX_BUF_SIZE]="";
715
716 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
717 return RETURN_ERR;
718 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
719 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
720 return RETURN_ERR;
721
722 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
723 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
724 return RETURN_ERR;
725
726 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
727 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
728 return RETURN_ERR;
729
730 return RETURN_OK;
731}
732
733INT File_Reading(CHAR *file, char *Value)
734{
735 FILE *fp = NULL;
736 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
737 int count = 0;
738
739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
740 fp = popen(file,"r");
741 if(fp == NULL)
742 return RETURN_ERR;
743
744 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
745 {
746 for(count=0;buf[count]!='\n';count++)
747 copy_buf[count]=buf[count];
748 copy_buf[count]='\0';
749 }
750 strcpy(Value,copy_buf);
751 pclose(fp);
752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
753
754 return RETURN_OK;
755}
756
757void wifi_RestartHostapd_2G()
758{
759 int Public2GApIndex = 4;
760
761 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
762 wifi_setApEnable(Public2GApIndex, FALSE);
763 wifi_setApEnable(Public2GApIndex, TRUE);
764 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
765}
766
767void wifi_RestartHostapd_5G()
768{
769 int Public5GApIndex = 5;
770
771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
772 wifi_setApEnable(Public5GApIndex, FALSE);
773 wifi_setApEnable(Public5GApIndex, TRUE);
774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
775}
776
777void wifi_RestartPrivateWifi_2G()
778{
779 int PrivateApIndex = 0;
780
781 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
782 wifi_setApEnable(PrivateApIndex, FALSE);
783 wifi_setApEnable(PrivateApIndex, TRUE);
784 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
785}
786
787void wifi_RestartPrivateWifi_5G()
788{
789 int Private5GApIndex = 1;
790
791 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
792 wifi_setApEnable(Private5GApIndex, FALSE);
793 wifi_setApEnable(Private5GApIndex, TRUE);
794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
795}
796
797static int writeBandWidth(int radioIndex,char *bw_value)
798{
799 char buf[MAX_BUF_SIZE];
800 char cmd[MAX_CMD_SIZE];
801
802 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
803 if(_syscmd(cmd, buf, sizeof(buf)))
804 {
805 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
806 _syscmd(cmd, buf, sizeof(buf));
807 return RETURN_OK;
808 }
809
810 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
811 _syscmd(cmd,buf,sizeof(buf));
812 return RETURN_OK;
813}
814
815static int readBandWidth(int radioIndex,char *bw_value)
816{
817 char buf[MAX_BUF_SIZE] = {0};
818 char cmd[MAX_CMD_SIZE] = {0};
819 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
820 _syscmd(cmd,buf,sizeof(buf));
821 if(NULL!=strstr(buf,"20MHz"))
822 {
823 strcpy(bw_value,"20MHz");
824 }
825 else if(NULL!=strstr(buf,"40MHz"))
826 {
827 strcpy(bw_value,"40MHz");
828 }
829 else if(NULL!=strstr(buf,"80MHz"))
830 {
831 strcpy(bw_value,"80MHz");
832 }
833 else
834 {
835 return RETURN_ERR;
836 }
837 return RETURN_OK;
838}
839
840// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
841INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
842{
843 struct params params={'\0'};
844 char config_file[MAX_BUF_SIZE] = {0};
845 char buf[MAX_BUF_SIZE] = {'\0'};
846
847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
848 // Copy the numeric value
849 if (strlen (beaconRate) >= 5) {
850 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
851 buf[strlen(beaconRate) - 4] = '\0';
852 } else if (strlen(beaconRate) > 0)
853 strcpy(buf, beaconRate);
854 else
855 return RETURN_ERR;
856
857 params.name = "beacon_rate";
858 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
859 if (strncmp(buf, "5.5", 3) == 0) {
860 snprintf(buf, sizeof(buf), "55");
861 params.value = buf;
862 } else {
863 strcat(buf, "0");
864 params.value = buf;
865 }
866
867 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
868 wifi_hostapdWrite(config_file, &params, 1);
869 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
870 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
871
872 return RETURN_OK;
873}
874
875INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
876{
877 char config_file[128] = {'\0'};
878 char temp_output[128] = {'\0'};
879 char buf[128] = {'\0'};
880 char cmd[128] = {'\0'};
881 int rate = 0;
882 int phyId = 0;
883
884 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
885 if (NULL == beaconRate)
886 return RETURN_ERR;
887
888 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
889 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
890 phyId = radio_index_to_phy(radioIndex);
891 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
892 if(strlen(buf) > 0) {
893 if (strncmp(buf, "55", 2) == 0)
894 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
895 else {
896 rate = strtol(buf, NULL, 10)/10;
897 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
898 }
899 } else {
900 // config not set, so we would use lowest rate as default
901 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
902 _syscmd(cmd, buf, sizeof(buf));
903 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
904 }
905 strncpy(beaconRate, temp_output, sizeof(temp_output));
906 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
907
908 return RETURN_OK;
909}
910
911INT wifi_setLED(INT radioIndex, BOOL enable)
912{
913 return 0;
914}
915INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
916{
917 return RETURN_OK;
918}
919/**********************************************************************************
920 *
921 * Wifi Subsystem level function prototypes
922 *
923**********************************************************************************/
924//---------------------------------------------------------------------------------------------------
925//Wifi system api
926//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
927INT wifi_getHalVersion(CHAR *output_string) //RDKB
928{
929 if(!output_string)
930 return RETURN_ERR;
931 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
932
933 return RETURN_OK;
934}
935
936
937/* wifi_factoryReset() function */
938/**
939* @description Clears internal variables to implement a factory reset of the Wi-Fi
940* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
941*
942* @param None
943*
944* @return The status of the operation.
945* @retval RETURN_OK if successful.
946* @retval RETURN_ERR if any error is detected
947*
948* @execution Synchronous
949* @sideeffect None
950*
951* @note This function must not suspend and must not invoke any blocking system
952* calls. It should probably just send a message to a driver event handler task.
953*
954*/
955INT wifi_factoryReset()
956{
957 char cmd[128];
958
959 /*delete running hostapd conf files*/
960 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
961 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
962 system(cmd);
963 system("systemctl restart hostapd.service");
964
965 return RETURN_OK;
966}
967
968/* wifi_factoryResetRadios() function */
969/**
970* @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.
971*
972* @param None
973* @return The status of the operation
974* @retval RETURN_OK if successful
975* @retval RETURN_ERR if any error is detected
976*
977* @execution Synchronous
978*
979* @sideeffect None
980*
981* @note This function must not suspend and must not invoke any blocking system
982* calls. It should probably just send a message to a driver event handler task.
983*
984*/
985INT wifi_factoryResetRadios()
986{
987 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
988 return RETURN_OK;
989
990 return RETURN_ERR;
991}
992
993
994/* wifi_factoryResetRadio() function */
995/**
996* @description Restore selected radio parameters without touching access point parameters
997*
998* @param radioIndex - Index of Wi-Fi Radio channel
999*
1000* @return The status of the operation.
1001* @retval RETURN_OK if successful.
1002* @retval RETURN_ERR if any error is detected
1003*
1004* @execution Synchronous.
1005* @sideeffect None.
1006*
1007* @note This function must not suspend and must not invoke any blocking system
1008* calls. It should probably just send a message to a driver event handler task.
1009*
1010*/
1011INT wifi_factoryResetRadio(int radioIndex) //RDKB
1012{
1013 system("systemctl stop hostapd.service");
1014
1015 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1016 if(radioIndex == 0)
1017 system("rm /nvram/hostapd0.conf");
1018 else if(radioIndex == 1)
1019 system("rm /nvram/hostapd1.conf");
1020 else
1021 return RETURN_ERR;
1022
1023 system("systemctl start hostapd.service");
1024 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1025 return RETURN_OK;
1026}
1027
1028/* wifi_initRadio() function */
1029/**
1030* Description: This function call initializes the specified radio.
1031* Implementation specifics may dictate the functionality since
1032* different hardware implementations may have different initilization requirements.
1033* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1034*
1035* @return The status of the operation.
1036* @retval RETURN_OK if successful.
1037* @retval RETURN_ERR if any error is detected
1038*
1039* @execution Synchronous.
1040* @sideeffect None.
1041*
1042* @note This function must not suspend and must not invoke any blocking system
1043* calls. It should probably just send a message to a driver event handler task.
1044*
1045*/
1046INT wifi_initRadio(INT radioIndex)
1047{
1048 //TODO: Initializes the wifi subsystem (for specified radio)
1049 return RETURN_OK;
1050}
1051void macfilter_init()
1052{
1053 char count[4]={'\0'};
1054 char buf[253]={'\0'};
1055 char tmp[19]={'\0'};
1056 int dev_count,block,mac_entry=0;
1057 char res[4]={'\0'};
1058 char acl_file_path[64] = {'\0'};
1059 FILE *fp = NULL;
1060 int index=0;
1061 char iface[10]={'\0'};
1062 char config_file[MAX_BUF_SIZE] = {0};
1063
1064
1065 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1066
1067 fp=fopen(acl_file_path,"w+");
1068 if (fp == NULL) {
1069 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001070 return;
developer72fb0bb2023-01-11 09:46:29 +08001071 }
1072 sprintf(buf,"#!/bin/sh \n");
1073 fprintf(fp,"%s\n",buf);
1074
1075 system("chmod 0777 /tmp/mac_filter.sh");
1076
1077 for(index=0;index<=1;index++)
1078 {
1079 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1080 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1081 sprintf(buf,"syscfg get %dcountfilter",index);
1082 _syscmd(buf,count,sizeof(count));
1083 mac_entry=atoi(count);
1084
1085 sprintf(buf,"syscfg get %dblockall",index);
1086 _syscmd(buf,res,sizeof(res));
1087 block = atoi(res);
1088
1089 //Allow only those macs mentioned in ACL
1090 if(block==1)
1091 {
1092 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1093 fprintf(fp,"%s\n",buf);
1094 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1095 {
1096 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1097 _syscmd(buf,tmp,sizeof(tmp));
1098 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1099 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1100 fprintf(fp,"%s\n",buf);
1101 }
1102 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1103 fprintf(fp,"%s\n",buf);
1104 }
1105
1106 //Block all the macs mentioned in ACL
1107 else if(block==2)
1108 {
1109 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1110 fprintf(fp,"%s\n",buf);
1111
1112 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1113 {
1114 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1115 _syscmd(buf,tmp,sizeof(tmp));
1116 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
1117 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1118 fprintf(fp,"%s\n",buf);
1119 }
1120 }
1121 }
1122 fclose(fp);
1123}
1124
developer17038e62023-03-02 14:43:43 +08001125
1126static void
1127wifi_ParseProfile(void)
1128{
1129 int i;
1130 int max_radio_num = 0;
1131 int card_idx;
1132 int band_idx;
1133 int phy_idx = 0;
1134 char buf[MAX_BUF_SIZE] = {0};
1135 char chip_name[12];
1136 char card_profile[MAX_BUF_SIZE] = {0};
1137 char band_profile[MAX_BUF_SIZE] = {0};
1138 FILE* fp;
1139
1140 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1141
1142 memset(main_prefix, 0, sizeof(main_prefix));
1143 memset(ext_prefix, 0, sizeof(ext_prefix));
1144 memset(default_ssid, 0, sizeof(default_ssid));
1145
1146 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1147 /* LOG */
1148 return;
1149 }
1150
1151 for (card_idx = 0; card_idx < 3; card_idx++) {
1152 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1153 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1154 break;
1155 }
1156 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1157 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1158 break;
1159 }
1160 for (band_idx = 0; band_idx < 3; band_idx++) {
1161 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1162 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1163 /* LOG */
1164 break;
1165 }
1166
1167 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1168 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1169 /* LOG */
1170 }
1171
1172 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1173 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1174 /* LOG */
1175 }
1176
1177 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1178 /* LOG */
1179 }
1180 phy_idx++;
1181 }
1182 }
1183
1184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1185}
1186
1187static void
1188wifi_PrepareDefaultHostapdConfigs(void)
1189{
1190 int radio_idx;
1191 int bss_idx;
1192 int ap_idx;
1193 int band_idx;
1194 char buf[MAX_BUF_SIZE] = {0};
1195 char config_file[MAX_BUF_SIZE] = {0};
1196 char ssid[MAX_BUF_SIZE] = {0};
1197 char interface[32] = {0};
1198 char ret_buf[MAX_BUF_SIZE] = {0};
1199 struct params params[2];
1200
1201 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1202 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1203 band_idx = radio_index_to_band(radio_idx);
1204 if (band_idx < 0) {
1205 break;
1206 }
1207 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1208 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1209
1210 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1211 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
1212 _syscmd(buf, ret_buf, sizeof(ret_buf));
1213
1214 if (bss_idx == 0) {
1215 snprintf(ssid, sizeof(ssid), "%s", default_ssid[radio_idx]);
1216 snprintf(interface, sizeof(interface), "%s", main_prefix[radio_idx]);
1217 } else {
1218 snprintf(ssid, sizeof(ssid), "%s_%d", default_ssid[radio_idx], bss_idx);
1219 snprintf(interface, sizeof(interface), "%s%d", ext_prefix[radio_idx], bss_idx);
1220 }
1221
1222 params[0].name = "ssid";
1223 params[0].value = ssid;
1224 params[1].name = "interface";
1225 params[1].value = interface;
1226
1227 wifi_hostapdWrite(config_file, params, 2);
1228 }
1229 }
1230 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1231}
1232
1233static void
1234wifiBringUpInterfacesForRadio(int radio_idx)
1235{
1236 int bss_idx;
1237 int ap_idx;
1238 int band_idx;
1239 char cmd[MAX_BUF_SIZE] = {0};
1240 char config_file[MAX_BUF_SIZE] = {0};
1241 char ret_buf[MAX_BUF_SIZE]={'\0'};
1242
1243 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1244 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1245 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1246
1247 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1248 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=%s:%s", main_prefix[radio_idx], config_file);
1249 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1250 }
1251 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1252}
1253
1254static void
1255wifi_BringUpInterfaces(void)
1256{
1257 int radio_idx;
1258 int bss_idx;
1259 int ap_idx;
1260 int band_idx;
1261 char cmd[MAX_BUF_SIZE] = {0};
1262 char config_file[MAX_BUF_SIZE] = {0};
1263 char ret_buf[MAX_BUF_SIZE]={'\0'};
1264
1265 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1266 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1267 band_idx = radio_index_to_band(radio_idx);
1268 if (band_idx < 0) {
1269 break;
1270 }
1271 wifiBringUpInterfacesForRadio(radio_idx);
1272 }
1273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1274}
1275
1276static void
1277wifi_BringDownInterfacesForRadio(int radio_idx)
1278{
1279 int bss_idx;
1280 int ap_idx;
1281 int band_idx;
1282 char cmd[MAX_BUF_SIZE] = {0};
1283 char config_file[MAX_BUF_SIZE] = {0};
1284 char ret_buf[MAX_BUF_SIZE]={'\0'};
1285
1286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1287 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1288 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1289
1290 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1291 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1292 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1293 }
1294 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1295}
1296
1297
1298static void
1299wifi_BringDownInterfaces(void)
1300{
1301 int radio_idx;
1302 int bss_idx;
1303 int ap_idx;
1304 int band_idx;
1305 char cmd[MAX_BUF_SIZE] = {0};
1306 char config_file[MAX_BUF_SIZE] = {0};
1307 char ret_buf[MAX_BUF_SIZE]={'\0'};
1308
1309 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1310 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1311 band_idx = radio_index_to_band(radio_idx);
1312 if (band_idx < 0) {
1313 break;
1314 }
1315 wifi_BringDownInterfacesForRadio(radio_idx);
1316 }
1317 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1318}
1319
1320
developer72fb0bb2023-01-11 09:46:29 +08001321// Initializes the wifi subsystem (all radios)
1322INT wifi_init() //RDKB
1323{
developer96b38512023-02-22 11:17:45 +08001324 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1325 //Not intitializing macfilter for Turris-Omnia Platform for now
1326 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001327 wifi_ParseProfile();
1328 wifi_PrepareDefaultHostapdConfigs();
1329 //system("/usr/sbin/iw reg set US");
1330 system("systemctl start hostapd.service");
1331 sleep(2);
1332 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001333
developer96b38512023-02-22 11:17:45 +08001334
1335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001336
1337 return RETURN_OK;
1338}
1339
1340/* wifi_reset() function */
1341/**
1342* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
1343* Implementation specifics may dictate what is actualy reset since
1344* different hardware implementations may have different requirements.
1345* Parameters : None
1346*
1347* @return The status of the operation.
1348* @retval RETURN_OK if successful.
1349* @retval RETURN_ERR if any error is detected
1350*
1351* @execution Synchronous.
1352* @sideeffect None.
1353*
1354* @note This function must not suspend and must not invoke any blocking system
1355* calls. It should probably just send a message to a driver event handler task.
1356*
1357*/
1358INT wifi_reset()
1359{
developer17038e62023-03-02 14:43:43 +08001360
1361 wifi_BringDownInterfaces();
1362 sleep(2);
1363
developer96b38512023-02-22 11:17:45 +08001364 //TODO: resets the wifi subsystem, deletes all APs
1365 system("systemctl stop hostapd.service");
1366 sleep(2);
developer17038e62023-03-02 14:43:43 +08001367
developer96b38512023-02-22 11:17:45 +08001368 system("systemctl start hostapd.service");
1369 sleep(5);
developer17038e62023-03-02 14:43:43 +08001370
1371 wifi_PrepareDefaultHostapdConfigs();
1372 sleep(2);
1373 wifi_BringUpInterfaces();
1374
developer72fb0bb2023-01-11 09:46:29 +08001375 return RETURN_OK;
1376}
1377
1378/* wifi_down() function */
1379/**
1380* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1381* Implementation specifics may dictate some functionality since
1382* different hardware implementations may have different requirements.
1383*
1384* @param None
1385*
1386* @return The status of the operation
1387* @retval RETURN_OK if successful
1388* @retval RETURN_ERR if any error is detected
1389*
1390* @execution Synchronous
1391* @sideeffect None
1392*
1393* @note This function must not suspend and must not invoke any blocking system
1394* calls. It should probably just send a message to a driver event handler task.
1395*
1396*/
1397INT wifi_down()
1398{
developer96b38512023-02-22 11:17:45 +08001399 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001400 wifi_BringDownInterfaces();
1401 sleep(2);
1402
developer96b38512023-02-22 11:17:45 +08001403 system("systemctl stop hostapd.service");
1404 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001405 return RETURN_OK;
1406}
1407
1408
1409/* wifi_createInitialConfigFiles() function */
1410/**
1411* @description This function creates wifi configuration files. The format
1412* and content of these files are implementation dependent. This function call is
1413* used to trigger this task if necessary. Some implementations may not need this
1414* function. If an implementation does not need to create config files the function call can
1415* do nothing and return RETURN_OK.
1416*
1417* @param None
1418*
1419* @return The status of the operation
1420* @retval RETURN_OK if successful
1421* @retval RETURN_ERR if any error is detected
1422*
1423* @execution Synchronous
1424* @sideeffect None
1425*
1426* @note This function must not suspend and must not invoke any blocking system
1427* calls. It should probably just send a message to a driver event handler task.
1428*
1429*/
1430INT wifi_createInitialConfigFiles()
1431{
1432 //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)
1433 return RETURN_OK;
1434}
1435
1436// outputs the country code to a max 64 character string
1437INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1438{
1439 char interface_name[16] = {0};
1440 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1441 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
1442 return RETURN_ERR;
1443
1444 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1445 return RETURN_ERR;
1446 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
1447 _syscmd(cmd, buf, sizeof(buf));
1448 if(strlen(buf) > 0)
1449 snprintf(output_string, 64, "%s", buf);
1450 else
1451 return RETURN_ERR;
1452
1453 return RETURN_OK;
1454}
1455
1456INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1457{
1458 //Set wifi config. Wait for wifi reset to apply
1459 char str[MAX_BUF_SIZE]={'\0'};
1460 char cmd[MAX_CMD_SIZE]={'\0'};
1461 struct params params;
1462 char config_file[MAX_BUF_SIZE] = {0};
1463
1464 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1465 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1466 return RETURN_ERR;
1467
1468 if (strlen(CountryCode) == 0)
1469 strcpy(CountryCode, "US");
1470
1471 params.name = "country_code";
1472 params.value = CountryCode;
1473 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1474 int ret = wifi_hostapdWrite(config_file, &params, 1);
1475 if (ret) {
1476 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1477 ,__func__, ret);
1478 }
1479
1480 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1481 if (ret) {
1482 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1483 ,__func__, ret);
1484 }
1485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1486
1487 return RETURN_OK;
1488}
1489
1490INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1491{
1492 char interface_name[16] = {0};
1493 char channel_util_file[64] = {0};
1494 char cmd[128] = {0};
1495 char buf[128] = {0};
1496 char line[128] = {0};
1497 char *param = NULL, *value = NULL;
1498 int read = 0;
1499 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1500 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1501 size_t len = 0;
1502 FILE *f = NULL;
1503
1504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1505
1506 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1507 return RETURN_ERR;
1508 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1509 _syscmd(cmd, buf, sizeof(buf));
1510 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1511
1512 memset(cmd, 0, sizeof(cmd));
1513 memset(buf, 0, sizeof(buf));
1514 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1515 if ((f = popen(cmd, "r")) == NULL) {
1516 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1517 return RETURN_ERR;
1518 }
1519
1520 read = getline(&line, &len, f);
1521 while (read != -1) {
1522 param = strtok(line, ":\t");
1523 value = strtok(NULL, " ");
1524 if(strstr(param, "frequency") != NULL) {
1525 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1526 }
1527 if(strstr(param, "noise") != NULL) {
1528 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1529 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1530 }
1531 if(strstr(param, "channel active time") != NULL) {
1532 ActiveTime = strtol(value, NULL, 10);
1533 }
1534 if(strstr(param, "channel busy time") != NULL) {
1535 BusyTime = strtol(value, NULL, 10);
1536 }
1537 if(strstr(param, "channel transmit time") != NULL) {
1538 TransmitTime = strtol(value, NULL, 10);
1539 }
1540 read = getline(&line, &len, f);
1541 }
1542 pclose(f);
1543
1544 // The file should store the last active, busy and transmit time
1545 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1546 f = fopen(channel_util_file, "r");
1547 if (f != NULL) {
1548 read = getline(&line, &len, f);
1549 preActiveTime = strtol(line, NULL, 10);
1550 read = getline(&line, &len, f);
1551 preBusyTime = strtol(line, NULL, 10);
1552 read = getline(&line, &len, f);
1553 preTransmitTime = strtol(line, NULL, 10);
1554 fclose(f);
1555 }
1556
1557 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1558 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1559
1560 f = fopen(channel_util_file, "w");
1561 if (f != NULL) {
1562 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1563 fclose(f);
1564 }
1565 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1566 return RETURN_OK;
1567}
1568
1569/**********************************************************************************
1570 *
1571 * Wifi radio level function prototypes
1572 *
1573**********************************************************************************/
1574
1575//Get the total number of radios in this wifi subsystem
1576INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1577{
1578 if (NULL == output)
1579 return RETURN_ERR;
1580 *output = MAX_NUM_RADIOS;
1581
1582 return RETURN_OK;
1583}
1584
1585//Get the total number of SSID entries in this wifi subsystem
1586INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1587{
1588 if (NULL == output)
1589 return RETURN_ERR;
1590 *output = MAX_APS;
1591
1592 return RETURN_OK;
1593}
1594
1595//Get the Radio enable config parameter
1596INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1597{
1598 char interface_name[16] = {0};
1599 char buf[128] = {0}, cmd[128] = {0};
1600
1601 if (NULL == output_bool)
1602 return RETURN_ERR;
1603
1604 *output_bool = FALSE;
1605 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1606 return RETURN_ERR;
1607
1608 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1609 return RETURN_ERR;
1610 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1611 _syscmd(cmd, buf, sizeof(buf));
1612
1613 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1614 *output_bool = TRUE;
1615 return RETURN_OK;
1616}
1617
1618INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1619{
1620 char interface_name[16] = {0};
1621 char cmd[MAX_CMD_SIZE] = {0};
1622 char buf[MAX_CMD_SIZE] = {0};
1623 int apIndex, ret;
1624 int max_radio_num = 0;
1625 int phyId = 0;
1626
1627 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1628
1629 phyId = radio_index_to_phy(radioIndex);
1630
1631 wifi_getMaxRadioNumber(&max_radio_num);
1632
1633 if(enable==FALSE)
1634 {
1635 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1636 {
1637 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1638 return RETURN_ERR;
1639
1640 //Detaching %s%d from hostapd daemon
1641 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", interface_name);
1642 _syscmd(cmd, buf, sizeof(buf));
1643 if(strncmp(buf, "OK", 2))
1644 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1645
1646 snprintf(cmd, sizeof(cmd), "iw %s del", interface_name);
1647 _syscmd(cmd, buf, sizeof(buf));
1648 }
1649 }
1650 else
1651 {
1652 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=max_radio_num)
1653 {
1654 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1655 return RETURN_ERR;
1656
1657 snprintf(cmd, sizeof(cmd), "iw phy%d interface add %s type __ap", phyId, interface_name);
1658 ret = _syscmd(cmd, buf, sizeof(buf));
1659 if ( ret == RETURN_ERR)
1660 {
1661 fprintf(stderr, "VAP interface creation failed\n");
1662 continue;
1663 }
1664 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1665 _syscmd(cmd, buf, sizeof(buf));
1666 if(*buf == '1')
1667 {
1668 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1669 phyId, apIndex);
1670 _syscmd(cmd, buf, sizeof(buf));
1671 if(strncmp(buf, "OK", 2))
1672 fprintf(stderr, "Could not detach %s from hostapd daemon", interface_name);
1673 }
1674 }
1675 }
1676
1677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1678 return RETURN_OK;
1679}
1680
1681//Get the Radio enable status
1682INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1683{
1684 if (NULL == output_bool)
1685 return RETURN_ERR;
1686
1687 return wifi_getRadioEnable(radioIndex, output_bool);
1688}
1689
1690//Get the Radio Interface name from platform, eg "wlan0"
1691INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1692{
1693 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1694 return RETURN_ERR;
1695 return wifi_GetInterfaceName(radioIndex, output_string);
1696}
1697
1698//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1699//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.
1700INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1701{
1702 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1703 // For max bit rate, we should always choose the best MCS
1704 char mode[64] = {0};
1705 char channel_bandwidth_str[64] = {0};
1706 char *tmp = NULL;
1707 UINT mode_map = 0;
1708 UINT num_subcarrier = 0;
1709 UINT code_bits = 0;
1710 float code_rate = 0; // use max code rate
1711 int NSS = 0;
1712 UINT Symbol_duration = 0;
1713 UINT GI_duration = 0;
1714 wifi_band band = band_invalid;
1715 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1716 BOOL enable = FALSE;
1717 float bit_rate = 0;
1718
1719 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1720 if (NULL == output_string)
1721 return RETURN_ERR;
1722
1723 wifi_getRadioEnable(radioIndex, &enable);
1724 if (enable == FALSE) {
1725 snprintf(output_string, 64, "0 Mb/s");
1726 return RETURN_OK;
1727 }
1728
1729 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1730 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1731 return RETURN_ERR;
1732 }
1733
1734 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1735 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1736 return RETURN_ERR;
1737 }
1738
1739 if (gi == wifi_guard_interval_3200)
1740 GI_duration = 32;
1741 else if (gi == wifi_guard_interval_1600)
1742 GI_duration = 16;
1743 else if (gi == wifi_guard_interval_800)
1744 GI_duration = 8;
1745 else // auto, 400
1746 GI_duration = 4;
1747
1748 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1749 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1750 return RETURN_ERR;
1751 }
1752
1753 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1754 strcpy(channel_bandwidth_str, "160");
1755
1756 if (mode_map & WIFI_MODE_AX) {
1757 if (strstr(channel_bandwidth_str, "160") != NULL)
1758 num_subcarrier = 1960;
1759 else if (strstr(channel_bandwidth_str, "80") != NULL)
1760 num_subcarrier = 980;
1761 else if (strstr(channel_bandwidth_str, "40") != NULL)
1762 num_subcarrier = 468;
1763 else if (strstr(channel_bandwidth_str, "20") != NULL)
1764 num_subcarrier = 234;
1765 code_bits = 10;
1766 code_rate = (float)5/6;
1767 Symbol_duration = 128;
1768 } else if (mode_map & WIFI_MODE_AC) {
1769 if (strstr(channel_bandwidth_str, "160") != NULL)
1770 num_subcarrier = 468;
1771 else if (strstr(channel_bandwidth_str, "80") != NULL)
1772 num_subcarrier = 234;
1773 else if (strstr(channel_bandwidth_str, "40") != NULL)
1774 num_subcarrier = 108;
1775 else if (strstr(channel_bandwidth_str, "20") != NULL)
1776 num_subcarrier = 52;
1777 code_bits = 8;
1778 code_rate = (float)5/6;
1779 Symbol_duration = 32;
1780 } else if (mode_map & WIFI_MODE_N) {
1781 if (strstr(channel_bandwidth_str, "160") != NULL)
1782 num_subcarrier = 468;
1783 else if (strstr(channel_bandwidth_str, "80") != NULL)
1784 num_subcarrier = 234;
1785 else if (strstr(channel_bandwidth_str, "40") != NULL)
1786 num_subcarrier = 108;
1787 else if (strstr(channel_bandwidth_str, "20") != NULL)
1788 num_subcarrier = 52;
1789 code_bits = 6;
1790 code_rate = (float)3/4;
1791 Symbol_duration = 32;
1792 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1793 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1794 snprintf(output_string, 64, "65 Mb/s");
1795 return RETURN_OK;
1796 } else {
1797 snprintf(output_string, 64, "0 Mb/s");
1798 return RETURN_OK;
1799 }
1800
1801 // Spatial streams
1802 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1803 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1804 return RETURN_ERR;
1805 }
1806
1807 // multiple 10 is to align duration unit (0.1 us)
1808 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1809 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1810
1811 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1812
1813 return RETURN_OK;
1814}
1815#if 0
1816INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1817{
1818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1819 char cmd[64];
1820 char buf[1024];
1821 int apIndex;
1822
1823 if (NULL == output_string)
1824 return RETURN_ERR;
1825
1826 apIndex=(radioIndex==0)?0:1;
1827
1828 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
1829 _syscmd(cmd,buf, sizeof(buf));
1830
1831 snprintf(output_string, 64, "%s", buf);
1832 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1833 return RETURN_OK;
1834}
1835#endif
1836
1837
1838//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1839//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.
1840INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1841{
1842 wifi_band band = band_invalid;
1843
1844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1845 if (NULL == output_string)
1846 return RETURN_ERR;
1847
1848 band = wifi_index_to_band(radioIndex);
1849
1850 memset(output_string, 0, 10);
1851 if (band == band_2_4)
1852 strcpy(output_string, "2.4GHz");
1853 else if (band == band_5)
1854 strcpy(output_string, "5GHz");
1855 else if (band == band_6)
1856 strcpy(output_string, "6GHz");
1857 else
1858 return RETURN_ERR;
1859 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1860
1861 return RETURN_OK;
1862#if 0
1863 char buf[MAX_BUF_SIZE]={'\0'};
1864 char str[MAX_BUF_SIZE]={'\0'};
1865 char cmd[MAX_CMD_SIZE]={'\0'};
1866 char *ch=NULL;
1867 char *ch2=NULL;
1868
1869 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1870 if (NULL == output_string)
1871 return RETURN_ERR;
1872
1873
1874 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1875
1876 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1877 {
1878 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1879 return RETURN_ERR;
1880 }
1881 ch=strchr(buf,'\n');
1882 *ch='\0';
1883 ch=strchr(buf,'=');
1884 if(ch==NULL)
1885 return RETURN_ERR;
1886
1887
1888 ch++;
1889
1890 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1891 strcpy(buf,"0");
1892 if(strlen(ch) == 1)
1893 ch=strcat(buf,ch);
1894
1895
1896 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1897
1898 if(_syscmd(cmd,str,64) == RETURN_ERR)
1899 {
1900 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1901 return RETURN_ERR;
1902 }
1903
1904
1905 ch2=strchr(str,'\n');
1906 //replace \n with \0
1907 *ch2='\0';
1908 ch2=strchr(str,'=');
1909 if(ch2==NULL)
1910 {
1911 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1912 return RETURN_ERR;
1913 }
1914 else
1915 wifi_dbg_printf("%s",ch2+1);
1916
1917
1918 ch2++;
1919
1920
1921 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1922
1923 memset(buf,'\0',sizeof(buf));
1924 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1925 {
1926 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1927 return RETURN_ERR;
1928 }
1929 if (strstr(buf,"2.4") != NULL )
1930 strcpy(output_string,"2.4GHz");
1931 else if(strstr(buf,"5.") != NULL )
1932 strcpy(output_string,"5GHz");
1933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1934
1935 return RETURN_OK;
1936#endif
1937}
1938
1939//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1940//The output_string is a max length 64 octet string that is allocated by the RDKB code. Implementations must ensure that strings are not longer than this.
1941INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1942{
1943 wifi_band band = band_invalid;
1944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1945 if (NULL == output_string)
1946 return RETURN_ERR;
1947 band = wifi_index_to_band(radioIndex);
1948
1949 if (band == band_2_4)
1950 snprintf(output_string, 64, "2.4GHz");
1951 else if (band == band_5)
1952 snprintf(output_string, 64, "5GHz");
1953 else if (band == band_6)
1954 snprintf(output_string, 64, "6GHz");
1955
1956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1957
1958 return RETURN_OK;
1959#if 0
1960 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1961 char buf[MAX_BUF_SIZE]={'\0'};
1962 char str[MAX_BUF_SIZE]={'\0'};
1963 char cmd[MAX_CMD_SIZE]={'\0'};
1964 char *ch=NULL;
1965 char *ch2=NULL;
1966 char ch1[5]="0";
1967
1968 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1969
1970 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1971 {
1972 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1973 return RETURN_ERR;
1974 }
1975
1976 ch=strchr(buf,'\n');
1977 *ch='\0';
1978 ch=strchr(buf,'=');
1979 if(ch==NULL)
1980 return RETURN_ERR;
1981 ch++;
1982
1983 if(strlen(ch)==1)
1984 {
1985 strcat(ch1,ch);
1986
1987 }
1988 else
1989 {
1990 strcpy(ch1,ch);
1991 }
1992
1993
1994
1995 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1996 if(_syscmd(cmd,str,64) == RETURN_ERR)
1997 {
1998 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1999 return RETURN_ERR;
2000 }
2001
2002
2003 ch2=strchr(str,'\n');
2004 //replace \n with \0
2005 *ch2='\0';
2006 ch2=strchr(str,'=');
2007 if(ch2==NULL)
2008 {
2009 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2010 return RETURN_ERR;
2011 }
2012 else
2013 wifi_dbg_printf("%s",ch2+1);
2014 ch2++;
2015
2016
2017 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2018 memset(buf,'\0',sizeof(buf));
2019 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2020 {
2021 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2022 return RETURN_ERR;
2023 }
2024
2025
2026 if(strstr(buf,"2.4")!=NULL)
2027 {
2028 strcpy(output_string,"2.4GHz");
2029 }
2030 if(strstr(buf,"5.")!=NULL)
2031 {
2032 strcpy(output_string,"5GHz");
2033 }
2034 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2035 return RETURN_OK;
2036#endif
2037}
2038
2039//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2040//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.
2041INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2042{
2043 char cmd[128]={0};
2044 char buf[128]={0};
2045 char temp_output[128] = {0};
2046 wifi_band band;
2047 int phyId = 0;
2048
2049 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2050 if (NULL == output_string)
2051 return RETURN_ERR;
2052
2053 band = wifi_index_to_band(radioIndex);
2054 if (band == band_2_4) {
2055 strcat(temp_output, "b,g,");
2056 } else if (band == band_5) {
2057 strcat(temp_output, "a,");
2058 }
2059 phyId = radio_index_to_phy(radioIndex);
2060 // ht capabilities
2061 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);
2062 _syscmd(cmd, buf, sizeof(buf));
2063 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2064 strcat(temp_output, "n,");
2065 }
2066
2067 // vht capabilities
2068 if (band == band_5) {
2069 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2070 _syscmd(cmd, buf, sizeof(buf));
2071 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2072 strcat(temp_output, "ac,");
2073 }
2074 }
2075
2076 // he capabilities
2077 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);
2078 _syscmd(cmd, buf, sizeof(buf));
2079 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2080 strcat(temp_output, "ax,");
2081 }
2082
2083 // Remove the last comma
2084 if (strlen(temp_output) != 0)
2085 temp_output[strlen(temp_output)-1] = '\0';
2086 strncpy(output_string, temp_output, strlen(temp_output));
2087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2088 return RETURN_OK;
2089}
2090
2091//Get the radio operating mode, and pure mode flag. eg: "ac"
2092//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.
2093INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2094{
2095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2096 if (NULL == output_string)
2097 return RETURN_ERR;
2098
2099 if (radioIndex == 0) {
2100 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2101 *gOnly = FALSE;
2102 *nOnly = TRUE;
2103 *acOnly = FALSE;
2104 } else {
2105 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2106 *gOnly = FALSE;
2107 *nOnly = FALSE;
2108 *acOnly = FALSE;
2109 }
2110 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2111
2112 return RETURN_OK;
2113#if 0
2114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2115 char buf[64] = {0};
2116 char config_file[MAX_BUF_SIZE] = {0};
2117
2118 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
2119 return RETURN_ERR;
2120
2121 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2122 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2123
2124 wifi_dbg_printf("\nhw_mode=%s\n",buf);
2125 if (strlen(buf) == 0)
2126 {
2127 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2128 return RETURN_ERR;
2129 }
2130 if(strcmp(buf,"g")==0)
2131 {
2132 wifi_dbg_printf("\nG\n");
2133 *gOnly=TRUE;
2134 *nOnly=FALSE;
2135 *acOnly=FALSE;
2136 }
2137 else if(strcmp(buf,"n")==0)
2138 {
2139 wifi_dbg_printf("\nN\n");
2140 *gOnly=FALSE;
2141 *nOnly=TRUE;
2142 *acOnly=FALSE;
2143 }
2144 else if(strcmp(buf,"ac")==0)
2145 {
2146 wifi_dbg_printf("\nac\n");
2147 *gOnly=FALSE;
2148 *nOnly=FALSE;
2149 *acOnly=TRUE;
2150 }
2151 /* hostapd-5G.conf has "a" as hw_mode */
2152 else if(strcmp(buf,"a")==0)
2153 {
2154 wifi_dbg_printf("\na\n");
2155 *gOnly=FALSE;
2156 *nOnly=FALSE;
2157 *acOnly=FALSE;
2158 }
2159 else
2160 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2161
2162 //for a,n mode
2163 if(radioIndex == 1)
2164 {
2165 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2166 if(strcmp(buf,"1")==0)
2167 {
2168 strncpy(output_string, "n", 1);
2169 *nOnly=FALSE;
2170 }
2171 }
2172
2173 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2175 return RETURN_OK;
2176#endif
2177}
2178
2179INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2180{
2181 char cmd[128] = {0};
2182 char buf[64] = {0};
2183 char config_file[64] = {0};
2184 wifi_band band;
2185
2186 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2187 if(NULL == output_string || NULL == pureMode)
2188 return RETURN_ERR;
2189
2190 // grep all of the ieee80211 protocol config set to 1
2191 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2192 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
2193 _syscmd(cmd, buf, sizeof(buf));
2194
2195 band = wifi_index_to_band(radioIndex);
2196 // puremode is a bit map
2197 *pureMode = 0;
2198 if (band == band_2_4) {
2199 strcat(output_string, "b,g");
2200 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
2201 if (strstr(buf, "n") != NULL) {
2202 strcat(output_string, ",n");
2203 *pureMode |= WIFI_MODE_N;
2204 }
2205 if (strstr(buf, "ax") != NULL) {
2206 strcat(output_string, ",ax");
2207 *pureMode |= WIFI_MODE_AX;
2208 }
2209 } else if (band == band_5) {
2210 strcat(output_string, "a");
2211 *pureMode |= WIFI_MODE_A;
2212 if (strstr(buf, "n") != NULL) {
2213 strcat(output_string, ",n");
2214 *pureMode |= WIFI_MODE_N;
2215 }
2216 if (strstr(buf, "ac") != NULL) {
2217 strcat(output_string, ",ac");
2218 *pureMode |= WIFI_MODE_AC;
2219 }
2220 if (strstr(buf, "ax") != NULL) {
2221 strcat(output_string, ",ax");
2222 *pureMode |= WIFI_MODE_AX;
2223 }
2224 } else if (band == band_6) {
2225 if (strstr(buf, "ax") != NULL) {
2226 strcat(output_string, "ax");
2227 *pureMode |= WIFI_MODE_AX;
2228 }
2229 }
2230
2231 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2232 return RETURN_OK;
2233}
2234
2235// Set the radio operating mode, and pure mode flag.
2236INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2237{
2238 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
2239 if (strcmp (channelMode,"11A") == 0)
2240 {
2241 writeBandWidth(radioIndex,"20MHz");
2242 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2243 printf("\nChannel Mode is 802.11a (5GHz)\n");
2244 }
2245 else if (strcmp (channelMode,"11NAHT20") == 0)
2246 {
2247 writeBandWidth(radioIndex,"20MHz");
2248 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2249 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2250 }
2251 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2252 {
2253 writeBandWidth(radioIndex,"40MHz");
2254 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2255 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2256 }
2257 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2258 {
2259 writeBandWidth(radioIndex,"40MHz");
2260 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2261 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2262 }
2263 else if (strcmp (channelMode,"11ACVHT20") == 0)
2264 {
2265 writeBandWidth(radioIndex,"20MHz");
2266 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2267 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2268 }
2269 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2270 {
2271 writeBandWidth(radioIndex,"40MHz");
2272 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2273 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2274 }
2275 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2276 {
2277 writeBandWidth(radioIndex,"40MHz");
2278 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2279 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2280 }
2281 else if (strcmp (channelMode,"11ACVHT80") == 0)
2282 {
2283 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2284 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2285 }
2286 else if (strcmp (channelMode,"11ACVHT160") == 0)
2287 {
2288 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2289 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
2290 }
2291 else if (strcmp (channelMode,"11B") == 0)
2292 {
2293 writeBandWidth(radioIndex,"20MHz");
2294 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2295 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2296 }
2297 else if (strcmp (channelMode,"11G") == 0)
2298 {
2299 writeBandWidth(radioIndex,"20MHz");
2300 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2301 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2302 }
2303 else if (strcmp (channelMode,"11NGHT20") == 0)
2304 {
2305 writeBandWidth(radioIndex,"20MHz");
2306 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2307 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2308 }
2309 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2310 {
2311 writeBandWidth(radioIndex,"40MHz");
2312 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2313 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2314 }
2315 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2316 {
2317 writeBandWidth(radioIndex,"40MHz");
2318 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2319 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2320 }
2321 else
2322 {
2323 return RETURN_ERR;
2324 }
2325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2326
2327 return RETURN_OK;
2328}
2329
2330// Set the radio operating mode, and pure mode flag.
2331INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2332{
2333 int num_hostapd_support_mode = 3; // n, ac, ax
2334 struct params list[num_hostapd_support_mode];
2335 char config_file[64] = {0};
2336 char bandwidth[16] = {0};
2337 int mode_check_bit = 1 << 3; // n mode
2338
2339
2340 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2341 // Set radio mode
2342 list[0].name = "ieee80211n";
2343 list[1].name = "ieee80211ac";
2344 list[2].name = "ieee80211ax";
2345 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2346
2347 // check the bit map from n to ax, and set hostapd config
2348 if (pureMode & WIFI_MODE_N)
2349 list[0].value = "1";
2350 else
2351 list[0].value = "0";
2352 if (pureMode & WIFI_MODE_AC)
2353 list[1].value = "1";
2354 else
2355 list[1].value = "0";
2356 if (pureMode & WIFI_MODE_AX)
2357 list[2].value = "1";
2358 else
2359 list[2].value = "0";
2360 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2361
2362 if (channelMode == NULL || strlen(channelMode) == 0)
2363 return RETURN_OK;
2364 // Set bandwidth
2365 if (strstr(channelMode, "40") != NULL)
2366 strcpy(bandwidth, "40MHz");
2367 else if (strstr(channelMode, "80") != NULL)
2368 strcpy(bandwidth, "80MHz");
2369 else if (strstr(channelMode, "160") != NULL)
2370 strcpy(bandwidth, "160MHz");
2371 else // 11A, 11B, 11G....
2372 strcpy(bandwidth, "20MHz");
2373
2374 writeBandWidth(radioIndex, bandwidth);
2375 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2376
2377 wifi_reloadAp(radioIndex);
2378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2379
2380 return RETURN_OK;
2381}
2382
2383INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2384
2385 char config_file[64] = {0};
2386 char buf[64] = {0};
2387 struct params params = {0};
2388 wifi_band band = band_invalid;
2389
2390 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2391
2392 band = wifi_index_to_band(radioIndex);
2393
2394 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2395 return RETURN_ERR;
2396 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2397 return RETURN_ERR;
2398 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2399 return RETURN_ERR;
2400
2401 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2402 params.name = "hw_mode";
2403 params.value = hw_mode;
2404 wifi_hostapdWrite(config_file, &params, 1);
2405 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2406
2407 if (band == band_2_4) {
2408 if (strncmp(hw_mode, "b", 1) == 0) {
2409 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2410 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2411 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2412 snprintf(buf, sizeof(buf), "%s", "1,2");
2413 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2414 } else {
2415 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2416
2417 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2418 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2419 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2420 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2421 }
2422 }
2423
2424 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2425 return RETURN_OK;
2426}
2427
2428INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2429{
2430 char config_file[64] = {0};
2431 struct params params = {0};
2432 wifi_band band = band_invalid;
2433
2434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2435
2436 band = wifi_index_to_band(radioIndex);
2437 if (band != band_2_4)
2438 return RETURN_OK;
2439
2440 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2441 params.name = "noscan";
2442 params.value = noscan;
2443 wifi_hostapdWrite(config_file, &params, 1);
2444 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2445
2446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2447 return RETURN_OK;
2448}
2449
2450//Get the list of supported channel. eg: "1-11"
2451//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.
2452INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2453{
2454 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2455 if (NULL == output_string)
2456 return RETURN_ERR;
2457 char cmd[256] = {0};
2458 char buf[128] = {0};
2459 BOOL dfs_enable = false;
2460 int phyId = 0;
2461
2462 // Parse possible channel number and separate them with commas.
2463 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2464 phyId = radio_index_to_phy(radioIndex);
2465 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2466 if (dfs_enable)
2467 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);
2468 else
2469 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);
2470
2471 _syscmd(cmd,buf,sizeof(buf));
2472 strncpy(output_string, buf, sizeof(buf));
2473
2474 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2475 return RETURN_OK;
2476}
2477
2478//Get the list for used channel. eg: "1,6,9,11"
2479//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.
2480INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2481{
2482 char interface_name[16] = {0};
2483 char cmd[128] = {0};
2484 char buf[128] = {0};
2485 char config_file[64] = {0};
2486 int channel = 0;
2487 int freq = 0;
2488 int bandwidth = 0;
2489 int center_freq = 0;
2490 int center_channel = 0;
2491 int channel_delta = 0;
2492 wifi_band band = band_invalid;
2493
2494 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2495
2496 if (NULL == output_string)
2497 return RETURN_ERR;
2498
2499 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2500 return RETURN_ERR;
2501 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2502 _syscmd(cmd, buf, sizeof(buf));
2503 if (strlen(buf) == 0) {
2504 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2505 return RETURN_ERR;
2506 }
2507 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2508
2509 if (bandwidth == 20) {
2510 snprintf(output_string, 256, "%d", channel);
2511 return RETURN_OK;
2512 }
2513
2514 center_channel = ieee80211_frequency_to_channel(center_freq);
2515
2516 band = wifi_index_to_band(radioIndex);
2517 if (band == band_2_4 && bandwidth == 40) {
2518 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2519 memset(buf, 0, sizeof(buf));
2520 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2521
2522 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2523 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2524 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2525 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2526 } else {
2527 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2528 return RETURN_ERR;
2529 }
2530 } else if (band == band_5 || band == band_6){
2531 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2532 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2533 channel_delta = (bandwidth-20)/10;
2534 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2535 } else
2536 return RETURN_ERR;
2537
2538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2539 return RETURN_OK;
2540}
2541
2542//Get the running channel number
2543INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2544{
2545 char channel_str[16] = {0};
2546 char config_file[128] = {0};
2547
2548 if (output_ulong == NULL)
2549 return RETURN_ERR;
2550
2551 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2552 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2553
2554 *output_ulong = strtoul(channel_str, NULL, 10);
2555
2556 return RETURN_OK;
2557}
2558
2559
2560INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2561{
2562 char cmd[1024] = {0}, buf[5] = {0};
2563 char interface_name[16] = {0};
2564
2565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2566 if (NULL == output_ulong)
2567 return RETURN_ERR;
2568
2569 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2570 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2571 return RETURN_ERR;
2572 _syscmd(cmd,buf,sizeof(buf));
2573 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2574 if (*output_ulong == 0) {
2575 return RETURN_ERR;
2576 }
2577
2578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2579 return RETURN_OK;
2580}
2581
2582//Storing the previous channel value
2583INT wifi_storeprevchanval(INT radioIndex)
2584{
2585 char buf[256] = {0};
2586 char output[4]={'\0'};
2587 char config_file[MAX_BUF_SIZE] = {0};
2588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2589 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2590 if(radioIndex == 0)
2591 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2592 else if(radioIndex == 1)
2593 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2594 system(buf);
2595 Radio_flag = FALSE;
2596 return RETURN_OK;
2597}
2598
2599//Set the running channel number
2600INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2601{
2602 // We only write hostapd config here
2603 char str_channel[8]={0};
2604 char *list_channel;
2605 char config_file[128] = {0};
2606 char possible_channels[256] = {0};
2607 int max_radio_num = 0;
2608 struct params list = {0};
2609
2610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2611
2612 // Check valid
2613 sprintf(str_channel, "%lu", channel);
2614
2615 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2616 list_channel = strtok(possible_channels, ",");
2617 while(true)
2618 {
2619 if(list_channel == NULL) { // input not in the list
2620 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2621 return RETURN_ERR;
2622 }
2623 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2624 break;
2625 list_channel = strtok(NULL, ",");
2626 }
2627
2628 list.name = "channel";
2629 list.value = str_channel;
2630 wifi_getMaxRadioNumber(&max_radio_num);
2631 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2632 {
2633 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2634 wifi_hostapdWrite(config_file, &list, 1);
2635 }
2636
2637 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2638 return RETURN_OK;
2639}
2640
2641INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2642{
2643 struct params list[2];
2644 char str_idx[16];
2645 char config_file[64];
2646 int max_num_radios = 0;
2647 wifi_band band = band_invalid;
2648
2649 band = wifi_index_to_band(radioIndex);
2650 if (band == band_2_4)
2651 return RETURN_OK;
2652
2653 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2654 list[0].name = "vht_oper_centr_freq_seg0_idx";
2655 list[0].value = str_idx;
2656 list[1].name = "he_oper_centr_freq_seg0_idx";
2657 list[1].value = str_idx;
2658
2659 wifi_getMaxRadioNumber(&max_num_radios);
2660 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2661 {
2662 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2663 if (band == band_6)
2664 wifi_hostapdWrite(config_file, &list[1], 1);
2665 else
2666 wifi_hostapdWrite(config_file, list, 2);
2667 }
2668
2669 return RETURN_OK;
2670}
2671
2672//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2673//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2674INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2675{
2676 //Set to wifi config only. Wait for wifi reset to apply.
2677 char buf[256] = {0};
2678 char str_channel[256] = {0};
2679 int count = 0;
2680 ULONG Value = 0;
2681 FILE *fp = NULL;
2682 if(enable == TRUE)
2683 {
2684 wifi_setRadioChannel(radioIndex,Value);
2685 }
2686 return RETURN_OK;
2687}
2688
2689INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2690{
2691 if (output_bool == NULL)
2692 return RETURN_ERR;
2693
2694 *output_bool = TRUE;
2695
2696 return RETURN_OK;
2697}
2698
2699INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2700{
2701 if (NULL == output_bool)
2702 return RETURN_ERR;
2703 *output_bool=FALSE;
2704 return RETURN_OK;
2705}
2706
2707INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2708{
2709 if (NULL == output_bool)
2710 return RETURN_ERR;
2711 *output_bool=FALSE;
2712 return RETURN_OK;
2713}
2714
2715INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2716{
2717 //Set to wifi config only. Wait for wifi reset to apply.
2718 return RETURN_OK;
2719}
2720
2721INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2722{
2723 return RETURN_OK;
2724}
2725
2726INT wifi_factoryResetAP(int apIndex)
2727{
2728 char ap_config_file[64] = {0};
2729 char cmd[128] = {0};
2730
2731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2732
2733 wifi_setApEnable(apIndex, FALSE);
2734 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2735 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2736 wifi_setApEnable(apIndex, TRUE);
2737
2738 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2739
2740 return RETURN_OK;
2741}
2742
2743//To set Band Steering AP group
2744//To-do
2745INT wifi_setBandSteeringApGroup(char *ApGroup)
2746{
2747 return RETURN_OK;
2748}
2749
2750INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2751{
2752 char config_file[128] = {'\0'};
2753 char buf[128] = {'\0'};
2754
2755 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2756 if (dtimInterval == NULL)
2757 return RETURN_ERR;
2758
2759 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2760 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2761
2762 if (strlen(buf) == 0) {
2763 *dtimInterval = 2;
2764 } else {
2765 *dtimInterval = strtoul(buf, NULL, 10);
2766 }
2767
2768 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2769 return RETURN_OK;
2770}
2771
2772INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2773{
2774 struct params params={0};
2775 char config_file[MAX_BUF_SIZE] = {'\0'};
2776 char buf[MAX_BUF_SIZE] = {'\0'};
2777
2778 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2779 if (dtimInterval < 1 || dtimInterval > 255) {
2780 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2781 return RETURN_ERR;
2782 }
2783
2784 params.name = "dtim_period";
2785 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2786 params.value = buf;
2787
2788 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2789 wifi_hostapdWrite(config_file, &params, 1);
2790 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2791
2792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2793 return RETURN_OK;
2794}
2795
2796//Check if the driver support the Dfs
2797INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2798{
2799 wifi_band band = band_invalid;
2800 if (NULL == output_bool)
2801 return RETURN_ERR;
2802 *output_bool=FALSE;
2803
2804 band = wifi_index_to_band(radioIndex);
2805 if (band == band_5)
2806 *output_bool = TRUE;
2807 return RETURN_OK;
2808}
2809
2810//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.
2811//The value of this parameter is a comma seperated list of channel number
2812INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2813{
2814 if (NULL == output_pool)
2815 return RETURN_ERR;
2816 if (radioIndex==1)
2817 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2818 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2819
2820 return RETURN_OK;
2821}
2822
2823INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2824{
2825 //Set to wifi config. And apply instantly.
2826 return RETURN_OK;
2827}
2828
2829INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2830{
2831 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2832 return RETURN_ERR;
2833 *output_interval_seconds=1800;
2834 *output_dwell_milliseconds=40;
2835
2836 return RETURN_OK;
2837}
2838
2839INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2840{
2841 //Set to wifi config. And apply instantly.
2842 return RETURN_OK;
2843}
2844
2845INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2846{
2847 if (output_bool == NULL)
2848 return RETURN_ERR;
2849 *output_bool = true;
2850 return RETURN_OK;
2851}
2852
2853INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2854{
2855 return RETURN_OK;
2856}
2857
2858//Get the Dfs enable status
2859INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2860{
2861 char buf[16] = {0};
2862 FILE *f = NULL;
2863
2864 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2865
2866 if (output_bool == NULL)
2867 return RETURN_ERR;
2868
2869 *output_bool = TRUE; // default
2870 f = fopen(DFS_ENABLE_FILE, "r");
2871 if (f != NULL) {
2872 fgets(buf, 2, f);
2873 if (strncmp(buf, "0", 1) == 0)
2874 *output_bool = FALSE;
2875 fclose(f);
2876 }
2877 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2878 return RETURN_OK;
2879}
2880
2881//Set the Dfs enable status
2882INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2883{
2884 char config_file[128] = {0};
2885 FILE *f = NULL;
2886 struct params params={0};
2887
2888 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2889
2890 f = fopen(DFS_ENABLE_FILE, "w");
2891 if (f == NULL)
2892 return RETURN_ERR;
2893 fprintf(f, "%d", enable);
2894 fclose(f);
2895
2896 params.name = "acs_exclude_dfs";
2897 params.value = enable?"0":"1";
2898 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2899 wifi_hostapdWrite(config_file, &params, 1);
2900 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2901
2902 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2903
2904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2905 return RETURN_OK;
2906}
2907
2908//Check if the driver support the AutoChannelRefreshPeriod
2909INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2910{
2911 if (NULL == output_bool)
2912 return RETURN_ERR;
2913 *output_bool=FALSE; //not support
2914
2915 return RETURN_OK;
2916}
2917
2918//Get the ACS refresh period in seconds
2919INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2920{
2921 if (NULL == output_ulong)
2922 return RETURN_ERR;
2923 *output_ulong=300;
2924
2925 return RETURN_OK;
2926}
2927
2928//Set the ACS refresh period in seconds
2929INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2930{
2931 return RETURN_ERR;
2932}
2933
2934//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2935//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.
2936INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2937{
2938 char cmd[128] = {0}, buf[64] = {0};
2939 char extchannel[128] = {0};
2940 char interface_name[64] = {0};
2941 int ret = 0, len=0;
2942 BOOL radio_enable = FALSE;
2943 wifi_band band;
2944
2945 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2946
2947 if (NULL == output_string)
2948 return RETURN_ERR;
2949
2950 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2951 return RETURN_ERR;
2952
2953 if (radio_enable != TRUE)
2954 return RETURN_OK;
2955
2956 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2957 return RETURN_ERR;
2958 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
2959 ret = _syscmd(cmd, buf, sizeof(buf));
2960 len = strlen(buf);
2961 if((ret != 0) || (len == 0))
2962 {
2963 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2964 return RETURN_ERR;
2965 }
2966
2967 band = wifi_index_to_band(radioIndex);
2968 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
2969 wifi_getRadioExtChannel(radioIndex, extchannel);
2970 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
2971 snprintf(buf, sizeof(buf), "40");
2972 }
2973 snprintf(output_string, 64, "%sMHz", buf);
2974 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2975
2976 return RETURN_OK;
2977}
2978
2979//Set the Operating Channel Bandwidth.
2980INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
2981{
2982 char config_file[128];
2983 char set_value[16];
2984 struct params params[2];
2985 int max_radio_num = 0;
2986
2987 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2988
2989 if(NULL == bandwidth)
2990 return RETURN_ERR;
2991
2992 if(strstr(bandwidth,"160") != NULL)
2993 strcpy(set_value, "2");
2994 else if(strstr(bandwidth,"80") != NULL)
2995 strcpy(set_value, "1");
2996 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2997 strcpy(set_value, "0");
2998 else
2999 {
3000 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3001 return RETURN_ERR;
3002 }
3003
3004 params[0].name = "vht_oper_chwidth";
3005 params[0].value = set_value;
3006 params[1].name = "he_oper_chwidth";
3007 params[1].value = set_value;
3008
3009 wifi_getMaxRadioNumber(&max_radio_num);
3010 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3011 {
3012 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3013 wifi_hostapdWrite(config_file, params, 2);
3014 }
3015
3016 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3017 return RETURN_OK;
3018}
3019
3020//Getting current radio extension channel
3021INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3022{
3023 CHAR buf[150] = {0};
3024 CHAR cmd[150] = {0};
3025 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
3026 _syscmd(cmd, buf, sizeof(buf));
3027 if(NULL != strstr(buf,"HT40+"))
3028 strcpy(Value,"AboveControlChannel");
3029 else if(NULL != strstr(buf,"HT40-"))
3030 strcpy(Value,"BelowControlChannel");
3031 return RETURN_OK;
3032}
3033
3034//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3035//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.
3036INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3037{
3038 char config_file[64] = {0};
3039 char mode_str[16] = {0};
3040 char buf[64] = {0};
3041 wifi_band band;
3042 int channel = 0, centr_channel = 0;
3043 UINT mode_map = 0;
3044
3045 if (output_string == NULL)
3046 return RETURN_ERR;
3047
3048 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3049
3050 band = wifi_index_to_band(radioIndex);
3051 if (band == band_invalid)
3052 return RETURN_ERR;
3053
3054 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3055
3056 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003057 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08003058 // 2G band or ac and ax mode is disable, we will check ht_capab
3059 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08003060 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003061 snprintf(output_string, 64, "Auto");
3062 } else {
3063 // 5G and 6G band with ac or ax mode.
3064 wifi_getRadioChannel(radioIndex, &channel);
3065 if (mode_map&WIFI_MODE_AX)
3066 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3067 else
3068 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3069 centr_channel = strtol(buf, NULL, 10);
3070 if (centr_channel > channel)
3071 snprintf(output_string, 64, "AboveControlChannel");
3072 else
3073 snprintf(output_string, 64, "BelowControlChannel");
3074 }
3075
3076 return RETURN_OK;
3077}
3078
3079//Set the extension channel.
3080INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
3081{
3082 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3083 struct params params={0};
3084 char config_file[64] = {0};
3085 char ext_channel[128]={0};
3086 char buf[128] = {0};
3087 char cmd[128] = {0};
3088 int max_radio_num =0, ret = 0, bandwidth = 0;
3089 unsigned long channel = 0, centr_channel = 0;
3090 bool stbcEnable = FALSE;
3091 params.name = "ht_capab";
3092 wifi_band band;
3093
3094 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3095 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3096 _syscmd(cmd, buf, sizeof(buf));
3097 if (strlen(buf) != 0)
3098 stbcEnable = TRUE;
3099 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3100 return RETURN_ERR;
3101 bandwidth = strtol(buf, NULL, 10);
3102 // TDK expected to get error with 20MHz
3103 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3104 return RETURN_ERR;
3105
3106 band = wifi_index_to_band(radioIndex);
3107 if (band == band_invalid)
3108 return RETURN_ERR;
3109
3110 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3111 return RETURN_ERR;
3112
3113 if (band == band_5) {
3114 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3115 centr_channel = util_unii_5g_centerfreq(buf, channel);
3116 if (centr_channel == 0)
3117 return RETURN_ERR;
3118 }
3119
3120 if(NULL!= strstr(string,"Above")) {
3121 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3122 return RETURN_ERR;
3123 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
3124 } else if(NULL!= strstr(string,"Below")) {
3125 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3126 return RETURN_ERR;
3127 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
3128 } else {
3129 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
3130 }
3131
3132 params.value = ext_channel;
3133
3134 wifi_getMaxRadioNumber(&max_radio_num);
3135 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3136 {
3137 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
3138 wifi_hostapdWrite(config_file, &params, 1);
3139 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3140 }
3141
3142 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3143 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3144 return RETURN_OK;
3145}
3146
3147//Get the guard interval value. eg "400nsec" or "800nsec"
3148//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.
3149INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3150{
3151 wifi_guard_interval_t GI;
3152
3153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3154
3155 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3156 return RETURN_ERR;
3157
3158 if (GI == wifi_guard_interval_400)
3159 strcpy(output_string, "400nsec");
3160 else if (GI == wifi_guard_interval_800)
3161 strcpy(output_string, "800nsec");
3162 else if (GI == wifi_guard_interval_1600)
3163 strcpy(output_string, "1600nsec");
3164 else if (GI == wifi_guard_interval_3200)
3165 strcpy(output_string, "3200nsec");
3166 else
3167 strcpy(output_string, "Auto");
3168
3169 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3170 return RETURN_OK;
3171}
3172
3173//Set the guard interval value.
3174INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3175{
3176 wifi_guard_interval_t GI;
3177 int ret = 0;
3178
3179 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3180
3181 if (strcmp(string, "400nsec") == 0)
3182 GI = wifi_guard_interval_400;
3183 else if (strcmp(string , "800nsec") == 0)
3184 GI = wifi_guard_interval_800;
3185 else if (strcmp(string , "1600nsec") == 0)
3186 GI = wifi_guard_interval_1600;
3187 else if (strcmp(string , "3200nsec") == 0)
3188 GI = wifi_guard_interval_3200;
3189 else
3190 GI = wifi_guard_interval_auto;
3191
3192 ret = wifi_setGuardInterval(radioIndex, GI);
3193
3194 if (ret == RETURN_ERR) {
3195 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3196 return RETURN_ERR;
3197 }
3198
3199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3200 return RETURN_OK;
3201}
3202
3203//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3204INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3205{
3206 char buf[32]={0};
3207 char mcs_file[64] = {0};
3208 char cmd[64] = {0};
3209 int mode_bitmap = 0;
3210
3211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3212 if(output_int == NULL)
3213 return RETURN_ERR;
3214 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3215
3216 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3217 _syscmd(cmd, buf, sizeof(buf));
3218 if (strlen(buf) > 0)
3219 *output_int = strtol(buf, NULL, 10);
3220 else {
3221 // output the max MCS for the current radio mode
3222 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3223 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3224 return RETURN_ERR;
3225 }
3226 if (mode_bitmap & WIFI_MODE_AX) {
3227 *output_int = 11;
3228 } else if (mode_bitmap & WIFI_MODE_AC) {
3229 *output_int = 9;
3230 } else if (mode_bitmap & WIFI_MODE_N) {
3231 *output_int = 7;
3232 }
3233 }
3234 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3235
3236 return RETURN_OK;
3237}
3238
3239//Set the Modulation Coding Scheme index
3240INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3241{
3242 // 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).
3243 char config_file[64] = {0};
3244 char set_value[16] = {0};
3245 char mcs_file[32] = {0};
3246 wifi_band band = band_invalid;
3247 struct params set_config = {0};
3248 FILE *f = NULL;
3249
3250 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3251
3252 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3253
3254 // -1 means auto
3255 if (MCS > 15 || MCS < -1) {
3256 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3257 return RETURN_ERR;
3258 }
3259
3260 if (MCS > 9 || MCS == -1)
3261 strcpy(set_value, "2");
3262 else if (MCS > 7)
3263 strcpy(set_value, "1");
3264 else
3265 strcpy(set_value, "0");
3266
3267 set_config.name = "he_basic_mcs_nss_set";
3268 set_config.value = set_value;
3269
3270 wifi_hostapdWrite(config_file, &set_config, 1);
3271 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3272
3273 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3274 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3275 f = fopen(mcs_file, "w");
3276 if (f == NULL) {
3277 fprintf(stderr, "%s: fopen failed\n", __func__);
3278 return RETURN_ERR;
3279 }
3280 fprintf(f, "%d", MCS);
3281 fclose(f);
3282
3283 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3284 return RETURN_OK;
3285}
3286
3287//Get supported Transmit Power list, eg : "0,25,50,75,100"
3288//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.
3289INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3290{
3291 if (NULL == output_list)
3292 return RETURN_ERR;
3293 snprintf(output_list, 64,"0,25,50,75,100");
3294 return RETURN_OK;
3295}
3296
3297//Get current Transmit Power in dBm units.
3298//The transmite power level is in units of full power for this radio.
3299INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3300{
3301 char interface_name[16] = {0};
3302 char cmd[128]={0};
3303 char buf[16]={0};
3304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3305
3306 if(output_ulong == NULL)
3307 return RETURN_ERR;
3308
3309 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3310 return RETURN_ERR;
3311 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3312 _syscmd(cmd, buf, sizeof(buf));
3313
3314 *output_ulong = strtol(buf, NULL, 10);
3315
3316 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3317 return RETURN_OK;
3318}
3319
3320//Set Transmit Power
3321//The transmite power level is in units of full power for this radio.
3322INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3323{
3324 char interface_name[16] = {0};
3325 char *support;
3326 char cmd[128]={0};
3327 char buf[128]={0};
3328 char txpower_str[64] = {0};
3329 int txpower = 0;
3330 int maximum_tx = 0;
3331 int phyId = 0;
3332
3333 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3334
3335 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3336 return RETURN_ERR;
3337 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
3338 _syscmd(cmd, buf, sizeof(buf));
3339 maximum_tx = strtol(buf, NULL, 10);
3340
3341 // Get the Tx power supported list and check that is the input in the list
3342 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3343 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3344 support = strtok(buf, ",");
3345 while(true)
3346 {
3347 if(support == NULL) { // input not in the list
3348 wifi_dbg_printf("Input value is invalid.\n");
3349 return RETURN_ERR;
3350 }
3351 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3352 break;
3353 }
3354 support = strtok(NULL, ",");
3355 }
3356 txpower = TransmitPower*maximum_tx/100;
3357 phyId = radio_index_to_phy(radioIndex);
3358 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3359 _syscmd(cmd, buf, sizeof(buf));
3360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3361
3362 return RETURN_OK;
3363}
3364
3365//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3366INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3367{
3368 if (NULL == Supported)
3369 return RETURN_ERR;
3370 *Supported = TRUE;
3371
3372 return RETURN_OK;
3373}
3374
3375//Get 80211h feature enable
3376INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3377{
3378 char buf[64]={'\0'};
3379 char config_file[64] = {'\0'};
3380
3381 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3382 if(enable == NULL)
3383 return RETURN_ERR;
3384
3385 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3386 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3387
3388 if (strncmp(buf, "1", 1) == 0)
3389 *enable = TRUE;
3390 else
3391 *enable = FALSE;
3392
3393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3394 return RETURN_OK;
3395}
3396
3397//Set 80211h feature enable
3398INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3399{
3400 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3401 struct params params={'\0'};
3402 char config_file[MAX_BUF_SIZE] = {0};
3403
3404 params.name = "ieee80211h";
3405
3406 if (enable) {
3407 params.value = "1";
3408 } else {
3409 params.value = "0";
3410 }
3411
3412 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3413 wifi_hostapdWrite(config_file, &params, 1);
3414
3415 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3416 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3417 return RETURN_OK;
3418}
3419
3420//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.
3421INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3422{
3423 if (NULL == output)
3424 return RETURN_ERR;
3425 *output=100;
3426
3427 return RETURN_OK;
3428}
3429
3430//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.
3431INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3432{
3433 if (NULL == output)
3434 return RETURN_ERR;
3435 *output = -99;
3436
3437 return RETURN_OK;
3438}
3439
3440INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3441{
3442 return RETURN_ERR;
3443}
3444
3445
3446//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3447INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3448{
3449 char interface_name[16] = {0};
3450 char cmd[MAX_BUF_SIZE]={'\0'};
3451 char buf[MAX_CMD_SIZE]={'\0'};
3452
3453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3454 if(output == NULL)
3455 return RETURN_ERR;
3456
3457 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3458 return RETURN_ERR;
3459 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3460 _syscmd(cmd, buf, sizeof(buf));
3461 *output = atoi(buf);
3462
3463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3464 return RETURN_OK;
3465}
3466
3467INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3468{
3469 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3470 struct params params={'\0'};
3471 char buf[MAX_BUF_SIZE] = {'\0'};
3472 char config_file[MAX_BUF_SIZE] = {'\0'};
3473
3474 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3475 return RETURN_ERR;
3476
3477 params.name = "beacon_int";
3478 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3479 params.value = buf;
3480
3481 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3482 wifi_hostapdWrite(config_file, &params, 1);
3483
3484 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3485 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3486 return RETURN_OK;
3487}
3488
3489//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.
3490INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3491{
3492 //TODO: need to revisit below implementation
3493 char *temp;
3494 char temp_output[128] = {0};
3495 char temp_TransmitRates[64] = {0};
3496 char config_file[64] = {0};
3497
3498 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3499 if (NULL == output)
3500 return RETURN_ERR;
3501 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3502 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3503
3504 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3505 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3506 } else {
3507 temp = strtok(temp_TransmitRates," ");
3508 while(temp!=NULL)
3509 {
3510 // Convert 100 kbps to Mbps
3511 temp[strlen(temp)-1]=0;
3512 if((temp[0]=='5') && (temp[1]=='\0'))
3513 {
3514 temp="5.5";
3515 }
3516 strcat(temp_output,temp);
3517 temp = strtok(NULL," ");
3518 if(temp!=NULL)
3519 {
3520 strcat(temp_output,",");
3521 }
3522 }
3523 strcpy(output,temp_output);
3524 }
3525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3526 return RETURN_OK;
3527}
3528
3529INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3530{
3531 char *temp;
3532 char temp1[128];
3533 char temp_output[128];
3534 char temp_TransmitRates[128];
3535 char set[128];
3536 char sub_set[128];
3537 int set_count=0,subset_count=0;
3538 int set_index=0,subset_index=0;
3539 char *token;
3540 int flag=0, i=0;
3541 struct params params={'\0'};
3542 char config_file[MAX_BUF_SIZE] = {0};
3543 wifi_band band = wifi_index_to_band(radioIndex);
3544
3545 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3546 if(NULL == TransmitRates)
3547 return RETURN_ERR;
3548 strcpy(sub_set,TransmitRates);
3549
3550 //Allow only supported Data transmit rate to be set
3551 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3552 token = strtok(sub_set,",");
3553 while( token != NULL ) /* split the basic rate to be set, by comma */
3554 {
3555 sub_set[subset_count]=atoi(token);
3556 subset_count++;
3557 token=strtok(NULL,",");
3558 }
3559 token=strtok(set,",");
3560 while(token!=NULL) /* split the supported rate by comma */
3561 {
3562 set[set_count]=atoi(token);
3563 set_count++;
3564 token=strtok(NULL,",");
3565 }
3566 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3567 {
3568 for(set_index=0;set_index < set_count;set_index++)
3569 {
3570 flag=0;
3571 if(sub_set[subset_index]==set[set_index])
3572 break;
3573 else
3574 flag=1; /* No match found */
3575 }
3576 if(flag==1)
3577 return RETURN_ERR; //If value not found return Error
3578 }
3579 strcpy(temp_TransmitRates,TransmitRates);
3580
3581 for(i=0;i<strlen(temp_TransmitRates);i++)
3582 {
3583 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3584 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3585 {
3586 continue;
3587 }
3588 else
3589 {
3590 return RETURN_ERR;
3591 }
3592 }
3593 strcpy(temp_output,"");
3594 temp = strtok(temp_TransmitRates,",");
3595 while(temp!=NULL)
3596 {
3597 strcpy(temp1,temp);
3598 if(band == band_5)
3599 {
3600 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3601 {
3602 return RETURN_ERR;
3603 }
3604 }
3605
3606 if(strcmp(temp,"5.5")==0)
3607 {
3608 strcpy(temp1,"55");
3609 }
3610 else
3611 {
3612 strcat(temp1,"0");
3613 }
3614 strcat(temp_output,temp1);
3615 temp = strtok(NULL,",");
3616 if(temp!=NULL)
3617 {
3618 strcat(temp_output," ");
3619 }
3620 }
3621 strcpy(TransmitRates,temp_output);
3622
3623 params.name= "basic_rates";
3624 params.value =TransmitRates;
3625
3626 wifi_dbg_printf("\n%s:",__func__);
3627 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3628 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3629 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3630 wifi_hostapdWrite(config_file,&params,1);
3631 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3632 return RETURN_OK;
3633}
3634
3635//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3636INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3637{
3638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3639 FILE *fp = NULL;
3640 char path[256] = {0}, output_string[256] = {0};
3641 int count = 0;
3642 char *interface = NULL;
3643
3644 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3645 if (fp == NULL)
3646 {
3647 printf("Failed to run command in Function %s\n", __FUNCTION__);
3648 return RETURN_ERR;
3649 }
3650 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3651 {
3652 interface = strchr(path, '=');
3653
3654 if (interface != NULL)
3655 {
3656 strcpy(output_string, interface + 1);
3657 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3658 interface_name[count] = output_string[count];
3659
3660 interface_name[count] = '\0';
3661 }
3662 }
3663 pclose(fp);
3664 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3665 return RETURN_OK;
3666}
3667
3668INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3669{
3670 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3671 output_struct->radio_BytesSent = 0;
3672 output_struct->radio_BytesReceived = 0;
3673 output_struct->radio_PacketsSent = 0;
3674 output_struct->radio_PacketsReceived = 0;
3675 output_struct->radio_ErrorsSent = 0;
3676 output_struct->radio_ErrorsReceived = 0;
3677 output_struct->radio_DiscardPacketsSent = 0;
3678 output_struct->radio_DiscardPacketsReceived = 0;
3679 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3680 return RETURN_OK;
3681}
3682
3683
3684INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3685{
3686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3687 CHAR buf[MAX_CMD_SIZE] = {0};
3688 CHAR Value[MAX_BUF_SIZE] = {0};
3689 FILE *fp = NULL;
3690
3691 if (ifname == NULL || strlen(ifname) <= 1)
3692 return RETURN_OK;
3693
3694 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3695 system(buf);
3696
3697 fp = fopen("/tmp/Radio_Stats.txt", "r");
3698 if(fp == NULL)
3699 {
3700 printf("/tmp/Radio_Stats.txt not exists \n");
3701 return RETURN_ERR;
3702 }
3703 fclose(fp);
3704
3705 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3706 File_Reading(buf, Value);
3707 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3708
3709 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3710 File_Reading(buf, Value);
3711 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3712
3713 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3714 File_Reading(buf, Value);
3715 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3716
3717 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3718 File_Reading(buf, Value);
3719 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3720
3721 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3722 File_Reading(buf, Value);
3723 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3724
3725 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3726 File_Reading(buf, Value);
3727 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3728
3729 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3730 File_Reading(buf, Value);
3731 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3732
3733 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3734 File_Reading(buf, Value);
3735 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3736
3737 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3738 return RETURN_OK;
3739}
3740
3741INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3742{
3743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3744 CHAR buf[MAX_CMD_SIZE] = {0};
3745 FILE *fp = NULL;
3746 INT count = 0;
3747
3748 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3749 {
3750 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3751 File_Reading(buf, status);
3752 }
3753 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3754 return RETURN_OK;
3755}
3756
3757//Get detail radio traffic static info
3758INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3759{
3760
3761#if 0
3762 //ifconfig radio_x
3763 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3764 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3765 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3766 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3767
3768 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3769 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3770 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.
3771 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.
3772
3773 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3774 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].
3775 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3776 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.
3777 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
3778 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
3779 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
3780 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
3781 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
3782
3783 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
3784 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
3785 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
3786 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.
3787
3788 return RETURN_OK;
3789#endif
3790
3791 CHAR interface_name[64] = {0};
3792 BOOL iface_status = FALSE;
3793 wifi_radioTrafficStats2_t radioTrafficStats = {0};
3794
3795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3796 if (NULL == output_struct)
3797 return RETURN_ERR;
3798
3799 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3800 return RETURN_ERR;
3801
3802 wifi_getApEnable(radioIndex, &iface_status);
3803
3804 if (iface_status == TRUE)
3805 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3806 else
3807 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
3808
3809 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3810 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3811 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3812 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3813 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3814 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3815 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3816 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
3817
3818 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3819 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].
3820 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3821 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.
3822 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
3823 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
3824 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
3825 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
3826 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
3827
3828 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
3829 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
3830 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
3831 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.
3832
3833 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3834
3835 return RETURN_OK;
3836}
3837
3838//Set radio traffic static Measureing rules
3839INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3840{
3841 //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
3842 // Else, save the MeasuringRate and MeasuringInterval for future usage
3843
3844 return RETURN_OK;
3845}
3846
3847//To start or stop RadioTrafficStats
3848INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3849{
3850 //zqiu: If the RadioTrafficStats process running
3851 // if(enable)
3852 // return RETURN_OK.
3853 // else
3854 // Stop RadioTrafficStats process
3855 // Else
3856 // if(enable)
3857 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3858 // else
3859 // return RETURN_OK.
3860
3861 return RETURN_OK;
3862}
3863
3864//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
3865INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3866{
3867 //zqiu: Please ignor signalIndex.
3868 if (NULL == SignalLevel)
3869 return RETURN_ERR;
3870 *SignalLevel=(radioIndex==0)?-19:-19;
3871
3872 return RETURN_OK;
3873}
3874
3875//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3876INT wifi_applyRadioSettings(INT radioIndex)
3877{
3878 return RETURN_OK;
3879}
3880
3881//Get the radio index assocated with this SSID entry
3882INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3883{
3884 if(NULL == radioIndex)
3885 return RETURN_ERR;
3886 int max_radio_num = 0;
3887 wifi_getMaxRadioNumber(&max_radio_num);
3888 *radioIndex = ssidIndex%max_radio_num;
3889 return RETURN_OK;
3890}
3891
3892//Device.WiFi.SSID.{i}.Enable
3893//Get SSID enable configuration parameters (not the SSID enable status)
3894INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3895{
3896 if (NULL == output_bool)
3897 return RETURN_ERR;
3898
3899 return wifi_getApEnable(ssidIndex, output_bool);
3900}
3901
3902//Device.WiFi.SSID.{i}.Enable
3903//Set SSID enable configuration parameters
3904INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3905{
3906 return wifi_setApEnable(ssidIndex, enable);
3907}
3908
3909//Device.WiFi.SSID.{i}.Status
3910//Get the SSID enable status
3911INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3912{
3913 char cmd[MAX_CMD_SIZE]={0};
3914 char buf[MAX_BUF_SIZE]={0};
3915 BOOL output_bool;
3916
3917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3918 if (NULL == output_string)
3919 return RETURN_ERR;
3920
3921 wifi_getApEnable(ssidIndex,&output_bool);
3922 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3923
3924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3925 return RETURN_OK;
3926}
3927
3928// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3929INT wifi_getSSIDName(INT apIndex, CHAR *output)
3930{
3931 char config_file[MAX_BUF_SIZE] = {0};
3932
3933 if (NULL == output)
3934 return RETURN_ERR;
3935
3936 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3937 wifi_hostapdRead(config_file,"ssid",output,32);
3938
3939 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3940 return RETURN_OK;
3941}
3942
3943// Set a max 32 byte string and sets an internal variable to the SSID name
3944INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3945{
3946 char str[MAX_BUF_SIZE]={'\0'};
3947 char cmd[MAX_CMD_SIZE]={'\0'};
3948 struct params params;
3949 char config_file[MAX_BUF_SIZE] = {0};
3950
3951 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3952 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3953 return RETURN_ERR;
3954
3955 params.name = "ssid";
3956 params.value = ssid_string;
3957 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3958 wifi_hostapdWrite(config_file, &params, 1);
3959 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3961
3962 return RETURN_OK;
3963}
3964
3965//Get the BSSID
3966INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3967{
3968 char cmd[MAX_CMD_SIZE]="";
3969
3970 if (NULL == output_string)
3971 return RETURN_ERR;
3972
3973 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3974 {
3975 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
3976 _syscmd(cmd, output_string, 64);
3977 return RETURN_OK;
3978 }
3979 strncpy(output_string, "\0", 1);
3980
3981 return RETURN_ERR;
3982}
3983
3984//Get the MAC address associated with this Wifi SSID
3985INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3986{
3987 wifi_getBaseBSSID(ssidIndex,output_string);
3988 return RETURN_OK;
3989}
3990
3991//Get the basic SSID traffic static info
3992//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3993//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3994INT wifi_applySSIDSettings(INT ssidIndex)
3995{
3996 char interface_name[16] = {0};
3997 BOOL status = false;
3998 char cmd[MAX_CMD_SIZE] = {0};
3999 char buf[MAX_CMD_SIZE] = {0};
4000 int apIndex, ret;
4001 int max_radio_num = 0;
4002 int radioIndex = 0;
4003
4004 wifi_getMaxRadioNumber(&max_radio_num);
4005
4006 radioIndex = ssidIndex % max_radio_num;
4007
4008 wifi_getApEnable(ssidIndex,&status);
4009 // Do not apply when ssid index is disabled
4010 if (status == false)
4011 return RETURN_OK;
4012
4013 /* Doing full remove and add for ssid Index
4014 * Not all hostapd options are supported with reload
4015 * for example macaddr_acl
4016 */
4017 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4018 return RETURN_ERR;
4019
4020 ret = wifi_setApEnable(ssidIndex,true);
4021
4022 /* Workaround for hostapd issue with multiple bss definitions
4023 * when first created interface will be removed
4024 * then all vaps other vaps on same phy are removed
4025 * after calling setApEnable to false readd all enabled vaps */
4026 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4027 apIndex = max_radio_num*i+radioIndex;
4028 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4029 return RETURN_ERR;
4030 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4031 _syscmd(cmd, buf, sizeof(buf));
4032 if(*buf == '1')
4033 wifi_setApEnable(apIndex, true);
4034 }
4035
4036 return ret;
4037}
4038
4039struct channels_noise {
4040 int channel;
4041 int noise;
4042};
4043
4044// Return noise array for each channel
4045int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4046{
4047 char interface_name[16] = {0};
4048 FILE *f = NULL;
4049 char cmd[128] = {0};
4050 char line[256] = {0};
4051 size_t len = 0;
4052 ssize_t read = 0;
4053 int tmp = 0, arr_index = -1;
4054
4055 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4056 return RETURN_ERR;
4057 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4058
4059 if ((f = popen(cmd, "r")) == NULL) {
4060 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4061 return RETURN_ERR;
4062 }
4063
4064 while(fgets(line, sizeof(line), f) != NULL) {
4065 if(arr_index < channels_num){
4066 sscanf(line, "%d", &tmp);
4067 if (tmp > 0) { // channel frequency, the first line must be frequency
4068 arr_index++;
4069 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4070 } else { // noise
4071 channels_noise_arr[arr_index].noise = tmp;
4072 }
4073 }else{
4074 break;
4075 }
4076 }
4077 pclose(f);
4078 return RETURN_OK;
4079}
4080
4081//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4082//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
4083INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
4084{
4085 int index = -1;
4086 wifi_neighbor_ap2_t *scan_array = NULL;
4087 char cmd[256]={0};
4088 char buf[128]={0};
4089 char file_name[32] = {0};
4090 char filter_SSID[32] = {0};
4091 char line[256] = {0};
4092 char interface_name[16] = {0};
4093 char *ret = NULL;
4094 int freq=0;
4095 FILE *f = NULL;
4096 size_t len=0;
4097 int channels_num = 0;
4098 int vht_channel_width = 0;
4099 int get_noise_ret = RETURN_ERR;
4100 bool filter_enable = false;
4101 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4102 int phyId = 0;
4103
4104 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4105
4106 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4107 return RETURN_ERR;
4108
4109 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4110 f = fopen(file_name, "r");
4111 if (f != NULL) {
4112 fgets(filter_SSID, sizeof(file_name), f);
4113 if (strlen(filter_SSID) != 0)
4114 filter_enable = true;
4115 fclose(f);
4116 }
4117
4118 phyId = radio_index_to_phy(radioIndex);
4119 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4120 _syscmd(cmd, buf, sizeof(buf));
4121 channels_num = strtol(buf, NULL, 10);
4122
4123
4124
4125 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4126 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4127 fprintf(stderr, "cmd: %s\n", cmd);
4128 if ((f = popen(cmd, "r")) == NULL) {
4129 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4130 return RETURN_ERR;
4131 }
4132
4133 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4134 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
4135
4136 ret = fgets(line, sizeof(line), f);
4137 while (ret != NULL) {
4138 if(strstr(line, "BSS") != NULL) { // new neighbor info
4139 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
4140 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4141 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4142
4143 if (!filter_BSS) {
4144 index++;
4145 wifi_neighbor_ap2_t *tmp;
4146 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4147 if (tmp == NULL) { // no more memory to use
4148 index--;
4149 wifi_dbg_printf("%s: realloc failed\n", __func__);
4150 break;
4151 }
4152 scan_array = tmp;
4153 }
4154 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4155
4156 filter_BSS = false;
4157 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4158 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4159 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4160 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4161 } else if (strstr(line, "freq") != NULL) {
4162 sscanf(line," freq: %d", &freq);
4163 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4164
4165 if (freq >= 2412 && freq <= 2484) {
4166 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4167 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4168 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4169 }
4170 else if (freq >= 5160 && freq <= 5805) {
4171 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4172 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4173 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4174 }
4175
4176 scan_array[index].ap_Noise = 0;
4177 if (get_noise_ret == RETURN_OK) {
4178 for (int i = 0; i < channels_num; i++) {
4179 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4180 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4181 break;
4182 }
4183 }
4184 }
4185 } else if (strstr(line, "beacon interval") != NULL) {
4186 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4187 } else if (strstr(line, "signal") != NULL) {
4188 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4189 } else if (strstr(line,"SSID") != NULL) {
4190 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4191 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4192 filter_BSS = true;
4193 }
4194 } else if (strstr(line, "Supported rates") != NULL) {
4195 char SRate[80] = {0}, *tmp = NULL;
4196 memset(buf, 0, sizeof(buf));
4197 strcpy(SRate, line);
4198 tmp = strtok(SRate, ":");
4199 tmp = strtok(NULL, ":");
4200 strcpy(buf, tmp);
4201 memset(SRate, 0, sizeof(SRate));
4202
4203 tmp = strtok(buf, " \n");
4204 while (tmp != NULL) {
4205 strcat(SRate, tmp);
4206 if (SRate[strlen(SRate) - 1] == '*') {
4207 SRate[strlen(SRate) - 1] = '\0';
4208 }
4209 strcat(SRate, ",");
4210
4211 tmp = strtok(NULL, " \n");
4212 }
4213 SRate[strlen(SRate) - 1] = '\0';
4214 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4215 } else if (strstr(line, "DTIM") != NULL) {
4216 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4217 } else if (strstr(line, "VHT capabilities") != NULL) {
4218 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4219 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4220 } else if (strstr(line, "HT capabilities") != NULL) {
4221 strcat(scan_array[index].ap_SupportedStandards, ",n");
4222 strcpy(scan_array[index].ap_OperatingStandards, "n");
4223 } else if (strstr(line, "VHT operation") != NULL) {
4224 ret = fgets(line, sizeof(line), f);
4225 sscanf(line," * channel width: %d", &vht_channel_width);
4226 if(vht_channel_width == 1) {
4227 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4228 } else {
4229 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4230 }
4231 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4232 continue;
4233 } else if (strstr(line, "HT operation") != NULL) {
4234 ret = fgets(line, sizeof(line), f);
4235 sscanf(line," * secondary channel offset: %s", &buf);
4236 if (!strcmp(buf, "above")) {
4237 //40Mhz +
4238 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4239 }
4240 else if (!strcmp(buf, "below")) {
4241 //40Mhz -
4242 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4243 } else {
4244 //20Mhz
4245 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4246 }
4247 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4248 continue;
4249 } else if (strstr(line, "HE capabilities") != NULL) {
4250 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4251 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4252 ret = fgets(line, sizeof(line), f);
4253 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4254 if (strstr(line, "HE40/2.4GHz") != NULL)
4255 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4256 else
4257 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4258 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4259 if (strstr(line, "HE80/5GHz") != NULL) {
4260 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4261 ret = fgets(line, sizeof(line), f);
4262 } else
4263 continue;
4264 if (strstr(line, "HE160/5GHz") != NULL)
4265 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4266 }
4267 continue;
4268 } else if (strstr(line, "WPA") != NULL) {
4269 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4270 } else if (strstr(line, "RSN") != NULL) {
4271 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4272 } else if (strstr(line, "Group cipher") != NULL) {
4273 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4274 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4275 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4276 }
4277 }
4278 ret = fgets(line, sizeof(line), f);
4279 }
4280
4281 if (!filter_BSS) {
4282 *output_array_size = index + 1;
4283 } else {
4284 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4285 *output_array_size = index;
4286 }
4287 *neighbor_ap_array = scan_array;
4288 pclose(f);
4289 free(channels_noise_arr);
4290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4291 return RETURN_OK;
4292}
4293
4294//>> Deprecated: used for old RDKB code.
4295INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4296{
4297 INT status = RETURN_ERR;
4298
4299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4300 output_struct->wifi_PLCPErrorCount = 0;
4301 output_struct->wifi_FCSErrorCount = 0;
4302 output_struct->wifi_InvalidMACCount = 0;
4303 output_struct->wifi_PacketsOtherReceived = 0;
4304 output_struct->wifi_Noise = 0;
4305 status = RETURN_OK;
4306 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4307 return status;
4308}
4309
4310INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4311{
4312 char interface_name[16] = {0};
4313 char cmd[128] = {0};
4314 char buf[1280] = {0};
4315 char *pos = NULL;
4316
4317 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4318 if (NULL == output_struct)
4319 return RETURN_ERR;
4320
4321 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4322 return RETURN_ERR;
4323
4324 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4325
4326 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4327 _syscmd(cmd, buf, sizeof(buf));
4328
4329 pos = buf;
4330 if ((pos = strstr(pos, "RX packets:")) == NULL)
4331 return RETURN_ERR;
4332 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4333
4334 if ((pos = strstr(pos, "TX packets:")) == NULL)
4335 return RETURN_ERR;
4336 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4337
4338 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4339 return RETURN_ERR;
4340 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4341
4342 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4343 return RETURN_ERR;
4344 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4345
4346 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4347 _syscmd(cmd, buf, sizeof(buf));
4348 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4349
4350#if 0
4351 //TODO: need to revisit below implementation
4352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4353 char interface_name[MAX_BUF_SIZE] = {0};
4354 char interface_status[MAX_BUF_SIZE] = {0};
4355 char Value[MAX_BUF_SIZE] = {0};
4356 char buf[MAX_CMD_SIZE] = {0};
4357 char cmd[MAX_CMD_SIZE] = {0};
4358 FILE *fp = NULL;
4359
4360 if (NULL == output_struct) {
4361 return RETURN_ERR;
4362 }
4363
4364 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4365
4366 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4367 {
4368 if(apIndex == 0) //private_wifi for 2.4G
4369 {
4370 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4371 }
4372 else if(apIndex == 1) //private_wifi for 5G
4373 {
4374 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4375 }
4376 else if(apIndex == 4) //public_wifi for 2.4G
4377 {
4378 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4379 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4380 {
4381 return RETURN_ERR;
4382 }
4383 if(buf[0] == '#')//tp-link
4384 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4385 else//tenda
4386 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4387 }
4388 else if(apIndex == 5) //public_wifi for 5G
4389 {
4390 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4391 }
4392
4393 GetIfacestatus(interface_name, interface_status);
4394
4395 if(0 != strcmp(interface_status, "1"))
4396 return RETURN_ERR;
4397
4398 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4399 system(cmd);
4400
4401 fp = fopen("/tmp/SSID_Stats.txt", "r");
4402 if(fp == NULL)
4403 {
4404 printf("/tmp/SSID_Stats.txt not exists \n");
4405 return RETURN_ERR;
4406 }
4407 fclose(fp);
4408
4409 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4410 File_Reading(buf, Value);
4411 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4412
4413 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4414 File_Reading(buf, Value);
4415 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4416
4417 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4418 File_Reading(buf, Value);
4419 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4420
4421 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4422 File_Reading(buf, Value);
4423 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4424
4425 /* There is no specific parameter from caller to associate the value wifi_Associations */
4426 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4427 //_syscmd(cmd, buf, sizeof(buf));
4428 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4429 }
4430#endif
4431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4432 return RETURN_OK;
4433}
4434
4435INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4436{
4437 char interface_name[MAX_BUF_SIZE] = {0};
4438 char interface_status[MAX_BUF_SIZE] = {0};
4439 char Value[MAX_BUF_SIZE] = {0};
4440 char buf[MAX_CMD_SIZE] = {0};
4441 char cmd[MAX_CMD_SIZE] = {0};
4442 FILE *fp = NULL;
4443
4444 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4445 if (NULL == output_struct)
4446 return RETURN_ERR;
4447
4448 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4449
4450 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4451 return RETURN_ERR;
4452 GetIfacestatus(interface_name, interface_status);
4453
4454 if(0 != strcmp(interface_status, "1"))
4455 return RETURN_ERR;
4456
4457 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4458 system(cmd);
4459
4460 fp = fopen("/tmp/SSID_Stats.txt", "r");
4461 if(fp == NULL)
4462 {
4463 printf("/tmp/SSID_Stats.txt not exists \n");
4464 return RETURN_ERR;
4465 }
4466 fclose(fp);
4467
4468 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4469 File_Reading(buf, Value);
4470 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4471
4472 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4473 File_Reading(buf, Value);
4474 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4475
4476 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4477 File_Reading(buf, Value);
4478 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4479
4480 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4481 File_Reading(buf, Value);
4482 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4483
4484 output_struct->wifi_UnicastPacketsSent = 0;
4485 output_struct->wifi_UnicastPacketsReceived = 0;
4486 output_struct->wifi_MulticastPacketsSent = 0;
4487 output_struct->wifi_MulticastPacketsReceived = 0;
4488 output_struct->wifi_BroadcastPacketsSent = 0;
4489 output_struct->wifi_BroadcastPacketsRecevied = 0;
4490 output_struct->wifi_UnknownPacketsReceived = 0;
4491
4492 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4493 return RETURN_OK;
4494}
4495
4496INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4497{
4498 INT status = RETURN_ERR;
4499
4500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4501 //Below values should get updated from hal
4502 output_struct->wifi_RetransCount=0;
4503 output_struct->wifi_FailedRetransCount=0;
4504 output_struct->wifi_RetryCount=0;
4505 output_struct->wifi_MultipleRetryCount=0;
4506 output_struct->wifi_ACKFailureCount=0;
4507 output_struct->wifi_AggregatedPacketCount=0;
4508
4509 status = RETURN_OK;
4510 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4511
4512 return status;
4513}
4514
4515INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4516{
4517 INT status = RETURN_ERR;
4518 UINT index;
4519 wifi_neighbor_ap_t *pt=NULL;
4520
4521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4522 *output_array_size=2;
4523 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4524 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4525 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4526 strcpy(pt->ap_Radio,"");
4527 strcpy(pt->ap_SSID,"");
4528 strcpy(pt->ap_BSSID,"");
4529 strcpy(pt->ap_Mode,"");
4530 pt->ap_Channel=1;
4531 pt->ap_SignalStrength=0;
4532 strcpy(pt->ap_SecurityModeEnabled,"");
4533 strcpy(pt->ap_EncryptionMode,"");
4534 strcpy(pt->ap_OperatingFrequencyBand,"");
4535 strcpy(pt->ap_SupportedStandards,"");
4536 strcpy(pt->ap_OperatingStandards,"");
4537 strcpy(pt->ap_OperatingChannelBandwidth,"");
4538 pt->ap_BeaconPeriod=1;
4539 pt->ap_Noise=0;
4540 strcpy(pt->ap_BasicDataTransferRates,"");
4541 strcpy(pt->ap_SupportedDataTransferRates,"");
4542 pt->ap_DTIMPeriod=1;
4543 pt->ap_ChannelUtilization = 1;
4544 }
4545
4546 status = RETURN_OK;
4547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4548
4549 return status;
4550}
4551
4552//----------------- AP HAL -------------------------------
4553
4554//>> Deprecated: used for old RDKB code.
4555INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4556{
4557 if (NULL == output_ulong || NULL == output_struct)
4558 return RETURN_ERR;
4559 *output_ulong = 0;
4560 *output_struct = NULL;
4561 return RETURN_OK;
4562}
4563
4564#ifdef HAL_NETLINK_IMPL
4565static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4566 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4567 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4568 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4569 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4570 char mac_addr[20];
4571 static int count=0;
4572 int rate=0;
4573
4574 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4575
4576 nla_parse(tb,
4577 NL80211_ATTR_MAX,
4578 genlmsg_attrdata(gnlh, 0),
4579 genlmsg_attrlen(gnlh, 0),
4580 NULL);
4581
4582 if(!tb[NL80211_ATTR_STA_INFO]) {
4583 fprintf(stderr, "sta stats missing!\n");
4584 return NL_SKIP;
4585 }
4586
4587
4588 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4589 fprintf(stderr, "failed to parse nested attributes!\n");
4590 return NL_SKIP;
4591 }
4592
4593 //devIndex starts from 1
4594 if( ++count == out->wifi_devIndex )
4595 {
4596 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4597 //Getting the mac addrress
4598 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4599
4600 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4601 fprintf(stderr, "failed to parse nested rate attributes!");
4602 return NL_SKIP;
4603 }
4604
4605 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4606 if(rinfo[NL80211_RATE_INFO_BITRATE])
4607 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4608 out->wifi_devTxRate = rate/10;
4609 }
4610
4611 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4612 fprintf(stderr, "failed to parse nested rate attributes!");
4613 return NL_SKIP;
4614 }
4615
4616 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4617 if(rinfo[NL80211_RATE_INFO_BITRATE])
4618 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4619 out->wifi_devRxRate = rate/10;
4620 }
4621 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4622 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4623
4624 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4625 count = 0; //starts the count for next cycle
4626 return NL_STOP;
4627 }
4628
4629 return NL_SKIP;
4630
4631}
4632#endif
4633
4634INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4635{
4636#ifdef HAL_NETLINK_IMPL
4637 Netlink nl = {0};
4638 char if_name[10] = {0};
4639 char interface_name[16] = {0};
4640
4641 wifi_device_info_t info = {0};
4642 info.wifi_devIndex = devIndex;
4643
4644 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4645 return RETURN_ERR;
4646
4647 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4648
4649 nl.id = initSock80211(&nl);
4650
4651 if (nl.id < 0) {
4652 fprintf(stderr, "Error initializing netlink \n");
4653 return -1;
4654 }
4655
4656 struct nl_msg* msg = nlmsg_alloc();
4657
4658 if (!msg) {
4659 fprintf(stderr, "Failed to allocate netlink message.\n");
4660 nlfree(&nl);
4661 return -2;
4662 }
4663
4664 genlmsg_put(msg,
4665 NL_AUTO_PORT,
4666 NL_AUTO_SEQ,
4667 nl.id,
4668 0,
4669 NLM_F_DUMP,
4670 NL80211_CMD_GET_STATION,
4671 0);
4672
4673 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4674 nl_send_auto(nl.socket, msg);
4675 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4676 nl_recvmsgs(nl.socket, nl.cb);
4677 nlmsg_free(msg);
4678 nlfree(&nl);
4679
4680 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4681 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4682 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4683 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4684 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4685 return RETURN_OK;
4686#else
4687 //iw utility to retrieve station information
4688#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4689#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4690#define MACFILE "/tmp/wifi_AssoMac.txt"
4691#define TXRATEFILE "/tmp/wifi_txrate.txt"
4692#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4693 FILE *file = NULL;
4694 char if_name[10] = {'\0'};
4695 char pipeCmd[256] = {'\0'};
4696 char line[256] = {0};
4697 char interface_name[16] = {0};
4698 int count = 0, device = 0;
4699
4700 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4701 return RETURN_ERR;
4702
4703 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4704
4705 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4706 file = popen(pipeCmd, "r");
4707
4708 if(file == NULL)
4709 return RETURN_ERR; //popen failed
4710
4711 fgets(line, sizeof line, file);
4712 device = atoi(line);
4713 pclose(file);
4714
4715 if(device == 0)
4716 return RETURN_ERR; //No devices are connected
4717
4718 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4719 system(pipeCmd);
4720
4721 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4722
4723 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4724
4725 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4726
4727 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4728
4729 //devIndex starts from 1, ++count
4730 if((file = fopen(SIGNALFILE, "r")) != NULL )
4731 {
4732 for(count =0;fgets(line, sizeof line, file) != NULL;)
4733 {
4734 if (++count == devIndex)
4735 {
4736 output_struct->wifi_devSignalStrength = atoi(line);
4737 break;
4738 }
4739 }
4740 fclose(file);
4741 }
4742 else
4743 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4744
4745 if((file = fopen(MACFILE, "r")) != NULL )
4746 {
4747 for(count =0;fgets(line, sizeof line, file) != NULL;)
4748 {
4749 if (++count == devIndex)
4750 {
4751 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]);
4752 break;
4753 }
4754 }
4755 fclose(file);
4756 }
4757 else
4758 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4759
4760 if((file = fopen(TXRATEFILE, "r")) != NULL )
4761 {
4762 for(count =0;fgets(line, sizeof line, file) != NULL;)
4763 {
4764 if (++count == devIndex)
4765 {
4766 output_struct->wifi_devTxRate = atoi(line);
4767 break;
4768 }
4769 }
4770 fclose(file);
4771 }
4772 else
4773 fprintf(stderr,"fopen wifi_txrate.txt failed");
4774
4775 if((file = fopen(RXRATEFILE, "r")) != NULL)
4776 {
4777 for(count =0;fgets(line, sizeof line, file) != NULL;)
4778 {
4779 if (++count == devIndex)
4780 {
4781 output_struct->wifi_devRxRate = atoi(line);
4782 break;
4783 }
4784 }
4785 fclose(file);
4786 }
4787 else
4788 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4789
4790 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4791
4792 return RETURN_OK;
4793#endif
4794}
4795
4796INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4797{
4798 if (NULL == device)
4799 return RETURN_ERR;
4800 return RETURN_OK;
4801}
4802//<<
4803
4804
4805//--------------wifi_ap_hal-----------------------------
4806//enables CTS protection for the radio used by this AP
4807INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4808{
4809 //save config and Apply instantly
4810 return RETURN_ERR;
4811}
4812
4813// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4814INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4815{
4816 char config_file[64] = {'\0'};
4817 char buf[64] = {'\0'};
4818 struct params list;
4819
4820 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4821 list.name = "ht_coex";
4822 snprintf(buf, sizeof(buf), "%d", enable);
4823 list.value = buf;
4824
4825 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4826 wifi_hostapdWrite(config_file, &list, 1);
4827 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4828
4829 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4830
4831 return RETURN_OK;
4832}
4833
4834//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4835INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4836{
4837 char config_file[MAX_BUF_SIZE] = {'\0'};
4838 char buf[MAX_BUF_SIZE] = {'\0'};
4839 struct params list;
4840
4841 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4842 if (threshold < 256 || threshold > 2346 )
4843 return RETURN_ERR;
4844 list.name = "fragm_threshold";
4845 snprintf(buf, sizeof(buf), "%d", threshold);
4846 list.value = buf;
4847
4848 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4849 wifi_hostapdWrite(config_file, &list, 1);
4850 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4851
4852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4853
4854 return RETURN_OK;
4855}
4856
4857// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4858INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4859{
4860 char config_file[64] = {'\0'};
4861 char cmd[512] = {'\0'};
4862 char buf[512] = {'\0'};
4863 char stbc_config[16] = {'\0'};
4864 wifi_band band;
4865 int iterator = 0;
4866 BOOL current_stbc = FALSE;
4867 int ant_count = 0;
4868 int ant_bitmap = 0;
4869 struct params list;
4870
4871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4872
4873 band = wifi_index_to_band(radioIndex);
4874 if (band == band_invalid)
4875 return RETURN_ERR;
4876
4877 if (band == band_2_4)
4878 iterator = 1;
4879 else if (band == band_5)
4880 iterator = 2;
4881 else
4882 return RETURN_OK;
4883
4884 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4885 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4886 ant_count += ant_bitmap & 1;
4887
4888 if (ant_count == 1 && STBC_Enable == TRUE) {
4889 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4890 return RETURN_OK;
4891 }
4892
4893 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4894
4895 // set ht and vht config
4896 for (int i = 0; i < iterator; i++) {
4897 memset(stbc_config, 0, sizeof(stbc_config));
4898 memset(cmd, 0, sizeof(cmd));
4899 memset(buf, 0, sizeof(buf));
4900 list.name = (i == 0)?"ht_capab":"vht_capab";
4901 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
4902 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4903 _syscmd(cmd, buf, sizeof(buf));
4904 if (strlen(buf) != 0)
4905 current_stbc = TRUE;
4906 if (current_stbc == STBC_Enable)
4907 continue;
4908
4909 if (STBC_Enable == TRUE) {
4910 // Append the STBC flags in capab config
4911 memset(cmd, 0, sizeof(cmd));
4912 if (i == 0)
4913 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4914 else
4915 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4916 _syscmd(cmd, buf, sizeof(buf));
4917 } else if (STBC_Enable == FALSE) {
4918 // Remove the STBC flags and remain other flags in capab
4919 memset(cmd, 0, sizeof(cmd));
4920 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4921 _syscmd(cmd, buf, sizeof(buf));
4922 memset(cmd, 0, sizeof(cmd));
4923 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4924 _syscmd(cmd, buf, sizeof(buf));
4925 }
4926 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4927 list.value = buf;
4928 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4929 }
4930
4931 wifi_reloadAp(radioIndex);
4932
4933 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4934 return RETURN_OK;
4935}
4936
4937// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4938INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4939{
4940 char cmd[128] = {0};
4941 char buf[128] = {0};
4942 char interface_name[16] = {0};
4943
4944 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4945
4946 if(output_bool == NULL)
4947 return RETURN_ERR;
4948
4949 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4950 return RETURN_ERR;
4951
4952 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
4953 _syscmd(cmd, buf, sizeof(buf));
4954
4955 if (strncmp(buf, "1", 1) == 0)
4956 *output_bool = TRUE;
4957 else
4958 *output_bool = FALSE;
4959
4960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4961 return RETURN_OK;
4962}
4963
4964// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4965INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4966{
4967 char config_file[128] = {0};
4968 struct params list = {0};
4969 BOOL enable;
4970
4971 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4972
4973 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
4974 return RETURN_ERR;
4975
4976 if (amsduEnable == enable)
4977 return RETURN_OK;
4978
4979 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4980 list.name = "amsdu";
4981 list.value = amsduEnable? "1":"0";
4982 wifi_hostapdWrite(config_file, &list, 1);
4983 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4984 wifi_reloadAp(radioIndex);
4985
4986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4987 return RETURN_OK;
4988}
4989
4990//P2 // outputs the number of Tx streams
4991INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4992{
4993 char buf[8] = {0};
4994 char cmd[128] = {0};
4995 int phyId = 0;
4996
4997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4998
4999 phyId = radio_index_to_phy(radioIndex);
5000 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5001 _syscmd(cmd, buf, sizeof(buf));
5002
5003 *output_int = (INT)strtol(buf, NULL, 16);
5004
5005 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5006
5007 return RETURN_OK;
5008}
5009
5010INT fitChainMask(INT radioIndex, int antcount)
5011{
5012 char buf[128] = {0};
5013 char cmd[128] = {0};
5014 char config_file[64] = {0};
5015 wifi_band band;
5016 struct params list[2] = {0};
5017
5018 band = wifi_index_to_band(radioIndex);
5019 if (band == band_invalid)
5020 return RETURN_ERR;
5021
5022 list[0].name = "he_mu_beamformer";
5023 list[1].name = "he_su_beamformer";
5024
5025 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5026 if (antcount == 1) {
5027 // remove config about multiple antennas
5028 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5029 _syscmd(cmd, buf, sizeof(buf));
5030
5031 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5032 _syscmd(cmd, buf, sizeof(buf));
5033
5034 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5035 _syscmd(cmd, buf, sizeof(buf));
5036
5037 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5038 _syscmd(cmd, buf, sizeof(buf));
5039
5040 list[0].value = "0";
5041 list[1].value = "0";
5042 } else {
5043 // 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.
5044 if (band == band_2_4 || band == band_5) {
5045 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5046 _syscmd(cmd, buf, sizeof(buf));
5047 if (strlen(buf) > 0) {
5048 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5049 _syscmd(cmd, buf, sizeof(buf));
5050 }
5051 }
5052 if (band == band_5) {
5053 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5054 _syscmd(cmd, buf, sizeof(buf));
5055 if (strlen(buf) > 0) {
5056 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5057 _syscmd(cmd, buf, sizeof(buf));
5058 }
5059 }
5060
5061 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5062 _syscmd(cmd, buf, sizeof(buf));
5063 if (strlen(buf) == 0) {
5064 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5065 _syscmd(cmd, buf, sizeof(buf));
5066 }
5067
5068 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5069 _syscmd(cmd, buf, sizeof(buf));
5070 if (strlen(buf) == 0) {
5071 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5072 _syscmd(cmd, buf, sizeof(buf));
5073 }
5074
5075 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5076 _syscmd(cmd, buf, sizeof(buf));
5077 if (strlen(buf) == 0) {
5078 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5079 } else {
5080 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5081 }
5082 _syscmd(cmd, buf, sizeof(buf));
5083
5084 list[0].value = "1";
5085 list[1].value = "1";
5086 }
5087 wifi_hostapdWrite(config_file, list, 2);
5088}
5089
5090//P2 // sets the number of Tx streams to an enviornment variable
5091INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5092{
5093 char cmd[128] = {0};
5094 char buf[128] = {0};
5095 int phyId = 0;
5096 int cur_mask = 0;
5097 int antcount = 0;
5098 wifi_band band;
5099
5100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5101
5102 if (numStreams <= 0) {
5103 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5104 return RETURN_ERR;
5105 }
5106
5107 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5108 if (cur_mask == numStreams)
5109 return RETURN_OK;
5110
5111 wifi_setRadioEnable(radioIndex, FALSE);
5112
5113 phyId = radio_index_to_phy(radioIndex);
5114 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
5115 _syscmd(cmd, buf, sizeof(buf));
5116
5117 if (strlen(buf) > 0) {
5118 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5119 return RETURN_ERR;
5120 }
5121
5122 // if chain mask changed, we need to make the hostapd config valid.
5123 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5124 antcount += cur_mask & 1;
5125 }
5126 fitChainMask(radioIndex, antcount);
5127
5128 wifi_setRadioEnable(radioIndex, TRUE);
5129
5130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5131 return RETURN_OK;
5132}
5133
5134//P2 // outputs the number of Rx streams
5135INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5136{
5137 char buf[8] = {0};
5138 char cmd[128] = {0};
5139 int phyId = 0;
5140
5141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5142
5143 phyId = radio_index_to_phy(radioIndex);
5144 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5145 _syscmd(cmd, buf, sizeof(buf));
5146
5147 *output_int = (INT)strtol(buf, NULL, 16);
5148
5149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5150
5151 return RETURN_OK;
5152}
5153
5154//P2 // sets the number of Rx streams to an enviornment variable
5155INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5156{
5157 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5158 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5159 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5160 return RETURN_ERR;
5161 }
5162 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5163 return RETURN_ERR;
5164}
5165
5166//Get radio RDG enable setting
5167INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5168{
5169 if (NULL == output_bool)
5170 return RETURN_ERR;
5171 *output_bool = TRUE;
5172 return RETURN_OK;
5173}
5174
5175//Get radio RDG enable setting
5176INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5177{
5178 if (NULL == output_bool)
5179 return RETURN_ERR;
5180 *output_bool = TRUE;
5181 return RETURN_OK;
5182}
5183
5184//Set radio RDG enable setting
5185INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5186{
5187 return RETURN_ERR;
5188}
5189
5190//Get radio ADDBA enable setting
5191INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5192{
5193 if (NULL == output_bool)
5194 return RETURN_ERR;
5195 *output_bool = TRUE;
5196 return RETURN_OK;
5197}
5198
5199//Set radio ADDBA enable setting
5200INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5201{
5202 return RETURN_ERR;
5203}
5204
5205//Get radio auto block ack enable setting
5206INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5207{
5208 if (NULL == output_bool)
5209 return RETURN_ERR;
5210 *output_bool = TRUE;
5211 return RETURN_OK;
5212}
5213
5214//Set radio auto block ack enable setting
5215INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5216{
5217 return RETURN_ERR;
5218}
5219
5220//Get radio 11n pure mode enable support
5221INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5222{
5223 if (NULL == output_bool)
5224 return RETURN_ERR;
5225 *output_bool = TRUE;
5226 return RETURN_OK;
5227}
5228
5229//Get radio 11n pure mode enable setting
5230INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5231{
5232 if (NULL == output_bool)
5233 return RETURN_ERR;
5234 *output_bool = TRUE;
5235 return RETURN_OK;
5236}
5237
5238//Set radio 11n pure mode enable setting
5239INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5240{
5241 return RETURN_ERR;
5242}
5243
5244//Get radio IGMP snooping enable setting
5245INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5246{
5247 char interface_name[16] = {0};
5248 char cmd[128]={0};
5249 char buf[4]={0};
5250 bool bridge = FALSE, mac80211 = FALSE;
5251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5252
5253 if(output_bool == NULL)
5254 return RETURN_ERR;
5255
5256 *output_bool = FALSE;
5257
5258 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5259 _syscmd(cmd, buf, sizeof(buf));
5260 if (strncmp(buf, "1", 1) == 0)
5261 bridge = TRUE;
5262
5263 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5264 return RETURN_ERR;
5265 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5266 _syscmd(cmd, buf, sizeof(buf));
5267 if (strncmp(buf, "1", 1) == 0)
5268 mac80211 = TRUE;
5269
5270 if (bridge && mac80211)
5271 *output_bool = TRUE;
5272
5273 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5274 return RETURN_OK;
5275}
5276
5277//Set radio IGMP snooping enable setting
5278INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5279{
5280 char interface_name[16] = {0};
5281 char cmd[128]={0};
5282 char buf[4]={0};
5283 int max_num_radios =0;
5284 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5285
5286 // bridge
5287 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5288 _syscmd(cmd, buf, sizeof(buf));
5289
5290 wifi_getMaxRadioNumber(&max_num_radios);
5291 // mac80211
5292 for (int i = 0; i < max_num_radios; i++) {
5293 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5294 return RETURN_ERR;
5295 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5296 _syscmd(cmd, buf, sizeof(buf));
5297 }
5298 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5299 return RETURN_OK;
5300}
5301
5302//Get the Reset count of radio
5303INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
5304{
5305 if (NULL == output_int)
5306 return RETURN_ERR;
5307 *output_int = (radioIndex==0)? 1: 3;
5308
5309 return RETURN_OK;
5310}
5311
5312
5313//---------------------------------------------------------------------------------------------------
5314//
5315// Additional Wifi AP level APIs used for Access Point devices
5316//
5317//---------------------------------------------------------------------------------------------------
5318
5319// creates a new ap and pushes these parameters to the hardware
5320INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5321{
5322 // Deprecated when use hal version 3, use wifi_createVap() instead.
5323 return RETURN_OK;
5324}
5325
5326// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5327INT wifi_deleteAp(INT apIndex)
5328{
5329 char interface_name[16] = {0};
5330 char buf[1024];
5331 char cmd[128];
5332
5333 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5334 return RETURN_ERR;
5335 snprintf(cmd,sizeof(cmd), "iw %s del", interface_name);
5336 _syscmd(cmd, buf, sizeof(buf));
5337
5338 wifi_removeApSecVaribles(apIndex);
5339
5340 return RETURN_OK;
5341}
5342
5343// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5344INT wifi_getApName(INT apIndex, CHAR *output_string)
5345{
5346 char interface_name[16] = {0};
5347 if(NULL == output_string)
5348 return RETURN_ERR;
5349
5350 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5351 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
5352 else
5353 snprintf(output_string, 16, "%s", interface_name);
5354 return RETURN_OK;
5355}
5356
5357// Outputs the index number in that corresponds to the SSID string
5358INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5359{
5360 char cmd [128] = {0};
5361 char buf[32] = {0};
5362 char *apIndex_str = NULL;
5363 bool enable = FALSE;
5364
5365 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5366 _syscmd(cmd, buf, sizeof(buf));
5367
5368 if (strlen(buf) != 0) {
5369 apIndex_str = strtok(buf, "\n");
5370 *output_int = strtoul(apIndex_str, NULL, 10);
5371 return RETURN_OK;
5372 }
5373
5374 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5375 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5376 if (apIndex_str) {
5377 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5378 return RETURN_OK;
5379 }
5380 *output_int = -1;
5381 return RETURN_OK;
5382}
5383
5384INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5385{
5386 return wifi_getIndexFromName(inputSsidString, output_int);
5387}
5388
5389// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5390INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5391{
5392 char buf[MAX_BUF_SIZE] = {0};
5393 char cmd[MAX_CMD_SIZE] = {0};
5394 char config_file[MAX_BUF_SIZE] = {0};
5395
5396 if(NULL == output_string)
5397 return RETURN_ERR;
5398
5399 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5400 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5401 if((strcmp(buf,"3")==0))
5402 snprintf(output_string, 32, "WPAand11i");
5403 else if((strcmp(buf,"2")==0))
5404 snprintf(output_string, 32, "11i");
5405 else if((strcmp(buf,"1")==0))
5406 snprintf(output_string, 32, "WPA");
5407 else
5408 snprintf(output_string, 32, "None");
5409
5410 return RETURN_OK;
5411}
5412
5413// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5414INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5415{
5416 char config_file[MAX_BUF_SIZE] = {0};
5417 struct params list;
5418
5419 if (NULL == beaconTypeString)
5420 return RETURN_ERR;
5421 list.name = "wpa";
5422 list.value = "0";
5423
5424 if((strcmp(beaconTypeString,"WPAand11i")==0))
5425 list.value="3";
5426 else if((strcmp(beaconTypeString,"11i")==0))
5427 list.value="2";
5428 else if((strcmp(beaconTypeString,"WPA")==0))
5429 list.value="1";
5430
5431 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5432 wifi_hostapdWrite(config_file, &list, 1);
5433 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5434 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5435 return RETURN_OK;
5436}
5437
5438// sets the beacon interval on the hardware for this AP
5439INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5440{
5441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5442 struct params params={'\0'};
5443 char buf[MAX_BUF_SIZE] = {'\0'};
5444 char config_file[MAX_BUF_SIZE] = {'\0'};
5445
5446 params.name = "beacon_int";
5447 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5448 params.value = buf;
5449
5450 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5451 wifi_hostapdWrite(config_file, &params, 1);
5452
5453 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5454 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5455 return RETURN_OK;
5456}
5457
5458INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5459{
5460 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5461 return RETURN_ERR;
5462 return RETURN_OK;
5463}
5464
5465// Get the packet size threshold supported.
5466INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5467{
5468 //save config and apply instantly
5469 if (NULL == output_bool)
5470 return RETURN_ERR;
5471 *output_bool = TRUE;
5472 return RETURN_OK;
5473}
5474
5475// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5476INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5477{
developer72fb0bb2023-01-11 09:46:29 +08005478 char buf[16] = {0};
5479 char config_file[128] = {0};
5480 struct params param = {0};
5481
5482 if (threshold > 65535) {
5483 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5484 return RETURN_ERR;
5485 }
5486
developer23e71282023-01-18 10:25:19 +08005487 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005488 snprintf(buf, sizeof(buf), "%u", threshold);
5489 param.name = "rts_threshold";
5490 param.value = buf;
5491 wifi_hostapdWrite(config_file, &param, 1);
5492 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5493 wifi_reloadAp(apIndex);
5494
5495 return RETURN_OK;
5496}
5497
5498// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5499INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5500{
5501 if (NULL == output_string)
5502 return RETURN_ERR;
5503 snprintf(output_string, 32, "TKIPandAESEncryption");
5504 return RETURN_OK;
5505
5506}
5507
5508// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5509INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5510{
5511 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5512 char *param_name = NULL;
5513 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5514
5515 if(NULL == output_string)
5516 return RETURN_ERR;
5517
5518 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5519 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5520
5521 if(strcmp(buf,"0")==0)
5522 {
5523 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5524 snprintf(output_string, 32, "None");
5525 return RETURN_OK;
5526 }
5527 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5528 param_name = "rsn_pairwise";
5529 else if((strcmp(buf,"1")==0))
5530 param_name = "wpa_pairwise";
5531 else
5532 return RETURN_ERR;
5533 memset(output_string,'\0',32);
5534 wifi_hostapdRead(config_file,param_name,output_string,32);
5535 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5536 param_name = "wpa_pairwise";
5537 memset(output_string, '\0', 32);
5538 wifi_hostapdRead(config_file, param_name, output_string, 32);
5539 }
5540 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5541
5542 if(strcmp(output_string,"TKIP") == 0)
5543 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5544 else if(strcmp(output_string,"CCMP") == 0)
5545 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5546 else if(strcmp(output_string,"TKIP CCMP") == 0)
5547 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5548
5549 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5550 return RETURN_OK;
5551}
5552
5553// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5554INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5555{
5556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5557 struct params params={'\0'};
5558 char output_string[32];
5559 char config_file[MAX_BUF_SIZE] = {0};
5560
5561 memset(output_string,'\0',32);
5562 wifi_getApWpaEncryptionMode(apIndex,output_string);
5563
5564 if(strcmp(encMode, "TKIPEncryption") == 0)
5565 params.value = "TKIP";
5566 else if(strcmp(encMode,"AESEncryption") == 0)
5567 params.value = "CCMP";
5568 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5569 params.value = "TKIP CCMP";
5570
5571 if((strcmp(output_string,"WPAand11i")==0))
5572 {
5573 params.name = "wpa_pairwise";
5574 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5575 wifi_hostapdWrite(config_file, &params, 1);
5576 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5577
5578 params.name = "rsn_pairwise";
5579 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5580 wifi_hostapdWrite(config_file, &params, 1);
5581 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5582
5583 return RETURN_OK;
5584 }
5585 else if((strcmp(output_string,"11i")==0))
5586 {
5587 params.name = "rsn_pairwise";
5588 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5589 wifi_hostapdWrite(config_file, &params, 1);
5590 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5591 return RETURN_OK;
5592 }
5593 else if((strcmp(output_string,"WPA")==0))
5594 {
5595 params.name = "wpa_pairwise";
5596 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5597 wifi_hostapdWrite(config_file, &params, 1);
5598 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5599 return RETURN_OK;
5600 }
5601
5602 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5603 return RETURN_OK;
5604}
5605
5606// deletes internal security varable settings for this ap
5607INT wifi_removeApSecVaribles(INT apIndex)
5608{
5609 //TODO: remove the entry in hostapd config file
5610 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5611 //_syscmd(cmd, buf, sizeof(buf));
5612
5613 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5614 //_syscmd(cmd, buf, sizeof(buf));
5615 return RETURN_ERR;
5616}
5617
5618// changes the hardware settings to disable encryption on this ap
5619INT wifi_disableApEncryption(INT apIndex)
5620{
5621 //Apply instantly
5622 return RETURN_ERR;
5623}
5624
5625// set the authorization mode on this ap
5626// mode mapping as: 1: open, 2: shared, 4:auto
5627INT wifi_setApAuthMode(INT apIndex, INT mode)
5628{
5629 struct params params={0};
5630 char config_file[64] = {0};
5631 int ret;
5632
5633 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5634
5635 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5636 params.name = "auth_algs";
5637
5638 if (mode & 1 && mode & 2)
5639 params.value = "3";
5640 else if (mode & 2)
5641 params.value = "2";
5642 else if (mode & 1)
5643 params.value = "1";
5644 else
5645 params.value = "0";
5646
5647 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5648 wifi_hostapdWrite(config_file, &params, 1);
5649 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5650 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5651
5652 return RETURN_OK;
5653}
5654
5655// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5656INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5657{
5658 //save to wifi config, and wait for wifi restart to apply
5659 struct params params={'\0'};
5660 char config_file[MAX_BUF_SIZE] = {0};
5661 int ret;
5662
5663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5664 if(authMode == NULL)
5665 return RETURN_ERR;
5666
5667 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5668 params.name = "wpa_key_mgmt";
5669
5670 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5671 params.value = "WPA-PSK";
5672 else if(strcmp(authMode,"EAPAuthentication") == 0)
5673 params.value = "WPA-EAP";
5674 else if (strcmp(authMode, "SAEAuthentication") == 0)
5675 params.value = "SAE";
5676 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5677 params.value = "WPA-EAP-SUITE-B-192";
5678 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5679 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08005680 else if (strcmp(authMode, "Enhanced_Open") == 0)
5681 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08005682 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5683 return RETURN_OK; //This is taken careof in beaconType
5684
5685 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5686 ret=wifi_hostapdWrite(config_file,&params,1);
5687 if(!ret)
5688 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5689 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5690
5691 return ret;
5692}
5693
5694// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5695INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5696{
5697 //save to wifi config, and wait for wifi restart to apply
5698 char BeaconType[50] = {0};
5699 char config_file[MAX_BUF_SIZE] = {0};
5700
5701 *authMode = 0;
5702 wifi_getApBeaconType(apIndex,BeaconType);
5703 printf("%s____%s \n",__FUNCTION__,BeaconType);
5704
5705 if(strcmp(BeaconType,"None") == 0)
5706 strcpy(authMode,"None");
5707 else
5708 {
5709 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5710 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5711 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5712 if(strcmp(authMode,"WPA-PSK") == 0)
5713 strcpy(authMode,"SharedAuthentication");
5714 else if(strcmp(authMode,"WPA-EAP") == 0)
5715 strcpy(authMode,"EAPAuthentication");
5716 }
5717
5718 return RETURN_OK;
5719}
5720
5721// Outputs the number of stations associated per AP
5722INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5723{
5724 char interface_name[16] = {0};
5725 char cmd[128]={0};
5726 char buf[128]={0};
5727 BOOL status = false;
5728
5729 if(apIndex > MAX_APS)
5730 return RETURN_ERR;
5731
5732 wifi_getApEnable(apIndex,&status);
5733 if (!status)
5734 return RETURN_OK;
5735
5736 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5737 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5738 return RETURN_ERR;
5739 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
5740 _syscmd(cmd, buf, sizeof(buf));
5741 sscanf(buf,"%lu", output_ulong);
5742
5743 return RETURN_OK;
5744}
5745
5746// manually removes any active wi-fi association with the device specified on this ap
5747INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5748{
5749 char interface_name[16] = {0};
5750 char buf[126]={'\0'};
5751
5752 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5753 return RETURN_ERR;
5754 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
5755 system(buf);
5756
5757 return RETURN_OK;
5758}
5759
5760// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5761INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5762{
5763 if(NULL == output_int)
5764 return RETURN_ERR;
5765 int max_radio_num = 0;
5766 wifi_getMaxRadioNumber(&max_radio_num);
5767 *output_int = apIndex%max_radio_num;
5768 return RETURN_OK;
5769}
5770
5771// sets the radio index for the specific ap
5772INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5773{
5774 //set to config only and wait for wifi reset to apply settings
5775 return RETURN_ERR;
5776}
5777
5778// Get the ACL MAC list per AP
5779INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5780{
5781 char interface_name[16] = {0};
5782 char cmd[MAX_CMD_SIZE]={'\0'};
5783 int ret = 0;
5784
5785 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5786 return RETURN_ERR;
5787 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
5788 ret = _syscmd(cmd,macArray,buf_size);
5789 if (ret != 0)
5790 return RETURN_ERR;
5791
5792 return RETURN_OK;
5793}
5794
5795INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5796{
5797 char interface_name[16] = {0};
5798 char cmd[MAX_CMD_SIZE]={'\0'};
5799 int ret = 0;
5800
5801 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5802 return RETURN_ERR;
5803 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
5804 ret = _syscmd(cmd,macArray,buf_size);
5805 if (ret != 0)
5806 return RETURN_ERR;
5807
5808 return RETURN_OK;
5809}
5810
5811
5812// Get the list of stations associated per AP
5813INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5814{
5815 char interface_name[16] = {0};
5816 char cmd[128];
5817
5818 if(apIndex > 3) //Currently supporting apIndex upto 3
5819 return RETURN_ERR;
5820 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5821 return RETURN_ERR;
5822 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5823 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
5824 _syscmd(cmd, macArray, buf_size);
5825
5826 return RETURN_OK;
5827}
5828
5829// adds the mac address to the filter list
5830//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5831INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5832{
5833 char cmd[MAX_CMD_SIZE]={'\0'};
5834 char buf[MAX_BUF_SIZE]={'\0'};
5835
5836#if 0
5837 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
5838 if(_syscmd(cmd,buf,sizeof(buf)))
5839 return RETURN_ERR;
5840#endif
5841 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5842 if(_syscmd(cmd,buf,sizeof(buf)))
5843 return RETURN_ERR;
5844
5845 return RETURN_OK;
5846}
5847
5848// deletes the mac address from the filter list
5849//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5850INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5851{
5852 char cmd[MAX_CMD_SIZE]={'\0'};
5853 char buf[MAX_BUF_SIZE]={'\0'};
5854
5855#if 0
5856 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
5857 if(_syscmd(cmd,buf,sizeof(buf)))
5858 return RETURN_ERR;
5859
5860#endif
5861 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5862 if(_syscmd(cmd,buf,sizeof(buf)))
5863 return RETURN_ERR;
5864
5865 return RETURN_OK;
5866}
5867
5868// outputs the number of devices in the filter list
5869INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5870{
5871 char cmd[MAX_BUF_SIZE]={0};
5872 char buf[MAX_CMD_SIZE]={0};
5873
5874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5875 if(output_uint == NULL)
5876 return RETURN_ERR;
5877
5878 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5879 _syscmd(cmd, buf, sizeof(buf));
5880
5881 *output_uint = atoi(buf);
5882
5883 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5884 return RETURN_OK;
5885}
5886
5887INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5888{
5889 char cmd[128]={'\0'};
5890 char buf[128]={'\0'};
5891
5892 if(strcmp(action,"DENY")==0)
5893 {
5894 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5895 system(buf);
5896 return RETURN_OK;
5897 }
5898
5899 if(strcmp(action,"ALLOW")==0)
5900 {
5901 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5902 system(buf);
5903 return RETURN_OK;
5904 }
5905
5906 return RETURN_ERR;
5907
5908}
5909
5910// enable kick for devices on acl black list
5911INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5912{
5913 char aclArray[512] = {0}, *acl = NULL;
5914 char assocArray[512] = {0}, *asso = NULL;
5915
5916 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
5917 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5918
5919 // if there are no devices connected there is nothing to do
5920 if (strlen(assocArray) < 17)
5921 return RETURN_OK;
5922
5923 if (enable == TRUE)
5924 {
5925 //kick off the MAC which is in ACL array (deny list)
5926 acl = strtok(aclArray, "\r\n");
5927 while (acl != NULL) {
5928 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5929 wifi_kickApAssociatedDevice(apIndex, acl);
5930
5931 acl = strtok(NULL, "\r\n");
5932 }
5933 wifi_setApMacAddressControlMode(apIndex, 2);
5934 }
5935 else
5936 {
5937 wifi_setApMacAddressControlMode(apIndex, 0);
5938 }
5939
5940#if 0
5941 //TODO: need to revisit below implementation
5942 char aclArray[512]={0}, *acl=NULL;
5943 char assocArray[512]={0}, *asso=NULL;
5944 char buf[256]={'\0'};
5945 char action[10]={'\0'};
5946 FILE *fr=NULL;
5947 char interface[10]={'\0'};
5948 char config_file[MAX_BUF_SIZE] = {0};
5949
5950 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5951 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5952 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5953 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5954
5955 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5956 system(buf);
5957 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5958 system(buf);
5959 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5960 system(buf);
5961 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5962 system(buf);
5963 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5964 system(buf);
5965
5966 if ( enable == TRUE )
5967 {
5968 int device_count=0;
5969 strcpy(action,"DENY");
5970 //kick off the MAC which is in ACL array (deny list)
5971 acl = strtok (aclArray,",");
5972 while (acl != NULL) {
5973 if(strlen(acl)>=17)
5974 {
5975 apply_rules(apIndex, acl,action,interface);
5976 device_count++;
5977 //Register mac to be blocked ,in syscfg.db persistent storage
5978 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5979 system(buf);
5980 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5981 system(buf);
5982 system("syscfg commit");
5983
5984 wifi_kickApAssociatedDevice(apIndex, acl);
5985 }
5986 acl = strtok (NULL, ",");
5987 }
5988 }
5989 else
5990 {
5991 int device_count=0;
5992 char cmdmac[20]={'\0'};
5993 strcpy(action,"ALLOW");
5994 //kick off the MAC which is not in ACL array (allow list)
5995 acl = strtok (aclArray,",");
5996 while (acl != NULL) {
5997 if(strlen(acl)>=17)
5998 {
5999 apply_rules(apIndex, acl,action,interface);
6000 device_count++;
6001 //Register mac to be Allowed ,in syscfg.db persistent storage
6002 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
6003 system(buf);
6004 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
6005 system(buf);
6006 sprintf(cmdmac,"%s",acl);
6007 }
6008 acl = strtok (NULL, ",");
6009 }
6010 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
6011 system(buf);
6012
6013 //Disconnect the mac which is not in ACL
6014 asso = strtok (assocArray,",");
6015 while (asso != NULL) {
6016 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
6017 wifi_kickApAssociatedDevice(apIndex, asso);
6018 asso = strtok (NULL, ",");
6019 }
6020 }
6021#endif
6022 return RETURN_OK;
6023}
6024
6025INT wifi_setPreferPrivateConnection(BOOL enable)
6026{
6027 return RETURN_OK;
6028}
6029
6030// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6031INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6032{
6033 char interface_name[16] = {0};
6034 int items = 1;
6035 struct params list[2];
6036 char buf[MAX_BUF_SIZE] = {0};
6037 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
6038 char deny_file[MAX_BUF_SIZE] = {0};
6039
6040 list[0].name = "macaddr_acl";
6041
6042 if (filterMode == 0) {
6043 sprintf(buf, "%d", 0);
6044 list[0].value = buf;
6045
6046 char cmd[128], rtn[128];
6047 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6048 return RETURN_ERR;
6049 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
6050 _syscmd(cmd, rtn, sizeof(rtn));
6051 memset(cmd,0,sizeof(cmd));
6052 // Delete deny_mac_file in hostapd configuration
6053 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
6054 _syscmd(cmd, rtn, sizeof(rtn));
6055 }
6056 else if (filterMode == 1) {
6057 sprintf(buf, "%d", filterMode);
6058 list[0].value = buf;
6059 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6060 list[1].name = "accept_mac_file";
6061 list[1].value = acl_file;
6062 items = 2;
6063 } else if (filterMode == 2) {
6064 //TODO: deny_mac_file
6065 sprintf(buf, "%d", 0);
6066 list[0].value = buf;
6067 list[1].name = "deny_mac_file";
6068 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6069 list[1].value = deny_file;
6070 items = 2;
6071 } else {
6072 return RETURN_ERR;
6073 }
6074
6075 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6076 wifi_hostapdWrite(config_file, list, items);
6077
6078 return RETURN_OK;
6079
6080#if 0
6081 if(apIndex==0 || apIndex==1)
6082 {
6083 //set the filtermode
6084 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6085 system(buf);
6086 system("syscfg commit");
6087
6088 if(filterMode==0)
6089 {
6090 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6091 system(buf);
6092 return RETURN_OK;
6093 }
6094 }
6095 return RETURN_OK;
6096#endif
6097}
6098
6099// 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.
6100INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6101{
6102 return RETURN_ERR;
6103}
6104
6105// gets the vlan ID for this ap from an internal enviornment variable
6106INT wifi_getApVlanID(INT apIndex, INT *output_int)
6107{
6108 if(apIndex==0)
6109 {
6110 *output_int=100;
6111 return RETURN_OK;
6112 }
6113
6114 return RETURN_ERR;
6115}
6116
6117// sets the vlan ID for this ap to an internal enviornment variable
6118INT wifi_setApVlanID(INT apIndex, INT vlanId)
6119{
6120 //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)
6121 return RETURN_ERR;
6122}
6123
6124// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6125INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6126{
6127 snprintf(bridgeName, 32, "brlan0");
6128 snprintf(IP, 32, "10.0.0.1");
6129 snprintf(subnet, 32, "255.255.255.0");
6130
6131 return RETURN_OK;
6132}
6133
6134//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6135INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6136{
6137 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6138 return RETURN_ERR;
6139}
6140
6141// reset the vlan configuration for this ap
6142INT wifi_resetApVlanCfg(INT apIndex)
6143{
6144 char original_config_file[64] = {0};
6145 char current_config_file[64] = {0};
6146 char buf[64] = {0};
6147 char cmd[64] = {0};
6148 char vlan_file[64] = {0};
6149 char vlan_tagged_interface[16] = {0};
6150 char vlan_bridge[16] = {0};
6151 char vlan_naming[16] = {0};
6152 struct params list[4] = {0};
6153 wifi_band band;
6154
6155 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6156
6157 band = wifi_index_to_band(apIndex);
6158 if (band == band_2_4)
6159 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6160 else if (band == band_5)
6161 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6162 else if (band == band_6)
6163 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6164
6165 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6166
6167 if (strlen(vlan_file) == 0)
6168 strcpy(vlan_file, VLAN_FILE);
6169
6170 // The file should exist or this vap would not work.
6171 if (access(vlan_file, F_OK) != 0) {
6172 sprintf(cmd, "touch %s", vlan_file);
6173 _syscmd(cmd, buf, sizeof(buf));
6174 }
6175 list[0].name = "vlan_file";
6176 list[0].value = vlan_file;
6177
6178 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6179 list[1].name = "vlan_tagged_interface";
6180 list[1].value = vlan_tagged_interface;
6181
6182 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6183 list[2].name = "vlan_bridge";
6184 list[2].value = vlan_bridge;
6185
6186 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6187 list[3].name = "vlan_naming";
6188 list[3].value = vlan_naming;
6189
6190 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6191 wifi_hostapdWrite(current_config_file, list, 4);
6192 //Reapply vlan settings
6193 // wifi_pushBridgeInfo(apIndex);
6194
6195 // restart this ap
6196 wifi_setApEnable(apIndex, FALSE);
6197 wifi_setApEnable(apIndex, TRUE);
6198
6199 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6200
6201 return RETURN_OK;
6202}
6203
6204// 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.
6205INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6206{
6207 return RETURN_ERR;
6208}
6209
6210// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6211INT wifi_startHostApd()
6212{
6213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6214 system("systemctl start hostapd.service");
6215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6216 return RETURN_OK;
6217 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6218}
6219
6220// stops hostapd
6221INT wifi_stopHostApd()
6222{
6223 char cmd[128] = {0};
6224 char buf[128] = {0};
6225
6226 sprintf(cmd,"systemctl stop hostapd");
6227 _syscmd(cmd, buf, sizeof(buf));
6228
6229 return RETURN_OK;
6230}
6231
6232// restart hostapd dummy function
6233INT wifi_restartHostApd()
6234{
6235 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6236 system("systemctl restart hostapd-global");
6237 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6238
6239 return RETURN_OK;
6240}
6241
6242static int align_hostapd_config(int index)
6243{
6244 ULONG lval;
6245 wifi_getRadioChannel(index%2, &lval);
6246 wifi_setRadioChannel(index%2, lval);
6247 return RETURN_OK;
6248}
6249
6250// sets the AP enable status variable for the specified ap.
6251INT wifi_setApEnable(INT apIndex, BOOL enable)
6252{
6253 char interface_name[16] = {0};
6254 char config_file[MAX_BUF_SIZE] = {0};
6255 char cmd[MAX_CMD_SIZE] = {0};
6256 char buf[MAX_BUF_SIZE] = {0};
6257 BOOL status;
6258 int max_radio_num = 0;
6259 int phyId = 0;
6260
6261 wifi_getApEnable(apIndex,&status);
6262
6263 wifi_getMaxRadioNumber(&max_radio_num);
6264 if (enable == status)
6265 return RETURN_OK;
6266
6267 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6268 return RETURN_ERR;
6269
6270 if (enable == TRUE) {
6271 int radioIndex = apIndex % max_radio_num;
6272 phyId = radio_index_to_phy(radioIndex);
6273 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6274 //Hostapd will bring up this interface
6275 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
6276 _syscmd(cmd, buf, sizeof(buf));
developer23e71282023-01-18 10:25:19 +08006277 sprintf(cmd, "iw %s del", interface_name);
6278 _syscmd(cmd, buf, sizeof(buf));
6279 sprintf(cmd, "iw phy phy%d interface add %s type __ap", phyId, interface_name);
6280 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006281 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6282 _syscmd(cmd, buf, sizeof(buf));
6283 }
6284 else {
6285 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
6286 _syscmd(cmd, buf, sizeof(buf));
6287 sprintf(cmd, "ip link set %s down", interface_name);
6288 _syscmd(cmd, buf, sizeof(buf));
6289 }
6290 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6291 interface_name, interface_name, enable, VAP_STATUS_FILE);
6292 _syscmd(cmd, buf, sizeof(buf));
6293 //Wait for wifi up/down to apply
6294 return RETURN_OK;
6295}
6296
6297// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6298INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6299{
6300 char interface_name[16] = {0};
6301 char cmd[MAX_CMD_SIZE] = {'\0'};
6302 char buf[MAX_BUF_SIZE] = {'\0'};
6303
6304 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6305 return RETURN_ERR;
6306
6307 *output_bool = 0;
6308
6309 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6310 {
6311 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6312 *output_bool = FALSE;
6313 return RETURN_OK;
6314 }
6315 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6316 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6317 }
6318
6319 return RETURN_OK;
6320}
6321
6322// Outputs the AP "Enabled" "Disabled" status from driver
6323INT wifi_getApStatus(INT apIndex, CHAR *output_string)
6324{
6325 char cmd[128] = {0};
6326 char buf[128] = {0};
6327 BOOL output_bool;
6328
6329 if ( NULL == output_string)
6330 return RETURN_ERR;
6331 wifi_getApEnable(apIndex,&output_bool);
6332
6333 if(output_bool == 1)
6334 snprintf(output_string, 32, "Up");
6335 else
6336 snprintf(output_string, 32, "Disable");
6337
6338 return RETURN_OK;
6339}
6340
6341//Indicates whether or not beacons include the SSID name.
6342// outputs a 1 if SSID on the AP is enabled, else outputs 0
6343INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6344{
6345 //get the running status
6346 char config_file[MAX_BUF_SIZE] = {0};
6347 char buf[16] = {0};
6348
6349 if (!output)
6350 return RETURN_ERR;
6351
6352 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6353 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6354 // default is enable
6355 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6356 *output = TRUE;
6357
6358 return RETURN_OK;
6359}
6360
6361// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6362INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6363{
6364 //store the config, apply instantly
6365 char config_file[MAX_BUF_SIZE] = {0};
6366 struct params list;
6367
6368 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6369 list.name = "ignore_broadcast_ssid";
6370 list.value = enable?"0":"1";
6371
6372 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6373 wifi_hostapdWrite(config_file, &list, 1);
6374 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6375 //TODO: call hostapd_cli for dynamic_config_control
6376 wifi_reloadAp(apIndex);
6377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6378
6379 return RETURN_OK;
6380}
6381
6382//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6383INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6384{
6385 //get the running status
6386 if(!output_uint)
6387 return RETURN_ERR;
6388 *output_uint=16;
6389 return RETURN_OK;
6390}
6391
6392INT wifi_setApRetryLimit(INT apIndex, UINT number)
6393{
6394 //apply instantly
6395 return RETURN_ERR;
6396}
6397
6398//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6399INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6400{
6401 if(!output)
6402 return RETURN_ERR;
6403 *output=TRUE;
6404 return RETURN_OK;
6405}
6406
6407//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6408INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6409{
6410 //get the running status from driver
6411 char cmd[128] = {0};
6412 char buf[128] = {0};
6413 int max_radio_num = 0, radioIndex = 0;
6414 int phyId = 0;
6415
6416 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6417
6418 wifi_getMaxRadioNumber(&max_radio_num);
6419 radioIndex = apIndex % max_radio_num;
6420 phyId = radio_index_to_phy(radioIndex);
6421 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6422 _syscmd(cmd,buf, sizeof(buf));
6423
6424 if (strlen(buf) > 0)
6425 *output = true;
6426
6427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6428
6429 return RETURN_OK;
6430}
6431
6432//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6433INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6434{
6435 //get the running status from driver
6436 if(!output)
6437 return RETURN_ERR;
6438
6439 char config_file[MAX_BUF_SIZE] = {0};
6440 char buf[16] = {0};
6441
6442 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6443 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6444 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6445 *output = TRUE;
6446 else
6447 *output = FALSE;
6448
6449 return RETURN_OK;
6450}
6451
6452// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6453INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6454{
6455 //Save config and apply instantly.
6456 char config_file[MAX_BUF_SIZE] = {0};
6457 struct params list;
6458
6459 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6460 list.name = "wmm_enabled";
6461 list.value = enable?"1":"0";
6462
6463 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6464 wifi_hostapdWrite(config_file, &list, 1);
6465 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6466 wifi_reloadAp(apIndex);
6467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6468
6469 return RETURN_OK;
6470}
6471
6472//Whether U-APSD support is currently enabled. When enabled, this is indicated in beacon frames. Note: U-APSD can only be enabled if WMM is also enabled.
6473INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6474{
6475 //get the running status from driver
6476 if(!output)
6477 return RETURN_ERR;
6478
6479 char config_file[128] = {0};
6480 char buf[16] = {0};
6481
6482 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6483 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6484 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6485 *output = TRUE;
6486 else
6487 *output = FALSE;
6488
6489 return RETURN_OK;
6490}
6491
6492// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6493INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6494{
6495 //save config and apply instantly.
6496 char config_file[MAX_BUF_SIZE] = {0};
6497 struct params list;
6498
6499 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6500 list.name = "uapsd_advertisement_enabled";
6501 list.value = enable?"1":"0";
6502
6503 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6504 wifi_hostapdWrite(config_file, &list, 1);
6505 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6506 wifi_reloadAp(apIndex);
6507 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6508
6509 return RETURN_OK;
6510}
6511
6512// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6513INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6514{
6515 char interface_name[16] = {0};
6516 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6517 char cmd[128] = {0};
6518 char buf[128] = {0};
6519 char ack_filepath[128] = {0};
6520 uint16_t bitmap = 0;
6521 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6522 FILE *f = NULL;
6523
6524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6525
6526 // Get current setting
6527 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6528 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6529 _syscmd(cmd, buf, sizeof(buf));
6530 if (strlen(buf) > 0)
6531 bitmap = strtoul(buf, NULL, 10);
6532
6533 bitmap = strtoul(buf, NULL, 10);
6534
6535 if (ackPolicy == TRUE) { // True, unset this class
6536 bitmap &= ~class_map[class];
6537 } else { // False, set this class
6538 bitmap |= class_map[class];
6539 }
6540
6541 f = fopen(ack_filepath, "w");
6542 if (f == NULL) {
6543 fprintf(stderr, "%s: fopen failed\n", __func__);
6544 return RETURN_ERR;
6545 }
6546 fprintf(f, "%hu", bitmap);
6547 fclose(f);
6548
6549 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6550 return RETURN_ERR;
6551 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6552 _syscmd(cmd, buf, sizeof(buf));
6553
6554 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6555 return RETURN_OK;
6556}
6557
6558//The maximum number of devices that can simultaneously be connected to the access point. A value of 0 means that there is no specific limit.
6559INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6560{
6561 //get the running status from driver
6562 if(!output_uint)
6563 return RETURN_ERR;
6564
6565 char output[16]={'\0'};
6566 char config_file[MAX_BUF_SIZE] = {0};
6567
6568 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6569 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6570 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6571 else {
6572 int device_num = atoi(output);
6573 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6574 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6575 return RETURN_ERR;
6576 }
6577 else {
6578 *output_uint = device_num;
6579 }
6580 }
6581
6582 return RETURN_OK;
6583}
6584
6585INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6586{
6587 //store to wifi config, apply instantly
6588 char str[MAX_BUF_SIZE]={'\0'};
6589 char cmd[MAX_CMD_SIZE]={'\0'};
6590 struct params params;
6591 char config_file[MAX_BUF_SIZE] = {0};
6592
6593 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6594 if (number > MAX_ASSOCIATED_STA_NUM) {
6595 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6596 return RETURN_ERR;
6597 }
6598 sprintf(str, "%d", number);
6599 params.name = "max_num_sta";
6600 params.value = str;
6601
6602 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6603 int ret = wifi_hostapdWrite(config_file, &params, 1);
6604 if (ret) {
6605 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6606 ,__func__, ret);
6607 }
6608
6609 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6610 if (ret) {
6611 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6612 ,__func__, ret);
6613 }
6614 wifi_reloadAp(apIndex);
6615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6616
6617 return RETURN_OK;
6618}
6619
6620//The HighWatermarkThreshold value that is lesser than or equal to MaxAssociatedDevices. Setting this parameter does not actually limit the number of clients that can associate with this access point as that is controlled by MaxAssociatedDevices. MaxAssociatedDevices or 50. The default value of this parameter should be equal to MaxAssociatedDevices. In case MaxAssociatedDevices is 0 (zero), the default value of this parameter should be 50. A value of 0 means that there is no specific limit and Watermark calculation algorithm should be turned off.
6621INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6622{
6623 //get the current threshold
6624 if(!output_uint)
6625 return RETURN_ERR;
6626 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6627 if (*output_uint == 0)
6628 *output_uint = 50;
6629 return RETURN_OK;
6630}
6631
6632INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6633{
6634 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6635 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6636 return RETURN_OK;
6637 return RETURN_ERR;
6638}
6639
6640//Number of times the current total number of associated device has reached the HighWatermarkThreshold value. This calculation can be based on the parameter AssociatedDeviceNumberOfEntries as well. Implementation specifics about this parameter are left to the product group and the device vendors. It can be updated whenever there is a new client association request to the access point.
6641INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6642{
6643 if(!output_uint)
6644 return RETURN_ERR;
6645 *output_uint = 3;
6646 return RETURN_OK;
6647}
6648
6649//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6650INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6651{
6652 if(!output_uint)
6653 return RETURN_ERR;
6654 *output_uint = 3;
6655 return RETURN_OK;
6656}
6657
6658//Date and Time at which the maximum number of associated devices ever associated with the access point concurrenlty since the last reset of the device or WiFi module (or in short when was X_COMCAST-COM_AssociatedDevicesHighWatermark updated). This dateTime value is in UTC.
6659INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6660{
6661 if(!output_in_seconds)
6662 return RETURN_ERR;
6663 *output_in_seconds = 0;
6664 return RETURN_OK;
6665}
6666
6667//Comma-separated list of strings. Indicates which security modes this AccessPoint instance is capable of supporting. Each list item is an enumeration of: None,WEP-64,WEP-128,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise
6668INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6669{
6670 if(!output || apIndex>=MAX_APS)
6671 return RETURN_ERR;
6672 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6673 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6674 return RETURN_OK;
6675}
6676
6677//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6678INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6679{
6680 char config_file[128] = {0};
6681 char wpa[16] = {0};
6682 char key_mgmt[64] = {0};
6683 char buf[16] = {0};
6684 if (!output)
6685 return RETURN_ERR;
6686
6687 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6688 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6689
6690 strcpy(output, "None");//Copying "None" to output string for default case
6691 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6692 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6693 if (!strcmp(wpa, "1"))
6694 snprintf(output, 32, "WPA-Personal");
6695 else if (!strcmp(wpa, "2"))
6696 snprintf(output, 32, "WPA2-Personal");
6697 else if (!strcmp(wpa, "3"))
6698 snprintf(output, 32, "WPA-WPA2-Personal");
6699
6700 } else if (strstr(key_mgmt, "WPA-EAP")) {
6701 if (!strcmp(wpa, "1"))
6702 snprintf(output, 32, "WPA-Enterprise");
6703 else if (!strcmp(wpa, "2"))
6704 snprintf(output, 32, "WPA2-Enterprise");
6705 else if (!strcmp(wpa, "3"))
6706 snprintf(output, 32, "WPA-WPA2-Enterprise");
6707 } else if (strstr(key_mgmt, "SAE")) {
6708 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6709 snprintf(output, 32, "WPA3-Personal");
6710 else
6711 snprintf(output, 32, "WPA3-Personal-Transition");
6712 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6713 snprintf(output, 32, "WPA3-Enterprise");
6714 }
6715
6716 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6717 return RETURN_OK;
6718#if 0
6719 //TODO: need to revisit below implementation
6720 char securityType[32], authMode[32];
6721 int enterpriseMode=0;
6722
6723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6724 if(!output)
6725 return RETURN_ERR;
6726
6727 wifi_getApBeaconType(apIndex, securityType);
6728 strcpy(output,"None");//By default, copying "None" to output string
6729 if (strncmp(securityType,"None", strlen("None")) == 0)
6730 return RETURN_OK;
6731
6732 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6733 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6734
6735 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6736 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6737 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6738 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6739 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6740 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6741 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6742
6743 return RETURN_OK;
6744#endif
6745}
6746
6747INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6748{
6749 char securityType[32];
6750 char authMode[32];
6751
6752 //store settings and wait for wifi up to apply
6753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6754 if(!encMode)
6755 return RETURN_ERR;
6756
6757 if (strcmp(encMode, "None")==0)
6758 {
6759 strcpy(securityType,"None");
6760 strcpy(authMode,"None");
6761 }
6762 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6763 {
6764 strcpy(securityType,"WPAand11i");
6765 strcpy(authMode,"PSKAuthentication");
6766 }
6767 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6768 {
6769 strcpy(securityType,"WPAand11i");
6770 strcpy(authMode,"EAPAuthentication");
6771 }
6772 else if (strcmp(encMode, "WPA-Personal")==0)
6773 {
6774 strcpy(securityType,"WPA");
6775 strcpy(authMode,"PSKAuthentication");
6776 }
6777 else if (strcmp(encMode, "WPA-Enterprise")==0)
6778 {
6779 strcpy(securityType,"WPA");
6780 strcpy(authMode,"EAPAuthentication");
6781 }
6782 else if (strcmp(encMode, "WPA2-Personal")==0)
6783 {
6784 strcpy(securityType,"11i");
6785 strcpy(authMode,"PSKAuthentication");
6786 }
6787 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6788 {
6789 strcpy(securityType,"11i");
6790 strcpy(authMode,"EAPAuthentication");
6791 }
6792 else if (strcmp(encMode, "WPA3-Personal") == 0)
6793 {
6794 strcpy(securityType,"11i");
6795 strcpy(authMode,"SAEAuthentication");
6796 }
6797 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6798 {
6799 strcpy(securityType, "11i");
6800 strcpy(authMode, "PSK-SAEAuthentication");
6801 }
6802 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6803 {
6804 strcpy(securityType,"11i");
6805 strcpy(authMode,"EAP_192-bit_Authentication");
6806 }
developer3086e2f2023-01-17 09:40:01 +08006807 else if (strcmp(encMode, "OWE") == 0)
6808 {
6809 strcpy(securityType,"11i");
6810 strcpy(authMode,"Enhanced_Open");
6811 }
developer72fb0bb2023-01-11 09:46:29 +08006812 else
6813 {
6814 strcpy(securityType,"None");
6815 strcpy(authMode,"None");
6816 }
6817 wifi_setApBeaconType(apIndex, securityType);
6818 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6819 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6820
6821 return RETURN_OK;
6822}
6823
6824
6825//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6826// output_string must be pre-allocated as 64 character string by caller
6827// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6828INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6829{
6830 char buf[16] = {0};
6831 char config_file[MAX_BUF_SIZE] = {0};
6832
6833 if(output_string==NULL)
6834 return RETURN_ERR;
6835
6836 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6837 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6838
6839 if(strcmp(buf,"0")==0)
6840 {
6841 printf("wpa_mode is %s ......... \n",buf);
6842 return RETURN_ERR;
6843 }
6844
6845 wifi_dbg_printf("\nFunc=%s\n",__func__);
6846 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6847 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6848 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6849
6850 return RETURN_OK;
6851}
6852
6853// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6854// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6855INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6856{
6857 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6858 struct params params={'\0'};
6859 int ret;
6860 char config_file[MAX_BUF_SIZE] = {0};
6861
6862 if(NULL == preSharedKey)
6863 return RETURN_ERR;
6864
6865 params.name = "wpa_passphrase";
6866
6867 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6868 {
6869 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6870 return RETURN_ERR;
6871 }
6872 params.value = preSharedKey;
6873 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6874 ret = wifi_hostapdWrite(config_file, &params, 1);
6875 if(!ret)
6876 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6877 return ret;
6878 //TODO: call hostapd_cli for dynamic_config_control
6879}
6880
6881//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6882// outputs the passphrase, maximum 63 characters
6883INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6884{
6885 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6886
6887 wifi_dbg_printf("\nFunc=%s\n",__func__);
6888 if (NULL == output_string)
6889 return RETURN_ERR;
6890
6891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6892 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6893 if(strcmp(buf,"0")==0)
6894 {
6895 printf("wpa_mode is %s ......... \n",buf);
6896 return RETURN_ERR;
6897 }
6898
6899 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6900 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6901
6902 return RETURN_OK;
6903}
6904
6905// sets the passphrase enviornment variable, max 63 characters
6906INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6907{
6908 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6909 struct params params={'\0'};
6910 char config_file[MAX_BUF_SIZE] = {0};
6911 int ret;
6912
6913 if(NULL == passPhrase)
6914 return RETURN_ERR;
6915
6916 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6917 {
6918 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6919 return RETURN_ERR;
6920 }
6921 params.name = "wpa_passphrase";
6922 params.value = passPhrase;
6923 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6924 ret=wifi_hostapdWrite(config_file,&params,1);
6925 if(!ret)
6926 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6927
6928 return ret;
6929}
6930
6931//When set to true, this AccessPoint instance's WiFi security settings are reset to their factory default values. The affected settings include ModeEnabled, WEPKey, PreSharedKey and KeyPassphrase.
6932INT wifi_setApSecurityReset(INT apIndex)
6933{
6934 char original_config_file[64] = {0};
6935 char current_config_file[64] = {0};
6936 char buf[64] = {0};
6937 char cmd[64] = {0};
6938 char wpa[4] = {0};
6939 char wpa_psk[64] = {0};
6940 char wpa_passphrase[64] = {0};
6941 char wpa_psk_file[128] = {0};
6942 char wpa_key_mgmt[64] = {0};
6943 char wpa_pairwise[32] = {0};
6944 wifi_band band;
6945 struct params list[6];
6946
6947 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6948
6949 band = wifi_index_to_band(apIndex);
6950 if (band == band_2_4)
6951 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6952 else if (band == band_5)
6953 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6954 else if (band == band_6)
6955 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6956 else
6957 return RETURN_ERR;
6958
6959 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6960 list[0].name = "wpa";
6961 list[0].value = wpa;
6962
6963 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6964 list[1].name = "wpa_psk";
6965 list[1].value = wpa_psk;
6966
6967 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6968 list[2].name = "wpa_passphrase";
6969 list[2].value = wpa_passphrase;
6970
6971 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6972
6973 if (strlen(wpa_psk_file) == 0)
6974 strcpy(wpa_psk_file, PSK_FILE);
6975
6976 if (access(wpa_psk_file, F_OK) != 0) {
6977 sprintf(cmd, "touch %s", wpa_psk_file);
6978 _syscmd(cmd, buf, sizeof(buf));
6979 }
6980 list[3].name = "wpa_psk_file";
6981 list[3].value = wpa_psk_file;
6982
6983 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6984 list[4].name = "wpa_key_mgmt";
6985 list[4].value = wpa_key_mgmt;
6986
6987 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6988 list[5].name = "wpa_pairwise";
6989 list[5].value = wpa_pairwise;
6990
6991 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6992 wifi_hostapdWrite(current_config_file, list, 6);
6993
6994 wifi_setApEnable(apIndex, FALSE);
6995 wifi_setApEnable(apIndex, TRUE);
6996
6997 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6998 return RETURN_OK;
6999}
7000
7001//The IP Address and port number of the RADIUS server used for WLAN security. RadiusServerIPAddr is only applicable when ModeEnabled is an Enterprise type (i.e. WPA-Enterprise, WPA2-Enterprise or WPA-WPA2-Enterprise).
7002INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7003{
7004 char config_file[64] = {0};
7005 char buf[64] = {0};
7006 char cmd[256] = {0};
7007
7008 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7009
7010 if(!IP_output || !Port_output || !RadiusSecret_output)
7011 return RETURN_ERR;
7012
7013 // Read the first matched config
7014 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7015 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7016 _syscmd(cmd, buf, sizeof(buf));
7017 strncpy(IP_output, buf, 64);
7018
7019 memset(buf, 0, sizeof(buf));
7020 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7021 _syscmd(cmd, buf, sizeof(buf));
7022 *Port_output = atoi(buf);
7023
7024 memset(buf, 0, sizeof(buf));
7025 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7026 _syscmd(cmd, buf, sizeof(buf));
7027 strncpy(RadiusSecret_output, buf, 64);
7028
7029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7030 return RETURN_OK;
7031}
7032
7033INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7034{
7035 char config_file[64] = {0};
7036 char port_str[8] = {0};
7037 char cmd[256] = {0};
7038 char buf[128] = {0};
7039
7040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7041
7042 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7043
7044 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7045 _syscmd(cmd, buf, sizeof(buf));
7046 memset(cmd, 0, sizeof(cmd));
7047
7048 snprintf(port_str, sizeof(port_str), "%d", port);
7049 if (strlen(buf) == 0)
7050 // Append
7051 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7052 "auth_server_addr=%s\\n"
7053 "auth_server_port=%s\\n"
7054 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7055 else {
7056 // Delete the three lines setting after the "# radius 1" comment
7057 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7058 _syscmd(cmd, buf, sizeof(buf));
7059 memset(cmd, 0, sizeof(cmd));
7060 // Use "# radius 1" comment to find the location to insert the radius setting
7061 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7062 "# radius 1\\n"
7063 "auth_server_addr=%s\\n"
7064 "auth_server_port=%s\\n"
7065 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7066 }
7067 if(_syscmd(cmd, buf, sizeof(buf))) {
7068 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7069 return RETURN_ERR;
7070 }
7071
7072 wifi_reloadAp(apIndex);
7073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7074 return RETURN_OK;
7075}
7076
7077INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7078{
7079 char config_file[64] = {0};
7080 char buf[64] = {0};
7081 char cmd[256] = {0};
7082
7083 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7084
7085 if(!IP_output || !Port_output || !RadiusSecret_output)
7086 return RETURN_ERR;
7087
7088 // Read the second matched config
7089 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7090 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7091 _syscmd(cmd, buf, sizeof(buf));
7092 strncpy(IP_output, buf, 64);
7093
7094 memset(buf, 0, sizeof(buf));
7095 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7096 _syscmd(cmd, buf, sizeof(buf));
7097 *Port_output = atoi(buf);
7098
7099 memset(buf, 0, sizeof(buf));
7100 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7101 _syscmd(cmd, buf, sizeof(buf));
7102 strncpy(RadiusSecret_output, buf, 64);
7103
7104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7105 return RETURN_OK;
7106}
7107
7108INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7109{
7110 char config_file[64] = {0};
7111 char port_str[8] = {0};
7112 char cmd[256] = {0};
7113 char buf[128] = {0};
7114
7115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7116
7117 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7118
7119 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7120 _syscmd(cmd, buf, sizeof(buf));
7121 memset(cmd, 0, sizeof(cmd));
7122
7123 snprintf(port_str, sizeof(port_str), "%d", port);
7124 if (strlen(buf) == 0)
7125 // Append
7126 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7127 "auth_server_addr=%s\\n"
7128 "auth_server_port=%s\\n"
7129 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7130 else {
7131 // Delete the three lines setting after the "# radius 2" comment
7132 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7133 _syscmd(cmd, buf, sizeof(buf));
7134 memset(cmd, 0, sizeof(cmd));
7135 // Use "# radius 2" comment to find the location to insert the radius setting
7136 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7137 "# radius 2\\n"
7138 "auth_server_addr=%s\\n"
7139 "auth_server_port=%s\\n"
7140 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7141 }
7142 if(_syscmd(cmd, buf, sizeof(buf))) {
7143 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7144 return RETURN_ERR;
7145 }
7146
7147 wifi_reloadAp(apIndex);
7148 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7149 return RETURN_OK;
7150}
7151
7152//RadiusSettings
7153INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7154{
7155 if(!output)
7156 return RETURN_ERR;
7157
7158 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
7159 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7160 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7161 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7162 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
7163 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.
7164 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7165 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7166 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
7167 //snprintf(output->RadiusSecret, 64, "12345678"); //The secret used for handshaking with the RADIUS server [RFC2865]. When read, this parameter returns an empty string, regardless of the actual value.
7168
7169 return RETURN_OK;
7170}
7171
7172INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7173{
7174 //store the paramters, and apply instantly
7175 return RETURN_ERR;
7176}
7177
7178//Device.WiFi.AccessPoint.{i}.WPS.Enable
7179//Enables or disables WPS functionality for this access point.
7180// outputs the WPS enable state of this ap in output_bool
7181INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7182{
7183 char interface_name[16] = {0};
7184 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7185 if(!output_bool)
7186 return RETURN_ERR;
7187 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7188 return RETURN_ERR;
7189 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7190 _syscmd(cmd, buf, sizeof(buf));
7191 if(strstr(buf, "configured"))
7192 *output_bool=TRUE;
7193 else
7194 *output_bool=FALSE;
7195
7196 return RETURN_OK;
7197}
7198
7199//Device.WiFi.AccessPoint.{i}.WPS.Enable
7200// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7201INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7202{
7203 char config_file[MAX_BUF_SIZE] = {0};
7204 struct params params;
7205
7206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7207 //store the paramters, and wait for wifi up to apply
7208 params.name = "wps_state";
7209 params.value = enable ? "2":"0";
7210
7211 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7212 wifi_hostapdWrite(config_file, &params, 1);
7213 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7214 wifi_reloadAp(apIndex);
7215
7216 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7217 return RETURN_OK;
7218}
7219
7220//Comma-separated list of strings. Indicates WPS configuration methods supported by the device. Each list item is an enumeration of: USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
7221INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7222{
7223 if(!output)
7224 return RETURN_ERR;
7225 snprintf(output, 128, "PushButton,PIN");
7226 return RETURN_OK;
7227}
7228
7229//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7230//Comma-separated list of strings. Each list item MUST be a member of the list reported by the ConfigMethodsSupported parameter. Indicates WPS configuration methods enabled on the device.
7231// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7232INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7233{
7234 if(!output)
7235 return RETURN_ERR;
7236 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7237
7238 return RETURN_OK;
7239}
7240
7241//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7242// sets an enviornment variable that specifies the WPS configuration method(s). methodString is a comma separated list of methods USBFlashDrive,Ethernet,ExternalNFCToken,IntegratedNFCToken,NFCInterface,PushButton,PIN
7243INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7244{
7245 //apply instantly. No setting need to be stored.
7246 char methods[MAX_BUF_SIZE], *token, *next_token;
7247 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7248 struct params params;
7249
7250 if(!methodString)
7251 return RETURN_ERR;
7252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7253 //store the paramters, and wait for wifi up to apply
7254
7255 snprintf(methods, sizeof(methods), "%s", methodString);
7256 for(token=methods; *token; token=next_token)
7257 {
7258 strtok_r(token, ",", &next_token);
7259 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7260 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7261 else if(*token=='E')
7262 {
7263 if(!strcmp(methods, "Ethernet"))
7264 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7265 else if(!strcmp(methods, "ExternalNFCToken"))
7266 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7267 else
7268 printf("%s: Unknown WpsConfigMethod\n", __func__);
7269 }
7270 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7271 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7272 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7273 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7274 else if(*token=='P' )
7275 {
7276 if(!strcmp(token, "PushButton"))
7277 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7278 else if(!strcmp(token, "PIN"))
7279 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7280 else
7281 printf("%s: Unknown WpsConfigMethod\n", __func__);
7282 }
7283 else
7284 printf("%s: Unknown WpsConfigMethod\n", __func__);
7285 }
7286 params.name = "config_methods";
7287 params.value = config_methods;
7288 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7289 wifi_hostapdWrite(config_file, &params, 1);
7290 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7292
7293 return RETURN_OK;
7294}
7295
7296// outputs the pin value, ulong_pin must be allocated by the caller
7297INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7298{
7299 char buf[MAX_BUF_SIZE] = {0};
7300 char cmd[MAX_CMD_SIZE] = {0};
7301
7302 if(!output_ulong)
7303 return RETURN_ERR;
7304 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7305 _syscmd(cmd, buf, sizeof(buf));
7306 if(strlen(buf) > 0)
7307 *output_ulong=strtoul(buf, NULL, 10);
7308
7309 return RETURN_OK;
7310}
7311
7312// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7313INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7314{
7315 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7316 char ap_pin[16] = {0};
7317 char buf[MAX_BUF_SIZE] = {0};
7318 char config_file[MAX_BUF_SIZE] = {0};
7319 ULONG prev_pin = 0;
7320 struct params params;
7321
7322 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7323 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7324 params.name = "ap_pin";
7325 params.value = ap_pin;
7326 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7327 wifi_hostapdWrite(config_file, &params, 1);
7328 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7330
7331 return RETURN_OK;
7332}
7333
7334// Output string is either Not configured or Configured, max 32 characters
7335INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7336{
7337 char interface_name[16] = {0};
7338 char cmd[MAX_CMD_SIZE];
7339 char buf[MAX_BUF_SIZE]={0};
7340
7341 if(!output_string)
7342 return RETURN_ERR;
7343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7344 snprintf(output_string, 32, "Not configured");
7345 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7346 return RETURN_ERR;
7347 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7348 _syscmd(cmd, buf, sizeof(buf));
7349
7350 if(!strncmp(buf, "configured", 10))
7351 snprintf(output_string, 32, "Configured");
7352 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7353
7354 return RETURN_OK;
7355}
7356
7357// sets the WPS pin for this AP
7358INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7359{
7360 char interface_name[16] = {0};
7361 char cmd[MAX_CMD_SIZE];
7362 char buf[MAX_BUF_SIZE]={0};
7363 BOOL enable;
7364
7365 wifi_getApEnable(apIndex, &enable);
7366 if (!enable)
7367 return RETURN_ERR;
7368 wifi_getApWpsEnable(apIndex, &enable);
7369 if (!enable)
7370 return RETURN_ERR;
7371
7372 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7373 return RETURN_ERR;
7374 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7375 _syscmd(cmd, buf, sizeof(buf));
7376 if((strstr(buf, "OK"))!=NULL)
7377 return RETURN_OK;
7378
7379 return RETURN_ERR;
7380}
7381
7382// This function is called when the WPS push button has been pressed for this AP
7383INT wifi_setApWpsButtonPush(INT apIndex)
7384{
7385 char cmd[MAX_CMD_SIZE];
7386 char buf[MAX_BUF_SIZE]={0};
7387 char interface_name[16] = {0};
7388 BOOL enable=FALSE;
7389
7390 wifi_getApEnable(apIndex, &enable);
7391 if (!enable)
7392 return RETURN_ERR;
7393
7394 wifi_getApWpsEnable(apIndex, &enable);
7395 if (!enable)
7396 return RETURN_ERR;
7397
7398 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7399 return RETURN_ERR;
7400
7401 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7402 _syscmd(cmd, buf, sizeof(buf));
7403
7404 if((strstr(buf, "OK"))!=NULL)
7405 return RETURN_OK;
7406 return RETURN_ERR;
7407}
7408
7409// cancels WPS mode for this AP
7410INT wifi_cancelApWPS(INT apIndex)
7411{
7412 char interface_name[16] = {0};
7413 char cmd[MAX_CMD_SIZE];
7414 char buf[MAX_BUF_SIZE]={0};
7415
7416 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7417 return RETURN_ERR;
7418 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7419 _syscmd(cmd,buf, sizeof(buf));
7420
7421 if((strstr(buf, "OK"))!=NULL)
7422 return RETURN_OK;
7423 return RETURN_ERR;
7424}
7425
7426//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7427//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7428INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7429{
7430 char interface_name[16] = {0};
7431 FILE *f = NULL;
7432 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7433 char cmd[256] = {0}, buf[2048] = {0};
7434 char *param = NULL, *value = NULL, *line=NULL;
7435 size_t len = 0;
7436 ssize_t nread = 0;
7437 wifi_associated_dev_t *dev=NULL;
7438
7439 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7440 *associated_dev_array = NULL;
7441 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7442 return RETURN_ERR;
7443 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7444 _syscmd(cmd,buf,sizeof(buf));
7445 *output_array_size = atoi(buf);
7446
7447 if (*output_array_size <= 0)
7448 return RETURN_OK;
7449
7450 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7451 *associated_dev_array = dev;
7452 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7453 _syscmd(cmd,buf,sizeof(buf));
7454 f = fopen("/tmp/connected_devices.txt", "r");
7455 if (f==NULL)
7456 {
7457 *output_array_size=0;
7458 return RETURN_ERR;
7459 }
7460 while ((getline(&line, &len, f)) != -1)
7461 {
7462 param = strtok(line,"=");
7463 value = strtok(NULL,"=");
7464
7465 if( strcmp("flags",param) == 0 )
7466 {
7467 value[strlen(value)-1]='\0';
7468 if(strstr (value,"AUTHORIZED") != NULL )
7469 {
7470 dev[auth_temp].cli_AuthenticationState = 1;
7471 dev[auth_temp].cli_Active = 1;
7472 auth_temp++;
7473 read_flag=1;
7474 }
7475 }
7476 if(read_flag==1)
7477 {
7478 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7479 {
7480 value[strlen(value)-1]='\0';
7481 sscanf(value, "%x:%x:%x:%x:%x:%x",
7482 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7483 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7484 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7485 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7486 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7487 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7488 mac_temp++;
7489 read_flag=0;
7490 }
7491 }
7492 }
7493 *output_array_size = auth_temp;
7494 auth_temp=0;
7495 mac_temp=0;
7496 free(line);
7497 fclose(f);
7498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7499 return RETURN_OK;
7500}
7501
7502#define MACADDRESS_SIZE 6
7503
7504INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7505{
7506 FILE *fp = NULL;
7507 char str[MAX_BUF_SIZE] = {0};
7508 int wificlientindex = 0 ;
7509 int count = 0;
7510 int signalstrength = 0;
7511 int arr[MACADDRESS_SIZE] = {0};
7512 unsigned char mac[MACADDRESS_SIZE] = {0};
7513 UINT wifi_count = 0;
7514 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7515 char pipeCmd[MAX_CMD_SIZE] = {0};
7516
7517 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7518 *output_array_size = 0;
7519 *associated_dev_array = NULL;
7520
7521 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7522 fp = popen(pipeCmd, "r");
7523 if (fp == NULL)
7524 {
7525 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7526 return RETURN_ERR;
7527 }
7528
7529 /* Read the output a line at a time - output it. */
7530 fgets(str, sizeof(str)-1, fp);
7531 wifi_count = (unsigned int) atoi ( str );
7532 *output_array_size = wifi_count;
7533 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7534 pclose(fp);
7535
7536 if(wifi_count == 0)
7537 {
7538 return RETURN_OK;
7539 }
7540 else
7541 {
7542 wifi_associated_dev3_t* temp = NULL;
7543 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7544 if(temp == NULL)
7545 {
7546 printf("Error Statement. Insufficient memory \n");
7547 return RETURN_ERR;
7548 }
7549
7550 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7551 system(pipeCmd);
7552 memset(pipeCmd,0,sizeof(pipeCmd));
7553 if(apIndex == 0)
7554 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7555 else if(apIndex == 1)
7556 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7557 system(pipeCmd);
7558
7559 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7560 if(fp == NULL)
7561 {
7562 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7563 free(temp);
7564 return RETURN_ERR;
7565 }
7566 fclose(fp);
7567
7568 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7569 fp = popen(pipeCmd, "r");
7570 if(fp)
7571 {
7572 for(count =0 ; count < wifi_count; count++)
7573 {
7574 fgets(str, MAX_BUF_SIZE, fp);
7575 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7576 {
7577 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7578 {
7579 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7580
7581 }
7582 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7583 printf("MAC %d = %X:%X:%X:%X:%X:%X \n", count, temp[count].cli_MACAddress[0],temp[count].cli_MACAddress[1], temp[count].cli_MACAddress[2], temp[count].cli_MACAddress[3], temp[count].cli_MACAddress[4], temp[count].cli_MACAddress[5]);
7584 }
7585 temp[count].cli_AuthenticationState = 1; //TODO
7586 temp[count].cli_Active = 1; //TODO
7587 }
7588 pclose(fp);
7589 }
7590
7591 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7592 fp = popen(pipeCmd, "r");
7593 if(fp)
7594 {
7595 pclose(fp);
7596 }
7597 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7598 if(fp)
7599 {
7600 for(count =0 ; count < wifi_count ;count++)
7601 {
7602 fgets(str, MAX_BUF_SIZE, fp);
7603 signalstrength = atoi(str);
7604 temp[count].cli_SignalStrength = signalstrength;
7605 temp[count].cli_RSSI = signalstrength;
7606 temp[count].cli_SNR = signalstrength + 95;
7607 }
7608 pclose(fp);
7609 }
7610
7611
7612 if((apIndex == 0) || (apIndex == 4))
7613 {
7614 for(count =0 ; count < wifi_count ;count++)
7615 {
7616 strcpy(temp[count].cli_OperatingStandard,"g");
7617 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7618 }
7619
7620 //BytesSent
7621 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7622 fp = popen(pipeCmd, "r");
7623 if(fp)
7624 {
7625 pclose(fp);
7626 }
7627 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7628 if(fp)
7629 {
7630 for (count = 0; count < wifi_count; count++)
7631 {
7632 fgets(str, MAX_BUF_SIZE, fp);
7633 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7634 }
7635 pclose(fp);
7636 }
7637
7638 //BytesReceived
7639 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7640 fp = popen(pipeCmd, "r");
7641 if (fp)
7642 {
7643 pclose(fp);
7644 }
7645 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7646 if (fp)
7647 {
7648 for (count = 0; count < wifi_count; count++)
7649 {
7650 fgets(str, MAX_BUF_SIZE, fp);
7651 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7652 }
7653 pclose(fp);
7654 }
7655
7656 //PacketsSent
7657 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7658 fp = popen(pipeCmd, "r");
7659 if (fp)
7660 {
7661 pclose(fp);
7662 }
7663
7664 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7665 if (fp)
7666 {
7667 for (count = 0; count < wifi_count; count++)
7668 {
7669 fgets(str, MAX_BUF_SIZE, fp);
7670 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7671 }
7672 pclose(fp);
7673 }
7674
7675 //PacketsReceived
7676 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7677 fp = popen(pipeCmd, "r");
7678 if (fp)
7679 {
7680 pclose(fp);
7681 }
7682 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7683 if (fp)
7684 {
7685 for (count = 0; count < wifi_count; count++)
7686 {
7687 fgets(str, MAX_BUF_SIZE, fp);
7688 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7689 }
7690 pclose(fp);
7691 }
7692
7693 //ErrorsSent
7694 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7695 fp = popen(pipeCmd, "r");
7696 if (fp)
7697 {
7698 pclose(fp);
7699 }
7700 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7701 if (fp)
7702 {
7703 for (count = 0; count < wifi_count; count++)
7704 {
7705 fgets(str, MAX_BUF_SIZE, fp);
7706 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7707 }
7708 pclose(fp);
7709 }
7710
7711 //ErrorsSent
7712 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7713 fp = popen(pipeCmd, "r");
7714 if (fp)
7715 {
7716 pclose(fp);
7717 }
7718 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7719 if (fp)
7720 {
7721 for (count = 0; count < wifi_count; count++)
7722 {
7723 fgets(str, MAX_BUF_SIZE, fp);
7724 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7725 }
7726 pclose(fp);
7727 }
7728
7729 //LastDataDownlinkRate
7730 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7731 fp = popen(pipeCmd, "r");
7732 if (fp)
7733 {
7734 pclose(fp);
7735 }
7736 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7737 if (fp)
7738 {
7739 for (count = 0; count < wifi_count; count++)
7740 {
7741 fgets(str, MAX_BUF_SIZE, fp);
7742 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7743 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7744 }
7745 pclose(fp);
7746 }
7747
7748 //LastDataUplinkRate
7749 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7750 fp = popen(pipeCmd, "r");
7751 if (fp)
7752 {
7753 pclose(fp);
7754 }
7755 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7756 if (fp)
7757 {
7758 for (count = 0; count < wifi_count; count++)
7759 {
7760 fgets(str, MAX_BUF_SIZE, fp);
7761 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7762 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7763 }
7764 pclose(fp);
7765 }
7766
7767 }
7768 else if ((apIndex == 1) || (apIndex == 5))
7769 {
7770 for (count = 0; count < wifi_count; count++)
7771 {
7772 strcpy(temp[count].cli_OperatingStandard, "a");
7773 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7774 temp[count].cli_BytesSent = 0;
7775 temp[count].cli_BytesReceived = 0;
7776 temp[count].cli_LastDataUplinkRate = 0;
7777 temp[count].cli_LastDataDownlinkRate = 0;
7778 temp[count].cli_PacketsSent = 0;
7779 temp[count].cli_PacketsReceived = 0;
7780 temp[count].cli_ErrorsSent = 0;
7781 }
7782 }
7783
7784 for (count = 0; count < wifi_count; count++)
7785 {
7786 temp[count].cli_Retransmissions = 0;
7787 temp[count].cli_DataFramesSentAck = 0;
7788 temp[count].cli_DataFramesSentNoAck = 0;
7789 temp[count].cli_MinRSSI = 0;
7790 temp[count].cli_MaxRSSI = 0;
7791 strncpy(temp[count].cli_InterferenceSources, "", 64);
7792 memset(temp[count].cli_IPAddress, 0, 64);
7793 temp[count].cli_RetransCount = 0;
7794 temp[count].cli_FailedRetransCount = 0;
7795 temp[count].cli_RetryCount = 0;
7796 temp[count].cli_MultipleRetryCount = 0;
7797 }
7798 *associated_dev_array = temp;
7799 }
7800 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7801 return RETURN_OK;
7802}
7803
7804int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7805{
7806 FILE *fp = NULL;
7807 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7808 char cmd[MAX_CMD_SIZE];
7809 int count = 0;
7810
7811 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7812 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7813 fp = popen(cmd,"r");
7814 if(fp == NULL)
7815 {
7816 printf("Failed to run command in Function %s\n",__FUNCTION__);
7817 return 0;
7818 }
7819 if(fgets(path, sizeof(path)-1, fp) != NULL)
7820 {
7821 for(count=0;path[count]!='\n';count++)
7822 status[count]=path[count];
7823 status[count]='\0';
7824 }
7825 strcpy(wifi_status,status);
7826 pclose(fp);
7827 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7828 return RETURN_OK;
7829}
7830
7831/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7832struct hostapd_sta_param {
7833 char key[50];
7834 char value[100];
7835}
7836
7837static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7838 int i = 0;
7839
7840 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7841 if (strncmp(params[i].key,key,50) == 0){
7842 return &params[i].value;
7843 }
7844 i++;
7845 }
7846 return NULL;
7847
7848} */
7849
7850static unsigned int count_occurences(const char *buf, const char *word)
7851{
7852 unsigned int n = 0;
7853 char *ptr = strstr(buf, word);
7854
7855 while (ptr++) {
7856 n++;
7857 ptr = strstr(ptr, word);
7858 }
7859
7860 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7861 return n;
7862}
7863
7864static const char *get_line_from_str_buf(const char *buf, char *line)
7865{
7866 int i;
7867 int n = strlen(buf);
7868
7869 for (i = 0; i < n; i++) {
7870 line[i] = buf[i];
7871 if (buf[i] == '\n') {
7872 line[i] = '\0';
7873 return &buf[i + 1];
7874 }
7875 }
7876
7877 return NULL;
7878}
7879
7880INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7881{
7882 unsigned int assoc_cnt = 0;
7883 char interface_name[50] = {0};
7884 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7885 char cmd[MAX_CMD_SIZE] = {'\0'};
7886 char line[256] = {'\0'};
7887 int i = 0;
7888 int ret = 0;
7889 const char *ptr = NULL;
7890 char *key = NULL;
7891 char *val = NULL;
7892 wifi_associated_dev3_t *temp = NULL;
7893 int rssi;
7894
7895 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7896
7897 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7898 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7899 return RETURN_ERR;
7900 }
7901
7902 // Example filtered output of 'iw dev' command:
7903 // Station 0a:69:72:10:d2:fa (on wifi0)
7904 // signal avg:-67 [-71, -71] dBm
7905 // Station 28:c2:1f:25:5f:99 (on wifi0)
7906 // signal avg:-67 [-71, -70] dBm
7907 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7908 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7909 return RETURN_ERR;
7910 }
7911
7912 ret = _syscmd(cmd, buf, sizeof(buf));
7913 if (ret == RETURN_ERR) {
7914 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7915 return RETURN_ERR;
7916 }
7917
7918 *output_array_size = count_occurences(buf, "Station");
7919 if (*output_array_size == 0) return RETURN_OK;
7920
7921 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7922 if (temp == NULL) {
7923 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7924 return RETURN_ERR;
7925 }
7926 *associated_dev_array = temp;
7927
7928 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7929 ptr = get_line_from_str_buf(buf, line);
7930 i = -1;
7931 while (ptr) {
7932 if (strstr(line, "Station")) {
7933 i++;
7934 key = strtok(line, " ");
7935 val = strtok(NULL, " ");
7936 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7937 &temp[i].cli_MACAddress[0],
7938 &temp[i].cli_MACAddress[1],
7939 &temp[i].cli_MACAddress[2],
7940 &temp[i].cli_MACAddress[3],
7941 &temp[i].cli_MACAddress[4],
7942 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7943 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7944 free(*associated_dev_array);
7945 return RETURN_ERR;
7946 }
7947 }
7948 else if (i < 0) {
7949 ptr = get_line_from_str_buf(ptr, line);
7950 continue; // We didn't detect 'station' entry yet
7951 }
7952 else if (strstr(line, "signal avg")) {
7953 key = strtok(line, ":");
7954 val = strtok(NULL, " ");
7955 if (sscanf(val, "%d", &rssi) <= 0 ) {
7956 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7957 free(*associated_dev_array);
7958 return RETURN_ERR;
7959 }
7960 temp[i].cli_RSSI = rssi;
7961 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7962 }
7963 // Here other fields can be parsed if added to filter of 'iw dev' command
7964
7965 ptr = get_line_from_str_buf(ptr, line);
7966 };
7967
7968 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7969
7970 return RETURN_OK;
7971}
7972
7973#if 0
7974//To-do
7975INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7976{
7977 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7978
7979 //Using different approach to get required WiFi Parameters from system available commands
7980#if 0
7981 FILE *f;
7982 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7983 char cmd[256], buf[2048];
7984 char *param , *value, *line=NULL;
7985 size_t len = 0;
7986 ssize_t nread;
7987 wifi_associated_dev3_t *dev=NULL;
7988 *associated_dev_array = NULL;
7989 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7990 _syscmd(cmd,buf,sizeof(buf));
7991 *output_array_size = atoi(buf);
7992
7993 if (*output_array_size <= 0)
7994 return RETURN_OK;
7995
7996 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7997 *associated_dev_array = dev;
7998 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
7999 _syscmd(cmd,buf,sizeof(buf));
8000 f = fopen("/tmp/connected_devices.txt", "r");
8001 if (f==NULL)
8002 {
8003 *output_array_size=0;
8004 return RETURN_ERR;
8005 }
8006 while ((nread = getline(&line, &len, f)) != -1)
8007 {
8008 param = strtok(line,"=");
8009 value = strtok(NULL,"=");
8010
8011 if( strcmp("flags",param) == 0 )
8012 {
8013 value[strlen(value)-1]='\0';
8014 if(strstr (value,"AUTHORIZED") != NULL )
8015 {
8016 dev[auth_temp].cli_AuthenticationState = 1;
8017 dev[auth_temp].cli_Active = 1;
8018 auth_temp++;
8019 read_flag=1;
8020 }
8021 }
8022 if(read_flag==1)
8023 {
8024 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8025 {
8026 value[strlen(value)-1]='\0';
8027 sscanf(value, "%x:%x:%x:%x:%x:%x",
8028 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8029 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8030 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8031 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8032 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8033 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8034
8035 }
8036 else if( strcmp("rx_packets",param) == 0 )
8037 {
8038 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8039 }
8040
8041 else if( strcmp("tx_packets",param) == 0 )
8042 {
8043 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
8044 }
8045
8046 else if( strcmp("rx_bytes",param) == 0 )
8047 {
8048 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8049 }
8050
8051 else if( strcmp("tx_bytes",param) == 0 )
8052 {
8053 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
8054 mac_temp++;
8055 read_flag=0;
8056 }
8057 }
8058 }
8059
8060 *output_array_size = auth_temp;
8061 auth_temp=0;
8062 mac_temp=0;
8063 free(line);
8064 fclose(f);
8065#endif
8066 char interface_name[MAX_BUF_SIZE] = {0};
8067 char wifi_status[MAX_BUF_SIZE] = {0};
8068 char hostapdconf[MAX_BUF_SIZE] = {0};
8069
8070 wifi_associated_dev3_t *dev_array = NULL;
8071 ULONG wifi_count = 0;
8072
8073 *associated_dev_array = NULL;
8074 *output_array_size = 0;
8075
8076 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8077 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8078 {
8079 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8080
8081 wifi_GetInterfaceName(interface_name, hostapdconf);
8082
8083 if(strlen(interface_name) > 1)
8084 {
8085 wifihal_interfacestatus(wifi_status,interface_name);
8086 if(strcmp(wifi_status,"RUNNING") == 0)
8087 {
8088 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8089
8090 *associated_dev_array = dev_array;
8091 *output_array_size = wifi_count;
8092 }
8093 else
8094 {
8095 *associated_dev_array = NULL;
8096 }
8097 }
8098 }
8099
8100 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8101 return RETURN_OK;
8102}
8103#endif
8104
8105/* getIPAddress function */
8106/**
8107* @description Returning IpAddress of the Matched String
8108*
8109* @param
8110* @str Having MacAddress
8111* @ipaddr Having ipaddr
8112* @return The status of the operation
8113* @retval RETURN_OK if successful
8114* @retval RETURN_ERR if any error is detected
8115*
8116*/
8117
8118INT getIPAddress(char *str,char *ipaddr)
8119{
8120 FILE *fp = NULL;
8121 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8122 int LeaseTime = 0,ret = 0;
8123 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8124 {
8125 return RETURN_ERR;
8126 }
8127
8128 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8129 {
8130 /*
8131 Sample:sss
8132 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8133 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8134 */
8135 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8136 &(LeaseTime),
8137 phyAddr,
8138 ipAddr,
8139 hostName
8140 );
8141 if(ret != 4)
8142 continue;
8143 if(strcmp(str,phyAddr) == 0)
8144 strcpy(ipaddr,ipAddr);
8145 }
8146 fclose(fp);
8147 return RETURN_OK;
8148}
8149
8150/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8151/**
8152* @description Returning Inactive wireless connected clients informations
8153*
8154* @param
8155* @filename Holding private_wifi 2g/5g content files
8156* @associated_dev_array Having inactiv wireless clients informations
8157* @output_array_size Returning Inactive wireless counts
8158* @return The status of the operation
8159* @retval RETURN_OK if successful
8160* @retval RETURN_ERR if any error is detected
8161*
8162*/
8163
8164INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8165{
8166 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8167 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8168 FILE *fp = NULL;
8169 int arr[MACADDRESS_SIZE] = {0};
8170 unsigned char mac[MACADDRESS_SIZE] = {0};
8171 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8172 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8173 fp = popen(buf,"r");
8174 if(fp == NULL)
8175 return RETURN_ERR;
8176 else
8177 {
8178 fgets(path,sizeof(path),fp);
8179 maccount = atoi(path);
8180 }
8181 pclose(fp);
8182 *output_array_size = maccount;
8183 wifi_associated_dev3_t* temp = NULL;
8184 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8185 *associated_dev_array = temp;
8186 if(temp == NULL)
8187 {
8188 printf("Error Statement. Insufficient memory \n");
8189 return RETURN_ERR;
8190 }
8191 memset(buf,0,sizeof(buf));
8192 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8193 fp = popen(buf,"r");
8194 if (fp == NULL) {
8195 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8196 return RETURN_ERR;
8197 }
8198 for(count = 0; count < maccount ; count++)
8199 {
8200 fgets(path,sizeof(path),fp);
8201 for(i = 0; path[i]!='\n';i++)
8202 str[i]=path[i];
8203 str[i]='\0';
8204 getIPAddress(str,ipaddr);
8205 memset(buf,0,sizeof(buf));
8206 if(strlen(ipaddr) > 0)
8207 {
8208 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8209 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8210 {
8211 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8212 {
8213 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8214 {
8215 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8216
8217 }
8218 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8219 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]);
8220 }
8221 temp[count].cli_AuthenticationState = 0; //TODO
8222 temp[count].cli_Active = 0; //TODO
8223 temp[count].cli_SignalStrength = 0;
8224 }
8225 else //Active wireless clients info
8226 {
8227 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8228 {
8229 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8230 {
8231 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8232
8233 }
8234 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8235 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]);
8236 }
8237 temp[count].cli_Active = 1;
8238 }
8239 }
8240 memset(ipaddr,0,sizeof(ipaddr));
8241 }
8242 pclose(fp);
8243 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8244 return RETURN_OK;
8245}
8246//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8247//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8248//To get Band Steering Capability
8249INT wifi_getBandSteeringCapability(BOOL *support)
8250{
8251 *support = FALSE;
8252 return RETURN_OK;
8253}
8254
8255
8256//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8257//To get Band Steering enable status
8258INT wifi_getBandSteeringEnable(BOOL *enable)
8259{
8260 *enable = FALSE;
8261 return RETURN_OK;
8262}
8263
8264//To turn on/off Band steering
8265INT wifi_setBandSteeringEnable(BOOL enable)
8266{
8267 return RETURN_OK;
8268}
8269
8270//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8271//To get Band Steering AP group
8272INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8273{
8274 if (NULL == output_ApGroup)
8275 return RETURN_ERR;
8276
8277 strcpy(output_ApGroup, "1,2");
8278 return RETURN_OK;
8279}
8280
8281//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8282//to set and read the band steering BandUtilizationThreshold parameters
8283INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8284{
8285 return RETURN_ERR;
8286}
8287
8288INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8289{
8290 return RETURN_ERR;
8291}
8292
8293//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8294//to set and read the band steering RSSIThreshold parameters
8295INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8296{
8297 return RETURN_ERR;
8298}
8299
8300INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8301{
8302 return RETURN_ERR;
8303}
8304
8305
8306//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8307//to set and read the band steering physical modulation rate threshold parameters
8308INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8309{
8310 //If chip is not support, return -1
8311 return RETURN_ERR;
8312}
8313
8314INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8315{
8316 //If chip is not support, return -1
8317 return RETURN_ERR;
8318}
8319
8320//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8321//to set and read the inactivity time (in seconds) for steering under overload condition
8322INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8323{
8324 return RETURN_ERR;
8325}
8326
8327INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8328{
8329 return RETURN_ERR;
8330}
8331
8332//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8333//to set and read the inactivity time (in seconds) for steering under Idle condition
8334INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8335{
8336 return RETURN_ERR;
8337}
8338
8339INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8340{
8341 return RETURN_ERR;
8342}
8343
8344//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8345//pClientMAC[64]
8346//pSourceSSIDIndex[64]
8347//pDestSSIDIndex[64]
8348//pSteeringReason[256]
8349INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8350{
8351 //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
8352 *pSteeringTime=time(NULL);
8353 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8354 return RETURN_OK;
8355}
8356
8357INT wifi_ifConfigDown(INT apIndex)
8358{
8359 INT status = RETURN_OK;
8360 char cmd[64];
8361
8362 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8363 printf("%s: %s\n", __func__, cmd);
8364 system(cmd);
8365
8366 return status;
8367}
8368
8369INT wifi_ifConfigUp(INT apIndex)
8370{
8371 char interface_name[16] = {0};
8372 char cmd[128];
8373 char buf[1024];
8374
8375 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8376 return RETURN_ERR;
8377 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8378 _syscmd(cmd, buf, sizeof(buf));
8379 return 0;
8380}
8381
8382//>> Deprecated. Replace with wifi_applyRadioSettings
8383INT wifi_pushBridgeInfo(INT apIndex)
8384{
8385 char interface_name[16] = {0};
8386 char ip[32] = {0};
8387 char subnet[32] = {0};
8388 char bridge[32] = {0};
8389 int vlanId = 0;
8390 char cmd[128] = {0};
8391 char buf[1024] = {0};
8392
8393 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8394 wifi_getApVlanID(apIndex,&vlanId);
8395
8396 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8397 return RETURN_ERR;
8398 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8399 _syscmd(cmd,buf, sizeof(buf));
8400
8401 return 0;
8402}
8403
8404INT wifi_pushChannel(INT radioIndex, UINT channel)
8405{
8406 char interface_name[16] = {0};
8407 char cmd[128];
8408 char buf[1024];
8409 int apIndex;
8410
8411 apIndex=(radioIndex==0)?0:1;
8412 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8413 return RETURN_ERR;
8414 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8415 _syscmd(cmd,buf, sizeof(buf));
8416
8417 return 0;
8418}
8419
8420INT wifi_pushChannelMode(INT radioIndex)
8421{
8422 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8423 return RETURN_ERR;
8424}
8425
8426INT wifi_pushDefaultValues(INT radioIndex)
8427{
8428 //Apply Comcast specified default radio settings instantly
8429 //AMPDU=1
8430 //AMPDUFrames=32
8431 //AMPDULim=50000
8432 //txqueuelen=1000
8433
8434 return RETURN_ERR;
8435}
8436
8437INT wifi_pushTxChainMask(INT radioIndex)
8438{
8439 //Apply default TxChainMask instantly
8440 return RETURN_ERR;
8441}
8442
8443INT wifi_pushRxChainMask(INT radioIndex)
8444{
8445 //Apply default RxChainMask instantly
8446 return RETURN_ERR;
8447}
8448
8449INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8450{
8451 INT status;
8452
8453 status = wifi_setSSIDName(apIndex,ssid);
8454 wifi_setApEnable(apIndex,FALSE);
8455 wifi_setApEnable(apIndex,TRUE);
8456
8457 return status;
8458}
8459
8460INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8461{
8462 //Apply default Ssid Advertisement instantly
8463 return RETURN_ERR;
8464}
8465
8466INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8467{
8468 INT status = RETURN_ERR;
8469 *output = 0;
8470 return RETURN_ERR;
8471}
8472
8473INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8474{
8475 return RETURN_OK;
8476}
8477
8478INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8479{
8480 return RETURN_OK;
8481}
8482
8483//To-do
8484INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8485{
8486 char output[16]={'\0'};
8487 char config_file[MAX_BUF_SIZE] = {0};
8488
8489 if (!output_string)
8490 return RETURN_ERR;
8491
8492 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8493 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8494
8495 if (strlen(output) == 0)
8496 snprintf(output_string, 64, "Disabled");
8497 else if (strncmp(output, "0", 1) == 0)
8498 snprintf(output_string, 64, "Disabled");
8499 else if (strncmp(output, "1", 1) == 0)
8500 snprintf(output_string, 64, "Optional");
8501 else if (strncmp(output, "2", 1) == 0)
8502 snprintf(output_string, 64, "Required");
8503 else {
8504 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8505 return RETURN_ERR;
8506 }
8507
8508 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8509 return RETURN_OK;
8510}
8511INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8512{
8513 char str[MAX_BUF_SIZE]={'\0'};
8514 char cmd[MAX_CMD_SIZE]={'\0'};
8515 struct params params;
8516 char config_file[MAX_BUF_SIZE] = {0};
8517
8518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8519 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8520 return RETURN_ERR;
8521
8522 params.name = "ieee80211w";
8523 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8524 params.value = "0";
8525 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8526 params.value = "1";
8527 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8528 params.value = "2";
8529 else{
8530 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8531 return RETURN_ERR;
8532 }
8533 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8534 wifi_hostapdWrite(config_file, &params, 1);
8535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8536 return RETURN_OK;
8537}
8538INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8539{
8540 char output[16]={'\0'};
8541 char config_file[MAX_BUF_SIZE] = {0};
8542
8543 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8544 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8545 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8546
8547 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8548 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8549
8550 return RETURN_OK;
8551}
8552
8553INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8554{
8555 return RETURN_OK;
8556}
8557
8558INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8559{
8560 return RETURN_OK;
8561}
8562
8563INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8564{
8565 return RETURN_OK;
8566}
8567
8568INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8569{
8570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8571 char config_file[MAX_BUF_SIZE] = {0};
8572
8573 if (NULL == output)
8574 return RETURN_ERR;
8575 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8576 wifi_hostapdRead(config_file,"hw_mode",output,64);
8577
8578 if(strcmp(output,"b")==0)
8579 sprintf(output, "%s", "1,2,5.5,11");
8580 else if (strcmp(output,"a")==0)
8581 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8582 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8583 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8584
8585 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8586 return RETURN_OK;
8587}
8588
8589INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8590{
8591 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8592 char *temp;
8593 char temp_output[128];
8594 char temp_TransmitRates[128];
8595 char config_file[MAX_BUF_SIZE] = {0};
8596
8597 if (NULL == output)
8598 return RETURN_ERR;
8599
8600 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8601 wifi_hostapdRead(config_file,"supported_rates",output,64);
8602
8603 if (strlen(output) == 0) {
8604 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8605 return RETURN_OK;
8606 }
8607 strcpy(temp_TransmitRates,output);
8608 strcpy(temp_output,"");
8609 temp = strtok(temp_TransmitRates," ");
8610 while(temp!=NULL)
8611 {
8612 temp[strlen(temp)-1]=0;
8613 if((temp[0]=='5') && (temp[1]=='\0'))
8614 {
8615 temp="5.5";
8616 }
8617 strcat(temp_output,temp);
8618 temp = strtok(NULL," ");
8619 if(temp!=NULL)
8620 {
8621 strcat(temp_output,",");
8622 }
8623 }
8624 strcpy(output,temp_output);
8625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8626
8627 return RETURN_OK;
8628}
8629
8630INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8631{
8632 return RETURN_OK;
8633}
8634
8635
8636INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8637{
8638 int i=0;
8639 char *temp;
8640 char temp1[128] = {0};
8641 char temp_output[128] = {0};
8642 char temp_TransmitRates[128] = {0};
8643 struct params params={'\0'};
8644 char config_file[MAX_BUF_SIZE] = {0};
8645 wifi_band band = wifi_index_to_band(wlanIndex);
8646
8647 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8648 if(NULL == output)
8649 return RETURN_ERR;
8650 strcpy(temp_TransmitRates,output);
8651
8652 for(i=0;i<strlen(temp_TransmitRates);i++)
8653 {
8654 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8655 {
8656 continue;
8657 }
8658 else
8659 {
8660 return RETURN_ERR;
8661 }
8662 }
8663 strcpy(temp_output,"");
8664 temp = strtok(temp_TransmitRates,",");
8665 while(temp!=NULL)
8666 {
8667 strcpy(temp1,temp);
8668 if(band == band_5)
8669 {
8670 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8671 {
8672 return RETURN_ERR;
8673 }
8674 }
8675
8676 if(strcmp(temp,"5.5")==0)
8677 {
8678 strcpy(temp1,"55");
8679 }
8680 else
8681 {
8682 strcat(temp1,"0");
8683 }
8684 strcat(temp_output,temp1);
8685 temp = strtok(NULL,",");
8686 if(temp!=NULL)
8687 {
8688 strcat(temp_output," ");
8689 }
8690 }
8691 strcpy(output,temp_output);
8692
8693 params.name = "supported_rates";
8694 params.value = output;
8695
8696 wifi_dbg_printf("\n%s:",__func__);
8697 wifi_dbg_printf("params.value=%s\n",params.value);
8698 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8699 wifi_hostapdWrite(config_file,&params,1);
8700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8701
8702 return RETURN_OK;
8703}
8704
8705
8706static char *sncopy(char *dst, int dst_sz, const char *src)
8707{
8708 if (src && dst && dst_sz > 0) {
8709 strncpy(dst, src, dst_sz);
8710 dst[dst_sz - 1] = '\0';
8711 }
8712 return dst;
8713}
8714
8715static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8716{
8717 if (0 == strcmp(ht_mode, "HT40") ||
8718 0 == strcmp(ht_mode, "HT80") ||
8719 0 == strcmp(ht_mode, "HT160")) {
8720 switch (channel) {
8721 case 1 ... 7:
8722 case 36:
8723 case 44:
8724 case 52:
8725 case 60:
8726 case 100:
8727 case 108:
8728 case 116:
8729 case 124:
8730 case 132:
8731 case 140:
8732 case 149:
8733 case 157:
8734 return 1;
8735 case 8 ... 13:
8736 case 40:
8737 case 48:
8738 case 56:
8739 case 64:
8740 case 104:
8741 case 112:
8742 case 120:
8743 case 128:
8744 case 136:
8745 case 144:
8746 case 153:
8747 case 161:
8748 return -1;
8749 default:
8750 return -EINVAL;
8751 }
8752 }
8753
8754 return -EINVAL;
8755}
8756
8757static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8758{
8759 int idx = channel%8;
8760 if (0 == strcmp(ht_mode, "HT40") ||
8761 0 == strcmp(ht_mode, "HT80") ||
8762 0 == strcmp(ht_mode, "HT160")) {
8763 switch (idx) {
8764 case 1:
8765 return 1;
8766 case 5:
8767 return -1;
8768 default:
8769 return -EINVAL;
8770 }
8771 }
8772
8773 return -EINVAL;
8774}
8775static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8776{
8777 if (NULL == hw_mode) return;
8778
8779 if (0 == strcmp(hw_mode, "ac"))
8780 sncopy(bw_mode, bw_mode_len, "ht vht");
8781
8782 if (0 == strcmp(hw_mode, "n"))
8783 sncopy(bw_mode, bw_mode_len, "ht");
8784
8785 return;
8786}
8787
8788static int util_chan_to_freq(int chan)
8789{
8790 if (chan == 14)
8791 return 2484;
8792 else if (chan < 14)
8793 return 2407 + chan * 5;
8794 else if (chan >= 182 && chan <= 196)
8795 return 4000 + chan * 5;
8796 else
8797 return 5000 + chan * 5;
8798 return 0;
8799}
8800
8801static int util_6G_chan_to_freq(int chan)
8802{
8803 if (chan)
8804 return 5950 + chan * 5;
8805 else
8806 return 0;
8807
8808}
8809const int *util_unii_5g_chan2list(int chan, int width)
8810{
8811 static const int lists[] = {
8812 // <width>, <chan1>, <chan2>..., 0,
8813 20, 36, 0,
8814 20, 40, 0,
8815 20, 44, 0,
8816 20, 48, 0,
8817 20, 52, 0,
8818 20, 56, 0,
8819 20, 60, 0,
8820 20, 64, 0,
8821 20, 100, 0,
8822 20, 104, 0,
8823 20, 108, 0,
8824 20, 112, 0,
8825 20, 116, 0,
8826 20, 120, 0,
8827 20, 124, 0,
8828 20, 128, 0,
8829 20, 132, 0,
8830 20, 136, 0,
8831 20, 140, 0,
8832 20, 144, 0,
8833 20, 149, 0,
8834 20, 153, 0,
8835 20, 157, 0,
8836 20, 161, 0,
8837 20, 165, 0,
8838 40, 36, 40, 0,
8839 40, 44, 48, 0,
8840 40, 52, 56, 0,
8841 40, 60, 64, 0,
8842 40, 100, 104, 0,
8843 40, 108, 112, 0,
8844 40, 116, 120, 0,
8845 40, 124, 128, 0,
8846 40, 132, 136, 0,
8847 40, 140, 144, 0,
8848 40, 149, 153, 0,
8849 40, 157, 161, 0,
8850 80, 36, 40, 44, 48, 0,
8851 80, 52, 56, 60, 64, 0,
8852 80, 100, 104, 108, 112, 0,
8853 80, 116, 120, 124, 128, 0,
8854 80, 132, 136, 140, 144, 0,
8855 80, 149, 153, 157, 161, 0,
8856 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8857 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8858 -1 // final delimiter
8859 };
8860 const int *start;
8861 const int *p;
8862
8863 for (p = lists; *p != -1; p++) {
8864 if (*p == width) {
8865 for (start = ++p; *p != 0; p++) {
8866 if (*p == chan)
8867 return start;
8868 }
8869 }
8870 // move to the end of channel list of given width
8871 while (*p != 0) {
8872 p++;
8873 }
8874 }
8875
8876 return NULL;
8877}
8878
8879static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8880{
8881 if (NULL == ht_mode)
8882 return 0;
8883
8884 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8885 const int *chans = util_unii_5g_chan2list(channel, width);
8886 int sum = 0;
8887 int cnt = 0;
8888
8889 if (NULL == chans)
8890 return 0;
8891
8892 while (*chans) {
8893 sum += *chans;
8894 cnt++;
8895 chans++;
8896 }
8897 if (cnt == 0)
8898 return 0;
8899 return sum / cnt;
8900}
8901
8902static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8903{
8904 if (NULL == ht_mode)
8905 return 0;
8906
8907 int width = strtol((ht_mode + 2), NULL, 10);
8908
8909 int idx = 0 ;
8910 int centerchan = 0;
8911 int chan_ofs = 1;
8912
8913 if (width == 40){
8914 idx = ((channel/4) + chan_ofs)%2;
8915 switch (idx) {
8916 case 0:
8917 centerchan = (channel - 2);
8918 break;
8919 case 1:
8920 centerchan = (channel + 2);
8921 break;
8922 default:
8923 return -EINVAL;
8924 }
8925 }else if (width == 80){
8926 idx = ((channel/4) + chan_ofs)%4;
8927 switch (idx) {
8928 case 0:
8929 centerchan = (channel - 6);
8930 break;
8931 case 1:
8932 centerchan = (channel + 6);
8933 break;
8934 case 2:
8935 centerchan = (channel + 2);
8936 break;
8937 case 3:
8938 centerchan = (channel - 2);
8939 break;
8940 default:
8941 return -EINVAL;
8942 }
8943 }else if (width == 160){
8944 switch (channel) {
8945 case 1 ... 29:
8946 centerchan = 15;
8947 break;
8948 case 33 ... 61:
8949 centerchan = 47;
8950 break;
8951 case 65 ... 93:
8952 centerchan = 79;
8953 break;
8954 case 97 ... 125:
8955 centerchan = 111;
8956 break;
8957 case 129 ... 157:
8958 centerchan = 143;
8959 break;
8960 case 161 ... 189:
8961 centerchan = 175;
8962 break;
8963 case 193 ... 221:
8964 centerchan = 207;
8965 break;
8966 default:
8967 return -EINVAL;
8968 }
8969 }
8970 return centerchan;
8971}
8972static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8973{
8974 BOOL onlyG, onlyN, onlyA;
8975 CHAR tmp[64];
8976 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8977 if (ret == RETURN_OK) {
8978 sncopy(hw_mode, hw_mode_size, tmp);
8979 }
8980 return ret;
8981}
8982
8983INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8984{
8985 // Sample commands:
8986 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8987 // hostapd_cli -i wifi0 chan_switch 30 2437
8988 char cmd[MAX_CMD_SIZE] = {0};
8989 char buf[MAX_BUF_SIZE] = {0};
8990 int freq = 0, ret = 0;
8991 char center_freq1_str[32] = ""; // center_freq1=%d
8992 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8993 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8994 char hw_mode[16] = ""; // n|ac
8995 char bw_mode[16] = ""; // ht|ht vht
8996 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8997 char interface_name[16] = {0};
8998 int sec_chan_offset;
8999 int width;
9000 char config_file[64] = {0};
9001 BOOL stbcEnable = FALSE;
9002 char *ext_str = "None";
9003 wifi_band band = band_invalid;
9004 int center_chan = 0;
9005 int center_freq1 = 0;
9006
9007 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9008
9009 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9010 return RETURN_ERR;
9011
9012 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9013
9014 band = wifi_index_to_band(radioIndex);
9015
9016 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9017
9018 // Get radio mode HT20|HT40|HT80 etc.
9019 if (channel){
9020 if (band == band_6){
9021 freq = util_6G_chan_to_freq(channel);
9022 }else{
9023 freq = util_chan_to_freq(channel);
9024 }
9025 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9026
9027 // Provide bandwith if specified
9028 if (channel_width_MHz > 20) {
9029 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9030 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9031 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9032
9033 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9034 }else if (channel_width_MHz == 20){
9035 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9036 }
9037
9038
9039 if (channel_width_MHz > 20) {
9040 if (band == band_6){
9041 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9042 if(center_chan){
9043 center_freq1 = util_6G_chan_to_freq(center_chan);
9044 }
9045 }else{
9046 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9047 if(center_chan){
9048 center_freq1 = util_chan_to_freq(center_chan);
9049 }
9050 }
9051
9052 if (center_freq1)
9053 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
9054
9055 }
9056
9057 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9058 if (band == band_6){
9059 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9060 }else{
9061 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9062 }
9063 if (sec_chan_offset != -EINVAL)
9064 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9065
9066 // Only the first AP, other are hanging on the same radio
9067 int apIndex = radioIndex;
9068 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9069 interface_name, csa_beacon_count, freq,
9070 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9071 wifi_dbg_printf("execute: '%s'\n", cmd);
9072 ret = _syscmd(cmd, buf, sizeof(buf));
9073 wifi_reloadAp(radioIndex);
9074
9075 ret = wifi_setRadioChannel(radioIndex, channel);
9076 if (ret != RETURN_OK) {
9077 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9078 return RETURN_ERR;
9079 }
9080
9081 if (sec_chan_offset == 1) ext_str = "Above";
9082 else if (sec_chan_offset == -1) ext_str = "Below";
9083
9084 wifi_setRadioCenterChannel(radioIndex, center_chan);
9085
9086 } else {
9087 if (channel_width_MHz > 20)
9088 ext_str = "Above";
9089 }
9090
9091 wifi_setRadioExtChannel(radioIndex, ext_str);
9092
9093 char mhz_str[16];
9094 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9095 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9096
9097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9098
9099 return RETURN_OK;
9100}
9101
9102INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9103{
9104 int index = -1;
9105 wifi_neighbor_ap2_t *scan_array = NULL;
9106 char cmd[256]={0};
9107 char buf[128]={0};
9108 char file_name[32] = {0};
9109 char filter_SSID[32] = {0};
9110 char line[256] = {0};
9111 char interface_name[16] = {0};
9112 char *ret = NULL;
9113 int freq=0;
9114 FILE *f = NULL;
9115 size_t len=0;
9116 int channels_num = 0;
9117 int vht_channel_width = 0;
9118 int get_noise_ret = RETURN_ERR;
9119 bool filter_enable = false;
9120 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9121 int phyId = 0;
9122
9123 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9124
9125 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9126 f = fopen(file_name, "r");
9127 if (f != NULL) {
9128 fgets(filter_SSID, sizeof(file_name), f);
9129 if (strlen(filter_SSID) != 0)
9130 filter_enable = true;
9131 fclose(f);
9132 }
9133
9134 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9135 return RETURN_ERR;
9136
9137 phyId = radio_index_to_phy(radio_index);
9138
9139 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9140 _syscmd(cmd, buf, sizeof(buf));
9141 channels_num = strtol(buf, NULL, 10);
9142
9143 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9144 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9145 fprintf(stderr, "cmd: %s\n", cmd);
9146 if ((f = popen(cmd, "r")) == NULL) {
9147 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9148 return RETURN_ERR;
9149 }
9150
9151 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9152 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
9153
9154 ret = fgets(line, sizeof(line), f);
9155 while (ret != NULL) {
9156 if(strstr(line, "BSS") != NULL) { // new neighbor info
9157 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
9158 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9159 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9160
9161 if (!filter_BSS) {
9162 index++;
9163 wifi_neighbor_ap2_t *tmp;
9164 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9165 if (tmp == NULL) { // no more memory to use
9166 index--;
9167 wifi_dbg_printf("%s: realloc failed\n", __func__);
9168 break;
9169 }
9170 scan_array = tmp;
9171 }
9172 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9173
9174 filter_BSS = false;
9175 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9176 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9177 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9178 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9179 } else if (strstr(line, "freq") != NULL) {
9180 sscanf(line," freq: %d", &freq);
9181 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9182
9183 if (freq >= 2412 && freq <= 2484) {
9184 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9185 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9186 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9187 }
9188 else if (freq >= 5160 && freq <= 5805) {
9189 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9190 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9191 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9192 }
9193
9194 scan_array[index].ap_Noise = 0;
9195 if (get_noise_ret == RETURN_OK) {
9196 for (int i = 0; i < channels_num; i++) {
9197 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9198 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9199 break;
9200 }
9201 }
9202 }
9203 } else if (strstr(line, "beacon interval") != NULL) {
9204 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9205 } else if (strstr(line, "signal") != NULL) {
9206 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9207 } else if (strstr(line,"SSID") != NULL) {
9208 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9209 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9210 filter_BSS = true;
9211 }
9212 } else if (strstr(line, "Supported rates") != NULL) {
9213 char SRate[80] = {0}, *tmp = NULL;
9214 memset(buf, 0, sizeof(buf));
9215 strcpy(SRate, line);
9216 tmp = strtok(SRate, ":");
9217 tmp = strtok(NULL, ":");
9218 strcpy(buf, tmp);
9219 memset(SRate, 0, sizeof(SRate));
9220
9221 tmp = strtok(buf, " \n");
9222 while (tmp != NULL) {
9223 strcat(SRate, tmp);
9224 if (SRate[strlen(SRate) - 1] == '*') {
9225 SRate[strlen(SRate) - 1] = '\0';
9226 }
9227 strcat(SRate, ",");
9228
9229 tmp = strtok(NULL, " \n");
9230 }
9231 SRate[strlen(SRate) - 1] = '\0';
9232 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9233 } else if (strstr(line, "DTIM") != NULL) {
9234 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9235 } else if (strstr(line, "VHT capabilities") != NULL) {
9236 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9237 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9238 } else if (strstr(line, "HT capabilities") != NULL) {
9239 strcat(scan_array[index].ap_SupportedStandards, ",n");
9240 strcpy(scan_array[index].ap_OperatingStandards, "n");
9241 } else if (strstr(line, "VHT operation") != NULL) {
9242 ret = fgets(line, sizeof(line), f);
9243 sscanf(line," * channel width: %d", &vht_channel_width);
9244 if(vht_channel_width == 1) {
9245 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9246 } else {
9247 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9248 }
9249 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9250 continue;
9251 } else if (strstr(line, "HT operation") != NULL) {
9252 ret = fgets(line, sizeof(line), f);
9253 sscanf(line," * secondary channel offset: %s", &buf);
9254 if (!strcmp(buf, "above")) {
9255 //40Mhz +
9256 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9257 }
9258 else if (!strcmp(buf, "below")) {
9259 //40Mhz -
9260 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9261 } else {
9262 //20Mhz
9263 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9264 }
9265 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9266 continue;
9267 } else if (strstr(line, "HE capabilities") != NULL) {
9268 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9269 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9270 ret = fgets(line, sizeof(line), f);
9271 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9272 if (strstr(line, "HE40/2.4GHz") != NULL)
9273 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9274 else
9275 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9276 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9277 if (strstr(line, "HE80/5GHz") != NULL) {
9278 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9279 ret = fgets(line, sizeof(line), f);
9280 } else
9281 continue;
9282 if (strstr(line, "HE160/5GHz") != NULL)
9283 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9284 }
9285 continue;
9286 } else if (strstr(line, "WPA") != NULL) {
9287 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9288 } else if (strstr(line, "RSN") != NULL) {
9289 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9290 } else if (strstr(line, "Group cipher") != NULL) {
9291 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9292 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9293 strcpy(scan_array[index].ap_EncryptionMode, "AES");
9294 }
9295 }
9296 ret = fgets(line, sizeof(line), f);
9297 }
9298
9299 if (!filter_BSS) {
9300 *output_array_size = index + 1;
9301 } else {
9302 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9303 *output_array_size = index;
9304 }
9305 *neighbor_ap_array = scan_array;
9306 pclose(f);
9307 free(channels_noise_arr);
9308 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9309 return RETURN_OK;
9310}
9311
9312INT wifi_getApAssociatedDeviceStats(
9313 INT apIndex,
9314 mac_address_t *clientMacAddress,
9315 wifi_associated_dev_stats_t *associated_dev_stats,
9316 u64 *handle)
9317{
9318 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9319 char interface_name[50] = {0};
9320 char cmd[1024] = {0};
9321 char mac_str[18] = {0};
9322 char *key = NULL;
9323 char *val = NULL;
9324 FILE *f = NULL;
9325 char *line = NULL;
9326 size_t len = 0;
9327
9328 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9329 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9330 return RETURN_ERR;
9331 }
9332
9333 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9334 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9335 if((f = popen(cmd, "r")) == NULL) {
9336 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9337 return RETURN_ERR;
9338 }
9339
9340 while ((getline(&line, &len, f)) != -1) {
9341 key = strtok(line,":");
9342 val = strtok(NULL,":");
9343
9344 if(!strncmp(key,"rx bytes",8))
9345 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9346 if(!strncmp(key,"tx bytes",8))
9347 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9348 if(!strncmp(key,"rx packets",10))
9349 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9350 if(!strncmp(key,"tx packets",10))
9351 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9352 if(!strncmp(key,"tx retries",10))
9353 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9354 if(!strncmp(key,"tx failed",9))
9355 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9356 if(!strncmp(key,"rx drop misc",13))
9357 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9358 if(!strncmp(key,"rx bitrate",10)) {
9359 val = strtok(val, " ");
9360 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9361 }
9362 if(!strncmp(key,"tx bitrate",10)) {
9363 val = strtok(val, " ");
9364 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9365 }
9366 }
9367 free(line);
9368 pclose(f);
9369 return RETURN_OK;
9370}
9371
9372INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9373{
9374 char interface_name[16] = {0};
9375 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9376
9377 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9378 if (NULL == output_string)
9379 return RETURN_ERR;
9380
9381 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9382 return RETURN_ERR;
9383 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
9384 _syscmd(cmd, buf, sizeof(buf));
9385
9386 //size of SSID name restricted to value less than 32 bytes
9387 snprintf(output_string, 32, "%s", buf);
9388 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9389
9390 return RETURN_OK;
9391}
9392
9393INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9394{
9395 //char cmd[MAX_CMD_SIZE] = {0};
9396 char config_file[MAX_BUF_SIZE] = {0};
9397 char buf[32] = {0};
9398
9399 if (!output_filterMode)
9400 return RETURN_ERR;
9401
9402 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9403 //_syscmd(cmd, buf, sizeof(buf));
9404 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9405 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9406 if(strlen(buf) == 0) {
9407 *output_filterMode = 0;
9408 }
9409 else {
9410 int macaddr_acl_mode = strtol(buf, NULL, 10);
9411 if (macaddr_acl_mode == 1) {
9412 *output_filterMode = 1;
9413 } else if (macaddr_acl_mode == 0) {
9414 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9415 if (strlen(buf) == 0) {
9416 *output_filterMode = 0;
9417 } else {
9418 *output_filterMode = 2;
9419 }
9420 } else {
9421 return RETURN_ERR;
9422 }
9423 }
9424
9425 return RETURN_OK;
9426}
9427
9428INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9429{
9430 FILE *fp = NULL;
9431 char str[MAX_BUF_SIZE] = {0};
9432 int wificlientindex = 0 ;
9433 int count = 0;
9434 int signalstrength = 0;
9435 int arr[MACADDRESS_SIZE] = {0};
9436 unsigned char mac[MACADDRESS_SIZE] = {0};
9437 UINT wifi_count = 0;
9438 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9439 char pipeCmd[MAX_CMD_SIZE] = {0};
9440
9441 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9442 *output_array_size = 0;
9443 *associated_dev_array = NULL;
9444 char interface_name[50] = {0};
9445
9446 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9447 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9448 return RETURN_ERR;
9449 }
9450
9451 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9452 fp = popen(pipeCmd, "r");
9453 if (fp == NULL)
9454 {
9455 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9456 return RETURN_ERR;
9457 }
9458
9459 /* Read the output a line at a time - output it. */
9460 fgets(str, sizeof(str)-1, fp);
9461 wifi_count = (unsigned int) atoi ( str );
9462 *output_array_size = wifi_count;
9463 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9464 pclose(fp);
9465
9466 if(wifi_count == 0)
9467 {
9468 return RETURN_OK;
9469 }
9470 else
9471 {
9472 wifi_associated_dev2_t* temp = NULL;
9473 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9474 *associated_dev_array = temp;
9475 if(temp == NULL)
9476 {
9477 printf("Error Statement. Insufficient memory \n");
9478 return RETURN_ERR;
9479 }
9480
9481 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9482 system(pipeCmd);
9483
9484 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9485 if(fp == NULL)
9486 {
9487 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9488 return RETURN_ERR;
9489 }
9490 fclose(fp);
9491
9492 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9493 fp = popen(pipeCmd, "r");
9494 if(fp)
9495 {
9496 for(count =0 ; count < wifi_count; count++)
9497 {
9498 fgets(str, MAX_BUF_SIZE, fp);
9499 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9500 {
9501 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9502 {
9503 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9504
9505 }
9506 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9507 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]);
9508 }
9509 temp[count].cli_AuthenticationState = 1; //TODO
9510 temp[count].cli_Active = 1; //TODO
9511 }
9512 pclose(fp);
9513 }
9514
9515 //Updating RSSI per client
9516 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9517 fp = popen(pipeCmd, "r");
9518 if(fp)
9519 {
9520 pclose(fp);
9521 }
9522 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9523 if(fp)
9524 {
9525 for(count =0 ; count < wifi_count ;count++)
9526 {
9527 fgets(str, MAX_BUF_SIZE, fp);
9528 signalstrength = atoi(str);
9529 temp[count].cli_RSSI = signalstrength;
9530 }
9531 pclose(fp);
9532 }
9533
9534
9535 //LastDataDownlinkRate
9536 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9537 fp = popen(pipeCmd, "r");
9538 if (fp)
9539 {
9540 pclose(fp);
9541 }
9542 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9543 if (fp)
9544 {
9545 for (count = 0; count < wifi_count; count++)
9546 {
9547 fgets(str, MAX_BUF_SIZE, fp);
9548 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9549 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9550 }
9551 pclose(fp);
9552 }
9553
9554 //LastDataUplinkRate
9555 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9556 fp = popen(pipeCmd, "r");
9557 if (fp)
9558 {
9559 pclose(fp);
9560 }
9561 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9562 if (fp)
9563 {
9564 for (count = 0; count < wifi_count; count++)
9565 {
9566 fgets(str, MAX_BUF_SIZE, fp);
9567 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9568 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9569 }
9570 pclose(fp);
9571 }
9572 }
9573 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9574 return RETURN_OK;
9575
9576}
9577
9578INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9579{
9580#if 0
9581 /*char buf[1024] = {0};
9582 sprintf(cmd, "ifconfig %s ", interface_name);
9583 _syscmd(cmd, buf, sizeof(buf));*/
9584
9585 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9586 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9587 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9588 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9589
9590 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.
9591 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].
9592 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].
9593 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].
9594 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9595 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9596
9597 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9598 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9599 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9600 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.
9601 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.
9602 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.
9603 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.
9604 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.
9605 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.
9606 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.
9607 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9608#endif
9609
9610 FILE *fp = NULL;
9611 char interface_name[50] = {0};
9612 char pipeCmd[128] = {0};
9613 char str[256] = {0};
9614 wifi_ssidTrafficStats2_t *out = output_struct;
9615
9616 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9617 if (!output_struct)
9618 return RETURN_ERR;
9619
9620 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9621 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9622 return RETURN_ERR;
9623 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9624
9625 fp = popen(pipeCmd, "r");
9626 if (fp == NULL) {
9627 fprintf(stderr, "%s: popen failed\n", __func__);
9628 return RETURN_ERR;
9629 }
9630 fgets(str, sizeof(str), fp);
9631 pclose(fp);
9632
9633 if (strlen(str) == 0) // interface not exist
9634 return RETURN_OK;
9635
9636 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9637 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9638
9639 memset(str, 0, sizeof(str));
9640 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9641 fp = popen(pipeCmd, "r");
9642 if (fp == NULL) {
9643 fprintf(stderr, "%s: popen failed\n", __func__);
9644 return RETURN_ERR;
9645 }
9646 fgets(str, sizeof(str), fp);
9647
9648 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9649 &out->ssid_BroadcastPacketsSent);
9650 pclose(fp);
9651
9652 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9653 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9654
9655 // Not supported
9656 output_struct->ssid_RetransCount = 0;
9657 output_struct->ssid_FailedRetransCount = 0;
9658 output_struct->ssid_RetryCount = 0;
9659 output_struct->ssid_MultipleRetryCount = 0;
9660 output_struct->ssid_ACKFailureCount = 0;
9661 output_struct->ssid_AggregatedPacketCount = 0;
9662
9663 return RETURN_OK;
9664}
9665
9666//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).
9667INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9668{
9669 char output_val[16]={'\0'};
9670 char config_file[MAX_BUF_SIZE] = {0};
9671
9672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9673 if (!output)
9674 return RETURN_ERR;
9675 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9676 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9677
9678 if( strcmp(output_val,"1") == 0 )
9679 *output = TRUE;
9680 else
9681 *output = FALSE;
9682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9683
9684 return RETURN_OK;
9685}
9686
9687INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9688{
9689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9690 char str[MAX_BUF_SIZE]={'\0'};
9691 char string[MAX_BUF_SIZE]={'\0'};
9692 char cmd[MAX_CMD_SIZE]={'\0'};
9693 char *ch;
9694 char config_file[MAX_BUF_SIZE] = {0};
9695 struct params params;
9696
9697 if(enable == TRUE)
9698 strcpy(string,"1");
9699 else
9700 strcpy(string,"0");
9701
9702 params.name = "ap_isolate";
9703 params.value = string;
9704
9705 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9706 wifi_hostapdWrite(config_file,&params,1);
9707 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9708
9709 return RETURN_OK;
9710}
9711
9712INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9713{
9714 if (NULL == output_dBm)
9715 return RETURN_ERR;
9716
9717 *output_dBm = 0;
9718 return RETURN_OK;
9719}
9720
9721INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9722{
9723 return RETURN_OK;
9724}
9725INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9726{
9727 return RETURN_OK;
9728}
9729INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9730{
9731 return RETURN_OK;
9732}
9733INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9734{
9735 return RETURN_OK;
9736}
9737INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9738{
9739 return RETURN_OK;
9740}
9741INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9742{
9743 char config_file[MAX_BUF_SIZE] = {0};
9744 struct params list;
9745
9746 list.name = "bss_transition";
9747 list.value = activate?"1":"0";
9748 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9749 wifi_hostapdWrite(config_file, &list, 1);
9750
9751 return RETURN_OK;
9752}
9753wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9754
9755void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9756{
9757 return;
9758}
9759
9760INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9761{
9762 // TODO Implement me!
9763 return RETURN_OK;
9764}
9765
9766INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9767{
9768 char file_name[128] = {0};
9769 char buf[128] = {0};
9770 FILE *f = NULL;
9771 int max_num_radios = 0;
9772
9773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9774
9775 wifi_getMaxRadioNumber(&max_num_radios);
9776 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9777 for (int index = 0; index < max_num_radios; index++) {
9778 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9779 f = fopen(file_name, "w");
9780 if (f == NULL)
9781 return RETURN_ERR;
9782 // For mode == 0 is to disable filter, just don't write to the file.
9783 if (mode)
9784 fprintf(f, "%s", essid);
9785
9786 fclose(f);
9787 }
9788 } else { // special case, need to set AP's SSID as filter for each radio.
9789 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9790 f = fopen(file_name, "w");
9791 if (f == NULL)
9792 return RETURN_ERR;
9793
9794 // For mode == 0 is to disable filter, just don't write to the file.
9795 if (mode)
9796 fprintf(f, "%s", essid);
9797
9798 fclose(f);
9799 }
9800
9801 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9802 return RETURN_OK;
9803}
9804
9805INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9806{
9807 // TODO Implement me!
9808 //Apply wifi_pushRadioChannel() instantly
9809 return RETURN_ERR;
9810}
9811
9812INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9813{
9814 // TODO Implement me!
9815 return RETURN_OK;
9816}
9817
9818#ifdef HAL_NETLINK_IMPL
9819static int tidStats_callback(struct nl_msg *msg, void *arg) {
9820 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9821 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9822 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9823 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9824 int rem , tid_index = 0;
9825
9826 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9827 wifi_associated_dev_tid_entry_t *stats_entry;
9828
9829 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9830 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9831 };
9832 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9833 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9834 };
9835
9836 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9837 genlmsg_attrlen(gnlh, 0), NULL);
9838
9839
9840 if (!tb[NL80211_ATTR_STA_INFO]) {
9841 fprintf(stderr, "station stats missing!\n");
9842 return NL_SKIP;
9843 }
9844
9845 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9846 tb[NL80211_ATTR_STA_INFO],
9847 stats_policy)) {
9848 fprintf(stderr, "failed to parse nested attributes!\n");
9849 return NL_SKIP;
9850 }
9851
9852 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9853 {
9854 stats_entry = &out->tid_array[tid_index];
9855
9856 stats_entry->tid = tid_index;
9857 stats_entry->ac = _tid_ac_index_get[tid_index];
9858
9859 if(sinfo[NL80211_STA_INFO_TID_STATS])
9860 {
9861 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9862 printf("failed to parse nested stats attributes!");
9863 return NL_SKIP;
9864 }
9865 }
9866 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9867 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9868
9869 if(tid_index < (PS_MAX_TID - 1))
9870 tid_index++;
9871 }
9872 //ToDo: sum_time_ms, ewma_time_ms
9873 return NL_SKIP;
9874}
9875#endif
9876
9877INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9878{
9879#ifdef HAL_NETLINK_IMPL
9880 Netlink nl;
9881 char if_name[10];
9882 char interface_name[16] = {0};
9883
9884 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9885 return RETURN_ERR;
9886
9887 snprintf(if_name, sizeof(if_name), "%s", interface_name);
9888
9889 nl.id = initSock80211(&nl);
9890
9891 if (nl.id < 0) {
9892 fprintf(stderr, "Error initializing netlink \n");
9893 return -1;
9894 }
9895
9896 struct nl_msg* msg = nlmsg_alloc();
9897
9898 if (!msg) {
9899 fprintf(stderr, "Failed to allocate netlink message.\n");
9900 nlfree(&nl);
9901 return -2;
9902 }
9903
9904 genlmsg_put(msg,
9905 NL_AUTO_PORT,
9906 NL_AUTO_SEQ,
9907 nl.id,
9908 0,
9909 0,
9910 NL80211_CMD_GET_STATION,
9911 0);
9912
9913 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9914 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9915 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9916 nl_send_auto(nl.socket, msg);
9917 nl_recvmsgs(nl.socket, nl.cb);
9918 nlmsg_free(msg);
9919 nlfree(&nl);
9920 return RETURN_OK;
9921#else
9922//iw implementation
9923#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9924#define TOTAL_MAX_LINES 50
9925
9926 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9927 char if_name[32] = {0};
9928 FILE *fp=NULL;
9929 char pipeCmd[1024]= {'\0'};
9930 int lines,tid_index=0;
9931 char mac_addr[20] = {'\0'};
9932
9933 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9934 return RETURN_ERR;
9935
9936 wifi_associated_dev_tid_entry_t *stats_entry;
9937
9938 strcpy(mac_addr,clientMacAddress);
9939
9940 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9941 fp= popen(pipeCmd,"r");
9942 if(fp == NULL)
9943 {
9944 perror("popen for station dump failed\n");
9945 return RETURN_ERR;
9946 }
9947 pclose(fp);
9948
9949 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9950 fp=popen(pipeCmd,"r");
9951 if(fp == NULL)
9952 {
9953 perror("popen for grep station failed\n");
9954 return RETURN_ERR;
9955 }
9956 else if(fgets(buf,sizeof(buf),fp) != NULL)
9957 lines=atoi(buf);
9958 else
9959 {
9960 pclose(fp);
9961 fprintf(stderr,"No devices are connected \n");
9962 return RETURN_ERR;
9963 }
9964 pclose(fp);
9965
9966 if(lines == 1)
9967 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9968
9969 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9970 {
9971 stats_entry = &tid_stats->tid_array[tid_index];
9972 stats_entry->tid = tid_index;
9973
9974 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);
9975
9976 fp=popen(pipeCmd,"r");
9977 if(fp ==NULL)
9978 {
9979 perror("Failed to read from tid file \n");
9980 return RETURN_ERR;
9981 }
9982 else if(fgets(buf,sizeof(buf),fp) != NULL)
9983 stats_entry->num_msdus = atol(buf);
9984
9985 pclose(fp);
9986 stats_entry->ac = _tid_ac_index_get[tid_index];
9987// TODO:
9988// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9989// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9990 }
9991 return RETURN_OK;
9992#endif
9993}
9994
9995
9996INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9997{
9998 char interface_name[16] = {0};
9999 char cmd[128]={0};
10000 char buf[128]={0};
10001 int freq = 0;
10002
10003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10004
10005 // full mode is used to scan all channels.
10006 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10007 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10008 ieee80211_channel_to_frequency(chan_list[0], &freq);
10009
10010 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10011 return RETURN_ERR;
10012
10013 if (freq)
10014 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10015 else
10016 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10017
10018 _syscmd(cmd, buf, sizeof(buf));
10019 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10020
10021 return RETURN_OK;
10022}
10023
10024
10025INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10026{
10027 // TODO Implement me!
10028 return RETURN_ERR;
10029}
10030
10031INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10032{
10033 // TODO Implement me!
10034 return RETURN_ERR;
10035}
10036
10037INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10038{
10039 // TODO Implement me!
10040 return RETURN_ERR;
10041}
10042
10043INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10044{
10045 // TODO Implement me!
10046 return RETURN_ERR;
10047}
10048
10049INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10050{
10051 // TODO Implement me!
10052 return RETURN_ERR;
10053}
10054
10055INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10056{
10057 // TODO Implement me!
10058 return RETURN_ERR;
10059}
10060
10061INT wifi_steering_eventUnregister(void)
10062{
10063 // TODO Implement me!
10064 return RETURN_ERR;
10065}
10066
10067INT wifi_delApAclDevices(INT apIndex)
10068{
10069#if 0
10070 char cmd[MAX_BUF_SIZE] = {0};
10071 char buf[MAX_BUF_SIZE] = {0};
10072
10073 /* Not reset proof solution */
10074 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
10075 if(_syscmd(cmd,buf,sizeof(buf)))
10076 return RETURN_ERR;
10077#endif
10078 char cmd[MAX_CMD_SIZE]={0};
10079 char buf[MAX_BUF_SIZE]={0};
10080
10081 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10082 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
10083 if(_syscmd(cmd, buf, sizeof(buf)))
10084 return RETURN_ERR;
10085 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10086
10087 return RETURN_OK;
10088}
10089
10090#ifdef HAL_NETLINK_IMPL
10091static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10092 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10093 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10094 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10095 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10096 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10097 char mac_addr[20],dev[20];
10098
10099 nla_parse(tb,
10100 NL80211_ATTR_MAX,
10101 genlmsg_attrdata(gnlh, 0),
10102 genlmsg_attrlen(gnlh, 0),
10103 NULL);
10104
10105 if(!tb[NL80211_ATTR_STA_INFO]) {
10106 fprintf(stderr, "sta stats missing!\n");
10107 return NL_SKIP;
10108 }
10109
10110 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10111 fprintf(stderr, "failed to parse nested attributes!\n");
10112 return NL_SKIP;
10113 }
10114 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10115
10116 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10117
10118 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10119 fprintf(stderr, "failed to parse nested rate attributes!");
10120 return NL_SKIP;
10121 }
10122
10123 if(sinfo[NL80211_STA_INFO_TID_STATS])
10124 {
10125 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10126 printf("failed to parse nested stats attributes!");
10127 return NL_SKIP;
10128 }
10129 }
10130
10131 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10132 {
10133 printf("Type is VHT\n");
10134 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10135 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10136
10137 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10138 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10139 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10140 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10141 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10142 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10143 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10144 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10145 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10146 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10147 }
10148 else
10149 {
10150 printf(" OFDM or CCK \n");
10151 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10152 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10153 }
10154
10155 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10156 if(rinfo[NL80211_RATE_INFO_MCS])
10157 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10158 }
10159 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10160 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10161 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10162 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10163
10164 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10165 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10166
10167 if (sinfo[NL80211_STA_INFO_SIGNAL])
10168 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10169 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10170 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10171 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10172 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10173 //rssi_array need to be filled
10174 return NL_SKIP;
10175}
10176#endif
10177
10178INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10179{
10180#ifdef HAL_NETLINK_IMPL
10181 Netlink nl;
10182 char if_name[32];
10183 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10184 return RETURN_ERR;
10185
10186 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10187
10188 if (*output_array_size <= 0)
10189 return RETURN_OK;
10190
10191 nl.id = initSock80211(&nl);
10192
10193 if (nl.id < 0) {
10194 fprintf(stderr, "Error initializing netlink \n");
10195 return 0;
10196 }
10197
10198 struct nl_msg* msg = nlmsg_alloc();
10199
10200 if (!msg) {
10201 fprintf(stderr, "Failed to allocate netlink message.\n");
10202 nlfree(&nl);
10203 return 0;
10204 }
10205
10206 genlmsg_put(msg,
10207 NL_AUTO_PORT,
10208 NL_AUTO_SEQ,
10209 nl.id,
10210 0,
10211 0,
10212 NL80211_CMD_GET_STATION,
10213 0);
10214
10215 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10216 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10217 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10218 nl_send_auto(nl.socket, msg);
10219 nl_recvmsgs(nl.socket, nl.cb);
10220 nlmsg_free(msg);
10221 nlfree(&nl);
10222 return RETURN_OK;
10223#else
10224 //TODO Implement me
10225 return RETURN_OK;
10226#endif
10227}
10228
10229#ifdef HAL_NETLINK_IMPL
10230static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10231 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10232 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10233 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10234 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10235 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10236 char mac_addr[20],dev[20];
10237
10238 nla_parse(tb,
10239 NL80211_ATTR_MAX,
10240 genlmsg_attrdata(gnlh, 0),
10241 genlmsg_attrlen(gnlh, 0),
10242 NULL);
10243
10244 if(!tb[NL80211_ATTR_STA_INFO]) {
10245 fprintf(stderr, "sta stats missing!\n");
10246 return NL_SKIP;
10247 }
10248
10249 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10250 fprintf(stderr, "failed to parse nested attributes!\n");
10251 return NL_SKIP;
10252 }
10253
10254 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10255
10256 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10257
10258 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10259 fprintf(stderr, "failed to parse nested rate attributes!");
10260 return NL_SKIP;
10261 }
10262
10263 if(sinfo[NL80211_STA_INFO_TID_STATS])
10264 {
10265 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10266 printf("failed to parse nested stats attributes!");
10267 return NL_SKIP;
10268 }
10269 }
10270 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10271 {
10272 printf("Type is VHT\n");
10273 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10274 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10275
10276 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10277 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10278 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10279 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10280 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10281 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10282 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10283 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10284 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10285 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10286 }
10287 else
10288 {
10289 printf(" OFDM or CCK \n");
10290 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10291 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10292 }
10293
10294 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10295 if(rinfo[NL80211_RATE_INFO_MCS])
10296 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10297 }
10298
10299 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10300 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10301 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10302 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10303
10304 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10305 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10306 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10307
10308 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10309 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10310
10311 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10312 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10313
10314 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10315 ((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]);
10316
10317 return NL_SKIP;
10318}
10319#endif
10320
10321INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10322{
10323#ifdef HAL_NETLINK_IMPL
10324 Netlink nl;
10325 char if_name[10];
10326 char interface_name[16] = {0};
10327 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10328 return RETURN_ERR;
10329
10330 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10331
10332 if (*output_array_size <= 0)
10333 return RETURN_OK;
10334
10335 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10336
10337 nl.id = initSock80211(&nl);
10338
10339 if(nl.id < 0) {
10340 fprintf(stderr, "Error initializing netlink \n");
10341 return 0;
10342 }
10343
10344 struct nl_msg* msg = nlmsg_alloc();
10345
10346 if(!msg) {
10347 fprintf(stderr, "Failed to allocate netlink message.\n");
10348 nlfree(&nl);
10349 return 0;
10350 }
10351
10352 genlmsg_put(msg,
10353 NL_AUTO_PORT,
10354 NL_AUTO_SEQ,
10355 nl.id,
10356 0,
10357 0,
10358 NL80211_CMD_GET_STATION,
10359 0);
10360
10361 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10362 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10363 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10364 nl_send_auto(nl.socket, msg);
10365 nl_recvmsgs(nl.socket, nl.cb);
10366 nlmsg_free(msg);
10367 nlfree(&nl);
10368 return RETURN_OK;
10369#else
10370 //TODO Implement me
10371 return RETURN_OK;
10372#endif
10373}
10374
10375INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10376{
10377 // TODO Implement me!
10378 char buf[MAX_BUF_SIZE] = {0};
10379 char config_file[MAX_BUF_SIZE] = {0};
10380
10381 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10382 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10383 *activate = (strncmp("1",buf,1) == 0);
10384
10385 return RETURN_OK;
10386}
10387
10388INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10389{
10390 char config_file[MAX_BUF_SIZE] = {0};
10391 struct params list;
10392
10393 list.name = "rrm_neighbor_report";
10394 list.value = activate?"1":"0";
10395 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10396 wifi_hostapdWrite(config_file, &list, 1);
10397
10398 return RETURN_OK;
10399}
10400
10401INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10402{
10403 char buf[32] = {0};
10404 char config_file[MAX_BUF_SIZE] = {0};
10405
10406 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10407 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10408 *activate = (strncmp("1",buf,1) == 0);
10409
10410 return RETURN_OK;
10411}
10412#undef HAL_NETLINK_IMPL
10413#ifdef HAL_NETLINK_IMPL
10414static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10415 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10416 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10417 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10418 char dev[20];
10419 int freq =0 ;
10420 static int i=0;
10421
10422 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10423
10424 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10425 };
10426
10427 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10428
10429 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10430
10431 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10432 fprintf(stderr, "survey data missing!\n");
10433 return NL_SKIP;
10434 }
10435
10436 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10437 {
10438 fprintf(stderr, "failed to parse nested attributes!\n");
10439 return NL_SKIP;
10440 }
10441
10442
10443 if(out[0].array_size == 1 )
10444 {
10445 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10446 {
10447 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10448 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10449 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10450
10451 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10452 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10453 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10454 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10455 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10456 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10457 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10458 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10459 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10460 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10461 if (sinfo[NL80211_SURVEY_INFO_TIME])
10462 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10463 return NL_STOP;
10464 }
10465 }
10466 else
10467 {
10468 if ( i <= out[0].array_size )
10469 {
10470 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10471 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10472 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10473
10474 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10475 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10476 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10477 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10478 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10479 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10480 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10481 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10482 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10483 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10484 if (sinfo[NL80211_SURVEY_INFO_TIME])
10485 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10486 }
10487 }
10488
10489 i++;
10490 return NL_SKIP;
10491}
10492#endif
10493
10494static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10495{
10496 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10497 FILE *fp;
10498
10499 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10500 {
10501 printf("Creating Frequency-Channel Map\n");
10502 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10503 }
10504 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10505 if((fp = popen(command, "r")))
10506 {
10507 fgets(output, sizeof(output), fp);
10508 *freqMHz = atoi(output);
10509 pclose(fp);
10510 }
10511
10512 return 0;
10513}
10514
10515static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10516{
10517 int freqMHz = -1;
10518 char cmd[MAX_CMD_SIZE] = {'\0'};
10519 char interface_name[16] = {0};
10520
10521 ieee80211_channel_to_frequency(channel, &freqMHz);
10522 if (freqMHz == -1) {
10523 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10524 return -1;
10525 }
10526
10527 wifi_GetInterfaceName(radioIndex, interface_name);
10528 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10529 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10530 radioIndex, freqMHz);
10531 return -1;
10532 }
10533
10534 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10535 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10536 return -1;
10537 }
10538
10539 return 0;
10540}
10541
10542static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10543{
10544 const char *ptr = buf;
10545 char *key = NULL;
10546 char *val = NULL;
10547 char line[256] = { '\0' };
10548
10549 while (ptr = get_line_from_str_buf(ptr, line)) {
10550 if (strstr(line, "Frequency")) continue;
10551
10552 key = strtok(line, ":");
10553 val = strtok(NULL, " ");
10554 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10555
10556 if (!strcmp(key, "noise")) {
10557 sscanf(val, "%d", &stats->ch_noise);
10558 if (stats->ch_noise == 0) {
10559 // Workaround for missing noise information.
10560 // Assume -95 for 2.4G and -103 for 5G
10561 if (radioIndex == 0) stats->ch_noise = -95;
10562 if (radioIndex == 1) stats->ch_noise = -103;
10563 }
10564 }
10565 else if (!strcmp(key, "channel active time")) {
10566 sscanf(val, "%llu", &stats->ch_utilization_total);
10567 }
10568 else if (!strcmp(key, "channel busy time")) {
10569 sscanf(val, "%llu", &stats->ch_utilization_busy);
10570 }
10571 else if (!strcmp(key, "channel receive time")) {
10572 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10573 }
10574 else if (!strcmp(key, "channel transmit time")) {
10575 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10576 }
10577 };
10578
10579 return 0;
10580}
10581
10582INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10583{
10584 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10585#ifdef HAL_NETLINK_IMPL
10586 Netlink nl;
10587 wifi_channelStats_t_loc local[array_size];
10588 char if_name[32];
10589
10590 local[0].array_size = array_size;
10591
10592 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10593 return RETURN_ERR;
10594
10595 nl.id = initSock80211(&nl);
10596
10597 if (nl.id < 0) {
10598 fprintf(stderr, "Error initializing netlink \n");
10599 return -1;
10600 }
10601
10602 struct nl_msg* msg = nlmsg_alloc();
10603
10604 if (!msg) {
10605 fprintf(stderr, "Failed to allocate netlink message.\n");
10606 nlfree(&nl);
10607 return -2;
10608 }
10609
10610 genlmsg_put(msg,
10611 NL_AUTO_PORT,
10612 NL_AUTO_SEQ,
10613 nl.id,
10614 0,
10615 NLM_F_DUMP,
10616 NL80211_CMD_GET_SURVEY,
10617 0);
10618
10619 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10620 nl_send_auto(nl.socket, msg);
10621 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10622 nl_recvmsgs(nl.socket, nl.cb);
10623 nlmsg_free(msg);
10624 nlfree(&nl);
10625 //Copying the Values
10626 for(int i=0;i<array_size;i++)
10627 {
10628 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10629 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10630 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10631 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10632 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10633 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10634 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10635 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10636 }
10637#else
10638 ULONG channel = 0;
10639 int i;
10640 int number_of_channels = array_size;
10641 char buf[512];
10642 INT ret;
10643 wifi_channelStats_t tmp_stats;
10644
10645 if (number_of_channels == 0) {
10646 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10647 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10648 return RETURN_ERR;
10649 }
10650 number_of_channels = 1;
10651 input_output_channelStats_array[0].ch_number = channel;
10652 }
10653
10654 for (i = 0; i < number_of_channels; i++) {
10655
10656 input_output_channelStats_array[i].ch_noise = 0;
10657 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10658 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10659 input_output_channelStats_array[i].ch_utilization_busy = 0;
10660 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10661 input_output_channelStats_array[i].ch_utilization_total = 0;
10662
10663 memset(buf, 0, sizeof(buf));
10664 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10665 return RETURN_ERR;
10666 }
10667 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10668 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10669 return RETURN_ERR;
10670 }
10671
10672 // XXX: fake missing 'self' counter which is not available in iw survey output
10673 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10674 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10675
10676 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10677 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10678 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10679 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10680 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10681
10682 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",
10683 __func__,
10684 input_output_channelStats_array[i].ch_number,
10685 input_output_channelStats_array[i].ch_noise,
10686 input_output_channelStats_array[i].ch_utilization_total,
10687 input_output_channelStats_array[i].ch_utilization_busy,
10688 input_output_channelStats_array[i].ch_utilization_busy_rx,
10689 input_output_channelStats_array[i].ch_utilization_busy_tx,
10690 input_output_channelStats_array[i].ch_utilization_busy_self,
10691 input_output_channelStats_array[i].ch_utilization_busy_ext);
10692 }
10693#endif
10694 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10695 return RETURN_OK;
10696}
10697#define HAL_NETLINK_IMPL
10698
10699/* Hostapd events */
10700
10701#ifndef container_of
10702#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10703#define container_of(ptr, type, member) \
10704 ((type *)((char *)ptr - offset_of(type, member)))
10705#endif /* container_of */
10706
10707struct ctrl {
10708 char sockpath[128];
10709 char sockdir[128];
10710 char bss[IFNAMSIZ];
10711 char reply[4096];
10712 int ssid_index;
10713 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10714 void (*overrun)(struct ctrl *ctrl);
10715 struct wpa_ctrl *wpa;
10716 unsigned int ovfl;
10717 size_t reply_len;
10718 int initialized;
10719 ev_timer retry;
10720 ev_timer watchdog;
10721 ev_stat stat;
10722 ev_io io;
10723};
10724static wifi_newApAssociatedDevice_callback clients_connect_cb;
10725static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10726static struct ctrl wpa_ctrl[MAX_APS];
10727static int initialized;
10728
10729static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10730{
10731 char cbuf[256] = {};
10732 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10733 struct cmsghdr *cmsg;
10734 unsigned int ovfl = ctrl->ovfl;
10735 unsigned int drop;
10736
10737 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10738 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10739 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10740 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10741
10742 drop = ovfl - ctrl->ovfl;
10743 ctrl->ovfl = ovfl;
10744
10745 return drop;
10746}
10747
10748static void ctrl_close(struct ctrl *ctrl)
10749{
10750 if (ctrl->io.cb)
10751 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10752 if (ctrl->retry.cb)
10753 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10754 if (!ctrl->wpa)
10755 return;
10756
10757 wpa_ctrl_detach(ctrl->wpa);
10758 wpa_ctrl_close(ctrl->wpa);
10759 ctrl->wpa = NULL;
10760 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10761}
10762
10763static void ctrl_process(struct ctrl *ctrl)
10764{
10765 const char *str;
10766 int drops;
10767 int level;
10768 int err;
10769
10770 /* Example events:
10771 *
10772 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10773 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10774 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10775 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10776 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10777 */
10778 if (!(str = index(ctrl->reply, '>')))
10779 return;
10780 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10781 return;
10782
10783 str++;
10784
10785 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10786 if (!(str = index(ctrl->reply, ' ')))
10787 return;
10788 wifi_associated_dev_t sta;
10789 memset(&sta, 0, sizeof(sta));
10790
10791 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10792 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10793 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10794
10795 sta.cli_Active=true;
10796
10797 (clients_connect_cb)(ctrl->ssid_index, &sta);
10798 goto handled;
10799 }
10800
10801 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10802 if (!(str = index(ctrl->reply, ' ')))
10803 return;
10804
10805 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10806 goto handled;
10807 }
10808
10809 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10810 printf("CTRL_WPA: handle TERMINATING event\n");
10811 goto retry;
10812 }
10813
10814 if (strncmp("AP-DISABLED", str, 11) == 0) {
10815 printf("CTRL_WPA: handle AP-DISABLED\n");
10816 goto retry;
10817 }
10818
10819 printf("Event not supported!!\n");
10820
10821handled:
10822
10823 if ((drops = ctrl_get_drops(ctrl))) {
10824 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10825 if (ctrl->overrun)
10826 ctrl->overrun(ctrl);
10827 }
10828
10829 return;
10830
10831retry:
10832 printf("WPA_CTRL: closing\n");
10833 ctrl_close(ctrl);
10834 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10835 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10836}
10837
10838static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10839{
10840 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10841 int err;
10842
10843 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10844 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10845 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10846 ctrl->reply[ctrl->reply_len] = 0;
10847 if (err < 0) {
10848 if (errno == EAGAIN || errno == EWOULDBLOCK)
10849 return;
10850 ctrl_close(ctrl);
10851 ev_timer_again(EV_A_ &ctrl->retry);
10852 return;
10853 }
10854
10855 ctrl_process(ctrl);
10856}
10857
10858static int ctrl_open(struct ctrl *ctrl)
10859{
10860 int fd;
10861
10862 if (ctrl->wpa)
10863 return 0;
10864
10865 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10866 if (!ctrl->wpa)
10867 goto err;
10868
10869 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10870 goto err_close;
10871
10872 fd = wpa_ctrl_get_fd(ctrl->wpa);
10873 if (fd < 0)
10874 goto err_detach;
10875
10876 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10877 goto err_detach;
10878
10879 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10880 ev_io_start(EV_DEFAULT_ &ctrl->io);
10881
10882 return 0;
10883
10884err_detach:
10885 wpa_ctrl_detach(ctrl->wpa);
10886err_close:
10887 wpa_ctrl_close(ctrl->wpa);
10888err:
10889 ctrl->wpa = NULL;
10890 return -1;
10891}
10892
10893static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10894{
10895 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10896
10897 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10898 ctrl_open(ctrl);
10899}
10900
10901static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10902{
10903 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10904
10905 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10906 if (ctrl_open(ctrl) == 0) {
10907 printf("WPA_CTRL: retry successful\n");
10908 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10909 }
10910}
10911
10912int ctrl_enable(struct ctrl *ctrl)
10913{
10914 if (ctrl->wpa)
10915 return 0;
10916
10917 if (!ctrl->stat.cb) {
10918 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10919 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10920 }
10921
10922 if (!ctrl->retry.cb) {
10923 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10924 }
10925
10926 return ctrl_open(ctrl);
10927}
10928
10929static void
10930ctrl_msg_cb(char *buf, size_t len)
10931{
10932 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10933
10934 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10935 ctrl_process(ctrl);
10936}
10937
10938static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10939{
10940 int err;
10941
10942 if (!ctrl->wpa)
10943 return -1;
10944 if (*reply_len < 2)
10945 return -1;
10946
10947 (*reply_len)--;
10948 ctrl->reply_len = sizeof(ctrl->reply);
10949 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10950 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10951 if (err < 0)
10952 return err;
10953
10954 if (ctrl->reply_len > *reply_len)
10955 ctrl->reply_len = *reply_len;
10956
10957 *reply_len = ctrl->reply_len;
10958 memcpy(reply, ctrl->reply, *reply_len);
10959 reply[*reply_len - 1] = 0;
10960 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10961 return 0;
10962}
10963
10964static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10965{
10966 const char *pong = "PONG";
10967 const char *ping = "PING";
10968 char reply[1024];
10969 size_t len = sizeof(reply);
10970 int err;
10971 ULONG s, snum;
10972 INT ret;
10973 BOOL status;
10974
10975 printf("WPA_CTRL: watchdog cb\n");
10976
10977 ret = wifi_getSSIDNumberOfEntries(&snum);
10978 if (ret != RETURN_OK) {
10979 printf("%s: failed to get SSID count", __func__);
10980 return;
10981 }
10982
10983 if (snum > MAX_APS) {
10984 printf("more ssid than supported! %lu\n", snum);
10985 return;
10986 }
10987
10988 for (s = 0; s < snum; s++) {
10989 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10990 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
10991 continue;
10992 }
10993 if (status == false) continue;
10994
10995 memset(reply, 0, sizeof(reply));
10996 len = sizeof(reply);
10997 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10998 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10999 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11000 continue;
11001
11002 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11003 ctrl_close(&wpa_ctrl[s]);
11004 printf("WPA_CTRL: ev_timer_again %lu\n", s);
11005 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11006 }
11007}
11008
11009static int init_wpa()
11010{
11011 int ret = 0, i = 0;
11012 ULONG s, snum;
11013
11014 ret = wifi_getSSIDNumberOfEntries(&snum);
11015 if (ret != RETURN_OK) {
11016 printf("%s: failed to get SSID count", __func__);
11017 return RETURN_ERR;
11018 }
11019
11020 if (snum > MAX_APS) {
11021 printf("more ssid than supported! %lu\n", snum);
11022 return RETURN_ERR;
11023 }
11024
11025 for (s = 0; s < snum; s++) {
11026 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11027 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11028 wpa_ctrl[s].ssid_index = s;
11029 ctrl_enable(&wpa_ctrl[s]);
11030 }
11031
11032 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11033 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11034
11035 initialized = 1;
11036 printf("WPA_CTRL: initialized\n");
11037
11038 return RETURN_OK;
11039}
11040
11041void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11042{
11043 clients_connect_cb = callback_proc;
11044 if (!initialized)
11045 init_wpa();
11046}
11047
11048void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11049{
11050 clients_disconnect_cb = callback_proc;
11051 if (!initialized)
11052 init_wpa();
11053}
11054
11055INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11056{
11057 // TODO Implement me!
11058 return RETURN_ERR;
11059}
11060
11061INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11062{
11063 // TODO Implement me!
11064 return RETURN_ERR;
11065}
11066
11067INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11068{
11069 int i;
11070 char cmd[256];
11071 char channel_numbers_buf[256];
11072 char dfs_state_buf[256];
11073 char line[256];
11074 const char *ptr;
11075
11076 memset(cmd, 0, sizeof(cmd));
11077 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
11078 memset(line, 0, sizeof(line));
11079 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11080 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
11081
11082 if (radioIndex == 0) { // 2.4G - all allowed
11083 if (outputMapSize < 11) {
11084 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
11085 return RETURN_ERR;
11086 }
11087
11088 for (i = 0; i < 11; i++) {
11089 outputMap[i].ch_number = i + 1;
11090 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11091 }
11092
11093 return RETURN_OK;
11094 }
11095
11096 if (radioIndex == 1) { // 5G
11097// Example output of iw list:
11098//
11099// Frequencies:
11100// * 5180 MHz [36] (17.0 dBm)
11101// * 5200 MHz [40] (17.0 dBm)
11102// * 5220 MHz [44] (17.0 dBm)
11103// * 5240 MHz [48] (17.0 dBm)
11104// * 5260 MHz [52] (23.0 dBm) (radar detection)
11105// DFS state: usable (for 78930 sec)
11106// DFS CAC time: 60000 ms
11107// * 5280 MHz [56] (23.0 dBm) (radar detection)
11108// DFS state: usable (for 78930 sec)
11109// DFS CAC time: 60000 ms
11110// * 5300 MHz [60] (23.0 dBm) (radar detection)
11111// DFS state: usable (for 78930 sec)
11112// DFS CAC time: 60000 ms
11113// * 5320 MHz [64] (23.0 dBm) (radar detection)
11114// DFS state: usable (for 78930 sec)
11115// DFS CAC time: 60000 ms
11116// * 5500 MHz [100] (disabled)
11117// * 5520 MHz [104] (disabled)
11118// * 5540 MHz [108] (disabled)
11119// * 5560 MHz [112] (disabled)
11120//
11121// Below command should fetch channel numbers of each enabled channel in 5GHz band:
11122 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
11123 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
11124 return RETURN_ERR;
11125 }
11126
11127 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11128 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11129 return RETURN_ERR;
11130 }
11131
11132 ptr = channel_numbers_buf;
11133 i = 0;
11134 while (ptr = get_line_from_str_buf(ptr, line)) {
11135 if (i >= outputMapSize) {
11136 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11137 return RETURN_ERR;
11138 }
11139 sscanf(line, "%d", &outputMap[i].ch_number);
11140
11141 memset(cmd, 0, sizeof(cmd));
11142 // Below command should fetch string for DFS state (usable, available or unavailable)
11143 // Example line: "DFS state: usable (for 78930 sec)"
11144 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) {
11145 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
11146 return RETURN_ERR;
11147 }
11148
11149 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11150 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
11151 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11152 return RETURN_ERR;
11153 }
11154
11155 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
11156
11157 if (!strcmp(dfs_state_buf, "usable")) {
11158 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11159 } else if (!strcmp(dfs_state_buf, "available")) {
11160 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11161 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11162 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11163 } else {
11164 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11165 }
11166 i++;
11167 }
11168
11169 return RETURN_OK;
11170 }
11171
11172 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11173 return RETURN_ERR;
11174}
11175
11176INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11177{
11178 // TODO Implement me!
11179 return RETURN_ERR;
11180}
11181
11182INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11183{
11184 return RETURN_OK;
11185}
11186
11187INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11188{
11189 // TODO Implement me!
11190 return RETURN_ERR;
11191}
11192
11193INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11194{
11195 // TODO API refrence Implementaion is present on RPI hal
11196 return RETURN_ERR;
11197}
11198
11199INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11200{
11201 char interface_name[16] = {0};
11202 char cmd[128]={'\0'};
11203 char buf[128]={'\0'};
11204 char *support;
11205 int maximum_tx = 0, current_tx = 0;
11206
11207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11208 if(txpwr_pcntg == NULL)
11209 return RETURN_ERR;
11210
11211 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11212 return RETURN_ERR;
11213
11214 // Get the maximum tx power of the device
11215 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11216 _syscmd(cmd, buf, sizeof(buf));
11217 maximum_tx = strtol(buf, NULL, 10);
11218
11219 // Get the current tx power
11220 memset(cmd, 0, sizeof(cmd));
11221 memset(buf, 0, sizeof(buf));
11222 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11223 _syscmd(cmd, buf, sizeof(buf));
11224 current_tx = strtol(buf, NULL, 10);
11225
11226 // Get the power supported list and find the current power percentage in supported list
11227 memset(buf, 0, sizeof(buf));
11228 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11229 support = strtok(buf, ",");
11230 while(true)
11231 {
11232 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11233 *txpwr_pcntg = 100;
11234 wifi_dbg_printf("current power is not in supported list\n");
11235 return RETURN_OK;
11236 }
11237 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11238 if (tmp == current_tx) {
11239 *txpwr_pcntg = strtol(support, NULL, 10);
11240 break;
11241 }
11242 support = strtok(NULL, ",");
11243 }
11244 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11245 return RETURN_OK;
11246}
11247
11248INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11249{
11250 // TODO precac feature.
11251 struct params params = {0};
11252 char config_file[128] = {0};
11253
11254 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11255
11256 params.name = "enable_background_radar";
11257 params.value = enable?"1":"0";
11258 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11259 wifi_hostapdWrite(config_file, &params, 1);
11260 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11261
11262 /* TODO precac feature */
11263
11264 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11265 return RETURN_OK;
11266}
11267
11268INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11269{
11270 char config_file[128] = {0};
11271 char buf[64] = {0};
11272
11273 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11274 if (NULL == enable || NULL == precac)
11275 return RETURN_ERR;
11276
11277 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11278 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11279 if (strncmp(enable, "1", 1) == 0)
11280 *enable = true;
11281 else
11282 *enable = false;
11283
11284 /* TODO precac feature */
11285
11286 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11287 return RETURN_OK;
11288}
11289
11290INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11291{
11292 *supported = TRUE;
11293 return RETURN_OK;
11294}
11295
11296INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11297{
11298 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11299 struct params params = {0};
11300 char config_file[64] = {0};
11301 char buf[64] = {0};
11302 unsigned int set_mu_type = 0;
11303 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11304
11305 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11306 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11307
11308 if (strlen(buf) > 0)
11309 set_mu_type = strtol(buf, NULL, 10);
11310
11311 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11312 set_mu_type &= ~0x05; // unset bit 0, 2
11313 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11314 set_mu_type |= 0x01;
11315 set_mu_type &= ~0x04;
11316 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11317 set_mu_type &= ~0x01;
11318 set_mu_type |= 0x04;
11319 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11320 set_mu_type |= 0x05; // set bit 0, 2
11321 }
11322
11323 params.name = "hemu_onoff";
11324 sprintf(buf, "%u", set_mu_type);
11325 params.value = buf;
11326 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11327 wifi_hostapdWrite(config_file, &params, 1);
11328 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11329
11330 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11331 return RETURN_OK;
11332}
11333
11334INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11335{
11336 struct params params={0};
11337 char config_file[64] = {0};
11338 char buf[64] = {0};
11339 unsigned int get_mu_type = 0;
11340
11341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11342
11343 if (mu_type == NULL)
11344 return RETURN_ERR;
11345
11346 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11347 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11348 get_mu_type = strtol(buf, NULL, 10);
11349
11350 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11351 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11352 else if (get_mu_type & 0x04)
11353 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11354 else if (get_mu_type & 0x01)
11355 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11356 else
11357 *mu_type = WIFI_DL_MU_TYPE_NONE;
11358
11359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11360 return RETURN_OK;
11361}
11362
11363INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11364{
11365 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11366 struct params params={0};
11367 char config_file[64] = {0};
11368 char buf[64] = {0};
11369 unsigned int set_mu_type = 0;
11370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11371
11372 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11373 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11374
11375 if (strlen(buf) > 0)
11376 set_mu_type = strtol(buf, NULL, 10);
11377
11378 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11379 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11380 set_mu_type &= ~0x0a;
11381 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11382 set_mu_type |= 0x02;
11383 set_mu_type &= ~0x08;
11384 }
11385
11386 params.name = "hemu_onoff";
11387 sprintf(buf, "%u", set_mu_type);
11388 params.value = buf;
11389 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11390 wifi_hostapdWrite(config_file, &params, 1);
11391 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11392
11393 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11394 return RETURN_OK;
11395}
11396
11397INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11398{
11399 struct params params={0};
11400 char config_file[64] = {0};
11401 char buf[64] = {0};
11402 unsigned int get_mu_type = 0;
11403
11404 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11405
11406 if (mu_type == NULL)
11407 return RETURN_ERR;
11408
11409 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11410 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11411
11412 get_mu_type = strtol(buf, NULL, 10);
11413 if (get_mu_type & 0x02)
11414 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11415 else
11416 *mu_type = WIFI_DL_MU_TYPE_NONE;
11417
11418 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11419 return RETURN_OK;
11420}
11421
11422
11423INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11424{
11425 char cmd[128] = {0};
11426 char buf[256] = {0};
11427 char config_file[64] = {0};
11428 char GI[8] = {0};
11429 int mode_map = 0;
11430 FILE *f = NULL;
11431 wifi_band band = band_invalid;
11432
11433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11434
11435 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11436 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11437 return RETURN_ERR;
11438 }
11439
11440 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11441 band = wifi_index_to_band(radio_index);
11442
11443 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11444 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11445 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11446 _syscmd(cmd, buf, sizeof(buf));
11447 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11448 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11449 if (strstr(buf, "[SHORT-GI-") == NULL) {
11450 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11451 _syscmd(cmd, buf, sizeof(buf));
11452 }
11453 if (band == band_5) {
11454 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11455 if (strstr(buf, "[SHORT-GI-") == NULL) {
11456 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11457 _syscmd(cmd, buf, sizeof(buf));
11458 }
11459 }
11460 }
11461 wifi_reloadAp(radio_index);
11462
11463 if (guard_interval == wifi_guard_interval_400)
11464 strcpy(GI, "0.4");
11465 else if (guard_interval == wifi_guard_interval_800)
11466 strcpy(GI, "0.8");
11467 else if (guard_interval == wifi_guard_interval_1600)
11468 strcpy(GI, "1.6");
11469 else if (guard_interval == wifi_guard_interval_3200)
11470 strcpy(GI, "3.2");
11471 else if (guard_interval == wifi_guard_interval_auto)
11472 strcpy(GI, "auto");
11473 // Record GI for get GI function
11474 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11475 f = fopen(buf, "w");
11476 if (f == NULL)
11477 return RETURN_ERR;
11478 fprintf(f, "%s", GI);
11479 fclose(f);
11480 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11481 return RETURN_OK;
11482}
11483
11484INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11485{
11486 char buf[32] = {0};
11487 char cmd[64] = {0};
11488
11489 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11490
11491 if (guard_interval == NULL)
11492 return RETURN_ERR;
11493
11494 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11495 _syscmd(cmd, buf, sizeof(buf));
11496
11497 if (strncmp(buf, "0.4", 3) == 0)
11498 *guard_interval = wifi_guard_interval_400;
11499 else if (strncmp(buf, "0.8", 3) == 0)
11500 *guard_interval = wifi_guard_interval_800;
11501 else if (strncmp(buf, "1.6", 3) == 0)
11502 *guard_interval = wifi_guard_interval_1600;
11503 else if (strncmp(buf, "3.2", 3) == 0)
11504 *guard_interval = wifi_guard_interval_3200;
11505 else
11506 *guard_interval = wifi_guard_interval_auto;
11507
11508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11509 return RETURN_OK;
11510}
11511
11512INT wifi_setBSSColor(INT radio_index, UCHAR color)
11513{
11514 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11515 struct params params = {0};
11516 char config_file[128] = {0};
11517 char bss_color[4] ={0};
11518
11519 params.name = "he_bss_color";
11520 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11521 params.value = bss_color;
11522 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11523 wifi_hostapdWrite(config_file, &params, 1);
11524 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11525
11526 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11527 return RETURN_OK;
11528}
11529
11530INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11531{
11532 char config_file[128] = {0};
11533 char buf[64] = {0};
11534 char temp_output[128] = {'\0'};
11535
11536 wifi_dbg_printf("\nFunc=%s\n", __func__);
11537 if (NULL == color)
11538 return RETURN_ERR;
11539
11540 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11541 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11542
11543 if(strlen(buf) > 0) {
11544 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11545 } else {
11546 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11547 }
11548
11549 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11550 wifi_dbg_printf("\noutput_string=%s\n", color);
11551
11552 return RETURN_OK;
11553}
11554
11555/* multi-psk support */
11556INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11557{
11558 char cmd[256];
11559 char interface_name[16] = {0};
11560
11561 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11562 return RETURN_ERR;
11563
11564 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11565 interface_name,
11566 mac[0],
11567 mac[1],
11568 mac[2],
11569 mac[3],
11570 mac[4],
11571 mac[5]
11572 );
11573 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11574 _syscmd(cmd, key->wifi_keyId, 64);
11575
11576
11577 return RETURN_OK;
11578}
11579
11580INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11581{
11582 char interface_name[16] = {0};
11583 FILE *fd = NULL;
11584 char fname[100];
11585 char cmd[128] = {0};
11586 char out[64] = {0};
11587 wifi_key_multi_psk_t * key = NULL;
11588 if(keysNumber < 0)
11589 return RETURN_ERR;
11590
11591 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11592 fd = fopen(fname, "w");
11593 if (!fd) {
11594 return RETURN_ERR;
11595 }
11596 key= (wifi_key_multi_psk_t *) keys;
11597 for(int i=0; i<keysNumber; ++i, key++) {
11598 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11599 }
11600 fclose(fd);
11601
11602 //reload file
11603 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11604 return RETURN_ERR;
11605 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11606 _syscmd(cmd, out, 64);
11607 return RETURN_OK;
11608}
11609
11610INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11611{
11612 FILE *fd = NULL;
11613 char fname[100];
11614 char * line = NULL;
11615 char * pos = NULL;
11616 size_t len = 0;
11617 ssize_t read = 0;
11618 INT ret = RETURN_OK;
11619 wifi_key_multi_psk_t *keys_it = NULL;
11620
11621 if (keysNumber < 1) {
11622 return RETURN_ERR;
11623 }
11624
11625 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11626 fd = fopen(fname, "r");
11627 if (!fd) {
11628 return RETURN_ERR;
11629 }
11630
11631 if (keys == NULL) {
11632 ret = RETURN_ERR;
11633 goto close;
11634 }
11635
11636 keys_it = keys;
11637 while ((read = getline(&line, &len, fd)) != -1) {
11638 //Strip trailing new line if present
11639 if (read > 0 && line[read-1] == '\n') {
11640 line[read-1] = '\0';
11641 }
11642
11643 if(strcmp(line,"keyid=")) {
11644 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11645 if (!(pos = index(line, ' '))) {
11646 ret = RETURN_ERR;
11647 goto close;
11648 }
11649 pos++;
11650 //Here should be 00:00:00:00:00:00
11651 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11652 printf("Not supported MAC: %s\n", pos);
11653 }
11654 if (!(pos = index(pos, ' '))) {
11655 ret = RETURN_ERR;
11656 goto close;
11657 }
11658 pos++;
11659
11660 //The rest is PSK
11661 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11662 keys_it++;
11663
11664 if(--keysNumber <= 0)
11665 break;
11666 }
11667 }
11668
11669close:
11670 free(line);
11671 fclose(fd);
11672 return ret;
11673}
11674/* end of multi-psk support */
11675
11676INT wifi_setNeighborReports(UINT apIndex,
11677 UINT numNeighborReports,
11678 wifi_NeighborReport_t *neighborReports)
11679{
11680 char cmd[256] = { 0 };
11681 char hex_bssid[13] = { 0 };
11682 char bssid[18] = { 0 };
11683 char nr[256] = { 0 };
11684 char ssid[256];
11685 char hex_ssid[256];
11686 char interface_name[16] = {0};
11687 INT ret;
11688
11689 /*rmeove all neighbors*/
11690 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11691 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11692 return RETURN_ERR;
11693 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);
11694 system(cmd);
11695
11696 for(unsigned int i = 0; i < numNeighborReports; i++)
11697 {
11698 memset(ssid, 0, sizeof(ssid));
11699 ret = wifi_getSSIDName(apIndex, ssid);
11700 if (ret != RETURN_OK)
11701 return RETURN_ERR;
11702
11703 memset(hex_ssid, 0, sizeof(hex_ssid));
11704 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11705 sprintf(hex_ssid + k,"%02x", ssid[j]);
11706
11707 snprintf(hex_bssid, sizeof(hex_bssid),
11708 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11709 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11710 snprintf(bssid, sizeof(bssid),
11711 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11712 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11713
11714 snprintf(nr, sizeof(nr),
11715 "%s" // bssid
11716 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11717 "%02hhx" // operclass
11718 "%02hhx" // channel
11719 "%02hhx", // phy_mode
11720 hex_bssid,
11721 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11722 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11723 neighborReports[i].opClass,
11724 neighborReports[i].channel,
11725 neighborReports[i].phyTable);
11726
11727 snprintf(cmd, sizeof(cmd),
11728 "hostapd_cli set_neighbor "
11729 "%s " // bssid
11730 "ssid=%s " // ssid
11731 "nr=%s " // nr
11732 "-i %s",
11733 bssid,hex_ssid,nr, interface_name);
11734
11735 if (WEXITSTATUS(system(cmd)) != 0)
11736 {
11737 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11738 }
11739 }
11740
11741 return RETURN_OK;
11742}
11743
11744INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11745{
11746 return RETURN_OK;
11747}
11748
11749#ifdef _WIFI_HAL_TEST_
11750int main(int argc,char **argv)
11751{
11752 int index;
11753 INT ret=0;
11754 char buf[1024]="";
11755
11756 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11757 if(argc<3)
11758 {
11759 if(argc==2)
11760 {
11761 if(!strcmp(argv[1], "init"))
11762 return wifi_init();
11763 if(!strcmp(argv[1], "reset"))
11764 return wifi_reset();
11765 if(!strcmp(argv[1], "wifi_getHalVersion"))
11766 {
11767 char buffer[64];
11768 if(wifi_getHalVersion(buffer)==RETURN_OK)
11769 printf("Version: %s\n", buffer);
11770 else
11771 printf("Error in wifi_getHalVersion\n");
11772 return RETURN_OK;
11773 }
11774 }
11775 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11776 exit(-1);
11777 }
11778
11779 index = atoi(argv[2]);
11780 if(strstr(argv[1], "wifi_getApName")!=NULL)
11781 {
11782 wifi_getApName(index,buf);
11783 printf("Ap name is %s \n",buf);
11784 return 0;
11785 }
11786 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11787 {
11788 BOOL b = FALSE;
11789 BOOL *output_bool = &b;
11790 wifi_getRadioAutoChannelEnable(index,output_bool);
11791 printf("Channel enabled = %d \n",b);
11792 return 0;
11793 }
11794 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11795 {
11796 wifi_getApWpaEncryptionMode(index,buf);
11797 printf("encryption enabled = %s\n",buf);
11798 return 0;
11799 }
11800 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11801 {
11802 BOOL b = FALSE;
11803 BOOL *output_bool = &b;
11804 wifi_getApSsidAdvertisementEnable(index,output_bool);
11805 printf("advertisment enabled = %d\n",b);
11806 return 0;
11807 }
11808 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11809 {
11810 if(argc <= 3 )
11811 {
11812 printf("Insufficient arguments \n");
11813 exit(-1);
11814 }
11815
11816 char sta[20] = {'\0'};
11817 ULLONG handle= 0;
11818 strcpy(sta,argv[3]);
11819 mac_address_t st;
11820 mac_addr_aton(st,sta);
11821
11822 wifi_associated_dev_tid_stats_t tid_stats;
11823 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11824 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11825 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);
11826 }
11827
11828 if(strstr(argv[1], "getApEnable")!=NULL) {
11829 BOOL enable;
11830 ret=wifi_getApEnable(index, &enable);
11831 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11832 }
11833 else if(strstr(argv[1], "setApEnable")!=NULL) {
11834 BOOL enable = atoi(argv[3]);
11835 ret=wifi_setApEnable(index, enable);
11836 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11837 }
11838 else if(strstr(argv[1], "getApStatus")!=NULL) {
11839 char status[64];
11840 ret=wifi_getApStatus(index, status);
11841 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11842 }
11843 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11844 {
11845 wifi_getSSIDNameStatus(index,buf);
11846 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11847 return 0;
11848 }
11849 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11850 wifi_ssidTrafficStats2_t stats={0};
11851 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11852 printf("%s %d: returns %d\n", argv[1], index, ret);
11853 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11854 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11855 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11856 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11857 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11858 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11859 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11860 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11861 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11862 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11863 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11864 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11865 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11866 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11867 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11868 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11869 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11870 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11871 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11872 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11873 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11874 }
11875 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11876 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11877 UINT array_size=0;
11878 UINT i=0;
11879 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11880 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11881 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11882 printf(" neighbor %d:\n", i);
11883 printf(" ap_SSID =%s\n", pt->ap_SSID);
11884 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11885 printf(" ap_Mode =%s\n", pt->ap_Mode);
11886 printf(" ap_Channel =%d\n", pt->ap_Channel);
11887 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11888 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11889 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11890 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11891 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11892 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11893 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11894 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11895 printf(" ap_Noise =%d\n", pt->ap_Noise);
11896 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11897 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11898 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11899 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11900 }
11901 if(neighbor_ap_array)
11902 free(neighbor_ap_array); //make sure to free the list
11903 }
11904 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11905 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11906 UINT array_size=0;
11907 UINT i=0;
11908 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11909 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11910 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11911 printf(" associated_dev %d:\n", i);
11912 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11913 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11914 printf(" cli_SNR =%d\n", pt->cli_SNR);
11915 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11916 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11917 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11918 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11919 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11920 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11921 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11922 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11923 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11924 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11925 }
11926 if(associated_dev_array)
11927 free(associated_dev_array); //make sure to free the list
11928 }
11929
11930 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11931 {
11932#define MAX_ARRAY_SIZE 64
11933 int i, array_size;
11934 char *p, *ch_str;
11935 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11936
11937 if(argc != 5)
11938 {
11939 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11940 exit(-1);
11941 }
11942 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11943
11944 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11945 {
11946 strtok_r(ch_str, ",", &p);
11947 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11948 }
11949 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11950 if(!array_size)
11951 array_size=1;//Need to print current channel statistics
11952 for(i=0; i<array_size; i++)
11953 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11954 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11955 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11956 input_output_channelStats_array[i].ch_number,\
11957 input_output_channelStats_array[i].ch_noise,\
11958 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11959 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11960 input_output_channelStats_array[i].ch_utilization_busy,\
11961 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11962 input_output_channelStats_array[i].ch_utilization_total);
11963 }
11964
11965 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11966 {
11967 if(argc <= 3 )
11968 {
11969 printf("Insufficient arguments \n");
11970 exit(-1);
11971 }
11972 char mac_addr[20] = {'\0'};
11973 wifi_device_t output_struct;
11974 int dev_index = atoi(argv[3]);
11975
11976 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11977 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11978 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);
11979 }
11980
11981 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11982 {
11983 if (argc <= 3)
11984 {
11985 printf("Insufficient arguments\n");
11986 exit(-1);
11987 }
11988 char args[256];
11989 wifi_NeighborReport_t *neighborReports;
11990
11991 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11992 if (!neighborReports)
11993 {
11994 printf("Failed to allocate memory");
11995 exit(-1);
11996 }
11997
11998 for (int i = 3; i < argc; ++i)
11999 {
12000 char *val;
12001 int j = 0;
12002 memset(args, 0, sizeof(args));
12003 strncpy(args, argv[i], sizeof(args));
12004 val = strtok(args, ";");
12005 while (val != NULL)
12006 {
12007 if (j == 0)
12008 {
12009 mac_addr_aton(neighborReports[i - 3].bssid, val);
12010 } else if (j == 1)
12011 {
12012 neighborReports[i - 3].info = strtol(val, NULL, 16);
12013 } else if (j == 2)
12014 {
12015 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12016 } else if (j == 3)
12017 {
12018 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12019 } else if (j == 4)
12020 {
12021 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12022 } else {
12023 printf("Insufficient arguments]n\n");
12024 exit(-1);
12025 }
12026 val = strtok(NULL, ";");
12027 j++;
12028 }
12029 }
12030
12031 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12032 if (ret != RETURN_OK)
12033 {
12034 printf("wifi_setNeighborReports ret = %d", ret);
12035 exit(-1);
12036 }
12037 }
12038 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12039 {
12040 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12041 printf("%s.\n", buf);
12042 else
12043 printf("Error returned\n");
12044 }
12045 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12046 {
12047 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12048 printf("%s.\n", buf);
12049 else
12050 printf("Error returned\n");
12051 }
12052 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12053 {
12054 if (argc <= 2)
12055 {
12056 printf("Insufficient arguments\n");
12057 exit(-1);
12058 }
12059 char buf[64]= {'\0'};
12060 wifi_getRadioOperatingChannelBandwidth(index,buf);
12061 printf("Current bandwidth is %s \n",buf);
12062 return 0;
12063 }
12064 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12065 {
12066 if (argc <= 5)
12067 {
12068 printf("Insufficient arguments\n");
12069 exit(-1);
12070 }
12071 UINT channel = atoi(argv[3]);
12072 UINT width = atoi(argv[4]);
12073 UINT beacon = atoi(argv[5]);
12074 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12075 printf("Result = %d", ret);
12076 }
12077
12078 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12079 return 0;
12080}
12081
12082#endif
12083
12084#ifdef WIFI_HAL_VERSION_3
12085
12086INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12087{
12088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12089 if (bitMap & WIFI_BITRATE_1MBPS)
12090 strcat(BasicRate, "1,");
12091 if (bitMap & WIFI_BITRATE_2MBPS)
12092 strcat(BasicRate, "2,");
12093 if (bitMap & WIFI_BITRATE_5_5MBPS)
12094 strcat(BasicRate, "5.5,");
12095 if (bitMap & WIFI_BITRATE_6MBPS)
12096 strcat(BasicRate, "6,");
12097 if (bitMap & WIFI_BITRATE_9MBPS)
12098 strcat(BasicRate, "9,");
12099 if (bitMap & WIFI_BITRATE_11MBPS)
12100 strcat(BasicRate, "11,");
12101 if (bitMap & WIFI_BITRATE_12MBPS)
12102 strcat(BasicRate, "12,");
12103 if (bitMap & WIFI_BITRATE_18MBPS)
12104 strcat(BasicRate, "18,");
12105 if (bitMap & WIFI_BITRATE_24MBPS)
12106 strcat(BasicRate, "24,");
12107 if (bitMap & WIFI_BITRATE_36MBPS)
12108 strcat(BasicRate, "36,");
12109 if (bitMap & WIFI_BITRATE_48MBPS)
12110 strcat(BasicRate, "48,");
12111 if (bitMap & WIFI_BITRATE_54MBPS)
12112 strcat(BasicRate, "54,");
12113 if (strlen(BasicRate) != 0) // remove last comma
12114 BasicRate[strlen(BasicRate) - 1] = '\0';
12115 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12116 return RETURN_OK;
12117}
12118
12119INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12120{
12121 UINT BitMap = 0;
12122 char *rate;
12123
12124 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12125 rate = strtok(BasicRatesList, ",");
12126 while(rate != NULL)
12127 {
12128 if (strcmp(rate, "1") == 0)
12129 BitMap |= WIFI_BITRATE_1MBPS;
12130 else if (strcmp(rate, "2") == 0)
12131 BitMap |= WIFI_BITRATE_2MBPS;
12132 else if (strcmp(rate, "5.5") == 0)
12133 BitMap |= WIFI_BITRATE_5_5MBPS;
12134 else if (strcmp(rate, "6") == 0)
12135 BitMap |= WIFI_BITRATE_6MBPS;
12136 else if (strcmp(rate, "9") == 0)
12137 BitMap |= WIFI_BITRATE_9MBPS;
12138 else if (strcmp(rate, "11") == 0)
12139 BitMap |= WIFI_BITRATE_11MBPS;
12140 else if (strcmp(rate, "12") == 0)
12141 BitMap |= WIFI_BITRATE_12MBPS;
12142 else if (strcmp(rate, "18") == 0)
12143 BitMap |= WIFI_BITRATE_18MBPS;
12144 else if (strcmp(rate, "24") == 0)
12145 BitMap |= WIFI_BITRATE_24MBPS;
12146 else if (strcmp(rate, "36") == 0)
12147 BitMap |= WIFI_BITRATE_36MBPS;
12148 else if (strcmp(rate, "48") == 0)
12149 BitMap |= WIFI_BITRATE_48MBPS;
12150 else if (strcmp(rate, "54") == 0)
12151 BitMap |= WIFI_BITRATE_54MBPS;
12152 rate = strtok(NULL, ",");
12153 }
12154 *basicRateBitMap = BitMap;
12155 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12156 return RETURN_OK;
12157}
12158
12159// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
12160INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12161{
12162 char buf[128] = {0};
12163 char cmd[128] = {0};
12164 char config_file[64] = {0};
12165 int bandwidth;
12166 int set_mode = 0;
12167 wifi_radio_operationParam_t current_param;
12168
12169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12170
12171 multiple_set = TRUE;
12172 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12173 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12174 return RETURN_ERR;
12175 }
12176 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12177 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12178 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12179 return RETURN_ERR;
12180 }
12181 }
12182
12183 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12184 bandwidth = 20;
12185 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12186 bandwidth = 40;
12187 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12188 bandwidth = 80;
12189 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12190 bandwidth = 160;
12191 if (operationParam->autoChannelEnabled){
12192 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12193 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12194 return RETURN_ERR;
12195 }
12196 }else{
12197 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12198 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12199 return RETURN_ERR;
12200 }
12201 }
12202
12203 if (current_param.variant != operationParam->variant) {
12204 // Two different definition bit map, so need to check every bit.
12205 if (operationParam->variant & WIFI_80211_VARIANT_A)
12206 set_mode |= WIFI_MODE_A;
12207 if (operationParam->variant & WIFI_80211_VARIANT_B)
12208 set_mode |= WIFI_MODE_B;
12209 if (operationParam->variant & WIFI_80211_VARIANT_G)
12210 set_mode |= WIFI_MODE_G;
12211 if (operationParam->variant & WIFI_80211_VARIANT_N)
12212 set_mode |= WIFI_MODE_N;
12213 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12214 set_mode |= WIFI_MODE_AC;
12215 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12216 set_mode |= WIFI_MODE_AX;
12217 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12218 memset(buf, 0, sizeof(buf));
12219 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12220 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12221 return RETURN_ERR;
12222 }
12223 }
12224 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12225 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12226 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12227 return RETURN_ERR;
12228 }
12229 }
12230 if (current_param.beaconInterval != operationParam->beaconInterval) {
12231 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12232 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12233 return RETURN_ERR;
12234 }
12235 }
12236 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12237 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12238 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12239 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12240 return RETURN_ERR;
12241 }
12242 }
12243 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12244 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12245 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12246 return RETURN_ERR;
12247 }
12248 }
12249 if (current_param.guardInterval != operationParam->guardInterval) {
12250 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12251 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12252 return RETURN_ERR;
12253 }
12254 }
12255 if (current_param.transmitPower != operationParam->transmitPower) {
12256 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12257 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12258 return RETURN_ERR;
12259 }
12260 }
12261 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12262 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12263 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12264 return RETURN_ERR;
12265 }
12266 }
12267 if (current_param.obssCoex != operationParam->obssCoex) {
12268 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12269 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12270 return RETURN_ERR;
12271 }
12272 }
12273 if (current_param.stbcEnable != operationParam->stbcEnable) {
12274 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12275 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12276 return RETURN_ERR;
12277 }
12278 }
12279 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12280 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12281 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12282 return RETURN_ERR;
12283 }
12284 }
12285
12286 // if enable is true, then restart the radio
12287 wifi_setRadioEnable(index, FALSE);
12288 if (operationParam->enable == TRUE)
12289 wifi_setRadioEnable(index, TRUE);
12290 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12291
12292 return RETURN_OK;
12293}
12294
12295INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12296{
12297 char band[64] = {0};
12298 char buf[256] = {0};
12299 char config_file[64] = {0};
12300 char cmd[128] = {0};
12301 int ret = RETURN_ERR;
12302 int mode = 0;
12303 ULONG channel = 0;
12304 BOOL enabled = FALSE;
12305
12306 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12307 printf("Entering %s index = %d\n", __func__, (int)index);
12308
12309 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12310 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12311 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12312 {
12313 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12314 return RETURN_ERR;
12315 }
12316 operationParam->enable = enabled;
12317
12318 memset(band, 0, sizeof(band));
12319 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12320 {
12321 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12322 return RETURN_ERR;
12323 }
12324
12325 if (!strcmp(band, "2.4GHz"))
12326 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12327 else if (!strcmp(band, "5GHz"))
12328 operationParam->band = WIFI_FREQUENCY_5_BAND;
12329 else if (!strcmp(band, "6GHz"))
12330 operationParam->band = WIFI_FREQUENCY_6_BAND;
12331 else
12332 {
12333 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12334 band);
12335 }
12336
12337 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12338 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12339 operationParam->channel = 0;
12340 operationParam->autoChannelEnabled = TRUE;
12341 } else {
12342 operationParam->channel = strtol(buf, NULL, 10);
12343 operationParam->autoChannelEnabled = FALSE;
12344 }
12345
12346 memset(buf, 0, sizeof(buf));
12347 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12348 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12349 return RETURN_ERR;
12350 }
12351 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12352 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12353 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12354 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12355 else
12356 {
12357 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12358 return false;
12359 }
12360
12361 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12362 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12363 return RETURN_ERR;
12364 }
12365 // Two different definition bit map, so need to check every bit.
12366 if (mode & WIFI_MODE_A)
12367 operationParam->variant |= WIFI_80211_VARIANT_A;
12368 if (mode & WIFI_MODE_B)
12369 operationParam->variant |= WIFI_80211_VARIANT_B;
12370 if (mode & WIFI_MODE_G)
12371 operationParam->variant |= WIFI_80211_VARIANT_G;
12372 if (mode & WIFI_MODE_N)
12373 operationParam->variant |= WIFI_80211_VARIANT_N;
12374 if (mode & WIFI_MODE_AC)
12375 operationParam->variant |= WIFI_80211_VARIANT_AC;
12376 if (mode & WIFI_MODE_AX)
12377 operationParam->variant |= WIFI_80211_VARIANT_AX;
12378 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12379 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12380 return RETURN_ERR;
12381 }
12382 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12383 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12384 return RETURN_ERR;
12385 }
12386 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12387 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12388 return RETURN_ERR;
12389 }
12390
12391 memset(buf, 0, sizeof(buf));
12392 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12393 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12394 return RETURN_ERR;
12395 }
12396 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12397
12398 memset(buf, 0, sizeof(buf));
12399 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12400 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12401 return RETURN_ERR;
12402 }
12403 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12404
12405 memset(buf, 0, sizeof(buf));
12406 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12407 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12408
12409 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12410 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12411 return RETURN_ERR;
12412 }
12413 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12414 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12415 return RETURN_ERR;
12416 }
12417
12418 memset(buf, 0, sizeof(buf));
12419 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12420 if (strcmp(buf, "-1") == 0) {
12421 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12422 operationParam->ctsProtection = FALSE;
12423 } else {
12424 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12425 operationParam->ctsProtection = TRUE;
12426 }
12427
12428 memset(buf, 0, sizeof(buf));
12429 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12430 if (strcmp(buf, "0") == 0)
12431 operationParam->obssCoex = FALSE;
12432 else
12433 operationParam->obssCoex = TRUE;
12434
12435 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12436 _syscmd(cmd, buf, sizeof(buf));
12437 if (strlen(buf) != 0)
12438 operationParam->stbcEnable = TRUE;
12439 else
12440 operationParam->stbcEnable = FALSE;
12441
12442 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12443 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12444 return RETURN_ERR;
12445 }
12446
12447 // Below value is hardcoded
12448
12449 operationParam->numSecondaryChannels = 0;
12450 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12451 operationParam->channelSecondary[i] = 0;
12452 }
12453 operationParam->csa_beacon_count = 15;
12454 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12455
12456 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12457 return RETURN_OK;
12458}
12459
12460static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12461{
12462 int max_radio_num = 0;
12463
12464 wifi_getMaxRadioNumber(&max_radio_num);
12465 if (radioIndex >= max_radio_num) {
12466 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12467 return RETURN_ERR;
12468 }
12469
12470 return (arrayIndex * max_radio_num) + radioIndex;
12471}
12472
developer96b38512023-02-22 11:17:45 +080012473static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
12474{
12475 int max_radio_num = 0;
12476
12477 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
12478 return -1;
12479
12480 wifi_getMaxRadioNumber(&max_radio_num);
12481
12482 (*radioIndex) = vapIndex % max_radio_num;
12483 (*arrayIndex) = vapIndex / max_radio_num;
12484
12485 return 0;
12486}
12487
12488
developer72fb0bb2023-01-11 09:46:29 +080012489wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12490 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12491 return WIFI_BITRATE_1MBPS;
12492 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12493 return WIFI_BITRATE_2MBPS;
12494 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12495 return WIFI_BITRATE_5_5MBPS;
12496 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12497 return WIFI_BITRATE_6MBPS;
12498 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12499 return WIFI_BITRATE_9MBPS;
12500 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12501 return WIFI_BITRATE_11MBPS;
12502 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12503 return WIFI_BITRATE_12MBPS;
12504 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12505 return WIFI_BITRATE_18MBPS;
12506 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12507 return WIFI_BITRATE_24MBPS;
12508 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12509 return WIFI_BITRATE_36MBPS;
12510 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12511 return WIFI_BITRATE_48MBPS;
12512 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12513 return WIFI_BITRATE_54MBPS;
12514 return WIFI_BITRATE_DEFAULT;
12515}
12516
12517INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12518{
12519 if (beacon == WIFI_BITRATE_1MBPS)
12520 strcpy(beacon_str, "1Mbps");
12521 else if (beacon == WIFI_BITRATE_2MBPS)
12522 strcpy(beacon_str, "2Mbps");
12523 else if (beacon == WIFI_BITRATE_5_5MBPS)
12524 strcpy(beacon_str, "5.5Mbps");
12525 else if (beacon == WIFI_BITRATE_6MBPS)
12526 strcpy(beacon_str, "6Mbps");
12527 else if (beacon == WIFI_BITRATE_9MBPS)
12528 strcpy(beacon_str, "9Mbps");
12529 else if (beacon == WIFI_BITRATE_11MBPS)
12530 strcpy(beacon_str, "11Mbps");
12531 else if (beacon == WIFI_BITRATE_12MBPS)
12532 strcpy(beacon_str, "12Mbps");
12533 else if (beacon == WIFI_BITRATE_18MBPS)
12534 strcpy(beacon_str, "18Mbps");
12535 else if (beacon == WIFI_BITRATE_24MBPS)
12536 strcpy(beacon_str, "24Mbps");
12537 else if (beacon == WIFI_BITRATE_36MBPS)
12538 strcpy(beacon_str, "36Mbps");
12539 else if (beacon == WIFI_BITRATE_48MBPS)
12540 strcpy(beacon_str, "48Mbps");
12541 else if (beacon == WIFI_BITRATE_54MBPS)
12542 strcpy(beacon_str, "54Mbps");
12543 return RETURN_OK;
12544}
12545
12546INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12547{
12548 INT mode = 0;
12549 INT ret = -1;
12550 INT output = 0;
12551 int i = 0;
12552 int vap_index = 0;
12553 BOOL enabled = FALSE;
12554 char buf[256] = {0};
12555 wifi_vap_security_t security = {0};
12556 map->num_vaps = 5; // Hardcoded
12557
12558 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12559 printf("Entering %s index = %d\n", __func__, (int)index);
12560
12561 for (i = 0; i < 5; i++)
12562 {
12563 map->vap_array[i].radio_index = index;
12564
12565 vap_index = array_index_to_vap_index(index, i);
12566 if (vap_index < 0)
12567 return RETURN_ERR;
12568
12569 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12570
12571 map->vap_array[i].vap_index = vap_index;
12572
12573 memset(buf, 0, sizeof(buf));
12574 ret = wifi_getApName(vap_index, buf);
12575 if (ret != RETURN_OK) {
12576 printf("%s: wifi_getApName return error\n", __func__);
12577 return RETURN_ERR;
12578 }
12579 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12580
12581 memset(buf, 0, sizeof(buf));
12582 ret = wifi_getSSIDName(vap_index, buf);
12583 if (ret != RETURN_OK) {
12584 printf("%s: wifi_getSSIDName return error\n", __func__);
12585 return RETURN_ERR;
12586 }
12587 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12588
12589 ret = wifi_getSSIDEnable(vap_index, &enabled);
12590 if (ret != RETURN_OK) {
12591 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12592 return RETURN_ERR;
12593 }
12594 map->vap_array[i].u.bss_info.enabled = enabled;
12595
12596 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12597 if (ret != RETURN_OK) {
12598 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12599 return RETURN_ERR;
12600 }
12601 map->vap_array[i].u.bss_info.showSsid = enabled;
12602
12603 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12604 if (ret != RETURN_OK) {
12605 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12606 return RETURN_ERR;
12607 }
12608 map->vap_array[i].u.bss_info.isolation = enabled;
12609
12610 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12611 if (ret != RETURN_OK) {
12612 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12613 return RETURN_ERR;
12614 }
12615 map->vap_array[i].u.bss_info.bssMaxSta = output;
12616
12617 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12618 if (ret != RETURN_OK) {
12619 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12620 return RETURN_ERR;
12621 }
12622 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12623
12624 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12625 if (ret != RETURN_OK) {
12626 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12627 return RETURN_ERR;
12628 }
12629 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12630
12631 ret = wifi_getApSecurity(vap_index, &security);
12632 if (ret != RETURN_OK) {
12633 printf("%s: wifi_getApSecurity return error\n", __func__);
12634 return RETURN_ERR;
12635 }
12636 map->vap_array[i].u.bss_info.security = security;
12637
12638 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12639 if (ret != RETURN_OK) {
12640 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12641 return RETURN_ERR;
12642 }
12643 if (mode == 0)
12644 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
12645 else
12646 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
12647 if (mode == 1)
12648 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
12649 else if (mode == 2)
12650 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12651
12652 ret = wifi_getApWmmEnable(vap_index, &enabled);
12653 if (ret != RETURN_OK) {
12654 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12655 return RETURN_ERR;
12656 }
12657 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12658
12659 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12660 if (ret != RETURN_OK) {
12661 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12662 return RETURN_ERR;
12663 }
12664 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12665
12666 memset(buf, 0, sizeof(buf));
12667 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12668 if (ret != RETURN_OK) {
12669 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12670 return RETURN_ERR;
12671 }
12672 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12673
12674 memset(buf, 0, sizeof(buf));
12675 ret = wifi_getBaseBSSID(vap_index, buf);
12676 if (ret != RETURN_OK) {
12677 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12678 return RETURN_ERR;
12679 }
12680 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12681 &map->vap_array[i].u.bss_info.bssid[0],
12682 &map->vap_array[i].u.bss_info.bssid[1],
12683 &map->vap_array[i].u.bss_info.bssid[2],
12684 &map->vap_array[i].u.bss_info.bssid[3],
12685 &map->vap_array[i].u.bss_info.bssid[4],
12686 &map->vap_array[i].u.bss_info.bssid[5]);
12687 // 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]);
12688
12689 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12690 if (ret != RETURN_OK) {
12691 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12692 return RETURN_ERR;
12693 }
12694 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12695
12696 // TODO: wps, noack
12697 }
12698 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12699 return RETURN_OK;
12700}
12701
12702void checkVapStatus(int apIndex, bool *enable)
12703{
12704 char if_name[16] = {0};
12705 char cmd[128] = {0};
12706 char buf[128] = {0};
12707
12708 *enable = FALSE;
12709 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12710 return;
12711
12712 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12713 _syscmd(cmd, buf, sizeof(buf));
12714 if (strlen(buf) > 0)
12715 *enable = TRUE;
12716 return;
12717}
12718
12719static int prepareInterface(UINT apIndex, char *new_interface)
12720{
12721 char cur_interface[16] = {0};
12722 char config_file[128] = {0};
12723 char cmd[128] = {0};
12724 char buf[16] = {0};
12725 int max_radio_num = 0;
12726 int radioIndex = -1;
12727 int phyIndex = -1;
12728
12729 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12730 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12731
12732 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
12733 wifi_getMaxRadioNumber(&max_radio_num);
12734 radioIndex = apIndex % max_radio_num;
12735 phyIndex = radio_index_to_phy(radioIndex);
12736 // disable and del old interface, then add new interface
12737 wifi_setApEnable(apIndex, FALSE);
12738 snprintf(cmd, sizeof(cmd), "iw %s del && iw phy%d interface add %s type __ap", cur_interface, phyIndex, new_interface);
12739 _syscmd(cmd, buf, sizeof(buf));
12740 }
12741 // update the vap status file
12742 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12743 _syscmd(cmd, buf, sizeof(buf));
12744 return RETURN_OK;
12745}
12746
12747INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12748{
12749 char interface_name[16] = {0};
12750 unsigned int i;
12751 wifi_vap_info_t *vap_info = NULL;
12752 int acl_mode;
12753 int ret = 0;
12754 char *sec_str = NULL;
12755 char buf[256] = {0};
12756 char cmd[128] = {0};
12757 char config_file[64] = {0};
12758 char bssid[32] = {0};
12759 char psk_file[64] = {0};
12760 bool enable = FALSE;
12761
12762 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12763 printf("Entering %s index = %d\n", __func__, (int)index);
12764 for (i = 0; i < map->num_vaps; i++)
12765 {
12766 multiple_set = TRUE;
12767 vap_info = &map->vap_array[i];
12768
12769 // Check vap status file to enable multiple ap if the system boot.
12770 checkVapStatus(vap_info->vap_index, &enable);
12771 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
12772 continue;
12773
12774 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12775
12776 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12777 enable = FALSE;
12778
12779 // multi-ap first up need to copy current radio config
12780 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
12781 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12782 _syscmd(cmd, buf, sizeof(buf));
12783 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12784 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12785 } else {
12786 // Check whether the interface name is valid or this ap change it.
12787 int apIndex = -1;
12788 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12789 if (apIndex != -1 && apIndex != vap_info->vap_index)
12790 continue;
12791 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12792 }
12793
12794 struct params params[3];
12795 params[0].name = "interface";
12796 params[0].value = vap_info->vap_name;
12797 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12798 params[1].name = "bssid";
12799 params[1].value = bssid;
12800 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
12801 params[2].name = "wpa_psk_file";
12802 params[2].value = psk_file;
12803
12804 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12805 wifi_hostapdWrite(config_file, params, 3);
12806
12807 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12808 _syscmd(cmd, buf, sizeof(buf));
12809
12810 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12811 if (ret != RETURN_OK) {
12812 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12813 return RETURN_ERR;
12814 }
12815
12816 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12817 if (ret != RETURN_OK) {
12818 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12819 return RETURN_ERR;
12820 }
12821
12822 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12823 if (ret != RETURN_OK) {
12824 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12825 return RETURN_ERR;
12826 }
12827
12828 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12829 if (ret != RETURN_OK) {
12830 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12831 return RETURN_ERR;
12832 }
12833
12834 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12835 if (ret != RETURN_OK) {
12836 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12837 return RETURN_ERR;
12838 }
12839
12840 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12841 if (ret != RETURN_OK) {
12842 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12843 return RETURN_ERR;
12844 }
12845
12846 if (vap_info->u.bss_info.mac_filter_enable == false){
12847 acl_mode = 0;
12848 }else {
12849 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
12850 acl_mode = 2;
12851 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12852 _syscmd(cmd, buf, sizeof(buf));
12853 }else{
12854 acl_mode = 1;
12855 }
12856 }
12857
12858 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12859 if (ret != RETURN_OK) {
12860 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12861 return RETURN_ERR;
12862 }
12863
12864 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12865 if (ret != RETURN_OK) {
12866 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12867 return RETURN_ERR;
12868 }
12869
12870 memset(buf, 0, sizeof(buf));
12871 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12872 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12873 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12874 if (ret != RETURN_OK) {
12875 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12876 return RETURN_ERR;
12877 }
12878
12879 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12880 if (ret != RETURN_OK) {
12881 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12882 return RETURN_ERR;
12883 }
12884
developer72fb0bb2023-01-11 09:46:29 +080012885 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12886 if (ret != RETURN_OK) {
12887 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12888 return RETURN_ERR;
12889 }
12890
developer23e71282023-01-18 10:25:19 +080012891 wifi_setApEnable(vap_info->vap_index, FALSE);
12892 wifi_setApEnable(vap_info->vap_index, TRUE);
12893 multiple_set = FALSE;
12894
12895 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080012896 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12897 if (ret != RETURN_OK) {
12898 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12899 return RETURN_ERR;
12900 }
12901
12902 // TODO mgmtPowerControl, interworking, wps
12903 }
12904 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12905 return RETURN_OK;
12906}
12907
12908int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12909{
12910 char *token, *next;
12911 const char s[2] = ",";
12912 int count =0;
12913
12914 /* get the first token */
12915 token = strtok_r(pchannels, s, &next);
12916
12917 /* walk through other tokens */
12918 while( token != NULL && count < MAX_CHANNELS) {
12919 chlistptr->channels_list[count++] = atoi(token);
12920 token = strtok_r(NULL, s, &next);
12921 }
12922
12923 return count;
12924}
12925
12926static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12927{
12928 INT status;
12929 wifi_channels_list_t *chlistp;
12930 CHAR output_string[64];
12931 CHAR pchannels[128];
12932 CHAR interface_name[16] = {0};
12933 wifi_band band;
12934
12935 if(rcap == NULL)
12936 {
12937 return RETURN_ERR;
12938 }
12939
12940 rcap->numSupportedFreqBand = 1;
12941 band = wifi_index_to_band(radioIndex);
12942
12943 if (band == band_2_4)
12944 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12945 else if (band == band_5)
12946 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12947 else if (band == band_6)
12948 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
12949
12950 chlistp = &(rcap->channel_list[0]);
12951 memset(pchannels, 0, sizeof(pchannels));
12952
12953 /* possible number of radio channels */
12954 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
12955 {
12956 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
12957 }
12958 /* Number of channels and list*/
12959 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
12960
12961 /* autoChannelSupported */
12962 /* always ON with wifi_getRadioAutoChannelSupported */
12963 rcap->autoChannelSupported = TRUE;
12964
12965 /* DCSSupported */
12966 /* always ON with wifi_getRadioDCSSupported */
12967 rcap->DCSSupported = TRUE;
12968
12969 /* zeroDFSSupported - TBD */
12970 rcap->zeroDFSSupported = FALSE;
12971
12972 /* Supported Country List*/
12973 memset(output_string, 0, sizeof(output_string));
12974 status = wifi_getRadioCountryCode(radioIndex, output_string);
12975 if( status != 0 ) {
12976 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
12977 return RETURN_ERR;
12978 } else {
12979 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
12980 }
12981 if(!strcmp(output_string,"US")){
12982 rcap->countrySupported[0] = wifi_countrycode_US;
12983 rcap->countrySupported[1] = wifi_countrycode_CA;
12984 } else if (!strcmp(output_string,"CA")) {
12985 rcap->countrySupported[0] = wifi_countrycode_CA;
12986 rcap->countrySupported[1] = wifi_countrycode_US;
12987 } else {
12988 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
12989 }
12990
12991 rcap->numcountrySupported = 2;
12992
12993 /* csi */
12994 rcap->csi.maxDevices = 8;
12995 rcap->csi.soudingFrameSupported = TRUE;
12996
12997 wifi_GetInterfaceName(radioIndex, interface_name);
12998 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
12999
13000 /* channelWidth - all supported bandwidths */
13001 int i=0;
13002 rcap->channelWidth[i] = 0;
13003 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13004 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13005 WIFI_CHANNELBANDWIDTH_40MHZ);
13006
13007 }
13008 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
13009 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13010 WIFI_CHANNELBANDWIDTH_40MHZ |
13011 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13012 }
13013
13014
13015 /* mode - all supported variants */
13016 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13017 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13018 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13019 }
13020 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13021 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13022 }
13023 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13024 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13025 }
13026 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13027 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13028
13029 /* supportedBitRate - all supported bitrates */
13030 rcap->supportedBitRate[i] = 0;
13031 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13032 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13033 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13034 }
13035 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13036 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13037 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13038 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13039 }
13040
13041
13042 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13043 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13044 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13045 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13046 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13047 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13048 rcap->cipherSupported = 0;
13049 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13050 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13051
13052 return RETURN_OK;
13053}
13054
13055INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13056{
13057 INT status = 0, radioIndex = 0;
13058 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13059 int iter = 0;
13060 unsigned int j = 0;
13061 int max_num_radios;
13062 wifi_interface_name_idex_map_t *iface_info = NULL;
13063
13064 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13065
13066 memset(cap, 0, sizeof(wifi_hal_capability_t));
13067
13068 /* version */
13069 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13070 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13071
13072 /* number of radios platform property */
13073 wifi_getMaxRadioNumber(&max_num_radios);
13074 cap->wifi_prop.numRadios = max_num_radios;
13075
13076 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13077 {
13078 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13079 if (status != 0) {
13080 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13081 return RETURN_ERR;
13082 }
13083
13084 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13085 {
13086 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13087 {
13088 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13089 return RETURN_ERR;
13090 }
13091 iface_info = &cap->wifi_prop.interface_map[iter];
13092 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13093 iface_info->rdk_radio_index = radioIndex;
13094 memset(output, 0, sizeof(output));
13095 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13096 {
13097 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13098 }
13099 // TODO: bridge name
13100 // TODO: vlan id
13101 // TODO: primary
13102 iface_info->index = array_index_to_vap_index(radioIndex, j);
13103 memset(output, 0, sizeof(output));
13104 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13105 {
13106 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13107 }
13108 iter++;
13109 }
13110 }
13111
13112 cap->BandSteeringSupported = FALSE;
13113 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13114 return RETURN_OK;
13115}
13116
13117INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13118{
13119 struct params h_config={0};
13120 char config_file[64] = {0};
13121
13122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13123
13124 h_config.name = "okc";
13125 h_config.value = okc_enable?"1":"0";
13126
13127 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13128 wifi_hostapdWrite(config_file, &h_config, 1);
13129 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13130
13131 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13132 return RETURN_OK;
13133}
13134
13135INT wifi_setSAEMFP(int ap_index, BOOL enable)
13136{
13137 struct params h_config={0};
13138 char config_file[64] = {0};
13139 char buf[128] = {0};
13140
13141 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13142
13143 h_config.name = "sae_require_mfp";
13144 h_config.value = enable?"1":"0";
13145
13146 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13147 wifi_hostapdWrite(config_file, &h_config, 1);
13148 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13149
13150 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13151 return RETURN_OK;
13152}
13153
13154INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13155{
13156 struct params h_config={0};
13157 char config_file[64] = {0};
13158 char buf[128] = {0};
13159
13160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13161
13162 h_config.name = "sae_pwe";
13163 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13164 h_config.value = buf;
13165
13166 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13167 wifi_hostapdWrite(config_file, &h_config, 1);
13168 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13169
13170 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13171 return RETURN_OK;
13172}
13173
13174INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13175{
13176 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13177 struct params h_config={0};
13178 char config_file[64] = {0};
13179
13180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13181
13182 h_config.name = "wpa_disable_eapol_key_retries";
13183 h_config.value = disable_EAPOL_retries?"1":"0";
13184
13185 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13186 wifi_hostapdWrite(config_file, &h_config, 1);
13187 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13188
13189 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13190 return RETURN_OK;
13191}
13192
13193INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13194{
13195 char buf[128] = {0};
13196 char config_file[128] = {0};
13197 char password[64] = {0};
13198 char mfp[32] = {0};
13199 char wpa_mode[32] = {0};
13200 BOOL okc_enable = FALSE;
13201 BOOL sae_MFP = FALSE;
13202 BOOL disable_EAPOL_retries = TRUE;
13203 int sae_pwe = 0;
13204 struct params params = {0};
13205 wifi_band band = band_invalid;
13206
13207 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13208
13209 multiple_set = TRUE;
13210 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13211 if (security->mode == wifi_security_mode_none) {
13212 strcpy(wpa_mode, "None");
13213 } else if (security->mode == wifi_security_mode_wpa_personal)
13214 strcpy(wpa_mode, "WPA-Personal");
13215 else if (security->mode == wifi_security_mode_wpa2_personal)
13216 strcpy(wpa_mode, "WPA2-Personal");
13217 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13218 strcpy(wpa_mode, "WPA-WPA2-Personal");
13219 else if (security->mode == wifi_security_mode_wpa_enterprise)
13220 strcpy(wpa_mode, "WPA-Enterprise");
13221 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13222 strcpy(wpa_mode, "WPA2-Enterprise");
13223 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13224 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
13225 else if (security->mode == wifi_security_mode_wpa3_personal) {
13226 strcpy(wpa_mode, "WPA3-Personal");
13227 okc_enable = TRUE;
13228 sae_MFP = TRUE;
13229 sae_pwe = 2;
13230 disable_EAPOL_retries = FALSE;
13231 } else if (security->mode == wifi_security_mode_wpa3_transition) {
13232 strcpy(wpa_mode, "WPA3-Personal-Transition");
13233 okc_enable = TRUE;
13234 sae_MFP = TRUE;
13235 sae_pwe = 2;
13236 disable_EAPOL_retries = FALSE;
13237 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
13238 strcpy(wpa_mode, "WPA3-Enterprise");
13239 sae_MFP = TRUE;
13240 sae_pwe = 2;
13241 disable_EAPOL_retries = FALSE;
developer3086e2f2023-01-17 09:40:01 +080013242 } else if (security->mode == wifi_security_mode_owe) {
13243 strcpy(wpa_mode, "OWE");
13244 sae_MFP = TRUE;
13245 sae_pwe = 2;
13246 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013247 }
13248
13249 band = wifi_index_to_band(ap_index);
13250 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13251 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13252 return RETURN_ERR;
13253 }
13254
13255 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
13256 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
13257 wifi_setSAEMFP(ap_index, sae_MFP);
13258 wifi_setSAEpwe(ap_index, sae_pwe);
13259 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
13260
developer23e71282023-01-18 10:25:19 +080013261 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer72fb0bb2023-01-11 09:46:29 +080013262 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
13263 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
13264 password[63] = '\0';
13265 wifi_setApSecurityKeyPassphrase(ap_index, password);
13266 }
13267 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13268 params.name = "sae_password";
13269 params.value = security->u.key.key;
13270 wifi_hostapdWrite(config_file, &params, 1);
13271 }
13272 }
13273
13274 if (security->mode != wifi_security_mode_none) {
13275 memset(&params, 0, sizeof(params));
13276 params.name = "wpa_pairwise";
13277 if (security->encr == wifi_encryption_tkip)
13278 params.value = "TKIP";
13279 else if (security->encr == wifi_encryption_aes)
13280 params.value = "CCMP";
13281 else if (security->encr == wifi_encryption_aes_tkip)
13282 params.value = "TKIP CCMP";
13283 wifi_hostapdWrite(config_file, &params, 1);
13284 }
13285
13286 if (security->mfp == wifi_mfp_cfg_disabled)
13287 strcpy(mfp, "Disabled");
13288 else if (security->mfp == wifi_mfp_cfg_optional)
13289 strcpy(mfp, "Optional");
13290 else if (security->mfp == wifi_mfp_cfg_required)
13291 strcpy(mfp, "Required");
13292 wifi_setApSecurityMFPConfig(ap_index, mfp);
13293
13294 memset(&params, 0, sizeof(params));
13295 params.name = "transition_disable";
13296 if (security->wpa3_transition_disable == TRUE)
13297 params.value = "0x01";
13298 else
13299 params.value = "0x00";
13300 wifi_hostapdWrite(config_file, &params, 1);
13301
13302 memset(&params, 0, sizeof(params));
13303 params.name = "wpa_group_rekey";
13304 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13305 params.value = buf;
13306 wifi_hostapdWrite(config_file, &params, 1);
13307
13308 memset(&params, 0, sizeof(params));
13309 params.name = "wpa_strict_rekey";
13310 params.value = security->strict_rekey?"1":"0";
13311 wifi_hostapdWrite(config_file, &params, 1);
13312
13313 memset(&params, 0, sizeof(params));
13314 params.name = "wpa_pairwise_update_count";
13315 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13316 params.value = buf;
13317 wifi_hostapdWrite(config_file, &params, 1);
13318
13319 memset(&params, 0, sizeof(params));
13320 params.name = "disable_pmksa_caching";
13321 params.value = security->disable_pmksa_caching?"1":"0";
13322 wifi_hostapdWrite(config_file, &params, 1);
13323
developer23e71282023-01-18 10:25:19 +080013324 if (multiple_set == FALSE) {
13325 wifi_setApEnable(ap_index, FALSE);
13326 wifi_setApEnable(ap_index, TRUE);
13327 }
developer72fb0bb2023-01-11 09:46:29 +080013328
13329 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13330
13331 return RETURN_OK;
13332}
13333
13334INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13335{
13336 char buf[256] = {0};
13337 char config_file[128] = {0};
13338 int disable = 0;
13339 // struct params params = {0};
13340
13341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13342 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13343 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13344 security->mode = wifi_security_mode_none;
13345 if (strlen(buf) != 0) {
13346 if (!strcmp(buf, "WPA-Personal"))
13347 security->mode = wifi_security_mode_wpa_personal;
13348 else if (!strcmp(buf, "WPA2-Personal"))
13349 security->mode = wifi_security_mode_wpa2_personal;
13350 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13351 security->mode = wifi_security_mode_wpa_wpa2_personal;
13352 else if (!strcmp(buf, "WPA-Enterprise"))
13353 security->mode = wifi_security_mode_wpa_enterprise;
13354 else if (!strcmp(buf, "WPA2-Enterprise"))
13355 security->mode = wifi_security_mode_wpa2_enterprise;
13356 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13357 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13358 else if (!strcmp(buf, "WPA3-Personal"))
13359 security->mode = wifi_security_mode_wpa3_personal;
13360 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13361 security->mode = wifi_security_mode_wpa3_transition;
13362 else if (!strcmp(buf, "WPA3-Enterprise"))
13363 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013364 else if (!strcmp(buf, "OWE"))
13365 security->mode = wifi_security_mode_owe;
developer72fb0bb2023-01-11 09:46:29 +080013366 }
13367
13368 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13369 if (security->mode == wifi_security_mode_none)
13370 security->encr = wifi_encryption_none;
13371 else {
13372 if (strcmp(buf, "TKIP") == 0)
13373 security->encr = wifi_encryption_tkip;
13374 else if (strcmp(buf, "CCMP") == 0)
13375 security->encr = wifi_encryption_aes;
13376 else
13377 security->encr = wifi_encryption_aes_tkip;
13378 }
13379
13380 if (security->mode != wifi_encryption_none) {
13381 memset(buf, 0, sizeof(buf));
13382 // wpa3 can use one or both configs as password, so we check sae_password first.
13383 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13384 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13385 security->u.key.type = wifi_security_key_type_sae;
13386 } else {
13387 security->u.key.type = wifi_security_key_type_psk;
13388 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13389 }
13390 strncpy(security->u.key.key, buf, sizeof(buf));
13391 security->u.key.key[255] = '\0';
13392 }
13393
13394 memset(buf, 0, sizeof(buf));
13395 wifi_getApSecurityMFPConfig(ap_index, buf);
13396 if (strcmp(buf, "Disabled") == 0)
13397 security->mfp = wifi_mfp_cfg_disabled;
13398 else if (strcmp(buf, "Optional") == 0)
13399 security->mfp = wifi_mfp_cfg_optional;
13400 else if (strcmp(buf, "Required") == 0)
13401 security->mfp = wifi_mfp_cfg_required;
13402
13403 memset(buf, 0, sizeof(buf));
13404 security->wpa3_transition_disable = FALSE;
13405 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13406 disable = strtol(buf, NULL, 16);
13407 if (disable != 0)
13408 security->wpa3_transition_disable = TRUE;
13409
13410 memset(buf, 0, sizeof(buf));
13411 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13412 if (strlen(buf) == 0)
13413 security->rekey_interval = 86400;
13414 else
13415 security->rekey_interval = strtol(buf, NULL, 10);
13416
13417 memset(buf, 0, sizeof(buf));
13418 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13419 if (strlen(buf) == 0)
13420 security->strict_rekey = 1;
13421 else
13422 security->strict_rekey = strtol(buf, NULL, 10);
13423
13424 memset(buf, 0, sizeof(buf));
13425 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13426 if (strlen(buf) == 0)
13427 security->eapol_key_retries = 4;
13428 else
13429 security->eapol_key_retries = strtol(buf, NULL, 10);
13430
13431 memset(buf, 0, sizeof(buf));
13432 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13433 if (strlen(buf) == 0)
13434 security->disable_pmksa_caching = FALSE;
13435 else
13436 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13437
13438 /* TODO
13439 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13440 */
13441 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13442 security->eap_identity_req_timeout = 0;
13443 security->eap_identity_req_retries = 0;
13444 security->eap_req_timeout = 0;
13445 security->eap_req_retries = 0;
13446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13447 return RETURN_OK;
13448}
13449
13450#endif /* WIFI_HAL_VERSION_3 */
13451
13452#ifdef WIFI_HAL_VERSION_3_PHASE2
13453INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13454{
13455 char interface_name[16] = {0};
13456 char cmd[128] = {0};
13457 char buf[128] = {0};
13458 char *mac_addr = NULL;
13459 BOOL status = FALSE;
13460 size_t len = 0;
13461
13462 if(ap_index > MAX_APS)
13463 return RETURN_ERR;
13464
13465 *output_numDevices = 0;
13466 wifi_getApEnable(ap_index, &status);
13467 if (status == FALSE)
13468 return RETURN_OK;
13469
13470 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13471 return RETURN_ERR;
13472 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13473 _syscmd(cmd, buf, sizeof(buf));
13474
13475 mac_addr = strtok(buf, "\n");
13476 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13477 *output_numDevices = i + 1;
13478 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13479 addr_ptr = output_deviceMacAddressArray[i];
13480 mac_addr_aton(addr_ptr, mac_addr);
13481 mac_addr = strtok(NULL, "\n");
13482 }
13483
13484 return RETURN_OK;
13485}
13486#else
13487INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13488{
13489 char interface_name[16] = {0};
13490 char cmd[128];
13491 BOOL status = false;
13492
13493 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13494 return RETURN_ERR;
13495
13496 output_buf[0] = '\0';
13497
13498 wifi_getApEnable(ap_index,&status);
13499 if (!status)
13500 return RETURN_OK;
13501
13502 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13503 return RETURN_ERR;
13504 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13505 _syscmd(cmd, output_buf, output_buf_size);
13506
13507 return RETURN_OK;
13508}
13509#endif
13510
13511INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13512{
13513 char output[16]={'\0'};
13514 char config_file[MAX_BUF_SIZE] = {0};
13515
13516 if (!enable)
13517 return RETURN_ERR;
13518
13519 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13520 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13521
13522 if (strlen(output) == 0)
13523 *enable = FALSE;
13524 else if (strncmp(output, "1", 1) == 0)
13525 *enable = TRUE;
13526 else
13527 *enable = FALSE;
13528
13529 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13530 return RETURN_OK;
13531}
13532
13533INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13534{
13535 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13536 return RETURN_ERR;
13537 *output_enable=TRUE;
13538 return RETURN_OK;
13539}
13540
13541INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13542{
13543 char cmd[128] = {0};
13544 char buf[128] = {0};
13545 char line[128] = {0};
13546 size_t len = 0;
13547 FILE *f = NULL;
13548 int index = 0;
13549 int exp = 0;
13550 int mantissa = 0;
13551 int duration = 0;
13552 int radio_index = 0;
13553 int max_radio_num = 0;
13554 uint twt_wake_interval = 0;
13555 int phyId = 0;
13556 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13557
13558 wifi_getMaxRadioNumber(&max_radio_num);
13559
13560 radio_index = ap_index % max_radio_num;
13561
13562 phyId = radio_index_to_phy(radio_index);
13563 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13564 _syscmd(cmd, buf, sizeof(buf));
13565 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13566 if (*numSessionReturned > maxNumberSessions)
13567 *numSessionReturned = maxNumberSessions;
13568 else if (*numSessionReturned < 1) {
13569 *numSessionReturned = 0;
13570 return RETURN_OK;
13571 }
13572
13573 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13574 if ((f = popen(cmd, "r")) == NULL) {
13575 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13576 return RETURN_ERR;
13577 }
13578
13579 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13580 while((fgets(line, sizeof(line), f)) != NULL) {
13581 char *tmp = NULL;
13582 strcpy(buf, line);
13583 tmp = strtok(buf, " ");
13584 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13585 tmp = strtok(NULL, " ");
13586 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13587 tmp = strtok(NULL, " ");
13588 if (strstr(tmp, "t")) {
13589 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13590 }
13591 if (strstr(tmp, "a")) {
13592 twtSessions[index].twtParameters.operation.announced = TRUE;
13593 }
13594 tmp = strtok(NULL, " ");
13595 exp = strtol(tmp, NULL, 10);
13596 tmp = strtok(NULL, " ");
13597 mantissa = strtol(tmp, NULL, 10);
13598 tmp = strtok(NULL, " ");
13599 duration = strtol(tmp, NULL, 10);
13600
13601 // only implicit supported
13602 twtSessions[index].twtParameters.operation.implicit = TRUE;
13603 // only individual agreement supported
13604 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13605
13606 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13607 twt_wake_interval = mantissa * (1 << exp);
13608 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13609 // Overflow handling
13610 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13611 } else {
13612 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13613 }
13614 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13615 index++;
13616 }
13617
13618 pclose(f);
13619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13620 return RETURN_OK;
13621}