blob: 876d06ff3a52dead88241085f847e23c4b0bf4e6 [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];;
developer745f0bd2023-03-06 14:32:53 +0800272int radio_band[MAX_NUM_RADIOS];
developer17038e62023-03-02 14:43:43 +0800273
274static int array_index_to_vap_index(UINT radioIndex, int arrayIndex);
275static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex);
276
developer96b38512023-02-22 11:17:45 +0800277
278static int
279get_value(const char *conf_file, const char *param, char *value, int len)
280{
281 FILE *fp;
282 int ret = -1;
283 int param_len = strlen(param);
284 int buf_len;
285 char buf[256];
286
287 fp = fopen(conf_file, "r");
288 if (!fp) {
289 return -1;
290 }
291
292 while (fgets(buf, sizeof(buf), fp)) {
293 buf_len = strlen(buf);
294 if (buf[buf_len - 1] == '\n') {
295 buf_len--;
296 buf[buf_len] = '\0';
297 }
298 if ((buf_len > param_len) &&
299 (strncmp(buf, param, param_len) == 0) &&
300 (buf[param_len] == '=')) {
301
302 if (buf_len == (param_len + 1)) {
303 value[0] = '\0';
304 ret = 0;
305 } else {
306 ret = snprintf(value, len, "%s", buf + (param_len + 1));
307 }
308 fclose(fp);
309 return ret;
310 }
311 }
312 fclose(fp);
313 return -1;
314}
315
316static int
317get_value_by_idx(const char *conf_file, const char *param, int idx, char *value, int len)
318{
319 char buf[256];
320 int ret;
321 char *save_ptr = NULL;
322 char *tok = NULL;
323
324 ret = get_value(conf_file, param, buf, sizeof(buf));
325 if (ret < 0)
326 return ret;
327
328 tok = strtok_r(buf, ";", &save_ptr);
329 do {
330 if (idx == 0 || tok == NULL)
331 break;
332 else
333 idx--;
334
335 tok = strtok_r(NULL, ";", &save_ptr);
336 } while (tok != NULL);
337
338 if (tok) {
339 ret = snprintf(value, len, "%s", tok);
340 } else {
341 ret = 0;
342 value[0] = '\0';
343 }
344
345 return ret;
346}
347
348
developer72fb0bb2023-01-11 09:46:29 +0800349#ifdef HAL_NETLINK_IMPL
350typedef struct {
351 int id;
352 struct nl_sock* socket;
353 struct nl_cb* cb;
354} Netlink;
355
356static int mac_addr_aton(unsigned char *mac_addr, char *arg)
357{
358 unsigned int mac_addr_int[6]={};
359 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);
360 mac_addr[0] = mac_addr_int[0];
361 mac_addr[1] = mac_addr_int[1];
362 mac_addr[2] = mac_addr_int[2];
363 mac_addr[3] = mac_addr_int[3];
364 mac_addr[4] = mac_addr_int[4];
365 mac_addr[5] = mac_addr_int[5];
366 return 0;
367}
368
369static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
370{
371 unsigned int mac_addr_int[6]={};
372 mac_addr_int[0] = arg[0];
373 mac_addr_int[1] = arg[1];
374 mac_addr_int[2] = arg[2];
375 mac_addr_int[3] = arg[3];
376 mac_addr_int[4] = arg[4];
377 mac_addr_int[5] = arg[5];
378 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]);
379 return;
380}
381
382static int ieee80211_frequency_to_channel(int freq)
383{
384 /* see 802.11-2007 17.3.8.3.2 and Annex J */
385 if (freq == 2484)
386 return 14;
387 /* see 802.11ax D6.1 27.3.23.2 and Annex E */
388 else if (freq == 5935)
389 return 2;
390 else if (freq < 2484)
391 return (freq - 2407) / 5;
392 else if (freq >= 4910 && freq <= 4980)
393 return (freq - 4000) / 5;
394 else if (freq < 5950)
395 return (freq - 5000) / 5;
396 else if (freq <= 45000) /* DMG band lower limit */
397 /* see 802.11ax D6.1 27.3.23.2 */
398 return (freq - 5950) / 5;
399 else if (freq >= 58320 && freq <= 70200)
400 return (freq - 56160) / 2160;
401 else
402 return 0;
403}
404
405static int initSock80211(Netlink* nl) {
406 nl->socket = nl_socket_alloc();
407 if (!nl->socket) {
408 fprintf(stderr, "Failing to allocate the sock\n");
409 return -ENOMEM;
410 }
411
412 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
413
414 if (genl_connect(nl->socket)) {
415 fprintf(stderr, "Failed to connect\n");
416 nl_close(nl->socket);
417 nl_socket_free(nl->socket);
418 return -ENOLINK;
419 }
420
421 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
422 if (nl->id< 0) {
423 fprintf(stderr, "interface not found.\n");
424 nl_close(nl->socket);
425 nl_socket_free(nl->socket);
426 return -ENOENT;
427 }
428
429 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
430 if ((!nl->cb)) {
431 fprintf(stderr, "Failed to allocate netlink callback.\n");
432 nl_close(nl->socket);
433 nl_socket_free(nl->socket);
434 return ENOMEM;
435 }
436
437 return nl->id;
438}
439
440static int nlfree(Netlink *nl)
441{
442 nl_cb_put(nl->cb);
443 nl_close(nl->socket);
444 nl_socket_free(nl->socket);
445 return 0;
446}
447
448static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
449 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
450 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
451 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
452};
453
454static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
455};
456
457static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
458};
459
460typedef struct _wifi_channelStats_loc {
461 INT array_size;
462 INT ch_number;
463 BOOL ch_in_pool;
464 INT ch_noise;
465 BOOL ch_radar_noise;
466 INT ch_max_80211_rssi;
467 INT ch_non_80211_noise;
468 INT ch_utilization;
469 ULLONG ch_utilization_total;
470 ULLONG ch_utilization_busy;
471 ULLONG ch_utilization_busy_tx;
472 ULLONG ch_utilization_busy_rx;
473 ULLONG ch_utilization_busy_self;
474 ULLONG ch_utilization_busy_ext;
475} wifi_channelStats_t_loc;
476
477typedef struct wifi_device_info {
478 INT wifi_devIndex;
479 UCHAR wifi_devMacAddress[6];
480 CHAR wifi_devIPAddress[64];
481 BOOL wifi_devAssociatedDeviceAuthentiationState;
482 INT wifi_devSignalStrength;
483 INT wifi_devTxRate;
484 INT wifi_devRxRate;
485} wifi_device_info_t;
486
487#endif
488
489//For 5g Alias Interfaces
490static BOOL priv_flag = TRUE;
491static BOOL pub_flag = TRUE;
492static BOOL Radio_flag = TRUE;
493//wifi_setApBeaconRate(1, beaconRate);
494
495BOOL multiple_set = FALSE;
496
497struct params
498{
499 char * name;
500 char * value;
501};
502
503static int _syscmd(char *cmd, char *retBuf, int retBufSize)
504{
505 FILE *f;
506 char *ptr = retBuf;
507 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
508
509 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
510 if((f = popen(cmd, "r")) == NULL) {
511 fprintf(stderr,"\npopen %s error\n", cmd);
512 return RETURN_ERR;
513 }
514
515 while(!feof(f))
516 {
517 *ptr = 0;
518 if(bufSize>=128) {
519 bufbytes=128;
520 } else {
521 bufbytes=bufSize-1;
522 }
523
524 fgets(ptr,bufbytes,f);
525 readbytes=strlen(ptr);
526
527 if(!readbytes)
528 break;
529
530 bufSize-=readbytes;
531 ptr += readbytes;
532 }
533 cmd_ret = pclose(f);
534 retBuf[retBufSize-1]=0;
535 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
536
537 return cmd_ret >> 8;
538}
539
540INT radio_index_to_phy(int radioIndex)
541{
developer17038e62023-03-02 14:43:43 +0800542 /* TODO */
543 return radioIndex;
developer72fb0bb2023-01-11 09:46:29 +0800544}
545
546INT wifi_getMaxRadioNumber(INT *max_radio_num)
547{
548 char cmd[64] = {0};
549 char buf[4] = {0};
550
551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
552
553 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
554 _syscmd(cmd, buf, sizeof(buf));
555 *max_radio_num = strtoul(buf, NULL, 10) > MAX_NUM_RADIOS ? MAX_NUM_RADIOS:strtoul(buf, NULL, 10);
556
557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
558
559 return RETURN_OK;
560}
561
developer17038e62023-03-02 14:43:43 +0800562wifi_band radio_index_to_band(int radioIndex)
563{
developer745f0bd2023-03-06 14:32:53 +0800564 return radio_band[radioIndex];
developer17038e62023-03-02 14:43:43 +0800565}
566
developer72fb0bb2023-01-11 09:46:29 +0800567wifi_band wifi_index_to_band(int apIndex)
568{
569 char cmd[128] = {0};
570 char buf[64] = {0};
571 int nl80211_band = 0;
572 int i = 0;
573 int phyIndex = 0;
574 int radioIndex = 0;
575 int max_radio_num = 0;
576 wifi_band band = band_invalid;
577
578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
579
580 wifi_getMaxRadioNumber(&max_radio_num);
581 radioIndex = apIndex % max_radio_num;
582 phyIndex = radio_index_to_phy(radioIndex);
583 while(i < 10){
584 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Band .:' | tail -n 1 | tr -d ':\\n' | awk '{print $2}'", phyIndex);
585 _syscmd(cmd, buf, sizeof(buf));
586 nl80211_band = strtol(buf, NULL, 10);
587 if (nl80211_band == 1)
588 band = band_2_4;
589 else if (nl80211_band == 2)
590 band = band_5;
591 else if (nl80211_band == 4) // band == 3 is 60GHz
592 band = band_6;
593
594 if(band != band_invalid)
595 break;
developer69b61b02023-03-07 17:17:44 +0800596
developer72fb0bb2023-01-11 09:46:29 +0800597 i++;
598 sleep(1);
599 }
600
601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
602 return band;
603}
604
605static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
606{
607 char cmd[MAX_CMD_SIZE]={'\0'};
608 char buf[MAX_BUF_SIZE]={'\0'};
609 int ret = 0;
610
611 sprintf(cmd, "cat %s 2> /dev/null | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
612 ret = _syscmd(cmd, buf, sizeof(buf));
613 if ((ret != 0) && (strlen(buf) == 0))
614 return -1;
615 snprintf(output, output_size, "%s", buf);
616
617 return 0;
618}
619
620static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
621{
622 char cmd[MAX_CMD_SIZE]={'\0'};
623 char buf[MAX_BUF_SIZE]={'\0'};
624
625 for(int i=0;i<item_count;i++)
626 {
627 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
628 if (strlen(buf) == 0) //Insert
629 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
630 else //Update
631 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
developer69b61b02023-03-07 17:17:44 +0800632
developer72fb0bb2023-01-11 09:46:29 +0800633 if(_syscmd(cmd, buf, sizeof(buf)))
634 return -1;
635 }
636
637 return 0;
638}
639
640//For Getting Current Interface Name from corresponding hostapd configuration
641static int wifi_GetInterfaceName(int apIndex, char *interface_name)
642{
643 char config_file[128] = {0};
644
645 if (interface_name == NULL)
646 return RETURN_ERR;
647
648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
649
650 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
651 wifi_hostapdRead(config_file, "interface", interface_name, 16);
652 if (strlen(interface_name) == 0)
653 return RETURN_ERR;
654
655 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
656 return RETURN_OK;
657}
658
developer72fb0bb2023-01-11 09:46:29 +0800659
660static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
661{
662 char interface_name[16] = {0};
663 if (multiple_set == TRUE)
664 return RETURN_OK;
665 char cmd[MAX_CMD_SIZE]="", output[32]="";
666 FILE *fp;
667 int i;
668 //NOTE RELOAD should be done in ApplySSIDSettings
669 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
670 return RETURN_ERR;
671 for(i=0; i<item_count; i++, list++)
672 {
673 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s SET %s %s", interface_name, list->name, list->value);
674 if((fp = popen(cmd, "r"))==NULL)
675 {
676 perror("popen failed");
677 return -1;
678 }
679 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
680 {
681 pclose(fp);
682 perror("fgets failed");
683 return -1;
684 }
685 pclose(fp);
686 }
687 return 0;
688}
689
690static int wifi_reloadAp(int apIndex)
691{
692 char interface_name[16] = {0};
693 if (multiple_set == TRUE)
694 return RETURN_OK;
695 char cmd[MAX_CMD_SIZE]="";
696 char buf[MAX_BUF_SIZE]="";
697
698 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
699 return RETURN_ERR;
700 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s reload", interface_name);
701 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
702 return RETURN_ERR;
703
704 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s disable", interface_name);
705 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
706 return RETURN_ERR;
707
708 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s enable", interface_name);
709 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
710 return RETURN_ERR;
711
712 return RETURN_OK;
713}
714
715INT File_Reading(CHAR *file, char *Value)
716{
717 FILE *fp = NULL;
718 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
719 int count = 0;
720
721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
722 fp = popen(file,"r");
723 if(fp == NULL)
724 return RETURN_ERR;
725
726 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
727 {
728 for(count=0;buf[count]!='\n';count++)
729 copy_buf[count]=buf[count];
730 copy_buf[count]='\0';
731 }
732 strcpy(Value,copy_buf);
733 pclose(fp);
734 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
735
736 return RETURN_OK;
737}
738
739void wifi_RestartHostapd_2G()
740{
741 int Public2GApIndex = 4;
742
743 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
744 wifi_setApEnable(Public2GApIndex, FALSE);
745 wifi_setApEnable(Public2GApIndex, TRUE);
746 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
747}
748
749void wifi_RestartHostapd_5G()
750{
751 int Public5GApIndex = 5;
752
753 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
754 wifi_setApEnable(Public5GApIndex, FALSE);
755 wifi_setApEnable(Public5GApIndex, TRUE);
756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
757}
758
759void wifi_RestartPrivateWifi_2G()
760{
761 int PrivateApIndex = 0;
762
763 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
764 wifi_setApEnable(PrivateApIndex, FALSE);
765 wifi_setApEnable(PrivateApIndex, TRUE);
766 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
767}
768
769void wifi_RestartPrivateWifi_5G()
770{
771 int Private5GApIndex = 1;
772
773 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
774 wifi_setApEnable(Private5GApIndex, FALSE);
775 wifi_setApEnable(Private5GApIndex, TRUE);
776 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
777}
778
779static int writeBandWidth(int radioIndex,char *bw_value)
780{
781 char buf[MAX_BUF_SIZE];
782 char cmd[MAX_CMD_SIZE];
783
784 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
785 if(_syscmd(cmd, buf, sizeof(buf)))
786 {
787 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
788 _syscmd(cmd, buf, sizeof(buf));
789 return RETURN_OK;
790 }
791
792 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
793 _syscmd(cmd,buf,sizeof(buf));
794 return RETURN_OK;
795}
796
797static int readBandWidth(int radioIndex,char *bw_value)
798{
799 char buf[MAX_BUF_SIZE] = {0};
800 char cmd[MAX_CMD_SIZE] = {0};
801 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
802 _syscmd(cmd,buf,sizeof(buf));
803 if(NULL!=strstr(buf,"20MHz"))
804 {
805 strcpy(bw_value,"20MHz");
806 }
807 else if(NULL!=strstr(buf,"40MHz"))
808 {
809 strcpy(bw_value,"40MHz");
810 }
811 else if(NULL!=strstr(buf,"80MHz"))
812 {
813 strcpy(bw_value,"80MHz");
814 }
815 else
816 {
817 return RETURN_ERR;
818 }
819 return RETURN_OK;
820}
821
822// Input could be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
823INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
824{
825 struct params params={'\0'};
826 char config_file[MAX_BUF_SIZE] = {0};
827 char buf[MAX_BUF_SIZE] = {'\0'};
828
829 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
830 // Copy the numeric value
831 if (strlen (beaconRate) >= 5) {
832 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
833 buf[strlen(beaconRate) - 4] = '\0';
834 } else if (strlen(beaconRate) > 0)
835 strcpy(buf, beaconRate);
836 else
837 return RETURN_ERR;
838
839 params.name = "beacon_rate";
840 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
841 if (strncmp(buf, "5.5", 3) == 0) {
842 snprintf(buf, sizeof(buf), "55");
843 params.value = buf;
844 } else {
845 strcat(buf, "0");
846 params.value = buf;
847 }
848
849 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
850 wifi_hostapdWrite(config_file, &params, 1);
851 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
853
854 return RETURN_OK;
855}
856
857INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
858{
859 char config_file[128] = {'\0'};
860 char temp_output[128] = {'\0'};
861 char buf[128] = {'\0'};
862 char cmd[128] = {'\0'};
863 int rate = 0;
864 int phyId = 0;
865
866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
867 if (NULL == beaconRate)
868 return RETURN_ERR;
869
870 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
871 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
872 phyId = radio_index_to_phy(radioIndex);
873 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
874 if(strlen(buf) > 0) {
875 if (strncmp(buf, "55", 2) == 0)
876 snprintf(temp_output, sizeof(temp_output), "5.5Mbps");
877 else {
878 rate = strtol(buf, NULL, 10)/10;
879 snprintf(temp_output, sizeof(temp_output), "%dMbps", rate);
880 }
881 } else {
882 // config not set, so we would use lowest rate as default
883 sprintf(cmd, "iw phy%d info | grep Bitrates -A1 | tail -n 1 | awk '{print $2}' | tr -d '.0\\n'", phyId);
884 _syscmd(cmd, buf, sizeof(buf));
885 snprintf(temp_output, sizeof(temp_output), "%sMbps", buf);
886 }
887 strncpy(beaconRate, temp_output, sizeof(temp_output));
888 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
889
890 return RETURN_OK;
891}
892
893INT wifi_setLED(INT radioIndex, BOOL enable)
894{
895 return 0;
896}
897INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
898{
899 return RETURN_OK;
900}
901/**********************************************************************************
902 *
developer69b61b02023-03-07 17:17:44 +0800903 * Wifi Subsystem level function prototypes
developer72fb0bb2023-01-11 09:46:29 +0800904 *
905**********************************************************************************/
906//---------------------------------------------------------------------------------------------------
907//Wifi system api
908//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
developer69b61b02023-03-07 17:17:44 +0800909INT wifi_getHalVersion(CHAR *output_string) //RDKB
developer72fb0bb2023-01-11 09:46:29 +0800910{
911 if(!output_string)
912 return RETURN_ERR;
913 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
914
915 return RETURN_OK;
916}
917
918
919/* wifi_factoryReset() function */
920/**
developer69b61b02023-03-07 17:17:44 +0800921* @description Clears internal variables to implement a factory reset of the Wi-Fi
developer72fb0bb2023-01-11 09:46:29 +0800922* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
923*
924* @param None
925*
926* @return The status of the operation.
927* @retval RETURN_OK if successful.
928* @retval RETURN_ERR if any error is detected
929*
930* @execution Synchronous
931* @sideeffect None
932*
933* @note This function must not suspend and must not invoke any blocking system
934* calls. It should probably just send a message to a driver event handler task.
935*
936*/
937INT wifi_factoryReset()
938{
939 char cmd[128];
940
941 /*delete running hostapd conf files*/
942 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
943 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
944 system(cmd);
945 system("systemctl restart hostapd.service");
946
947 return RETURN_OK;
948}
949
950/* wifi_factoryResetRadios() function */
951/**
952* @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.
953*
954* @param None
955* @return The status of the operation
956* @retval RETURN_OK if successful
957* @retval RETURN_ERR if any error is detected
958*
959* @execution Synchronous
960*
961* @sideeffect None
962*
963* @note This function must not suspend and must not invoke any blocking system
964* calls. It should probably just send a message to a driver event handler task.
965*
966*/
967INT wifi_factoryResetRadios()
968{
969 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
970 return RETURN_OK;
971
972 return RETURN_ERR;
973}
974
975
976/* wifi_factoryResetRadio() function */
977/**
978* @description Restore selected radio parameters without touching access point parameters
979*
980* @param radioIndex - Index of Wi-Fi Radio channel
981*
982* @return The status of the operation.
983* @retval RETURN_OK if successful.
984* @retval RETURN_ERR if any error is detected
985*
986* @execution Synchronous.
987* @sideeffect None.
988*
989* @note This function must not suspend and must not invoke any blocking system
990* calls. It should probably just send a message to a driver event handler task.
991*
992*/
993INT wifi_factoryResetRadio(int radioIndex) //RDKB
994{
995 system("systemctl stop hostapd.service");
996
997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
998 if(radioIndex == 0)
999 system("rm /nvram/hostapd0.conf");
1000 else if(radioIndex == 1)
1001 system("rm /nvram/hostapd1.conf");
1002 else
1003 return RETURN_ERR;
1004
1005 system("systemctl start hostapd.service");
1006 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1007 return RETURN_OK;
1008}
1009
1010/* wifi_initRadio() function */
1011/**
1012* Description: This function call initializes the specified radio.
developer69b61b02023-03-07 17:17:44 +08001013* Implementation specifics may dictate the functionality since
developer72fb0bb2023-01-11 09:46:29 +08001014* different hardware implementations may have different initilization requirements.
1015* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
1016*
1017* @return The status of the operation.
1018* @retval RETURN_OK if successful.
1019* @retval RETURN_ERR if any error is detected
1020*
1021* @execution Synchronous.
1022* @sideeffect None.
1023*
1024* @note This function must not suspend and must not invoke any blocking system
1025* calls. It should probably just send a message to a driver event handler task.
1026*
1027*/
1028INT wifi_initRadio(INT radioIndex)
1029{
1030 //TODO: Initializes the wifi subsystem (for specified radio)
1031 return RETURN_OK;
1032}
1033void macfilter_init()
1034{
1035 char count[4]={'\0'};
1036 char buf[253]={'\0'};
1037 char tmp[19]={'\0'};
1038 int dev_count,block,mac_entry=0;
1039 char res[4]={'\0'};
1040 char acl_file_path[64] = {'\0'};
1041 FILE *fp = NULL;
1042 int index=0;
1043 char iface[10]={'\0'};
1044 char config_file[MAX_BUF_SIZE] = {0};
1045
1046
1047 sprintf(acl_file_path,"/tmp/mac_filter.sh");
1048
1049 fp=fopen(acl_file_path,"w+");
1050 if (fp == NULL) {
1051 fprintf(stderr, "%s: failed to open file %s.\n", __func__, acl_file_path);
developer17038e62023-03-02 14:43:43 +08001052 return;
developer72fb0bb2023-01-11 09:46:29 +08001053 }
1054 sprintf(buf,"#!/bin/sh \n");
1055 fprintf(fp,"%s\n",buf);
1056
1057 system("chmod 0777 /tmp/mac_filter.sh");
1058
1059 for(index=0;index<=1;index++)
1060 {
1061 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
1062 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
1063 sprintf(buf,"syscfg get %dcountfilter",index);
1064 _syscmd(buf,count,sizeof(count));
1065 mac_entry=atoi(count);
1066
1067 sprintf(buf,"syscfg get %dblockall",index);
1068 _syscmd(buf,res,sizeof(res));
1069 block = atoi(res);
1070
1071 //Allow only those macs mentioned in ACL
1072 if(block==1)
1073 {
1074 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1075 fprintf(fp,"%s\n",buf);
1076 for(dev_count=1;dev_count<=mac_entry;dev_count++)
1077 {
1078 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
1079 _syscmd(buf,tmp,sizeof(tmp));
1080 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
1081 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
1082 fprintf(fp,"%s\n",buf);
1083 }
1084 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
1085 fprintf(fp,"%s\n",buf);
1086 }
1087
1088 //Block all the macs mentioned in ACL
1089 else if(block==2)
1090 {
1091 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
1092 fprintf(fp,"%s\n",buf);
1093
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 blocked *%s* ###########\n",tmp);
1099 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
1100 fprintf(fp,"%s\n",buf);
1101 }
1102 }
1103 }
1104 fclose(fp);
1105}
1106
developer17038e62023-03-02 14:43:43 +08001107
1108static void
1109wifi_ParseProfile(void)
1110{
1111 int i;
1112 int max_radio_num = 0;
1113 int card_idx;
1114 int band_idx;
1115 int phy_idx = 0;
developer745f0bd2023-03-06 14:32:53 +08001116 int wireless_mode = 0;
developer17038e62023-03-02 14:43:43 +08001117 char buf[MAX_BUF_SIZE] = {0};
1118 char chip_name[12];
1119 char card_profile[MAX_BUF_SIZE] = {0};
1120 char band_profile[MAX_BUF_SIZE] = {0};
1121 FILE* fp;
1122
1123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1124
1125 memset(main_prefix, 0, sizeof(main_prefix));
1126 memset(ext_prefix, 0, sizeof(ext_prefix));
1127 memset(default_ssid, 0, sizeof(default_ssid));
developer745f0bd2023-03-06 14:32:53 +08001128 for (i = 0; i < MAX_NUM_RADIOS; i++)
1129 radio_band[i] = band_invalid;
developer17038e62023-03-02 14:43:43 +08001130
1131 if (wifi_getMaxRadioNumber(&max_radio_num) != RETURN_OK) {
1132 /* LOG */
1133 return;
1134 }
1135
1136 for (card_idx = 0; card_idx < 3; card_idx++) {
1137 snprintf(buf, sizeof(buf), "INDEX%d", card_idx);
1138 if (get_value(l1profile, buf, chip_name, sizeof(chip_name)) < 0) {
1139 break;
1140 }
1141 snprintf(buf, sizeof(buf), "INDEX%d_profile_path", card_idx);
1142 if (get_value(l1profile, buf, card_profile, sizeof(card_profile)) < 0) {
1143 break;
1144 }
1145 for (band_idx = 0; band_idx < 3; band_idx++) {
1146 snprintf(buf, sizeof(buf), "BN%d_profile_path", band_idx);
1147 if (get_value(card_profile, buf, band_profile, sizeof(band_profile)) < 0) {
1148 /* LOG */
1149 break;
1150 }
1151
1152 snprintf(buf, sizeof(buf), "INDEX%d_main_ifname", card_idx);
1153 if (get_value_by_idx(l1profile, buf, band_idx, main_prefix[phy_idx], IFNAMSIZ) < 0) {
1154 /* LOG */
1155 }
1156
1157 snprintf(buf, sizeof(buf), "INDEX%d_ext_ifname", card_idx);
1158 if (get_value_by_idx(l1profile, buf, band_idx, ext_prefix[phy_idx], IFNAMSIZ) < 0) {
1159 /* LOG */
1160 }
1161
1162 if (get_value(band_profile, "SSID1", default_ssid[phy_idx], sizeof(default_ssid[phy_idx])) < 0) {
1163 /* LOG */
1164 }
developer745f0bd2023-03-06 14:32:53 +08001165 if (get_value(band_profile, "WirelessMode", buf, sizeof(buf)) < 0) {
1166 /* LOG */
1167 }
1168
1169 wireless_mode = atoi(buf);
1170 switch (wireless_mode) {
1171 case 22:
1172 case 16:
1173 case 6:
1174 case 4:
1175 case 1:
1176 radio_band[phy_idx] = band_2_4;
1177 break;
1178 case 23:
1179 case 17:
1180 case 14:
1181 case 11:
1182 case 2:
1183 radio_band[phy_idx] = band_5;
1184 break;
1185 case 24:
1186 case 18:
1187 radio_band[phy_idx] = band_6;
1188 break;
1189 }
developer17038e62023-03-02 14:43:43 +08001190 phy_idx++;
1191 }
1192 }
1193
1194 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1195}
1196
1197static void
1198wifi_PrepareDefaultHostapdConfigs(void)
1199{
developer0132ed92023-03-21 13:48:53 +08001200 int radio_idx;
1201 int bss_idx;
1202 int ap_idx;
1203 int band_idx;
1204 char buf[MAX_BUF_SIZE] = {0};
1205 char config_file[MAX_BUF_SIZE] = {0};
1206 char ssid[MAX_BUF_SIZE] = {0};
1207 char interface[32] = {0};
1208 char ret_buf[MAX_BUF_SIZE] = {0};
1209 char psk_file[64] = {0};
1210 struct params params[3];
developer17038e62023-03-02 14:43:43 +08001211
developer0132ed92023-03-21 13:48:53 +08001212 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1213 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1214 band_idx = radio_index_to_band(radio_idx);
1215 if (band_idx < 0) {
1216 break;
1217 }
1218 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1219 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1220
1221 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1222 snprintf(buf, sizeof(buf), "cp /etc/hostapd-%s.conf %s", wifi_band_str[band_idx], config_file);
1223 _syscmd(buf, ret_buf, sizeof(ret_buf));
developer17038e62023-03-02 14:43:43 +08001224
developer0132ed92023-03-21 13:48:53 +08001225 if (bss_idx == 0) {
1226 snprintf(ssid, sizeof(ssid), "%s", default_ssid[radio_idx]);
1227 snprintf(interface, sizeof(interface), "%s", main_prefix[radio_idx]);
1228 } else {
1229 snprintf(ssid, sizeof(ssid), "%s_%d", default_ssid[radio_idx], bss_idx);
1230 snprintf(interface, sizeof(interface), "%s%d", ext_prefix[radio_idx], bss_idx);
1231 }
developer17038e62023-03-02 14:43:43 +08001232
developer0132ed92023-03-21 13:48:53 +08001233 /* fix wpa_psk_file path */
1234 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", ap_idx);
developer17038e62023-03-02 14:43:43 +08001235
developer0132ed92023-03-21 13:48:53 +08001236 params[0].name = "ssid";
1237 params[0].value = ssid;
1238 params[1].name = "interface";
1239 params[1].value = interface;
1240 params[2].name = "wpa_psk_file";
1241 params[2].value = psk_file;
developer17038e62023-03-02 14:43:43 +08001242
developer0132ed92023-03-21 13:48:53 +08001243 wifi_hostapdWrite(config_file, params, 3);
1244 }
1245 }
1246 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001247}
1248
1249static void
1250wifiBringUpInterfacesForRadio(int radio_idx)
1251{
developer0132ed92023-03-21 13:48:53 +08001252 int bss_idx;
1253 int ap_idx;
1254 int band_idx;
1255 char cmd[MAX_CMD_SIZE] = {0};
1256 char config_file[MAX_BUF_SIZE] = {0};
1257 char ret_buf[MAX_BUF_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001258 char inf_name[IF_NAME_SIZE] = {0};
developer17038e62023-03-02 14:43:43 +08001259
1260 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer8a3bbbf2023-03-15 17:47:23 +08001261
developer0132ed92023-03-21 13:48:53 +08001262 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1263 ap_idx = array_index_to_vap_index(radio_idx, bss_idx);
1264
1265 snprintf(cmd, sizeof(cmd), "touch %s%d.psk", PSK_FILE, ap_idx);
1266 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1267
1268 memset(cmd, 0, MAX_CMD_SIZE);
1269 memset(ret_buf, 0, MAX_BUF_SIZE);
developer17038e62023-03-02 14:43:43 +08001270
developer0132ed92023-03-21 13:48:53 +08001271 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_idx);
1272 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radio_idx, config_file);
1273 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer8a3bbbf2023-03-15 17:47:23 +08001274
1275 wifi_GetInterfaceName(ap_idx, inf_name);
1276
1277 memset(cmd, 0, MAX_CMD_SIZE);
1278 memset(ret_buf, 0, MAX_BUF_SIZE);
1279
1280 /* fix vap-status file */
1281 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=1/\" %s", inf_name, inf_name, VAP_STATUS_FILE);
1282 _syscmd(cmd, ret_buf, sizeof(ret_buf));
developer0132ed92023-03-21 13:48:53 +08001283 }
1284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001285}
1286
1287static void
1288wifi_BringUpInterfaces(void)
1289{
1290 int radio_idx;
1291 int bss_idx;
1292 int ap_idx;
1293 int band_idx;
1294 char cmd[MAX_BUF_SIZE] = {0};
1295 char config_file[MAX_BUF_SIZE] = {0};
1296 char ret_buf[MAX_BUF_SIZE]={'\0'};
1297
1298 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1299 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1300 band_idx = radio_index_to_band(radio_idx);
1301 if (band_idx < 0) {
1302 break;
1303 }
1304 wifiBringUpInterfacesForRadio(radio_idx);
1305 }
1306 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1307}
1308
1309static void
1310wifi_BringDownInterfacesForRadio(int radio_idx)
1311{
1312 int bss_idx;
1313 int ap_idx;
1314 int band_idx;
1315 char cmd[MAX_BUF_SIZE] = {0};
1316 char config_file[MAX_BUF_SIZE] = {0};
1317 char ret_buf[MAX_BUF_SIZE]={'\0'};
1318
1319 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer17038e62023-03-02 14:43:43 +08001320
developer8a3bbbf2023-03-15 17:47:23 +08001321 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s", main_prefix[radio_idx]);
1322 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1323
1324
developer17038e62023-03-02 14:43:43 +08001325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1326}
1327
1328
1329static void
1330wifi_BringDownInterfaces(void)
1331{
1332 int radio_idx;
1333 int bss_idx;
1334 int ap_idx;
1335 int band_idx;
1336 char cmd[MAX_BUF_SIZE] = {0};
1337 char config_file[MAX_BUF_SIZE] = {0};
1338 char ret_buf[MAX_BUF_SIZE]={'\0'};
1339
1340 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1341 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++) {
1342 band_idx = radio_index_to_band(radio_idx);
1343 if (band_idx < 0) {
1344 break;
1345 }
1346 wifi_BringDownInterfacesForRadio(radio_idx);
1347 }
1348 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1349}
1350
developer8a3bbbf2023-03-15 17:47:23 +08001351static void wifi_vap_status_reset()
1352{
1353 char cmd[MAX_CMD_SIZE] = {0};
1354 char ret_buf[MAX_BUF_SIZE] = {0};
1355 char radio_idx = 0;
1356 char bss_idx = 0;
developer8666b312023-03-24 14:05:31 +08001357
developer8a3bbbf2023-03-15 17:47:23 +08001358 if (access(VAP_STATUS_FILE, F_OK) != 0) {
1359 snprintf(cmd, MAX_CMD_SIZE, "touch %s", VAP_STATUS_FILE);
1360 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1361 } else {
1362 snprintf(cmd, MAX_CMD_SIZE, "echo '' > %s", VAP_STATUS_FILE);
1363 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1364 }
1365
1366 memset(cmd, 0, MAX_CMD_SIZE);
1367 memset(ret_buf, 0, MAX_BUF_SIZE);
1368
1369 for (radio_idx = 0; radio_idx < MAX_NUM_RADIOS; radio_idx++)
1370 for (bss_idx = 0; bss_idx < 5; bss_idx++) {
1371 snprintf(cmd, MAX_CMD_SIZE, "echo %s%d=0 >> %s", ext_prefix[radio_idx], bss_idx, VAP_STATUS_FILE);
1372 _syscmd(cmd, ret_buf, sizeof(ret_buf));
1373 }
1374
1375}
developer17038e62023-03-02 14:43:43 +08001376
developer72fb0bb2023-01-11 09:46:29 +08001377// Initializes the wifi subsystem (all radios)
1378INT wifi_init() //RDKB
1379{
developer96b38512023-02-22 11:17:45 +08001380 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1381 //Not intitializing macfilter for Turris-Omnia Platform for now
1382 //macfilter_init();
developer17038e62023-03-02 14:43:43 +08001383 wifi_ParseProfile();
1384 wifi_PrepareDefaultHostapdConfigs();
1385 //system("/usr/sbin/iw reg set US");
1386 system("systemctl start hostapd.service");
1387 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001388
1389 wifi_vap_status_reset();
1390
developer17038e62023-03-02 14:43:43 +08001391 wifi_BringUpInterfaces();
developer96b38512023-02-22 11:17:45 +08001392
developer96b38512023-02-22 11:17:45 +08001393
1394 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer72fb0bb2023-01-11 09:46:29 +08001395
1396 return RETURN_OK;
1397}
1398
1399/* wifi_reset() function */
1400/**
1401* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
developer69b61b02023-03-07 17:17:44 +08001402* Implementation specifics may dictate what is actualy reset since
developer72fb0bb2023-01-11 09:46:29 +08001403* different hardware implementations may have different requirements.
1404* Parameters : None
1405*
1406* @return The status of the operation.
1407* @retval RETURN_OK if successful.
1408* @retval RETURN_ERR if any error is detected
1409*
1410* @execution Synchronous.
1411* @sideeffect None.
1412*
1413* @note This function must not suspend and must not invoke any blocking system
1414* calls. It should probably just send a message to a driver event handler task.
1415*
1416*/
1417INT wifi_reset()
1418{
developer17038e62023-03-02 14:43:43 +08001419
1420 wifi_BringDownInterfaces();
1421 sleep(2);
1422
developer96b38512023-02-22 11:17:45 +08001423 //TODO: resets the wifi subsystem, deletes all APs
1424 system("systemctl stop hostapd.service");
1425 sleep(2);
developer17038e62023-03-02 14:43:43 +08001426
developer96b38512023-02-22 11:17:45 +08001427 system("systemctl start hostapd.service");
1428 sleep(5);
developer17038e62023-03-02 14:43:43 +08001429
1430 wifi_PrepareDefaultHostapdConfigs();
1431 sleep(2);
developer8a3bbbf2023-03-15 17:47:23 +08001432
1433 wifi_vap_status_reset();
1434
developer17038e62023-03-02 14:43:43 +08001435 wifi_BringUpInterfaces();
1436
developer72fb0bb2023-01-11 09:46:29 +08001437 return RETURN_OK;
1438}
1439
1440/* wifi_down() function */
1441/**
1442* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
developer69b61b02023-03-07 17:17:44 +08001443* Implementation specifics may dictate some functionality since
developer72fb0bb2023-01-11 09:46:29 +08001444* different hardware implementations may have different requirements.
1445*
1446* @param None
1447*
1448* @return The status of the operation
1449* @retval RETURN_OK if successful
1450* @retval RETURN_ERR if any error is detected
1451*
1452* @execution Synchronous
1453* @sideeffect None
1454*
1455* @note This function must not suspend and must not invoke any blocking system
1456* calls. It should probably just send a message to a driver event handler task.
1457*
1458*/
1459INT wifi_down()
1460{
developer96b38512023-02-22 11:17:45 +08001461 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developer17038e62023-03-02 14:43:43 +08001462 wifi_BringDownInterfaces();
1463 sleep(2);
1464
developer96b38512023-02-22 11:17:45 +08001465 system("systemctl stop hostapd.service");
1466 sleep(2);
developer72fb0bb2023-01-11 09:46:29 +08001467 return RETURN_OK;
1468}
1469
1470
1471/* wifi_createInitialConfigFiles() function */
1472/**
1473* @description This function creates wifi configuration files. The format
developer69b61b02023-03-07 17:17:44 +08001474* and content of these files are implementation dependent. This function call is
1475* used to trigger this task if necessary. Some implementations may not need this
1476* function. If an implementation does not need to create config files the function call can
developer72fb0bb2023-01-11 09:46:29 +08001477* do nothing and return RETURN_OK.
1478*
1479* @param None
1480*
1481* @return The status of the operation
1482* @retval RETURN_OK if successful
1483* @retval RETURN_ERR if any error is detected
1484*
1485* @execution Synchronous
1486* @sideeffect None
1487*
1488* @note This function must not suspend and must not invoke any blocking system
1489* calls. It should probably just send a message to a driver event handler task.
1490*
1491*/
1492INT wifi_createInitialConfigFiles()
1493{
1494 //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)
1495 return RETURN_OK;
1496}
1497
1498// outputs the country code to a max 64 character string
1499INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1500{
1501 char interface_name[16] = {0};
1502 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1503 if(!output_string || (radioIndex >= MAX_NUM_RADIOS))
1504 return RETURN_ERR;
1505
1506 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1507 return RETURN_ERR;
1508 sprintf(cmd,"hostapd_cli -i %s status driver | grep country | cut -d '=' -f2", interface_name);
1509 _syscmd(cmd, buf, sizeof(buf));
1510 if(strlen(buf) > 0)
1511 snprintf(output_string, 64, "%s", buf);
1512 else
1513 return RETURN_ERR;
1514
1515 return RETURN_OK;
1516}
1517
1518INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1519{
1520 //Set wifi config. Wait for wifi reset to apply
1521 char str[MAX_BUF_SIZE]={'\0'};
1522 char cmd[MAX_CMD_SIZE]={'\0'};
1523 struct params params;
1524 char config_file[MAX_BUF_SIZE] = {0};
1525
1526 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1527 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1528 return RETURN_ERR;
1529
1530 if (strlen(CountryCode) == 0)
1531 strcpy(CountryCode, "US");
1532
1533 params.name = "country_code";
1534 params.value = CountryCode;
1535 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1536 int ret = wifi_hostapdWrite(config_file, &params, 1);
1537 if (ret) {
1538 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1539 ,__func__, ret);
1540 }
1541
1542 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1543 if (ret) {
1544 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1545 ,__func__, ret);
1546 }
1547 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1548
1549 return RETURN_OK;
1550}
1551
1552INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1553{
1554 char interface_name[16] = {0};
1555 char channel_util_file[64] = {0};
1556 char cmd[128] = {0};
1557 char buf[128] = {0};
1558 char line[128] = {0};
1559 char *param = NULL, *value = NULL;
1560 int read = 0;
1561 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1562 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1563 size_t len = 0;
1564 FILE *f = NULL;
1565
1566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1567
1568 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1569 return RETURN_ERR;
1570 snprintf(cmd, sizeof(cmd), "iw %s scan | grep signal | awk '{print $2}' | sort -n | tail -n1", interface_name);
1571 _syscmd(cmd, buf, sizeof(buf));
1572 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1573
1574 memset(cmd, 0, sizeof(cmd));
1575 memset(buf, 0, sizeof(buf));
1576 snprintf(cmd, sizeof(cmd), "iw %s survey dump | grep 'in use' -A6", interface_name);
1577 if ((f = popen(cmd, "r")) == NULL) {
1578 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1579 return RETURN_ERR;
1580 }
1581
1582 read = getline(&line, &len, f);
1583 while (read != -1) {
1584 param = strtok(line, ":\t");
1585 value = strtok(NULL, " ");
1586 if(strstr(param, "frequency") != NULL) {
1587 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1588 }
1589 if(strstr(param, "noise") != NULL) {
1590 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1591 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1592 }
1593 if(strstr(param, "channel active time") != NULL) {
1594 ActiveTime = strtol(value, NULL, 10);
1595 }
1596 if(strstr(param, "channel busy time") != NULL) {
1597 BusyTime = strtol(value, NULL, 10);
1598 }
1599 if(strstr(param, "channel transmit time") != NULL) {
1600 TransmitTime = strtol(value, NULL, 10);
1601 }
1602 read = getline(&line, &len, f);
1603 }
1604 pclose(f);
1605
1606 // The file should store the last active, busy and transmit time
1607 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1608 f = fopen(channel_util_file, "r");
1609 if (f != NULL) {
1610 read = getline(&line, &len, f);
1611 preActiveTime = strtol(line, NULL, 10);
1612 read = getline(&line, &len, f);
1613 preBusyTime = strtol(line, NULL, 10);
1614 read = getline(&line, &len, f);
1615 preTransmitTime = strtol(line, NULL, 10);
1616 fclose(f);
1617 }
1618
1619 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1620 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1621
1622 f = fopen(channel_util_file, "w");
1623 if (f != NULL) {
1624 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1625 fclose(f);
1626 }
1627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1628 return RETURN_OK;
1629}
1630
1631/**********************************************************************************
1632 *
1633 * Wifi radio level function prototypes
1634 *
1635**********************************************************************************/
1636
1637//Get the total number of radios in this wifi subsystem
1638INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1639{
1640 if (NULL == output)
1641 return RETURN_ERR;
1642 *output = MAX_NUM_RADIOS;
1643
1644 return RETURN_OK;
1645}
1646
developer69b61b02023-03-07 17:17:44 +08001647//Get the total number of SSID entries in this wifi subsystem
developer72fb0bb2023-01-11 09:46:29 +08001648INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1649{
1650 if (NULL == output)
1651 return RETURN_ERR;
1652 *output = MAX_APS;
1653
1654 return RETURN_OK;
1655}
1656
1657//Get the Radio enable config parameter
1658INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1659{
1660 char interface_name[16] = {0};
1661 char buf[128] = {0}, cmd[128] = {0};
1662
1663 if (NULL == output_bool)
1664 return RETURN_ERR;
1665
1666 *output_bool = FALSE;
1667 if (radioIndex >= MAX_NUM_RADIOS)// Target has two wifi radios
1668 return RETURN_ERR;
1669
1670 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
1671 return RETURN_ERR;
1672 sprintf(cmd, "hostapd_cli -i %s status | grep state | cut -d '=' -f2", interface_name);
1673 _syscmd(cmd, buf, sizeof(buf));
1674
1675 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1676 *output_bool = TRUE;
1677 return RETURN_OK;
1678}
1679
1680INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1681{
1682 char interface_name[16] = {0};
1683 char cmd[MAX_CMD_SIZE] = {0};
developer8a3bbbf2023-03-15 17:47:23 +08001684 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +08001685 int apIndex, ret;
developer69b61b02023-03-07 17:17:44 +08001686 int max_radio_num = 0;
developer72fb0bb2023-01-11 09:46:29 +08001687 int phyId = 0;
1688
1689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1690
1691 phyId = radio_index_to_phy(radioIndex);
1692
1693 wifi_getMaxRadioNumber(&max_radio_num);
1694
developer8a3bbbf2023-03-15 17:47:23 +08001695 if(enable == FALSE) {
1696 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s DISABLE", main_prefix[radioIndex]);
1697 _syscmd(cmd, buf, sizeof(buf));
1698 printf("ck_test: %s, cmd:%s\n", __func__, cmd);
developer72fb0bb2023-01-11 09:46:29 +08001699
developer8a3bbbf2023-03-15 17:47:23 +08001700 } else {
developer72fb0bb2023-01-11 09:46:29 +08001701
developer8a3bbbf2023-03-15 17:47:23 +08001702 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s ENABLE", main_prefix[radioIndex]);
1703 _syscmd(cmd, buf, sizeof(buf));
1704
1705 /*start from bss1 not main bss */
1706 for(apIndex = (radioIndex + max_radio_num); apIndex < MAX_APS; apIndex += max_radio_num) {
1707
developer72fb0bb2023-01-11 09:46:29 +08001708 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
1709 return RETURN_ERR;
1710
developer8a3bbbf2023-03-15 17:47:23 +08001711 memset(cmd, 0, MAX_CMD_SIZE);
1712 memset(buf, 0, MAX_BUF_SIZE);
1713
developer72fb0bb2023-01-11 09:46:29 +08001714 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
1715 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001716
1717 if(*buf == '1') {
1718
1719 memset(cmd, 0, MAX_CMD_SIZE);
1720 memset(buf, 0, MAX_BUF_SIZE);
1721
developer72fb0bb2023-01-11 09:46:29 +08001722 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1723 phyId, apIndex);
1724 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08001725
developer72fb0bb2023-01-11 09:46:29 +08001726 }
1727 }
1728 }
1729
1730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1731 return RETURN_OK;
1732}
1733
1734//Get the Radio enable status
1735INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1736{
1737 if (NULL == output_bool)
1738 return RETURN_ERR;
1739
1740 return wifi_getRadioEnable(radioIndex, output_bool);
1741}
1742
1743//Get the Radio Interface name from platform, eg "wlan0"
1744INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1745{
1746 if (NULL == output_string || radioIndex>=MAX_NUM_RADIOS || radioIndex<0)
1747 return RETURN_ERR;
1748 return wifi_GetInterfaceName(radioIndex, output_string);
1749}
1750
1751//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1752//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.
1753INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1754{
1755 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1756 // For max bit rate, we should always choose the best MCS
1757 char mode[64] = {0};
1758 char channel_bandwidth_str[64] = {0};
1759 char *tmp = NULL;
1760 UINT mode_map = 0;
1761 UINT num_subcarrier = 0;
1762 UINT code_bits = 0;
1763 float code_rate = 0; // use max code rate
1764 int NSS = 0;
1765 UINT Symbol_duration = 0;
developer69b61b02023-03-07 17:17:44 +08001766 UINT GI_duration = 0;
developer72fb0bb2023-01-11 09:46:29 +08001767 wifi_band band = band_invalid;
1768 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1769 BOOL enable = FALSE;
1770 float bit_rate = 0;
1771
1772 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1773 if (NULL == output_string)
1774 return RETURN_ERR;
1775
1776 wifi_getRadioEnable(radioIndex, &enable);
1777 if (enable == FALSE) {
1778 snprintf(output_string, 64, "0 Mb/s");
1779 return RETURN_OK;
1780 }
1781
1782 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1783 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1784 return RETURN_ERR;
1785 }
1786
1787 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1788 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1789 return RETURN_ERR;
1790 }
1791
1792 if (gi == wifi_guard_interval_3200)
1793 GI_duration = 32;
1794 else if (gi == wifi_guard_interval_1600)
1795 GI_duration = 16;
1796 else if (gi == wifi_guard_interval_800)
1797 GI_duration = 8;
1798 else // auto, 400
1799 GI_duration = 4;
1800
1801 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1802 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1803 return RETURN_ERR;
1804 }
1805
1806 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1807 strcpy(channel_bandwidth_str, "160");
1808
1809 if (mode_map & WIFI_MODE_AX) {
1810 if (strstr(channel_bandwidth_str, "160") != NULL)
1811 num_subcarrier = 1960;
1812 else if (strstr(channel_bandwidth_str, "80") != NULL)
1813 num_subcarrier = 980;
1814 else if (strstr(channel_bandwidth_str, "40") != NULL)
1815 num_subcarrier = 468;
1816 else if (strstr(channel_bandwidth_str, "20") != NULL)
1817 num_subcarrier = 234;
1818 code_bits = 10;
1819 code_rate = (float)5/6;
1820 Symbol_duration = 128;
1821 } else if (mode_map & WIFI_MODE_AC) {
1822 if (strstr(channel_bandwidth_str, "160") != NULL)
1823 num_subcarrier = 468;
1824 else if (strstr(channel_bandwidth_str, "80") != NULL)
1825 num_subcarrier = 234;
1826 else if (strstr(channel_bandwidth_str, "40") != NULL)
1827 num_subcarrier = 108;
1828 else if (strstr(channel_bandwidth_str, "20") != NULL)
1829 num_subcarrier = 52;
1830 code_bits = 8;
1831 code_rate = (float)5/6;
1832 Symbol_duration = 32;
1833 } else if (mode_map & WIFI_MODE_N) {
1834 if (strstr(channel_bandwidth_str, "160") != NULL)
1835 num_subcarrier = 468;
1836 else if (strstr(channel_bandwidth_str, "80") != NULL)
1837 num_subcarrier = 234;
1838 else if (strstr(channel_bandwidth_str, "40") != NULL)
1839 num_subcarrier = 108;
1840 else if (strstr(channel_bandwidth_str, "20") != NULL)
1841 num_subcarrier = 52;
1842 code_bits = 6;
1843 code_rate = (float)3/4;
1844 Symbol_duration = 32;
1845 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1846 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1847 snprintf(output_string, 64, "65 Mb/s");
1848 return RETURN_OK;
1849 } else {
1850 snprintf(output_string, 64, "0 Mb/s");
1851 return RETURN_OK;
1852 }
1853
1854 // Spatial streams
1855 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1856 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1857 return RETURN_ERR;
1858 }
1859
1860 // multiple 10 is to align duration unit (0.1 us)
1861 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1862 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1863
1864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1865
1866 return RETURN_OK;
1867}
1868#if 0
1869INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1870{
1871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1872 char cmd[64];
1873 char buf[1024];
1874 int apIndex;
1875
developer69b61b02023-03-07 17:17:44 +08001876 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08001877 return RETURN_ERR;
1878
1879 apIndex=(radioIndex==0)?0:1;
1880
1881 snprintf(cmd, sizeof(cmd), "iwconfig %s | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", interface_name);
1882 _syscmd(cmd,buf, sizeof(buf));
1883
1884 snprintf(output_string, 64, "%s", buf);
1885 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1886 return RETURN_OK;
1887}
1888#endif
1889
1890
1891//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1892//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.
1893INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1894{
1895 wifi_band band = band_invalid;
1896
1897 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1898 if (NULL == output_string)
1899 return RETURN_ERR;
1900
1901 band = wifi_index_to_band(radioIndex);
1902
1903 memset(output_string, 0, 10);
1904 if (band == band_2_4)
1905 strcpy(output_string, "2.4GHz");
1906 else if (band == band_5)
1907 strcpy(output_string, "5GHz");
1908 else if (band == band_6)
1909 strcpy(output_string, "6GHz");
1910 else
1911 return RETURN_ERR;
1912 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1913
1914 return RETURN_OK;
1915#if 0
1916 char buf[MAX_BUF_SIZE]={'\0'};
1917 char str[MAX_BUF_SIZE]={'\0'};
1918 char cmd[MAX_CMD_SIZE]={'\0'};
1919 char *ch=NULL;
1920 char *ch2=NULL;
1921
1922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1923 if (NULL == output_string)
1924 return RETURN_ERR;
1925
1926
1927 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1928
1929 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1930 {
1931 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1932 return RETURN_ERR;
1933 }
1934 ch=strchr(buf,'\n');
1935 *ch='\0';
1936 ch=strchr(buf,'=');
1937 if(ch==NULL)
1938 return RETURN_ERR;
1939
1940
1941 ch++;
1942
1943 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1944 strcpy(buf,"0");
1945 if(strlen(ch) == 1)
1946 ch=strcat(buf,ch);
1947
1948
1949 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1950
1951 if(_syscmd(cmd,str,64) == RETURN_ERR)
1952 {
1953 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1954 return RETURN_ERR;
1955 }
1956
1957
1958 ch2=strchr(str,'\n');
1959 //replace \n with \0
1960 *ch2='\0';
1961 ch2=strchr(str,'=');
1962 if(ch2==NULL)
1963 {
1964 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1965 return RETURN_ERR;
1966 }
1967 else
1968 wifi_dbg_printf("%s",ch2+1);
1969
1970
1971 ch2++;
1972
1973
1974 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1975
1976 memset(buf,'\0',sizeof(buf));
1977 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1978 {
1979 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1980 return RETURN_ERR;
1981 }
1982 if (strstr(buf,"2.4") != NULL )
1983 strcpy(output_string,"2.4GHz");
1984 else if(strstr(buf,"5.") != NULL )
1985 strcpy(output_string,"5GHz");
1986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1987
1988 return RETURN_OK;
1989#endif
1990}
1991
1992//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1993//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.
1994INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1995{
1996 wifi_band band = band_invalid;
1997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1998 if (NULL == output_string)
1999 return RETURN_ERR;
2000 band = wifi_index_to_band(radioIndex);
2001
developer69b61b02023-03-07 17:17:44 +08002002 if (band == band_2_4)
developer72fb0bb2023-01-11 09:46:29 +08002003 snprintf(output_string, 64, "2.4GHz");
2004 else if (band == band_5)
developer69b61b02023-03-07 17:17:44 +08002005 snprintf(output_string, 64, "5GHz");
developer72fb0bb2023-01-11 09:46:29 +08002006 else if (band == band_6)
2007 snprintf(output_string, 64, "6GHz");
2008
2009 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2010
2011 return RETURN_OK;
2012#if 0
2013 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2014 char buf[MAX_BUF_SIZE]={'\0'};
2015 char str[MAX_BUF_SIZE]={'\0'};
2016 char cmd[MAX_CMD_SIZE]={'\0'};
2017 char *ch=NULL;
2018 char *ch2=NULL;
2019 char ch1[5]="0";
2020
2021 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2022
2023 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
2024 {
2025 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2026 return RETURN_ERR;
2027 }
2028
2029 ch=strchr(buf,'\n');
2030 *ch='\0';
2031 ch=strchr(buf,'=');
2032 if(ch==NULL)
2033 return RETURN_ERR;
2034 ch++;
2035
2036 if(strlen(ch)==1)
2037 {
2038 strcat(ch1,ch);
2039
2040 }
2041 else
2042 {
2043 strcpy(ch1,ch);
2044 }
2045
2046
2047
2048 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
2049 if(_syscmd(cmd,str,64) == RETURN_ERR)
2050 {
2051 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2052 return RETURN_ERR;
2053 }
2054
2055
2056 ch2=strchr(str,'\n');
2057 //replace \n with \0
2058 *ch2='\0';
2059 ch2=strchr(str,'=');
2060 if(ch2==NULL)
2061 {
2062 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2063 return RETURN_ERR;
2064 }
2065 else
2066 wifi_dbg_printf("%s",ch2+1);
2067 ch2++;
2068
2069
2070 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
2071 memset(buf,'\0',sizeof(buf));
2072 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
2073 {
2074 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
2075 return RETURN_ERR;
2076 }
2077
2078
2079 if(strstr(buf,"2.4")!=NULL)
2080 {
2081 strcpy(output_string,"2.4GHz");
2082 }
2083 if(strstr(buf,"5.")!=NULL)
2084 {
2085 strcpy(output_string,"5GHz");
2086 }
2087 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2088 return RETURN_OK;
2089#endif
2090}
2091
2092//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
2093//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.
2094INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
2095{
2096 char cmd[128]={0};
2097 char buf[128]={0};
2098 char temp_output[128] = {0};
2099 wifi_band band;
2100 int phyId = 0;
2101
2102 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002103 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002104 return RETURN_ERR;
2105
2106 band = wifi_index_to_band(radioIndex);
2107 if (band == band_2_4) {
2108 strcat(temp_output, "b,g,");
2109 } else if (band == band_5) {
2110 strcat(temp_output, "a,");
2111 }
2112 phyId = radio_index_to_phy(radioIndex);
2113 // ht capabilities
2114 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);
2115 _syscmd(cmd, buf, sizeof(buf));
2116 if (strlen(buf) >= 4 && strncmp(buf, "0x00", 4) != 0) {
2117 strcat(temp_output, "n,");
2118 }
2119
2120 // vht capabilities
2121 if (band == band_5) {
2122 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", phyId);
2123 _syscmd(cmd, buf, sizeof(buf));
2124 if (strlen(buf) >= 10 && strncmp(buf, "0x00000000", 10) != 0) {
2125 strcat(temp_output, "ac,");
2126 }
2127 }
2128
2129 // he capabilities
2130 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);
2131 _syscmd(cmd, buf, sizeof(buf));
2132 if (strlen(buf) >= 6 && strncmp (buf, "0x0000", 6) != 0) {
2133 strcat(temp_output, "ax,");
2134 }
2135
2136 // Remove the last comma
2137 if (strlen(temp_output) != 0)
2138 temp_output[strlen(temp_output)-1] = '\0';
2139 strncpy(output_string, temp_output, strlen(temp_output));
2140 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2141 return RETURN_OK;
2142}
2143
2144//Get the radio operating mode, and pure mode flag. eg: "ac"
2145//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.
2146INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
2147{
2148 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2149 if (NULL == output_string)
2150 return RETURN_ERR;
2151
2152 if (radioIndex == 0) {
2153 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
2154 *gOnly = FALSE;
2155 *nOnly = TRUE;
2156 *acOnly = FALSE;
2157 } else {
2158 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
2159 *gOnly = FALSE;
2160 *nOnly = FALSE;
2161 *acOnly = FALSE;
2162 }
2163 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2164
2165 return RETURN_OK;
2166#if 0
2167 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2168 char buf[64] = {0};
2169 char config_file[MAX_BUF_SIZE] = {0};
2170
developer69b61b02023-03-07 17:17:44 +08002171 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
developer72fb0bb2023-01-11 09:46:29 +08002172 return RETURN_ERR;
2173
2174 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2175 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
2176
2177 wifi_dbg_printf("\nhw_mode=%s\n",buf);
developer69b61b02023-03-07 17:17:44 +08002178 if (strlen(buf) == 0)
developer72fb0bb2023-01-11 09:46:29 +08002179 {
2180 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
2181 return RETURN_ERR;
2182 }
2183 if(strcmp(buf,"g")==0)
2184 {
2185 wifi_dbg_printf("\nG\n");
2186 *gOnly=TRUE;
2187 *nOnly=FALSE;
2188 *acOnly=FALSE;
2189 }
2190 else if(strcmp(buf,"n")==0)
2191 {
2192 wifi_dbg_printf("\nN\n");
2193 *gOnly=FALSE;
2194 *nOnly=TRUE;
2195 *acOnly=FALSE;
2196 }
2197 else if(strcmp(buf,"ac")==0)
2198 {
2199 wifi_dbg_printf("\nac\n");
2200 *gOnly=FALSE;
2201 *nOnly=FALSE;
2202 *acOnly=TRUE;
2203 }
2204 /* hostapd-5G.conf has "a" as hw_mode */
2205 else if(strcmp(buf,"a")==0)
2206 {
2207 wifi_dbg_printf("\na\n");
2208 *gOnly=FALSE;
2209 *nOnly=FALSE;
2210 *acOnly=FALSE;
2211 }
2212 else
2213 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
2214
2215 //for a,n mode
2216 if(radioIndex == 1)
2217 {
2218 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
2219 if(strcmp(buf,"1")==0)
2220 {
2221 strncpy(output_string, "n", 1);
2222 *nOnly=FALSE;
2223 }
2224 }
2225
2226 wifi_dbg_printf("\nReturning from getRadioStandard\n");
2227 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2228 return RETURN_OK;
2229#endif
2230}
2231
2232INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
2233{
2234 char cmd[128] = {0};
2235 char buf[64] = {0};
2236 char config_file[64] = {0};
2237 wifi_band band;
2238
2239 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2240 if(NULL == output_string || NULL == pureMode)
2241 return RETURN_ERR;
2242
2243 // grep all of the ieee80211 protocol config set to 1
2244 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2245 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
2246 _syscmd(cmd, buf, sizeof(buf));
2247
2248 band = wifi_index_to_band(radioIndex);
2249 // puremode is a bit map
2250 *pureMode = 0;
2251 if (band == band_2_4) {
2252 strcat(output_string, "b,g");
2253 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
2254 if (strstr(buf, "n") != NULL) {
2255 strcat(output_string, ",n");
2256 *pureMode |= WIFI_MODE_N;
2257 }
2258 if (strstr(buf, "ax") != NULL) {
2259 strcat(output_string, ",ax");
2260 *pureMode |= WIFI_MODE_AX;
2261 }
2262 } else if (band == band_5) {
2263 strcat(output_string, "a");
2264 *pureMode |= WIFI_MODE_A;
2265 if (strstr(buf, "n") != NULL) {
2266 strcat(output_string, ",n");
2267 *pureMode |= WIFI_MODE_N;
2268 }
2269 if (strstr(buf, "ac") != NULL) {
2270 strcat(output_string, ",ac");
2271 *pureMode |= WIFI_MODE_AC;
2272 }
2273 if (strstr(buf, "ax") != NULL) {
2274 strcat(output_string, ",ax");
2275 *pureMode |= WIFI_MODE_AX;
2276 }
2277 } else if (band == band_6) {
2278 if (strstr(buf, "ax") != NULL) {
2279 strcat(output_string, "ax");
2280 *pureMode |= WIFI_MODE_AX;
2281 }
2282 }
2283
2284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2285 return RETURN_OK;
2286}
2287
2288// Set the radio operating mode, and pure mode flag.
2289INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
2290{
developer69b61b02023-03-07 17:17:44 +08002291 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
developer72fb0bb2023-01-11 09:46:29 +08002292 if (strcmp (channelMode,"11A") == 0)
2293 {
2294 writeBandWidth(radioIndex,"20MHz");
2295 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2296 printf("\nChannel Mode is 802.11a (5GHz)\n");
2297 }
2298 else if (strcmp (channelMode,"11NAHT20") == 0)
2299 {
2300 writeBandWidth(radioIndex,"20MHz");
2301 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2302 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
2303 }
2304 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
2305 {
2306 writeBandWidth(radioIndex,"40MHz");
2307 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2308 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2309 }
2310 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
2311 {
2312 writeBandWidth(radioIndex,"40MHz");
2313 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2314 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
2315 }
2316 else if (strcmp (channelMode,"11ACVHT20") == 0)
2317 {
2318 writeBandWidth(radioIndex,"20MHz");
2319 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2320 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
2321 }
2322 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
2323 {
2324 writeBandWidth(radioIndex,"40MHz");
2325 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2326 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2327 }
2328 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
2329 {
2330 writeBandWidth(radioIndex,"40MHz");
2331 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2332 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
2333 }
2334 else if (strcmp (channelMode,"11ACVHT80") == 0)
2335 {
2336 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
2337 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
2338 }
2339 else if (strcmp (channelMode,"11ACVHT160") == 0)
2340 {
2341 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
2342 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
developer69b61b02023-03-07 17:17:44 +08002343 }
developer72fb0bb2023-01-11 09:46:29 +08002344 else if (strcmp (channelMode,"11B") == 0)
2345 {
2346 writeBandWidth(radioIndex,"20MHz");
2347 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2348 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
2349 }
2350 else if (strcmp (channelMode,"11G") == 0)
2351 {
2352 writeBandWidth(radioIndex,"20MHz");
2353 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2354 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
2355 }
2356 else if (strcmp (channelMode,"11NGHT20") == 0)
2357 {
2358 writeBandWidth(radioIndex,"20MHz");
2359 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
2360 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
2361 }
2362 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
2363 {
2364 writeBandWidth(radioIndex,"40MHz");
2365 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2366 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2367 }
2368 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
2369 {
2370 writeBandWidth(radioIndex,"40MHz");
2371 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
2372 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
2373 }
developer69b61b02023-03-07 17:17:44 +08002374 else
developer72fb0bb2023-01-11 09:46:29 +08002375 {
2376 return RETURN_ERR;
2377 }
2378 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2379
2380 return RETURN_OK;
2381}
2382
2383// Set the radio operating mode, and pure mode flag.
2384INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
2385{
2386 int num_hostapd_support_mode = 3; // n, ac, ax
2387 struct params list[num_hostapd_support_mode];
2388 char config_file[64] = {0};
2389 char bandwidth[16] = {0};
2390 int mode_check_bit = 1 << 3; // n mode
developer69b61b02023-03-07 17:17:44 +08002391
developer72fb0bb2023-01-11 09:46:29 +08002392
2393 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
2394 // Set radio mode
2395 list[0].name = "ieee80211n";
2396 list[1].name = "ieee80211ac";
2397 list[2].name = "ieee80211ax";
2398 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2399
2400 // check the bit map from n to ax, and set hostapd config
2401 if (pureMode & WIFI_MODE_N)
2402 list[0].value = "1";
2403 else
2404 list[0].value = "0";
2405 if (pureMode & WIFI_MODE_AC)
2406 list[1].value = "1";
2407 else
2408 list[1].value = "0";
2409 if (pureMode & WIFI_MODE_AX)
2410 list[2].value = "1";
2411 else
2412 list[2].value = "0";
2413 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
2414
2415 if (channelMode == NULL || strlen(channelMode) == 0)
2416 return RETURN_OK;
2417 // Set bandwidth
2418 if (strstr(channelMode, "40") != NULL)
2419 strcpy(bandwidth, "40MHz");
2420 else if (strstr(channelMode, "80") != NULL)
2421 strcpy(bandwidth, "80MHz");
2422 else if (strstr(channelMode, "160") != NULL)
2423 strcpy(bandwidth, "160MHz");
2424 else // 11A, 11B, 11G....
2425 strcpy(bandwidth, "20MHz");
2426
2427 writeBandWidth(radioIndex, bandwidth);
2428 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
2429
2430 wifi_reloadAp(radioIndex);
2431 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2432
2433 return RETURN_OK;
2434}
2435
2436INT wifi_setRadioHwMode(INT radioIndex, CHAR *hw_mode) {
2437
2438 char config_file[64] = {0};
2439 char buf[64] = {0};
2440 struct params params = {0};
2441 wifi_band band = band_invalid;
2442
2443 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2444
2445 band = wifi_index_to_band(radioIndex);
2446
2447 if (strncmp(hw_mode, "a", 1) == 0 && (band != band_5 && band != band_6))
2448 return RETURN_ERR;
2449 else if ((strncmp(hw_mode, "b", 1) == 0 || strncmp(hw_mode, "g", 1) == 0) && band != band_2_4)
2450 return RETURN_ERR;
2451 else if ((strncmp(hw_mode, "a", 1) && strncmp(hw_mode, "b", 1) && strncmp(hw_mode, "g", 1)) || band == band_invalid)
2452 return RETURN_ERR;
2453
2454 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2455 params.name = "hw_mode";
2456 params.value = hw_mode;
2457 wifi_hostapdWrite(config_file, &params, 1);
2458 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2459
2460 if (band == band_2_4) {
2461 if (strncmp(hw_mode, "b", 1) == 0) {
2462 wifi_setRadioMode(radioIndex, "20MHz", WIFI_MODE_B);
2463 snprintf(buf, sizeof(buf), "%s", "1,2,5.5,11");
2464 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2465 snprintf(buf, sizeof(buf), "%s", "1,2");
2466 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2467 } else {
2468 // We don't set mode here, because we don't know whitch mode should be set (g, n or ax?).
2469
2470 snprintf(buf, sizeof(buf), "%s", "6,9,12,18,24,36,48,54");
2471 wifi_setRadioOperationalDataTransmitRates(radioIndex, buf);
2472 snprintf(buf, sizeof(buf), "%s", "6,12,24");
2473 wifi_setRadioBasicDataTransmitRates(radioIndex, buf);
2474 }
2475 }
2476
2477 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2478 return RETURN_OK;
2479}
2480
2481INT wifi_setNoscan(INT radioIndex, CHAR *noscan)
2482{
2483 char config_file[64] = {0};
2484 struct params params = {0};
2485 wifi_band band = band_invalid;
2486
2487 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2488
2489 band = wifi_index_to_band(radioIndex);
2490 if (band != band_2_4)
2491 return RETURN_OK;
2492
2493 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2494 params.name = "noscan";
2495 params.value = noscan;
2496 wifi_hostapdWrite(config_file, &params, 1);
2497 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2498
2499 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2500 return RETURN_OK;
2501}
2502
2503//Get the list of supported channel. eg: "1-11"
2504//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.
2505INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2506{
2507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer69b61b02023-03-07 17:17:44 +08002508 if (NULL == output_string)
developer72fb0bb2023-01-11 09:46:29 +08002509 return RETURN_ERR;
2510 char cmd[256] = {0};
2511 char buf[128] = {0};
2512 BOOL dfs_enable = false;
2513 int phyId = 0;
2514
2515 // Parse possible channel number and separate them with commas.
2516 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2517 phyId = radio_index_to_phy(radioIndex);
2518 // Channel 68 and 96 only allow bandwidth 20MHz, so we remove them with their frequency.
2519 if (dfs_enable)
2520 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'no IR\\|5340\\|5480' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", phyId);
developer69b61b02023-03-07 17:17:44 +08002521 else
developer72fb0bb2023-01-11 09:46:29 +08002522 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);
2523
2524 _syscmd(cmd,buf,sizeof(buf));
2525 strncpy(output_string, buf, sizeof(buf));
2526
2527 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2528 return RETURN_OK;
2529}
2530
2531//Get the list for used channel. eg: "1,6,9,11"
2532//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.
2533INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2534{
2535 char interface_name[16] = {0};
2536 char cmd[128] = {0};
2537 char buf[128] = {0};
2538 char config_file[64] = {0};
2539 int channel = 0;
2540 int freq = 0;
2541 int bandwidth = 0;
2542 int center_freq = 0;
2543 int center_channel = 0;
2544 int channel_delta = 0;
2545 wifi_band band = band_invalid;
2546
2547 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
2548
2549 if (NULL == output_string)
2550 return RETURN_ERR;
2551
2552 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
2553 return RETURN_ERR;
2554 sprintf(cmd, "iw %s info | grep channel | sed -e 's/[^0-9 ]//g'", interface_name);
2555 _syscmd(cmd, buf, sizeof(buf));
2556 if (strlen(buf) == 0) {
2557 fprintf(stderr, "%s: failed to get channel information from iw.\n", __func__);
2558 return RETURN_ERR;
2559 }
2560 sscanf(buf, "%d %d %d %*d %d", &channel, &freq, &bandwidth, &center_freq);
2561
2562 if (bandwidth == 20) {
2563 snprintf(output_string, 256, "%d", channel);
2564 return RETURN_OK;
2565 }
2566
2567 center_channel = ieee80211_frequency_to_channel(center_freq);
2568
2569 band = wifi_index_to_band(radioIndex);
2570 if (band == band_2_4 && bandwidth == 40) {
2571 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2572 memset(buf, 0, sizeof(buf));
2573 wifi_halgetRadioExtChannel(config_file, buf); // read ht_capab for HT40+ or -
2574
2575 if (strncmp(buf, "AboveControlChannel", strlen("AboveControlChannel")) == 0 && channel < 10) {
2576 snprintf(output_string, 256, "%d,%d", channel, channel+4);
2577 } else if (strncmp(buf, "BelowControlChannel", strlen("BelowControlChannel")) == 0 && channel > 4) {
2578 snprintf(output_string, 256, "%d,%d", channel-4, channel);
2579 } else {
2580 fprintf(stderr, "%s: invalid channel %d set with %s\n.", __func__, channel, buf);
2581 return RETURN_ERR;
2582 }
2583 } else if (band == band_5 || band == band_6){
2584 // to minus 20 is an offset, because frequence of a channel have a range. We need to use offset to calculate correct channel.
2585 // example: bandwidth 80: center is 42 (5210), channels are 36-48 (5170-5250). The delta should be 6.
2586 channel_delta = (bandwidth-20)/10;
2587 snprintf(output_string, 256, "%d-%d", (center_channel-channel_delta), (center_channel+channel_delta));
2588 } else
2589 return RETURN_ERR;
2590
2591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2592 return RETURN_OK;
2593}
2594
developer69b61b02023-03-07 17:17:44 +08002595//Get the running channel number
developer72fb0bb2023-01-11 09:46:29 +08002596INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2597{
2598 char channel_str[16] = {0};
2599 char config_file[128] = {0};
2600
2601 if (output_ulong == NULL)
2602 return RETURN_ERR;
2603
2604 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2605 wifi_hostapdRead(config_file, "channel", channel_str, sizeof(channel_str));
2606
2607 *output_ulong = strtoul(channel_str, NULL, 10);
2608
2609 return RETURN_OK;
2610}
2611
2612
2613INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2614{
2615 char cmd[1024] = {0}, buf[5] = {0};
2616 char interface_name[16] = {0};
2617
2618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2619 if (NULL == output_ulong)
2620 return RETURN_ERR;
2621
2622 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2623 if (wifi_getApName(apIndex,interface_name) != RETURN_OK)
2624 return RETURN_ERR;
2625 _syscmd(cmd,buf,sizeof(buf));
2626 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2627 if (*output_ulong == 0) {
2628 return RETURN_ERR;
2629 }
2630
2631 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2632 return RETURN_OK;
2633}
2634
2635//Storing the previous channel value
2636INT wifi_storeprevchanval(INT radioIndex)
2637{
2638 char buf[256] = {0};
2639 char output[4]={'\0'};
2640 char config_file[MAX_BUF_SIZE] = {0};
2641 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2642 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2643 if(radioIndex == 0)
2644 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2645 else if(radioIndex == 1)
2646 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2647 system(buf);
2648 Radio_flag = FALSE;
2649 return RETURN_OK;
2650}
2651
2652//Set the running channel number
2653INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2654{
2655 // We only write hostapd config here
2656 char str_channel[8]={0};
2657 char *list_channel;
2658 char config_file[128] = {0};
2659 char possible_channels[256] = {0};
2660 int max_radio_num = 0;
2661 struct params list = {0};
2662
2663 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2664
2665 // Check valid
2666 sprintf(str_channel, "%lu", channel);
2667
2668 wifi_getRadioPossibleChannels(radioIndex, possible_channels);
2669 list_channel = strtok(possible_channels, ",");
2670 while(true)
2671 {
2672 if(list_channel == NULL) { // input not in the list
2673 fprintf(stderr, "%s: Channel %s is not in possible list\n", __func__, str_channel);
2674 return RETURN_ERR;
2675 }
2676 if (strncmp(str_channel, list_channel, strlen(list_channel)) == 0 || strncmp(str_channel, "0", 1) == 0)
2677 break;
2678 list_channel = strtok(NULL, ",");
2679 }
2680
2681 list.name = "channel";
2682 list.value = str_channel;
2683 wifi_getMaxRadioNumber(&max_radio_num);
2684 for(int i=0; i<=MAX_APS/max_radio_num;i++)
2685 {
2686 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2687 wifi_hostapdWrite(config_file, &list, 1);
2688 }
2689
2690 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
2691 return RETURN_OK;
2692}
2693
2694INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2695{
2696 struct params list[2];
2697 char str_idx[16];
2698 char config_file[64];
2699 int max_num_radios = 0;
2700 wifi_band band = band_invalid;
2701
2702 band = wifi_index_to_band(radioIndex);
2703 if (band == band_2_4)
2704 return RETURN_OK;
2705
2706 snprintf(str_idx, sizeof(str_idx), "%lu", channel);
2707 list[0].name = "vht_oper_centr_freq_seg0_idx";
2708 list[0].value = str_idx;
2709 list[1].name = "he_oper_centr_freq_seg0_idx";
2710 list[1].value = str_idx;
2711
2712 wifi_getMaxRadioNumber(&max_num_radios);
2713 for(int i=0; i<=MAX_APS/max_num_radios; i++)
2714 {
2715 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_num_radios*i));
2716 if (band == band_6)
2717 wifi_hostapdWrite(config_file, &list[1], 1);
2718 else
2719 wifi_hostapdWrite(config_file, list, 2);
2720 }
2721
2722 return RETURN_OK;
2723}
2724
2725//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2726//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2727INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2728{
2729 //Set to wifi config only. Wait for wifi reset to apply.
2730 char buf[256] = {0};
2731 char str_channel[256] = {0};
2732 int count = 0;
2733 ULONG Value = 0;
2734 FILE *fp = NULL;
2735 if(enable == TRUE)
2736 {
2737 wifi_setRadioChannel(radioIndex,Value);
2738 }
2739 return RETURN_OK;
2740}
2741
2742INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2743{
2744 if (output_bool == NULL)
2745 return RETURN_ERR;
2746
2747 *output_bool = TRUE;
2748
2749 return RETURN_OK;
2750}
2751
2752INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2753{
developer69b61b02023-03-07 17:17:44 +08002754 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002755 return RETURN_ERR;
2756 *output_bool=FALSE;
2757 return RETURN_OK;
2758}
2759
2760INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2761{
developer69b61b02023-03-07 17:17:44 +08002762 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002763 return RETURN_ERR;
2764 *output_bool=FALSE;
2765 return RETURN_OK;
2766}
2767
2768INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2769{
2770 //Set to wifi config only. Wait for wifi reset to apply.
2771 return RETURN_OK;
2772}
2773
2774INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2775{
2776 return RETURN_OK;
2777}
2778
2779INT wifi_factoryResetAP(int apIndex)
2780{
2781 char ap_config_file[64] = {0};
2782 char cmd[128] = {0};
2783
2784 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2785
2786 wifi_setApEnable(apIndex, FALSE);
2787 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2788 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2789 wifi_setApEnable(apIndex, TRUE);
2790
2791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2792
2793 return RETURN_OK;
2794}
2795
2796//To set Band Steering AP group
2797//To-do
2798INT wifi_setBandSteeringApGroup(char *ApGroup)
2799{
2800 return RETURN_OK;
2801}
2802
2803INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2804{
2805 char config_file[128] = {'\0'};
2806 char buf[128] = {'\0'};
2807
2808 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2809 if (dtimInterval == NULL)
2810 return RETURN_ERR;
2811
2812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2813 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2814
2815 if (strlen(buf) == 0) {
2816 *dtimInterval = 2;
2817 } else {
2818 *dtimInterval = strtoul(buf, NULL, 10);
2819 }
2820
2821 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2822 return RETURN_OK;
2823}
2824
2825INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2826{
2827 struct params params={0};
2828 char config_file[MAX_BUF_SIZE] = {'\0'};
2829 char buf[MAX_BUF_SIZE] = {'\0'};
2830
2831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2832 if (dtimInterval < 1 || dtimInterval > 255) {
2833 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2834 return RETURN_ERR;
2835 }
developer69b61b02023-03-07 17:17:44 +08002836
developer72fb0bb2023-01-11 09:46:29 +08002837 params.name = "dtim_period";
2838 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2839 params.value = buf;
2840
2841 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2842 wifi_hostapdWrite(config_file, &params, 1);
2843 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2844
2845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2846 return RETURN_OK;
2847}
2848
2849//Check if the driver support the Dfs
2850INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2851{
2852 wifi_band band = band_invalid;
developer69b61b02023-03-07 17:17:44 +08002853 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002854 return RETURN_ERR;
2855 *output_bool=FALSE;
2856
2857 band = wifi_index_to_band(radioIndex);
2858 if (band == band_5)
2859 *output_bool = TRUE;
2860 return RETURN_OK;
2861}
2862
2863//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.
2864//The value of this parameter is a comma seperated list of channel number
2865INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2866{
developer69b61b02023-03-07 17:17:44 +08002867 if (NULL == output_pool)
developer72fb0bb2023-01-11 09:46:29 +08002868 return RETURN_ERR;
2869 if (radioIndex==1)
developer69b61b02023-03-07 17:17:44 +08002870 return RETURN_OK;//TODO need to handle for 5GHz band, i think
developer72fb0bb2023-01-11 09:46:29 +08002871 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2872
2873 return RETURN_OK;
2874}
2875
2876INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2877{
2878 //Set to wifi config. And apply instantly.
2879 return RETURN_OK;
2880}
2881
2882INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2883{
developer69b61b02023-03-07 17:17:44 +08002884 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
developer72fb0bb2023-01-11 09:46:29 +08002885 return RETURN_ERR;
2886 *output_interval_seconds=1800;
2887 *output_dwell_milliseconds=40;
2888
2889 return RETURN_OK;
2890}
2891
2892INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2893{
2894 //Set to wifi config. And apply instantly.
2895 return RETURN_OK;
2896}
2897
2898INT wifi_getRadioDfsAtBootUpEnable(INT radioIndex, BOOL *output_bool) //Tr181
2899{
2900 if (output_bool == NULL)
2901 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08002902 *output_bool = true;
2903 return RETURN_OK;
developer72fb0bb2023-01-11 09:46:29 +08002904}
2905
2906INT wifi_setRadioDfsAtBootUpEnable(INT radioIndex, BOOL enable) //Tr181
2907{
2908 return RETURN_OK;
2909}
2910
2911//Get the Dfs enable status
2912INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2913{
2914 char buf[16] = {0};
2915 FILE *f = NULL;
2916
2917 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2918
2919 if (output_bool == NULL)
2920 return RETURN_ERR;
2921
2922 *output_bool = TRUE; // default
2923 f = fopen(DFS_ENABLE_FILE, "r");
2924 if (f != NULL) {
2925 fgets(buf, 2, f);
2926 if (strncmp(buf, "0", 1) == 0)
2927 *output_bool = FALSE;
2928 fclose(f);
2929 }
2930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2931 return RETURN_OK;
2932}
2933
2934//Set the Dfs enable status
2935INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2936{
2937 char config_file[128] = {0};
2938 FILE *f = NULL;
2939 struct params params={0};
2940
2941 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2942
2943 f = fopen(DFS_ENABLE_FILE, "w");
2944 if (f == NULL)
2945 return RETURN_ERR;
2946 fprintf(f, "%d", enable);
2947 fclose(f);
2948
2949 params.name = "acs_exclude_dfs";
2950 params.value = enable?"0":"1";
2951 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2952 wifi_hostapdWrite(config_file, &params, 1);
2953 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2954
2955 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2956
2957 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2958 return RETURN_OK;
2959}
2960
2961//Check if the driver support the AutoChannelRefreshPeriod
2962INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2963{
developer69b61b02023-03-07 17:17:44 +08002964 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08002965 return RETURN_ERR;
2966 *output_bool=FALSE; //not support
2967
2968 return RETURN_OK;
2969}
2970
2971//Get the ACS refresh period in seconds
2972INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2973{
developer69b61b02023-03-07 17:17:44 +08002974 if (NULL == output_ulong)
developer72fb0bb2023-01-11 09:46:29 +08002975 return RETURN_ERR;
2976 *output_ulong=300;
2977
2978 return RETURN_OK;
2979}
2980
2981//Set the ACS refresh period in seconds
2982INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2983{
2984 return RETURN_ERR;
2985}
2986
2987//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2988//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.
2989INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2990{
developer8666b312023-03-24 14:05:31 +08002991 char cmd[MAX_CMD_SIZE] = {0}, buf[64] = {0};
developer72fb0bb2023-01-11 09:46:29 +08002992 char extchannel[128] = {0};
developer8666b312023-03-24 14:05:31 +08002993 char interface_name[64] = {0};
2994 int ret = 0, len=0;
developer72fb0bb2023-01-11 09:46:29 +08002995 BOOL radio_enable = FALSE;
2996 wifi_band band;
2997
2998 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2999
3000 if (NULL == output_string)
3001 return RETURN_ERR;
3002
3003 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
3004 return RETURN_ERR;
3005
3006 if (radio_enable != TRUE)
3007 return RETURN_OK;
3008
developer8666b312023-03-24 14:05:31 +08003009 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3010 return RETURN_ERR;
3011 /*IW command get BW320 to do*/
3012 snprintf(cmd, sizeof(cmd),"iw dev %s info | grep 'width' | cut -d ' ' -f6 | tr -d '\\n'", interface_name);
3013 ret = _syscmd(cmd, buf, sizeof(buf));
3014 len = strlen(buf);
3015 if((ret != 0) || (len == 0))
3016 {
3017 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
3018 return RETURN_ERR;
3019 }
3020
developer72fb0bb2023-01-11 09:46:29 +08003021 band = wifi_index_to_band(radioIndex);
developer8666b312023-03-24 14:05:31 +08003022 if (band == band_2_4 && strncmp(buf, "20", 2) == 0) {
developer72fb0bb2023-01-11 09:46:29 +08003023 wifi_getRadioExtChannel(radioIndex, extchannel);
developer8666b312023-03-24 14:05:31 +08003024 if (strncmp(extchannel, "Auto", 4) != 0) // not auto means we have set HT40+/-
3025 snprintf(buf, sizeof(buf), "40");
developer72fb0bb2023-01-11 09:46:29 +08003026 }
developer8666b312023-03-24 14:05:31 +08003027 snprintf(output_string, 64, "%sMHz", buf);
developer72fb0bb2023-01-11 09:46:29 +08003028 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3029
3030 return RETURN_OK;
3031}
developer72fb0bb2023-01-11 09:46:29 +08003032//Set the Operating Channel Bandwidth.
3033INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
3034{
3035 char config_file[128];
3036 char set_value[16];
3037 struct params params[2];
3038 int max_radio_num = 0;
3039
3040 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3041
3042 if(NULL == bandwidth)
3043 return RETURN_ERR;
3044
3045 if(strstr(bandwidth,"160") != NULL)
3046 strcpy(set_value, "2");
3047 else if(strstr(bandwidth,"80") != NULL)
3048 strcpy(set_value, "1");
3049 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
3050 strcpy(set_value, "0");
3051 else
3052 {
3053 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
3054 return RETURN_ERR;
3055 }
3056
3057 params[0].name = "vht_oper_chwidth";
3058 params[0].value = set_value;
3059 params[1].name = "he_oper_chwidth";
3060 params[1].value = set_value;
3061
3062 wifi_getMaxRadioNumber(&max_radio_num);
3063 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3064 {
3065 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
3066 wifi_hostapdWrite(config_file, params, 2);
3067 }
3068
3069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3070 return RETURN_OK;
3071}
3072
3073//Getting current radio extension channel
3074INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
3075{
3076 CHAR buf[150] = {0};
3077 CHAR cmd[150] = {0};
3078 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
3079 _syscmd(cmd, buf, sizeof(buf));
3080 if(NULL != strstr(buf,"HT40+"))
3081 strcpy(Value,"AboveControlChannel");
3082 else if(NULL != strstr(buf,"HT40-"))
3083 strcpy(Value,"BelowControlChannel");
3084 return RETURN_OK;
3085}
3086
3087//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
3088//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.
3089INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
3090{
3091 char config_file[64] = {0};
3092 char mode_str[16] = {0};
3093 char buf[64] = {0};
3094 wifi_band band;
3095 int channel = 0, centr_channel = 0;
3096 UINT mode_map = 0;
3097
3098 if (output_string == NULL)
3099 return RETURN_ERR;
3100
3101 wifi_getRadioMode(radioIndex, mode_str, &mode_map);
3102
3103 band = wifi_index_to_band(radioIndex);
3104 if (band == band_invalid)
3105 return RETURN_ERR;
3106
3107 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3108
3109 snprintf(output_string, 64, "Auto");
developer23e71282023-01-18 10:25:19 +08003110 if (band == band_2_4 || (!(mode_map&WIFI_MODE_AC) && !(mode_map&WIFI_MODE_AX))) {
developer72fb0bb2023-01-11 09:46:29 +08003111 // 2G band or ac and ax mode is disable, we will check ht_capab
3112 wifi_halgetRadioExtChannel(config_file, output_string);
developer23e71282023-01-18 10:25:19 +08003113 if (!(mode_map&WIFI_MODE_N))
developer72fb0bb2023-01-11 09:46:29 +08003114 snprintf(output_string, 64, "Auto");
3115 } else {
3116 // 5G and 6G band with ac or ax mode.
3117 wifi_getRadioChannel(radioIndex, &channel);
3118 if (mode_map&WIFI_MODE_AX)
3119 wifi_hostapdRead(config_file, "he_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3120 else
3121 wifi_hostapdRead(config_file, "vht_oper_centr_freq_seg0_idx", buf, sizeof(buf));
3122 centr_channel = strtol(buf, NULL, 10);
3123 if (centr_channel > channel)
3124 snprintf(output_string, 64, "AboveControlChannel");
3125 else
3126 snprintf(output_string, 64, "BelowControlChannel");
3127 }
3128
3129 return RETURN_OK;
3130}
3131
3132//Set the extension channel.
3133INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
developer69b61b02023-03-07 17:17:44 +08003134{
developer72fb0bb2023-01-11 09:46:29 +08003135 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3136 struct params params={0};
3137 char config_file[64] = {0};
3138 char ext_channel[128]={0};
3139 char buf[128] = {0};
3140 char cmd[128] = {0};
3141 int max_radio_num =0, ret = 0, bandwidth = 0;
3142 unsigned long channel = 0, centr_channel = 0;
3143 bool stbcEnable = FALSE;
3144 params.name = "ht_capab";
3145 wifi_band band;
3146
3147 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3148 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
3149 _syscmd(cmd, buf, sizeof(buf));
3150 if (strlen(buf) != 0)
3151 stbcEnable = TRUE;
3152 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, buf) != RETURN_OK)
3153 return RETURN_ERR;
3154 bandwidth = strtol(buf, NULL, 10);
3155 // TDK expected to get error with 20MHz
3156 if (bandwidth == 20 || strstr(buf, "80+80") != NULL)
3157 return RETURN_ERR;
3158
3159 band = wifi_index_to_band(radioIndex);
3160 if (band == band_invalid)
3161 return RETURN_ERR;
3162
3163 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK)
3164 return RETURN_ERR;
3165
3166 if (band == band_5) {
3167 snprintf(buf, sizeof(buf), "HT%d", bandwidth);
3168 centr_channel = util_unii_5g_centerfreq(buf, channel);
3169 if (centr_channel == 0)
3170 return RETURN_ERR;
3171 }
3172
3173 if(NULL!= strstr(string,"Above")) {
3174 if ((band == band_2_4 && channel > 9) || (band == band_5 && channel > centr_channel))
3175 return RETURN_ERR;
3176 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
3177 } else if(NULL!= strstr(string,"Below")) {
3178 if ((band == band_2_4 && channel < 5) || (band == band_5 && channel < centr_channel))
3179 return RETURN_ERR;
3180 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
3181 } else {
3182 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
3183 }
3184
3185 params.value = ext_channel;
3186
3187 wifi_getMaxRadioNumber(&max_radio_num);
3188 for(int i=0; i<=MAX_APS/max_radio_num; i++)
3189 {
3190 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(max_radio_num*i));
3191 wifi_hostapdWrite(config_file, &params, 1);
3192 wifi_setRadioSTBCEnable(radioIndex+(max_radio_num*i), stbcEnable);
3193 }
3194
3195 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
3196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3197 return RETURN_OK;
3198}
3199
3200//Get the guard interval value. eg "400nsec" or "800nsec"
3201//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.
3202INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
3203{
3204 wifi_guard_interval_t GI;
3205
3206 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3207
3208 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
3209 return RETURN_ERR;
3210
3211 if (GI == wifi_guard_interval_400)
3212 strcpy(output_string, "400nsec");
3213 else if (GI == wifi_guard_interval_800)
3214 strcpy(output_string, "800nsec");
3215 else if (GI == wifi_guard_interval_1600)
3216 strcpy(output_string, "1600nsec");
3217 else if (GI == wifi_guard_interval_3200)
3218 strcpy(output_string, "3200nsec");
3219 else
3220 strcpy(output_string, "Auto");
3221
3222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3223 return RETURN_OK;
3224}
3225
3226//Set the guard interval value.
3227INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
3228{
3229 wifi_guard_interval_t GI;
3230 int ret = 0;
3231
3232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3233
3234 if (strcmp(string, "400nsec") == 0)
3235 GI = wifi_guard_interval_400;
3236 else if (strcmp(string , "800nsec") == 0)
3237 GI = wifi_guard_interval_800;
3238 else if (strcmp(string , "1600nsec") == 0)
3239 GI = wifi_guard_interval_1600;
3240 else if (strcmp(string , "3200nsec") == 0)
3241 GI = wifi_guard_interval_3200;
3242 else
3243 GI = wifi_guard_interval_auto;
3244
3245 ret = wifi_setGuardInterval(radioIndex, GI);
3246
3247 if (ret == RETURN_ERR) {
3248 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
3249 return RETURN_ERR;
3250 }
3251
3252 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3253 return RETURN_OK;
3254}
3255
3256//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
3257INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
3258{
3259 char buf[32]={0};
3260 char mcs_file[64] = {0};
3261 char cmd[64] = {0};
3262 int mode_bitmap = 0;
3263
3264 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3265 if(output_int == NULL)
3266 return RETURN_ERR;
3267 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3268
3269 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
3270 _syscmd(cmd, buf, sizeof(buf));
3271 if (strlen(buf) > 0)
3272 *output_int = strtol(buf, NULL, 10);
3273 else {
3274 // output the max MCS for the current radio mode
3275 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
3276 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
3277 return RETURN_ERR;
3278 }
3279 if (mode_bitmap & WIFI_MODE_AX) {
3280 *output_int = 11;
3281 } else if (mode_bitmap & WIFI_MODE_AC) {
3282 *output_int = 9;
3283 } else if (mode_bitmap & WIFI_MODE_N) {
3284 *output_int = 7;
3285 }
3286 }
3287 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3288
3289 return RETURN_OK;
3290}
3291
3292//Set the Modulation Coding Scheme index
3293INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
3294{
3295 // 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).
3296 char config_file[64] = {0};
3297 char set_value[16] = {0};
3298 char mcs_file[32] = {0};
3299 wifi_band band = band_invalid;
3300 struct params set_config = {0};
3301 FILE *f = NULL;
3302
3303 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3304
3305 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
3306
3307 // -1 means auto
3308 if (MCS > 15 || MCS < -1) {
3309 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
3310 return RETURN_ERR;
3311 }
3312
3313 if (MCS > 9 || MCS == -1)
3314 strcpy(set_value, "2");
3315 else if (MCS > 7)
3316 strcpy(set_value, "1");
3317 else
3318 strcpy(set_value, "0");
3319
3320 set_config.name = "he_basic_mcs_nss_set";
3321 set_config.value = set_value;
3322
3323 wifi_hostapdWrite(config_file, &set_config, 1);
3324 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
3325
3326 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
3327 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
3328 f = fopen(mcs_file, "w");
3329 if (f == NULL) {
3330 fprintf(stderr, "%s: fopen failed\n", __func__);
3331 return RETURN_ERR;
3332 }
3333 fprintf(f, "%d", MCS);
3334 fclose(f);
3335
3336 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3337 return RETURN_OK;
3338}
3339
3340//Get supported Transmit Power list, eg : "0,25,50,75,100"
3341//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.
3342INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
3343{
3344 if (NULL == output_list)
3345 return RETURN_ERR;
3346 snprintf(output_list, 64,"0,25,50,75,100");
3347 return RETURN_OK;
3348}
3349
3350//Get current Transmit Power in dBm units.
3351//The transmite power level is in units of full power for this radio.
3352INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
3353{
3354 char interface_name[16] = {0};
3355 char cmd[128]={0};
3356 char buf[16]={0};
3357 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3358
3359 if(output_ulong == NULL)
3360 return RETURN_ERR;
3361
3362 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3363 return RETURN_ERR;
3364 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
3365 _syscmd(cmd, buf, sizeof(buf));
3366
3367 *output_ulong = strtol(buf, NULL, 10);
3368
3369 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3370 return RETURN_OK;
3371}
3372
3373//Set Transmit Power
3374//The transmite power level is in units of full power for this radio.
3375INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
3376{
3377 char interface_name[16] = {0};
3378 char *support;
3379 char cmd[128]={0};
3380 char buf[128]={0};
3381 char txpower_str[64] = {0};
3382 int txpower = 0;
3383 int maximum_tx = 0;
3384 int phyId = 0;
3385
3386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3387
3388 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3389 return RETURN_ERR;
3390 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
3391 _syscmd(cmd, buf, sizeof(buf));
3392 maximum_tx = strtol(buf, NULL, 10);
3393
3394 // Get the Tx power supported list and check that is the input in the list
3395 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
3396 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
3397 support = strtok(buf, ",");
3398 while(true)
3399 {
3400 if(support == NULL) { // input not in the list
3401 wifi_dbg_printf("Input value is invalid.\n");
3402 return RETURN_ERR;
3403 }
3404 if (strncmp(txpower_str, support, strlen(support)) == 0) {
3405 break;
3406 }
3407 support = strtok(NULL, ",");
3408 }
3409 txpower = TransmitPower*maximum_tx/100;
3410 phyId = radio_index_to_phy(radioIndex);
3411 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", phyId, txpower);
3412 _syscmd(cmd, buf, sizeof(buf));
3413 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3414
3415 return RETURN_OK;
3416}
3417
3418//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
3419INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
3420{
developer69b61b02023-03-07 17:17:44 +08003421 if (NULL == Supported)
developer72fb0bb2023-01-11 09:46:29 +08003422 return RETURN_ERR;
3423 *Supported = TRUE;
3424
3425 return RETURN_OK;
3426}
3427
3428//Get 80211h feature enable
3429INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
3430{
3431 char buf[64]={'\0'};
3432 char config_file[64] = {'\0'};
3433
3434 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3435 if(enable == NULL)
3436 return RETURN_ERR;
3437
3438 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3439 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
3440
3441 if (strncmp(buf, "1", 1) == 0)
3442 *enable = TRUE;
3443 else
3444 *enable = FALSE;
3445
3446 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3447 return RETURN_OK;
3448}
3449
3450//Set 80211h feature enable
3451INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
3452{
3453 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3454 struct params params={'\0'};
3455 char config_file[MAX_BUF_SIZE] = {0};
3456
3457 params.name = "ieee80211h";
3458
3459 if (enable) {
3460 params.value = "1";
3461 } else {
3462 params.value = "0";
3463 }
3464
3465 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3466 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003467
developer72fb0bb2023-01-11 09:46:29 +08003468 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3469 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3470 return RETURN_OK;
3471}
3472
3473//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.
3474INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
3475{
3476 if (NULL == output)
3477 return RETURN_ERR;
3478 *output=100;
3479
3480 return RETURN_OK;
3481}
3482
3483//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.
3484INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
3485{
3486 if (NULL == output)
3487 return RETURN_ERR;
3488 *output = -99;
3489
3490 return RETURN_OK;
3491}
3492
3493INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
3494{
3495 return RETURN_ERR;
3496}
3497
3498
3499//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
3500INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
3501{
3502 char interface_name[16] = {0};
3503 char cmd[MAX_BUF_SIZE]={'\0'};
3504 char buf[MAX_CMD_SIZE]={'\0'};
3505
3506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3507 if(output == NULL)
3508 return RETURN_ERR;
3509
3510 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3511 return RETURN_ERR;
3512 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", interface_name);
3513 _syscmd(cmd, buf, sizeof(buf));
3514 *output = atoi(buf);
3515
3516 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3517 return RETURN_OK;
3518}
developer69b61b02023-03-07 17:17:44 +08003519
developer72fb0bb2023-01-11 09:46:29 +08003520INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3521{
3522 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3523 struct params params={'\0'};
3524 char buf[MAX_BUF_SIZE] = {'\0'};
3525 char config_file[MAX_BUF_SIZE] = {'\0'};
3526
3527 if (BeaconPeriod < 15 || BeaconPeriod > 65535)
3528 return RETURN_ERR;
3529
3530 params.name = "beacon_int";
3531 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3532 params.value = buf;
3533
3534 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3535 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08003536
developer72fb0bb2023-01-11 09:46:29 +08003537 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3539 return RETURN_OK;
3540}
3541
3542//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.
3543INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3544{
3545 //TODO: need to revisit below implementation
3546 char *temp;
3547 char temp_output[128] = {0};
3548 char temp_TransmitRates[64] = {0};
3549 char config_file[64] = {0};
3550
3551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3552 if (NULL == output)
3553 return RETURN_ERR;
3554 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3555 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
developer69b61b02023-03-07 17:17:44 +08003556
developer72fb0bb2023-01-11 09:46:29 +08003557 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3558 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3559 } else {
3560 temp = strtok(temp_TransmitRates," ");
3561 while(temp!=NULL)
3562 {
3563 // Convert 100 kbps to Mbps
3564 temp[strlen(temp)-1]=0;
3565 if((temp[0]=='5') && (temp[1]=='\0'))
3566 {
3567 temp="5.5";
3568 }
3569 strcat(temp_output,temp);
3570 temp = strtok(NULL," ");
3571 if(temp!=NULL)
3572 {
3573 strcat(temp_output,",");
3574 }
3575 }
3576 strcpy(output,temp_output);
3577 }
3578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3579 return RETURN_OK;
3580}
3581
3582INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3583{
3584 char *temp;
3585 char temp1[128];
3586 char temp_output[128];
3587 char temp_TransmitRates[128];
3588 char set[128];
3589 char sub_set[128];
3590 int set_count=0,subset_count=0;
3591 int set_index=0,subset_index=0;
3592 char *token;
3593 int flag=0, i=0;
3594 struct params params={'\0'};
3595 char config_file[MAX_BUF_SIZE] = {0};
3596 wifi_band band = wifi_index_to_band(radioIndex);
3597
3598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3599 if(NULL == TransmitRates)
3600 return RETURN_ERR;
3601 strcpy(sub_set,TransmitRates);
3602
3603 //Allow only supported Data transmit rate to be set
3604 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3605 token = strtok(sub_set,",");
3606 while( token != NULL ) /* split the basic rate to be set, by comma */
3607 {
3608 sub_set[subset_count]=atoi(token);
3609 subset_count++;
3610 token=strtok(NULL,",");
3611 }
3612 token=strtok(set,",");
3613 while(token!=NULL) /* split the supported rate by comma */
3614 {
3615 set[set_count]=atoi(token);
3616 set_count++;
3617 token=strtok(NULL,",");
3618 }
3619 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3620 {
3621 for(set_index=0;set_index < set_count;set_index++)
3622 {
3623 flag=0;
3624 if(sub_set[subset_index]==set[set_index])
3625 break;
3626 else
3627 flag=1; /* No match found */
3628 }
3629 if(flag==1)
3630 return RETURN_ERR; //If value not found return Error
3631 }
3632 strcpy(temp_TransmitRates,TransmitRates);
3633
3634 for(i=0;i<strlen(temp_TransmitRates);i++)
3635 {
3636 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3637 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
3638 {
3639 continue;
3640 }
3641 else
3642 {
3643 return RETURN_ERR;
3644 }
3645 }
3646 strcpy(temp_output,"");
3647 temp = strtok(temp_TransmitRates,",");
3648 while(temp!=NULL)
3649 {
3650 strcpy(temp1,temp);
3651 if(band == band_5)
3652 {
3653 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
3654 {
3655 return RETURN_ERR;
3656 }
3657 }
3658
3659 if(strcmp(temp,"5.5")==0)
3660 {
3661 strcpy(temp1,"55");
3662 }
3663 else
3664 {
3665 strcat(temp1,"0");
3666 }
3667 strcat(temp_output,temp1);
3668 temp = strtok(NULL,",");
3669 if(temp!=NULL)
3670 {
3671 strcat(temp_output," ");
3672 }
3673 }
3674 strcpy(TransmitRates,temp_output);
3675
3676 params.name= "basic_rates";
3677 params.value =TransmitRates;
3678
3679 wifi_dbg_printf("\n%s:",__func__);
3680 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3681 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3682 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3683 wifi_hostapdWrite(config_file,&params,1);
3684 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3685 return RETURN_OK;
3686}
3687
3688//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3689INT wifi_GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3690{
3691 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3692 FILE *fp = NULL;
3693 char path[256] = {0}, output_string[256] = {0};
3694 int count = 0;
3695 char *interface = NULL;
3696
3697 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3698 if (fp == NULL)
3699 {
3700 printf("Failed to run command in Function %s\n", __FUNCTION__);
3701 return RETURN_ERR;
3702 }
3703 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3704 {
3705 interface = strchr(path, '=');
3706
3707 if (interface != NULL)
3708 {
3709 strcpy(output_string, interface + 1);
3710 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3711 interface_name[count] = output_string[count];
3712
3713 interface_name[count] = '\0';
3714 }
3715 }
3716 pclose(fp);
3717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3718 return RETURN_OK;
3719}
3720
3721INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3722{
3723 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3724 output_struct->radio_BytesSent = 0;
3725 output_struct->radio_BytesReceived = 0;
3726 output_struct->radio_PacketsSent = 0;
3727 output_struct->radio_PacketsReceived = 0;
3728 output_struct->radio_ErrorsSent = 0;
3729 output_struct->radio_ErrorsReceived = 0;
3730 output_struct->radio_DiscardPacketsSent = 0;
3731 output_struct->radio_DiscardPacketsReceived = 0;
3732 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3733 return RETURN_OK;
3734}
3735
3736
3737INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3738{
3739 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3740 CHAR buf[MAX_CMD_SIZE] = {0};
3741 CHAR Value[MAX_BUF_SIZE] = {0};
3742 FILE *fp = NULL;
3743
3744 if (ifname == NULL || strlen(ifname) <= 1)
3745 return RETURN_OK;
3746
3747 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3748 system(buf);
3749
3750 fp = fopen("/tmp/Radio_Stats.txt", "r");
3751 if(fp == NULL)
3752 {
3753 printf("/tmp/Radio_Stats.txt not exists \n");
3754 return RETURN_ERR;
3755 }
3756 fclose(fp);
3757
3758 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3759 File_Reading(buf, Value);
3760 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3761
3762 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3763 File_Reading(buf, Value);
3764 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3765
3766 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3767 File_Reading(buf, Value);
3768 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3769
3770 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3771 File_Reading(buf, Value);
3772 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3773
3774 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3775 File_Reading(buf, Value);
3776 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3777
3778 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3779 File_Reading(buf, Value);
3780 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3781
3782 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3783 File_Reading(buf, Value);
3784 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3785
3786 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3787 File_Reading(buf, Value);
3788 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3789
3790 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3791 return RETURN_OK;
3792}
3793
3794INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3795{
3796 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3797 CHAR buf[MAX_CMD_SIZE] = {0};
3798 FILE *fp = NULL;
3799 INT count = 0;
3800
3801 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3802 {
3803 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3804 File_Reading(buf, status);
3805 }
3806 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3807 return RETURN_OK;
3808}
3809
3810//Get detail radio traffic static info
3811INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3812{
3813
developer69b61b02023-03-07 17:17:44 +08003814#if 0
3815 //ifconfig radio_x
developer72fb0bb2023-01-11 09:46:29 +08003816 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3817 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3818 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3819 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3820
3821 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3822 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3823 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.
3824 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.
3825
developer69b61b02023-03-07 17:17:44 +08003826 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
developer72fb0bb2023-01-11 09:46:29 +08003827 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].
3828 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3829 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.
3830 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
3831 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
3832 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
3833 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
3834 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
3835
3836 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
3837 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
3838 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
3839 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.
3840
3841 return RETURN_OK;
3842#endif
3843
3844 CHAR interface_name[64] = {0};
3845 BOOL iface_status = FALSE;
3846 wifi_radioTrafficStats2_t radioTrafficStats = {0};
3847
3848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3849 if (NULL == output_struct)
3850 return RETURN_ERR;
3851
3852 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
3853 return RETURN_ERR;
3854
3855 wifi_getApEnable(radioIndex, &iface_status);
3856
3857 if (iface_status == TRUE)
3858 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3859 else
3860 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
3861
3862 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3863 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3864 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3865 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3866 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3867 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3868 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3869 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
3870
3871 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3872 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].
3873 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3874 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.
3875 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
3876 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
3877 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
3878 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
3879 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
3880
3881 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
3882 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
3883 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
3884 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.
3885
3886 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3887
3888 return RETURN_OK;
3889}
3890
3891//Set radio traffic static Measureing rules
3892INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3893{
3894 //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
3895 // Else, save the MeasuringRate and MeasuringInterval for future usage
3896
3897 return RETURN_OK;
3898}
3899
3900//To start or stop RadioTrafficStats
3901INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3902{
3903 //zqiu: If the RadioTrafficStats process running
3904 // if(enable)
3905 // return RETURN_OK.
3906 // else
3907 // Stop RadioTrafficStats process
developer69b61b02023-03-07 17:17:44 +08003908 // Else
developer72fb0bb2023-01-11 09:46:29 +08003909 // if(enable)
3910 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3911 // else
3912 // return RETURN_OK.
3913
3914 return RETURN_OK;
3915}
3916
3917//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
3918INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3919{
3920 //zqiu: Please ignor signalIndex.
developer69b61b02023-03-07 17:17:44 +08003921 if (NULL == SignalLevel)
developer72fb0bb2023-01-11 09:46:29 +08003922 return RETURN_ERR;
3923 *SignalLevel=(radioIndex==0)?-19:-19;
3924
3925 return RETURN_OK;
3926}
3927
3928//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3929INT wifi_applyRadioSettings(INT radioIndex)
3930{
3931 return RETURN_OK;
3932}
3933
3934//Get the radio index assocated with this SSID entry
3935INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3936{
3937 if(NULL == radioIndex)
3938 return RETURN_ERR;
3939 int max_radio_num = 0;
3940 wifi_getMaxRadioNumber(&max_radio_num);
3941 *radioIndex = ssidIndex%max_radio_num;
3942 return RETURN_OK;
3943}
3944
3945//Device.WiFi.SSID.{i}.Enable
3946//Get SSID enable configuration parameters (not the SSID enable status)
3947INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3948{
developer69b61b02023-03-07 17:17:44 +08003949 if (NULL == output_bool)
developer72fb0bb2023-01-11 09:46:29 +08003950 return RETURN_ERR;
3951
3952 return wifi_getApEnable(ssidIndex, output_bool);
3953}
3954
3955//Device.WiFi.SSID.{i}.Enable
3956//Set SSID enable configuration parameters
3957INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3958{
3959 return wifi_setApEnable(ssidIndex, enable);
3960}
3961
3962//Device.WiFi.SSID.{i}.Status
3963//Get the SSID enable status
3964INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3965{
3966 char cmd[MAX_CMD_SIZE]={0};
3967 char buf[MAX_BUF_SIZE]={0};
3968 BOOL output_bool;
3969
3970 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3971 if (NULL == output_string)
3972 return RETURN_ERR;
developer69b61b02023-03-07 17:17:44 +08003973
developer72fb0bb2023-01-11 09:46:29 +08003974 wifi_getApEnable(ssidIndex,&output_bool);
3975 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3976
3977 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3978 return RETURN_OK;
3979}
3980
3981// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3982INT wifi_getSSIDName(INT apIndex, CHAR *output)
3983{
3984 char config_file[MAX_BUF_SIZE] = {0};
3985
developer69b61b02023-03-07 17:17:44 +08003986 if (NULL == output)
developer72fb0bb2023-01-11 09:46:29 +08003987 return RETURN_ERR;
3988
3989 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3990 wifi_hostapdRead(config_file,"ssid",output,32);
3991
3992 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3993 return RETURN_OK;
3994}
3995
developer69b61b02023-03-07 17:17:44 +08003996// Set a max 32 byte string and sets an internal variable to the SSID name
developer72fb0bb2023-01-11 09:46:29 +08003997INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3998{
3999 char str[MAX_BUF_SIZE]={'\0'};
4000 char cmd[MAX_CMD_SIZE]={'\0'};
4001 struct params params;
4002 char config_file[MAX_BUF_SIZE] = {0};
4003
4004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4005 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
4006 return RETURN_ERR;
4007
4008 params.name = "ssid";
4009 params.value = ssid_string;
4010 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4011 wifi_hostapdWrite(config_file, &params, 1);
4012 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4014
4015 return RETURN_OK;
4016}
4017
4018//Get the BSSID
4019INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
4020{
4021 char cmd[MAX_CMD_SIZE]="";
4022
4023 if (NULL == output_string)
4024 return RETURN_ERR;
4025
4026 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
4027 {
4028 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep bssid | cut -d '=' -f2 | tr -d '\n'", CONFIG_PREFIX, ssidIndex);
4029 _syscmd(cmd, output_string, 64);
4030 return RETURN_OK;
4031 }
4032 strncpy(output_string, "\0", 1);
4033
4034 return RETURN_ERR;
4035}
4036
4037//Get the MAC address associated with this Wifi SSID
4038INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
4039{
4040 wifi_getBaseBSSID(ssidIndex,output_string);
4041 return RETURN_OK;
4042}
4043
4044//Get the basic SSID traffic static info
4045//Apply SSID and AP (in the case of Acess Point devices) to the hardware
4046//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
4047INT wifi_applySSIDSettings(INT ssidIndex)
4048{
4049 char interface_name[16] = {0};
4050 BOOL status = false;
4051 char cmd[MAX_CMD_SIZE] = {0};
4052 char buf[MAX_CMD_SIZE] = {0};
4053 int apIndex, ret;
4054 int max_radio_num = 0;
4055 int radioIndex = 0;
4056
4057 wifi_getMaxRadioNumber(&max_radio_num);
4058
4059 radioIndex = ssidIndex % max_radio_num;
4060
4061 wifi_getApEnable(ssidIndex,&status);
4062 // Do not apply when ssid index is disabled
4063 if (status == false)
4064 return RETURN_OK;
4065
4066 /* Doing full remove and add for ssid Index
4067 * Not all hostapd options are supported with reload
4068 * for example macaddr_acl
4069 */
4070 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
4071 return RETURN_ERR;
4072
4073 ret = wifi_setApEnable(ssidIndex,true);
4074
4075 /* Workaround for hostapd issue with multiple bss definitions
4076 * when first created interface will be removed
4077 * then all vaps other vaps on same phy are removed
4078 * after calling setApEnable to false readd all enabled vaps */
4079 for(int i=0; i < MAX_APS/max_radio_num; i++) {
4080 apIndex = max_radio_num*i+radioIndex;
4081 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4082 return RETURN_ERR;
4083 snprintf(cmd, sizeof(cmd), "cat %s | grep %s | cut -d'=' -f2", VAP_STATUS_FILE, interface_name);
4084 _syscmd(cmd, buf, sizeof(buf));
4085 if(*buf == '1')
4086 wifi_setApEnable(apIndex, true);
4087 }
4088
4089 return ret;
4090}
4091
4092struct channels_noise {
4093 int channel;
4094 int noise;
4095};
4096
4097// Return noise array for each channel
4098int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
4099{
4100 char interface_name[16] = {0};
4101 FILE *f = NULL;
4102 char cmd[128] = {0};
4103 char line[256] = {0};
4104 size_t len = 0;
4105 ssize_t read = 0;
4106 int tmp = 0, arr_index = -1;
4107
4108 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4109 return RETURN_ERR;
4110 sprintf(cmd, "iw dev %s survey dump | grep 'frequency\\|noise' | awk '{print $2}'", interface_name);
4111
4112 if ((f = popen(cmd, "r")) == NULL) {
4113 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4114 return RETURN_ERR;
4115 }
developer69b61b02023-03-07 17:17:44 +08004116
developer72fb0bb2023-01-11 09:46:29 +08004117 while(fgets(line, sizeof(line), f) != NULL) {
4118 if(arr_index < channels_num){
4119 sscanf(line, "%d", &tmp);
4120 if (tmp > 0) { // channel frequency, the first line must be frequency
4121 arr_index++;
4122 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
4123 } else { // noise
4124 channels_noise_arr[arr_index].noise = tmp;
4125 }
4126 }else{
4127 break;
4128 }
4129 }
4130 pclose(f);
4131 return RETURN_OK;
4132}
4133
4134//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
4135//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
developer69b61b02023-03-07 17:17:44 +08004136INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
developer72fb0bb2023-01-11 09:46:29 +08004137{
4138 int index = -1;
4139 wifi_neighbor_ap2_t *scan_array = NULL;
4140 char cmd[256]={0};
4141 char buf[128]={0};
4142 char file_name[32] = {0};
4143 char filter_SSID[32] = {0};
4144 char line[256] = {0};
4145 char interface_name[16] = {0};
4146 char *ret = NULL;
4147 int freq=0;
4148 FILE *f = NULL;
4149 size_t len=0;
4150 int channels_num = 0;
4151 int vht_channel_width = 0;
4152 int get_noise_ret = RETURN_ERR;
4153 bool filter_enable = false;
4154 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
4155 int phyId = 0;
4156
4157 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
4158
4159 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
4160 return RETURN_ERR;
4161
4162 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
4163 f = fopen(file_name, "r");
4164 if (f != NULL) {
4165 fgets(filter_SSID, sizeof(file_name), f);
4166 if (strlen(filter_SSID) != 0)
4167 filter_enable = true;
4168 fclose(f);
4169 }
4170
4171 phyId = radio_index_to_phy(radioIndex);
4172 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
4173 _syscmd(cmd, buf, sizeof(buf));
4174 channels_num = strtol(buf, NULL, 10);
4175
4176
4177
4178 sprintf(cmd, "iw dev %s scan | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
4179 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
4180 fprintf(stderr, "cmd: %s\n", cmd);
4181 if ((f = popen(cmd, "r")) == NULL) {
4182 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
4183 return RETURN_ERR;
4184 }
developer69b61b02023-03-07 17:17:44 +08004185
developer72fb0bb2023-01-11 09:46:29 +08004186 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
4187 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08004188
developer72fb0bb2023-01-11 09:46:29 +08004189 ret = fgets(line, sizeof(line), f);
4190 while (ret != NULL) {
4191 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08004192 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08004193 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
4194 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
4195
4196 if (!filter_BSS) {
4197 index++;
4198 wifi_neighbor_ap2_t *tmp;
4199 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
4200 if (tmp == NULL) { // no more memory to use
4201 index--;
4202 wifi_dbg_printf("%s: realloc failed\n", __func__);
4203 break;
4204 }
4205 scan_array = tmp;
4206 }
4207 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4208
4209 filter_BSS = false;
4210 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
4211 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
4212 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
4213 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
4214 } else if (strstr(line, "freq") != NULL) {
4215 sscanf(line," freq: %d", &freq);
4216 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
4217
4218 if (freq >= 2412 && freq <= 2484) {
4219 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
4220 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
4221 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
4222 }
4223 else if (freq >= 5160 && freq <= 5805) {
4224 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
4225 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
4226 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
4227 }
4228
4229 scan_array[index].ap_Noise = 0;
4230 if (get_noise_ret == RETURN_OK) {
4231 for (int i = 0; i < channels_num; i++) {
4232 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
4233 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
4234 break;
4235 }
4236 }
4237 }
4238 } else if (strstr(line, "beacon interval") != NULL) {
4239 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
4240 } else if (strstr(line, "signal") != NULL) {
4241 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
4242 } else if (strstr(line,"SSID") != NULL) {
4243 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
4244 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
4245 filter_BSS = true;
4246 }
4247 } else if (strstr(line, "Supported rates") != NULL) {
4248 char SRate[80] = {0}, *tmp = NULL;
4249 memset(buf, 0, sizeof(buf));
4250 strcpy(SRate, line);
4251 tmp = strtok(SRate, ":");
4252 tmp = strtok(NULL, ":");
4253 strcpy(buf, tmp);
4254 memset(SRate, 0, sizeof(SRate));
4255
4256 tmp = strtok(buf, " \n");
4257 while (tmp != NULL) {
4258 strcat(SRate, tmp);
4259 if (SRate[strlen(SRate) - 1] == '*') {
4260 SRate[strlen(SRate) - 1] = '\0';
4261 }
4262 strcat(SRate, ",");
4263
4264 tmp = strtok(NULL, " \n");
4265 }
4266 SRate[strlen(SRate) - 1] = '\0';
4267 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
4268 } else if (strstr(line, "DTIM") != NULL) {
4269 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
4270 } else if (strstr(line, "VHT capabilities") != NULL) {
4271 strcat(scan_array[index].ap_SupportedStandards, ",ac");
4272 strcpy(scan_array[index].ap_OperatingStandards, "ac");
4273 } else if (strstr(line, "HT capabilities") != NULL) {
4274 strcat(scan_array[index].ap_SupportedStandards, ",n");
4275 strcpy(scan_array[index].ap_OperatingStandards, "n");
4276 } else if (strstr(line, "VHT operation") != NULL) {
4277 ret = fgets(line, sizeof(line), f);
4278 sscanf(line," * channel width: %d", &vht_channel_width);
4279 if(vht_channel_width == 1) {
4280 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
4281 } else {
4282 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
4283 }
4284 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4285 continue;
4286 } else if (strstr(line, "HT operation") != NULL) {
4287 ret = fgets(line, sizeof(line), f);
4288 sscanf(line," * secondary channel offset: %s", &buf);
4289 if (!strcmp(buf, "above")) {
4290 //40Mhz +
4291 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
4292 }
4293 else if (!strcmp(buf, "below")) {
4294 //40Mhz -
4295 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
4296 } else {
4297 //20Mhz
4298 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
4299 }
4300 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
4301 continue;
4302 } else if (strstr(line, "HE capabilities") != NULL) {
4303 strcat(scan_array[index].ap_SupportedStandards, ",ax");
4304 strcpy(scan_array[index].ap_OperatingStandards, "ax");
4305 ret = fgets(line, sizeof(line), f);
4306 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
4307 if (strstr(line, "HE40/2.4GHz") != NULL)
4308 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
4309 else
4310 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
4311 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
4312 if (strstr(line, "HE80/5GHz") != NULL) {
4313 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
4314 ret = fgets(line, sizeof(line), f);
4315 } else
4316 continue;
4317 if (strstr(line, "HE160/5GHz") != NULL)
4318 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
4319 }
4320 continue;
4321 } else if (strstr(line, "WPA") != NULL) {
4322 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
4323 } else if (strstr(line, "RSN") != NULL) {
4324 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
4325 } else if (strstr(line, "Group cipher") != NULL) {
4326 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
4327 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
4328 strcpy(scan_array[index].ap_EncryptionMode, "AES");
4329 }
4330 }
4331 ret = fgets(line, sizeof(line), f);
4332 }
4333
4334 if (!filter_BSS) {
4335 *output_array_size = index + 1;
4336 } else {
4337 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
4338 *output_array_size = index;
4339 }
4340 *neighbor_ap_array = scan_array;
4341 pclose(f);
4342 free(channels_noise_arr);
4343 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4344 return RETURN_OK;
4345}
4346
4347//>> Deprecated: used for old RDKB code.
4348INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
4349{
4350 INT status = RETURN_ERR;
4351
4352 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4353 output_struct->wifi_PLCPErrorCount = 0;
4354 output_struct->wifi_FCSErrorCount = 0;
4355 output_struct->wifi_InvalidMACCount = 0;
4356 output_struct->wifi_PacketsOtherReceived = 0;
4357 output_struct->wifi_Noise = 0;
4358 status = RETURN_OK;
4359 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4360 return status;
4361}
4362
4363INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
4364{
4365 char interface_name[16] = {0};
4366 char cmd[128] = {0};
4367 char buf[1280] = {0};
4368 char *pos = NULL;
4369
4370 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4371 if (NULL == output_struct)
4372 return RETURN_ERR;
4373
4374 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4375 return RETURN_ERR;
4376
4377 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4378
4379 snprintf(cmd, sizeof(cmd), "ifconfig %s", interface_name);
4380 _syscmd(cmd, buf, sizeof(buf));
4381
4382 pos = buf;
4383 if ((pos = strstr(pos, "RX packets:")) == NULL)
4384 return RETURN_ERR;
4385 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
4386
4387 if ((pos = strstr(pos, "TX packets:")) == NULL)
4388 return RETURN_ERR;
4389 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
4390
4391 if ((pos = strstr(pos, "RX bytes:")) == NULL)
4392 return RETURN_ERR;
4393 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
4394
4395 if ((pos = strstr(pos, "TX bytes:")) == NULL)
4396 return RETURN_ERR;
4397 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
4398
4399 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l | tr -d '\n'", interface_name);
4400 _syscmd(cmd, buf, sizeof(buf));
4401 sscanf(buf, "%lu", &output_struct->wifi_Associations);
4402
4403#if 0
4404 //TODO: need to revisit below implementation
4405 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4406 char interface_name[MAX_BUF_SIZE] = {0};
4407 char interface_status[MAX_BUF_SIZE] = {0};
4408 char Value[MAX_BUF_SIZE] = {0};
4409 char buf[MAX_CMD_SIZE] = {0};
4410 char cmd[MAX_CMD_SIZE] = {0};
4411 FILE *fp = NULL;
4412
4413 if (NULL == output_struct) {
4414 return RETURN_ERR;
4415 }
4416
4417 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
4418
4419 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4420 {
4421 if(apIndex == 0) //private_wifi for 2.4G
4422 {
4423 wifi_GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4424 }
4425 else if(apIndex == 1) //private_wifi for 5G
4426 {
4427 wifi_GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4428 }
4429 else if(apIndex == 4) //public_wifi for 2.4G
4430 {
4431 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4432 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4433 {
4434 return RETURN_ERR;
4435 }
4436 if(buf[0] == '#')//tp-link
4437 wifi_GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4438 else//tenda
4439 wifi_GetInterfaceName_virtualInterfaceName_2G(interface_name);
4440 }
4441 else if(apIndex == 5) //public_wifi for 5G
4442 {
4443 wifi_GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4444 }
4445
4446 GetIfacestatus(interface_name, interface_status);
4447
4448 if(0 != strcmp(interface_status, "1"))
4449 return RETURN_ERR;
4450
4451 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4452 system(cmd);
4453
4454 fp = fopen("/tmp/SSID_Stats.txt", "r");
4455 if(fp == NULL)
4456 {
4457 printf("/tmp/SSID_Stats.txt not exists \n");
4458 return RETURN_ERR;
4459 }
4460 fclose(fp);
4461
4462 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4463 File_Reading(buf, Value);
4464 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
4465
4466 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4467 File_Reading(buf, Value);
4468 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
4469
4470 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
4471 File_Reading(buf, Value);
4472 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
4473
4474 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4475 File_Reading(buf, Value);
4476 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
4477
4478 /* There is no specific parameter from caller to associate the value wifi_Associations */
4479 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
4480 //_syscmd(cmd, buf, sizeof(buf));
4481 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
4482 }
4483#endif
4484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4485 return RETURN_OK;
4486}
4487
4488INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
4489{
4490 char interface_name[MAX_BUF_SIZE] = {0};
4491 char interface_status[MAX_BUF_SIZE] = {0};
4492 char Value[MAX_BUF_SIZE] = {0};
4493 char buf[MAX_CMD_SIZE] = {0};
4494 char cmd[MAX_CMD_SIZE] = {0};
4495 FILE *fp = NULL;
4496
4497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4498 if (NULL == output_struct)
4499 return RETURN_ERR;
4500
4501 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4502
4503 if (wifi_GetInterfaceName(apIndex,interface_name) != RETURN_OK)
4504 return RETURN_ERR;
4505 GetIfacestatus(interface_name, interface_status);
4506
4507 if(0 != strcmp(interface_status, "1"))
4508 return RETURN_ERR;
4509
4510 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4511 system(cmd);
4512
4513 fp = fopen("/tmp/SSID_Stats.txt", "r");
4514 if(fp == NULL)
4515 {
4516 printf("/tmp/SSID_Stats.txt not exists \n");
4517 return RETURN_ERR;
4518 }
4519 fclose(fp);
4520
4521 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4522 File_Reading(buf, Value);
4523 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4524
4525 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4526 File_Reading(buf, Value);
4527 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4528
4529 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4530 File_Reading(buf, Value);
4531 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4532
4533 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4534 File_Reading(buf, Value);
4535 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4536
4537 output_struct->wifi_UnicastPacketsSent = 0;
4538 output_struct->wifi_UnicastPacketsReceived = 0;
4539 output_struct->wifi_MulticastPacketsSent = 0;
4540 output_struct->wifi_MulticastPacketsReceived = 0;
4541 output_struct->wifi_BroadcastPacketsSent = 0;
4542 output_struct->wifi_BroadcastPacketsRecevied = 0;
4543 output_struct->wifi_UnknownPacketsReceived = 0;
4544
4545 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4546 return RETURN_OK;
4547}
4548
4549INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4550{
4551 INT status = RETURN_ERR;
4552
4553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4554 //Below values should get updated from hal
4555 output_struct->wifi_RetransCount=0;
4556 output_struct->wifi_FailedRetransCount=0;
4557 output_struct->wifi_RetryCount=0;
4558 output_struct->wifi_MultipleRetryCount=0;
4559 output_struct->wifi_ACKFailureCount=0;
4560 output_struct->wifi_AggregatedPacketCount=0;
4561
4562 status = RETURN_OK;
4563 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4564
4565 return status;
4566}
4567
4568INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4569{
4570 INT status = RETURN_ERR;
4571 UINT index;
4572 wifi_neighbor_ap_t *pt=NULL;
4573
4574 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4575 *output_array_size=2;
4576 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4577 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4578 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4579 strcpy(pt->ap_Radio,"");
4580 strcpy(pt->ap_SSID,"");
4581 strcpy(pt->ap_BSSID,"");
4582 strcpy(pt->ap_Mode,"");
4583 pt->ap_Channel=1;
4584 pt->ap_SignalStrength=0;
4585 strcpy(pt->ap_SecurityModeEnabled,"");
4586 strcpy(pt->ap_EncryptionMode,"");
4587 strcpy(pt->ap_OperatingFrequencyBand,"");
4588 strcpy(pt->ap_SupportedStandards,"");
4589 strcpy(pt->ap_OperatingStandards,"");
4590 strcpy(pt->ap_OperatingChannelBandwidth,"");
4591 pt->ap_BeaconPeriod=1;
4592 pt->ap_Noise=0;
4593 strcpy(pt->ap_BasicDataTransferRates,"");
4594 strcpy(pt->ap_SupportedDataTransferRates,"");
4595 pt->ap_DTIMPeriod=1;
4596 pt->ap_ChannelUtilization = 1;
4597 }
4598
4599 status = RETURN_OK;
4600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4601
4602 return status;
4603}
4604
4605//----------------- AP HAL -------------------------------
4606
4607//>> Deprecated: used for old RDKB code.
4608INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4609{
4610 if (NULL == output_ulong || NULL == output_struct)
4611 return RETURN_ERR;
4612 *output_ulong = 0;
4613 *output_struct = NULL;
4614 return RETURN_OK;
4615}
4616
4617#ifdef HAL_NETLINK_IMPL
4618static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4619 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4620 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4621 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4622 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4623 char mac_addr[20];
4624 static int count=0;
4625 int rate=0;
4626
4627 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4628
4629 nla_parse(tb,
4630 NL80211_ATTR_MAX,
4631 genlmsg_attrdata(gnlh, 0),
4632 genlmsg_attrlen(gnlh, 0),
4633 NULL);
4634
4635 if(!tb[NL80211_ATTR_STA_INFO]) {
4636 fprintf(stderr, "sta stats missing!\n");
4637 return NL_SKIP;
4638 }
4639
4640
4641 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4642 fprintf(stderr, "failed to parse nested attributes!\n");
4643 return NL_SKIP;
4644 }
4645
4646 //devIndex starts from 1
4647 if( ++count == out->wifi_devIndex )
4648 {
4649 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4650 //Getting the mac addrress
4651 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4652
4653 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4654 fprintf(stderr, "failed to parse nested rate attributes!");
4655 return NL_SKIP;
4656 }
4657
4658 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4659 if(rinfo[NL80211_RATE_INFO_BITRATE])
4660 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4661 out->wifi_devTxRate = rate/10;
4662 }
4663
4664 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4665 fprintf(stderr, "failed to parse nested rate attributes!");
4666 return NL_SKIP;
4667 }
4668
4669 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4670 if(rinfo[NL80211_RATE_INFO_BITRATE])
4671 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4672 out->wifi_devRxRate = rate/10;
4673 }
4674 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4675 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4676
4677 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4678 count = 0; //starts the count for next cycle
4679 return NL_STOP;
4680 }
4681
4682 return NL_SKIP;
4683
4684}
4685#endif
4686
4687INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4688{
4689#ifdef HAL_NETLINK_IMPL
4690 Netlink nl = {0};
4691 char if_name[10] = {0};
4692 char interface_name[16] = {0};
4693
4694 wifi_device_info_t info = {0};
4695 info.wifi_devIndex = devIndex;
4696
4697 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4698 return RETURN_ERR;
4699
4700 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4701
4702 nl.id = initSock80211(&nl);
4703
4704 if (nl.id < 0) {
4705 fprintf(stderr, "Error initializing netlink \n");
4706 return -1;
4707 }
4708
4709 struct nl_msg* msg = nlmsg_alloc();
4710
4711 if (!msg) {
4712 fprintf(stderr, "Failed to allocate netlink message.\n");
4713 nlfree(&nl);
4714 return -2;
4715 }
4716
4717 genlmsg_put(msg,
4718 NL_AUTO_PORT,
4719 NL_AUTO_SEQ,
4720 nl.id,
4721 0,
4722 NLM_F_DUMP,
4723 NL80211_CMD_GET_STATION,
4724 0);
4725
4726 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4727 nl_send_auto(nl.socket, msg);
4728 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4729 nl_recvmsgs(nl.socket, nl.cb);
4730 nlmsg_free(msg);
4731 nlfree(&nl);
4732
4733 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4734 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4735 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4736 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4737 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4738 return RETURN_OK;
4739#else
4740 //iw utility to retrieve station information
4741#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4742#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4743#define MACFILE "/tmp/wifi_AssoMac.txt"
4744#define TXRATEFILE "/tmp/wifi_txrate.txt"
4745#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4746 FILE *file = NULL;
4747 char if_name[10] = {'\0'};
4748 char pipeCmd[256] = {'\0'};
4749 char line[256] = {0};
4750 char interface_name[16] = {0};
4751 int count = 0, device = 0;
4752
4753 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
4754 return RETURN_ERR;
4755
4756 snprintf(if_name,sizeof(if_name),"%s", interface_name);
4757
4758 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4759 file = popen(pipeCmd, "r");
4760
4761 if(file == NULL)
4762 return RETURN_ERR; //popen failed
4763
4764 fgets(line, sizeof line, file);
4765 device = atoi(line);
4766 pclose(file);
4767
4768 if(device == 0)
4769 return RETURN_ERR; //No devices are connected
4770
4771 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4772 system(pipeCmd);
4773
4774 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4775
4776 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4777
4778 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4779
4780 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4781
4782 //devIndex starts from 1, ++count
4783 if((file = fopen(SIGNALFILE, "r")) != NULL )
4784 {
4785 for(count =0;fgets(line, sizeof line, file) != NULL;)
4786 {
4787 if (++count == devIndex)
4788 {
4789 output_struct->wifi_devSignalStrength = atoi(line);
4790 break;
4791 }
4792 }
4793 fclose(file);
4794 }
4795 else
4796 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4797
4798 if((file = fopen(MACFILE, "r")) != NULL )
4799 {
4800 for(count =0;fgets(line, sizeof line, file) != NULL;)
4801 {
4802 if (++count == devIndex)
4803 {
4804 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]);
4805 break;
4806 }
4807 }
4808 fclose(file);
4809 }
4810 else
4811 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4812
4813 if((file = fopen(TXRATEFILE, "r")) != NULL )
4814 {
4815 for(count =0;fgets(line, sizeof line, file) != NULL;)
4816 {
4817 if (++count == devIndex)
4818 {
4819 output_struct->wifi_devTxRate = atoi(line);
4820 break;
4821 }
4822 }
4823 fclose(file);
4824 }
4825 else
4826 fprintf(stderr,"fopen wifi_txrate.txt failed");
4827
4828 if((file = fopen(RXRATEFILE, "r")) != NULL)
4829 {
4830 for(count =0;fgets(line, sizeof line, file) != NULL;)
4831 {
4832 if (++count == devIndex)
4833 {
4834 output_struct->wifi_devRxRate = atoi(line);
4835 break;
4836 }
4837 }
4838 fclose(file);
4839 }
4840 else
4841 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4842
4843 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4844
4845 return RETURN_OK;
4846#endif
4847}
4848
4849INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4850{
4851 if (NULL == device)
4852 return RETURN_ERR;
4853 return RETURN_OK;
4854}
4855//<<
4856
4857
4858//--------------wifi_ap_hal-----------------------------
4859//enables CTS protection for the radio used by this AP
4860INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4861{
4862 //save config and Apply instantly
4863 return RETURN_ERR;
4864}
4865
4866// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4867INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4868{
4869 char config_file[64] = {'\0'};
4870 char buf[64] = {'\0'};
4871 struct params list;
4872
4873 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4874 list.name = "ht_coex";
4875 snprintf(buf, sizeof(buf), "%d", enable);
4876 list.value = buf;
4877
4878 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4879 wifi_hostapdWrite(config_file, &list, 1);
4880 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4881
4882 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4883
4884 return RETURN_OK;
4885}
4886
4887//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4888INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4889{
4890 char config_file[MAX_BUF_SIZE] = {'\0'};
4891 char buf[MAX_BUF_SIZE] = {'\0'};
4892 struct params list;
4893
4894 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4895 if (threshold < 256 || threshold > 2346 )
4896 return RETURN_ERR;
4897 list.name = "fragm_threshold";
4898 snprintf(buf, sizeof(buf), "%d", threshold);
4899 list.value = buf;
4900
4901 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4902 wifi_hostapdWrite(config_file, &list, 1);
4903 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4904
4905 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4906
4907 return RETURN_OK;
4908}
4909
4910// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4911INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4912{
4913 char config_file[64] = {'\0'};
4914 char cmd[512] = {'\0'};
4915 char buf[512] = {'\0'};
4916 char stbc_config[16] = {'\0'};
4917 wifi_band band;
4918 int iterator = 0;
4919 BOOL current_stbc = FALSE;
4920 int ant_count = 0;
4921 int ant_bitmap = 0;
4922 struct params list;
4923
4924 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4925
4926 band = wifi_index_to_band(radioIndex);
4927 if (band == band_invalid)
4928 return RETURN_ERR;
4929
4930 if (band == band_2_4)
4931 iterator = 1;
4932 else if (band == band_5)
4933 iterator = 2;
4934 else
4935 return RETURN_OK;
4936
4937 wifi_getRadioTxChainMask(radioIndex, &ant_bitmap);
4938 for (; ant_bitmap > 0; ant_bitmap >>= 1)
4939 ant_count += ant_bitmap & 1;
4940
4941 if (ant_count == 1 && STBC_Enable == TRUE) {
4942 fprintf(stderr, "%s: can not enable STBC when using only one antenna\n", __func__);
4943 return RETURN_OK;
4944 }
4945
4946 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4947
4948 // set ht and vht config
4949 for (int i = 0; i < iterator; i++) {
4950 memset(stbc_config, 0, sizeof(stbc_config));
4951 memset(cmd, 0, sizeof(cmd));
4952 memset(buf, 0, sizeof(buf));
4953 list.name = (i == 0)?"ht_capab":"vht_capab";
4954 snprintf(stbc_config, sizeof(stbc_config), "%s", list.name);
4955 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4956 _syscmd(cmd, buf, sizeof(buf));
4957 if (strlen(buf) != 0)
4958 current_stbc = TRUE;
4959 if (current_stbc == STBC_Enable)
4960 continue;
4961
4962 if (STBC_Enable == TRUE) {
4963 // Append the STBC flags in capab config
4964 memset(cmd, 0, sizeof(cmd));
4965 if (i == 0)
4966 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4967 else
4968 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4969 _syscmd(cmd, buf, sizeof(buf));
4970 } else if (STBC_Enable == FALSE) {
4971 // Remove the STBC flags and remain other flags in capab
4972 memset(cmd, 0, sizeof(cmd));
4973 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4974 _syscmd(cmd, buf, sizeof(buf));
4975 memset(cmd, 0, sizeof(cmd));
4976 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4977 _syscmd(cmd, buf, sizeof(buf));
4978 }
4979 wifi_hostapdRead(config_file, list.name, buf, sizeof(buf));
4980 list.value = buf;
4981 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
4982 }
4983
4984 wifi_reloadAp(radioIndex);
4985
4986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4987 return RETURN_OK;
4988}
4989
4990// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4991INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4992{
4993 char cmd[128] = {0};
4994 char buf[128] = {0};
4995 char interface_name[16] = {0};
4996
4997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4998
4999 if(output_bool == NULL)
5000 return RETURN_ERR;
5001
5002 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5003 return RETURN_ERR;
5004
5005 sprintf(cmd, "hostapd_cli -i %s get_amsdu | awk '{print $3}'", interface_name);
5006 _syscmd(cmd, buf, sizeof(buf));
5007
5008 if (strncmp(buf, "1", 1) == 0)
5009 *output_bool = TRUE;
5010 else
5011 *output_bool = FALSE;
5012
5013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5014 return RETURN_OK;
5015}
5016
5017// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
5018INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
5019{
5020 char config_file[128] = {0};
5021 struct params list = {0};
5022 BOOL enable;
5023
5024 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5025
5026 if (wifi_getRadioAMSDUEnable(radioIndex, &enable) != RETURN_OK)
5027 return RETURN_ERR;
5028
5029 if (amsduEnable == enable)
5030 return RETURN_OK;
5031
5032 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5033 list.name = "amsdu";
5034 list.value = amsduEnable? "1":"0";
5035 wifi_hostapdWrite(config_file, &list, 1);
5036 wifi_hostapdProcessUpdate(radioIndex, &list, 1);
5037 wifi_reloadAp(radioIndex);
5038
5039 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5040 return RETURN_OK;
5041}
5042
5043//P2 // outputs the number of Tx streams
5044INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
5045{
5046 char buf[8] = {0};
5047 char cmd[128] = {0};
5048 int phyId = 0;
5049
5050 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5051
5052 phyId = radio_index_to_phy(radioIndex);
5053 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'Configured Antennas' | awk '{print $4}'", phyId);
5054 _syscmd(cmd, buf, sizeof(buf));
5055
5056 *output_int = (INT)strtol(buf, NULL, 16);
5057
5058 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5059
5060 return RETURN_OK;
5061}
5062
5063INT fitChainMask(INT radioIndex, int antcount)
5064{
5065 char buf[128] = {0};
5066 char cmd[128] = {0};
5067 char config_file[64] = {0};
5068 wifi_band band;
5069 struct params list[2] = {0};
5070
5071 band = wifi_index_to_band(radioIndex);
5072 if (band == band_invalid)
5073 return RETURN_ERR;
5074
5075 list[0].name = "he_mu_beamformer";
5076 list[1].name = "he_su_beamformer";
5077
5078 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
5079 if (antcount == 1) {
5080 // remove config about multiple antennas
5081 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
5082 _syscmd(cmd, buf, sizeof(buf));
5083
5084 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SOUNDING-DIMENSION-.\\]//' %s", config_file);
5085 _syscmd(cmd, buf, sizeof(buf));
5086
5087 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SU-BEAMFORMER\\]//' %s", config_file);
5088 _syscmd(cmd, buf, sizeof(buf));
5089
5090 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[MU-BEAMFORMER\\]//' %s", config_file);
5091 _syscmd(cmd, buf, sizeof(buf));
5092
5093 list[0].value = "0";
5094 list[1].value = "0";
5095 } else {
5096 // 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.
5097 if (band == band_2_4 || band == band_5) {
5098 snprintf(cmd, sizeof(cmd), "cat %s | grep '^ht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5099 _syscmd(cmd, buf, sizeof(buf));
5100 if (strlen(buf) > 0) {
5101 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[TX-STBC]/' %s", config_file);
5102 _syscmd(cmd, buf, sizeof(buf));
5103 }
5104 }
5105 if (band == band_5) {
5106 snprintf(cmd, sizeof(cmd), "cat %s | grep '^vht_capab=.*RX-STBC' | grep -v 'TX-STBC'", config_file);
5107 _syscmd(cmd, buf, sizeof(buf));
5108 if (strlen(buf) > 0) {
5109 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1]/' %s", config_file);
5110 _syscmd(cmd, buf, sizeof(buf));
5111 }
5112 }
5113
5114 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SU-BEAMFORMER\\]'", config_file);
5115 _syscmd(cmd, buf, sizeof(buf));
5116 if (strlen(buf) == 0) {
5117 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SU-BEAMFORMER]/' %s", config_file);
5118 _syscmd(cmd, buf, sizeof(buf));
5119 }
5120
5121 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[MU-BEAMFORMER\\]'", config_file);
5122 _syscmd(cmd, buf, sizeof(buf));
5123 if (strlen(buf) == 0) {
5124 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[MU-BEAMFORMER]/' %s", config_file);
5125 _syscmd(cmd, buf, sizeof(buf));
5126 }
5127
5128 snprintf(cmd, sizeof(cmd), "cat %s | grep '\\[SOUNDING-DIMENSION-.\\]'", config_file);
5129 _syscmd(cmd, buf, sizeof(buf));
5130 if (strlen(buf) == 0) {
5131 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SOUNDING-DIMENSION-%d]/' %s", antcount, config_file);
5132 } else {
5133 snprintf(cmd, sizeof(cmd), "sed -r -i 's/(SOUNDING-DIMENSION-)./\\1%d/' %s", antcount, config_file);
5134 }
5135 _syscmd(cmd, buf, sizeof(buf));
5136
5137 list[0].value = "1";
5138 list[1].value = "1";
5139 }
5140 wifi_hostapdWrite(config_file, list, 2);
5141}
5142
5143//P2 // sets the number of Tx streams to an enviornment variable
5144INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
5145{
5146 char cmd[128] = {0};
5147 char buf[128] = {0};
5148 int phyId = 0;
5149 int cur_mask = 0;
5150 int antcount = 0;
5151 wifi_band band;
5152
5153 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5154
5155 if (numStreams <= 0) {
5156 fprintf(stderr, "%s: chainmask is not supported %d.\n", __func__, numStreams);
5157 return RETURN_ERR;
5158 }
5159
5160 wifi_getRadioTxChainMask(radioIndex, &cur_mask);
5161 if (cur_mask == numStreams)
5162 return RETURN_OK;
5163
5164 wifi_setRadioEnable(radioIndex, FALSE);
5165
5166 phyId = radio_index_to_phy(radioIndex);
5167 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", phyId, numStreams);
5168 _syscmd(cmd, buf, sizeof(buf));
5169
5170 if (strlen(buf) > 0) {
5171 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
5172 return RETURN_ERR;
5173 }
5174
5175 // if chain mask changed, we need to make the hostapd config valid.
5176 for (cur_mask = numStreams; cur_mask > 0; cur_mask >>= 1) {
5177 antcount += cur_mask & 1;
5178 }
5179 fitChainMask(radioIndex, antcount);
5180
5181 wifi_setRadioEnable(radioIndex, TRUE);
5182
5183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5184 return RETURN_OK;
5185}
5186
5187//P2 // outputs the number of Rx streams
5188INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
5189{
5190 char buf[8] = {0};
5191 char cmd[128] = {0};
5192 int phyId = 0;
5193
5194 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5195
5196 phyId = radio_index_to_phy(radioIndex);
5197 sprintf(cmd, "iw phy%d info | grep 'Configured Antennas' | awk '{print $6}'", phyId);
5198 _syscmd(cmd, buf, sizeof(buf));
5199
5200 *output_int = (INT)strtol(buf, NULL, 16);
5201
5202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5203
5204 return RETURN_OK;
5205}
5206
5207//P2 // sets the number of Rx streams to an enviornment variable
5208INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
5209{
5210 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5211 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
5212 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
5213 return RETURN_ERR;
5214 }
5215 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5216 return RETURN_ERR;
5217}
5218
5219//Get radio RDG enable setting
5220INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
5221{
5222 if (NULL == output_bool)
5223 return RETURN_ERR;
5224 *output_bool = TRUE;
5225 return RETURN_OK;
5226}
5227
5228//Get radio RDG enable setting
5229INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
5230{
5231 if (NULL == output_bool)
5232 return RETURN_ERR;
5233 *output_bool = TRUE;
5234 return RETURN_OK;
5235}
5236
5237//Set radio RDG enable setting
5238INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
5239{
5240 return RETURN_ERR;
5241}
5242
5243//Get radio ADDBA enable setting
5244INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
5245{
5246 if (NULL == output_bool)
5247 return RETURN_ERR;
5248 *output_bool = TRUE;
5249 return RETURN_OK;
5250}
5251
5252//Set radio ADDBA enable setting
5253INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
5254{
5255 return RETURN_ERR;
5256}
5257
5258//Get radio auto block ack enable setting
5259INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
5260{
5261 if (NULL == output_bool)
5262 return RETURN_ERR;
5263 *output_bool = TRUE;
5264 return RETURN_OK;
5265}
5266
5267//Set radio auto block ack enable setting
5268INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
5269{
5270 return RETURN_ERR;
5271}
5272
5273//Get radio 11n pure mode enable support
5274INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
5275{
5276 if (NULL == output_bool)
5277 return RETURN_ERR;
5278 *output_bool = TRUE;
5279 return RETURN_OK;
5280}
5281
5282//Get radio 11n pure mode enable setting
5283INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
5284{
5285 if (NULL == output_bool)
5286 return RETURN_ERR;
5287 *output_bool = TRUE;
5288 return RETURN_OK;
5289}
5290
5291//Set radio 11n pure mode enable setting
5292INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
5293{
5294 return RETURN_ERR;
5295}
5296
5297//Get radio IGMP snooping enable setting
5298INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
5299{
5300 char interface_name[16] = {0};
5301 char cmd[128]={0};
5302 char buf[4]={0};
5303 bool bridge = FALSE, mac80211 = FALSE;
5304 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5305
5306 if(output_bool == NULL)
5307 return RETURN_ERR;
5308
5309 *output_bool = FALSE;
5310
5311 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
5312 _syscmd(cmd, buf, sizeof(buf));
5313 if (strncmp(buf, "1", 1) == 0)
5314 bridge = TRUE;
5315
5316 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
5317 return RETURN_ERR;
5318 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", BRIDGE_NAME, interface_name);
5319 _syscmd(cmd, buf, sizeof(buf));
5320 if (strncmp(buf, "1", 1) == 0)
5321 mac80211 = TRUE;
5322
5323 if (bridge && mac80211)
5324 *output_bool = TRUE;
5325
5326 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5327 return RETURN_OK;
5328}
5329
5330//Set radio IGMP snooping enable setting
5331INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
5332{
5333 char interface_name[16] = {0};
5334 char cmd[128]={0};
5335 char buf[4]={0};
5336 int max_num_radios =0;
5337 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5338
5339 // bridge
5340 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
5341 _syscmd(cmd, buf, sizeof(buf));
5342
5343 wifi_getMaxRadioNumber(&max_num_radios);
5344 // mac80211
5345 for (int i = 0; i < max_num_radios; i++) {
5346 if (wifi_GetInterfaceName(i, interface_name) != RETURN_OK)
5347 return RETURN_ERR;
5348 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s/multicast_to_unicast", enable, BRIDGE_NAME, interface_name);
5349 _syscmd(cmd, buf, sizeof(buf));
5350 }
5351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5352 return RETURN_OK;
5353}
5354
5355//Get the Reset count of radio
developer69b61b02023-03-07 17:17:44 +08005356INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
developer72fb0bb2023-01-11 09:46:29 +08005357{
developer69b61b02023-03-07 17:17:44 +08005358 if (NULL == output_int)
developer72fb0bb2023-01-11 09:46:29 +08005359 return RETURN_ERR;
5360 *output_int = (radioIndex==0)? 1: 3;
5361
5362 return RETURN_OK;
5363}
5364
5365
5366//---------------------------------------------------------------------------------------------------
5367//
5368// Additional Wifi AP level APIs used for Access Point devices
5369//
5370//---------------------------------------------------------------------------------------------------
5371
5372// creates a new ap and pushes these parameters to the hardware
5373INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
5374{
5375 // Deprecated when use hal version 3, use wifi_createVap() instead.
5376 return RETURN_OK;
5377}
5378
5379// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
5380INT wifi_deleteAp(INT apIndex)
5381{
5382 char interface_name[16] = {0};
5383 char buf[1024];
5384 char cmd[128];
5385
5386 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5387 return RETURN_ERR;
developer8a3bbbf2023-03-15 17:47:23 +08005388
5389 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
developer72fb0bb2023-01-11 09:46:29 +08005390 _syscmd(cmd, buf, sizeof(buf));
5391
5392 wifi_removeApSecVaribles(apIndex);
5393
5394 return RETURN_OK;
5395}
5396
5397// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
5398INT wifi_getApName(INT apIndex, CHAR *output_string)
5399{
5400 char interface_name[16] = {0};
5401 if(NULL == output_string)
5402 return RETURN_ERR;
5403
5404 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5405 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex); // For wifiagent generating data model.
5406 else
5407 snprintf(output_string, 16, "%s", interface_name);
5408 return RETURN_OK;
5409}
5410
5411// Outputs the index number in that corresponds to the SSID string
5412INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
5413{
5414 char cmd [128] = {0};
5415 char buf[32] = {0};
5416 char *apIndex_str = NULL;
5417 bool enable = FALSE;
5418
5419 snprintf(cmd, sizeof(cmd), "grep -rn ^interface=%s$ /nvram/hostapd*.conf | cut -d '.' -f1 | cut -d 'd' -f2 | tr -d '\\n'", inputSsidString);
5420 _syscmd(cmd, buf, sizeof(buf));
5421
5422 if (strlen(buf) != 0) {
5423 apIndex_str = strtok(buf, "\n");
5424 *output_int = strtoul(apIndex_str, NULL, 10);
5425 return RETURN_OK;
5426 }
5427
5428 // If interface name is not in hostapd config, the caller maybe wifi agent to generate data model.
5429 apIndex_str = strstr(inputSsidString, AP_PREFIX);
5430 if (apIndex_str) {
5431 sscanf(apIndex_str + strlen(AP_PREFIX), "%d", output_int);
5432 return RETURN_OK;
5433 }
5434 *output_int = -1;
5435 return RETURN_OK;
5436}
5437
5438INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
5439{
5440 return wifi_getIndexFromName(inputSsidString, output_int);
5441}
5442
5443// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
5444INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
5445{
5446 char buf[MAX_BUF_SIZE] = {0};
5447 char cmd[MAX_CMD_SIZE] = {0};
5448 char config_file[MAX_BUF_SIZE] = {0};
5449
5450 if(NULL == output_string)
5451 return RETURN_ERR;
5452
5453 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5454 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
5455 if((strcmp(buf,"3")==0))
5456 snprintf(output_string, 32, "WPAand11i");
5457 else if((strcmp(buf,"2")==0))
5458 snprintf(output_string, 32, "11i");
5459 else if((strcmp(buf,"1")==0))
5460 snprintf(output_string, 32, "WPA");
5461 else
5462 snprintf(output_string, 32, "None");
5463
5464 return RETURN_OK;
5465}
5466
5467// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
5468INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
5469{
5470 char config_file[MAX_BUF_SIZE] = {0};
5471 struct params list;
5472
5473 if (NULL == beaconTypeString)
5474 return RETURN_ERR;
5475 list.name = "wpa";
5476 list.value = "0";
5477
5478 if((strcmp(beaconTypeString,"WPAand11i")==0))
5479 list.value="3";
5480 else if((strcmp(beaconTypeString,"11i")==0))
5481 list.value="2";
5482 else if((strcmp(beaconTypeString,"WPA")==0))
5483 list.value="1";
5484
5485 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5486 wifi_hostapdWrite(config_file, &list, 1);
5487 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5488 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
5489 return RETURN_OK;
5490}
5491
5492// sets the beacon interval on the hardware for this AP
5493INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
5494{
5495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5496 struct params params={'\0'};
5497 char buf[MAX_BUF_SIZE] = {'\0'};
5498 char config_file[MAX_BUF_SIZE] = {'\0'};
5499
5500 params.name = "beacon_int";
5501 snprintf(buf, sizeof(buf), "%u", beaconInterval);
5502 params.value = buf;
5503
5504 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5505 wifi_hostapdWrite(config_file, &params, 1);
developer69b61b02023-03-07 17:17:44 +08005506
developer72fb0bb2023-01-11 09:46:29 +08005507 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5509 return RETURN_OK;
5510}
5511
5512INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
5513{
5514 if (wifi_setApDTIMInterval(apIndex, dtimInterval) != RETURN_OK)
5515 return RETURN_ERR;
5516 return RETURN_OK;
5517}
5518
5519// Get the packet size threshold supported.
5520INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
5521{
5522 //save config and apply instantly
5523 if (NULL == output_bool)
5524 return RETURN_ERR;
5525 *output_bool = TRUE;
5526 return RETURN_OK;
5527}
5528
5529// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
5530INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
5531{
developer72fb0bb2023-01-11 09:46:29 +08005532 char buf[16] = {0};
5533 char config_file[128] = {0};
5534 struct params param = {0};
5535
5536 if (threshold > 65535) {
5537 fprintf(stderr, "%s: rts threshold %u is too big.\n", __func__, threshold);
5538 return RETURN_ERR;
5539 }
5540
developer23e71282023-01-18 10:25:19 +08005541 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08005542 snprintf(buf, sizeof(buf), "%u", threshold);
5543 param.name = "rts_threshold";
5544 param.value = buf;
5545 wifi_hostapdWrite(config_file, &param, 1);
5546 wifi_hostapdProcessUpdate(apIndex, &param, 1);
5547 wifi_reloadAp(apIndex);
5548
5549 return RETURN_OK;
5550}
5551
5552// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5553INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
5554{
5555 if (NULL == output_string)
5556 return RETURN_ERR;
5557 snprintf(output_string, 32, "TKIPandAESEncryption");
5558 return RETURN_OK;
5559
5560}
5561
5562// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5563INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
5564{
5565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5566 char *param_name = NULL;
5567 char buf[32] = {0}, config_file[MAX_BUF_SIZE] = {0};
5568
5569 if(NULL == output_string)
5570 return RETURN_ERR;
5571
5572 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5573 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
5574
5575 if(strcmp(buf,"0")==0)
5576 {
5577 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
5578 snprintf(output_string, 32, "None");
5579 return RETURN_OK;
5580 }
5581 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
5582 param_name = "rsn_pairwise";
5583 else if((strcmp(buf,"1")==0))
5584 param_name = "wpa_pairwise";
5585 else
5586 return RETURN_ERR;
5587 memset(output_string,'\0',32);
5588 wifi_hostapdRead(config_file,param_name,output_string,32);
5589 if (strlen(output_string) == 0) { // rsn_pairwise is optional. When it is empty use wpa_pairwise instead.
5590 param_name = "wpa_pairwise";
5591 memset(output_string, '\0', 32);
5592 wifi_hostapdRead(config_file, param_name, output_string, 32);
5593 }
5594 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
5595
5596 if(strcmp(output_string,"TKIP") == 0)
5597 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
5598 else if(strcmp(output_string,"CCMP") == 0)
5599 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
5600 else if(strcmp(output_string,"TKIP CCMP") == 0)
5601 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
5602
5603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5604 return RETURN_OK;
5605}
5606
5607// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
5608INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
5609{
5610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5611 struct params params={'\0'};
5612 char output_string[32];
5613 char config_file[MAX_BUF_SIZE] = {0};
5614
5615 memset(output_string,'\0',32);
5616 wifi_getApWpaEncryptionMode(apIndex,output_string);
5617
5618 if(strcmp(encMode, "TKIPEncryption") == 0)
5619 params.value = "TKIP";
5620 else if(strcmp(encMode,"AESEncryption") == 0)
5621 params.value = "CCMP";
5622 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5623 params.value = "TKIP CCMP";
5624
5625 if((strcmp(output_string,"WPAand11i")==0))
5626 {
5627 params.name = "wpa_pairwise";
5628 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5629 wifi_hostapdWrite(config_file, &params, 1);
5630 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5631
5632 params.name = "rsn_pairwise";
5633 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5634 wifi_hostapdWrite(config_file, &params, 1);
5635 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5636
5637 return RETURN_OK;
5638 }
5639 else if((strcmp(output_string,"11i")==0))
5640 {
5641 params.name = "rsn_pairwise";
5642 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5643 wifi_hostapdWrite(config_file, &params, 1);
5644 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5645 return RETURN_OK;
5646 }
5647 else if((strcmp(output_string,"WPA")==0))
5648 {
5649 params.name = "wpa_pairwise";
5650 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5651 wifi_hostapdWrite(config_file, &params, 1);
5652 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5653 return RETURN_OK;
5654 }
5655
5656 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5657 return RETURN_OK;
5658}
5659
5660// deletes internal security varable settings for this ap
5661INT wifi_removeApSecVaribles(INT apIndex)
5662{
5663 //TODO: remove the entry in hostapd config file
5664 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s.conf//g' /tmp/conf_filename", interface_name);
5665 //_syscmd(cmd, buf, sizeof(buf));
5666
5667 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s//g' /tmp/conf_filename", interface_name);
5668 //_syscmd(cmd, buf, sizeof(buf));
5669 return RETURN_ERR;
5670}
5671
5672// changes the hardware settings to disable encryption on this ap
5673INT wifi_disableApEncryption(INT apIndex)
5674{
5675 //Apply instantly
5676 return RETURN_ERR;
5677}
5678
5679// set the authorization mode on this ap
5680// mode mapping as: 1: open, 2: shared, 4:auto
5681INT wifi_setApAuthMode(INT apIndex, INT mode)
5682{
5683 struct params params={0};
5684 char config_file[64] = {0};
5685 int ret;
5686
5687 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5688
5689 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5690 params.name = "auth_algs";
5691
5692 if (mode & 1 && mode & 2)
5693 params.value = "3";
5694 else if (mode & 2)
5695 params.value = "2";
5696 else if (mode & 1)
5697 params.value = "1";
5698 else
5699 params.value = "0";
5700
5701 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5702 wifi_hostapdWrite(config_file, &params, 1);
5703 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5705
5706 return RETURN_OK;
5707}
5708
5709// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5710INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5711{
5712 //save to wifi config, and wait for wifi restart to apply
5713 struct params params={'\0'};
5714 char config_file[MAX_BUF_SIZE] = {0};
5715 int ret;
5716
5717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5718 if(authMode == NULL)
5719 return RETURN_ERR;
5720
5721 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5722 params.name = "wpa_key_mgmt";
5723
5724 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5725 params.value = "WPA-PSK";
5726 else if(strcmp(authMode,"EAPAuthentication") == 0)
5727 params.value = "WPA-EAP";
5728 else if (strcmp(authMode, "SAEAuthentication") == 0)
5729 params.value = "SAE";
5730 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5731 params.value = "WPA-EAP-SUITE-B-192";
5732 else if (strcmp(authMode, "PSK-SAEAuthentication") == 0)
5733 params.value = "WPA-PSK WPA-PSK-SHA256 SAE";
developer3086e2f2023-01-17 09:40:01 +08005734 else if (strcmp(authMode, "Enhanced_Open") == 0)
5735 params.value = "OWE";
developer72fb0bb2023-01-11 09:46:29 +08005736 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5737 return RETURN_OK; //This is taken careof in beaconType
5738
5739 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5740 ret=wifi_hostapdWrite(config_file,&params,1);
5741 if(!ret)
5742 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5744
5745 return ret;
5746}
5747
5748// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5749INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5750{
5751 //save to wifi config, and wait for wifi restart to apply
5752 char BeaconType[50] = {0};
5753 char config_file[MAX_BUF_SIZE] = {0};
5754
5755 *authMode = 0;
5756 wifi_getApBeaconType(apIndex,BeaconType);
5757 printf("%s____%s \n",__FUNCTION__,BeaconType);
5758
5759 if(strcmp(BeaconType,"None") == 0)
5760 strcpy(authMode,"None");
5761 else
5762 {
5763 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5764 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5765 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5766 if(strcmp(authMode,"WPA-PSK") == 0)
5767 strcpy(authMode,"SharedAuthentication");
5768 else if(strcmp(authMode,"WPA-EAP") == 0)
5769 strcpy(authMode,"EAPAuthentication");
5770 }
5771
5772 return RETURN_OK;
5773}
5774
5775// Outputs the number of stations associated per AP
5776INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5777{
5778 char interface_name[16] = {0};
5779 char cmd[128]={0};
5780 char buf[128]={0};
5781 BOOL status = false;
5782
5783 if(apIndex > MAX_APS)
5784 return RETURN_ERR;
5785
5786 wifi_getApEnable(apIndex,&status);
5787 if (!status)
5788 return RETURN_OK;
5789
5790 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);//alternate method
5791 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5792 return RETURN_ERR;
5793 sprintf(cmd, "hostapd_cli -i %s list_sta | wc -l", interface_name);
5794 _syscmd(cmd, buf, sizeof(buf));
5795 sscanf(buf,"%lu", output_ulong);
5796
5797 return RETURN_OK;
5798}
5799
5800// manually removes any active wi-fi association with the device specified on this ap
5801INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5802{
5803 char interface_name[16] = {0};
5804 char buf[126]={'\0'};
5805
5806 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5807 return RETURN_ERR;
5808 sprintf(buf,"hostapd_cli -i%s disassociate %s", interface_name, client_mac);
5809 system(buf);
5810
5811 return RETURN_OK;
5812}
5813
5814// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5815INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5816{
5817 if(NULL == output_int)
5818 return RETURN_ERR;
5819 int max_radio_num = 0;
5820 wifi_getMaxRadioNumber(&max_radio_num);
5821 *output_int = apIndex%max_radio_num;
5822 return RETURN_OK;
5823}
5824
5825// sets the radio index for the specific ap
5826INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5827{
5828 //set to config only and wait for wifi reset to apply settings
5829 return RETURN_ERR;
5830}
5831
5832// Get the ACL MAC list per AP
5833INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5834{
5835 char interface_name[16] = {0};
5836 char cmd[MAX_CMD_SIZE]={'\0'};
5837 int ret = 0;
5838
5839 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5840 return RETURN_ERR;
5841 sprintf(cmd, "hostapd_cli -i %s accept_acl SHOW | awk '{print $1}'", interface_name);
5842 ret = _syscmd(cmd,macArray,buf_size);
5843 if (ret != 0)
5844 return RETURN_ERR;
5845
5846 return RETURN_OK;
5847}
5848
5849INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5850{
5851 char interface_name[16] = {0};
5852 char cmd[MAX_CMD_SIZE]={'\0'};
5853 int ret = 0;
5854
5855 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5856 return RETURN_ERR;
5857 sprintf(cmd, "hostapd_cli -i %s deny_acl SHOW | awk '{print $1}'", interface_name);
5858 ret = _syscmd(cmd,macArray,buf_size);
5859 if (ret != 0)
5860 return RETURN_ERR;
5861
5862 return RETURN_OK;
5863}
5864
5865
5866// Get the list of stations associated per AP
5867INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5868{
5869 char interface_name[16] = {0};
5870 char cmd[128];
5871
5872 if(apIndex > 3) //Currently supporting apIndex upto 3
5873 return RETURN_ERR;
5874 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
5875 return RETURN_ERR;
5876 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
5877 //sprintf(buf,"iw dev %s station dump | grep Station | cut -d ' ' -f2", interface_name);//alternate method
5878 _syscmd(cmd, macArray, buf_size);
5879
5880 return RETURN_OK;
5881}
5882
5883// adds the mac address to the filter list
5884//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5885INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5886{
5887 char cmd[MAX_CMD_SIZE]={'\0'};
5888 char buf[MAX_BUF_SIZE]={'\0'};
5889
5890#if 0
5891 sprintf(cmd, "hostapd_cli -i %s accept_acl ADD_MAC %s", interface_name,DeviceMacAddress);
5892 if(_syscmd(cmd,buf,sizeof(buf)))
5893 return RETURN_ERR;
5894#endif
5895 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5896 if(_syscmd(cmd,buf,sizeof(buf)))
5897 return RETURN_ERR;
5898
5899 return RETURN_OK;
5900}
5901
5902// deletes the mac address from the filter list
5903//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5904INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5905{
5906 char cmd[MAX_CMD_SIZE]={'\0'};
5907 char buf[MAX_BUF_SIZE]={'\0'};
5908
5909#if 0
5910 sprintf(cmd, "hostapd_cli -i %s accept_acl DEL_MAC %s", interface_name,DeviceMacAddress);
5911 if(_syscmd(cmd,buf,sizeof(buf)))
5912 return RETURN_ERR;
5913
5914#endif
5915 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5916 if(_syscmd(cmd,buf,sizeof(buf)))
5917 return RETURN_ERR;
5918
5919 return RETURN_OK;
5920}
5921
5922// outputs the number of devices in the filter list
5923INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5924{
5925 char cmd[MAX_BUF_SIZE]={0};
5926 char buf[MAX_CMD_SIZE]={0};
5927
5928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5929 if(output_uint == NULL)
5930 return RETURN_ERR;
5931
5932 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5933 _syscmd(cmd, buf, sizeof(buf));
5934
5935 *output_uint = atoi(buf);
5936
5937 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5938 return RETURN_OK;
5939}
5940
5941INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5942{
5943 char cmd[128]={'\0'};
5944 char buf[128]={'\0'};
5945
5946 if(strcmp(action,"DENY")==0)
5947 {
5948 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5949 system(buf);
5950 return RETURN_OK;
5951 }
5952
5953 if(strcmp(action,"ALLOW")==0)
5954 {
5955 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5956 system(buf);
5957 return RETURN_OK;
5958 }
5959
5960 return RETURN_ERR;
5961
5962}
5963
5964// enable kick for devices on acl black list
5965INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5966{
5967 char aclArray[512] = {0}, *acl = NULL;
5968 char assocArray[512] = {0}, *asso = NULL;
5969
5970 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
5971 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5972
5973 // if there are no devices connected there is nothing to do
5974 if (strlen(assocArray) < 17)
5975 return RETURN_OK;
5976
5977 if (enable == TRUE)
5978 {
5979 //kick off the MAC which is in ACL array (deny list)
5980 acl = strtok(aclArray, "\r\n");
5981 while (acl != NULL) {
5982 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5983 wifi_kickApAssociatedDevice(apIndex, acl);
5984
5985 acl = strtok(NULL, "\r\n");
5986 }
5987 wifi_setApMacAddressControlMode(apIndex, 2);
5988 }
5989 else
5990 {
5991 wifi_setApMacAddressControlMode(apIndex, 0);
5992 }
5993
5994#if 0
5995 //TODO: need to revisit below implementation
5996 char aclArray[512]={0}, *acl=NULL;
5997 char assocArray[512]={0}, *asso=NULL;
5998 char buf[256]={'\0'};
5999 char action[10]={'\0'};
6000 FILE *fr=NULL;
6001 char interface[10]={'\0'};
6002 char config_file[MAX_BUF_SIZE] = {0};
6003
6004 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
6005 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
6006 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6007 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
6008
6009 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6010 system(buf);
6011 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
6012 system(buf);
6013 sprintf(buf,"iptables -X WifiServices%d",apIndex);
6014 system(buf);
6015 sprintf(buf,"iptables -N WifiServices%d",apIndex);
6016 system(buf);
6017 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
6018 system(buf);
6019
6020 if ( enable == TRUE )
6021 {
6022 int device_count=0;
6023 strcpy(action,"DENY");
6024 //kick off the MAC which is in ACL array (deny list)
6025 acl = strtok (aclArray,",");
6026 while (acl != NULL) {
6027 if(strlen(acl)>=17)
6028 {
6029 apply_rules(apIndex, acl,action,interface);
6030 device_count++;
developer69b61b02023-03-07 17:17:44 +08006031 //Register mac to be blocked ,in syscfg.db persistent storage
developer72fb0bb2023-01-11 09:46:29 +08006032 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
6033 system(buf);
6034 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
6035 system(buf);
6036 system("syscfg commit");
6037
6038 wifi_kickApAssociatedDevice(apIndex, acl);
6039 }
6040 acl = strtok (NULL, ",");
6041 }
6042 }
6043 else
6044 {
6045 int device_count=0;
6046 char cmdmac[20]={'\0'};
6047 strcpy(action,"ALLOW");
6048 //kick off the MAC which is not in ACL array (allow list)
6049 acl = strtok (aclArray,",");
6050 while (acl != NULL) {
6051 if(strlen(acl)>=17)
6052 {
6053 apply_rules(apIndex, acl,action,interface);
6054 device_count++;
developer69b61b02023-03-07 17:17:44 +08006055 //Register mac to be Allowed ,in syscfg.db persistent storage
developer72fb0bb2023-01-11 09:46:29 +08006056 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
6057 system(buf);
6058 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
6059 system(buf);
6060 sprintf(cmdmac,"%s",acl);
6061 }
6062 acl = strtok (NULL, ",");
6063 }
6064 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
6065 system(buf);
6066
6067 //Disconnect the mac which is not in ACL
6068 asso = strtok (assocArray,",");
6069 while (asso != NULL) {
6070 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
6071 wifi_kickApAssociatedDevice(apIndex, asso);
6072 asso = strtok (NULL, ",");
6073 }
6074 }
6075#endif
6076 return RETURN_OK;
6077}
6078
6079INT wifi_setPreferPrivateConnection(BOOL enable)
6080{
6081 return RETURN_OK;
6082}
6083
6084// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
6085INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
6086{
6087 char interface_name[16] = {0};
6088 int items = 1;
6089 struct params list[2];
6090 char buf[MAX_BUF_SIZE] = {0};
6091 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
6092 char deny_file[MAX_BUF_SIZE] = {0};
6093
6094 list[0].name = "macaddr_acl";
6095
6096 if (filterMode == 0) {
6097 sprintf(buf, "%d", 0);
6098 list[0].value = buf;
6099
6100 char cmd[128], rtn[128];
6101 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6102 return RETURN_ERR;
6103 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s deny_acl CLEAR", interface_name);
6104 _syscmd(cmd, rtn, sizeof(rtn));
6105 memset(cmd,0,sizeof(cmd));
6106 // Delete deny_mac_file in hostapd configuration
6107 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
6108 _syscmd(cmd, rtn, sizeof(rtn));
6109 }
6110 else if (filterMode == 1) {
6111 sprintf(buf, "%d", filterMode);
6112 list[0].value = buf;
6113 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
6114 list[1].name = "accept_mac_file";
6115 list[1].value = acl_file;
6116 items = 2;
6117 } else if (filterMode == 2) {
6118 //TODO: deny_mac_file
6119 sprintf(buf, "%d", 0);
6120 list[0].value = buf;
6121 list[1].name = "deny_mac_file";
6122 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
6123 list[1].value = deny_file;
6124 items = 2;
6125 } else {
6126 return RETURN_ERR;
6127 }
6128
6129 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6130 wifi_hostapdWrite(config_file, list, items);
6131
6132 return RETURN_OK;
6133
6134#if 0
6135 if(apIndex==0 || apIndex==1)
6136 {
6137 //set the filtermode
6138 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
6139 system(buf);
6140 system("syscfg commit");
6141
6142 if(filterMode==0)
6143 {
6144 sprintf(buf,"iptables -F WifiServices%d",apIndex);
6145 system(buf);
6146 return RETURN_OK;
6147 }
6148 }
6149 return RETURN_OK;
6150#endif
6151}
6152
6153// 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.
6154INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
6155{
6156 return RETURN_ERR;
6157}
6158
6159// gets the vlan ID for this ap from an internal enviornment variable
6160INT wifi_getApVlanID(INT apIndex, INT *output_int)
6161{
6162 if(apIndex==0)
6163 {
6164 *output_int=100;
6165 return RETURN_OK;
6166 }
6167
6168 return RETURN_ERR;
6169}
6170
6171// sets the vlan ID for this ap to an internal enviornment variable
6172INT wifi_setApVlanID(INT apIndex, INT vlanId)
6173{
6174 //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)
6175 return RETURN_ERR;
6176}
6177
6178// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
6179INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6180{
6181 snprintf(bridgeName, 32, "brlan0");
6182 snprintf(IP, 32, "10.0.0.1");
6183 snprintf(subnet, 32, "255.255.255.0");
6184
6185 return RETURN_OK;
6186}
6187
6188//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
6189INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
6190{
6191 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
6192 return RETURN_ERR;
6193}
6194
6195// reset the vlan configuration for this ap
6196INT wifi_resetApVlanCfg(INT apIndex)
6197{
6198 char original_config_file[64] = {0};
6199 char current_config_file[64] = {0};
6200 char buf[64] = {0};
6201 char cmd[64] = {0};
6202 char vlan_file[64] = {0};
6203 char vlan_tagged_interface[16] = {0};
6204 char vlan_bridge[16] = {0};
6205 char vlan_naming[16] = {0};
6206 struct params list[4] = {0};
6207 wifi_band band;
6208
6209 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6210
6211 band = wifi_index_to_band(apIndex);
6212 if (band == band_2_4)
6213 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6214 else if (band == band_5)
6215 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6216 else if (band == band_6)
6217 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6218
6219 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
6220
6221 if (strlen(vlan_file) == 0)
6222 strcpy(vlan_file, VLAN_FILE);
6223
6224 // The file should exist or this vap would not work.
6225 if (access(vlan_file, F_OK) != 0) {
6226 sprintf(cmd, "touch %s", vlan_file);
6227 _syscmd(cmd, buf, sizeof(buf));
6228 }
6229 list[0].name = "vlan_file";
6230 list[0].value = vlan_file;
6231
6232 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
6233 list[1].name = "vlan_tagged_interface";
6234 list[1].value = vlan_tagged_interface;
6235
6236 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
6237 list[2].name = "vlan_bridge";
6238 list[2].value = vlan_bridge;
6239
6240 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
6241 list[3].name = "vlan_naming";
6242 list[3].value = vlan_naming;
6243
6244 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6245 wifi_hostapdWrite(current_config_file, list, 4);
6246 //Reapply vlan settings
6247 // wifi_pushBridgeInfo(apIndex);
6248
6249 // restart this ap
6250 wifi_setApEnable(apIndex, FALSE);
6251 wifi_setApEnable(apIndex, TRUE);
6252
6253 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6254
6255 return RETURN_OK;
6256}
6257
6258// 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.
6259INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
6260{
6261 return RETURN_ERR;
6262}
6263
6264// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
6265INT wifi_startHostApd()
6266{
6267 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6268 system("systemctl start hostapd.service");
6269 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6270 return RETURN_OK;
6271 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
6272}
6273
6274// stops hostapd
developer69b61b02023-03-07 17:17:44 +08006275INT wifi_stopHostApd()
developer72fb0bb2023-01-11 09:46:29 +08006276{
6277 char cmd[128] = {0};
6278 char buf[128] = {0};
6279
6280 sprintf(cmd,"systemctl stop hostapd");
6281 _syscmd(cmd, buf, sizeof(buf));
6282
6283 return RETURN_OK;
6284}
6285
6286// restart hostapd dummy function
6287INT wifi_restartHostApd()
6288{
6289 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6290 system("systemctl restart hostapd-global");
6291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6292
6293 return RETURN_OK;
6294}
6295
6296static int align_hostapd_config(int index)
6297{
6298 ULONG lval;
6299 wifi_getRadioChannel(index%2, &lval);
6300 wifi_setRadioChannel(index%2, lval);
6301 return RETURN_OK;
6302}
6303
6304// sets the AP enable status variable for the specified ap.
6305INT wifi_setApEnable(INT apIndex, BOOL enable)
6306{
6307 char interface_name[16] = {0};
6308 char config_file[MAX_BUF_SIZE] = {0};
6309 char cmd[MAX_CMD_SIZE] = {0};
6310 char buf[MAX_BUF_SIZE] = {0};
6311 BOOL status;
6312 int max_radio_num = 0;
6313 int phyId = 0;
6314
6315 wifi_getApEnable(apIndex,&status);
6316
6317 wifi_getMaxRadioNumber(&max_radio_num);
6318 if (enable == status)
6319 return RETURN_OK;
6320
6321 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6322 return RETURN_ERR;
6323
6324 if (enable == TRUE) {
6325 int radioIndex = apIndex % max_radio_num;
6326 phyId = radio_index_to_phy(radioIndex);
developer8a3bbbf2023-03-15 17:47:23 +08006327
6328 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
developer72fb0bb2023-01-11 09:46:29 +08006329 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyId, config_file);
6330 _syscmd(cmd, buf, sizeof(buf));
developer8a3bbbf2023-03-15 17:47:23 +08006331 } else {
developer72fb0bb2023-01-11 09:46:29 +08006332 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s", interface_name);
6333 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +08006334 }
6335 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=%d' %s",
6336 interface_name, interface_name, enable, VAP_STATUS_FILE);
6337 _syscmd(cmd, buf, sizeof(buf));
6338 //Wait for wifi up/down to apply
6339 return RETURN_OK;
6340}
6341
6342// Outputs the setting of the internal variable that is set by wifi_setApEnable().
6343INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
6344{
6345 char interface_name[16] = {0};
6346 char cmd[MAX_CMD_SIZE] = {'\0'};
6347 char buf[MAX_BUF_SIZE] = {'\0'};
6348
6349 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
6350 return RETURN_ERR;
6351
6352 *output_bool = 0;
6353
6354 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
6355 {
6356 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK) {
6357 *output_bool = FALSE;
6358 return RETURN_OK;
6359 }
6360 sprintf(cmd, "ifconfig %s 2> /dev/null | grep UP", interface_name);
6361 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
6362 }
6363
6364 return RETURN_OK;
6365}
6366
developer69b61b02023-03-07 17:17:44 +08006367// Outputs the AP "Enabled" "Disabled" status from driver
6368INT wifi_getApStatus(INT apIndex, CHAR *output_string)
developer72fb0bb2023-01-11 09:46:29 +08006369{
6370 char cmd[128] = {0};
6371 char buf[128] = {0};
6372 BOOL output_bool;
6373
6374 if ( NULL == output_string)
6375 return RETURN_ERR;
6376 wifi_getApEnable(apIndex,&output_bool);
6377
developer69b61b02023-03-07 17:17:44 +08006378 if(output_bool == 1)
developer72fb0bb2023-01-11 09:46:29 +08006379 snprintf(output_string, 32, "Up");
6380 else
6381 snprintf(output_string, 32, "Disable");
6382
6383 return RETURN_OK;
6384}
6385
6386//Indicates whether or not beacons include the SSID name.
6387// outputs a 1 if SSID on the AP is enabled, else outputs 0
6388INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
6389{
6390 //get the running status
6391 char config_file[MAX_BUF_SIZE] = {0};
6392 char buf[16] = {0};
6393
6394 if (!output)
6395 return RETURN_ERR;
6396
6397 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6398 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
6399 // default is enable
6400 if (strlen(buf) == 0 || strncmp("0", buf, 1) == 0)
6401 *output = TRUE;
6402
6403 return RETURN_OK;
6404}
6405
6406// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
6407INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
6408{
6409 //store the config, apply instantly
6410 char config_file[MAX_BUF_SIZE] = {0};
6411 struct params list;
6412
6413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6414 list.name = "ignore_broadcast_ssid";
6415 list.value = enable?"0":"1";
6416
6417 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6418 wifi_hostapdWrite(config_file, &list, 1);
6419 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6420 //TODO: call hostapd_cli for dynamic_config_control
6421 wifi_reloadAp(apIndex);
6422 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6423
6424 return RETURN_OK;
6425}
6426
6427//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
6428INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
6429{
6430 //get the running status
6431 if(!output_uint)
6432 return RETURN_ERR;
6433 *output_uint=16;
6434 return RETURN_OK;
6435}
6436
6437INT wifi_setApRetryLimit(INT apIndex, UINT number)
6438{
6439 //apply instantly
6440 return RETURN_ERR;
6441}
6442
6443//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
6444INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
6445{
6446 if(!output)
6447 return RETURN_ERR;
6448 *output=TRUE;
6449 return RETURN_OK;
6450}
6451
6452//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
6453INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
6454{
6455 //get the running status from driver
6456 char cmd[128] = {0};
6457 char buf[128] = {0};
6458 int max_radio_num = 0, radioIndex = 0;
6459 int phyId = 0;
6460
6461 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6462
6463 wifi_getMaxRadioNumber(&max_radio_num);
6464 radioIndex = apIndex % max_radio_num;
6465 phyId = radio_index_to_phy(radioIndex);
6466 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", phyId);
6467 _syscmd(cmd,buf, sizeof(buf));
6468
6469 if (strlen(buf) > 0)
6470 *output = true;
6471
6472 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6473
6474 return RETURN_OK;
6475}
6476
6477//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
6478INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
6479{
6480 //get the running status from driver
6481 if(!output)
6482 return RETURN_ERR;
6483
6484 char config_file[MAX_BUF_SIZE] = {0};
6485 char buf[16] = {0};
6486
6487 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6488 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
6489 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6490 *output = TRUE;
6491 else
6492 *output = FALSE;
6493
6494 return RETURN_OK;
6495}
6496
6497// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
6498INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
6499{
6500 //Save config and apply instantly.
6501 char config_file[MAX_BUF_SIZE] = {0};
6502 struct params list;
6503
6504 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6505 list.name = "wmm_enabled";
6506 list.value = enable?"1":"0";
6507
6508 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6509 wifi_hostapdWrite(config_file, &list, 1);
6510 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6511 wifi_reloadAp(apIndex);
6512 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6513
6514 return RETURN_OK;
6515}
6516
6517//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.
6518INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
6519{
6520 //get the running status from driver
6521 if(!output)
6522 return RETURN_ERR;
6523
6524 char config_file[128] = {0};
6525 char buf[16] = {0};
6526
6527 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6528 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
6529 if (strlen(buf) == 0 || strncmp("1", buf, 1) == 0)
6530 *output = TRUE;
6531 else
6532 *output = FALSE;
6533
6534 return RETURN_OK;
6535}
6536
6537// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
6538INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
6539{
6540 //save config and apply instantly.
6541 char config_file[MAX_BUF_SIZE] = {0};
6542 struct params list;
6543
6544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6545 list.name = "uapsd_advertisement_enabled";
6546 list.value = enable?"1":"0";
6547
6548 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6549 wifi_hostapdWrite(config_file, &list, 1);
6550 wifi_hostapdProcessUpdate(apIndex, &list, 1);
6551 wifi_reloadAp(apIndex);
6552 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6553
6554 return RETURN_OK;
6555}
6556
6557// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
6558INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
6559{
6560 char interface_name[16] = {0};
6561 // assume class 0->BE, 1->BK, 2->VI, 3->VO
6562 char cmd[128] = {0};
6563 char buf[128] = {0};
6564 char ack_filepath[128] = {0};
6565 uint16_t bitmap = 0;
6566 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
6567 FILE *f = NULL;
6568
6569 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
6570
6571 // Get current setting
6572 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
6573 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
6574 _syscmd(cmd, buf, sizeof(buf));
6575 if (strlen(buf) > 0)
6576 bitmap = strtoul(buf, NULL, 10);
6577
6578 bitmap = strtoul(buf, NULL, 10);
6579
6580 if (ackPolicy == TRUE) { // True, unset this class
6581 bitmap &= ~class_map[class];
6582 } else { // False, set this class
6583 bitmap |= class_map[class];
6584 }
6585
6586 f = fopen(ack_filepath, "w");
6587 if (f == NULL) {
6588 fprintf(stderr, "%s: fopen failed\n", __func__);
6589 return RETURN_ERR;
6590 }
6591 fprintf(f, "%hu", bitmap);
6592 fclose(f);
6593
6594 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
6595 return RETURN_ERR;
6596 snprintf(cmd, sizeof(cmd), "iw dev %s set noack_map 0x%04x\n", interface_name, bitmap);
6597 _syscmd(cmd, buf, sizeof(buf));
6598
6599 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
6600 return RETURN_OK;
6601}
6602
6603//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.
6604INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
6605{
6606 //get the running status from driver
6607 if(!output_uint)
6608 return RETURN_ERR;
6609
6610 char output[16]={'\0'};
6611 char config_file[MAX_BUF_SIZE] = {0};
6612
6613 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6614 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
6615 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
6616 else {
6617 int device_num = atoi(output);
6618 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
6619 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
6620 return RETURN_ERR;
6621 }
6622 else {
6623 *output_uint = device_num;
6624 }
6625 }
6626
6627 return RETURN_OK;
6628}
6629
6630INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
6631{
6632 //store to wifi config, apply instantly
6633 char str[MAX_BUF_SIZE]={'\0'};
6634 char cmd[MAX_CMD_SIZE]={'\0'};
6635 struct params params;
6636 char config_file[MAX_BUF_SIZE] = {0};
6637
6638 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6639 if (number > MAX_ASSOCIATED_STA_NUM) {
6640 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
6641 return RETURN_ERR;
6642 }
6643 sprintf(str, "%d", number);
6644 params.name = "max_num_sta";
6645 params.value = str;
6646
6647 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
6648 int ret = wifi_hostapdWrite(config_file, &params, 1);
6649 if (ret) {
6650 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
6651 ,__func__, ret);
6652 }
6653
6654 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6655 if (ret) {
6656 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
6657 ,__func__, ret);
6658 }
6659 wifi_reloadAp(apIndex);
6660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6661
6662 return RETURN_OK;
6663}
6664
6665//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.
6666INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
6667{
6668 //get the current threshold
6669 if(!output_uint)
6670 return RETURN_ERR;
6671 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6672 if (*output_uint == 0)
6673 *output_uint = 50;
6674 return RETURN_OK;
6675}
6676
6677INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6678{
6679 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
6680 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6681 return RETURN_OK;
6682 return RETURN_ERR;
6683}
6684
6685//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.
6686INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6687{
6688 if(!output_uint)
6689 return RETURN_ERR;
6690 *output_uint = 3;
6691 return RETURN_OK;
6692}
6693
6694//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6695INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6696{
6697 if(!output_uint)
6698 return RETURN_ERR;
6699 *output_uint = 3;
6700 return RETURN_OK;
6701}
6702
6703//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.
6704INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6705{
6706 if(!output_in_seconds)
6707 return RETURN_ERR;
6708 *output_in_seconds = 0;
6709 return RETURN_OK;
6710}
6711
6712//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
6713INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6714{
6715 if(!output || apIndex>=MAX_APS)
6716 return RETURN_ERR;
6717 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
6718 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
6719 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006720}
developer72fb0bb2023-01-11 09:46:29 +08006721
6722//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6723INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6724{
6725 char config_file[128] = {0};
6726 char wpa[16] = {0};
6727 char key_mgmt[64] = {0};
6728 char buf[16] = {0};
6729 if (!output)
6730 return RETURN_ERR;
6731
6732 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6733 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
6734
6735 strcpy(output, "None");//Copying "None" to output string for default case
6736 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6737 if (strstr(key_mgmt, "WPA-PSK") && strstr(key_mgmt, "SAE") == NULL) {
6738 if (!strcmp(wpa, "1"))
6739 snprintf(output, 32, "WPA-Personal");
6740 else if (!strcmp(wpa, "2"))
6741 snprintf(output, 32, "WPA2-Personal");
6742 else if (!strcmp(wpa, "3"))
6743 snprintf(output, 32, "WPA-WPA2-Personal");
6744
6745 } else if (strstr(key_mgmt, "WPA-EAP")) {
6746 if (!strcmp(wpa, "1"))
6747 snprintf(output, 32, "WPA-Enterprise");
6748 else if (!strcmp(wpa, "2"))
6749 snprintf(output, 32, "WPA2-Enterprise");
6750 else if (!strcmp(wpa, "3"))
6751 snprintf(output, 32, "WPA-WPA2-Enterprise");
6752 } else if (strstr(key_mgmt, "SAE")) {
6753 if (strstr(key_mgmt, "WPA-PSK") == NULL)
6754 snprintf(output, 32, "WPA3-Personal");
6755 else
6756 snprintf(output, 32, "WPA3-Personal-Transition");
6757 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6758 snprintf(output, 32, "WPA3-Enterprise");
6759 }
6760
6761 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6762 return RETURN_OK;
6763#if 0
6764 //TODO: need to revisit below implementation
6765 char securityType[32], authMode[32];
6766 int enterpriseMode=0;
6767
6768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6769 if(!output)
6770 return RETURN_ERR;
6771
6772 wifi_getApBeaconType(apIndex, securityType);
6773 strcpy(output,"None");//By default, copying "None" to output string
6774 if (strncmp(securityType,"None", strlen("None")) == 0)
6775 return RETURN_OK;
6776
6777 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6778 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6779
6780 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6781 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6782 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6783 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6784 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6785 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6786 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6787
6788 return RETURN_OK;
6789#endif
6790}
developer69b61b02023-03-07 17:17:44 +08006791
developer72fb0bb2023-01-11 09:46:29 +08006792INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6793{
6794 char securityType[32];
6795 char authMode[32];
6796
6797 //store settings and wait for wifi up to apply
6798 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6799 if(!encMode)
6800 return RETURN_ERR;
6801
6802 if (strcmp(encMode, "None")==0)
6803 {
6804 strcpy(securityType,"None");
6805 strcpy(authMode,"None");
6806 }
6807 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6808 {
6809 strcpy(securityType,"WPAand11i");
6810 strcpy(authMode,"PSKAuthentication");
6811 }
6812 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6813 {
6814 strcpy(securityType,"WPAand11i");
6815 strcpy(authMode,"EAPAuthentication");
6816 }
6817 else if (strcmp(encMode, "WPA-Personal")==0)
6818 {
6819 strcpy(securityType,"WPA");
6820 strcpy(authMode,"PSKAuthentication");
6821 }
6822 else if (strcmp(encMode, "WPA-Enterprise")==0)
6823 {
6824 strcpy(securityType,"WPA");
6825 strcpy(authMode,"EAPAuthentication");
6826 }
6827 else if (strcmp(encMode, "WPA2-Personal")==0)
6828 {
6829 strcpy(securityType,"11i");
6830 strcpy(authMode,"PSKAuthentication");
6831 }
6832 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6833 {
6834 strcpy(securityType,"11i");
6835 strcpy(authMode,"EAPAuthentication");
6836 }
6837 else if (strcmp(encMode, "WPA3-Personal") == 0)
6838 {
6839 strcpy(securityType,"11i");
6840 strcpy(authMode,"SAEAuthentication");
6841 }
6842 else if (strcmp(encMode, "WPA3-Personal-Transition") == 0)
6843 {
6844 strcpy(securityType, "11i");
6845 strcpy(authMode, "PSK-SAEAuthentication");
6846 }
6847 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6848 {
6849 strcpy(securityType,"11i");
6850 strcpy(authMode,"EAP_192-bit_Authentication");
6851 }
developer3086e2f2023-01-17 09:40:01 +08006852 else if (strcmp(encMode, "OWE") == 0)
6853 {
6854 strcpy(securityType,"11i");
6855 strcpy(authMode,"Enhanced_Open");
6856 }
developer72fb0bb2023-01-11 09:46:29 +08006857 else
6858 {
6859 strcpy(securityType,"None");
6860 strcpy(authMode,"None");
6861 }
6862 wifi_setApBeaconType(apIndex, securityType);
6863 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6864 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6865
6866 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08006867}
developer72fb0bb2023-01-11 09:46:29 +08006868
6869
6870//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6871// output_string must be pre-allocated as 64 character string by caller
6872// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6873INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6874{
6875 char buf[16] = {0};
6876 char config_file[MAX_BUF_SIZE] = {0};
6877
6878 if(output_string==NULL)
6879 return RETURN_ERR;
6880
6881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6882 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6883
6884 if(strcmp(buf,"0")==0)
6885 {
6886 printf("wpa_mode is %s ......... \n",buf);
6887 return RETURN_ERR;
6888 }
6889
6890 wifi_dbg_printf("\nFunc=%s\n",__func__);
6891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6892 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6893 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6894
6895 return RETURN_OK;
6896}
6897
6898// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6899// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6900INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6901{
6902 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6903 struct params params={'\0'};
6904 int ret;
6905 char config_file[MAX_BUF_SIZE] = {0};
6906
6907 if(NULL == preSharedKey)
6908 return RETURN_ERR;
6909
6910 params.name = "wpa_passphrase";
6911
6912 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6913 {
6914 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6915 return RETURN_ERR;
6916 }
6917 params.value = preSharedKey;
6918 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6919 ret = wifi_hostapdWrite(config_file, &params, 1);
6920 if(!ret)
6921 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6922 return ret;
6923 //TODO: call hostapd_cli for dynamic_config_control
6924}
6925
6926//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6927// outputs the passphrase, maximum 63 characters
6928INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6929{
6930 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6931
6932 wifi_dbg_printf("\nFunc=%s\n",__func__);
6933 if (NULL == output_string)
6934 return RETURN_ERR;
6935
6936 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6937 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6938 if(strcmp(buf,"0")==0)
6939 {
6940 printf("wpa_mode is %s ......... \n",buf);
6941 return RETURN_ERR;
6942 }
6943
6944 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6945 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6946
6947 return RETURN_OK;
6948}
6949
6950// sets the passphrase enviornment variable, max 63 characters
6951INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6952{
6953 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6954 struct params params={'\0'};
6955 char config_file[MAX_BUF_SIZE] = {0};
6956 int ret;
6957
6958 if(NULL == passPhrase)
6959 return RETURN_ERR;
6960
6961 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6962 {
6963 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6964 return RETURN_ERR;
6965 }
6966 params.name = "wpa_passphrase";
6967 params.value = passPhrase;
6968 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6969 ret=wifi_hostapdWrite(config_file,&params,1);
6970 if(!ret)
6971 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6972
6973 return ret;
6974}
6975
6976//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.
6977INT wifi_setApSecurityReset(INT apIndex)
6978{
6979 char original_config_file[64] = {0};
6980 char current_config_file[64] = {0};
6981 char buf[64] = {0};
6982 char cmd[64] = {0};
6983 char wpa[4] = {0};
6984 char wpa_psk[64] = {0};
6985 char wpa_passphrase[64] = {0};
6986 char wpa_psk_file[128] = {0};
6987 char wpa_key_mgmt[64] = {0};
6988 char wpa_pairwise[32] = {0};
6989 wifi_band band;
6990 struct params list[6];
6991
6992 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6993
6994 band = wifi_index_to_band(apIndex);
6995 if (band == band_2_4)
6996 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6997 else if (band == band_5)
6998 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6999 else if (band == band_6)
7000 sprintf(original_config_file, "/etc/hostapd-6G.conf");
7001 else
7002 return RETURN_ERR;
7003
7004 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
7005 list[0].name = "wpa";
7006 list[0].value = wpa;
developer69b61b02023-03-07 17:17:44 +08007007
developer72fb0bb2023-01-11 09:46:29 +08007008 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
7009 list[1].name = "wpa_psk";
7010 list[1].value = wpa_psk;
7011
7012 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
7013 list[2].name = "wpa_passphrase";
7014 list[2].value = wpa_passphrase;
7015
7016 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
7017
7018 if (strlen(wpa_psk_file) == 0)
7019 strcpy(wpa_psk_file, PSK_FILE);
7020
7021 if (access(wpa_psk_file, F_OK) != 0) {
7022 sprintf(cmd, "touch %s", wpa_psk_file);
7023 _syscmd(cmd, buf, sizeof(buf));
7024 }
7025 list[3].name = "wpa_psk_file";
7026 list[3].value = wpa_psk_file;
7027
7028 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
7029 list[4].name = "wpa_key_mgmt";
7030 list[4].value = wpa_key_mgmt;
7031
7032 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
7033 list[5].name = "wpa_pairwise";
7034 list[5].value = wpa_pairwise;
7035
7036 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7037 wifi_hostapdWrite(current_config_file, list, 6);
7038
7039 wifi_setApEnable(apIndex, FALSE);
7040 wifi_setApEnable(apIndex, TRUE);
7041
7042 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7043 return RETURN_OK;
7044}
7045
7046//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).
7047INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7048{
7049 char config_file[64] = {0};
7050 char buf[64] = {0};
7051 char cmd[256] = {0};
7052
7053 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7054
7055 if(!IP_output || !Port_output || !RadiusSecret_output)
7056 return RETURN_ERR;
7057
7058 // Read the first matched config
7059 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7060 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7061 _syscmd(cmd, buf, sizeof(buf));
7062 strncpy(IP_output, buf, 64);
7063
7064 memset(buf, 0, sizeof(buf));
7065 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7066 _syscmd(cmd, buf, sizeof(buf));
7067 *Port_output = atoi(buf);
7068
7069 memset(buf, 0, sizeof(buf));
7070 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
7071 _syscmd(cmd, buf, sizeof(buf));
7072 strncpy(RadiusSecret_output, buf, 64);
7073
7074 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7075 return RETURN_OK;
7076}
7077
7078INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7079{
7080 char config_file[64] = {0};
7081 char port_str[8] = {0};
7082 char cmd[256] = {0};
7083 char buf[128] = {0};
7084
7085 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7086
7087 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7088
7089 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
7090 _syscmd(cmd, buf, sizeof(buf));
7091 memset(cmd, 0, sizeof(cmd));
7092
7093 snprintf(port_str, sizeof(port_str), "%d", port);
7094 if (strlen(buf) == 0)
7095 // Append
7096 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
7097 "auth_server_addr=%s\\n"
7098 "auth_server_port=%s\\n"
7099 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7100 else {
7101 // Delete the three lines setting after the "# radius 1" comment
7102 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
7103 _syscmd(cmd, buf, sizeof(buf));
7104 memset(cmd, 0, sizeof(cmd));
7105 // Use "# radius 1" comment to find the location to insert the radius setting
7106 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
7107 "# radius 1\\n"
7108 "auth_server_addr=%s\\n"
7109 "auth_server_port=%s\\n"
7110 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7111 }
7112 if(_syscmd(cmd, buf, sizeof(buf))) {
7113 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7114 return RETURN_ERR;
7115 }
7116
7117 wifi_reloadAp(apIndex);
7118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7119 return RETURN_OK;
7120}
7121
7122INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
7123{
7124 char config_file[64] = {0};
7125 char buf[64] = {0};
7126 char cmd[256] = {0};
7127
7128 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7129
7130 if(!IP_output || !Port_output || !RadiusSecret_output)
7131 return RETURN_ERR;
7132
7133 // Read the second matched config
7134 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7135 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7136 _syscmd(cmd, buf, sizeof(buf));
7137 strncpy(IP_output, buf, 64);
7138
7139 memset(buf, 0, sizeof(buf));
7140 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7141 _syscmd(cmd, buf, sizeof(buf));
7142 *Port_output = atoi(buf);
7143
7144 memset(buf, 0, sizeof(buf));
7145 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
7146 _syscmd(cmd, buf, sizeof(buf));
7147 strncpy(RadiusSecret_output, buf, 64);
7148
7149 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7150 return RETURN_OK;
7151}
7152
7153INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
7154{
7155 char config_file[64] = {0};
7156 char port_str[8] = {0};
7157 char cmd[256] = {0};
7158 char buf[128] = {0};
7159
7160 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7161
7162 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7163
7164 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
7165 _syscmd(cmd, buf, sizeof(buf));
7166 memset(cmd, 0, sizeof(cmd));
7167
7168 snprintf(port_str, sizeof(port_str), "%d", port);
7169 if (strlen(buf) == 0)
7170 // Append
7171 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
7172 "auth_server_addr=%s\\n"
7173 "auth_server_port=%s\\n"
7174 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
7175 else {
7176 // Delete the three lines setting after the "# radius 2" comment
7177 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
7178 _syscmd(cmd, buf, sizeof(buf));
7179 memset(cmd, 0, sizeof(cmd));
7180 // Use "# radius 2" comment to find the location to insert the radius setting
7181 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
7182 "# radius 2\\n"
7183 "auth_server_addr=%s\\n"
7184 "auth_server_port=%s\\n"
7185 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
7186 }
7187 if(_syscmd(cmd, buf, sizeof(buf))) {
7188 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
7189 return RETURN_ERR;
7190 }
7191
7192 wifi_reloadAp(apIndex);
7193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7194 return RETURN_OK;
7195}
7196
7197//RadiusSettings
7198INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
7199{
7200 if(!output)
7201 return RETURN_ERR;
7202
7203 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
developer69b61b02023-03-07 17:17:44 +08007204 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
7205 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
7206 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
7207 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
developer72fb0bb2023-01-11 09:46:29 +08007208 output->MaxAuthenticationAttempts = 3; //Indicates the # of time, a client can attempt to login with incorrect credentials. When this limit is reached, the client is blacklisted and not allowed to attempt loging into the network. Settings this parameter to 0 (zero) disables the blacklisting feature.
developer69b61b02023-03-07 17:17:44 +08007209 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
7210 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
7211 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
developer72fb0bb2023-01-11 09:46:29 +08007212 //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.
7213
7214 return RETURN_OK;
7215}
7216
7217INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
7218{
7219 //store the paramters, and apply instantly
7220 return RETURN_ERR;
7221}
7222
7223//Device.WiFi.AccessPoint.{i}.WPS.Enable
7224//Enables or disables WPS functionality for this access point.
7225// outputs the WPS enable state of this ap in output_bool
7226INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
7227{
7228 char interface_name[16] = {0};
7229 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
7230 if(!output_bool)
7231 return RETURN_ERR;
7232 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7233 return RETURN_ERR;
7234 sprintf(cmd,"hostapd_cli -i %s get_config | grep wps_state | cut -d '=' -f2", interface_name);
7235 _syscmd(cmd, buf, sizeof(buf));
7236 if(strstr(buf, "configured"))
7237 *output_bool=TRUE;
7238 else
7239 *output_bool=FALSE;
7240
7241 return RETURN_OK;
developer69b61b02023-03-07 17:17:44 +08007242}
developer72fb0bb2023-01-11 09:46:29 +08007243
7244//Device.WiFi.AccessPoint.{i}.WPS.Enable
7245// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
7246INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
7247{
7248 char config_file[MAX_BUF_SIZE] = {0};
7249 struct params params;
7250
7251 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7252 //store the paramters, and wait for wifi up to apply
7253 params.name = "wps_state";
7254 params.value = enable ? "2":"0";
7255
7256 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7257 wifi_hostapdWrite(config_file, &params, 1);
7258 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7259 wifi_reloadAp(apIndex);
7260
7261 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7262 return RETURN_OK;
7263}
7264
7265//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
7266INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
7267{
7268 if(!output)
7269 return RETURN_ERR;
7270 snprintf(output, 128, "PushButton,PIN");
7271 return RETURN_OK;
7272}
7273
7274//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7275//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.
7276// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
7277INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
7278{
7279 if(!output)
7280 return RETURN_ERR;
7281 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
7282
7283 return RETURN_OK;
7284}
7285
7286//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
7287// 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
7288INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
7289{
7290 //apply instantly. No setting need to be stored.
7291 char methods[MAX_BUF_SIZE], *token, *next_token;
7292 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
7293 struct params params;
7294
7295 if(!methodString)
7296 return RETURN_ERR;
7297 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7298 //store the paramters, and wait for wifi up to apply
7299
7300 snprintf(methods, sizeof(methods), "%s", methodString);
7301 for(token=methods; *token; token=next_token)
7302 {
7303 strtok_r(token, ",", &next_token);
7304 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
7305 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
7306 else if(*token=='E')
7307 {
7308 if(!strcmp(methods, "Ethernet"))
7309 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
7310 else if(!strcmp(methods, "ExternalNFCToken"))
7311 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
7312 else
7313 printf("%s: Unknown WpsConfigMethod\n", __func__);
7314 }
7315 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
7316 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
7317 else if(*token=='N' && !strcmp(token, "NFCInterface"))
7318 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
7319 else if(*token=='P' )
7320 {
7321 if(!strcmp(token, "PushButton"))
7322 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
7323 else if(!strcmp(token, "PIN"))
7324 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
7325 else
7326 printf("%s: Unknown WpsConfigMethod\n", __func__);
7327 }
7328 else
7329 printf("%s: Unknown WpsConfigMethod\n", __func__);
7330 }
7331 params.name = "config_methods";
7332 params.value = config_methods;
7333 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7334 wifi_hostapdWrite(config_file, &params, 1);
7335 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7336 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7337
7338 return RETURN_OK;
7339}
7340
7341// outputs the pin value, ulong_pin must be allocated by the caller
7342INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
7343{
7344 char buf[MAX_BUF_SIZE] = {0};
7345 char cmd[MAX_CMD_SIZE] = {0};
7346
7347 if(!output_ulong)
7348 return RETURN_ERR;
7349 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
7350 _syscmd(cmd, buf, sizeof(buf));
7351 if(strlen(buf) > 0)
7352 *output_ulong=strtoul(buf, NULL, 10);
7353
7354 return RETURN_OK;
7355}
7356
7357// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
7358INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
7359{
7360 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
7361 char ap_pin[16] = {0};
7362 char buf[MAX_BUF_SIZE] = {0};
7363 char config_file[MAX_BUF_SIZE] = {0};
7364 ULONG prev_pin = 0;
7365 struct params params;
7366
7367 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7368 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
7369 params.name = "ap_pin";
7370 params.value = ap_pin;
7371 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
7372 wifi_hostapdWrite(config_file, &params, 1);
7373 wifi_hostapdProcessUpdate(apIndex, &params, 1);
7374 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7375
7376 return RETURN_OK;
7377}
7378
7379// Output string is either Not configured or Configured, max 32 characters
7380INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
7381{
7382 char interface_name[16] = {0};
7383 char cmd[MAX_CMD_SIZE];
7384 char buf[MAX_BUF_SIZE]={0};
7385
7386 if(!output_string)
7387 return RETURN_ERR;
7388 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7389 snprintf(output_string, 32, "Not configured");
7390 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7391 return RETURN_ERR;
7392 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep wps_state | cut -d'=' -f2", interface_name);
7393 _syscmd(cmd, buf, sizeof(buf));
7394
7395 if(!strncmp(buf, "configured", 10))
7396 snprintf(output_string, 32, "Configured");
7397 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7398
7399 return RETURN_OK;
7400}
7401
7402// sets the WPS pin for this AP
7403INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
7404{
7405 char interface_name[16] = {0};
7406 char cmd[MAX_CMD_SIZE];
7407 char buf[MAX_BUF_SIZE]={0};
7408 BOOL enable;
7409
7410 wifi_getApEnable(apIndex, &enable);
7411 if (!enable)
7412 return RETURN_ERR;
7413 wifi_getApWpsEnable(apIndex, &enable);
7414 if (!enable)
7415 return RETURN_ERR;
7416
7417 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7418 return RETURN_ERR;
7419 snprintf(cmd, 64, "hostapd_cli -i%s wps_pin any %s", interface_name, pin);
7420 _syscmd(cmd, buf, sizeof(buf));
7421 if((strstr(buf, "OK"))!=NULL)
7422 return RETURN_OK;
7423
7424 return RETURN_ERR;
7425}
7426
7427// This function is called when the WPS push button has been pressed for this AP
7428INT wifi_setApWpsButtonPush(INT apIndex)
7429{
7430 char cmd[MAX_CMD_SIZE];
7431 char buf[MAX_BUF_SIZE]={0};
7432 char interface_name[16] = {0};
7433 BOOL enable=FALSE;
7434
7435 wifi_getApEnable(apIndex, &enable);
7436 if (!enable)
7437 return RETURN_ERR;
7438
7439 wifi_getApWpsEnable(apIndex, &enable);
7440 if (!enable)
7441 return RETURN_ERR;
7442
7443 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7444 return RETURN_ERR;
7445
7446 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel; hostapd_cli -i%s wps_pbc", interface_name, interface_name);
7447 _syscmd(cmd, buf, sizeof(buf));
7448
7449 if((strstr(buf, "OK"))!=NULL)
7450 return RETURN_OK;
7451 return RETURN_ERR;
7452}
7453
7454// cancels WPS mode for this AP
7455INT wifi_cancelApWPS(INT apIndex)
7456{
7457 char interface_name[16] = {0};
7458 char cmd[MAX_CMD_SIZE];
7459 char buf[MAX_BUF_SIZE]={0};
7460
7461 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7462 return RETURN_ERR;
7463 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s wps_cancel", interface_name);
7464 _syscmd(cmd,buf, sizeof(buf));
7465
7466 if((strstr(buf, "OK"))!=NULL)
7467 return RETURN_OK;
7468 return RETURN_ERR;
7469}
7470
7471//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
7472//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
7473INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
7474{
7475 char interface_name[16] = {0};
7476 FILE *f = NULL;
7477 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7478 char cmd[256] = {0}, buf[2048] = {0};
7479 char *param = NULL, *value = NULL, *line=NULL;
7480 size_t len = 0;
7481 ssize_t nread = 0;
7482 wifi_associated_dev_t *dev=NULL;
7483
7484 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7485 *associated_dev_array = NULL;
7486 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
7487 return RETURN_ERR;
7488 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
7489 _syscmd(cmd,buf,sizeof(buf));
7490 *output_array_size = atoi(buf);
7491
7492 if (*output_array_size <= 0)
7493 return RETURN_OK;
7494
7495 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
7496 *associated_dev_array = dev;
7497 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt" , interface_name);
7498 _syscmd(cmd,buf,sizeof(buf));
7499 f = fopen("/tmp/connected_devices.txt", "r");
7500 if (f==NULL)
7501 {
7502 *output_array_size=0;
7503 return RETURN_ERR;
7504 }
7505 while ((getline(&line, &len, f)) != -1)
7506 {
7507 param = strtok(line,"=");
7508 value = strtok(NULL,"=");
7509
7510 if( strcmp("flags",param) == 0 )
7511 {
7512 value[strlen(value)-1]='\0';
7513 if(strstr (value,"AUTHORIZED") != NULL )
7514 {
7515 dev[auth_temp].cli_AuthenticationState = 1;
7516 dev[auth_temp].cli_Active = 1;
7517 auth_temp++;
7518 read_flag=1;
7519 }
7520 }
7521 if(read_flag==1)
7522 {
7523 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7524 {
7525 value[strlen(value)-1]='\0';
7526 sscanf(value, "%x:%x:%x:%x:%x:%x",
7527 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7528 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7529 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7530 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7531 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7532 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7533 mac_temp++;
7534 read_flag=0;
7535 }
7536 }
7537 }
7538 *output_array_size = auth_temp;
7539 auth_temp=0;
7540 mac_temp=0;
7541 free(line);
7542 fclose(f);
7543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7544 return RETURN_OK;
7545}
7546
7547#define MACADDRESS_SIZE 6
7548
7549INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7550{
7551 FILE *fp = NULL;
7552 char str[MAX_BUF_SIZE] = {0};
7553 int wificlientindex = 0 ;
7554 int count = 0;
7555 int signalstrength = 0;
7556 int arr[MACADDRESS_SIZE] = {0};
7557 unsigned char mac[MACADDRESS_SIZE] = {0};
7558 UINT wifi_count = 0;
7559 char virtual_interface_name[MAX_BUF_SIZE] = {0};
7560 char pipeCmd[MAX_CMD_SIZE] = {0};
7561
7562 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7563 *output_array_size = 0;
7564 *associated_dev_array = NULL;
7565
7566 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
7567 fp = popen(pipeCmd, "r");
developer69b61b02023-03-07 17:17:44 +08007568 if (fp == NULL)
developer72fb0bb2023-01-11 09:46:29 +08007569 {
7570 printf("Failed to run command inside function %s\n",__FUNCTION__ );
7571 return RETURN_ERR;
7572 }
7573
7574 /* Read the output a line at a time - output it. */
7575 fgets(str, sizeof(str)-1, fp);
7576 wifi_count = (unsigned int) atoi ( str );
7577 *output_array_size = wifi_count;
7578 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
7579 pclose(fp);
7580
7581 if(wifi_count == 0)
7582 {
7583 return RETURN_OK;
7584 }
7585 else
7586 {
7587 wifi_associated_dev3_t* temp = NULL;
7588 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
7589 if(temp == NULL)
7590 {
7591 printf("Error Statement. Insufficient memory \n");
7592 return RETURN_ERR;
7593 }
7594
7595 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
7596 system(pipeCmd);
7597 memset(pipeCmd,0,sizeof(pipeCmd));
7598 if(apIndex == 0)
7599 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
7600 else if(apIndex == 1)
7601 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
7602 system(pipeCmd);
7603
7604 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
7605 if(fp == NULL)
7606 {
7607 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
7608 free(temp);
7609 return RETURN_ERR;
7610 }
7611 fclose(fp);
7612
7613 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
7614 fp = popen(pipeCmd, "r");
7615 if(fp)
7616 {
7617 for(count =0 ; count < wifi_count; count++)
7618 {
7619 fgets(str, MAX_BUF_SIZE, fp);
7620 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7621 {
7622 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7623 {
7624 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7625
7626 }
7627 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7628 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]);
7629 }
7630 temp[count].cli_AuthenticationState = 1; //TODO
7631 temp[count].cli_Active = 1; //TODO
7632 }
7633 pclose(fp);
7634 }
7635
7636 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
7637 fp = popen(pipeCmd, "r");
7638 if(fp)
developer69b61b02023-03-07 17:17:44 +08007639 {
developer72fb0bb2023-01-11 09:46:29 +08007640 pclose(fp);
7641 }
7642 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
7643 if(fp)
7644 {
7645 for(count =0 ; count < wifi_count ;count++)
7646 {
7647 fgets(str, MAX_BUF_SIZE, fp);
7648 signalstrength = atoi(str);
7649 temp[count].cli_SignalStrength = signalstrength;
7650 temp[count].cli_RSSI = signalstrength;
7651 temp[count].cli_SNR = signalstrength + 95;
7652 }
7653 pclose(fp);
7654 }
7655
7656
7657 if((apIndex == 0) || (apIndex == 4))
7658 {
7659 for(count =0 ; count < wifi_count ;count++)
developer69b61b02023-03-07 17:17:44 +08007660 {
developer72fb0bb2023-01-11 09:46:29 +08007661 strcpy(temp[count].cli_OperatingStandard,"g");
7662 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
7663 }
7664
7665 //BytesSent
7666 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt");
7667 fp = popen(pipeCmd, "r");
7668 if(fp)
developer69b61b02023-03-07 17:17:44 +08007669 {
developer72fb0bb2023-01-11 09:46:29 +08007670 pclose(fp);
7671 }
7672 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
7673 if(fp)
7674 {
7675 for (count = 0; count < wifi_count; count++)
7676 {
7677 fgets(str, MAX_BUF_SIZE, fp);
7678 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
7679 }
7680 pclose(fp);
7681 }
7682
7683 //BytesReceived
7684 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt");
7685 fp = popen(pipeCmd, "r");
7686 if (fp)
7687 {
7688 pclose(fp);
7689 }
7690 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7691 if (fp)
7692 {
7693 for (count = 0; count < wifi_count; count++)
7694 {
7695 fgets(str, MAX_BUF_SIZE, fp);
7696 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7697 }
7698 pclose(fp);
7699 }
7700
7701 //PacketsSent
7702 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt");
7703 fp = popen(pipeCmd, "r");
7704 if (fp)
7705 {
7706 pclose(fp);
7707 }
7708
7709 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7710 if (fp)
7711 {
7712 for (count = 0; count < wifi_count; count++)
7713 {
7714 fgets(str, MAX_BUF_SIZE, fp);
7715 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7716 }
7717 pclose(fp);
7718 }
7719
7720 //PacketsReceived
7721 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt");
7722 fp = popen(pipeCmd, "r");
7723 if (fp)
7724 {
7725 pclose(fp);
7726 }
7727 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7728 if (fp)
7729 {
7730 for (count = 0; count < wifi_count; count++)
7731 {
7732 fgets(str, MAX_BUF_SIZE, fp);
7733 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7734 }
7735 pclose(fp);
7736 }
7737
7738 //ErrorsSent
7739 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7740 fp = popen(pipeCmd, "r");
7741 if (fp)
7742 {
7743 pclose(fp);
7744 }
7745 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7746 if (fp)
7747 {
7748 for (count = 0; count < wifi_count; count++)
7749 {
7750 fgets(str, MAX_BUF_SIZE, fp);
7751 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7752 }
7753 pclose(fp);
7754 }
7755
7756 //ErrorsSent
7757 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt");
7758 fp = popen(pipeCmd, "r");
7759 if (fp)
7760 {
7761 pclose(fp);
7762 }
7763 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7764 if (fp)
7765 {
7766 for (count = 0; count < wifi_count; count++)
7767 {
7768 fgets(str, MAX_BUF_SIZE, fp);
7769 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7770 }
7771 pclose(fp);
7772 }
7773
7774 //LastDataDownlinkRate
7775 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
7776 fp = popen(pipeCmd, "r");
7777 if (fp)
7778 {
7779 pclose(fp);
7780 }
7781 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7782 if (fp)
7783 {
7784 for (count = 0; count < wifi_count; count++)
7785 {
7786 fgets(str, MAX_BUF_SIZE, fp);
7787 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7788 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7789 }
7790 pclose(fp);
7791 }
7792
7793 //LastDataUplinkRate
7794 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
7795 fp = popen(pipeCmd, "r");
7796 if (fp)
7797 {
7798 pclose(fp);
7799 }
7800 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7801 if (fp)
7802 {
7803 for (count = 0; count < wifi_count; count++)
7804 {
7805 fgets(str, MAX_BUF_SIZE, fp);
7806 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7807 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7808 }
7809 pclose(fp);
7810 }
7811
7812 }
7813 else if ((apIndex == 1) || (apIndex == 5))
7814 {
7815 for (count = 0; count < wifi_count; count++)
7816 {
7817 strcpy(temp[count].cli_OperatingStandard, "a");
7818 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7819 temp[count].cli_BytesSent = 0;
7820 temp[count].cli_BytesReceived = 0;
7821 temp[count].cli_LastDataUplinkRate = 0;
7822 temp[count].cli_LastDataDownlinkRate = 0;
7823 temp[count].cli_PacketsSent = 0;
7824 temp[count].cli_PacketsReceived = 0;
7825 temp[count].cli_ErrorsSent = 0;
7826 }
7827 }
7828
7829 for (count = 0; count < wifi_count; count++)
7830 {
7831 temp[count].cli_Retransmissions = 0;
7832 temp[count].cli_DataFramesSentAck = 0;
7833 temp[count].cli_DataFramesSentNoAck = 0;
7834 temp[count].cli_MinRSSI = 0;
7835 temp[count].cli_MaxRSSI = 0;
7836 strncpy(temp[count].cli_InterferenceSources, "", 64);
7837 memset(temp[count].cli_IPAddress, 0, 64);
7838 temp[count].cli_RetransCount = 0;
7839 temp[count].cli_FailedRetransCount = 0;
7840 temp[count].cli_RetryCount = 0;
7841 temp[count].cli_MultipleRetryCount = 0;
7842 }
7843 *associated_dev_array = temp;
7844 }
7845 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7846 return RETURN_OK;
7847}
7848
7849int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7850{
7851 FILE *fp = NULL;
7852 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7853 char cmd[MAX_CMD_SIZE];
7854 int count = 0;
7855
7856 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7857 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7858 fp = popen(cmd,"r");
7859 if(fp == NULL)
7860 {
7861 printf("Failed to run command in Function %s\n",__FUNCTION__);
7862 return 0;
7863 }
7864 if(fgets(path, sizeof(path)-1, fp) != NULL)
7865 {
7866 for(count=0;path[count]!='\n';count++)
7867 status[count]=path[count];
7868 status[count]='\0';
7869 }
7870 strcpy(wifi_status,status);
7871 pclose(fp);
7872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7873 return RETURN_OK;
7874}
7875
7876/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7877struct hostapd_sta_param {
7878 char key[50];
7879 char value[100];
7880}
7881
7882static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7883 int i = 0;
7884
7885 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7886 if (strncmp(params[i].key,key,50) == 0){
7887 return &params[i].value;
7888 }
7889 i++;
7890 }
7891 return NULL;
7892
7893} */
7894
7895static unsigned int count_occurences(const char *buf, const char *word)
7896{
7897 unsigned int n = 0;
7898 char *ptr = strstr(buf, word);
7899
7900 while (ptr++) {
7901 n++;
7902 ptr = strstr(ptr, word);
7903 }
7904
7905 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7906 return n;
7907}
7908
7909static const char *get_line_from_str_buf(const char *buf, char *line)
7910{
7911 int i;
7912 int n = strlen(buf);
7913
7914 for (i = 0; i < n; i++) {
7915 line[i] = buf[i];
7916 if (buf[i] == '\n') {
7917 line[i] = '\0';
7918 return &buf[i + 1];
7919 }
7920 }
7921
7922 return NULL;
7923}
7924
7925INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7926{
7927 unsigned int assoc_cnt = 0;
7928 char interface_name[50] = {0};
7929 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7930 char cmd[MAX_CMD_SIZE] = {'\0'};
7931 char line[256] = {'\0'};
7932 int i = 0;
7933 int ret = 0;
7934 const char *ptr = NULL;
7935 char *key = NULL;
7936 char *val = NULL;
7937 wifi_associated_dev3_t *temp = NULL;
7938 int rssi;
7939
7940 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7941
7942 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7943 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7944 return RETURN_ERR;
7945 }
7946
7947 // Example filtered output of 'iw dev' command:
7948 // Station 0a:69:72:10:d2:fa (on wifi0)
7949 // signal avg:-67 [-71, -71] dBm
7950 // Station 28:c2:1f:25:5f:99 (on wifi0)
7951 // signal avg:-67 [-71, -70] dBm
7952 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7953 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7954 return RETURN_ERR;
7955 }
7956
7957 ret = _syscmd(cmd, buf, sizeof(buf));
7958 if (ret == RETURN_ERR) {
7959 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7960 return RETURN_ERR;
7961 }
7962
7963 *output_array_size = count_occurences(buf, "Station");
7964 if (*output_array_size == 0) return RETURN_OK;
7965
7966 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7967 if (temp == NULL) {
7968 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7969 return RETURN_ERR;
7970 }
7971 *associated_dev_array = temp;
7972
7973 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7974 ptr = get_line_from_str_buf(buf, line);
7975 i = -1;
7976 while (ptr) {
7977 if (strstr(line, "Station")) {
7978 i++;
7979 key = strtok(line, " ");
7980 val = strtok(NULL, " ");
7981 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7982 &temp[i].cli_MACAddress[0],
7983 &temp[i].cli_MACAddress[1],
7984 &temp[i].cli_MACAddress[2],
7985 &temp[i].cli_MACAddress[3],
7986 &temp[i].cli_MACAddress[4],
7987 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7988 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7989 free(*associated_dev_array);
7990 return RETURN_ERR;
7991 }
7992 }
7993 else if (i < 0) {
7994 ptr = get_line_from_str_buf(ptr, line);
7995 continue; // We didn't detect 'station' entry yet
7996 }
7997 else if (strstr(line, "signal avg")) {
7998 key = strtok(line, ":");
7999 val = strtok(NULL, " ");
8000 if (sscanf(val, "%d", &rssi) <= 0 ) {
8001 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
8002 free(*associated_dev_array);
8003 return RETURN_ERR;
8004 }
8005 temp[i].cli_RSSI = rssi;
8006 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
8007 }
8008 // Here other fields can be parsed if added to filter of 'iw dev' command
8009
8010 ptr = get_line_from_str_buf(ptr, line);
8011 };
8012
8013 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8014
8015 return RETURN_OK;
8016}
8017
8018#if 0
8019//To-do
8020INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8021{
8022 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8023
8024 //Using different approach to get required WiFi Parameters from system available commands
developer69b61b02023-03-07 17:17:44 +08008025#if 0
developer72fb0bb2023-01-11 09:46:29 +08008026 FILE *f;
8027 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
8028 char cmd[256], buf[2048];
8029 char *param , *value, *line=NULL;
8030 size_t len = 0;
8031 ssize_t nread;
8032 wifi_associated_dev3_t *dev=NULL;
8033 *associated_dev_array = NULL;
8034 sprintf(cmd, "hostapd_cli -i%s all_sta | grep AUTHORIZED | wc -l", interface_name);
8035 _syscmd(cmd,buf,sizeof(buf));
8036 *output_array_size = atoi(buf);
8037
8038 if (*output_array_size <= 0)
8039 return RETURN_OK;
8040
8041 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
8042 *associated_dev_array = dev;
8043 sprintf(cmd, "hostapd_cli -i%s all_sta > /tmp/connected_devices.txt", interface_name);
8044 _syscmd(cmd,buf,sizeof(buf));
8045 f = fopen("/tmp/connected_devices.txt", "r");
8046 if (f==NULL)
8047 {
8048 *output_array_size=0;
8049 return RETURN_ERR;
8050 }
8051 while ((nread = getline(&line, &len, f)) != -1)
8052 {
8053 param = strtok(line,"=");
8054 value = strtok(NULL,"=");
8055
8056 if( strcmp("flags",param) == 0 )
8057 {
8058 value[strlen(value)-1]='\0';
8059 if(strstr (value,"AUTHORIZED") != NULL )
8060 {
8061 dev[auth_temp].cli_AuthenticationState = 1;
8062 dev[auth_temp].cli_Active = 1;
8063 auth_temp++;
8064 read_flag=1;
8065 }
8066 }
8067 if(read_flag==1)
8068 {
8069 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
8070 {
8071 value[strlen(value)-1]='\0';
8072 sscanf(value, "%x:%x:%x:%x:%x:%x",
8073 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
8074 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
8075 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
8076 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
8077 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
8078 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
8079
8080 }
8081 else if( strcmp("rx_packets",param) == 0 )
8082 {
8083 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
8084 }
8085
8086 else if( strcmp("tx_packets",param) == 0 )
8087 {
developer69b61b02023-03-07 17:17:44 +08008088 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
developer72fb0bb2023-01-11 09:46:29 +08008089 }
8090
8091 else if( strcmp("rx_bytes",param) == 0 )
8092 {
8093 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
8094 }
8095
8096 else if( strcmp("tx_bytes",param) == 0 )
8097 {
developer69b61b02023-03-07 17:17:44 +08008098 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
developer72fb0bb2023-01-11 09:46:29 +08008099 mac_temp++;
8100 read_flag=0;
developer69b61b02023-03-07 17:17:44 +08008101 }
developer72fb0bb2023-01-11 09:46:29 +08008102 }
8103 }
8104
8105 *output_array_size = auth_temp;
8106 auth_temp=0;
8107 mac_temp=0;
8108 free(line);
8109 fclose(f);
8110#endif
8111 char interface_name[MAX_BUF_SIZE] = {0};
8112 char wifi_status[MAX_BUF_SIZE] = {0};
8113 char hostapdconf[MAX_BUF_SIZE] = {0};
8114
8115 wifi_associated_dev3_t *dev_array = NULL;
8116 ULONG wifi_count = 0;
8117
8118 *associated_dev_array = NULL;
8119 *output_array_size = 0;
8120
8121 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
8122 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
8123 {
8124 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
8125
8126 wifi_GetInterfaceName(interface_name, hostapdconf);
8127
8128 if(strlen(interface_name) > 1)
8129 {
8130 wifihal_interfacestatus(wifi_status,interface_name);
8131 if(strcmp(wifi_status,"RUNNING") == 0)
8132 {
8133 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
8134
8135 *associated_dev_array = dev_array;
developer69b61b02023-03-07 17:17:44 +08008136 *output_array_size = wifi_count;
developer72fb0bb2023-01-11 09:46:29 +08008137 }
8138 else
8139 {
8140 *associated_dev_array = NULL;
8141 }
8142 }
8143 }
8144
8145 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8146 return RETURN_OK;
8147}
8148#endif
8149
8150/* getIPAddress function */
8151/**
8152* @description Returning IpAddress of the Matched String
8153*
developer69b61b02023-03-07 17:17:44 +08008154* @param
developer72fb0bb2023-01-11 09:46:29 +08008155* @str Having MacAddress
developer69b61b02023-03-07 17:17:44 +08008156* @ipaddr Having ipaddr
developer72fb0bb2023-01-11 09:46:29 +08008157* @return The status of the operation
8158* @retval RETURN_OK if successful
8159* @retval RETURN_ERR if any error is detected
8160*
8161*/
8162
8163INT getIPAddress(char *str,char *ipaddr)
8164{
8165 FILE *fp = NULL;
8166 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
8167 int LeaseTime = 0,ret = 0;
8168 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
8169 {
8170 return RETURN_ERR;
8171 }
8172
8173 while ( fgets(buf, sizeof(buf), fp)!= NULL )
8174 {
8175 /*
8176 Sample:sss
8177 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
8178 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
8179 */
8180 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
8181 &(LeaseTime),
8182 phyAddr,
8183 ipAddr,
8184 hostName
8185 );
8186 if(ret != 4)
8187 continue;
8188 if(strcmp(str,phyAddr) == 0)
8189 strcpy(ipaddr,ipAddr);
8190 }
8191 fclose(fp);
8192 return RETURN_OK;
8193}
8194
8195/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
8196/**
8197* @description Returning Inactive wireless connected clients informations
8198*
developer69b61b02023-03-07 17:17:44 +08008199* @param
developer72fb0bb2023-01-11 09:46:29 +08008200* @filename Holding private_wifi 2g/5g content files
8201* @associated_dev_array Having inactiv wireless clients informations
8202* @output_array_size Returning Inactive wireless counts
8203* @return The status of the operation
8204* @retval RETURN_OK if successful
8205* @retval RETURN_ERR if any error is detected
8206*
8207*/
8208
8209INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
8210{
8211 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8212 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
8213 FILE *fp = NULL;
8214 int arr[MACADDRESS_SIZE] = {0};
8215 unsigned char mac[MACADDRESS_SIZE] = {0};
8216 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
8217 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
8218 fp = popen(buf,"r");
8219 if(fp == NULL)
8220 return RETURN_ERR;
8221 else
8222 {
8223 fgets(path,sizeof(path),fp);
8224 maccount = atoi(path);
8225 }
8226 pclose(fp);
8227 *output_array_size = maccount;
8228 wifi_associated_dev3_t* temp = NULL;
8229 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
8230 *associated_dev_array = temp;
8231 if(temp == NULL)
8232 {
8233 printf("Error Statement. Insufficient memory \n");
8234 return RETURN_ERR;
8235 }
8236 memset(buf,0,sizeof(buf));
8237 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
8238 fp = popen(buf,"r");
8239 if (fp == NULL) {
8240 fprintf(stderr, "%s: failed pipe command %s.\n", __func__, buf);
8241 return RETURN_ERR;
8242 }
8243 for(count = 0; count < maccount ; count++)
8244 {
8245 fgets(path,sizeof(path),fp);
8246 for(i = 0; path[i]!='\n';i++)
8247 str[i]=path[i];
8248 str[i]='\0';
8249 getIPAddress(str,ipaddr);
8250 memset(buf,0,sizeof(buf));
8251 if(strlen(ipaddr) > 0)
8252 {
8253 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
8254 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
8255 {
8256 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8257 {
8258 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8259 {
8260 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8261
8262 }
8263 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8264 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]);
8265 }
8266 temp[count].cli_AuthenticationState = 0; //TODO
developer69b61b02023-03-07 17:17:44 +08008267 temp[count].cli_Active = 0; //TODO
developer72fb0bb2023-01-11 09:46:29 +08008268 temp[count].cli_SignalStrength = 0;
8269 }
8270 else //Active wireless clients info
8271 {
8272 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8273 {
8274 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8275 {
8276 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8277
8278 }
8279 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8280 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]);
8281 }
8282 temp[count].cli_Active = 1;
8283 }
8284 }
8285 memset(ipaddr,0,sizeof(ipaddr));
8286 }
8287 pclose(fp);
8288 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8289 return RETURN_OK;
8290}
8291//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
8292//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
8293//To get Band Steering Capability
8294INT wifi_getBandSteeringCapability(BOOL *support)
8295{
8296 *support = FALSE;
8297 return RETURN_OK;
8298}
8299
8300
8301//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
8302//To get Band Steering enable status
8303INT wifi_getBandSteeringEnable(BOOL *enable)
8304{
8305 *enable = FALSE;
8306 return RETURN_OK;
8307}
8308
8309//To turn on/off Band steering
8310INT wifi_setBandSteeringEnable(BOOL enable)
8311{
8312 return RETURN_OK;
8313}
8314
8315//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
8316//To get Band Steering AP group
8317INT wifi_getBandSteeringApGroup(char *output_ApGroup)
8318{
8319 if (NULL == output_ApGroup)
8320 return RETURN_ERR;
8321
8322 strcpy(output_ApGroup, "1,2");
8323 return RETURN_OK;
8324}
8325
8326//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
8327//to set and read the band steering BandUtilizationThreshold parameters
8328INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
8329{
8330 return RETURN_ERR;
8331}
8332
8333INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
8334{
8335 return RETURN_ERR;
8336}
8337
8338//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
8339//to set and read the band steering RSSIThreshold parameters
8340INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
8341{
8342 return RETURN_ERR;
8343}
8344
8345INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
8346{
8347 return RETURN_ERR;
8348}
8349
8350
8351//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
8352//to set and read the band steering physical modulation rate threshold parameters
8353INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
8354{
8355 //If chip is not support, return -1
8356 return RETURN_ERR;
8357}
8358
8359INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
8360{
8361 //If chip is not support, return -1
8362 return RETURN_ERR;
8363}
8364
8365//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
8366//to set and read the inactivity time (in seconds) for steering under overload condition
8367INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
8368{
8369 return RETURN_ERR;
8370}
8371
8372INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
8373{
8374 return RETURN_ERR;
8375}
8376
8377//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
8378//to set and read the inactivity time (in seconds) for steering under Idle condition
8379INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
8380{
8381 return RETURN_ERR;
8382}
8383
8384INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
8385{
8386 return RETURN_ERR;
8387}
8388
8389//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
8390//pClientMAC[64]
8391//pSourceSSIDIndex[64]
8392//pDestSSIDIndex[64]
8393//pSteeringReason[256]
8394INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
8395{
8396 //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
8397 *pSteeringTime=time(NULL);
8398 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
8399 return RETURN_OK;
8400}
8401
8402INT wifi_ifConfigDown(INT apIndex)
8403{
8404 INT status = RETURN_OK;
8405 char cmd[64];
8406
8407 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
8408 printf("%s: %s\n", __func__, cmd);
8409 system(cmd);
8410
8411 return status;
8412}
8413
8414INT wifi_ifConfigUp(INT apIndex)
8415{
8416 char interface_name[16] = {0};
8417 char cmd[128];
8418 char buf[1024];
8419
8420 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8421 return RETURN_ERR;
8422 snprintf(cmd, sizeof(cmd), "ifconfig %s up 2>/dev/null", interface_name);
8423 _syscmd(cmd, buf, sizeof(buf));
8424 return 0;
8425}
8426
8427//>> Deprecated. Replace with wifi_applyRadioSettings
8428INT wifi_pushBridgeInfo(INT apIndex)
8429{
8430 char interface_name[16] = {0};
8431 char ip[32] = {0};
8432 char subnet[32] = {0};
8433 char bridge[32] = {0};
8434 int vlanId = 0;
8435 char cmd[128] = {0};
8436 char buf[1024] = {0};
8437
8438 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
8439 wifi_getApVlanID(apIndex,&vlanId);
8440
8441 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
8442 return RETURN_ERR;
8443 snprintf(cmd, sizeof(cmd), "cfgVlan %s %s %d %s ", interface_name, bridge, vlanId, ip);
8444 _syscmd(cmd,buf, sizeof(buf));
8445
8446 return 0;
8447}
8448
8449INT wifi_pushChannel(INT radioIndex, UINT channel)
8450{
8451 char interface_name[16] = {0};
8452 char cmd[128];
8453 char buf[1024];
8454 int apIndex;
8455
developer69b61b02023-03-07 17:17:44 +08008456 apIndex=(radioIndex==0)?0:1;
developer72fb0bb2023-01-11 09:46:29 +08008457 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
8458 return RETURN_ERR;
8459 snprintf(cmd, sizeof(cmd), "iwconfig %s freq %d",interface_name,channel);
8460 _syscmd(cmd,buf, sizeof(buf));
8461
8462 return 0;
8463}
8464
8465INT wifi_pushChannelMode(INT radioIndex)
8466{
8467 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
8468 return RETURN_ERR;
8469}
8470
8471INT wifi_pushDefaultValues(INT radioIndex)
8472{
8473 //Apply Comcast specified default radio settings instantly
8474 //AMPDU=1
8475 //AMPDUFrames=32
8476 //AMPDULim=50000
8477 //txqueuelen=1000
8478
8479 return RETURN_ERR;
8480}
8481
8482INT wifi_pushTxChainMask(INT radioIndex)
8483{
8484 //Apply default TxChainMask instantly
8485 return RETURN_ERR;
8486}
8487
8488INT wifi_pushRxChainMask(INT radioIndex)
8489{
8490 //Apply default RxChainMask instantly
8491 return RETURN_ERR;
8492}
8493
8494INT wifi_pushSSID(INT apIndex, CHAR *ssid)
8495{
8496 INT status;
8497
8498 status = wifi_setSSIDName(apIndex,ssid);
8499 wifi_setApEnable(apIndex,FALSE);
8500 wifi_setApEnable(apIndex,TRUE);
8501
8502 return status;
8503}
8504
8505INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
8506{
8507 //Apply default Ssid Advertisement instantly
8508 return RETURN_ERR;
8509}
8510
8511INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
8512{
8513 INT status = RETURN_ERR;
8514 *output = 0;
8515 return RETURN_ERR;
8516}
8517
8518INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
8519{
8520 return RETURN_OK;
8521}
8522
8523INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
8524{
8525 return RETURN_OK;
8526}
8527
8528//To-do
8529INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
8530{
8531 char output[16]={'\0'};
8532 char config_file[MAX_BUF_SIZE] = {0};
8533
8534 if (!output_string)
8535 return RETURN_ERR;
8536
8537 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8538 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
8539
8540 if (strlen(output) == 0)
8541 snprintf(output_string, 64, "Disabled");
8542 else if (strncmp(output, "0", 1) == 0)
8543 snprintf(output_string, 64, "Disabled");
8544 else if (strncmp(output, "1", 1) == 0)
8545 snprintf(output_string, 64, "Optional");
8546 else if (strncmp(output, "2", 1) == 0)
8547 snprintf(output_string, 64, "Required");
8548 else {
8549 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
8550 return RETURN_ERR;
8551 }
8552
8553 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
8554 return RETURN_OK;
8555}
8556INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
8557{
8558 char str[MAX_BUF_SIZE]={'\0'};
8559 char cmd[MAX_CMD_SIZE]={'\0'};
8560 struct params params;
8561 char config_file[MAX_BUF_SIZE] = {0};
8562
8563 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8564 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
8565 return RETURN_ERR;
8566
8567 params.name = "ieee80211w";
8568 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
8569 params.value = "0";
8570 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
8571 params.value = "1";
8572 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
8573 params.value = "2";
8574 else{
8575 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
8576 return RETURN_ERR;
8577 }
8578 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8579 wifi_hostapdWrite(config_file, &params, 1);
8580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
8581 return RETURN_OK;
8582}
8583INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
8584{
8585 char output[16]={'\0'};
8586 char config_file[MAX_BUF_SIZE] = {0};
8587
8588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8589 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
8590 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
8591
8592 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
8593 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8594
8595 return RETURN_OK;
8596}
8597
8598INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
8599{
8600 return RETURN_OK;
8601}
8602
8603INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
8604{
8605 return RETURN_OK;
8606}
8607
8608INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
8609{
8610 return RETURN_OK;
8611}
8612
8613INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8614{
8615 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8616 char config_file[MAX_BUF_SIZE] = {0};
8617
8618 if (NULL == output)
8619 return RETURN_ERR;
8620 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8621 wifi_hostapdRead(config_file,"hw_mode",output,64);
8622
8623 if(strcmp(output,"b")==0)
8624 sprintf(output, "%s", "1,2,5.5,11");
8625 else if (strcmp(output,"a")==0)
8626 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
8627 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
8628 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
8629
8630 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8631 return RETURN_OK;
8632}
8633
8634INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8635{
8636 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8637 char *temp;
8638 char temp_output[128];
8639 char temp_TransmitRates[128];
8640 char config_file[MAX_BUF_SIZE] = {0};
8641
8642 if (NULL == output)
8643 return RETURN_ERR;
8644
8645 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8646 wifi_hostapdRead(config_file,"supported_rates",output,64);
8647
8648 if (strlen(output) == 0) {
8649 wifi_getRadioSupportedDataTransmitRates(wlanIndex, output);
8650 return RETURN_OK;
8651 }
8652 strcpy(temp_TransmitRates,output);
8653 strcpy(temp_output,"");
8654 temp = strtok(temp_TransmitRates," ");
8655 while(temp!=NULL)
8656 {
8657 temp[strlen(temp)-1]=0;
8658 if((temp[0]=='5') && (temp[1]=='\0'))
8659 {
8660 temp="5.5";
8661 }
8662 strcat(temp_output,temp);
8663 temp = strtok(NULL," ");
8664 if(temp!=NULL)
8665 {
8666 strcat(temp_output,",");
8667 }
8668 }
8669 strcpy(output,temp_output);
8670 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8671
8672 return RETURN_OK;
8673}
8674
8675INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
8676{
8677 return RETURN_OK;
8678}
8679
8680
8681INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
8682{
8683 int i=0;
8684 char *temp;
8685 char temp1[128] = {0};
8686 char temp_output[128] = {0};
8687 char temp_TransmitRates[128] = {0};
8688 struct params params={'\0'};
8689 char config_file[MAX_BUF_SIZE] = {0};
8690 wifi_band band = wifi_index_to_band(wlanIndex);
8691
8692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8693 if(NULL == output)
8694 return RETURN_ERR;
8695 strcpy(temp_TransmitRates,output);
8696
8697 for(i=0;i<strlen(temp_TransmitRates);i++)
8698 {
8699 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) || (temp_TransmitRates[i]==' ') || (temp_TransmitRates[i]=='.') || (temp_TransmitRates[i]==','))
8700 {
8701 continue;
8702 }
8703 else
8704 {
8705 return RETURN_ERR;
8706 }
8707 }
8708 strcpy(temp_output,"");
8709 temp = strtok(temp_TransmitRates,",");
8710 while(temp!=NULL)
8711 {
8712 strcpy(temp1,temp);
8713 if(band == band_5)
8714 {
8715 if((strcmp(temp,"1")==0) || (strcmp(temp,"2")==0) || (strcmp(temp,"5.5")==0))
8716 {
8717 return RETURN_ERR;
8718 }
8719 }
8720
8721 if(strcmp(temp,"5.5")==0)
8722 {
8723 strcpy(temp1,"55");
8724 }
8725 else
8726 {
8727 strcat(temp1,"0");
8728 }
8729 strcat(temp_output,temp1);
8730 temp = strtok(NULL,",");
8731 if(temp!=NULL)
8732 {
8733 strcat(temp_output," ");
8734 }
8735 }
8736 strcpy(output,temp_output);
8737
8738 params.name = "supported_rates";
8739 params.value = output;
8740
8741 wifi_dbg_printf("\n%s:",__func__);
8742 wifi_dbg_printf("params.value=%s\n",params.value);
8743 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8744 wifi_hostapdWrite(config_file,&params,1);
8745 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8746
8747 return RETURN_OK;
8748}
8749
8750
8751static char *sncopy(char *dst, int dst_sz, const char *src)
8752{
8753 if (src && dst && dst_sz > 0) {
8754 strncpy(dst, src, dst_sz);
8755 dst[dst_sz - 1] = '\0';
8756 }
8757 return dst;
8758}
8759
8760static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8761{
8762 if (0 == strcmp(ht_mode, "HT40") ||
8763 0 == strcmp(ht_mode, "HT80") ||
8764 0 == strcmp(ht_mode, "HT160")) {
8765 switch (channel) {
8766 case 1 ... 7:
8767 case 36:
8768 case 44:
8769 case 52:
8770 case 60:
8771 case 100:
8772 case 108:
8773 case 116:
8774 case 124:
8775 case 132:
8776 case 140:
8777 case 149:
8778 case 157:
8779 return 1;
8780 case 8 ... 13:
8781 case 40:
8782 case 48:
8783 case 56:
8784 case 64:
8785 case 104:
8786 case 112:
8787 case 120:
8788 case 128:
8789 case 136:
8790 case 144:
8791 case 153:
8792 case 161:
8793 return -1;
8794 default:
8795 return -EINVAL;
8796 }
8797 }
8798
8799 return -EINVAL;
8800}
8801
8802static int util_get_6g_sec_chan_offset(int channel, const char* ht_mode)
8803{
8804 int idx = channel%8;
8805 if (0 == strcmp(ht_mode, "HT40") ||
8806 0 == strcmp(ht_mode, "HT80") ||
8807 0 == strcmp(ht_mode, "HT160")) {
8808 switch (idx) {
8809 case 1:
8810 return 1;
8811 case 5:
8812 return -1;
8813 default:
8814 return -EINVAL;
8815 }
8816 }
8817
8818 return -EINVAL;
8819}
8820static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8821{
8822 if (NULL == hw_mode) return;
8823
8824 if (0 == strcmp(hw_mode, "ac"))
8825 sncopy(bw_mode, bw_mode_len, "ht vht");
8826
8827 if (0 == strcmp(hw_mode, "n"))
8828 sncopy(bw_mode, bw_mode_len, "ht");
8829
8830 return;
8831}
8832
8833static int util_chan_to_freq(int chan)
8834{
8835 if (chan == 14)
8836 return 2484;
8837 else if (chan < 14)
8838 return 2407 + chan * 5;
8839 else if (chan >= 182 && chan <= 196)
8840 return 4000 + chan * 5;
8841 else
8842 return 5000 + chan * 5;
8843 return 0;
8844}
8845
8846static int util_6G_chan_to_freq(int chan)
8847{
8848 if (chan)
8849 return 5950 + chan * 5;
8850 else
8851 return 0;
developer69b61b02023-03-07 17:17:44 +08008852
developer72fb0bb2023-01-11 09:46:29 +08008853}
8854const int *util_unii_5g_chan2list(int chan, int width)
8855{
8856 static const int lists[] = {
8857 // <width>, <chan1>, <chan2>..., 0,
8858 20, 36, 0,
8859 20, 40, 0,
8860 20, 44, 0,
8861 20, 48, 0,
8862 20, 52, 0,
8863 20, 56, 0,
8864 20, 60, 0,
8865 20, 64, 0,
8866 20, 100, 0,
8867 20, 104, 0,
8868 20, 108, 0,
8869 20, 112, 0,
8870 20, 116, 0,
8871 20, 120, 0,
8872 20, 124, 0,
8873 20, 128, 0,
8874 20, 132, 0,
8875 20, 136, 0,
8876 20, 140, 0,
8877 20, 144, 0,
8878 20, 149, 0,
8879 20, 153, 0,
8880 20, 157, 0,
8881 20, 161, 0,
8882 20, 165, 0,
8883 40, 36, 40, 0,
8884 40, 44, 48, 0,
8885 40, 52, 56, 0,
8886 40, 60, 64, 0,
8887 40, 100, 104, 0,
8888 40, 108, 112, 0,
8889 40, 116, 120, 0,
8890 40, 124, 128, 0,
8891 40, 132, 136, 0,
8892 40, 140, 144, 0,
8893 40, 149, 153, 0,
8894 40, 157, 161, 0,
8895 80, 36, 40, 44, 48, 0,
8896 80, 52, 56, 60, 64, 0,
8897 80, 100, 104, 108, 112, 0,
8898 80, 116, 120, 124, 128, 0,
8899 80, 132, 136, 140, 144, 0,
8900 80, 149, 153, 157, 161, 0,
8901 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8902 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8903 -1 // final delimiter
8904 };
8905 const int *start;
8906 const int *p;
8907
8908 for (p = lists; *p != -1; p++) {
8909 if (*p == width) {
8910 for (start = ++p; *p != 0; p++) {
8911 if (*p == chan)
8912 return start;
8913 }
8914 }
8915 // move to the end of channel list of given width
8916 while (*p != 0) {
8917 p++;
8918 }
8919 }
8920
8921 return NULL;
8922}
8923
8924static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8925{
8926 if (NULL == ht_mode)
8927 return 0;
8928
8929 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8930 const int *chans = util_unii_5g_chan2list(channel, width);
8931 int sum = 0;
8932 int cnt = 0;
8933
8934 if (NULL == chans)
8935 return 0;
8936
8937 while (*chans) {
8938 sum += *chans;
8939 cnt++;
8940 chans++;
8941 }
8942 if (cnt == 0)
8943 return 0;
8944 return sum / cnt;
8945}
8946
8947static int util_unii_6g_centerfreq(const char *ht_mode, int channel)
8948{
8949 if (NULL == ht_mode)
8950 return 0;
8951
8952 int width = strtol((ht_mode + 2), NULL, 10);
8953
8954 int idx = 0 ;
8955 int centerchan = 0;
8956 int chan_ofs = 1;
8957
8958 if (width == 40){
8959 idx = ((channel/4) + chan_ofs)%2;
8960 switch (idx) {
8961 case 0:
8962 centerchan = (channel - 2);
8963 break;
8964 case 1:
8965 centerchan = (channel + 2);
developer69b61b02023-03-07 17:17:44 +08008966 break;
developer72fb0bb2023-01-11 09:46:29 +08008967 default:
8968 return -EINVAL;
8969 }
8970 }else if (width == 80){
developer69b61b02023-03-07 17:17:44 +08008971 idx = ((channel/4) + chan_ofs)%4;
developer72fb0bb2023-01-11 09:46:29 +08008972 switch (idx) {
8973 case 0:
8974 centerchan = (channel - 6);
8975 break;
8976 case 1:
8977 centerchan = (channel + 6);
8978 break;
8979 case 2:
8980 centerchan = (channel + 2);
8981 break;
8982 case 3:
8983 centerchan = (channel - 2);
8984 break;
8985 default:
8986 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08008987 }
developer72fb0bb2023-01-11 09:46:29 +08008988 }else if (width == 160){
8989 switch (channel) {
8990 case 1 ... 29:
8991 centerchan = 15;
8992 break;
8993 case 33 ... 61:
8994 centerchan = 47;
8995 break;
8996 case 65 ... 93:
8997 centerchan = 79;
8998 break;
8999 case 97 ... 125:
9000 centerchan = 111;
9001 break;
9002 case 129 ... 157:
9003 centerchan = 143;
9004 break;
9005 case 161 ... 189:
9006 centerchan = 175;
9007 break;
9008 case 193 ... 221:
9009 centerchan = 207;
9010 break;
9011 default:
9012 return -EINVAL;
developer69b61b02023-03-07 17:17:44 +08009013 }
developer72fb0bb2023-01-11 09:46:29 +08009014 }
9015 return centerchan;
9016}
9017static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
9018{
9019 BOOL onlyG, onlyN, onlyA;
9020 CHAR tmp[64];
9021 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
9022 if (ret == RETURN_OK) {
9023 sncopy(hw_mode, hw_mode_size, tmp);
9024 }
9025 return ret;
9026}
9027
9028INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
9029{
9030 // Sample commands:
9031 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
9032 // hostapd_cli -i wifi0 chan_switch 30 2437
9033 char cmd[MAX_CMD_SIZE] = {0};
9034 char buf[MAX_BUF_SIZE] = {0};
9035 int freq = 0, ret = 0;
9036 char center_freq1_str[32] = ""; // center_freq1=%d
9037 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
9038 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
9039 char hw_mode[16] = ""; // n|ac
9040 char bw_mode[16] = ""; // ht|ht vht
9041 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
9042 char interface_name[16] = {0};
9043 int sec_chan_offset;
9044 int width;
9045 char config_file[64] = {0};
9046 BOOL stbcEnable = FALSE;
9047 char *ext_str = "None";
9048 wifi_band band = band_invalid;
9049 int center_chan = 0;
9050 int center_freq1 = 0;
9051
9052 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
9053
9054 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9055 return RETURN_ERR;
9056
9057 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9058
9059 band = wifi_index_to_band(radioIndex);
9060
9061 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
9062
9063 // Get radio mode HT20|HT40|HT80 etc.
9064 if (channel){
9065 if (band == band_6){
9066 freq = util_6G_chan_to_freq(channel);
9067 }else{
9068 freq = util_chan_to_freq(channel);
9069 }
9070 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
9071
9072 // Provide bandwith if specified
9073 if (channel_width_MHz > 20) {
9074 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
9075 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
9076 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
9077
9078 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
9079 }else if (channel_width_MHz == 20){
9080 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d ht", width);
9081 }
9082
9083
9084 if (channel_width_MHz > 20) {
9085 if (band == band_6){
9086 center_chan = util_unii_6g_centerfreq(ht_mode, channel);
9087 if(center_chan){
9088 center_freq1 = util_6G_chan_to_freq(center_chan);
9089 }
9090 }else{
9091 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
9092 if(center_chan){
9093 center_freq1 = util_chan_to_freq(center_chan);
9094 }
9095 }
developer69b61b02023-03-07 17:17:44 +08009096
developer72fb0bb2023-01-11 09:46:29 +08009097 if (center_freq1)
9098 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
developer69b61b02023-03-07 17:17:44 +08009099
developer72fb0bb2023-01-11 09:46:29 +08009100 }
9101
9102 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
9103 if (band == band_6){
9104 sec_chan_offset = util_get_6g_sec_chan_offset(channel, ht_mode);
9105 }else{
9106 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
9107 }
9108 if (sec_chan_offset != -EINVAL)
9109 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
9110
9111 // Only the first AP, other are hanging on the same radio
9112 int apIndex = radioIndex;
9113 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s chan_switch %d %d %s %s %s",
9114 interface_name, csa_beacon_count, freq,
9115 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
9116 wifi_dbg_printf("execute: '%s'\n", cmd);
9117 ret = _syscmd(cmd, buf, sizeof(buf));
9118 wifi_reloadAp(radioIndex);
9119
9120 ret = wifi_setRadioChannel(radioIndex, channel);
9121 if (ret != RETURN_OK) {
9122 fprintf(stderr, "%s: wifi_setRadioChannel return error.\n", __func__);
9123 return RETURN_ERR;
9124 }
9125
9126 if (sec_chan_offset == 1) ext_str = "Above";
9127 else if (sec_chan_offset == -1) ext_str = "Below";
9128
9129 wifi_setRadioCenterChannel(radioIndex, center_chan);
9130
9131 } else {
9132 if (channel_width_MHz > 20)
9133 ext_str = "Above";
9134 }
9135
9136 wifi_setRadioExtChannel(radioIndex, ext_str);
9137
9138 char mhz_str[16];
9139 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
9140 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
9141
9142 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9143
9144 return RETURN_OK;
9145}
9146
9147INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
9148{
9149 int index = -1;
9150 wifi_neighbor_ap2_t *scan_array = NULL;
9151 char cmd[256]={0};
9152 char buf[128]={0};
9153 char file_name[32] = {0};
9154 char filter_SSID[32] = {0};
9155 char line[256] = {0};
9156 char interface_name[16] = {0};
9157 char *ret = NULL;
9158 int freq=0;
9159 FILE *f = NULL;
9160 size_t len=0;
9161 int channels_num = 0;
9162 int vht_channel_width = 0;
9163 int get_noise_ret = RETURN_ERR;
9164 bool filter_enable = false;
9165 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
9166 int phyId = 0;
9167
9168 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
9169
9170 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
9171 f = fopen(file_name, "r");
9172 if (f != NULL) {
9173 fgets(filter_SSID, sizeof(file_name), f);
9174 if (strlen(filter_SSID) != 0)
9175 filter_enable = true;
9176 fclose(f);
9177 }
9178
9179 if (wifi_GetInterfaceName(radio_index, interface_name) != RETURN_OK)
9180 return RETURN_ERR;
9181
9182 phyId = radio_index_to_phy(radio_index);
9183
9184 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", phyId);
9185 _syscmd(cmd, buf, sizeof(buf));
9186 channels_num = strtol(buf, NULL, 10);
9187
9188 sprintf(cmd, "iw dev %s scan dump | grep '%s\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
9189 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", interface_name, interface_name);
9190 fprintf(stderr, "cmd: %s\n", cmd);
9191 if ((f = popen(cmd, "r")) == NULL) {
9192 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9193 return RETURN_ERR;
9194 }
developer69b61b02023-03-07 17:17:44 +08009195
developer72fb0bb2023-01-11 09:46:29 +08009196 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
9197 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
developer69b61b02023-03-07 17:17:44 +08009198
developer72fb0bb2023-01-11 09:46:29 +08009199 ret = fgets(line, sizeof(line), f);
9200 while (ret != NULL) {
9201 if(strstr(line, "BSS") != NULL) { // new neighbor info
developer69b61b02023-03-07 17:17:44 +08009202 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
developer72fb0bb2023-01-11 09:46:29 +08009203 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
9204 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
9205
9206 if (!filter_BSS) {
9207 index++;
9208 wifi_neighbor_ap2_t *tmp;
9209 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
9210 if (tmp == NULL) { // no more memory to use
9211 index--;
9212 wifi_dbg_printf("%s: realloc failed\n", __func__);
9213 break;
9214 }
9215 scan_array = tmp;
9216 }
9217 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9218
9219 filter_BSS = false;
9220 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
9221 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
9222 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
9223 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
9224 } else if (strstr(line, "freq") != NULL) {
9225 sscanf(line," freq: %d", &freq);
9226 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
9227
9228 if (freq >= 2412 && freq <= 2484) {
9229 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
9230 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
9231 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
9232 }
9233 else if (freq >= 5160 && freq <= 5805) {
9234 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
9235 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
9236 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
9237 }
9238
9239 scan_array[index].ap_Noise = 0;
9240 if (get_noise_ret == RETURN_OK) {
9241 for (int i = 0; i < channels_num; i++) {
9242 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
9243 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
9244 break;
9245 }
9246 }
9247 }
9248 } else if (strstr(line, "beacon interval") != NULL) {
9249 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
9250 } else if (strstr(line, "signal") != NULL) {
9251 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
9252 } else if (strstr(line,"SSID") != NULL) {
9253 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
9254 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
9255 filter_BSS = true;
9256 }
9257 } else if (strstr(line, "Supported rates") != NULL) {
9258 char SRate[80] = {0}, *tmp = NULL;
9259 memset(buf, 0, sizeof(buf));
9260 strcpy(SRate, line);
9261 tmp = strtok(SRate, ":");
9262 tmp = strtok(NULL, ":");
9263 strcpy(buf, tmp);
9264 memset(SRate, 0, sizeof(SRate));
9265
9266 tmp = strtok(buf, " \n");
9267 while (tmp != NULL) {
9268 strcat(SRate, tmp);
9269 if (SRate[strlen(SRate) - 1] == '*') {
9270 SRate[strlen(SRate) - 1] = '\0';
9271 }
9272 strcat(SRate, ",");
9273
9274 tmp = strtok(NULL, " \n");
9275 }
9276 SRate[strlen(SRate) - 1] = '\0';
9277 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
9278 } else if (strstr(line, "DTIM") != NULL) {
9279 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
9280 } else if (strstr(line, "VHT capabilities") != NULL) {
9281 strcat(scan_array[index].ap_SupportedStandards, ",ac");
9282 strcpy(scan_array[index].ap_OperatingStandards, "ac");
9283 } else if (strstr(line, "HT capabilities") != NULL) {
9284 strcat(scan_array[index].ap_SupportedStandards, ",n");
9285 strcpy(scan_array[index].ap_OperatingStandards, "n");
9286 } else if (strstr(line, "VHT operation") != NULL) {
9287 ret = fgets(line, sizeof(line), f);
9288 sscanf(line," * channel width: %d", &vht_channel_width);
9289 if(vht_channel_width == 1) {
9290 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
9291 } else {
9292 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
9293 }
9294 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9295 continue;
9296 } else if (strstr(line, "HT operation") != NULL) {
9297 ret = fgets(line, sizeof(line), f);
9298 sscanf(line," * secondary channel offset: %s", &buf);
9299 if (!strcmp(buf, "above")) {
9300 //40Mhz +
9301 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
9302 }
9303 else if (!strcmp(buf, "below")) {
9304 //40Mhz -
9305 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
9306 } else {
9307 //20Mhz
9308 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
9309 }
9310 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
9311 continue;
9312 } else if (strstr(line, "HE capabilities") != NULL) {
9313 strcat(scan_array[index].ap_SupportedStandards, ",ax");
9314 strcpy(scan_array[index].ap_OperatingStandards, "ax");
9315 ret = fgets(line, sizeof(line), f);
9316 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
9317 if (strstr(line, "HE40/2.4GHz") != NULL)
9318 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
9319 else
9320 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
9321 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
9322 if (strstr(line, "HE80/5GHz") != NULL) {
9323 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
9324 ret = fgets(line, sizeof(line), f);
9325 } else
9326 continue;
9327 if (strstr(line, "HE160/5GHz") != NULL)
9328 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
9329 }
9330 continue;
9331 } else if (strstr(line, "WPA") != NULL) {
9332 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
9333 } else if (strstr(line, "RSN") != NULL) {
9334 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
9335 } else if (strstr(line, "Group cipher") != NULL) {
9336 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
9337 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
9338 strcpy(scan_array[index].ap_EncryptionMode, "AES");
9339 }
9340 }
9341 ret = fgets(line, sizeof(line), f);
9342 }
9343
9344 if (!filter_BSS) {
9345 *output_array_size = index + 1;
9346 } else {
9347 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
9348 *output_array_size = index;
9349 }
9350 *neighbor_ap_array = scan_array;
9351 pclose(f);
9352 free(channels_noise_arr);
9353 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9354 return RETURN_OK;
9355}
9356
9357INT wifi_getApAssociatedDeviceStats(
9358 INT apIndex,
9359 mac_address_t *clientMacAddress,
9360 wifi_associated_dev_stats_t *associated_dev_stats,
9361 u64 *handle)
9362{
9363 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
9364 char interface_name[50] = {0};
9365 char cmd[1024] = {0};
9366 char mac_str[18] = {0};
9367 char *key = NULL;
9368 char *val = NULL;
9369 FILE *f = NULL;
9370 char *line = NULL;
9371 size_t len = 0;
9372
9373 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9374 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9375 return RETURN_ERR;
9376 }
9377
9378 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
9379 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
9380 if((f = popen(cmd, "r")) == NULL) {
9381 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
9382 return RETURN_ERR;
9383 }
9384
9385 while ((getline(&line, &len, f)) != -1) {
9386 key = strtok(line,":");
9387 val = strtok(NULL,":");
9388
9389 if(!strncmp(key,"rx bytes",8))
9390 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
9391 if(!strncmp(key,"tx bytes",8))
9392 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
9393 if(!strncmp(key,"rx packets",10))
9394 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9395 if(!strncmp(key,"tx packets",10))
9396 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
9397 if(!strncmp(key,"tx retries",10))
9398 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
9399 if(!strncmp(key,"tx failed",9))
9400 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
9401 if(!strncmp(key,"rx drop misc",13))
9402 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
9403 if(!strncmp(key,"rx bitrate",10)) {
9404 val = strtok(val, " ");
9405 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
9406 }
9407 if(!strncmp(key,"tx bitrate",10)) {
9408 val = strtok(val, " ");
9409 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
9410 }
9411 }
9412 free(line);
9413 pclose(f);
9414 return RETURN_OK;
9415}
9416
9417INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
9418{
9419 char interface_name[16] = {0};
9420 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
9421
9422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9423 if (NULL == output_string)
9424 return RETURN_ERR;
9425
9426 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
9427 return RETURN_ERR;
9428 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", interface_name);
9429 _syscmd(cmd, buf, sizeof(buf));
9430
9431 //size of SSID name restricted to value less than 32 bytes
9432 snprintf(output_string, 32, "%s", buf);
9433 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
9434
9435 return RETURN_OK;
9436}
9437
9438INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
9439{
9440 //char cmd[MAX_CMD_SIZE] = {0};
9441 char config_file[MAX_BUF_SIZE] = {0};
9442 char buf[32] = {0};
9443
9444 if (!output_filterMode)
9445 return RETURN_ERR;
9446
9447 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
9448 //_syscmd(cmd, buf, sizeof(buf));
9449 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
9450 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
9451 if(strlen(buf) == 0) {
9452 *output_filterMode = 0;
9453 }
9454 else {
9455 int macaddr_acl_mode = strtol(buf, NULL, 10);
9456 if (macaddr_acl_mode == 1) {
9457 *output_filterMode = 1;
9458 } else if (macaddr_acl_mode == 0) {
9459 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
9460 if (strlen(buf) == 0) {
9461 *output_filterMode = 0;
9462 } else {
9463 *output_filterMode = 2;
9464 }
9465 } else {
9466 return RETURN_ERR;
9467 }
9468 }
9469
9470 return RETURN_OK;
9471}
9472
9473INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
9474{
9475 FILE *fp = NULL;
9476 char str[MAX_BUF_SIZE] = {0};
9477 int wificlientindex = 0 ;
9478 int count = 0;
9479 int signalstrength = 0;
9480 int arr[MACADDRESS_SIZE] = {0};
9481 unsigned char mac[MACADDRESS_SIZE] = {0};
9482 UINT wifi_count = 0;
9483 char virtual_interface_name[MAX_BUF_SIZE] = {0};
9484 char pipeCmd[MAX_CMD_SIZE] = {0};
9485
9486 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9487 *output_array_size = 0;
9488 *associated_dev_array = NULL;
9489 char interface_name[50] = {0};
9490
9491 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
9492 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
9493 return RETURN_ERR;
9494 }
9495
9496 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
9497 fp = popen(pipeCmd, "r");
9498 if (fp == NULL)
9499 {
9500 printf("Failed to run command inside function %s\n",__FUNCTION__ );
9501 return RETURN_ERR;
9502 }
9503
9504 /* Read the output a line at a time - output it. */
9505 fgets(str, sizeof(str)-1, fp);
9506 wifi_count = (unsigned int) atoi ( str );
9507 *output_array_size = wifi_count;
9508 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
9509 pclose(fp);
9510
9511 if(wifi_count == 0)
9512 {
9513 return RETURN_OK;
9514 }
9515 else
9516 {
9517 wifi_associated_dev2_t* temp = NULL;
9518 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
9519 *associated_dev_array = temp;
9520 if(temp == NULL)
9521 {
9522 printf("Error Statement. Insufficient memory \n");
9523 return RETURN_ERR;
9524 }
9525
9526 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
9527 system(pipeCmd);
9528
9529 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
9530 if(fp == NULL)
9531 {
9532 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
9533 return RETURN_ERR;
9534 }
9535 fclose(fp);
9536
9537 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2");
9538 fp = popen(pipeCmd, "r");
9539 if(fp)
9540 {
9541 for(count =0 ; count < wifi_count; count++)
9542 {
9543 fgets(str, MAX_BUF_SIZE, fp);
9544 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
9545 {
9546 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
9547 {
9548 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
9549
9550 }
9551 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
9552 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]);
9553 }
9554 temp[count].cli_AuthenticationState = 1; //TODO
9555 temp[count].cli_Active = 1; //TODO
9556 }
9557 pclose(fp);
9558 }
9559
9560 //Updating RSSI per client
9561 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt");
9562 fp = popen(pipeCmd, "r");
9563 if(fp)
9564 {
9565 pclose(fp);
9566 }
9567 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
9568 if(fp)
9569 {
9570 for(count =0 ; count < wifi_count ;count++)
9571 {
9572 fgets(str, MAX_BUF_SIZE, fp);
9573 signalstrength = atoi(str);
9574 temp[count].cli_RSSI = signalstrength;
9575 }
9576 pclose(fp);
9577 }
9578
9579
9580 //LastDataDownlinkRate
9581 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt");
9582 fp = popen(pipeCmd, "r");
9583 if (fp)
9584 {
9585 pclose(fp);
9586 }
9587 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
9588 if (fp)
9589 {
9590 for (count = 0; count < wifi_count; count++)
9591 {
9592 fgets(str, MAX_BUF_SIZE, fp);
9593 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
9594 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
9595 }
9596 pclose(fp);
9597 }
9598
9599 //LastDataUplinkRate
9600 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt");
9601 fp = popen(pipeCmd, "r");
9602 if (fp)
9603 {
9604 pclose(fp);
9605 }
9606 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
9607 if (fp)
9608 {
9609 for (count = 0; count < wifi_count; count++)
9610 {
9611 fgets(str, MAX_BUF_SIZE, fp);
9612 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
9613 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
9614 }
9615 pclose(fp);
9616 }
9617 }
9618 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9619 return RETURN_OK;
9620
9621}
9622
9623INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
9624{
9625#if 0
9626 /*char buf[1024] = {0};
9627 sprintf(cmd, "ifconfig %s ", interface_name);
9628 _syscmd(cmd, buf, sizeof(buf));*/
9629
9630 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
9631 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
9632 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
9633 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
9634
9635 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.
9636 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].
9637 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].
9638 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].
9639 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
9640 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
9641
9642 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
9643 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9644 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
9645 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.
9646 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.
9647 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.
9648 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.
9649 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.
9650 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.
9651 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.
9652 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
9653#endif
9654
9655 FILE *fp = NULL;
9656 char interface_name[50] = {0};
9657 char pipeCmd[128] = {0};
9658 char str[256] = {0};
9659 wifi_ssidTrafficStats2_t *out = output_struct;
9660
9661 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
9662 if (!output_struct)
9663 return RETURN_ERR;
9664
9665 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
9666 if (wifi_GetInterfaceName(ssidIndex, interface_name) != RETURN_OK)
9667 return RETURN_ERR;
9668 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
9669
9670 fp = popen(pipeCmd, "r");
9671 if (fp == NULL) {
9672 fprintf(stderr, "%s: popen failed\n", __func__);
9673 return RETURN_ERR;
9674 }
9675 fgets(str, sizeof(str), fp);
9676 pclose(fp);
9677
9678 if (strlen(str) == 0) // interface not exist
9679 return RETURN_OK;
9680
9681 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
9682 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
9683
9684 memset(str, 0, sizeof(str));
9685 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
9686 fp = popen(pipeCmd, "r");
9687 if (fp == NULL) {
9688 fprintf(stderr, "%s: popen failed\n", __func__);
9689 return RETURN_ERR;
9690 }
9691 fgets(str, sizeof(str), fp);
9692
9693 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
9694 &out->ssid_BroadcastPacketsSent);
9695 pclose(fp);
9696
9697 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
9698 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
9699
9700 // Not supported
9701 output_struct->ssid_RetransCount = 0;
9702 output_struct->ssid_FailedRetransCount = 0;
9703 output_struct->ssid_RetryCount = 0;
9704 output_struct->ssid_MultipleRetryCount = 0;
9705 output_struct->ssid_ACKFailureCount = 0;
9706 output_struct->ssid_AggregatedPacketCount = 0;
9707
9708 return RETURN_OK;
9709}
9710
9711//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).
9712INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
9713{
9714 char output_val[16]={'\0'};
9715 char config_file[MAX_BUF_SIZE] = {0};
9716
9717 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9718 if (!output)
9719 return RETURN_ERR;
9720 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9721 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
9722
9723 if( strcmp(output_val,"1") == 0 )
9724 *output = TRUE;
9725 else
9726 *output = FALSE;
9727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9728
9729 return RETURN_OK;
9730}
9731
9732INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
9733{
9734 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9735 char str[MAX_BUF_SIZE]={'\0'};
9736 char string[MAX_BUF_SIZE]={'\0'};
9737 char cmd[MAX_CMD_SIZE]={'\0'};
9738 char *ch;
9739 char config_file[MAX_BUF_SIZE] = {0};
9740 struct params params;
9741
9742 if(enable == TRUE)
9743 strcpy(string,"1");
9744 else
9745 strcpy(string,"0");
9746
9747 params.name = "ap_isolate";
9748 params.value = string;
9749
9750 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9751 wifi_hostapdWrite(config_file,&params,1);
9752 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9753
9754 return RETURN_OK;
9755}
9756
9757INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
9758{
9759 if (NULL == output_dBm)
9760 return RETURN_ERR;
9761
9762 *output_dBm = 0;
9763 return RETURN_OK;
9764}
9765
9766INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
9767{
9768 return RETURN_OK;
9769}
9770INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
9771{
9772 return RETURN_OK;
9773}
9774INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
9775{
9776 return RETURN_OK;
9777}
9778INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
9779{
9780 return RETURN_OK;
9781}
9782INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
9783{
9784 return RETURN_OK;
9785}
9786INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
9787{
9788 char config_file[MAX_BUF_SIZE] = {0};
9789 struct params list;
9790
9791 list.name = "bss_transition";
9792 list.value = activate?"1":"0";
9793 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
9794 wifi_hostapdWrite(config_file, &list, 1);
9795
9796 return RETURN_OK;
9797}
9798wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
9799
9800void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
9801{
9802 return;
9803}
9804
9805INT wifi_setApCsaDeauth(INT apIndex, INT mode)
9806{
9807 // TODO Implement me!
9808 return RETURN_OK;
9809}
9810
9811INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
9812{
9813 char file_name[128] = {0};
9814 char buf[128] = {0};
9815 FILE *f = NULL;
9816 int max_num_radios = 0;
9817
9818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9819
9820 wifi_getMaxRadioNumber(&max_num_radios);
9821 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
9822 for (int index = 0; index < max_num_radios; index++) {
9823 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
9824 f = fopen(file_name, "w");
9825 if (f == NULL)
9826 return RETURN_ERR;
9827 // For mode == 0 is to disable filter, just don't write to the file.
9828 if (mode)
9829 fprintf(f, "%s", essid);
9830
9831 fclose(f);
9832 }
9833 } else { // special case, need to set AP's SSID as filter for each radio.
9834 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
9835 f = fopen(file_name, "w");
9836 if (f == NULL)
9837 return RETURN_ERR;
9838
9839 // For mode == 0 is to disable filter, just don't write to the file.
9840 if (mode)
9841 fprintf(f, "%s", essid);
9842
9843 fclose(f);
9844 }
9845
9846 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9847 return RETURN_OK;
9848}
9849
9850INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9851{
9852 // TODO Implement me!
9853 //Apply wifi_pushRadioChannel() instantly
9854 return RETURN_ERR;
9855}
9856
9857INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9858{
9859 // TODO Implement me!
9860 return RETURN_OK;
9861}
9862
9863#ifdef HAL_NETLINK_IMPL
9864static int tidStats_callback(struct nl_msg *msg, void *arg) {
9865 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9866 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9867 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9868 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9869 int rem , tid_index = 0;
9870
9871 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9872 wifi_associated_dev_tid_entry_t *stats_entry;
9873
9874 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9875 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9876 };
9877 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9878 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9879 };
9880
9881 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9882 genlmsg_attrlen(gnlh, 0), NULL);
9883
9884
9885 if (!tb[NL80211_ATTR_STA_INFO]) {
9886 fprintf(stderr, "station stats missing!\n");
9887 return NL_SKIP;
9888 }
9889
9890 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9891 tb[NL80211_ATTR_STA_INFO],
9892 stats_policy)) {
9893 fprintf(stderr, "failed to parse nested attributes!\n");
9894 return NL_SKIP;
9895 }
9896
9897 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9898 {
9899 stats_entry = &out->tid_array[tid_index];
9900
9901 stats_entry->tid = tid_index;
9902 stats_entry->ac = _tid_ac_index_get[tid_index];
9903
9904 if(sinfo[NL80211_STA_INFO_TID_STATS])
9905 {
9906 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9907 printf("failed to parse nested stats attributes!");
9908 return NL_SKIP;
9909 }
9910 }
9911 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9912 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9913
9914 if(tid_index < (PS_MAX_TID - 1))
9915 tid_index++;
9916 }
9917 //ToDo: sum_time_ms, ewma_time_ms
9918 return NL_SKIP;
9919}
9920#endif
9921
9922INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9923{
9924#ifdef HAL_NETLINK_IMPL
9925 Netlink nl;
9926 char if_name[10];
9927 char interface_name[16] = {0};
9928
9929 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
9930 return RETURN_ERR;
9931
9932 snprintf(if_name, sizeof(if_name), "%s", interface_name);
9933
9934 nl.id = initSock80211(&nl);
9935
9936 if (nl.id < 0) {
9937 fprintf(stderr, "Error initializing netlink \n");
9938 return -1;
9939 }
9940
9941 struct nl_msg* msg = nlmsg_alloc();
9942
9943 if (!msg) {
9944 fprintf(stderr, "Failed to allocate netlink message.\n");
9945 nlfree(&nl);
9946 return -2;
9947 }
9948
9949 genlmsg_put(msg,
9950 NL_AUTO_PORT,
9951 NL_AUTO_SEQ,
9952 nl.id,
9953 0,
9954 0,
9955 NL80211_CMD_GET_STATION,
9956 0);
9957
9958 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9959 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9960 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9961 nl_send_auto(nl.socket, msg);
9962 nl_recvmsgs(nl.socket, nl.cb);
9963 nlmsg_free(msg);
9964 nlfree(&nl);
9965 return RETURN_OK;
9966#else
9967//iw implementation
9968#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9969#define TOTAL_MAX_LINES 50
9970
9971 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9972 char if_name[32] = {0};
9973 FILE *fp=NULL;
9974 char pipeCmd[1024]= {'\0'};
9975 int lines,tid_index=0;
9976 char mac_addr[20] = {'\0'};
9977
9978 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
9979 return RETURN_ERR;
9980
9981 wifi_associated_dev_tid_entry_t *stats_entry;
9982
9983 strcpy(mac_addr,clientMacAddress);
9984
9985 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9986 fp= popen(pipeCmd,"r");
9987 if(fp == NULL)
9988 {
9989 perror("popen for station dump failed\n");
9990 return RETURN_ERR;
9991 }
9992 pclose(fp);
9993
9994 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9995 fp=popen(pipeCmd,"r");
9996 if(fp == NULL)
9997 {
9998 perror("popen for grep station failed\n");
9999 return RETURN_ERR;
10000 }
10001 else if(fgets(buf,sizeof(buf),fp) != NULL)
10002 lines=atoi(buf);
10003 else
10004 {
10005 pclose(fp);
10006 fprintf(stderr,"No devices are connected \n");
10007 return RETURN_ERR;
10008 }
10009 pclose(fp);
10010
10011 if(lines == 1)
10012 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
10013
10014 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
10015 {
10016 stats_entry = &tid_stats->tid_array[tid_index];
10017 stats_entry->tid = tid_index;
10018
10019 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);
10020
10021 fp=popen(pipeCmd,"r");
10022 if(fp ==NULL)
10023 {
10024 perror("Failed to read from tid file \n");
10025 return RETURN_ERR;
10026 }
10027 else if(fgets(buf,sizeof(buf),fp) != NULL)
10028 stats_entry->num_msdus = atol(buf);
10029
10030 pclose(fp);
10031 stats_entry->ac = _tid_ac_index_get[tid_index];
10032// TODO:
10033// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
10034// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
10035 }
10036 return RETURN_OK;
10037#endif
10038}
10039
10040
10041INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
10042{
10043 char interface_name[16] = {0};
10044 char cmd[128]={0};
10045 char buf[128]={0};
10046 int freq = 0;
10047
10048 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10049
10050 // full mode is used to scan all channels.
10051 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
10052 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
10053 ieee80211_channel_to_frequency(chan_list[0], &freq);
10054
10055 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
10056 return RETURN_ERR;
10057
10058 if (freq)
10059 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d freq %d", interface_name, dwell_time, freq);
10060 else
10061 snprintf(cmd, sizeof(cmd), "iw dev %s scan trigger duration %d", interface_name, dwell_time);
10062
10063 _syscmd(cmd, buf, sizeof(buf));
10064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10065
10066 return RETURN_OK;
10067}
10068
10069
10070INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
10071{
10072 // TODO Implement me!
10073 return RETURN_ERR;
10074}
10075
10076INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
10077{
10078 // TODO Implement me!
10079 return RETURN_ERR;
10080}
10081
10082INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10083{
10084 // TODO Implement me!
10085 return RETURN_ERR;
10086}
10087
10088INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
10089{
10090 // TODO Implement me!
10091 return RETURN_ERR;
10092}
10093
10094INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
10095{
10096 // TODO Implement me!
10097 return RETURN_ERR;
10098}
10099
10100INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
10101{
10102 // TODO Implement me!
10103 return RETURN_ERR;
10104}
10105
10106INT wifi_steering_eventUnregister(void)
10107{
10108 // TODO Implement me!
10109 return RETURN_ERR;
10110}
10111
10112INT wifi_delApAclDevices(INT apIndex)
10113{
10114#if 0
10115 char cmd[MAX_BUF_SIZE] = {0};
10116 char buf[MAX_BUF_SIZE] = {0};
10117
10118 /* Not reset proof solution */
10119 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s accept_acl CLEAR", interface_name);
10120 if(_syscmd(cmd,buf,sizeof(buf)))
10121 return RETURN_ERR;
10122#endif
10123 char cmd[MAX_CMD_SIZE]={0};
10124 char buf[MAX_BUF_SIZE]={0};
10125
10126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10127 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
10128 if(_syscmd(cmd, buf, sizeof(buf)))
10129 return RETURN_ERR;
10130 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10131
10132 return RETURN_OK;
10133}
10134
10135#ifdef HAL_NETLINK_IMPL
10136static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
10137 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10138 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10139 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10140 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10141 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10142 char mac_addr[20],dev[20];
10143
10144 nla_parse(tb,
10145 NL80211_ATTR_MAX,
10146 genlmsg_attrdata(gnlh, 0),
10147 genlmsg_attrlen(gnlh, 0),
10148 NULL);
10149
10150 if(!tb[NL80211_ATTR_STA_INFO]) {
10151 fprintf(stderr, "sta stats missing!\n");
10152 return NL_SKIP;
10153 }
10154
10155 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10156 fprintf(stderr, "failed to parse nested attributes!\n");
10157 return NL_SKIP;
10158 }
10159 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10160
10161 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10162
10163 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
10164 fprintf(stderr, "failed to parse nested rate attributes!");
10165 return NL_SKIP;
10166 }
10167
10168 if(sinfo[NL80211_STA_INFO_TID_STATS])
10169 {
10170 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10171 printf("failed to parse nested stats attributes!");
10172 return NL_SKIP;
10173 }
10174 }
10175
10176 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
10177 {
10178 printf("Type is VHT\n");
10179 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10180 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10181
10182 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10183 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
10184 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10185 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10186 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10187 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10188 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10189 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
10190 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
10191 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10192 }
10193 else
10194 {
10195 printf(" OFDM or CCK \n");
10196 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
10197 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
10198 }
10199
10200 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
10201 if(rinfo[NL80211_RATE_INFO_MCS])
10202 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10203 }
10204 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
10205 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
10206 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
10207 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
10208
10209 if(stats_info[NL80211_TID_STATS_RX_MSDU])
10210 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
10211
10212 if (sinfo[NL80211_STA_INFO_SIGNAL])
10213 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
10214 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
10215 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
10216 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
10217 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
10218 //rssi_array need to be filled
10219 return NL_SKIP;
10220}
10221#endif
10222
10223INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10224{
10225#ifdef HAL_NETLINK_IMPL
10226 Netlink nl;
10227 char if_name[32];
10228 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10229 return RETURN_ERR;
10230
10231 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
10232
10233 if (*output_array_size <= 0)
10234 return RETURN_OK;
10235
10236 nl.id = initSock80211(&nl);
10237
10238 if (nl.id < 0) {
10239 fprintf(stderr, "Error initializing netlink \n");
10240 return 0;
10241 }
10242
10243 struct nl_msg* msg = nlmsg_alloc();
10244
10245 if (!msg) {
10246 fprintf(stderr, "Failed to allocate netlink message.\n");
10247 nlfree(&nl);
10248 return 0;
10249 }
10250
10251 genlmsg_put(msg,
10252 NL_AUTO_PORT,
10253 NL_AUTO_SEQ,
10254 nl.id,
10255 0,
10256 0,
10257 NL80211_CMD_GET_STATION,
10258 0);
10259
10260 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
10261 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10262 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
10263 nl_send_auto(nl.socket, msg);
10264 nl_recvmsgs(nl.socket, nl.cb);
10265 nlmsg_free(msg);
10266 nlfree(&nl);
10267 return RETURN_OK;
10268#else
10269 //TODO Implement me
10270 return RETURN_OK;
10271#endif
10272}
10273
10274#ifdef HAL_NETLINK_IMPL
10275static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
10276 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10277 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10278 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
10279 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
10280 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
10281 char mac_addr[20],dev[20];
10282
10283 nla_parse(tb,
10284 NL80211_ATTR_MAX,
10285 genlmsg_attrdata(gnlh, 0),
10286 genlmsg_attrlen(gnlh, 0),
10287 NULL);
10288
10289 if(!tb[NL80211_ATTR_STA_INFO]) {
10290 fprintf(stderr, "sta stats missing!\n");
10291 return NL_SKIP;
10292 }
10293
10294 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
10295 fprintf(stderr, "failed to parse nested attributes!\n");
10296 return NL_SKIP;
10297 }
10298
10299 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
10300
10301 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10302
10303 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
10304 fprintf(stderr, "failed to parse nested rate attributes!");
10305 return NL_SKIP;
10306 }
10307
10308 if(sinfo[NL80211_STA_INFO_TID_STATS])
10309 {
10310 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
10311 printf("failed to parse nested stats attributes!");
10312 return NL_SKIP;
10313 }
10314 }
10315 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
10316 {
10317 printf("Type is VHT\n");
10318 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
10319 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
10320
10321 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
10322 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
10323 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
10324 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10325 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
10326 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10327 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
10328 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
10329 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
10330 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10331 }
10332 else
10333 {
10334 printf(" OFDM or CCK \n");
10335 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
10336 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
10337 }
10338
10339 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
10340 if(rinfo[NL80211_RATE_INFO_MCS])
10341 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
10342 }
10343
10344 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
10345 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
10346 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
10347 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
10348
10349 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
10350 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10351 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
10352
10353 if(stats_info[NL80211_TID_STATS_TX_MSDU])
10354 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
10355
10356 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
10357 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
10358
10359 if(sinfo[NL80211_STA_INFO_TX_FAILED])
10360 ((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]);
10361
10362 return NL_SKIP;
10363}
10364#endif
10365
10366INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
10367{
10368#ifdef HAL_NETLINK_IMPL
10369 Netlink nl;
10370 char if_name[10];
10371 char interface_name[16] = {0};
10372 if (wifi_GetInterfaceName(radioIndex, interface_name) != RETURN_OK)
10373 return RETURN_ERR;
10374
10375 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
10376
10377 if (*output_array_size <= 0)
10378 return RETURN_OK;
10379
10380 snprintf(if_name, sizeof(if_name), "%s", interface_name);
10381
10382 nl.id = initSock80211(&nl);
10383
10384 if(nl.id < 0) {
10385 fprintf(stderr, "Error initializing netlink \n");
10386 return 0;
10387 }
10388
10389 struct nl_msg* msg = nlmsg_alloc();
10390
10391 if(!msg) {
10392 fprintf(stderr, "Failed to allocate netlink message.\n");
10393 nlfree(&nl);
10394 return 0;
10395 }
10396
10397 genlmsg_put(msg,
10398 NL_AUTO_PORT,
10399 NL_AUTO_SEQ,
10400 nl.id,
10401 0,
10402 0,
10403 NL80211_CMD_GET_STATION,
10404 0);
10405
10406 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
10407 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10408 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
10409 nl_send_auto(nl.socket, msg);
10410 nl_recvmsgs(nl.socket, nl.cb);
10411 nlmsg_free(msg);
10412 nlfree(&nl);
10413 return RETURN_OK;
10414#else
10415 //TODO Implement me
10416 return RETURN_OK;
10417#endif
10418}
10419
10420INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
10421{
10422 // TODO Implement me!
10423 char buf[MAX_BUF_SIZE] = {0};
10424 char config_file[MAX_BUF_SIZE] = {0};
10425
10426 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
10427 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
10428 *activate = (strncmp("1",buf,1) == 0);
10429
10430 return RETURN_OK;
10431}
10432
10433INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
10434{
10435 char config_file[MAX_BUF_SIZE] = {0};
10436 struct params list;
10437
10438 list.name = "rrm_neighbor_report";
10439 list.value = activate?"1":"0";
10440 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10441 wifi_hostapdWrite(config_file, &list, 1);
10442
10443 return RETURN_OK;
10444}
10445
10446INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
10447{
10448 char buf[32] = {0};
10449 char config_file[MAX_BUF_SIZE] = {0};
10450
10451 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
10452 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
10453 *activate = (strncmp("1",buf,1) == 0);
10454
10455 return RETURN_OK;
10456}
10457#undef HAL_NETLINK_IMPL
10458#ifdef HAL_NETLINK_IMPL
10459static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
10460 struct nlattr *tb[NL80211_ATTR_MAX + 1];
10461 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
10462 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
10463 char dev[20];
10464 int freq =0 ;
10465 static int i=0;
10466
10467 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
10468
10469 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
10470 };
10471
10472 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
10473
10474 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
10475
10476 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
10477 fprintf(stderr, "survey data missing!\n");
10478 return NL_SKIP;
10479 }
10480
10481 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
10482 {
10483 fprintf(stderr, "failed to parse nested attributes!\n");
10484 return NL_SKIP;
10485 }
10486
10487
10488 if(out[0].array_size == 1 )
10489 {
10490 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
10491 {
10492 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10493 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10494 out[0].ch_number = ieee80211_frequency_to_channel(freq);
10495
10496 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10497 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10498 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10499 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10500 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10501 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10502 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10503 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10504 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10505 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10506 if (sinfo[NL80211_SURVEY_INFO_TIME])
10507 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10508 return NL_STOP;
10509 }
10510 }
10511 else
10512 {
10513 if ( i <= out[0].array_size )
10514 {
10515 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
10516 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
10517 out[i].ch_number = ieee80211_frequency_to_channel(freq);
10518
10519 if (sinfo[NL80211_SURVEY_INFO_NOISE])
10520 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
10521 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
10522 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
10523 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
10524 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
10525 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
10526 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
10527 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
10528 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
10529 if (sinfo[NL80211_SURVEY_INFO_TIME])
10530 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
10531 }
10532 }
10533
10534 i++;
10535 return NL_SKIP;
10536}
10537#endif
10538
10539static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
10540{
10541 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
10542 FILE *fp;
10543
10544 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
10545 {
10546 printf("Creating Frequency-Channel Map\n");
10547 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
10548 }
10549 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
10550 if((fp = popen(command, "r")))
10551 {
10552 fgets(output, sizeof(output), fp);
10553 *freqMHz = atoi(output);
10554 pclose(fp);
10555 }
10556
10557 return 0;
10558}
10559
10560static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
10561{
10562 int freqMHz = -1;
10563 char cmd[MAX_CMD_SIZE] = {'\0'};
10564 char interface_name[16] = {0};
10565
10566 ieee80211_channel_to_frequency(channel, &freqMHz);
10567 if (freqMHz == -1) {
10568 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
10569 return -1;
10570 }
10571
10572 wifi_GetInterfaceName(radioIndex, interface_name);
10573 if (sprintf(cmd,"iw dev %s survey dump | grep -A5 %d | tr -d '\\t'", interface_name, freqMHz) < 0) {
10574 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
10575 radioIndex, freqMHz);
10576 return -1;
10577 }
10578
10579 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
10580 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
10581 return -1;
10582 }
10583
10584 return 0;
10585}
10586
10587static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
10588{
10589 const char *ptr = buf;
10590 char *key = NULL;
10591 char *val = NULL;
10592 char line[256] = { '\0' };
10593
10594 while (ptr = get_line_from_str_buf(ptr, line)) {
10595 if (strstr(line, "Frequency")) continue;
10596
10597 key = strtok(line, ":");
10598 val = strtok(NULL, " ");
10599 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
10600
10601 if (!strcmp(key, "noise")) {
10602 sscanf(val, "%d", &stats->ch_noise);
10603 if (stats->ch_noise == 0) {
10604 // Workaround for missing noise information.
10605 // Assume -95 for 2.4G and -103 for 5G
10606 if (radioIndex == 0) stats->ch_noise = -95;
10607 if (radioIndex == 1) stats->ch_noise = -103;
10608 }
10609 }
10610 else if (!strcmp(key, "channel active time")) {
10611 sscanf(val, "%llu", &stats->ch_utilization_total);
10612 }
10613 else if (!strcmp(key, "channel busy time")) {
10614 sscanf(val, "%llu", &stats->ch_utilization_busy);
10615 }
10616 else if (!strcmp(key, "channel receive time")) {
10617 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
10618 }
10619 else if (!strcmp(key, "channel transmit time")) {
10620 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
10621 }
10622 };
10623
10624 return 0;
10625}
10626
10627INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
10628{
10629 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10630#ifdef HAL_NETLINK_IMPL
10631 Netlink nl;
10632 wifi_channelStats_t_loc local[array_size];
10633 char if_name[32];
10634
10635 local[0].array_size = array_size;
10636
10637 if (wifi_GetInterfaceName(radioIndex, if_name) != RETURN_OK)
10638 return RETURN_ERR;
10639
10640 nl.id = initSock80211(&nl);
10641
10642 if (nl.id < 0) {
10643 fprintf(stderr, "Error initializing netlink \n");
10644 return -1;
10645 }
10646
10647 struct nl_msg* msg = nlmsg_alloc();
10648
10649 if (!msg) {
10650 fprintf(stderr, "Failed to allocate netlink message.\n");
10651 nlfree(&nl);
10652 return -2;
10653 }
10654
10655 genlmsg_put(msg,
10656 NL_AUTO_PORT,
10657 NL_AUTO_SEQ,
10658 nl.id,
10659 0,
10660 NLM_F_DUMP,
10661 NL80211_CMD_GET_SURVEY,
10662 0);
10663
10664 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
10665 nl_send_auto(nl.socket, msg);
10666 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
10667 nl_recvmsgs(nl.socket, nl.cb);
10668 nlmsg_free(msg);
10669 nlfree(&nl);
10670 //Copying the Values
10671 for(int i=0;i<array_size;i++)
10672 {
10673 input_output_channelStats_array[i].ch_number = local[i].ch_number;
10674 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
10675 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
10676 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
10677 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
10678 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
10679 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
10680 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
10681 }
10682#else
10683 ULONG channel = 0;
10684 int i;
10685 int number_of_channels = array_size;
10686 char buf[512];
10687 INT ret;
10688 wifi_channelStats_t tmp_stats;
10689
10690 if (number_of_channels == 0) {
10691 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
10692 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
10693 return RETURN_ERR;
10694 }
10695 number_of_channels = 1;
10696 input_output_channelStats_array[0].ch_number = channel;
10697 }
10698
10699 for (i = 0; i < number_of_channels; i++) {
10700
10701 input_output_channelStats_array[i].ch_noise = 0;
10702 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
10703 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
10704 input_output_channelStats_array[i].ch_utilization_busy = 0;
10705 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
10706 input_output_channelStats_array[i].ch_utilization_total = 0;
10707
10708 memset(buf, 0, sizeof(buf));
10709 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
10710 return RETURN_ERR;
10711 }
10712 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
10713 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
10714 return RETURN_ERR;
10715 }
10716
10717 // XXX: fake missing 'self' counter which is not available in iw survey output
10718 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
10719 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
10720
10721 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
10722 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
10723 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
10724 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
10725 input_output_channelStats_array[i].ch_utilization_total *= 1000;
10726
10727 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",
10728 __func__,
10729 input_output_channelStats_array[i].ch_number,
10730 input_output_channelStats_array[i].ch_noise,
10731 input_output_channelStats_array[i].ch_utilization_total,
10732 input_output_channelStats_array[i].ch_utilization_busy,
10733 input_output_channelStats_array[i].ch_utilization_busy_rx,
10734 input_output_channelStats_array[i].ch_utilization_busy_tx,
10735 input_output_channelStats_array[i].ch_utilization_busy_self,
10736 input_output_channelStats_array[i].ch_utilization_busy_ext);
10737 }
10738#endif
10739 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10740 return RETURN_OK;
10741}
10742#define HAL_NETLINK_IMPL
10743
10744/* Hostapd events */
10745
10746#ifndef container_of
10747#define offset_of(st, m) ((size_t)&(((st *)0)->m))
10748#define container_of(ptr, type, member) \
10749 ((type *)((char *)ptr - offset_of(type, member)))
10750#endif /* container_of */
10751
10752struct ctrl {
10753 char sockpath[128];
10754 char sockdir[128];
10755 char bss[IFNAMSIZ];
10756 char reply[4096];
10757 int ssid_index;
10758 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
10759 void (*overrun)(struct ctrl *ctrl);
10760 struct wpa_ctrl *wpa;
10761 unsigned int ovfl;
10762 size_t reply_len;
10763 int initialized;
10764 ev_timer retry;
10765 ev_timer watchdog;
10766 ev_stat stat;
10767 ev_io io;
10768};
10769static wifi_newApAssociatedDevice_callback clients_connect_cb;
10770static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
10771static struct ctrl wpa_ctrl[MAX_APS];
10772static int initialized;
10773
10774static unsigned int ctrl_get_drops(struct ctrl *ctrl)
10775{
10776 char cbuf[256] = {};
10777 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
10778 struct cmsghdr *cmsg;
10779 unsigned int ovfl = ctrl->ovfl;
10780 unsigned int drop;
10781
10782 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
10783 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
10784 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
10785 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
10786
10787 drop = ovfl - ctrl->ovfl;
10788 ctrl->ovfl = ovfl;
10789
10790 return drop;
10791}
10792
10793static void ctrl_close(struct ctrl *ctrl)
10794{
10795 if (ctrl->io.cb)
10796 ev_io_stop(EV_DEFAULT_ &ctrl->io);
10797 if (ctrl->retry.cb)
10798 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10799 if (!ctrl->wpa)
10800 return;
10801
10802 wpa_ctrl_detach(ctrl->wpa);
10803 wpa_ctrl_close(ctrl->wpa);
10804 ctrl->wpa = NULL;
10805 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
10806}
10807
10808static void ctrl_process(struct ctrl *ctrl)
10809{
10810 const char *str;
10811 int drops;
10812 int level;
10813 int err;
10814
10815 /* Example events:
10816 *
10817 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
10818 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
10819 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
10820 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
10821 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
10822 */
10823 if (!(str = index(ctrl->reply, '>')))
10824 return;
10825 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
10826 return;
10827
10828 str++;
10829
10830 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
10831 if (!(str = index(ctrl->reply, ' ')))
10832 return;
10833 wifi_associated_dev_t sta;
10834 memset(&sta, 0, sizeof(sta));
10835
10836 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
10837 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
10838 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
10839
10840 sta.cli_Active=true;
10841
10842 (clients_connect_cb)(ctrl->ssid_index, &sta);
10843 goto handled;
10844 }
10845
10846 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
10847 if (!(str = index(ctrl->reply, ' ')))
10848 return;
10849
10850 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
10851 goto handled;
10852 }
10853
10854 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
10855 printf("CTRL_WPA: handle TERMINATING event\n");
10856 goto retry;
10857 }
10858
10859 if (strncmp("AP-DISABLED", str, 11) == 0) {
10860 printf("CTRL_WPA: handle AP-DISABLED\n");
10861 goto retry;
10862 }
10863
10864 printf("Event not supported!!\n");
10865
10866handled:
10867
10868 if ((drops = ctrl_get_drops(ctrl))) {
10869 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10870 if (ctrl->overrun)
10871 ctrl->overrun(ctrl);
10872 }
10873
10874 return;
10875
10876retry:
10877 printf("WPA_CTRL: closing\n");
10878 ctrl_close(ctrl);
10879 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10880 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10881}
10882
10883static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10884{
10885 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10886 int err;
10887
10888 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10889 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10890 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10891 ctrl->reply[ctrl->reply_len] = 0;
10892 if (err < 0) {
10893 if (errno == EAGAIN || errno == EWOULDBLOCK)
10894 return;
10895 ctrl_close(ctrl);
10896 ev_timer_again(EV_A_ &ctrl->retry);
10897 return;
10898 }
10899
10900 ctrl_process(ctrl);
10901}
10902
10903static int ctrl_open(struct ctrl *ctrl)
10904{
10905 int fd;
10906
10907 if (ctrl->wpa)
10908 return 0;
10909
10910 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10911 if (!ctrl->wpa)
10912 goto err;
10913
10914 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10915 goto err_close;
10916
10917 fd = wpa_ctrl_get_fd(ctrl->wpa);
10918 if (fd < 0)
10919 goto err_detach;
10920
10921 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10922 goto err_detach;
10923
10924 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10925 ev_io_start(EV_DEFAULT_ &ctrl->io);
10926
10927 return 0;
10928
10929err_detach:
10930 wpa_ctrl_detach(ctrl->wpa);
10931err_close:
10932 wpa_ctrl_close(ctrl->wpa);
10933err:
10934 ctrl->wpa = NULL;
10935 return -1;
10936}
10937
10938static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10939{
10940 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10941
10942 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10943 ctrl_open(ctrl);
10944}
10945
10946static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10947{
10948 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10949
10950 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10951 if (ctrl_open(ctrl) == 0) {
10952 printf("WPA_CTRL: retry successful\n");
10953 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10954 }
10955}
10956
10957int ctrl_enable(struct ctrl *ctrl)
10958{
10959 if (ctrl->wpa)
10960 return 0;
10961
10962 if (!ctrl->stat.cb) {
10963 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10964 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10965 }
10966
10967 if (!ctrl->retry.cb) {
10968 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10969 }
10970
10971 return ctrl_open(ctrl);
10972}
10973
10974static void
10975ctrl_msg_cb(char *buf, size_t len)
10976{
10977 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10978
10979 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10980 ctrl_process(ctrl);
10981}
10982
10983static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10984{
10985 int err;
10986
10987 if (!ctrl->wpa)
10988 return -1;
10989 if (*reply_len < 2)
10990 return -1;
10991
10992 (*reply_len)--;
10993 ctrl->reply_len = sizeof(ctrl->reply);
10994 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10995 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10996 if (err < 0)
10997 return err;
10998
10999 if (ctrl->reply_len > *reply_len)
11000 ctrl->reply_len = *reply_len;
11001
11002 *reply_len = ctrl->reply_len;
11003 memcpy(reply, ctrl->reply, *reply_len);
11004 reply[*reply_len - 1] = 0;
11005 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
11006 return 0;
11007}
11008
11009static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
11010{
11011 const char *pong = "PONG";
11012 const char *ping = "PING";
11013 char reply[1024];
11014 size_t len = sizeof(reply);
11015 int err;
11016 ULONG s, snum;
11017 INT ret;
11018 BOOL status;
11019
11020 printf("WPA_CTRL: watchdog cb\n");
11021
11022 ret = wifi_getSSIDNumberOfEntries(&snum);
11023 if (ret != RETURN_OK) {
11024 printf("%s: failed to get SSID count", __func__);
11025 return;
11026 }
11027
11028 if (snum > MAX_APS) {
11029 printf("more ssid than supported! %lu\n", snum);
11030 return;
11031 }
11032
11033 for (s = 0; s < snum; s++) {
11034 if (wifi_getApEnable(s, &status) != RETURN_OK) {
11035 printf("%s: failed to get AP Enable for index: %lu\n", __func__, s);
11036 continue;
11037 }
11038 if (status == false) continue;
11039
11040 memset(reply, 0, sizeof(reply));
11041 len = sizeof(reply);
11042 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
11043 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
11044 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
11045 continue;
11046
11047 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
11048 ctrl_close(&wpa_ctrl[s]);
11049 printf("WPA_CTRL: ev_timer_again %lu\n", s);
11050 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
11051 }
11052}
11053
11054static int init_wpa()
11055{
11056 int ret = 0, i = 0;
11057 ULONG s, snum;
11058
11059 ret = wifi_getSSIDNumberOfEntries(&snum);
11060 if (ret != RETURN_OK) {
11061 printf("%s: failed to get SSID count", __func__);
11062 return RETURN_ERR;
11063 }
11064
11065 if (snum > MAX_APS) {
11066 printf("more ssid than supported! %lu\n", snum);
11067 return RETURN_ERR;
11068 }
11069
11070 for (s = 0; s < snum; s++) {
11071 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
11072 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
11073 wpa_ctrl[s].ssid_index = s;
11074 ctrl_enable(&wpa_ctrl[s]);
11075 }
11076
11077 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
11078 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
11079
11080 initialized = 1;
11081 printf("WPA_CTRL: initialized\n");
11082
11083 return RETURN_OK;
11084}
11085
11086void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
11087{
11088 clients_connect_cb = callback_proc;
11089 if (!initialized)
11090 init_wpa();
11091}
11092
11093void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
11094{
11095 clients_disconnect_cb = callback_proc;
11096 if (!initialized)
11097 init_wpa();
11098}
11099
11100INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
11101{
11102 // TODO Implement me!
11103 return RETURN_ERR;
11104}
11105
11106INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
11107{
11108 // TODO Implement me!
11109 return RETURN_ERR;
11110}
11111
11112INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
11113{
11114 int i;
11115 char cmd[256];
11116 char channel_numbers_buf[256];
11117 char dfs_state_buf[256];
11118 char line[256];
11119 const char *ptr;
11120
11121 memset(cmd, 0, sizeof(cmd));
11122 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
11123 memset(line, 0, sizeof(line));
11124 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11125 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
11126
11127 if (radioIndex == 0) { // 2.4G - all allowed
11128 if (outputMapSize < 11) {
11129 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
11130 return RETURN_ERR;
11131 }
11132
11133 for (i = 0; i < 11; i++) {
11134 outputMap[i].ch_number = i + 1;
11135 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11136 }
11137
11138 return RETURN_OK;
11139 }
11140
11141 if (radioIndex == 1) { // 5G
11142// Example output of iw list:
11143//
11144// Frequencies:
11145// * 5180 MHz [36] (17.0 dBm)
11146// * 5200 MHz [40] (17.0 dBm)
11147// * 5220 MHz [44] (17.0 dBm)
11148// * 5240 MHz [48] (17.0 dBm)
11149// * 5260 MHz [52] (23.0 dBm) (radar detection)
11150// DFS state: usable (for 78930 sec)
11151// DFS CAC time: 60000 ms
11152// * 5280 MHz [56] (23.0 dBm) (radar detection)
11153// DFS state: usable (for 78930 sec)
11154// DFS CAC time: 60000 ms
11155// * 5300 MHz [60] (23.0 dBm) (radar detection)
11156// DFS state: usable (for 78930 sec)
11157// DFS CAC time: 60000 ms
11158// * 5320 MHz [64] (23.0 dBm) (radar detection)
11159// DFS state: usable (for 78930 sec)
11160// DFS CAC time: 60000 ms
11161// * 5500 MHz [100] (disabled)
11162// * 5520 MHz [104] (disabled)
11163// * 5540 MHz [108] (disabled)
11164// * 5560 MHz [112] (disabled)
11165//
11166// Below command should fetch channel numbers of each enabled channel in 5GHz band:
11167 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
11168 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
11169 return RETURN_ERR;
11170 }
11171
11172 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
11173 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11174 return RETURN_ERR;
11175 }
11176
11177 ptr = channel_numbers_buf;
11178 i = 0;
11179 while (ptr = get_line_from_str_buf(ptr, line)) {
11180 if (i >= outputMapSize) {
11181 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
11182 return RETURN_ERR;
11183 }
11184 sscanf(line, "%d", &outputMap[i].ch_number);
11185
11186 memset(cmd, 0, sizeof(cmd));
11187 // Below command should fetch string for DFS state (usable, available or unavailable)
11188 // Example line: "DFS state: usable (for 78930 sec)"
11189 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) {
11190 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
11191 return RETURN_ERR;
11192 }
11193
11194 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
11195 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
11196 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
11197 return RETURN_ERR;
11198 }
11199
11200 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
11201
11202 if (!strcmp(dfs_state_buf, "usable")) {
11203 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
11204 } else if (!strcmp(dfs_state_buf, "available")) {
11205 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
11206 } else if (!strcmp(dfs_state_buf, "unavailable")) {
11207 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
11208 } else {
11209 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
11210 }
11211 i++;
11212 }
11213
11214 return RETURN_OK;
11215 }
11216
11217 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
11218 return RETURN_ERR;
11219}
11220
11221INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
11222{
11223 // TODO Implement me!
11224 return RETURN_ERR;
11225}
11226
11227INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
11228{
11229 return RETURN_OK;
11230}
11231
11232INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
11233{
11234 // TODO Implement me!
11235 return RETURN_ERR;
11236}
11237
11238INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
11239{
11240 // TODO API refrence Implementaion is present on RPI hal
11241 return RETURN_ERR;
11242}
11243
11244INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
11245{
11246 char interface_name[16] = {0};
11247 char cmd[128]={'\0'};
11248 char buf[128]={'\0'};
11249 char *support;
11250 int maximum_tx = 0, current_tx = 0;
11251
11252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11253 if(txpwr_pcntg == NULL)
11254 return RETURN_ERR;
11255
11256 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11257 return RETURN_ERR;
11258
11259 // Get the maximum tx power of the device
11260 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", interface_name);
11261 _syscmd(cmd, buf, sizeof(buf));
11262 maximum_tx = strtol(buf, NULL, 10);
11263
11264 // Get the current tx power
11265 memset(cmd, 0, sizeof(cmd));
11266 memset(buf, 0, sizeof(buf));
11267 snprintf(cmd, sizeof(cmd), "iw %s info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", interface_name);
11268 _syscmd(cmd, buf, sizeof(buf));
11269 current_tx = strtol(buf, NULL, 10);
11270
11271 // Get the power supported list and find the current power percentage in supported list
11272 memset(buf, 0, sizeof(buf));
11273 wifi_getRadioTransmitPowerSupported(apIndex, buf);
11274 support = strtok(buf, ",");
11275 while(true)
11276 {
11277 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
11278 *txpwr_pcntg = 100;
11279 wifi_dbg_printf("current power is not in supported list\n");
11280 return RETURN_OK;
11281 }
11282 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
11283 if (tmp == current_tx) {
11284 *txpwr_pcntg = strtol(support, NULL, 10);
11285 break;
11286 }
11287 support = strtok(NULL, ",");
11288 }
11289 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11290 return RETURN_OK;
11291}
11292
11293INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
11294{
11295 // TODO precac feature.
11296 struct params params = {0};
11297 char config_file[128] = {0};
11298
11299 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11300
11301 params.name = "enable_background_radar";
11302 params.value = enable?"1":"0";
11303 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11304 wifi_hostapdWrite(config_file, &params, 1);
11305 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
11306
11307 /* TODO precac feature */
11308
11309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11310 return RETURN_OK;
11311}
11312
11313INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
11314{
11315 char config_file[128] = {0};
11316 char buf[64] = {0};
11317
11318 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11319 if (NULL == enable || NULL == precac)
11320 return RETURN_ERR;
11321
11322 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
11323 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
11324 if (strncmp(enable, "1", 1) == 0)
11325 *enable = true;
11326 else
11327 *enable = false;
11328
11329 /* TODO precac feature */
11330
11331 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11332 return RETURN_OK;
11333}
11334
11335INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
11336{
11337 *supported = TRUE;
11338 return RETURN_OK;
11339}
11340
11341INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
11342{
11343 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11344 struct params params = {0};
11345 char config_file[64] = {0};
11346 char buf[64] = {0};
11347 unsigned int set_mu_type = 0;
11348 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11349
11350 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11351 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11352
11353 if (strlen(buf) > 0)
11354 set_mu_type = strtol(buf, NULL, 10);
11355
11356 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
11357 set_mu_type &= ~0x05; // unset bit 0, 2
11358 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11359 set_mu_type |= 0x01;
11360 set_mu_type &= ~0x04;
11361 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
11362 set_mu_type &= ~0x01;
11363 set_mu_type |= 0x04;
11364 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
11365 set_mu_type |= 0x05; // set bit 0, 2
11366 }
11367
11368 params.name = "hemu_onoff";
11369 sprintf(buf, "%u", set_mu_type);
11370 params.value = buf;
11371 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11372 wifi_hostapdWrite(config_file, &params, 1);
11373 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11374
11375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11376 return RETURN_OK;
11377}
11378
11379INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
11380{
11381 struct params params={0};
11382 char config_file[64] = {0};
11383 char buf[64] = {0};
11384 unsigned int get_mu_type = 0;
11385
11386 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11387
11388 if (mu_type == NULL)
11389 return RETURN_ERR;
11390
11391 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11392 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11393 get_mu_type = strtol(buf, NULL, 10);
11394
11395 if (get_mu_type & 0x04 && get_mu_type & 0x01)
11396 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
11397 else if (get_mu_type & 0x04)
11398 *mu_type = WIFI_DL_MU_TYPE_MIMO;
11399 else if (get_mu_type & 0x01)
11400 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11401 else
11402 *mu_type = WIFI_DL_MU_TYPE_NONE;
11403
11404 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11405 return RETURN_OK;
11406}
11407
11408INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
11409{
11410 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
11411 struct params params={0};
11412 char config_file[64] = {0};
11413 char buf[64] = {0};
11414 unsigned int set_mu_type = 0;
11415 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11416
11417 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11418 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11419
11420 if (strlen(buf) > 0)
11421 set_mu_type = strtol(buf, NULL, 10);
11422
11423 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
11424 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
11425 set_mu_type &= ~0x0a;
11426 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
11427 set_mu_type |= 0x02;
11428 set_mu_type &= ~0x08;
11429 }
11430
11431 params.name = "hemu_onoff";
11432 sprintf(buf, "%u", set_mu_type);
11433 params.value = buf;
11434 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11435 wifi_hostapdWrite(config_file, &params, 1);
11436 wifi_hostapdProcessUpdate(radio_index, &params, 1);
11437
11438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11439 return RETURN_OK;
11440}
11441
11442INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
11443{
11444 struct params params={0};
11445 char config_file[64] = {0};
11446 char buf[64] = {0};
11447 unsigned int get_mu_type = 0;
11448
11449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11450
11451 if (mu_type == NULL)
11452 return RETURN_ERR;
11453
11454 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11455 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
11456
11457 get_mu_type = strtol(buf, NULL, 10);
11458 if (get_mu_type & 0x02)
11459 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
11460 else
11461 *mu_type = WIFI_DL_MU_TYPE_NONE;
11462
11463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11464 return RETURN_OK;
11465}
11466
11467
11468INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
11469{
11470 char cmd[128] = {0};
11471 char buf[256] = {0};
11472 char config_file[64] = {0};
11473 char GI[8] = {0};
11474 int mode_map = 0;
11475 FILE *f = NULL;
11476 wifi_band band = band_invalid;
11477
11478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11479
11480 if (wifi_getRadioMode(radio_index, buf, &mode_map) == RETURN_ERR) {
11481 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
11482 return RETURN_ERR;
11483 }
11484
11485 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radio_index);
11486 band = wifi_index_to_band(radio_index);
11487
11488 // Hostapd are not supported HE mode GI 1600, 3200 ns.
11489 if (guard_interval == wifi_guard_interval_800) { // remove all capab about short GI
11490 snprintf(cmd, sizeof(cmd), "sed -r -i 's/\\[SHORT-GI-(.){1,2}0\\]//g' %s", config_file);
11491 _syscmd(cmd, buf, sizeof(buf));
11492 } else if (guard_interval == wifi_guard_interval_400 || guard_interval == wifi_guard_interval_auto){
11493 wifi_hostapdRead(config_file, "ht_capab", buf, sizeof(buf));
11494 if (strstr(buf, "[SHORT-GI-") == NULL) {
11495 snprintf(cmd, sizeof(cmd), "sed -r -i '/^ht_capab=.*/s/$/[SHORT-GI-20][SHORT-GI-40]/' %s", config_file);
11496 _syscmd(cmd, buf, sizeof(buf));
11497 }
11498 if (band == band_5) {
11499 wifi_hostapdRead(config_file, "vht_capab", buf, sizeof(buf));
11500 if (strstr(buf, "[SHORT-GI-") == NULL) {
11501 snprintf(cmd, sizeof(cmd), "sed -r -i '/^vht_capab=.*/s/$/[SHORT-GI-80][SHORT-GI-160]/' %s", config_file);
11502 _syscmd(cmd, buf, sizeof(buf));
11503 }
11504 }
11505 }
11506 wifi_reloadAp(radio_index);
11507
11508 if (guard_interval == wifi_guard_interval_400)
11509 strcpy(GI, "0.4");
11510 else if (guard_interval == wifi_guard_interval_800)
11511 strcpy(GI, "0.8");
11512 else if (guard_interval == wifi_guard_interval_1600)
11513 strcpy(GI, "1.6");
11514 else if (guard_interval == wifi_guard_interval_3200)
11515 strcpy(GI, "3.2");
11516 else if (guard_interval == wifi_guard_interval_auto)
11517 strcpy(GI, "auto");
11518 // Record GI for get GI function
11519 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11520 f = fopen(buf, "w");
11521 if (f == NULL)
11522 return RETURN_ERR;
11523 fprintf(f, "%s", GI);
11524 fclose(f);
11525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11526 return RETURN_OK;
11527}
11528
11529INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
11530{
11531 char buf[32] = {0};
11532 char cmd[64] = {0};
11533
11534 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11535
11536 if (guard_interval == NULL)
11537 return RETURN_ERR;
11538
11539 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
11540 _syscmd(cmd, buf, sizeof(buf));
11541
11542 if (strncmp(buf, "0.4", 3) == 0)
11543 *guard_interval = wifi_guard_interval_400;
11544 else if (strncmp(buf, "0.8", 3) == 0)
11545 *guard_interval = wifi_guard_interval_800;
11546 else if (strncmp(buf, "1.6", 3) == 0)
11547 *guard_interval = wifi_guard_interval_1600;
11548 else if (strncmp(buf, "3.2", 3) == 0)
11549 *guard_interval = wifi_guard_interval_3200;
11550 else
11551 *guard_interval = wifi_guard_interval_auto;
11552
11553 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11554 return RETURN_OK;
11555}
11556
11557INT wifi_setBSSColor(INT radio_index, UCHAR color)
11558{
11559 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11560 struct params params = {0};
11561 char config_file[128] = {0};
11562 char bss_color[4] ={0};
11563
11564 params.name = "he_bss_color";
11565 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
11566 params.value = bss_color;
11567 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11568 wifi_hostapdWrite(config_file, &params, 1);
11569 wifi_hostapdProcessUpdate(radio_index, &params, 1);
developer69b61b02023-03-07 17:17:44 +080011570
developer72fb0bb2023-01-11 09:46:29 +080011571 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11572 return RETURN_OK;
11573}
11574
11575INT wifi_getBSSColor(INT radio_index, UCHAR *color)
11576{
11577 char config_file[128] = {0};
11578 char buf[64] = {0};
11579 char temp_output[128] = {'\0'};
11580
11581 wifi_dbg_printf("\nFunc=%s\n", __func__);
11582 if (NULL == color)
11583 return RETURN_ERR;
11584
11585 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
11586 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
11587
11588 if(strlen(buf) > 0) {
11589 snprintf(temp_output, sizeof(temp_output), "%s", buf);
11590 } else {
11591 snprintf(temp_output, sizeof(temp_output), "1"); // default value
11592 }
11593
11594 *color = (UCHAR)strtoul(temp_output, NULL, 10);
11595 wifi_dbg_printf("\noutput_string=%s\n", color);
11596
11597 return RETURN_OK;
11598}
11599
11600/* multi-psk support */
11601INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
11602{
11603 char cmd[256];
11604 char interface_name[16] = {0};
11605
11606 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11607 return RETURN_ERR;
11608
11609 sprintf(cmd, "hostapd_cli -i %s sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
11610 interface_name,
11611 mac[0],
11612 mac[1],
11613 mac[2],
11614 mac[3],
11615 mac[4],
11616 mac[5]
11617 );
11618 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
11619 _syscmd(cmd, key->wifi_keyId, 64);
11620
11621
11622 return RETURN_OK;
11623}
11624
11625INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11626{
11627 char interface_name[16] = {0};
11628 FILE *fd = NULL;
11629 char fname[100];
11630 char cmd[128] = {0};
11631 char out[64] = {0};
11632 wifi_key_multi_psk_t * key = NULL;
11633 if(keysNumber < 0)
11634 return RETURN_ERR;
11635
11636 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11637 fd = fopen(fname, "w");
11638 if (!fd) {
11639 return RETURN_ERR;
11640 }
11641 key= (wifi_key_multi_psk_t *) keys;
11642 for(int i=0; i<keysNumber; ++i, key++) {
11643 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
11644 }
11645 fclose(fd);
11646
11647 //reload file
11648 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11649 return RETURN_ERR;
11650 sprintf(cmd, "hostapd_cli -i%s raw RELOAD_WPA_PSK", interface_name);
11651 _syscmd(cmd, out, 64);
11652 return RETURN_OK;
11653}
11654
11655INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
11656{
11657 FILE *fd = NULL;
11658 char fname[100];
11659 char * line = NULL;
11660 char * pos = NULL;
11661 size_t len = 0;
11662 ssize_t read = 0;
11663 INT ret = RETURN_OK;
11664 wifi_key_multi_psk_t *keys_it = NULL;
11665
11666 if (keysNumber < 1) {
11667 return RETURN_ERR;
11668 }
11669
11670 snprintf(fname, sizeof(fname), "%s%d.psk", PSK_FILE, apIndex);
11671 fd = fopen(fname, "r");
11672 if (!fd) {
11673 return RETURN_ERR;
11674 }
11675
11676 if (keys == NULL) {
11677 ret = RETURN_ERR;
11678 goto close;
11679 }
11680
11681 keys_it = keys;
11682 while ((read = getline(&line, &len, fd)) != -1) {
11683 //Strip trailing new line if present
11684 if (read > 0 && line[read-1] == '\n') {
11685 line[read-1] = '\0';
11686 }
11687
11688 if(strcmp(line,"keyid=")) {
11689 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
11690 if (!(pos = index(line, ' '))) {
11691 ret = RETURN_ERR;
11692 goto close;
11693 }
11694 pos++;
11695 //Here should be 00:00:00:00:00:00
11696 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
11697 printf("Not supported MAC: %s\n", pos);
11698 }
11699 if (!(pos = index(pos, ' '))) {
11700 ret = RETURN_ERR;
11701 goto close;
11702 }
11703 pos++;
11704
11705 //The rest is PSK
11706 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
11707 keys_it++;
11708
11709 if(--keysNumber <= 0)
11710 break;
11711 }
11712 }
11713
11714close:
11715 free(line);
11716 fclose(fd);
11717 return ret;
11718}
11719/* end of multi-psk support */
11720
11721INT wifi_setNeighborReports(UINT apIndex,
11722 UINT numNeighborReports,
11723 wifi_NeighborReport_t *neighborReports)
11724{
11725 char cmd[256] = { 0 };
11726 char hex_bssid[13] = { 0 };
11727 char bssid[18] = { 0 };
11728 char nr[256] = { 0 };
11729 char ssid[256];
11730 char hex_ssid[256];
11731 char interface_name[16] = {0};
11732 INT ret;
11733
11734 /*rmeove all neighbors*/
11735 wifi_dbg_printf("\n[%s]: removing all neighbors from %s\n", __func__, interface_name);
11736 if (wifi_GetInterfaceName(apIndex, interface_name) != RETURN_OK)
11737 return RETURN_ERR;
11738 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);
11739 system(cmd);
11740
11741 for(unsigned int i = 0; i < numNeighborReports; i++)
11742 {
11743 memset(ssid, 0, sizeof(ssid));
11744 ret = wifi_getSSIDName(apIndex, ssid);
11745 if (ret != RETURN_OK)
11746 return RETURN_ERR;
11747
11748 memset(hex_ssid, 0, sizeof(hex_ssid));
11749 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
11750 sprintf(hex_ssid + k,"%02x", ssid[j]);
11751
11752 snprintf(hex_bssid, sizeof(hex_bssid),
11753 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
11754 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11755 snprintf(bssid, sizeof(bssid),
11756 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
11757 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
11758
11759 snprintf(nr, sizeof(nr),
11760 "%s" // bssid
11761 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
11762 "%02hhx" // operclass
11763 "%02hhx" // channel
11764 "%02hhx", // phy_mode
11765 hex_bssid,
11766 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
11767 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
11768 neighborReports[i].opClass,
11769 neighborReports[i].channel,
11770 neighborReports[i].phyTable);
11771
11772 snprintf(cmd, sizeof(cmd),
11773 "hostapd_cli set_neighbor "
11774 "%s " // bssid
11775 "ssid=%s " // ssid
11776 "nr=%s " // nr
11777 "-i %s",
11778 bssid,hex_ssid,nr, interface_name);
11779
11780 if (WEXITSTATUS(system(cmd)) != 0)
11781 {
11782 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
11783 }
11784 }
11785
11786 return RETURN_OK;
11787}
11788
11789INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
11790{
11791 return RETURN_OK;
11792}
11793
11794#ifdef _WIFI_HAL_TEST_
11795int main(int argc,char **argv)
11796{
11797 int index;
11798 INT ret=0;
11799 char buf[1024]="";
11800
11801 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11802 if(argc<3)
11803 {
11804 if(argc==2)
11805 {
11806 if(!strcmp(argv[1], "init"))
11807 return wifi_init();
11808 if(!strcmp(argv[1], "reset"))
11809 return wifi_reset();
11810 if(!strcmp(argv[1], "wifi_getHalVersion"))
11811 {
11812 char buffer[64];
11813 if(wifi_getHalVersion(buffer)==RETURN_OK)
11814 printf("Version: %s\n", buffer);
11815 else
11816 printf("Error in wifi_getHalVersion\n");
11817 return RETURN_OK;
11818 }
11819 }
11820 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
11821 exit(-1);
11822 }
11823
11824 index = atoi(argv[2]);
11825 if(strstr(argv[1], "wifi_getApName")!=NULL)
11826 {
11827 wifi_getApName(index,buf);
11828 printf("Ap name is %s \n",buf);
11829 return 0;
11830 }
11831 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
11832 {
11833 BOOL b = FALSE;
11834 BOOL *output_bool = &b;
11835 wifi_getRadioAutoChannelEnable(index,output_bool);
11836 printf("Channel enabled = %d \n",b);
11837 return 0;
11838 }
11839 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
11840 {
11841 wifi_getApWpaEncryptionMode(index,buf);
11842 printf("encryption enabled = %s\n",buf);
11843 return 0;
11844 }
11845 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
11846 {
11847 BOOL b = FALSE;
11848 BOOL *output_bool = &b;
11849 wifi_getApSsidAdvertisementEnable(index,output_bool);
11850 printf("advertisment enabled = %d\n",b);
11851 return 0;
11852 }
11853 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
11854 {
11855 if(argc <= 3 )
11856 {
11857 printf("Insufficient arguments \n");
11858 exit(-1);
11859 }
11860
11861 char sta[20] = {'\0'};
11862 ULLONG handle= 0;
11863 strcpy(sta,argv[3]);
11864 mac_address_t st;
11865 mac_addr_aton(st,sta);
11866
11867 wifi_associated_dev_tid_stats_t tid_stats;
11868 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
11869 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
11870 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);
11871 }
11872
11873 if(strstr(argv[1], "getApEnable")!=NULL) {
11874 BOOL enable;
11875 ret=wifi_getApEnable(index, &enable);
11876 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11877 }
11878 else if(strstr(argv[1], "setApEnable")!=NULL) {
11879 BOOL enable = atoi(argv[3]);
11880 ret=wifi_setApEnable(index, enable);
11881 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11882 }
11883 else if(strstr(argv[1], "getApStatus")!=NULL) {
developer69b61b02023-03-07 17:17:44 +080011884 char status[64];
developer72fb0bb2023-01-11 09:46:29 +080011885 ret=wifi_getApStatus(index, status);
11886 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11887 }
11888 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11889 {
11890 wifi_getSSIDNameStatus(index,buf);
11891 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11892 return 0;
11893 }
11894 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11895 wifi_ssidTrafficStats2_t stats={0};
11896 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11897 printf("%s %d: returns %d\n", argv[1], index, ret);
11898 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11899 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11900 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11901 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11902 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11903 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11904 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11905 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11906 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11907 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11908 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11909 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11910 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11911 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11912 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11913 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11914 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11915 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11916 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11917 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11918 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11919 }
11920 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11921 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11922 UINT array_size=0;
11923 UINT i=0;
11924 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11925 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080011926 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080011927 printf(" neighbor %d:\n", i);
11928 printf(" ap_SSID =%s\n", pt->ap_SSID);
11929 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11930 printf(" ap_Mode =%s\n", pt->ap_Mode);
11931 printf(" ap_Channel =%d\n", pt->ap_Channel);
11932 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11933 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11934 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11935 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11936 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11937 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11938 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11939 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11940 printf(" ap_Noise =%d\n", pt->ap_Noise);
11941 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11942 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11943 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
developer69b61b02023-03-07 17:17:44 +080011944 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
developer72fb0bb2023-01-11 09:46:29 +080011945 }
11946 if(neighbor_ap_array)
11947 free(neighbor_ap_array); //make sure to free the list
11948 }
11949 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11950 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11951 UINT array_size=0;
11952 UINT i=0;
11953 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11954 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
developer69b61b02023-03-07 17:17:44 +080011955 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
developer72fb0bb2023-01-11 09:46:29 +080011956 printf(" associated_dev %d:\n", i);
11957 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11958 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11959 printf(" cli_SNR =%d\n", pt->cli_SNR);
11960 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11961 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11962 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11963 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11964 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11965 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11966 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11967 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11968 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11969 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11970 }
11971 if(associated_dev_array)
11972 free(associated_dev_array); //make sure to free the list
11973 }
11974
11975 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11976 {
11977#define MAX_ARRAY_SIZE 64
11978 int i, array_size;
11979 char *p, *ch_str;
11980 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11981
11982 if(argc != 5)
11983 {
11984 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11985 exit(-1);
11986 }
11987 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11988
11989 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11990 {
11991 strtok_r(ch_str, ",", &p);
11992 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11993 }
11994 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11995 if(!array_size)
11996 array_size=1;//Need to print current channel statistics
11997 for(i=0; i<array_size; i++)
11998 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11999 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
12000 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
12001 input_output_channelStats_array[i].ch_number,\
12002 input_output_channelStats_array[i].ch_noise,\
12003 input_output_channelStats_array[i].ch_utilization_busy_rx,\
12004 input_output_channelStats_array[i].ch_utilization_busy_tx,\
12005 input_output_channelStats_array[i].ch_utilization_busy,\
12006 input_output_channelStats_array[i].ch_utilization_busy_ext,\
12007 input_output_channelStats_array[i].ch_utilization_total);
12008 }
12009
12010 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
12011 {
12012 if(argc <= 3 )
12013 {
12014 printf("Insufficient arguments \n");
12015 exit(-1);
12016 }
12017 char mac_addr[20] = {'\0'};
12018 wifi_device_t output_struct;
12019 int dev_index = atoi(argv[3]);
12020
12021 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
12022 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
12023 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);
12024 }
12025
12026 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
12027 {
12028 if (argc <= 3)
12029 {
12030 printf("Insufficient arguments\n");
12031 exit(-1);
12032 }
12033 char args[256];
12034 wifi_NeighborReport_t *neighborReports;
12035
12036 neighborReports = calloc(argc - 2, sizeof(neighborReports));
12037 if (!neighborReports)
12038 {
12039 printf("Failed to allocate memory");
12040 exit(-1);
12041 }
12042
12043 for (int i = 3; i < argc; ++i)
12044 {
12045 char *val;
12046 int j = 0;
12047 memset(args, 0, sizeof(args));
12048 strncpy(args, argv[i], sizeof(args));
12049 val = strtok(args, ";");
12050 while (val != NULL)
12051 {
12052 if (j == 0)
12053 {
12054 mac_addr_aton(neighborReports[i - 3].bssid, val);
12055 } else if (j == 1)
12056 {
12057 neighborReports[i - 3].info = strtol(val, NULL, 16);
12058 } else if (j == 2)
12059 {
12060 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
12061 } else if (j == 3)
12062 {
12063 neighborReports[i - 3].channel = strtol(val, NULL, 16);
12064 } else if (j == 4)
12065 {
12066 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
12067 } else {
12068 printf("Insufficient arguments]n\n");
12069 exit(-1);
12070 }
12071 val = strtok(NULL, ";");
12072 j++;
12073 }
12074 }
12075
12076 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
12077 if (ret != RETURN_OK)
12078 {
12079 printf("wifi_setNeighborReports ret = %d", ret);
12080 exit(-1);
12081 }
12082 }
12083 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
12084 {
12085 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
12086 printf("%s.\n", buf);
12087 else
12088 printf("Error returned\n");
12089 }
12090 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
12091 {
12092 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
12093 printf("%s.\n", buf);
12094 else
12095 printf("Error returned\n");
12096 }
12097 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
12098 {
12099 if (argc <= 2)
12100 {
12101 printf("Insufficient arguments\n");
12102 exit(-1);
12103 }
12104 char buf[64]= {'\0'};
12105 wifi_getRadioOperatingChannelBandwidth(index,buf);
12106 printf("Current bandwidth is %s \n",buf);
12107 return 0;
12108 }
12109 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
12110 {
12111 if (argc <= 5)
12112 {
12113 printf("Insufficient arguments\n");
12114 exit(-1);
12115 }
12116 UINT channel = atoi(argv[3]);
12117 UINT width = atoi(argv[4]);
12118 UINT beacon = atoi(argv[5]);
12119 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
12120 printf("Result = %d", ret);
12121 }
12122
12123 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12124 return 0;
12125}
12126
12127#endif
12128
12129#ifdef WIFI_HAL_VERSION_3
12130
12131INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
12132{
12133 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12134 if (bitMap & WIFI_BITRATE_1MBPS)
12135 strcat(BasicRate, "1,");
12136 if (bitMap & WIFI_BITRATE_2MBPS)
12137 strcat(BasicRate, "2,");
12138 if (bitMap & WIFI_BITRATE_5_5MBPS)
12139 strcat(BasicRate, "5.5,");
12140 if (bitMap & WIFI_BITRATE_6MBPS)
12141 strcat(BasicRate, "6,");
12142 if (bitMap & WIFI_BITRATE_9MBPS)
12143 strcat(BasicRate, "9,");
12144 if (bitMap & WIFI_BITRATE_11MBPS)
12145 strcat(BasicRate, "11,");
12146 if (bitMap & WIFI_BITRATE_12MBPS)
12147 strcat(BasicRate, "12,");
12148 if (bitMap & WIFI_BITRATE_18MBPS)
12149 strcat(BasicRate, "18,");
12150 if (bitMap & WIFI_BITRATE_24MBPS)
12151 strcat(BasicRate, "24,");
12152 if (bitMap & WIFI_BITRATE_36MBPS)
12153 strcat(BasicRate, "36,");
12154 if (bitMap & WIFI_BITRATE_48MBPS)
12155 strcat(BasicRate, "48,");
12156 if (bitMap & WIFI_BITRATE_54MBPS)
12157 strcat(BasicRate, "54,");
12158 if (strlen(BasicRate) != 0) // remove last comma
12159 BasicRate[strlen(BasicRate) - 1] = '\0';
12160 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12161 return RETURN_OK;
12162}
12163
12164INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
12165{
12166 UINT BitMap = 0;
12167 char *rate;
12168
12169 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12170 rate = strtok(BasicRatesList, ",");
12171 while(rate != NULL)
12172 {
12173 if (strcmp(rate, "1") == 0)
12174 BitMap |= WIFI_BITRATE_1MBPS;
12175 else if (strcmp(rate, "2") == 0)
12176 BitMap |= WIFI_BITRATE_2MBPS;
12177 else if (strcmp(rate, "5.5") == 0)
12178 BitMap |= WIFI_BITRATE_5_5MBPS;
12179 else if (strcmp(rate, "6") == 0)
12180 BitMap |= WIFI_BITRATE_6MBPS;
12181 else if (strcmp(rate, "9") == 0)
12182 BitMap |= WIFI_BITRATE_9MBPS;
12183 else if (strcmp(rate, "11") == 0)
12184 BitMap |= WIFI_BITRATE_11MBPS;
12185 else if (strcmp(rate, "12") == 0)
12186 BitMap |= WIFI_BITRATE_12MBPS;
12187 else if (strcmp(rate, "18") == 0)
12188 BitMap |= WIFI_BITRATE_18MBPS;
12189 else if (strcmp(rate, "24") == 0)
12190 BitMap |= WIFI_BITRATE_24MBPS;
12191 else if (strcmp(rate, "36") == 0)
12192 BitMap |= WIFI_BITRATE_36MBPS;
12193 else if (strcmp(rate, "48") == 0)
12194 BitMap |= WIFI_BITRATE_48MBPS;
12195 else if (strcmp(rate, "54") == 0)
12196 BitMap |= WIFI_BITRATE_54MBPS;
12197 rate = strtok(NULL, ",");
12198 }
12199 *basicRateBitMap = BitMap;
12200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12201 return RETURN_OK;
12202}
12203
12204// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
12205INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12206{
12207 char buf[128] = {0};
12208 char cmd[128] = {0};
12209 char config_file[64] = {0};
12210 int bandwidth;
12211 int set_mode = 0;
12212 wifi_radio_operationParam_t current_param;
12213
12214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12215
12216 multiple_set = TRUE;
12217 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
12218 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
12219 return RETURN_ERR;
12220 }
12221 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
12222 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
12223 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
12224 return RETURN_ERR;
12225 }
12226 }
12227
12228 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
12229 bandwidth = 20;
12230 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
12231 bandwidth = 40;
12232 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
12233 bandwidth = 80;
12234 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
12235 bandwidth = 160;
12236 if (operationParam->autoChannelEnabled){
12237 if (wifi_pushRadioChannel2(index, 0, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12238 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12239 return RETURN_ERR;
12240 }
developer69b61b02023-03-07 17:17:44 +080012241 }else{
developer72fb0bb2023-01-11 09:46:29 +080012242 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
12243 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
12244 return RETURN_ERR;
12245 }
12246 }
12247
12248 if (current_param.variant != operationParam->variant) {
12249 // Two different definition bit map, so need to check every bit.
12250 if (operationParam->variant & WIFI_80211_VARIANT_A)
12251 set_mode |= WIFI_MODE_A;
12252 if (operationParam->variant & WIFI_80211_VARIANT_B)
12253 set_mode |= WIFI_MODE_B;
12254 if (operationParam->variant & WIFI_80211_VARIANT_G)
12255 set_mode |= WIFI_MODE_G;
12256 if (operationParam->variant & WIFI_80211_VARIANT_N)
12257 set_mode |= WIFI_MODE_N;
12258 if (operationParam->variant & WIFI_80211_VARIANT_AC)
12259 set_mode |= WIFI_MODE_AC;
12260 if (operationParam->variant & WIFI_80211_VARIANT_AX)
12261 set_mode |= WIFI_MODE_AX;
12262 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
12263 memset(buf, 0, sizeof(buf));
12264 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
12265 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
12266 return RETURN_ERR;
12267 }
12268 }
12269 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
12270 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
12271 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
12272 return RETURN_ERR;
12273 }
12274 }
12275 if (current_param.beaconInterval != operationParam->beaconInterval) {
12276 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
12277 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
12278 return RETURN_ERR;
12279 }
12280 }
12281 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
12282 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
12283 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12284 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
12285 return RETURN_ERR;
12286 }
12287 }
12288 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
12289 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
12290 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
12291 return RETURN_ERR;
12292 }
12293 }
12294 if (current_param.guardInterval != operationParam->guardInterval) {
12295 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
12296 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
12297 return RETURN_ERR;
12298 }
12299 }
12300 if (current_param.transmitPower != operationParam->transmitPower) {
12301 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
12302 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
12303 return RETURN_ERR;
12304 }
12305 }
12306 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
12307 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
12308 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
12309 return RETURN_ERR;
12310 }
12311 }
12312 if (current_param.obssCoex != operationParam->obssCoex) {
12313 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
12314 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
12315 return RETURN_ERR;
12316 }
12317 }
12318 if (current_param.stbcEnable != operationParam->stbcEnable) {
12319 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
12320 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
12321 return RETURN_ERR;
12322 }
12323 }
12324 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
12325 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
12326 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
12327 return RETURN_ERR;
12328 }
12329 }
12330
12331 // if enable is true, then restart the radio
12332 wifi_setRadioEnable(index, FALSE);
12333 if (operationParam->enable == TRUE)
12334 wifi_setRadioEnable(index, TRUE);
12335 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12336
12337 return RETURN_OK;
12338}
12339
12340INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
12341{
12342 char band[64] = {0};
12343 char buf[256] = {0};
12344 char config_file[64] = {0};
12345 char cmd[128] = {0};
12346 int ret = RETURN_ERR;
12347 int mode = 0;
12348 ULONG channel = 0;
12349 BOOL enabled = FALSE;
12350
12351 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12352 printf("Entering %s index = %d\n", __func__, (int)index);
12353
12354 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
12355 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
12356 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
12357 {
12358 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
12359 return RETURN_ERR;
12360 }
12361 operationParam->enable = enabled;
12362
12363 memset(band, 0, sizeof(band));
12364 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
12365 {
12366 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
12367 return RETURN_ERR;
12368 }
12369
12370 if (!strcmp(band, "2.4GHz"))
12371 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
12372 else if (!strcmp(band, "5GHz"))
12373 operationParam->band = WIFI_FREQUENCY_5_BAND;
12374 else if (!strcmp(band, "6GHz"))
12375 operationParam->band = WIFI_FREQUENCY_6_BAND;
12376 else
12377 {
12378 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
12379 band);
12380 }
12381
12382 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
12383 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
12384 operationParam->channel = 0;
12385 operationParam->autoChannelEnabled = TRUE;
12386 } else {
12387 operationParam->channel = strtol(buf, NULL, 10);
12388 operationParam->autoChannelEnabled = FALSE;
12389 }
12390
12391 memset(buf, 0, sizeof(buf));
12392 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
12393 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
12394 return RETURN_ERR;
12395 }
12396 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
12397 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
12398 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
12399 else if (!strcmp(buf, "160MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
12400 else
12401 {
12402 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
12403 return false;
12404 }
12405
12406 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
12407 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
12408 return RETURN_ERR;
12409 }
12410 // Two different definition bit map, so need to check every bit.
12411 if (mode & WIFI_MODE_A)
12412 operationParam->variant |= WIFI_80211_VARIANT_A;
12413 if (mode & WIFI_MODE_B)
12414 operationParam->variant |= WIFI_80211_VARIANT_B;
12415 if (mode & WIFI_MODE_G)
12416 operationParam->variant |= WIFI_80211_VARIANT_G;
12417 if (mode & WIFI_MODE_N)
12418 operationParam->variant |= WIFI_80211_VARIANT_N;
12419 if (mode & WIFI_MODE_AC)
12420 operationParam->variant |= WIFI_80211_VARIANT_AC;
12421 if (mode & WIFI_MODE_AX)
12422 operationParam->variant |= WIFI_80211_VARIANT_AX;
12423 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
12424 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
12425 return RETURN_ERR;
12426 }
12427 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
12428 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
12429 return RETURN_ERR;
12430 }
12431 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
12432 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
12433 return RETURN_ERR;
12434 }
12435
12436 memset(buf, 0, sizeof(buf));
12437 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
12438 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
12439 return RETURN_ERR;
12440 }
12441 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
12442
12443 memset(buf, 0, sizeof(buf));
12444 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
12445 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
12446 return RETURN_ERR;
12447 }
12448 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
12449
12450 memset(buf, 0, sizeof(buf));
12451 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
12452 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
12453
12454 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
12455 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
12456 return RETURN_ERR;
12457 }
12458 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
12459 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
12460 return RETURN_ERR;
12461 }
12462
12463 memset(buf, 0, sizeof(buf));
12464 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
12465 if (strcmp(buf, "-1") == 0) {
12466 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
12467 operationParam->ctsProtection = FALSE;
12468 } else {
12469 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
12470 operationParam->ctsProtection = TRUE;
12471 }
12472
12473 memset(buf, 0, sizeof(buf));
12474 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
12475 if (strcmp(buf, "0") == 0)
12476 operationParam->obssCoex = FALSE;
12477 else
12478 operationParam->obssCoex = TRUE;
12479
12480 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
12481 _syscmd(cmd, buf, sizeof(buf));
12482 if (strlen(buf) != 0)
12483 operationParam->stbcEnable = TRUE;
12484 else
12485 operationParam->stbcEnable = FALSE;
12486
12487 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
12488 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
12489 return RETURN_ERR;
12490 }
12491
12492 // Below value is hardcoded
12493
12494 operationParam->numSecondaryChannels = 0;
12495 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
12496 operationParam->channelSecondary[i] = 0;
12497 }
12498 operationParam->csa_beacon_count = 15;
12499 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
12500
12501 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12502 return RETURN_OK;
12503}
12504
12505static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
12506{
12507 int max_radio_num = 0;
12508
12509 wifi_getMaxRadioNumber(&max_radio_num);
12510 if (radioIndex >= max_radio_num) {
12511 fprintf(stderr, "%s: Wrong radio index (%d)\n", __func__, radioIndex);
12512 return RETURN_ERR;
12513 }
12514
12515 return (arrayIndex * max_radio_num) + radioIndex;
12516}
12517
developer96b38512023-02-22 11:17:45 +080012518static int vap_index_to_array_index(int vapIndex, int *radioIndex, int *arrayIndex)
12519{
12520 int max_radio_num = 0;
12521
12522 if ((vapIndex < 0) || (vapIndex > MAX_NUM_VAP_PER_RADIO*MAX_NUM_RADIOS))
12523 return -1;
12524
12525 wifi_getMaxRadioNumber(&max_radio_num);
12526
12527 (*radioIndex) = vapIndex % max_radio_num;
12528 (*arrayIndex) = vapIndex / max_radio_num;
12529
12530 return 0;
12531}
12532
12533
developer72fb0bb2023-01-11 09:46:29 +080012534wifi_bitrate_t beaconRate_string_to_enum(char *beaconRate) {
12535 if (strncmp(beaconRate, "1Mbps", 5) == 0)
12536 return WIFI_BITRATE_1MBPS;
12537 else if (strncmp(beaconRate, "2Mbps", 5) == 0)
12538 return WIFI_BITRATE_2MBPS;
12539 else if (strncmp(beaconRate, "5.5Mbps", 7) == 0)
12540 return WIFI_BITRATE_5_5MBPS;
12541 else if (strncmp(beaconRate, "6Mbps", 5) == 0)
12542 return WIFI_BITRATE_6MBPS;
12543 else if (strncmp(beaconRate, "9Mbps", 5) == 0)
12544 return WIFI_BITRATE_9MBPS;
12545 else if (strncmp(beaconRate, "11Mbps", 6) == 0)
12546 return WIFI_BITRATE_11MBPS;
12547 else if (strncmp(beaconRate, "12Mbps", 6) == 0)
12548 return WIFI_BITRATE_12MBPS;
12549 else if (strncmp(beaconRate, "18Mbps", 6) == 0)
12550 return WIFI_BITRATE_18MBPS;
12551 else if (strncmp(beaconRate, "24Mbps", 6) == 0)
12552 return WIFI_BITRATE_24MBPS;
12553 else if (strncmp(beaconRate, "36Mbps", 6) == 0)
12554 return WIFI_BITRATE_36MBPS;
12555 else if (strncmp(beaconRate, "48Mbps", 6) == 0)
12556 return WIFI_BITRATE_48MBPS;
12557 else if (strncmp(beaconRate, "54Mbps", 6) == 0)
12558 return WIFI_BITRATE_54MBPS;
12559 return WIFI_BITRATE_DEFAULT;
12560}
12561
12562INT beaconRate_enum_to_string(wifi_bitrate_t beacon, char *beacon_str)
12563{
12564 if (beacon == WIFI_BITRATE_1MBPS)
12565 strcpy(beacon_str, "1Mbps");
12566 else if (beacon == WIFI_BITRATE_2MBPS)
12567 strcpy(beacon_str, "2Mbps");
12568 else if (beacon == WIFI_BITRATE_5_5MBPS)
12569 strcpy(beacon_str, "5.5Mbps");
12570 else if (beacon == WIFI_BITRATE_6MBPS)
12571 strcpy(beacon_str, "6Mbps");
12572 else if (beacon == WIFI_BITRATE_9MBPS)
12573 strcpy(beacon_str, "9Mbps");
12574 else if (beacon == WIFI_BITRATE_11MBPS)
12575 strcpy(beacon_str, "11Mbps");
12576 else if (beacon == WIFI_BITRATE_12MBPS)
12577 strcpy(beacon_str, "12Mbps");
12578 else if (beacon == WIFI_BITRATE_18MBPS)
12579 strcpy(beacon_str, "18Mbps");
12580 else if (beacon == WIFI_BITRATE_24MBPS)
12581 strcpy(beacon_str, "24Mbps");
12582 else if (beacon == WIFI_BITRATE_36MBPS)
12583 strcpy(beacon_str, "36Mbps");
12584 else if (beacon == WIFI_BITRATE_48MBPS)
12585 strcpy(beacon_str, "48Mbps");
12586 else if (beacon == WIFI_BITRATE_54MBPS)
12587 strcpy(beacon_str, "54Mbps");
12588 return RETURN_OK;
12589}
12590
12591INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12592{
12593 INT mode = 0;
12594 INT ret = -1;
12595 INT output = 0;
12596 int i = 0;
12597 int vap_index = 0;
12598 BOOL enabled = FALSE;
12599 char buf[256] = {0};
12600 wifi_vap_security_t security = {0};
12601 map->num_vaps = 5; // Hardcoded
12602
12603 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12604 printf("Entering %s index = %d\n", __func__, (int)index);
12605
12606 for (i = 0; i < 5; i++)
12607 {
12608 map->vap_array[i].radio_index = index;
12609
12610 vap_index = array_index_to_vap_index(index, i);
12611 if (vap_index < 0)
12612 return RETURN_ERR;
12613
12614 strcpy(map->vap_array[i].bridge_name, BRIDGE_NAME);
12615
12616 map->vap_array[i].vap_index = vap_index;
12617
12618 memset(buf, 0, sizeof(buf));
12619 ret = wifi_getApName(vap_index, buf);
12620 if (ret != RETURN_OK) {
12621 printf("%s: wifi_getApName return error\n", __func__);
12622 return RETURN_ERR;
12623 }
12624 snprintf(map->vap_array[i].vap_name, sizeof(map->vap_array[i].vap_name), "%s", buf);
12625
12626 memset(buf, 0, sizeof(buf));
12627 ret = wifi_getSSIDName(vap_index, buf);
12628 if (ret != RETURN_OK) {
12629 printf("%s: wifi_getSSIDName return error\n", __func__);
12630 return RETURN_ERR;
12631 }
12632 snprintf(map->vap_array[i].u.bss_info.ssid, sizeof(map->vap_array[i].u.bss_info.ssid), "%s", buf);
12633
12634 ret = wifi_getSSIDEnable(vap_index, &enabled);
12635 if (ret != RETURN_OK) {
12636 printf("%s: wifi_getSSIDEnable return error\n", __func__);
12637 return RETURN_ERR;
12638 }
12639 map->vap_array[i].u.bss_info.enabled = enabled;
12640
12641 ret = wifi_getApSsidAdvertisementEnable(vap_index, &enabled);
12642 if (ret != RETURN_OK) {
12643 printf("%s: wifi_getApSsidAdvertisementEnable return error\n", __func__);
12644 return RETURN_ERR;
12645 }
12646 map->vap_array[i].u.bss_info.showSsid = enabled;
developer69b61b02023-03-07 17:17:44 +080012647
developer72fb0bb2023-01-11 09:46:29 +080012648 ret = wifi_getApIsolationEnable(vap_index, &enabled);
12649 if (ret != RETURN_OK) {
12650 printf("%s: wifi_getApIsolationEnable return error\n", __func__);
12651 return RETURN_ERR;
12652 }
12653 map->vap_array[i].u.bss_info.isolation = enabled;
12654
12655 ret = wifi_getApMaxAssociatedDevices(vap_index, &output);
12656 if (ret != RETURN_OK) {
12657 printf("%s: wifi_getApMaxAssociatedDevices return error\n", __func__);
12658 return RETURN_ERR;
12659 }
12660 map->vap_array[i].u.bss_info.bssMaxSta = output;
12661
12662 ret = wifi_getBSSTransitionActivation(vap_index, &enabled);
12663 if (ret != RETURN_OK) {
12664 printf("%s: wifi_getBSSTransitionActivation return error\n", __func__);
12665 return RETURN_ERR;
12666 }
12667 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
12668
12669 ret = wifi_getNeighborReportActivation(vap_index, &enabled);
12670 if (ret != RETURN_OK) {
12671 printf("%s: wifi_getNeighborReportActivation return error\n", __func__);
12672 return RETURN_ERR;
12673 }
12674 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
12675
12676 ret = wifi_getApSecurity(vap_index, &security);
12677 if (ret != RETURN_OK) {
12678 printf("%s: wifi_getApSecurity return error\n", __func__);
12679 return RETURN_ERR;
12680 }
12681 map->vap_array[i].u.bss_info.security = security;
12682
12683 ret = wifi_getApMacAddressControlMode(vap_index, &mode);
12684 if (ret != RETURN_OK) {
12685 printf("%s: wifi_getApMacAddressControlMode return error\n", __func__);
12686 return RETURN_ERR;
12687 }
developer69b61b02023-03-07 17:17:44 +080012688 if (mode == 0)
developer72fb0bb2023-01-11 09:46:29 +080012689 map->vap_array[i].u.bss_info.mac_filter_enable = FALSE;
developer69b61b02023-03-07 17:17:44 +080012690 else
developer72fb0bb2023-01-11 09:46:29 +080012691 map->vap_array[i].u.bss_info.mac_filter_enable = TRUE;
developer69b61b02023-03-07 17:17:44 +080012692 if (mode == 1)
developer72fb0bb2023-01-11 09:46:29 +080012693 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
developer69b61b02023-03-07 17:17:44 +080012694 else if (mode == 2)
developer72fb0bb2023-01-11 09:46:29 +080012695 map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list;
12696
12697 ret = wifi_getApWmmEnable(vap_index, &enabled);
12698 if (ret != RETURN_OK) {
12699 printf("%s: wifi_getApWmmEnable return error\n", __func__);
12700 return RETURN_ERR;
12701 }
12702 map->vap_array[i].u.bss_info.wmm_enabled = enabled;
12703
12704 ret = wifi_getApUAPSDCapability(vap_index, &enabled);
12705 if (ret != RETURN_OK) {
12706 printf("%s: wifi_getApUAPSDCapability return error\n", __func__);
12707 return RETURN_ERR;
12708 }
12709 map->vap_array[i].u.bss_info.UAPSDEnabled = enabled;
12710
12711 memset(buf, 0, sizeof(buf));
12712 ret = wifi_getApBeaconRate(map->vap_array[i].radio_index, buf);
12713 if (ret != RETURN_OK) {
12714 printf("%s: wifi_getApBeaconRate return error\n", __func__);
12715 return RETURN_ERR;
12716 }
12717 map->vap_array[i].u.bss_info.beaconRate = beaconRate_string_to_enum(buf);
12718
12719 memset(buf, 0, sizeof(buf));
12720 ret = wifi_getBaseBSSID(vap_index, buf);
12721 if (ret != RETURN_OK) {
12722 printf("%s: wifi_getBaseBSSID return error\n", __func__);
12723 return RETURN_ERR;
12724 }
12725 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
12726 &map->vap_array[i].u.bss_info.bssid[0],
12727 &map->vap_array[i].u.bss_info.bssid[1],
12728 &map->vap_array[i].u.bss_info.bssid[2],
12729 &map->vap_array[i].u.bss_info.bssid[3],
12730 &map->vap_array[i].u.bss_info.bssid[4],
12731 &map->vap_array[i].u.bss_info.bssid[5]);
12732 // 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]);
12733
12734 ret = wifi_getRadioIGMPSnoopingEnable(map->vap_array[i].radio_index, &enabled);
12735 if (ret != RETURN_OK) {
12736 fprintf(stderr, "%s: wifi_getRadioIGMPSnoopingEnable\n", __func__);
12737 return RETURN_ERR;
12738 }
12739 map->vap_array[i].u.bss_info.mcast2ucast = enabled;
12740
12741 // TODO: wps, noack
12742 }
12743 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12744 return RETURN_OK;
12745}
12746
12747void checkVapStatus(int apIndex, bool *enable)
12748{
12749 char if_name[16] = {0};
12750 char cmd[128] = {0};
12751 char buf[128] = {0};
12752
12753 *enable = FALSE;
12754 if (wifi_GetInterfaceName(apIndex, if_name) != RETURN_OK)
12755 return;
12756
12757 snprintf(cmd, sizeof(cmd), "cat %s | grep ^%s=1", VAP_STATUS_FILE, if_name);
12758 _syscmd(cmd, buf, sizeof(buf));
12759 if (strlen(buf) > 0)
12760 *enable = TRUE;
12761 return;
12762}
12763
12764static int prepareInterface(UINT apIndex, char *new_interface)
12765{
12766 char cur_interface[16] = {0};
12767 char config_file[128] = {0};
developer8a3bbbf2023-03-15 17:47:23 +080012768 char cmd[MAX_CMD_SIZE] = {0};
12769 char buf[MAX_BUF_SIZE] = {0};
developer72fb0bb2023-01-11 09:46:29 +080012770 int max_radio_num = 0;
12771 int radioIndex = -1;
12772 int phyIndex = -1;
developer8a3bbbf2023-03-15 17:47:23 +080012773 struct params params;
developer72fb0bb2023-01-11 09:46:29 +080012774
12775 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
12776 wifi_hostapdRead(config_file, "interface", cur_interface, sizeof(cur_interface));
12777
12778 if (strncmp(cur_interface, new_interface, sizeof(cur_interface)) != 0) {
developer8a3bbbf2023-03-15 17:47:23 +080012779 wifi_getMaxRadioNumber(&max_radio_num);
developer72fb0bb2023-01-11 09:46:29 +080012780 radioIndex = apIndex % max_radio_num;
12781 phyIndex = radio_index_to_phy(radioIndex);
12782 // disable and del old interface, then add new interface
12783 wifi_setApEnable(apIndex, FALSE);
developer8a3bbbf2023-03-15 17:47:23 +080012784
12785 params.name = "interface";
12786 params.value = new_interface;
12787 wifi_hostapdWrite(config_file, &params, 1);
12788
12789 snprintf(cmd, MAX_CMD_SIZE, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", phyIndex, config_file);
12790 _syscmd(cmd, buf, sizeof(buf));
developer72fb0bb2023-01-11 09:46:29 +080012791 }
developer8a3bbbf2023-03-15 17:47:23 +080012792
developer72fb0bb2023-01-11 09:46:29 +080012793 // update the vap status file
12794 snprintf(cmd, sizeof(cmd), "sed -i -n -e '/^%s=/!p' -e '$a%s=1' %s", cur_interface, new_interface, VAP_STATUS_FILE);
12795 _syscmd(cmd, buf, sizeof(buf));
12796 return RETURN_OK;
12797}
12798
12799INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
12800{
12801 char interface_name[16] = {0};
12802 unsigned int i;
12803 wifi_vap_info_t *vap_info = NULL;
12804 int acl_mode;
12805 int ret = 0;
12806 char *sec_str = NULL;
12807 char buf[256] = {0};
12808 char cmd[128] = {0};
12809 char config_file[64] = {0};
12810 char bssid[32] = {0};
12811 char psk_file[64] = {0};
12812 bool enable = FALSE;
12813
12814 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12815 printf("Entering %s index = %d\n", __func__, (int)index);
12816 for (i = 0; i < map->num_vaps; i++)
12817 {
12818 multiple_set = TRUE;
12819 vap_info = &map->vap_array[i];
12820
12821 // Check vap status file to enable multiple ap if the system boot.
12822 checkVapStatus(vap_info->vap_index, &enable);
12823 if (vap_info->u.bss_info.enabled == FALSE && enable == FALSE)
12824 continue;
12825
12826 fprintf(stderr, "\nCreate VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
12827
12828 if (wifi_getApEnable(vap_info->vap_index, &enable) != RETURN_OK)
12829 enable = FALSE;
12830
12831 // multi-ap first up need to copy current radio config
12832 if (vap_info->radio_index != vap_info->vap_index && enable == FALSE) {
12833 snprintf(cmd, sizeof(cmd), "cp %s%d.conf %s%d.conf", CONFIG_PREFIX, vap_info->radio_index, CONFIG_PREFIX, vap_info->vap_index);
12834 _syscmd(cmd, buf, sizeof(buf));
12835 if (strlen(vap_info->vap_name) == 0) // default name of the interface is wifiX
12836 snprintf(vap_info->vap_name, 16, "wifi%d", vap_info->vap_index);
12837 } else {
12838 // Check whether the interface name is valid or this ap change it.
12839 int apIndex = -1;
12840 wifi_getApIndexFromName(vap_info->vap_name, &apIndex);
12841 if (apIndex != -1 && apIndex != vap_info->vap_index)
12842 continue;
12843 prepareInterface(vap_info->vap_index, vap_info->vap_name);
12844 }
12845
12846 struct params params[3];
12847 params[0].name = "interface";
12848 params[0].value = vap_info->vap_name;
12849 mac_addr_ntoa(bssid, vap_info->u.bss_info.bssid);
12850 params[1].name = "bssid";
12851 params[1].value = bssid;
12852 snprintf(psk_file, sizeof(psk_file), "\\/nvram\\/hostapd%d.psk", vap_info->vap_index);
12853 params[2].name = "wpa_psk_file";
12854 params[2].value = psk_file;
12855
12856 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, vap_info->vap_index);
12857 wifi_hostapdWrite(config_file, params, 3);
12858
12859 snprintf(cmd, sizeof(cmd), "touch %s", psk_file);
12860 _syscmd(cmd, buf, sizeof(buf));
12861
12862 ret = wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid);
12863 if (ret != RETURN_OK) {
12864 fprintf(stderr, "%s: wifi_setSSIDName return error\n", __func__);
12865 return RETURN_ERR;
12866 }
12867
12868 ret = wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid);
12869 if (ret != RETURN_OK) {
12870 fprintf(stderr, "%s: wifi_setApSsidAdvertisementEnable return error\n", __func__);
12871 return RETURN_ERR;
12872 }
12873
12874 ret = wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
12875 if (ret != RETURN_OK) {
12876 fprintf(stderr, "%s: wifi_setApIsolationEnable return error\n", __func__);
12877 return RETURN_ERR;
12878 }
12879
12880 ret = wifi_setApMaxAssociatedDevices(vap_info->vap_index, vap_info->u.bss_info.bssMaxSta);
12881 if (ret != RETURN_OK) {
12882 fprintf(stderr, "%s: wifi_setApMaxAssociatedDevices return error\n", __func__);
12883 return RETURN_ERR;
12884 }
12885
12886 ret = wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated);
12887 if (ret != RETURN_OK) {
12888 fprintf(stderr, "%s: wifi_setBSSTransitionActivation return error\n", __func__);
12889 return RETURN_ERR;
12890 }
12891
12892 ret = wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated);
12893 if (ret != RETURN_OK) {
12894 fprintf(stderr, "%s: wifi_setNeighborReportActivation return error\n", __func__);
12895 return RETURN_ERR;
12896 }
12897
12898 if (vap_info->u.bss_info.mac_filter_enable == false){
12899 acl_mode = 0;
12900 }else {
12901 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list){
12902 acl_mode = 2;
12903 snprintf(cmd, sizeof(cmd), "touch %s%d", DENY_PREFIX, vap_info->vap_index);
12904 _syscmd(cmd, buf, sizeof(buf));
12905 }else{
12906 acl_mode = 1;
12907 }
12908 }
12909
12910 ret = wifi_setApWmmEnable(vap_info->vap_index, vap_info->u.bss_info.wmm_enabled);
12911 if (ret != RETURN_OK) {
12912 fprintf(stderr, "%s: wifi_setApWmmEnable return error\n", __func__);
12913 return RETURN_ERR;
12914 }
12915
12916 ret = wifi_setApWmmUapsdEnable(vap_info->vap_index, vap_info->u.bss_info.UAPSDEnabled);
12917 if (ret != RETURN_OK) {
12918 fprintf(stderr, "%s: wifi_setApWmmUapsdEnable return error\n", __func__);
12919 return RETURN_ERR;
12920 }
12921
12922 memset(buf, 0, sizeof(buf));
12923 beaconRate_enum_to_string(vap_info->u.bss_info.beaconRate, buf);
12924 // fprintf(stderr, "%s: beaconrate: %d, buf: %s\n", __func__, vap_info->u.bss_info.beaconRate, buf);
12925 ret = wifi_setApBeaconRate(vap_info->radio_index, buf);
12926 if (ret != RETURN_OK) {
12927 fprintf(stderr, "%s: wifi_setApBeaconRate return error\n", __func__);
12928 return RETURN_ERR;
12929 }
12930
12931 ret = wifi_setRadioIGMPSnoopingEnable(vap_info->radio_index, vap_info->u.bss_info.mcast2ucast);
12932 if (ret != RETURN_OK) {
12933 fprintf(stderr, "%s: wifi_setRadioIGMPSnoopingEnable\n", __func__);
12934 return RETURN_ERR;
12935 }
12936
developer72fb0bb2023-01-11 09:46:29 +080012937 ret = wifi_setApSecurity(vap_info->vap_index, &vap_info->u.bss_info.security);
12938 if (ret != RETURN_OK) {
12939 fprintf(stderr, "%s: wifi_setApSecurity return error\n", __func__);
12940 return RETURN_ERR;
12941 }
12942
developer23e71282023-01-18 10:25:19 +080012943 wifi_setApEnable(vap_info->vap_index, FALSE);
12944 wifi_setApEnable(vap_info->vap_index, TRUE);
12945 multiple_set = FALSE;
12946
12947 // If config use hostapd_cli to set, we calling these type of functions after enable the ap.
developer72fb0bb2023-01-11 09:46:29 +080012948 ret = wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode);
12949 if (ret != RETURN_OK) {
12950 fprintf(stderr, "%s: wifi_setApMacAddressControlMode return error\n", __func__);
12951 return RETURN_ERR;
12952 }
12953
12954 // TODO mgmtPowerControl, interworking, wps
12955 }
12956 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12957 return RETURN_OK;
12958}
12959
12960int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
12961{
12962 char *token, *next;
12963 const char s[2] = ",";
12964 int count =0;
12965
12966 /* get the first token */
12967 token = strtok_r(pchannels, s, &next);
12968
12969 /* walk through other tokens */
12970 while( token != NULL && count < MAX_CHANNELS) {
12971 chlistptr->channels_list[count++] = atoi(token);
12972 token = strtok_r(NULL, s, &next);
12973 }
12974
12975 return count;
12976}
12977
12978static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
12979{
12980 INT status;
12981 wifi_channels_list_t *chlistp;
12982 CHAR output_string[64];
12983 CHAR pchannels[128];
12984 CHAR interface_name[16] = {0};
12985 wifi_band band;
12986
12987 if(rcap == NULL)
12988 {
12989 return RETURN_ERR;
12990 }
12991
12992 rcap->numSupportedFreqBand = 1;
12993 band = wifi_index_to_band(radioIndex);
12994
12995 if (band == band_2_4)
12996 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
12997 else if (band == band_5)
12998 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
12999 else if (band == band_6)
13000 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
13001
13002 chlistp = &(rcap->channel_list[0]);
13003 memset(pchannels, 0, sizeof(pchannels));
13004
13005 /* possible number of radio channels */
13006 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
13007 {
13008 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
13009 }
13010 /* Number of channels and list*/
13011 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
13012
13013 /* autoChannelSupported */
13014 /* always ON with wifi_getRadioAutoChannelSupported */
13015 rcap->autoChannelSupported = TRUE;
13016
13017 /* DCSSupported */
13018 /* always ON with wifi_getRadioDCSSupported */
13019 rcap->DCSSupported = TRUE;
13020
13021 /* zeroDFSSupported - TBD */
13022 rcap->zeroDFSSupported = FALSE;
13023
13024 /* Supported Country List*/
13025 memset(output_string, 0, sizeof(output_string));
13026 status = wifi_getRadioCountryCode(radioIndex, output_string);
13027 if( status != 0 ) {
13028 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
13029 return RETURN_ERR;
13030 } else {
13031 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
13032 }
13033 if(!strcmp(output_string,"US")){
13034 rcap->countrySupported[0] = wifi_countrycode_US;
13035 rcap->countrySupported[1] = wifi_countrycode_CA;
13036 } else if (!strcmp(output_string,"CA")) {
13037 rcap->countrySupported[0] = wifi_countrycode_CA;
13038 rcap->countrySupported[1] = wifi_countrycode_US;
13039 } else {
13040 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
13041 }
13042
13043 rcap->numcountrySupported = 2;
13044
13045 /* csi */
13046 rcap->csi.maxDevices = 8;
13047 rcap->csi.soudingFrameSupported = TRUE;
13048
13049 wifi_GetInterfaceName(radioIndex, interface_name);
13050 snprintf(rcap->ifaceName, sizeof(interface_name), "%s",interface_name);
13051
13052 /* channelWidth - all supported bandwidths */
13053 int i=0;
13054 rcap->channelWidth[i] = 0;
13055 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13056 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13057 WIFI_CHANNELBANDWIDTH_40MHZ);
13058
13059 }
13060 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
13061 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
13062 WIFI_CHANNELBANDWIDTH_40MHZ |
13063 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
13064 }
13065
13066
13067 /* mode - all supported variants */
13068 // rcap->mode[i] = WIFI_80211_VARIANT_H;
13069 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
13070 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
13071 }
13072 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
13073 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
13074 }
13075 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
13076 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
13077 }
13078 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
13079 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
13080
13081 /* supportedBitRate - all supported bitrates */
13082 rcap->supportedBitRate[i] = 0;
13083 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
13084 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13085 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
13086 }
13087 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
13088 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
13089 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
13090 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
13091 }
13092
13093
13094 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
13095 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
13096 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
13097 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
13098 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
13099 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
13100 rcap->cipherSupported = 0;
13101 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
13102 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
13103
13104 return RETURN_OK;
13105}
13106
13107INT wifi_getHalCapability(wifi_hal_capability_t *cap)
13108{
13109 INT status = 0, radioIndex = 0;
13110 char cmd[MAX_BUF_SIZE] = {0}, output[MAX_BUF_SIZE] = {0};
13111 int iter = 0;
13112 unsigned int j = 0;
13113 int max_num_radios;
13114 wifi_interface_name_idex_map_t *iface_info = NULL;
13115
13116 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13117
13118 memset(cap, 0, sizeof(wifi_hal_capability_t));
13119
13120 /* version */
13121 cap->version.major = WIFI_HAL_MAJOR_VERSION;
13122 cap->version.minor = WIFI_HAL_MINOR_VERSION;
13123
13124 /* number of radios platform property */
13125 wifi_getMaxRadioNumber(&max_num_radios);
13126 cap->wifi_prop.numRadios = max_num_radios;
13127
13128 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
13129 {
13130 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
13131 if (status != 0) {
13132 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
13133 return RETURN_ERR;
13134 }
13135
13136 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
13137 {
13138 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
13139 {
13140 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
13141 return RETURN_ERR;
13142 }
13143 iface_info = &cap->wifi_prop.interface_map[iter];
13144 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
13145 iface_info->rdk_radio_index = radioIndex;
13146 memset(output, 0, sizeof(output));
13147 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
13148 {
13149 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
13150 }
13151 // TODO: bridge name
13152 // TODO: vlan id
13153 // TODO: primary
13154 iface_info->index = array_index_to_vap_index(radioIndex, j);
13155 memset(output, 0, sizeof(output));
13156 if (wifi_getApName(iface_info->index, output) == RETURN_OK)
13157 {
13158 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
13159 }
13160 iter++;
13161 }
13162 }
13163
13164 cap->BandSteeringSupported = FALSE;
13165 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13166 return RETURN_OK;
13167}
13168
13169INT wifi_setOpportunisticKeyCaching(int ap_index, BOOL okc_enable)
13170{
13171 struct params h_config={0};
13172 char config_file[64] = {0};
13173
13174 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13175
13176 h_config.name = "okc";
13177 h_config.value = okc_enable?"1":"0";
13178
13179 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13180 wifi_hostapdWrite(config_file, &h_config, 1);
13181 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13182
13183 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13184 return RETURN_OK;
13185}
13186
13187INT wifi_setSAEMFP(int ap_index, BOOL enable)
13188{
13189 struct params h_config={0};
13190 char config_file[64] = {0};
13191 char buf[128] = {0};
13192
13193 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13194
13195 h_config.name = "sae_require_mfp";
13196 h_config.value = enable?"1":"0";
13197
13198 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13199 wifi_hostapdWrite(config_file, &h_config, 1);
13200 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13201
13202 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13203 return RETURN_OK;
13204}
13205
13206INT wifi_setSAEpwe(int ap_index, int sae_pwe)
13207{
13208 struct params h_config={0};
13209 char config_file[64] = {0};
13210 char buf[128] = {0};
13211
13212 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13213
13214 h_config.name = "sae_pwe";
13215 snprintf(buf, sizeof(buf), "%d", sae_pwe);
13216 h_config.value = buf;
13217
13218 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13219 wifi_hostapdWrite(config_file, &h_config, 1);
13220 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13221
13222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13223 return RETURN_OK;
13224}
13225
13226INT wifi_setDisable_EAPOL_retries(int ap_index, BOOL disable_EAPOL_retries)
13227{
13228 // wpa3 use SAE instead of PSK, so we need to disable this feature when using wpa3.
13229 struct params h_config={0};
13230 char config_file[64] = {0};
13231
13232 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
13233
13234 h_config.name = "wpa_disable_eapol_key_retries";
13235 h_config.value = disable_EAPOL_retries?"1":"0";
13236
13237 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, ap_index);
13238 wifi_hostapdWrite(config_file, &h_config, 1);
13239 wifi_hostapdProcessUpdate(ap_index, &h_config, 1);
13240
13241 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
13242 return RETURN_OK;
13243}
13244
13245INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
13246{
13247 char buf[128] = {0};
13248 char config_file[128] = {0};
13249 char password[64] = {0};
13250 char mfp[32] = {0};
13251 char wpa_mode[32] = {0};
13252 BOOL okc_enable = FALSE;
13253 BOOL sae_MFP = FALSE;
13254 BOOL disable_EAPOL_retries = TRUE;
13255 int sae_pwe = 0;
13256 struct params params = {0};
13257 wifi_band band = band_invalid;
13258
13259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13260
13261 multiple_set = TRUE;
13262 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13263 if (security->mode == wifi_security_mode_none) {
13264 strcpy(wpa_mode, "None");
13265 } else if (security->mode == wifi_security_mode_wpa_personal)
13266 strcpy(wpa_mode, "WPA-Personal");
13267 else if (security->mode == wifi_security_mode_wpa2_personal)
13268 strcpy(wpa_mode, "WPA2-Personal");
13269 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
13270 strcpy(wpa_mode, "WPA-WPA2-Personal");
13271 else if (security->mode == wifi_security_mode_wpa_enterprise)
13272 strcpy(wpa_mode, "WPA-Enterprise");
13273 else if (security->mode == wifi_security_mode_wpa2_enterprise)
13274 strcpy(wpa_mode, "WPA2-Enterprise");
13275 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
13276 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
13277 else if (security->mode == wifi_security_mode_wpa3_personal) {
13278 strcpy(wpa_mode, "WPA3-Personal");
13279 okc_enable = TRUE;
13280 sae_MFP = TRUE;
13281 sae_pwe = 2;
13282 disable_EAPOL_retries = FALSE;
13283 } else if (security->mode == wifi_security_mode_wpa3_transition) {
13284 strcpy(wpa_mode, "WPA3-Personal-Transition");
13285 okc_enable = TRUE;
13286 sae_MFP = TRUE;
13287 sae_pwe = 2;
13288 disable_EAPOL_retries = FALSE;
13289 } else if (security->mode == wifi_security_mode_wpa3_enterprise) {
13290 strcpy(wpa_mode, "WPA3-Enterprise");
13291 sae_MFP = TRUE;
13292 sae_pwe = 2;
13293 disable_EAPOL_retries = FALSE;
developer3086e2f2023-01-17 09:40:01 +080013294 } else if (security->mode == wifi_security_mode_owe) {
13295 strcpy(wpa_mode, "OWE");
13296 sae_MFP = TRUE;
13297 sae_pwe = 2;
13298 disable_EAPOL_retries = FALSE;
developer72fb0bb2023-01-11 09:46:29 +080013299 }
13300
13301 band = wifi_index_to_band(ap_index);
13302 if (band == band_6 && strstr(wpa_mode, "WPA3") == NULL) {
13303 fprintf(stderr, "%s: 6G band must set with wpa3.\n", __func__);
13304 return RETURN_ERR;
13305 }
13306
13307 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
13308 wifi_setOpportunisticKeyCaching(ap_index, okc_enable);
13309 wifi_setSAEMFP(ap_index, sae_MFP);
13310 wifi_setSAEpwe(ap_index, sae_pwe);
13311 wifi_setDisable_EAPOL_retries(ap_index, disable_EAPOL_retries);
13312
developer23e71282023-01-18 10:25:19 +080013313 if (security->mode != wifi_security_mode_none && security->mode != wifi_security_mode_owe) {
developer72fb0bb2023-01-11 09:46:29 +080013314 if (security->u.key.type == wifi_security_key_type_psk || security->u.key.type == wifi_security_key_type_psk_sae) {
13315 strncpy(password, security->u.key.key, 63); // 8 to 63 characters
13316 password[63] = '\0';
13317 wifi_setApSecurityKeyPassphrase(ap_index, password);
13318 }
13319 if (security->u.key.type == wifi_security_key_type_sae || security->u.key.type == wifi_security_key_type_psk_sae) {
13320 params.name = "sae_password";
13321 params.value = security->u.key.key;
13322 wifi_hostapdWrite(config_file, &params, 1);
13323 }
13324 }
13325
13326 if (security->mode != wifi_security_mode_none) {
13327 memset(&params, 0, sizeof(params));
13328 params.name = "wpa_pairwise";
13329 if (security->encr == wifi_encryption_tkip)
13330 params.value = "TKIP";
13331 else if (security->encr == wifi_encryption_aes)
13332 params.value = "CCMP";
13333 else if (security->encr == wifi_encryption_aes_tkip)
13334 params.value = "TKIP CCMP";
13335 wifi_hostapdWrite(config_file, &params, 1);
13336 }
13337
13338 if (security->mfp == wifi_mfp_cfg_disabled)
13339 strcpy(mfp, "Disabled");
13340 else if (security->mfp == wifi_mfp_cfg_optional)
13341 strcpy(mfp, "Optional");
13342 else if (security->mfp == wifi_mfp_cfg_required)
13343 strcpy(mfp, "Required");
13344 wifi_setApSecurityMFPConfig(ap_index, mfp);
13345
13346 memset(&params, 0, sizeof(params));
13347 params.name = "transition_disable";
13348 if (security->wpa3_transition_disable == TRUE)
13349 params.value = "0x01";
13350 else
13351 params.value = "0x00";
13352 wifi_hostapdWrite(config_file, &params, 1);
13353
13354 memset(&params, 0, sizeof(params));
13355 params.name = "wpa_group_rekey";
13356 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
13357 params.value = buf;
13358 wifi_hostapdWrite(config_file, &params, 1);
13359
13360 memset(&params, 0, sizeof(params));
13361 params.name = "wpa_strict_rekey";
13362 params.value = security->strict_rekey?"1":"0";
13363 wifi_hostapdWrite(config_file, &params, 1);
13364
13365 memset(&params, 0, sizeof(params));
13366 params.name = "wpa_pairwise_update_count";
13367 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
13368 params.value = buf;
13369 wifi_hostapdWrite(config_file, &params, 1);
13370
13371 memset(&params, 0, sizeof(params));
13372 params.name = "disable_pmksa_caching";
13373 params.value = security->disable_pmksa_caching?"1":"0";
13374 wifi_hostapdWrite(config_file, &params, 1);
13375
developer23e71282023-01-18 10:25:19 +080013376 if (multiple_set == FALSE) {
13377 wifi_setApEnable(ap_index, FALSE);
13378 wifi_setApEnable(ap_index, TRUE);
13379 }
developer72fb0bb2023-01-11 09:46:29 +080013380
13381 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13382
13383 return RETURN_OK;
13384}
13385
13386INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
13387{
13388 char buf[256] = {0};
13389 char config_file[128] = {0};
13390 int disable = 0;
13391 // struct params params = {0};
13392
13393 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13394 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
13395 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
13396 security->mode = wifi_security_mode_none;
13397 if (strlen(buf) != 0) {
13398 if (!strcmp(buf, "WPA-Personal"))
13399 security->mode = wifi_security_mode_wpa_personal;
13400 else if (!strcmp(buf, "WPA2-Personal"))
13401 security->mode = wifi_security_mode_wpa2_personal;
13402 else if (!strcmp(buf, "WPA-WPA2-Personal"))
13403 security->mode = wifi_security_mode_wpa_wpa2_personal;
13404 else if (!strcmp(buf, "WPA-Enterprise"))
13405 security->mode = wifi_security_mode_wpa_enterprise;
13406 else if (!strcmp(buf, "WPA2-Enterprise"))
13407 security->mode = wifi_security_mode_wpa2_enterprise;
13408 else if (!strcmp(buf, "WPA-WPA2-Enterprise"))
13409 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
13410 else if (!strcmp(buf, "WPA3-Personal"))
13411 security->mode = wifi_security_mode_wpa3_personal;
13412 else if (!strcmp(buf, "WPA3-Personal-Transition"))
13413 security->mode = wifi_security_mode_wpa3_transition;
13414 else if (!strcmp(buf, "WPA3-Enterprise"))
13415 security->mode = wifi_security_mode_wpa3_enterprise;
developer3086e2f2023-01-17 09:40:01 +080013416 else if (!strcmp(buf, "OWE"))
13417 security->mode = wifi_security_mode_owe;
developer72fb0bb2023-01-11 09:46:29 +080013418 }
13419
13420 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
13421 if (security->mode == wifi_security_mode_none)
13422 security->encr = wifi_encryption_none;
13423 else {
13424 if (strcmp(buf, "TKIP") == 0)
13425 security->encr = wifi_encryption_tkip;
13426 else if (strcmp(buf, "CCMP") == 0)
13427 security->encr = wifi_encryption_aes;
13428 else
13429 security->encr = wifi_encryption_aes_tkip;
13430 }
13431
13432 if (security->mode != wifi_encryption_none) {
13433 memset(buf, 0, sizeof(buf));
13434 // wpa3 can use one or both configs as password, so we check sae_password first.
13435 wifi_hostapdRead(config_file, "sae_password", buf, sizeof(buf));
13436 if (security->mode == wifi_security_mode_wpa3_personal && strlen(buf) != 0) {
13437 security->u.key.type = wifi_security_key_type_sae;
13438 } else {
13439 security->u.key.type = wifi_security_key_type_psk;
13440 wifi_hostapdRead(config_file, "wpa_passphrase", buf, sizeof(buf));
13441 }
13442 strncpy(security->u.key.key, buf, sizeof(buf));
13443 security->u.key.key[255] = '\0';
13444 }
13445
13446 memset(buf, 0, sizeof(buf));
13447 wifi_getApSecurityMFPConfig(ap_index, buf);
13448 if (strcmp(buf, "Disabled") == 0)
13449 security->mfp = wifi_mfp_cfg_disabled;
13450 else if (strcmp(buf, "Optional") == 0)
13451 security->mfp = wifi_mfp_cfg_optional;
13452 else if (strcmp(buf, "Required") == 0)
13453 security->mfp = wifi_mfp_cfg_required;
13454
13455 memset(buf, 0, sizeof(buf));
13456 security->wpa3_transition_disable = FALSE;
13457 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
13458 disable = strtol(buf, NULL, 16);
13459 if (disable != 0)
13460 security->wpa3_transition_disable = TRUE;
13461
13462 memset(buf, 0, sizeof(buf));
13463 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
13464 if (strlen(buf) == 0)
13465 security->rekey_interval = 86400;
13466 else
13467 security->rekey_interval = strtol(buf, NULL, 10);
13468
13469 memset(buf, 0, sizeof(buf));
13470 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
13471 if (strlen(buf) == 0)
13472 security->strict_rekey = 1;
13473 else
13474 security->strict_rekey = strtol(buf, NULL, 10);
13475
13476 memset(buf, 0, sizeof(buf));
13477 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
13478 if (strlen(buf) == 0)
13479 security->eapol_key_retries = 4;
13480 else
13481 security->eapol_key_retries = strtol(buf, NULL, 10);
13482
13483 memset(buf, 0, sizeof(buf));
13484 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
13485 if (strlen(buf) == 0)
13486 security->disable_pmksa_caching = FALSE;
13487 else
13488 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
13489
13490 /* TODO
13491 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
13492 */
13493 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
13494 security->eap_identity_req_timeout = 0;
13495 security->eap_identity_req_retries = 0;
13496 security->eap_req_timeout = 0;
13497 security->eap_req_retries = 0;
13498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13499 return RETURN_OK;
13500}
13501
13502#endif /* WIFI_HAL_VERSION_3 */
13503
13504#ifdef WIFI_HAL_VERSION_3_PHASE2
13505INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
13506{
13507 char interface_name[16] = {0};
13508 char cmd[128] = {0};
13509 char buf[128] = {0};
13510 char *mac_addr = NULL;
13511 BOOL status = FALSE;
13512 size_t len = 0;
13513
13514 if(ap_index > MAX_APS)
13515 return RETURN_ERR;
13516
13517 *output_numDevices = 0;
13518 wifi_getApEnable(ap_index, &status);
13519 if (status == FALSE)
13520 return RETURN_OK;
13521
13522 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13523 return RETURN_ERR;
13524 sprintf(cmd, "hostapd_cli -i %s list_sta", interface_name);
13525 _syscmd(cmd, buf, sizeof(buf));
13526
13527 mac_addr = strtok(buf, "\n");
13528 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
13529 *output_numDevices = i + 1;
13530 fprintf(stderr, "mac_addr: %s\n", mac_addr);
13531 addr_ptr = output_deviceMacAddressArray[i];
13532 mac_addr_aton(addr_ptr, mac_addr);
13533 mac_addr = strtok(NULL, "\n");
13534 }
13535
13536 return RETURN_OK;
13537}
13538#else
13539INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
13540{
13541 char interface_name[16] = {0};
13542 char cmd[128];
13543 BOOL status = false;
13544
13545 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
13546 return RETURN_ERR;
13547
13548 output_buf[0] = '\0';
13549
13550 wifi_getApEnable(ap_index,&status);
13551 if (!status)
13552 return RETURN_OK;
13553
13554 if (wifi_GetInterfaceName(ap_index, interface_name) != RETURN_OK)
13555 return RETURN_ERR;
13556 sprintf(cmd, "hostapd_cli -i %s list_sta | tr '\\n' ',' | sed 's/.$//'", interface_name);
13557 _syscmd(cmd, output_buf, output_buf_size);
developer69b61b02023-03-07 17:17:44 +080013558
developer72fb0bb2023-01-11 09:46:29 +080013559 return RETURN_OK;
13560}
13561#endif
13562
13563INT wifi_getProxyArp(INT apIndex, BOOL *enable)
13564{
13565 char output[16]={'\0'};
13566 char config_file[MAX_BUF_SIZE] = {0};
13567
13568 if (!enable)
13569 return RETURN_ERR;
13570
13571 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
13572 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
13573
13574 if (strlen(output) == 0)
13575 *enable = FALSE;
13576 else if (strncmp(output, "1", 1) == 0)
13577 *enable = TRUE;
13578 else
13579 *enable = FALSE;
13580
13581 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
13582 return RETURN_OK;
13583}
13584
13585INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
13586{
13587 if (NULL == output_enable || radioIndex >=MAX_NUM_RADIOS)
13588 return RETURN_ERR;
13589 *output_enable=TRUE;
13590 return RETURN_OK;
13591}
13592
13593INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
13594{
13595 char cmd[128] = {0};
13596 char buf[128] = {0};
13597 char line[128] = {0};
13598 size_t len = 0;
13599 FILE *f = NULL;
13600 int index = 0;
13601 int exp = 0;
13602 int mantissa = 0;
13603 int duration = 0;
13604 int radio_index = 0;
13605 int max_radio_num = 0;
13606 uint twt_wake_interval = 0;
13607 int phyId = 0;
13608 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
13609
13610 wifi_getMaxRadioNumber(&max_radio_num);
13611
13612 radio_index = ap_index % max_radio_num;
13613
13614 phyId = radio_index_to_phy(radio_index);
13615 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", phyId);
13616 _syscmd(cmd, buf, sizeof(buf));
13617 *numSessionReturned = strtol(buf, NULL, 10) - 1;
13618 if (*numSessionReturned > maxNumberSessions)
13619 *numSessionReturned = maxNumberSessions;
13620 else if (*numSessionReturned < 1) {
13621 *numSessionReturned = 0;
13622 return RETURN_OK;
13623 }
13624
13625 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", phyId, *numSessionReturned);
13626 if ((f = popen(cmd, "r")) == NULL) {
13627 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
13628 return RETURN_ERR;
13629 }
13630
13631 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
13632 while((fgets(line, sizeof(line), f)) != NULL) {
13633 char *tmp = NULL;
13634 strcpy(buf, line);
13635 tmp = strtok(buf, " ");
13636 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
13637 tmp = strtok(NULL, " ");
13638 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
13639 tmp = strtok(NULL, " ");
13640 if (strstr(tmp, "t")) {
13641 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
13642 }
13643 if (strstr(tmp, "a")) {
13644 twtSessions[index].twtParameters.operation.announced = TRUE;
13645 }
13646 tmp = strtok(NULL, " ");
13647 exp = strtol(tmp, NULL, 10);
13648 tmp = strtok(NULL, " ");
13649 mantissa = strtol(tmp, NULL, 10);
13650 tmp = strtok(NULL, " ");
13651 duration = strtol(tmp, NULL, 10);
13652
13653 // only implicit supported
13654 twtSessions[index].twtParameters.operation.implicit = TRUE;
13655 // only individual agreement supported
13656 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
13657
13658 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
13659 twt_wake_interval = mantissa * (1 << exp);
13660 if (mantissa == 0 || twt_wake_interval/mantissa != (1 << exp)) {
13661 // Overflow handling
13662 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
13663 } else {
13664 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
13665 }
13666 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
13667 index++;
13668 }
13669
13670 pclose(f);
13671 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
13672 return RETURN_OK;
13673}