blob: 36e6b22c690d75e92d678c9cb9f7d2667ee96b98 [file] [log] [blame]
developer06a01d92022-09-07 16:32:39 +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*/
developerda1ed692022-09-13 13:59:20 +080037#define MTK_IMPL
developer06a01d92022-09-07 16:32:39 +080038#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 128
67#define MAX_CMD_SIZE 1024
68#define MAX_POSSIBLE_CHANNEL_STRING_BUF 512
69#define IF_NAME_SIZE 50
70#define CONFIG_PREFIX "/nvram/hostapd"
71#define ACL_PREFIX "/tmp/hostapd-acl"
developer10adcc12022-09-13 14:39:17 +080072#define DENY_PREFIX "/tmp/hostapd-deny"
developer06a01d92022-09-07 16:32:39 +080073//#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
74#define SOCK_PREFIX "/var/run/hostapd/wifi"
75#define VAP_STATUS_FILE "/tmp/vap-status"
developera3c68b92022-09-13 15:27:29 +080076#define ESSID_FILE "/tmp/essid"
developer454b9462022-09-13 15:29:16 +080077#define GUARD_INTERVAL_FILE "/tmp/guard-interval"
developera748dcf2022-09-13 15:56:48 +080078#define CHANNEL_STATS_FILE "/tmp/channel_stats"
developer9964b5b2022-09-13 15:59:34 +080079#define DFS_ENABLE_FILE "/nvram/dfs_enable.txt"
developerf5fef612022-09-20 19:38:26 +080080#define VLAN_FILE "/nvram/hostapd.vlan"
developer8d583982022-09-20 11:28:22 +080081#define PSK_FILE "/tmp/hostapd"
developer2de97692022-09-26 14:00:03 +080082#define CHAIN_MASK_FILE "/tmp/chain_mask"
developer54e6b9f2022-09-28 14:41:20 +080083#define AMSDU_FILE "/tmp/AMSDU"
developerf49437e2022-09-29 19:58:21 +080084#define MCS_FILE "/tmp/MCS"
developer454b9462022-09-13 15:29:16 +080085
developer06a01d92022-09-07 16:32:39 +080086#define DRIVER_2GHZ "ath9k"
87#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080088#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080089
90/*
91 MAX_APS - Number of all AP available in system
92 2x Home AP
93 2x Backhaul AP
94 2x Guest AP
95 2x Secure Onboard AP
96 2x Service AP
97
98*/
99#define MAX_APS 10
100#define NUMBER_OF_RADIOS 2
101
102#ifndef AP_PREFIX
103#define AP_PREFIX "wifi"
104#endif
105
106#ifndef RADIO_PREFIX
107#define RADIO_PREFIX "wlan"
108#endif
109
110#define MAX_BUF_SIZE 128
111#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800112#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800113
114//Uncomment to enable debug logs
115//#define WIFI_DEBUG
116
117#ifdef WIFI_DEBUG
118#define wifi_dbg_printf printf
119#define WIFI_ENTRY_EXIT_DEBUG printf
120#else
121#define wifi_dbg_printf(format, args...) printf("")
122#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
123#endif
124
125#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
126#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
127#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
128#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
129#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
130#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
131#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
132#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
133#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
134#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
135
136#define HOSTAPD_HT_CAPAB_20 "[SHORT-GI-20]"
137#define HOSTAPD_HT_CAPAB_40 "[SHORT-GI-20][SHORT-GI-40]"
developer3cc0f2e2022-09-15 18:25:39 +0800138#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800139
140#define BW_FNAME "/nvram/bw_file.txt"
141
142#define PS_MAX_TID 16
143
144static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
145 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
147 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
148 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
150 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
152 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
153 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
155 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
156 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
158 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
160 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
161};
162
163typedef unsigned long long u64;
164
165/* Enum to define WiFi Bands */
166typedef enum
167{
168 band_invalid = -1,
169 band_2_4 = 0,
170 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800171 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800172} wifi_band;
173
developerdb744382022-09-13 15:34:54 +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
developer06a01d92022-09-07 16:32:39 +0800183#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
203wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
204wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
205char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800206static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800207
208static wifi_secur_list map_security[] =
209{
210 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
212 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
218 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
219};
220
221wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
222{
223 wifi_secur_list *item;
224 int i;
225
226 for (item = list,i = 0;i < list_sz; item++, i++) {
227 if ((int)(item->key) == key) {
228 return item;
229 }
230 }
231
232 return NULL;
233}
234
235char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
236{
237 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
238
239 if (!item) {
240 return "";
241 }
242
243 return (char *)(item->data);
244}
245
246wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
247{
248 wifi_secur_list *item;
249 int i;
250
251 for (item = list,i = 0;i < list_sz; item++, i++) {
252 if (strcmp((char *)(item->data), str) == 0) {
253 return item;
254 }
255 }
256
257 return NULL;
258}
259#endif /* WIFI_HAL_VERSION_3 */
260
261#ifdef HAL_NETLINK_IMPL
262typedef struct {
263 int id;
264 struct nl_sock* socket;
265 struct nl_cb* cb;
266} Netlink;
267
268static int mac_addr_aton(unsigned char *mac_addr, char *arg)
269{
270 unsigned int mac_addr_int[6]={};
271 sscanf(arg, "%x:%x:%x:%x:%x:%x", mac_addr_int+0, mac_addr_int+1, mac_addr_int+2, mac_addr_int+3, mac_addr_int+4, mac_addr_int+5);
272 mac_addr[0] = mac_addr_int[0];
273 mac_addr[1] = mac_addr_int[1];
274 mac_addr[2] = mac_addr_int[2];
275 mac_addr[3] = mac_addr_int[3];
276 mac_addr[4] = mac_addr_int[4];
277 mac_addr[5] = mac_addr_int[5];
278 return 0;
279}
280
281static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
282{
283 unsigned int mac_addr_int[6]={};
284 mac_addr_int[0] = arg[0];
285 mac_addr_int[1] = arg[1];
286 mac_addr_int[2] = arg[2];
287 mac_addr_int[3] = arg[3];
288 mac_addr_int[4] = arg[4];
289 mac_addr_int[5] = arg[5];
290 snprintf(mac_addr, 20, "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr_int[0], mac_addr_int[1],mac_addr_int[2],mac_addr_int[3],mac_addr_int[4],mac_addr_int[5]);
291 return;
292}
293
294static int ieee80211_frequency_to_channel(int freq)
295{
296 if (freq == 2484)
297 return 14;
298 else if (freq < 2484)
299 return (freq - 2407) / 5;
300 else if (freq >= 4910 && freq <= 4980)
301 return (freq - 4000) / 5;
302 else if (freq <= 45000)
303 return (freq - 5000) / 5;
304 else if (freq >= 58320 && freq <= 64800)
305 return (freq - 56160) / 2160;
306 else
307 return 0;
308}
309
310static int initSock80211(Netlink* nl) {
311 nl->socket = nl_socket_alloc();
312 if (!nl->socket) {
313 fprintf(stderr, "Failing to allocate the sock\n");
314 return -ENOMEM;
315 }
316
317 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
318
319 if (genl_connect(nl->socket)) {
320 fprintf(stderr, "Failed to connect\n");
321 nl_close(nl->socket);
322 nl_socket_free(nl->socket);
323 return -ENOLINK;
324 }
325
326 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
327 if (nl->id< 0) {
328 fprintf(stderr, "interface not found.\n");
329 nl_close(nl->socket);
330 nl_socket_free(nl->socket);
331 return -ENOENT;
332 }
333
334 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
335 if ((!nl->cb)) {
336 fprintf(stderr, "Failed to allocate netlink callback.\n");
337 nl_close(nl->socket);
338 nl_socket_free(nl->socket);
339 return ENOMEM;
340 }
341
342 return nl->id;
343}
344
345static int nlfree(Netlink *nl)
346{
347 nl_cb_put(nl->cb);
348 nl_close(nl->socket);
349 nl_socket_free(nl->socket);
350 return 0;
351}
352
353static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
354 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
355 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
356 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
357};
358
359static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
360};
361
362static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
363};
364
365typedef struct _wifi_channelStats_loc {
366 INT array_size;
367 INT ch_number;
368 BOOL ch_in_pool;
369 INT ch_noise;
370 BOOL ch_radar_noise;
371 INT ch_max_80211_rssi;
372 INT ch_non_80211_noise;
373 INT ch_utilization;
374 ULLONG ch_utilization_total;
375 ULLONG ch_utilization_busy;
376 ULLONG ch_utilization_busy_tx;
377 ULLONG ch_utilization_busy_rx;
378 ULLONG ch_utilization_busy_self;
379 ULLONG ch_utilization_busy_ext;
380} wifi_channelStats_t_loc;
381
382typedef struct wifi_device_info {
383 INT wifi_devIndex;
384 UCHAR wifi_devMacAddress[6];
385 CHAR wifi_devIPAddress[64];
386 BOOL wifi_devAssociatedDeviceAuthentiationState;
387 INT wifi_devSignalStrength;
388 INT wifi_devTxRate;
389 INT wifi_devRxRate;
390} wifi_device_info_t;
391
392#endif
393
394//For 5g Alias Interfaces
395static BOOL priv_flag = TRUE;
396static BOOL pub_flag = TRUE;
397static BOOL Radio_flag = TRUE;
398//wifi_setApBeaconRate(1, beaconRate);
399
developer1e5aa162022-09-13 16:06:24 +0800400BOOL multiple_set = FALSE;
401
developer06a01d92022-09-07 16:32:39 +0800402struct params
403{
404 char * name;
405 char * value;
406};
407
408static int _syscmd(char *cmd, char *retBuf, int retBufSize)
409{
410 FILE *f;
411 char *ptr = retBuf;
412 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
413
414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
415 if((f = popen(cmd, "r")) == NULL) {
416 fprintf(stderr,"\npopen %s error\n", cmd);
417 return RETURN_ERR;
418 }
419
420 while(!feof(f))
421 {
422 *ptr = 0;
423 if(bufSize>=128) {
424 bufbytes=128;
425 } else {
426 bufbytes=bufSize-1;
427 }
428
429 fgets(ptr,bufbytes,f);
430 readbytes=strlen(ptr);
431
432 if(!readbytes)
433 break;
434
435 bufSize-=readbytes;
436 ptr += readbytes;
437 }
438 cmd_ret = pclose(f);
439 retBuf[retBufSize-1]=0;
440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
441
442 return cmd_ret >> 8;
443}
444
developerc707e972022-09-13 15:38:02 +0800445wifi_band wifi_index_to_band(int apIndex)
446{
447 char cmd[128] = {0};
448 char buf[64] = {0};
449 int freq = 0;
450 wifi_band band = band_invalid;
451
452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
453 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
454 _syscmd(cmd, buf, sizeof(buf));
455 freq = strtol(buf, NULL, 10);
456 if (freq > 2401 && freq < 2495)
457 band = band_2_4;
458 else if (freq > 5160 && freq < 5915)
459 band = band_5;
460 else if (freq > 5955 && freq < 7125)
461 band = band_6;
462
463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
464 return band;
465}
466
developer06a01d92022-09-07 16:32:39 +0800467static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
468{
469 char cmd[MAX_CMD_SIZE]={'\0'};
470 char buf[MAX_BUF_SIZE]={'\0'};
471 int ret = 0;
472
473 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
474 ret = _syscmd(cmd, buf, sizeof(buf));
475 if ((ret != 0) && (strlen(buf) == 0))
476 return -1;
477 snprintf(output, output_size, "%s", buf);
478
479 return 0;
480}
481
482static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
483{
484 char cmd[MAX_CMD_SIZE]={'\0'};
485 char buf[MAX_BUF_SIZE]={'\0'};
486
487 for(int i=0;i<item_count;i++)
488 {
489 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
490 if (strlen(buf) == 0) //Insert
491 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
492 else //Update
493 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
494 if(_syscmd(cmd, buf, sizeof(buf)))
495 return -1;
496 }
497
498 return 0;
499}
500
501static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
502{
developer1e5aa162022-09-13 16:06:24 +0800503 if (multiple_set == TRUE)
504 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800505 char cmd[MAX_CMD_SIZE]="", output[32]="";
506 FILE *fp;
507 int i;
508 //NOTE RELOAD should be done in ApplySSIDSettings
509
510 for(i=0; i<item_count; i++, list++)
511 {
512 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
513 if((fp = popen(cmd, "r"))==NULL)
514 {
515 perror("popen failed");
516 return -1;
517 }
518 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
519 {
520 pclose(fp);
521 perror("fgets failed");
522 return -1;
523 }
524 pclose(fp);
525 }
526 return 0;
527}
528
529static int wifi_reloadAp(int apIndex)
530{
developer1e5aa162022-09-13 16:06:24 +0800531 if (multiple_set == TRUE)
532 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800533 char cmd[MAX_CMD_SIZE]="";
534 char buf[MAX_BUF_SIZE]="";
535
536 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
537 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
538 return RETURN_ERR;
539
540 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
541 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
542 return RETURN_ERR;
543
544 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
545 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
546 return RETURN_ERR;
547
548 return RETURN_OK;
549}
550
551
552//For Getting Current Interface Name from corresponding hostapd configuration
553void GetInterfaceName(char *interface_name, char *conf_file)
554{
555 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
556 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
557 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
558}
559
560INT File_Reading(CHAR *file, char *Value)
561{
562 FILE *fp = NULL;
563 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
564 int count = 0;
565
566 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
567 fp = popen(file,"r");
568 if(fp == NULL)
569 return RETURN_ERR;
570
571 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
572 {
573 for(count=0;buf[count]!='\n';count++)
574 copy_buf[count]=buf[count];
575 copy_buf[count]='\0';
576 }
577 strcpy(Value,copy_buf);
578 pclose(fp);
579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
580
581 return RETURN_OK;
582}
583
584void wifi_RestartHostapd_2G()
585{
586 int Public2GApIndex = 4;
587
588 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
589 wifi_setApEnable(Public2GApIndex, FALSE);
590 wifi_setApEnable(Public2GApIndex, TRUE);
591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
592}
593
594void wifi_RestartHostapd_5G()
595{
596 int Public5GApIndex = 5;
597
598 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
599 wifi_setApEnable(Public5GApIndex, FALSE);
600 wifi_setApEnable(Public5GApIndex, TRUE);
601 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
602}
603
604void wifi_RestartPrivateWifi_2G()
605{
606 int PrivateApIndex = 0;
607
608 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
609 wifi_setApEnable(PrivateApIndex, FALSE);
610 wifi_setApEnable(PrivateApIndex, TRUE);
611 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
612}
613
614void wifi_RestartPrivateWifi_5G()
615{
616 int Private5GApIndex = 1;
617
618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
619 wifi_setApEnable(Private5GApIndex, FALSE);
620 wifi_setApEnable(Private5GApIndex, TRUE);
621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
622}
623
624static int writeBandWidth(int radioIndex,char *bw_value)
625{
626 char buf[MAX_BUF_SIZE];
627 char cmd[MAX_CMD_SIZE];
628
629 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
630 if(_syscmd(cmd, buf, sizeof(buf)))
631 {
632 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
633 _syscmd(cmd, buf, sizeof(buf));
634 return RETURN_OK;
635 }
636
637 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
638 _syscmd(cmd,buf,sizeof(buf));
639 return RETURN_OK;
640}
641
642static int readBandWidth(int radioIndex,char *bw_value)
643{
644 char buf[MAX_BUF_SIZE];
645 char cmd[MAX_CMD_SIZE];
646 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
647 _syscmd(cmd,buf,sizeof(buf));
648 if(NULL!=strstr(buf,"20MHz"))
649 {
650 strcpy(bw_value,"20MHz");
651 }
652 else if(NULL!=strstr(buf,"40MHz"))
653 {
654 strcpy(bw_value,"40MHz");
655 }
656 else if(NULL!=strstr(buf,"80MHz"))
657 {
658 strcpy(bw_value,"80MHz");
659 }
660 else
661 {
662 return RETURN_ERR;
663 }
664 return RETURN_OK;
665}
666
developer39a5efb2022-09-13 16:09:06 +0800667INT wifi_getMaxRadioNumber(INT *max_radio_num)
668{
669 char cmd[64] = {0};
670 char buf[4] = {0};
671
672 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
673
674 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
675 _syscmd(cmd, buf, sizeof(buf));
676 *max_radio_num = strtoul(buf, NULL, 10);
677
678 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
679
680 return RETURN_OK;
681}
682
developer5f222492022-09-13 15:21:52 +0800683// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800684INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
685{
developer5f222492022-09-13 15:21:52 +0800686 struct params params={'\0'};
687 char config_file[MAX_BUF_SIZE] = {0};
688 char buf[MAX_BUF_SIZE] = {'\0'};
689
690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
691 if (strlen (beaconRate) < 5)
692 return RETURN_ERR;
693 // Copy the numeric value
694 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
695 buf[strlen(beaconRate) - 4] = '\0';
696
697 params.name = "beacon_rate";
698 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
699 if (strncmp(buf, "5.5", 3) == 0) {
700 snprintf(buf, sizeof(buf), "55");
701 params.value = buf;
702 } else {
703 strcat(buf, "0");
704 params.value = buf;
705 }
706
707 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
708 wifi_hostapdWrite(config_file, &params, 1);
709 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
710 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
711
712 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800713}
714
715INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
716{
developer5f222492022-09-13 15:21:52 +0800717 char config_file[MAX_BUF_SIZE] = {'\0'};
718 char temp_output[MAX_BUF_SIZE] = {'\0'};
719 char buf[MAX_BUF_SIZE] = {'\0'};
720 float rate = 0;
721
722 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
723 if (NULL == beaconRate)
724 return RETURN_ERR;
725
726 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
727 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
728 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
729 if(strlen(buf) > 0) {
730 rate = atof(buf)/10;
731 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
732 } else {
733 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
734 }
735 strncpy(beaconRate, temp_output, sizeof(temp_output));
736 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
737
738 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800739}
740
741INT wifi_setLED(INT radioIndex, BOOL enable)
742{
743 return 0;
744}
745INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
746{
747 return RETURN_OK;
748}
749/**********************************************************************************
750 *
751 * Wifi Subsystem level function prototypes
752 *
753**********************************************************************************/
754//---------------------------------------------------------------------------------------------------
755//Wifi system api
756//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
757INT wifi_getHalVersion(CHAR *output_string) //RDKB
758{
759 if(!output_string)
760 return RETURN_ERR;
761 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
762
763 return RETURN_OK;
764}
765
766
767/* wifi_factoryReset() function */
768/**
769* @description Clears internal variables to implement a factory reset of the Wi-Fi
770* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
771*
772* @param None
773*
774* @return The status of the operation.
775* @retval RETURN_OK if successful.
776* @retval RETURN_ERR if any error is detected
777*
778* @execution Synchronous
779* @sideeffect None
780*
781* @note This function must not suspend and must not invoke any blocking system
782* calls. It should probably just send a message to a driver event handler task.
783*
784*/
785INT wifi_factoryReset()
786{
787 char cmd[128];
788
789 /*delete running hostapd conf files*/
790 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
791 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
792 system(cmd);
793 system("systemctl restart hostapd.service");
794
795 return RETURN_OK;
796}
797
798/* wifi_factoryResetRadios() function */
799/**
800* @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.
801*
802* @param None
803* @return The status of the operation
804* @retval RETURN_OK if successful
805* @retval RETURN_ERR if any error is detected
806*
807* @execution Synchronous
808*
809* @sideeffect None
810*
811* @note This function must not suspend and must not invoke any blocking system
812* calls. It should probably just send a message to a driver event handler task.
813*
814*/
815INT wifi_factoryResetRadios()
816{
817 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
818 return RETURN_OK;
819
820 return RETURN_ERR;
821}
822
823
824/* wifi_factoryResetRadio() function */
825/**
826* @description Restore selected radio parameters without touching access point parameters
827*
828* @param radioIndex - Index of Wi-Fi Radio channel
829*
830* @return The status of the operation.
831* @retval RETURN_OK if successful.
832* @retval RETURN_ERR if any error is detected
833*
834* @execution Synchronous.
835* @sideeffect None.
836*
837* @note This function must not suspend and must not invoke any blocking system
838* calls. It should probably just send a message to a driver event handler task.
839*
840*/
841INT wifi_factoryResetRadio(int radioIndex) //RDKB
842{
developer5ff7f5f2022-09-13 15:12:16 +0800843 system("systemctl stop hostapd.service");
844
developer06a01d92022-09-07 16:32:39 +0800845 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
846 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800847 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800848 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800849 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800850 else
851 return RETURN_ERR;
852
developer5ff7f5f2022-09-13 15:12:16 +0800853 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800854 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
855 return RETURN_OK;
856}
857
858/* wifi_initRadio() function */
859/**
860* Description: This function call initializes the specified radio.
861* Implementation specifics may dictate the functionality since
862* different hardware implementations may have different initilization requirements.
863* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
864*
865* @return The status of the operation.
866* @retval RETURN_OK if successful.
867* @retval RETURN_ERR if any error is detected
868*
869* @execution Synchronous.
870* @sideeffect None.
871*
872* @note This function must not suspend and must not invoke any blocking system
873* calls. It should probably just send a message to a driver event handler task.
874*
875*/
876INT wifi_initRadio(INT radioIndex)
877{
878 //TODO: Initializes the wifi subsystem (for specified radio)
879 return RETURN_OK;
880}
881void macfilter_init()
882{
883 char count[4]={'\0'};
884 char buf[253]={'\0'};
885 char tmp[19]={'\0'};
886 int dev_count,block,mac_entry=0;
887 char res[4]={'\0'};
888 char acl_file_path[64] = {'\0'};
889 FILE *fp = NULL;
890 int index=0;
891 char iface[10]={'\0'};
892 char config_file[MAX_BUF_SIZE] = {0};
893
894
895 sprintf(acl_file_path,"/tmp/mac_filter.sh");
896
897 fp=fopen(acl_file_path,"w+");
898 sprintf(buf,"#!/bin/sh \n");
899 fprintf(fp,"%s\n",buf);
900
901 system("chmod 0777 /tmp/mac_filter.sh");
902
903 for(index=0;index<=1;index++)
904 {
905 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
906 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
907 sprintf(buf,"syscfg get %dcountfilter",index);
908 _syscmd(buf,count,sizeof(count));
909 mac_entry=atoi(count);
910
911 sprintf(buf,"syscfg get %dblockall",index);
912 _syscmd(buf,res,sizeof(res));
913 block = atoi(res);
914
915 //Allow only those macs mentioned in ACL
916 if(block==1)
917 {
918 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
919 fprintf(fp,"%s\n",buf);
920 for(dev_count=1;dev_count<=mac_entry;dev_count++)
921 {
922 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
923 _syscmd(buf,tmp,sizeof(tmp));
924 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
925 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
926 fprintf(fp,"%s\n",buf);
927 }
928 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
929 fprintf(fp,"%s\n",buf);
930 }
931
932 //Block all the macs mentioned in ACL
933 else if(block==2)
934 {
935 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
936 fprintf(fp,"%s\n",buf);
937
938 for(dev_count=1;dev_count<=mac_entry;dev_count++)
939 {
940 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
941 _syscmd(buf,tmp,sizeof(tmp));
942 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
943 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
944 fprintf(fp,"%s\n",buf);
945 }
946 }
947 }
948 fclose(fp);
949}
950
951// Initializes the wifi subsystem (all radios)
952INT wifi_init() //RDKB
953{
954 char interface[MAX_BUF_SIZE]={'\0'};
955 char bridge_name[MAX_BUF_SIZE]={'\0'};
956 INT len=0;
957
958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
959 //Not intitializing macfilter for Turris-Omnia Platform for now
960 //macfilter_init();
961
962 system("/usr/sbin/iw reg set US");
963 system("systemctl start hostapd.service");
964 sleep(2);//sleep to wait for hostapd to start
965
966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
967
968 return RETURN_OK;
969}
970
971/* wifi_reset() function */
972/**
973* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
974* Implementation specifics may dictate what is actualy reset since
975* different hardware implementations may have different requirements.
976* Parameters : None
977*
978* @return The status of the operation.
979* @retval RETURN_OK if successful.
980* @retval RETURN_ERR if any error is detected
981*
982* @execution Synchronous.
983* @sideeffect None.
984*
985* @note This function must not suspend and must not invoke any blocking system
986* calls. It should probably just send a message to a driver event handler task.
987*
988*/
989INT wifi_reset()
990{
991 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800992 system("systemctl stop hostapd.service");
993 sleep(2);
994 system("systemctl start hostapd.service");
995 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800996 return RETURN_OK;
997}
998
999/* wifi_down() function */
1000/**
1001* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1002* Implementation specifics may dictate some functionality since
1003* different hardware implementations may have different requirements.
1004*
1005* @param None
1006*
1007* @return The status of the operation
1008* @retval RETURN_OK if successful
1009* @retval RETURN_ERR if any error is detected
1010*
1011* @execution Synchronous
1012* @sideeffect None
1013*
1014* @note This function must not suspend and must not invoke any blocking system
1015* calls. It should probably just send a message to a driver event handler task.
1016*
1017*/
1018INT wifi_down()
1019{
1020 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001021 system("systemctl stop hostapd.service");
1022 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001023 return RETURN_OK;
1024}
1025
1026
1027/* wifi_createInitialConfigFiles() function */
1028/**
1029* @description This function creates wifi configuration files. The format
1030* and content of these files are implementation dependent. This function call is
1031* used to trigger this task if necessary. Some implementations may not need this
1032* function. If an implementation does not need to create config files the function call can
1033* do nothing and return RETURN_OK.
1034*
1035* @param None
1036*
1037* @return The status of the operation
1038* @retval RETURN_OK if successful
1039* @retval RETURN_ERR if any error is detected
1040*
1041* @execution Synchronous
1042* @sideeffect None
1043*
1044* @note This function must not suspend and must not invoke any blocking system
1045* calls. It should probably just send a message to a driver event handler task.
1046*
1047*/
1048INT wifi_createInitialConfigFiles()
1049{
1050 //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)
1051 return RETURN_OK;
1052}
1053
1054// outputs the country code to a max 64 character string
1055INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1056{
developer7543b3b2022-09-13 13:47:17 +08001057 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1058 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001059 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001060
1061 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1062 _syscmd(cmd, buf, sizeof(buf));
1063 if(strlen(buf) > 0)
1064 snprintf(output_string, 64, "%s", buf);
1065 else
1066 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001067
1068 return RETURN_OK;
1069}
1070
1071INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1072{
1073 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001074 char str[MAX_BUF_SIZE]={'\0'};
1075 char cmd[MAX_CMD_SIZE]={'\0'};
1076 struct params params;
1077 char config_file[MAX_BUF_SIZE] = {0};
1078
1079 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1080 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1081 return RETURN_ERR;
1082
1083 params.name = "country_code";
1084 params.value = CountryCode;
1085 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1086 int ret = wifi_hostapdWrite(config_file, &params, 1);
1087 if (ret) {
1088 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1089 ,__func__, ret);
1090 }
1091
1092 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1093 if (ret) {
1094 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1095 ,__func__, ret);
1096 }
1097 wifi_reloadAp(radioIndex);
1098 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1099
developer06a01d92022-09-07 16:32:39 +08001100 return RETURN_OK;
1101}
1102
developera748dcf2022-09-13 15:56:48 +08001103INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1104{
1105 char channel_util_file[64] = {0};
1106 char cmd[128] = {0};
1107 char buf[128] = {0};
1108 char line[128] = {0};
1109 char *param = NULL, *value = NULL;
1110 int read = 0;
1111 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1112 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1113 size_t len = 0;
1114 FILE *f = NULL;
1115
1116 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1117
1118 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1119 _syscmd(cmd, buf, sizeof(buf));
1120 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1121
1122 memset(cmd, 0, sizeof(cmd));
1123 memset(buf, 0, sizeof(buf));
1124 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1125 if ((f = popen(cmd, "r")) == NULL) {
1126 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1127 return RETURN_ERR;
1128 }
1129
1130 read = getline(&line, &len, f);
1131 while (read != -1) {
1132 param = strtok(line, ":\t");
1133 value = strtok(NULL, " ");
1134 if(strstr(param, "frequency") != NULL) {
1135 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1136 }
1137 if(strstr(param, "noise") != NULL) {
1138 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1139 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1140 }
1141 if(strstr(param, "channel active time") != NULL) {
1142 ActiveTime = strtol(value, NULL, 10);
1143 }
1144 if(strstr(param, "channel busy time") != NULL) {
1145 BusyTime = strtol(value, NULL, 10);
1146 }
1147 if(strstr(param, "channel transmit time") != NULL) {
1148 TransmitTime = strtol(value, NULL, 10);
1149 }
1150 read = getline(&line, &len, f);
1151 }
1152 pclose(f);
1153
1154 // The file should store the last active, busy and transmit time
1155 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1156 f = fopen(channel_util_file, "r");
1157 if (f != NULL) {
1158 read = getline(&line, &len, f);
1159 preActiveTime = strtol(line, NULL, 10);
1160 read = getline(&line, &len, f);
1161 preBusyTime = strtol(line, NULL, 10);
1162 read = getline(&line, &len, f);
1163 preTransmitTime = strtol(line, NULL, 10);
1164 fclose(f);
1165 }
1166
1167 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1168 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1169
1170 f = fopen(channel_util_file, "w");
1171 if (f != NULL) {
1172 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1173 fclose(f);
1174 }
1175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1176 return RETURN_OK;
1177}
1178
developer06a01d92022-09-07 16:32:39 +08001179/**********************************************************************************
1180 *
1181 * Wifi radio level function prototypes
1182 *
1183**********************************************************************************/
1184
1185//Get the total number of radios in this wifi subsystem
1186INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1187{
1188 if (NULL == output)
1189 return RETURN_ERR;
1190 *output = 2;
1191
1192 return RETURN_OK;
1193}
1194
1195//Get the total number of SSID entries in this wifi subsystem
1196INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1197{
1198 if (NULL == output)
1199 return RETURN_ERR;
1200 *output = MAX_APS;
1201
1202 return RETURN_OK;
1203}
1204
1205//Get the Radio enable config parameter
1206INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1207{
1208 char interface_path[MAX_CMD_SIZE] = {0};
1209 FILE *fp = NULL;
1210
1211 if (NULL == output_bool)
1212 return RETURN_ERR;
1213
1214 *output_bool = FALSE;
1215 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1216 return RETURN_ERR;
1217
1218 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1219 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001220 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001221 {
developercf48e482022-09-13 14:49:50 +08001222 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001223 }
1224 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001225 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1226 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1227 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001228
developercf48e482022-09-13 14:49:50 +08001229 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1230 *output_bool = TRUE;
1231 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001232 return RETURN_OK;
1233}
1234
1235INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1236{
1237 char cmd[MAX_CMD_SIZE] = {0};
1238 char buf[MAX_CMD_SIZE] = {0};
1239 int apIndex, ret;
1240 FILE *fp = NULL;
1241
1242 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1243 if(enable==FALSE)
1244 {
1245 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1246 {
1247 //Detaching %s%d from hostapd daemon
1248 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1249 _syscmd(cmd, buf, sizeof(buf));
1250 if(strncmp(buf, "OK", 2))
1251 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1252 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1253 _syscmd(cmd, buf, sizeof(buf));
1254 }
developer456aa3e2022-09-13 14:27:36 +08001255 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001256 _syscmd(cmd, buf, sizeof(buf));
1257 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001258 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001259 }
1260 else
1261 {
developer456aa3e2022-09-13 14:27:36 +08001262 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001263 _syscmd(cmd, buf, sizeof(buf));
1264 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001265 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001266 sleep(1);
1267 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1268 {
1269 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1270 fp = fopen(cmd, "r");
1271 if(!fp)
1272 {
1273 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1274 _syscmd(cmd, buf, sizeof(buf));
1275 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1276 _syscmd(cmd, buf, sizeof(buf));
1277 }
1278 if(fp)
1279 fclose(fp);
1280 }
1281 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1282 {
1283 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1284 ret = _syscmd(cmd, buf, sizeof(buf));
1285 if ( ret == RETURN_ERR)
1286 {
1287 fprintf(stderr, "VAP interface creation failed\n");
1288 continue;
1289 }
1290 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1291 _syscmd(cmd, buf, sizeof(buf));
1292 if(*buf == '1')
1293 {
1294 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1295 radioIndex, apIndex);
1296 _syscmd(cmd, buf, sizeof(buf));
1297 if(strncmp(buf, "OK", 2))
1298 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1299 }
1300 }
1301 }
1302
1303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1304 return RETURN_OK;
1305}
1306
1307//Get the Radio enable status
1308INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1309{
1310 if (NULL == output_bool)
1311 return RETURN_ERR;
1312
1313 return wifi_getRadioEnable(radioIndex, output_bool);
1314}
1315
1316//Get the Radio Interface name from platform, eg "wlan0"
1317INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1318{
1319 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1320 return RETURN_ERR;
1321 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1322
1323 return RETURN_OK;
1324}
1325
1326//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1327//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.
1328INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1329{
developerbcc556a2022-09-22 20:02:45 +08001330 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1331 // For max bit rate, we should always choose the best MCS
1332 char mode[64] = {0};
1333 char channel_bandwidth_str[16] = {0};
1334 char *tmp = NULL;
1335 UINT mode_map = 0;
1336 UINT num_subcarrier = 0;
1337 UINT code_bits = 0;
1338 float code_rate = 0; // use max code rate
1339 int NSS = 0;
1340 UINT Symbol_duration = 0;
1341 UINT GI_duration = 0;
1342 wifi_band band = band_invalid;
1343 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1344 BOOL enable = FALSE;
1345 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001346
1347 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1348 if (NULL == output_string)
1349 return RETURN_ERR;
1350
developerbcc556a2022-09-22 20:02:45 +08001351 wifi_getRadioEnable(radioIndex, &enable);
1352 if (enable == FALSE) {
1353 snprintf(output_string, 64, "0 Mb/s");
1354 return RETURN_OK;
1355 }
1356
1357 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1358 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1359 return RETURN_ERR;
1360 }
1361
1362 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1363 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1364 return RETURN_ERR;
1365 }
1366
1367 if (gi == wifi_guard_interval_3200)
1368 GI_duration = 32;
1369 else if (gi == wifi_guard_interval_1600)
1370 GI_duration = 16;
1371 else if (gi == wifi_guard_interval_800)
1372 GI_duration = 8;
1373 else // auto, 400
1374 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001375
developerbcc556a2022-09-22 20:02:45 +08001376 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1377 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1378 return RETURN_ERR;
1379 }
1380
1381 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1382 strcpy(channel_bandwidth_str, "160");
1383
1384 if (mode_map & WIFI_MODE_AX) {
1385 if (strstr(channel_bandwidth_str, "160") != NULL)
1386 num_subcarrier = 1960;
1387 else if (strstr(channel_bandwidth_str, "80") != NULL)
1388 num_subcarrier = 980;
1389 else if (strstr(channel_bandwidth_str, "40") != NULL)
1390 num_subcarrier = 468;
1391 else if (strstr(channel_bandwidth_str, "20") != NULL)
1392 num_subcarrier = 234;
1393 code_bits = 10;
1394 code_rate = (float)5/6;
1395 Symbol_duration = 128;
1396 } else if (mode_map & WIFI_MODE_AC) {
1397 if (strstr(channel_bandwidth_str, "160") != NULL)
1398 num_subcarrier = 468;
1399 else if (strstr(channel_bandwidth_str, "80") != NULL)
1400 num_subcarrier = 234;
1401 else if (strstr(channel_bandwidth_str, "40") != NULL)
1402 num_subcarrier = 108;
1403 else if (strstr(channel_bandwidth_str, "20") != NULL)
1404 num_subcarrier = 52;
1405 code_bits = 8;
1406 code_rate = (float)5/6;
1407 Symbol_duration = 32;
1408 } else if (mode_map & WIFI_MODE_N) {
1409 if (strstr(channel_bandwidth_str, "160") != NULL)
1410 num_subcarrier = 468;
1411 else if (strstr(channel_bandwidth_str, "80") != NULL)
1412 num_subcarrier = 234;
1413 else if (strstr(channel_bandwidth_str, "40") != NULL)
1414 num_subcarrier = 108;
1415 else if (strstr(channel_bandwidth_str, "20") != NULL)
1416 num_subcarrier = 52;
1417 code_bits = 6;
1418 code_rate = (float)3/4;
1419 Symbol_duration = 32;
1420 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1421 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1422 snprintf(output_string, 64, "65 Mb/s");
1423 return RETURN_OK;
1424 } else {
1425 snprintf(output_string, 64, "0 Mb/s");
1426 return RETURN_OK;
1427 }
developer06a01d92022-09-07 16:32:39 +08001428
developerbcc556a2022-09-22 20:02:45 +08001429 // Spatial streams
1430 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1431 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1432 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001433 }
developerbcc556a2022-09-22 20:02:45 +08001434
1435 // multiple 10 is to align duration unit (0.1 us)
1436 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1437 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1438
developer06a01d92022-09-07 16:32:39 +08001439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1440
1441 return RETURN_OK;
1442}
1443#if 0
1444INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1445{
1446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1447 char cmd[64];
1448 char buf[1024];
1449 int apIndex;
1450
1451 if (NULL == output_string)
1452 return RETURN_ERR;
1453
1454 apIndex=(radioIndex==0)?0:1;
1455
1456 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1457 _syscmd(cmd,buf, sizeof(buf));
1458
1459 snprintf(output_string, 64, "%s", buf);
1460 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1461 return RETURN_OK;
1462}
1463#endif
1464
1465
1466//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1467//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.
1468INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1469{
developer963da0c2022-09-13 15:58:27 +08001470 wifi_band band = band_invalid;
1471
developer06a01d92022-09-07 16:32:39 +08001472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1473 if (NULL == output_string)
1474 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001475
1476 band = wifi_index_to_band(radioIndex);
1477
1478 memset(output_string, 0, 10);
1479 if (band == band_2_4)
1480 strcpy(output_string, "2.4GHz");
1481 else if (band == band_5)
1482 strcpy(output_string, "5GHz");
1483 else if (band == band_6)
1484 strcpy(output_string, "6GHz");
1485 else
1486 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001487 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1488
1489 return RETURN_OK;
1490#if 0
1491 char buf[MAX_BUF_SIZE]={'\0'};
1492 char str[MAX_BUF_SIZE]={'\0'};
1493 char cmd[MAX_CMD_SIZE]={'\0'};
1494 char *ch=NULL;
1495 char *ch2=NULL;
1496
1497 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1498 if (NULL == output_string)
1499 return RETURN_ERR;
1500
1501
1502 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1503
1504 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1505 {
1506 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1507 return RETURN_ERR;
1508 }
1509 ch=strchr(buf,'\n');
1510 *ch='\0';
1511 ch=strchr(buf,'=');
1512 if(ch==NULL)
1513 return RETURN_ERR;
1514
1515
1516 ch++;
1517
1518 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1519 strcpy(buf,"0");
1520 if(strlen(ch) == 1)
1521 ch=strcat(buf,ch);
1522
1523
1524 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1525
1526 if(_syscmd(cmd,str,64) == RETURN_ERR)
1527 {
1528 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1529 return RETURN_ERR;
1530 }
1531
1532
1533 ch2=strchr(str,'\n');
1534 //replace \n with \0
1535 *ch2='\0';
1536 ch2=strchr(str,'=');
1537 if(ch2==NULL)
1538 {
1539 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1540 return RETURN_ERR;
1541 }
1542 else
1543 wifi_dbg_printf("%s",ch2+1);
1544
1545
1546 ch2++;
1547
1548
1549 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1550
1551 memset(buf,'\0',sizeof(buf));
1552 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1553 {
1554 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1555 return RETURN_ERR;
1556 }
1557 if (strstr(buf,"2.4") != NULL )
1558 strcpy(output_string,"2.4GHz");
1559 else if(strstr(buf,"5.") != NULL )
1560 strcpy(output_string,"5GHz");
1561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1562
1563 return RETURN_OK;
1564#endif
1565}
1566
1567//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1568//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.
1569INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1570{
1571 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1572 if (NULL == output_string)
1573 return RETURN_ERR;
1574 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1575 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1576
1577 return RETURN_OK;
1578#if 0
1579 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1580 char buf[MAX_BUF_SIZE]={'\0'};
1581 char str[MAX_BUF_SIZE]={'\0'};
1582 char cmd[MAX_CMD_SIZE]={'\0'};
1583 char *ch=NULL;
1584 char *ch2=NULL;
1585 char ch1[5]="0";
1586
1587 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1588
1589 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1590 {
1591 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1592 return RETURN_ERR;
1593 }
1594
1595 ch=strchr(buf,'\n');
1596 *ch='\0';
1597 ch=strchr(buf,'=');
1598 if(ch==NULL)
1599 return RETURN_ERR;
1600 ch++;
1601
1602 if(strlen(ch)==1)
1603 {
1604 strcat(ch1,ch);
1605
1606 }
1607 else
1608 {
1609 strcpy(ch1,ch);
1610 }
1611
1612
1613
1614 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1615 if(_syscmd(cmd,str,64) == RETURN_ERR)
1616 {
1617 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1618 return RETURN_ERR;
1619 }
1620
1621
1622 ch2=strchr(str,'\n');
1623 //replace \n with \0
1624 *ch2='\0';
1625 ch2=strchr(str,'=');
1626 if(ch2==NULL)
1627 {
1628 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1629 return RETURN_ERR;
1630 }
1631 else
1632 wifi_dbg_printf("%s",ch2+1);
1633 ch2++;
1634
1635
1636 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1637 memset(buf,'\0',sizeof(buf));
1638 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1639 {
1640 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1641 return RETURN_ERR;
1642 }
1643
1644
1645 if(strstr(buf,"2.4")!=NULL)
1646 {
1647 strcpy(output_string,"2.4GHz");
1648 }
1649 if(strstr(buf,"5.")!=NULL)
1650 {
1651 strcpy(output_string,"5GHz");
1652 }
1653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1654 return RETURN_OK;
1655#endif
1656}
1657
1658//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1659//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.
1660INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1661{
developer963da0c2022-09-13 15:58:27 +08001662 char cmd[128]={0};
1663 char buf[128]={0};
1664 char temp_output[128] = {0};
1665 wifi_band band;
1666
1667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001668 if (NULL == output_string)
1669 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001670
1671 band = wifi_index_to_band(radioIndex);
1672 if (band == band_2_4) {
1673 strcat(temp_output, "b,g,");
1674 } else if (band == band_5) {
1675 strcat(temp_output, "a,");
1676 }
1677
1678 // ht capabilities
1679 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep '[^PHY|MAC|VHT].Capabilities' | head -n 1 | cut -d ':' -f2 | sed 's/^.//' | tr -d '\\n'", radioIndex);
1680 _syscmd(cmd, buf, sizeof(buf));
1681 if (strncmp(buf, "0x00", 4) != 0) {
1682 strcat(temp_output, "n,");
1683 }
developer06a01d92022-09-07 16:32:39 +08001684
developer963da0c2022-09-13 15:58:27 +08001685 // vht capabilities
1686 if (band == band_5) {
1687 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1688 _syscmd(cmd, buf, sizeof(buf));
1689 if (strncmp(buf, "0x00000000", 10) != 0) {
1690 strcat(temp_output, "ac,");
1691 }
1692 }
1693
1694 // he capabilities
1695 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'", radioIndex);
1696 _syscmd(cmd, buf, sizeof(buf));
1697 if (strncmp (buf, "0x0000", 6) != 0) {
1698 strcat(temp_output, "ax,");
1699 }
1700
1701 // Remove the last comma
1702 if (strlen(temp_output) != 0)
1703 temp_output[strlen(temp_output)-1] = '\0';
1704 strncpy(output_string, temp_output, strlen(temp_output));
1705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001706 return RETURN_OK;
1707}
1708
1709//Get the radio operating mode, and pure mode flag. eg: "ac"
1710//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.
1711INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1712{
1713 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1714 if (NULL == output_string)
1715 return RETURN_ERR;
1716
1717 if (radioIndex == 0) {
1718 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1719 *gOnly = FALSE;
1720 *nOnly = TRUE;
1721 *acOnly = FALSE;
1722 } else {
1723 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1724 *gOnly = FALSE;
1725 *nOnly = FALSE;
1726 *acOnly = FALSE;
1727 }
1728 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1729
1730 return RETURN_OK;
1731#if 0
1732 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1733 char buf[64] = {0};
1734 char config_file[MAX_BUF_SIZE] = {0};
1735
1736 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1737 return RETURN_ERR;
1738
1739 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1740 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1741
1742 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1743 if (strlen(buf) == 0)
1744 {
1745 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1746 return RETURN_ERR;
1747 }
1748 if(strcmp(buf,"g")==0)
1749 {
1750 wifi_dbg_printf("\nG\n");
1751 *gOnly=TRUE;
1752 *nOnly=FALSE;
1753 *acOnly=FALSE;
1754 }
1755 else if(strcmp(buf,"n")==0)
1756 {
1757 wifi_dbg_printf("\nN\n");
1758 *gOnly=FALSE;
1759 *nOnly=TRUE;
1760 *acOnly=FALSE;
1761 }
1762 else if(strcmp(buf,"ac")==0)
1763 {
1764 wifi_dbg_printf("\nac\n");
1765 *gOnly=FALSE;
1766 *nOnly=FALSE;
1767 *acOnly=TRUE;
1768 }
1769 /* hostapd-5G.conf has "a" as hw_mode */
1770 else if(strcmp(buf,"a")==0)
1771 {
1772 wifi_dbg_printf("\na\n");
1773 *gOnly=FALSE;
1774 *nOnly=FALSE;
1775 *acOnly=FALSE;
1776 }
1777 else
1778 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1779
1780 //for a,n mode
1781 if(radioIndex == 1)
1782 {
1783 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1784 if(strcmp(buf,"1")==0)
1785 {
1786 strncpy(output_string, "n", 1);
1787 *nOnly=FALSE;
1788 }
1789 }
1790
1791 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1792 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1793 return RETURN_OK;
1794#endif
1795}
1796
developerdb744382022-09-13 15:34:54 +08001797INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1798{
1799 char cmd[128] = {0};
1800 char buf[64] = {0};
1801 char config_file[64] = {0};
1802 wifi_band band;
1803
1804 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1805 if(NULL == output_string || NULL == pureMode)
1806 return RETURN_ERR;
1807
1808 // grep all of the ieee80211 protocol config set to 1
1809 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1810 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1811 _syscmd(cmd, buf, sizeof(buf));
1812
1813 band = wifi_index_to_band(radioIndex);
1814 // puremode is a bit map
1815 *pureMode = 0;
1816 if (band == band_2_4) {
1817 strcat(output_string, "b,g");
1818 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1819 if (strstr(buf, "n") != NULL) {
1820 strcat(output_string, ",n");
1821 *pureMode |= WIFI_MODE_N;
1822 }
1823 if (strstr(buf, "ax") != NULL) {
1824 strcat(output_string, ",ax");
1825 *pureMode |= WIFI_MODE_AX;
1826 }
1827 } else if (band == band_5) {
1828 strcat(output_string, "a");
1829 *pureMode |= WIFI_MODE_A;
1830 if (strstr(buf, "n") != NULL) {
1831 strcat(output_string, ",n");
1832 *pureMode |= WIFI_MODE_N;
1833 }
1834 if (strstr(buf, "ac") != NULL) {
1835 strcat(output_string, ",ac");
1836 *pureMode |= WIFI_MODE_AC;
1837 }
1838 if (strstr(buf, "ax") != NULL) {
1839 strcat(output_string, ",ax");
1840 *pureMode |= WIFI_MODE_AX;
1841 }
1842 } else if (band == band_6) {
1843 if (strstr(buf, "ax") != NULL) {
1844 strcat(output_string, "ax");
1845 *pureMode |= WIFI_MODE_AX;
1846 }
1847 }
1848
1849 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1850 return RETURN_OK;
1851}
1852
1853// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001854INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1855{
1856 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1857 if (strcmp (channelMode,"11A") == 0)
1858 {
1859 writeBandWidth(radioIndex,"20MHz");
1860 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1861 printf("\nChannel Mode is 802.11a (5GHz)\n");
1862 }
1863 else if (strcmp (channelMode,"11NAHT20") == 0)
1864 {
1865 writeBandWidth(radioIndex,"20MHz");
1866 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1867 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1868 }
1869 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1870 {
1871 writeBandWidth(radioIndex,"40MHz");
1872 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1873 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1874 }
1875 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1876 {
1877 writeBandWidth(radioIndex,"40MHz");
1878 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1879 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1880 }
1881 else if (strcmp (channelMode,"11ACVHT20") == 0)
1882 {
1883 writeBandWidth(radioIndex,"20MHz");
1884 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1885 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1886 }
1887 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1888 {
1889 writeBandWidth(radioIndex,"40MHz");
1890 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1891 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1892 }
1893 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1894 {
1895 writeBandWidth(radioIndex,"40MHz");
1896 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1897 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1898 }
1899 else if (strcmp (channelMode,"11ACVHT80") == 0)
1900 {
1901 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1902 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1903 }
1904 else if (strcmp (channelMode,"11ACVHT160") == 0)
1905 {
1906 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1907 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1908 }
1909 else if (strcmp (channelMode,"11B") == 0)
1910 {
1911 writeBandWidth(radioIndex,"20MHz");
1912 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1913 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1914 }
1915 else if (strcmp (channelMode,"11G") == 0)
1916 {
1917 writeBandWidth(radioIndex,"20MHz");
1918 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1919 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1920 }
1921 else if (strcmp (channelMode,"11NGHT20") == 0)
1922 {
1923 writeBandWidth(radioIndex,"20MHz");
1924 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1925 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1926 }
1927 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1928 {
1929 writeBandWidth(radioIndex,"40MHz");
1930 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1931 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1932 }
1933 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1934 {
1935 writeBandWidth(radioIndex,"40MHz");
1936 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1937 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1938 }
1939 else
1940 {
1941 return RETURN_ERR;
1942 }
1943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1944
1945 return RETURN_OK;
1946}
1947
developerdb744382022-09-13 15:34:54 +08001948// Set the radio operating mode, and pure mode flag.
1949INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1950{
1951 int num_hostapd_support_mode = 3; // n, ac, ax
1952 struct params list[num_hostapd_support_mode];
1953 char config_file[64] = {0};
1954 char bandwidth[16] = {0};
1955 int mode_check_bit = 1 << 3; // n mode
1956 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1957
1958 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1959 // Set radio mode
1960 list[0].name = "ieee80211n";
1961 list[1].name = "ieee80211ac";
1962 list[2].name = "ieee80211ax";
1963 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1964
1965 // check the bit map from n to ax, and set hostapd config
1966 if (mode & WIFI_MODE_N)
1967 list[0].value = "1";
1968 else
1969 list[0].value = "0";
1970 if (mode & WIFI_MODE_AC)
1971 list[1].value = "1";
1972 else
1973 list[1].value = "0";
1974 if (mode & WIFI_MODE_AX)
1975 list[2].value = "1";
1976 else
1977 list[2].value = "0";
1978 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1979
1980 if (channelMode == NULL || strlen(channelMode) == 0)
1981 return RETURN_OK;
1982 // Set bandwidth
1983 if (strstr(channelMode, "40") != NULL)
1984 strcpy(bandwidth, "40MHz");
1985 else if (strstr(channelMode, "80") != NULL)
1986 strcpy(bandwidth, "80MHz");
1987 else if (strstr(channelMode, "160") != NULL)
1988 strcpy(bandwidth, "160MHz");
1989 else // 11A, 11B, 11G....
1990 strcpy(bandwidth, "20MHz");
1991
1992 writeBandWidth(radioIndex, bandwidth);
1993 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1994
1995 wifi_reloadAp(radioIndex);
1996 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1997
1998 return RETURN_OK;
1999}
2000
developer06a01d92022-09-07 16:32:39 +08002001//Get the list of supported channel. eg: "1-11"
2002//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.
2003INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2004{
developer6318ed52022-09-13 15:17:58 +08002005 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002006 if (NULL == output_string)
2007 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002008 char cmd[256] = {0};
2009 char buf[128] = {0};
2010 BOOL dfs_enable = false;
2011 // Parse possible channel number and separate them with commas.
2012 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2013 if (dfs_enable)
2014 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2015 else
2016 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | grep -v 'radar' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2017
2018 _syscmd(cmd,buf,sizeof(buf));
2019 strncpy(output_string, buf, sizeof(buf));
2020
2021 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2022 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002023#if 0
2024 char IFName[50] ={0};
2025 char buf[MAX_BUF_SIZE] = {0};
2026 char cmd[MAX_CMD_SIZE] = {0};
2027 int count = 0;
2028 if (NULL == output_string)
2029 return RETURN_ERR;
2030
2031 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2032 if(radioIndex == 0)
2033 {
2034 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2035 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2036 }
2037 else if(radioIndex == 1)
2038 {
2039 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2040 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep '5\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2041 }
2042 _syscmd(cmd, buf, sizeof(buf));
2043 if(strlen(buf) > 0)
2044 strcpy(output_string,buf);
2045 else
2046 strcpy(output_string,"0");
2047#endif
2048 return RETURN_OK;
2049}
2050
2051//Get the list for used channel. eg: "1,6,9,11"
2052//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.
2053INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2054{
2055 if (NULL == output_string)
2056 return RETURN_ERR;
2057 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2058#if 0
2059 char IFName[50] ={0};
2060 char buf[MAX_BUF_SIZE] = {0};
2061 char cmd[MAX_CMD_SIZE] = {0};
2062 if (NULL == output_string)
2063 return RETURN_ERR;
2064
2065 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2066 if(radioIndex == 0)
2067 {
2068 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2069 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 2'\\.' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 | sed 's/^0//g' | tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2070 }
2071 else if(radioIndex == 1)
2072 {
2073 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2074 sprintf(cmd,"%s %s %s","iwlist",IFName,"channel | grep Channel | grep -v 'Current Frequency' | grep 5'\\.[1-9]' | cut -d ':' -f1 | tr -s ' ' | cut -d ' ' -f3 |tr '\\n' ' ' | sed 's/ /,/g' | sed 's/,$/ /g'");
2075 }
2076 _syscmd(cmd,buf, sizeof(buf));
2077 if(strlen(buf) > 0)
2078 strcpy(output_string,buf);
2079 else
2080 strcpy(output_string,"0");
2081#endif
2082 return RETURN_OK;
2083}
2084
2085//Get the running channel number
2086INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2087{
developerda1ed692022-09-13 13:59:20 +08002088#ifdef MTK_IMPL
2089 if(!wifi_getApChannel(radioIndex, output_ulong))
2090 return RETURN_OK;
2091 else
2092 return RETURN_ERR;
2093#else
developer06a01d92022-09-07 16:32:39 +08002094 char cmd[1024] = {0}, buf[5] = {0};
2095
2096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2097 if (NULL == output_ulong)
2098 return RETURN_ERR;
2099
2100 snprintf(cmd, sizeof(cmd),
2101 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2102 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2103 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2104 _syscmd(cmd, buf, sizeof(buf));
2105
2106 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2107 if (*output_ulong <= 0) {
2108 *output_ulong = 0;
2109 return RETURN_ERR;
2110 }
2111
2112 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2113 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002114#endif
developer06a01d92022-09-07 16:32:39 +08002115}
2116
2117
2118INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2119{
2120 char cmd[1024] = {0}, buf[5] = {0};
2121 char interface_name[50] = {0};
2122
2123 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2124 if (NULL == output_ulong)
2125 return RETURN_ERR;
2126
2127 wifi_getApName(apIndex,interface_name);
2128 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2129 _syscmd(cmd,buf,sizeof(buf));
2130 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2131 if (*output_ulong == 0) {
2132 return RETURN_ERR;
2133 }
2134
2135 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2136 return RETURN_OK;
2137}
2138
2139//Storing the previous channel value
2140INT wifi_storeprevchanval(INT radioIndex)
2141{
2142 char buf[256] = {0};
2143 char output[4]={'\0'};
2144 char config_file[MAX_BUF_SIZE] = {0};
2145 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2146 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2147 if(radioIndex == 0)
2148 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2149 else if(radioIndex == 1)
2150 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2151 system(buf);
2152 Radio_flag = FALSE;
2153 return RETURN_OK;
2154}
2155
2156//Set the running channel number
2157INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2158{
2159 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2160 struct params params={'\0'};
2161 char str_channel[4]={'\0'};
2162 struct params list;
2163 char config_file[MAX_BUF_SIZE] = {0};
2164
2165 list.name = "channel";
2166
2167 if(Radio_flag == TRUE)
2168 wifi_storeprevchanval(radioIndex); //for autochannel
2169
2170 if(radioIndex == 0)
2171 {
2172 switch(channel)
2173 {
2174 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2175 sprintf(str_channel,"%ld", channel);
2176 list.value = str_channel;
2177 break;
2178 default:
2179 return RETURN_ERR;
2180 }
2181 }
2182 else if(radioIndex == 1)
2183 {
2184 switch(channel)
2185 {
2186 case 36: case 40: case 44: case 48: case 52: case 56: case 60: case 64: case 144: case 149: case 153: case 157: case 161: case 165: case 169:
2187 sprintf(str_channel,"%ld", channel);
2188 list.value = str_channel;
2189 break;
2190 default:
2191 return RETURN_ERR;
2192 }
2193 }
2194
2195 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2196 {
2197 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2198 wifi_hostapdWrite(config_file,&list,1);
2199 }
2200
2201 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2202 return RETURN_OK;
2203 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2204 }
2205
2206INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2207{
2208 struct params list;
2209 char str_idx[16];
2210 char config_file[MAX_BUF_SIZE];
2211
2212 list.name = "vht_oper_centr_freq_seg0_idx";
2213 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2214 list.value = str_idx;
2215
2216 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2217 {
2218 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2219 wifi_hostapdWrite(config_file, &list, 1);
2220 }
2221
2222 return RETURN_OK;
2223}
2224
2225//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2226//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2227INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2228{
2229 //Set to wifi config only. Wait for wifi reset to apply.
2230 char buf[256] = {0};
2231 char str_channel[256] = {0};
2232 int count = 0;
2233 ULONG Value = 0;
2234 FILE *fp = NULL;
2235 if(enable == TRUE)
2236 {
2237 if(radioIndex == 0)
2238 {
2239 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2240 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2241 }
2242 else if(radioIndex == 1)
2243 {
2244 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2245 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2246 }
2247 if(fp == NULL) //first time boot-up
2248 {
2249 if(radioIndex == 0)
2250 Value = 6;
2251 else if(radioIndex == 1)
2252 Value = 36;
2253 }
2254 else
2255 {
2256 if(fgets(buf,sizeof(buf),fp) != NULL)
2257 {
2258 for(count = 0;buf[count]!='\n';count++)
2259 str_channel[count] = buf[count];
2260 str_channel[count] = '\0';
2261 Value = atol(str_channel);
2262 printf("%sValue is %ld \n",__FUNCTION__,Value);
2263 pclose(fp);
2264 }
2265 }
2266 Radio_flag = FALSE;//for storing previous channel value
2267 wifi_setRadioChannel(radioIndex,Value);
2268 return RETURN_OK;
2269 }
2270 return RETURN_ERR;
2271}
2272
2273INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2274{
2275 if (NULL == output_bool)
2276 return RETURN_ERR;
2277 *output_bool=FALSE;
2278 return RETURN_OK;
2279}
2280
2281INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2282{
2283 if (NULL == output_bool)
2284 return RETURN_ERR;
2285 *output_bool=FALSE;
2286 return RETURN_OK;
2287}
2288
2289INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2290{
2291 //Set to wifi config only. Wait for wifi reset to apply.
2292 return RETURN_OK;
2293}
2294
2295INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2296{
2297 return RETURN_OK;
2298}
2299
2300INT wifi_factoryResetAP(int apIndex)
2301{
2302 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2303 //factory reset is not done for now on Turris
2304 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2305 return RETURN_OK;
2306}
2307
2308//To set Band Steering AP group
2309//To-do
2310INT wifi_setBandSteeringApGroup(char *ApGroup)
2311{
2312 return RETURN_OK;
2313}
2314
developer1e5aa162022-09-13 16:06:24 +08002315INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2316{
2317 char config_file[128] = {'\0'};
2318 char buf[128] = {'\0'};
2319
2320 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2321 if (dtimInterval == NULL)
2322 return RETURN_ERR;
2323
2324 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2325 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2326
2327 if (strlen(buf) == 0) {
2328 *dtimInterval = 2;
2329 } else {
2330 *dtimInterval = strtoul(buf, NULL, 10);
2331 }
2332
2333 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2334 return RETURN_OK;
2335}
2336
developer06a01d92022-09-07 16:32:39 +08002337INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2338{
developer5f222492022-09-13 15:21:52 +08002339 struct params params={0};
2340 char config_file[MAX_BUF_SIZE] = {'\0'};
2341 char buf[MAX_BUF_SIZE] = {'\0'};
2342
2343 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2344 if (dtimInterval < 1 || dtimInterval > 255) {
2345 return RETURN_ERR;
2346 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2347 }
2348
2349 params.name = "dtim_period";
2350 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2351 params.value = buf;
2352
2353 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2354 wifi_hostapdWrite(config_file, &params, 1);
2355 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2356
2357 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2358 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002359}
2360
2361//Check if the driver support the Dfs
2362INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2363{
2364 if (NULL == output_bool)
2365 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002366 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002367 return RETURN_OK;
2368}
2369
2370//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.
2371//The value of this parameter is a comma seperated list of channel number
2372INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2373{
2374 if (NULL == output_pool)
2375 return RETURN_ERR;
2376 if (radioIndex==1)
2377 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2378 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2379
2380 return RETURN_OK;
2381}
2382
2383INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2384{
2385 //Set to wifi config. And apply instantly.
2386 return RETURN_OK;
2387}
2388
2389INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2390{
2391 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2392 return RETURN_ERR;
2393 *output_interval_seconds=1800;
2394 *output_dwell_milliseconds=40;
2395
2396 return RETURN_OK;
2397}
2398
2399INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2400{
2401 //Set to wifi config. And apply instantly.
2402 return RETURN_OK;
2403}
2404
2405//Get the Dfs enable status
2406INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2407{
developer9964b5b2022-09-13 15:59:34 +08002408 char buf[16] = {0};
2409 FILE *f = NULL;
2410 wifi_band band;
2411
2412 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2413
2414 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002415 if (NULL == output_bool)
2416 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002417
2418 band = wifi_index_to_band(radioIndex);
2419 if (band != band_5)
2420 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002421
developer9964b5b2022-09-13 15:59:34 +08002422 f = fopen(DFS_ENABLE_FILE, "r");
2423 if (f != NULL) {
2424 fgets(buf, 2, f);
2425 if (strncmp(buf, "0", 0) == 0)
2426 *output_bool = FALSE;
2427 fclose(f);
2428 }
2429 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002430 return RETURN_OK;
2431}
2432
2433//Set the Dfs enable status
2434INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2435{
developer9964b5b2022-09-13 15:59:34 +08002436 char buf[128] = {0};
2437 char config_file[128] = {0};
2438 FILE *f = NULL;
2439 struct params params={0};
2440 wifi_band band;
2441
2442 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2443
2444 band = wifi_index_to_band(radioIndex);
2445 if (band != band_5)
2446 return RETURN_OK;
2447
2448 f = fopen(DFS_ENABLE_FILE, "w");
2449 if (f == NULL)
2450 return RETURN_ERR;
2451 fprintf(f, "%d", enable);
2452 fclose(f);
2453
2454 params.name = "acs_exclude_dfs";
2455 sprintf(buf, "%d", enable?"1":"0");
2456 params.value = buf;
2457 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2458 wifi_hostapdWrite(config_file, &params, 1);
2459 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2460
2461 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2462
2463 wifi_reloadAp(radioIndex);
2464
2465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002466}
2467
2468//Check if the driver support the AutoChannelRefreshPeriod
2469INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2470{
2471 if (NULL == output_bool)
2472 return RETURN_ERR;
2473 *output_bool=FALSE; //not support
2474
2475 return RETURN_OK;
2476}
2477
2478//Get the ACS refresh period in seconds
2479INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2480{
2481 if (NULL == output_ulong)
2482 return RETURN_ERR;
2483 *output_ulong=300;
2484
2485 return RETURN_OK;
2486}
2487
2488//Set the ACS refresh period in seconds
2489INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2490{
2491 return RETURN_ERR;
2492}
2493
2494//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2495//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.
2496INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2497{
developer70490032022-09-13 15:45:20 +08002498 char cmd[128] = {0}, buf[64] = {0};
2499 char interface_name[64] = {0};
2500 int ret = 0, len=0;
2501 BOOL radio_enable = FALSE;
2502
2503 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2504
developer06a01d92022-09-07 16:32:39 +08002505 if (NULL == output_string)
2506 return RETURN_ERR;
2507
developer70490032022-09-13 15:45:20 +08002508 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2509 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002510
developer70490032022-09-13 15:45:20 +08002511 if (radio_enable != TRUE)
2512 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002513
developer70490032022-09-13 15:45:20 +08002514 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002515 ret = _syscmd(cmd, buf, sizeof(buf));
2516 len = strlen(buf);
2517 if((ret != 0) || (len == 0))
2518 {
2519 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2520 return RETURN_ERR;
2521 }
2522
2523 buf[len-1] = '\0';
2524 snprintf(output_string, 64, "%sMHz", buf);
2525 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2526
2527#if 0
2528 //TODO: revisit below implementation
2529 char output_buf[8]={0};
2530 char bw_value[10];
2531 char config_file[MAX_BUF_SIZE] = {0};
2532
2533 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2534 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2535 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2536 readBandWidth(radioIndex,bw_value);
2537
2538 if(strstr (output_buf,"0") != NULL )
2539 {
2540 strcpy(output_string,bw_value);
2541 }
2542 else if (strstr (output_buf,"1") != NULL)
2543 {
2544 strcpy(output_string,"80MHz");
2545 }
2546 else if (strstr (output_buf,"2") != NULL)
2547 {
2548 strcpy(output_string,"160MHz");
2549 }
2550 else if (strstr (output_buf,"3") != NULL)
2551 {
2552 strcpy(output_string,"80+80");
2553 }
2554 else
2555 {
2556 strcpy(output_string,"Auto");
2557 }
2558 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2559#endif
2560
2561 return RETURN_OK;
2562}
2563
2564//Set the Operating Channel Bandwidth.
2565INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181 //AP only
2566{
2567 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2568 char config_file[MAX_BUF_SIZE];
2569 struct params params[4];
2570 struct params *pptr = params;
2571
2572 if(NULL == output_string)
2573 return RETURN_ERR;
2574
2575 pptr->name = "vht_oper_chwidth";
2576 if(strcmp(output_string,"20MHz") == 0) // This piece of code only support for wifi hal api's validation
2577 pptr->value="0";
2578 else if(strcmp(output_string,"40MHz") == 0)
2579 pptr->value="0";
2580 else if(strcmp(output_string,"80MHz") == 0)
2581 pptr->value="1";
2582 else if(strcmp(output_string,"160MHz") == 0)
2583 pptr->value="2";
2584 else if(strcmp(output_string,"80+80") == 0)
2585 pptr->value="3";
2586 else
2587 {
2588 printf("Invalid Bandwidth \n");
2589 return RETURN_ERR;
2590 }
2591
2592 pptr++; // added vht_oper_chwidth
2593
2594 if(radioIndex == 1)
2595 {
2596 pptr->name= "ieee80211n";
2597 if(strcmp(output_string,"20MHz") == 0)
2598 pptr->value="0";
2599 else if(strcmp(output_string,"40MHz") == 0)
2600 pptr->value="1";
2601 else if(strcmp(output_string,"80MHz") == 0)
2602 pptr->value="1";
2603 else
2604 pptr->value="0";
2605
2606 pptr++; // added ieee80211n
2607
2608 pptr->name="ieee80211ac";
2609 if(strcmp(output_string,"80MHz") == 0)
2610 pptr->value="1";
2611 else
2612 pptr->value="0";
2613 pptr++;
2614 }
2615
2616 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2617 {
2618 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2619 wifi_hostapdWrite(config_file, params, (pptr - params));
2620 }
2621
2622 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2623 return RETURN_OK;
2624}
2625
2626//Getting current radio extension channel
2627INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2628{
2629 CHAR buf[150] = {0};
2630 CHAR cmd[150] = {0};
2631 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2632 _syscmd(cmd, buf, sizeof(buf));
2633 if(NULL != strstr(buf,"HT40+"))
2634 strcpy(Value,"AboveControlChannel");
2635 else if(NULL != strstr(buf,"HT40-"))
2636 strcpy(Value,"BelowControlChannel");
2637 return RETURN_OK;
2638}
2639
2640//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2641//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.
2642INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2643{
2644 if (NULL == output_string)
2645 return RETURN_ERR;
2646
2647 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2648#if 0
2649 CHAR Value[100] = {0};
2650 if (NULL == output_string)
2651 return RETURN_ERR;
2652 if(radioIndex == 0)
2653 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2654 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2655 {
2656 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2657 if(strcmp(Value,"40MHz") == 0)
2658 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2659 else
2660 strcpy(Value,"Auto");
2661 }
2662 strcpy(output_string,Value);
2663#endif
2664
2665 return RETURN_OK;
2666}
2667
2668//Set the extension channel.
2669INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2670{
2671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2672 struct params params={'\0'};
2673 char config_file[MAX_BUF_SIZE] = {0};
2674 char ext_channel[127]={'\0'};
2675
2676 params.name = "ht_capab";
2677
2678 if(radioIndex == 0)
2679 {
2680 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002681 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002682 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002683 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002684 else
developer3cc0f2e2022-09-15 18:25:39 +08002685 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002686 }
2687 else if(radioIndex == 1)
2688 {
2689 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002690 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002691 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002692 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002693 else
developer3cc0f2e2022-09-15 18:25:39 +08002694 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002695 }
2696
2697 params.value = ext_channel;
2698 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2699 {
2700 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2701 wifi_hostapdWrite(config_file, &params, 1);
2702 }
2703
2704 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2705 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2706 return RETURN_OK;
2707}
2708
2709//Get the guard interval value. eg "400nsec" or "800nsec"
2710//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.
2711INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2712{
developer454b9462022-09-13 15:29:16 +08002713 wifi_guard_interval_t GI;
2714
2715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2716
2717 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002718 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002719
2720 if (GI == wifi_guard_interval_400)
2721 strcpy(output_string, "400nsec");
2722 else if (GI == wifi_guard_interval_800)
2723 strcpy(output_string, "800nsec");
2724 else if (GI == wifi_guard_interval_1600)
2725 strcpy(output_string, "1600nsec");
2726 else if (GI == wifi_guard_interval_3200)
2727 strcpy(output_string, "3200nsec");
2728 else
2729 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002730
developer454b9462022-09-13 15:29:16 +08002731 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002732 return RETURN_OK;
2733}
2734
2735//Set the guard interval value.
2736INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2737{
developer454b9462022-09-13 15:29:16 +08002738 wifi_guard_interval_t GI;
2739 int ret = 0;
2740
2741 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2742
2743 if (strcmp(string, "400nsec") == 0)
2744 GI = wifi_guard_interval_400;
2745 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2746 GI = wifi_guard_interval_800;
2747 else if (strcmp(string , "1600nsec") == 0)
2748 GI = wifi_guard_interval_1600;
2749 else if (strcmp(string , "3200nsec") == 0)
2750 GI = wifi_guard_interval_3200;
2751
2752 ret = wifi_setGuardInterval(radioIndex, GI);
2753
2754 if (ret == RETURN_ERR) {
2755 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2756 return RETURN_ERR;
2757 }
2758
2759 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2760 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002761}
2762
2763//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2764INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2765{
developerf49437e2022-09-29 19:58:21 +08002766 char buf[32]={0};
2767 char mcs_file[64] = {0};
2768 char cmd[64] = {0};
2769 int mode_bitmap = 0;
2770
2771 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2772 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002773 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002774 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2775
2776 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2777 _syscmd(cmd, buf, sizeof(buf));
2778 if (strlen(buf) > 0)
2779 *output_int = strtol(buf, NULL, 10);
2780 else {
2781 // output the max MCS for the current radio mode
2782 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2783 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2784 return RETURN_ERR;
2785 }
2786 if (mode_bitmap & WIFI_MODE_AX) {
2787 *output_int = 11;
2788 } else if (mode_bitmap & WIFI_MODE_AC) {
2789 *output_int = 9;
2790 } else if (mode_bitmap & WIFI_MODE_N) {
2791 *output_int = 7;
2792 }
2793 }
2794 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002795
2796 return RETURN_OK;
2797}
2798
2799//Set the Modulation Coding Scheme index
2800INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2801{
developerf49437e2022-09-29 19:58:21 +08002802 // 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).
2803 char config_file[64] = {0};
2804 char set_value[16] = {0};
2805 char mcs_file[32] = {0};
2806 wifi_band band = band_invalid;
2807 struct params set_config = {0};
2808 FILE *f = NULL;
2809
2810 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2811
2812 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2813
2814 if (MCS > 11 || MCS < 0) {
2815 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2816 return RETURN_ERR;
2817 }
2818
2819 if (MCS <= 7)
2820 strcpy(set_value, "0");
2821 else if (MCS <= 9)
2822 strcpy(set_value, "1");
2823 else
2824 strcpy(set_value, "2");
2825
2826 set_config.name = "he_basic_mcs_nss_set";
2827 set_config.value = set_value;
2828
2829 wifi_hostapdWrite(config_file, &set_config, 1);
2830 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2831
2832 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2833 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2834 f = fopen(mcs_file, "w");
2835 if (f == NULL) {
2836 fprintf(stderr, "%s: fopen failed\n", __func__);
2837 return RETURN_ERR;
2838 }
2839 fprintf(f, "%d", MCS);
2840 fclose(f);
2841
2842 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2843 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002844}
2845
2846//Get supported Transmit Power list, eg : "0,25,50,75,100"
2847//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.
2848INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2849{
2850 if (NULL == output_list)
2851 return RETURN_ERR;
2852 snprintf(output_list, 64,"0,25,50,75,100");
2853 return RETURN_OK;
2854}
2855
developera5005b62022-09-13 15:43:35 +08002856//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002857//The transmite power level is in units of full power for this radio.
2858INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2859{
2860 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002861 char buf[16]={0};
2862 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002863
developera5005b62022-09-13 15:43:35 +08002864 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002865 return RETURN_ERR;
2866
developera5005b62022-09-13 15:43:35 +08002867 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002868 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002869
developera5005b62022-09-13 15:43:35 +08002870 *output_ulong = strtol(buf, NULL, 10);
2871
2872 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002873 return RETURN_OK;
2874}
2875
2876//Set Transmit Power
2877//The transmite power level is in units of full power for this radio.
2878INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2879{
developera5005b62022-09-13 15:43:35 +08002880 char *support;
developer06a01d92022-09-07 16:32:39 +08002881 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002882 char buf[128]={0};
2883 char txpower_str[64] = {0};
2884 int txpower = 0;
2885 int maximum_tx = 0;
2886
2887 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002888
developera5005b62022-09-13 15:43:35 +08002889 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002890 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002891 maximum_tx = strtol(buf, NULL, 10);
2892
2893 // Get the Tx power supported list and check that is the input in the list
2894 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2895 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2896 support = strtok(buf, ",");
2897 while(true)
2898 {
2899 if(support == NULL) { // input not in the list
2900 wifi_dbg_printf("Input value is invalid.\n");
2901 return RETURN_ERR;
2902 }
2903 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2904 break;
2905 }
2906 support = strtok(NULL, ",");
2907 }
2908 txpower = TransmitPower*maximum_tx/100;
2909 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2910 _syscmd(cmd, buf, sizeof(buf));
2911 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002912
2913 return RETURN_OK;
2914}
2915
2916//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2917INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2918{
2919 if (NULL == Supported)
2920 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002921 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002922
2923 return RETURN_OK;
2924}
2925
2926//Get 80211h feature enable
2927INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2928{
developer3885fec2022-09-13 15:13:47 +08002929 char buf[64]={'\0'};
2930 char config_file[64] = {'\0'};
2931
2932 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2933 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002934 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002935
2936 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2937 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002938
developer3885fec2022-09-13 15:13:47 +08002939 if (strncmp(buf, "1", 1) == 0)
2940 *enable = TRUE;
2941 else
2942 *enable = FALSE;
2943
2944 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002945 return RETURN_OK;
2946}
2947
2948//Set 80211h feature enable
2949INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2950{
developer3885fec2022-09-13 15:13:47 +08002951 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2952 struct params params={'\0'};
2953 char config_file[MAX_BUF_SIZE] = {0};
2954
2955 params.name = "ieee80211h";
2956
2957 if (enable) {
2958 params.value = "1";
2959 } else {
2960 params.value = "0";
2961 }
2962
2963 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2964 wifi_hostapdWrite(config_file, &params, 1);
2965
2966 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2967 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2968 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002969}
2970
2971//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.
2972INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2973{
2974 if (NULL == output)
2975 return RETURN_ERR;
2976 *output=100;
2977
2978 return RETURN_OK;
2979}
2980
2981//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.
2982INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2983{
2984 if (NULL == output)
2985 return RETURN_ERR;
2986 *output = -99;
2987
2988 return RETURN_OK;
2989}
2990
2991INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2992{
2993 return RETURN_ERR;
2994}
2995
2996
2997//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2998INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2999{
developer5f222492022-09-13 15:21:52 +08003000 char cmd[MAX_BUF_SIZE]={'\0'};
3001 char buf[MAX_CMD_SIZE]={'\0'};
3002
3003 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3004 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003005 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003006
3007 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3008 _syscmd(cmd, buf, sizeof(buf));
3009 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003010
developer5f222492022-09-13 15:21:52 +08003011 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003012 return RETURN_OK;
3013}
3014
3015INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3016{
developer5f222492022-09-13 15:21:52 +08003017 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3018 struct params params={'\0'};
3019 char buf[MAX_BUF_SIZE] = {'\0'};
3020 char config_file[MAX_BUF_SIZE] = {'\0'};
3021
3022 params.name = "beacon_int";
3023 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3024 params.value = buf;
3025
3026 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3027 wifi_hostapdWrite(config_file, &params, 1);
3028
3029 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3030 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3031 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003032}
3033
3034//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.
3035INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3036{
developer06a01d92022-09-07 16:32:39 +08003037 //TODO: need to revisit below implementation
3038 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003039 char temp_output[128] = {0};
3040 char temp_TransmitRates[64] = {0};
3041 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003042
3043 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3044 if (NULL == output)
3045 return RETURN_ERR;
3046 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003047 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3048
3049 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3050 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3051 } else {
3052 temp = strtok(temp_TransmitRates," ");
3053 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003054 {
developere9d0abd2022-09-13 15:40:57 +08003055 // Convert 100 kbps to Mbps
3056 temp[strlen(temp)-1]=0;
3057 if((temp[0]=='5') && (temp[1]=='\0'))
3058 {
3059 temp="5.5";
3060 }
3061 strcat(temp_output,temp);
3062 temp = strtok(NULL," ");
3063 if(temp!=NULL)
3064 {
3065 strcat(temp_output,",");
3066 }
developer06a01d92022-09-07 16:32:39 +08003067 }
developere9d0abd2022-09-13 15:40:57 +08003068 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003069 }
developer06a01d92022-09-07 16:32:39 +08003070 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003071 return RETURN_OK;
3072}
3073
3074INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3075{
3076 char *temp;
3077 char temp1[128];
3078 char temp_output[128];
3079 char temp_TransmitRates[128];
3080 char set[128];
3081 char sub_set[128];
3082 int set_count=0,subset_count=0;
3083 int set_index=0,subset_index=0;
3084 char *token;
3085 int flag=0, i=0;
3086 struct params params={'\0'};
3087 char config_file[MAX_BUF_SIZE] = {0};
3088
3089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3090 if(NULL == TransmitRates)
3091 return RETURN_ERR;
3092 strcpy(sub_set,TransmitRates);
3093
3094 //Allow only supported Data transmit rate to be set
3095 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3096 token = strtok(sub_set,",");
3097 while( token != NULL ) /* split the basic rate to be set, by comma */
3098 {
3099 sub_set[subset_count]=atoi(token);
3100 subset_count++;
3101 token=strtok(NULL,",");
3102 }
3103 token=strtok(set,",");
3104 while(token!=NULL) /* split the supported rate by comma */
3105 {
3106 set[set_count]=atoi(token);
3107 set_count++;
3108 token=strtok(NULL,",");
3109 }
3110 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3111 {
3112 for(set_index=0;set_index < set_count;set_index++)
3113 {
3114 flag=0;
3115 if(sub_set[subset_index]==set[set_index])
3116 break;
3117 else
3118 flag=1; /* No match found */
3119 }
3120 if(flag==1)
3121 return RETURN_ERR; //If value not found return Error
3122 }
3123 strcpy(temp_TransmitRates,TransmitRates);
3124
3125 for(i=0;i<strlen(temp_TransmitRates);i++)
3126 {
3127 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3128 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3129 {
3130 continue;
3131 }
3132 else
3133 {
3134 return RETURN_ERR;
3135 }
3136 }
3137 strcpy(temp_output,"");
3138 temp = strtok(temp_TransmitRates,",");
3139 while(temp!=NULL)
3140 {
3141 strcpy(temp1,temp);
3142 if(radioIndex==1)
3143 {
3144 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3145 {
3146 return RETURN_ERR;
3147 }
3148 }
3149
3150 if(strcmp(temp,"5.5")==0)
3151 {
3152 strcpy(temp1,"55");
3153 }
3154 else
3155 {
3156 strcat(temp1,"0");
3157 }
3158 strcat(temp_output,temp1);
3159 temp = strtok(NULL,",");
3160 if(temp!=NULL)
3161 {
3162 strcat(temp_output," ");
3163 }
3164 }
3165 strcpy(TransmitRates,temp_output);
3166
3167 params.name= "basic_rates";
3168 params.value =TransmitRates;
3169
3170 wifi_dbg_printf("\n%s:",__func__);
3171 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3172 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3173 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3174 wifi_hostapdWrite(config_file,&params,1);
3175 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3176 return RETURN_OK;
3177}
3178
3179//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3180INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3181{
3182 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3183 FILE *fp = NULL;
3184 char path[256] = {0}, output_string[256] = {0};
3185 int count = 0;
3186 char *interface = NULL;
3187
3188 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3189 if (fp == NULL)
3190 {
3191 printf("Failed to run command in Function %s\n", __FUNCTION__);
3192 return RETURN_ERR;
3193 }
3194 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3195 {
3196 interface = strchr(path, '=');
3197
3198 if (interface != NULL)
3199 {
3200 strcpy(output_string, interface + 1);
3201 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3202 interface_name[count] = output_string[count];
3203
3204 interface_name[count] = '\0';
3205 }
3206 }
3207 pclose(fp);
3208 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3209 return RETURN_OK;
3210}
3211
3212INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3213{
3214 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3215 output_struct->radio_BytesSent = 0;
3216 output_struct->radio_BytesReceived = 0;
3217 output_struct->radio_PacketsSent = 0;
3218 output_struct->radio_PacketsReceived = 0;
3219 output_struct->radio_ErrorsSent = 0;
3220 output_struct->radio_ErrorsReceived = 0;
3221 output_struct->radio_DiscardPacketsSent = 0;
3222 output_struct->radio_DiscardPacketsReceived = 0;
3223 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3224 return RETURN_OK;
3225}
3226
3227
3228INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3229{
3230 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3231 CHAR buf[MAX_CMD_SIZE] = {0};
3232 CHAR Value[MAX_BUF_SIZE] = {0};
3233 FILE *fp = NULL;
3234
3235 if (ifname == NULL || strlen(ifname) <= 1)
3236 return RETURN_OK;
3237
3238 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3239 system(buf);
3240
3241 fp = fopen("/tmp/Radio_Stats.txt", "r");
3242 if(fp == NULL)
3243 {
3244 printf("/tmp/Radio_Stats.txt not exists \n");
3245 return RETURN_ERR;
3246 }
3247 fclose(fp);
3248
3249 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3250 File_Reading(buf, Value);
3251 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3252
3253 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3254 File_Reading(buf, Value);
3255 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3256
3257 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3258 File_Reading(buf, Value);
3259 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3260
3261 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3262 File_Reading(buf, Value);
3263 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3264
3265 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3266 File_Reading(buf, Value);
3267 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3268
3269 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3270 File_Reading(buf, Value);
3271 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3272
3273 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3274 File_Reading(buf, Value);
3275 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3276
3277 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3278 File_Reading(buf, Value);
3279 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3280
3281 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3282 return RETURN_OK;
3283}
3284
3285INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3286{
3287 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3288 CHAR buf[MAX_CMD_SIZE] = {0};
3289 FILE *fp = NULL;
3290 INT count = 0;
3291
3292 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3293 {
3294 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3295 File_Reading(buf, status);
3296 }
3297 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3298 return RETURN_OK;
3299}
3300
3301//Get detail radio traffic static info
3302INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3303{
3304
3305#if 0
3306 //ifconfig radio_x
3307 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3308 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3309 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3310 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3311
3312 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3313 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3314 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.
3315 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.
3316
3317 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3318 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].
3319 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3320 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.
3321 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
3322 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
3323 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
3324 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
3325 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
3326
3327 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
3328 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
3329 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
3330 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.
3331
3332 return RETURN_OK;
3333#endif
3334
3335 CHAR private_interface_name[MAX_BUF_SIZE] = {0}, public_interface_name[MAX_BUF_SIZE] = {0};
3336 CHAR private_interface_status[MAX_BUF_SIZE] = {0}, public_interface_status[MAX_BUF_SIZE] = {0};
3337 char buf[MAX_BUF_SIZE] = {0};
3338 char cmd[MAX_CMD_SIZE] = {0};
3339 wifi_radioTrafficStats2_t private_radioTrafficStats = {0}, public_radioTrafficStats = {0};
3340
3341 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3342 if (NULL == output_struct)
3343 return RETURN_ERR;
3344
3345 if (radioIndex == 0) //2.4GHz ?
3346 {
3347
3348 GetInterfaceName(private_interface_name, "/nvram/hostapd0.conf");
3349
3350 GetIfacestatus(private_interface_name, private_interface_status);
3351
3352 sprintf(cmd, "%s", "cat /nvram/hostapd0.conf | grep bss=");
3353 File_Reading(cmd, buf);
3354
3355 if (buf[0] == '#')
3356 {
3357 GetInterfaceName(public_interface_name, "/nvram/hostapd4.conf");
3358 }
3359 else
3360 {
3361 GetInterfaceName_virtualInterfaceName_2G(public_interface_name);
3362 }
3363
3364 GetIfacestatus(public_interface_name, public_interface_status);
3365
3366 if (strcmp(private_interface_status, "1") == 0)
3367 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3368 else
3369 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3370
3371 if (strcmp(public_interface_status, "1") == 0)
3372 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3373 else
3374 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3375 }
3376 else if (radioIndex == 1) //5GHz ?
3377 {
3378 GetInterfaceName(private_interface_name, "/nvram/hostapd1.conf");
3379 GetIfacestatus(private_interface_name, private_interface_status);
3380
3381 GetInterfaceName(public_interface_name, "/nvram/hostapd5.conf");
3382 GetIfacestatus(public_interface_name, public_interface_status);
3383
3384 if (strcmp(private_interface_status, "1") == 0)
3385 wifi_halGetIfStats(private_interface_name, &private_radioTrafficStats);
3386 else
3387 wifi_halGetIfStatsNull(&private_radioTrafficStats);
3388
3389 if (strcmp(public_interface_status, "1") == 0)
3390 wifi_halGetIfStats(public_interface_name, &public_radioTrafficStats);
3391 else
3392 wifi_halGetIfStatsNull(&public_radioTrafficStats);
3393 }
3394
3395 output_struct->radio_BytesSent = private_radioTrafficStats.radio_BytesSent + public_radioTrafficStats.radio_BytesSent;
3396 output_struct->radio_BytesReceived = private_radioTrafficStats.radio_BytesReceived + public_radioTrafficStats.radio_BytesReceived;
3397 output_struct->radio_PacketsSent = private_radioTrafficStats.radio_PacketsSent + public_radioTrafficStats.radio_PacketsSent;
3398 output_struct->radio_PacketsReceived = private_radioTrafficStats.radio_PacketsReceived + public_radioTrafficStats.radio_PacketsReceived;
3399 output_struct->radio_ErrorsSent = private_radioTrafficStats.radio_ErrorsSent + public_radioTrafficStats.radio_ErrorsSent;
3400 output_struct->radio_ErrorsReceived = private_radioTrafficStats.radio_ErrorsReceived + public_radioTrafficStats.radio_ErrorsReceived;
3401 output_struct->radio_DiscardPacketsSent = private_radioTrafficStats.radio_DiscardPacketsSent + public_radioTrafficStats.radio_DiscardPacketsSent;
3402 output_struct->radio_DiscardPacketsReceived = private_radioTrafficStats.radio_DiscardPacketsReceived + public_radioTrafficStats.radio_DiscardPacketsReceived;
3403
3404 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3405 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].
3406 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3407 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.
3408 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
3409 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
3410 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
3411 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
3412 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
3413
3414 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
3415 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
3416 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
3417 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.
3418
3419 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3420
3421 return RETURN_OK;
3422}
3423
3424//Set radio traffic static Measureing rules
3425INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3426{
3427 //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
3428 // Else, save the MeasuringRate and MeasuringInterval for future usage
3429
3430 return RETURN_OK;
3431}
3432
3433//To start or stop RadioTrafficStats
3434INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3435{
3436 //zqiu: If the RadioTrafficStats process running
3437 // if(enable)
3438 // return RETURN_OK.
3439 // else
3440 // Stop RadioTrafficStats process
3441 // Else
3442 // if(enable)
3443 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3444 // else
3445 // return RETURN_OK.
3446
3447 return RETURN_OK;
3448}
3449
3450//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
3451INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3452{
3453 //zqiu: Please ignor signalIndex.
3454 if (NULL == SignalLevel)
3455 return RETURN_ERR;
3456 *SignalLevel=(radioIndex==0)?-19:-19;
3457
3458 return RETURN_OK;
3459}
3460
3461//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3462INT wifi_applyRadioSettings(INT radioIndex)
3463{
3464 return RETURN_OK;
3465}
3466
3467//Get the radio index assocated with this SSID entry
3468INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3469{
3470 if (NULL == radioIndex)
3471 return RETURN_ERR;
3472 *radioIndex=ssidIndex%2;
3473
3474 return RETURN_OK;
3475}
3476
3477//Device.WiFi.SSID.{i}.Enable
3478//Get SSID enable configuration parameters (not the SSID enable status)
3479INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3480{
3481 if (NULL == output_bool)
3482 return RETURN_ERR;
3483
3484 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3485 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3486 return wifi_getApEnable(ssidIndex, output_bool);
3487}
3488
3489//Device.WiFi.SSID.{i}.Enable
3490//Set SSID enable configuration parameters
3491INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3492{
3493 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3494 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3495 return wifi_setApEnable(ssidIndex, enable);
3496}
3497
3498//Device.WiFi.SSID.{i}.Status
3499//Get the SSID enable status
3500INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3501{
3502 char cmd[MAX_CMD_SIZE]={0};
3503 char buf[MAX_BUF_SIZE]={0};
3504 BOOL output_bool;
3505
3506 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3507 if (NULL == output_string)
3508 return RETURN_ERR;
3509 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3510 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3511
3512 wifi_getApEnable(ssidIndex,&output_bool);
3513 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3514
3515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3516 return RETURN_OK;
3517}
3518
3519// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3520INT wifi_getSSIDName(INT apIndex, CHAR *output)
3521{
3522 char config_file[MAX_BUF_SIZE] = {0};
3523
3524 if (NULL == output)
3525 return RETURN_ERR;
3526
3527 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3528 wifi_hostapdRead(config_file,"ssid",output,32);
3529
3530 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3531 return RETURN_OK;
3532}
3533
3534// Set a max 32 byte string and sets an internal variable to the SSID name
3535INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3536{
3537 char str[MAX_BUF_SIZE]={'\0'};
3538 char cmd[MAX_CMD_SIZE]={'\0'};
3539 struct params params;
3540 char config_file[MAX_BUF_SIZE] = {0};
3541
3542 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3543 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3544 return RETURN_ERR;
3545
3546 params.name = "ssid";
3547 params.value = ssid_string;
3548 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3549 wifi_hostapdWrite(config_file, &params, 1);
3550 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3551 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3552
3553 return RETURN_OK;
3554}
3555
3556//Get the BSSID
3557INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3558{
3559 char cmd[MAX_CMD_SIZE]="";
3560
3561 if (NULL == output_string)
3562 return RETURN_ERR;
3563
3564 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3565 {
3566 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3567 _syscmd(cmd, output_string, 64);
3568 return RETURN_OK;
3569 }
3570 strncpy(output_string, "\0", 1);
3571
3572 return RETURN_ERR;
3573}
3574
3575//Get the MAC address associated with this Wifi SSID
3576INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3577{
3578 wifi_getBaseBSSID(ssidIndex,output_string);
3579 return RETURN_OK;
3580}
3581
3582//Get the basic SSID traffic static info
3583//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3584//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3585INT wifi_applySSIDSettings(INT ssidIndex)
3586{
3587 BOOL status = false;
3588 char cmd[MAX_CMD_SIZE] = {0};
3589 char buf[MAX_CMD_SIZE] = {0};
3590 int apIndex, ret;
3591 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3592
3593 wifi_getApEnable(ssidIndex,&status);
3594 // Do not apply when ssid index is disabled
3595 if (status == false)
3596 return RETURN_OK;
3597
3598 /* Doing full remove and add for ssid Index
3599 * Not all hostapd options are supported with reload
3600 * for example macaddr_acl
3601 */
3602 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3603 return RETURN_ERR;
3604
3605 ret = wifi_setApEnable(ssidIndex,true);
3606
3607 /* Workaround for hostapd issue with multiple bss definitions
3608 * when first created interface will be removed
3609 * then all vaps other vaps on same phy are removed
3610 * after calling setApEnable to false readd all enabled vaps */
3611 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3612 apIndex = 2*i+radioIndex;
3613 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3614 _syscmd(cmd, buf, sizeof(buf));
3615 if(*buf == '1')
3616 wifi_setApEnable(apIndex, true);
3617 }
3618
3619 return ret;
3620}
3621
developera3c68b92022-09-13 15:27:29 +08003622struct channels_noise {
3623 int channel;
3624 int noise;
3625};
3626
3627// Return noise array for each channel
3628int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3629{
3630 FILE *f = NULL;
3631 char cmd[128] = {0};
3632 char *line = NULL;
3633 size_t len = 0;
3634 ssize_t read = 0;
3635 int tmp = 0, arr_index = -1;
3636
3637 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3638
3639 if ((f = popen(cmd, "r")) == NULL) {
3640 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3641 return RETURN_ERR;
3642 }
3643 line = malloc(sizeof(char) * 256);
3644 while((read = getline(&line, &len, f)) != -1) {
3645 sscanf(line, "%d", &tmp);
3646 if (tmp > 0) { // channel frequency, the first line must be frequency
3647 arr_index++;
3648 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3649 } else { // noise
3650 channels_noise_arr[arr_index].noise = tmp;
3651 }
3652 }
3653 free(line);
3654 pclose(f);
3655 return RETURN_OK;
3656}
3657
developer06a01d92022-09-07 16:32:39 +08003658//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3659//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3660INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3661{
developera3c68b92022-09-13 15:27:29 +08003662 int index = -1;
3663 wifi_neighbor_ap2_t *scan_array = NULL;
3664 char cmd[256]={0};
3665 char buf[128]={0};
3666 char file_name[32] = {0};
3667 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003668 char line[256] = {0};
3669 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003670 int freq=0;
3671 FILE *f = NULL;
3672 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003673 int channels_num = 0;
3674 int vht_channel_width = 0;
3675 bool get_nosie_ret = false;
3676 bool filter_enable = false;
3677 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003678
developer615510b2022-09-27 10:14:35 +08003679 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003680
3681 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3682 f = fopen(file_name, "r");
3683 if (f != NULL) {
3684 fgets(filter_SSID, sizeof(file_name), f);
3685 if (strlen(filter_SSID) != 0)
3686 filter_enable = true;
3687 fclose(f);
3688 }
3689
3690 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003691 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003692 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003693
developera3c68b92022-09-13 15:27:29 +08003694 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3695 get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
developer06a01d92022-09-07 16:32:39 +08003696
developera3c68b92022-09-13 15:27:29 +08003697 sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
developer615510b2022-09-27 10:14:35 +08003698 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
developera3c68b92022-09-13 15:27:29 +08003699 fprintf(stderr, "cmd: %s\n", cmd);
3700 if ((f = popen(cmd, "r")) == NULL) {
3701 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3702 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003703 }
developer615510b2022-09-27 10:14:35 +08003704 ret = fgets(line, sizeof(line), f);
3705 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003706 if(strstr(line, "BSS") != NULL) { // new neighbor info
3707 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3708 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3709 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
developer06a01d92022-09-07 16:32:39 +08003710
developera3c68b92022-09-13 15:27:29 +08003711 if (!filter_BSS) {
3712 index++;
3713 wifi_neighbor_ap2_t *tmp;
3714 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3715 if (tmp == NULL) { // no more memory to use
3716 index--;
3717 wifi_dbg_printf("%s: realloc failed\n", __func__);
3718 break;
3719 }
3720 scan_array = tmp;
3721 }
3722 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3723
3724 filter_BSS = false;
3725 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3726 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3727 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3728 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3729 } else if (strstr(line, "freq") != NULL) {
3730 sscanf(line," freq: %d", &freq);
3731 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3732
3733 if (freq >= 2412 && freq <= 2484) {
3734 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3735 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3736 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3737 }
3738 else if (freq >= 5160 && freq <= 5805) {
3739 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3740 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3741 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3742 }
3743
3744 scan_array[index].ap_Noise = 0;
3745 if (get_nosie_ret) {
3746 for (int i = 0; i < channels_num; i++) {
3747 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3748 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3749 break;
3750 }
3751 }
3752 }
3753 } else if (strstr(line, "beacon interval") != NULL) {
3754 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3755 } else if (strstr(line, "signal") != NULL) {
3756 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3757 } else if (strstr(line,"SSID") != NULL) {
3758 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3759 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3760 filter_BSS = true;
3761 }
3762 } else if (strstr(line, "Supported rates") != NULL) {
3763 char SRate[80] = {0}, *tmp = NULL;
3764 memset(buf, 0, sizeof(buf));
3765 strcpy(SRate, line);
3766 tmp = strtok(SRate, ":");
3767 tmp = strtok(NULL, ":");
3768 strcpy(buf, tmp);
3769 memset(SRate, 0, sizeof(SRate));
3770
3771 tmp = strtok(buf, " \n");
3772 while (tmp != NULL) {
3773 strcat(SRate, tmp);
3774 if (SRate[strlen(SRate) - 1] == '*') {
3775 SRate[strlen(SRate) - 1] = '\0';
3776 }
3777 strcat(SRate, ",");
3778
3779 tmp = strtok(NULL, " \n");
3780 }
3781 SRate[strlen(SRate) - 1] = '\0';
3782 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3783 } else if (strstr(line, "DTIM") != NULL) {
3784 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3785 } else if (strstr(line, "VHT capabilities") != NULL) {
3786 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3787 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3788 } else if (strstr(line, "HT capabilities") != NULL) {
3789 strcat(scan_array[index].ap_SupportedStandards, ",n");
3790 strcpy(scan_array[index].ap_OperatingStandards, "n");
3791 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003792 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003793 sscanf(line," * channel width: %d", &vht_channel_width);
3794 if(vht_channel_width == 1) {
3795 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3796 } else {
3797 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3798 }
3799 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3800 continue;
3801 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003802 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003803 sscanf(line," * secondary channel offset: %s", &buf);
3804 if (!strcmp(buf, "above")) {
3805 //40Mhz +
3806 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3807 }
3808 else if (!strcmp(buf, "below")) {
3809 //40Mhz -
3810 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3811 } else {
3812 //20Mhz
3813 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3814 }
3815 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3816 continue;
3817 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003818 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3819 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3820 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003821 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3822 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003823 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003824 else
developer615510b2022-09-27 10:14:35 +08003825 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003826 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003827 if (strstr(line, "HE80/5GHz") != NULL) {
3828 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3829 ret = fgets(line, sizeof(line), f);
3830 } else
3831 continue;
developera3c68b92022-09-13 15:27:29 +08003832 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003833 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003834 }
developer615510b2022-09-27 10:14:35 +08003835 continue;
developera3c68b92022-09-13 15:27:29 +08003836 } else if (strstr(line, "WPA") != NULL) {
3837 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3838 } else if (strstr(line, "RSN") != NULL) {
3839 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3840 } else if (strstr(line, "Group cipher") != NULL) {
3841 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3842 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3843 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3844 }
3845 }
developer615510b2022-09-27 10:14:35 +08003846 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003847 }
3848
3849 if (!filter_BSS) {
3850 *output_array_size = index + 1;
3851 } else {
3852 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3853 *output_array_size = index;
3854 }
3855 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003856 pclose(f);
developer06a01d92022-09-07 16:32:39 +08003857 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003858 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003859}
3860
3861//>> Deprecated: used for old RDKB code.
3862INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3863{
3864 INT status = RETURN_ERR;
3865
3866 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3867 output_struct->wifi_PLCPErrorCount = 0;
3868 output_struct->wifi_FCSErrorCount = 0;
3869 output_struct->wifi_InvalidMACCount = 0;
3870 output_struct->wifi_PacketsOtherReceived = 0;
3871 output_struct->wifi_Noise = 0;
3872 status = RETURN_OK;
3873 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3874 return status;
3875}
3876
3877INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3878{
3879 char cmd[128];
3880 char buf[1280];
3881 char *pos = NULL;
3882
3883 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3884 if (NULL == output_struct)
3885 return RETURN_ERR;
3886
3887 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3888
3889 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3890 _syscmd(cmd, buf, sizeof(buf));
3891
3892 pos = buf;
3893 if ((pos = strstr(pos, "RX packets:")) == NULL)
3894 return RETURN_ERR;
3895 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3896
3897 if ((pos = strstr(pos, "TX packets:")) == NULL)
3898 return RETURN_ERR;
3899 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3900
3901 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3902 return RETURN_ERR;
3903 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3904
3905 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3906 return RETURN_ERR;
3907 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3908
3909 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3910 _syscmd(cmd, buf, sizeof(buf));
3911 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3912
3913#if 0
3914 //TODO: need to revisit below implementation
3915 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3916 char interface_name[MAX_BUF_SIZE] = {0};
3917 char interface_status[MAX_BUF_SIZE] = {0};
3918 char Value[MAX_BUF_SIZE] = {0};
3919 char buf[MAX_CMD_SIZE] = {0};
3920 char cmd[MAX_CMD_SIZE] = {0};
3921 FILE *fp = NULL;
3922
3923 if (NULL == output_struct) {
3924 return RETURN_ERR;
3925 }
3926
3927 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3928
3929 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3930 {
3931 if(apIndex == 0) //private_wifi for 2.4G
3932 {
3933 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3934 }
3935 else if(apIndex == 1) //private_wifi for 5G
3936 {
3937 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3938 }
3939 else if(apIndex == 4) //public_wifi for 2.4G
3940 {
3941 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3942 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3943 {
3944 return RETURN_ERR;
3945 }
3946 if(buf[0] == '#')//tp-link
3947 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3948 else//tenda
3949 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3950 }
3951 else if(apIndex == 5) //public_wifi for 5G
3952 {
3953 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3954 }
3955
3956 GetIfacestatus(interface_name, interface_status);
3957
3958 if(0 != strcmp(interface_status, "1"))
3959 return RETURN_ERR;
3960
3961 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3962 system(cmd);
3963
3964 fp = fopen("/tmp/SSID_Stats.txt", "r");
3965 if(fp == NULL)
3966 {
3967 printf("/tmp/SSID_Stats.txt not exists \n");
3968 return RETURN_ERR;
3969 }
3970 fclose(fp);
3971
3972 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3973 File_Reading(buf, Value);
3974 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3975
3976 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3977 File_Reading(buf, Value);
3978 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3979
3980 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3981 File_Reading(buf, Value);
3982 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3983
3984 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3985 File_Reading(buf, Value);
3986 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3987
3988 /* There is no specific parameter from caller to associate the value wifi_Associations */
3989 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3990 //_syscmd(cmd, buf, sizeof(buf));
3991 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3992 }
3993#endif
3994 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3995 return RETURN_OK;
3996}
3997
3998INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3999{
4000 char interface_name[MAX_BUF_SIZE] = {0};
4001 char interface_status[MAX_BUF_SIZE] = {0};
4002 char Value[MAX_BUF_SIZE] = {0};
4003 char buf[MAX_CMD_SIZE] = {0};
4004 char cmd[MAX_CMD_SIZE] = {0};
4005 FILE *fp = NULL;
4006
4007 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4008 if (NULL == output_struct)
4009 return RETURN_ERR;
4010
4011 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
4012
4013 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
4014 {
4015 if(apIndex == 0) //private_wifi for 2.4G
4016 {
4017 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
4018 }
4019 else if(apIndex == 1) //private_wifi for 5G
4020 {
4021 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
4022 }
4023 else if(apIndex == 4) //public_wifi for 2.4G
4024 {
4025 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
4026 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
4027 {
4028 return RETURN_ERR;
4029 }
4030 if(buf[0] == '#')
4031 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
4032 else
4033 GetInterfaceName_virtualInterfaceName_2G(interface_name);
4034 }
4035 else if(apIndex == 5) //public_wifi for 5G
4036 {
4037 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4038 }
4039
4040 GetIfacestatus(interface_name, interface_status);
4041
4042 if(0 != strcmp(interface_status, "1"))
4043 return RETURN_ERR;
4044
4045 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4046 system(cmd);
4047
4048 fp = fopen("/tmp/SSID_Stats.txt", "r");
4049 if(fp == NULL)
4050 {
4051 printf("/tmp/SSID_Stats.txt not exists \n");
4052 return RETURN_ERR;
4053 }
4054 fclose(fp);
4055
4056 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4057 File_Reading(buf, Value);
4058 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4059
4060 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4061 File_Reading(buf, Value);
4062 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4063
4064 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4065 File_Reading(buf, Value);
4066 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4067
4068 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4069 File_Reading(buf, Value);
4070 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4071 }
4072
4073 output_struct->wifi_UnicastPacketsSent = 0;
4074 output_struct->wifi_UnicastPacketsReceived = 0;
4075 output_struct->wifi_MulticastPacketsSent = 0;
4076 output_struct->wifi_MulticastPacketsReceived = 0;
4077 output_struct->wifi_BroadcastPacketsSent = 0;
4078 output_struct->wifi_BroadcastPacketsRecevied = 0;
4079 output_struct->wifi_UnknownPacketsReceived = 0;
4080
4081 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4082 return RETURN_OK;
4083}
4084
4085INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4086{
4087 INT status = RETURN_ERR;
4088
4089 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4090 //Below values should get updated from hal
4091 output_struct->wifi_RetransCount=0;
4092 output_struct->wifi_FailedRetransCount=0;
4093 output_struct->wifi_RetryCount=0;
4094 output_struct->wifi_MultipleRetryCount=0;
4095 output_struct->wifi_ACKFailureCount=0;
4096 output_struct->wifi_AggregatedPacketCount=0;
4097
4098 status = RETURN_OK;
4099 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4100
4101 return status;
4102}
4103
4104INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4105{
4106 INT status = RETURN_ERR;
4107 UINT index;
4108 wifi_neighbor_ap_t *pt=NULL;
4109
4110 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4111 *output_array_size=2;
4112 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4113 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4114 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4115 strcpy(pt->ap_Radio,"");
4116 strcpy(pt->ap_SSID,"");
4117 strcpy(pt->ap_BSSID,"");
4118 strcpy(pt->ap_Mode,"");
4119 pt->ap_Channel=1;
4120 pt->ap_SignalStrength=0;
4121 strcpy(pt->ap_SecurityModeEnabled,"");
4122 strcpy(pt->ap_EncryptionMode,"");
4123 strcpy(pt->ap_OperatingFrequencyBand,"");
4124 strcpy(pt->ap_SupportedStandards,"");
4125 strcpy(pt->ap_OperatingStandards,"");
4126 strcpy(pt->ap_OperatingChannelBandwidth,"");
4127 pt->ap_BeaconPeriod=1;
4128 pt->ap_Noise=0;
4129 strcpy(pt->ap_BasicDataTransferRates,"");
4130 strcpy(pt->ap_SupportedDataTransferRates,"");
4131 pt->ap_DTIMPeriod=1;
4132 pt->ap_ChannelUtilization = 1;
4133 }
4134
4135 status = RETURN_OK;
4136 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4137
4138 return status;
4139}
4140
4141//----------------- AP HAL -------------------------------
4142
4143//>> Deprecated: used for old RDKB code.
4144INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4145{
4146 if (NULL == output_ulong || NULL == output_struct)
4147 return RETURN_ERR;
4148 *output_ulong = 0;
4149 *output_struct = NULL;
4150 return RETURN_OK;
4151}
4152
4153#ifdef HAL_NETLINK_IMPL
4154static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4155 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4156 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4157 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4158 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4159 char mac_addr[20];
4160 static int count=0;
4161 int rate=0;
4162
4163 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4164
4165 nla_parse(tb,
4166 NL80211_ATTR_MAX,
4167 genlmsg_attrdata(gnlh, 0),
4168 genlmsg_attrlen(gnlh, 0),
4169 NULL);
4170
4171 if(!tb[NL80211_ATTR_STA_INFO]) {
4172 fprintf(stderr, "sta stats missing!\n");
4173 return NL_SKIP;
4174 }
4175
4176
4177 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4178 fprintf(stderr, "failed to parse nested attributes!\n");
4179 return NL_SKIP;
4180 }
4181
4182 //devIndex starts from 1
4183 if( ++count == out->wifi_devIndex )
4184 {
4185 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4186 //Getting the mac addrress
4187 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4188
4189 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4190 fprintf(stderr, "failed to parse nested rate attributes!");
4191 return NL_SKIP;
4192 }
4193
4194 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4195 if(rinfo[NL80211_RATE_INFO_BITRATE])
4196 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4197 out->wifi_devTxRate = rate/10;
4198 }
4199
4200 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4201 fprintf(stderr, "failed to parse nested rate attributes!");
4202 return NL_SKIP;
4203 }
4204
4205 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4206 if(rinfo[NL80211_RATE_INFO_BITRATE])
4207 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4208 out->wifi_devRxRate = rate/10;
4209 }
4210 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4211 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4212
4213 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4214 count = 0; //starts the count for next cycle
4215 return NL_STOP;
4216 }
4217
4218 return NL_SKIP;
4219
4220}
4221#endif
4222
4223INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4224{
4225#ifdef HAL_NETLINK_IMPL
4226 Netlink nl;
4227 char if_name[10];
4228
4229 wifi_device_info_t info;
4230 info.wifi_devIndex = devIndex;
4231
4232 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4233
4234 nl.id = initSock80211(&nl);
4235
4236 if (nl.id < 0) {
4237 fprintf(stderr, "Error initializing netlink \n");
4238 return -1;
4239 }
4240
4241 struct nl_msg* msg = nlmsg_alloc();
4242
4243 if (!msg) {
4244 fprintf(stderr, "Failed to allocate netlink message.\n");
4245 nlfree(&nl);
4246 return -2;
4247 }
4248
4249 genlmsg_put(msg,
4250 NL_AUTO_PORT,
4251 NL_AUTO_SEQ,
4252 nl.id,
4253 0,
4254 NLM_F_DUMP,
4255 NL80211_CMD_GET_STATION,
4256 0);
4257
4258 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4259 nl_send_auto(nl.socket, msg);
4260 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4261 nl_recvmsgs(nl.socket, nl.cb);
4262 nlmsg_free(msg);
4263 nlfree(&nl);
4264
4265 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4266 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4267 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4268 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4269 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4270 return RETURN_OK;
4271#else
4272 //iw utility to retrieve station information
4273#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4274#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4275#define MACFILE "/tmp/wifi_AssoMac.txt"
4276#define TXRATEFILE "/tmp/wifi_txrate.txt"
4277#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4278 FILE *file = NULL;
4279 char if_name[10] = {'\0'};
4280 char pipeCmd[256] = {'\0'};
4281 char line[256];
4282 int count,device = 0;
4283
4284 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4285
4286 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4287 file = popen(pipeCmd, "r");
4288
4289 if(file == NULL)
4290 return RETURN_ERR; //popen failed
4291
4292 fgets(line, sizeof line, file);
4293 device = atoi(line);
4294 pclose(file);
4295
4296 if(device == 0)
4297 return RETURN_ERR; //No devices are connected
4298
4299 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4300 system(pipeCmd);
4301
4302 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4303
4304 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4305
4306 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4307
4308 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4309
4310 //devIndex starts from 1, ++count
4311 if((file = fopen(SIGNALFILE, "r")) != NULL )
4312 {
4313 for(count =0;fgets(line, sizeof line, file) != NULL;)
4314 {
4315 if (++count == devIndex)
4316 {
4317 output_struct->wifi_devSignalStrength = atoi(line);
4318 break;
4319 }
4320 }
4321 fclose(file);
4322 }
4323 else
4324 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4325
4326 if((file = fopen(MACFILE, "r")) != NULL )
4327 {
4328 for(count =0;fgets(line, sizeof line, file) != NULL;)
4329 {
4330 if (++count == devIndex)
4331 {
4332 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]);
4333 break;
4334 }
4335 }
4336 fclose(file);
4337 }
4338 else
4339 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4340
4341 if((file = fopen(TXRATEFILE, "r")) != NULL )
4342 {
4343 for(count =0;fgets(line, sizeof line, file) != NULL;)
4344 {
4345 if (++count == devIndex)
4346 {
4347 output_struct->wifi_devTxRate = atoi(line);
4348 break;
4349 }
4350 }
4351 fclose(file);
4352 }
4353 else
4354 fprintf(stderr,"fopen wifi_txrate.txt failed");
4355
4356 if((file = fopen(RXRATEFILE, "r")) != NULL)
4357 {
4358 for(count =0;fgets(line, sizeof line, file) != NULL;)
4359 {
4360 if (++count == devIndex)
4361 {
4362 output_struct->wifi_devRxRate = atoi(line);
4363 break;
4364 }
4365 }
4366 fclose(file);
4367 }
4368 else
4369 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4370
4371 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4372
4373 return RETURN_OK;
4374#endif
4375}
4376
4377INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4378{
4379 if (NULL == device)
4380 return RETURN_ERR;
4381 return RETURN_OK;
4382}
4383//<<
4384
4385
4386//--------------wifi_ap_hal-----------------------------
4387//enables CTS protection for the radio used by this AP
4388INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4389{
4390 //save config and Apply instantly
4391 return RETURN_ERR;
4392}
4393
4394// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4395INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4396{
developer463d39a2022-09-13 15:32:51 +08004397 char config_file[64] = {'\0'};
4398 char buf[64] = {'\0'};
4399 struct params list;
4400
4401 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4402 list.name = "ht_coex";
4403 snprintf(buf, sizeof(buf), "%d", enable);
4404 list.value = buf;
4405
4406 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4407 wifi_hostapdWrite(config_file, &list, 1);
4408 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4409
4410 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4411
4412 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004413}
4414
4415//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4416INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4417{
developerea4bcce2022-09-13 15:26:13 +08004418 char config_file[MAX_BUF_SIZE] = {'\0'};
4419 char buf[MAX_BUF_SIZE] = {'\0'};
4420 struct params list;
4421
4422 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4423 if (threshold < 256 || threshold > 2346 )
4424 return RETURN_ERR;
4425 list.name = "fragm_threshold";
4426 snprintf(buf, sizeof(buf), "%d", threshold);
4427 list.value = buf;
4428
4429 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4430 wifi_hostapdWrite(config_file, &list, 1);
4431 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004432
developerea4bcce2022-09-13 15:26:13 +08004433 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004434
4435 return RETURN_OK;
4436}
4437
4438// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4439INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4440{
developer51a927d2022-09-13 15:42:22 +08004441 char config_file[64] = {'\0'};
4442 char cmd[128] = {'\0'};
4443 char buf[64] = {'\0'};
4444 char stbc_config[16] = {'\0'};
4445 wifi_band band;
4446 int iterator = 0;
4447 BOOL current_stbc = FALSE;
4448
4449 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4450
4451 band = wifi_index_to_band(radioIndex);
4452 if (band == band_invalid)
4453 return RETURN_ERR;
4454
4455 if (band == band_2_4)
4456 iterator = 1;
4457 else if (band == band_5)
4458 iterator = 2;
4459 else
4460 return RETURN_OK;
4461
4462 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4463
4464 // set ht and vht config
4465 for (int i = 0; i < iterator; i++) {
4466 memset(stbc_config, 0, sizeof(stbc_config));
4467 memset(cmd, 0, sizeof(cmd));
4468 memset(buf, 0, sizeof(buf));
4469 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4470 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4471 _syscmd(cmd, buf, sizeof(buf));
4472 if (strlen(buf) != 0)
4473 current_stbc = TRUE;
4474 if (current_stbc == STBC_Enable)
4475 continue;
4476
4477 if (STBC_Enable == TRUE) {
4478 // Append the STBC flags in capab config
4479 memset(cmd, 0, sizeof(cmd));
4480 if (i == 0)
4481 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4482 else
4483 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4484 _syscmd(cmd, buf, sizeof(buf));
4485 } else if (STBC_Enable == FALSE) {
4486 // Remove the STBC flags and remain other flags in capab
4487 memset(cmd, 0, sizeof(cmd));
4488 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4489 _syscmd(cmd, buf, sizeof(buf));
4490 memset(cmd, 0, sizeof(cmd));
4491 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4492 _syscmd(cmd, buf, sizeof(buf));
4493 }
4494 }
4495
4496 wifi_reloadAp(radioIndex);
4497
4498 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4499 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004500}
4501
4502// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4503INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4504{
developer54e6b9f2022-09-28 14:41:20 +08004505 char AMSDU_file_path[64] = {0};
4506
4507 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4508
4509 if(output_bool == NULL)
4510 return RETURN_ERR;
4511
4512 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4513
4514 if (access(AMSDU_file_path, F_OK) == 0)
4515 *output_bool = TRUE;
4516 else
4517 *output_bool = FALSE;
4518
4519 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4520 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004521}
4522
4523// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4524INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4525{
developer54e6b9f2022-09-28 14:41:20 +08004526 char cmd[64]={0};
4527 char buf[64]={0};
4528 char AMSDU_file_path[64] = {0};
4529
4530 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4531
4532 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4533 _syscmd(cmd, buf, sizeof(buf));
4534
4535 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4536 memset(cmd, 0, sizeof(cmd));
4537 if (amsduEnable == TRUE)
4538 sprintf(cmd, "touch %s", AMSDU_file_path);
4539 else
4540 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4541 _syscmd(cmd, buf, sizeof(buf));
4542
4543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4544 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004545}
4546
4547//P2 // outputs the number of Tx streams
4548INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4549{
developer2de97692022-09-26 14:00:03 +08004550 char buf[8] = {0};
4551 char cmd[128] = {0};
4552
4553 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4554
4555 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4556 _syscmd(cmd, buf, sizeof(buf));
4557
4558 // if there is no record, output the max number of spatial streams
4559 if (strlen(buf) == 0) {
4560 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4561 _syscmd(cmd, buf, sizeof(buf));
4562 }
4563
4564 *output_int = (INT)strtol(buf, NULL, 10);
4565
4566 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4567
4568 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004569}
4570
4571//P2 // sets the number of Tx streams to an enviornment variable
4572INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4573{
developer2de97692022-09-26 14:00:03 +08004574 char cmd[128] = {0};
4575 char buf[128] = {0};
4576 char chain_mask_file[128] = {0};
4577 FILE *f = NULL;
4578
4579 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4580
4581 if (numStreams == 0) {
4582 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4583 return RETURN_ERR;
4584 }
4585 wifi_setRadioEnable(radioIndex, FALSE);
4586 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4587 _syscmd(cmd, buf, sizeof(buf));
4588
4589 if (strlen(buf) > 0) {
4590 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4591 return RETURN_ERR;
4592 }
4593 wifi_setRadioEnable(radioIndex, TRUE);
4594
4595 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4596 f = fopen(chain_mask_file, "w");
4597 if (f == NULL) {
4598 fprintf(stderr, "%s: fopen failed.\n", __func__);
4599 return RETURN_ERR;
4600 }
4601 fprintf(f, "%d", numStreams);
4602 fclose(f);
4603 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4604 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004605}
4606
4607//P2 // outputs the number of Rx streams
4608INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4609{
developer2de97692022-09-26 14:00:03 +08004610 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4611 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4612 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004613 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004614 }
4615 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004616 return RETURN_OK;
4617}
4618
4619//P2 // sets the number of Rx streams to an enviornment variable
4620INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4621{
developer2de97692022-09-26 14:00:03 +08004622 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4623 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4624 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4625 return RETURN_ERR;
4626 }
4627 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004628 return RETURN_ERR;
4629}
4630
4631//Get radio RDG enable setting
4632INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4633{
4634 if (NULL == output_bool)
4635 return RETURN_ERR;
4636 *output_bool = TRUE;
4637 return RETURN_OK;
4638}
4639
4640//Get radio RDG enable setting
4641INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4642{
4643 if (NULL == output_bool)
4644 return RETURN_ERR;
4645 *output_bool = TRUE;
4646 return RETURN_OK;
4647}
4648
4649//Set radio RDG enable setting
4650INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4651{
4652 return RETURN_ERR;
4653}
4654
4655//Get radio ADDBA enable setting
4656INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4657{
4658 if (NULL == output_bool)
4659 return RETURN_ERR;
4660 *output_bool = TRUE;
4661 return RETURN_OK;
4662}
4663
4664//Set radio ADDBA enable setting
4665INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4666{
4667 return RETURN_ERR;
4668}
4669
4670//Get radio auto block ack enable setting
4671INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4672{
4673 if (NULL == output_bool)
4674 return RETURN_ERR;
4675 *output_bool = TRUE;
4676 return RETURN_OK;
4677}
4678
4679//Set radio auto block ack enable setting
4680INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4681{
4682 return RETURN_ERR;
4683}
4684
4685//Get radio 11n pure mode enable support
4686INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4687{
4688 if (NULL == output_bool)
4689 return RETURN_ERR;
4690 *output_bool = TRUE;
4691 return RETURN_OK;
4692}
4693
4694//Get radio 11n pure mode enable setting
4695INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4696{
4697 if (NULL == output_bool)
4698 return RETURN_ERR;
4699 *output_bool = TRUE;
4700 return RETURN_OK;
4701}
4702
4703//Set radio 11n pure mode enable setting
4704INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4705{
4706 return RETURN_ERR;
4707}
4708
4709//Get radio IGMP snooping enable setting
4710INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4711{
developer81bf2ed2022-09-13 15:31:14 +08004712 char cmd[128]={0};
4713 char buf[4]={0};
4714 bool bridge = FALSE, mac80211 = FALSE;
4715 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4716
4717 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004718 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004719
4720 *output_bool = FALSE;
4721
4722 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4723 _syscmd(cmd, buf, sizeof(buf));
4724 if (strncmp(buf, "1", 1) == 0)
4725 bridge = TRUE;
4726
4727 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4728 _syscmd(cmd, buf, sizeof(buf));
4729 if (strncmp(buf, "1", 1) == 0)
4730 mac80211 = TRUE;
4731
4732 if (bridge && mac80211)
4733 *output_bool = TRUE;
4734
4735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004736 return RETURN_OK;
4737}
4738
4739//Set radio IGMP snooping enable setting
4740INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4741{
developer81bf2ed2022-09-13 15:31:14 +08004742 char cmd[128]={0};
4743 char buf[4]={0};
4744
4745 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4746
4747 // bridge
4748 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4749 _syscmd(cmd, buf, sizeof(buf));
4750
4751 // mac80211
4752 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4753 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4754 _syscmd(cmd, buf, sizeof(buf));
4755 }
4756 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4757 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004758}
4759
4760//Get the Reset count of radio
4761INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4762{
4763 if (NULL == output_int)
4764 return RETURN_ERR;
4765 *output_int = (radioIndex==0)? 1: 3;
4766
4767 return RETURN_OK;
4768}
4769
4770
4771//---------------------------------------------------------------------------------------------------
4772//
4773// Additional Wifi AP level APIs used for Access Point devices
4774//
4775//---------------------------------------------------------------------------------------------------
4776
4777// creates a new ap and pushes these parameters to the hardware
4778INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4779{
4780 char buf[1024];
4781 char cmd[128];
4782
4783 if (NULL == essid)
4784 return RETURN_ERR;
4785
4786 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4787 _syscmd(cmd, buf, sizeof(buf));
4788
4789 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4790 _syscmd(cmd, buf, sizeof(buf));
4791
4792 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4793
4794 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4795 _syscmd(cmd, buf, sizeof(buf));
4796
4797 return RETURN_OK;
4798}
4799
4800// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4801INT wifi_deleteAp(INT apIndex)
4802{
4803 char buf[1024];
4804 char cmd[128];
4805
4806 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4807 _syscmd(cmd, buf, sizeof(buf));
4808
4809 wifi_removeApSecVaribles(apIndex);
4810
4811 return RETURN_OK;
4812}
4813
4814// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4815INT wifi_getApName(INT apIndex, CHAR *output_string)
4816{
4817 if(NULL == output_string)
4818 return RETURN_ERR;
4819
4820 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4821 return RETURN_OK;
4822}
4823
4824// Outputs the index number in that corresponds to the SSID string
4825INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4826{
4827 CHAR *pos = NULL;
4828
4829 *output_int = -1;
4830 pos = strstr(inputSsidString, AP_PREFIX);
4831 if(pos)
4832 {
4833 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4834 return RETURN_OK;
4835 }
4836 return RETURN_ERR;
4837}
4838
4839INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4840{
4841 return wifi_getIndexFromName(inputSsidString, output_int);
4842}
4843
4844// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4845INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4846{
4847 char buf[MAX_BUF_SIZE] = {0};
4848 char cmd[MAX_CMD_SIZE] = {0};
4849 char config_file[MAX_BUF_SIZE] = {0};
4850
4851 if(NULL == output_string)
4852 return RETURN_ERR;
4853
4854 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4855 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4856 if((strcmp(buf,"3")==0))
4857 snprintf(output_string, 32, "WPAand11i");
4858 else if((strcmp(buf,"2")==0))
4859 snprintf(output_string, 32, "11i");
4860 else if((strcmp(buf,"1")==0))
4861 snprintf(output_string, 32, "WPA");
4862 else
4863 snprintf(output_string, 32, "None");
4864
4865 return RETURN_OK;
4866}
4867
4868// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4869INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4870{
4871 char config_file[MAX_BUF_SIZE] = {0};
4872 struct params list;
4873
4874 if (NULL == beaconTypeString)
4875 return RETURN_ERR;
4876 list.name = "wpa";
4877 list.value = "0";
4878
4879 if((strcmp(beaconTypeString,"WPAand11i")==0))
4880 list.value="3";
4881 else if((strcmp(beaconTypeString,"11i")==0))
4882 list.value="2";
4883 else if((strcmp(beaconTypeString,"WPA")==0))
4884 list.value="1";
4885
4886 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4887 wifi_hostapdWrite(config_file, &list, 1);
4888 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4889 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4890 return RETURN_OK;
4891}
4892
4893// sets the beacon interval on the hardware for this AP
4894INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4895{
developer5f222492022-09-13 15:21:52 +08004896 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4897 struct params params={'\0'};
4898 char buf[MAX_BUF_SIZE] = {'\0'};
4899 char config_file[MAX_BUF_SIZE] = {'\0'};
4900
4901 params.name = "beacon_int";
4902 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4903 params.value = buf;
4904
4905 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4906 wifi_hostapdWrite(config_file, &params, 1);
4907
4908 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4910 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004911}
4912
4913INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4914{
4915 //save config and apply instantly
4916 return RETURN_ERR;
4917}
4918
4919// Get the packet size threshold supported.
4920INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4921{
4922 //save config and apply instantly
4923 if (NULL == output_bool)
4924 return RETURN_ERR;
4925 *output_bool = FALSE;
4926 return RETURN_OK;
4927}
4928
4929// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4930INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4931{
4932 char cmd[128];
4933 char buf[512];
4934
4935 if (threshold > 0)
4936 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4937 else
4938 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4939 _syscmd(cmd, buf, sizeof(buf));
4940
4941 return RETURN_OK;
4942}
4943
4944// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4945INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4946{
4947 if (NULL == output_string)
4948 return RETURN_ERR;
4949 snprintf(output_string, 32, "TKIPandAESEncryption");
4950 return RETURN_OK;
4951
4952}
4953
4954// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4955INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4956{
4957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4958 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4959
4960 if(NULL == output_string)
4961 return RETURN_ERR;
4962
4963 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4964 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4965
4966 if(strcmp(buf,"0")==0)
4967 {
4968 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4969 snprintf(output_string, 32, "None");
4970 return RETURN_OK;
4971 }
4972 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4973 param_name = "rsn_pairwise";
4974 else if((strcmp(buf,"1")==0))
4975 param_name = "wpa_pairwise";
4976 else
4977 return RETURN_ERR;
4978 memset(output_string,'\0',32);
4979 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4980 wifi_hostapdRead(config_file,param_name,output_string,32);
4981 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4982
4983 if(strcmp(output_string,"TKIP") == 0)
4984 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4985 else if(strcmp(output_string,"CCMP") == 0)
4986 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4987 else if(strcmp(output_string,"TKIP CCMP") == 0)
4988 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4989
4990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4991 return RETURN_OK;
4992}
4993
4994// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4995INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4996{
4997 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4998 struct params params={'\0'};
4999 char output_string[32];
5000 char config_file[MAX_BUF_SIZE] = {0};
5001
5002 memset(output_string,'\0',32);
5003 wifi_getApWpaEncryptionMode(apIndex,output_string);
5004
5005 if(strcmp(encMode, "TKIPEncryption") == 0)
5006 params.value = "TKIP";
5007 else if(strcmp(encMode,"AESEncryption") == 0)
5008 params.value = "CCMP";
5009 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
5010 params.value = "TKIP CCMP";
5011
5012 if((strcmp(output_string,"WPAand11i")==0))
5013 {
5014 params.name = "wpa_pairwise";
5015 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5016 wifi_hostapdWrite(config_file, &params, 1);
5017 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5018
5019 params.name,"rsn_pairwise";
5020 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5021 wifi_hostapdWrite(config_file, &params, 1);
5022 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5023
5024 return RETURN_OK;
5025 }
5026 else if((strcmp(output_string,"11i")==0))
5027 {
5028 params.name = "rsn_pairwise";
5029 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5030 wifi_hostapdWrite(config_file, &params, 1);
5031 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5032 return RETURN_OK;
5033 }
5034 else if((strcmp(output_string,"WPA")==0))
5035 {
5036 params.name = "wpa_pairwise";
5037 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5038 wifi_hostapdWrite(config_file, &params, 1);
5039 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5040 return RETURN_OK;
5041 }
5042
5043 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5044 return RETURN_OK;
5045}
5046
5047// deletes internal security varable settings for this ap
5048INT wifi_removeApSecVaribles(INT apIndex)
5049{
5050 //TODO: remove the entry in hostapd config file
5051 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5052 //_syscmd(cmd, buf, sizeof(buf));
5053
5054 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5055 //_syscmd(cmd, buf, sizeof(buf));
5056 return RETURN_ERR;
5057}
5058
5059// changes the hardware settings to disable encryption on this ap
5060INT wifi_disableApEncryption(INT apIndex)
5061{
5062 //Apply instantly
5063 return RETURN_ERR;
5064}
5065
5066// set the authorization mode on this ap
5067// mode mapping as: 1: open, 2: shared, 4:auto
5068INT wifi_setApAuthMode(INT apIndex, INT mode)
5069{
developeraf95c502022-09-13 16:18:22 +08005070 struct params params={0};
5071 char config_file[64] = {0};
5072 int ret;
5073
5074 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5075
5076 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5077 params.name = "auth_algs";
5078
5079 if (mode & 1 && mode & 2)
5080 params.value = "3";
5081 else if (mode & 2)
5082 params.value = "2";
5083 else if (mode & 1)
5084 params.value = "1";
5085 else
5086 params.value = "0";
5087
5088 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5089 wifi_hostapdWrite(config_file, &params, 1);
5090 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5092
5093 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005094}
5095
5096// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5097INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5098{
5099 //save to wifi config, and wait for wifi restart to apply
5100 struct params params={'\0'};
5101 char config_file[MAX_BUF_SIZE] = {0};
5102 int ret;
5103
5104 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5105 if(authMode == NULL)
5106 return RETURN_ERR;
5107
5108 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5109 params.name = "wpa_key_mgmt";
5110
5111 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5112 params.value = "WPA-PSK";
5113 else if(strcmp(authMode,"EAPAuthentication") == 0)
5114 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005115 else if (strcmp(authMode, "SAEAuthentication") == 0)
5116 params.value = "SAE";
5117 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5118 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005119 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5120 return RETURN_OK; //This is taken careof in beaconType
5121
5122 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5123 ret=wifi_hostapdWrite(config_file,&params,1);
5124 if(!ret)
5125 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5126 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5127
5128 return ret;
5129}
5130
5131// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5132INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5133{
5134 //save to wifi config, and wait for wifi restart to apply
5135 char BeaconType[50] = {0};
5136 char config_file[MAX_BUF_SIZE] = {0};
5137
5138 *authMode = 0;
5139 wifi_getApBeaconType(apIndex,BeaconType);
5140 printf("%s____%s \n",__FUNCTION__,BeaconType);
5141
5142 if(strcmp(BeaconType,"None") == 0)
5143 strcpy(authMode,"None");
5144 else
5145 {
5146 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5147 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5148 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5149 if(strcmp(authMode,"WPA-PSK") == 0)
5150 strcpy(authMode,"SharedAuthentication");
5151 else if(strcmp(authMode,"WPA-EAP") == 0)
5152 strcpy(authMode,"EAPAuthentication");
5153 }
5154
5155 return RETURN_OK;
5156}
5157
5158// Outputs the number of stations associated per AP
5159INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5160{
5161 char cmd[128]={0};
5162 char buf[128]={0};
5163 BOOL status = false;
5164
5165 if(apIndex > MAX_APS)
5166 return RETURN_ERR;
5167
5168 wifi_getApEnable(apIndex,&status);
5169 if (!status)
5170 return RETURN_OK;
5171
5172 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5173 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5174 _syscmd(cmd, buf, sizeof(buf));
5175 sscanf(buf,"%lu", output_ulong);
5176
5177 return RETURN_OK;
5178}
5179
5180// manually removes any active wi-fi association with the device specified on this ap
5181INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5182{
5183 char buf[126]={'\0'};
5184
5185 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5186 system(buf);
5187
5188 return RETURN_OK;
5189}
5190
5191// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5192INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5193{
5194 if(NULL == output_int)
5195 return RETURN_ERR;
5196 *output_int = apIndex%2;
5197 return RETURN_OK;
5198}
5199
5200// sets the radio index for the specific ap
5201INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5202{
5203 //set to config only and wait for wifi reset to apply settings
5204 return RETURN_ERR;
5205}
5206
5207// Get the ACL MAC list per AP
5208INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5209{
5210 char cmd[MAX_CMD_SIZE]={'\0'};
5211 int ret = 0;
5212
5213 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5214 ret = _syscmd(cmd,macArray,buf_size);
5215 if (ret != 0)
5216 return RETURN_ERR;
5217
5218 return RETURN_OK;
5219}
5220
developere6aafda2022-09-13 14:59:28 +08005221INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5222{
5223 char cmd[MAX_CMD_SIZE]={'\0'};
5224 int ret = 0;
5225
5226 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5227 ret = _syscmd(cmd,macArray,buf_size);
5228 if (ret != 0)
5229 return RETURN_ERR;
5230
5231 return RETURN_OK;
5232}
5233
5234
developer06a01d92022-09-07 16:32:39 +08005235// Get the list of stations associated per AP
5236INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5237{
5238 char cmd[128];
5239
5240 if(apIndex > 3) //Currently supporting apIndex upto 3
5241 return RETURN_ERR;
5242 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5243 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5244 _syscmd(cmd, macArray, buf_size);
5245
5246 return RETURN_OK;
5247}
5248
5249// adds the mac address to the filter list
5250//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5251INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5252{
5253 char cmd[MAX_CMD_SIZE]={'\0'};
5254 char buf[MAX_BUF_SIZE]={'\0'};
5255
5256#if 0
5257 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5258 if(_syscmd(cmd,buf,sizeof(buf)))
5259 return RETURN_ERR;
5260#endif
5261 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5262 if(_syscmd(cmd,buf,sizeof(buf)))
5263 return RETURN_ERR;
5264
5265 return RETURN_OK;
5266}
5267
5268// deletes the mac address from the filter list
5269//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5270INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5271{
5272 char cmd[MAX_CMD_SIZE]={'\0'};
5273 char buf[MAX_BUF_SIZE]={'\0'};
5274
5275#if 0
5276 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5277 if(_syscmd(cmd,buf,sizeof(buf)))
5278 return RETURN_ERR;
5279
5280#endif
5281 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5282 if(_syscmd(cmd,buf,sizeof(buf)))
5283 return RETURN_ERR;
5284
5285 return RETURN_OK;
5286}
5287
5288// outputs the number of devices in the filter list
5289INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5290{
developere6aafda2022-09-13 14:59:28 +08005291 char cmd[MAX_BUF_SIZE]={0};
5292 char buf[MAX_CMD_SIZE]={0};
5293
5294 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5295 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005296 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005297
5298 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5299 _syscmd(cmd, buf, sizeof(buf));
5300
5301 *output_uint = atoi(buf);
5302
5303 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5304 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005305}
5306
5307INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5308{
5309 char cmd[128]={'\0'};
5310 char buf[128]={'\0'};
5311
5312 if(strcmp(action,"DENY")==0)
5313 {
5314 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5315 system(buf);
5316 return RETURN_OK;
5317 }
5318
5319 if(strcmp(action,"ALLOW")==0)
5320 {
5321 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5322 system(buf);
5323 return RETURN_OK;
5324 }
5325
5326 return RETURN_ERR;
5327
5328}
5329
5330// enable kick for devices on acl black list
5331INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5332{
5333 char aclArray[512] = {0}, *acl = NULL;
5334 char assocArray[512] = {0}, *asso = NULL;
5335
developere6aafda2022-09-13 14:59:28 +08005336 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005337 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5338
5339 // if there are no devices connected there is nothing to do
5340 if (strlen(assocArray) < 17)
5341 return RETURN_OK;
5342
5343 if (enable == TRUE)
5344 {
5345 //kick off the MAC which is in ACL array (deny list)
5346 acl = strtok(aclArray, "\r\n");
5347 while (acl != NULL) {
5348 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5349 wifi_kickApAssociatedDevice(apIndex, acl);
5350
5351 acl = strtok(NULL, "\r\n");
5352 }
developere6aafda2022-09-13 14:59:28 +08005353 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005354 }
5355 else
5356 {
developere6aafda2022-09-13 14:59:28 +08005357 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005358 }
5359
5360#if 0
5361 //TODO: need to revisit below implementation
5362 char aclArray[512]={0}, *acl=NULL;
5363 char assocArray[512]={0}, *asso=NULL;
5364 char buf[256]={'\0'};
5365 char action[10]={'\0'};
5366 FILE *fr=NULL;
5367 char interface[10]={'\0'};
5368 char config_file[MAX_BUF_SIZE] = {0};
5369
5370 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5371 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5372 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5373 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5374
5375 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5376 system(buf);
5377 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5378 system(buf);
5379 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5380 system(buf);
5381 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5382 system(buf);
5383 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5384 system(buf);
5385
5386 if ( enable == TRUE )
5387 {
5388 int device_count=0;
5389 strcpy(action,"DENY");
5390 //kick off the MAC which is in ACL array (deny list)
5391 acl = strtok (aclArray,",");
5392 while (acl != NULL) {
5393 if(strlen(acl)>=17)
5394 {
5395 apply_rules(apIndex, acl,action,interface);
5396 device_count++;
5397 //Register mac to be blocked ,in syscfg.db persistent storage
5398 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5399 system(buf);
5400 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5401 system(buf);
5402 system("syscfg commit");
5403
5404 wifi_kickApAssociatedDevice(apIndex, acl);
5405 }
5406 acl = strtok (NULL, ",");
5407 }
5408 }
5409 else
5410 {
5411 int device_count=0;
5412 char cmdmac[20]={'\0'};
5413 strcpy(action,"ALLOW");
5414 //kick off the MAC which is not in ACL array (allow list)
5415 acl = strtok (aclArray,",");
5416 while (acl != NULL) {
5417 if(strlen(acl)>=17)
5418 {
5419 apply_rules(apIndex, acl,action,interface);
5420 device_count++;
5421 //Register mac to be Allowed ,in syscfg.db persistent storage
5422 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5423 system(buf);
5424 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5425 system(buf);
5426 sprintf(cmdmac,"%s",acl);
5427 }
5428 acl = strtok (NULL, ",");
5429 }
5430 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5431 system(buf);
5432
5433 //Disconnect the mac which is not in ACL
5434 asso = strtok (assocArray,",");
5435 while (asso != NULL) {
5436 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5437 wifi_kickApAssociatedDevice(apIndex, asso);
5438 asso = strtok (NULL, ",");
5439 }
5440 }
5441#endif
5442 return RETURN_OK;
5443}
5444
5445INT wifi_setPreferPrivateConnection(BOOL enable)
5446{
5447 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5448 char buf[1024] = {0};
5449
5450 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5451 if(enable == TRUE)
5452 {
5453 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5454 sprintf(buf,"ifconfig %s down" ,interface_name);
5455 system(buf);
5456 memset(buf,0,sizeof(buf));
5457 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5458 sprintf(buf,"ifconfig %s down" ,interface_name);
5459 system(buf);
5460 }
5461 else
5462 {
5463 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5464 if(strcmp(ssid_cur_value,"1") == 0)
5465 wifi_RestartPrivateWifi_5G();
5466 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5467 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5468 if(strcmp(ssid_cur_value,"1") == 0)
5469 wifi_RestartHostapd_2G();
5470 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5471 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5472 if(strcmp(ssid_cur_value,"1") == 0)
5473 wifi_RestartHostapd_5G();
5474 }
5475 return RETURN_OK;
5476}
5477
5478// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5479INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5480{
5481 int items = 1;
5482 struct params list[2];
5483 char buf[MAX_BUF_SIZE] = {0};
5484 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005485 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005486
5487 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005488
developer10adcc12022-09-13 14:39:17 +08005489 if (filterMode == 0) {
5490 sprintf(buf, "%d", 0);
5491 list[0].value = buf;
5492
5493 char cmd[128], rtn[128];
5494 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5495 _syscmd(cmd, rtn, sizeof(rtn));
5496 memset(cmd,0,sizeof(cmd));
5497 // Delete deny_mac_file in hostapd configuration
5498 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5499 _syscmd(cmd, rtn, sizeof(rtn));
5500 }
5501 else if (filterMode == 1) {
5502 sprintf(buf, "%d", filterMode);
5503 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005504 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5505 list[1].name = "accept_mac_file";
5506 list[1].value = acl_file;
5507 items = 2;
developer10adcc12022-09-13 14:39:17 +08005508 } else if (filterMode == 2) {
5509 //TODO: deny_mac_file
5510 sprintf(buf, "%d", 0);
5511 list[0].value = buf;
5512 list[1].name = "deny_mac_file";
5513 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5514 list[1].value = deny_file;
5515 items = 2;
5516 } else {
5517 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005518 }
developer10adcc12022-09-13 14:39:17 +08005519
developer06a01d92022-09-07 16:32:39 +08005520 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5521 wifi_hostapdWrite(config_file, list, items);
5522
5523 return RETURN_OK;
5524
5525#if 0
5526 if(apIndex==0 || apIndex==1)
5527 {
5528 //set the filtermode
5529 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5530 system(buf);
5531 system("syscfg commit");
5532
5533 if(filterMode==0)
5534 {
5535 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5536 system(buf);
5537 return RETURN_OK;
5538 }
5539 }
5540 return RETURN_OK;
5541#endif
5542}
5543
5544// 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.
5545INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5546{
5547 return RETURN_ERR;
5548}
5549
5550// gets the vlan ID for this ap from an internal enviornment variable
5551INT wifi_getApVlanID(INT apIndex, INT *output_int)
5552{
5553 if(apIndex=0)
5554 {
5555 *output_int=100;
5556 return RETURN_OK;
5557 }
5558
5559 return RETURN_ERR;
5560}
5561
5562// sets the vlan ID for this ap to an internal enviornment variable
5563INT wifi_setApVlanID(INT apIndex, INT vlanId)
5564{
5565 //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)
5566 return RETURN_ERR;
5567}
5568
5569// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5570INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5571{
5572 snprintf(bridgeName, 32, "brlan0");
5573 snprintf(IP, 32, "10.0.0.1");
5574 snprintf(subnet, 32, "255.255.255.0");
5575
5576 return RETURN_OK;
5577}
5578
5579//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5580INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5581{
5582 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5583 return RETURN_ERR;
5584}
5585
5586// reset the vlan configuration for this ap
5587INT wifi_resetApVlanCfg(INT apIndex)
5588{
developerf5fef612022-09-20 19:38:26 +08005589 char original_config_file[64] = {0};
5590 char current_config_file[64] = {0};
5591 char buf[64] = {0};
5592 char cmd[64] = {0};
5593 char vlan_file[64] = {0};
5594 char vlan_tagged_interface[16] = {0};
5595 char vlan_bridge[16] = {0};
5596 char vlan_naming[16] = {0};
5597 struct params list[4] = {0};
5598 wifi_band band;
5599
5600 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5601
5602 band = wifi_index_to_band(apIndex);
5603 if (band == band_2_4)
5604 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5605 else if (band = band_5)
5606 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5607 else if (band = band_6)
5608 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5609
5610 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5611
5612 if (strlen(vlan_file) == 0)
5613 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005614
developerf5fef612022-09-20 19:38:26 +08005615 // The file should exist or this vap would not work.
5616 if (access(vlan_file, F_OK) != 0) {
5617 sprintf(cmd, "touch %s", vlan_file);
5618 _syscmd(cmd, buf, sizeof(buf));
5619 }
5620 list[0].name = "vlan_file";
5621 list[0].value = vlan_file;
5622
5623 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5624 list[1].name = "vlan_tagged_interface";
5625 list[1].value = vlan_tagged_interface;
5626
5627 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5628 list[2].name = "vlan_bridge";
5629 list[2].value = vlan_bridge;
5630
5631 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5632 list[3].name = "vlan_naming";
5633 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005634
developerf5fef612022-09-20 19:38:26 +08005635 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5636 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005637 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005638 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005639
developerf5fef612022-09-20 19:38:26 +08005640 // restart this ap
5641 wifi_setApEnable(apIndex, FALSE);
5642 wifi_setApEnable(apIndex, TRUE);
5643
5644 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5645
5646 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005647}
5648
5649// 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.
5650INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5651{
5652 return RETURN_ERR;
5653}
5654
5655// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5656INT wifi_startHostApd()
5657{
5658 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5659 system("systemctl start hostapd.service");
5660 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5661 return RETURN_OK;
5662 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5663}
5664
5665// stops hostapd
5666INT wifi_stopHostApd()
5667{
5668 char cmd[128] = {0};
5669 char buf[128] = {0};
5670
5671 sprintf(cmd,"systemctl stop hostapd");
5672 _syscmd(cmd, buf, sizeof(buf));
5673
5674 return RETURN_OK;
5675}
5676
5677// restart hostapd dummy function
5678INT wifi_restartHostApd()
5679{
5680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5681 system("systemctl restart hostapd-global");
5682 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5683
5684 return RETURN_OK;
5685}
5686
5687static int align_hostapd_config(int index)
5688{
5689 ULONG lval;
5690 wifi_getRadioChannel(index%2, &lval);
5691 wifi_setRadioChannel(index%2, lval);
5692}
5693
5694// sets the AP enable status variable for the specified ap.
5695INT wifi_setApEnable(INT apIndex, BOOL enable)
5696{
5697 char config_file[MAX_BUF_SIZE] = {0};
5698 char cmd[MAX_CMD_SIZE] = {0};
5699 char buf[MAX_BUF_SIZE] = {0};
5700 BOOL status;
5701
5702 wifi_getApEnable(apIndex,&status);
5703 if (enable == status)
5704 return RETURN_OK;
5705
5706 if (enable == TRUE) {
5707 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5708 align_hostapd_config(apIndex);
5709 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5710 //Hostapd will bring up this interface
5711 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5712 _syscmd(cmd, buf, sizeof(buf));
5713 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5714 _syscmd(cmd, buf, sizeof(buf));
5715 }
5716 else {
5717 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5718 _syscmd(cmd, buf, sizeof(buf));
5719 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5720 _syscmd(cmd, buf, sizeof(buf));
5721 }
5722 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5723 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5724 _syscmd(cmd, buf, sizeof(buf));
5725 //Wait for wifi up/down to apply
5726 return RETURN_OK;
5727}
5728
5729// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5730INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5731{
5732 char cmd[MAX_CMD_SIZE] = {'\0'};
5733 char buf[MAX_BUF_SIZE] = {'\0'};
5734
5735 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5736 return RETURN_ERR;
5737
5738 *output_bool = 0;
5739
5740 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5741 {
developer70490032022-09-13 15:45:20 +08005742 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005743 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5744 }
5745
5746 return RETURN_OK;
5747}
5748
5749// Outputs the AP "Enabled" "Disabled" status from driver
5750INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5751{
5752 char cmd[128] = {0};
5753 char buf[128] = {0};
5754 BOOL output_bool;
5755
5756 if ( NULL == output_string)
5757 return RETURN_ERR;
5758 wifi_getApEnable(apIndex,&output_bool);
5759
5760 if(output_bool == 1)
5761 snprintf(output_string, 32, "Up");
5762 else
5763 snprintf(output_string, 32, "Disable");
5764
5765 return RETURN_OK;
5766}
5767
5768//Indicates whether or not beacons include the SSID name.
5769// outputs a 1 if SSID on the AP is enabled, else outputs 0
5770INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5771{
5772 //get the running status
5773 char config_file[MAX_BUF_SIZE] = {0};
5774 char buf[16] = {0};
5775
5776 if (!output)
5777 return RETURN_ERR;
5778
5779 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5780 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5781 *output = (strncmp("0",buf,1) == 0);
5782
5783 return RETURN_OK;
5784}
5785
5786// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5787INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5788{
5789 //store the config, apply instantly
5790 char config_file[MAX_BUF_SIZE] = {0};
5791 struct params list;
5792
5793 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5794 list.name = "ignore_broadcast_ssid";
5795 list.value = enable?"0":"1";
5796
5797 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5798 wifi_hostapdWrite(config_file, &list, 1);
5799 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5800 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005801 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005802 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5803
5804 return RETURN_OK;
5805}
5806
5807//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5808INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5809{
5810 //get the running status
5811 if(!output_uint)
5812 return RETURN_ERR;
5813 *output_uint=16;
5814 return RETURN_OK;
5815}
5816
5817INT wifi_setApRetryLimit(INT apIndex, UINT number)
5818{
5819 //apply instantly
5820 return RETURN_ERR;
5821}
5822
5823//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5824INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5825{
5826 if(!output)
5827 return RETURN_ERR;
5828 *output=TRUE;
5829 return RETURN_OK;
5830}
5831
5832//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5833INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5834{
5835 //get the running status from driver
5836 if(!output)
5837 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005838
5839 char config_file[MAX_BUF_SIZE] = {0};
5840 char buf[16] = {0};
5841
5842 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5843 wifi_hostapdRead(config_file, "uapsd_advertisement_enabled", buf, sizeof(buf));
5844 if (strncmp("1",buf,1) == 0)
5845 *output = TRUE;
5846 else
5847 *output = FALSE;
5848
developer06a01d92022-09-07 16:32:39 +08005849 return RETURN_OK;
5850}
5851
5852//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5853INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5854{
5855 //get the running status from driver
5856 if(!output)
5857 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005858
5859 char config_file[MAX_BUF_SIZE] = {0};
5860 char buf[16] = {0};
5861
5862 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5863 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5864 if (strncmp("1",buf,1) == 0)
5865 *output = TRUE;
5866 else
5867 *output = FALSE;
5868
developer06a01d92022-09-07 16:32:39 +08005869 return RETURN_OK;
5870}
5871
5872// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5873INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5874{
5875 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005876 char config_file[MAX_BUF_SIZE] = {0};
5877 struct params list;
5878
5879 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5880 list.name = "wmm_enabled";
5881 list.value = enable?"1":"0";
5882
5883 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5884 wifi_hostapdWrite(config_file, &list, 1);
5885 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5886 wifi_reloadAp(apIndex);
5887 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5888
5889 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005890}
5891
5892//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.
5893INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5894{
5895 //get the running status from driver
5896 if(!output)
5897 return RETURN_ERR;
5898 *output=TRUE;
5899 return RETURN_OK;
5900}
5901
5902// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5903INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5904{
5905 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005906 char config_file[MAX_BUF_SIZE] = {0};
5907 struct params list;
5908
5909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5910 list.name = "uapsd_advertisement_enabled";
5911 list.value = enable?"1":"0";
5912
5913 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5914 wifi_hostapdWrite(config_file, &list, 1);
5915 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5916 wifi_reloadAp(apIndex);
5917 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5918
5919 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005920}
5921
5922// Sets the WMM ACK polity on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
5923INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5924{
5925 //save config and apply instantly.
5926 return RETURN_ERR;
5927}
5928
5929//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.
5930INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5931{
5932 //get the running status from driver
5933 if(!output_uint)
5934 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005935
5936 char output[16]={'\0'};
5937 char config_file[MAX_BUF_SIZE] = {0};
5938
5939 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5940 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5941 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5942 else {
5943 int device_num = atoi(output);
5944 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5945 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5946 return RETURN_ERR;
5947 }
5948 else {
5949 *output_uint = device_num;
5950 }
5951 }
5952
developer06a01d92022-09-07 16:32:39 +08005953 return RETURN_OK;
5954}
5955
5956INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5957{
5958 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005959 char str[MAX_BUF_SIZE]={'\0'};
5960 char cmd[MAX_CMD_SIZE]={'\0'};
5961 struct params params;
5962 char config_file[MAX_BUF_SIZE] = {0};
5963
5964 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5965 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5966 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5967 return RETURN_ERR;
5968 }
5969 sprintf(str, "%d", number);
5970 params.name = "max_num_sta";
5971 params.value = str;
5972
5973 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5974 int ret = wifi_hostapdWrite(config_file, &params, 1);
5975 if (ret) {
5976 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5977 ,__func__, ret);
5978 }
5979
5980 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5981 if (ret) {
5982 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5983 ,__func__, ret);
5984 }
5985 wifi_reloadAp(apIndex);
5986 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5987
5988 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005989}
5990
5991//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.
5992INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5993{
5994 //get the current threshold
5995 if(!output_uint)
5996 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005997 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
5998 if (*output_uint == 0)
5999 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006000 return RETURN_OK;
6001}
6002
6003INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6004{
6005 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006006 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6007 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006008 return RETURN_ERR;
6009}
6010
6011//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.
6012INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6013{
6014 if(!output_uint)
6015 return RETURN_ERR;
6016 *output_uint = 3;
6017 return RETURN_OK;
6018}
6019
6020//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6021INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6022{
6023 if(!output_uint)
6024 return RETURN_ERR;
6025 *output_uint = 3;
6026 return RETURN_OK;
6027}
6028
6029//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.
6030INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6031{
6032 if(!output_in_seconds)
6033 return RETURN_ERR;
6034 *output_in_seconds = 0;
6035 return RETURN_OK;
6036}
6037
6038//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
6039INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6040{
6041 if(!output || apIndex>=MAX_APS)
6042 return RETURN_ERR;
6043 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006044 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006045 return RETURN_OK;
6046}
6047
6048//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6049INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6050{
developer587c1b62022-09-27 15:58:59 +08006051 char config_file[128] = {0};
6052 char wpa[16] = {0};
6053 char key_mgmt[64] = {0};
6054 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006055 if (!output)
6056 return RETURN_ERR;
6057
6058 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006059 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006060
developer587c1b62022-09-27 15:58:59 +08006061 strcpy(output, "None");//Copying "None" to output string for default case
6062 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6063 if (strstr(key_mgmt, "WPA-PSK")) {
6064 if (strcmp(wpa, "1"))
6065 snprintf(output, 32, "WPA-Personal");
6066 else if (strcmp(wpa, "2"))
6067 snprintf(output, 32, "WPA2-Personal");
6068 else if (strcmp(wpa, "3"))
6069 snprintf(output, 32, "WPA-WPA2-Personal");
6070
6071 } else if (strstr(key_mgmt, "WPA-EAP")) {
6072 if (strcmp(wpa, "1"))
6073 snprintf(output, 32, "WPA-Enterprise");
6074 else if (strcmp(wpa, "2"))
6075 snprintf(output, 32, "WPA2-Enterprise");
6076 else if (strcmp(wpa, "3"))
6077 snprintf(output, 32, "WPA-WPA2-Enterprise");
6078 } else if (strstr(key_mgmt, "SAE")) {
6079 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6080 int disable = strtol(buf, NULL, 16);
6081 if (disable & 0x1)
6082 snprintf(output, 32, "WPA3-Personal");
6083 else
6084 snprintf(output, 32, "WPA3-Transition");
6085 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6086 snprintf(output, 32, "WPA3-Enterprise");
6087 }
developer06a01d92022-09-07 16:32:39 +08006088
6089 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6090 return RETURN_OK;
6091#if 0
6092 //TODO: need to revisit below implementation
6093 char securityType[32], authMode[32];
6094 int enterpriseMode=0;
6095
6096 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6097 if(!output)
6098 return RETURN_ERR;
6099
6100 wifi_getApBeaconType(apIndex, securityType);
6101 strcpy(output,"None");//By default, copying "None" to output string
6102 if (strncmp(securityType,"None", strlen("None")) == 0)
6103 return RETURN_OK;
6104
6105 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6106 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6107
6108 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6109 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6110 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6111 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6112 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6113 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6114 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6115
6116 return RETURN_OK;
6117#endif
6118}
6119
6120INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6121{
6122 char securityType[32];
6123 char authMode[32];
6124
6125 //store settings and wait for wifi up to apply
6126 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6127 if(!encMode)
6128 return RETURN_ERR;
6129
developer06a01d92022-09-07 16:32:39 +08006130 if (strcmp(encMode, "None")==0)
6131 {
6132 strcpy(securityType,"None");
6133 strcpy(authMode,"None");
6134 }
6135 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6136 {
6137 strcpy(securityType,"WPAand11i");
6138 strcpy(authMode,"PSKAuthentication");
6139 }
6140 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6141 {
6142 strcpy(securityType,"WPAand11i");
6143 strcpy(authMode,"EAPAuthentication");
6144 }
6145 else if (strcmp(encMode, "WPA-Personal")==0)
6146 {
6147 strcpy(securityType,"WPA");
6148 strcpy(authMode,"PSKAuthentication");
6149 }
6150 else if (strcmp(encMode, "WPA-Enterprise")==0)
6151 {
6152 strcpy(securityType,"WPA");
6153 strcpy(authMode,"EAPAuthentication");
6154 }
6155 else if (strcmp(encMode, "WPA2-Personal")==0)
6156 {
6157 strcpy(securityType,"11i");
6158 strcpy(authMode,"PSKAuthentication");
6159 }
6160 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6161 {
6162 strcpy(securityType,"11i");
6163 strcpy(authMode,"EAPAuthentication");
6164 }
developer587c1b62022-09-27 15:58:59 +08006165 else if (strcmp(encMode, "WPA3-Personal") == 0)
6166 {
6167 strcpy(securityType,"11i");
6168 strcpy(authMode,"SAEAuthentication");
6169 }
6170 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6171 {
6172 strcpy(securityType,"11i");
6173 strcpy(authMode,"EAP_192-bit_Authentication");
6174 }
developer06a01d92022-09-07 16:32:39 +08006175 else
6176 {
6177 strcpy(securityType,"None");
6178 strcpy(authMode,"None");
6179 }
6180 wifi_setApBeaconType(apIndex, securityType);
6181 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6182 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6183
6184 return RETURN_OK;
6185}
6186
6187
6188//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6189// output_string must be pre-allocated as 64 character string by caller
6190// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6191INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6192{
6193 char buf[16];
6194 char config_file[MAX_BUF_SIZE] = {0};
6195
6196 if(output_string==NULL)
6197 return RETURN_ERR;
6198
6199 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6200 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6201
6202 if(strcmp(buf,"0")==0)
6203 {
6204 printf("wpa_mode is %s ......... \n",buf);
6205 return RETURN_ERR;
6206 }
6207
6208 wifi_dbg_printf("\nFunc=%s\n",__func__);
6209 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6210 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6211 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6212
6213 return RETURN_OK;
6214}
6215
6216// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6217// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6218INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6219{
6220 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6221 struct params params={'\0'};
6222 int ret;
6223 char config_file[MAX_BUF_SIZE] = {0};
6224
6225 if(NULL == preSharedKey)
6226 return RETURN_ERR;
6227
6228 params.name = "wpa_passphrase";
6229
6230 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6231 {
6232 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6233 return RETURN_ERR;
6234 }
6235 params.value = preSharedKey;
6236 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6237 ret = wifi_hostapdWrite(config_file, &params, 1);
6238 if(!ret)
6239 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6240 return ret;
6241 //TODO: call hostapd_cli for dynamic_config_control
6242}
6243
6244//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6245// outputs the passphrase, maximum 63 characters
6246INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6247{
6248 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6249
6250 wifi_dbg_printf("\nFunc=%s\n",__func__);
6251 if (NULL == output_string)
6252 return RETURN_ERR;
6253
6254 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6255 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6256 if(strcmp(buf,"0")==0)
6257 {
6258 printf("wpa_mode is %s ......... \n",buf);
6259 return RETURN_ERR;
6260 }
6261
6262 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6263 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6264
6265 return RETURN_OK;
6266}
6267
6268// sets the passphrase enviornment variable, max 63 characters
6269INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6270{
6271 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6272 struct params params={'\0'};
6273 char config_file[MAX_BUF_SIZE] = {0};
6274 int ret;
6275
6276 if(NULL == passPhrase)
6277 return RETURN_ERR;
6278
6279 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6280 {
6281 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6282 return RETURN_ERR;
6283 }
6284 params.name = "wpa_passphrase";
6285 params.value = passPhrase;
6286 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6287 ret=wifi_hostapdWrite(config_file,&params,1);
6288 if(!ret)
6289 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6290
6291 return ret;
6292}
6293
6294//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.
6295INT wifi_setApSecurityReset(INT apIndex)
6296{
developer8d583982022-09-20 11:28:22 +08006297 char original_config_file[64] = {0};
6298 char current_config_file[64] = {0};
6299 char buf[64] = {0};
6300 char cmd[64] = {0};
6301 char wpa[4] = {0};
6302 char wpa_psk[64] = {0};
6303 char wpa_passphrase[64] = {0};
6304 char wpa_psk_file[128] = {0};
6305 char wpa_key_mgmt[64] = {0};
6306 char wpa_pairwise[32] = {0};
6307 wifi_band band;
6308 struct params list[6];
6309
6310 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6311
6312 band = wifi_index_to_band(apIndex);
6313 if (band == band_2_4)
6314 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6315 else if (band = band_5)
6316 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6317 else if (band = band_6)
6318 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6319 else
6320 return RETURN_ERR;
6321
6322 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6323 list[0].name = "wpa";
6324 list[0].value = wpa;
6325
6326 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6327 list[1].name = "wpa_psk";
6328 list[1].value = wpa_psk;
6329
6330 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6331 list[2].name = "wpa_passphrase";
6332 list[2].value = wpa_passphrase;
6333
6334 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6335
6336 if (strlen(wpa_psk_file) == 0)
6337 strcpy(wpa_psk_file, PSK_FILE);
6338
6339 if (access(wpa_psk_file, F_OK) != 0) {
6340 sprintf(cmd, "touch %s", wpa_psk_file);
6341 _syscmd(cmd, buf, sizeof(buf));
6342 }
6343 list[3].name = "wpa_psk_file";
6344 list[3].value = wpa_psk_file;
6345
6346 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6347 list[4].name = "wpa_key_mgmt";
6348 list[4].value = wpa_key_mgmt;
6349
6350 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6351 list[5].name = "wpa_pairwise";
6352 list[5].value = wpa_pairwise;
6353
6354 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6355 wifi_hostapdWrite(current_config_file, list, 6);
6356
6357 wifi_setApEnable(apIndex, FALSE);
6358 wifi_setApEnable(apIndex, TRUE);
6359
6360 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6361 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006362}
6363
6364//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).
6365INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6366{
developer8f2ddd52022-09-13 15:39:24 +08006367 char config_file[64] = {0};
6368 char buf[64] = {0};
6369 char cmd[256] = {0};
6370
6371 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6372
developer06a01d92022-09-07 16:32:39 +08006373 if(!IP_output || !Port_output || !RadiusSecret_output)
6374 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006375
developer8f2ddd52022-09-13 15:39:24 +08006376 // Read the first matched config
6377 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6378 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6379 _syscmd(cmd, buf, sizeof(buf));
6380 strncpy(IP_output, buf, 64);
6381
6382 memset(buf, 0, sizeof(buf));
6383 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6384 _syscmd(cmd, buf, sizeof(buf));
6385 *Port_output = atoi(buf);
6386
6387 memset(buf, 0, sizeof(buf));
6388 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6389 _syscmd(cmd, buf, sizeof(buf));
6390 strncpy(RadiusSecret_output, buf, 64);
6391
6392 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006393 return RETURN_OK;
6394}
6395
6396INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6397{
developer8f2ddd52022-09-13 15:39:24 +08006398 char config_file[64] = {0};
6399 char port_str[8] = {0};
6400 char cmd[256] = {0};
6401 char buf[128] = {0};
6402
6403 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6404
6405 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6406
6407 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6408 _syscmd(cmd, buf, sizeof(buf));
6409 memset(cmd, 0, sizeof(cmd));
6410
6411 snprintf(port_str, sizeof(port_str), "%d", port);
6412 if (strlen(buf) == 0)
6413 // Append
6414 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6415 "auth_server_addr=%s\\n"
6416 "auth_server_port=%s\\n"
6417 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6418 else {
6419 // Delete the three lines setting after the "# radius 1" comment
6420 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6421 _syscmd(cmd, buf, sizeof(buf));
6422 memset(cmd, 0, sizeof(cmd));
6423 // Use "# radius 1" comment to find the location to insert the radius setting
6424 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6425 "# radius 1\\n"
6426 "auth_server_addr=%s\\n"
6427 "auth_server_port=%s\\n"
6428 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6429 }
6430 if(_syscmd(cmd, buf, sizeof(buf))) {
6431 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6432 return RETURN_ERR;
6433 }
6434
6435 wifi_reloadAp(apIndex);
6436 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6437 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006438}
6439
6440INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6441{
developer8f2ddd52022-09-13 15:39:24 +08006442 char config_file[64] = {0};
6443 char buf[64] = {0};
6444 char cmd[256] = {0};
6445
6446 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6447
developer06a01d92022-09-07 16:32:39 +08006448 if(!IP_output || !Port_output || !RadiusSecret_output)
6449 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006450
6451 // Read the second matched config
6452 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6453 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6454 _syscmd(cmd, buf, sizeof(buf));
6455 strncpy(IP_output, buf, 64);
6456
6457 memset(buf, 0, sizeof(buf));
6458 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6459 _syscmd(cmd, buf, sizeof(buf));
6460 *Port_output = atoi(buf);
6461
6462 memset(buf, 0, sizeof(buf));
6463 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6464 _syscmd(cmd, buf, sizeof(buf));
6465 strncpy(RadiusSecret_output, buf, 64);
6466
6467 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006468 return RETURN_OK;
6469}
6470
6471INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6472{
developer8f2ddd52022-09-13 15:39:24 +08006473 char config_file[64] = {0};
6474 char port_str[8] = {0};
6475 char cmd[256] = {0};
6476 char buf[128] = {0};
6477
6478 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6479
6480 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6481
6482 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6483 _syscmd(cmd, buf, sizeof(buf));
6484 memset(cmd, 0, sizeof(cmd));
6485
6486 snprintf(port_str, sizeof(port_str), "%d", port);
6487 if (strlen(buf) == 0)
6488 // Append
6489 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6490 "auth_server_addr=%s\\n"
6491 "auth_server_port=%s\\n"
6492 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6493 else {
6494 // Delete the three lines setting after the "# radius 2" comment
6495 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6496 _syscmd(cmd, buf, sizeof(buf));
6497 memset(cmd, 0, sizeof(cmd));
6498 // Use "# radius 2" comment to find the location to insert the radius setting
6499 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6500 "# radius 2\\n"
6501 "auth_server_addr=%s\\n"
6502 "auth_server_port=%s\\n"
6503 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6504 }
6505 if(_syscmd(cmd, buf, sizeof(buf))) {
6506 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6507 return RETURN_ERR;
6508 }
6509
6510 wifi_reloadAp(apIndex);
6511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6512 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006513}
6514
6515//RadiusSettings
6516INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6517{
6518 if(!output)
6519 return RETURN_ERR;
6520
6521 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6522 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6523 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6524 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6525 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6526 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.
6527 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6528 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6529 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6530 //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.
6531
6532 return RETURN_OK;
6533}
6534
6535INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6536{
6537 //store the paramters, and apply instantly
6538 return RETURN_ERR;
6539}
6540
6541//Device.WiFi.AccessPoint.{i}.WPS.Enable
6542//Enables or disables WPS functionality for this access point.
6543// outputs the WPS enable state of this ap in output_bool
6544INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6545{
6546 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6547 if(!output_bool || !(apIndex==0 || apIndex==1))
6548 return RETURN_ERR;
6549 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6550 _syscmd(cmd, buf, sizeof(buf));
6551 if(strstr(buf, "configured"))
6552 *output_bool=TRUE;
6553 else
6554 *output_bool=FALSE;
6555
6556 return RETURN_OK;
6557}
6558
6559//Device.WiFi.AccessPoint.{i}.WPS.Enable
6560// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6561INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6562{
6563 char config_file[MAX_BUF_SIZE] = {0};
6564 struct params params;
6565
6566 if(!(apIndex==0 || apIndex==1))
6567 return RETURN_ERR;
6568 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6569 //store the paramters, and wait for wifi up to apply
6570 params.name = "wps_state";
6571 params.value = enable ? "2":"0";
6572
6573 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6574 wifi_hostapdWrite(config_file, &params, 1);
6575 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6576 wifi_reloadAp(apIndex);
6577
6578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6579 return RETURN_OK;
6580}
6581
6582//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
6583INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6584{
6585 if(!output)
6586 return RETURN_ERR;
6587 snprintf(output, 128, "PushButton,PIN");
6588 return RETURN_OK;
6589}
6590
6591//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6592//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.
6593// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6594INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6595{
6596 if(!output)
6597 return RETURN_ERR;
6598 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6599
6600 return RETURN_OK;
6601}
6602
6603//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6604// 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
6605INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6606{
6607 //apply instantly. No setting need to be stored.
6608 char methods[MAX_BUF_SIZE], *token, *next_token;
6609 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6610 struct params params;
6611
6612 if(!methodString || !(apIndex==0 || apIndex==1))
6613 return RETURN_ERR;
6614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6615 //store the paramters, and wait for wifi up to apply
6616
6617 snprintf(methods, sizeof(methods), "%s", methodString);
6618 for(token=methods; *token; token=next_token)
6619 {
6620 strtok_r(token, ",", &next_token);
6621 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6622 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6623 else if(*token=='E')
6624 {
6625 if(!strcmp(methods, "Ethernet"))
6626 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6627 else if(!strcmp(methods, "ExternalNFCToken"))
6628 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6629 else
6630 printf("%s: Unknown WpsConfigMethod\n", __func__);
6631 }
6632 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6633 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6634 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6635 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6636 else if(*token=='P' )
6637 {
6638 if(!strcmp(token, "PushButton"))
6639 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6640 else if(!strcmp(token, "PIN"))
6641 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6642 else
6643 printf("%s: Unknown WpsConfigMethod\n", __func__);
6644 }
6645 else
6646 printf("%s: Unknown WpsConfigMethod\n", __func__);
6647 }
6648 params.name = "config_methods";
6649 params.value = config_methods;
6650 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6651 wifi_hostapdWrite(config_file, &params, 1);
6652 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6653 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6654
6655 return RETURN_OK;
6656}
6657
6658// outputs the pin value, ulong_pin must be allocated by the caller
6659INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6660{
6661 char buf[MAX_BUF_SIZE] = {0};
6662 char cmd[MAX_CMD_SIZE] = {0};
6663
6664 if(!output_ulong || !(apIndex==0 || apIndex==1))
6665 return RETURN_ERR;
6666 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6667 _syscmd(cmd, buf, sizeof(buf));
6668 if(strlen(buf) > 0)
6669 *output_ulong=strtoul(buf, NULL, 10);
6670
6671 return RETURN_OK;
6672}
6673
6674// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6675INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6676{
6677 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6678 char ap_pin[16] = {0};
6679 char buf[MAX_BUF_SIZE] = {0};
6680 char config_file[MAX_BUF_SIZE] = {0};
6681 ULONG prev_pin = 0;
6682 struct params params;
6683
6684 if(!(apIndex==0 || apIndex==1))
6685 return RETURN_ERR;
6686 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6687 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6688 params.name = "ap_pin";
6689 params.value = ap_pin;
6690 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6691 wifi_hostapdWrite(config_file, &params, 1);
6692 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6693 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6694
6695 return RETURN_OK;
6696}
6697
6698// Output string is either Not configured or Configured, max 32 characters
6699INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6700{
6701 char cmd[MAX_CMD_SIZE];
6702 char buf[MAX_BUF_SIZE]={0};
6703
6704 if(!output_string || !(apIndex==0 || apIndex==1))
6705 return RETURN_ERR;
6706 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6707 snprintf(output_string, 32, "Not configured");
6708 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6709 _syscmd(cmd, buf, sizeof(buf));
6710
developer348e3d92022-09-13 14:48:41 +08006711 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006712 snprintf(output_string, 32, "Configured");
6713 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6714
6715 return RETURN_OK;
6716}
6717
6718// sets the WPS pin for this AP
6719INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6720{
6721 char cmd[MAX_CMD_SIZE];
6722 char buf[MAX_BUF_SIZE]={0};
6723 BOOL enable;
6724
6725 if(!(apIndex==0 || apIndex==1))
6726 return RETURN_ERR;
6727 wifi_getApEnable(apIndex, &enable);
6728 if (!enable)
6729 return RETURN_ERR;
6730 wifi_getApWpsEnable(apIndex, &enable);
6731 if (!enable)
6732 return RETURN_ERR;
6733
6734 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6735 _syscmd(cmd, buf, sizeof(buf));
6736 if((strstr(buf, "OK"))!=NULL)
6737 return RETURN_OK;
6738
6739 return RETURN_ERR;
6740}
6741
6742// This function is called when the WPS push button has been pressed for this AP
6743INT wifi_setApWpsButtonPush(INT apIndex)
6744{
6745 char cmd[MAX_CMD_SIZE];
6746 char buf[MAX_BUF_SIZE]={0};
6747 BOOL enable=FALSE;
6748
6749 if(!(apIndex==0 || apIndex==1))
6750 return RETURN_ERR;
6751 wifi_getApEnable(apIndex, &enable);
6752 if (!enable)
6753 return RETURN_ERR;
6754
6755 wifi_getApWpsEnable(apIndex, &enable);
6756 if (!enable)
6757 return RETURN_ERR;
6758
6759 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6760 _syscmd(cmd, buf, sizeof(buf));
6761
6762 if((strstr(buf, "OK"))!=NULL)
6763 return RETURN_OK;
6764 return RETURN_ERR;
6765}
6766
6767// cancels WPS mode for this AP
6768INT wifi_cancelApWPS(INT apIndex)
6769{
6770 char cmd[MAX_CMD_SIZE];
6771 char buf[MAX_BUF_SIZE]={0};
6772
6773 if(!(apIndex==0 || apIndex==1))
6774 return RETURN_ERR;
6775 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6776 _syscmd(cmd,buf, sizeof(buf));
6777
6778 if((strstr(buf, "OK"))!=NULL)
6779 return RETURN_OK;
6780 return RETURN_ERR;
6781}
6782
6783//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6784//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6785INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6786{
6787 FILE *f;
6788 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6789 char cmd[256], buf[2048];
6790 char *param , *value, *line=NULL;
6791 size_t len = 0;
6792 ssize_t nread;
6793 wifi_associated_dev_t *dev=NULL;
6794
6795 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6796 *associated_dev_array = NULL;
6797 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6798 _syscmd(cmd,buf,sizeof(buf));
6799 *output_array_size = atoi(buf);
6800
6801 if (*output_array_size <= 0)
6802 return RETURN_OK;
6803
6804 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6805 *associated_dev_array = dev;
6806 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6807 _syscmd(cmd,buf,sizeof(buf));
6808 f = fopen("/tmp/connected_devices.txt", "r");
6809 if (f==NULL)
6810 {
6811 *output_array_size=0;
6812 return RETURN_ERR;
6813 }
6814 while ((nread = getline(&line, &len, f)) != -1)
6815 {
6816 param = strtok(line,"=");
6817 value = strtok(NULL,"=");
6818
6819 if( strcmp("flags",param) == 0 )
6820 {
6821 value[strlen(value)-1]='\0';
6822 if(strstr (value,"AUTHORIZED") != NULL )
6823 {
6824 dev[auth_temp].cli_AuthenticationState = 1;
6825 dev[auth_temp].cli_Active = 1;
6826 auth_temp++;
6827 read_flag=1;
6828 }
6829 }
6830 if(read_flag==1)
6831 {
6832 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6833 {
6834 value[strlen(value)-1]='\0';
6835 sscanf(value, "%x:%x:%x:%x:%x:%x",
6836 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6837 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6838 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6839 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6840 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6841 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6842 mac_temp++;
6843 read_flag=0;
6844 }
6845 }
6846 }
6847 *output_array_size = auth_temp;
6848 auth_temp=0;
6849 mac_temp=0;
6850 free(line);
6851 fclose(f);
6852 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6853 return RETURN_OK;
6854}
6855
6856#define MACADDRESS_SIZE 6
6857
6858INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6859{
6860 FILE *fp = NULL;
6861 char str[MAX_BUF_SIZE] = {0};
6862 int wificlientindex = 0 ;
6863 int count = 0;
6864 int signalstrength = 0;
6865 int arr[MACADDRESS_SIZE] = {0};
6866 unsigned char mac[MACADDRESS_SIZE] = {0};
6867 UINT wifi_count = 0;
6868 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6869 char pipeCmd[MAX_CMD_SIZE] = {0};
6870
6871 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6872 *output_array_size = 0;
6873 *associated_dev_array = NULL;
6874
6875 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6876 fp = popen(pipeCmd, "r");
6877 if (fp == NULL)
6878 {
6879 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6880 return RETURN_ERR;
6881 }
6882
6883 /* Read the output a line at a time - output it. */
6884 fgets(str, sizeof(str)-1, fp);
6885 wifi_count = (unsigned int) atoi ( str );
6886 *output_array_size = wifi_count;
6887 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6888 pclose(fp);
6889
6890 if(wifi_count == 0)
6891 {
6892 return RETURN_OK;
6893 }
6894 else
6895 {
6896 wifi_associated_dev3_t* temp = NULL;
6897 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6898 if(temp == NULL)
6899 {
6900 printf("Error Statement. Insufficient memory \n");
6901 return RETURN_ERR;
6902 }
6903
6904 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6905 system(pipeCmd);
6906 memset(pipeCmd,0,sizeof(pipeCmd));
6907 if(apIndex == 0)
6908 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6909 else if(apIndex == 1)
6910 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6911 system(pipeCmd);
6912
6913 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6914 if(fp == NULL)
6915 {
6916 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6917 return RETURN_ERR;
6918 }
6919 fclose(fp);
6920
6921 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6922 fp = popen(pipeCmd, "r");
6923 if(fp)
6924 {
6925 for(count =0 ; count < wifi_count; count++)
6926 {
6927 fgets(str, MAX_BUF_SIZE, fp);
6928 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6929 {
6930 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6931 {
6932 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6933
6934 }
6935 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6936 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]);
6937 }
6938 temp[count].cli_AuthenticationState = 1; //TODO
6939 temp[count].cli_Active = 1; //TODO
6940 }
6941 pclose(fp);
6942 }
6943
6944 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6945 fp = popen(pipeCmd, "r");
6946 if(fp)
6947 {
6948 pclose(fp);
6949 }
6950 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6951 if(fp)
6952 {
6953 for(count =0 ; count < wifi_count ;count++)
6954 {
6955 fgets(str, MAX_BUF_SIZE, fp);
6956 signalstrength = atoi(str);
6957 temp[count].cli_SignalStrength = signalstrength;
6958 temp[count].cli_RSSI = signalstrength;
6959 temp[count].cli_SNR = signalstrength + 95;
6960 }
6961 pclose(fp);
6962 }
6963
6964
6965 if((apIndex == 0) || (apIndex == 4))
6966 {
6967 for(count =0 ; count < wifi_count ;count++)
6968 {
6969 strcpy(temp[count].cli_OperatingStandard,"g");
6970 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6971 }
6972
6973 //BytesSent
6974 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6975 fp = popen(pipeCmd, "r");
6976 if(fp)
6977 {
6978 pclose(fp);
6979 }
6980 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6981 if(fp)
6982 {
6983 for (count = 0; count < wifi_count; count++)
6984 {
6985 fgets(str, MAX_BUF_SIZE, fp);
6986 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6987 }
6988 pclose(fp);
6989 }
6990
6991 //BytesReceived
6992 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6993 fp = popen(pipeCmd, "r");
6994 if (fp)
6995 {
6996 pclose(fp);
6997 }
6998 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
6999 if (fp)
7000 {
7001 for (count = 0; count < wifi_count; count++)
7002 {
7003 fgets(str, MAX_BUF_SIZE, fp);
7004 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7005 }
7006 pclose(fp);
7007 }
7008
7009 //PacketsSent
7010 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7011 fp = popen(pipeCmd, "r");
7012 if (fp)
7013 {
7014 pclose(fp);
7015 }
7016
7017 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7018 if (fp)
7019 {
7020 for (count = 0; count < wifi_count; count++)
7021 {
7022 fgets(str, MAX_BUF_SIZE, fp);
7023 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7024 }
7025 pclose(fp);
7026 }
7027
7028 //PacketsReceived
7029 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7030 fp = popen(pipeCmd, "r");
7031 if (fp)
7032 {
7033 pclose(fp);
7034 }
7035 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7036 if (fp)
7037 {
7038 for (count = 0; count < wifi_count; count++)
7039 {
7040 fgets(str, MAX_BUF_SIZE, fp);
7041 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7042 }
7043 pclose(fp);
7044 }
7045
7046 //ErrorsSent
7047 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7048 fp = popen(pipeCmd, "r");
7049 if (fp)
7050 {
7051 pclose(fp);
7052 }
7053 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7054 if (fp)
7055 {
7056 for (count = 0; count < wifi_count; count++)
7057 {
7058 fgets(str, MAX_BUF_SIZE, fp);
7059 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7060 }
7061 pclose(fp);
7062 }
7063
7064 //ErrorsSent
7065 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7066 fp = popen(pipeCmd, "r");
7067 if (fp)
7068 {
7069 pclose(fp);
7070 }
7071 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7072 if (fp)
7073 {
7074 for (count = 0; count < wifi_count; count++)
7075 {
7076 fgets(str, MAX_BUF_SIZE, fp);
7077 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7078 }
7079 pclose(fp);
7080 }
7081
7082 //LastDataDownlinkRate
7083 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7084 fp = popen(pipeCmd, "r");
7085 if (fp)
7086 {
7087 pclose(fp);
7088 }
7089 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7090 if (fp)
7091 {
7092 for (count = 0; count < wifi_count; count++)
7093 {
7094 fgets(str, MAX_BUF_SIZE, fp);
7095 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7096 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7097 }
7098 pclose(fp);
7099 }
7100
7101 //LastDataUplinkRate
7102 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7103 fp = popen(pipeCmd, "r");
7104 if (fp)
7105 {
7106 pclose(fp);
7107 }
7108 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7109 if (fp)
7110 {
7111 for (count = 0; count < wifi_count; count++)
7112 {
7113 fgets(str, MAX_BUF_SIZE, fp);
7114 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7115 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7116 }
7117 pclose(fp);
7118 }
7119
7120 }
7121 else if ((apIndex == 1) || (apIndex == 5))
7122 {
7123 for (count = 0; count < wifi_count; count++)
7124 {
7125 strcpy(temp[count].cli_OperatingStandard, "a");
7126 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7127 temp[count].cli_BytesSent = 0;
7128 temp[count].cli_BytesReceived = 0;
7129 temp[count].cli_LastDataUplinkRate = 0;
7130 temp[count].cli_LastDataDownlinkRate = 0;
7131 temp[count].cli_PacketsSent = 0;
7132 temp[count].cli_PacketsReceived = 0;
7133 temp[count].cli_ErrorsSent = 0;
7134 }
7135 }
7136
7137 for (count = 0; count < wifi_count; count++)
7138 {
7139 temp[count].cli_Retransmissions = 0;
7140 temp[count].cli_DataFramesSentAck = 0;
7141 temp[count].cli_DataFramesSentNoAck = 0;
7142 temp[count].cli_MinRSSI = 0;
7143 temp[count].cli_MaxRSSI = 0;
7144 strncpy(temp[count].cli_InterferenceSources, "", 64);
7145 memset(temp[count].cli_IPAddress, 0, 64);
7146 temp[count].cli_RetransCount = 0;
7147 temp[count].cli_FailedRetransCount = 0;
7148 temp[count].cli_RetryCount = 0;
7149 temp[count].cli_MultipleRetryCount = 0;
7150 }
7151 *associated_dev_array = temp;
7152 }
7153 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7154 return RETURN_OK;
7155}
7156
7157int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7158{
7159 FILE *fp = NULL;
7160 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7161 char cmd[MAX_CMD_SIZE];
7162 int count = 0;
7163
7164 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7165 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7166 fp = popen(cmd,"r");
7167 if(fp == NULL)
7168 {
7169 printf("Failed to run command in Function %s\n",__FUNCTION__);
7170 return 0;
7171 }
7172 if(fgets(path, sizeof(path)-1, fp) != NULL)
7173 {
7174 for(count=0;path[count]!='\n';count++)
7175 status[count]=path[count];
7176 status[count]='\0';
7177 }
7178 strcpy(wifi_status,status);
7179 pclose(fp);
7180 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7181 return RETURN_OK;
7182}
7183
7184/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7185struct hostapd_sta_param {
7186 char key[50];
7187 char value[100];
7188}
7189
7190static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7191 int i = 0;
7192
7193 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7194 if (strncmp(params[i].key,key,50) == 0){
7195 return &params[i].value;
7196 }
7197 i++;
7198 }
7199 return NULL;
7200
7201} */
7202
7203static unsigned int count_occurences(const char *buf, const char *word)
7204{
7205 unsigned int n = 0;
7206 char *ptr = strstr(buf, word);
7207
7208 while (ptr++) {
7209 n++;
7210 ptr = strstr(ptr, word);
7211 }
7212
7213 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7214 return n;
7215}
7216
7217static const char *get_line_from_str_buf(const char *buf, char *line)
7218{
7219 int i;
7220 int n = strlen(buf);
7221
7222 for (i = 0; i < n; i++) {
7223 line[i] = buf[i];
7224 if (buf[i] == '\n') {
7225 line[i] = '\0';
7226 return &buf[i + 1];
7227 }
7228 }
7229
7230 return NULL;
7231}
7232
7233INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7234{
7235 unsigned int assoc_cnt = 0;
7236 char interface_name[50] = {0};
7237 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7238 char cmd[MAX_CMD_SIZE] = {'\0'};
7239 char line[256] = {'\0'};
7240 int i = 0;
7241 int ret = 0;
7242 const char *ptr = NULL;
7243 char *key = NULL;
7244 char *val = NULL;
7245 wifi_associated_dev3_t *temp = NULL;
7246 int rssi;
7247
7248 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7249
7250 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7251 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7252 return RETURN_ERR;
7253 }
7254
7255 // Example filtered output of 'iw dev' command:
7256 // Station 0a:69:72:10:d2:fa (on wifi0)
7257 // signal avg:-67 [-71, -71] dBm
7258 // Station 28:c2:1f:25:5f:99 (on wifi0)
7259 // signal avg:-67 [-71, -70] dBm
7260 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7261 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7262 return RETURN_ERR;
7263 }
7264
7265 ret = _syscmd(cmd, buf, sizeof(buf));
7266 if (ret == RETURN_ERR) {
7267 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7268 return RETURN_ERR;
7269 }
7270
7271 *output_array_size = count_occurences(buf, "Station");
7272 if (*output_array_size == 0) return RETURN_OK;
7273
7274 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7275 if (temp == NULL) {
7276 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7277 return RETURN_ERR;
7278 }
7279 *associated_dev_array = temp;
7280
7281 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7282 ptr = get_line_from_str_buf(buf, line);
7283 i = -1;
7284 while (ptr) {
7285 if (strstr(line, "Station")) {
7286 i++;
7287 key = strtok(line, " ");
7288 val = strtok(NULL, " ");
7289 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7290 &temp[i].cli_MACAddress[0],
7291 &temp[i].cli_MACAddress[1],
7292 &temp[i].cli_MACAddress[2],
7293 &temp[i].cli_MACAddress[3],
7294 &temp[i].cli_MACAddress[4],
7295 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7296 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7297 free(*associated_dev_array);
7298 return RETURN_ERR;
7299 }
7300 }
7301 else if (i < 0) {
7302 ptr = get_line_from_str_buf(ptr, line);
7303 continue; // We didn't detect 'station' entry yet
7304 }
7305 else if (strstr(line, "signal avg")) {
7306 key = strtok(line, ":");
7307 val = strtok(NULL, " ");
7308 if (sscanf(val, "%d", &rssi) <= 0 ) {
7309 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7310 free(*associated_dev_array);
7311 return RETURN_ERR;
7312 }
7313 temp[i].cli_RSSI = rssi;
7314 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7315 }
7316 // Here other fields can be parsed if added to filter of 'iw dev' command
7317
7318 ptr = get_line_from_str_buf(ptr, line);
7319 };
7320
7321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7322
7323 return RETURN_OK;
7324}
7325
7326#if 0
7327//To-do
7328INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7329{
7330 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7331
7332 //Using different approach to get required WiFi Parameters from system available commands
7333#if 0
7334 FILE *f;
7335 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7336 char cmd[256], buf[2048];
7337 char *param , *value, *line=NULL;
7338 size_t len = 0;
7339 ssize_t nread;
7340 wifi_associated_dev3_t *dev=NULL;
7341 *associated_dev_array = NULL;
7342 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7343 _syscmd(cmd,buf,sizeof(buf));
7344 *output_array_size = atoi(buf);
7345
7346 if (*output_array_size <= 0)
7347 return RETURN_OK;
7348
7349 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7350 *associated_dev_array = dev;
7351 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7352 _syscmd(cmd,buf,sizeof(buf));
7353 f = fopen("/tmp/connected_devices.txt", "r");
7354 if (f==NULL)
7355 {
7356 *output_array_size=0;
7357 return RETURN_ERR;
7358 }
7359 while ((nread = getline(&line, &len, f)) != -1)
7360 {
7361 param = strtok(line,"=");
7362 value = strtok(NULL,"=");
7363
7364 if( strcmp("flags",param) == 0 )
7365 {
7366 value[strlen(value)-1]='\0';
7367 if(strstr (value,"AUTHORIZED") != NULL )
7368 {
7369 dev[auth_temp].cli_AuthenticationState = 1;
7370 dev[auth_temp].cli_Active = 1;
7371 auth_temp++;
7372 read_flag=1;
7373 }
7374 }
7375 if(read_flag==1)
7376 {
7377 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7378 {
7379 value[strlen(value)-1]='\0';
7380 sscanf(value, "%x:%x:%x:%x:%x:%x",
7381 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7382 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7383 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7384 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7385 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7386 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7387
7388 }
7389 else if( strcmp("rx_packets",param) == 0 )
7390 {
7391 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7392 }
7393
7394 else if( strcmp("tx_packets",param) == 0 )
7395 {
7396 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7397 }
7398
7399 else if( strcmp("rx_bytes",param) == 0 )
7400 {
7401 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7402 }
7403
7404 else if( strcmp("tx_bytes",param) == 0 )
7405 {
7406 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7407 mac_temp++;
7408 read_flag=0;
7409 }
7410 }
7411 }
7412
7413 *output_array_size = auth_temp;
7414 auth_temp=0;
7415 mac_temp=0;
7416 free(line);
7417 fclose(f);
7418#endif
7419 char interface_name[MAX_BUF_SIZE] = {0};
7420 char wifi_status[MAX_BUF_SIZE] = {0};
7421 char hostapdconf[MAX_BUF_SIZE] = {0};
7422
7423 wifi_associated_dev3_t *dev_array = NULL;
7424 ULONG wifi_count = 0;
7425
7426 *associated_dev_array = NULL;
7427 *output_array_size = 0;
7428
7429 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7430 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7431 {
7432 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7433
7434 GetInterfaceName(interface_name, hostapdconf);
7435
7436 if(strlen(interface_name) > 1)
7437 {
7438 wifihal_interfacestatus(wifi_status,interface_name);
7439 if(strcmp(wifi_status,"RUNNING") == 0)
7440 {
7441 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7442
7443 *associated_dev_array = dev_array;
7444 *output_array_size = wifi_count;
7445 }
7446 else
7447 {
7448 *associated_dev_array = NULL;
7449 }
7450 }
7451 }
7452
7453 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7454 return RETURN_OK;
7455}
7456#endif
7457
7458/* getIPAddress function */
7459/**
7460* @description Returning IpAddress of the Matched String
7461*
7462* @param
7463* @str Having MacAddress
7464* @ipaddr Having ipaddr
7465* @return The status of the operation
7466* @retval RETURN_OK if successful
7467* @retval RETURN_ERR if any error is detected
7468*
7469*/
7470
7471INT getIPAddress(char *str,char *ipaddr)
7472{
7473 FILE *fp = NULL;
7474 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7475 int LeaseTime = 0,ret = 0;
7476 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7477 {
7478 return RETURN_ERR;
7479 }
7480
7481 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7482 {
7483 /*
7484 Sample:sss
7485 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7486 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7487 */
7488 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7489 &(LeaseTime),
7490 phyAddr,
7491 ipAddr,
7492 hostName
7493 );
7494 if(ret != 4)
7495 continue;
7496 if(strcmp(str,phyAddr) == 0)
7497 strcpy(ipaddr,ipAddr);
7498 }
7499 return RETURN_OK;
7500}
7501
7502/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7503/**
7504* @description Returning Inactive wireless connected clients informations
7505*
7506* @param
7507* @filename Holding private_wifi 2g/5g content files
7508* @associated_dev_array Having inactiv wireless clients informations
7509* @output_array_size Returning Inactive wireless counts
7510* @return The status of the operation
7511* @retval RETURN_OK if successful
7512* @retval RETURN_ERR if any error is detected
7513*
7514*/
7515
7516INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7517{
7518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7519 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7520 FILE *fp = NULL;
7521 int arr[MACADDRESS_SIZE] = {0};
7522 unsigned char mac[MACADDRESS_SIZE] = {0};
7523 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7524 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7525 fp = popen(buf,"r");
7526 if(fp == NULL)
7527 return RETURN_ERR;
7528 else
7529 {
7530 fgets(path,sizeof(path),fp);
7531 maccount = atoi(path);
7532 }
7533 pclose(fp);
7534 *output_array_size = maccount;
7535 wifi_associated_dev3_t* temp = NULL;
7536 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7537 *associated_dev_array = temp;
7538 if(temp == NULL)
7539 {
7540 printf("Error Statement. Insufficient memory \n");
7541 return RETURN_ERR;
7542 }
7543 memset(buf,0,sizeof(buf));
7544 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7545 fp = popen(buf,"r");
7546 for(count = 0; count < maccount ; count++)
7547 {
7548 fgets(path,sizeof(path),fp);
7549 for(i = 0; path[i]!='\n';i++)
7550 str[i]=path[i];
7551 str[i]='\0';
7552 getIPAddress(str,ipaddr);
7553 memset(buf,0,sizeof(buf));
7554 if(strlen(ipaddr) > 0)
7555 {
7556 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7557 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7558 {
7559 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7560 {
7561 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7562 {
7563 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7564
7565 }
7566 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7567 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]);
7568 }
7569 temp[count].cli_AuthenticationState = 0; //TODO
7570 temp[count].cli_Active = 0; //TODO
7571 temp[count].cli_SignalStrength = 0;
7572 }
7573 else //Active wireless clients info
7574 {
7575 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7576 {
7577 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7578 {
7579 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7580
7581 }
7582 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7583 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]);
7584 }
7585 temp[count].cli_Active = 1;
7586 }
7587 }
7588 memset(ipaddr,0,sizeof(ipaddr));
7589 }
7590 pclose(fp);
7591 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7592 return RETURN_OK;
7593}
7594//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7595//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7596//To get Band Steering Capability
7597INT wifi_getBandSteeringCapability(BOOL *support)
7598{
7599 *support = FALSE;
7600 return RETURN_OK;
7601}
7602
7603
7604//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7605//To get Band Steering enable status
7606INT wifi_getBandSteeringEnable(BOOL *enable)
7607{
7608 *enable = FALSE;
7609 return RETURN_OK;
7610}
7611
7612//To turn on/off Band steering
7613INT wifi_setBandSteeringEnable(BOOL enable)
7614{
7615 return RETURN_OK;
7616}
7617
7618//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7619//To get Band Steering AP group
7620INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7621{
7622 if (NULL == output_ApGroup)
7623 return RETURN_ERR;
7624
7625 strcpy(output_ApGroup, "1,2");
7626 return RETURN_OK;
7627}
7628
7629//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7630//to set and read the band steering BandUtilizationThreshold parameters
7631INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7632{
7633 return RETURN_ERR;
7634}
7635
7636INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7637{
7638 return RETURN_ERR;
7639}
7640
7641//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7642//to set and read the band steering RSSIThreshold parameters
7643INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7644{
7645 return RETURN_ERR;
7646}
7647
7648INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7649{
7650 return RETURN_ERR;
7651}
7652
7653
7654//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7655//to set and read the band steering physical modulation rate threshold parameters
7656INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7657{
7658 //If chip is not support, return -1
7659 return RETURN_ERR;
7660}
7661
7662INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7663{
7664 //If chip is not support, return -1
7665 return RETURN_ERR;
7666}
7667
7668//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7669//to set and read the inactivity time (in seconds) for steering under overload condition
7670INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7671{
7672 return RETURN_ERR;
7673}
7674
7675INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7676{
7677 return RETURN_ERR;
7678}
7679
7680//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7681//to set and read the inactivity time (in seconds) for steering under Idle condition
7682INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7683{
7684 return RETURN_ERR;
7685}
7686
7687INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7688{
7689 return RETURN_ERR;
7690}
7691
7692//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7693//pClientMAC[64]
7694//pSourceSSIDIndex[64]
7695//pDestSSIDIndex[64]
7696//pSteeringReason[256]
7697INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7698{
7699 //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
7700 *pSteeringTime=time(NULL);
7701 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7702 return RETURN_OK;
7703}
7704
7705INT wifi_ifConfigDown(INT apIndex)
7706{
7707 INT status = RETURN_OK;
7708 char cmd[64];
7709
7710 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7711 printf("%s: %s\n", __func__, cmd);
7712 system(cmd);
7713
7714 return status;
7715}
7716
7717INT wifi_ifConfigUp(INT apIndex)
7718{
7719 char cmd[128];
7720 char buf[1024];
7721
7722 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7723 _syscmd(cmd, buf, sizeof(buf));
7724 return 0;
7725}
7726
7727//>> Deprecated. Replace with wifi_applyRadioSettings
7728INT wifi_pushBridgeInfo(INT apIndex)
7729{
7730 char ip[32];
7731 char subnet[32];
7732 char bridge[32];
7733 int vlanId;
7734 char cmd[128];
7735 char buf[1024];
7736
7737 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7738 wifi_getApVlanID(apIndex,&vlanId);
7739
7740 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7741 _syscmd(cmd,buf, sizeof(buf));
7742
7743 return 0;
7744}
7745
7746INT wifi_pushChannel(INT radioIndex, UINT channel)
7747{
7748 char cmd[128];
7749 char buf[1024];
7750 int apIndex;
7751
7752 apIndex=(radioIndex==0)?0:1;
7753 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7754 _syscmd(cmd,buf, sizeof(buf));
7755
7756 return 0;
7757}
7758
7759INT wifi_pushChannelMode(INT radioIndex)
7760{
7761 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7762 return RETURN_ERR;
7763}
7764
7765INT wifi_pushDefaultValues(INT radioIndex)
7766{
7767 //Apply Comcast specified default radio settings instantly
7768 //AMPDU=1
7769 //AMPDUFrames=32
7770 //AMPDULim=50000
7771 //txqueuelen=1000
7772
7773 return RETURN_ERR;
7774}
7775
7776INT wifi_pushTxChainMask(INT radioIndex)
7777{
7778 //Apply default TxChainMask instantly
7779 return RETURN_ERR;
7780}
7781
7782INT wifi_pushRxChainMask(INT radioIndex)
7783{
7784 //Apply default RxChainMask instantly
7785 return RETURN_ERR;
7786}
7787
7788INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7789{
7790 INT status;
7791
7792 status = wifi_setSSIDName(apIndex,ssid);
7793 wifi_setApEnable(apIndex,FALSE);
7794 wifi_setApEnable(apIndex,TRUE);
7795
7796 return status;
7797}
7798
7799INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7800{
7801 //Apply default Ssid Advertisement instantly
7802 return RETURN_ERR;
7803}
7804
7805INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7806{
7807 INT status = RETURN_ERR;
7808 *output = 0;
7809 return RETURN_ERR;
7810}
7811
7812INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7813{
7814 return RETURN_OK;
7815}
7816
7817INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7818{
7819 return RETURN_OK;
7820}
7821
7822//To-do
7823INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7824{
developereb199ae2022-09-13 14:04:27 +08007825 char output[16]={'\0'};
7826 char config_file[MAX_BUF_SIZE] = {0};
7827
7828 if (!output_string)
7829 return RETURN_ERR;
7830
7831 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7832 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7833
7834 if (strlen(output) == 0)
7835 snprintf(output_string, 64, "Disabled");
7836 else if (strncmp(output, "0", 1) == 0)
7837 snprintf(output_string, 64, "Disabled");
7838 else if (strncmp(output, "1", 1) == 0)
7839 snprintf(output_string, 64, "Optional");
7840 else if (strncmp(output, "2", 1) == 0)
7841 snprintf(output_string, 64, "Required");
7842 else {
7843 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7844 return RETURN_ERR;
7845 }
7846
7847 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007848 return RETURN_OK;
7849}
7850INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7851{
developereb199ae2022-09-13 14:04:27 +08007852 char str[MAX_BUF_SIZE]={'\0'};
7853 char cmd[MAX_CMD_SIZE]={'\0'};
7854 struct params params;
7855 char config_file[MAX_BUF_SIZE] = {0};
7856
7857 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7858 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7859 return RETURN_ERR;
7860
7861 params.name = "ieee80211w";
7862 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7863 params.value = "0";
7864 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7865 params.value = "1";
7866 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7867 params.value = "2";
7868 else{
7869 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7870 return RETURN_ERR;
7871 }
7872 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7873 wifi_hostapdWrite(config_file, &params, 1);
7874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007875 return RETURN_OK;
7876}
7877INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7878{
7879 char output[16]={'\0'};
7880 char config_file[MAX_BUF_SIZE] = {0};
7881
7882 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7883 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7884 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7885
7886 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7887 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7888
7889 return RETURN_OK;
7890}
7891
7892INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7893{
7894 return RETURN_OK;
7895}
7896
7897INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7898{
7899 return RETURN_OK;
7900}
7901
7902INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7903{
7904 return RETURN_OK;
7905}
7906
7907INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7908{
7909 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7910 char config_file[MAX_BUF_SIZE] = {0};
7911
7912 if (NULL == output)
7913 return RETURN_ERR;
7914 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7915 wifi_hostapdRead(config_file,"hw_mode",output,64);
7916
7917 if(strcmp(output,"b")==0)
7918 sprintf(output, "%s", "1,2,5.5,11");
7919 else if (strcmp(output,"a")==0)
7920 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7921 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7922 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7923
7924 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7925 return RETURN_OK;
7926}
7927
7928INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7929{
7930 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7931 char *temp;
7932 char temp_output[128];
7933 char temp_TransmitRates[128];
7934 char config_file[MAX_BUF_SIZE] = {0};
7935
7936 if (NULL == output)
7937 return RETURN_ERR;
7938
7939 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7940 wifi_hostapdRead(config_file,"supported_rates",output,64);
7941
7942 strcpy(temp_TransmitRates,output);
7943 strcpy(temp_output,"");
7944 temp = strtok(temp_TransmitRates," ");
7945 while(temp!=NULL)
7946 {
7947 temp[strlen(temp)-1]=0;
7948 if((temp[0]=='5') && (temp[1]=='\0'))
7949 {
7950 temp="5.5";
7951 }
7952 strcat(temp_output,temp);
7953 temp = strtok(NULL," ");
7954 if(temp!=NULL)
7955 {
7956 strcat(temp_output,",");
7957 }
7958 }
7959 strcpy(output,temp_output);
7960 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7961
7962 return RETURN_OK;
7963}
7964
7965INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7966{
7967 return RETURN_OK;
7968}
7969
7970
7971INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7972{
7973 int i=0;
7974 char *temp;
7975 char temp1[128];
7976 char temp_output[128];
7977 char temp_TransmitRates[128];
7978 struct params params={'\0'};
7979 char config_file[MAX_BUF_SIZE] = {0};
7980
7981 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7982 if(NULL == output)
7983 return RETURN_ERR;
7984
7985 strcpy(temp_TransmitRates,output);
7986
7987 for(i=0;i<strlen(temp_TransmitRates);i++)
7988 {
7989 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7990 {
7991 continue;
7992 }
7993 else
7994 {
7995 return RETURN_ERR;
7996 }
7997 }
7998 strcpy(temp_output,"");
7999 temp = strtok(temp_TransmitRates," ");
8000 while(temp!=NULL)
8001 {
8002 strcpy(temp1,temp);
8003 if(wlanIndex==1)
8004 {
8005 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8006 {
8007 return RETURN_ERR;
8008 }
8009 }
8010
8011 if(strcmp(temp,"5.5")==0)
8012 {
8013 strcpy(temp1,"55");
8014 }
8015 else
8016 {
8017 strcat(temp1,"0");
8018 }
8019 strcat(temp_output,temp1);
8020 temp = strtok(NULL," ");
8021 if(temp!=NULL)
8022 {
8023 strcat(temp_output," ");
8024 }
8025 }
8026 strcpy(output,temp_output);
8027
8028
8029 params.name = "supported_rates";
8030 params.value = output;
8031
8032 wifi_dbg_printf("\n%s:",__func__);
8033 wifi_dbg_printf("params.value=%s\n",params.value);
8034 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8035 wifi_hostapdWrite(config_file,&params,1);
8036 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8037
8038 return RETURN_OK;
8039}
8040
8041
8042static char *sncopy(char *dst, int dst_sz, const char *src)
8043{
8044 if (src && dst && dst_sz > 0) {
8045 strncpy(dst, src, dst_sz);
8046 dst[dst_sz - 1] = '\0';
8047 }
8048 return dst;
8049}
8050
8051static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8052{
8053 if (0 == strcmp(ht_mode, "HT40") ||
8054 0 == strcmp(ht_mode, "HT80") ||
8055 0 == strcmp(ht_mode, "HT160")) {
8056 switch (channel) {
8057 case 1 ... 7:
8058 case 36:
8059 case 44:
8060 case 52:
8061 case 60:
8062 case 100:
8063 case 108:
8064 case 116:
8065 case 124:
8066 case 132:
8067 case 140:
8068 case 149:
8069 case 157:
8070 return 1;
8071 case 8 ... 13:
8072 case 40:
8073 case 48:
8074 case 56:
8075 case 64:
8076 case 104:
8077 case 112:
8078 case 120:
8079 case 128:
8080 case 136:
8081 case 144:
8082 case 153:
8083 case 161:
8084 return -1;
8085 default:
8086 return -EINVAL;
8087 }
8088 }
8089
8090 return -EINVAL;
8091}
8092
8093static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8094{
8095 if (NULL == hw_mode) return;
8096
8097 if (0 == strcmp(hw_mode, "ac"))
8098 sncopy(bw_mode, bw_mode_len, "ht vht");
8099
8100 if (0 == strcmp(hw_mode, "n"))
8101 sncopy(bw_mode, bw_mode_len, "ht");
8102
8103 return;
8104}
8105
8106static int util_chan_to_freq(int chan)
8107{
8108 if (chan == 14)
8109 return 2484;
8110 else if (chan < 14)
8111 return 2407 + chan * 5;
8112 else if (chan >= 182 && chan <= 196)
8113 return 4000 + chan * 5;
8114 else
8115 return 5000 + chan * 5;
8116 return 0;
8117}
8118
8119const int *util_unii_5g_chan2list(int chan, int width)
8120{
8121 static const int lists[] = {
8122 // <width>, <chan1>, <chan2>..., 0,
8123 20, 36, 0,
8124 20, 40, 0,
8125 20, 44, 0,
8126 20, 48, 0,
8127 20, 52, 0,
8128 20, 56, 0,
8129 20, 60, 0,
8130 20, 64, 0,
8131 20, 100, 0,
8132 20, 104, 0,
8133 20, 108, 0,
8134 20, 112, 0,
8135 20, 116, 0,
8136 20, 120, 0,
8137 20, 124, 0,
8138 20, 128, 0,
8139 20, 132, 0,
8140 20, 136, 0,
8141 20, 140, 0,
8142 20, 144, 0,
8143 20, 149, 0,
8144 20, 153, 0,
8145 20, 157, 0,
8146 20, 161, 0,
8147 20, 165, 0,
8148 40, 36, 40, 0,
8149 40, 44, 48, 0,
8150 40, 52, 56, 0,
8151 40, 60, 64, 0,
8152 40, 100, 104, 0,
8153 40, 108, 112, 0,
8154 40, 116, 120, 0,
8155 40, 124, 128, 0,
8156 40, 132, 136, 0,
8157 40, 140, 144, 0,
8158 40, 149, 153, 0,
8159 40, 157, 161, 0,
8160 80, 36, 40, 44, 48, 0,
8161 80, 52, 56, 60, 64, 0,
8162 80, 100, 104, 108, 112, 0,
8163 80, 116, 120, 124, 128, 0,
8164 80, 132, 136, 140, 144, 0,
8165 80, 149, 153, 157, 161, 0,
8166 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8167 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8168 -1 // final delimiter
8169 };
8170 const int *start;
8171 const int *p;
8172
8173 for (p = lists; *p != -1; p++) {
8174 if (*p == width) {
8175 for (start = ++p; *p != 0; p++) {
8176 if (*p == chan)
8177 return start;
8178 }
8179 }
8180 // move to the end of channel list of given width
8181 while (*p != 0) {
8182 p++;
8183 }
8184 }
8185
8186 return NULL;
8187}
8188
8189static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8190{
8191 if (NULL == ht_mode)
8192 return 0;
8193
8194 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8195 const int *chans = util_unii_5g_chan2list(channel, width);
8196 int sum = 0;
8197 int cnt = 0;
8198
8199 if (NULL == chans)
8200 return 0;
8201
8202 while (*chans) {
8203 sum += *chans;
8204 cnt++;
8205 chans++;
8206 }
8207 return sum / cnt;
8208}
8209
8210static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8211{
8212 BOOL onlyG, onlyN, onlyA;
8213 CHAR tmp[64];
8214 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8215 if (ret == RETURN_OK) {
8216 sncopy(hw_mode, hw_mode_size, tmp);
8217 }
8218 return ret;
8219}
8220
8221INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8222{
8223 // Sample commands:
8224 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8225 // hostapd_cli -i wifi0 chan_switch 30 2437
8226 char cmd[MAX_CMD_SIZE] = {0};
8227 char buf[MAX_BUF_SIZE] = {0};
8228 int freq = 0, ret = 0;
8229 char center_freq1_str[32] = ""; // center_freq1=%d
8230 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8231 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8232 char hw_mode[16] = ""; // n|ac
8233 char bw_mode[16] = ""; // ht|ht vht
8234 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8235 int sec_chan_offset;
8236 int width;
8237
8238 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8239
8240 freq = util_chan_to_freq(channel);
8241
8242 // Get radio mode HT20|HT40|HT80 etc.
8243 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8244 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8245 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8246 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8247 if (sec_chan_offset != -EINVAL)
8248 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8249
8250
8251 // Provide bandwith if specified
8252 if (channel_width_MHz > 20) {
8253 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8254 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8255 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8256
8257 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8258 }
8259
8260 int center_chan = 0;
8261 if (channel_width_MHz > 20) {
8262 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8263 if (center_chan > 0) {
8264 int center_freq1 = util_chan_to_freq(center_chan);
8265 if (center_freq1)
8266 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8267 }
8268 }
8269
8270 {
8271 // Only the first AP, other are hanging on the same radio
8272 int apIndex = radioIndex;
8273 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8274 AP_PREFIX, apIndex, csa_beacon_count, freq,
8275 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8276 wifi_dbg_printf("execute: '%s'\n", cmd);
8277 ret = _syscmd(cmd, buf, sizeof(buf));
8278 }
8279
8280 wifi_setRadioChannel(radioIndex, channel);
8281
8282 char *ext_str = "None";
8283 if (sec_chan_offset == 1) ext_str = "Above";
8284 else if (sec_chan_offset == -1) ext_str = "Below";
8285 wifi_setRadioExtChannel(radioIndex, ext_str);
8286
8287 wifi_setRadioCenterChannel(radioIndex, center_chan);
8288
8289 char mhz_str[16];
8290 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8291 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8292
8293 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8294
8295 return RETURN_OK;
8296}
8297
8298INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8299{
developer615510b2022-09-27 10:14:35 +08008300 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008301 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008302 char cmd[256]={0};
8303 char buf[128]={0};
8304 char file_name[32] = {0};
8305 char filter_SSID[32] = {0};
8306 char line[256] = {0};
8307 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008308 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008309 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008310 size_t len=0;
8311 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008312 int vht_channel_width = 0;
developer615510b2022-09-27 10:14:35 +08008313 bool get_nosie_ret = false;
8314 bool filter_enable = false;
8315 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008316
developer615510b2022-09-27 10:14:35 +08008317 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008318
developer615510b2022-09-27 10:14:35 +08008319 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8320 f = fopen(file_name, "r");
8321 if (f != NULL) {
8322 fgets(filter_SSID, sizeof(file_name), f);
8323 if (strlen(filter_SSID) != 0)
8324 filter_enable = true;
8325 fclose(f);
8326 }
8327
8328 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8329 _syscmd(cmd, buf, sizeof(buf));
8330 channels_num = strtol(buf, NULL, 10);
8331
8332 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8333 get_nosie_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8334
8335 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8336 // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE.*GHz' | grep -v -e '*.*BSS'", AP_PREFIX, radio_index, AP_PREFIX, radio_index);
8337 fprintf(stderr, "cmd: %s\n", cmd);
8338 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008339 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8340 return RETURN_ERR;
8341 }
developer615510b2022-09-27 10:14:35 +08008342 ret = fgets(line, sizeof(line), f);
8343 while (ret != NULL) {
8344 if(strstr(line, "BSS") != NULL) { // new neighbor info
8345 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8346 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8347 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8348
8349 if (!filter_BSS) {
8350 index++;
8351 wifi_neighbor_ap2_t *tmp;
8352 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8353 if (tmp == NULL) { // no more memory to use
8354 index--;
8355 wifi_dbg_printf("%s: realloc failed\n", __func__);
8356 break;
8357 }
8358 scan_array = tmp;
8359 }
8360 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008361
developer615510b2022-09-27 10:14:35 +08008362 filter_BSS = false;
8363 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8364 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8365 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8366 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8367 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008368 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008369 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008370
developer615510b2022-09-27 10:14:35 +08008371 if (freq >= 2412 && freq <= 2484) {
8372 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8373 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8374 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8375 }
8376 else if (freq >= 5160 && freq <= 5805) {
8377 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8378 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8379 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8380 }
developer06a01d92022-09-07 16:32:39 +08008381
developer615510b2022-09-27 10:14:35 +08008382 scan_array[index].ap_Noise = 0;
8383 if (get_nosie_ret) {
8384 for (int i = 0; i < channels_num; i++) {
8385 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8386 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8387 break;
8388 }
8389 }
developer06a01d92022-09-07 16:32:39 +08008390 }
developer615510b2022-09-27 10:14:35 +08008391 } else if (strstr(line, "beacon interval") != NULL) {
8392 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8393 } else if (strstr(line, "signal") != NULL) {
8394 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8395 } else if (strstr(line,"SSID") != NULL) {
8396 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8397 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8398 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008399 }
developer615510b2022-09-27 10:14:35 +08008400 } else if (strstr(line, "Supported rates") != NULL) {
8401 char SRate[80] = {0}, *tmp = NULL;
8402 memset(buf, 0, sizeof(buf));
8403 strcpy(SRate, line);
8404 tmp = strtok(SRate, ":");
8405 tmp = strtok(NULL, ":");
8406 strcpy(buf, tmp);
8407 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008408
developer615510b2022-09-27 10:14:35 +08008409 tmp = strtok(buf, " \n");
8410 while (tmp != NULL) {
8411 strcat(SRate, tmp);
8412 if (SRate[strlen(SRate) - 1] == '*') {
8413 SRate[strlen(SRate) - 1] = '\0';
8414 }
8415 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008416
developer615510b2022-09-27 10:14:35 +08008417 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008418 }
developer615510b2022-09-27 10:14:35 +08008419 SRate[strlen(SRate) - 1] = '\0';
8420 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8421 } else if (strstr(line, "DTIM") != NULL) {
8422 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8423 } else if (strstr(line, "VHT capabilities") != NULL) {
8424 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8425 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8426 } else if (strstr(line, "HT capabilities") != NULL) {
8427 strcat(scan_array[index].ap_SupportedStandards, ",n");
8428 strcpy(scan_array[index].ap_OperatingStandards, "n");
8429 } else if (strstr(line, "VHT operation") != NULL) {
8430 ret = fgets(line, sizeof(line), f);
8431 sscanf(line," * channel width: %d", &vht_channel_width);
8432 if(vht_channel_width == 1) {
8433 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8434 } else {
8435 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8436 }
8437 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8438 continue;
8439 } else if (strstr(line, "HT operation") != NULL) {
8440 ret = fgets(line, sizeof(line), f);
8441 sscanf(line," * secondary channel offset: %s", &buf);
8442 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008443 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008444 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008445 }
developer615510b2022-09-27 10:14:35 +08008446 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008447 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008448 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8449 } else {
8450 //20Mhz
8451 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radio_index%1 ? "A": "G");
developer06a01d92022-09-07 16:32:39 +08008452 }
developer615510b2022-09-27 10:14:35 +08008453 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008454 continue;
developer615510b2022-09-27 10:14:35 +08008455 } else if (strstr(line, "HE capabilities") != NULL) {
8456 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8457 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8458 ret = fgets(line, sizeof(line), f);
8459 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8460 if (strstr(line, "HE40/2.4GHz") != NULL)
8461 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8462 else
8463 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8464 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8465 if (strstr(line, "HE80/5GHz") != NULL) {
8466 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8467 ret = fgets(line, sizeof(line), f);
8468 } else
8469 continue;
8470 if (strstr(line, "HE160/5GHz") != NULL)
8471 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008472 }
developer615510b2022-09-27 10:14:35 +08008473 continue;
8474 } else if (strstr(line, "WPA") != NULL) {
8475 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8476 } else if (strstr(line, "RSN") != NULL) {
8477 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8478 } else if (strstr(line, "Group cipher") != NULL) {
8479 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8480 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8481 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008482 }
developer06a01d92022-09-07 16:32:39 +08008483 }
developer615510b2022-09-27 10:14:35 +08008484 ret = fgets(line, sizeof(line), f);
8485 }
8486
8487 if (!filter_BSS) {
8488 *output_array_size = index + 1;
8489 } else {
8490 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8491 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008492 }
developer06a01d92022-09-07 16:32:39 +08008493 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008494 pclose(f);
developer615510b2022-09-27 10:14:35 +08008495 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008496 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008497}
developer615510b2022-09-27 10:14:35 +08008498
developer06a01d92022-09-07 16:32:39 +08008499INT wifi_getApAssociatedDeviceStats(
8500 INT apIndex,
8501 mac_address_t *clientMacAddress,
8502 wifi_associated_dev_stats_t *associated_dev_stats,
8503 u64 *handle)
8504{
8505 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8506 char interface_name[50] = {0};
8507 char cmd[1024] = {0};
8508 char mac_str[18] = {0};
8509 char *key = NULL;
8510 char *val = NULL;
8511 FILE *f = NULL;
8512 char *line = NULL;
8513 size_t len = 0;
8514 ssize_t read = 0;
8515
8516 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8517 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8518 return RETURN_ERR;
8519 }
8520
8521 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8522 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8523 if((f = popen(cmd, "r")) == NULL) {
8524 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8525 return RETURN_ERR;
8526 }
8527
8528 while ((read = getline(&line, &len, f)) != -1) {
8529 key = strtok(line,":");
8530 val = strtok(NULL,":");
8531
8532 if(!strncmp(key,"rx bytes",8))
8533 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8534 if(!strncmp(key,"tx bytes",8))
8535 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8536 if(!strncmp(key,"rx packets",10))
8537 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8538 if(!strncmp(key,"tx packets",10))
8539 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8540 if(!strncmp(key,"tx retries",10))
8541 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8542 if(!strncmp(key,"tx failed",9))
8543 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8544 if(!strncmp(key,"rx drop misc",13))
8545 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8546 if(!strncmp(key,"rx bitrate",10)) {
8547 val = strtok(val, " ");
8548 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8549 }
8550 if(!strncmp(key,"tx bitrate",10)) {
8551 val = strtok(val, " ");
8552 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8553 }
8554 }
8555 free(line);
8556 pclose(f);
8557 return RETURN_OK;
8558}
8559
8560INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8561{
8562 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8563
8564 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8565 if (NULL == output_string)
8566 return RETURN_ERR;
8567
8568 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8569 _syscmd(cmd, buf, sizeof(buf));
8570
8571 //size of SSID name restricted to value less than 32 bytes
8572 snprintf(output_string, 32, "%s", buf);
8573 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8574
8575 return RETURN_OK;
8576}
8577
8578INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8579{
8580 //char cmd[MAX_CMD_SIZE] = {0};
8581 char config_file[MAX_BUF_SIZE] = {0};
8582 char buf[32] = {0};
8583
8584 if (!output_filterMode)
8585 return RETURN_ERR;
8586
8587 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8588 //_syscmd(cmd, buf, sizeof(buf));
8589 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8590 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008591 if(strlen(buf) == 0) {
8592 *output_filterMode = 0;
8593 }
8594 else {
8595 int macaddr_acl_mode = strtol(buf, NULL, 10);
8596 if (macaddr_acl_mode == 1) {
8597 *output_filterMode = 1;
8598 } else if (macaddr_acl_mode == 0) {
8599 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8600 if (strlen(buf) == 0) {
8601 *output_filterMode = 0;
8602 } else {
8603 *output_filterMode = 2;
8604 }
8605 } else {
8606 return RETURN_ERR;
8607 }
8608 }
developer06a01d92022-09-07 16:32:39 +08008609
8610 return RETURN_OK;
8611}
8612
8613INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8614{
8615 FILE *fp = NULL;
8616 char str[MAX_BUF_SIZE] = {0};
8617 int wificlientindex = 0 ;
8618 int count = 0;
8619 int signalstrength = 0;
8620 int arr[MACADDRESS_SIZE] = {0};
8621 unsigned char mac[MACADDRESS_SIZE] = {0};
8622 UINT wifi_count = 0;
8623 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8624 char pipeCmd[MAX_CMD_SIZE] = {0};
8625
8626 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8627 *output_array_size = 0;
8628 *associated_dev_array = NULL;
8629 char interface_name[50] = {0};
8630
8631 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8632 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8633 return RETURN_ERR;
8634 }
8635
8636 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8637 fp = popen(pipeCmd, "r");
8638 if (fp == NULL)
8639 {
8640 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8641 return RETURN_ERR;
8642 }
8643
8644 /* Read the output a line at a time - output it. */
8645 fgets(str, sizeof(str)-1, fp);
8646 wifi_count = (unsigned int) atoi ( str );
8647 *output_array_size = wifi_count;
8648 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8649 pclose(fp);
8650
8651 if(wifi_count == 0)
8652 {
8653 return RETURN_OK;
8654 }
8655 else
8656 {
8657 wifi_associated_dev2_t* temp = NULL;
8658 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8659 *associated_dev_array = temp;
8660 if(temp == NULL)
8661 {
8662 printf("Error Statement. Insufficient memory \n");
8663 return RETURN_ERR;
8664 }
8665
8666 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8667 system(pipeCmd);
8668
8669 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8670 if(fp == NULL)
8671 {
8672 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8673 return RETURN_ERR;
8674 }
8675 fclose(fp);
8676
8677 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8678 fp = popen(pipeCmd, "r");
8679 if(fp)
8680 {
8681 for(count =0 ; count < wifi_count; count++)
8682 {
8683 fgets(str, MAX_BUF_SIZE, fp);
8684 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8685 {
8686 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8687 {
8688 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8689
8690 }
8691 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8692 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]);
8693 }
8694 temp[count].cli_AuthenticationState = 1; //TODO
8695 temp[count].cli_Active = 1; //TODO
8696 }
8697 pclose(fp);
8698 }
8699
8700 //Updating RSSI per client
8701 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8702 fp = popen(pipeCmd, "r");
8703 if(fp)
8704 {
8705 pclose(fp);
8706 }
8707 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8708 if(fp)
8709 {
8710 for(count =0 ; count < wifi_count ;count++)
8711 {
8712 fgets(str, MAX_BUF_SIZE, fp);
8713 signalstrength = atoi(str);
8714 temp[count].cli_RSSI = signalstrength;
8715 }
8716 pclose(fp);
8717 }
8718
8719
8720 //LastDataDownlinkRate
8721 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8722 fp = popen(pipeCmd, "r");
8723 if (fp)
8724 {
8725 pclose(fp);
8726 }
8727 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8728 if (fp)
8729 {
8730 for (count = 0; count < wifi_count; count++)
8731 {
8732 fgets(str, MAX_BUF_SIZE, fp);
8733 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8734 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8735 }
8736 pclose(fp);
8737 }
8738
8739 //LastDataUplinkRate
8740 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8741 fp = popen(pipeCmd, "r");
8742 if (fp)
8743 {
8744 pclose(fp);
8745 }
8746 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8747 if (fp)
8748 {
8749 for (count = 0; count < wifi_count; count++)
8750 {
8751 fgets(str, MAX_BUF_SIZE, fp);
8752 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8753 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8754 }
8755 pclose(fp);
8756 }
8757 }
8758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8759 return RETURN_OK;
8760
8761}
8762
8763INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8764{
8765#if 0
8766 /*char buf[1024] = {0};
8767 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8768 _syscmd(cmd, buf, sizeof(buf));*/
8769
8770 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8771 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8772 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8773 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8774
8775 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.
8776 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].
8777 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].
8778 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].
8779 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8780 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8781
8782 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8783 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8784 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8785 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.
8786 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.
8787 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.
8788 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.
8789 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.
8790 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.
8791 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.
8792 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8793#endif
8794
8795 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008796 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008797 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008798 char pipeCmd[128] = {0};
8799 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008800 wifi_ssidTrafficStats2_t *out = output_struct;
8801
developerce736392022-09-13 15:24:34 +08008802 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008803 if (!output_struct)
8804 return RETURN_ERR;
8805
developerce736392022-09-13 15:24:34 +08008806 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8807 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8808 GetInterfaceName(interface_name, HConf_file);
8809 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008810
developer06a01d92022-09-07 16:32:39 +08008811 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008812 if (fp == NULL) {
8813 fprintf(stderr, "%s: popen failed\n", __func__);
8814 return RETURN_ERR;
8815 }
8816 fgets(str, sizeof(str), fp);
developer06a01d92022-09-07 16:32:39 +08008817
developerce736392022-09-13 15:24:34 +08008818 if (strlen(str) == 0) // interface not exist
8819 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008820
developerce736392022-09-13 15:24:34 +08008821 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8822 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008823 pclose(fp);
8824
developerce736392022-09-13 15:24:34 +08008825 memset(str, 0, sizeof(str));
8826 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008827 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008828 if (fp == NULL) {
8829 fprintf(stderr, "%s: popen failed\n", __func__);
8830 return RETURN_ERR;
8831 }
8832 fgets(str, sizeof(str), fp);
8833
8834 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8835 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008836 pclose(fp);
developerce736392022-09-13 15:24:34 +08008837
8838 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8839 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8840
8841 // Not supported
8842 output_struct->ssid_RetransCount = 0;
8843 output_struct->ssid_FailedRetransCount = 0;
8844 output_struct->ssid_RetryCount = 0;
8845 output_struct->ssid_MultipleRetryCount = 0;
8846 output_struct->ssid_ACKFailureCount = 0;
8847 output_struct->ssid_AggregatedPacketCount = 0;
8848
developer06a01d92022-09-07 16:32:39 +08008849 return RETURN_OK;
8850}
8851
8852//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).
8853INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8854{
8855 char output_val[16]={'\0'};
8856 char config_file[MAX_BUF_SIZE] = {0};
8857
8858 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8859 if (!output)
8860 return RETURN_ERR;
8861 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8862 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8863
8864 if( strcmp(output_val,"1") == 0 )
8865 *output = TRUE;
8866 else
8867 *output = FALSE;
8868 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8869
8870 return RETURN_OK;
8871}
8872
8873INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8874{
8875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8876 char str[MAX_BUF_SIZE]={'\0'};
8877 char string[MAX_BUF_SIZE]={'\0'};
8878 char cmd[MAX_CMD_SIZE]={'\0'};
8879 char *ch;
8880 char config_file[MAX_BUF_SIZE] = {0};
8881 struct params params;
8882
8883 if(enable == TRUE)
8884 strcpy(string,"1");
8885 else
8886 strcpy(string,"0");
8887
8888 params.name = "ap_isolate";
8889 params.value = string;
8890
8891 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8892 wifi_hostapdWrite(config_file,&params,1);
8893 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8894
8895 return RETURN_OK;
8896}
8897
8898INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8899{
8900 if (NULL == output_dBm)
8901 return RETURN_ERR;
8902
8903 *output_dBm = 0;
8904 return RETURN_OK;
8905}
8906
8907INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8908{
8909 return RETURN_OK;
8910}
8911INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8912{
8913 return RETURN_OK;
8914}
8915INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8916{
8917 return RETURN_OK;
8918}
8919INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8920{
8921 return RETURN_OK;
8922}
8923INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8924{
8925 return RETURN_OK;
8926}
8927INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8928{
8929 char config_file[MAX_BUF_SIZE] = {0};
8930 struct params list;
8931
8932 list.name = "bss_transition";
8933 list.value = activate?"1":"0";
8934 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8935 wifi_hostapdWrite(config_file, &list, 1);
8936
8937 return RETURN_OK;
8938}
8939wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8940
8941void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8942{
8943 return;
8944}
8945
8946INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8947{
8948 // TODO Implement me!
8949 return RETURN_OK;
8950}
8951
8952INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8953{
developera3c68b92022-09-13 15:27:29 +08008954 char file_name[128] = {0};
8955 char buf[128] = {0};
8956 FILE *f = NULL;
8957
8958 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8959
8960 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8961 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8962 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8963 f = fopen(file_name, "w");
8964 if (f == NULL)
8965 return RETURN_ERR;
8966 // For mode == 0 is to disable filter, just don't write to the file.
8967 if (mode)
8968 fprintf(f, "%s", essid);
8969
8970 fclose(f);
8971 }
8972 } else { // special case, need to set AP's SSID as filter for each radio.
8973 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8974 f = fopen(file_name, "w");
8975 if (f == NULL)
8976 return RETURN_ERR;
8977
8978 // For mode == 0 is to disable filter, just don't write to the file.
8979 if (mode)
8980 fprintf(f, "%s", essid);
8981
8982 fclose(f);
8983 }
8984
8985 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008986 return RETURN_OK;
8987}
8988
8989INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
8990{
8991 // TODO Implement me!
8992 //Apply wifi_pushRadioChannel() instantly
8993 return RETURN_ERR;
8994}
8995
8996INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
8997{
8998 // TODO Implement me!
8999 return RETURN_OK;
9000}
9001
9002#ifdef HAL_NETLINK_IMPL
9003static int tidStats_callback(struct nl_msg *msg, void *arg) {
9004 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9005 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9006 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9007 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9008 int rem , tid_index = 0;
9009
9010 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9011 wifi_associated_dev_tid_entry_t *stats_entry;
9012
9013 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9014 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9015 };
9016 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9017 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9018 };
9019
9020 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9021 genlmsg_attrlen(gnlh, 0), NULL);
9022
9023
9024 if (!tb[NL80211_ATTR_STA_INFO]) {
9025 fprintf(stderr, "station stats missing!\n");
9026 return NL_SKIP;
9027 }
9028
9029 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9030 tb[NL80211_ATTR_STA_INFO],
9031 stats_policy)) {
9032 fprintf(stderr, "failed to parse nested attributes!\n");
9033 return NL_SKIP;
9034 }
9035
9036 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9037 {
9038 stats_entry = &out->tid_array[tid_index];
9039
9040 stats_entry->tid = tid_index;
9041 stats_entry->ac = _tid_ac_index_get[tid_index];
9042
9043 if(sinfo[NL80211_STA_INFO_TID_STATS])
9044 {
9045 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9046 printf("failed to parse nested stats attributes!");
9047 return NL_SKIP;
9048 }
9049 }
9050 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9051 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9052
9053 if(tid_index < (PS_MAX_TID - 1))
9054 tid_index++;
9055 }
9056 //ToDo: sum_time_ms, ewma_time_ms
9057 return NL_SKIP;
9058}
9059#endif
9060
9061INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9062{
9063#ifdef HAL_NETLINK_IMPL
9064 Netlink nl;
9065 char if_name[10];
9066
9067 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9068
9069 nl.id = initSock80211(&nl);
9070
9071 if (nl.id < 0) {
9072 fprintf(stderr, "Error initializing netlink \n");
9073 return -1;
9074 }
9075
9076 struct nl_msg* msg = nlmsg_alloc();
9077
9078 if (!msg) {
9079 fprintf(stderr, "Failed to allocate netlink message.\n");
9080 nlfree(&nl);
9081 return -2;
9082 }
9083
9084 genlmsg_put(msg,
9085 NL_AUTO_PORT,
9086 NL_AUTO_SEQ,
9087 nl.id,
9088 0,
9089 0,
9090 NL80211_CMD_GET_STATION,
9091 0);
9092
9093 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9094 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9095 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9096 nl_send_auto(nl.socket, msg);
9097 nl_recvmsgs(nl.socket, nl.cb);
9098 nlmsg_free(msg);
9099 nlfree(&nl);
9100 return RETURN_OK;
9101#else
9102//iw implementation
9103#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9104#define TOTAL_MAX_LINES 50
9105
9106 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9107 char if_name[10];
9108 FILE *fp=NULL;
9109 char pipeCmd[1024]= {'\0'};
9110 int lines,tid_index=0;
9111 char mac_addr[20] = {'\0'};
9112
9113 wifi_associated_dev_tid_entry_t *stats_entry;
9114
9115 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9116 strcpy(mac_addr,clientMacAddress);
9117
9118 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9119 fp= popen(pipeCmd,"r");
9120 if(fp == NULL)
9121 {
9122 perror("popen for station dump failed\n");
9123 return RETURN_ERR;
9124 }
9125 pclose(fp);
9126
9127 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9128 fp=popen(pipeCmd,"r");
9129 if(fp == NULL)
9130 {
9131 perror("popen for grep station failed\n");
9132 return RETURN_ERR;
9133 }
9134 else if(fgets(buf,sizeof(buf),fp) != NULL)
9135 lines=atoi(buf);
9136 else
9137 {
9138 pclose(fp);
9139 fprintf(stderr,"No devices are connected \n");
9140 return RETURN_ERR;
9141 }
9142 pclose(fp);
9143
9144 if(lines == 1)
9145 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9146
9147 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9148 {
9149 stats_entry = &tid_stats->tid_array[tid_index];
9150 stats_entry->tid = tid_index;
9151
9152 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);
9153
9154 fp=popen(pipeCmd,"r");
9155 if(fp ==NULL)
9156 {
9157 perror("Failed to read from tid file \n");
9158 return RETURN_ERR;
9159 }
9160 else if(fgets(buf,sizeof(buf),fp) != NULL)
9161 stats_entry->num_msdus = atol(buf);
9162
9163 pclose(fp);
9164 stats_entry->ac = _tid_ac_index_get[tid_index];
9165// TODO:
9166// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9167// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9168 }
9169 return RETURN_OK;
9170#endif
9171}
9172
9173
9174INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9175{
developer615510b2022-09-27 10:14:35 +08009176 char cmd[128]={0};
9177 char buf[128]={0};
9178 int freq = 0;
9179
9180 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9181
9182 // full mode is used to scan all channels.
9183 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9184 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9185 ieee80211_channel_to_frequency(chan_list[0], &freq);
9186
9187 if (freq)
9188 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9189 else
9190 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9191
9192 _syscmd(cmd, buf, sizeof(buf));
9193 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9194
developer06a01d92022-09-07 16:32:39 +08009195 return RETURN_OK;
9196}
9197
9198
9199INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9200{
9201 // TODO Implement me!
9202 return RETURN_ERR;
9203}
9204
9205INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9206{
9207 // TODO Implement me!
9208 return RETURN_ERR;
9209}
9210
9211INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9212{
9213 // TODO Implement me!
9214 return RETURN_ERR;
9215}
9216
9217INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9218{
9219 // TODO Implement me!
9220 return RETURN_ERR;
9221}
9222
9223INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9224{
9225 // TODO Implement me!
9226 return RETURN_ERR;
9227}
9228
9229INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9230{
9231 // TODO Implement me!
9232 return RETURN_ERR;
9233}
9234
9235INT wifi_steering_eventUnregister(void)
9236{
9237 // TODO Implement me!
9238 return RETURN_ERR;
9239}
9240
9241INT wifi_delApAclDevices(INT apIndex)
9242{
9243#if 0
9244 char cmd[MAX_BUF_SIZE] = {0};
9245 char buf[MAX_BUF_SIZE] = {0};
9246
9247 /* Not reset proof solution */
9248 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9249 if(_syscmd(cmd,buf,sizeof(buf)))
9250 return RETURN_ERR;
9251#endif
developere6aafda2022-09-13 14:59:28 +08009252 char cmd[MAX_CMD_SIZE]={0};
9253 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009254
developere6aafda2022-09-13 14:59:28 +08009255 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9256 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9257 if(_syscmd(cmd, buf, sizeof(buf)))
9258 return RETURN_ERR;
9259 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009260
9261 return RETURN_OK;
9262}
9263
9264#ifdef HAL_NETLINK_IMPL
9265static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9266 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9267 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9268 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9269 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9270 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9271 char mac_addr[20],dev[20];
9272
9273 nla_parse(tb,
9274 NL80211_ATTR_MAX,
9275 genlmsg_attrdata(gnlh, 0),
9276 genlmsg_attrlen(gnlh, 0),
9277 NULL);
9278
9279 if(!tb[NL80211_ATTR_STA_INFO]) {
9280 fprintf(stderr, "sta stats missing!\n");
9281 return NL_SKIP;
9282 }
9283
9284 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9285 fprintf(stderr, "failed to parse nested attributes!\n");
9286 return NL_SKIP;
9287 }
9288 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9289
9290 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9291
9292 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9293 fprintf(stderr, "failed to parse nested rate attributes!");
9294 return NL_SKIP;
9295 }
9296
9297 if(sinfo[NL80211_STA_INFO_TID_STATS])
9298 {
9299 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9300 printf("failed to parse nested stats attributes!");
9301 return NL_SKIP;
9302 }
9303 }
9304
9305 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9306 {
9307 printf("Type is VHT\n");
9308 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9309 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9310
9311 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9312 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9313 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9314 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9315 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9316 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9317 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9318 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9319 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9320 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9321 }
9322 else
9323 {
9324 printf(" OFDM or CCK \n");
9325 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9326 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9327 }
9328
9329 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9330 if(rinfo[NL80211_RATE_INFO_MCS])
9331 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9332 }
9333 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9334 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9335 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9336 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9337
9338 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9339 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9340
9341 if (sinfo[NL80211_STA_INFO_SIGNAL])
9342 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9343 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9344 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9345 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9346 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9347 //rssi_array need to be filled
9348 return NL_SKIP;
9349}
9350#endif
9351
9352INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9353{
9354#ifdef HAL_NETLINK_IMPL
9355 Netlink nl;
9356 char if_name[10];
9357
9358 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9359
9360 if (*output_array_size <= 0)
9361 return RETURN_OK;
9362
9363 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9364 nl.id = initSock80211(&nl);
9365
9366 if (nl.id < 0) {
9367 fprintf(stderr, "Error initializing netlink \n");
9368 return 0;
9369 }
9370
9371 struct nl_msg* msg = nlmsg_alloc();
9372
9373 if (!msg) {
9374 fprintf(stderr, "Failed to allocate netlink message.\n");
9375 nlfree(&nl);
9376 return 0;
9377 }
9378
9379 genlmsg_put(msg,
9380 NL_AUTO_PORT,
9381 NL_AUTO_SEQ,
9382 nl.id,
9383 0,
9384 0,
9385 NL80211_CMD_GET_STATION,
9386 0);
9387
9388 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9389 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9390 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9391 nl_send_auto(nl.socket, msg);
9392 nl_recvmsgs(nl.socket, nl.cb);
9393 nlmsg_free(msg);
9394 nlfree(&nl);
9395 return RETURN_OK;
9396#else
9397 //TODO Implement me
9398 return RETURN_OK;
9399#endif
9400}
9401
9402#ifdef HAL_NETLINK_IMPL
9403static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9404 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9405 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9406 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9407 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9408 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9409 char mac_addr[20],dev[20];
9410
9411 nla_parse(tb,
9412 NL80211_ATTR_MAX,
9413 genlmsg_attrdata(gnlh, 0),
9414 genlmsg_attrlen(gnlh, 0),
9415 NULL);
9416
9417 if(!tb[NL80211_ATTR_STA_INFO]) {
9418 fprintf(stderr, "sta stats missing!\n");
9419 return NL_SKIP;
9420 }
9421
9422 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9423 fprintf(stderr, "failed to parse nested attributes!\n");
9424 return NL_SKIP;
9425 }
9426
9427 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9428
9429 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9430
9431 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9432 fprintf(stderr, "failed to parse nested rate attributes!");
9433 return NL_SKIP;
9434 }
9435
9436 if(sinfo[NL80211_STA_INFO_TID_STATS])
9437 {
9438 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9439 printf("failed to parse nested stats attributes!");
9440 return NL_SKIP;
9441 }
9442 }
9443 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9444 {
9445 printf("Type is VHT\n");
9446 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9447 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9448
9449 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9450 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9451 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9452 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9453 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9454 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9455 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9456 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9457 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9458 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9459 }
9460 else
9461 {
9462 printf(" OFDM or CCK \n");
9463 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9464 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9465 }
9466
9467 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9468 if(rinfo[NL80211_RATE_INFO_MCS])
9469 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9470 }
9471
9472 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9473 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9474 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9475 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9476
9477 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9478 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9479 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9480
9481 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9482 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9483
9484 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9486
9487 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9488 ((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]);
9489
9490 return NL_SKIP;
9491}
9492#endif
9493
9494INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9495{
9496#ifdef HAL_NETLINK_IMPL
9497 Netlink nl;
9498 char if_name[10];
9499
9500 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9501
9502 if (*output_array_size <= 0)
9503 return RETURN_OK;
9504
9505 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9506
9507 nl.id = initSock80211(&nl);
9508
9509 if(nl.id < 0) {
9510 fprintf(stderr, "Error initializing netlink \n");
9511 return 0;
9512 }
9513
9514 struct nl_msg* msg = nlmsg_alloc();
9515
9516 if(!msg) {
9517 fprintf(stderr, "Failed to allocate netlink message.\n");
9518 nlfree(&nl);
9519 return 0;
9520 }
9521
9522 genlmsg_put(msg,
9523 NL_AUTO_PORT,
9524 NL_AUTO_SEQ,
9525 nl.id,
9526 0,
9527 0,
9528 NL80211_CMD_GET_STATION,
9529 0);
9530
9531 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9532 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9533 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9534 nl_send_auto(nl.socket, msg);
9535 nl_recvmsgs(nl.socket, nl.cb);
9536 nlmsg_free(msg);
9537 nlfree(&nl);
9538 return RETURN_OK;
9539#else
9540 //TODO Implement me
9541 return RETURN_OK;
9542#endif
9543}
9544
9545INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9546{
9547 // TODO Implement me!
9548 char buf[MAX_BUF_SIZE] = {0};
9549 char config_file[MAX_BUF_SIZE] = {0};
9550
9551 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9552 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9553 *activate = (strncmp("1",buf,1) == 0);
9554
9555 return RETURN_OK;
9556}
9557
9558INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9559{
9560 char config_file[MAX_BUF_SIZE] = {0};
9561 struct params list;
9562
9563 list.name = "rrm_neighbor_report";
9564 list.value = activate?"1":"0";
9565 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9566 wifi_hostapdWrite(config_file, &list, 1);
9567
9568 return RETURN_OK;
9569}
9570
9571INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9572{
9573 char buf[32] = {0};
9574 char config_file[MAX_BUF_SIZE] = {0};
9575
9576 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9577 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9578 *activate = (strncmp("1",buf,1) == 0);
9579
9580 return RETURN_OK;
9581}
9582#undef HAL_NETLINK_IMPL
9583#ifdef HAL_NETLINK_IMPL
9584static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9585 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9586 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9587 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9588 char dev[20];
9589 int freq =0 ;
9590 static int i=0;
9591
9592 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9593
9594 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9595 };
9596
9597 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9598
9599 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9600
9601 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9602 fprintf(stderr, "survey data missing!\n");
9603 return NL_SKIP;
9604 }
9605
9606 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9607 {
9608 fprintf(stderr, "failed to parse nested attributes!\n");
9609 return NL_SKIP;
9610 }
9611
9612
9613 if(out[0].array_size == 1 )
9614 {
9615 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9616 {
9617 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9618 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9619 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9620
9621 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9622 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9623 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9624 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9625 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9626 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9627 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9628 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9629 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9630 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9631 if (sinfo[NL80211_SURVEY_INFO_TIME])
9632 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9633 return NL_STOP;
9634 }
9635 }
9636 else
9637 {
9638 if ( i <= out[0].array_size )
9639 {
9640 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9641 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9642 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9643
9644 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9645 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9646 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9647 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9648 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9649 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9650 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9651 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9652 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9653 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9654 if (sinfo[NL80211_SURVEY_INFO_TIME])
9655 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9656 }
9657 }
9658
9659 i++;
9660 return NL_SKIP;
9661}
9662#endif
9663
9664static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9665{
9666 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9667 FILE *fp;
9668
9669 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9670 {
9671 printf("Creating Frequency-Channel Map\n");
9672 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9673 }
9674 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9675 if((fp = popen(command, "r")))
9676 {
9677 fgets(output, sizeof(output), fp);
9678 *freqMHz = atoi(output);
9679 fclose(fp);
9680 }
9681
9682 return 0;
9683}
9684
9685static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9686{
9687 int freqMHz = -1;
9688 char cmd[MAX_CMD_SIZE] = {'\0'};
9689
9690 ieee80211_channel_to_frequency(channel, &freqMHz);
9691 if (freqMHz == -1) {
9692 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9693 return -1;
9694 }
9695
9696 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9697 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9698 radioIndex, freqMHz);
9699 return -1;
9700 }
9701
9702 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9703 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9704 return -1;
9705 }
9706
9707 return 0;
9708}
9709
9710static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9711{
9712 const char *ptr = buf;
9713 char *key = NULL;
9714 char *val = NULL;
9715 char line[256] = { '\0' };
9716
9717 while (ptr = get_line_from_str_buf(ptr, line)) {
9718 if (strstr(line, "Frequency")) continue;
9719
9720 key = strtok(line, ":");
9721 val = strtok(NULL, " ");
9722 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9723
9724 if (!strcmp(key, "noise")) {
9725 sscanf(val, "%d", &stats->ch_noise);
9726 if (stats->ch_noise == 0) {
9727 // Workaround for missing noise information.
9728 // Assume -95 for 2.4G and -103 for 5G
9729 if (radioIndex == 0) stats->ch_noise = -95;
9730 if (radioIndex == 1) stats->ch_noise = -103;
9731 }
9732 }
9733 else if (!strcmp(key, "channel active time")) {
9734 sscanf(val, "%llu", &stats->ch_utilization_total);
9735 }
9736 else if (!strcmp(key, "channel busy time")) {
9737 sscanf(val, "%llu", &stats->ch_utilization_busy);
9738 }
9739 else if (!strcmp(key, "channel receive time")) {
9740 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9741 }
9742 else if (!strcmp(key, "channel transmit time")) {
9743 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9744 }
9745 };
9746
9747 return 0;
9748}
9749
9750INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9751{
9752 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9753#ifdef HAL_NETLINK_IMPL
9754 Netlink nl;
9755 wifi_channelStats_t_loc local[array_size];
9756 char if_name[10];
9757
9758 local[0].array_size = array_size;
9759
9760 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9761
9762 nl.id = initSock80211(&nl);
9763
9764 if (nl.id < 0) {
9765 fprintf(stderr, "Error initializing netlink \n");
9766 return -1;
9767 }
9768
9769 struct nl_msg* msg = nlmsg_alloc();
9770
9771 if (!msg) {
9772 fprintf(stderr, "Failed to allocate netlink message.\n");
9773 nlfree(&nl);
9774 return -2;
9775 }
9776
9777 genlmsg_put(msg,
9778 NL_AUTO_PORT,
9779 NL_AUTO_SEQ,
9780 nl.id,
9781 0,
9782 NLM_F_DUMP,
9783 NL80211_CMD_GET_SURVEY,
9784 0);
9785
9786 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9787 nl_send_auto(nl.socket, msg);
9788 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9789 nl_recvmsgs(nl.socket, nl.cb);
9790 nlmsg_free(msg);
9791 nlfree(&nl);
9792 //Copying the Values
9793 for(int i=0;i<array_size;i++)
9794 {
9795 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9796 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9797 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9798 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9799 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9800 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9801 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9802 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9803 }
9804#else
9805 ULONG channel = 0;
9806 int i;
9807 int number_of_channels = array_size;
9808 char buf[512];
9809 INT ret;
9810 wifi_channelStats_t tmp_stats;
9811
9812 if (number_of_channels == 0) {
9813 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9814 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9815 return RETURN_ERR;
9816 }
9817 number_of_channels = 1;
9818 input_output_channelStats_array[0].ch_number = channel;
9819 }
9820
9821 for (i = 0; i < number_of_channels; i++) {
9822
9823 input_output_channelStats_array[i].ch_noise = 0;
9824 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9825 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9826 input_output_channelStats_array[i].ch_utilization_busy = 0;
9827 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9828 input_output_channelStats_array[i].ch_utilization_total = 0;
9829
9830 memset(buf, 0, sizeof(buf));
9831 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9832 return RETURN_ERR;
9833 }
9834 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9835 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9836 return RETURN_ERR;
9837 }
9838
9839 // XXX: fake missing 'self' counter which is not available in iw survey output
9840 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9841 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9842
9843 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9844 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9845 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9846 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9847 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9848
9849 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",
9850 __func__,
9851 input_output_channelStats_array[i].ch_number,
9852 input_output_channelStats_array[i].ch_noise,
9853 input_output_channelStats_array[i].ch_utilization_total,
9854 input_output_channelStats_array[i].ch_utilization_busy,
9855 input_output_channelStats_array[i].ch_utilization_busy_rx,
9856 input_output_channelStats_array[i].ch_utilization_busy_tx,
9857 input_output_channelStats_array[i].ch_utilization_busy_self,
9858 input_output_channelStats_array[i].ch_utilization_busy_ext);
9859 }
9860#endif
9861 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9862 return RETURN_OK;
9863}
9864#define HAL_NETLINK_IMPL
9865
9866/* Hostapd events */
9867
9868#ifndef container_of
9869#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9870#define container_of(ptr, type, member) \
9871 ((type *)((char *)ptr - offset_of(type, member)))
9872#endif /* container_of */
9873
9874struct ctrl {
9875 char sockpath[128];
9876 char sockdir[128];
9877 char bss[IFNAMSIZ];
9878 char reply[4096];
9879 int ssid_index;
9880 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9881 void (*overrun)(struct ctrl *ctrl);
9882 struct wpa_ctrl *wpa;
9883 unsigned int ovfl;
9884 size_t reply_len;
9885 int initialized;
9886 ev_timer retry;
9887 ev_timer watchdog;
9888 ev_stat stat;
9889 ev_io io;
9890};
9891static wifi_newApAssociatedDevice_callback clients_connect_cb;
9892static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9893static struct ctrl wpa_ctrl[MAX_APS];
9894static int initialized;
9895
9896static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9897{
9898 char cbuf[256] = {};
9899 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9900 struct cmsghdr *cmsg;
9901 unsigned int ovfl = ctrl->ovfl;
9902 unsigned int drop;
9903
9904 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9905 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9906 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9907 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9908
9909 drop = ovfl - ctrl->ovfl;
9910 ctrl->ovfl = ovfl;
9911
9912 return drop;
9913}
9914
9915static void ctrl_close(struct ctrl *ctrl)
9916{
9917 if (ctrl->io.cb)
9918 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9919 if (ctrl->retry.cb)
9920 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9921 if (!ctrl->wpa)
9922 return;
9923
9924 wpa_ctrl_detach(ctrl->wpa);
9925 wpa_ctrl_close(ctrl->wpa);
9926 ctrl->wpa = NULL;
9927 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9928}
9929
9930static void ctrl_process(struct ctrl *ctrl)
9931{
9932 const char *str;
9933 int drops;
9934 int level;
9935 int err;
9936
9937 /* Example events:
9938 *
9939 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9940 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9941 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9942 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9943 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9944 */
9945 if (!(str = index(ctrl->reply, '>')))
9946 return;
9947 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9948 return;
9949
9950 str++;
9951
9952 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9953 if (!(str = index(ctrl->reply, ' ')))
9954 return;
9955 wifi_associated_dev_t sta;
9956 memset(&sta, 0, sizeof(sta));
9957
9958 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9959 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9960 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9961
9962 sta.cli_Active=true;
9963
9964 (clients_connect_cb)(ctrl->ssid_index, &sta);
9965 goto handled;
9966 }
9967
9968 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9969 if (!(str = index(ctrl->reply, ' ')))
9970 return;
9971
9972 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9973 goto handled;
9974 }
9975
9976 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9977 printf("CTRL_WPA: handle TERMINATING event\n");
9978 goto retry;
9979 }
9980
9981 if (strncmp("AP-DISABLED", str, 11) == 0) {
9982 printf("CTRL_WPA: handle AP-DISABLED\n");
9983 goto retry;
9984 }
9985
9986 printf("Event not supported!!\n");
9987
9988handled:
9989
9990 if ((drops = ctrl_get_drops(ctrl))) {
9991 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
9992 if (ctrl->overrun)
9993 ctrl->overrun(ctrl);
9994 }
9995
9996 return;
9997
9998retry:
9999 printf("WPA_CTRL: closing\n");
10000 ctrl_close(ctrl);
10001 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10002 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10003}
10004
10005static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10006{
10007 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10008 int err;
10009
10010 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10011 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10012 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10013 ctrl->reply[ctrl->reply_len] = 0;
10014 if (err < 0) {
10015 if (errno == EAGAIN || errno == EWOULDBLOCK)
10016 return;
10017 ctrl_close(ctrl);
10018 ev_timer_again(EV_A_ &ctrl->retry);
10019 return;
10020 }
10021
10022 ctrl_process(ctrl);
10023}
10024
10025static int ctrl_open(struct ctrl *ctrl)
10026{
10027 int fd;
10028
10029 if (ctrl->wpa)
10030 return 0;
10031
10032 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10033 if (!ctrl->wpa)
10034 goto err;
10035
10036 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10037 goto err_close;
10038
10039 fd = wpa_ctrl_get_fd(ctrl->wpa);
10040 if (fd < 0)
10041 goto err_detach;
10042
10043 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10044 goto err_detach;
10045
10046 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10047 ev_io_start(EV_DEFAULT_ &ctrl->io);
10048
10049 return 0;
10050
10051err_detach:
10052 wpa_ctrl_detach(ctrl->wpa);
10053err_close:
10054 wpa_ctrl_close(ctrl->wpa);
10055err:
10056 ctrl->wpa = NULL;
10057 return -1;
10058}
10059
10060static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10061{
10062 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10063
10064 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10065 ctrl_open(ctrl);
10066}
10067
10068static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10069{
10070 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10071
10072 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10073 if (ctrl_open(ctrl) == 0) {
10074 printf("WPA_CTRL: retry successful\n");
10075 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10076 }
10077}
10078
10079int ctrl_enable(struct ctrl *ctrl)
10080{
10081 if (ctrl->wpa)
10082 return 0;
10083
10084 if (!ctrl->stat.cb) {
10085 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10086 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10087 }
10088
10089 if (!ctrl->retry.cb) {
10090 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10091 }
10092
10093 return ctrl_open(ctrl);
10094}
10095
10096static void
10097ctrl_msg_cb(char *buf, size_t len)
10098{
10099 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10100
10101 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10102 ctrl_process(ctrl);
10103}
10104
10105static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10106{
10107 int err;
10108
10109 if (!ctrl->wpa)
10110 return -1;
10111 if (*reply_len < 2)
10112 return -1;
10113
10114 (*reply_len)--;
10115 ctrl->reply_len = sizeof(ctrl->reply);
10116 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10117 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10118 if (err < 0)
10119 return err;
10120
10121 if (ctrl->reply_len > *reply_len)
10122 ctrl->reply_len = *reply_len;
10123
10124 *reply_len = ctrl->reply_len;
10125 memcpy(reply, ctrl->reply, *reply_len);
10126 reply[*reply_len - 1] = 0;
10127 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10128 return 0;
10129}
10130
10131static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10132{
10133 const char *pong = "PONG";
10134 const char *ping = "PING";
10135 char reply[1024];
10136 size_t len = sizeof(reply);
10137 int err;
10138 ULONG s, snum;
10139 INT ret;
10140 BOOL status;
10141
10142 printf("WPA_CTRL: watchdog cb\n");
10143
10144 ret = wifi_getSSIDNumberOfEntries(&snum);
10145 if (ret != RETURN_OK) {
10146 printf("%s: failed to get SSID count", __func__);
10147 return;
10148 }
10149
10150 if (snum > MAX_APS) {
10151 printf("more ssid than supported! %lu\n", snum);
10152 return;
10153 }
10154
10155 for (s = 0; s < snum; s++) {
10156 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10157 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10158 continue;
10159 }
10160 if (status == false) continue;
10161
10162 memset(reply, 0, sizeof(reply));
10163 len = sizeof(reply);
10164 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10165 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10166 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10167 continue;
10168
10169 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10170 ctrl_close(&wpa_ctrl[s]);
10171 printf("WPA_CTRL: ev_timer_again %d\n", s);
10172 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10173 }
10174}
10175
10176static int init_wpa()
10177{
10178 int ret = 0, i = 0;
10179 ULONG s, snum;
10180
10181 ret = wifi_getSSIDNumberOfEntries(&snum);
10182 if (ret != RETURN_OK) {
10183 printf("%s: failed to get SSID count", __func__);
10184 return RETURN_ERR;
10185 }
10186
10187 if (snum > MAX_APS) {
10188 printf("more ssid than supported! %lu\n", snum);
10189 return RETURN_ERR;
10190 }
10191
10192 for (s = 0; s < snum; s++) {
10193 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10194 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10195 wpa_ctrl[s].ssid_index = s;
10196 ctrl_enable(&wpa_ctrl[s]);
10197 }
10198
10199 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10200 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10201
10202 initialized = 1;
10203 printf("WPA_CTRL: initialized\n");
10204
10205 return RETURN_OK;
10206}
10207
10208void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10209{
10210 clients_connect_cb = callback_proc;
10211 if (!initialized)
10212 init_wpa();
10213}
10214
10215void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10216{
10217 clients_disconnect_cb = callback_proc;
10218 if (!initialized)
10219 init_wpa();
10220}
10221
10222INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10223{
10224 // TODO Implement me!
10225 return RETURN_ERR;
10226}
10227
10228INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10229{
10230 // TODO Implement me!
10231 return RETURN_ERR;
10232}
10233
10234INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10235{
10236 int i;
10237 char cmd[256];
10238 char channel_numbers_buf[256];
10239 char dfs_state_buf[256];
10240 char line[256];
10241 const char *ptr;
10242
10243 memset(cmd, 0, sizeof(cmd));
10244 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10245 memset(line, 0, sizeof(line));
10246 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10247 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10248
10249 if (radioIndex == 0) { // 2.4G - all allowed
10250 if (outputMapSize < 11) {
10251 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10252 return RETURN_ERR;
10253 }
10254
10255 for (i = 0; i < 11; i++) {
10256 outputMap[i].ch_number = i + 1;
10257 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10258 }
10259
10260 return RETURN_OK;
10261 }
10262
10263 if (radioIndex == 1) { // 5G
10264// Example output of iw list:
10265//
10266// Frequencies:
10267// * 5180 MHz [36] (17.0 dBm)
10268// * 5200 MHz [40] (17.0 dBm)
10269// * 5220 MHz [44] (17.0 dBm)
10270// * 5240 MHz [48] (17.0 dBm)
10271// * 5260 MHz [52] (23.0 dBm) (radar detection)
10272// DFS state: usable (for 78930 sec)
10273// DFS CAC time: 60000 ms
10274// * 5280 MHz [56] (23.0 dBm) (radar detection)
10275// DFS state: usable (for 78930 sec)
10276// DFS CAC time: 60000 ms
10277// * 5300 MHz [60] (23.0 dBm) (radar detection)
10278// DFS state: usable (for 78930 sec)
10279// DFS CAC time: 60000 ms
10280// * 5320 MHz [64] (23.0 dBm) (radar detection)
10281// DFS state: usable (for 78930 sec)
10282// DFS CAC time: 60000 ms
10283// * 5500 MHz [100] (disabled)
10284// * 5520 MHz [104] (disabled)
10285// * 5540 MHz [108] (disabled)
10286// * 5560 MHz [112] (disabled)
10287//
10288// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10289 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10290 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10291 return RETURN_ERR;
10292 }
10293
10294 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10295 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10296 return RETURN_ERR;
10297 }
10298
10299 ptr = channel_numbers_buf;
10300 i = 0;
10301 while (ptr = get_line_from_str_buf(ptr, line)) {
10302 if (i >= outputMapSize) {
10303 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10304 return RETURN_ERR;
10305 }
10306 sscanf(line, "%d", &outputMap[i].ch_number);
10307
10308 memset(cmd, 0, sizeof(cmd));
10309 // Below command should fetch string for DFS state (usable, available or unavailable)
10310 // Example line: "DFS state: usable (for 78930 sec)"
10311 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) {
10312 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10313 return RETURN_ERR;
10314 }
10315
10316 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10317 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10318 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10319 return RETURN_ERR;
10320 }
10321
10322 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10323
10324 if (!strcmp(dfs_state_buf, "usable")) {
10325 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10326 } else if (!strcmp(dfs_state_buf, "available")) {
10327 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10328 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10329 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10330 } else {
10331 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10332 }
10333 i++;
10334 }
10335
10336 return RETURN_OK;
10337 }
10338
10339 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10340 return RETURN_ERR;
10341}
10342
10343INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10344{
10345 // TODO Implement me!
10346 return RETURN_ERR;
10347}
10348
10349INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10350{
10351 return RETURN_OK;
10352}
10353
10354INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10355{
10356 // TODO Implement me!
10357 return RETURN_ERR;
10358}
10359
10360INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10361{
10362 // TODO API refrence Implementaion is present on RPI hal
10363 return RETURN_ERR;
10364}
10365
10366INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10367{
developera5005b62022-09-13 15:43:35 +080010368 char cmd[128]={'\0'};
10369 char buf[128]={'\0'};
10370 char *support;
10371 int maximum_tx = 0, current_tx = 0;
10372
10373 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10374 if(txpwr_pcntg == NULL)
10375 return RETURN_ERR;
10376
10377 // Get the maximum tx power of the device
10378 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10379 _syscmd(cmd, buf, sizeof(buf));
10380 maximum_tx = strtol(buf, NULL, 10);
10381
10382 // Get the current tx power
10383 memset(cmd, 0, sizeof(cmd));
10384 memset(buf, 0, sizeof(buf));
10385 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10386 _syscmd(cmd, buf, sizeof(buf));
10387 current_tx = strtol(buf, NULL, 10);
10388
10389 // Get the power supported list and find the current power percentage in supported list
10390 memset(buf, 0, sizeof(buf));
10391 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10392 support = strtok(buf, ",");
10393 while(true)
10394 {
10395 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10396 *txpwr_pcntg = 0;
10397 wifi_dbg_printf("current power is not in supported list\n");
10398 return RETURN_ERR;
10399 }
10400 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10401 if (tmp == current_tx) {
10402 *txpwr_pcntg = strtol(support, NULL, 10);
10403 break;
10404 }
10405 support = strtok(NULL, ",");
10406 }
10407 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010408 return RETURN_OK;
10409}
10410
10411INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10412{
developer58599c22022-09-13 16:40:34 +080010413 // TODO precac feature.
10414 struct params params = {0};
10415 char config_file[128] = {0};
10416
10417 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10418
10419 params.name = "enable_background_radar";
10420 params.value = enable?"1":"0";
10421 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10422 wifi_hostapdWrite(config_file, &params, 1);
10423 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10424
10425 /* TODO precac feature */
10426
10427 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10428 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010429}
10430
10431INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10432{
developer58599c22022-09-13 16:40:34 +080010433 char config_file[128] = {0};
10434 char buf[64] = {0};
10435
10436 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10437 if (NULL == enable || NULL == precac)
10438 return RETURN_ERR;
10439
10440 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10441 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10442 if (strncmp(enable, "1", 1) == 0)
10443 *enable = true;
10444 else
10445 *enable = false;
10446
10447 /* TODO precac feature */
10448
10449 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10450 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010451}
10452
10453INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10454{
developer58599c22022-09-13 16:40:34 +080010455 *supported = TRUE;
10456 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010457}
10458
developer454b9462022-09-13 15:29:16 +080010459INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10460{
10461 char cmd[128] = {0};
10462 char buf[64] = {0};
10463 char band_str[8] = {0};
10464 char GI[8] = {0};
10465 int tmp = 0;
10466 BOOL ax_mode = FALSE;
10467 BOOL short_GI = FALSE;
10468 FILE *f = NULL;
10469 wifi_band band;
10470
10471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10472
10473 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10474 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10475 return RETURN_ERR;
10476 }
10477 if (strstr(buf, "ax") != NULL)
10478 ax_mode = TRUE;
10479
10480 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10481 short_GI = TRUE;
10482 strcpy(GI, "0.4");
10483 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10484 strcpy(GI, "1.6");
10485 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10486 strcpy(GI, "3.2");
10487 else // default
10488 strcpy(GI, "0.8");
10489
10490 band = wifi_index_to_band(radio_index);
10491 if (band == band_2_4)
10492 strcpy(band_str, "2.4");
10493 else if (band == band_5)
10494 strcpy(band_str, "5");
10495 else if (band == band_6)
10496 strcpy(band_str, "6");
10497 else {
10498 wifi_dbg_printf("%s: invalid band\n");
10499 return RETURN_ERR;
10500 }
10501
10502 if (ax_mode == TRUE)
10503 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10504 else
10505 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10506 _syscmd(cmd, buf, sizeof(buf));
10507
10508 // Record GI for get GI function
10509 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10510 f = fopen(buf, "w");
10511 if (f != NULL) {
10512 fprintf(f, "%s", GI);
10513 }
10514 fclose(f);
10515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10516 return RETURN_OK;
10517}
10518
10519INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10520{
10521 char buf[32] = {0};
10522 char cmd[64] = {0};
10523
10524 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10525
10526 if (guard_interval == NULL)
10527 return RETURN_ERR;
10528
10529 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10530 _syscmd(cmd, buf, sizeof(buf));
10531
10532 if (strncmp(buf, "0.4", 3) == 0)
10533 *guard_interval = wifi_guard_interval_400;
10534 else if (strncmp(buf, "0.8", 3) == 0)
10535 *guard_interval = wifi_guard_interval_800;
10536 else if (strncmp(buf, "1.6", 3) == 0)
10537 *guard_interval = wifi_guard_interval_1600;
10538 else if (strncmp(buf, "3.2", 3) == 0)
10539 *guard_interval = wifi_guard_interval_3200;
10540 else
10541 *guard_interval = wifi_guard_interval_auto;
10542
10543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10544 return RETURN_OK;
10545}
10546
developer3cc61d12022-09-13 16:36:05 +080010547INT wifi_setBSSColor(INT radio_index, UCHAR color)
10548{
10549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10550 struct params params = {0};
10551 char config_file[128] = {0};
10552 char bss_color[4] ={0};
10553
10554 params.name = "he_bss_color";
10555 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10556 params.value = bss_color;
10557 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10558 wifi_hostapdWrite(config_file, &params, 1);
10559 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10560
10561 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10562 return RETURN_OK;
10563}
10564
10565INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10566{
10567 char config_file[128] = {0};
10568 char buf[64] = {0};
10569 char temp_output[128] = {'\0'};
10570
10571 wifi_dbg_printf("\nFunc=%s\n", __func__);
10572 if (NULL == color)
10573 return RETURN_ERR;
10574
10575 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10576 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10577
10578 if(strlen(buf) > 0) {
10579 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10580 } else {
10581 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10582 }
10583
10584 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10585 wifi_dbg_printf("\noutput_string=%s\n", color);
10586
10587 return RETURN_OK;
10588}
10589
developer06a01d92022-09-07 16:32:39 +080010590/* multi-psk support */
10591INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10592{
10593 char cmd[256];
10594
10595 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10596 AP_PREFIX,
10597 apIndex,
10598 mac[0],
10599 mac[1],
10600 mac[2],
10601 mac[3],
10602 mac[4],
10603 mac[5]
10604 );
10605 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10606 _syscmd(cmd, key->wifi_keyId, 64);
10607
10608
10609 return RETURN_OK;
10610}
10611
10612INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10613{
10614 FILE *fd = NULL;
10615 char fname[100];
10616 char cmd[128] = {0};
10617 char out[64] = {0};
10618 wifi_key_multi_psk_t * key = NULL;
10619 if(keysNumber < 0)
10620 return RETURN_ERR;
10621
10622 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10623 fd = fopen(fname, "w");
10624 if (!fd) {
10625 return RETURN_ERR;
10626 }
10627 key= (wifi_key_multi_psk_t *) keys;
10628 for(int i=0; i<keysNumber; ++i, key++) {
10629 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10630 }
10631 fclose(fd);
10632
10633 //reload file
10634 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10635 _syscmd(cmd, out, 64);
10636 return RETURN_OK;
10637}
10638
10639INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10640{
10641 FILE *fd = NULL;
10642 char fname[100];
10643 char * line = NULL;
10644 char * pos = NULL;
10645 size_t len = 0;
10646 ssize_t read = 0;
10647 INT ret = RETURN_OK;
10648 wifi_key_multi_psk_t *keys_it = NULL;
10649
10650 if (keysNumber < 1) {
10651 return RETURN_ERR;
10652 }
10653
10654 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10655 fd = fopen(fname, "r");
10656 if (!fd) {
10657 return RETURN_ERR;
10658 }
10659
10660 if (keys == NULL) {
10661 ret = RETURN_ERR;
10662 goto close;
10663 }
10664
10665 keys_it = keys;
10666 while ((read = getline(&line, &len, fd)) != -1) {
10667 //Strip trailing new line if present
10668 if (read > 0 && line[read-1] == '\n') {
10669 line[read-1] = '\0';
10670 }
10671
10672 if(strcmp(line,"keyid=")) {
10673 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10674 if (!(pos = index(line, ' '))) {
10675 ret = RETURN_ERR;
10676 goto close;
10677 }
10678 pos++;
10679 //Here should be 00:00:00:00:00:00
10680 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10681 printf("Not supported MAC: %s\n", pos);
10682 }
10683 if (!(pos = index(pos, ' '))) {
10684 ret = RETURN_ERR;
10685 goto close;
10686 }
10687 pos++;
10688
10689 //The rest is PSK
10690 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10691 keys_it++;
10692
10693 if(--keysNumber <= 0)
10694 break;
10695 }
10696 }
10697
10698close:
10699 free(line);
10700 fclose(fd);
10701 return ret;
10702}
10703/* end of multi-psk support */
10704
10705INT wifi_setNeighborReports(UINT apIndex,
10706 UINT numNeighborReports,
10707 wifi_NeighborReport_t *neighborReports)
10708{
10709 char cmd[256] = { 0 };
10710 char hex_bssid[13] = { 0 };
10711 char bssid[18] = { 0 };
10712 char nr[256] = { 0 };
10713 char ssid[256];
10714 char hex_ssid[256];
10715 INT ret;
10716
10717 /*rmeove all neighbors*/
10718 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10719 sprintf(cmd, "hostapd_cli show_neighbor -i %s%d | awk '{print $1 \" \" $2}' | xargs -n2 -r hostapd_cli remove_neighbor -i %s%d",AP_PREFIX,apIndex,AP_PREFIX,apIndex);
10720 system(cmd);
10721
10722 for(unsigned int i = 0; i < numNeighborReports; i++)
10723 {
10724 memset(ssid, 0, sizeof(ssid));
10725 ret = wifi_getSSIDName(apIndex, ssid);
10726 if (ret != RETURN_OK)
10727 return RETURN_ERR;
10728
10729 memset(hex_ssid, 0, sizeof(hex_ssid));
10730 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10731 sprintf(hex_ssid + k,"%02x", ssid[j]);
10732
10733 snprintf(hex_bssid, sizeof(hex_bssid),
10734 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10735 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10736 snprintf(bssid, sizeof(bssid),
10737 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10738 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10739
10740 snprintf(nr, sizeof(nr),
10741 "%s" // bssid
10742 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10743 "%02hhx" // operclass
10744 "%02hhx" // channel
10745 "%02hhx", // phy_mode
10746 hex_bssid,
10747 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10748 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10749 neighborReports[i].opClass,
10750 neighborReports[i].channel,
10751 neighborReports[i].phyTable);
10752
10753 snprintf(cmd, sizeof(cmd),
10754 "hostapd_cli set_neighbor "
10755 "%s " // bssid
10756 "ssid=%s " // ssid
10757 "nr=%s " // nr
10758 "-i %s%d",
10759 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10760
10761 if (WEXITSTATUS(system(cmd)) != 0)
10762 {
10763 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10764 }
10765 }
10766
10767 return RETURN_OK;
10768}
10769
10770INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10771{
10772 return RETURN_OK;
10773}
10774
10775#ifdef _WIFI_HAL_TEST_
10776int main(int argc,char **argv)
10777{
10778 int index;
10779 INT ret=0;
10780 char buf[1024]="";
10781
10782 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10783 if(argc<3)
10784 {
10785 if(argc==2)
10786 {
10787 if(!strcmp(argv[1], "init"))
10788 return wifi_init();
10789 if(!strcmp(argv[1], "reset"))
10790 return wifi_reset();
10791 if(!strcmp(argv[1], "wifi_getHalVersion"))
10792 {
10793 char buffer[64];
10794 if(wifi_getHalVersion(buffer)==RETURN_OK)
10795 printf("Version: %s\n", buffer);
10796 else
10797 printf("Error in wifi_getHalVersion\n");
10798 return RETURN_OK;
10799 }
10800 }
10801 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10802 exit(-1);
10803 }
10804
10805 index = atoi(argv[2]);
10806 if(strstr(argv[1], "wifi_getApName")!=NULL)
10807 {
10808 wifi_getApName(index,buf);
10809 printf("Ap name is %s \n",buf);
10810 return 0;
10811 }
10812 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10813 {
10814 BOOL b = FALSE;
10815 BOOL *output_bool = &b;
10816 wifi_getRadioAutoChannelEnable(index,output_bool);
10817 printf("Channel enabled = %d \n",b);
10818 return 0;
10819 }
10820 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10821 {
10822 wifi_getApWpaEncryptionMode(index,buf);
10823 printf("encryption enabled = %s\n",buf);
10824 return 0;
10825 }
10826 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10827 {
10828 BOOL b = FALSE;
10829 BOOL *output_bool = &b;
10830 wifi_getApSsidAdvertisementEnable(index,output_bool);
10831 printf("advertisment enabled = %d\n",b);
10832 return 0;
10833 }
10834 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10835 {
10836 if(argc <= 3 )
10837 {
10838 printf("Insufficient arguments \n");
10839 exit(-1);
10840 }
10841
10842 char sta[20] = {'\0'};
10843 ULLONG handle= 0;
10844 strcpy(sta,argv[3]);
10845 mac_address_t st;
10846 mac_addr_aton(st,sta);
10847
10848 wifi_associated_dev_tid_stats_t tid_stats;
10849 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10850 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10851 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);
10852 }
10853
10854 if(strstr(argv[1], "getApEnable")!=NULL) {
10855 BOOL enable;
10856 ret=wifi_getApEnable(index, &enable);
10857 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10858 }
10859 else if(strstr(argv[1], "setApEnable")!=NULL) {
10860 BOOL enable = atoi(argv[3]);
10861 ret=wifi_setApEnable(index, enable);
10862 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
10863 }
10864 else if(strstr(argv[1], "getApStatus")!=NULL) {
10865 char status[64];
10866 ret=wifi_getApStatus(index, status);
10867 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
10868 }
10869 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
10870 {
10871 wifi_getSSIDNameStatus(index,buf);
10872 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
10873 return 0;
10874 }
10875 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
10876 wifi_ssidTrafficStats2_t stats={0};
10877 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
10878 printf("%s %d: returns %d\n", argv[1], index, ret);
10879 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
10880 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
10881 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
10882 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
10883 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
10884 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
10885 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
10886 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
10887 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
10888 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
10889 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
10890 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
10891 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
10892 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
10893 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
10894 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
10895 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
10896 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
10897 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
10898 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
10899 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
10900 }
10901 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
10902 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
10903 UINT array_size=0;
10904 UINT i=0;
10905 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
10906 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10907 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
10908 printf(" neighbor %d:\n", i);
10909 printf(" ap_SSID =%s\n", pt->ap_SSID);
10910 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
10911 printf(" ap_Mode =%s\n", pt->ap_Mode);
10912 printf(" ap_Channel =%d\n", pt->ap_Channel);
10913 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
10914 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10915 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
10916 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
10917 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
10918 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
10919 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
10920 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
10921 printf(" ap_Noise =%d\n", pt->ap_Noise);
10922 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
10923 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
10924 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
10925 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
10926 }
10927 if(neighbor_ap_array)
10928 free(neighbor_ap_array); //make sure to free the list
10929 }
10930 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
10931 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
10932 UINT array_size=0;
10933 UINT i=0;
10934 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
10935 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
10936 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
10937 printf(" associated_dev %d:\n", i);
10938 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
10939 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
10940 printf(" cli_SNR =%d\n", pt->cli_SNR);
10941 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
10942 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
10943 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
10944 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
10945 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
10946 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
10947 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
10948 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
10949 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
10950 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
10951 }
10952 if(associated_dev_array)
10953 free(associated_dev_array); //make sure to free the list
10954 }
10955
10956 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
10957 {
10958#define MAX_ARRAY_SIZE 64
10959 int i, array_size;
10960 char *p, *ch_str;
10961 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
10962
10963 if(argc != 5)
10964 {
10965 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
10966 exit(-1);
10967 }
10968 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
10969
10970 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
10971 {
10972 strtok_r(ch_str, ",", &p);
10973 input_output_channelStats_array[i].ch_number = atoi(ch_str);
10974 }
10975 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
10976 if(!array_size)
10977 array_size=1;//Need to print current channel statistics
10978 for(i=0; i<array_size; i++)
10979 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
10980 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
10981 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
10982 input_output_channelStats_array[i].ch_number,\
10983 input_output_channelStats_array[i].ch_noise,\
10984 input_output_channelStats_array[i].ch_utilization_busy_rx,\
10985 input_output_channelStats_array[i].ch_utilization_busy_tx,\
10986 input_output_channelStats_array[i].ch_utilization_busy,\
10987 input_output_channelStats_array[i].ch_utilization_busy_ext,\
10988 input_output_channelStats_array[i].ch_utilization_total);
10989 }
10990
10991 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
10992 {
10993 if(argc <= 3 )
10994 {
10995 printf("Insufficient arguments \n");
10996 exit(-1);
10997 }
10998 char mac_addr[20] = {'\0'};
10999 wifi_device_t output_struct;
11000 int dev_index = atoi(argv[3]);
11001
11002 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11003 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11004 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);
11005 }
11006
11007 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11008 {
11009 if (argc <= 3)
11010 {
11011 printf("Insufficient arguments\n");
11012 exit(-1);
11013 }
11014 char args[256];
11015 wifi_NeighborReport_t *neighborReports;
11016
11017 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11018 if (!neighborReports)
11019 {
11020 printf("Failed to allocate memory");
11021 exit(-1);
11022 }
11023
11024 for (int i = 3; i < argc; ++i)
11025 {
11026 char *val;
11027 int j = 0;
11028 memset(args, 0, sizeof(args));
11029 strncpy(args, argv[i], sizeof(args));
11030 val = strtok(args, ";");
11031 while (val != NULL)
11032 {
11033 if (j == 0)
11034 {
11035 mac_addr_aton(neighborReports[i - 3].bssid, val);
11036 } else if (j == 1)
11037 {
11038 neighborReports[i - 3].info = strtol(val, NULL, 16);
11039 } else if (j == 2)
11040 {
11041 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11042 } else if (j == 3)
11043 {
11044 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11045 } else if (j == 4)
11046 {
11047 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11048 } else {
11049 printf("Insufficient arguments]n\n");
11050 exit(-1);
11051 }
11052 val = strtok(NULL, ";");
11053 j++;
11054 }
11055 }
11056
11057 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11058 if (ret != RETURN_OK)
11059 {
11060 printf("wifi_setNeighborReports ret = %d", ret);
11061 exit(-1);
11062 }
11063 }
11064 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11065 {
11066 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11067 printf("%s.\n", buf);
11068 else
11069 printf("Error returned\n");
11070 }
11071 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11072 {
11073 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11074 printf("%s.\n", buf);
11075 else
11076 printf("Error returned\n");
11077 }
11078 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11079 {
11080 if (argc <= 2)
11081 {
11082 printf("Insufficient arguments\n");
11083 exit(-1);
11084 }
11085 char buf[64]= {'\0'};
11086 wifi_getRadioOperatingChannelBandwidth(index,buf);
11087 printf("Current bandwidth is %s \n",buf);
11088 return 0;
11089 }
11090 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11091 {
11092 if (argc <= 5)
11093 {
11094 printf("Insufficient arguments\n");
11095 exit(-1);
11096 }
11097 UINT channel = atoi(argv[3]);
11098 UINT width = atoi(argv[4]);
11099 UINT beacon = atoi(argv[5]);
11100 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11101 printf("Result = %d", ret);
11102 }
11103
11104 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11105 return 0;
11106}
11107
11108#endif
11109
11110#ifdef WIFI_HAL_VERSION_3
11111
developer1e5aa162022-09-13 16:06:24 +080011112INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11113{
11114 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11115 if (bitMap & WIFI_BITRATE_1MBPS)
11116 strcat(BasicRate, "1,");
11117 if (bitMap & WIFI_BITRATE_2MBPS)
11118 strcat(BasicRate, "2,");
11119 if (bitMap & WIFI_BITRATE_5_5MBPS)
11120 strcat(BasicRate, "5.5,");
11121 if (bitMap & WIFI_BITRATE_6MBPS)
11122 strcat(BasicRate, "6,");
11123 if (bitMap & WIFI_BITRATE_9MBPS)
11124 strcat(BasicRate, "9,");
11125 if (bitMap & WIFI_BITRATE_11MBPS)
11126 strcat(BasicRate, "11,");
11127 if (bitMap & WIFI_BITRATE_12MBPS)
11128 strcat(BasicRate, "12,");
11129 if (bitMap & WIFI_BITRATE_18MBPS)
11130 strcat(BasicRate, "18,");
11131 if (bitMap & WIFI_BITRATE_24MBPS)
11132 strcat(BasicRate, "24,");
11133 if (bitMap & WIFI_BITRATE_36MBPS)
11134 strcat(BasicRate, "36,");
11135 if (bitMap & WIFI_BITRATE_48MBPS)
11136 strcat(BasicRate, "48,");
11137 if (bitMap & WIFI_BITRATE_54MBPS)
11138 strcat(BasicRate, "54,");
11139 if (strlen(BasicRate) != 0) // remove last comma
11140 BasicRate[strlen(BasicRate) - 1] = '\0';
11141 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11142 return RETURN_OK;
11143}
11144
11145INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11146{
11147 UINT BitMap = 0;
11148 char *rate;
11149
11150 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11151 rate = strtok(BasicRatesList, ",");
11152 while(rate != NULL)
11153 {
11154 if (strcmp(rate, "1") == 0)
11155 BitMap |= WIFI_BITRATE_1MBPS;
11156 else if (strcmp(rate, "2") == 0)
11157 BitMap |= WIFI_BITRATE_2MBPS;
11158 else if (strcmp(rate, "5.5") == 0)
11159 BitMap |= WIFI_BITRATE_5_5MBPS;
11160 else if (strcmp(rate, "6") == 0)
11161 BitMap |= WIFI_BITRATE_6MBPS;
11162 else if (strcmp(rate, "9") == 0)
11163 BitMap |= WIFI_BITRATE_9MBPS;
11164 else if (strcmp(rate, "11") == 0)
11165 BitMap |= WIFI_BITRATE_11MBPS;
11166 else if (strcmp(rate, "12") == 0)
11167 BitMap |= WIFI_BITRATE_12MBPS;
11168 else if (strcmp(rate, "18") == 0)
11169 BitMap |= WIFI_BITRATE_18MBPS;
11170 else if (strcmp(rate, "24") == 0)
11171 BitMap |= WIFI_BITRATE_24MBPS;
11172 else if (strcmp(rate, "36") == 0)
11173 BitMap |= WIFI_BITRATE_36MBPS;
11174 else if (strcmp(rate, "48") == 0)
11175 BitMap |= WIFI_BITRATE_48MBPS;
11176 else if (strcmp(rate, "54") == 0)
11177 BitMap |= WIFI_BITRATE_54MBPS;
11178 rate = strtok(NULL, ",");
11179 }
11180 *basicRateBitMap = BitMap;
11181 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11182 return RETURN_OK;
11183}
11184
11185// This API is used to configured all radio operation parameter in a single set. it includes channel number, channelWidth, mode and auto chammel configuration.
developer06a01d92022-09-07 16:32:39 +080011186INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11187{
developer1e5aa162022-09-13 16:06:24 +080011188 char buf[128] = {0};
11189 char cmd[128] = {0};
11190 char config_file[64] = {0};
11191 int bandwidth;
11192 int set_mode;
11193 wifi_radio_operationParam_t current_param;
11194
11195 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11196
11197 multiple_set = TRUE;
11198 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11199 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11200 return RETURN_ERR;
11201 }
11202 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11203 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11204 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11205 return RETURN_ERR;
11206 }
11207 }
11208 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11209 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11210 bandwidth = 20;
11211 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11212 bandwidth = 40;
11213 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11214 bandwidth = 80;
11215 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11216 bandwidth = 160;
11217 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11218 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11219 return RETURN_ERR;
11220 }
11221 }
11222 if (current_param.variant != operationParam->variant) {
11223 // Two different definition bit map, so need to check every bit.
11224 if (operationParam->variant & WIFI_80211_VARIANT_A)
11225 set_mode |= WIFI_MODE_A;
11226 if (operationParam->variant & WIFI_80211_VARIANT_B)
11227 set_mode |= WIFI_MODE_B;
11228 if (operationParam->variant & WIFI_80211_VARIANT_G)
11229 set_mode |= WIFI_MODE_G;
11230 if (operationParam->variant & WIFI_80211_VARIANT_N)
11231 set_mode |= WIFI_MODE_N;
11232 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11233 set_mode |= WIFI_MODE_AC;
11234 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11235 set_mode |= WIFI_MODE_AX;
11236 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11237 memset(buf, 0, sizeof(buf));
11238 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11239 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11240 return RETURN_ERR;
11241 }
11242 }
11243 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11244 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11245 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11246 return RETURN_ERR;
11247 }
11248 }
11249 if (current_param.beaconInterval != operationParam->beaconInterval) {
11250 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11251 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11252 return RETURN_ERR;
11253 }
11254 }
11255 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11256 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11257 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11258 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11259 return RETURN_ERR;
11260 }
11261 }
11262 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11263 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11264 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11265 return RETURN_ERR;
11266 }
11267 }
11268 if (current_param.guardInterval != operationParam->guardInterval) {
11269 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11270 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11271 return RETURN_ERR;
11272 }
11273 }
11274 if (current_param.transmitPower != operationParam->transmitPower) {
11275 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11276 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11277 return RETURN_ERR;
11278 }
11279 }
11280 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11281 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11282 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11283 return RETURN_ERR;
11284 }
11285 }
11286 if (current_param.obssCoex != operationParam->obssCoex) {
11287 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11288 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11289 return RETURN_ERR;
11290 }
11291 }
11292 if (current_param.stbcEnable != operationParam->stbcEnable) {
11293 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11294 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11295 return RETURN_ERR;
11296 }
11297 }
11298 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11299 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11300 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11301 return RETURN_ERR;
11302 }
11303 }
11304
11305 // if enable is true, then restart the radio
11306 wifi_setRadioEnable(index, FALSE);
11307 if (operationParam->enable == TRUE)
11308 wifi_setRadioEnable(index, TRUE);
11309 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11310
developer06a01d92022-09-07 16:32:39 +080011311 return RETURN_OK;
11312}
11313
11314INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11315{
developer1e5aa162022-09-13 16:06:24 +080011316 char band[64] = {0};
11317 char buf[256] = {0};
11318 char config_file[64] = {0};
11319 char cmd[128] = {0};
11320 int ret = RETURN_ERR;
11321 int mode = 0;
11322 ULONG channel = 0;
11323 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011324
11325 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11326 printf("Entering %s index = %d\n", __func__, (int)index);
11327
developer1e5aa162022-09-13 16:06:24 +080011328 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11329 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11330 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011331 {
developer1e5aa162022-09-13 16:06:24 +080011332 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011333 return RETURN_ERR;
11334 }
11335 operationParam->enable = enabled;
11336
11337 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011338 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011339 {
developer1e5aa162022-09-13 16:06:24 +080011340 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011341 return RETURN_ERR;
11342 }
11343
11344 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011345 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011346 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011347 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011348 else if (!strcmp(band, "6GHz"))
11349 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011350 else
11351 {
developer1e5aa162022-09-13 16:06:24 +080011352 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011353 band);
11354 }
11355
developer1e5aa162022-09-13 16:06:24 +080011356 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11357 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11358 operationParam->channel = 0;
11359 operationParam->autoChannelEnabled = TRUE;
11360 } else {
11361 operationParam->channel = strtol(buf, NULL, 10);
11362 operationParam->autoChannelEnabled = FALSE;
11363 }
11364
developer06a01d92022-09-07 16:32:39 +080011365 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011366 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11367 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11368 return RETURN_ERR;
11369 }
developer06a01d92022-09-07 16:32:39 +080011370 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11371 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11372 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011373 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11374 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011375 else
11376 {
developer1e5aa162022-09-13 16:06:24 +080011377 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11378 return false;
developer06a01d92022-09-07 16:32:39 +080011379 }
11380
developer1e5aa162022-09-13 16:06:24 +080011381 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11382 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11383 return RETURN_ERR;
11384 }
11385 // Two different definition bit map, so need to check every bit.
11386 if (mode & WIFI_MODE_A)
11387 operationParam->variant |= WIFI_80211_VARIANT_A;
11388 if (mode & WIFI_MODE_B)
11389 operationParam->variant |= WIFI_80211_VARIANT_B;
11390 if (mode & WIFI_MODE_G)
11391 operationParam->variant |= WIFI_80211_VARIANT_G;
11392 if (mode & WIFI_MODE_N)
11393 operationParam->variant |= WIFI_80211_VARIANT_N;
11394 if (mode & WIFI_MODE_AC)
11395 operationParam->variant |= WIFI_80211_VARIANT_AC;
11396 if (mode & WIFI_MODE_AX)
11397 operationParam->variant |= WIFI_80211_VARIANT_AX;
11398 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11399 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11400 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011401 }
developer1e5aa162022-09-13 16:06:24 +080011402 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11403 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11404 return RETURN_ERR;
11405 }
11406 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11407 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11408 return RETURN_ERR;
11409 }
developer06a01d92022-09-07 16:32:39 +080011410
developer1e5aa162022-09-13 16:06:24 +080011411 memset(buf, 0, sizeof(buf));
11412 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11413 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11414 return RETURN_ERR;
11415 }
11416 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11417
11418 memset(buf, 0, sizeof(buf));
11419 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11420 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11421 return RETURN_ERR;
11422 }
11423 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11424
11425 memset(buf, 0, sizeof(buf));
11426 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11427 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11428
11429 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11430 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11431 return RETURN_ERR;
11432 }
11433 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11434 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11435 return RETURN_ERR;
11436 }
11437
11438 memset(buf, 0, sizeof(buf));
11439 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11440 if (strcmp(buf, "-1") == 0) {
11441 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11442 operationParam->ctsProtection = FALSE;
11443 } else {
11444 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11445 operationParam->ctsProtection = TRUE;
11446 }
11447
11448 memset(buf, 0, sizeof(buf));
11449 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11450 if (strcmp(buf, "0") == 0)
11451 operationParam->obssCoex = FALSE;
11452 else
11453 operationParam->obssCoex = TRUE;
11454
11455 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11456 _syscmd(cmd, buf, sizeof(buf));
11457 if (strlen(buf) != 0)
11458 operationParam->stbcEnable = TRUE;
11459 else
11460 operationParam->stbcEnable = FALSE;
11461
11462 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11463 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11464 return RETURN_ERR;
11465 }
11466
11467 // Below value is hardcoded
11468
11469 operationParam->numSecondaryChannels = 0;
11470 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11471 operationParam->channelSecondary[i] = 0;
11472 }
11473 operationParam->csa_beacon_count = 15;
11474 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011475
11476 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11477 return RETURN_OK;
11478}
11479
11480static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11481{
11482 if (radioIndex != 0 && radioIndex != 1)
11483 {
11484 printf("%s: Wrong radio index (%d)\n", __func__, index);
11485 return -1;
11486 }
11487
11488 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11489 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11490
11491 return (arrayIndex * 2) + radioIndex;
11492}
11493
11494INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11495{
11496 INT ret;
11497 int i;
11498 BOOL enabled = false;
11499 char buf[256];
11500 wifi_secur_list *secur_item;
11501 int vap_index;
11502 INT mode;
11503 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11504
11505 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11506 printf("Entering %s index = %d\n", __func__, (int)index);
11507
11508 map->vap_array[index].radio_index = index;
11509 for (i = 0; i < 5; i++)
11510 {
11511 vap_index = array_index_to_vap_index(index, i);
11512 if (vap_index < 0)
11513 {
11514 return RETURN_ERR;
11515 }
11516
11517 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11518
11519 map->vap_array[i].vap_index = vap_index;
11520
11521 memset(buf, 0, sizeof(buf));
11522 wifi_getApName(vap_index, buf); // XXX: error handling
11523 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11524
11525 ret = wifi_getSSIDEnable(vap_index, &enabled);
11526 if (ret != RETURN_OK)
11527 {
11528 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11529 return RETURN_ERR;
11530 }
11531 map->vap_array[i].u.bss_info.enabled = enabled;
11532
11533 memset(buf, 0, sizeof(buf));
11534 wifi_getBaseBSSID(vap_index, buf);
11535 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11536 &map->vap_array[i].u.bss_info.bssid[0],
11537 &map->vap_array[i].u.bss_info.bssid[1],
11538 &map->vap_array[i].u.bss_info.bssid[2],
11539 &map->vap_array[i].u.bss_info.bssid[3],
11540 &map->vap_array[i].u.bss_info.bssid[4],
11541 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11542
11543 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11544 map->vap_array[i].u.bss_info.showSsid = enabled;
11545
11546 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11547 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11548 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11549
11550 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11551 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11552
11553 memset(buf, 0, sizeof(buf));
11554 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11555 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11556
11557 wifi_getApSecurityModeEnabled(vap_index, buf);
11558
11559 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11560 {
11561 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11562 return RETURN_ERR;
11563 }
11564 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11565
11566 memset(buf, 0, sizeof(buf));
11567 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11568 strncpy(map->vap_array[i].u.bss_info.security.u.key.key, buf, sizeof(map->vap_array[i].u.bss_info.security.u.key.key) - 1);
11569
11570 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11571 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11572
11573 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11574 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11575
11576 wifi_getApIsolationEnable(vap_index, &enabled);
11577 map->vap_array[i].u.bss_info.isolation = enabled;
11578 }
11579 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11580 return RETURN_OK;
11581}
11582
11583INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11584{
11585 unsigned int i;
11586 wifi_vap_info_t *vap_info = NULL;
11587 int acl_mode;
11588 char *sec_str = NULL;
11589
11590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11591 printf("Entering %s index = %d\n", __func__, (int)index);
11592 for (i = 0; i < map->num_vaps; i++)
11593 {
11594 vap_info = &map->vap_array[i];
11595 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11596
11597 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11598 else
11599 {
11600 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11601 else acl_mode = 1;
11602 }
11603 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11604 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11605 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11606
11607 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11608 if (sec_str)
11609 {
11610 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11611 }
11612 else
11613 {
11614 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11615 }
11616
11617 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11618 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11619
11620 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11621 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11622
11623 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11624
11625 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11626 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11627 }
11628 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11629 return RETURN_OK;
11630}
11631
11632int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11633{
11634 char *token, *next;
11635 const char s[2] = ",";
11636 int count =0;
11637
11638 /* get the first token */
11639 token = strtok_r(pchannels, s, &next);
11640
11641 /* walk through other tokens */
11642 while( token != NULL && count < MAX_CHANNELS) {
11643 chlistptr->channels_list[count++] = atoi(token);
11644 token = strtok_r(NULL, s, &next);
11645 }
11646
11647 return count;
11648}
11649
11650static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11651{
11652 INT status;
11653 wifi_channels_list_t *chlistp;
11654 CHAR output_string[64];
11655 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011656 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011657
11658 if(rcap == NULL)
11659 {
11660 return RETURN_ERR;
11661 }
11662
11663 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011664 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011665
developer1e5aa162022-09-13 16:06:24 +080011666 if (band == band_2_4)
11667 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11668 else if (band == band_5)
11669 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11670 else if (band == band_6)
11671 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011672
11673 chlistp = &(rcap->channel_list[0]);
11674 memset(pchannels, 0, sizeof(pchannels));
11675
11676 /* possible number of radio channels */
11677 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11678 {
11679 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11680 }
11681 /* Number of channels and list*/
11682 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11683
11684 /* autoChannelSupported */
11685 /* always ON with wifi_getRadioAutoChannelSupported */
11686 rcap->autoChannelSupported = TRUE;
11687
11688 /* DCSSupported */
11689 /* always ON with wifi_getRadioDCSSupported */
11690 rcap->DCSSupported = TRUE;
11691
11692 /* zeroDFSSupported - TBD */
11693 rcap->zeroDFSSupported = FALSE;
11694
11695 /* Supported Country List*/
11696 memset(output_string, 0, sizeof(output_string));
11697 status = wifi_getRadioCountryCode(radioIndex, output_string);
11698 if( status != 0 ) {
11699 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11700 return RETURN_ERR;
11701 } else {
11702 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11703 }
11704 if(!strcmp(output_string,"US")){
11705 rcap->countrySupported[0] = wifi_countrycode_US;
11706 rcap->countrySupported[1] = wifi_countrycode_CA;
11707 } else if (!strcmp(output_string,"CA")) {
11708 rcap->countrySupported[0] = wifi_countrycode_CA;
11709 rcap->countrySupported[1] = wifi_countrycode_US;
11710 } else {
11711 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11712 }
11713
11714 rcap->numcountrySupported = 2;
11715
11716 /* csi */
11717 rcap->csi.maxDevices = 8;
11718 rcap->csi.soudingFrameSupported = TRUE;
11719
11720 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11721
11722 /* channelWidth - all supported bandwidths */
11723 int i=0;
11724 rcap->channelWidth[i] = 0;
11725 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11726 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11727 WIFI_CHANNELBANDWIDTH_40MHZ);
11728
11729 }
developer1e5aa162022-09-13 16:06:24 +080011730 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011731 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11732 WIFI_CHANNELBANDWIDTH_40MHZ |
11733 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11734 }
11735
11736
11737 /* mode - all supported variants */
11738 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11739 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011740 rcap->mode[i] = ( WIFI_80211_VARIANT_B | WIFI_80211_VARIANT_G | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011741 }
11742 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011743 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11744 }
11745 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11746 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011747 }
11748 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11749 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11750
11751 /* supportedBitRate - all supported bitrates */
11752 rcap->supportedBitRate[i] = 0;
11753 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11754 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11755 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11756 }
developer1e5aa162022-09-13 16:06:24 +080011757 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011758 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11759 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11760 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11761 }
11762
11763
11764 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11765 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11766 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11767 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11768 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11769 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11770 rcap->cipherSupported = 0;
11771 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11772 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11773
11774 return RETURN_OK;
11775}
11776
11777INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11778{
11779 INT status, radioIndex;
11780 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11781 int iter = 0;
11782 unsigned int j;
11783 wifi_interface_name_idex_map_t *iface_info;
11784
11785 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11786
11787 memset(cap, 0, sizeof(wifi_hal_capability_t));
11788
11789 /* version */
11790 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11791 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11792
11793 /* number of radios platform property */
11794 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11795 _syscmd(cmd, output, sizeof(output));
11796 cap->wifi_prop.numRadios = atoi(output);
11797
11798 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11799 {
11800 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11801 if (status != 0) {
11802 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11803 return RETURN_ERR;
11804 }
11805
11806 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11807 {
11808 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11809 {
11810 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11811 return RETURN_ERR;
11812 }
11813 iface_info = &cap->wifi_prop.interface_map[iter];
11814 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11815 iface_info->rdk_radio_index = radioIndex;
11816 memset(output, 0, sizeof(output));
11817 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11818 {
11819 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11820 }
11821 // TODO: bridge name
11822 // TODO: vlan id
11823 // TODO: primary
11824 iface_info->index = array_index_to_vap_index(radioIndex, j);
11825 memset(output, 0, sizeof(output));
11826 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11827 {
11828 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11829 }
11830 iter++;
11831 }
11832 }
11833
11834 cap->BandSteeringSupported = FALSE;
11835 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11836 return RETURN_OK;
11837}
11838
11839INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11840{
developer587c1b62022-09-27 15:58:59 +080011841 char buf[128] = {0};
11842 char config_file[128] = {0};
11843 char password[64] = {0};
11844 char mfp[32] = {0};
11845 char wpa_mode[32] = {0};
11846 struct params params = {0};
11847
11848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11849
11850 multiple_set = TRUE;
11851 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11852 if (security->mode == wifi_security_mode_none) {
11853 strcpy(wpa_mode, "None");
11854 } else if (security->mode == wifi_security_mode_wpa_personal)
11855 strcpy(wpa_mode, "WPA-Personal");
11856 else if (security->mode == wifi_security_mode_wpa2_personal)
11857 strcpy(wpa_mode, "WPA2-Personal");
11858 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
11859 strcpy(wpa_mode, "WPA-WPA2-Personal");
11860 else if (security->mode == wifi_security_mode_wpa_enterprise)
11861 strcpy(wpa_mode, "WPA-Enterprise");
11862 else if (security->mode == wifi_security_mode_wpa2_enterprise)
11863 strcpy(wpa_mode, "WPA2-Enterprise");
11864 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
11865 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
11866 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
11867 strcpy(wpa_mode, "WPA3-Personal");
11868 else if (security->mode == wifi_security_mode_wpa3_enterprise)
11869 strcpy(wpa_mode, "WPA3-Enterprise");
11870
11871 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
11872
11873 strncpy(password, security->u.key.key, 63);
11874 password[63] = '\0';
11875 wifi_setApSecurityKeyPassphrase(ap_index, password);
11876
11877 if (security->mode != wifi_security_mode_none) {
11878 memset(&params, 0, sizeof(params));
11879 params.name = "wpa_pairwise";
11880 if (security->encr == wifi_encryption_tkip)
11881 params.value = "TKIP";
11882 else if (security->encr == wifi_encryption_aes)
11883 params.value = "CCMP";
11884 else if (security->encr == wifi_encryption_aes_tkip)
11885 params.value = "TKIP CCMP";
11886 wifi_hostapdWrite(config_file, &params, 1);
11887 }
11888
11889 if (security->mfp == wifi_mfp_cfg_disabled)
11890 strcpy(mfp, "Disable");
11891 else if (security->mfp == wifi_mfp_cfg_optional)
11892 strcpy(mfp, "Optional");
11893 else if (security->mfp == wifi_mfp_cfg_required)
11894 strcpy(mfp, "Required");
11895 wifi_setApSecurityMFPConfig(ap_index, mfp);
11896
11897 memset(&params, 0, sizeof(params));
11898 params.name = "transition_disable";
11899 if (security->wpa3_transition_disable == TRUE)
11900 params.value = "0x01";
11901 else
11902 params.value = "0x00";
11903 wifi_hostapdWrite(config_file, &params, 1);
11904
11905 memset(&params, 0, sizeof(params));
11906 params.name = "wpa_group_rekey";
11907 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
11908 params.value = buf;
11909 wifi_hostapdWrite(config_file, &params, 1);
11910
11911 memset(&params, 0, sizeof(params));
11912 params.name = "wpa_strict_rekey";
11913 params.value = security->strict_rekey?"1":"0";
11914 wifi_hostapdWrite(config_file, &params, 1);
11915
11916 memset(&params, 0, sizeof(params));
11917 params.name = "wpa_pairwise_update_count";
11918 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
11919 params.value = buf;
11920 wifi_hostapdWrite(config_file, &params, 1);
11921
11922 memset(&params, 0, sizeof(params));
11923 params.name = "disable_pmksa_caching";
11924 params.value = security->disable_pmksa_caching?"1":"0";
11925 wifi_hostapdWrite(config_file, &params, 1);
11926
11927 wifi_setApEnable(ap_index, FALSE);
11928 wifi_setApEnable(ap_index, TRUE);
11929
11930 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11931
developer06a01d92022-09-07 16:32:39 +080011932 return RETURN_OK;
11933}
11934
11935INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
11936{
developer587c1b62022-09-27 15:58:59 +080011937 char buf[128] = {0};
11938 char config_file[128] = {0};
11939 int disable = 0;
11940 // struct params params = {0};
11941
11942 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11943 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11944 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
11945 security->mode = wifi_security_mode_none;
11946 if (strlen(buf) != 0) {
11947 if (strcmp(buf, "WPA-Personal"))
11948 security->mode = wifi_security_mode_wpa_personal;
11949 else if (strcmp(buf, "WPA2-Personal"))
11950 security->mode = wifi_security_mode_wpa2_personal;
11951 else if (strcmp(buf, "WPA-WPA2-Personal"))
11952 security->mode = wifi_security_mode_wpa_wpa2_personal;
11953 else if (strcmp(buf, "WPA-Enterprise"))
11954 security->mode = wifi_security_mode_wpa_enterprise;
11955 else if (strcmp(buf, "WPA2-Enterprise"))
11956 security->mode = wifi_security_mode_wpa2_enterprise;
11957 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
11958 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
11959 else if (strcmp(buf, "WPA3-Personal"))
11960 security->mode = wifi_security_mode_wpa3_personal;
11961 else if (strcmp(buf, "WPA3-Transition"))
11962 security->mode = wifi_security_mode_wpa3_transition;
11963 else if (strcmp(buf, "WPA3-Enterprise"))
11964 security->mode = wifi_security_mode_wpa3_enterprise;
11965 }
11966
11967 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
11968 if (security->mode == wifi_security_mode_none)
11969 security->encr = wifi_encryption_none;
11970 else {
11971 if (strcmp(buf, "TKIP") == 0)
11972 security->encr = wifi_encryption_tkip;
11973 else if (strcmp(buf, "CCMP") == 0)
11974 security->encr = wifi_encryption_aes;
11975 else
11976 security->encr = wifi_encryption_aes_tkip;
11977 }
11978
11979 memset(buf, 0, sizeof(buf));
11980 wifi_getApSecurityMFPConfig(ap_index, buf);
11981 if (strcmp(buf, "Disabled") == 0)
11982 security->mfp = wifi_mfp_cfg_disabled;
11983 else if (strcmp(buf, "Optional") == 0)
11984 security->mfp = wifi_mfp_cfg_optional;
11985 else if (strcmp(buf, "Required") == 0)
11986 security->mfp = wifi_mfp_cfg_required;
11987
11988 memset(buf, 0, sizeof(buf));
11989 security->wpa3_transition_disable = FALSE;
11990 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
11991 disable = strtol(buf, NULL, 16);
11992 if (disable != 0)
11993 security->wpa3_transition_disable = TRUE;
11994
11995 memset(buf, 0, sizeof(buf));
11996 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
11997 if (strlen(buf) == 0)
11998 security->rekey_interval = 86400;
11999 else
12000 security->rekey_interval = strtol(buf, NULL, 10);
12001
12002 memset(buf, 0, sizeof(buf));
12003 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12004 if (strlen(buf) == 0)
12005 security->strict_rekey = 1;
12006 else
12007 security->strict_rekey = strtol(buf, NULL, 10);
12008
12009 memset(buf, 0, sizeof(buf));
12010 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12011 if (strlen(buf) == 0)
12012 security->eapol_key_retries = 4;
12013 else
12014 security->eapol_key_retries = strtol(buf, NULL, 10);
12015
12016 memset(buf, 0, sizeof(buf));
12017 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12018 if (strlen(buf) == 0)
12019 security->disable_pmksa_caching = FALSE;
12020 else
12021 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12022
12023 /* TODO
12024 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12025 */
12026 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12027 security->eap_identity_req_timeout = 0;
12028 security->eap_identity_req_retries = 0;
12029 security->eap_req_timeout = 0;
12030 security->eap_req_retries = 0;
12031 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012032 return RETURN_OK;
12033}
12034
12035#endif /* WIFI_HAL_VERSION_3 */
12036
12037#ifdef WIFI_HAL_VERSION_3_PHASE2
12038INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12039{
developer13df9332022-09-27 16:53:22 +080012040 char cmd[128] = {0};
12041 char buf[128] = {0};
12042 char *mac_addr = NULL;
12043 BOOL status = FALSE;
12044 size_t len = 0;
12045
12046 if(ap_index > MAX_APS)
12047 return RETURN_ERR;
12048
12049 *output_numDevices = 0;
12050 wifi_getApEnable(ap_index, &status);
12051 if (status == FALSE)
12052 return RETURN_OK;
12053
12054 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12055 _syscmd(cmd, buf, sizeof(buf));
12056
12057 mac_addr = strtok(buf, "\n");
12058 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12059 *output_numDevices = i + 1;
12060 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12061 addr_ptr = output_deviceMacAddressArray[i];
12062 mac_addr_aton(addr_ptr, mac_addr);
12063 mac_addr = strtok(NULL, "\n");
12064 }
12065
12066 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012067}
12068#else
12069INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12070{
12071 char cmd[128];
12072 BOOL status = false;
12073
12074 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12075 return RETURN_ERR;
12076
12077 output_buf[0] = '\0';
12078
12079 wifi_getApEnable(ap_index,&status);
12080 if (!status)
12081 return RETURN_OK;
12082
12083 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12084 _syscmd(cmd, output_buf, output_buf_size);
12085
12086 return RETURN_OK;
12087}
12088#endif
developer2f513ab2022-09-13 14:26:06 +080012089
12090INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12091{
12092 char output[16]={'\0'};
12093 char config_file[MAX_BUF_SIZE] = {0};
12094
12095 if (!enable)
12096 return RETURN_ERR;
12097
12098 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12099 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12100
12101 if (strlen(output) == 0)
12102 *enable = FALSE;
12103 else if (strncmp(output, "1", 1) == 0)
12104 *enable = TRUE;
12105 else
12106 *enable = FALSE;
12107
12108 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12109 return RETURN_OK;
12110}
developer2d9c30f2022-09-13 15:06:14 +080012111
12112INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12113{
12114 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12115 return RETURN_ERR;
12116 *output_enable=TRUE;
12117 return RETURN_OK;
12118}
developerfd7d2892022-09-13 16:44:53 +080012119
12120INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12121{
12122 char cmd[128] = {0};
12123 char buf[128] = {0};
12124 char line[128] = {0};
12125 size_t len = 0;
12126 ssize_t read = 0;
12127 FILE *f = NULL;
12128 int index = 0;
12129 int exp = 0;
12130 int mantissa = 0;
12131 int duration = 0;
12132 int radio_index = 0;
12133 int max_radio_num = 0;
12134 uint twt_wake_interval = 0;
12135
12136 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12137
12138 wifi_getMaxRadioNumber(&max_radio_num);
12139 radio_index = ap_index % max_radio_num;
12140 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12141 _syscmd(cmd, buf, sizeof(buf));
12142 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12143 if (*numSessionReturned > maxNumberSessions)
12144 *numSessionReturned = maxNumberSessions;
12145 else if (*numSessionReturned < 1) {
12146 *numSessionReturned = 0;
12147 return RETURN_OK;
12148 }
12149
12150 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12151 if ((f = popen(cmd, "r")) == NULL) {
12152 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12153 return RETURN_ERR;
12154 }
12155
12156 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12157 while((read = fgets(line, sizeof(line), f)) != NULL) {
12158 char *tmp = NULL;
12159 strcpy(buf, line);
12160 tmp = strtok(buf, " ");
12161 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12162 tmp = strtok(NULL, " ");
12163 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12164 tmp = strtok(NULL, " ");
12165 if (strstr(tmp, "t")) {
12166 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12167 }
12168 if (strstr(tmp, "a")) {
12169 twtSessions[index].twtParameters.operation.announced = TRUE;
12170 }
12171 tmp = strtok(NULL, " ");
12172 exp = strtol(tmp, NULL, 10);
12173 tmp = strtok(NULL, " ");
12174 mantissa = strtol(tmp, NULL, 10);
12175 tmp = strtok(NULL, " ");
12176 duration = strtol(tmp, NULL, 10);
12177
12178 // only implicit supported
12179 twtSessions[index].twtParameters.operation.implicit = TRUE;
12180 // only individual agreement supported
12181 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12182
12183 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12184 twt_wake_interval = mantissa * (1 << exp);
12185 if (twt_wake_interval/mantissa != (1 << exp)) {
12186 // Overflow handling
12187 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12188 } else {
12189 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12190 }
12191 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12192 index++;
12193 }
12194
12195 pclose(f);
12196 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12197 return RETURN_OK;
12198}