blob: 3081b77739737e364bd247f6fb6407bfe56186b3 [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"
developer6daeb3f2022-09-30 13:36:39 +080085#define NOACK_MAP_FILE "/tmp/NoAckMap"
developer454b9462022-09-13 15:29:16 +080086
developer06a01d92022-09-07 16:32:39 +080087#define DRIVER_2GHZ "ath9k"
88#define DRIVER_5GHZ "ath10k_pci"
developer81bf2ed2022-09-13 15:31:14 +080089#define BRIDGE_NAME "brlan0"
developer06a01d92022-09-07 16:32:39 +080090
91/*
92 MAX_APS - Number of all AP available in system
93 2x Home AP
94 2x Backhaul AP
95 2x Guest AP
96 2x Secure Onboard AP
97 2x Service AP
98
99*/
100#define MAX_APS 10
101#define NUMBER_OF_RADIOS 2
102
103#ifndef AP_PREFIX
104#define AP_PREFIX "wifi"
105#endif
106
107#ifndef RADIO_PREFIX
108#define RADIO_PREFIX "wlan"
109#endif
110
111#define MAX_BUF_SIZE 128
112#define MAX_CMD_SIZE 1024
developer0947e1a2022-09-13 14:15:25 +0800113#define MAX_ASSOCIATED_STA_NUM 2007
developer06a01d92022-09-07 16:32:39 +0800114
115//Uncomment to enable debug logs
116//#define WIFI_DEBUG
117
118#ifdef WIFI_DEBUG
119#define wifi_dbg_printf printf
120#define WIFI_ENTRY_EXIT_DEBUG printf
121#else
122#define wifi_dbg_printf(format, args...) printf("")
123#define WIFI_ENTRY_EXIT_DEBUG(format, args...) printf("")
124#endif
125
126#define HOSTAPD_CONF_0 "/nvram/hostapd0.conf" //private-wifi-2g
127#define HOSTAPD_CONF_1 "/nvram/hostapd1.conf" //private-wifi-5g
128#define HOSTAPD_CONF_4 "/nvram/hostapd4.conf" //public-wifi-2g
129#define HOSTAPD_CONF_5 "/nvram/hostapd5.conf" //public-wifi-5g
130#define DEF_HOSTAPD_CONF_0 "/usr/ccsp/wifi/hostapd0.conf"
131#define DEF_HOSTAPD_CONF_1 "/usr/ccsp/wifi/hostapd1.conf"
132#define DEF_HOSTAPD_CONF_4 "/usr/ccsp/wifi/hostapd4.conf"
133#define DEF_HOSTAPD_CONF_5 "/usr/ccsp/wifi/hostapd5.conf"
134#define DEF_RADIO_PARAM_CONF "/usr/ccsp/wifi/radio_param_def.cfg"
135#define LM_DHCP_CLIENT_FORMAT "%63d %17s %63s %63s"
136
developer4fb0b922022-09-30 14:29:09 +0800137#define HOSTAPD_HT_CAPAB "[LDPC][SHORT-GI-20][SHORT-GI-40][MAX-AMSDU-7935]"
developer06a01d92022-09-07 16:32:39 +0800138
139#define BW_FNAME "/nvram/bw_file.txt"
140
141#define PS_MAX_TID 16
142
143static wifi_radioQueueType_t _tid_ac_index_get[PS_MAX_TID] = {
144 WIFI_RADIO_QUEUE_TYPE_BE, /* 0 */
145 WIFI_RADIO_QUEUE_TYPE_BK, /* 1 */
146 WIFI_RADIO_QUEUE_TYPE_BK, /* 2 */
147 WIFI_RADIO_QUEUE_TYPE_BE, /* 3 */
148 WIFI_RADIO_QUEUE_TYPE_VI, /* 4 */
149 WIFI_RADIO_QUEUE_TYPE_VI, /* 5 */
150 WIFI_RADIO_QUEUE_TYPE_VO, /* 6 */
151 WIFI_RADIO_QUEUE_TYPE_VO, /* 7 */
152 WIFI_RADIO_QUEUE_TYPE_BE, /* 8 */
153 WIFI_RADIO_QUEUE_TYPE_BK, /* 9 */
154 WIFI_RADIO_QUEUE_TYPE_BK, /* 10 */
155 WIFI_RADIO_QUEUE_TYPE_BE, /* 11 */
156 WIFI_RADIO_QUEUE_TYPE_VI, /* 12 */
157 WIFI_RADIO_QUEUE_TYPE_VI, /* 13 */
158 WIFI_RADIO_QUEUE_TYPE_VO, /* 14 */
159 WIFI_RADIO_QUEUE_TYPE_VO, /* 15 */
160};
161
162typedef unsigned long long u64;
163
164/* Enum to define WiFi Bands */
165typedef enum
166{
167 band_invalid = -1,
168 band_2_4 = 0,
169 band_5 = 1,
developerc707e972022-09-13 15:38:02 +0800170 band_6 = 2,
developer06a01d92022-09-07 16:32:39 +0800171} wifi_band;
172
developerdb744382022-09-13 15:34:54 +0800173typedef enum {
174 WIFI_MODE_A = 0x01,
175 WIFI_MODE_B = 0x02,
176 WIFI_MODE_G = 0x04,
177 WIFI_MODE_N = 0x08,
178 WIFI_MODE_AC = 0x10,
179 WIFI_MODE_AX = 0x20,
180} wifi_ieee80211_Mode;
181
developer06a01d92022-09-07 16:32:39 +0800182#ifdef WIFI_HAL_VERSION_3
183
184// Return number of elements in array
185#ifndef ARRAY_SIZE
186#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
187#endif /* ARRAY_SIZE */
188
189#ifndef ARRAY_AND_SIZE
190#define ARRAY_AND_SIZE(x) (x),ARRAY_SIZE(x)
191#endif /* ARRAY_AND_SIZE */
192
193#define WIFI_ITEM_STR(key, str) {0, sizeof(str)-1, (int)key, (intptr_t)str}
194
195typedef struct {
196 int32_t value;
197 int32_t param;
198 intptr_t key;
199 intptr_t data;
200} wifi_secur_list;
201
202wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key);
203wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str);
204char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key);
developer615510b2022-09-27 10:14:35 +0800205static int ieee80211_channel_to_frequency(int channel, int *freqMHz);
developer06a01d92022-09-07 16:32:39 +0800206
207static wifi_secur_list map_security[] =
208{
209 WIFI_ITEM_STR(wifi_security_mode_none, "None"),
210 WIFI_ITEM_STR(wifi_security_mode_wep_64, "WEP-64"),
211 WIFI_ITEM_STR(wifi_security_mode_wep_128, "WEP-128"),
212 WIFI_ITEM_STR(wifi_security_mode_wpa_personal, "WPA-Personal"),
213 WIFI_ITEM_STR(wifi_security_mode_wpa_enterprise, "WPA-Enterprise"),
214 WIFI_ITEM_STR(wifi_security_mode_wpa2_personal, "WPA2-Personal"),
215 WIFI_ITEM_STR(wifi_security_mode_wpa2_enterprise, "WPA2-Enterprise"),
216 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_personal, "WPA-WPA2-Personal"),
217 WIFI_ITEM_STR(wifi_security_mode_wpa_wpa2_enterprise, "WPA-WPA2-Enterprise")
218};
219
220wifi_secur_list * wifi_get_item_by_key(wifi_secur_list *list, int list_sz, int key)
221{
222 wifi_secur_list *item;
223 int i;
224
225 for (item = list,i = 0;i < list_sz; item++, i++) {
226 if ((int)(item->key) == key) {
227 return item;
228 }
229 }
230
231 return NULL;
232}
233
234char * wifi_get_str_by_key(wifi_secur_list *list, int list_sz, int key)
235{
236 wifi_secur_list *item = wifi_get_item_by_key(list, list_sz, key);
237
238 if (!item) {
239 return "";
240 }
241
242 return (char *)(item->data);
243}
244
245wifi_secur_list * wifi_get_item_by_str(wifi_secur_list *list, int list_sz, const char *str)
246{
247 wifi_secur_list *item;
248 int i;
249
250 for (item = list,i = 0;i < list_sz; item++, i++) {
251 if (strcmp((char *)(item->data), str) == 0) {
252 return item;
253 }
254 }
255
256 return NULL;
257}
258#endif /* WIFI_HAL_VERSION_3 */
259
260#ifdef HAL_NETLINK_IMPL
261typedef struct {
262 int id;
263 struct nl_sock* socket;
264 struct nl_cb* cb;
265} Netlink;
266
267static int mac_addr_aton(unsigned char *mac_addr, char *arg)
268{
269 unsigned int mac_addr_int[6]={};
270 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);
271 mac_addr[0] = mac_addr_int[0];
272 mac_addr[1] = mac_addr_int[1];
273 mac_addr[2] = mac_addr_int[2];
274 mac_addr[3] = mac_addr_int[3];
275 mac_addr[4] = mac_addr_int[4];
276 mac_addr[5] = mac_addr_int[5];
277 return 0;
278}
279
280static void mac_addr_ntoa(char *mac_addr, unsigned char *arg)
281{
282 unsigned int mac_addr_int[6]={};
283 mac_addr_int[0] = arg[0];
284 mac_addr_int[1] = arg[1];
285 mac_addr_int[2] = arg[2];
286 mac_addr_int[3] = arg[3];
287 mac_addr_int[4] = arg[4];
288 mac_addr_int[5] = arg[5];
289 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]);
290 return;
291}
292
293static int ieee80211_frequency_to_channel(int freq)
294{
295 if (freq == 2484)
296 return 14;
297 else if (freq < 2484)
298 return (freq - 2407) / 5;
299 else if (freq >= 4910 && freq <= 4980)
300 return (freq - 4000) / 5;
301 else if (freq <= 45000)
302 return (freq - 5000) / 5;
303 else if (freq >= 58320 && freq <= 64800)
304 return (freq - 56160) / 2160;
305 else
306 return 0;
307}
308
309static int initSock80211(Netlink* nl) {
310 nl->socket = nl_socket_alloc();
311 if (!nl->socket) {
312 fprintf(stderr, "Failing to allocate the sock\n");
313 return -ENOMEM;
314 }
315
316 nl_socket_set_buffer_size(nl->socket, 8192, 8192);
317
318 if (genl_connect(nl->socket)) {
319 fprintf(stderr, "Failed to connect\n");
320 nl_close(nl->socket);
321 nl_socket_free(nl->socket);
322 return -ENOLINK;
323 }
324
325 nl->id = genl_ctrl_resolve(nl->socket, "nl80211");
326 if (nl->id< 0) {
327 fprintf(stderr, "interface not found.\n");
328 nl_close(nl->socket);
329 nl_socket_free(nl->socket);
330 return -ENOENT;
331 }
332
333 nl->cb = nl_cb_alloc(NL_CB_DEFAULT);
334 if ((!nl->cb)) {
335 fprintf(stderr, "Failed to allocate netlink callback.\n");
336 nl_close(nl->socket);
337 nl_socket_free(nl->socket);
338 return ENOMEM;
339 }
340
341 return nl->id;
342}
343
344static int nlfree(Netlink *nl)
345{
346 nl_cb_put(nl->cb);
347 nl_close(nl->socket);
348 nl_socket_free(nl->socket);
349 return 0;
350}
351
352static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
353 [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
354 [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
355 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED }
356};
357
358static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
359};
360
361static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
362};
363
364typedef struct _wifi_channelStats_loc {
365 INT array_size;
366 INT ch_number;
367 BOOL ch_in_pool;
368 INT ch_noise;
369 BOOL ch_radar_noise;
370 INT ch_max_80211_rssi;
371 INT ch_non_80211_noise;
372 INT ch_utilization;
373 ULLONG ch_utilization_total;
374 ULLONG ch_utilization_busy;
375 ULLONG ch_utilization_busy_tx;
376 ULLONG ch_utilization_busy_rx;
377 ULLONG ch_utilization_busy_self;
378 ULLONG ch_utilization_busy_ext;
379} wifi_channelStats_t_loc;
380
381typedef struct wifi_device_info {
382 INT wifi_devIndex;
383 UCHAR wifi_devMacAddress[6];
384 CHAR wifi_devIPAddress[64];
385 BOOL wifi_devAssociatedDeviceAuthentiationState;
386 INT wifi_devSignalStrength;
387 INT wifi_devTxRate;
388 INT wifi_devRxRate;
389} wifi_device_info_t;
390
391#endif
392
393//For 5g Alias Interfaces
394static BOOL priv_flag = TRUE;
395static BOOL pub_flag = TRUE;
396static BOOL Radio_flag = TRUE;
397//wifi_setApBeaconRate(1, beaconRate);
398
developer1e5aa162022-09-13 16:06:24 +0800399BOOL multiple_set = FALSE;
400
developer06a01d92022-09-07 16:32:39 +0800401struct params
402{
403 char * name;
404 char * value;
405};
406
407static int _syscmd(char *cmd, char *retBuf, int retBufSize)
408{
409 FILE *f;
410 char *ptr = retBuf;
411 int bufSize=retBufSize, bufbytes=0, readbytes=0, cmd_ret=0;
412
413 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
414 if((f = popen(cmd, "r")) == NULL) {
415 fprintf(stderr,"\npopen %s error\n", cmd);
416 return RETURN_ERR;
417 }
418
419 while(!feof(f))
420 {
421 *ptr = 0;
422 if(bufSize>=128) {
423 bufbytes=128;
424 } else {
425 bufbytes=bufSize-1;
426 }
427
428 fgets(ptr,bufbytes,f);
429 readbytes=strlen(ptr);
430
431 if(!readbytes)
432 break;
433
434 bufSize-=readbytes;
435 ptr += readbytes;
436 }
437 cmd_ret = pclose(f);
438 retBuf[retBufSize-1]=0;
439 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
440
441 return cmd_ret >> 8;
442}
443
developerc707e972022-09-13 15:38:02 +0800444wifi_band wifi_index_to_band(int apIndex)
445{
446 char cmd[128] = {0};
447 char buf[64] = {0};
448 int freq = 0;
449 wifi_band band = band_invalid;
450
451 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
452 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep 'freq=' | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
453 _syscmd(cmd, buf, sizeof(buf));
454 freq = strtol(buf, NULL, 10);
455 if (freq > 2401 && freq < 2495)
456 band = band_2_4;
457 else if (freq > 5160 && freq < 5915)
458 band = band_5;
459 else if (freq > 5955 && freq < 7125)
460 band = band_6;
461
462 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
463 return band;
464}
465
developer06a01d92022-09-07 16:32:39 +0800466static int wifi_hostapdRead(char *conf_file, char *param, char *output, int output_size)
467{
468 char cmd[MAX_CMD_SIZE]={'\0'};
469 char buf[MAX_BUF_SIZE]={'\0'};
470 int ret = 0;
471
472 sprintf(cmd, "cat %s | grep \"^%s=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", conf_file, param);
473 ret = _syscmd(cmd, buf, sizeof(buf));
474 if ((ret != 0) && (strlen(buf) == 0))
475 return -1;
476 snprintf(output, output_size, "%s", buf);
477
478 return 0;
479}
480
481static int wifi_hostapdWrite(char *conf_file, struct params *list, int item_count)
482{
483 char cmd[MAX_CMD_SIZE]={'\0'};
484 char buf[MAX_BUF_SIZE]={'\0'};
485
486 for(int i=0;i<item_count;i++)
487 {
488 wifi_hostapdRead(conf_file, list[i].name, buf, sizeof(buf));
489 if (strlen(buf) == 0) //Insert
490 snprintf(cmd, sizeof(cmd), "echo \"%s=%s\" >> %s", list[i].name, list[i].value, conf_file);
491 else //Update
492 snprintf(cmd, sizeof(cmd), "sed -i \"s/^%s=.*/%s=%s/\" %s", list[i].name, list[i].name, list[i].value, conf_file);
493 if(_syscmd(cmd, buf, sizeof(buf)))
494 return -1;
495 }
496
497 return 0;
498}
499
500static int wifi_hostapdProcessUpdate(int apIndex, struct params *list, int item_count)
501{
developer1e5aa162022-09-13 16:06:24 +0800502 if (multiple_set == TRUE)
503 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800504 char cmd[MAX_CMD_SIZE]="", output[32]="";
505 FILE *fp;
506 int i;
507 //NOTE RELOAD should be done in ApplySSIDSettings
508
509 for(i=0; i<item_count; i++, list++)
510 {
511 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d SET %s %s", AP_PREFIX, apIndex, list->name, list->value);
512 if((fp = popen(cmd, "r"))==NULL)
513 {
514 perror("popen failed");
515 return -1;
516 }
517 if(!fgets(output, sizeof(output), fp) || strncmp(output, "OK", 2))
518 {
519 pclose(fp);
520 perror("fgets failed");
521 return -1;
522 }
523 pclose(fp);
524 }
525 return 0;
526}
527
528static int wifi_reloadAp(int apIndex)
529{
developer1e5aa162022-09-13 16:06:24 +0800530 if (multiple_set == TRUE)
531 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800532 char cmd[MAX_CMD_SIZE]="";
533 char buf[MAX_BUF_SIZE]="";
534
535 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d reload", AP_PREFIX, apIndex);
536 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
537 return RETURN_ERR;
538
539 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d disable", AP_PREFIX, apIndex);
540 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
541 return RETURN_ERR;
542
543 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d enable", AP_PREFIX, apIndex);
544 if (_syscmd(cmd, buf, sizeof(buf)) == RETURN_ERR)
545 return RETURN_ERR;
546
547 return RETURN_OK;
548}
549
550
551//For Getting Current Interface Name from corresponding hostapd configuration
552void GetInterfaceName(char *interface_name, char *conf_file)
553{
554 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
555 wifi_hostapdRead(conf_file,"interface",interface_name, IF_NAME_SIZE);
556 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
557}
558
559INT File_Reading(CHAR *file, char *Value)
560{
561 FILE *fp = NULL;
562 char buf[MAX_CMD_SIZE] = {0}, copy_buf[MAX_CMD_SIZE] ={0};
563 int count = 0;
564
565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
566 fp = popen(file,"r");
567 if(fp == NULL)
568 return RETURN_ERR;
569
570 if(fgets(buf,sizeof(buf) -1,fp) != NULL)
571 {
572 for(count=0;buf[count]!='\n';count++)
573 copy_buf[count]=buf[count];
574 copy_buf[count]='\0';
575 }
576 strcpy(Value,copy_buf);
577 pclose(fp);
578 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
579
580 return RETURN_OK;
581}
582
583void wifi_RestartHostapd_2G()
584{
585 int Public2GApIndex = 4;
586
587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
588 wifi_setApEnable(Public2GApIndex, FALSE);
589 wifi_setApEnable(Public2GApIndex, TRUE);
590 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
591}
592
593void wifi_RestartHostapd_5G()
594{
595 int Public5GApIndex = 5;
596
597 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
598 wifi_setApEnable(Public5GApIndex, FALSE);
599 wifi_setApEnable(Public5GApIndex, TRUE);
600 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
601}
602
603void wifi_RestartPrivateWifi_2G()
604{
605 int PrivateApIndex = 0;
606
607 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
608 wifi_setApEnable(PrivateApIndex, FALSE);
609 wifi_setApEnable(PrivateApIndex, TRUE);
610 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
611}
612
613void wifi_RestartPrivateWifi_5G()
614{
615 int Private5GApIndex = 1;
616
617 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
618 wifi_setApEnable(Private5GApIndex, FALSE);
619 wifi_setApEnable(Private5GApIndex, TRUE);
620 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
621}
622
623static int writeBandWidth(int radioIndex,char *bw_value)
624{
625 char buf[MAX_BUF_SIZE];
626 char cmd[MAX_CMD_SIZE];
627
628 snprintf(cmd, sizeof(cmd), "grep SET_BW%d %s", radioIndex, BW_FNAME);
629 if(_syscmd(cmd, buf, sizeof(buf)))
630 {
631 snprintf(cmd, sizeof(cmd), "echo SET_BW%d=%s >> %s", radioIndex, bw_value, BW_FNAME);
632 _syscmd(cmd, buf, sizeof(buf));
633 return RETURN_OK;
634 }
635
636 sprintf(cmd,"sed -i 's/^SET_BW%d=.*$/SET_BW%d=%s/' %s",radioIndex,radioIndex,bw_value,BW_FNAME);
637 _syscmd(cmd,buf,sizeof(buf));
638 return RETURN_OK;
639}
640
641static int readBandWidth(int radioIndex,char *bw_value)
642{
643 char buf[MAX_BUF_SIZE];
644 char cmd[MAX_CMD_SIZE];
645 sprintf(cmd,"grep 'SET_BW%d=' %s | sed 's/^.*=//'",radioIndex,BW_FNAME);
646 _syscmd(cmd,buf,sizeof(buf));
647 if(NULL!=strstr(buf,"20MHz"))
648 {
649 strcpy(bw_value,"20MHz");
650 }
651 else if(NULL!=strstr(buf,"40MHz"))
652 {
653 strcpy(bw_value,"40MHz");
654 }
655 else if(NULL!=strstr(buf,"80MHz"))
656 {
657 strcpy(bw_value,"80MHz");
658 }
659 else
660 {
661 return RETURN_ERR;
662 }
663 return RETURN_OK;
664}
665
developer39a5efb2022-09-13 16:09:06 +0800666INT wifi_getMaxRadioNumber(INT *max_radio_num)
667{
668 char cmd[64] = {0};
669 char buf[4] = {0};
670
671 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
672
673 snprintf(cmd, sizeof(cmd), "iw list | grep Wiphy | wc -l");
674 _syscmd(cmd, buf, sizeof(buf));
675 *max_radio_num = strtoul(buf, NULL, 10);
676
677 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
678
679 return RETURN_OK;
680}
681
developer5f222492022-09-13 15:21:52 +0800682// Input must be "1Mbps"; "5.5Mbps"; "6Mbps"; "2Mbps"; "11Mbps"; "12Mbps"; "24Mbps"
developer06a01d92022-09-07 16:32:39 +0800683INT wifi_setApBeaconRate(INT radioIndex,CHAR *beaconRate)
684{
developer5f222492022-09-13 15:21:52 +0800685 struct params params={'\0'};
686 char config_file[MAX_BUF_SIZE] = {0};
687 char buf[MAX_BUF_SIZE] = {'\0'};
688
689 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
690 if (strlen (beaconRate) < 5)
691 return RETURN_ERR;
692 // Copy the numeric value
693 strncpy(buf, beaconRate, strlen(beaconRate) - 4);
694 buf[strlen(beaconRate) - 4] = '\0';
695
696 params.name = "beacon_rate";
697 // hostapd config unit is 100 kbps. To convert Mbps to 100kbps, the value need to multiply 10.
698 if (strncmp(buf, "5.5", 3) == 0) {
699 snprintf(buf, sizeof(buf), "55");
700 params.value = buf;
701 } else {
702 strcat(buf, "0");
703 params.value = buf;
704 }
705
706 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
707 wifi_hostapdWrite(config_file, &params, 1);
708 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
709 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
710
711 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800712}
713
714INT wifi_getApBeaconRate(INT radioIndex, CHAR *beaconRate)
715{
developer5f222492022-09-13 15:21:52 +0800716 char config_file[MAX_BUF_SIZE] = {'\0'};
717 char temp_output[MAX_BUF_SIZE] = {'\0'};
718 char buf[MAX_BUF_SIZE] = {'\0'};
719 float rate = 0;
720
721 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
722 if (NULL == beaconRate)
723 return RETURN_ERR;
724
725 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
726 wifi_hostapdRead(config_file, "beacon_rate", buf, sizeof(buf));
727 // Hostapd unit is 100kbps. To convert to 100kbps to Mbps, the value need to divide 10.
728 if(strlen(buf) > 0) {
729 rate = atof(buf)/10;
730 snprintf(temp_output, sizeof(temp_output), "%.1fMbps", rate);
731 } else {
732 snprintf(temp_output, sizeof(temp_output), "1Mbps"); // default value
733 }
734 strncpy(beaconRate, temp_output, sizeof(temp_output));
735 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
736
737 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +0800738}
739
740INT wifi_setLED(INT radioIndex, BOOL enable)
741{
742 return 0;
743}
744INT wifi_setRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG seconds)
745{
746 return RETURN_OK;
747}
748/**********************************************************************************
749 *
750 * Wifi Subsystem level function prototypes
751 *
752**********************************************************************************/
753//---------------------------------------------------------------------------------------------------
754//Wifi system api
755//Get the wifi hal version in string, eg "2.0.0". WIFI_HAL_MAJOR_VERSION.WIFI_HAL_MINOR_VERSION.WIFI_HAL_MAINTENANCE_VERSION
756INT wifi_getHalVersion(CHAR *output_string) //RDKB
757{
758 if(!output_string)
759 return RETURN_ERR;
760 snprintf(output_string, 64, "%d.%d.%d", WIFI_HAL_MAJOR_VERSION, WIFI_HAL_MINOR_VERSION, WIFI_HAL_MAINTENANCE_VERSION);
761
762 return RETURN_OK;
763}
764
765
766/* wifi_factoryReset() function */
767/**
768* @description Clears internal variables to implement a factory reset of the Wi-Fi
769* subsystem. Resets Implementation specifics may dictate some functionality since different hardware implementations may have different requirements.
770*
771* @param None
772*
773* @return The status of the operation.
774* @retval RETURN_OK if successful.
775* @retval RETURN_ERR if any error is detected
776*
777* @execution Synchronous
778* @sideeffect None
779*
780* @note This function must not suspend and must not invoke any blocking system
781* calls. It should probably just send a message to a driver event handler task.
782*
783*/
784INT wifi_factoryReset()
785{
786 char cmd[128];
787
788 /*delete running hostapd conf files*/
789 wifi_dbg_printf("\n[%s]: deleting hostapd conf file %s and %s",__func__,HOSTAPD_CONF_0,HOSTAPD_CONF_1);
790 sprintf(cmd, "rm -rf %s %s",HOSTAPD_CONF_0,HOSTAPD_CONF_1);
791 system(cmd);
792 system("systemctl restart hostapd.service");
793
794 return RETURN_OK;
795}
796
797/* wifi_factoryResetRadios() function */
798/**
799* @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.
800*
801* @param None
802* @return The status of the operation
803* @retval RETURN_OK if successful
804* @retval RETURN_ERR if any error is detected
805*
806* @execution Synchronous
807*
808* @sideeffect None
809*
810* @note This function must not suspend and must not invoke any blocking system
811* calls. It should probably just send a message to a driver event handler task.
812*
813*/
814INT wifi_factoryResetRadios()
815{
816 if((RETURN_OK == wifi_factoryResetRadio(0)) && (RETURN_OK == wifi_factoryResetRadio(1)))
817 return RETURN_OK;
818
819 return RETURN_ERR;
820}
821
822
823/* wifi_factoryResetRadio() function */
824/**
825* @description Restore selected radio parameters without touching access point parameters
826*
827* @param radioIndex - Index of Wi-Fi Radio channel
828*
829* @return The status of the operation.
830* @retval RETURN_OK if successful.
831* @retval RETURN_ERR if any error is detected
832*
833* @execution Synchronous.
834* @sideeffect None.
835*
836* @note This function must not suspend and must not invoke any blocking system
837* calls. It should probably just send a message to a driver event handler task.
838*
839*/
840INT wifi_factoryResetRadio(int radioIndex) //RDKB
841{
developer5ff7f5f2022-09-13 15:12:16 +0800842 system("systemctl stop hostapd.service");
843
developer06a01d92022-09-07 16:32:39 +0800844 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
845 if(radioIndex == 0)
developer5ff7f5f2022-09-13 15:12:16 +0800846 system("rm /nvram/hostapd0.conf");
developer06a01d92022-09-07 16:32:39 +0800847 else if(radioIndex == 1)
developer5ff7f5f2022-09-13 15:12:16 +0800848 system("rm /nvram/hostapd1.conf");
developer06a01d92022-09-07 16:32:39 +0800849 else
850 return RETURN_ERR;
851
developer5ff7f5f2022-09-13 15:12:16 +0800852 system("systemctl start hostapd.service");
developer06a01d92022-09-07 16:32:39 +0800853 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
854 return RETURN_OK;
855}
856
857/* wifi_initRadio() function */
858/**
859* Description: This function call initializes the specified radio.
860* Implementation specifics may dictate the functionality since
861* different hardware implementations may have different initilization requirements.
862* Parameters : radioIndex - The index of the radio. First radio is index 0. 2nd radio is index 1 - type INT
863*
864* @return The status of the operation.
865* @retval RETURN_OK if successful.
866* @retval RETURN_ERR if any error is detected
867*
868* @execution Synchronous.
869* @sideeffect None.
870*
871* @note This function must not suspend and must not invoke any blocking system
872* calls. It should probably just send a message to a driver event handler task.
873*
874*/
875INT wifi_initRadio(INT radioIndex)
876{
877 //TODO: Initializes the wifi subsystem (for specified radio)
878 return RETURN_OK;
879}
880void macfilter_init()
881{
882 char count[4]={'\0'};
883 char buf[253]={'\0'};
884 char tmp[19]={'\0'};
885 int dev_count,block,mac_entry=0;
886 char res[4]={'\0'};
887 char acl_file_path[64] = {'\0'};
888 FILE *fp = NULL;
889 int index=0;
890 char iface[10]={'\0'};
891 char config_file[MAX_BUF_SIZE] = {0};
892
893
894 sprintf(acl_file_path,"/tmp/mac_filter.sh");
895
896 fp=fopen(acl_file_path,"w+");
897 sprintf(buf,"#!/bin/sh \n");
898 fprintf(fp,"%s\n",buf);
899
900 system("chmod 0777 /tmp/mac_filter.sh");
901
902 for(index=0;index<=1;index++)
903 {
904 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,index);
905 wifi_hostapdRead(config_file, "interface", iface, sizeof(iface));
906 sprintf(buf,"syscfg get %dcountfilter",index);
907 _syscmd(buf,count,sizeof(count));
908 mac_entry=atoi(count);
909
910 sprintf(buf,"syscfg get %dblockall",index);
911 _syscmd(buf,res,sizeof(res));
912 block = atoi(res);
913
914 //Allow only those macs mentioned in ACL
915 if(block==1)
916 {
917 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
918 fprintf(fp,"%s\n",buf);
919 for(dev_count=1;dev_count<=mac_entry;dev_count++)
920 {
921 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
922 _syscmd(buf,tmp,sizeof(tmp));
923 fprintf(stderr,"MAcs to be Allowed *%s* ###########\n",tmp);
924 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",index,iface,tmp);
925 fprintf(fp,"%s\n",buf);
926 }
927 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",index,iface,tmp);
928 fprintf(fp,"%s\n",buf);
929 }
930
931 //Block all the macs mentioned in ACL
932 else if(block==2)
933 {
934 sprintf(buf,"iptables -N WifiServices%d\n iptables -I INPUT 21 -j WifiServices%d\n",index,index);
935 fprintf(fp,"%s\n",buf);
936
937 for(dev_count=1;dev_count<=mac_entry;dev_count++)
938 {
939 sprintf(buf,"syscfg get %dmacfilter%d",index,dev_count);
940 _syscmd(buf,tmp,sizeof(tmp));
941 fprintf(stderr,"MAcs to be blocked *%s* ###########\n",tmp);
942 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",index,iface,tmp);
943 fprintf(fp,"%s\n",buf);
944 }
945 }
946 }
947 fclose(fp);
948}
949
950// Initializes the wifi subsystem (all radios)
951INT wifi_init() //RDKB
952{
953 char interface[MAX_BUF_SIZE]={'\0'};
954 char bridge_name[MAX_BUF_SIZE]={'\0'};
955 INT len=0;
956
957 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
958 //Not intitializing macfilter for Turris-Omnia Platform for now
959 //macfilter_init();
960
961 system("/usr/sbin/iw reg set US");
962 system("systemctl start hostapd.service");
963 sleep(2);//sleep to wait for hostapd to start
964
965 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
966
967 return RETURN_OK;
968}
969
970/* wifi_reset() function */
971/**
972* Description: Resets the Wifi subsystem. This includes reset of all AP varibles.
973* Implementation specifics may dictate what is actualy reset since
974* different hardware implementations may have different requirements.
975* Parameters : None
976*
977* @return The status of the operation.
978* @retval RETURN_OK if successful.
979* @retval RETURN_ERR if any error is detected
980*
981* @execution Synchronous.
982* @sideeffect None.
983*
984* @note This function must not suspend and must not invoke any blocking system
985* calls. It should probably just send a message to a driver event handler task.
986*
987*/
988INT wifi_reset()
989{
990 //TODO: resets the wifi subsystem, deletes all APs
developerb222b212022-09-13 14:01:01 +0800991 system("systemctl stop hostapd.service");
992 sleep(2);
993 system("systemctl start hostapd.service");
994 sleep(5);
developer06a01d92022-09-07 16:32:39 +0800995 return RETURN_OK;
996}
997
998/* wifi_down() function */
999/**
1000* @description Turns off transmit power for the entire Wifi subsystem, for all radios.
1001* Implementation specifics may dictate some functionality since
1002* different hardware implementations may have different requirements.
1003*
1004* @param None
1005*
1006* @return The status of the operation
1007* @retval RETURN_OK if successful
1008* @retval RETURN_ERR if any error is detected
1009*
1010* @execution Synchronous
1011* @sideeffect None
1012*
1013* @note This function must not suspend and must not invoke any blocking system
1014* calls. It should probably just send a message to a driver event handler task.
1015*
1016*/
1017INT wifi_down()
1018{
1019 //TODO: turns off transmit power for the entire Wifi subsystem, for all radios
developerb222b212022-09-13 14:01:01 +08001020 system("systemctl stop hostapd.service");
1021 sleep(2);
developer06a01d92022-09-07 16:32:39 +08001022 return RETURN_OK;
1023}
1024
1025
1026/* wifi_createInitialConfigFiles() function */
1027/**
1028* @description This function creates wifi configuration files. The format
1029* and content of these files are implementation dependent. This function call is
1030* used to trigger this task if necessary. Some implementations may not need this
1031* function. If an implementation does not need to create config files the function call can
1032* do nothing and return RETURN_OK.
1033*
1034* @param None
1035*
1036* @return The status of the operation
1037* @retval RETURN_OK if successful
1038* @retval RETURN_ERR if any error is detected
1039*
1040* @execution Synchronous
1041* @sideeffect None
1042*
1043* @note This function must not suspend and must not invoke any blocking system
1044* calls. It should probably just send a message to a driver event handler task.
1045*
1046*/
1047INT wifi_createInitialConfigFiles()
1048{
1049 //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)
1050 return RETURN_OK;
1051}
1052
1053// outputs the country code to a max 64 character string
1054INT wifi_getRadioCountryCode(INT radioIndex, CHAR *output_string)
1055{
developer7543b3b2022-09-13 13:47:17 +08001056 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
1057 if(!output_string || !(radioIndex==0 || radioIndex==1))
developer06a01d92022-09-07 16:32:39 +08001058 return RETURN_ERR;
developer7543b3b2022-09-13 13:47:17 +08001059
1060 sprintf(cmd,"hostapd_cli -i %s%d status driver | grep country | cut -d '=' -f2", AP_PREFIX, radioIndex);
1061 _syscmd(cmd, buf, sizeof(buf));
1062 if(strlen(buf) > 0)
1063 snprintf(output_string, 64, "%s", buf);
1064 else
1065 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001066
1067 return RETURN_OK;
1068}
1069
1070INT wifi_setRadioCountryCode(INT radioIndex, CHAR *CountryCode)
1071{
1072 //Set wifi config. Wait for wifi reset to apply
developer7543b3b2022-09-13 13:47:17 +08001073 char str[MAX_BUF_SIZE]={'\0'};
1074 char cmd[MAX_CMD_SIZE]={'\0'};
1075 struct params params;
1076 char config_file[MAX_BUF_SIZE] = {0};
1077
1078 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1079 if(NULL == CountryCode || strlen(CountryCode) >= 32 )
1080 return RETURN_ERR;
1081
1082 params.name = "country_code";
1083 params.value = CountryCode;
1084 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, radioIndex);
1085 int ret = wifi_hostapdWrite(config_file, &params, 1);
1086 if (ret) {
1087 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
1088 ,__func__, ret);
1089 }
1090
1091 ret = wifi_hostapdProcessUpdate(radioIndex, &params, 1);
1092 if (ret) {
1093 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
1094 ,__func__, ret);
1095 }
1096 wifi_reloadAp(radioIndex);
1097 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1098
developer06a01d92022-09-07 16:32:39 +08001099 return RETURN_OK;
1100}
1101
developera748dcf2022-09-13 15:56:48 +08001102INT wifi_getRadioChannelStats2(INT radioIndex, wifi_channelStats2_t *outputChannelStats2)
1103{
1104 char channel_util_file[64] = {0};
1105 char cmd[128] = {0};
1106 char buf[128] = {0};
1107 char line[128] = {0};
1108 char *param = NULL, *value = NULL;
1109 int read = 0;
1110 unsigned int ActiveTime = 0, BusyTime = 0, TransmitTime = 0;
1111 unsigned int preActiveTime = 0, preBusyTime = 0, preTransmitTime = 0;
1112 size_t len = 0;
1113 FILE *f = NULL;
1114
1115 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1116
1117 snprintf(cmd, sizeof(cmd), "iw %s%d scan | grep signal | awk '{print $2}' | sort -n | tail -n1", AP_PREFIX, radioIndex);
1118 _syscmd(cmd, buf, sizeof(buf));
1119 outputChannelStats2->ch_Max80211Rssi = strtol(buf, NULL, 10);
1120
1121 memset(cmd, 0, sizeof(cmd));
1122 memset(buf, 0, sizeof(buf));
1123 snprintf(cmd, sizeof(cmd), "iw %s%d survey dump | grep 'in use' -A6", AP_PREFIX, radioIndex);
1124 if ((f = popen(cmd, "r")) == NULL) {
1125 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
1126 return RETURN_ERR;
1127 }
1128
1129 read = getline(&line, &len, f);
1130 while (read != -1) {
1131 param = strtok(line, ":\t");
1132 value = strtok(NULL, " ");
1133 if(strstr(param, "frequency") != NULL) {
1134 outputChannelStats2->ch_Frequency = strtol(value, NULL, 10);
1135 }
1136 if(strstr(param, "noise") != NULL) {
1137 outputChannelStats2->ch_NoiseFloor = strtol(value, NULL, 10);
1138 outputChannelStats2->ch_Non80211Noise = strtol(value, NULL, 10);
1139 }
1140 if(strstr(param, "channel active time") != NULL) {
1141 ActiveTime = strtol(value, NULL, 10);
1142 }
1143 if(strstr(param, "channel busy time") != NULL) {
1144 BusyTime = strtol(value, NULL, 10);
1145 }
1146 if(strstr(param, "channel transmit time") != NULL) {
1147 TransmitTime = strtol(value, NULL, 10);
1148 }
1149 read = getline(&line, &len, f);
1150 }
1151 pclose(f);
1152
1153 // The file should store the last active, busy and transmit time
1154 snprintf(channel_util_file, sizeof(channel_util_file), "%s%d.txt", CHANNEL_STATS_FILE, radioIndex);
1155 f = fopen(channel_util_file, "r");
1156 if (f != NULL) {
1157 read = getline(&line, &len, f);
1158 preActiveTime = strtol(line, NULL, 10);
1159 read = getline(&line, &len, f);
1160 preBusyTime = strtol(line, NULL, 10);
1161 read = getline(&line, &len, f);
1162 preTransmitTime = strtol(line, NULL, 10);
1163 fclose(f);
1164 }
1165
1166 outputChannelStats2->ch_ObssUtil = (BusyTime - preBusyTime)*100/(ActiveTime - preActiveTime);
1167 outputChannelStats2->ch_SelfBssUtil = (TransmitTime - preTransmitTime)*100/(ActiveTime - preActiveTime);
1168
1169 f = fopen(channel_util_file, "w");
1170 if (f != NULL) {
1171 fprintf(f, "%u\n%u\n%u\n", ActiveTime, BusyTime, TransmitTime);
1172 fclose(f);
1173 }
1174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1175 return RETURN_OK;
1176}
1177
developer06a01d92022-09-07 16:32:39 +08001178/**********************************************************************************
1179 *
1180 * Wifi radio level function prototypes
1181 *
1182**********************************************************************************/
1183
1184//Get the total number of radios in this wifi subsystem
1185INT wifi_getRadioNumberOfEntries(ULONG *output) //Tr181
1186{
1187 if (NULL == output)
1188 return RETURN_ERR;
1189 *output = 2;
1190
1191 return RETURN_OK;
1192}
1193
1194//Get the total number of SSID entries in this wifi subsystem
1195INT wifi_getSSIDNumberOfEntries(ULONG *output) //Tr181
1196{
1197 if (NULL == output)
1198 return RETURN_ERR;
1199 *output = MAX_APS;
1200
1201 return RETURN_OK;
1202}
1203
1204//Get the Radio enable config parameter
1205INT wifi_getRadioEnable(INT radioIndex, BOOL *output_bool) //RDKB
1206{
1207 char interface_path[MAX_CMD_SIZE] = {0};
1208 FILE *fp = NULL;
1209
1210 if (NULL == output_bool)
1211 return RETURN_ERR;
1212
1213 *output_bool = FALSE;
1214 if (!((radioIndex == 0) || (radioIndex == 1)))// Target has two wifi radios
1215 return RETURN_ERR;
1216
1217 snprintf(interface_path, sizeof(interface_path), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1218 fp = fopen(interface_path, "r");
developercf48e482022-09-13 14:49:50 +08001219 if(!fp)
developer06a01d92022-09-07 16:32:39 +08001220 {
developercf48e482022-09-13 14:49:50 +08001221 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001222 }
1223 //TODO: check if hostapd with config is running
developercf48e482022-09-13 14:49:50 +08001224 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0};
1225 sprintf(cmd, "hostapd_cli -i %s%d status | grep state | cut -d '=' -f2", AP_PREFIX, radioIndex);
1226 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08001227
developercf48e482022-09-13 14:49:50 +08001228 if(strncmp(buf, "ENABLED", 7) == 0 || strncmp(buf, "ACS", 3) == 0 || strncmp(buf, "HT_SCAN", 7) == 0 || strncmp(buf, "DFS", 3) == 0)
1229 *output_bool = TRUE;
1230 fclose(fp);
developer06a01d92022-09-07 16:32:39 +08001231 return RETURN_OK;
1232}
1233
1234INT wifi_setRadioEnable(INT radioIndex, BOOL enable)
1235{
1236 char cmd[MAX_CMD_SIZE] = {0};
1237 char buf[MAX_CMD_SIZE] = {0};
1238 int apIndex, ret;
1239 FILE *fp = NULL;
1240
1241 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1242 if(enable==FALSE)
1243 {
1244 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1245 {
1246 //Detaching %s%d from hostapd daemon
1247 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
1248 _syscmd(cmd, buf, sizeof(buf));
1249 if(strncmp(buf, "OK", 2))
1250 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1251 snprintf(cmd, sizeof(cmd), "iw %s%d del", AP_PREFIX, apIndex);
1252 _syscmd(cmd, buf, sizeof(buf));
1253 }
developer456aa3e2022-09-13 14:27:36 +08001254 snprintf(cmd, sizeof(cmd), "ifconfig %s%d down 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001255 _syscmd(cmd, buf, sizeof(buf));
1256 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001257 fprintf(stderr, "Could not shut down the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001258 }
1259 else
1260 {
developer456aa3e2022-09-13 14:27:36 +08001261 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>&1", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001262 _syscmd(cmd, buf, sizeof(buf));
1263 if(strlen(buf))
developer456aa3e2022-09-13 14:27:36 +08001264 fprintf(stderr, "Could not up the radio interface: %s%d", RADIO_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08001265 sleep(1);
1266 if(radioIndex == 1)//If "wlan0" interface created for 5GHz radio, then need to rename to wlan1
1267 {
1268 snprintf(cmd, sizeof(cmd), "/sys/class/net/%s%d/address", RADIO_PREFIX, radioIndex);
1269 fp = fopen(cmd, "r");
1270 if(!fp)
1271 {
1272 snprintf(cmd, sizeof(cmd), "ip link set %s0 down", RADIO_PREFIX);
1273 _syscmd(cmd, buf, sizeof(buf));
1274 snprintf(cmd, sizeof(cmd), "ip link set %s0 name %s%d", RADIO_PREFIX, RADIO_PREFIX, radioIndex);
1275 _syscmd(cmd, buf, sizeof(buf));
1276 }
1277 if(fp)
1278 fclose(fp);
1279 }
1280 for(apIndex=radioIndex; apIndex<MAX_APS; apIndex+=2)
1281 {
1282 snprintf(cmd, sizeof(cmd), "iw %s%d interface add %s%d type __ap", RADIO_PREFIX, radioIndex, AP_PREFIX, apIndex);
1283 ret = _syscmd(cmd, buf, sizeof(buf));
1284 if ( ret == RETURN_ERR)
1285 {
1286 fprintf(stderr, "VAP interface creation failed\n");
1287 continue;
1288 }
1289 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
1290 _syscmd(cmd, buf, sizeof(buf));
1291 if(*buf == '1')
1292 {
1293 snprintf(cmd, sizeof(cmd), "hostapd_cli -i global raw ADD bss_config=phy%d:/nvram/hostapd%d.conf",
1294 radioIndex, apIndex);
1295 _syscmd(cmd, buf, sizeof(buf));
1296 if(strncmp(buf, "OK", 2))
1297 fprintf(stderr, "Could not detach %s%d from hostapd daemon", AP_PREFIX, apIndex);
1298 }
1299 }
1300 }
1301
1302 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1303 return RETURN_OK;
1304}
1305
1306//Get the Radio enable status
1307INT wifi_getRadioStatus(INT radioIndex, BOOL *output_bool) //RDKB
1308{
1309 if (NULL == output_bool)
1310 return RETURN_ERR;
1311
1312 return wifi_getRadioEnable(radioIndex, output_bool);
1313}
1314
1315//Get the Radio Interface name from platform, eg "wlan0"
1316INT wifi_getRadioIfName(INT radioIndex, CHAR *output_string) //Tr181
1317{
1318 if (NULL == output_string || radioIndex>=NUMBER_OF_RADIOS || radioIndex<0)
1319 return RETURN_ERR;
1320 snprintf(output_string, 64, "%s%d", RADIO_PREFIX, radioIndex);
1321
1322 return RETURN_OK;
1323}
1324
1325//Get the maximum PHY bit rate supported by this interface. eg: "216.7 Mb/s", "1.3 Gb/s"
1326//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.
1327INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1328{
developerbcc556a2022-09-22 20:02:45 +08001329 // The formula to coculate bit rate is "Subcarriers * Modulation * Coding rate * Spatial stream / (Data interval + Guard interval)"
1330 // For max bit rate, we should always choose the best MCS
1331 char mode[64] = {0};
1332 char channel_bandwidth_str[16] = {0};
1333 char *tmp = NULL;
1334 UINT mode_map = 0;
1335 UINT num_subcarrier = 0;
1336 UINT code_bits = 0;
1337 float code_rate = 0; // use max code rate
1338 int NSS = 0;
1339 UINT Symbol_duration = 0;
1340 UINT GI_duration = 0;
1341 wifi_band band = band_invalid;
1342 wifi_guard_interval_t gi = wifi_guard_interval_auto;
1343 BOOL enable = FALSE;
1344 float bit_rate = 0;
developer06a01d92022-09-07 16:32:39 +08001345
1346 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1347 if (NULL == output_string)
1348 return RETURN_ERR;
1349
developerbcc556a2022-09-22 20:02:45 +08001350 wifi_getRadioEnable(radioIndex, &enable);
1351 if (enable == FALSE) {
1352 snprintf(output_string, 64, "0 Mb/s");
1353 return RETURN_OK;
1354 }
1355
1356 if (wifi_getRadioMode(radioIndex, mode, &mode_map) == RETURN_ERR) {
1357 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
1358 return RETURN_ERR;
1359 }
1360
1361 if (wifi_getGuardInterval(radioIndex, &gi) == RETURN_ERR) {
1362 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
1363 return RETURN_ERR;
1364 }
1365
1366 if (gi == wifi_guard_interval_3200)
1367 GI_duration = 32;
1368 else if (gi == wifi_guard_interval_1600)
1369 GI_duration = 16;
1370 else if (gi == wifi_guard_interval_800)
1371 GI_duration = 8;
1372 else // auto, 400
1373 GI_duration = 4;
developer06a01d92022-09-07 16:32:39 +08001374
developerbcc556a2022-09-22 20:02:45 +08001375 if (wifi_getRadioOperatingChannelBandwidth(radioIndex, channel_bandwidth_str) != RETURN_OK) {
1376 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error\n", __func__);
1377 return RETURN_ERR;
1378 }
1379
1380 if (strstr(channel_bandwidth_str, "80+80") != NULL)
1381 strcpy(channel_bandwidth_str, "160");
1382
1383 if (mode_map & WIFI_MODE_AX) {
1384 if (strstr(channel_bandwidth_str, "160") != NULL)
1385 num_subcarrier = 1960;
1386 else if (strstr(channel_bandwidth_str, "80") != NULL)
1387 num_subcarrier = 980;
1388 else if (strstr(channel_bandwidth_str, "40") != NULL)
1389 num_subcarrier = 468;
1390 else if (strstr(channel_bandwidth_str, "20") != NULL)
1391 num_subcarrier = 234;
1392 code_bits = 10;
1393 code_rate = (float)5/6;
1394 Symbol_duration = 128;
1395 } else if (mode_map & WIFI_MODE_AC) {
1396 if (strstr(channel_bandwidth_str, "160") != NULL)
1397 num_subcarrier = 468;
1398 else if (strstr(channel_bandwidth_str, "80") != NULL)
1399 num_subcarrier = 234;
1400 else if (strstr(channel_bandwidth_str, "40") != NULL)
1401 num_subcarrier = 108;
1402 else if (strstr(channel_bandwidth_str, "20") != NULL)
1403 num_subcarrier = 52;
1404 code_bits = 8;
1405 code_rate = (float)5/6;
1406 Symbol_duration = 32;
1407 } else if (mode_map & WIFI_MODE_N) {
1408 if (strstr(channel_bandwidth_str, "160") != NULL)
1409 num_subcarrier = 468;
1410 else if (strstr(channel_bandwidth_str, "80") != NULL)
1411 num_subcarrier = 234;
1412 else if (strstr(channel_bandwidth_str, "40") != NULL)
1413 num_subcarrier = 108;
1414 else if (strstr(channel_bandwidth_str, "20") != NULL)
1415 num_subcarrier = 52;
1416 code_bits = 6;
1417 code_rate = (float)3/4;
1418 Symbol_duration = 32;
1419 } else if ((mode_map & WIFI_MODE_G || mode_map & WIFI_MODE_B) || mode_map & WIFI_MODE_A) {
1420 // mode b must run with mode g, so we output mode g bitrate in 2.4 G.
1421 snprintf(output_string, 64, "65 Mb/s");
1422 return RETURN_OK;
1423 } else {
1424 snprintf(output_string, 64, "0 Mb/s");
1425 return RETURN_OK;
1426 }
developer06a01d92022-09-07 16:32:39 +08001427
developerbcc556a2022-09-22 20:02:45 +08001428 // Spatial streams
1429 if (wifi_getRadioTxChainMask(radioIndex, &NSS) != RETURN_OK) {
1430 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error\n", __func__);
1431 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001432 }
developerbcc556a2022-09-22 20:02:45 +08001433
1434 // multiple 10 is to align duration unit (0.1 us)
1435 bit_rate = (num_subcarrier * code_bits * code_rate * NSS) / (Symbol_duration + GI_duration) * 10;
1436 snprintf(output_string, 64, "%.1f Mb/s", bit_rate);
1437
developer06a01d92022-09-07 16:32:39 +08001438 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1439
1440 return RETURN_OK;
1441}
1442#if 0
1443INT wifi_getRadioMaxBitRate(INT radioIndex, CHAR *output_string) //RDKB
1444{
1445 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1446 char cmd[64];
1447 char buf[1024];
1448 int apIndex;
1449
1450 if (NULL == output_string)
1451 return RETURN_ERR;
1452
1453 apIndex=(radioIndex==0)?0:1;
1454
1455 snprintf(cmd, sizeof(cmd), "iwconfig %s%d | grep \"Bit Rate\" | cut -d':' -f2 | cut -d' ' -f1,2", AP_PREFIX, apIndex);
1456 _syscmd(cmd,buf, sizeof(buf));
1457
1458 snprintf(output_string, 64, "%s", buf);
1459 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1460 return RETURN_OK;
1461}
1462#endif
1463
1464
1465//Get Supported frequency bands at which the radio can operate. eg: "2.4GHz,5GHz"
1466//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.
1467INT wifi_getRadioSupportedFrequencyBands(INT radioIndex, CHAR *output_string) //RDKB
1468{
developer963da0c2022-09-13 15:58:27 +08001469 wifi_band band = band_invalid;
1470
developer06a01d92022-09-07 16:32:39 +08001471 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1472 if (NULL == output_string)
1473 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001474
1475 band = wifi_index_to_band(radioIndex);
1476
1477 memset(output_string, 0, 10);
1478 if (band == band_2_4)
1479 strcpy(output_string, "2.4GHz");
1480 else if (band == band_5)
1481 strcpy(output_string, "5GHz");
1482 else if (band == band_6)
1483 strcpy(output_string, "6GHz");
1484 else
1485 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08001486 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1487
1488 return RETURN_OK;
1489#if 0
1490 char buf[MAX_BUF_SIZE]={'\0'};
1491 char str[MAX_BUF_SIZE]={'\0'};
1492 char cmd[MAX_CMD_SIZE]={'\0'};
1493 char *ch=NULL;
1494 char *ch2=NULL;
1495
1496 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1497 if (NULL == output_string)
1498 return RETURN_ERR;
1499
1500
1501 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1502
1503 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1504 {
1505 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1506 return RETURN_ERR;
1507 }
1508 ch=strchr(buf,'\n');
1509 *ch='\0';
1510 ch=strchr(buf,'=');
1511 if(ch==NULL)
1512 return RETURN_ERR;
1513
1514
1515 ch++;
1516
1517 /* prepend 0 for channel with single digit. for ex, 6 would be 06 */
1518 strcpy(buf,"0");
1519 if(strlen(ch) == 1)
1520 ch=strcat(buf,ch);
1521
1522
1523 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1524
1525 if(_syscmd(cmd,str,64) == RETURN_ERR)
1526 {
1527 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1528 return RETURN_ERR;
1529 }
1530
1531
1532 ch2=strchr(str,'\n');
1533 //replace \n with \0
1534 *ch2='\0';
1535 ch2=strchr(str,'=');
1536 if(ch2==NULL)
1537 {
1538 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1539 return RETURN_ERR;
1540 }
1541 else
1542 wifi_dbg_printf("%s",ch2+1);
1543
1544
1545 ch2++;
1546
1547
1548 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch);
1549
1550 memset(buf,'\0',sizeof(buf));
1551 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1552 {
1553 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1554 return RETURN_ERR;
1555 }
1556 if (strstr(buf,"2.4") != NULL )
1557 strcpy(output_string,"2.4GHz");
1558 else if(strstr(buf,"5.") != NULL )
1559 strcpy(output_string,"5GHz");
1560 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1561
1562 return RETURN_OK;
1563#endif
1564}
1565
1566//Get the frequency band at which the radio is operating, eg: "2.4GHz"
1567//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.
1568INT wifi_getRadioOperatingFrequencyBand(INT radioIndex, CHAR *output_string) //Tr181
1569{
1570 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1571 if (NULL == output_string)
1572 return RETURN_ERR;
1573 snprintf(output_string, 64, (radioIndex == 0)?"2.4GHz":"5GHz");
1574 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1575
1576 return RETURN_OK;
1577#if 0
1578 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1579 char buf[MAX_BUF_SIZE]={'\0'};
1580 char str[MAX_BUF_SIZE]={'\0'};
1581 char cmd[MAX_CMD_SIZE]={'\0'};
1582 char *ch=NULL;
1583 char *ch2=NULL;
1584 char ch1[5]="0";
1585
1586 sprintf(cmd,"grep 'channel=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1587
1588 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
1589 {
1590 printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1591 return RETURN_ERR;
1592 }
1593
1594 ch=strchr(buf,'\n');
1595 *ch='\0';
1596 ch=strchr(buf,'=');
1597 if(ch==NULL)
1598 return RETURN_ERR;
1599 ch++;
1600
1601 if(strlen(ch)==1)
1602 {
1603 strcat(ch1,ch);
1604
1605 }
1606 else
1607 {
1608 strcpy(ch1,ch);
1609 }
1610
1611
1612
1613 sprintf(cmd,"grep 'interface=' %s%d.conf",CONFIG_PREFIX,radioIndex);
1614 if(_syscmd(cmd,str,64) == RETURN_ERR)
1615 {
1616 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1617 return RETURN_ERR;
1618 }
1619
1620
1621 ch2=strchr(str,'\n');
1622 //replace \n with \0
1623 *ch2='\0';
1624 ch2=strchr(str,'=');
1625 if(ch2==NULL)
1626 {
1627 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1628 return RETURN_ERR;
1629 }
1630 else
1631 wifi_dbg_printf("%s",ch2+1);
1632 ch2++;
1633
1634
1635 sprintf(cmd,"iwlist %s frequency|grep 'Channel %s'",ch2,ch1);
1636 memset(buf,'\0',sizeof(buf));
1637 if(_syscmd(cmd,buf,sizeof(buf))==RETURN_ERR)
1638 {
1639 wifi_dbg_printf("\nError %d:%s:%s\n",__LINE__,__func__,__FILE__);
1640 return RETURN_ERR;
1641 }
1642
1643
1644 if(strstr(buf,"2.4")!=NULL)
1645 {
1646 strcpy(output_string,"2.4GHz");
1647 }
1648 if(strstr(buf,"5.")!=NULL)
1649 {
1650 strcpy(output_string,"5GHz");
1651 }
1652 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1653 return RETURN_OK;
1654#endif
1655}
1656
1657//Get the Supported Radio Mode. eg: "b,g,n"; "n,ac"
1658//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.
1659INT wifi_getRadioSupportedStandards(INT radioIndex, CHAR *output_string) //Tr181
1660{
developer963da0c2022-09-13 15:58:27 +08001661 char cmd[128]={0};
1662 char buf[128]={0};
1663 char temp_output[128] = {0};
1664 wifi_band band;
1665
1666 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001667 if (NULL == output_string)
1668 return RETURN_ERR;
developer963da0c2022-09-13 15:58:27 +08001669
1670 band = wifi_index_to_band(radioIndex);
1671 if (band == band_2_4) {
1672 strcat(temp_output, "b,g,");
1673 } else if (band == band_5) {
1674 strcat(temp_output, "a,");
1675 }
1676
1677 // ht capabilities
1678 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);
1679 _syscmd(cmd, buf, sizeof(buf));
1680 if (strncmp(buf, "0x00", 4) != 0) {
1681 strcat(temp_output, "n,");
1682 }
developer06a01d92022-09-07 16:32:39 +08001683
developer963da0c2022-09-13 15:58:27 +08001684 // vht capabilities
1685 if (band == band_5) {
1686 snprintf(cmd, sizeof(cmd), "iw phy%d info | grep 'VHT Capabilities' | cut -d '(' -f2 | cut -c1-10 | tr -d '\\n'", radioIndex);
1687 _syscmd(cmd, buf, sizeof(buf));
1688 if (strncmp(buf, "0x00000000", 10) != 0) {
1689 strcat(temp_output, "ac,");
1690 }
1691 }
1692
1693 // he capabilities
1694 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);
1695 _syscmd(cmd, buf, sizeof(buf));
1696 if (strncmp (buf, "0x0000", 6) != 0) {
1697 strcat(temp_output, "ax,");
1698 }
1699
1700 // Remove the last comma
1701 if (strlen(temp_output) != 0)
1702 temp_output[strlen(temp_output)-1] = '\0';
1703 strncpy(output_string, temp_output, strlen(temp_output));
1704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08001705 return RETURN_OK;
1706}
1707
1708//Get the radio operating mode, and pure mode flag. eg: "ac"
1709//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.
1710INT wifi_getRadioStandard(INT radioIndex, CHAR *output_string, BOOL *gOnly, BOOL *nOnly, BOOL *acOnly) //RDKB
1711{
1712 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1713 if (NULL == output_string)
1714 return RETURN_ERR;
1715
1716 if (radioIndex == 0) {
1717 snprintf(output_string, 64, "n"); //"ht" needs to be translated to "n" or others
1718 *gOnly = FALSE;
1719 *nOnly = TRUE;
1720 *acOnly = FALSE;
1721 } else {
1722 snprintf(output_string, 64, "ac"); //"vht" needs to be translated to "ac"
1723 *gOnly = FALSE;
1724 *nOnly = FALSE;
1725 *acOnly = FALSE;
1726 }
1727 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1728
1729 return RETURN_OK;
1730#if 0
1731 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1732 char buf[64] = {0};
1733 char config_file[MAX_BUF_SIZE] = {0};
1734
1735 if ((NULL == output_string) || (NULL == gOnly) || (NULL == nOnly) || (NULL == acOnly))
1736 return RETURN_ERR;
1737
1738 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
1739 wifi_hostapdRead(config_file, "hw_mode", buf, sizeof(buf));
1740
1741 wifi_dbg_printf("\nhw_mode=%s\n",buf);
1742 if (strlen(buf) == 0)
1743 {
1744 wifi_dbg_printf("\nwifi_hostapdRead returned none\n");
1745 return RETURN_ERR;
1746 }
1747 if(strcmp(buf,"g")==0)
1748 {
1749 wifi_dbg_printf("\nG\n");
1750 *gOnly=TRUE;
1751 *nOnly=FALSE;
1752 *acOnly=FALSE;
1753 }
1754 else if(strcmp(buf,"n")==0)
1755 {
1756 wifi_dbg_printf("\nN\n");
1757 *gOnly=FALSE;
1758 *nOnly=TRUE;
1759 *acOnly=FALSE;
1760 }
1761 else if(strcmp(buf,"ac")==0)
1762 {
1763 wifi_dbg_printf("\nac\n");
1764 *gOnly=FALSE;
1765 *nOnly=FALSE;
1766 *acOnly=TRUE;
1767 }
1768 /* hostapd-5G.conf has "a" as hw_mode */
1769 else if(strcmp(buf,"a")==0)
1770 {
1771 wifi_dbg_printf("\na\n");
1772 *gOnly=FALSE;
1773 *nOnly=FALSE;
1774 *acOnly=FALSE;
1775 }
1776 else
1777 wifi_dbg_printf("\nInvalid Mode %s\n", buf);
1778
1779 //for a,n mode
1780 if(radioIndex == 1)
1781 {
1782 wifi_hostapdRead(config_file, "ieee80211n", buf, sizeof(buf));
1783 if(strcmp(buf,"1")==0)
1784 {
1785 strncpy(output_string, "n", 1);
1786 *nOnly=FALSE;
1787 }
1788 }
1789
1790 wifi_dbg_printf("\nReturning from getRadioStandard\n");
1791 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1792 return RETURN_OK;
1793#endif
1794}
1795
developerdb744382022-09-13 15:34:54 +08001796INT wifi_getRadioMode(INT radioIndex, CHAR *output_string, UINT *pureMode)
1797{
1798 char cmd[128] = {0};
1799 char buf[64] = {0};
1800 char config_file[64] = {0};
1801 wifi_band band;
1802
1803 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
1804 if(NULL == output_string || NULL == pureMode)
1805 return RETURN_ERR;
1806
1807 // grep all of the ieee80211 protocol config set to 1
1808 snprintf(config_file, sizeof(cmd), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1809 snprintf(cmd, sizeof(cmd), "cat %s | grep -E \"ieee.*=1\" | cut -d '=' -f1 | tr -d 'ieee80211'", config_file);
1810 _syscmd(cmd, buf, sizeof(buf));
1811
1812 band = wifi_index_to_band(radioIndex);
1813 // puremode is a bit map
1814 *pureMode = 0;
1815 if (band == band_2_4) {
1816 strcat(output_string, "b,g");
1817 *pureMode |= WIFI_MODE_B | WIFI_MODE_G;
1818 if (strstr(buf, "n") != NULL) {
1819 strcat(output_string, ",n");
1820 *pureMode |= WIFI_MODE_N;
1821 }
1822 if (strstr(buf, "ax") != NULL) {
1823 strcat(output_string, ",ax");
1824 *pureMode |= WIFI_MODE_AX;
1825 }
1826 } else if (band == band_5) {
1827 strcat(output_string, "a");
1828 *pureMode |= WIFI_MODE_A;
1829 if (strstr(buf, "n") != NULL) {
1830 strcat(output_string, ",n");
1831 *pureMode |= WIFI_MODE_N;
1832 }
1833 if (strstr(buf, "ac") != NULL) {
1834 strcat(output_string, ",ac");
1835 *pureMode |= WIFI_MODE_AC;
1836 }
1837 if (strstr(buf, "ax") != NULL) {
1838 strcat(output_string, ",ax");
1839 *pureMode |= WIFI_MODE_AX;
1840 }
1841 } else if (band == band_6) {
1842 if (strstr(buf, "ax") != NULL) {
1843 strcat(output_string, "ax");
1844 *pureMode |= WIFI_MODE_AX;
1845 }
1846 }
1847
1848 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1849 return RETURN_OK;
1850}
1851
1852// Set the radio operating mode, and pure mode flag.
developer06a01d92022-09-07 16:32:39 +08001853INT wifi_setRadioChannelMode(INT radioIndex, CHAR *channelMode, BOOL gOnlyFlag, BOOL nOnlyFlag, BOOL acOnlyFlag) //RDKB
1854{
1855 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%s_%d_%d:%d\n",__func__,channelMode,nOnlyFlag,gOnlyFlag,__LINE__);
1856 if (strcmp (channelMode,"11A") == 0)
1857 {
1858 writeBandWidth(radioIndex,"20MHz");
1859 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1860 printf("\nChannel Mode is 802.11a (5GHz)\n");
1861 }
1862 else if (strcmp (channelMode,"11NAHT20") == 0)
1863 {
1864 writeBandWidth(radioIndex,"20MHz");
1865 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1866 printf("\nChannel Mode is 802.11n-20MHz(5GHz)\n");
1867 }
1868 else if (strcmp (channelMode,"11NAHT40PLUS") == 0)
1869 {
1870 writeBandWidth(radioIndex,"40MHz");
1871 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1872 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1873 }
1874 else if (strcmp (channelMode,"11NAHT40MINUS") == 0)
1875 {
1876 writeBandWidth(radioIndex,"40MHz");
1877 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1878 printf("\nChannel Mode is 802.11n-40MHz(5GHz)\n");
1879 }
1880 else if (strcmp (channelMode,"11ACVHT20") == 0)
1881 {
1882 writeBandWidth(radioIndex,"20MHz");
1883 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1884 printf("\nChannel Mode is 802.11ac-20MHz(5GHz)\n");
1885 }
1886 else if (strcmp (channelMode,"11ACVHT40PLUS") == 0)
1887 {
1888 writeBandWidth(radioIndex,"40MHz");
1889 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1890 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1891 }
1892 else if (strcmp (channelMode,"11ACVHT40MINUS") == 0)
1893 {
1894 writeBandWidth(radioIndex,"40MHz");
1895 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1896 printf("\nChannel Mode is 802.11ac-40MHz(5GHz)\n");
1897 }
1898 else if (strcmp (channelMode,"11ACVHT80") == 0)
1899 {
1900 wifi_setRadioOperatingChannelBandwidth(radioIndex,"80MHz");
1901 printf("\nChannel Mode is 802.11ac-80MHz(5GHz)\n");
1902 }
1903 else if (strcmp (channelMode,"11ACVHT160") == 0)
1904 {
1905 wifi_setRadioOperatingChannelBandwidth(radioIndex,"160MHz");
1906 printf("\nChannel Mode is 802.11ac-160MHz(5GHz)\n");
1907 }
1908 else if (strcmp (channelMode,"11B") == 0)
1909 {
1910 writeBandWidth(radioIndex,"20MHz");
1911 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1912 printf("\nChannel Mode is 802.11b(2.4GHz)\n");
1913 }
1914 else if (strcmp (channelMode,"11G") == 0)
1915 {
1916 writeBandWidth(radioIndex,"20MHz");
1917 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1918 printf("\nChannel Mode is 802.11g(2.4GHz)\n");
1919 }
1920 else if (strcmp (channelMode,"11NGHT20") == 0)
1921 {
1922 writeBandWidth(radioIndex,"20MHz");
1923 wifi_setRadioOperatingChannelBandwidth(radioIndex,"20MHz");
1924 printf("\nChannel Mode is 802.11n-20MHz(2.4GHz)\n");
1925 }
1926 else if (strcmp (channelMode,"11NGHT40PLUS") == 0)
1927 {
1928 writeBandWidth(radioIndex,"40MHz");
1929 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1930 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1931 }
1932 else if (strcmp (channelMode,"11NGHT40MINUS") == 0)
1933 {
1934 writeBandWidth(radioIndex,"40MHz");
1935 wifi_setRadioOperatingChannelBandwidth(radioIndex,"40MHz");
1936 printf("\nChannel Mode is 802.11n-40MHz(2.4GHz)\n");
1937 }
1938 else
1939 {
1940 return RETURN_ERR;
1941 }
1942 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1943
1944 return RETURN_OK;
1945}
1946
developerdb744382022-09-13 15:34:54 +08001947// Set the radio operating mode, and pure mode flag.
1948INT wifi_setRadioMode(INT radioIndex, CHAR *channelMode, UINT pureMode)
1949{
1950 int num_hostapd_support_mode = 3; // n, ac, ax
1951 struct params list[num_hostapd_support_mode];
1952 char config_file[64] = {0};
1953 char bandwidth[16] = {0};
1954 int mode_check_bit = 1 << 3; // n mode
1955 wifi_ieee80211_Mode mode = (wifi_ieee80211_Mode)pureMode;
1956
1957 WIFI_ENTRY_EXIT_DEBUG("Inside %s_%d:%d\n", __func__, channelMode, pureMode, __LINE__);
1958 // Set radio mode
1959 list[0].name = "ieee80211n";
1960 list[1].name = "ieee80211ac";
1961 list[2].name = "ieee80211ax";
1962 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
1963
1964 // check the bit map from n to ax, and set hostapd config
1965 if (mode & WIFI_MODE_N)
1966 list[0].value = "1";
1967 else
1968 list[0].value = "0";
1969 if (mode & WIFI_MODE_AC)
1970 list[1].value = "1";
1971 else
1972 list[1].value = "0";
1973 if (mode & WIFI_MODE_AX)
1974 list[2].value = "1";
1975 else
1976 list[2].value = "0";
1977 wifi_hostapdWrite(config_file, list, num_hostapd_support_mode);
1978
1979 if (channelMode == NULL || strlen(channelMode) == 0)
1980 return RETURN_OK;
1981 // Set bandwidth
1982 if (strstr(channelMode, "40") != NULL)
1983 strcpy(bandwidth, "40MHz");
1984 else if (strstr(channelMode, "80") != NULL)
1985 strcpy(bandwidth, "80MHz");
1986 else if (strstr(channelMode, "160") != NULL)
1987 strcpy(bandwidth, "160MHz");
1988 else // 11A, 11B, 11G....
1989 strcpy(bandwidth, "20MHz");
1990
1991 writeBandWidth(radioIndex, bandwidth);
1992 wifi_setRadioOperatingChannelBandwidth(radioIndex, bandwidth);
1993
1994 wifi_reloadAp(radioIndex);
1995 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
1996
1997 return RETURN_OK;
1998}
1999
developer06a01d92022-09-07 16:32:39 +08002000//Get the list of supported channel. eg: "1-11"
2001//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.
2002INT wifi_getRadioPossibleChannels(INT radioIndex, CHAR *output_string) //RDKB
2003{
developer6318ed52022-09-13 15:17:58 +08002004 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002005 if (NULL == output_string)
2006 return RETURN_ERR;
developer6318ed52022-09-13 15:17:58 +08002007 char cmd[256] = {0};
2008 char buf[128] = {0};
2009 BOOL dfs_enable = false;
2010 // Parse possible channel number and separate them with commas.
2011 wifi_getRadioDfsEnable(radioIndex, &dfs_enable);
2012 if (dfs_enable)
2013 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep -e '\\*.*MHz .*dBm' | cut -d '[' -f2 | cut -d ']' -f1 | tr '\\n' ',' | sed 's/.$//'", radioIndex);
2014 else
2015 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);
2016
2017 _syscmd(cmd,buf,sizeof(buf));
2018 strncpy(output_string, buf, sizeof(buf));
2019
2020 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2021 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002022#if 0
2023 char IFName[50] ={0};
2024 char buf[MAX_BUF_SIZE] = {0};
2025 char cmd[MAX_CMD_SIZE] = {0};
2026 int count = 0;
2027 if (NULL == output_string)
2028 return RETURN_ERR;
2029
2030 //snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2031 if(radioIndex == 0)
2032 {
2033 GetInterfaceName(IFName,"/nvram/hostapd0.conf");
2034 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'");
2035 }
2036 else if(radioIndex == 1)
2037 {
2038 GetInterfaceName(IFName,"/nvram/hostapd1.conf");
2039 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'");
2040 }
2041 _syscmd(cmd, buf, sizeof(buf));
2042 if(strlen(buf) > 0)
2043 strcpy(output_string,buf);
2044 else
2045 strcpy(output_string,"0");
2046#endif
2047 return RETURN_OK;
2048}
2049
2050//Get the list for used channel. eg: "1,6,9,11"
2051//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.
2052INT wifi_getRadioChannelsInUse(INT radioIndex, CHAR *output_string) //RDKB
2053{
2054 if (NULL == output_string)
2055 return RETURN_ERR;
2056 snprintf(output_string, 256, (radioIndex == 0)?"1,6,11":"36,40");
2057#if 0
2058 char IFName[50] ={0};
2059 char buf[MAX_BUF_SIZE] = {0};
2060 char cmd[MAX_CMD_SIZE] = {0};
2061 if (NULL == output_string)
2062 return RETURN_ERR;
2063
2064 // snprintf(output_string, 256, (radioIndex==0)?"1,6,11":"36,40");
2065 if(radioIndex == 0)
2066 {
2067 GetInterfaceName(IFName, "/nvram/hostapd0.conf");
2068 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'");
2069 }
2070 else if(radioIndex == 1)
2071 {
2072 GetInterfaceName(IFName, "/nvram/hostapd1.conf");
2073 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'");
2074 }
2075 _syscmd(cmd,buf, sizeof(buf));
2076 if(strlen(buf) > 0)
2077 strcpy(output_string,buf);
2078 else
2079 strcpy(output_string,"0");
2080#endif
2081 return RETURN_OK;
2082}
2083
2084//Get the running channel number
2085INT wifi_getRadioChannel(INT radioIndex,ULONG *output_ulong) //RDKB
2086{
developerda1ed692022-09-13 13:59:20 +08002087#ifdef MTK_IMPL
2088 if(!wifi_getApChannel(radioIndex, output_ulong))
2089 return RETURN_OK;
2090 else
2091 return RETURN_ERR;
2092#else
developer06a01d92022-09-07 16:32:39 +08002093 char cmd[1024] = {0}, buf[5] = {0};
2094
2095 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2096 if (NULL == output_ulong)
2097 return RETURN_ERR;
2098
2099 snprintf(cmd, sizeof(cmd),
2100 "ls -1 /sys/class/net/%s%d/device/ieee80211/phy*/device/net/ | "
2101 "xargs -I {} iw dev {} info | grep channel | head -n1 | "
2102 "cut -d ' ' -f2", RADIO_PREFIX, radioIndex);
2103 _syscmd(cmd, buf, sizeof(buf));
2104
2105 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2106 if (*output_ulong <= 0) {
2107 *output_ulong = 0;
2108 return RETURN_ERR;
2109 }
2110
2111 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2112 return RETURN_OK;
developerda1ed692022-09-13 13:59:20 +08002113#endif
developer06a01d92022-09-07 16:32:39 +08002114}
2115
2116
2117INT wifi_getApChannel(INT apIndex,ULONG *output_ulong) //RDKB
2118{
2119 char cmd[1024] = {0}, buf[5] = {0};
2120 char interface_name[50] = {0};
2121
2122 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2123 if (NULL == output_ulong)
2124 return RETURN_ERR;
2125
2126 wifi_getApName(apIndex,interface_name);
2127 snprintf(cmd, sizeof(cmd), "iw dev %s info |grep channel | cut -d ' ' -f2",interface_name);
2128 _syscmd(cmd,buf,sizeof(buf));
2129 *output_ulong = (strlen(buf) >= 1)? atol(buf): 0;
2130 if (*output_ulong == 0) {
2131 return RETURN_ERR;
2132 }
2133
2134 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2135 return RETURN_OK;
2136}
2137
2138//Storing the previous channel value
2139INT wifi_storeprevchanval(INT radioIndex)
2140{
2141 char buf[256] = {0};
2142 char output[4]={'\0'};
2143 char config_file[MAX_BUF_SIZE] = {0};
2144 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2145 wifi_hostapdRead(config_file, "channel", output, sizeof(output));
2146 if(radioIndex == 0)
2147 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval2G_AutoChannelEnable");
2148 else if(radioIndex == 1)
2149 sprintf(buf,"%s%s%s","echo ",output," > /var/prevchanval5G_AutoChannelEnable");
2150 system(buf);
2151 Radio_flag = FALSE;
2152 return RETURN_OK;
2153}
2154
2155//Set the running channel number
2156INT wifi_setRadioChannel(INT radioIndex, ULONG channel) //RDKB //AP only
2157{
2158 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2159 struct params params={'\0'};
2160 char str_channel[4]={'\0'};
2161 struct params list;
2162 char config_file[MAX_BUF_SIZE] = {0};
2163
2164 list.name = "channel";
2165
2166 if(Radio_flag == TRUE)
2167 wifi_storeprevchanval(radioIndex); //for autochannel
2168
2169 if(radioIndex == 0)
2170 {
2171 switch(channel)
2172 {
2173 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12:
2174 sprintf(str_channel,"%ld", channel);
2175 list.value = str_channel;
2176 break;
2177 default:
2178 return RETURN_ERR;
2179 }
2180 }
2181 else if(radioIndex == 1)
2182 {
2183 switch(channel)
2184 {
2185 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:
2186 sprintf(str_channel,"%ld", channel);
2187 list.value = str_channel;
2188 break;
2189 default:
2190 return RETURN_ERR;
2191 }
2192 }
2193
2194 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS;i++)
2195 {
2196 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2197 wifi_hostapdWrite(config_file,&list,1);
2198 }
2199
2200 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2201 return RETURN_OK;
2202 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2203 }
2204
2205INT wifi_setRadioCenterChannel(INT radioIndex, ULONG channel)
2206{
2207 struct params list;
2208 char str_idx[16];
2209 char config_file[MAX_BUF_SIZE];
2210
2211 list.name = "vht_oper_centr_freq_seg0_idx";
2212 snprintf(str_idx, sizeof(str_idx), "%d", channel);
2213 list.value = str_idx;
2214
2215 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2216 {
2217 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(2*i));
2218 wifi_hostapdWrite(config_file, &list, 1);
2219 }
2220
2221 return RETURN_OK;
2222}
2223
2224//Enables or disables a driver level variable to indicate if auto channel selection is enabled on this radio
2225//This "auto channel" means the auto channel selection when radio is up. (which is different from the dynamic channel/frequency selection (DFC/DCS))
2226INT wifi_setRadioAutoChannelEnable(INT radioIndex, BOOL enable) //RDKB
2227{
2228 //Set to wifi config only. Wait for wifi reset to apply.
2229 char buf[256] = {0};
2230 char str_channel[256] = {0};
2231 int count = 0;
2232 ULONG Value = 0;
2233 FILE *fp = NULL;
2234 if(enable == TRUE)
2235 {
2236 if(radioIndex == 0)
2237 {
2238 // _syscmd("cat /var/prevchanval2G_AutoChannelEnable", buf, sizeof(buf));
2239 fp = fopen("/var/prevchanval2G_AutoChannelEnable","r");
2240 }
2241 else if(radioIndex == 1)
2242 {
2243 // _syscmd("cat /var/prevchanval5G_AutoChannelEnable", buf, sizeof(buf));
2244 fp = fopen("/var/prevchanval5G_AutoChannelEnable","r");
2245 }
2246 if(fp == NULL) //first time boot-up
2247 {
2248 if(radioIndex == 0)
2249 Value = 6;
2250 else if(radioIndex == 1)
2251 Value = 36;
2252 }
2253 else
2254 {
2255 if(fgets(buf,sizeof(buf),fp) != NULL)
2256 {
2257 for(count = 0;buf[count]!='\n';count++)
2258 str_channel[count] = buf[count];
2259 str_channel[count] = '\0';
2260 Value = atol(str_channel);
2261 printf("%sValue is %ld \n",__FUNCTION__,Value);
2262 pclose(fp);
2263 }
2264 }
2265 Radio_flag = FALSE;//for storing previous channel value
2266 wifi_setRadioChannel(radioIndex,Value);
2267 return RETURN_OK;
2268 }
2269 return RETURN_ERR;
2270}
2271
developer0b246d12022-09-30 15:24:20 +08002272INT wifi_getRadioAutoChannelSupported(INT radioIndex, BOOL *output_bool)
2273{
2274 if (output_bool == NULL)
2275 return RETURN_ERR;
2276
2277 *output_bool = TRUE;
2278
2279 return RETURN_OK;
2280}
2281
developer06a01d92022-09-07 16:32:39 +08002282INT wifi_getRadioDCSSupported(INT radioIndex, BOOL *output_bool) //RDKB
2283{
2284 if (NULL == output_bool)
2285 return RETURN_ERR;
2286 *output_bool=FALSE;
2287 return RETURN_OK;
2288}
2289
2290INT wifi_getRadioDCSEnable(INT radioIndex, BOOL *output_bool) //RDKB
2291{
2292 if (NULL == output_bool)
2293 return RETURN_ERR;
2294 *output_bool=FALSE;
2295 return RETURN_OK;
2296}
2297
2298INT wifi_setRadioDCSEnable(INT radioIndex, BOOL enable) //RDKB
2299{
2300 //Set to wifi config only. Wait for wifi reset to apply.
2301 return RETURN_OK;
2302}
2303
2304INT wifi_setApEnableOnLine(ULONG wlanIndex,BOOL enable)
2305{
2306 return RETURN_OK;
2307}
2308
2309INT wifi_factoryResetAP(int apIndex)
2310{
developer838cca92022-10-03 13:19:57 +08002311 char ap_config_file[64] = {0};
2312 char cmd[128] = {0};
2313
developer06a01d92022-09-07 16:32:39 +08002314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002315
2316 wifi_setApEnable(apIndex, FALSE);
2317 sprintf(ap_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
2318 sprintf(cmd, "rm %s && sh /lib/rdk/hostapd-init.sh", ap_config_file);
2319 wifi_setApEnable(apIndex, TRUE);
2320
developer06a01d92022-09-07 16:32:39 +08002321 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer838cca92022-10-03 13:19:57 +08002322
developer06a01d92022-09-07 16:32:39 +08002323 return RETURN_OK;
2324}
2325
2326//To set Band Steering AP group
2327//To-do
2328INT wifi_setBandSteeringApGroup(char *ApGroup)
2329{
2330 return RETURN_OK;
2331}
2332
developer1e5aa162022-09-13 16:06:24 +08002333INT wifi_getApDTIMInterval(INT apIndex, INT *dtimInterval)
2334{
2335 char config_file[128] = {'\0'};
2336 char buf[128] = {'\0'};
2337
2338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2339 if (dtimInterval == NULL)
2340 return RETURN_ERR;
2341
2342 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
2343 wifi_hostapdRead(config_file, "dtime_period", buf, sizeof(buf));
2344
2345 if (strlen(buf) == 0) {
2346 *dtimInterval = 2;
2347 } else {
2348 *dtimInterval = strtoul(buf, NULL, 10);
2349 }
2350
2351 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2352 return RETURN_OK;
2353}
2354
developer06a01d92022-09-07 16:32:39 +08002355INT wifi_setApDTIMInterval(INT apIndex, INT dtimInterval)
2356{
developer5f222492022-09-13 15:21:52 +08002357 struct params params={0};
2358 char config_file[MAX_BUF_SIZE] = {'\0'};
2359 char buf[MAX_BUF_SIZE] = {'\0'};
2360
2361 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2362 if (dtimInterval < 1 || dtimInterval > 255) {
2363 return RETURN_ERR;
2364 WIFI_ENTRY_EXIT_DEBUG("Invalid dtimInterval: %d\n", dtimInterval);
2365 }
2366
2367 params.name = "dtim_period";
2368 snprintf(buf, sizeof(buf), "%d", dtimInterval);
2369 params.value = buf;
2370
2371 sprintf(config_file,"%s%d.conf", CONFIG_PREFIX, apIndex);
2372 wifi_hostapdWrite(config_file, &params, 1);
2373 wifi_hostapdProcessUpdate(apIndex, &params, 1);
2374
2375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2376 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002377}
2378
2379//Check if the driver support the Dfs
2380INT wifi_getRadioDfsSupport(INT radioIndex, BOOL *output_bool) //Tr181
2381{
2382 if (NULL == output_bool)
2383 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002384 *output_bool=TRUE;
developer06a01d92022-09-07 16:32:39 +08002385 return RETURN_OK;
2386}
2387
2388//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.
2389//The value of this parameter is a comma seperated list of channel number
2390INT wifi_getRadioDCSChannelPool(INT radioIndex, CHAR *output_pool) //RDKB
2391{
2392 if (NULL == output_pool)
2393 return RETURN_ERR;
2394 if (radioIndex==1)
2395 return RETURN_OK;//TODO need to handle for 5GHz band, i think
2396 snprintf(output_pool, 256, "1,2,3,4,5,6,7,8,9,10,11");
2397
2398 return RETURN_OK;
2399}
2400
2401INT wifi_setRadioDCSChannelPool(INT radioIndex, CHAR *pool) //RDKB
2402{
2403 //Set to wifi config. And apply instantly.
2404 return RETURN_OK;
2405}
2406
2407INT wifi_getRadioDCSScanTime(INT radioIndex, INT *output_interval_seconds, INT *output_dwell_milliseconds)
2408{
2409 if (NULL == output_interval_seconds || NULL == output_dwell_milliseconds)
2410 return RETURN_ERR;
2411 *output_interval_seconds=1800;
2412 *output_dwell_milliseconds=40;
2413
2414 return RETURN_OK;
2415}
2416
2417INT wifi_setRadioDCSScanTime(INT radioIndex, INT interval_seconds, INT dwell_milliseconds)
2418{
2419 //Set to wifi config. And apply instantly.
2420 return RETURN_OK;
2421}
2422
2423//Get the Dfs enable status
2424INT wifi_getRadioDfsEnable(INT radioIndex, BOOL *output_bool) //Tr181
2425{
developer9964b5b2022-09-13 15:59:34 +08002426 char buf[16] = {0};
2427 FILE *f = NULL;
2428 wifi_band band;
2429
2430 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2431
2432 *output_bool = TRUE; // default
developer06a01d92022-09-07 16:32:39 +08002433 if (NULL == output_bool)
2434 return RETURN_ERR;
developer9964b5b2022-09-13 15:59:34 +08002435
2436 band = wifi_index_to_band(radioIndex);
2437 if (band != band_5)
2438 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002439
developer9964b5b2022-09-13 15:59:34 +08002440 f = fopen(DFS_ENABLE_FILE, "r");
2441 if (f != NULL) {
2442 fgets(buf, 2, f);
2443 if (strncmp(buf, "0", 0) == 0)
2444 *output_bool = FALSE;
2445 fclose(f);
2446 }
2447 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002448 return RETURN_OK;
2449}
2450
2451//Set the Dfs enable status
2452INT wifi_setRadioDfsEnable(INT radioIndex, BOOL enable) //Tr181
2453{
developer9964b5b2022-09-13 15:59:34 +08002454 char buf[128] = {0};
2455 char config_file[128] = {0};
2456 FILE *f = NULL;
2457 struct params params={0};
2458 wifi_band band;
2459
2460 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2461
2462 band = wifi_index_to_band(radioIndex);
2463 if (band != band_5)
2464 return RETURN_OK;
2465
2466 f = fopen(DFS_ENABLE_FILE, "w");
2467 if (f == NULL)
2468 return RETURN_ERR;
2469 fprintf(f, "%d", enable);
2470 fclose(f);
2471
2472 params.name = "acs_exclude_dfs";
2473 sprintf(buf, "%d", enable?"1":"0");
2474 params.value = buf;
2475 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2476 wifi_hostapdWrite(config_file, &params, 1);
2477 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2478
2479 wifi_setRadioIEEE80211hEnabled(radioIndex, enable);
2480
2481 wifi_reloadAp(radioIndex);
2482
2483 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002484}
2485
2486//Check if the driver support the AutoChannelRefreshPeriod
2487INT wifi_getRadioAutoChannelRefreshPeriodSupported(INT radioIndex, BOOL *output_bool) //Tr181
2488{
2489 if (NULL == output_bool)
2490 return RETURN_ERR;
2491 *output_bool=FALSE; //not support
2492
2493 return RETURN_OK;
2494}
2495
2496//Get the ACS refresh period in seconds
2497INT wifi_getRadioAutoChannelRefreshPeriod(INT radioIndex, ULONG *output_ulong) //Tr181
2498{
2499 if (NULL == output_ulong)
2500 return RETURN_ERR;
2501 *output_ulong=300;
2502
2503 return RETURN_OK;
2504}
2505
2506//Set the ACS refresh period in seconds
2507INT wifi_setRadioDfsRefreshPeriod(INT radioIndex, ULONG seconds) //Tr181
2508{
2509 return RETURN_ERR;
2510}
2511
2512//Get the Operating Channel Bandwidth. eg "20MHz", "40MHz", "80MHz", "80+80", "160"
2513//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.
2514INT wifi_getRadioOperatingChannelBandwidth(INT radioIndex, CHAR *output_string) //Tr181
2515{
developer70490032022-09-13 15:45:20 +08002516 char cmd[128] = {0}, buf[64] = {0};
2517 char interface_name[64] = {0};
2518 int ret = 0, len=0;
2519 BOOL radio_enable = FALSE;
2520
2521 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2522
developer06a01d92022-09-07 16:32:39 +08002523 if (NULL == output_string)
2524 return RETURN_ERR;
2525
developer70490032022-09-13 15:45:20 +08002526 if (wifi_getRadioEnable(radioIndex, &radio_enable) == RETURN_ERR)
2527 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08002528
developer70490032022-09-13 15:45:20 +08002529 if (radio_enable != TRUE)
2530 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002531
developer70490032022-09-13 15:45:20 +08002532 snprintf(cmd, sizeof(cmd),"iw dev %s%d info | grep 'width' | cut -d ' ' -f6", AP_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08002533 ret = _syscmd(cmd, buf, sizeof(buf));
2534 len = strlen(buf);
2535 if((ret != 0) || (len == 0))
2536 {
2537 WIFI_ENTRY_EXIT_DEBUG("failed with Command %s %s:%d\n",cmd,__func__, __LINE__);
2538 return RETURN_ERR;
2539 }
2540
2541 buf[len-1] = '\0';
2542 snprintf(output_string, 64, "%sMHz", buf);
2543 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2544
2545#if 0
2546 //TODO: revisit below implementation
2547 char output_buf[8]={0};
2548 char bw_value[10];
2549 char config_file[MAX_BUF_SIZE] = {0};
2550
2551 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2552 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
2553 wifi_hostapdRead(config_file, "vht_oper_chwidth", output_buf, sizeof(output_buf));
2554 readBandWidth(radioIndex,bw_value);
2555
2556 if(strstr (output_buf,"0") != NULL )
2557 {
2558 strcpy(output_string,bw_value);
2559 }
2560 else if (strstr (output_buf,"1") != NULL)
2561 {
2562 strcpy(output_string,"80MHz");
2563 }
2564 else if (strstr (output_buf,"2") != NULL)
2565 {
2566 strcpy(output_string,"160MHz");
2567 }
2568 else if (strstr (output_buf,"3") != NULL)
2569 {
2570 strcpy(output_string,"80+80");
2571 }
2572 else
2573 {
2574 strcpy(output_string,"Auto");
2575 }
2576 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2577#endif
2578
2579 return RETURN_OK;
2580}
2581
2582//Set the Operating Channel Bandwidth.
developerf7a466e2022-09-29 11:55:56 +08002583INT wifi_setRadioOperatingChannelBandwidth(INT radioIndex, CHAR *bandwidth) //Tr181 //AP only
developer06a01d92022-09-07 16:32:39 +08002584{
developerf7a466e2022-09-29 11:55:56 +08002585 char config_file[128];
2586 char set_value[16];
2587 struct params params[2];
2588 int max_radio_num = 0;
2589
developer06a01d92022-09-07 16:32:39 +08002590 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002591
developerf7a466e2022-09-29 11:55:56 +08002592 if(NULL == bandwidth)
developer06a01d92022-09-07 16:32:39 +08002593 return RETURN_ERR;
2594
developerf7a466e2022-09-29 11:55:56 +08002595 if(strstr(bandwidth,"80+80") != NULL)
2596 strcpy(set_value, "3");
2597 else if(strstr(bandwidth,"160") != NULL)
2598 strcpy(set_value, "2");
2599 else if(strstr(bandwidth,"80") != NULL)
2600 strcpy(set_value, "1");
2601 else if(strstr(bandwidth,"20") != NULL || strstr(bandwidth,"40") != NULL)
2602 strcpy(set_value, "0");
developer06a01d92022-09-07 16:32:39 +08002603 else
2604 {
developerf7a466e2022-09-29 11:55:56 +08002605 fprintf(stderr, "%s: Invalid Bandwidth %s\n", __func__, bandwidth);
developer06a01d92022-09-07 16:32:39 +08002606 return RETURN_ERR;
2607 }
2608
developerf7a466e2022-09-29 11:55:56 +08002609 params[0].name = "vht_oper_chwidth";
2610 params[0].value = set_value;
2611 params[1].name = "he_oper_chwidth";
2612 params[1].value = set_value;
developer06a01d92022-09-07 16:32:39 +08002613
developerf7a466e2022-09-29 11:55:56 +08002614 wifi_getMaxRadioNumber(&max_radio_num);
2615 for(int i=0; i<=MAX_APS/max_radio_num; i++)
developer06a01d92022-09-07 16:32:39 +08002616 {
developerf7a466e2022-09-29 11:55:56 +08002617 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex+(max_radio_num*i));
2618 wifi_hostapdWrite(config_file, params, 2);
developer06a01d92022-09-07 16:32:39 +08002619 }
2620
2621 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2622 return RETURN_OK;
2623}
2624
2625//Getting current radio extension channel
2626INT wifi_halgetRadioExtChannel(CHAR *file,CHAR *Value)
2627{
2628 CHAR buf[150] = {0};
2629 CHAR cmd[150] = {0};
2630 sprintf(cmd,"%s%s%s","cat ",file," | grep -w ht_capab=");
2631 _syscmd(cmd, buf, sizeof(buf));
2632 if(NULL != strstr(buf,"HT40+"))
2633 strcpy(Value,"AboveControlChannel");
2634 else if(NULL != strstr(buf,"HT40-"))
2635 strcpy(Value,"BelowControlChannel");
2636 return RETURN_OK;
2637}
2638
2639//Get the secondary extension channel position, "AboveControlChannel" or "BelowControlChannel". (this is for 40MHz and 80MHz bandwith only)
2640//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.
2641INT wifi_getRadioExtChannel(INT radioIndex, CHAR *output_string) //Tr181
2642{
2643 if (NULL == output_string)
2644 return RETURN_ERR;
2645
2646 snprintf(output_string, 64, (radioIndex==0)?"":"BelowControlChannel");
2647#if 0
2648 CHAR Value[100] = {0};
2649 if (NULL == output_string)
2650 return RETURN_ERR;
2651 if(radioIndex == 0)
2652 strcpy(Value,"Auto"); //so far rpi(2G) supports upto 150Mbps (i,e 20MHZ)
2653 else if(radioIndex == 1)//so far rpi(5G) supports upto 300mbps (i,e 20MHz/40MHz)
2654 {
2655 wifi_getRadioOperatingChannelBandwidth(radioIndex,Value);
2656 if(strcmp(Value,"40MHz") == 0)
2657 wifi_halgetRadioExtChannel("/nvram/hostapd1.conf",Value);
2658 else
2659 strcpy(Value,"Auto");
2660 }
2661 strcpy(output_string,Value);
2662#endif
2663
2664 return RETURN_OK;
2665}
2666
2667//Set the extension channel.
2668INT wifi_setRadioExtChannel(INT radioIndex, CHAR *string) //Tr181 //AP only
2669{
2670 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2671 struct params params={'\0'};
2672 char config_file[MAX_BUF_SIZE] = {0};
2673 char ext_channel[127]={'\0'};
2674
2675 params.name = "ht_capab";
2676
2677 if(radioIndex == 0)
2678 {
2679 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002680 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002681 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002682 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002683 else
developer3cc0f2e2022-09-15 18:25:39 +08002684 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002685 }
2686 else if(radioIndex == 1)
2687 {
2688 if(NULL!= strstr(string,"Above"))
developer3cc0f2e2022-09-15 18:25:39 +08002689 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40+]");
developer06a01d92022-09-07 16:32:39 +08002690 else if(NULL!= strstr(string,"Below"))
developer3cc0f2e2022-09-15 18:25:39 +08002691 strcpy(ext_channel, HOSTAPD_HT_CAPAB "[HT40-]");
developer06a01d92022-09-07 16:32:39 +08002692 else
developer3cc0f2e2022-09-15 18:25:39 +08002693 strcpy(ext_channel, HOSTAPD_HT_CAPAB);
developer06a01d92022-09-07 16:32:39 +08002694 }
2695
2696 params.value = ext_channel;
2697 for(int i=0; i<=MAX_APS/NUMBER_OF_RADIOS; i++)
2698 {
2699 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex+(2*i));
2700 wifi_hostapdWrite(config_file, &params, 1);
2701 }
2702
2703 //Set to wifi config only. Wait for wifi reset or wifi_pushRadioChannel to apply.
2704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2705 return RETURN_OK;
2706}
2707
2708//Get the guard interval value. eg "400nsec" or "800nsec"
2709//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.
2710INT wifi_getRadioGuardInterval(INT radioIndex, CHAR *output_string) //Tr181
2711{
developer454b9462022-09-13 15:29:16 +08002712 wifi_guard_interval_t GI;
2713
2714 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2715
2716 if (output_string == NULL || wifi_getGuardInterval(radioIndex, &GI) == RETURN_ERR)
developer06a01d92022-09-07 16:32:39 +08002717 return RETURN_ERR;
developer454b9462022-09-13 15:29:16 +08002718
2719 if (GI == wifi_guard_interval_400)
2720 strcpy(output_string, "400nsec");
2721 else if (GI == wifi_guard_interval_800)
2722 strcpy(output_string, "800nsec");
2723 else if (GI == wifi_guard_interval_1600)
2724 strcpy(output_string, "1600nsec");
2725 else if (GI == wifi_guard_interval_3200)
2726 strcpy(output_string, "3200nsec");
2727 else
2728 strcpy(output_string, "auto");
developer06a01d92022-09-07 16:32:39 +08002729
developer454b9462022-09-13 15:29:16 +08002730 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002731 return RETURN_OK;
2732}
2733
2734//Set the guard interval value.
2735INT wifi_setRadioGuardInterval(INT radioIndex, CHAR *string) //Tr181
2736{
developer454b9462022-09-13 15:29:16 +08002737 wifi_guard_interval_t GI;
2738 int ret = 0;
2739
2740 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2741
2742 if (strcmp(string, "400nsec") == 0)
2743 GI = wifi_guard_interval_400;
2744 else if (strcmp(string , "800nsec") == 0 || strcmp(string, "auto") == 0)
2745 GI = wifi_guard_interval_800;
2746 else if (strcmp(string , "1600nsec") == 0)
2747 GI = wifi_guard_interval_1600;
2748 else if (strcmp(string , "3200nsec") == 0)
2749 GI = wifi_guard_interval_3200;
2750
2751 ret = wifi_setGuardInterval(radioIndex, GI);
2752
2753 if (ret == RETURN_ERR) {
2754 wifi_dbg_printf("%s: wifi_setGuardInterval return error\n", __func__);
2755 return RETURN_ERR;
2756 }
2757
2758 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2759 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002760}
2761
2762//Get the Modulation Coding Scheme index, eg: "-1", "1", "15"
2763INT wifi_getRadioMCS(INT radioIndex, INT *output_int) //Tr181
2764{
developerf49437e2022-09-29 19:58:21 +08002765 char buf[32]={0};
2766 char mcs_file[64] = {0};
2767 char cmd[64] = {0};
2768 int mode_bitmap = 0;
2769
2770 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2771 if(output_int == NULL)
developer06a01d92022-09-07 16:32:39 +08002772 return RETURN_ERR;
developerf49437e2022-09-29 19:58:21 +08002773 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2774
2775 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", mcs_file);
2776 _syscmd(cmd, buf, sizeof(buf));
2777 if (strlen(buf) > 0)
2778 *output_int = strtol(buf, NULL, 10);
2779 else {
2780 // output the max MCS for the current radio mode
2781 if (wifi_getRadioMode(radioIndex, buf, &mode_bitmap) == RETURN_ERR) {
2782 wifi_dbg_printf("%s: wifi_getradiomode return error.\n", __func__);
2783 return RETURN_ERR;
2784 }
2785 if (mode_bitmap & WIFI_MODE_AX) {
2786 *output_int = 11;
2787 } else if (mode_bitmap & WIFI_MODE_AC) {
2788 *output_int = 9;
2789 } else if (mode_bitmap & WIFI_MODE_N) {
2790 *output_int = 7;
2791 }
2792 }
2793 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002794
2795 return RETURN_OK;
2796}
2797
2798//Set the Modulation Coding Scheme index
2799INT wifi_setRadioMCS(INT radioIndex, INT MCS) //Tr181
2800{
developerf49437e2022-09-29 19:58:21 +08002801 // 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).
2802 char config_file[64] = {0};
2803 char set_value[16] = {0};
2804 char mcs_file[32] = {0};
2805 wifi_band band = band_invalid;
2806 struct params set_config = {0};
2807 FILE *f = NULL;
2808
2809 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2810
2811 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
2812
2813 if (MCS > 11 || MCS < 0) {
2814 fprintf(stderr, "%s: invalid MCS %d\n", __func__, MCS);
2815 return RETURN_ERR;
2816 }
2817
2818 if (MCS <= 7)
2819 strcpy(set_value, "0");
2820 else if (MCS <= 9)
2821 strcpy(set_value, "1");
2822 else
2823 strcpy(set_value, "2");
2824
2825 set_config.name = "he_basic_mcs_nss_set";
2826 set_config.value = set_value;
2827
2828 wifi_hostapdWrite(config_file, &set_config, 1);
2829 wifi_hostapdProcessUpdate(radioIndex, &set_config, 1);
2830
2831 // For pass tdk test, we need to record last MCS setting. No matter whether it is effective or not.
2832 snprintf(mcs_file, sizeof(mcs_file), "%s%d.txt", MCS_FILE, radioIndex);
2833 f = fopen(mcs_file, "w");
2834 if (f == NULL) {
2835 fprintf(stderr, "%s: fopen failed\n", __func__);
2836 return RETURN_ERR;
2837 }
2838 fprintf(f, "%d", MCS);
2839 fclose(f);
2840
2841 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2842 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002843}
2844
2845//Get supported Transmit Power list, eg : "0,25,50,75,100"
2846//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.
2847INT wifi_getRadioTransmitPowerSupported(INT radioIndex, CHAR *output_list) //Tr181
2848{
2849 if (NULL == output_list)
2850 return RETURN_ERR;
2851 snprintf(output_list, 64,"0,25,50,75,100");
2852 return RETURN_OK;
2853}
2854
developera5005b62022-09-13 15:43:35 +08002855//Get current Transmit Power in dBm units.
developer06a01d92022-09-07 16:32:39 +08002856//The transmite power level is in units of full power for this radio.
2857INT wifi_getRadioTransmitPower(INT radioIndex, ULONG *output_ulong) //RDKB
2858{
2859 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002860 char buf[16]={0};
2861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002862
developera5005b62022-09-13 15:43:35 +08002863 if(output_ulong == NULL)
developer06a01d92022-09-07 16:32:39 +08002864 return RETURN_ERR;
2865
developera5005b62022-09-13 15:43:35 +08002866 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 +08002867 _syscmd(cmd, buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002868
developera5005b62022-09-13 15:43:35 +08002869 *output_ulong = strtol(buf, NULL, 10);
2870
2871 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002872 return RETURN_OK;
2873}
2874
2875//Set Transmit Power
2876//The transmite power level is in units of full power for this radio.
2877INT wifi_setRadioTransmitPower(INT radioIndex, ULONG TransmitPower) //RDKB
2878{
developera5005b62022-09-13 15:43:35 +08002879 char *support;
developer06a01d92022-09-07 16:32:39 +08002880 char cmd[128]={0};
developera5005b62022-09-13 15:43:35 +08002881 char buf[128]={0};
2882 char txpower_str[64] = {0};
2883 int txpower = 0;
2884 int maximum_tx = 0;
2885
2886 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002887
developera5005b62022-09-13 15:43:35 +08002888 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 +08002889 _syscmd(cmd, buf, sizeof(buf));
developera5005b62022-09-13 15:43:35 +08002890 maximum_tx = strtol(buf, NULL, 10);
2891
2892 // Get the Tx power supported list and check that is the input in the list
2893 snprintf(txpower_str, sizeof(txpower_str), "%lu", TransmitPower);
2894 wifi_getRadioTransmitPowerSupported(radioIndex, buf);
2895 support = strtok(buf, ",");
2896 while(true)
2897 {
2898 if(support == NULL) { // input not in the list
2899 wifi_dbg_printf("Input value is invalid.\n");
2900 return RETURN_ERR;
2901 }
2902 if (strncmp(txpower_str, support, strlen(support)) == 0) {
2903 break;
2904 }
2905 support = strtok(NULL, ",");
2906 }
2907 txpower = TransmitPower*maximum_tx/100;
2908 snprintf(cmd, sizeof(cmd), "iw phy phy%d set txpower fixed %d00", radioIndex, txpower);
2909 _syscmd(cmd, buf, sizeof(buf));
2910 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002911
2912 return RETURN_OK;
2913}
2914
2915//get 80211h Supported. 80211h solves interference with satellites and radar using the same 5 GHz frequency band
2916INT wifi_getRadioIEEE80211hSupported(INT radioIndex, BOOL *Supported) //Tr181
2917{
2918 if (NULL == Supported)
2919 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002920 *Supported = TRUE;
developer06a01d92022-09-07 16:32:39 +08002921
2922 return RETURN_OK;
2923}
2924
2925//Get 80211h feature enable
2926INT wifi_getRadioIEEE80211hEnabled(INT radioIndex, BOOL *enable) //Tr181
2927{
developer3885fec2022-09-13 15:13:47 +08002928 char buf[64]={'\0'};
2929 char config_file[64] = {'\0'};
2930
2931 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2932 if(enable == NULL)
developer06a01d92022-09-07 16:32:39 +08002933 return RETURN_ERR;
developer3885fec2022-09-13 15:13:47 +08002934
2935 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2936 wifi_hostapdRead(config_file, "ieee80211h", buf, sizeof(buf));
developer06a01d92022-09-07 16:32:39 +08002937
developer3885fec2022-09-13 15:13:47 +08002938 if (strncmp(buf, "1", 1) == 0)
2939 *enable = TRUE;
2940 else
2941 *enable = FALSE;
2942
2943 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08002944 return RETURN_OK;
2945}
2946
2947//Set 80211h feature enable
2948INT wifi_setRadioIEEE80211hEnabled(INT radioIndex, BOOL enable) //Tr181
2949{
developer3885fec2022-09-13 15:13:47 +08002950 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
2951 struct params params={'\0'};
2952 char config_file[MAX_BUF_SIZE] = {0};
2953
2954 params.name = "ieee80211h";
2955
2956 if (enable) {
2957 params.value = "1";
2958 } else {
2959 params.value = "0";
2960 }
2961
2962 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
2963 wifi_hostapdWrite(config_file, &params, 1);
2964
2965 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
2966 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
2967 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08002968}
2969
2970//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.
2971INT wifi_getRadioCarrierSenseThresholdRange(INT radioIndex, INT *output) //P3
2972{
2973 if (NULL == output)
2974 return RETURN_ERR;
2975 *output=100;
2976
2977 return RETURN_OK;
2978}
2979
2980//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.
2981INT wifi_getRadioCarrierSenseThresholdInUse(INT radioIndex, INT *output) //P3
2982{
2983 if (NULL == output)
2984 return RETURN_ERR;
2985 *output = -99;
2986
2987 return RETURN_OK;
2988}
2989
2990INT wifi_setRadioCarrierSenseThresholdInUse(INT radioIndex, INT threshold) //P3
2991{
2992 return RETURN_ERR;
2993}
2994
2995
2996//Time interval between transmitting beacons (expressed in milliseconds). This parameter is based ondot11BeaconPeriod from [802.11-2012].
2997INT wifi_getRadioBeaconPeriod(INT radioIndex, UINT *output)
2998{
developer5f222492022-09-13 15:21:52 +08002999 char cmd[MAX_BUF_SIZE]={'\0'};
3000 char buf[MAX_CMD_SIZE]={'\0'};
3001
3002 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3003 if(output == NULL)
developer06a01d92022-09-07 16:32:39 +08003004 return RETURN_ERR;
developer5f222492022-09-13 15:21:52 +08003005
3006 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep beacon_int | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, radioIndex);
3007 _syscmd(cmd, buf, sizeof(buf));
3008 *output = atoi(buf);
developer06a01d92022-09-07 16:32:39 +08003009
developer5f222492022-09-13 15:21:52 +08003010 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003011 return RETURN_OK;
3012}
3013
3014INT wifi_setRadioBeaconPeriod(INT radioIndex, UINT BeaconPeriod)
3015{
developer5f222492022-09-13 15:21:52 +08003016 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3017 struct params params={'\0'};
3018 char buf[MAX_BUF_SIZE] = {'\0'};
3019 char config_file[MAX_BUF_SIZE] = {'\0'};
3020
3021 params.name = "beacon_int";
3022 snprintf(buf, sizeof(buf), "%u", BeaconPeriod);
3023 params.value = buf;
3024
3025 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3026 wifi_hostapdWrite(config_file, &params, 1);
3027
3028 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
3029 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3030 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003031}
3032
3033//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.
3034INT wifi_getRadioBasicDataTransmitRates(INT radioIndex, CHAR *output)
3035{
developer06a01d92022-09-07 16:32:39 +08003036 //TODO: need to revisit below implementation
3037 char *temp;
developere9d0abd2022-09-13 15:40:57 +08003038 char temp_output[128] = {0};
3039 char temp_TransmitRates[64] = {0};
3040 char config_file[64] = {0};
developer06a01d92022-09-07 16:32:39 +08003041
3042 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3043 if (NULL == output)
3044 return RETURN_ERR;
3045 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
developere9d0abd2022-09-13 15:40:57 +08003046 wifi_hostapdRead(config_file,"basic_rates",temp_TransmitRates,64);
3047
3048 if (strlen(temp_TransmitRates) == 0) { // config not set, use supported rate
3049 wifi_getRadioSupportedDataTransmitRates(radioIndex, output);
3050 } else {
3051 temp = strtok(temp_TransmitRates," ");
3052 while(temp!=NULL)
developer06a01d92022-09-07 16:32:39 +08003053 {
developere9d0abd2022-09-13 15:40:57 +08003054 // Convert 100 kbps to Mbps
3055 temp[strlen(temp)-1]=0;
3056 if((temp[0]=='5') && (temp[1]=='\0'))
3057 {
3058 temp="5.5";
3059 }
3060 strcat(temp_output,temp);
3061 temp = strtok(NULL," ");
3062 if(temp!=NULL)
3063 {
3064 strcat(temp_output,",");
3065 }
developer06a01d92022-09-07 16:32:39 +08003066 }
developere9d0abd2022-09-13 15:40:57 +08003067 strcpy(output,temp_output);
developer06a01d92022-09-07 16:32:39 +08003068 }
developer06a01d92022-09-07 16:32:39 +08003069 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08003070 return RETURN_OK;
3071}
3072
3073INT wifi_setRadioBasicDataTransmitRates(INT radioIndex, CHAR *TransmitRates)
3074{
3075 char *temp;
3076 char temp1[128];
3077 char temp_output[128];
3078 char temp_TransmitRates[128];
3079 char set[128];
3080 char sub_set[128];
3081 int set_count=0,subset_count=0;
3082 int set_index=0,subset_index=0;
3083 char *token;
3084 int flag=0, i=0;
3085 struct params params={'\0'};
3086 char config_file[MAX_BUF_SIZE] = {0};
3087
3088 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3089 if(NULL == TransmitRates)
3090 return RETURN_ERR;
3091 strcpy(sub_set,TransmitRates);
3092
3093 //Allow only supported Data transmit rate to be set
3094 wifi_getRadioSupportedDataTransmitRates(radioIndex,set);
3095 token = strtok(sub_set,",");
3096 while( token != NULL ) /* split the basic rate to be set, by comma */
3097 {
3098 sub_set[subset_count]=atoi(token);
3099 subset_count++;
3100 token=strtok(NULL,",");
3101 }
3102 token=strtok(set,",");
3103 while(token!=NULL) /* split the supported rate by comma */
3104 {
3105 set[set_count]=atoi(token);
3106 set_count++;
3107 token=strtok(NULL,",");
3108 }
3109 for(subset_index=0;subset_index < subset_count;subset_index++) /* Compare each element of subset and set */
3110 {
3111 for(set_index=0;set_index < set_count;set_index++)
3112 {
3113 flag=0;
3114 if(sub_set[subset_index]==set[set_index])
3115 break;
3116 else
3117 flag=1; /* No match found */
3118 }
3119 if(flag==1)
3120 return RETURN_ERR; //If value not found return Error
3121 }
3122 strcpy(temp_TransmitRates,TransmitRates);
3123
3124 for(i=0;i<strlen(temp_TransmitRates);i++)
3125 {
3126 //if (((temp_TransmitRates[i]>=48) && (temp_TransmitRates[i]<=57)) | (temp_TransmitRates[i]==32))
3127 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.') | (temp_TransmitRates[i]==','))
3128 {
3129 continue;
3130 }
3131 else
3132 {
3133 return RETURN_ERR;
3134 }
3135 }
3136 strcpy(temp_output,"");
3137 temp = strtok(temp_TransmitRates,",");
3138 while(temp!=NULL)
3139 {
3140 strcpy(temp1,temp);
3141 if(radioIndex==1)
3142 {
3143 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
3144 {
3145 return RETURN_ERR;
3146 }
3147 }
3148
3149 if(strcmp(temp,"5.5")==0)
3150 {
3151 strcpy(temp1,"55");
3152 }
3153 else
3154 {
3155 strcat(temp1,"0");
3156 }
3157 strcat(temp_output,temp1);
3158 temp = strtok(NULL,",");
3159 if(temp!=NULL)
3160 {
3161 strcat(temp_output," ");
3162 }
3163 }
3164 strcpy(TransmitRates,temp_output);
3165
3166 params.name= "basic_rates";
3167 params.value =TransmitRates;
3168
3169 wifi_dbg_printf("\n%s:",__func__);
3170 wifi_dbg_printf("\nparams.value=%s\n",params.value);
3171 wifi_dbg_printf("\n******************Transmit rates=%s\n",TransmitRates);
3172 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
3173 wifi_hostapdWrite(config_file,&params,1);
3174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3175 return RETURN_OK;
3176}
3177
3178//passing the hostapd configuration file and get the virtual interface of xfinity(2g)
3179INT GetInterfaceName_virtualInterfaceName_2G(char interface_name[50])
3180{
3181 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3182 FILE *fp = NULL;
3183 char path[256] = {0}, output_string[256] = {0};
3184 int count = 0;
3185 char *interface = NULL;
3186
3187 fp = popen("cat /nvram/hostapd0.conf | grep -w bss", "r");
3188 if (fp == NULL)
3189 {
3190 printf("Failed to run command in Function %s\n", __FUNCTION__);
3191 return RETURN_ERR;
3192 }
3193 if (fgets(path, sizeof(path) - 1, fp) != NULL)
3194 {
3195 interface = strchr(path, '=');
3196
3197 if (interface != NULL)
3198 {
3199 strcpy(output_string, interface + 1);
3200 for (count = 0; output_string[count] != '\n' || output_string[count] != '\0'; count++)
3201 interface_name[count] = output_string[count];
3202
3203 interface_name[count] = '\0';
3204 }
3205 }
3206 pclose(fp);
3207 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3208 return RETURN_OK;
3209}
3210
3211INT wifi_halGetIfStatsNull(wifi_radioTrafficStats2_t *output_struct)
3212{
3213 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3214 output_struct->radio_BytesSent = 0;
3215 output_struct->radio_BytesReceived = 0;
3216 output_struct->radio_PacketsSent = 0;
3217 output_struct->radio_PacketsReceived = 0;
3218 output_struct->radio_ErrorsSent = 0;
3219 output_struct->radio_ErrorsReceived = 0;
3220 output_struct->radio_DiscardPacketsSent = 0;
3221 output_struct->radio_DiscardPacketsReceived = 0;
3222 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3223 return RETURN_OK;
3224}
3225
3226
3227INT wifi_halGetIfStats(char *ifname, wifi_radioTrafficStats2_t *pStats)
3228{
3229 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3230 CHAR buf[MAX_CMD_SIZE] = {0};
3231 CHAR Value[MAX_BUF_SIZE] = {0};
3232 FILE *fp = NULL;
3233
3234 if (ifname == NULL || strlen(ifname) <= 1)
3235 return RETURN_OK;
3236
3237 snprintf(buf, sizeof(buf), "ifconfig -a %s > /tmp/Radio_Stats.txt", ifname);
3238 system(buf);
3239
3240 fp = fopen("/tmp/Radio_Stats.txt", "r");
3241 if(fp == NULL)
3242 {
3243 printf("/tmp/Radio_Stats.txt not exists \n");
3244 return RETURN_ERR;
3245 }
3246 fclose(fp);
3247
3248 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3249 File_Reading(buf, Value);
3250 pStats->radio_PacketsReceived = strtoul(Value, NULL, 10);
3251
3252 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3253 File_Reading(buf, Value);
3254 pStats->radio_PacketsSent = strtoul(Value, NULL, 10);
3255
3256 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3257 File_Reading(buf, Value);
3258 pStats->radio_BytesReceived = strtoul(Value, NULL, 10);
3259
3260 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3261 File_Reading(buf, Value);
3262 pStats->radio_BytesSent = strtoul(Value, NULL, 10);
3263
3264 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3265 File_Reading(buf, Value);
3266 pStats->radio_ErrorsReceived = strtoul(Value, NULL, 10);
3267
3268 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3269 File_Reading(buf, Value);
3270 pStats->radio_ErrorsSent = strtoul(Value, NULL, 10);
3271
3272 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3273 File_Reading(buf, Value);
3274 pStats->radio_DiscardPacketsReceived = strtoul(Value, NULL, 10);
3275
3276 sprintf(buf, "cat /tmp/Radio_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
3277 File_Reading(buf, Value);
3278 pStats->radio_DiscardPacketsSent = strtoul(Value, NULL, 10);
3279
3280 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3281 return RETURN_OK;
3282}
3283
3284INT GetIfacestatus(CHAR *interface_name, CHAR *status)
3285{
3286 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3287 CHAR buf[MAX_CMD_SIZE] = {0};
3288 FILE *fp = NULL;
3289 INT count = 0;
3290
3291 if (interface_name != NULL && (strlen(interface_name) > 1) && status != NULL)
3292 {
3293 sprintf(buf, "%s%s%s%s%s", "ifconfig -a ", interface_name, " | grep ", interface_name, " | wc -l");
3294 File_Reading(buf, status);
3295 }
3296 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3297 return RETURN_OK;
3298}
3299
3300//Get detail radio traffic static info
3301INT wifi_getRadioTrafficStats2(INT radioIndex, wifi_radioTrafficStats2_t *output_struct) //Tr181
3302{
3303
3304#if 0
3305 //ifconfig radio_x
3306 output_struct->radio_BytesSent=250; //The total number of bytes transmitted out of the interface, including framing characters.
3307 output_struct->radio_BytesReceived=168; //The total number of bytes received on the interface, including framing characters.
3308 output_struct->radio_PacketsSent=25; //The total number of packets transmitted out of the interface.
3309 output_struct->radio_PacketsReceived=20; //The total number of packets received on the interface.
3310
3311 output_struct->radio_ErrorsSent=0; //The total number of outbound packets that could not be transmitted because of errors.
3312 output_struct->radio_ErrorsReceived=0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
3313 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.
3314 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.
3315
3316 output_struct->radio_PLCPErrorCount=0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3317 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].
3318 output_struct->radio_InvalidMACCount=0; //The number of packets that were received with a detected invalid MAC header error.
3319 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.
3320 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
3321 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
3322 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
3323 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
3324 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
3325
3326 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
3327 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
3328 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
3329 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.
3330
3331 return RETURN_OK;
3332#endif
3333
developera91d99f2022-09-29 15:59:10 +08003334 CHAR interface_name[64] = {0};
3335 CHAR config_path[64] = {0};
3336 BOOL iface_status = FALSE;
3337 wifi_radioTrafficStats2_t radioTrafficStats = {0};
developer06a01d92022-09-07 16:32:39 +08003338
3339 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
3340 if (NULL == output_struct)
3341 return RETURN_ERR;
3342
developera91d99f2022-09-29 15:59:10 +08003343 sprintf(config_path, "%s%d.conf", CONFIG_PREFIX, radioIndex);
3344 GetInterfaceName(interface_name, config_path);
developer06a01d92022-09-07 16:32:39 +08003345
developera91d99f2022-09-29 15:59:10 +08003346 wifi_getApEnable(radioIndex, &iface_status);
developer06a01d92022-09-07 16:32:39 +08003347
developera91d99f2022-09-29 15:59:10 +08003348 if (iface_status == TRUE)
3349 wifi_halGetIfStats(interface_name, &radioTrafficStats);
3350 else
3351 wifi_halGetIfStatsNull(&radioTrafficStats); // just set some transmission statistic value to 0
developer06a01d92022-09-07 16:32:39 +08003352
developera91d99f2022-09-29 15:59:10 +08003353 output_struct->radio_BytesSent = radioTrafficStats.radio_BytesSent;
3354 output_struct->radio_BytesReceived = radioTrafficStats.radio_BytesReceived;
3355 output_struct->radio_PacketsSent = radioTrafficStats.radio_PacketsSent;
3356 output_struct->radio_PacketsReceived = radioTrafficStats.radio_PacketsReceived;
3357 output_struct->radio_ErrorsSent = radioTrafficStats.radio_ErrorsSent;
3358 output_struct->radio_ErrorsReceived = radioTrafficStats.radio_ErrorsReceived;
3359 output_struct->radio_DiscardPacketsSent = radioTrafficStats.radio_DiscardPacketsSent;
3360 output_struct->radio_DiscardPacketsReceived = radioTrafficStats.radio_DiscardPacketsReceived;
developer06a01d92022-09-07 16:32:39 +08003361
3362 output_struct->radio_PLCPErrorCount = 0; //The number of packets that were received with a detected Physical Layer Convergence Protocol (PLCP) header error.
3363 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].
3364 output_struct->radio_InvalidMACCount = 0; //The number of packets that were received with a detected invalid MAC header error.
3365 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.
3366 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
3367 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
3368 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
3369 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
3370 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
3371
3372 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
3373 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
3374 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
3375 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.
3376
3377 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
3378
3379 return RETURN_OK;
3380}
3381
3382//Set radio traffic static Measureing rules
3383INT wifi_setRadioTrafficStatsMeasure(INT radioIndex, wifi_radioTrafficStatsMeasure_t *input_struct) //Tr181
3384{
3385 //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
3386 // Else, save the MeasuringRate and MeasuringInterval for future usage
3387
3388 return RETURN_OK;
3389}
3390
3391//To start or stop RadioTrafficStats
3392INT wifi_setRadioTrafficStatsRadioStatisticsEnable(INT radioIndex, BOOL enable)
3393{
3394 //zqiu: If the RadioTrafficStats process running
3395 // if(enable)
3396 // return RETURN_OK.
3397 // else
3398 // Stop RadioTrafficStats process
3399 // Else
3400 // if(enable)
3401 // Start RadioTrafficStats process with MeasuringRate and MeasuringInterval, and reset "StatisticsStartTime" to the current time, Units in Seconds
3402 // else
3403 // return RETURN_OK.
3404
3405 return RETURN_OK;
3406}
3407
3408//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
3409INT wifi_getRadioStatsReceivedSignalLevel(INT radioIndex, INT signalIndex, INT *SignalLevel) //Tr181
3410{
3411 //zqiu: Please ignor signalIndex.
3412 if (NULL == SignalLevel)
3413 return RETURN_ERR;
3414 *SignalLevel=(radioIndex==0)?-19:-19;
3415
3416 return RETURN_OK;
3417}
3418
3419//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3420INT wifi_applyRadioSettings(INT radioIndex)
3421{
3422 return RETURN_OK;
3423}
3424
3425//Get the radio index assocated with this SSID entry
3426INT wifi_getSSIDRadioIndex(INT ssidIndex, INT *radioIndex)
3427{
3428 if (NULL == radioIndex)
3429 return RETURN_ERR;
3430 *radioIndex=ssidIndex%2;
3431
3432 return RETURN_OK;
3433}
3434
3435//Device.WiFi.SSID.{i}.Enable
3436//Get SSID enable configuration parameters (not the SSID enable status)
3437INT wifi_getSSIDEnable(INT ssidIndex, BOOL *output_bool) //Tr181
3438{
3439 if (NULL == output_bool)
3440 return RETURN_ERR;
3441
3442 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3443 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3444 return wifi_getApEnable(ssidIndex, output_bool);
3445}
3446
3447//Device.WiFi.SSID.{i}.Enable
3448//Set SSID enable configuration parameters
3449INT wifi_setSSIDEnable(INT ssidIndex, BOOL enable) //Tr181
3450{
3451 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3452 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3453 return wifi_setApEnable(ssidIndex, enable);
3454}
3455
3456//Device.WiFi.SSID.{i}.Status
3457//Get the SSID enable status
3458INT wifi_getSSIDStatus(INT ssidIndex, CHAR *output_string) //Tr181
3459{
3460 char cmd[MAX_CMD_SIZE]={0};
3461 char buf[MAX_BUF_SIZE]={0};
3462 BOOL output_bool;
3463
3464 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3465 if (NULL == output_string)
3466 return RETURN_ERR;
3467 //For this target, mapping SSID Index 13 & 14 to 2 & 3 respectively.
3468 if(ssidIndex==13 || ssidIndex==14) ssidIndex -= 11;
3469
3470 wifi_getApEnable(ssidIndex,&output_bool);
3471 snprintf(output_string, 32, output_bool==1?"Enabled":"Disabled");
3472
3473 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3474 return RETURN_OK;
3475}
3476
3477// Outputs a 32 byte or less string indicating the SSID name. Sring buffer must be preallocated by the caller.
3478INT wifi_getSSIDName(INT apIndex, CHAR *output)
3479{
3480 char config_file[MAX_BUF_SIZE] = {0};
3481
3482 if (NULL == output)
3483 return RETURN_ERR;
3484
3485 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3486 wifi_hostapdRead(config_file,"ssid",output,32);
3487
3488 wifi_dbg_printf("\n[%s]: SSID Name is : %s",__func__,output);
3489 return RETURN_OK;
3490}
3491
3492// Set a max 32 byte string and sets an internal variable to the SSID name
3493INT wifi_setSSIDName(INT apIndex, CHAR *ssid_string)
3494{
3495 char str[MAX_BUF_SIZE]={'\0'};
3496 char cmd[MAX_CMD_SIZE]={'\0'};
3497 struct params params;
3498 char config_file[MAX_BUF_SIZE] = {0};
3499
3500 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3501 if(NULL == ssid_string || strlen(ssid_string) >= 32 || strlen(ssid_string) == 0 )
3502 return RETURN_ERR;
3503
3504 params.name = "ssid";
3505 params.value = ssid_string;
3506 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
3507 wifi_hostapdWrite(config_file, &params, 1);
3508 wifi_hostapdProcessUpdate(apIndex, &params, 1);
3509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3510
3511 return RETURN_OK;
3512}
3513
3514//Get the BSSID
3515INT wifi_getBaseBSSID(INT ssidIndex, CHAR *output_string) //RDKB
3516{
3517 char cmd[MAX_CMD_SIZE]="";
3518
3519 if (NULL == output_string)
3520 return RETURN_ERR;
3521
3522 if(ssidIndex >= 0 && ssidIndex < MAX_APS)
3523 {
3524 snprintf(cmd, sizeof(cmd), "iw dev %s%d info |grep addr | awk '{printf $2}'", AP_PREFIX, ssidIndex);
3525 _syscmd(cmd, output_string, 64);
3526 return RETURN_OK;
3527 }
3528 strncpy(output_string, "\0", 1);
3529
3530 return RETURN_ERR;
3531}
3532
3533//Get the MAC address associated with this Wifi SSID
3534INT wifi_getSSIDMACAddress(INT ssidIndex, CHAR *output_string) //Tr181
3535{
3536 wifi_getBaseBSSID(ssidIndex,output_string);
3537 return RETURN_OK;
3538}
3539
3540//Get the basic SSID traffic static info
3541//Apply SSID and AP (in the case of Acess Point devices) to the hardware
3542//Not all implementations may need this function. If not needed for a particular implementation simply return no-error (0)
3543INT wifi_applySSIDSettings(INT ssidIndex)
3544{
3545 BOOL status = false;
3546 char cmd[MAX_CMD_SIZE] = {0};
3547 char buf[MAX_CMD_SIZE] = {0};
3548 int apIndex, ret;
3549 int radioIndex = ssidIndex % NUMBER_OF_RADIOS;
3550
3551 wifi_getApEnable(ssidIndex,&status);
3552 // Do not apply when ssid index is disabled
3553 if (status == false)
3554 return RETURN_OK;
3555
3556 /* Doing full remove and add for ssid Index
3557 * Not all hostapd options are supported with reload
3558 * for example macaddr_acl
3559 */
3560 if(wifi_setApEnable(ssidIndex,false) != RETURN_OK)
3561 return RETURN_ERR;
3562
3563 ret = wifi_setApEnable(ssidIndex,true);
3564
3565 /* Workaround for hostapd issue with multiple bss definitions
3566 * when first created interface will be removed
3567 * then all vaps other vaps on same phy are removed
3568 * after calling setApEnable to false readd all enabled vaps */
3569 for(int i=0; i < MAX_APS/NUMBER_OF_RADIOS; i++) {
3570 apIndex = 2*i+radioIndex;
3571 snprintf(cmd, sizeof(cmd), "cat %s | grep %s%d | cut -d'=' -f2", VAP_STATUS_FILE, AP_PREFIX, apIndex);
3572 _syscmd(cmd, buf, sizeof(buf));
3573 if(*buf == '1')
3574 wifi_setApEnable(apIndex, true);
3575 }
3576
3577 return ret;
3578}
3579
developera3c68b92022-09-13 15:27:29 +08003580struct channels_noise {
3581 int channel;
3582 int noise;
3583};
3584
3585// Return noise array for each channel
3586int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
3587{
3588 FILE *f = NULL;
3589 char cmd[128] = {0};
developer5550e242022-09-30 09:59:32 +08003590 char line[256] = {0};
developera3c68b92022-09-13 15:27:29 +08003591 size_t len = 0;
3592 ssize_t read = 0;
3593 int tmp = 0, arr_index = -1;
3594
3595 sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
3596
3597 if ((f = popen(cmd, "r")) == NULL) {
3598 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3599 return RETURN_ERR;
3600 }
developer5550e242022-09-30 09:59:32 +08003601
3602 while(fgets(line, sizeof(line), f) != NULL) {
3603 if(arr_index < channels_num){
3604 sscanf(line, "%d", &tmp);
3605 if (tmp > 0) { // channel frequency, the first line must be frequency
3606 arr_index++;
3607 channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
3608 } else { // noise
3609 channels_noise_arr[arr_index].noise = tmp;
3610 }
3611 }else{
3612 break;
developera3c68b92022-09-13 15:27:29 +08003613 }
3614 }
developera3c68b92022-09-13 15:27:29 +08003615 pclose(f);
3616 return RETURN_OK;
3617}
3618
developer06a01d92022-09-07 16:32:39 +08003619//Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
3620//HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
3621INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
3622{
developera3c68b92022-09-13 15:27:29 +08003623 int index = -1;
3624 wifi_neighbor_ap2_t *scan_array = NULL;
3625 char cmd[256]={0};
3626 char buf[128]={0};
3627 char file_name[32] = {0};
3628 char filter_SSID[32] = {0};
developer615510b2022-09-27 10:14:35 +08003629 char line[256] = {0};
3630 char *ret = NULL;
developera3c68b92022-09-13 15:27:29 +08003631 int freq=0;
3632 FILE *f = NULL;
3633 size_t len=0;
developera3c68b92022-09-13 15:27:29 +08003634 int channels_num = 0;
3635 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08003636 int get_noise_ret = RETURN_ERR;
developera3c68b92022-09-13 15:27:29 +08003637 bool filter_enable = false;
3638 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08003639
developer615510b2022-09-27 10:14:35 +08003640 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003641
3642 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
3643 f = fopen(file_name, "r");
3644 if (f != NULL) {
3645 fgets(filter_SSID, sizeof(file_name), f);
3646 if (strlen(filter_SSID) != 0)
3647 filter_enable = true;
3648 fclose(f);
3649 }
3650
3651 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
developer06a01d92022-09-07 16:32:39 +08003652 _syscmd(cmd, buf, sizeof(buf));
developer615510b2022-09-27 10:14:35 +08003653 channels_num = strtol(buf, NULL, 10);
developer06a01d92022-09-07 16:32:39 +08003654
developer5550e242022-09-30 09:59:32 +08003655
developer06a01d92022-09-07 16:32:39 +08003656
developera3c68b92022-09-13 15:27:29 +08003657 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 +08003658 // 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 +08003659 fprintf(stderr, "cmd: %s\n", cmd);
3660 if ((f = popen(cmd, "r")) == NULL) {
3661 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
3662 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08003663 }
developer5550e242022-09-30 09:59:32 +08003664
3665 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
3666 get_noise_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
3667
developer615510b2022-09-27 10:14:35 +08003668 ret = fgets(line, sizeof(line), f);
3669 while (ret != NULL) {
developera3c68b92022-09-13 15:27:29 +08003670 if(strstr(line, "BSS") != NULL) { // new neighbor info
3671 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
3672 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
3673 // 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 +08003674
developera3c68b92022-09-13 15:27:29 +08003675 if (!filter_BSS) {
3676 index++;
3677 wifi_neighbor_ap2_t *tmp;
3678 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
3679 if (tmp == NULL) { // no more memory to use
3680 index--;
3681 wifi_dbg_printf("%s: realloc failed\n", __func__);
3682 break;
3683 }
3684 scan_array = tmp;
3685 }
3686 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3687
3688 filter_BSS = false;
3689 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
3690 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
3691 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
3692 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
3693 } else if (strstr(line, "freq") != NULL) {
3694 sscanf(line," freq: %d", &freq);
3695 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
3696
3697 if (freq >= 2412 && freq <= 2484) {
3698 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
3699 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
3700 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
3701 }
3702 else if (freq >= 5160 && freq <= 5805) {
3703 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
3704 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
3705 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
3706 }
3707
3708 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08003709 if (get_noise_ret == RETURN_OK) {
developera3c68b92022-09-13 15:27:29 +08003710 for (int i = 0; i < channels_num; i++) {
3711 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
3712 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
3713 break;
3714 }
3715 }
3716 }
3717 } else if (strstr(line, "beacon interval") != NULL) {
3718 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
3719 } else if (strstr(line, "signal") != NULL) {
3720 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
3721 } else if (strstr(line,"SSID") != NULL) {
3722 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
3723 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
3724 filter_BSS = true;
3725 }
3726 } else if (strstr(line, "Supported rates") != NULL) {
3727 char SRate[80] = {0}, *tmp = NULL;
3728 memset(buf, 0, sizeof(buf));
3729 strcpy(SRate, line);
3730 tmp = strtok(SRate, ":");
3731 tmp = strtok(NULL, ":");
3732 strcpy(buf, tmp);
3733 memset(SRate, 0, sizeof(SRate));
3734
3735 tmp = strtok(buf, " \n");
3736 while (tmp != NULL) {
3737 strcat(SRate, tmp);
3738 if (SRate[strlen(SRate) - 1] == '*') {
3739 SRate[strlen(SRate) - 1] = '\0';
3740 }
3741 strcat(SRate, ",");
3742
3743 tmp = strtok(NULL, " \n");
3744 }
3745 SRate[strlen(SRate) - 1] = '\0';
3746 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
3747 } else if (strstr(line, "DTIM") != NULL) {
3748 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
3749 } else if (strstr(line, "VHT capabilities") != NULL) {
3750 strcat(scan_array[index].ap_SupportedStandards, ",ac");
3751 strcpy(scan_array[index].ap_OperatingStandards, "ac");
3752 } else if (strstr(line, "HT capabilities") != NULL) {
3753 strcat(scan_array[index].ap_SupportedStandards, ",n");
3754 strcpy(scan_array[index].ap_OperatingStandards, "n");
3755 } else if (strstr(line, "VHT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003756 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003757 sscanf(line," * channel width: %d", &vht_channel_width);
3758 if(vht_channel_width == 1) {
3759 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
3760 } else {
3761 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
3762 }
3763 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3764 continue;
3765 } else if (strstr(line, "HT operation") != NULL) {
developer615510b2022-09-27 10:14:35 +08003766 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003767 sscanf(line," * secondary channel offset: %s", &buf);
3768 if (!strcmp(buf, "above")) {
3769 //40Mhz +
3770 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
3771 }
3772 else if (!strcmp(buf, "below")) {
3773 //40Mhz -
3774 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
3775 } else {
3776 //20Mhz
3777 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
3778 }
3779 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
3780 continue;
3781 } else if (strstr(line, "HE capabilities") != NULL) {
developer615510b2022-09-27 10:14:35 +08003782 strcat(scan_array[index].ap_SupportedStandards, ",ax");
3783 strcpy(scan_array[index].ap_OperatingStandards, "ax");
3784 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003785 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
3786 if (strstr(line, "HE40/2.4GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003787 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
developera3c68b92022-09-13 15:27:29 +08003788 else
developer615510b2022-09-27 10:14:35 +08003789 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
developera3c68b92022-09-13 15:27:29 +08003790 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
developer615510b2022-09-27 10:14:35 +08003791 if (strstr(line, "HE80/5GHz") != NULL) {
3792 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
3793 ret = fgets(line, sizeof(line), f);
3794 } else
3795 continue;
developera3c68b92022-09-13 15:27:29 +08003796 if (strstr(line, "HE160/5GHz") != NULL)
developer615510b2022-09-27 10:14:35 +08003797 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developera3c68b92022-09-13 15:27:29 +08003798 }
developer615510b2022-09-27 10:14:35 +08003799 continue;
developera3c68b92022-09-13 15:27:29 +08003800 } else if (strstr(line, "WPA") != NULL) {
3801 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
3802 } else if (strstr(line, "RSN") != NULL) {
3803 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
3804 } else if (strstr(line, "Group cipher") != NULL) {
3805 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
3806 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
3807 strcpy(scan_array[index].ap_EncryptionMode, "AES");
3808 }
3809 }
developer615510b2022-09-27 10:14:35 +08003810 ret = fgets(line, sizeof(line), f);
developera3c68b92022-09-13 15:27:29 +08003811 }
3812
3813 if (!filter_BSS) {
3814 *output_array_size = index + 1;
3815 } else {
3816 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
3817 *output_array_size = index;
3818 }
3819 *neighbor_ap_array = scan_array;
developera3c68b92022-09-13 15:27:29 +08003820 pclose(f);
developer5550e242022-09-30 09:59:32 +08003821 free(channels_noise_arr);
developer06a01d92022-09-07 16:32:39 +08003822 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developera3c68b92022-09-13 15:27:29 +08003823 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08003824}
3825
3826//>> Deprecated: used for old RDKB code.
3827INT wifi_getRadioWifiTrafficStats(INT radioIndex, wifi_radioTrafficStats_t *output_struct)
3828{
3829 INT status = RETURN_ERR;
3830
3831 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3832 output_struct->wifi_PLCPErrorCount = 0;
3833 output_struct->wifi_FCSErrorCount = 0;
3834 output_struct->wifi_InvalidMACCount = 0;
3835 output_struct->wifi_PacketsOtherReceived = 0;
3836 output_struct->wifi_Noise = 0;
3837 status = RETURN_OK;
3838 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3839 return status;
3840}
3841
3842INT wifi_getBasicTrafficStats(INT apIndex, wifi_basicTrafficStats_t *output_struct)
3843{
3844 char cmd[128];
3845 char buf[1280];
3846 char *pos = NULL;
3847
3848 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3849 if (NULL == output_struct)
3850 return RETURN_ERR;
3851
3852 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3853
3854 snprintf(cmd, sizeof(cmd), "ifconfig %s%d", AP_PREFIX, apIndex);
3855 _syscmd(cmd, buf, sizeof(buf));
3856
3857 pos = buf;
3858 if ((pos = strstr(pos, "RX packets:")) == NULL)
3859 return RETURN_ERR;
3860 output_struct->wifi_PacketsReceived = atoi(pos+strlen("RX packets:"));
3861
3862 if ((pos = strstr(pos, "TX packets:")) == NULL)
3863 return RETURN_ERR;
3864 output_struct->wifi_PacketsSent = atoi(pos+strlen("TX packets:"));
3865
3866 if ((pos = strstr(pos, "RX bytes:")) == NULL)
3867 return RETURN_ERR;
3868 output_struct->wifi_BytesReceived = atoi(pos+strlen("RX bytes:"));
3869
3870 if ((pos = strstr(pos, "TX bytes:")) == NULL)
3871 return RETURN_ERR;
3872 output_struct->wifi_BytesSent = atoi(pos+strlen("TX bytes:"));
3873
3874 sprintf(cmd, "wlanconfig %s%d list sta | grep -v HTCAP | wc -l", AP_PREFIX, apIndex);
3875 _syscmd(cmd, buf, sizeof(buf));
3876 sscanf(buf, "%lu", &output_struct->wifi_Associations);
3877
3878#if 0
3879 //TODO: need to revisit below implementation
3880 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3881 char interface_name[MAX_BUF_SIZE] = {0};
3882 char interface_status[MAX_BUF_SIZE] = {0};
3883 char Value[MAX_BUF_SIZE] = {0};
3884 char buf[MAX_CMD_SIZE] = {0};
3885 char cmd[MAX_CMD_SIZE] = {0};
3886 FILE *fp = NULL;
3887
3888 if (NULL == output_struct) {
3889 return RETURN_ERR;
3890 }
3891
3892 memset(output_struct, 0, sizeof(wifi_basicTrafficStats_t));
3893
3894 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3895 {
3896 if(apIndex == 0) //private_wifi for 2.4G
3897 {
3898 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3899 }
3900 else if(apIndex == 1) //private_wifi for 5G
3901 {
3902 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3903 }
3904 else if(apIndex == 4) //public_wifi for 2.4G
3905 {
3906 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3907 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3908 {
3909 return RETURN_ERR;
3910 }
3911 if(buf[0] == '#')//tp-link
3912 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3913 else//tenda
3914 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3915 }
3916 else if(apIndex == 5) //public_wifi for 5G
3917 {
3918 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
3919 }
3920
3921 GetIfacestatus(interface_name, interface_status);
3922
3923 if(0 != strcmp(interface_status, "1"))
3924 return RETURN_ERR;
3925
3926 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
3927 system(cmd);
3928
3929 fp = fopen("/tmp/SSID_Stats.txt", "r");
3930 if(fp == NULL)
3931 {
3932 printf("/tmp/SSID_Stats.txt not exists \n");
3933 return RETURN_ERR;
3934 }
3935 fclose(fp);
3936
3937 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3938 File_Reading(buf, Value);
3939 output_struct->wifi_PacketsReceived = strtoul(Value, NULL, 10);
3940
3941 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3942 File_Reading(buf, Value);
3943 output_struct->wifi_PacketsSent = strtoul(Value, NULL, 10);
3944
3945 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX bytes' | tr -s ' ' | cut -d ':' -f2 | cut -d ' ' -f1");
3946 File_Reading(buf, Value);
3947 output_struct->wifi_BytesReceived = strtoul(Value, NULL, 10);
3948
3949 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX bytes' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
3950 File_Reading(buf, Value);
3951 output_struct->wifi_BytesSent = strtoul(Value, NULL, 10);
3952
3953 /* There is no specific parameter from caller to associate the value wifi_Associations */
3954 //sprintf(cmd, "iw dev %s station dump | grep Station | wc -l", interface_name);
3955 //_syscmd(cmd, buf, sizeof(buf));
3956 //sscanf(buf,"%lu", &output_struct->wifi_Associations);
3957 }
3958#endif
3959 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
3960 return RETURN_OK;
3961}
3962
3963INT wifi_getWifiTrafficStats(INT apIndex, wifi_trafficStats_t *output_struct)
3964{
3965 char interface_name[MAX_BUF_SIZE] = {0};
3966 char interface_status[MAX_BUF_SIZE] = {0};
3967 char Value[MAX_BUF_SIZE] = {0};
3968 char buf[MAX_CMD_SIZE] = {0};
3969 char cmd[MAX_CMD_SIZE] = {0};
3970 FILE *fp = NULL;
3971
3972 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
3973 if (NULL == output_struct)
3974 return RETURN_ERR;
3975
3976 memset(output_struct, 0, sizeof(wifi_trafficStats_t));
3977
3978 if((apIndex == 0) || (apIndex == 1) || (apIndex == 4) || (apIndex == 5))
3979 {
3980 if(apIndex == 0) //private_wifi for 2.4G
3981 {
3982 GetInterfaceName(interface_name,"/nvram/hostapd0.conf");
3983 }
3984 else if(apIndex == 1) //private_wifi for 5G
3985 {
3986 GetInterfaceName(interface_name,"/nvram/hostapd1.conf");
3987 }
3988 else if(apIndex == 4) //public_wifi for 2.4G
3989 {
3990 sprintf(cmd,"%s","cat /nvram/hostapd0.conf | grep bss=");
3991 if(_syscmd(cmd,buf,sizeof(buf)) == RETURN_ERR)
3992 {
3993 return RETURN_ERR;
3994 }
3995 if(buf[0] == '#')
3996 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
3997 else
3998 GetInterfaceName_virtualInterfaceName_2G(interface_name);
3999 }
4000 else if(apIndex == 5) //public_wifi for 5G
4001 {
4002 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
4003 }
4004
4005 GetIfacestatus(interface_name, interface_status);
4006
4007 if(0 != strcmp(interface_status, "1"))
4008 return RETURN_ERR;
4009
4010 snprintf(cmd, sizeof(cmd), "ifconfig %s > /tmp/SSID_Stats.txt", interface_name);
4011 system(cmd);
4012
4013 fp = fopen("/tmp/SSID_Stats.txt", "r");
4014 if(fp == NULL)
4015 {
4016 printf("/tmp/SSID_Stats.txt not exists \n");
4017 return RETURN_ERR;
4018 }
4019 fclose(fp);
4020
4021 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4022 File_Reading(buf, Value);
4023 output_struct->wifi_ErrorsReceived = strtoul(Value, NULL, 10);
4024
4025 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f3 | cut -d ' ' -f1");
4026 File_Reading(buf, Value);
4027 output_struct->wifi_ErrorsSent = strtoul(Value, NULL, 10);
4028
4029 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'RX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4030 File_Reading(buf, Value);
4031 output_struct->wifi_DiscardedPacketsReceived = strtoul(Value, NULL, 10);
4032
4033 sprintf(buf, "cat /tmp/SSID_Stats.txt | grep 'TX packets' | tr -s ' ' | cut -d ':' -f4 | cut -d ' ' -f1");
4034 File_Reading(buf, Value);
4035 output_struct->wifi_DiscardedPacketsSent = strtoul(Value, NULL, 10);
4036 }
4037
4038 output_struct->wifi_UnicastPacketsSent = 0;
4039 output_struct->wifi_UnicastPacketsReceived = 0;
4040 output_struct->wifi_MulticastPacketsSent = 0;
4041 output_struct->wifi_MulticastPacketsReceived = 0;
4042 output_struct->wifi_BroadcastPacketsSent = 0;
4043 output_struct->wifi_BroadcastPacketsRecevied = 0;
4044 output_struct->wifi_UnknownPacketsReceived = 0;
4045
4046 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4047 return RETURN_OK;
4048}
4049
4050INT wifi_getSSIDTrafficStats(INT apIndex, wifi_ssidTrafficStats_t *output_struct)
4051{
4052 INT status = RETURN_ERR;
4053
4054 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4055 //Below values should get updated from hal
4056 output_struct->wifi_RetransCount=0;
4057 output_struct->wifi_FailedRetransCount=0;
4058 output_struct->wifi_RetryCount=0;
4059 output_struct->wifi_MultipleRetryCount=0;
4060 output_struct->wifi_ACKFailureCount=0;
4061 output_struct->wifi_AggregatedPacketCount=0;
4062
4063 status = RETURN_OK;
4064 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4065
4066 return status;
4067}
4068
4069INT wifi_getNeighboringWiFiDiagnosticResult(wifi_neighbor_ap_t **neighbor_ap_array, UINT *output_array_size)
4070{
4071 INT status = RETURN_ERR;
4072 UINT index;
4073 wifi_neighbor_ap_t *pt=NULL;
4074
4075 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4076 *output_array_size=2;
4077 //zqiu: HAL alloc the array and return to caller. Caller response to free it.
4078 *neighbor_ap_array=(wifi_neighbor_ap_t *)calloc(sizeof(wifi_neighbor_ap_t), *output_array_size);
4079 for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
4080 strcpy(pt->ap_Radio,"");
4081 strcpy(pt->ap_SSID,"");
4082 strcpy(pt->ap_BSSID,"");
4083 strcpy(pt->ap_Mode,"");
4084 pt->ap_Channel=1;
4085 pt->ap_SignalStrength=0;
4086 strcpy(pt->ap_SecurityModeEnabled,"");
4087 strcpy(pt->ap_EncryptionMode,"");
4088 strcpy(pt->ap_OperatingFrequencyBand,"");
4089 strcpy(pt->ap_SupportedStandards,"");
4090 strcpy(pt->ap_OperatingStandards,"");
4091 strcpy(pt->ap_OperatingChannelBandwidth,"");
4092 pt->ap_BeaconPeriod=1;
4093 pt->ap_Noise=0;
4094 strcpy(pt->ap_BasicDataTransferRates,"");
4095 strcpy(pt->ap_SupportedDataTransferRates,"");
4096 pt->ap_DTIMPeriod=1;
4097 pt->ap_ChannelUtilization = 1;
4098 }
4099
4100 status = RETURN_OK;
4101 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4102
4103 return status;
4104}
4105
4106//----------------- AP HAL -------------------------------
4107
4108//>> Deprecated: used for old RDKB code.
4109INT wifi_getAllAssociatedDeviceDetail(INT apIndex, ULONG *output_ulong, wifi_device_t **output_struct)
4110{
4111 if (NULL == output_ulong || NULL == output_struct)
4112 return RETURN_ERR;
4113 *output_ulong = 0;
4114 *output_struct = NULL;
4115 return RETURN_OK;
4116}
4117
4118#ifdef HAL_NETLINK_IMPL
4119static int AssoDevInfo_callback(struct nl_msg *msg, void *arg) {
4120 struct nlattr *tb[NL80211_ATTR_MAX + 1];
4121 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
4122 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
4123 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
4124 char mac_addr[20];
4125 static int count=0;
4126 int rate=0;
4127
4128 wifi_device_info_t *out = (wifi_device_info_t*)arg;
4129
4130 nla_parse(tb,
4131 NL80211_ATTR_MAX,
4132 genlmsg_attrdata(gnlh, 0),
4133 genlmsg_attrlen(gnlh, 0),
4134 NULL);
4135
4136 if(!tb[NL80211_ATTR_STA_INFO]) {
4137 fprintf(stderr, "sta stats missing!\n");
4138 return NL_SKIP;
4139 }
4140
4141
4142 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
4143 fprintf(stderr, "failed to parse nested attributes!\n");
4144 return NL_SKIP;
4145 }
4146
4147 //devIndex starts from 1
4148 if( ++count == out->wifi_devIndex )
4149 {
4150 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
4151 //Getting the mac addrress
4152 mac_addr_aton(out->wifi_devMacAddress,mac_addr);
4153
4154 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
4155 fprintf(stderr, "failed to parse nested rate attributes!");
4156 return NL_SKIP;
4157 }
4158
4159 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
4160 if(rinfo[NL80211_RATE_INFO_BITRATE])
4161 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4162 out->wifi_devTxRate = rate/10;
4163 }
4164
4165 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy)) {
4166 fprintf(stderr, "failed to parse nested rate attributes!");
4167 return NL_SKIP;
4168 }
4169
4170 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
4171 if(rinfo[NL80211_RATE_INFO_BITRATE])
4172 rate=nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
4173 out->wifi_devRxRate = rate/10;
4174 }
4175 if(sinfo[NL80211_STA_INFO_SIGNAL_AVG])
4176 out->wifi_devSignalStrength = (int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL_AVG]);
4177
4178 out->wifi_devAssociatedDeviceAuthentiationState = 1;
4179 count = 0; //starts the count for next cycle
4180 return NL_STOP;
4181 }
4182
4183 return NL_SKIP;
4184
4185}
4186#endif
4187
4188INT wifi_getAssociatedDeviceDetail(INT apIndex, INT devIndex, wifi_device_t *output_struct)
4189{
4190#ifdef HAL_NETLINK_IMPL
4191 Netlink nl;
4192 char if_name[10];
4193
4194 wifi_device_info_t info;
4195 info.wifi_devIndex = devIndex;
4196
4197 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4198
4199 nl.id = initSock80211(&nl);
4200
4201 if (nl.id < 0) {
4202 fprintf(stderr, "Error initializing netlink \n");
4203 return -1;
4204 }
4205
4206 struct nl_msg* msg = nlmsg_alloc();
4207
4208 if (!msg) {
4209 fprintf(stderr, "Failed to allocate netlink message.\n");
4210 nlfree(&nl);
4211 return -2;
4212 }
4213
4214 genlmsg_put(msg,
4215 NL_AUTO_PORT,
4216 NL_AUTO_SEQ,
4217 nl.id,
4218 0,
4219 NLM_F_DUMP,
4220 NL80211_CMD_GET_STATION,
4221 0);
4222
4223 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
4224 nl_send_auto(nl.socket, msg);
4225 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,AssoDevInfo_callback,&info);
4226 nl_recvmsgs(nl.socket, nl.cb);
4227 nlmsg_free(msg);
4228 nlfree(&nl);
4229
4230 output_struct->wifi_devAssociatedDeviceAuthentiationState = info.wifi_devAssociatedDeviceAuthentiationState;
4231 output_struct->wifi_devRxRate = info.wifi_devRxRate;
4232 output_struct->wifi_devTxRate = info.wifi_devTxRate;
4233 output_struct->wifi_devSignalStrength = info.wifi_devSignalStrength;
4234 memcpy(&output_struct->wifi_devMacAddress, &info.wifi_devMacAddress, sizeof(info.wifi_devMacAddress));
4235 return RETURN_OK;
4236#else
4237 //iw utility to retrieve station information
4238#define ASSODEVFILE "/tmp/AssociatedDevice_Stats.txt"
4239#define SIGNALFILE "/tmp/wifi_signalstrength.txt"
4240#define MACFILE "/tmp/wifi_AssoMac.txt"
4241#define TXRATEFILE "/tmp/wifi_txrate.txt"
4242#define RXRATEFILE "/tmp/wifi_rxrate.txt"
4243 FILE *file = NULL;
4244 char if_name[10] = {'\0'};
4245 char pipeCmd[256] = {'\0'};
4246 char line[256];
4247 int count,device = 0;
4248
4249 snprintf(if_name,sizeof(if_name),"%s%d", AP_PREFIX, apIndex);
4250
4251 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", if_name, if_name);
4252 file = popen(pipeCmd, "r");
4253
4254 if(file == NULL)
4255 return RETURN_ERR; //popen failed
4256
4257 fgets(line, sizeof line, file);
4258 device = atoi(line);
4259 pclose(file);
4260
4261 if(device == 0)
4262 return RETURN_ERR; //No devices are connected
4263
4264 sprintf(pipeCmd,"iw dev %s station dump > "ASSODEVFILE, if_name);
4265 system(pipeCmd);
4266
4267 system("cat "ASSODEVFILE" | grep 'signal avg' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' > "SIGNALFILE);
4268
4269 system("cat "ASSODEVFILE" | grep Station | cut -d ' ' -f 2 > "MACFILE);
4270
4271 system("cat "ASSODEVFILE" | grep 'tx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "TXRATEFILE);
4272
4273 system("cat "ASSODEVFILE" | grep 'rx bitrate' | cut -d ' ' -f2 | cut -d ':' -f2 | cut -f 2 | tr -s '\n' | cut -d '.' -f1 > "RXRATEFILE);
4274
4275 //devIndex starts from 1, ++count
4276 if((file = fopen(SIGNALFILE, "r")) != NULL )
4277 {
4278 for(count =0;fgets(line, sizeof line, file) != NULL;)
4279 {
4280 if (++count == devIndex)
4281 {
4282 output_struct->wifi_devSignalStrength = atoi(line);
4283 break;
4284 }
4285 }
4286 fclose(file);
4287 }
4288 else
4289 fprintf(stderr,"fopen wifi_signalstrength.txt failed");
4290
4291 if((file = fopen(MACFILE, "r")) != NULL )
4292 {
4293 for(count =0;fgets(line, sizeof line, file) != NULL;)
4294 {
4295 if (++count == devIndex)
4296 {
4297 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]);
4298 break;
4299 }
4300 }
4301 fclose(file);
4302 }
4303 else
4304 fprintf(stderr,"fopen wifi_AssoMac.txt failed");
4305
4306 if((file = fopen(TXRATEFILE, "r")) != NULL )
4307 {
4308 for(count =0;fgets(line, sizeof line, file) != NULL;)
4309 {
4310 if (++count == devIndex)
4311 {
4312 output_struct->wifi_devTxRate = atoi(line);
4313 break;
4314 }
4315 }
4316 fclose(file);
4317 }
4318 else
4319 fprintf(stderr,"fopen wifi_txrate.txt failed");
4320
4321 if((file = fopen(RXRATEFILE, "r")) != NULL)
4322 {
4323 for(count =0;fgets(line, sizeof line, file) != NULL;)
4324 {
4325 if (++count == devIndex)
4326 {
4327 output_struct->wifi_devRxRate = atoi(line);
4328 break;
4329 }
4330 }
4331 fclose(file);
4332 }
4333 else
4334 fprintf(stderr,"fopen wifi_rxrate.txt failed");
4335
4336 output_struct->wifi_devAssociatedDeviceAuthentiationState = 1;
4337
4338 return RETURN_OK;
4339#endif
4340}
4341
4342INT wifi_kickAssociatedDevice(INT apIndex, wifi_device_t *device)
4343{
4344 if (NULL == device)
4345 return RETURN_ERR;
4346 return RETURN_OK;
4347}
4348//<<
4349
4350
4351//--------------wifi_ap_hal-----------------------------
4352//enables CTS protection for the radio used by this AP
4353INT wifi_setRadioCtsProtectionEnable(INT apIndex, BOOL enable)
4354{
4355 //save config and Apply instantly
4356 return RETURN_ERR;
4357}
4358
4359// enables OBSS Coexistence - fall back to 20MHz if necessary for the radio used by this ap
4360INT wifi_setRadioObssCoexistenceEnable(INT apIndex, BOOL enable)
4361{
developer463d39a2022-09-13 15:32:51 +08004362 char config_file[64] = {'\0'};
4363 char buf[64] = {'\0'};
4364 struct params list;
4365
4366 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4367 list.name = "ht_coex";
4368 snprintf(buf, sizeof(buf), "%d", enable);
4369 list.value = buf;
4370
4371 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4372 wifi_hostapdWrite(config_file, &list, 1);
4373 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4374
4375 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4376
4377 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004378}
4379
4380//P3 // sets the fragmentation threshold in bytes for the radio used by this ap
4381INT wifi_setRadioFragmentationThreshold(INT apIndex, UINT threshold)
4382{
developerea4bcce2022-09-13 15:26:13 +08004383 char config_file[MAX_BUF_SIZE] = {'\0'};
4384 char buf[MAX_BUF_SIZE] = {'\0'};
4385 struct params list;
4386
4387 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4388 if (threshold < 256 || threshold > 2346 )
4389 return RETURN_ERR;
4390 list.name = "fragm_threshold";
4391 snprintf(buf, sizeof(buf), "%d", threshold);
4392 list.value = buf;
4393
4394 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
4395 wifi_hostapdWrite(config_file, &list, 1);
4396 wifi_hostapdProcessUpdate(apIndex, &list, 1);
developer06a01d92022-09-07 16:32:39 +08004397
developerea4bcce2022-09-13 15:26:13 +08004398 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004399
4400 return RETURN_OK;
4401}
4402
4403// enable STBC mode in the hardwarwe, 0 == not enabled, 1 == enabled
4404INT wifi_setRadioSTBCEnable(INT radioIndex, BOOL STBC_Enable)
4405{
developer51a927d2022-09-13 15:42:22 +08004406 char config_file[64] = {'\0'};
4407 char cmd[128] = {'\0'};
4408 char buf[64] = {'\0'};
4409 char stbc_config[16] = {'\0'};
4410 wifi_band band;
4411 int iterator = 0;
4412 BOOL current_stbc = FALSE;
4413
4414 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4415
4416 band = wifi_index_to_band(radioIndex);
4417 if (band == band_invalid)
4418 return RETURN_ERR;
4419
4420 if (band == band_2_4)
4421 iterator = 1;
4422 else if (band == band_5)
4423 iterator = 2;
4424 else
4425 return RETURN_OK;
4426
4427 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
4428
4429 // set ht and vht config
4430 for (int i = 0; i < iterator; i++) {
4431 memset(stbc_config, 0, sizeof(stbc_config));
4432 memset(cmd, 0, sizeof(cmd));
4433 memset(buf, 0, sizeof(buf));
4434 snprintf(stbc_config, sizeof(stbc_config), "%sht_capab", (i == 0)?"":"v");
4435 snprintf(cmd, sizeof(cmd), "cat %s | grep -E '^%s' | grep 'STBC'", config_file, stbc_config);
4436 _syscmd(cmd, buf, sizeof(buf));
4437 if (strlen(buf) != 0)
4438 current_stbc = TRUE;
4439 if (current_stbc == STBC_Enable)
4440 continue;
4441
4442 if (STBC_Enable == TRUE) {
4443 // Append the STBC flags in capab config
4444 memset(cmd, 0, sizeof(cmd));
4445 if (i == 0)
4446 snprintf(cmd, sizeof(cmd), "sed -E -i '/^ht_capab=.*/s/$/[TX-STBC][RX-STBC1]/' %s", config_file);
4447 else
4448 snprintf(cmd, sizeof(cmd), "sed -E -i '/^vht_capab=.*/s/$/[TX-STBC-2BY1][RX-STBC-1]/' %s", config_file);
4449 _syscmd(cmd, buf, sizeof(buf));
4450 } else if (STBC_Enable == FALSE) {
4451 // Remove the STBC flags and remain other flags in capab
4452 memset(cmd, 0, sizeof(cmd));
4453 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[TX-STBC(-2BY1)?*\\]//' %s", config_file);
4454 _syscmd(cmd, buf, sizeof(buf));
4455 memset(cmd, 0, sizeof(cmd));
4456 snprintf(cmd, sizeof(cmd), "sed -E -i 's/\\[RX-STBC-?[1-3]*\\]//' %s", config_file);
4457 _syscmd(cmd, buf, sizeof(buf));
4458 }
4459 }
4460
4461 wifi_reloadAp(radioIndex);
4462
4463 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4464 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004465}
4466
4467// outputs A-MSDU enable status, 0 == not enabled, 1 == enabled
4468INT wifi_getRadioAMSDUEnable(INT radioIndex, BOOL *output_bool)
4469{
developer54e6b9f2022-09-28 14:41:20 +08004470 char AMSDU_file_path[64] = {0};
4471
4472 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4473
4474 if(output_bool == NULL)
4475 return RETURN_ERR;
4476
4477 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4478
4479 if (access(AMSDU_file_path, F_OK) == 0)
4480 *output_bool = TRUE;
4481 else
4482 *output_bool = FALSE;
4483
4484 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4485 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004486}
4487
4488// enables A-MSDU in the hardware, 0 == not enabled, 1 == enabled
4489INT wifi_setRadioAMSDUEnable(INT radioIndex, BOOL amsduEnable)
4490{
developer54e6b9f2022-09-28 14:41:20 +08004491 char cmd[64]={0};
4492 char buf[64]={0};
4493 char AMSDU_file_path[64] = {0};
4494
4495 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4496
4497 sprintf(cmd, "mt76-vendor %s%d set ap_wireless amsdu=%d", AP_PREFIX, radioIndex, amsduEnable);
4498 _syscmd(cmd, buf, sizeof(buf));
4499
4500 sprintf(AMSDU_file_path, "%s%d.txt", AMSDU_FILE, radioIndex);
4501 memset(cmd, 0, sizeof(cmd));
4502 if (amsduEnable == TRUE)
4503 sprintf(cmd, "touch %s", AMSDU_file_path);
4504 else
4505 sprintf(cmd, "rm %s 2> /dev/null", AMSDU_file_path);
4506 _syscmd(cmd, buf, sizeof(buf));
4507
4508 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4509 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004510}
4511
4512//P2 // outputs the number of Tx streams
4513INT wifi_getRadioTxChainMask(INT radioIndex, INT *output_int)
4514{
developer2de97692022-09-26 14:00:03 +08004515 char buf[8] = {0};
4516 char cmd[128] = {0};
4517
4518 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4519
4520 sprintf(cmd, "cat %s%d.txt 2> /dev/null", CHAIN_MASK_FILE, radioIndex);
4521 _syscmd(cmd, buf, sizeof(buf));
4522
4523 // if there is no record, output the max number of spatial streams
4524 if (strlen(buf) == 0) {
4525 sprintf(cmd, "iw phy%d info | grep 'TX MCS and NSS set' -A8 | head -n8 | grep 'streams: MCS' | wc -l", radioIndex);
4526 _syscmd(cmd, buf, sizeof(buf));
4527 }
4528
4529 *output_int = (INT)strtol(buf, NULL, 10);
4530
4531 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4532
4533 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004534}
4535
4536//P2 // sets the number of Tx streams to an enviornment variable
4537INT wifi_setRadioTxChainMask(INT radioIndex, INT numStreams)
4538{
developer2de97692022-09-26 14:00:03 +08004539 char cmd[128] = {0};
4540 char buf[128] = {0};
4541 char chain_mask_file[128] = {0};
4542 FILE *f = NULL;
4543
4544 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4545
4546 if (numStreams == 0) {
4547 fprintf(stderr, "The mask did not support 0 (auto).\n", numStreams);
4548 return RETURN_ERR;
4549 }
4550 wifi_setRadioEnable(radioIndex, FALSE);
4551 sprintf(cmd, "iw phy%d set antenna 0x%x 2>&1", radioIndex, numStreams);
4552 _syscmd(cmd, buf, sizeof(buf));
4553
4554 if (strlen(buf) > 0) {
4555 fprintf(stderr, "%s: cmd %s error, output: %s\n", __func__, cmd, buf);
4556 return RETURN_ERR;
4557 }
4558 wifi_setRadioEnable(radioIndex, TRUE);
4559
4560 sprintf(chain_mask_file, "%s%d.txt", CHAIN_MASK_FILE, radioIndex);
4561 f = fopen(chain_mask_file, "w");
4562 if (f == NULL) {
4563 fprintf(stderr, "%s: fopen failed.\n", __func__);
4564 return RETURN_ERR;
4565 }
4566 fprintf(f, "%d", numStreams);
4567 fclose(f);
4568 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4569 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004570}
4571
4572//P2 // outputs the number of Rx streams
4573INT wifi_getRadioRxChainMask(INT radioIndex, INT *output_int)
4574{
developer2de97692022-09-26 14:00:03 +08004575 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4576 if (wifi_getRadioTxChainMask(radioIndex, output_int) == RETURN_ERR) {
4577 fprintf(stderr, "%s: wifi_getRadioTxChainMask return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +08004578 return RETURN_ERR;
developer2de97692022-09-26 14:00:03 +08004579 }
4580 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004581 return RETURN_OK;
4582}
4583
4584//P2 // sets the number of Rx streams to an enviornment variable
4585INT wifi_setRadioRxChainMask(INT radioIndex, INT numStreams)
4586{
developer2de97692022-09-26 14:00:03 +08004587 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4588 if (wifi_setRadioTxChainMask(radioIndex, numStreams) == RETURN_ERR) {
4589 fprintf(stderr, "%s: wifi_setRadioTxChainMask return error.\n", __func__);
4590 return RETURN_ERR;
4591 }
4592 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004593 return RETURN_ERR;
4594}
4595
4596//Get radio RDG enable setting
4597INT wifi_getRadioReverseDirectionGrantSupported(INT radioIndex, BOOL *output_bool)
4598{
4599 if (NULL == output_bool)
4600 return RETURN_ERR;
4601 *output_bool = TRUE;
4602 return RETURN_OK;
4603}
4604
4605//Get radio RDG enable setting
4606INT wifi_getRadioReverseDirectionGrantEnable(INT radioIndex, BOOL *output_bool)
4607{
4608 if (NULL == output_bool)
4609 return RETURN_ERR;
4610 *output_bool = TRUE;
4611 return RETURN_OK;
4612}
4613
4614//Set radio RDG enable setting
4615INT wifi_setRadioReverseDirectionGrantEnable(INT radioIndex, BOOL enable)
4616{
4617 return RETURN_ERR;
4618}
4619
4620//Get radio ADDBA enable setting
4621INT wifi_getRadioDeclineBARequestEnable(INT radioIndex, BOOL *output_bool)
4622{
4623 if (NULL == output_bool)
4624 return RETURN_ERR;
4625 *output_bool = TRUE;
4626 return RETURN_OK;
4627}
4628
4629//Set radio ADDBA enable setting
4630INT wifi_setRadioDeclineBARequestEnable(INT radioIndex, BOOL enable)
4631{
4632 return RETURN_ERR;
4633}
4634
4635//Get radio auto block ack enable setting
4636INT wifi_getRadioAutoBlockAckEnable(INT radioIndex, BOOL *output_bool)
4637{
4638 if (NULL == output_bool)
4639 return RETURN_ERR;
4640 *output_bool = TRUE;
4641 return RETURN_OK;
4642}
4643
4644//Set radio auto block ack enable setting
4645INT wifi_setRadioAutoBlockAckEnable(INT radioIndex, BOOL enable)
4646{
4647 return RETURN_ERR;
4648}
4649
4650//Get radio 11n pure mode enable support
4651INT wifi_getRadio11nGreenfieldSupported(INT radioIndex, BOOL *output_bool)
4652{
4653 if (NULL == output_bool)
4654 return RETURN_ERR;
4655 *output_bool = TRUE;
4656 return RETURN_OK;
4657}
4658
4659//Get radio 11n pure mode enable setting
4660INT wifi_getRadio11nGreenfieldEnable(INT radioIndex, BOOL *output_bool)
4661{
4662 if (NULL == output_bool)
4663 return RETURN_ERR;
4664 *output_bool = TRUE;
4665 return RETURN_OK;
4666}
4667
4668//Set radio 11n pure mode enable setting
4669INT wifi_setRadio11nGreenfieldEnable(INT radioIndex, BOOL enable)
4670{
4671 return RETURN_ERR;
4672}
4673
4674//Get radio IGMP snooping enable setting
4675INT wifi_getRadioIGMPSnoopingEnable(INT radioIndex, BOOL *output_bool)
4676{
developer81bf2ed2022-09-13 15:31:14 +08004677 char cmd[128]={0};
4678 char buf[4]={0};
4679 bool bridge = FALSE, mac80211 = FALSE;
4680 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4681
4682 if(output_bool == NULL)
developer06a01d92022-09-07 16:32:39 +08004683 return RETURN_ERR;
developer81bf2ed2022-09-13 15:31:14 +08004684
4685 *output_bool = FALSE;
4686
4687 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/bridge/multicast_snooping", BRIDGE_NAME);
4688 _syscmd(cmd, buf, sizeof(buf));
4689 if (strncmp(buf, "1", 1) == 0)
4690 bridge = TRUE;
4691
4692 snprintf(cmd, sizeof(cmd), "cat /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", BRIDGE_NAME, AP_PREFIX, radioIndex);
4693 _syscmd(cmd, buf, sizeof(buf));
4694 if (strncmp(buf, "1", 1) == 0)
4695 mac80211 = TRUE;
4696
4697 if (bridge && mac80211)
4698 *output_bool = TRUE;
4699
4700 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08004701 return RETURN_OK;
4702}
4703
4704//Set radio IGMP snooping enable setting
4705INT wifi_setRadioIGMPSnoopingEnable(INT radioIndex, BOOL enable)
4706{
developer81bf2ed2022-09-13 15:31:14 +08004707 char cmd[128]={0};
4708 char buf[4]={0};
4709
4710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4711
4712 // bridge
4713 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/bridge/multicast_snooping", enable, BRIDGE_NAME);
4714 _syscmd(cmd, buf, sizeof(buf));
4715
4716 // mac80211
4717 for (int i = 0; i < NUMBER_OF_RADIOS; i++) {
4718 snprintf(cmd, sizeof(cmd), "echo %d > /sys/devices/virtual/net/%s/brif/%s%d/multicast_to_unicast", enable, BRIDGE_NAME, AP_PREFIX, i);
4719 _syscmd(cmd, buf, sizeof(buf));
4720 }
4721 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4722 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004723}
4724
4725//Get the Reset count of radio
4726INT wifi_getRadioResetCount(INT radioIndex, ULONG *output_int)
4727{
4728 if (NULL == output_int)
4729 return RETURN_ERR;
4730 *output_int = (radioIndex==0)? 1: 3;
4731
4732 return RETURN_OK;
4733}
4734
4735
4736//---------------------------------------------------------------------------------------------------
4737//
4738// Additional Wifi AP level APIs used for Access Point devices
4739//
4740//---------------------------------------------------------------------------------------------------
4741
4742// creates a new ap and pushes these parameters to the hardware
4743INT wifi_createAp(INT apIndex, INT radioIndex, CHAR *essid, BOOL hideSsid)
4744{
4745 char buf[1024];
4746 char cmd[128];
4747
4748 if (NULL == essid)
4749 return RETURN_ERR;
4750
4751 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d create wlandev %s%d wlanmode ap", AP_PREFIX, apIndex, RADIO_PREFIX, radioIndex);
4752 _syscmd(cmd, buf, sizeof(buf));
4753
4754 snprintf(cmd,sizeof(cmd), "iwconfig %s%d essid %s mode master", AP_PREFIX, apIndex, essid);
4755 _syscmd(cmd, buf, sizeof(buf));
4756
4757 wifi_pushSsidAdvertisementEnable(apIndex, !hideSsid);
4758
4759 snprintf(cmd,sizeof(cmd), "ifconfig %s%d txqueuelen 1000", AP_PREFIX, apIndex);
4760 _syscmd(cmd, buf, sizeof(buf));
4761
4762 return RETURN_OK;
4763}
4764
4765// deletes this ap entry on the hardware, clears all internal variables associaated with this ap
4766INT wifi_deleteAp(INT apIndex)
4767{
4768 char buf[1024];
4769 char cmd[128];
4770
4771 snprintf(cmd,sizeof(cmd), "wlanconfig %s%d destroy", AP_PREFIX, apIndex);
4772 _syscmd(cmd, buf, sizeof(buf));
4773
4774 wifi_removeApSecVaribles(apIndex);
4775
4776 return RETURN_OK;
4777}
4778
4779// Outputs a 16 byte or less name assocated with the AP. String buffer must be pre-allocated by the caller
4780INT wifi_getApName(INT apIndex, CHAR *output_string)
4781{
4782 if(NULL == output_string)
4783 return RETURN_ERR;
4784
4785 snprintf(output_string, 16, "%s%d", AP_PREFIX, apIndex);
4786 return RETURN_OK;
4787}
4788
4789// Outputs the index number in that corresponds to the SSID string
4790INT wifi_getIndexFromName(CHAR *inputSsidString, INT *output_int)
4791{
4792 CHAR *pos = NULL;
4793
4794 *output_int = -1;
4795 pos = strstr(inputSsidString, AP_PREFIX);
4796 if(pos)
4797 {
4798 sscanf(pos+strlen(AP_PREFIX),"%d", output_int);
4799 return RETURN_OK;
4800 }
4801 return RETURN_ERR;
4802}
4803
4804INT wifi_getApIndexFromName(CHAR *inputSsidString, INT *output_int)
4805{
4806 return wifi_getIndexFromName(inputSsidString, output_int);
4807}
4808
4809// Outputs a 32 byte or less string indicating the beacon type as "None", "Basic", "WPA", "11i", "WPAand11i"
4810INT wifi_getApBeaconType(INT apIndex, CHAR *output_string)
4811{
4812 char buf[MAX_BUF_SIZE] = {0};
4813 char cmd[MAX_CMD_SIZE] = {0};
4814 char config_file[MAX_BUF_SIZE] = {0};
4815
4816 if(NULL == output_string)
4817 return RETURN_ERR;
4818
4819 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4820 wifi_hostapdRead(config_file, "wpa", buf, sizeof(buf));
4821 if((strcmp(buf,"3")==0))
4822 snprintf(output_string, 32, "WPAand11i");
4823 else if((strcmp(buf,"2")==0))
4824 snprintf(output_string, 32, "11i");
4825 else if((strcmp(buf,"1")==0))
4826 snprintf(output_string, 32, "WPA");
4827 else
4828 snprintf(output_string, 32, "None");
4829
4830 return RETURN_OK;
4831}
4832
4833// Sets the beacon type enviornment variable. Allowed input strings are "None", "Basic", "WPA, "11i", "WPAand11i"
4834INT wifi_setApBeaconType(INT apIndex, CHAR *beaconTypeString)
4835{
4836 char config_file[MAX_BUF_SIZE] = {0};
4837 struct params list;
4838
4839 if (NULL == beaconTypeString)
4840 return RETURN_ERR;
4841 list.name = "wpa";
4842 list.value = "0";
4843
4844 if((strcmp(beaconTypeString,"WPAand11i")==0))
4845 list.value="3";
4846 else if((strcmp(beaconTypeString,"11i")==0))
4847 list.value="2";
4848 else if((strcmp(beaconTypeString,"WPA")==0))
4849 list.value="1";
4850
4851 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4852 wifi_hostapdWrite(config_file, &list, 1);
4853 wifi_hostapdProcessUpdate(apIndex, &list, 1);
4854 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
4855 return RETURN_OK;
4856}
4857
4858// sets the beacon interval on the hardware for this AP
4859INT wifi_setApBeaconInterval(INT apIndex, INT beaconInterval)
4860{
developer5f222492022-09-13 15:21:52 +08004861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4862 struct params params={'\0'};
4863 char buf[MAX_BUF_SIZE] = {'\0'};
4864 char config_file[MAX_BUF_SIZE] = {'\0'};
4865
4866 params.name = "beacon_int";
4867 snprintf(buf, sizeof(buf), "%u", beaconInterval);
4868 params.value = buf;
4869
4870 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
4871 wifi_hostapdWrite(config_file, &params, 1);
4872
4873 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4874 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4875 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08004876}
4877
4878INT wifi_setDTIMInterval(INT apIndex, INT dtimInterval)
4879{
4880 //save config and apply instantly
4881 return RETURN_ERR;
4882}
4883
4884// Get the packet size threshold supported.
4885INT wifi_getApRtsThresholdSupported(INT apIndex, BOOL *output_bool)
4886{
4887 //save config and apply instantly
4888 if (NULL == output_bool)
4889 return RETURN_ERR;
4890 *output_bool = FALSE;
4891 return RETURN_OK;
4892}
4893
4894// sets the packet size threshold in bytes to apply RTS/CTS backoff rules.
4895INT wifi_setApRtsThreshold(INT apIndex, UINT threshold)
4896{
4897 char cmd[128];
4898 char buf[512];
4899
4900 if (threshold > 0)
4901 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts %d", AP_PREFIX, apIndex, threshold);
4902 else
4903 snprintf(cmd, sizeof(cmd), "iwconfig %s%d rts off", AP_PREFIX, apIndex);
4904 _syscmd(cmd, buf, sizeof(buf));
4905
4906 return RETURN_OK;
4907}
4908
4909// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4910INT wifi_getApWpaEncryptoinMode(INT apIndex, CHAR *output_string)
4911{
4912 if (NULL == output_string)
4913 return RETURN_ERR;
4914 snprintf(output_string, 32, "TKIPandAESEncryption");
4915 return RETURN_OK;
4916
4917}
4918
4919// outputs up to a 32 byte string as either "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4920INT wifi_getApWpaEncryptionMode(INT apIndex, CHAR *output_string)
4921{
4922 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4923 char *param_name, buf[32], config_file[MAX_BUF_SIZE] = {0};
4924
4925 if(NULL == output_string)
4926 return RETURN_ERR;
4927
4928 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4929 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
4930
4931 if(strcmp(buf,"0")==0)
4932 {
4933 printf("%s: wpa_mode is %s ......... \n", __func__, buf);
4934 snprintf(output_string, 32, "None");
4935 return RETURN_OK;
4936 }
4937 else if((strcmp(buf,"3")==0) || (strcmp(buf,"2")==0))
4938 param_name = "rsn_pairwise";
4939 else if((strcmp(buf,"1")==0))
4940 param_name = "wpa_pairwise";
4941 else
4942 return RETURN_ERR;
4943 memset(output_string,'\0',32);
4944 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4945 wifi_hostapdRead(config_file,param_name,output_string,32);
4946 wifi_dbg_printf("\n%s output_string=%s",__func__,output_string);
4947
4948 if(strcmp(output_string,"TKIP") == 0)
4949 strncpy(output_string,"TKIPEncryption", strlen("TKIPEncryption"));
4950 else if(strcmp(output_string,"CCMP") == 0)
4951 strncpy(output_string,"AESEncryption", strlen("AESEncryption"));
4952 else if(strcmp(output_string,"TKIP CCMP") == 0)
4953 strncpy(output_string,"TKIPandAESEncryption", strlen("TKIPandAESEncryption"));
4954
4955 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
4956 return RETURN_OK;
4957}
4958
4959// sets the encyption mode enviornment variable. Valid string format is "TKIPEncryption", "AESEncryption", or "TKIPandAESEncryption"
4960INT wifi_setApWpaEncryptionMode(INT apIndex, CHAR *encMode)
4961{
4962 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
4963 struct params params={'\0'};
4964 char output_string[32];
4965 char config_file[MAX_BUF_SIZE] = {0};
4966
4967 memset(output_string,'\0',32);
4968 wifi_getApWpaEncryptionMode(apIndex,output_string);
4969
4970 if(strcmp(encMode, "TKIPEncryption") == 0)
4971 params.value = "TKIP";
4972 else if(strcmp(encMode,"AESEncryption") == 0)
4973 params.value = "CCMP";
4974 else if(strcmp(encMode,"TKIPandAESEncryption") == 0)
4975 params.value = "TKIP CCMP";
4976
4977 if((strcmp(output_string,"WPAand11i")==0))
4978 {
4979 params.name = "wpa_pairwise";
4980 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4981 wifi_hostapdWrite(config_file, &params, 1);
4982 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4983
4984 params.name,"rsn_pairwise";
4985 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4986 wifi_hostapdWrite(config_file, &params, 1);
4987 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4988
4989 return RETURN_OK;
4990 }
4991 else if((strcmp(output_string,"11i")==0))
4992 {
4993 params.name = "rsn_pairwise";
4994 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
4995 wifi_hostapdWrite(config_file, &params, 1);
4996 wifi_hostapdProcessUpdate(apIndex, &params, 1);
4997 return RETURN_OK;
4998 }
4999 else if((strcmp(output_string,"WPA")==0))
5000 {
5001 params.name = "wpa_pairwise";
5002 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5003 wifi_hostapdWrite(config_file, &params, 1);
5004 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5005 return RETURN_OK;
5006 }
5007
5008 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5009 return RETURN_OK;
5010}
5011
5012// deletes internal security varable settings for this ap
5013INT wifi_removeApSecVaribles(INT apIndex)
5014{
5015 //TODO: remove the entry in hostapd config file
5016 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/nvram\\/etc\\/wpa2\\/WSC_%s%d.conf//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5017 //_syscmd(cmd, buf, sizeof(buf));
5018
5019 //snprintf(cmd,sizeof(cmd), "sed -i 's/\\/tmp\\//sec%s%d//g' /tmp/conf_filename", AP_PREFIX, apIndex);
5020 //_syscmd(cmd, buf, sizeof(buf));
5021 return RETURN_ERR;
5022}
5023
5024// changes the hardware settings to disable encryption on this ap
5025INT wifi_disableApEncryption(INT apIndex)
5026{
5027 //Apply instantly
5028 return RETURN_ERR;
5029}
5030
5031// set the authorization mode on this ap
5032// mode mapping as: 1: open, 2: shared, 4:auto
5033INT wifi_setApAuthMode(INT apIndex, INT mode)
5034{
developeraf95c502022-09-13 16:18:22 +08005035 struct params params={0};
5036 char config_file[64] = {0};
5037 int ret;
5038
5039 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5040
5041 wifi_dbg_printf("\n%s algo_mode=%d", __func__, mode);
5042 params.name = "auth_algs";
5043
5044 if (mode & 1 && mode & 2)
5045 params.value = "3";
5046 else if (mode & 2)
5047 params.value = "2";
5048 else if (mode & 1)
5049 params.value = "1";
5050 else
5051 params.value = "0";
5052
5053 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5054 wifi_hostapdWrite(config_file, &params, 1);
5055 wifi_hostapdProcessUpdate(apIndex, &params, 1);
5056 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5057
5058 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005059}
5060
5061// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5062INT wifi_setApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5063{
5064 //save to wifi config, and wait for wifi restart to apply
5065 struct params params={'\0'};
5066 char config_file[MAX_BUF_SIZE] = {0};
5067 int ret;
5068
5069 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5070 if(authMode == NULL)
5071 return RETURN_ERR;
5072
5073 wifi_dbg_printf("\n%s AuthMode=%s",__func__,authMode);
5074 params.name = "wpa_key_mgmt";
5075
5076 if((strcmp(authMode,"PSKAuthentication") == 0) || (strcmp(authMode,"SharedAuthentication") == 0))
5077 params.value = "WPA-PSK";
5078 else if(strcmp(authMode,"EAPAuthentication") == 0)
5079 params.value = "WPA-EAP";
developer587c1b62022-09-27 15:58:59 +08005080 else if (strcmp(authMode, "SAEAuthentication") == 0)
5081 params.value = "SAE";
5082 else if (strcmp(authMode, "EAP_192-bit_Authentication") == 0)
5083 params.value = "WPA-EAP-SUITE-B-192";
developer06a01d92022-09-07 16:32:39 +08005084 else if(strcmp(authMode,"None") == 0) //Donot change in case the authMode is None
5085 return RETURN_OK; //This is taken careof in beaconType
5086
5087 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5088 ret=wifi_hostapdWrite(config_file,&params,1);
5089 if(!ret)
5090 ret=wifi_hostapdProcessUpdate(apIndex, &params, 1);
5091 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5092
5093 return ret;
5094}
5095
5096// sets an enviornment variable for the authMode. Valid strings are "None", "EAPAuthentication" or "SharedAuthentication"
5097INT wifi_getApBasicAuthenticationMode(INT apIndex, CHAR *authMode)
5098{
5099 //save to wifi config, and wait for wifi restart to apply
5100 char BeaconType[50] = {0};
5101 char config_file[MAX_BUF_SIZE] = {0};
5102
5103 *authMode = 0;
5104 wifi_getApBeaconType(apIndex,BeaconType);
5105 printf("%s____%s \n",__FUNCTION__,BeaconType);
5106
5107 if(strcmp(BeaconType,"None") == 0)
5108 strcpy(authMode,"None");
5109 else
5110 {
5111 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5112 wifi_hostapdRead(config_file, "wpa_key_mgmt", authMode, 32);
5113 wifi_dbg_printf("\n[%s]: AuthMode Name is : %s",__func__,authMode);
5114 if(strcmp(authMode,"WPA-PSK") == 0)
5115 strcpy(authMode,"SharedAuthentication");
5116 else if(strcmp(authMode,"WPA-EAP") == 0)
5117 strcpy(authMode,"EAPAuthentication");
5118 }
5119
5120 return RETURN_OK;
5121}
5122
5123// Outputs the number of stations associated per AP
5124INT wifi_getApNumDevicesAssociated(INT apIndex, ULONG *output_ulong)
5125{
5126 char cmd[128]={0};
5127 char buf[128]={0};
5128 BOOL status = false;
5129
5130 if(apIndex > MAX_APS)
5131 return RETURN_ERR;
5132
5133 wifi_getApEnable(apIndex,&status);
5134 if (!status)
5135 return RETURN_OK;
5136
5137 //sprintf(cmd, "iw dev %s%d station dump | grep Station | wc -l", AP_PREFIX, apIndex);//alternate method
5138 sprintf(cmd, "hostapd_cli -i %s%d list_sta | wc -l", AP_PREFIX, apIndex);
5139 _syscmd(cmd, buf, sizeof(buf));
5140 sscanf(buf,"%lu", output_ulong);
5141
5142 return RETURN_OK;
5143}
5144
5145// manually removes any active wi-fi association with the device specified on this ap
5146INT wifi_kickApAssociatedDevice(INT apIndex, CHAR *client_mac)
5147{
5148 char buf[126]={'\0'};
5149
5150 sprintf(buf,"hostapd_cli -i%s%d disassociate %s", AP_PREFIX, apIndex, client_mac);
5151 system(buf);
5152
5153 return RETURN_OK;
5154}
5155
5156// outputs the radio index for the specified ap. similar as wifi_getSsidRadioIndex
5157INT wifi_getApRadioIndex(INT apIndex, INT *output_int)
5158{
5159 if(NULL == output_int)
5160 return RETURN_ERR;
5161 *output_int = apIndex%2;
5162 return RETURN_OK;
5163}
5164
5165// sets the radio index for the specific ap
5166INT wifi_setApRadioIndex(INT apIndex, INT radioIndex)
5167{
5168 //set to config only and wait for wifi reset to apply settings
5169 return RETURN_ERR;
5170}
5171
5172// Get the ACL MAC list per AP
5173INT wifi_getApAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5174{
5175 char cmd[MAX_CMD_SIZE]={'\0'};
5176 int ret = 0;
5177
5178 sprintf(cmd, "hostapd_cli -i %s%d accept_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5179 ret = _syscmd(cmd,macArray,buf_size);
5180 if (ret != 0)
5181 return RETURN_ERR;
5182
5183 return RETURN_OK;
5184}
5185
developere6aafda2022-09-13 14:59:28 +08005186INT wifi_getApDenyAclDevices(INT apIndex, CHAR *macArray, UINT buf_size)
5187{
5188 char cmd[MAX_CMD_SIZE]={'\0'};
5189 int ret = 0;
5190
5191 sprintf(cmd, "hostapd_cli -i %s%d deny_acl SHOW | awk '{print $1}'", AP_PREFIX,apIndex);
5192 ret = _syscmd(cmd,macArray,buf_size);
5193 if (ret != 0)
5194 return RETURN_ERR;
5195
5196 return RETURN_OK;
5197}
5198
5199
developer06a01d92022-09-07 16:32:39 +08005200// Get the list of stations associated per AP
5201INT wifi_getApDevicesAssociated(INT apIndex, CHAR *macArray, UINT buf_size)
5202{
5203 char cmd[128];
5204
5205 if(apIndex > 3) //Currently supporting apIndex upto 3
5206 return RETURN_ERR;
5207 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, apIndex);
5208 //sprintf(buf,"iw dev %s%d station dump | grep Station | cut -d ' ' -f2", AP_PREFIX,apIndex);//alternate method
5209 _syscmd(cmd, macArray, buf_size);
5210
5211 return RETURN_OK;
5212}
5213
5214// adds the mac address to the filter list
5215//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5216INT wifi_addApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5217{
5218 char cmd[MAX_CMD_SIZE]={'\0'};
5219 char buf[MAX_BUF_SIZE]={'\0'};
5220
5221#if 0
5222 sprintf(cmd, "hostapd_cli -i %s%d accept_acl ADD_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5223 if(_syscmd(cmd,buf,sizeof(buf)))
5224 return RETURN_ERR;
5225#endif
5226 sprintf(cmd, "echo '%s' >> %s%d", DeviceMacAddress, ACL_PREFIX, apIndex);
5227 if(_syscmd(cmd,buf,sizeof(buf)))
5228 return RETURN_ERR;
5229
5230 return RETURN_OK;
5231}
5232
5233// deletes the mac address from the filter list
5234//DeviceMacAddress is in XX:XX:XX:XX:XX:XX format
5235INT wifi_delApAclDevice(INT apIndex, CHAR *DeviceMacAddress)
5236{
5237 char cmd[MAX_CMD_SIZE]={'\0'};
5238 char buf[MAX_BUF_SIZE]={'\0'};
5239
5240#if 0
5241 sprintf(cmd, "hostapd_cli -i %s%d accept_acl DEL_MAC %s", AP_PREFIX,apIndex,DeviceMacAddress);
5242 if(_syscmd(cmd,buf,sizeof(buf)))
5243 return RETURN_ERR;
5244
5245#endif
5246 sprintf(cmd, "sed -i '/%s/d' %s%d ", DeviceMacAddress, ACL_PREFIX, apIndex);
5247 if(_syscmd(cmd,buf,sizeof(buf)))
5248 return RETURN_ERR;
5249
5250 return RETURN_OK;
5251}
5252
5253// outputs the number of devices in the filter list
5254INT wifi_getApAclDeviceNum(INT apIndex, UINT *output_uint)
5255{
developere6aafda2022-09-13 14:59:28 +08005256 char cmd[MAX_BUF_SIZE]={0};
5257 char buf[MAX_CMD_SIZE]={0};
5258
5259 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5260 if(output_uint == NULL)
developer06a01d92022-09-07 16:32:39 +08005261 return RETURN_ERR;
developere6aafda2022-09-13 14:59:28 +08005262
5263 snprintf(cmd, sizeof(cmd), "cat %s%d | wc -l | tr -d '\\n'", ACL_PREFIX, apIndex);
5264 _syscmd(cmd, buf, sizeof(buf));
5265
5266 *output_uint = atoi(buf);
5267
5268 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5269 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005270}
5271
5272INT apply_rules(INT apIndex, CHAR *client_mac,CHAR *action,CHAR *interface)
5273{
5274 char cmd[128]={'\0'};
5275 char buf[128]={'\0'};
5276
5277 if(strcmp(action,"DENY")==0)
5278 {
5279 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j DROP",apIndex,interface,client_mac);
5280 system(buf);
5281 return RETURN_OK;
5282 }
5283
5284 if(strcmp(action,"ALLOW")==0)
5285 {
5286 sprintf(buf,"iptables -I WifiServices%d -m physdev --physdev-in %s -m mac --mac-source %s -j RETURN",apIndex,interface,client_mac);
5287 system(buf);
5288 return RETURN_OK;
5289 }
5290
5291 return RETURN_ERR;
5292
5293}
5294
5295// enable kick for devices on acl black list
5296INT wifi_kickApAclAssociatedDevices(INT apIndex, BOOL enable)
5297{
5298 char aclArray[512] = {0}, *acl = NULL;
5299 char assocArray[512] = {0}, *asso = NULL;
5300
developere6aafda2022-09-13 14:59:28 +08005301 wifi_getApDenyAclDevices(apIndex, aclArray, sizeof(aclArray));
developer06a01d92022-09-07 16:32:39 +08005302 wifi_getApDevicesAssociated(apIndex, assocArray, sizeof(assocArray));
5303
5304 // if there are no devices connected there is nothing to do
5305 if (strlen(assocArray) < 17)
5306 return RETURN_OK;
5307
5308 if (enable == TRUE)
5309 {
5310 //kick off the MAC which is in ACL array (deny list)
5311 acl = strtok(aclArray, "\r\n");
5312 while (acl != NULL) {
5313 if (strlen(acl) >= 17 && strcasestr(assocArray, acl))
5314 wifi_kickApAssociatedDevice(apIndex, acl);
5315
5316 acl = strtok(NULL, "\r\n");
5317 }
developere6aafda2022-09-13 14:59:28 +08005318 wifi_setApMacAddressControlMode(apIndex, 2);
developer06a01d92022-09-07 16:32:39 +08005319 }
5320 else
5321 {
developere6aafda2022-09-13 14:59:28 +08005322 wifi_setApMacAddressControlMode(apIndex, 0);
developer06a01d92022-09-07 16:32:39 +08005323 }
5324
5325#if 0
5326 //TODO: need to revisit below implementation
5327 char aclArray[512]={0}, *acl=NULL;
5328 char assocArray[512]={0}, *asso=NULL;
5329 char buf[256]={'\0'};
5330 char action[10]={'\0'};
5331 FILE *fr=NULL;
5332 char interface[10]={'\0'};
5333 char config_file[MAX_BUF_SIZE] = {0};
5334
5335 wifi_getApAclDevices( apIndex, aclArray, sizeof(aclArray));
5336 wifi_getApDevicesAssociated( apIndex, assocArray, sizeof(assocArray));
5337 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5338 wifi_hostapdRead(config_file,"interface",interface,sizeof(interface));
5339
5340 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5341 system(buf);
5342 sprintf(buf,"iptables -D INPUT -j WifiServices%d",apIndex);
5343 system(buf);
5344 sprintf(buf,"iptables -X WifiServices%d",apIndex);
5345 system(buf);
5346 sprintf(buf,"iptables -N WifiServices%d",apIndex);
5347 system(buf);
5348 sprintf(buf,"iptables -I INPUT 21 -j WifiServices%d",apIndex);
5349 system(buf);
5350
5351 if ( enable == TRUE )
5352 {
5353 int device_count=0;
5354 strcpy(action,"DENY");
5355 //kick off the MAC which is in ACL array (deny list)
5356 acl = strtok (aclArray,",");
5357 while (acl != NULL) {
5358 if(strlen(acl)>=17)
5359 {
5360 apply_rules(apIndex, acl,action,interface);
5361 device_count++;
5362 //Register mac to be blocked ,in syscfg.db persistent storage
5363 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5364 system(buf);
5365 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5366 system(buf);
5367 system("syscfg commit");
5368
5369 wifi_kickApAssociatedDevice(apIndex, acl);
5370 }
5371 acl = strtok (NULL, ",");
5372 }
5373 }
5374 else
5375 {
5376 int device_count=0;
5377 char cmdmac[20]={'\0'};
5378 strcpy(action,"ALLOW");
5379 //kick off the MAC which is not in ACL array (allow list)
5380 acl = strtok (aclArray,",");
5381 while (acl != NULL) {
5382 if(strlen(acl)>=17)
5383 {
5384 apply_rules(apIndex, acl,action,interface);
5385 device_count++;
5386 //Register mac to be Allowed ,in syscfg.db persistent storage
5387 sprintf(buf,"syscfg set %dmacfilter%d %s",apIndex,device_count,acl);
5388 system(buf);
5389 sprintf(buf,"syscfg set %dcountfilter %d",apIndex,device_count);
5390 system(buf);
5391 sprintf(cmdmac,"%s",acl);
5392 }
5393 acl = strtok (NULL, ",");
5394 }
5395 sprintf(buf,"iptables -A WifiServices%d -m physdev --physdev-in %s -m mac ! --mac-source %s -j DROP",apIndex,interface,cmdmac);
5396 system(buf);
5397
5398 //Disconnect the mac which is not in ACL
5399 asso = strtok (assocArray,",");
5400 while (asso != NULL) {
5401 if(strlen(asso)>=17 && !strcasestr(aclArray, asso))
5402 wifi_kickApAssociatedDevice(apIndex, asso);
5403 asso = strtok (NULL, ",");
5404 }
5405 }
5406#endif
5407 return RETURN_OK;
5408}
5409
5410INT wifi_setPreferPrivateConnection(BOOL enable)
5411{
5412 char interface_name[100] = {0},ssid_cur_value[50] = {0};
5413 char buf[1024] = {0};
5414
5415 fprintf(stderr,"%s Value of %d",__FUNCTION__,enable);
5416 if(enable == TRUE)
5417 {
5418 GetInterfaceName(interface_name,"/nvram/hostapd4.conf");
5419 sprintf(buf,"ifconfig %s down" ,interface_name);
5420 system(buf);
5421 memset(buf,0,sizeof(buf));
5422 GetInterfaceName(interface_name,"/nvram/hostapd5.conf");
5423 sprintf(buf,"ifconfig %s down" ,interface_name);
5424 system(buf);
5425 }
5426 else
5427 {
5428 File_Reading("cat /tmp/Get5gssidEnable.txt", ssid_cur_value);
5429 if(strcmp(ssid_cur_value,"1") == 0)
5430 wifi_RestartPrivateWifi_5G();
5431 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5432 File_Reading("cat /tmp/GetPub2gssidEnable.txt", ssid_cur_value);
5433 if(strcmp(ssid_cur_value,"1") == 0)
5434 wifi_RestartHostapd_2G();
5435 memset(ssid_cur_value,0,sizeof(ssid_cur_value));
5436 File_Reading("cat /tmp/GetPub5gssidEnable.txt", ssid_cur_value);
5437 if(strcmp(ssid_cur_value,"1") == 0)
5438 wifi_RestartHostapd_5G();
5439 }
5440 return RETURN_OK;
5441}
5442
5443// sets the mac address filter control mode. 0 == filter disabled, 1 == filter as whitelist, 2 == filter as blacklist
5444INT wifi_setApMacAddressControlMode(INT apIndex, INT filterMode)
5445{
5446 int items = 1;
5447 struct params list[2];
5448 char buf[MAX_BUF_SIZE] = {0};
5449 char config_file[MAX_BUF_SIZE] = {0}, acl_file[MAX_BUF_SIZE] = {0};
developer10adcc12022-09-13 14:39:17 +08005450 char deny_file[MAX_BUF_SIZE] = {0};
developer06a01d92022-09-07 16:32:39 +08005451
5452 list[0].name = "macaddr_acl";
developer06a01d92022-09-07 16:32:39 +08005453
developer10adcc12022-09-13 14:39:17 +08005454 if (filterMode == 0) {
5455 sprintf(buf, "%d", 0);
5456 list[0].value = buf;
5457
5458 char cmd[128], rtn[128];
5459 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d deny_acl CLEAR", AP_PREFIX, apIndex);
5460 _syscmd(cmd, rtn, sizeof(rtn));
5461 memset(cmd,0,sizeof(cmd));
5462 // Delete deny_mac_file in hostapd configuration
5463 snprintf(cmd, sizeof(cmd), "sed -i '/deny_mac_file=/d' %s%d.conf ", CONFIG_PREFIX, apIndex);
5464 _syscmd(cmd, rtn, sizeof(rtn));
5465 }
5466 else if (filterMode == 1) {
5467 sprintf(buf, "%d", filterMode);
5468 list[0].value = buf;
developer06a01d92022-09-07 16:32:39 +08005469 sprintf(acl_file,"%s%d",ACL_PREFIX,apIndex);
5470 list[1].name = "accept_mac_file";
5471 list[1].value = acl_file;
5472 items = 2;
developer10adcc12022-09-13 14:39:17 +08005473 } else if (filterMode == 2) {
5474 //TODO: deny_mac_file
5475 sprintf(buf, "%d", 0);
5476 list[0].value = buf;
5477 list[1].name = "deny_mac_file";
5478 sprintf(deny_file,"%s%d", DENY_PREFIX,apIndex);
5479 list[1].value = deny_file;
5480 items = 2;
5481 } else {
5482 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08005483 }
developer10adcc12022-09-13 14:39:17 +08005484
developer06a01d92022-09-07 16:32:39 +08005485 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5486 wifi_hostapdWrite(config_file, list, items);
5487
5488 return RETURN_OK;
5489
5490#if 0
5491 if(apIndex==0 || apIndex==1)
5492 {
5493 //set the filtermode
5494 sprintf(buf,"syscfg set %dblockall %d",apIndex,filterMode);
5495 system(buf);
5496 system("syscfg commit");
5497
5498 if(filterMode==0)
5499 {
5500 sprintf(buf,"iptables -F WifiServices%d",apIndex);
5501 system(buf);
5502 return RETURN_OK;
5503 }
5504 }
5505 return RETURN_OK;
5506#endif
5507}
5508
5509// 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.
5510INT wifi_setApVlanEnable(INT apIndex, BOOL VlanEnabled)
5511{
5512 return RETURN_ERR;
5513}
5514
5515// gets the vlan ID for this ap from an internal enviornment variable
5516INT wifi_getApVlanID(INT apIndex, INT *output_int)
5517{
5518 if(apIndex=0)
5519 {
5520 *output_int=100;
5521 return RETURN_OK;
5522 }
5523
5524 return RETURN_ERR;
5525}
5526
5527// sets the vlan ID for this ap to an internal enviornment variable
5528INT wifi_setApVlanID(INT apIndex, INT vlanId)
5529{
5530 //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)
5531 return RETURN_ERR;
5532}
5533
5534// gets bridgeName, IP address and Subnet. bridgeName is a maximum of 32 characters,
5535INT wifi_getApBridgeInfo(INT index, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5536{
5537 snprintf(bridgeName, 32, "brlan0");
5538 snprintf(IP, 32, "10.0.0.1");
5539 snprintf(subnet, 32, "255.255.255.0");
5540
5541 return RETURN_OK;
5542}
5543
5544//sets bridgeName, IP address and Subnet to internal enviornment variables. bridgeName is a maximum of 32 characters
5545INT wifi_setApBridgeInfo(INT apIndex, CHAR *bridgeName, CHAR *IP, CHAR *subnet)
5546{
5547 //save settings, wait for wifi reset or wifi_pushBridgeInfo to apply.
5548 return RETURN_ERR;
5549}
5550
5551// reset the vlan configuration for this ap
5552INT wifi_resetApVlanCfg(INT apIndex)
5553{
developerf5fef612022-09-20 19:38:26 +08005554 char original_config_file[64] = {0};
5555 char current_config_file[64] = {0};
5556 char buf[64] = {0};
5557 char cmd[64] = {0};
5558 char vlan_file[64] = {0};
5559 char vlan_tagged_interface[16] = {0};
5560 char vlan_bridge[16] = {0};
5561 char vlan_naming[16] = {0};
5562 struct params list[4] = {0};
5563 wifi_band band;
5564
5565 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5566
5567 band = wifi_index_to_band(apIndex);
5568 if (band == band_2_4)
5569 sprintf(original_config_file, "/etc/hostapd-2G.conf");
5570 else if (band = band_5)
5571 sprintf(original_config_file, "/etc/hostapd-5G.conf");
5572 else if (band = band_6)
5573 sprintf(original_config_file, "/etc/hostapd-6G.conf");
5574
5575 wifi_hostapdRead(original_config_file, "vlan_file", vlan_file, sizeof(vlan_file));
5576
5577 if (strlen(vlan_file) == 0)
5578 strcpy(vlan_file, VLAN_FILE);
developer06a01d92022-09-07 16:32:39 +08005579
developerf5fef612022-09-20 19:38:26 +08005580 // The file should exist or this vap would not work.
5581 if (access(vlan_file, F_OK) != 0) {
5582 sprintf(cmd, "touch %s", vlan_file);
5583 _syscmd(cmd, buf, sizeof(buf));
5584 }
5585 list[0].name = "vlan_file";
5586 list[0].value = vlan_file;
5587
5588 wifi_hostapdRead(original_config_file, "vlan_tagged_interface", vlan_tagged_interface, sizeof(vlan_tagged_interface));
5589 list[1].name = "vlan_tagged_interface";
5590 list[1].value = vlan_tagged_interface;
5591
5592 wifi_hostapdRead(original_config_file, "vlan_bridge", vlan_bridge, sizeof(vlan_bridge));
5593 list[2].name = "vlan_bridge";
5594 list[2].value = vlan_bridge;
5595
5596 wifi_hostapdRead(original_config_file, "vlan_naming", vlan_naming, sizeof(vlan_naming));
5597 list[3].name = "vlan_naming";
5598 list[3].value = vlan_naming;
developer06a01d92022-09-07 16:32:39 +08005599
developerf5fef612022-09-20 19:38:26 +08005600 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5601 wifi_hostapdWrite(current_config_file, list, 4);
developer06a01d92022-09-07 16:32:39 +08005602 //Reapply vlan settings
developerf5fef612022-09-20 19:38:26 +08005603 // wifi_pushBridgeInfo(apIndex);
developer06a01d92022-09-07 16:32:39 +08005604
developerf5fef612022-09-20 19:38:26 +08005605 // restart this ap
5606 wifi_setApEnable(apIndex, FALSE);
5607 wifi_setApEnable(apIndex, TRUE);
5608
5609 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5610
5611 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005612}
5613
5614// 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.
5615INT wifi_createHostApdConfig(INT apIndex, BOOL createWpsCfg)
5616{
5617 return RETURN_ERR;
5618}
5619
5620// starts hostapd, uses the variables in the hostapd config with format compatible with the specific hostapd implementation
5621INT wifi_startHostApd()
5622{
5623 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5624 system("systemctl start hostapd.service");
5625 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5626 return RETURN_OK;
5627 //sprintf(cmd, "hostapd -B `cat /tmp/conf_filename` -e /nvram/etc/wpa2/entropy -P /tmp/hostapd.pid 1>&2");
5628}
5629
5630// stops hostapd
5631INT wifi_stopHostApd()
5632{
5633 char cmd[128] = {0};
5634 char buf[128] = {0};
5635
5636 sprintf(cmd,"systemctl stop hostapd");
5637 _syscmd(cmd, buf, sizeof(buf));
5638
5639 return RETURN_OK;
5640}
5641
5642// restart hostapd dummy function
5643INT wifi_restartHostApd()
5644{
5645 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5646 system("systemctl restart hostapd-global");
5647 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5648
5649 return RETURN_OK;
5650}
5651
5652static int align_hostapd_config(int index)
5653{
5654 ULONG lval;
5655 wifi_getRadioChannel(index%2, &lval);
5656 wifi_setRadioChannel(index%2, lval);
5657}
5658
5659// sets the AP enable status variable for the specified ap.
5660INT wifi_setApEnable(INT apIndex, BOOL enable)
5661{
5662 char config_file[MAX_BUF_SIZE] = {0};
5663 char cmd[MAX_CMD_SIZE] = {0};
5664 char buf[MAX_BUF_SIZE] = {0};
5665 BOOL status;
5666
5667 wifi_getApEnable(apIndex,&status);
5668 if (enable == status)
5669 return RETURN_OK;
5670
5671 if (enable == TRUE) {
5672 int radioIndex = apIndex % NUMBER_OF_RADIOS;
5673 align_hostapd_config(apIndex);
5674 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5675 //Hostapd will bring up this interface
5676 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5677 _syscmd(cmd, buf, sizeof(buf));
5678 sprintf(cmd, "hostapd_cli -i global raw ADD bss_config=phy%d:%s", radioIndex, config_file);
5679 _syscmd(cmd, buf, sizeof(buf));
5680 }
5681 else {
5682 sprintf(cmd, "hostapd_cli -i global raw REMOVE %s%d", AP_PREFIX, apIndex);
5683 _syscmd(cmd, buf, sizeof(buf));
5684 sprintf(cmd, "ip link set %s%d down", AP_PREFIX, apIndex);
5685 _syscmd(cmd, buf, sizeof(buf));
5686 }
5687 snprintf(cmd, sizeof(cmd), "sed '/%s%d/c %s%d=%d' -i %s",
5688 AP_PREFIX, apIndex, AP_PREFIX, apIndex, enable, VAP_STATUS_FILE);
5689 _syscmd(cmd, buf, sizeof(buf));
5690 //Wait for wifi up/down to apply
5691 return RETURN_OK;
5692}
5693
5694// Outputs the setting of the internal variable that is set by wifi_setApEnable().
5695INT wifi_getApEnable(INT apIndex, BOOL *output_bool)
5696{
5697 char cmd[MAX_CMD_SIZE] = {'\0'};
5698 char buf[MAX_BUF_SIZE] = {'\0'};
5699
5700 if((!output_bool) || (apIndex < 0) || (apIndex >= MAX_APS))
5701 return RETURN_ERR;
5702
5703 *output_bool = 0;
5704
5705 if((apIndex >= 0) && (apIndex < MAX_APS))//Handling 6 APs
5706 {
developer70490032022-09-13 15:45:20 +08005707 sprintf(cmd, "ifconfig %s%d 2> /dev/null | grep UP", AP_PREFIX, apIndex);
developer06a01d92022-09-07 16:32:39 +08005708 *output_bool = _syscmd(cmd,buf,sizeof(buf))?0:1;
5709 }
5710
5711 return RETURN_OK;
5712}
5713
5714// Outputs the AP "Enabled" "Disabled" status from driver
5715INT wifi_getApStatus(INT apIndex, CHAR *output_string)
5716{
5717 char cmd[128] = {0};
5718 char buf[128] = {0};
5719 BOOL output_bool;
5720
5721 if ( NULL == output_string)
5722 return RETURN_ERR;
5723 wifi_getApEnable(apIndex,&output_bool);
5724
5725 if(output_bool == 1)
5726 snprintf(output_string, 32, "Up");
5727 else
5728 snprintf(output_string, 32, "Disable");
5729
5730 return RETURN_OK;
5731}
5732
5733//Indicates whether or not beacons include the SSID name.
5734// outputs a 1 if SSID on the AP is enabled, else outputs 0
5735INT wifi_getApSsidAdvertisementEnable(INT apIndex, BOOL *output)
5736{
5737 //get the running status
5738 char config_file[MAX_BUF_SIZE] = {0};
5739 char buf[16] = {0};
5740
5741 if (!output)
5742 return RETURN_ERR;
5743
5744 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5745 wifi_hostapdRead(config_file, "ignore_broadcast_ssid", buf, sizeof(buf));
5746 *output = (strncmp("0",buf,1) == 0);
5747
5748 return RETURN_OK;
5749}
5750
5751// sets an internal variable for ssid advertisement. Set to 1 to enable, set to 0 to disable
5752INT wifi_setApSsidAdvertisementEnable(INT apIndex, BOOL enable)
5753{
5754 //store the config, apply instantly
5755 char config_file[MAX_BUF_SIZE] = {0};
5756 struct params list;
5757
5758 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5759 list.name = "ignore_broadcast_ssid";
5760 list.value = enable?"0":"1";
5761
5762 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5763 wifi_hostapdWrite(config_file, &list, 1);
5764 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5765 //TODO: call hostapd_cli for dynamic_config_control
developer384f25c2022-09-13 14:41:20 +08005766 wifi_reloadAp(apIndex);
developer06a01d92022-09-07 16:32:39 +08005767 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5768
5769 return RETURN_OK;
5770}
5771
5772//The maximum number of retransmission for a packet. This corresponds to IEEE 802.11 parameter dot11ShortRetryLimit.
5773INT wifi_getApRetryLimit(INT apIndex, UINT *output_uint)
5774{
5775 //get the running status
5776 if(!output_uint)
5777 return RETURN_ERR;
5778 *output_uint=16;
5779 return RETURN_OK;
5780}
5781
5782INT wifi_setApRetryLimit(INT apIndex, UINT number)
5783{
5784 //apply instantly
5785 return RETURN_ERR;
5786}
5787
5788//Indicates whether this access point supports WiFi Multimedia (WMM) Access Categories (AC).
5789INT wifi_getApWMMCapability(INT apIndex, BOOL *output)
5790{
5791 if(!output)
5792 return RETURN_ERR;
5793 *output=TRUE;
5794 return RETURN_OK;
5795}
5796
5797//Indicates whether this access point supports WMM Unscheduled Automatic Power Save Delivery (U-APSD). Note: U-APSD support implies WMM support.
5798INT wifi_getApUAPSDCapability(INT apIndex, BOOL *output)
5799{
5800 //get the running status from driver
developer0b246d12022-09-30 15:24:20 +08005801 char cmd[128] = {0};
5802 char buf[128] = {0};
5803 int max_radio_num = 0, radioIndex = 0;
developer3ab38042022-09-13 14:17:03 +08005804
developer0b246d12022-09-30 15:24:20 +08005805 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005806
developer0b246d12022-09-30 15:24:20 +08005807 wifi_getMaxRadioNumber(&max_radio_num);
5808 radioIndex = apIndex % max_radio_num;
5809 snprintf(cmd, sizeof(cmd), "iw phy phy%d info | grep u-APSD", radioIndex);
5810 _syscmd(cmd,buf, sizeof(buf));
5811
5812 if (strlen(buf) > 0)
5813 *output = true;
5814
5815 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer3ab38042022-09-13 14:17:03 +08005816
developer06a01d92022-09-07 16:32:39 +08005817 return RETURN_OK;
5818}
5819
5820//Whether WMM support is currently enabled. When enabled, this is indicated in beacon frames.
5821INT wifi_getApWmmEnable(INT apIndex, BOOL *output)
5822{
5823 //get the running status from driver
5824 if(!output)
5825 return RETURN_ERR;
developer3ab38042022-09-13 14:17:03 +08005826
5827 char config_file[MAX_BUF_SIZE] = {0};
5828 char buf[16] = {0};
5829
5830 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5831 wifi_hostapdRead(config_file, "wmm_enabled", buf, sizeof(buf));
5832 if (strncmp("1",buf,1) == 0)
5833 *output = TRUE;
5834 else
5835 *output = FALSE;
5836
developer06a01d92022-09-07 16:32:39 +08005837 return RETURN_OK;
5838}
5839
5840// enables/disables WMM on the hardwawre for this AP. enable==1, disable == 0
5841INT wifi_setApWmmEnable(INT apIndex, BOOL enable)
5842{
5843 //Save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005844 char config_file[MAX_BUF_SIZE] = {0};
5845 struct params list;
5846
5847 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5848 list.name = "wmm_enabled";
5849 list.value = enable?"1":"0";
5850
5851 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5852 wifi_hostapdWrite(config_file, &list, 1);
5853 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5854 wifi_reloadAp(apIndex);
5855 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5856
5857 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005858}
5859
5860//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.
5861INT wifi_getApWmmUapsdEnable(INT apIndex, BOOL *output)
5862{
5863 //get the running status from driver
5864 if(!output)
5865 return RETURN_ERR;
5866 *output=TRUE;
5867 return RETURN_OK;
5868}
5869
5870// enables/disables Automatic Power Save Delivery on the hardwarwe for this AP
5871INT wifi_setApWmmUapsdEnable(INT apIndex, BOOL enable)
5872{
5873 //save config and apply instantly.
developer3ab38042022-09-13 14:17:03 +08005874 char config_file[MAX_BUF_SIZE] = {0};
5875 struct params list;
5876
5877 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5878 list.name = "uapsd_advertisement_enabled";
5879 list.value = enable?"1":"0";
5880
5881 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
5882 wifi_hostapdWrite(config_file, &list, 1);
5883 wifi_hostapdProcessUpdate(apIndex, &list, 1);
5884 wifi_reloadAp(apIndex);
5885 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5886
5887 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005888}
5889
developer6daeb3f2022-09-30 13:36:39 +08005890// Sets the WMM ACK policy on the hardware. AckPolicy false means do not acknowledge, true means acknowledge
developer06a01d92022-09-07 16:32:39 +08005891INT wifi_setApWmmOgAckPolicy(INT apIndex, INT class, BOOL ackPolicy) //RDKB
5892{
developer6daeb3f2022-09-30 13:36:39 +08005893 // assume class 0->BE, 1->BK, 2->VI, 3->VO
5894 char cmd[128] = {0};
5895 char buf[128] = {0};
5896 char ack_filepath[128] = {0};
5897 uint16_t bitmap = 0;
5898 uint16_t class_map[4] = {0x0009, 0x0006, 0x0030, 0x00C0};
5899 FILE *f = NULL;
5900
5901 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
5902
5903 // Get current setting
5904 snprintf(ack_filepath, sizeof(ack_filepath), "%s%d.txt", NOACK_MAP_FILE, apIndex);
5905 snprintf(cmd, sizeof(cmd), "cat %s 2> /dev/null", ack_filepath);
5906 _syscmd(cmd, buf, sizeof(buf));
5907 if (strlen(buf) > 0)
5908 bitmap = strtoul(buf, NULL, 10);
5909
5910 bitmap = strtoul(buf, NULL, 10);
5911
5912 if (ackPolicy == TRUE) { // True, unset this class
5913 bitmap &= ~class_map[class];
5914 } else { // False, set this class
5915 bitmap |= class_map[class];
5916 }
5917
5918 f = fopen(ack_filepath, "w");
5919 if (f == NULL) {
5920 fprintf(stderr, "%s: fopen failed\n", __func__);
5921 return RETURN_ERR;
5922 }
5923 fprintf(f, "%hu", bitmap);
5924 fclose(f);
5925
5926 snprintf(cmd, sizeof(cmd), "iw dev %s%d set noack_map 0x%04x\n", AP_PREFIX, apIndex, bitmap);
5927 _syscmd(cmd, buf, sizeof(buf));
5928
5929 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
5930 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005931}
5932
5933//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.
5934INT wifi_getApMaxAssociatedDevices(INT apIndex, UINT *output_uint)
5935{
5936 //get the running status from driver
5937 if(!output_uint)
5938 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08005939
5940 char output[16]={'\0'};
5941 char config_file[MAX_BUF_SIZE] = {0};
5942
5943 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
5944 wifi_hostapdRead(config_file, "max_num_sta", output, sizeof(output));
5945 if (strlen(output) == 0) *output_uint = MAX_ASSOCIATED_STA_NUM;
5946 else {
5947 int device_num = atoi(output);
5948 if (device_num > MAX_ASSOCIATED_STA_NUM || device_num < 0) {
5949 wifi_dbg_printf("\n[%s]: get max_num_sta error: %d", __func__, device_num);
5950 return RETURN_ERR;
5951 }
5952 else {
5953 *output_uint = device_num;
5954 }
5955 }
5956
developer06a01d92022-09-07 16:32:39 +08005957 return RETURN_OK;
5958}
5959
5960INT wifi_setApMaxAssociatedDevices(INT apIndex, UINT number)
5961{
5962 //store to wifi config, apply instantly
developer0947e1a2022-09-13 14:15:25 +08005963 char str[MAX_BUF_SIZE]={'\0'};
5964 char cmd[MAX_CMD_SIZE]={'\0'};
5965 struct params params;
5966 char config_file[MAX_BUF_SIZE] = {0};
5967
5968 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
5969 if (number > MAX_ASSOCIATED_STA_NUM || number < 0) {
5970 WIFI_ENTRY_EXIT_DEBUG("%s: Invalid input\n",__func__);
5971 return RETURN_ERR;
5972 }
5973 sprintf(str, "%d", number);
5974 params.name = "max_num_sta";
5975 params.value = str;
5976
5977 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX, apIndex);
5978 int ret = wifi_hostapdWrite(config_file, &params, 1);
5979 if (ret) {
5980 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdWrite() return %d\n"
5981 ,__func__, ret);
5982 }
5983
5984 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
5985 if (ret) {
5986 WIFI_ENTRY_EXIT_DEBUG("Inside %s: wifi_hostapdProcessUpdate() return %d\n"
5987 ,__func__, ret);
5988 }
5989 wifi_reloadAp(apIndex);
5990 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
5991
5992 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08005993}
5994
5995//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.
5996INT wifi_getApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT *output_uint)
5997{
5998 //get the current threshold
5999 if(!output_uint)
6000 return RETURN_ERR;
developer0947e1a2022-09-13 14:15:25 +08006001 wifi_getApMaxAssociatedDevices(apIndex, output_uint);
6002 if (*output_uint == 0)
6003 *output_uint = 50;
developer06a01d92022-09-07 16:32:39 +08006004 return RETURN_OK;
6005}
6006
6007INT wifi_setApAssociatedDevicesHighWatermarkThreshold(INT apIndex, UINT Threshold)
6008{
6009 //store the config, reset threshold, reset AssociatedDevicesHighWatermarkThresholdReached, reset AssociatedDevicesHighWatermarkDate to current time
developer0947e1a2022-09-13 14:15:25 +08006010 if (!wifi_setApMaxAssociatedDevices(apIndex, Threshold))
6011 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006012 return RETURN_ERR;
6013}
6014
6015//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.
6016INT wifi_getApAssociatedDevicesHighWatermarkThresholdReached(INT apIndex, UINT *output_uint)
6017{
6018 if(!output_uint)
6019 return RETURN_ERR;
6020 *output_uint = 3;
6021 return RETURN_OK;
6022}
6023
6024//Maximum number of associated devices that have ever associated with the access point concurrently since the last reset of the device or WiFi module.
6025INT wifi_getApAssociatedDevicesHighWatermark(INT apIndex, UINT *output_uint)
6026{
6027 if(!output_uint)
6028 return RETURN_ERR;
6029 *output_uint = 3;
6030 return RETURN_OK;
6031}
6032
6033//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.
6034INT wifi_getApAssociatedDevicesHighWatermarkDate(INT apIndex, ULONG *output_in_seconds)
6035{
6036 if(!output_in_seconds)
6037 return RETURN_ERR;
6038 *output_in_seconds = 0;
6039 return RETURN_OK;
6040}
6041
6042//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
6043INT wifi_getApSecurityModesSupported(INT apIndex, CHAR *output)
6044{
6045 if(!output || apIndex>=MAX_APS)
6046 return RETURN_ERR;
6047 //snprintf(output, 128, "None,WPA-Personal,WPA2-Personal,WPA-WPA2-Personal,WPA-Enterprise,WPA2-Enterprise,WPA-WPA2-Enterprise");
developer587c1b62022-09-27 15:58:59 +08006048 snprintf(output, 128, "None,WPA2-Personal,WPA-WPA2-Personal,WPA2-Enterprise,WPA-WPA2-Enterprise,WPA3-Personal,WPA3-Enterprise");
developer06a01d92022-09-07 16:32:39 +08006049 return RETURN_OK;
6050}
6051
6052//The value MUST be a member of the list reported by the ModesSupported parameter. Indicates which security mode is enabled.
6053INT wifi_getApSecurityModeEnabled(INT apIndex, CHAR *output)
6054{
developer587c1b62022-09-27 15:58:59 +08006055 char config_file[128] = {0};
6056 char wpa[16] = {0};
6057 char key_mgmt[64] = {0};
6058 char buf[16] = {0};
developer06a01d92022-09-07 16:32:39 +08006059 if (!output)
6060 return RETURN_ERR;
6061
6062 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
developer587c1b62022-09-27 15:58:59 +08006063 wifi_hostapdRead(config_file, "wpa", wpa, sizeof(wpa));
developer06a01d92022-09-07 16:32:39 +08006064
developer587c1b62022-09-27 15:58:59 +08006065 strcpy(output, "None");//Copying "None" to output string for default case
6066 wifi_hostapdRead(config_file, "wpa_key_mgmt", key_mgmt, sizeof(key_mgmt));
6067 if (strstr(key_mgmt, "WPA-PSK")) {
6068 if (strcmp(wpa, "1"))
6069 snprintf(output, 32, "WPA-Personal");
6070 else if (strcmp(wpa, "2"))
6071 snprintf(output, 32, "WPA2-Personal");
6072 else if (strcmp(wpa, "3"))
6073 snprintf(output, 32, "WPA-WPA2-Personal");
6074
6075 } else if (strstr(key_mgmt, "WPA-EAP")) {
6076 if (strcmp(wpa, "1"))
6077 snprintf(output, 32, "WPA-Enterprise");
6078 else if (strcmp(wpa, "2"))
6079 snprintf(output, 32, "WPA2-Enterprise");
6080 else if (strcmp(wpa, "3"))
6081 snprintf(output, 32, "WPA-WPA2-Enterprise");
6082 } else if (strstr(key_mgmt, "SAE")) {
6083 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
6084 int disable = strtol(buf, NULL, 16);
6085 if (disable & 0x1)
6086 snprintf(output, 32, "WPA3-Personal");
6087 else
6088 snprintf(output, 32, "WPA3-Transition");
6089 } else if (strstr(key_mgmt, "WPA-EAP-SUITE-B-192")) {
6090 snprintf(output, 32, "WPA3-Enterprise");
6091 }
developer06a01d92022-09-07 16:32:39 +08006092
6093 //save the beaconTypeString to wifi config and hostapd config file. Wait for wifi reset or hostapd restart to apply
6094 return RETURN_OK;
6095#if 0
6096 //TODO: need to revisit below implementation
6097 char securityType[32], authMode[32];
6098 int enterpriseMode=0;
6099
6100 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6101 if(!output)
6102 return RETURN_ERR;
6103
6104 wifi_getApBeaconType(apIndex, securityType);
6105 strcpy(output,"None");//By default, copying "None" to output string
6106 if (strncmp(securityType,"None", strlen("None")) == 0)
6107 return RETURN_OK;
6108
6109 wifi_getApBasicAuthenticationMode(apIndex, authMode);
6110 enterpriseMode = (strncmp(authMode, "EAPAuthentication", strlen("EAPAuthentication")) == 0)? 1: 0;
6111
6112 if (strncmp(securityType, "WPAand11i", strlen("WPAand11i")) == 0)
6113 snprintf(output, 32, enterpriseMode==1? "WPA-WPA2-Enterprise": "WPA-WPA2-Personal");
6114 else if (strncmp(securityType, "WPA", strlen("WPA")) == 0)
6115 snprintf(output, 32, enterpriseMode==1? "WPA-Enterprise": "WPA-Personal");
6116 else if (strncmp(securityType, "11i", strlen("11i")) == 0)
6117 snprintf(output, 32, enterpriseMode==1? "WPA2-Enterprise": "WPA2-Personal");
6118 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6119
6120 return RETURN_OK;
6121#endif
6122}
6123
6124INT wifi_setApSecurityModeEnabled(INT apIndex, CHAR *encMode)
6125{
6126 char securityType[32];
6127 char authMode[32];
6128
6129 //store settings and wait for wifi up to apply
6130 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6131 if(!encMode)
6132 return RETURN_ERR;
6133
developer06a01d92022-09-07 16:32:39 +08006134 if (strcmp(encMode, "None")==0)
6135 {
6136 strcpy(securityType,"None");
6137 strcpy(authMode,"None");
6138 }
6139 else if (strcmp(encMode, "WPA-WPA2-Personal")==0)
6140 {
6141 strcpy(securityType,"WPAand11i");
6142 strcpy(authMode,"PSKAuthentication");
6143 }
6144 else if (strcmp(encMode, "WPA-WPA2-Enterprise")==0)
6145 {
6146 strcpy(securityType,"WPAand11i");
6147 strcpy(authMode,"EAPAuthentication");
6148 }
6149 else if (strcmp(encMode, "WPA-Personal")==0)
6150 {
6151 strcpy(securityType,"WPA");
6152 strcpy(authMode,"PSKAuthentication");
6153 }
6154 else if (strcmp(encMode, "WPA-Enterprise")==0)
6155 {
6156 strcpy(securityType,"WPA");
6157 strcpy(authMode,"EAPAuthentication");
6158 }
6159 else if (strcmp(encMode, "WPA2-Personal")==0)
6160 {
6161 strcpy(securityType,"11i");
6162 strcpy(authMode,"PSKAuthentication");
6163 }
6164 else if (strcmp(encMode, "WPA2-Enterprise")==0)
6165 {
6166 strcpy(securityType,"11i");
6167 strcpy(authMode,"EAPAuthentication");
6168 }
developer587c1b62022-09-27 15:58:59 +08006169 else if (strcmp(encMode, "WPA3-Personal") == 0)
6170 {
6171 strcpy(securityType,"11i");
6172 strcpy(authMode,"SAEAuthentication");
6173 }
6174 else if (strcmp(encMode, "WPA3-Enterprise") == 0)
6175 {
6176 strcpy(securityType,"11i");
6177 strcpy(authMode,"EAP_192-bit_Authentication");
6178 }
developer06a01d92022-09-07 16:32:39 +08006179 else
6180 {
6181 strcpy(securityType,"None");
6182 strcpy(authMode,"None");
6183 }
6184 wifi_setApBeaconType(apIndex, securityType);
6185 wifi_setApBasicAuthenticationMode(apIndex, authMode);
6186 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6187
6188 return RETURN_OK;
6189}
6190
6191
6192//A literal PreSharedKey (PSK) expressed as a hexadecimal string.
6193// output_string must be pre-allocated as 64 character string by caller
6194// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6195INT wifi_getApSecurityPreSharedKey(INT apIndex, CHAR *output_string)
6196{
6197 char buf[16];
6198 char config_file[MAX_BUF_SIZE] = {0};
6199
6200 if(output_string==NULL)
6201 return RETURN_ERR;
6202
6203 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6204 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6205
6206 if(strcmp(buf,"0")==0)
6207 {
6208 printf("wpa_mode is %s ......... \n",buf);
6209 return RETURN_ERR;
6210 }
6211
6212 wifi_dbg_printf("\nFunc=%s\n",__func__);
6213 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6214 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6215 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6216
6217 return RETURN_OK;
6218}
6219
6220// sets an enviornment variable for the psk. Input string preSharedKey must be a maximum of 64 characters
6221// PSK Key of 8 to 63 characters is considered an ASCII string, and 64 characters are considered as HEX value
6222INT wifi_setApSecurityPreSharedKey(INT apIndex, CHAR *preSharedKey)
6223{
6224 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6225 struct params params={'\0'};
6226 int ret;
6227 char config_file[MAX_BUF_SIZE] = {0};
6228
6229 if(NULL == preSharedKey)
6230 return RETURN_ERR;
6231
6232 params.name = "wpa_passphrase";
6233
6234 if(strlen(preSharedKey)<8 || strlen(preSharedKey)>63)
6235 {
6236 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6237 return RETURN_ERR;
6238 }
6239 params.value = preSharedKey;
6240 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6241 ret = wifi_hostapdWrite(config_file, &params, 1);
6242 if(!ret)
6243 ret = wifi_hostapdProcessUpdate(apIndex, &params, 1);
6244 return ret;
6245 //TODO: call hostapd_cli for dynamic_config_control
6246}
6247
6248//A passphrase from which the PreSharedKey is to be generated, for WPA-Personal or WPA2-Personal or WPA-WPA2-Personal security modes.
6249// outputs the passphrase, maximum 63 characters
6250INT wifi_getApSecurityKeyPassphrase(INT apIndex, CHAR *output_string)
6251{
6252 char config_file[MAX_BUF_SIZE] = {0}, buf[32] = {0};
6253
6254 wifi_dbg_printf("\nFunc=%s\n",__func__);
6255 if (NULL == output_string)
6256 return RETURN_ERR;
6257
6258 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6259 wifi_hostapdRead(config_file,"wpa",buf,sizeof(buf));
6260 if(strcmp(buf,"0")==0)
6261 {
6262 printf("wpa_mode is %s ......... \n",buf);
6263 return RETURN_ERR;
6264 }
6265
6266 wifi_hostapdRead(config_file,"wpa_passphrase",output_string,64);
6267 wifi_dbg_printf("\noutput_string=%s\n",output_string);
6268
6269 return RETURN_OK;
6270}
6271
6272// sets the passphrase enviornment variable, max 63 characters
6273INT wifi_setApSecurityKeyPassphrase(INT apIndex, CHAR *passPhrase)
6274{
6275 //save to wifi config and hotapd config. wait for wifi reset or hostapd restet to apply
6276 struct params params={'\0'};
6277 char config_file[MAX_BUF_SIZE] = {0};
6278 int ret;
6279
6280 if(NULL == passPhrase)
6281 return RETURN_ERR;
6282
6283 if(strlen(passPhrase)<8 || strlen(passPhrase)>63)
6284 {
6285 wifi_dbg_printf("\nCannot Set Preshared Key length of preshared key should be 8 to 63 chars\n");
6286 return RETURN_ERR;
6287 }
6288 params.name = "wpa_passphrase";
6289 params.value = passPhrase;
6290 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
6291 ret=wifi_hostapdWrite(config_file,&params,1);
6292 if(!ret)
6293 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6294
6295 return ret;
6296}
6297
6298//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.
6299INT wifi_setApSecurityReset(INT apIndex)
6300{
developer8d583982022-09-20 11:28:22 +08006301 char original_config_file[64] = {0};
6302 char current_config_file[64] = {0};
6303 char buf[64] = {0};
6304 char cmd[64] = {0};
6305 char wpa[4] = {0};
6306 char wpa_psk[64] = {0};
6307 char wpa_passphrase[64] = {0};
6308 char wpa_psk_file[128] = {0};
6309 char wpa_key_mgmt[64] = {0};
6310 char wpa_pairwise[32] = {0};
6311 wifi_band band;
6312 struct params list[6];
6313
6314 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6315
6316 band = wifi_index_to_band(apIndex);
6317 if (band == band_2_4)
6318 sprintf(original_config_file, "/etc/hostapd-2G.conf");
6319 else if (band = band_5)
6320 sprintf(original_config_file, "/etc/hostapd-5G.conf");
6321 else if (band = band_6)
6322 sprintf(original_config_file, "/etc/hostapd-6G.conf");
6323 else
6324 return RETURN_ERR;
6325
6326 wifi_hostapdRead(original_config_file, "wpa", wpa, sizeof(wpa));
6327 list[0].name = "wpa";
6328 list[0].value = wpa;
6329
6330 wifi_hostapdRead(original_config_file, "wpa_psk", wpa_psk, sizeof(wpa_psk));
6331 list[1].name = "wpa_psk";
6332 list[1].value = wpa_psk;
6333
6334 wifi_hostapdRead(original_config_file, "wpa_passphrase", wpa_passphrase, sizeof(wpa_passphrase));
6335 list[2].name = "wpa_passphrase";
6336 list[2].value = wpa_passphrase;
6337
6338 wifi_hostapdRead(original_config_file, "wpa_psk_file", wpa_psk_file, sizeof(wpa_psk_file));
6339
6340 if (strlen(wpa_psk_file) == 0)
6341 strcpy(wpa_psk_file, PSK_FILE);
6342
6343 if (access(wpa_psk_file, F_OK) != 0) {
6344 sprintf(cmd, "touch %s", wpa_psk_file);
6345 _syscmd(cmd, buf, sizeof(buf));
6346 }
6347 list[3].name = "wpa_psk_file";
6348 list[3].value = wpa_psk_file;
6349
6350 wifi_hostapdRead(original_config_file, "wpa_key_mgmt", wpa_key_mgmt, sizeof(wpa_key_mgmt));
6351 list[4].name = "wpa_key_mgmt";
6352 list[4].value = wpa_key_mgmt;
6353
6354 wifi_hostapdRead(original_config_file, "wpa_pairwise", wpa_pairwise, sizeof(wpa_pairwise));
6355 list[5].name = "wpa_pairwise";
6356 list[5].value = wpa_pairwise;
6357
6358 sprintf(current_config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
6359 wifi_hostapdWrite(current_config_file, list, 6);
6360
6361 wifi_setApEnable(apIndex, FALSE);
6362 wifi_setApEnable(apIndex, TRUE);
6363
6364 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6365 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006366}
6367
6368//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).
6369INT wifi_getApSecurityRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6370{
developer8f2ddd52022-09-13 15:39:24 +08006371 char config_file[64] = {0};
6372 char buf[64] = {0};
6373 char cmd[256] = {0};
6374
6375 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6376
developer06a01d92022-09-07 16:32:39 +08006377 if(!IP_output || !Port_output || !RadiusSecret_output)
6378 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +08006379
developer8f2ddd52022-09-13 15:39:24 +08006380 // Read the first matched config
6381 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6382 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6383 _syscmd(cmd, buf, sizeof(buf));
6384 strncpy(IP_output, buf, 64);
6385
6386 memset(buf, 0, sizeof(buf));
6387 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6388 _syscmd(cmd, buf, sizeof(buf));
6389 *Port_output = atoi(buf);
6390
6391 memset(buf, 0, sizeof(buf));
6392 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | head -n1 | tr -d \"\\n\"", config_file);
6393 _syscmd(cmd, buf, sizeof(buf));
6394 strncpy(RadiusSecret_output, buf, 64);
6395
6396 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006397 return RETURN_OK;
6398}
6399
6400INT wifi_setApSecurityRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6401{
developer8f2ddd52022-09-13 15:39:24 +08006402 char config_file[64] = {0};
6403 char port_str[8] = {0};
6404 char cmd[256] = {0};
6405 char buf[128] = {0};
6406
6407 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6408
6409 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6410
6411 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 1'", config_file);
6412 _syscmd(cmd, buf, sizeof(buf));
6413 memset(cmd, 0, sizeof(cmd));
6414
6415 snprintf(port_str, sizeof(port_str), "%d", port);
6416 if (strlen(buf) == 0)
6417 // Append
6418 snprintf(cmd, sizeof(cmd), "echo -e '# radius 1\\n"
6419 "auth_server_addr=%s\\n"
6420 "auth_server_port=%s\\n"
6421 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6422 else {
6423 // Delete the three lines setting after the "# radius 1" comment
6424 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 1/{n;N;N;d}' %s", config_file);
6425 _syscmd(cmd, buf, sizeof(buf));
6426 memset(cmd, 0, sizeof(cmd));
6427 // Use "# radius 1" comment to find the location to insert the radius setting
6428 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 1/"
6429 "# radius 1\\n"
6430 "auth_server_addr=%s\\n"
6431 "auth_server_port=%s\\n"
6432 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6433 }
6434 if(_syscmd(cmd, buf, sizeof(buf))) {
6435 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6436 return RETURN_ERR;
6437 }
6438
6439 wifi_reloadAp(apIndex);
6440 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6441 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006442}
6443
6444INT wifi_getApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IP_output, UINT *Port_output, CHAR *RadiusSecret_output)
6445{
developer8f2ddd52022-09-13 15:39:24 +08006446 char config_file[64] = {0};
6447 char buf[64] = {0};
6448 char cmd[256] = {0};
6449
6450 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6451
developer06a01d92022-09-07 16:32:39 +08006452 if(!IP_output || !Port_output || !RadiusSecret_output)
6453 return RETURN_ERR;
developer8f2ddd52022-09-13 15:39:24 +08006454
6455 // Read the second matched config
6456 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6457 sprintf(cmd, "cat %s | grep \"^auth_server_addr=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6458 _syscmd(cmd, buf, sizeof(buf));
6459 strncpy(IP_output, buf, 64);
6460
6461 memset(buf, 0, sizeof(buf));
6462 sprintf(cmd, "cat %s | grep \"^auth_server_port=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6463 _syscmd(cmd, buf, sizeof(buf));
6464 *Port_output = atoi(buf);
6465
6466 memset(buf, 0, sizeof(buf));
6467 sprintf(cmd, "cat %s | grep \"^auth_server_shared_secret=\" | cut -d \"=\" -f 2 | tail -n +2 | head -n1 | tr -d \"\\n\"", config_file);
6468 _syscmd(cmd, buf, sizeof(buf));
6469 strncpy(RadiusSecret_output, buf, 64);
6470
6471 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08006472 return RETURN_OK;
6473}
6474
6475INT wifi_setApSecuritySecondaryRadiusServer(INT apIndex, CHAR *IPAddress, UINT port, CHAR *RadiusSecret)
6476{
developer8f2ddd52022-09-13 15:39:24 +08006477 char config_file[64] = {0};
6478 char port_str[8] = {0};
6479 char cmd[256] = {0};
6480 char buf[128] = {0};
6481
6482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6483
6484 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6485
6486 snprintf(cmd, sizeof(cmd), "cat %s | grep '# radius 2'", config_file);
6487 _syscmd(cmd, buf, sizeof(buf));
6488 memset(cmd, 0, sizeof(cmd));
6489
6490 snprintf(port_str, sizeof(port_str), "%d", port);
6491 if (strlen(buf) == 0)
6492 // Append
6493 snprintf(cmd, sizeof(cmd), "echo -e '# radius 2\\n"
6494 "auth_server_addr=%s\\n"
6495 "auth_server_port=%s\\n"
6496 "auth_server_shared_secret=%s' >> %s", IPAddress, port_str, RadiusSecret, config_file);
6497 else {
6498 // Delete the three lines setting after the "# radius 2" comment
6499 snprintf(cmd, sizeof(cmd), "sed -i '/# radius 2/{n;N;N;d}' %s", config_file);
6500 _syscmd(cmd, buf, sizeof(buf));
6501 memset(cmd, 0, sizeof(cmd));
6502 // Use "# radius 2" comment to find the location to insert the radius setting
6503 snprintf(cmd, sizeof(cmd), "sed -i 's/# radius 2/"
6504 "# radius 2\\n"
6505 "auth_server_addr=%s\\n"
6506 "auth_server_port=%s\\n"
6507 "auth_server_shared_secret=%s/' %s", IPAddress, port_str, RadiusSecret, config_file);
6508 }
6509 if(_syscmd(cmd, buf, sizeof(buf))) {
6510 wifi_dbg_printf("%s: command failed, cmd: %s\n", __func__, cmd);
6511 return RETURN_ERR;
6512 }
6513
6514 wifi_reloadAp(apIndex);
6515 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6516 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08006517}
6518
6519//RadiusSettings
6520INT wifi_getApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *output)
6521{
6522 if(!output)
6523 return RETURN_ERR;
6524
6525 output->RadiusServerRetries = 3; //Number of retries for Radius requests.
6526 output->RadiusServerRequestTimeout = 5; //Radius request timeout in seconds after which the request must be retransmitted for the # of retries available.
6527 output->PMKLifetime = 28800; //Default time in seconds after which a Wi-Fi client is forced to ReAuthenticate (def 8 hrs).
6528 output->PMKCaching = FALSE; //Enable or disable caching of PMK.
6529 output->PMKCacheInterval = 300; //Time interval in seconds after which the PMKSA (Pairwise Master Key Security Association) cache is purged (def 5 minutes).
6530 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.
6531 output->BlacklistTableTimeout = 600; //Time interval in seconds for which a client will continue to be blacklisted once it is marked so.
6532 output->IdentityRequestRetryInterval = 5; //Time Interval in seconds between identity requests retries. A value of 0 (zero) disables it.
6533 output->QuietPeriodAfterFailedAuthentication = 5; //The enforced quiet period (time interval) in seconds following failed authentication. A value of 0 (zero) disables it.
6534 //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.
6535
6536 return RETURN_OK;
6537}
6538
6539INT wifi_setApSecurityRadiusSettings(INT apIndex, wifi_radius_setting_t *input)
6540{
6541 //store the paramters, and apply instantly
6542 return RETURN_ERR;
6543}
6544
6545//Device.WiFi.AccessPoint.{i}.WPS.Enable
6546//Enables or disables WPS functionality for this access point.
6547// outputs the WPS enable state of this ap in output_bool
6548INT wifi_getApWpsEnable(INT apIndex, BOOL *output_bool)
6549{
6550 char buf[MAX_BUF_SIZE] = {0}, cmd[MAX_CMD_SIZE] = {0}, *value;
6551 if(!output_bool || !(apIndex==0 || apIndex==1))
6552 return RETURN_ERR;
6553 sprintf(cmd,"hostapd_cli -i %s%d get_config | grep wps_state | cut -d '=' -f2", AP_PREFIX, apIndex);
6554 _syscmd(cmd, buf, sizeof(buf));
6555 if(strstr(buf, "configured"))
6556 *output_bool=TRUE;
6557 else
6558 *output_bool=FALSE;
6559
6560 return RETURN_OK;
6561}
6562
6563//Device.WiFi.AccessPoint.{i}.WPS.Enable
6564// sets the WPS enable enviornment variable for this ap to the value of enableValue, 1==enabled, 0==disabled
6565INT wifi_setApWpsEnable(INT apIndex, BOOL enable)
6566{
6567 char config_file[MAX_BUF_SIZE] = {0};
6568 struct params params;
6569
6570 if(!(apIndex==0 || apIndex==1))
6571 return RETURN_ERR;
6572 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6573 //store the paramters, and wait for wifi up to apply
6574 params.name = "wps_state";
6575 params.value = enable ? "2":"0";
6576
6577 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6578 wifi_hostapdWrite(config_file, &params, 1);
6579 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6580 wifi_reloadAp(apIndex);
6581
6582 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6583 return RETURN_OK;
6584}
6585
6586//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
6587INT wifi_getApWpsConfigMethodsSupported(INT apIndex, CHAR *output)
6588{
6589 if(!output)
6590 return RETURN_ERR;
6591 snprintf(output, 128, "PushButton,PIN");
6592 return RETURN_OK;
6593}
6594
6595//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6596//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.
6597// Outputs a common separated list of the enabled WPS config methods, 64 bytes max
6598INT wifi_getApWpsConfigMethodsEnabled(INT apIndex, CHAR *output)
6599{
6600 if(!output)
6601 return RETURN_ERR;
6602 snprintf(output, 64, "PushButton,PIN");//Currently, supporting these two methods
6603
6604 return RETURN_OK;
6605}
6606
6607//Device.WiFi.AccessPoint.{i}.WPS.ConfigMethodsEnabled
6608// 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
6609INT wifi_setApWpsConfigMethodsEnabled(INT apIndex, CHAR *methodString)
6610{
6611 //apply instantly. No setting need to be stored.
6612 char methods[MAX_BUF_SIZE], *token, *next_token;
6613 char config_file[MAX_BUF_SIZE], config_methods[MAX_BUF_SIZE] = {0};
6614 struct params params;
6615
6616 if(!methodString || !(apIndex==0 || apIndex==1))
6617 return RETURN_ERR;
6618 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6619 //store the paramters, and wait for wifi up to apply
6620
6621 snprintf(methods, sizeof(methods), "%s", methodString);
6622 for(token=methods; *token; token=next_token)
6623 {
6624 strtok_r(token, ",", &next_token);
6625 if(*token=='U' && !strcmp(methods, "USBFlashDrive"))
6626 snprintf(config_methods, sizeof(config_methods), "%s ", "usba");
6627 else if(*token=='E')
6628 {
6629 if(!strcmp(methods, "Ethernet"))
6630 snprintf(config_methods, sizeof(config_methods), "%s ", "ethernet");
6631 else if(!strcmp(methods, "ExternalNFCToken"))
6632 snprintf(config_methods, sizeof(config_methods), "%s ", "ext_nfc_token");
6633 else
6634 printf("%s: Unknown WpsConfigMethod\n", __func__);
6635 }
6636 else if(*token=='I' && !strcmp(token, "IntegratedNFCToken"))
6637 snprintf(config_methods, sizeof(config_methods), "%s ", "int_nfc_token");
6638 else if(*token=='N' && !strcmp(token, "NFCInterface"))
6639 snprintf(config_methods, sizeof(config_methods), "%s ", "nfc_interface");
6640 else if(*token=='P' )
6641 {
6642 if(!strcmp(token, "PushButton"))
6643 snprintf(config_methods, sizeof(config_methods), "%s ", "virtual_push_button");
6644 else if(!strcmp(token, "PIN"))
6645 snprintf(config_methods, sizeof(config_methods), "%s ", "keypad");
6646 else
6647 printf("%s: Unknown WpsConfigMethod\n", __func__);
6648 }
6649 else
6650 printf("%s: Unknown WpsConfigMethod\n", __func__);
6651 }
6652 params.name = "config_methods";
6653 params.value = config_methods;
6654 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6655 wifi_hostapdWrite(config_file, &params, 1);
6656 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6657 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6658
6659 return RETURN_OK;
6660}
6661
6662// outputs the pin value, ulong_pin must be allocated by the caller
6663INT wifi_getApWpsDevicePIN(INT apIndex, ULONG *output_ulong)
6664{
6665 char buf[MAX_BUF_SIZE] = {0};
6666 char cmd[MAX_CMD_SIZE] = {0};
6667
6668 if(!output_ulong || !(apIndex==0 || apIndex==1))
6669 return RETURN_ERR;
6670 snprintf(cmd, sizeof(cmd), "cat %s%d.conf | grep ap_pin | cut -d '=' -f2", CONFIG_PREFIX, apIndex);
6671 _syscmd(cmd, buf, sizeof(buf));
6672 if(strlen(buf) > 0)
6673 *output_ulong=strtoul(buf, NULL, 10);
6674
6675 return RETURN_OK;
6676}
6677
6678// set an enviornment variable for the WPS pin for the selected AP. Normally, Device PIN should not be changed.
6679INT wifi_setApWpsDevicePIN(INT apIndex, ULONG pin)
6680{
6681 //set the pin to wifi config and hostpad config. wait for wifi reset or hostapd reset to apply
6682 char ap_pin[16] = {0};
6683 char buf[MAX_BUF_SIZE] = {0};
6684 char config_file[MAX_BUF_SIZE] = {0};
6685 ULONG prev_pin = 0;
6686 struct params params;
6687
6688 if(!(apIndex==0 || apIndex==1))
6689 return RETURN_ERR;
6690 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6691 snprintf(ap_pin, sizeof(ap_pin), "%lu", pin);
6692 params.name = "ap_pin";
6693 params.value = ap_pin;
6694 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
6695 wifi_hostapdWrite(config_file, &params, 1);
6696 wifi_hostapdProcessUpdate(apIndex, &params, 1);
6697 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6698
6699 return RETURN_OK;
6700}
6701
6702// Output string is either Not configured or Configured, max 32 characters
6703INT wifi_getApWpsConfigurationState(INT apIndex, CHAR *output_string)
6704{
6705 char cmd[MAX_CMD_SIZE];
6706 char buf[MAX_BUF_SIZE]={0};
6707
6708 if(!output_string || !(apIndex==0 || apIndex==1))
6709 return RETURN_ERR;
6710 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6711 snprintf(output_string, 32, "Not configured");
6712 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep wps_state | cut -d'=' -f2", AP_PREFIX, apIndex);
6713 _syscmd(cmd, buf, sizeof(buf));
6714
developer348e3d92022-09-13 14:48:41 +08006715 if(!strncmp(buf, "configured", 10))
developer06a01d92022-09-07 16:32:39 +08006716 snprintf(output_string, 32, "Configured");
6717 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6718
6719 return RETURN_OK;
6720}
6721
6722// sets the WPS pin for this AP
6723INT wifi_setApWpsEnrolleePin(INT apIndex, CHAR *pin)
6724{
6725 char cmd[MAX_CMD_SIZE];
6726 char buf[MAX_BUF_SIZE]={0};
6727 BOOL enable;
6728
6729 if(!(apIndex==0 || apIndex==1))
6730 return RETURN_ERR;
6731 wifi_getApEnable(apIndex, &enable);
6732 if (!enable)
6733 return RETURN_ERR;
6734 wifi_getApWpsEnable(apIndex, &enable);
6735 if (!enable)
6736 return RETURN_ERR;
6737
6738 snprintf(cmd, 64, "hostapd_cli -i%s%d wps_pin any %s", AP_PREFIX, apIndex, pin);
6739 _syscmd(cmd, buf, sizeof(buf));
6740 if((strstr(buf, "OK"))!=NULL)
6741 return RETURN_OK;
6742
6743 return RETURN_ERR;
6744}
6745
6746// This function is called when the WPS push button has been pressed for this AP
6747INT wifi_setApWpsButtonPush(INT apIndex)
6748{
6749 char cmd[MAX_CMD_SIZE];
6750 char buf[MAX_BUF_SIZE]={0};
6751 BOOL enable=FALSE;
6752
6753 if(!(apIndex==0 || apIndex==1))
6754 return RETURN_ERR;
6755 wifi_getApEnable(apIndex, &enable);
6756 if (!enable)
6757 return RETURN_ERR;
6758
6759 wifi_getApWpsEnable(apIndex, &enable);
6760 if (!enable)
6761 return RETURN_ERR;
6762
6763 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel; hostapd_cli -i%s%d wps_pbc", AP_PREFIX, apIndex, AP_PREFIX, apIndex);
6764 _syscmd(cmd, buf, sizeof(buf));
6765
6766 if((strstr(buf, "OK"))!=NULL)
6767 return RETURN_OK;
6768 return RETURN_ERR;
6769}
6770
6771// cancels WPS mode for this AP
6772INT wifi_cancelApWPS(INT apIndex)
6773{
6774 char cmd[MAX_CMD_SIZE];
6775 char buf[MAX_BUF_SIZE]={0};
6776
6777 if(!(apIndex==0 || apIndex==1))
6778 return RETURN_ERR;
6779 snprintf(cmd, sizeof(cmd), "hostapd_cli -i%s%d wps_cancel", AP_PREFIX, apIndex);
6780 _syscmd(cmd,buf, sizeof(buf));
6781
6782 if((strstr(buf, "OK"))!=NULL)
6783 return RETURN_OK;
6784 return RETURN_ERR;
6785}
6786
6787//Device.WiFi.AccessPoint.{i}.AssociatedDevice.*
6788//HAL funciton should allocate an data structure array, and return to caller with "associated_dev_array"
6789INT wifi_getApAssociatedDeviceDiagnosticResult(INT apIndex, wifi_associated_dev_t **associated_dev_array, UINT *output_array_size)
6790{
6791 FILE *f;
6792 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
6793 char cmd[256], buf[2048];
6794 char *param , *value, *line=NULL;
6795 size_t len = 0;
6796 ssize_t nread;
6797 wifi_associated_dev_t *dev=NULL;
6798
6799 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6800 *associated_dev_array = NULL;
6801 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
6802 _syscmd(cmd,buf,sizeof(buf));
6803 *output_array_size = atoi(buf);
6804
6805 if (*output_array_size <= 0)
6806 return RETURN_OK;
6807
6808 dev=(wifi_associated_dev_t *) calloc (*output_array_size, sizeof(wifi_associated_dev_t));
6809 *associated_dev_array = dev;
6810 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt" , AP_PREFIX, apIndex);
6811 _syscmd(cmd,buf,sizeof(buf));
6812 f = fopen("/tmp/connected_devices.txt", "r");
6813 if (f==NULL)
6814 {
6815 *output_array_size=0;
6816 return RETURN_ERR;
6817 }
6818 while ((nread = getline(&line, &len, f)) != -1)
6819 {
6820 param = strtok(line,"=");
6821 value = strtok(NULL,"=");
6822
6823 if( strcmp("flags",param) == 0 )
6824 {
6825 value[strlen(value)-1]='\0';
6826 if(strstr (value,"AUTHORIZED") != NULL )
6827 {
6828 dev[auth_temp].cli_AuthenticationState = 1;
6829 dev[auth_temp].cli_Active = 1;
6830 auth_temp++;
6831 read_flag=1;
6832 }
6833 }
6834 if(read_flag==1)
6835 {
6836 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
6837 {
6838 value[strlen(value)-1]='\0';
6839 sscanf(value, "%x:%x:%x:%x:%x:%x",
6840 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
6841 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
6842 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
6843 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
6844 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
6845 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
6846 mac_temp++;
6847 read_flag=0;
6848 }
6849 }
6850 }
6851 *output_array_size = auth_temp;
6852 auth_temp=0;
6853 mac_temp=0;
6854 free(line);
6855 fclose(f);
6856 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
6857 return RETURN_OK;
6858}
6859
6860#define MACADDRESS_SIZE 6
6861
6862INT wifihal_AssociatedDevicesstats3(INT apIndex,CHAR *interface_name,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
6863{
6864 FILE *fp = NULL;
6865 char str[MAX_BUF_SIZE] = {0};
6866 int wificlientindex = 0 ;
6867 int count = 0;
6868 int signalstrength = 0;
6869 int arr[MACADDRESS_SIZE] = {0};
6870 unsigned char mac[MACADDRESS_SIZE] = {0};
6871 UINT wifi_count = 0;
6872 char virtual_interface_name[MAX_BUF_SIZE] = {0};
6873 char pipeCmd[MAX_CMD_SIZE] = {0};
6874
6875 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
6876 *output_array_size = 0;
6877 *associated_dev_array = NULL;
6878
6879 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
6880 fp = popen(pipeCmd, "r");
6881 if (fp == NULL)
6882 {
6883 printf("Failed to run command inside function %s\n",__FUNCTION__ );
6884 return RETURN_ERR;
6885 }
6886
6887 /* Read the output a line at a time - output it. */
6888 fgets(str, sizeof(str)-1, fp);
6889 wifi_count = (unsigned int) atoi ( str );
6890 *output_array_size = wifi_count;
6891 printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
6892 pclose(fp);
6893
6894 if(wifi_count == 0)
6895 {
6896 return RETURN_OK;
6897 }
6898 else
6899 {
6900 wifi_associated_dev3_t* temp = NULL;
6901 temp = (wifi_associated_dev3_t*)calloc(1, sizeof(wifi_associated_dev3_t)*wifi_count) ;
6902 if(temp == NULL)
6903 {
6904 printf("Error Statement. Insufficient memory \n");
6905 return RETURN_ERR;
6906 }
6907
6908 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
6909 system(pipeCmd);
6910 memset(pipeCmd,0,sizeof(pipeCmd));
6911 if(apIndex == 0)
6912 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_2G.txt", interface_name);
6913 else if(apIndex == 1)
6914 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump | grep Station >> /tmp/AllAssociated_Devices_5G.txt", interface_name);
6915 system(pipeCmd);
6916
6917 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
6918 if(fp == NULL)
6919 {
6920 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
6921 return RETURN_ERR;
6922 }
6923 fclose(fp);
6924
6925 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
6926 fp = popen(pipeCmd, "r");
6927 if(fp)
6928 {
6929 for(count =0 ; count < wifi_count; count++)
6930 {
6931 fgets(str, MAX_BUF_SIZE, fp);
6932 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
6933 {
6934 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
6935 {
6936 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
6937
6938 }
6939 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
6940 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]);
6941 }
6942 temp[count].cli_AuthenticationState = 1; //TODO
6943 temp[count].cli_Active = 1; //TODO
6944 }
6945 pclose(fp);
6946 }
6947
6948 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
6949 fp = popen(pipeCmd, "r");
6950 if(fp)
6951 {
6952 pclose(fp);
6953 }
6954 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
6955 if(fp)
6956 {
6957 for(count =0 ; count < wifi_count ;count++)
6958 {
6959 fgets(str, MAX_BUF_SIZE, fp);
6960 signalstrength = atoi(str);
6961 temp[count].cli_SignalStrength = signalstrength;
6962 temp[count].cli_RSSI = signalstrength;
6963 temp[count].cli_SNR = signalstrength + 95;
6964 }
6965 pclose(fp);
6966 }
6967
6968
6969 if((apIndex == 0) || (apIndex == 4))
6970 {
6971 for(count =0 ; count < wifi_count ;count++)
6972 {
6973 strcpy(temp[count].cli_OperatingStandard,"g");
6974 strcpy(temp[count].cli_OperatingChannelBandwidth,"20MHz");
6975 }
6976
6977 //BytesSent
6978 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Send.txt", interface_name);
6979 fp = popen(pipeCmd, "r");
6980 if(fp)
6981 {
6982 pclose(fp);
6983 }
6984 fp = popen("cat /tmp/Ass_Bytes_Send.txt | tr -s ' ' | cut -f 2","r");
6985 if(fp)
6986 {
6987 for (count = 0; count < wifi_count; count++)
6988 {
6989 fgets(str, MAX_BUF_SIZE, fp);
6990 temp[count].cli_BytesSent = strtoul(str, NULL, 10);
6991 }
6992 pclose(fp);
6993 }
6994
6995 //BytesReceived
6996 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bytes' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bytes_Received.txt", interface_name);
6997 fp = popen(pipeCmd, "r");
6998 if (fp)
6999 {
7000 pclose(fp);
7001 }
7002 fp = popen("cat /tmp/Ass_Bytes_Received.txt | tr -s ' ' | cut -f 2", "r");
7003 if (fp)
7004 {
7005 for (count = 0; count < wifi_count; count++)
7006 {
7007 fgets(str, MAX_BUF_SIZE, fp);
7008 temp[count].cli_BytesReceived = strtoul(str, NULL, 10);
7009 }
7010 pclose(fp);
7011 }
7012
7013 //PacketsSent
7014 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Send.txt", interface_name);
7015 fp = popen(pipeCmd, "r");
7016 if (fp)
7017 {
7018 pclose(fp);
7019 }
7020
7021 fp = popen("cat /tmp/Ass_Packets_Send.txt | tr -s ' ' | cut -f 2", "r");
7022 if (fp)
7023 {
7024 for (count = 0; count < wifi_count; count++)
7025 {
7026 fgets(str, MAX_BUF_SIZE, fp);
7027 temp[count].cli_PacketsSent = strtoul(str, NULL, 10);
7028 }
7029 pclose(fp);
7030 }
7031
7032 //PacketsReceived
7033 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx packets' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Packets_Received.txt", interface_name);
7034 fp = popen(pipeCmd, "r");
7035 if (fp)
7036 {
7037 pclose(fp);
7038 }
7039 fp = popen("cat /tmp/Ass_Packets_Received.txt | tr -s ' ' | cut -f 2", "r");
7040 if (fp)
7041 {
7042 for (count = 0; count < wifi_count; count++)
7043 {
7044 fgets(str, MAX_BUF_SIZE, fp);
7045 temp[count].cli_PacketsReceived = strtoul(str, NULL, 10);
7046 }
7047 pclose(fp);
7048 }
7049
7050 //ErrorsSent
7051 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7052 fp = popen(pipeCmd, "r");
7053 if (fp)
7054 {
7055 pclose(fp);
7056 }
7057 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7058 if (fp)
7059 {
7060 for (count = 0; count < wifi_count; count++)
7061 {
7062 fgets(str, MAX_BUF_SIZE, fp);
7063 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7064 }
7065 pclose(fp);
7066 }
7067
7068 //ErrorsSent
7069 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx failed' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Tx_Failed.txt", interface_name);
7070 fp = popen(pipeCmd, "r");
7071 if (fp)
7072 {
7073 pclose(fp);
7074 }
7075 fp = popen("cat /tmp/Ass_Tx_Failed.txt | tr -s ' ' | cut -f 2", "r");
7076 if (fp)
7077 {
7078 for (count = 0; count < wifi_count; count++)
7079 {
7080 fgets(str, MAX_BUF_SIZE, fp);
7081 temp[count].cli_ErrorsSent = strtoul(str, NULL, 10);
7082 }
7083 pclose(fp);
7084 }
7085
7086 //LastDataDownlinkRate
7087 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
7088 fp = popen(pipeCmd, "r");
7089 if (fp)
7090 {
7091 pclose(fp);
7092 }
7093 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
7094 if (fp)
7095 {
7096 for (count = 0; count < wifi_count; count++)
7097 {
7098 fgets(str, MAX_BUF_SIZE, fp);
7099 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
7100 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
7101 }
7102 pclose(fp);
7103 }
7104
7105 //LastDataUplinkRate
7106 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
7107 fp = popen(pipeCmd, "r");
7108 if (fp)
7109 {
7110 pclose(fp);
7111 }
7112 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
7113 if (fp)
7114 {
7115 for (count = 0; count < wifi_count; count++)
7116 {
7117 fgets(str, MAX_BUF_SIZE, fp);
7118 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
7119 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
7120 }
7121 pclose(fp);
7122 }
7123
7124 }
7125 else if ((apIndex == 1) || (apIndex == 5))
7126 {
7127 for (count = 0; count < wifi_count; count++)
7128 {
7129 strcpy(temp[count].cli_OperatingStandard, "a");
7130 strcpy(temp[count].cli_OperatingChannelBandwidth, "20MHz");
7131 temp[count].cli_BytesSent = 0;
7132 temp[count].cli_BytesReceived = 0;
7133 temp[count].cli_LastDataUplinkRate = 0;
7134 temp[count].cli_LastDataDownlinkRate = 0;
7135 temp[count].cli_PacketsSent = 0;
7136 temp[count].cli_PacketsReceived = 0;
7137 temp[count].cli_ErrorsSent = 0;
7138 }
7139 }
7140
7141 for (count = 0; count < wifi_count; count++)
7142 {
7143 temp[count].cli_Retransmissions = 0;
7144 temp[count].cli_DataFramesSentAck = 0;
7145 temp[count].cli_DataFramesSentNoAck = 0;
7146 temp[count].cli_MinRSSI = 0;
7147 temp[count].cli_MaxRSSI = 0;
7148 strncpy(temp[count].cli_InterferenceSources, "", 64);
7149 memset(temp[count].cli_IPAddress, 0, 64);
7150 temp[count].cli_RetransCount = 0;
7151 temp[count].cli_FailedRetransCount = 0;
7152 temp[count].cli_RetryCount = 0;
7153 temp[count].cli_MultipleRetryCount = 0;
7154 }
7155 *associated_dev_array = temp;
7156 }
7157 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7158 return RETURN_OK;
7159}
7160
7161int wifihal_interfacestatus(CHAR *wifi_status,CHAR *interface_name)
7162{
7163 FILE *fp = NULL;
7164 char path[512] = {0},status[MAX_BUF_SIZE] = {0};
7165 char cmd[MAX_CMD_SIZE];
7166 int count = 0;
7167
7168 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7169 sprintf(cmd, "ifconfig %s | grep RUNNING | tr -s ' ' | cut -d ' ' -f4", interface_name);
7170 fp = popen(cmd,"r");
7171 if(fp == NULL)
7172 {
7173 printf("Failed to run command in Function %s\n",__FUNCTION__);
7174 return 0;
7175 }
7176 if(fgets(path, sizeof(path)-1, fp) != NULL)
7177 {
7178 for(count=0;path[count]!='\n';count++)
7179 status[count]=path[count];
7180 status[count]='\0';
7181 }
7182 strcpy(wifi_status,status);
7183 pclose(fp);
7184 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7185 return RETURN_OK;
7186}
7187
7188/* #define HOSTAPD_STA_PARAM_ENTRIES 29
7189struct hostapd_sta_param {
7190 char key[50];
7191 char value[100];
7192}
7193
7194static char * hostapd_st_get_param(struct hostapd_sta_param * params, char *key){
7195 int i = 0;
7196
7197 while(i<HOSTAPD_STA_PARAM_ENTRIES) {
7198 if (strncmp(params[i].key,key,50) == 0){
7199 return &params[i].value;
7200 }
7201 i++;
7202 }
7203 return NULL;
7204
7205} */
7206
7207static unsigned int count_occurences(const char *buf, const char *word)
7208{
7209 unsigned int n = 0;
7210 char *ptr = strstr(buf, word);
7211
7212 while (ptr++) {
7213 n++;
7214 ptr = strstr(ptr, word);
7215 }
7216
7217 wifi_dbg_printf("%s: found %u of '%s'\n", __FUNCTION__, n, word);
7218 return n;
7219}
7220
7221static const char *get_line_from_str_buf(const char *buf, char *line)
7222{
7223 int i;
7224 int n = strlen(buf);
7225
7226 for (i = 0; i < n; i++) {
7227 line[i] = buf[i];
7228 if (buf[i] == '\n') {
7229 line[i] = '\0';
7230 return &buf[i + 1];
7231 }
7232 }
7233
7234 return NULL;
7235}
7236
7237INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7238{
7239 unsigned int assoc_cnt = 0;
7240 char interface_name[50] = {0};
7241 char buf[MAX_BUF_SIZE * 50]= {'\0'}; // Increase this buffer if more fields are added to 'iw dev' output filter
7242 char cmd[MAX_CMD_SIZE] = {'\0'};
7243 char line[256] = {'\0'};
7244 int i = 0;
7245 int ret = 0;
7246 const char *ptr = NULL;
7247 char *key = NULL;
7248 char *val = NULL;
7249 wifi_associated_dev3_t *temp = NULL;
7250 int rssi;
7251
7252 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7253
7254 if (wifi_getApName(apIndex, interface_name) != RETURN_OK) {
7255 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
7256 return RETURN_ERR;
7257 }
7258
7259 // Example filtered output of 'iw dev' command:
7260 // Station 0a:69:72:10:d2:fa (on wifi0)
7261 // signal avg:-67 [-71, -71] dBm
7262 // Station 28:c2:1f:25:5f:99 (on wifi0)
7263 // signal avg:-67 [-71, -70] dBm
7264 if (sprintf(cmd,"iw dev %s station dump | tr -d '\\t' | grep 'Station\\|signal avg'", interface_name) < 0) {
7265 wifi_dbg_printf("%s: failed to build iw dev command for %s\n", __FUNCTION__, interface_name);
7266 return RETURN_ERR;
7267 }
7268
7269 ret = _syscmd(cmd, buf, sizeof(buf));
7270 if (ret == RETURN_ERR) {
7271 wifi_dbg_printf("%s: failed to execute '%s' for %s\n", __FUNCTION__, cmd, interface_name);
7272 return RETURN_ERR;
7273 }
7274
7275 *output_array_size = count_occurences(buf, "Station");
7276 if (*output_array_size == 0) return RETURN_OK;
7277
7278 temp = calloc(*output_array_size, sizeof(wifi_associated_dev3_t));
7279 if (temp == NULL) {
7280 wifi_dbg_printf("%s: failed to allocate dev array for %s\n", __FUNCTION__, interface_name);
7281 return RETURN_ERR;
7282 }
7283 *associated_dev_array = temp;
7284
7285 wifi_dbg_printf("%s: array_size = %u\n", __FUNCTION__, *output_array_size);
7286 ptr = get_line_from_str_buf(buf, line);
7287 i = -1;
7288 while (ptr) {
7289 if (strstr(line, "Station")) {
7290 i++;
7291 key = strtok(line, " ");
7292 val = strtok(NULL, " ");
7293 if (sscanf(val, "%02x:%02x:%02x:%02x:%02x:%02x",
7294 &temp[i].cli_MACAddress[0],
7295 &temp[i].cli_MACAddress[1],
7296 &temp[i].cli_MACAddress[2],
7297 &temp[i].cli_MACAddress[3],
7298 &temp[i].cli_MACAddress[4],
7299 &temp[i].cli_MACAddress[5]) != MACADDRESS_SIZE) {
7300 wifi_dbg_printf("%s: failed to parse MAC of client connected to %s\n", __FUNCTION__, interface_name);
7301 free(*associated_dev_array);
7302 return RETURN_ERR;
7303 }
7304 }
7305 else if (i < 0) {
7306 ptr = get_line_from_str_buf(ptr, line);
7307 continue; // We didn't detect 'station' entry yet
7308 }
7309 else if (strstr(line, "signal avg")) {
7310 key = strtok(line, ":");
7311 val = strtok(NULL, " ");
7312 if (sscanf(val, "%d", &rssi) <= 0 ) {
7313 wifi_dbg_printf("%s: failed to parse RSSI of client connected to %s\n", __FUNCTION__, interface_name);
7314 free(*associated_dev_array);
7315 return RETURN_ERR;
7316 }
7317 temp[i].cli_RSSI = rssi;
7318 temp[i].cli_SNR = 95 + rssi; // We use constant -95 noise floor
7319 }
7320 // Here other fields can be parsed if added to filter of 'iw dev' command
7321
7322 ptr = get_line_from_str_buf(ptr, line);
7323 };
7324
7325 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7326
7327 return RETURN_OK;
7328}
7329
7330#if 0
7331//To-do
7332INT wifi_getApAssociatedDeviceDiagnosticResult3(INT apIndex, wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7333{
7334 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7335
7336 //Using different approach to get required WiFi Parameters from system available commands
7337#if 0
7338 FILE *f;
7339 int read_flag=0, auth_temp=0, mac_temp=0,i=0;
7340 char cmd[256], buf[2048];
7341 char *param , *value, *line=NULL;
7342 size_t len = 0;
7343 ssize_t nread;
7344 wifi_associated_dev3_t *dev=NULL;
7345 *associated_dev_array = NULL;
7346 sprintf(cmd, "hostapd_cli -i%s%d all_sta | grep AUTHORIZED | wc -l", AP_PREFIX, apIndex);
7347 _syscmd(cmd,buf,sizeof(buf));
7348 *output_array_size = atoi(buf);
7349
7350 if (*output_array_size <= 0)
7351 return RETURN_OK;
7352
7353 dev=(wifi_associated_dev3_t *) AnscAllocateMemory(*output_array_size * sizeof(wifi_associated_dev3_t));
7354 *associated_dev_array = dev;
7355 sprintf(cmd, "hostapd_cli -i%s%d all_sta > /tmp/connected_devices.txt", AP_PREFIX, apIndex);
7356 _syscmd(cmd,buf,sizeof(buf));
7357 f = fopen("/tmp/connected_devices.txt", "r");
7358 if (f==NULL)
7359 {
7360 *output_array_size=0;
7361 return RETURN_ERR;
7362 }
7363 while ((nread = getline(&line, &len, f)) != -1)
7364 {
7365 param = strtok(line,"=");
7366 value = strtok(NULL,"=");
7367
7368 if( strcmp("flags",param) == 0 )
7369 {
7370 value[strlen(value)-1]='\0';
7371 if(strstr (value,"AUTHORIZED") != NULL )
7372 {
7373 dev[auth_temp].cli_AuthenticationState = 1;
7374 dev[auth_temp].cli_Active = 1;
7375 auth_temp++;
7376 read_flag=1;
7377 }
7378 }
7379 if(read_flag==1)
7380 {
7381 if( strcmp("dot11RSNAStatsSTAAddress",param) == 0 )
7382 {
7383 value[strlen(value)-1]='\0';
7384 sscanf(value, "%x:%x:%x:%x:%x:%x",
7385 (unsigned int *)&dev[mac_temp].cli_MACAddress[0],
7386 (unsigned int *)&dev[mac_temp].cli_MACAddress[1],
7387 (unsigned int *)&dev[mac_temp].cli_MACAddress[2],
7388 (unsigned int *)&dev[mac_temp].cli_MACAddress[3],
7389 (unsigned int *)&dev[mac_temp].cli_MACAddress[4],
7390 (unsigned int *)&dev[mac_temp].cli_MACAddress[5] );
7391
7392 }
7393 else if( strcmp("rx_packets",param) == 0 )
7394 {
7395 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsReceived));
7396 }
7397
7398 else if( strcmp("tx_packets",param) == 0 )
7399 {
7400 sscanf(value, "%d", &(dev[mac_temp].cli_PacketsSent));
7401 }
7402
7403 else if( strcmp("rx_bytes",param) == 0 )
7404 {
7405 sscanf(value, "%d", &(dev[mac_temp].cli_BytesReceived));
7406 }
7407
7408 else if( strcmp("tx_bytes",param) == 0 )
7409 {
7410 sscanf(value, "%d", &(dev[mac_temp].cli_BytesSent));
7411 mac_temp++;
7412 read_flag=0;
7413 }
7414 }
7415 }
7416
7417 *output_array_size = auth_temp;
7418 auth_temp=0;
7419 mac_temp=0;
7420 free(line);
7421 fclose(f);
7422#endif
7423 char interface_name[MAX_BUF_SIZE] = {0};
7424 char wifi_status[MAX_BUF_SIZE] = {0};
7425 char hostapdconf[MAX_BUF_SIZE] = {0};
7426
7427 wifi_associated_dev3_t *dev_array = NULL;
7428 ULONG wifi_count = 0;
7429
7430 *associated_dev_array = NULL;
7431 *output_array_size = 0;
7432
7433 printf("wifi_getApAssociatedDeviceDiagnosticResult3 apIndex = %d \n", apIndex);
7434 //if(apIndex == 0 || apIndex == 1 || apIndex == 4 || apIndex == 5) // These are availble in RPI.
7435 {
7436 sprintf(hostapdconf, "/nvram/hostapd%d.conf", apIndex);
7437
7438 GetInterfaceName(interface_name, hostapdconf);
7439
7440 if(strlen(interface_name) > 1)
7441 {
7442 wifihal_interfacestatus(wifi_status,interface_name);
7443 if(strcmp(wifi_status,"RUNNING") == 0)
7444 {
7445 wifihal_AssociatedDevicesstats3(apIndex,interface_name,&dev_array,&wifi_count);
7446
7447 *associated_dev_array = dev_array;
7448 *output_array_size = wifi_count;
7449 }
7450 else
7451 {
7452 *associated_dev_array = NULL;
7453 }
7454 }
7455 }
7456
7457 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7458 return RETURN_OK;
7459}
7460#endif
7461
7462/* getIPAddress function */
7463/**
7464* @description Returning IpAddress of the Matched String
7465*
7466* @param
7467* @str Having MacAddress
7468* @ipaddr Having ipaddr
7469* @return The status of the operation
7470* @retval RETURN_OK if successful
7471* @retval RETURN_ERR if any error is detected
7472*
7473*/
7474
7475INT getIPAddress(char *str,char *ipaddr)
7476{
7477 FILE *fp = NULL;
7478 char buf[1024] = {0},ipAddr[50] = {0},phyAddr[100] = {0},hostName[100] = {0};
7479 int LeaseTime = 0,ret = 0;
7480 if ( (fp=fopen("/nvram/dnsmasq.leases", "r")) == NULL )
7481 {
7482 return RETURN_ERR;
7483 }
7484
7485 while ( fgets(buf, sizeof(buf), fp)!= NULL )
7486 {
7487 /*
7488 Sample:sss
7489 1560336751 00:cd:fe:f3:25:e6 10.0.0.153 NallamousiPhone 01:00:cd:fe:f3:25:e6
7490 1560336751 12:34:56:78:9a:bc 10.0.0.154 NallamousiPhone 01:00:cd:fe:f3:25:e6
7491 */
7492 ret = sscanf(buf, LM_DHCP_CLIENT_FORMAT,
7493 &(LeaseTime),
7494 phyAddr,
7495 ipAddr,
7496 hostName
7497 );
7498 if(ret != 4)
7499 continue;
7500 if(strcmp(str,phyAddr) == 0)
7501 strcpy(ipaddr,ipAddr);
7502 }
7503 return RETURN_OK;
7504}
7505
7506/* wifi_getApInactiveAssociatedDeviceDiagnosticResult function */
7507/**
7508* @description Returning Inactive wireless connected clients informations
7509*
7510* @param
7511* @filename Holding private_wifi 2g/5g content files
7512* @associated_dev_array Having inactiv wireless clients informations
7513* @output_array_size Returning Inactive wireless counts
7514* @return The status of the operation
7515* @retval RETURN_OK if successful
7516* @retval RETURN_ERR if any error is detected
7517*
7518*/
7519
7520INT wifi_getApInactiveAssociatedDeviceDiagnosticResult(char *filename,wifi_associated_dev3_t **associated_dev_array, UINT *output_array_size)
7521{
7522 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7523 int count = 0,maccount = 0,i = 0,wificlientindex = 0;
7524 FILE *fp = NULL;
7525 int arr[MACADDRESS_SIZE] = {0};
7526 unsigned char mac[MACADDRESS_SIZE] = {0};
7527 char path[1024] = {0},str[1024] = {0},ipaddr[50] = {0},buf[512] = {0};
7528 sprintf(buf,"cat %s | grep Station | sort | uniq | wc -l",filename);
7529 fp = popen(buf,"r");
7530 if(fp == NULL)
7531 return RETURN_ERR;
7532 else
7533 {
7534 fgets(path,sizeof(path),fp);
7535 maccount = atoi(path);
7536 }
7537 pclose(fp);
7538 *output_array_size = maccount;
7539 wifi_associated_dev3_t* temp = NULL;
7540 temp = (wifi_associated_dev3_t *) calloc (*output_array_size, sizeof(wifi_associated_dev3_t));
7541 *associated_dev_array = temp;
7542 if(temp == NULL)
7543 {
7544 printf("Error Statement. Insufficient memory \n");
7545 return RETURN_ERR;
7546 }
7547 memset(buf,0,sizeof(buf));
7548 sprintf(buf,"cat %s | grep Station | cut -d ' ' -f2 | sort | uniq",filename);
7549 fp = popen(buf,"r");
7550 for(count = 0; count < maccount ; count++)
7551 {
7552 fgets(path,sizeof(path),fp);
7553 for(i = 0; path[i]!='\n';i++)
7554 str[i]=path[i];
7555 str[i]='\0';
7556 getIPAddress(str,ipaddr);
7557 memset(buf,0,sizeof(buf));
7558 if(strlen(ipaddr) > 0)
7559 {
7560 sprintf(buf,"ping -q -c 1 -W 1 \"%s\" > /dev/null 2>&1",ipaddr);
7561 if (WEXITSTATUS(system(buf)) != 0) //InActive wireless clients info
7562 {
7563 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7564 {
7565 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7566 {
7567 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7568
7569 }
7570 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7571 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]);
7572 }
7573 temp[count].cli_AuthenticationState = 0; //TODO
7574 temp[count].cli_Active = 0; //TODO
7575 temp[count].cli_SignalStrength = 0;
7576 }
7577 else //Active wireless clients info
7578 {
7579 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
7580 {
7581 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
7582 {
7583 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
7584
7585 }
7586 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
7587 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]);
7588 }
7589 temp[count].cli_Active = 1;
7590 }
7591 }
7592 memset(ipaddr,0,sizeof(ipaddr));
7593 }
7594 pclose(fp);
7595 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7596 return RETURN_OK;
7597}
7598//Device.WiFi.X_RDKCENTRAL-COM_BandSteering object
7599//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Capability bool r/o
7600//To get Band Steering Capability
7601INT wifi_getBandSteeringCapability(BOOL *support)
7602{
7603 *support = FALSE;
7604 return RETURN_OK;
7605}
7606
7607
7608//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.Enable bool r/w
7609//To get Band Steering enable status
7610INT wifi_getBandSteeringEnable(BOOL *enable)
7611{
7612 *enable = FALSE;
7613 return RETURN_OK;
7614}
7615
7616//To turn on/off Band steering
7617INT wifi_setBandSteeringEnable(BOOL enable)
7618{
7619 return RETURN_OK;
7620}
7621
7622//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.APGroup string r/w
7623//To get Band Steering AP group
7624INT wifi_getBandSteeringApGroup(char *output_ApGroup)
7625{
7626 if (NULL == output_ApGroup)
7627 return RETURN_ERR;
7628
7629 strcpy(output_ApGroup, "1,2");
7630 return RETURN_OK;
7631}
7632
7633//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.UtilizationThreshold int r/w
7634//to set and read the band steering BandUtilizationThreshold parameters
7635INT wifi_getBandSteeringBandUtilizationThreshold (INT radioIndex, INT *pBuThreshold)
7636{
7637 return RETURN_ERR;
7638}
7639
7640INT wifi_setBandSteeringBandUtilizationThreshold (INT radioIndex, INT buThreshold)
7641{
7642 return RETURN_ERR;
7643}
7644
7645//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.RSSIThreshold int r/w
7646//to set and read the band steering RSSIThreshold parameters
7647INT wifi_getBandSteeringRSSIThreshold (INT radioIndex, INT *pRssiThreshold)
7648{
7649 return RETURN_ERR;
7650}
7651
7652INT wifi_setBandSteeringRSSIThreshold (INT radioIndex, INT rssiThreshold)
7653{
7654 return RETURN_ERR;
7655}
7656
7657
7658//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.PhyRateThreshold int r/w
7659//to set and read the band steering physical modulation rate threshold parameters
7660INT wifi_getBandSteeringPhyRateThreshold (INT radioIndex, INT *pPrThreshold)
7661{
7662 //If chip is not support, return -1
7663 return RETURN_ERR;
7664}
7665
7666INT wifi_setBandSteeringPhyRateThreshold (INT radioIndex, INT prThreshold)
7667{
7668 //If chip is not support, return -1
7669 return RETURN_ERR;
7670}
7671
7672//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.OverloadInactiveTime int r/w
7673//to set and read the inactivity time (in seconds) for steering under overload condition
7674INT wifi_getBandSteeringOverloadInactiveTime(INT radioIndex, INT *pPrThreshold)
7675{
7676 return RETURN_ERR;
7677}
7678
7679INT wifi_setBandSteeringOverloadInactiveTime(INT radioIndex, INT prThreshold)
7680{
7681 return RETURN_ERR;
7682}
7683
7684//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.BandSetting.{i}.IdleInactiveTime int r/w
7685//to set and read the inactivity time (in seconds) for steering under Idle condition
7686INT wifi_getBandSteeringIdleInactiveTime(INT radioIndex, INT *pPrThreshold)
7687{
7688 return RETURN_ERR;
7689}
7690
7691INT wifi_setBandSteeringIdleInactiveTime(INT radioIndex, INT prThreshold)
7692{
7693 return RETURN_ERR;
7694}
7695
7696//Device.WiFi.X_RDKCENTRAL-COM_BandSteering.History string r/o
7697//pClientMAC[64]
7698//pSourceSSIDIndex[64]
7699//pDestSSIDIndex[64]
7700//pSteeringReason[256]
7701INT wifi_getBandSteeringLog(INT record_index, ULONG *pSteeringTime, CHAR *pClientMAC, INT *pSourceSSIDIndex, INT *pDestSSIDIndex, INT *pSteeringReason)
7702{
7703 //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
7704 *pSteeringTime=time(NULL);
7705 *pSteeringReason = 0; //TODO: need to assign correct steering reason (INT numeric, i suppose)
7706 return RETURN_OK;
7707}
7708
7709INT wifi_ifConfigDown(INT apIndex)
7710{
7711 INT status = RETURN_OK;
7712 char cmd[64];
7713
7714 snprintf(cmd, sizeof(cmd), "ifconfig ath%d down", apIndex);
7715 printf("%s: %s\n", __func__, cmd);
7716 system(cmd);
7717
7718 return status;
7719}
7720
7721INT wifi_ifConfigUp(INT apIndex)
7722{
7723 char cmd[128];
7724 char buf[1024];
7725
7726 snprintf(cmd, sizeof(cmd), "ifconfig %s%d up 2>/dev/null", AP_PREFIX, apIndex);
7727 _syscmd(cmd, buf, sizeof(buf));
7728 return 0;
7729}
7730
7731//>> Deprecated. Replace with wifi_applyRadioSettings
7732INT wifi_pushBridgeInfo(INT apIndex)
7733{
7734 char ip[32];
7735 char subnet[32];
7736 char bridge[32];
7737 int vlanId;
7738 char cmd[128];
7739 char buf[1024];
7740
7741 wifi_getApBridgeInfo(apIndex,bridge,ip,subnet);
7742 wifi_getApVlanID(apIndex,&vlanId);
7743
7744 snprintf(cmd, sizeof(cmd), "cfgVlan %s%d %s %d %s ", AP_PREFIX, apIndex, bridge, vlanId, ip);
7745 _syscmd(cmd,buf, sizeof(buf));
7746
7747 return 0;
7748}
7749
7750INT wifi_pushChannel(INT radioIndex, UINT channel)
7751{
7752 char cmd[128];
7753 char buf[1024];
7754 int apIndex;
7755
7756 apIndex=(radioIndex==0)?0:1;
7757 snprintf(cmd, sizeof(cmd), "iwconfig %s%d freq %d",AP_PREFIX, apIndex,channel);
7758 _syscmd(cmd,buf, sizeof(buf));
7759
7760 return 0;
7761}
7762
7763INT wifi_pushChannelMode(INT radioIndex)
7764{
7765 //Apply Channel mode, pure mode, etc that been set by wifi_setRadioChannelMode() instantly
7766 return RETURN_ERR;
7767}
7768
7769INT wifi_pushDefaultValues(INT radioIndex)
7770{
7771 //Apply Comcast specified default radio settings instantly
7772 //AMPDU=1
7773 //AMPDUFrames=32
7774 //AMPDULim=50000
7775 //txqueuelen=1000
7776
7777 return RETURN_ERR;
7778}
7779
7780INT wifi_pushTxChainMask(INT radioIndex)
7781{
7782 //Apply default TxChainMask instantly
7783 return RETURN_ERR;
7784}
7785
7786INT wifi_pushRxChainMask(INT radioIndex)
7787{
7788 //Apply default RxChainMask instantly
7789 return RETURN_ERR;
7790}
7791
7792INT wifi_pushSSID(INT apIndex, CHAR *ssid)
7793{
7794 INT status;
7795
7796 status = wifi_setSSIDName(apIndex,ssid);
7797 wifi_setApEnable(apIndex,FALSE);
7798 wifi_setApEnable(apIndex,TRUE);
7799
7800 return status;
7801}
7802
7803INT wifi_pushSsidAdvertisementEnable(INT apIndex, BOOL enable)
7804{
7805 //Apply default Ssid Advertisement instantly
7806 return RETURN_ERR;
7807}
7808
7809INT wifi_getRadioUpTime(INT radioIndex, ULONG *output)
7810{
7811 INT status = RETURN_ERR;
7812 *output = 0;
7813 return RETURN_ERR;
7814}
7815
7816INT wifi_getApEnableOnLine(INT wlanIndex, BOOL *enabled)
7817{
7818 return RETURN_OK;
7819}
7820
7821INT wifi_getApSecurityWpaRekeyInterval(INT apIndex, INT *output_int)
7822{
7823 return RETURN_OK;
7824}
7825
7826//To-do
7827INT wifi_getApSecurityMFPConfig(INT apIndex, CHAR *output_string)
7828{
developereb199ae2022-09-13 14:04:27 +08007829 char output[16]={'\0'};
7830 char config_file[MAX_BUF_SIZE] = {0};
7831
7832 if (!output_string)
7833 return RETURN_ERR;
7834
7835 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7836 wifi_hostapdRead(config_file, "ieee80211w", output, sizeof(output));
7837
7838 if (strlen(output) == 0)
7839 snprintf(output_string, 64, "Disabled");
7840 else if (strncmp(output, "0", 1) == 0)
7841 snprintf(output_string, 64, "Disabled");
7842 else if (strncmp(output, "1", 1) == 0)
7843 snprintf(output_string, 64, "Optional");
7844 else if (strncmp(output, "2", 1) == 0)
7845 snprintf(output_string, 64, "Required");
7846 else {
7847 wifi_dbg_printf("\n[%s]: Unexpected ieee80211w=%s", __func__, output);
7848 return RETURN_ERR;
7849 }
7850
7851 wifi_dbg_printf("\n[%s]: ieee80211w is : %s", __func__, output);
developer06a01d92022-09-07 16:32:39 +08007852 return RETURN_OK;
7853}
7854INT wifi_setApSecurityMFPConfig(INT apIndex, CHAR *MfpConfig)
7855{
developereb199ae2022-09-13 14:04:27 +08007856 char str[MAX_BUF_SIZE]={'\0'};
7857 char cmd[MAX_CMD_SIZE]={'\0'};
7858 struct params params;
7859 char config_file[MAX_BUF_SIZE] = {0};
7860
7861 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7862 if(NULL == MfpConfig || strlen(MfpConfig) >= 32 )
7863 return RETURN_ERR;
7864
7865 params.name = "ieee80211w";
7866 if (strncmp(MfpConfig, "Disabled", strlen("Disabled")) == 0)
7867 params.value = "0";
7868 else if (strncmp(MfpConfig, "Optional", strlen("Optional")) == 0)
7869 params.value = "1";
7870 else if (strncmp(MfpConfig, "Required", strlen("Required")) == 0)
7871 params.value = "2";
7872 else{
7873 wifi_dbg_printf("%s: invalid MfpConfig. Input has to be Disabled, Optional or Required \n", __func__);
7874 return RETURN_ERR;
7875 }
7876 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
7877 wifi_hostapdWrite(config_file, &params, 1);
7878 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08007879 return RETURN_OK;
7880}
7881INT wifi_getRadioAutoChannelEnable(INT radioIndex, BOOL *output_bool)
7882{
7883 char output[16]={'\0'};
7884 char config_file[MAX_BUF_SIZE] = {0};
7885
7886 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7887 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,radioIndex);
7888 wifi_hostapdRead(config_file,"channel",output,sizeof(output));
7889
7890 *output_bool = (strncmp(output, "0", 1)==0) ? TRUE : FALSE;
7891 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
7892
7893 return RETURN_OK;
7894}
7895
7896INT wifi_getRouterEnable(INT wlanIndex, BOOL *enabled)
7897{
7898 return RETURN_OK;
7899}
7900
7901INT wifi_setApSecurityWpaRekeyInterval(INT apIndex, INT *rekeyInterval)
7902{
7903 return RETURN_OK;
7904}
7905
7906INT wifi_setRouterEnable(INT wlanIndex, INT *RouterEnabled)
7907{
7908 return RETURN_OK;
7909}
7910
7911INT wifi_getRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7912{
7913 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7914 char config_file[MAX_BUF_SIZE] = {0};
7915
7916 if (NULL == output)
7917 return RETURN_ERR;
7918 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7919 wifi_hostapdRead(config_file,"hw_mode",output,64);
7920
7921 if(strcmp(output,"b")==0)
7922 sprintf(output, "%s", "1,2,5.5,11");
7923 else if (strcmp(output,"a")==0)
7924 sprintf(output, "%s", "6,9,11,12,18,24,36,48,54");
7925 else if ((strcmp(output,"n")==0) | (strcmp(output,"g")==0))
7926 sprintf(output, "%s", "1,2,5.5,6,9,11,12,18,24,36,48,54");
7927
7928 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7929 return RETURN_OK;
7930}
7931
7932INT wifi_getRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7933{
7934 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7935 char *temp;
7936 char temp_output[128];
7937 char temp_TransmitRates[128];
7938 char config_file[MAX_BUF_SIZE] = {0};
7939
7940 if (NULL == output)
7941 return RETURN_ERR;
7942
7943 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
7944 wifi_hostapdRead(config_file,"supported_rates",output,64);
7945
7946 strcpy(temp_TransmitRates,output);
7947 strcpy(temp_output,"");
7948 temp = strtok(temp_TransmitRates," ");
7949 while(temp!=NULL)
7950 {
7951 temp[strlen(temp)-1]=0;
7952 if((temp[0]=='5') && (temp[1]=='\0'))
7953 {
7954 temp="5.5";
7955 }
7956 strcat(temp_output,temp);
7957 temp = strtok(NULL," ");
7958 if(temp!=NULL)
7959 {
7960 strcat(temp_output,",");
7961 }
7962 }
7963 strcpy(output,temp_output);
7964 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
7965
7966 return RETURN_OK;
7967}
7968
7969INT wifi_setRadioSupportedDataTransmitRates(INT wlanIndex,CHAR *output)
7970{
7971 return RETURN_OK;
7972}
7973
7974
7975INT wifi_setRadioOperationalDataTransmitRates(INT wlanIndex,CHAR *output)
7976{
7977 int i=0;
7978 char *temp;
7979 char temp1[128];
7980 char temp_output[128];
7981 char temp_TransmitRates[128];
7982 struct params params={'\0'};
7983 char config_file[MAX_BUF_SIZE] = {0};
7984
7985 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
7986 if(NULL == output)
7987 return RETURN_ERR;
7988
7989 strcpy(temp_TransmitRates,output);
7990
7991 for(i=0;i<strlen(temp_TransmitRates);i++)
7992 {
7993 if (((temp_TransmitRates[i]>='0') && (temp_TransmitRates[i]<='9')) | (temp_TransmitRates[i]==' ') | (temp_TransmitRates[i]=='.'))
7994 {
7995 continue;
7996 }
7997 else
7998 {
7999 return RETURN_ERR;
8000 }
8001 }
8002 strcpy(temp_output,"");
8003 temp = strtok(temp_TransmitRates," ");
8004 while(temp!=NULL)
8005 {
8006 strcpy(temp1,temp);
8007 if(wlanIndex==1)
8008 {
8009 if((strcmp(temp,"1")==0) | (strcmp(temp,"2")==0) | (strcmp(temp,"5.5")==0))
8010 {
8011 return RETURN_ERR;
8012 }
8013 }
8014
8015 if(strcmp(temp,"5.5")==0)
8016 {
8017 strcpy(temp1,"55");
8018 }
8019 else
8020 {
8021 strcat(temp1,"0");
8022 }
8023 strcat(temp_output,temp1);
8024 temp = strtok(NULL," ");
8025 if(temp!=NULL)
8026 {
8027 strcat(temp_output," ");
8028 }
8029 }
8030 strcpy(output,temp_output);
8031
8032
8033 params.name = "supported_rates";
8034 params.value = output;
8035
8036 wifi_dbg_printf("\n%s:",__func__);
8037 wifi_dbg_printf("params.value=%s\n",params.value);
8038 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,wlanIndex);
8039 wifi_hostapdWrite(config_file,&params,1);
8040 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8041
8042 return RETURN_OK;
8043}
8044
8045
8046static char *sncopy(char *dst, int dst_sz, const char *src)
8047{
8048 if (src && dst && dst_sz > 0) {
8049 strncpy(dst, src, dst_sz);
8050 dst[dst_sz - 1] = '\0';
8051 }
8052 return dst;
8053}
8054
8055static int util_get_sec_chan_offset(int channel, const char* ht_mode)
8056{
8057 if (0 == strcmp(ht_mode, "HT40") ||
8058 0 == strcmp(ht_mode, "HT80") ||
8059 0 == strcmp(ht_mode, "HT160")) {
8060 switch (channel) {
8061 case 1 ... 7:
8062 case 36:
8063 case 44:
8064 case 52:
8065 case 60:
8066 case 100:
8067 case 108:
8068 case 116:
8069 case 124:
8070 case 132:
8071 case 140:
8072 case 149:
8073 case 157:
8074 return 1;
8075 case 8 ... 13:
8076 case 40:
8077 case 48:
8078 case 56:
8079 case 64:
8080 case 104:
8081 case 112:
8082 case 120:
8083 case 128:
8084 case 136:
8085 case 144:
8086 case 153:
8087 case 161:
8088 return -1;
8089 default:
8090 return -EINVAL;
8091 }
8092 }
8093
8094 return -EINVAL;
8095}
8096
8097static void util_hw_mode_to_bw_mode(const char* hw_mode, char *bw_mode, int bw_mode_len)
8098{
8099 if (NULL == hw_mode) return;
8100
8101 if (0 == strcmp(hw_mode, "ac"))
8102 sncopy(bw_mode, bw_mode_len, "ht vht");
8103
8104 if (0 == strcmp(hw_mode, "n"))
8105 sncopy(bw_mode, bw_mode_len, "ht");
8106
8107 return;
8108}
8109
8110static int util_chan_to_freq(int chan)
8111{
8112 if (chan == 14)
8113 return 2484;
8114 else if (chan < 14)
8115 return 2407 + chan * 5;
8116 else if (chan >= 182 && chan <= 196)
8117 return 4000 + chan * 5;
8118 else
8119 return 5000 + chan * 5;
8120 return 0;
8121}
8122
8123const int *util_unii_5g_chan2list(int chan, int width)
8124{
8125 static const int lists[] = {
8126 // <width>, <chan1>, <chan2>..., 0,
8127 20, 36, 0,
8128 20, 40, 0,
8129 20, 44, 0,
8130 20, 48, 0,
8131 20, 52, 0,
8132 20, 56, 0,
8133 20, 60, 0,
8134 20, 64, 0,
8135 20, 100, 0,
8136 20, 104, 0,
8137 20, 108, 0,
8138 20, 112, 0,
8139 20, 116, 0,
8140 20, 120, 0,
8141 20, 124, 0,
8142 20, 128, 0,
8143 20, 132, 0,
8144 20, 136, 0,
8145 20, 140, 0,
8146 20, 144, 0,
8147 20, 149, 0,
8148 20, 153, 0,
8149 20, 157, 0,
8150 20, 161, 0,
8151 20, 165, 0,
8152 40, 36, 40, 0,
8153 40, 44, 48, 0,
8154 40, 52, 56, 0,
8155 40, 60, 64, 0,
8156 40, 100, 104, 0,
8157 40, 108, 112, 0,
8158 40, 116, 120, 0,
8159 40, 124, 128, 0,
8160 40, 132, 136, 0,
8161 40, 140, 144, 0,
8162 40, 149, 153, 0,
8163 40, 157, 161, 0,
8164 80, 36, 40, 44, 48, 0,
8165 80, 52, 56, 60, 64, 0,
8166 80, 100, 104, 108, 112, 0,
8167 80, 116, 120, 124, 128, 0,
8168 80, 132, 136, 140, 144, 0,
8169 80, 149, 153, 157, 161, 0,
8170 160, 36, 40, 44, 48, 52, 56, 60, 64, 0,
8171 160, 100, 104, 108, 112, 116, 120, 124, 128, 0,
8172 -1 // final delimiter
8173 };
8174 const int *start;
8175 const int *p;
8176
8177 for (p = lists; *p != -1; p++) {
8178 if (*p == width) {
8179 for (start = ++p; *p != 0; p++) {
8180 if (*p == chan)
8181 return start;
8182 }
8183 }
8184 // move to the end of channel list of given width
8185 while (*p != 0) {
8186 p++;
8187 }
8188 }
8189
8190 return NULL;
8191}
8192
8193static int util_unii_5g_centerfreq(const char *ht_mode, int channel)
8194{
8195 if (NULL == ht_mode)
8196 return 0;
8197
8198 const int width = atoi(strlen(ht_mode) > 2 ? ht_mode + 2 : "20");
8199 const int *chans = util_unii_5g_chan2list(channel, width);
8200 int sum = 0;
8201 int cnt = 0;
8202
8203 if (NULL == chans)
8204 return 0;
8205
8206 while (*chans) {
8207 sum += *chans;
8208 cnt++;
8209 chans++;
8210 }
8211 return sum / cnt;
8212}
8213
8214static int util_radio_get_hw_mode(int radioIndex, char *hw_mode, int hw_mode_size)
8215{
8216 BOOL onlyG, onlyN, onlyA;
8217 CHAR tmp[64];
8218 int ret = wifi_getRadioStandard(radioIndex, tmp, &onlyG, &onlyN, &onlyA);
8219 if (ret == RETURN_OK) {
8220 sncopy(hw_mode, hw_mode_size, tmp);
8221 }
8222 return ret;
8223}
8224
8225INT wifi_pushRadioChannel2(INT radioIndex, UINT channel, UINT channel_width_MHz, UINT csa_beacon_count)
8226{
8227 // Sample commands:
8228 // hostapd_cli -i wifi1 chan_switch 30 5200 sec_channel_offset=-1 center_freq1=5190 bandwidth=40 ht vht
8229 // hostapd_cli -i wifi0 chan_switch 30 2437
8230 char cmd[MAX_CMD_SIZE] = {0};
8231 char buf[MAX_BUF_SIZE] = {0};
8232 int freq = 0, ret = 0;
8233 char center_freq1_str[32] = ""; // center_freq1=%d
8234 char opt_chan_info_str[32] = ""; // bandwidth=%d ht vht
8235 char sec_chan_offset_str[32] = ""; // sec_channel_offset=%d
8236 char hw_mode[16] = ""; // n|ac
8237 char bw_mode[16] = ""; // ht|ht vht
8238 char ht_mode[16] = ""; // HT20|HT40|HT80|HT160
8239 int sec_chan_offset;
8240 int width;
developer4fb0b922022-09-30 14:29:09 +08008241 char config_file[64] = {0};
8242 BOOL stbcEnable = FALSE;
8243 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, radioIndex);
developer06a01d92022-09-07 16:32:39 +08008244
8245 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8246
8247 freq = util_chan_to_freq(channel);
8248
8249 // Get radio mode HT20|HT40|HT80 etc.
8250 width = channel_width_MHz > 20 ? channel_width_MHz : 20;
8251 snprintf(ht_mode, sizeof(ht_mode), "HT%d", width);
8252 // Find channel offset +1/-1 for wide modes (HT40|HT80|HT160)
8253 sec_chan_offset = util_get_sec_chan_offset(channel, ht_mode);
8254 if (sec_chan_offset != -EINVAL)
8255 snprintf(sec_chan_offset_str, sizeof(sec_chan_offset_str), "sec_channel_offset=%d", sec_chan_offset);
8256
8257
8258 // Provide bandwith if specified
8259 if (channel_width_MHz > 20) {
8260 // Select bandwidth mode from hardware n --> ht | ac --> ht vht
8261 util_radio_get_hw_mode(radioIndex, hw_mode, sizeof(hw_mode));
8262 util_hw_mode_to_bw_mode(hw_mode, bw_mode, sizeof(bw_mode));
8263
8264 snprintf(opt_chan_info_str, sizeof(opt_chan_info_str), "bandwidth=%d %s", width, bw_mode);
8265 }
8266
8267 int center_chan = 0;
8268 if (channel_width_MHz > 20) {
8269 center_chan = util_unii_5g_centerfreq(ht_mode, channel);
8270 if (center_chan > 0) {
8271 int center_freq1 = util_chan_to_freq(center_chan);
8272 if (center_freq1)
8273 snprintf(center_freq1_str, sizeof(center_freq1_str), "center_freq1=%d", center_freq1);
8274 }
8275 }
8276
8277 {
8278 // Only the first AP, other are hanging on the same radio
8279 int apIndex = radioIndex;
8280 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d chan_switch %d %d %s %s %s",
8281 AP_PREFIX, apIndex, csa_beacon_count, freq,
8282 sec_chan_offset_str, center_freq1_str, opt_chan_info_str);
8283 wifi_dbg_printf("execute: '%s'\n", cmd);
8284 ret = _syscmd(cmd, buf, sizeof(buf));
8285 }
8286
8287 wifi_setRadioChannel(radioIndex, channel);
8288
developer4fb0b922022-09-30 14:29:09 +08008289 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
8290 _syscmd(cmd, buf, sizeof(buf));
8291 if (strlen(buf) != 0)
8292 stbcEnable = TRUE;
8293
developer06a01d92022-09-07 16:32:39 +08008294 char *ext_str = "None";
8295 if (sec_chan_offset == 1) ext_str = "Above";
8296 else if (sec_chan_offset == -1) ext_str = "Below";
8297 wifi_setRadioExtChannel(radioIndex, ext_str);
8298
8299 wifi_setRadioCenterChannel(radioIndex, center_chan);
8300
developer4fb0b922022-09-30 14:29:09 +08008301 wifi_setRadioSTBCEnable(radioIndex, stbcEnable);
8302
developer06a01d92022-09-07 16:32:39 +08008303 char mhz_str[16];
8304 snprintf(mhz_str, sizeof(mhz_str), "%dMHz", width);
8305 wifi_setRadioOperatingChannelBandwidth(radioIndex, mhz_str);
8306
8307 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8308
8309 return RETURN_OK;
8310}
8311
8312INT wifi_getNeighboringWiFiStatus(INT radio_index, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size)
8313{
developer615510b2022-09-27 10:14:35 +08008314 int index = -1;
developer06a01d92022-09-07 16:32:39 +08008315 wifi_neighbor_ap2_t *scan_array = NULL;
developer615510b2022-09-27 10:14:35 +08008316 char cmd[256]={0};
8317 char buf[128]={0};
8318 char file_name[32] = {0};
8319 char filter_SSID[32] = {0};
8320 char line[256] = {0};
8321 char *ret = NULL;
developer06a01d92022-09-07 16:32:39 +08008322 int freq=0;
developer06a01d92022-09-07 16:32:39 +08008323 FILE *f = NULL;
developer615510b2022-09-27 10:14:35 +08008324 size_t len=0;
8325 int channels_num = 0;
developer06a01d92022-09-07 16:32:39 +08008326 int vht_channel_width = 0;
developer5550e242022-09-30 09:59:32 +08008327 int get_noise_ret = RETURN_ERR;
developer615510b2022-09-27 10:14:35 +08008328 bool filter_enable = false;
8329 bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
developer06a01d92022-09-07 16:32:39 +08008330
developer615510b2022-09-27 10:14:35 +08008331 WIFI_ENTRY_EXIT_DEBUG("Inside %s: %d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008332
developer615510b2022-09-27 10:14:35 +08008333 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radio_index);
8334 f = fopen(file_name, "r");
8335 if (f != NULL) {
8336 fgets(filter_SSID, sizeof(file_name), f);
8337 if (strlen(filter_SSID) != 0)
8338 filter_enable = true;
8339 fclose(f);
8340 }
8341
8342 snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radio_index);
8343 _syscmd(cmd, buf, sizeof(buf));
8344 channels_num = strtol(buf, NULL, 10);
8345
developer615510b2022-09-27 10:14:35 +08008346 sprintf(cmd, "iw dev %s%d scan dump | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
8347 // 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);
8348 fprintf(stderr, "cmd: %s\n", cmd);
8349 if ((f = popen(cmd, "r")) == NULL) {
developer06a01d92022-09-07 16:32:39 +08008350 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8351 return RETURN_ERR;
8352 }
developer5550e242022-09-30 09:59:32 +08008353
8354 struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
8355 get_noise_ret = get_noise(radio_index, channels_noise_arr, channels_num);
8356
developer615510b2022-09-27 10:14:35 +08008357 ret = fgets(line, sizeof(line), f);
8358 while (ret != NULL) {
8359 if(strstr(line, "BSS") != NULL) { // new neighbor info
8360 // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
8361 // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
8362 // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
8363
8364 if (!filter_BSS) {
8365 index++;
8366 wifi_neighbor_ap2_t *tmp;
8367 tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
8368 if (tmp == NULL) { // no more memory to use
8369 index--;
8370 wifi_dbg_printf("%s: realloc failed\n", __func__);
8371 break;
8372 }
8373 scan_array = tmp;
8374 }
8375 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
developer06a01d92022-09-07 16:32:39 +08008376
developer615510b2022-09-27 10:14:35 +08008377 filter_BSS = false;
8378 sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
8379 strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
8380 strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
8381 strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
8382 } else if (strstr(line, "freq") != NULL) {
developer06a01d92022-09-07 16:32:39 +08008383 sscanf(line," freq: %d", &freq);
developer615510b2022-09-27 10:14:35 +08008384 scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
developer06a01d92022-09-07 16:32:39 +08008385
developer615510b2022-09-27 10:14:35 +08008386 if (freq >= 2412 && freq <= 2484) {
8387 strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
8388 strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
8389 strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
8390 }
8391 else if (freq >= 5160 && freq <= 5805) {
8392 strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
8393 strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
8394 strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
8395 }
developer06a01d92022-09-07 16:32:39 +08008396
developer615510b2022-09-27 10:14:35 +08008397 scan_array[index].ap_Noise = 0;
developer5550e242022-09-30 09:59:32 +08008398 if (get_noise_ret == RETURN_OK) {
developer615510b2022-09-27 10:14:35 +08008399 for (int i = 0; i < channels_num; i++) {
8400 if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
8401 scan_array[index].ap_Noise = channels_noise_arr[i].noise;
8402 break;
8403 }
8404 }
developer06a01d92022-09-07 16:32:39 +08008405 }
developer615510b2022-09-27 10:14:35 +08008406 } else if (strstr(line, "beacon interval") != NULL) {
8407 sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
8408 } else if (strstr(line, "signal") != NULL) {
8409 sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
8410 } else if (strstr(line,"SSID") != NULL) {
8411 sscanf(line," SSID: %s", scan_array[index].ap_SSID);
8412 if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
8413 filter_BSS = true;
developer06a01d92022-09-07 16:32:39 +08008414 }
developer615510b2022-09-27 10:14:35 +08008415 } else if (strstr(line, "Supported rates") != NULL) {
8416 char SRate[80] = {0}, *tmp = NULL;
8417 memset(buf, 0, sizeof(buf));
8418 strcpy(SRate, line);
8419 tmp = strtok(SRate, ":");
8420 tmp = strtok(NULL, ":");
8421 strcpy(buf, tmp);
8422 memset(SRate, 0, sizeof(SRate));
developer06a01d92022-09-07 16:32:39 +08008423
developer615510b2022-09-27 10:14:35 +08008424 tmp = strtok(buf, " \n");
8425 while (tmp != NULL) {
8426 strcat(SRate, tmp);
8427 if (SRate[strlen(SRate) - 1] == '*') {
8428 SRate[strlen(SRate) - 1] = '\0';
8429 }
8430 strcat(SRate, ",");
developer06a01d92022-09-07 16:32:39 +08008431
developer615510b2022-09-27 10:14:35 +08008432 tmp = strtok(NULL, " \n");
developer06a01d92022-09-07 16:32:39 +08008433 }
developer615510b2022-09-27 10:14:35 +08008434 SRate[strlen(SRate) - 1] = '\0';
8435 strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
8436 } else if (strstr(line, "DTIM") != NULL) {
8437 sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
8438 } else if (strstr(line, "VHT capabilities") != NULL) {
8439 strcat(scan_array[index].ap_SupportedStandards, ",ac");
8440 strcpy(scan_array[index].ap_OperatingStandards, "ac");
8441 } else if (strstr(line, "HT capabilities") != NULL) {
8442 strcat(scan_array[index].ap_SupportedStandards, ",n");
8443 strcpy(scan_array[index].ap_OperatingStandards, "n");
8444 } else if (strstr(line, "VHT operation") != NULL) {
8445 ret = fgets(line, sizeof(line), f);
8446 sscanf(line," * channel width: %d", &vht_channel_width);
8447 if(vht_channel_width == 1) {
8448 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
8449 } else {
8450 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
8451 }
8452 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
8453 continue;
8454 } else if (strstr(line, "HT operation") != NULL) {
8455 ret = fgets(line, sizeof(line), f);
8456 sscanf(line," * secondary channel offset: %s", &buf);
8457 if (!strcmp(buf, "above")) {
developer06a01d92022-09-07 16:32:39 +08008458 //40Mhz +
developer615510b2022-09-27 10:14:35 +08008459 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 +08008460 }
developer615510b2022-09-27 10:14:35 +08008461 else if (!strcmp(buf, "below")) {
developer06a01d92022-09-07 16:32:39 +08008462 //40Mhz -
developer615510b2022-09-27 10:14:35 +08008463 snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radio_index%1 ? "A": "G");
8464 } else {
8465 //20Mhz
8466 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 +08008467 }
developer615510b2022-09-27 10:14:35 +08008468 if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
developer06a01d92022-09-07 16:32:39 +08008469 continue;
developer615510b2022-09-27 10:14:35 +08008470 } else if (strstr(line, "HE capabilities") != NULL) {
8471 strcat(scan_array[index].ap_SupportedStandards, ",ax");
8472 strcpy(scan_array[index].ap_OperatingStandards, "ax");
8473 ret = fgets(line, sizeof(line), f);
8474 if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
8475 if (strstr(line, "HE40/2.4GHz") != NULL)
8476 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS");
8477 else
8478 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20");
8479 } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
8480 if (strstr(line, "HE80/5GHz") != NULL) {
8481 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80");
8482 ret = fgets(line, sizeof(line), f);
8483 } else
8484 continue;
8485 if (strstr(line, "HE160/5GHz") != NULL)
8486 strcpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160");
developer06a01d92022-09-07 16:32:39 +08008487 }
developer615510b2022-09-27 10:14:35 +08008488 continue;
8489 } else if (strstr(line, "WPA") != NULL) {
8490 strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
8491 } else if (strstr(line, "RSN") != NULL) {
8492 strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
8493 } else if (strstr(line, "Group cipher") != NULL) {
8494 sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
8495 if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
8496 strcpy(scan_array[index].ap_EncryptionMode, "AES");
developer06a01d92022-09-07 16:32:39 +08008497 }
developer06a01d92022-09-07 16:32:39 +08008498 }
developer615510b2022-09-27 10:14:35 +08008499 ret = fgets(line, sizeof(line), f);
8500 }
8501
8502 if (!filter_BSS) {
8503 *output_array_size = index + 1;
8504 } else {
8505 memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
8506 *output_array_size = index;
developer06a01d92022-09-07 16:32:39 +08008507 }
developer06a01d92022-09-07 16:32:39 +08008508 *neighbor_ap_array = scan_array;
developer06a01d92022-09-07 16:32:39 +08008509 pclose(f);
developer5550e242022-09-30 09:59:32 +08008510 free(channels_noise_arr);
developer615510b2022-09-27 10:14:35 +08008511 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008512 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008513}
developer615510b2022-09-27 10:14:35 +08008514
developer06a01d92022-09-07 16:32:39 +08008515INT wifi_getApAssociatedDeviceStats(
8516 INT apIndex,
8517 mac_address_t *clientMacAddress,
8518 wifi_associated_dev_stats_t *associated_dev_stats,
8519 u64 *handle)
8520{
8521 wifi_associated_dev_stats_t *dev_stats = associated_dev_stats;
8522 char interface_name[50] = {0};
8523 char cmd[1024] = {0};
8524 char mac_str[18] = {0};
8525 char *key = NULL;
8526 char *val = NULL;
8527 FILE *f = NULL;
8528 char *line = NULL;
8529 size_t len = 0;
8530 ssize_t read = 0;
8531
8532 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8533 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8534 return RETURN_ERR;
8535 }
8536
8537 sprintf(mac_str, "%x:%x:%x:%x:%x:%x", (*clientMacAddress)[0],(*clientMacAddress)[1],(*clientMacAddress)[2],(*clientMacAddress)[3],(*clientMacAddress)[4],(*clientMacAddress)[5]);
8538 sprintf(cmd,"iw dev %s station get %s | grep 'rx\\|tx' | tr -d '\t'", interface_name, mac_str);
8539 if((f = popen(cmd, "r")) == NULL) {
8540 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
8541 return RETURN_ERR;
8542 }
8543
8544 while ((read = getline(&line, &len, f)) != -1) {
8545 key = strtok(line,":");
8546 val = strtok(NULL,":");
8547
8548 if(!strncmp(key,"rx bytes",8))
8549 sscanf(val, "%llu", &dev_stats->cli_rx_bytes);
8550 if(!strncmp(key,"tx bytes",8))
8551 sscanf(val, "%llu", &dev_stats->cli_tx_bytes);
8552 if(!strncmp(key,"rx packets",10))
8553 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8554 if(!strncmp(key,"tx packets",10))
8555 sscanf(val, "%llu", &dev_stats->cli_tx_frames);
8556 if(!strncmp(key,"tx retries",10))
8557 sscanf(val, "%llu", &dev_stats->cli_tx_retries);
8558 if(!strncmp(key,"tx failed",9))
8559 sscanf(val, "%llu", &dev_stats->cli_tx_errors);
8560 if(!strncmp(key,"rx drop misc",13))
8561 sscanf(val, "%llu", &dev_stats->cli_rx_errors);
8562 if(!strncmp(key,"rx bitrate",10)) {
8563 val = strtok(val, " ");
8564 sscanf(val, "%lf", &dev_stats->cli_rx_rate);
8565 }
8566 if(!strncmp(key,"tx bitrate",10)) {
8567 val = strtok(val, " ");
8568 sscanf(val, "%lf", &dev_stats->cli_tx_rate);
8569 }
8570 }
8571 free(line);
8572 pclose(f);
8573 return RETURN_OK;
8574}
8575
8576INT wifi_getSSIDNameStatus(INT apIndex, CHAR *output_string)
8577{
8578 char cmd[MAX_CMD_SIZE] = {0}, buf[MAX_BUF_SIZE] = {0};
8579
8580 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8581 if (NULL == output_string)
8582 return RETURN_ERR;
8583
8584 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d get_config | grep ^ssid | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX,apIndex);
8585 _syscmd(cmd, buf, sizeof(buf));
8586
8587 //size of SSID name restricted to value less than 32 bytes
8588 snprintf(output_string, 32, "%s", buf);
8589 WIFI_ENTRY_EXIT_DEBUG("Exit %s:%d\n",__func__, __LINE__);
8590
8591 return RETURN_OK;
8592}
8593
8594INT wifi_getApMacAddressControlMode(INT apIndex, INT *output_filterMode)
8595{
8596 //char cmd[MAX_CMD_SIZE] = {0};
8597 char config_file[MAX_BUF_SIZE] = {0};
8598 char buf[32] = {0};
8599
8600 if (!output_filterMode)
8601 return RETURN_ERR;
8602
8603 //snprintf(cmd, sizeof(cmd), "syscfg get %dblockall", apIndex);
8604 //_syscmd(cmd, buf, sizeof(buf));
8605 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
8606 wifi_hostapdRead(config_file, "macaddr_acl", buf, sizeof(buf));
developer10adcc12022-09-13 14:39:17 +08008607 if(strlen(buf) == 0) {
8608 *output_filterMode = 0;
8609 }
8610 else {
8611 int macaddr_acl_mode = strtol(buf, NULL, 10);
8612 if (macaddr_acl_mode == 1) {
8613 *output_filterMode = 1;
8614 } else if (macaddr_acl_mode == 0) {
8615 wifi_hostapdRead(config_file, "deny_mac_file", buf, sizeof(buf));
8616 if (strlen(buf) == 0) {
8617 *output_filterMode = 0;
8618 } else {
8619 *output_filterMode = 2;
8620 }
8621 } else {
8622 return RETURN_ERR;
8623 }
8624 }
developer06a01d92022-09-07 16:32:39 +08008625
8626 return RETURN_OK;
8627}
8628
8629INT wifi_getApAssociatedDeviceDiagnosticResult2(INT apIndex,wifi_associated_dev2_t **associated_dev_array,UINT *output_array_size)
8630{
8631 FILE *fp = NULL;
8632 char str[MAX_BUF_SIZE] = {0};
8633 int wificlientindex = 0 ;
8634 int count = 0;
8635 int signalstrength = 0;
8636 int arr[MACADDRESS_SIZE] = {0};
8637 unsigned char mac[MACADDRESS_SIZE] = {0};
8638 UINT wifi_count = 0;
8639 char virtual_interface_name[MAX_BUF_SIZE] = {0};
8640 char pipeCmd[MAX_CMD_SIZE] = {0};
8641
8642 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8643 *output_array_size = 0;
8644 *associated_dev_array = NULL;
8645 char interface_name[50] = {0};
8646
8647 if(wifi_getApName(apIndex, interface_name) != RETURN_OK) {
8648 wifi_dbg_printf("%s: wifi_getApName failed\n", __FUNCTION__);
8649 return RETURN_ERR;
8650 }
8651
8652 sprintf(pipeCmd, "iw dev %s station dump | grep %s | wc -l", interface_name, interface_name);
8653 fp = popen(pipeCmd, "r");
8654 if (fp == NULL)
8655 {
8656 printf("Failed to run command inside function %s\n",__FUNCTION__ );
8657 return RETURN_ERR;
8658 }
8659
8660 /* Read the output a line at a time - output it. */
8661 fgets(str, sizeof(str)-1, fp);
8662 wifi_count = (unsigned int) atoi ( str );
8663 *output_array_size = wifi_count;
8664 wifi_dbg_printf(" In rdkb hal ,Wifi Client Counts and index %d and %d \n",*output_array_size,apIndex);
8665 pclose(fp);
8666
8667 if(wifi_count == 0)
8668 {
8669 return RETURN_OK;
8670 }
8671 else
8672 {
8673 wifi_associated_dev2_t* temp = NULL;
8674 temp = (wifi_associated_dev2_t*)calloc(wifi_count, sizeof(wifi_associated_dev2_t));
8675 *associated_dev_array = temp;
8676 if(temp == NULL)
8677 {
8678 printf("Error Statement. Insufficient memory \n");
8679 return RETURN_ERR;
8680 }
8681
8682 snprintf(pipeCmd, sizeof(pipeCmd), "iw dev %s station dump > /tmp/AssociatedDevice_Stats.txt", interface_name);
8683 system(pipeCmd);
8684
8685 fp = fopen("/tmp/AssociatedDevice_Stats.txt", "r");
8686 if(fp == NULL)
8687 {
8688 printf("/tmp/AssociatedDevice_Stats.txt not exists \n");
8689 return RETURN_ERR;
8690 }
8691 fclose(fp);
8692
8693 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep Station | cut -d ' ' -f 2", interface_name);
8694 fp = popen(pipeCmd, "r");
8695 if(fp)
8696 {
8697 for(count =0 ; count < wifi_count; count++)
8698 {
8699 fgets(str, MAX_BUF_SIZE, fp);
8700 if( MACADDRESS_SIZE == sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",&arr[0],&arr[1],&arr[2],&arr[3],&arr[4],&arr[5]) )
8701 {
8702 for( wificlientindex = 0; wificlientindex < MACADDRESS_SIZE; ++wificlientindex )
8703 {
8704 mac[wificlientindex] = (unsigned char) arr[wificlientindex];
8705
8706 }
8707 memcpy(temp[count].cli_MACAddress,mac,(sizeof(unsigned char))*6);
8708 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]);
8709 }
8710 temp[count].cli_AuthenticationState = 1; //TODO
8711 temp[count].cli_Active = 1; //TODO
8712 }
8713 pclose(fp);
8714 }
8715
8716 //Updating RSSI per client
8717 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep signal | tr -s ' ' | cut -d ' ' -f 2 > /tmp/wifi_signalstrength.txt", interface_name);
8718 fp = popen(pipeCmd, "r");
8719 if(fp)
8720 {
8721 pclose(fp);
8722 }
8723 fp = popen("cat /tmp/wifi_signalstrength.txt | tr -s ' ' | cut -f 2","r");
8724 if(fp)
8725 {
8726 for(count =0 ; count < wifi_count ;count++)
8727 {
8728 fgets(str, MAX_BUF_SIZE, fp);
8729 signalstrength = atoi(str);
8730 temp[count].cli_RSSI = signalstrength;
8731 }
8732 pclose(fp);
8733 }
8734
8735
8736 //LastDataDownlinkRate
8737 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'tx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Send.txt", interface_name);
8738 fp = popen(pipeCmd, "r");
8739 if (fp)
8740 {
8741 pclose(fp);
8742 }
8743 fp = popen("cat /tmp/Ass_Bitrate_Send.txt | tr -s ' ' | cut -f 2", "r");
8744 if (fp)
8745 {
8746 for (count = 0; count < wifi_count; count++)
8747 {
8748 fgets(str, MAX_BUF_SIZE, fp);
8749 temp[count].cli_LastDataDownlinkRate = strtoul(str, NULL, 10);
8750 temp[count].cli_LastDataDownlinkRate = (temp[count].cli_LastDataDownlinkRate * 1024); //Mbps -> Kbps
8751 }
8752 pclose(fp);
8753 }
8754
8755 //LastDataUplinkRate
8756 sprintf(pipeCmd, "cat /tmp/AssociatedDevice_Stats.txt | grep 'rx bitrate' | tr -s ' ' | cut -d ' ' -f 2 > /tmp/Ass_Bitrate_Received.txt", interface_name);
8757 fp = popen(pipeCmd, "r");
8758 if (fp)
8759 {
8760 pclose(fp);
8761 }
8762 fp = popen("cat /tmp/Ass_Bitrate_Received.txt | tr -s ' ' | cut -f 2", "r");
8763 if (fp)
8764 {
8765 for (count = 0; count < wifi_count; count++)
8766 {
8767 fgets(str, MAX_BUF_SIZE, fp);
8768 temp[count].cli_LastDataUplinkRate = strtoul(str, NULL, 10);
8769 temp[count].cli_LastDataUplinkRate = (temp[count].cli_LastDataUplinkRate * 1024); //Mbps -> Kbps
8770 }
8771 pclose(fp);
8772 }
8773 }
8774 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8775 return RETURN_OK;
8776
8777}
8778
8779INT wifi_getSSIDTrafficStats2(INT ssidIndex,wifi_ssidTrafficStats2_t *output_struct)
8780{
8781#if 0
8782 /*char buf[1024] = {0};
8783 sprintf(cmd, "ifconfig %s%d ", AP_PREFIX, ssidIndex);
8784 _syscmd(cmd, buf, sizeof(buf));*/
8785
8786 output_struct->ssid_BytesSent = 2048; //The total number of bytes transmitted out of the interface, including framing characters.
8787 output_struct->ssid_BytesReceived = 4096; //The total number of bytes received on the interface, including framing characters.
8788 output_struct->ssid_PacketsSent = 128; //The total number of packets transmitted out of the interface.
8789 output_struct->ssid_PacketsReceived = 128; //The total number of packets received on the interface.
8790
8791 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.
8792 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].
8793 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].
8794 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].
8795 output_struct->ssid_ACKFailureCount = 0; //The number of expected ACKs that were never received. This parameter is based on dot11ACKFailureCount from [802.11-2012].
8796 output_struct->ssid_AggregatedPacketCount = 0; //The number of aggregated packets that were transmitted. This applies only to 802.11n and 802.11ac.
8797
8798 output_struct->ssid_ErrorsSent = 0; //The total number of outbound packets that could not be transmitted because of errors.
8799 output_struct->ssid_ErrorsReceived = 0; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8800 output_struct->ssid_UnicastPacketsSent = 2; //The total number of inbound packets that contained errors preventing them from being delivered to a higher-layer protocol.
8801 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.
8802 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.
8803 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.
8804 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.
8805 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.
8806 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.
8807 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.
8808 output_struct->ssid_UnknownPacketsReceived = 0; //The total number of packets received via the interface which were discarded because of an unknown or unsupported protocol.
8809#endif
8810
8811 FILE *fp = NULL;
developerce736392022-09-13 15:24:34 +08008812 char HConf_file[128] = {'\0'};
developer06a01d92022-09-07 16:32:39 +08008813 char interface_name[50] = {0};
developerce736392022-09-13 15:24:34 +08008814 char pipeCmd[128] = {0};
8815 char str[256] = {0};
developer06a01d92022-09-07 16:32:39 +08008816 wifi_ssidTrafficStats2_t *out = output_struct;
8817
developerce736392022-09-13 15:24:34 +08008818 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n", __func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08008819 if (!output_struct)
8820 return RETURN_ERR;
8821
developerce736392022-09-13 15:24:34 +08008822 memset(out, 0, sizeof(wifi_ssidTrafficStats2_t));
8823 sprintf(HConf_file, "%s%d.conf", CONFIG_PREFIX, ssidIndex);
8824 GetInterfaceName(interface_name, HConf_file);
8825 sprintf(pipeCmd, "cat /proc/net/dev | grep %s", interface_name);
developer06a01d92022-09-07 16:32:39 +08008826
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);
developer06a01d92022-09-07 16:32:39 +08008833
developerce736392022-09-13 15:24:34 +08008834 if (strlen(str) == 0) // interface not exist
8835 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +08008836
developerce736392022-09-13 15:24:34 +08008837 sscanf(str, "%*[^:]: %lu %lu %lu %lu %* %* %* %* %lu %lu %lu %lu", &out->ssid_BytesReceived, &out->ssid_PacketsReceived, &out->ssid_ErrorsReceived, \
8838 &out->ssid_DiscardedPacketsReceived, &out->ssid_BytesSent, &out->ssid_PacketsSent, &out->ssid_ErrorsSent, &out->ssid_DiscardedPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008839 pclose(fp);
8840
developerce736392022-09-13 15:24:34 +08008841 memset(str, 0, sizeof(str));
8842 sprintf(pipeCmd, "tail -n1 /proc/net/netstat");
developer06a01d92022-09-07 16:32:39 +08008843 fp = popen(pipeCmd, "r");
developerce736392022-09-13 15:24:34 +08008844 if (fp == NULL) {
8845 fprintf(stderr, "%s: popen failed\n", __func__);
8846 return RETURN_ERR;
8847 }
8848 fgets(str, sizeof(str), fp);
8849
8850 sscanf(str, "%*[^:]: %* %* %lu %lu %lu %lu", &out->ssid_MulticastPacketsReceived, &out->ssid_MulticastPacketsSent, &out->ssid_BroadcastPacketsRecevied, \
8851 &out->ssid_BroadcastPacketsSent);
developer06a01d92022-09-07 16:32:39 +08008852 pclose(fp);
developerce736392022-09-13 15:24:34 +08008853
8854 out->ssid_UnicastPacketsSent = out->ssid_PacketsSent - out->ssid_MulticastPacketsSent - out->ssid_BroadcastPacketsSent - out->ssid_DiscardedPacketsSent;
8855 out->ssid_UnicastPacketsReceived = out->ssid_PacketsReceived - out->ssid_MulticastPacketsReceived - out->ssid_BroadcastPacketsRecevied - out->ssid_DiscardedPacketsReceived;
8856
8857 // Not supported
8858 output_struct->ssid_RetransCount = 0;
8859 output_struct->ssid_FailedRetransCount = 0;
8860 output_struct->ssid_RetryCount = 0;
8861 output_struct->ssid_MultipleRetryCount = 0;
8862 output_struct->ssid_ACKFailureCount = 0;
8863 output_struct->ssid_AggregatedPacketCount = 0;
8864
developer06a01d92022-09-07 16:32:39 +08008865 return RETURN_OK;
8866}
8867
8868//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).
8869INT wifi_getApIsolationEnable(INT apIndex, BOOL *output)
8870{
8871 char output_val[16]={'\0'};
8872 char config_file[MAX_BUF_SIZE] = {0};
8873
8874 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8875 if (!output)
8876 return RETURN_ERR;
8877 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8878 wifi_hostapdRead(config_file, "ap_isolate", output_val, sizeof(output_val));
8879
8880 if( strcmp(output_val,"1") == 0 )
8881 *output = TRUE;
8882 else
8883 *output = FALSE;
8884 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8885
8886 return RETURN_OK;
8887}
8888
8889INT wifi_setApIsolationEnable(INT apIndex, BOOL enable)
8890{
8891 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8892 char str[MAX_BUF_SIZE]={'\0'};
8893 char string[MAX_BUF_SIZE]={'\0'};
8894 char cmd[MAX_CMD_SIZE]={'\0'};
8895 char *ch;
8896 char config_file[MAX_BUF_SIZE] = {0};
8897 struct params params;
8898
8899 if(enable == TRUE)
8900 strcpy(string,"1");
8901 else
8902 strcpy(string,"0");
8903
8904 params.name = "ap_isolate";
8905 params.value = string;
8906
8907 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
8908 wifi_hostapdWrite(config_file,&params,1);
8909 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
8910
8911 return RETURN_OK;
8912}
8913
8914INT wifi_getApManagementFramePowerControl(INT apIndex, INT *output_dBm)
8915{
8916 if (NULL == output_dBm)
8917 return RETURN_ERR;
8918
8919 *output_dBm = 0;
8920 return RETURN_OK;
8921}
8922
8923INT wifi_setApManagementFramePowerControl(INT wlanIndex, INT dBm)
8924{
8925 return RETURN_OK;
8926}
8927INT wifi_getRadioDcsChannelMetrics(INT radioIndex,wifi_channelMetrics_t *input_output_channelMetrics_array,INT size)
8928{
8929 return RETURN_OK;
8930}
8931INT wifi_setRadioDcsDwelltime(INT radioIndex, INT ms)
8932{
8933 return RETURN_OK;
8934}
8935INT wifi_getRadioDcsDwelltime(INT radioIndex, INT *ms)
8936{
8937 return RETURN_OK;
8938}
8939INT wifi_setRadioDcsScanning(INT radioIndex, BOOL enable)
8940{
8941 return RETURN_OK;
8942}
8943INT wifi_setBSSTransitionActivation(UINT apIndex, BOOL activate)
8944{
8945 char config_file[MAX_BUF_SIZE] = {0};
8946 struct params list;
8947
8948 list.name = "bss_transition";
8949 list.value = activate?"1":"0";
8950 snprintf(config_file, sizeof(config_file), "%s%d.conf",CONFIG_PREFIX,apIndex);
8951 wifi_hostapdWrite(config_file, &list, 1);
8952
8953 return RETURN_OK;
8954}
8955wifi_apAuthEvent_callback apAuthEvent_cb = NULL;
8956
8957void wifi_apAuthEvent_callback_register(wifi_apAuthEvent_callback callback_proc)
8958{
8959 return;
8960}
8961
8962INT wifi_setApCsaDeauth(INT apIndex, INT mode)
8963{
8964 // TODO Implement me!
8965 return RETURN_OK;
8966}
8967
8968INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
8969{
developera3c68b92022-09-13 15:27:29 +08008970 char file_name[128] = {0};
8971 char buf[128] = {0};
8972 FILE *f = NULL;
8973
8974 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
8975
8976 if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
8977 for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
8978 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
8979 f = fopen(file_name, "w");
8980 if (f == NULL)
8981 return RETURN_ERR;
8982 // For mode == 0 is to disable filter, just don't write to the file.
8983 if (mode)
8984 fprintf(f, "%s", essid);
8985
8986 fclose(f);
8987 }
8988 } else { // special case, need to set AP's SSID as filter for each radio.
8989 snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
8990 f = fopen(file_name, "w");
8991 if (f == NULL)
8992 return RETURN_ERR;
8993
8994 // For mode == 0 is to disable filter, just don't write to the file.
8995 if (mode)
8996 fprintf(f, "%s", essid);
8997
8998 fclose(f);
8999 }
9000
9001 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009002 return RETURN_OK;
9003}
9004
9005INT wifi_pushRadioChannel(INT radioIndex, UINT channel)
9006{
9007 // TODO Implement me!
9008 //Apply wifi_pushRadioChannel() instantly
9009 return RETURN_ERR;
9010}
9011
9012INT wifi_setRadioStatsEnable(INT radioIndex, BOOL enable)
9013{
9014 // TODO Implement me!
9015 return RETURN_OK;
9016}
9017
9018#ifdef HAL_NETLINK_IMPL
9019static int tidStats_callback(struct nl_msg *msg, void *arg) {
9020 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9021 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9022 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9023 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1],*tidattr;
9024 int rem , tid_index = 0;
9025
9026 wifi_associated_dev_tid_stats_t *out = (wifi_associated_dev_tid_stats_t*)arg;
9027 wifi_associated_dev_tid_entry_t *stats_entry;
9028
9029 static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
9030 [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
9031 };
9032 static struct nla_policy tid_policy[NL80211_TID_STATS_MAX + 1] = {
9033 [NL80211_TID_STATS_TX_MSDU] = { .type = NLA_U64 },
9034 };
9035
9036 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
9037 genlmsg_attrlen(gnlh, 0), NULL);
9038
9039
9040 if (!tb[NL80211_ATTR_STA_INFO]) {
9041 fprintf(stderr, "station stats missing!\n");
9042 return NL_SKIP;
9043 }
9044
9045 if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
9046 tb[NL80211_ATTR_STA_INFO],
9047 stats_policy)) {
9048 fprintf(stderr, "failed to parse nested attributes!\n");
9049 return NL_SKIP;
9050 }
9051
9052 nla_for_each_nested(tidattr, sinfo[NL80211_STA_INFO_TID_STATS], rem)
9053 {
9054 stats_entry = &out->tid_array[tid_index];
9055
9056 stats_entry->tid = tid_index;
9057 stats_entry->ac = _tid_ac_index_get[tid_index];
9058
9059 if(sinfo[NL80211_STA_INFO_TID_STATS])
9060 {
9061 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,tidattr, tid_policy)) {
9062 printf("failed to parse nested stats attributes!");
9063 return NL_SKIP;
9064 }
9065 }
9066 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9067 stats_entry->num_msdus = (unsigned long long)nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9068
9069 if(tid_index < (PS_MAX_TID - 1))
9070 tid_index++;
9071 }
9072 //ToDo: sum_time_ms, ewma_time_ms
9073 return NL_SKIP;
9074}
9075#endif
9076
9077INT wifi_getApAssociatedDeviceTidStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_tid_stats_t *tid_stats, ULLONG *handle)
9078{
9079#ifdef HAL_NETLINK_IMPL
9080 Netlink nl;
9081 char if_name[10];
9082
9083 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9084
9085 nl.id = initSock80211(&nl);
9086
9087 if (nl.id < 0) {
9088 fprintf(stderr, "Error initializing netlink \n");
9089 return -1;
9090 }
9091
9092 struct nl_msg* msg = nlmsg_alloc();
9093
9094 if (!msg) {
9095 fprintf(stderr, "Failed to allocate netlink message.\n");
9096 nlfree(&nl);
9097 return -2;
9098 }
9099
9100 genlmsg_put(msg,
9101 NL_AUTO_PORT,
9102 NL_AUTO_SEQ,
9103 nl.id,
9104 0,
9105 0,
9106 NL80211_CMD_GET_STATION,
9107 0);
9108
9109 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9110 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9111 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,tidStats_callback,tid_stats);
9112 nl_send_auto(nl.socket, msg);
9113 nl_recvmsgs(nl.socket, nl.cb);
9114 nlmsg_free(msg);
9115 nlfree(&nl);
9116 return RETURN_OK;
9117#else
9118//iw implementation
9119#define TID_STATS_FILE "/tmp/tid_stats_file.txt"
9120#define TOTAL_MAX_LINES 50
9121
9122 char buf[256] = {'\0'}; /* or other suitable maximum line size */
9123 char if_name[10];
9124 FILE *fp=NULL;
9125 char pipeCmd[1024]= {'\0'};
9126 int lines,tid_index=0;
9127 char mac_addr[20] = {'\0'};
9128
9129 wifi_associated_dev_tid_entry_t *stats_entry;
9130
9131 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9132 strcpy(mac_addr,clientMacAddress);
9133
9134 snprintf(pipeCmd,sizeof(pipeCmd),"iw dev %s station dump -v > "TID_STATS_FILE,if_name);
9135 fp= popen(pipeCmd,"r");
9136 if(fp == NULL)
9137 {
9138 perror("popen for station dump failed\n");
9139 return RETURN_ERR;
9140 }
9141 pclose(fp);
9142
9143 snprintf(pipeCmd,sizeof(pipeCmd),"grep -n 'Station' "TID_STATS_FILE " | cut -d ':' -f1 | head -2 | tail -1");
9144 fp=popen(pipeCmd,"r");
9145 if(fp == NULL)
9146 {
9147 perror("popen for grep station failed\n");
9148 return RETURN_ERR;
9149 }
9150 else if(fgets(buf,sizeof(buf),fp) != NULL)
9151 lines=atoi(buf);
9152 else
9153 {
9154 pclose(fp);
9155 fprintf(stderr,"No devices are connected \n");
9156 return RETURN_ERR;
9157 }
9158 pclose(fp);
9159
9160 if(lines == 1)
9161 lines = TOTAL_MAX_LINES; //only one client is connected , considering next MAX lines of iw output
9162
9163 for(tid_index=0; tid_index<PS_MAX_TID; tid_index++)
9164 {
9165 stats_entry = &tid_stats->tid_array[tid_index];
9166 stats_entry->tid = tid_index;
9167
9168 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);
9169
9170 fp=popen(pipeCmd,"r");
9171 if(fp ==NULL)
9172 {
9173 perror("Failed to read from tid file \n");
9174 return RETURN_ERR;
9175 }
9176 else if(fgets(buf,sizeof(buf),fp) != NULL)
9177 stats_entry->num_msdus = atol(buf);
9178
9179 pclose(fp);
9180 stats_entry->ac = _tid_ac_index_get[tid_index];
9181// TODO:
9182// ULLONG ewma_time_ms; <! Moving average value based on last couple of transmitted msdus
9183// ULLONG sum_time_ms; <! Delta of cumulative msdus times over interval
9184 }
9185 return RETURN_OK;
9186#endif
9187}
9188
9189
9190INT wifi_startNeighborScan(INT apIndex, wifi_neighborScanMode_t scan_mode, INT dwell_time, UINT chan_num, UINT *chan_list)
9191{
developer615510b2022-09-27 10:14:35 +08009192 char cmd[128]={0};
9193 char buf[128]={0};
9194 int freq = 0;
9195
9196 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9197
9198 // full mode is used to scan all channels.
9199 // multiple channels is ambiguous, iw can not set multiple frequencies in one time.
9200 if (scan_mode != WIFI_RADIO_SCAN_MODE_FULL)
9201 ieee80211_channel_to_frequency(chan_list[0], &freq);
9202
9203 if (freq)
9204 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d freq %d", AP_PREFIX, apIndex, dwell_time, freq);
9205 else
9206 snprintf(cmd, sizeof(cmd), "iw dev %s%d scan trigger duration %d", AP_PREFIX, apIndex, dwell_time);
9207
9208 _syscmd(cmd, buf, sizeof(buf));
9209 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9210
developer06a01d92022-09-07 16:32:39 +08009211 return RETURN_OK;
9212}
9213
9214
9215INT wifi_steering_setGroup(UINT steeringgroupIndex, wifi_steering_apConfig_t *cfg_2, wifi_steering_apConfig_t *cfg_5)
9216{
9217 // TODO Implement me!
9218 return RETURN_ERR;
9219}
9220
9221INT wifi_steering_clientSet(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_steering_clientConfig_t *config)
9222{
9223 // TODO Implement me!
9224 return RETURN_ERR;
9225}
9226
9227INT wifi_steering_clientRemove(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9228{
9229 // TODO Implement me!
9230 return RETURN_ERR;
9231}
9232
9233INT wifi_steering_clientMeasure(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac)
9234{
9235 // TODO Implement me!
9236 return RETURN_ERR;
9237}
9238
9239INT wifi_steering_clientDisconnect(UINT steeringgroupIndex, INT apIndex, mac_address_t client_mac, wifi_disconnectType_t type, UINT reason)
9240{
9241 // TODO Implement me!
9242 return RETURN_ERR;
9243}
9244
9245INT wifi_steering_eventRegister(wifi_steering_eventCB_t event_cb)
9246{
9247 // TODO Implement me!
9248 return RETURN_ERR;
9249}
9250
9251INT wifi_steering_eventUnregister(void)
9252{
9253 // TODO Implement me!
9254 return RETURN_ERR;
9255}
9256
9257INT wifi_delApAclDevices(INT apIndex)
9258{
9259#if 0
9260 char cmd[MAX_BUF_SIZE] = {0};
9261 char buf[MAX_BUF_SIZE] = {0};
9262
9263 /* Not reset proof solution */
9264 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d accept_acl CLEAR", AP_PREFIX, apIndex);
9265 if(_syscmd(cmd,buf,sizeof(buf)))
9266 return RETURN_ERR;
9267#endif
developere6aafda2022-09-13 14:59:28 +08009268 char cmd[MAX_CMD_SIZE]={0};
9269 char buf[MAX_BUF_SIZE]={0};
developer06a01d92022-09-07 16:32:39 +08009270
developere6aafda2022-09-13 14:59:28 +08009271 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9272 sprintf(cmd, "rm %s%d 2>&1 && touch %s%d", ACL_PREFIX, apIndex, ACL_PREFIX, apIndex);
9273 if(_syscmd(cmd, buf, sizeof(buf)))
9274 return RETURN_ERR;
9275 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +08009276
9277 return RETURN_OK;
9278}
9279
9280#ifdef HAL_NETLINK_IMPL
9281static int rxStatsInfo_callback(struct nl_msg *msg, void *arg) {
9282 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9283 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9284 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9285 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9286 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9287 char mac_addr[20],dev[20];
9288
9289 nla_parse(tb,
9290 NL80211_ATTR_MAX,
9291 genlmsg_attrdata(gnlh, 0),
9292 genlmsg_attrlen(gnlh, 0),
9293 NULL);
9294
9295 if(!tb[NL80211_ATTR_STA_INFO]) {
9296 fprintf(stderr, "sta stats missing!\n");
9297 return NL_SKIP;
9298 }
9299
9300 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9301 fprintf(stderr, "failed to parse nested attributes!\n");
9302 return NL_SKIP;
9303 }
9304 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9305
9306 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9307
9308 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_RX_BITRATE], rate_policy )) {
9309 fprintf(stderr, "failed to parse nested rate attributes!");
9310 return NL_SKIP;
9311 }
9312
9313 if(sinfo[NL80211_STA_INFO_TID_STATS])
9314 {
9315 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9316 printf("failed to parse nested stats attributes!");
9317 return NL_SKIP;
9318 }
9319 }
9320
9321 if( nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]) )
9322 {
9323 printf("Type is VHT\n");
9324 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9325 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9326
9327 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9328 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 1;
9329 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9330 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9331 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9332 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9333 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9334 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 2;
9335 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]) )
9336 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9337 }
9338 else
9339 {
9340 printf(" OFDM or CCK \n");
9341 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bw = 0;
9342 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->nss = 0;
9343 }
9344
9345 if(sinfo[NL80211_STA_INFO_RX_BITRATE]) {
9346 if(rinfo[NL80211_RATE_INFO_MCS])
9347 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9348 }
9349 if(sinfo[NL80211_STA_INFO_RX_BYTES64])
9350 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_RX_BYTES64]);
9351 else if (sinfo[NL80211_STA_INFO_RX_BYTES])
9352 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]);
9353
9354 if(stats_info[NL80211_TID_STATS_RX_MSDU])
9355 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_RX_MSDU]);
9356
9357 if (sinfo[NL80211_STA_INFO_SIGNAL])
9358 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->rssi_combined = nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]);
9359 //Assigning 0 for RETRIES ,PPDUS and MPDUS as we dont have rx retries attribute in libnl_3.3.0
9360 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->retries = 0;
9361 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->ppdus = 0;
9362 ((wifi_associated_dev_rate_info_rx_stats_t*)arg)->msdus = 0;
9363 //rssi_array need to be filled
9364 return NL_SKIP;
9365}
9366#endif
9367
9368INT wifi_getApAssociatedDeviceRxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_rx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9369{
9370#ifdef HAL_NETLINK_IMPL
9371 Netlink nl;
9372 char if_name[10];
9373
9374 *output_array_size = sizeof(wifi_associated_dev_rate_info_rx_stats_t);
9375
9376 if (*output_array_size <= 0)
9377 return RETURN_OK;
9378
9379 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9380 nl.id = initSock80211(&nl);
9381
9382 if (nl.id < 0) {
9383 fprintf(stderr, "Error initializing netlink \n");
9384 return 0;
9385 }
9386
9387 struct nl_msg* msg = nlmsg_alloc();
9388
9389 if (!msg) {
9390 fprintf(stderr, "Failed to allocate netlink message.\n");
9391 nlfree(&nl);
9392 return 0;
9393 }
9394
9395 genlmsg_put(msg,
9396 NL_AUTO_PORT,
9397 NL_AUTO_SEQ,
9398 nl.id,
9399 0,
9400 0,
9401 NL80211_CMD_GET_STATION,
9402 0);
9403
9404 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, *clientMacAddress);
9405 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9406 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, rxStatsInfo_callback, stats_array);
9407 nl_send_auto(nl.socket, msg);
9408 nl_recvmsgs(nl.socket, nl.cb);
9409 nlmsg_free(msg);
9410 nlfree(&nl);
9411 return RETURN_OK;
9412#else
9413 //TODO Implement me
9414 return RETURN_OK;
9415#endif
9416}
9417
9418#ifdef HAL_NETLINK_IMPL
9419static int txStatsInfo_callback(struct nl_msg *msg, void *arg) {
9420 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9421 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9422 struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
9423 struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
9424 struct nlattr *stats_info[NL80211_TID_STATS_MAX + 1];
9425 char mac_addr[20],dev[20];
9426
9427 nla_parse(tb,
9428 NL80211_ATTR_MAX,
9429 genlmsg_attrdata(gnlh, 0),
9430 genlmsg_attrlen(gnlh, 0),
9431 NULL);
9432
9433 if(!tb[NL80211_ATTR_STA_INFO]) {
9434 fprintf(stderr, "sta stats missing!\n");
9435 return NL_SKIP;
9436 }
9437
9438 if(nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,tb[NL80211_ATTR_STA_INFO], stats_policy)) {
9439 fprintf(stderr, "failed to parse nested attributes!\n");
9440 return NL_SKIP;
9441 }
9442
9443 mac_addr_ntoa(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
9444
9445 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9446
9447 if(nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) {
9448 fprintf(stderr, "failed to parse nested rate attributes!");
9449 return NL_SKIP;
9450 }
9451
9452 if(sinfo[NL80211_STA_INFO_TID_STATS])
9453 {
9454 if(nla_parse_nested(stats_info, NL80211_TID_STATS_MAX,sinfo[NL80211_STA_INFO_TID_STATS], tid_policy)) {
9455 printf("failed to parse nested stats attributes!");
9456 return NL_SKIP;
9457 }
9458 }
9459 if(nla_data(tb[NL80211_ATTR_VHT_CAPABILITY]))
9460 {
9461 printf("Type is VHT\n");
9462 if(rinfo[NL80211_RATE_INFO_VHT_NSS])
9463 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = nla_get_u8(rinfo[NL80211_RATE_INFO_VHT_NSS]);
9464
9465 if(rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
9466 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 1;
9467 if(rinfo[NL80211_RATE_INFO_80_MHZ_WIDTH])
9468 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9469 if(rinfo[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
9470 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9471 if(rinfo[NL80211_RATE_INFO_160_MHZ_WIDTH])
9472 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 2;
9473 if((rinfo[NL80211_RATE_INFO_10_MHZ_WIDTH]) || (rinfo[NL80211_RATE_INFO_5_MHZ_WIDTH]))
9474 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9475 }
9476 else
9477 {
9478 printf(" OFDM or CCK \n");
9479 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bw = 0;
9480 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->nss = 0;
9481 }
9482
9483 if(sinfo[NL80211_STA_INFO_TX_BITRATE]) {
9484 if(rinfo[NL80211_RATE_INFO_MCS])
9485 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mcs = nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]);
9486 }
9487
9488 if(sinfo[NL80211_STA_INFO_TX_BYTES64])
9489 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u64(sinfo[NL80211_STA_INFO_TX_BYTES64]);
9490 else if (sinfo[NL80211_STA_INFO_TX_BYTES])
9491 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->bytes = nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]);
9492
9493 //Assigning 0 for mpdus and ppdus , as we do not have attributes in netlink
9494 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9495 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->mpdus = 0;
9496
9497 if(stats_info[NL80211_TID_STATS_TX_MSDU])
9498 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->msdus = nla_get_u64(stats_info[NL80211_TID_STATS_TX_MSDU]);
9499
9500 if(sinfo[NL80211_STA_INFO_TX_RETRIES])
9501 ((wifi_associated_dev_rate_info_tx_stats_t*)arg)->retries = nla_get_u32(sinfo[NL80211_STA_INFO_TX_RETRIES]);
9502
9503 if(sinfo[NL80211_STA_INFO_TX_FAILED])
9504 ((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]);
9505
9506 return NL_SKIP;
9507}
9508#endif
9509
9510INT wifi_getApAssociatedDeviceTxStatsResult(INT radioIndex, mac_address_t *clientMacAddress, wifi_associated_dev_rate_info_tx_stats_t **stats_array, UINT *output_array_size, ULLONG *handle)
9511{
9512#ifdef HAL_NETLINK_IMPL
9513 Netlink nl;
9514 char if_name[10];
9515
9516 *output_array_size = sizeof(wifi_associated_dev_rate_info_tx_stats_t);
9517
9518 if (*output_array_size <= 0)
9519 return RETURN_OK;
9520
9521 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9522
9523 nl.id = initSock80211(&nl);
9524
9525 if(nl.id < 0) {
9526 fprintf(stderr, "Error initializing netlink \n");
9527 return 0;
9528 }
9529
9530 struct nl_msg* msg = nlmsg_alloc();
9531
9532 if(!msg) {
9533 fprintf(stderr, "Failed to allocate netlink message.\n");
9534 nlfree(&nl);
9535 return 0;
9536 }
9537
9538 genlmsg_put(msg,
9539 NL_AUTO_PORT,
9540 NL_AUTO_SEQ,
9541 nl.id,
9542 0,
9543 0,
9544 NL80211_CMD_GET_STATION,
9545 0);
9546
9547 nla_put(msg, NL80211_ATTR_MAC, MAC_ALEN, clientMacAddress);
9548 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9549 nl_cb_set(nl.cb, NL_CB_VALID , NL_CB_CUSTOM, txStatsInfo_callback, stats_array);
9550 nl_send_auto(nl.socket, msg);
9551 nl_recvmsgs(nl.socket, nl.cb);
9552 nlmsg_free(msg);
9553 nlfree(&nl);
9554 return RETURN_OK;
9555#else
9556 //TODO Implement me
9557 return RETURN_OK;
9558#endif
9559}
9560
9561INT wifi_getBSSTransitionActivation(UINT apIndex, BOOL *activate)
9562{
9563 // TODO Implement me!
9564 char buf[MAX_BUF_SIZE] = {0};
9565 char config_file[MAX_BUF_SIZE] = {0};
9566
9567 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, apIndex);
9568 wifi_hostapdRead(config_file, "bss_transition", buf, sizeof(buf));
9569 *activate = (strncmp("1",buf,1) == 0);
9570
9571 return RETURN_OK;
9572}
9573
9574INT wifi_setNeighborReportActivation(UINT apIndex, BOOL activate)
9575{
9576 char config_file[MAX_BUF_SIZE] = {0};
9577 struct params list;
9578
9579 list.name = "rrm_neighbor_report";
9580 list.value = activate?"1":"0";
9581 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9582 wifi_hostapdWrite(config_file, &list, 1);
9583
9584 return RETURN_OK;
9585}
9586
9587INT wifi_getNeighborReportActivation(UINT apIndex, BOOL *activate)
9588{
9589 char buf[32] = {0};
9590 char config_file[MAX_BUF_SIZE] = {0};
9591
9592 sprintf(config_file,"%s%d.conf",CONFIG_PREFIX,apIndex);
9593 wifi_hostapdRead(config_file, "rrm_neighbor_report", buf, sizeof(buf));
9594 *activate = (strncmp("1",buf,1) == 0);
9595
9596 return RETURN_OK;
9597}
9598#undef HAL_NETLINK_IMPL
9599#ifdef HAL_NETLINK_IMPL
9600static int chanSurveyInfo_callback(struct nl_msg *msg, void *arg) {
9601 struct nlattr *tb[NL80211_ATTR_MAX + 1];
9602 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
9603 struct nlattr *sinfo[NL80211_SURVEY_INFO_MAX + 1];
9604 char dev[20];
9605 int freq =0 ;
9606 static int i=0;
9607
9608 wifi_channelStats_t_loc *out = (wifi_channelStats_t_loc*)arg;
9609
9610 static struct nla_policy survey_policy[NL80211_SURVEY_INFO_MAX + 1] = {
9611 };
9612
9613 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),genlmsg_attrlen(gnlh, 0), NULL);
9614
9615 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
9616
9617 if (!tb[NL80211_ATTR_SURVEY_INFO]) {
9618 fprintf(stderr, "survey data missing!\n");
9619 return NL_SKIP;
9620 }
9621
9622 if (nla_parse_nested(sinfo, NL80211_SURVEY_INFO_MAX,tb[NL80211_ATTR_SURVEY_INFO],survey_policy))
9623 {
9624 fprintf(stderr, "failed to parse nested attributes!\n");
9625 return NL_SKIP;
9626 }
9627
9628
9629 if(out[0].array_size == 1 )
9630 {
9631 if(sinfo[NL80211_SURVEY_INFO_IN_USE])
9632 {
9633 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9634 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9635 out[0].ch_number = ieee80211_frequency_to_channel(freq);
9636
9637 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9638 out[0].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9639 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9640 out[0].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9641 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9642 out[0].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9643 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9644 out[0].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9645 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9646 out[0].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9647 if (sinfo[NL80211_SURVEY_INFO_TIME])
9648 out[0].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9649 return NL_STOP;
9650 }
9651 }
9652 else
9653 {
9654 if ( i <= out[0].array_size )
9655 {
9656 if (sinfo[NL80211_SURVEY_INFO_FREQUENCY])
9657 freq = nla_get_u32(sinfo[NL80211_SURVEY_INFO_FREQUENCY]);
9658 out[i].ch_number = ieee80211_frequency_to_channel(freq);
9659
9660 if (sinfo[NL80211_SURVEY_INFO_NOISE])
9661 out[i].ch_noise = nla_get_u8(sinfo[NL80211_SURVEY_INFO_NOISE]);
9662 if (sinfo[NL80211_SURVEY_INFO_TIME_RX])
9663 out[i].ch_utilization_busy_rx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_RX]);
9664 if (sinfo[NL80211_SURVEY_INFO_TIME_TX])
9665 out[i].ch_utilization_busy_tx = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_TX]);
9666 if (sinfo[NL80211_SURVEY_INFO_TIME_BUSY])
9667 out[i].ch_utilization_busy = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_BUSY]);
9668 if (sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY])
9669 out[i].ch_utilization_busy_ext = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME_EXT_BUSY]);
9670 if (sinfo[NL80211_SURVEY_INFO_TIME])
9671 out[i].ch_utilization_total = nla_get_u64(sinfo[NL80211_SURVEY_INFO_TIME]);
9672 }
9673 }
9674
9675 i++;
9676 return NL_SKIP;
9677}
9678#endif
9679
9680static int ieee80211_channel_to_frequency(int channel, int *freqMHz)
9681{
9682 char command[MAX_CMD_SIZE], output[MAX_BUF_SIZE];
9683 FILE *fp;
9684
9685 if(access("/tmp/freq-channel-map.txt", F_OK)==-1)
9686 {
9687 printf("Creating Frequency-Channel Map\n");
9688 system("iw phy | grep 'MHz \\[' | cut -d' ' -f2,4 > /tmp/freq-channel-map.txt");
9689 }
9690 snprintf(command, sizeof(command), "cat /tmp/freq-channel-map.txt | grep '\\[%d\\]$' | cut -d' ' -f1", channel);
9691 if((fp = popen(command, "r")))
9692 {
9693 fgets(output, sizeof(output), fp);
9694 *freqMHz = atoi(output);
9695 fclose(fp);
9696 }
9697
9698 return 0;
9699}
9700
9701static int get_survey_dump_buf(INT radioIndex, int channel, const char *buf, size_t bufsz)
9702{
9703 int freqMHz = -1;
9704 char cmd[MAX_CMD_SIZE] = {'\0'};
9705
9706 ieee80211_channel_to_frequency(channel, &freqMHz);
9707 if (freqMHz == -1) {
9708 wifi_dbg_printf("%s: failed to get channel frequency for channel: %d\n", __func__, channel);
9709 return -1;
9710 }
9711
9712 if (sprintf(cmd,"iw dev %s%d survey dump | grep -A5 %d | tr -d '\\t'", RADIO_PREFIX, radioIndex, freqMHz) < 0) {
9713 wifi_dbg_printf("%s: failed to build iw dev command for radioIndex=%d freq=%d\n", __FUNCTION__,
9714 radioIndex, freqMHz);
9715 return -1;
9716 }
9717
9718 if (_syscmd(cmd, buf, bufsz) == RETURN_ERR) {
9719 wifi_dbg_printf("%s: failed to execute '%s' for radioIndex=%d\n", __FUNCTION__, cmd, radioIndex);
9720 return -1;
9721 }
9722
9723 return 0;
9724}
9725
9726static int fetch_survey_from_buf(INT radioIndex, const char *buf, wifi_channelStats_t *stats)
9727{
9728 const char *ptr = buf;
9729 char *key = NULL;
9730 char *val = NULL;
9731 char line[256] = { '\0' };
9732
9733 while (ptr = get_line_from_str_buf(ptr, line)) {
9734 if (strstr(line, "Frequency")) continue;
9735
9736 key = strtok(line, ":");
9737 val = strtok(NULL, " ");
9738 wifi_dbg_printf("%s: key='%s' val='%s'\n", __func__, key, val);
9739
9740 if (!strcmp(key, "noise")) {
9741 sscanf(val, "%d", &stats->ch_noise);
9742 if (stats->ch_noise == 0) {
9743 // Workaround for missing noise information.
9744 // Assume -95 for 2.4G and -103 for 5G
9745 if (radioIndex == 0) stats->ch_noise = -95;
9746 if (radioIndex == 1) stats->ch_noise = -103;
9747 }
9748 }
9749 else if (!strcmp(key, "channel active time")) {
9750 sscanf(val, "%llu", &stats->ch_utilization_total);
9751 }
9752 else if (!strcmp(key, "channel busy time")) {
9753 sscanf(val, "%llu", &stats->ch_utilization_busy);
9754 }
9755 else if (!strcmp(key, "channel receive time")) {
9756 sscanf(val, "%llu", &stats->ch_utilization_busy_rx);
9757 }
9758 else if (!strcmp(key, "channel transmit time")) {
9759 sscanf(val, "%llu", &stats->ch_utilization_busy_tx);
9760 }
9761 };
9762
9763 return 0;
9764}
9765
9766INT wifi_getRadioChannelStats(INT radioIndex,wifi_channelStats_t *input_output_channelStats_array,INT array_size)
9767{
9768 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
9769#ifdef HAL_NETLINK_IMPL
9770 Netlink nl;
9771 wifi_channelStats_t_loc local[array_size];
9772 char if_name[10];
9773
9774 local[0].array_size = array_size;
9775
9776 snprintf(if_name, sizeof(if_name), "%s%d", AP_PREFIX, radioIndex);
9777
9778 nl.id = initSock80211(&nl);
9779
9780 if (nl.id < 0) {
9781 fprintf(stderr, "Error initializing netlink \n");
9782 return -1;
9783 }
9784
9785 struct nl_msg* msg = nlmsg_alloc();
9786
9787 if (!msg) {
9788 fprintf(stderr, "Failed to allocate netlink message.\n");
9789 nlfree(&nl);
9790 return -2;
9791 }
9792
9793 genlmsg_put(msg,
9794 NL_AUTO_PORT,
9795 NL_AUTO_SEQ,
9796 nl.id,
9797 0,
9798 NLM_F_DUMP,
9799 NL80211_CMD_GET_SURVEY,
9800 0);
9801
9802 nla_put_u32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(if_name));
9803 nl_send_auto(nl.socket, msg);
9804 nl_cb_set(nl.cb,NL_CB_VALID,NL_CB_CUSTOM,chanSurveyInfo_callback,local);
9805 nl_recvmsgs(nl.socket, nl.cb);
9806 nlmsg_free(msg);
9807 nlfree(&nl);
9808 //Copying the Values
9809 for(int i=0;i<array_size;i++)
9810 {
9811 input_output_channelStats_array[i].ch_number = local[i].ch_number;
9812 input_output_channelStats_array[i].ch_noise = local[i].ch_noise;
9813 input_output_channelStats_array[i].ch_utilization_busy_rx = local[i].ch_utilization_busy_rx;
9814 input_output_channelStats_array[i].ch_utilization_busy_tx = local[i].ch_utilization_busy_tx;
9815 input_output_channelStats_array[i].ch_utilization_busy = local[i].ch_utilization_busy;
9816 input_output_channelStats_array[i].ch_utilization_busy_ext = local[i].ch_utilization_busy_ext;
9817 input_output_channelStats_array[i].ch_utilization_total = local[i].ch_utilization_total;
9818 //TODO: ch_radar_noise, ch_max_80211_rssi, ch_non_80211_noise, ch_utilization_busy_self
9819 }
9820#else
9821 ULONG channel = 0;
9822 int i;
9823 int number_of_channels = array_size;
9824 char buf[512];
9825 INT ret;
9826 wifi_channelStats_t tmp_stats;
9827
9828 if (number_of_channels == 0) {
9829 if (wifi_getRadioChannel(radioIndex, &channel) != RETURN_OK) {
9830 wifi_dbg_printf("%s: cannot get current channel for radioIndex=%d\n", __func__, radioIndex);
9831 return RETURN_ERR;
9832 }
9833 number_of_channels = 1;
9834 input_output_channelStats_array[0].ch_number = channel;
9835 }
9836
9837 for (i = 0; i < number_of_channels; i++) {
9838
9839 input_output_channelStats_array[i].ch_noise = 0;
9840 input_output_channelStats_array[i].ch_utilization_busy_rx = 0;
9841 input_output_channelStats_array[i].ch_utilization_busy_tx = 0;
9842 input_output_channelStats_array[i].ch_utilization_busy = 0;
9843 input_output_channelStats_array[i].ch_utilization_busy_ext = 0; // XXX: unavailable
9844 input_output_channelStats_array[i].ch_utilization_total = 0;
9845
9846 memset(buf, 0, sizeof(buf));
9847 if (get_survey_dump_buf(radioIndex, input_output_channelStats_array[i].ch_number, buf, sizeof(buf))) {
9848 return RETURN_ERR;
9849 }
9850 if (fetch_survey_from_buf(radioIndex, buf, &input_output_channelStats_array[i])) {
9851 wifi_dbg_printf("%s: cannot fetch survey from buf for radioIndex=%d\n", __func__, radioIndex);
9852 return RETURN_ERR;
9853 }
9854
9855 // XXX: fake missing 'self' counter which is not available in iw survey output
9856 // the 'self' counter (a.k.a 'bss') requires Linux Kernel update
9857 input_output_channelStats_array[i].ch_utilization_busy_self = input_output_channelStats_array[i].ch_utilization_busy_rx / 8;
9858
9859 input_output_channelStats_array[i].ch_utilization_busy_rx *= 1000;
9860 input_output_channelStats_array[i].ch_utilization_busy_tx *= 1000;
9861 input_output_channelStats_array[i].ch_utilization_busy_self *= 1000;
9862 input_output_channelStats_array[i].ch_utilization_busy *= 1000;
9863 input_output_channelStats_array[i].ch_utilization_total *= 1000;
9864
9865 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",
9866 __func__,
9867 input_output_channelStats_array[i].ch_number,
9868 input_output_channelStats_array[i].ch_noise,
9869 input_output_channelStats_array[i].ch_utilization_total,
9870 input_output_channelStats_array[i].ch_utilization_busy,
9871 input_output_channelStats_array[i].ch_utilization_busy_rx,
9872 input_output_channelStats_array[i].ch_utilization_busy_tx,
9873 input_output_channelStats_array[i].ch_utilization_busy_self,
9874 input_output_channelStats_array[i].ch_utilization_busy_ext);
9875 }
9876#endif
9877 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
9878 return RETURN_OK;
9879}
9880#define HAL_NETLINK_IMPL
9881
9882/* Hostapd events */
9883
9884#ifndef container_of
9885#define offset_of(st, m) ((size_t)&(((st *)0)->m))
9886#define container_of(ptr, type, member) \
9887 ((type *)((char *)ptr - offset_of(type, member)))
9888#endif /* container_of */
9889
9890struct ctrl {
9891 char sockpath[128];
9892 char sockdir[128];
9893 char bss[IFNAMSIZ];
9894 char reply[4096];
9895 int ssid_index;
9896 void (*cb)(struct ctrl *ctrl, int level, const char *buf, size_t len);
9897 void (*overrun)(struct ctrl *ctrl);
9898 struct wpa_ctrl *wpa;
9899 unsigned int ovfl;
9900 size_t reply_len;
9901 int initialized;
9902 ev_timer retry;
9903 ev_timer watchdog;
9904 ev_stat stat;
9905 ev_io io;
9906};
9907static wifi_newApAssociatedDevice_callback clients_connect_cb;
9908static wifi_apDisassociatedDevice_callback clients_disconnect_cb;
9909static struct ctrl wpa_ctrl[MAX_APS];
9910static int initialized;
9911
9912static unsigned int ctrl_get_drops(struct ctrl *ctrl)
9913{
9914 char cbuf[256] = {};
9915 struct msghdr msg = { .msg_control = cbuf, .msg_controllen = sizeof(cbuf) };
9916 struct cmsghdr *cmsg;
9917 unsigned int ovfl = ctrl->ovfl;
9918 unsigned int drop;
9919
9920 recvmsg(ctrl->io.fd, &msg, MSG_DONTWAIT);
9921 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
9922 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_RXQ_OVFL)
9923 ovfl = *(unsigned int *)CMSG_DATA(cmsg);
9924
9925 drop = ovfl - ctrl->ovfl;
9926 ctrl->ovfl = ovfl;
9927
9928 return drop;
9929}
9930
9931static void ctrl_close(struct ctrl *ctrl)
9932{
9933 if (ctrl->io.cb)
9934 ev_io_stop(EV_DEFAULT_ &ctrl->io);
9935 if (ctrl->retry.cb)
9936 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
9937 if (!ctrl->wpa)
9938 return;
9939
9940 wpa_ctrl_detach(ctrl->wpa);
9941 wpa_ctrl_close(ctrl->wpa);
9942 ctrl->wpa = NULL;
9943 printf("WPA_CTRL: closed index=%d\n", ctrl->ssid_index);
9944}
9945
9946static void ctrl_process(struct ctrl *ctrl)
9947{
9948 const char *str;
9949 int drops;
9950 int level;
9951 int err;
9952
9953 /* Example events:
9954 *
9955 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19
9956 * <3>AP-STA-CONNECTED 60:b4:f7:f0:0a:19 keyid=sample_keyid
9957 * <3>AP-STA-DISCONNECTED 60:b4:f7:f0:0a:19
9958 * <3>CTRL-EVENT-CONNECTED - Connection to 00:1d:73:73:88:ea completed [id=0 id_str=]
9959 * <3>CTRL-EVENT-DISCONNECTED bssid=00:1d:73:73:88:ea reason=3 locally_generated=1
9960 */
9961 if (!(str = index(ctrl->reply, '>')))
9962 return;
9963 if (sscanf(ctrl->reply, "<%d>", &level) != 1)
9964 return;
9965
9966 str++;
9967
9968 if (strncmp("AP-STA-CONNECTED ", str, 17) == 0) {
9969 if (!(str = index(ctrl->reply, ' ')))
9970 return;
9971 wifi_associated_dev_t sta;
9972 memset(&sta, 0, sizeof(sta));
9973
9974 sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
9975 &sta.cli_MACAddress[0], &sta.cli_MACAddress[1], &sta.cli_MACAddress[2],
9976 &sta.cli_MACAddress[3], &sta.cli_MACAddress[4], &sta.cli_MACAddress[5]);
9977
9978 sta.cli_Active=true;
9979
9980 (clients_connect_cb)(ctrl->ssid_index, &sta);
9981 goto handled;
9982 }
9983
9984 if (strncmp("AP-STA-DISCONNECTED ", str, 20) == 0) {
9985 if (!(str = index(ctrl->reply, ' ')))
9986 return;
9987
9988 (clients_disconnect_cb)(ctrl->ssid_index, (char*)str, 0);
9989 goto handled;
9990 }
9991
9992 if (strncmp("CTRL-EVENT-TERMINATING", str, 22) == 0) {
9993 printf("CTRL_WPA: handle TERMINATING event\n");
9994 goto retry;
9995 }
9996
9997 if (strncmp("AP-DISABLED", str, 11) == 0) {
9998 printf("CTRL_WPA: handle AP-DISABLED\n");
9999 goto retry;
10000 }
10001
10002 printf("Event not supported!!\n");
10003
10004handled:
10005
10006 if ((drops = ctrl_get_drops(ctrl))) {
10007 printf("WPA_CTRL: dropped %d messages index=%d\n", drops, ctrl->ssid_index);
10008 if (ctrl->overrun)
10009 ctrl->overrun(ctrl);
10010 }
10011
10012 return;
10013
10014retry:
10015 printf("WPA_CTRL: closing\n");
10016 ctrl_close(ctrl);
10017 printf("WPA_CTRL: retrying from ctrl prcoess\n");
10018 ev_timer_again(EV_DEFAULT_ &ctrl->retry);
10019}
10020
10021static void ctrl_ev_cb(EV_P_ struct ev_io *io, int events)
10022{
10023 struct ctrl *ctrl = container_of(io, struct ctrl, io);
10024 int err;
10025
10026 memset(ctrl->reply, 0, sizeof(ctrl->reply));
10027 ctrl->reply_len = sizeof(ctrl->reply) - 1;
10028 err = wpa_ctrl_recv(ctrl->wpa, ctrl->reply, &ctrl->reply_len);
10029 ctrl->reply[ctrl->reply_len] = 0;
10030 if (err < 0) {
10031 if (errno == EAGAIN || errno == EWOULDBLOCK)
10032 return;
10033 ctrl_close(ctrl);
10034 ev_timer_again(EV_A_ &ctrl->retry);
10035 return;
10036 }
10037
10038 ctrl_process(ctrl);
10039}
10040
10041static int ctrl_open(struct ctrl *ctrl)
10042{
10043 int fd;
10044
10045 if (ctrl->wpa)
10046 return 0;
10047
10048 ctrl->wpa = wpa_ctrl_open(ctrl->sockpath);
10049 if (!ctrl->wpa)
10050 goto err;
10051
10052 if (wpa_ctrl_attach(ctrl->wpa) < 0)
10053 goto err_close;
10054
10055 fd = wpa_ctrl_get_fd(ctrl->wpa);
10056 if (fd < 0)
10057 goto err_detach;
10058
10059 if (setsockopt(fd, SOL_SOCKET, SO_RXQ_OVFL, (int[]){1}, sizeof(int)) < 0)
10060 goto err_detach;
10061
10062 ev_io_init(&ctrl->io, ctrl_ev_cb, fd, EV_READ);
10063 ev_io_start(EV_DEFAULT_ &ctrl->io);
10064
10065 return 0;
10066
10067err_detach:
10068 wpa_ctrl_detach(ctrl->wpa);
10069err_close:
10070 wpa_ctrl_close(ctrl->wpa);
10071err:
10072 ctrl->wpa = NULL;
10073 return -1;
10074}
10075
10076static void ctrl_stat_cb(EV_P_ ev_stat *stat, int events)
10077{
10078 struct ctrl *ctrl = container_of(stat, struct ctrl, stat);
10079
10080 printf("WPA_CTRL: index=%d file state changed\n", ctrl->ssid_index);
10081 ctrl_open(ctrl);
10082}
10083
10084static void ctrl_retry_cb(EV_P_ ev_timer *timer, int events)
10085{
10086 struct ctrl *ctrl = container_of(timer, struct ctrl, retry);
10087
10088 printf("WPA_CTRL: index=%d retrying\n", ctrl->ssid_index);
10089 if (ctrl_open(ctrl) == 0) {
10090 printf("WPA_CTRL: retry successful\n");
10091 ev_timer_stop(EV_DEFAULT_ &ctrl->retry);
10092 }
10093}
10094
10095int ctrl_enable(struct ctrl *ctrl)
10096{
10097 if (ctrl->wpa)
10098 return 0;
10099
10100 if (!ctrl->stat.cb) {
10101 ev_stat_init(&ctrl->stat, ctrl_stat_cb, ctrl->sockpath, 0.);
10102 ev_stat_start(EV_DEFAULT_ &ctrl->stat);
10103 }
10104
10105 if (!ctrl->retry.cb) {
10106 ev_timer_init(&ctrl->retry, ctrl_retry_cb, 0., 5.);
10107 }
10108
10109 return ctrl_open(ctrl);
10110}
10111
10112static void
10113ctrl_msg_cb(char *buf, size_t len)
10114{
10115 struct ctrl *ctrl = container_of(buf, struct ctrl, reply);
10116
10117 printf("WPA_CTRL: unsolicited message: index=%d len=%zu msg=%s", ctrl->ssid_index, len, buf);
10118 ctrl_process(ctrl);
10119}
10120
10121static int ctrl_request(struct ctrl *ctrl, const char *cmd, size_t cmd_len, char *reply, size_t *reply_len)
10122{
10123 int err;
10124
10125 if (!ctrl->wpa)
10126 return -1;
10127 if (*reply_len < 2)
10128 return -1;
10129
10130 (*reply_len)--;
10131 ctrl->reply_len = sizeof(ctrl->reply);
10132 err = wpa_ctrl_request(ctrl->wpa, cmd, cmd_len, ctrl->reply, &ctrl->reply_len, ctrl_msg_cb);
10133 printf("WPA_CTRL: index=%d cmd='%s' err=%d\n", ctrl->ssid_index, cmd, err);
10134 if (err < 0)
10135 return err;
10136
10137 if (ctrl->reply_len > *reply_len)
10138 ctrl->reply_len = *reply_len;
10139
10140 *reply_len = ctrl->reply_len;
10141 memcpy(reply, ctrl->reply, *reply_len);
10142 reply[*reply_len - 1] = 0;
10143 printf("WPA_CTRL: index=%d reply='%s'\n", ctrl->ssid_index, reply);
10144 return 0;
10145}
10146
10147static void ctrl_watchdog_cb(EV_P_ ev_timer *timer, int events)
10148{
10149 const char *pong = "PONG";
10150 const char *ping = "PING";
10151 char reply[1024];
10152 size_t len = sizeof(reply);
10153 int err;
10154 ULONG s, snum;
10155 INT ret;
10156 BOOL status;
10157
10158 printf("WPA_CTRL: watchdog cb\n");
10159
10160 ret = wifi_getSSIDNumberOfEntries(&snum);
10161 if (ret != RETURN_OK) {
10162 printf("%s: failed to get SSID count", __func__);
10163 return;
10164 }
10165
10166 if (snum > MAX_APS) {
10167 printf("more ssid than supported! %lu\n", snum);
10168 return;
10169 }
10170
10171 for (s = 0; s < snum; s++) {
10172 if (wifi_getApEnable(s, &status) != RETURN_OK) {
10173 printf("%s: failed to get AP Enable for index: %d\n", __func__, s);
10174 continue;
10175 }
10176 if (status == false) continue;
10177
10178 memset(reply, 0, sizeof(reply));
10179 len = sizeof(reply);
10180 printf("WPA_CTRL: pinging index=%d\n", wpa_ctrl[s].ssid_index);
10181 err = ctrl_request(&wpa_ctrl[s], ping, strlen(ping), reply, &len);
10182 if (err == 0 && len > strlen(pong) && !strncmp(reply, pong, strlen(pong)))
10183 continue;
10184
10185 printf("WPA_CTRL: ping timeout index=%d\n", wpa_ctrl[s].ssid_index);
10186 ctrl_close(&wpa_ctrl[s]);
10187 printf("WPA_CTRL: ev_timer_again %d\n", s);
10188 ev_timer_again(EV_DEFAULT_ &wpa_ctrl[s].retry);
10189 }
10190}
10191
10192static int init_wpa()
10193{
10194 int ret = 0, i = 0;
10195 ULONG s, snum;
10196
10197 ret = wifi_getSSIDNumberOfEntries(&snum);
10198 if (ret != RETURN_OK) {
10199 printf("%s: failed to get SSID count", __func__);
10200 return RETURN_ERR;
10201 }
10202
10203 if (snum > MAX_APS) {
10204 printf("more ssid than supported! %lu\n", snum);
10205 return RETURN_ERR;
10206 }
10207
10208 for (s = 0; s < snum; s++) {
10209 memset(&wpa_ctrl[s], 0, sizeof(struct ctrl));
10210 sprintf(wpa_ctrl[s].sockpath, "%s%lu", SOCK_PREFIX, s);
10211 wpa_ctrl[s].ssid_index = s;
10212 ctrl_enable(&wpa_ctrl[s]);
10213 }
10214
10215 ev_timer_init(&wpa_ctrl->watchdog, ctrl_watchdog_cb, 0., 30.);
10216 ev_timer_again(EV_DEFAULT_ &wpa_ctrl->watchdog);
10217
10218 initialized = 1;
10219 printf("WPA_CTRL: initialized\n");
10220
10221 return RETURN_OK;
10222}
10223
10224void wifi_newApAssociatedDevice_callback_register(wifi_newApAssociatedDevice_callback callback_proc)
10225{
10226 clients_connect_cb = callback_proc;
10227 if (!initialized)
10228 init_wpa();
10229}
10230
10231void wifi_apDisassociatedDevice_callback_register(wifi_apDisassociatedDevice_callback callback_proc)
10232{
10233 clients_disconnect_cb = callback_proc;
10234 if (!initialized)
10235 init_wpa();
10236}
10237
10238INT wifi_setBTMRequest(UINT apIndex, CHAR *peerMac, wifi_BTMRequest_t *request)
10239{
10240 // TODO Implement me!
10241 return RETURN_ERR;
10242}
10243
10244INT wifi_setRMBeaconRequest(UINT apIndex, CHAR *peer, wifi_BeaconRequest_t *in_request, UCHAR *out_DialogToken)
10245{
10246 // TODO Implement me!
10247 return RETURN_ERR;
10248}
10249
10250INT wifi_getRadioChannels(INT radioIndex, wifi_channelMap_t *outputMap, INT outputMapSize)
10251{
10252 int i;
10253 char cmd[256];
10254 char channel_numbers_buf[256];
10255 char dfs_state_buf[256];
10256 char line[256];
10257 const char *ptr;
10258
10259 memset(cmd, 0, sizeof(cmd));
10260 memset(channel_numbers_buf, 0, sizeof(channel_numbers_buf));
10261 memset(line, 0, sizeof(line));
10262 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10263 memset(outputMap, 0, outputMapSize); // all unused entries should be zero
10264
10265 if (radioIndex == 0) { // 2.4G - all allowed
10266 if (outputMapSize < 11) {
10267 wifi_dbg_printf("%s: outputMapSize too small (%d)\n", __FUNCTION__, outputMapSize);
10268 return RETURN_ERR;
10269 }
10270
10271 for (i = 0; i < 11; i++) {
10272 outputMap[i].ch_number = i + 1;
10273 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10274 }
10275
10276 return RETURN_OK;
10277 }
10278
10279 if (radioIndex == 1) { // 5G
10280// Example output of iw list:
10281//
10282// Frequencies:
10283// * 5180 MHz [36] (17.0 dBm)
10284// * 5200 MHz [40] (17.0 dBm)
10285// * 5220 MHz [44] (17.0 dBm)
10286// * 5240 MHz [48] (17.0 dBm)
10287// * 5260 MHz [52] (23.0 dBm) (radar detection)
10288// DFS state: usable (for 78930 sec)
10289// DFS CAC time: 60000 ms
10290// * 5280 MHz [56] (23.0 dBm) (radar detection)
10291// DFS state: usable (for 78930 sec)
10292// DFS CAC time: 60000 ms
10293// * 5300 MHz [60] (23.0 dBm) (radar detection)
10294// DFS state: usable (for 78930 sec)
10295// DFS CAC time: 60000 ms
10296// * 5320 MHz [64] (23.0 dBm) (radar detection)
10297// DFS state: usable (for 78930 sec)
10298// DFS CAC time: 60000 ms
10299// * 5500 MHz [100] (disabled)
10300// * 5520 MHz [104] (disabled)
10301// * 5540 MHz [108] (disabled)
10302// * 5560 MHz [112] (disabled)
10303//
10304// Below command should fetch channel numbers of each enabled channel in 5GHz band:
10305 if (sprintf(cmd,"iw list | grep MHz | tr -d '\\t' | grep -v disabled | tr -d '*' | grep '^ 5' | awk '{print $3}' | tr -d '[]'") < 0) {
10306 wifi_dbg_printf("%s: failed to build iw list command\n", __FUNCTION__);
10307 return RETURN_ERR;
10308 }
10309
10310 if (_syscmd(cmd, channel_numbers_buf, sizeof(channel_numbers_buf)) == RETURN_ERR) {
10311 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10312 return RETURN_ERR;
10313 }
10314
10315 ptr = channel_numbers_buf;
10316 i = 0;
10317 while (ptr = get_line_from_str_buf(ptr, line)) {
10318 if (i >= outputMapSize) {
10319 wifi_dbg_printf("%s: DFS map size too small\n", __FUNCTION__);
10320 return RETURN_ERR;
10321 }
10322 sscanf(line, "%d", &outputMap[i].ch_number);
10323
10324 memset(cmd, 0, sizeof(cmd));
10325 // Below command should fetch string for DFS state (usable, available or unavailable)
10326 // Example line: "DFS state: usable (for 78930 sec)"
10327 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) {
10328 wifi_dbg_printf("%s: failed to build dfs state command\n", __FUNCTION__);
10329 return RETURN_ERR;
10330 }
10331
10332 memset(dfs_state_buf, 0, sizeof(dfs_state_buf));
10333 if (_syscmd(cmd, dfs_state_buf, sizeof(dfs_state_buf)) == RETURN_ERR) {
10334 wifi_dbg_printf("%s: failed to execute '%s'\n", __FUNCTION__, cmd);
10335 return RETURN_ERR;
10336 }
10337
10338 wifi_dbg_printf("DFS state = '%s'\n", dfs_state_buf);
10339
10340 if (!strcmp(dfs_state_buf, "usable")) {
10341 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_FINISHED;
10342 } else if (!strcmp(dfs_state_buf, "available")) {
10343 outputMap[i].ch_state = CHAN_STATE_DFS_CAC_COMPLETED;
10344 } else if (!strcmp(dfs_state_buf, "unavailable")) {
10345 outputMap[i].ch_state = CHAN_STATE_DFS_NOP_START;
10346 } else {
10347 outputMap[i].ch_state = CHAN_STATE_AVAILABLE;
10348 }
10349 i++;
10350 }
10351
10352 return RETURN_OK;
10353 }
10354
10355 wifi_dbg_printf("%s: wrong radio index (%d)\n", __FUNCTION__, radioIndex);
10356 return RETURN_ERR;
10357}
10358
10359INT wifi_chan_eventRegister(wifi_chan_eventCB_t eventCb)
10360{
10361 // TODO Implement me!
10362 return RETURN_ERR;
10363}
10364
10365INT wifi_getRadioBandUtilization (INT radioIndex, INT *output_percentage)
10366{
10367 return RETURN_OK;
10368}
10369
10370INT wifi_getApAssociatedClientDiagnosticResult(INT apIndex, char *mac_addr, wifi_associated_dev3_t *dev_conn)
10371{
10372 // TODO Implement me!
10373 return RETURN_ERR;
10374}
10375
10376INT wifi_switchBand(char *interface_name,INT radioIndex,char *freqBand)
10377{
10378 // TODO API refrence Implementaion is present on RPI hal
10379 return RETURN_ERR;
10380}
10381
10382INT wifi_getRadioPercentageTransmitPower(INT apIndex, ULONG *txpwr_pcntg)
10383{
developera5005b62022-09-13 15:43:35 +080010384 char cmd[128]={'\0'};
10385 char buf[128]={'\0'};
10386 char *support;
10387 int maximum_tx = 0, current_tx = 0;
10388
10389 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10390 if(txpwr_pcntg == NULL)
10391 return RETURN_ERR;
10392
10393 // Get the maximum tx power of the device
10394 snprintf(cmd, sizeof(cmd), "hostapd_cli -i %s%d status | grep max_txpower | cut -d '=' -f2 | tr -d '\n'", AP_PREFIX, apIndex);
10395 _syscmd(cmd, buf, sizeof(buf));
10396 maximum_tx = strtol(buf, NULL, 10);
10397
10398 // Get the current tx power
10399 memset(cmd, 0, sizeof(cmd));
10400 memset(buf, 0, sizeof(buf));
10401 snprintf(cmd, sizeof(cmd), "iw %s%d info | grep txpower | awk '{print $2}' | cut -d '.' -f1 | tr -d '\\n'", AP_PREFIX, apIndex);
10402 _syscmd(cmd, buf, sizeof(buf));
10403 current_tx = strtol(buf, NULL, 10);
10404
10405 // Get the power supported list and find the current power percentage in supported list
10406 memset(buf, 0, sizeof(buf));
10407 wifi_getRadioTransmitPowerSupported(apIndex, buf);
10408 support = strtok(buf, ",");
10409 while(true)
10410 {
10411 if(support == NULL) { // current power is not in supported list, this should not happen if the power is set by hal.
10412 *txpwr_pcntg = 0;
10413 wifi_dbg_printf("current power is not in supported list\n");
10414 return RETURN_ERR;
10415 }
10416 int tmp = maximum_tx*strtol(support, NULL, 10)/100;
10417 if (tmp == current_tx) {
10418 *txpwr_pcntg = strtol(support, NULL, 10);
10419 break;
10420 }
10421 support = strtok(NULL, ",");
10422 }
10423 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080010424 return RETURN_OK;
10425}
10426
10427INT wifi_setZeroDFSState(UINT radioIndex, BOOL enable, BOOL precac)
10428{
developer58599c22022-09-13 16:40:34 +080010429 // TODO precac feature.
10430 struct params params = {0};
10431 char config_file[128] = {0};
10432
10433 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10434
10435 params.name = "enable_background_radar";
10436 params.value = enable?"1":"0";
10437 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10438 wifi_hostapdWrite(config_file, &params, 1);
10439 wifi_hostapdProcessUpdate(radioIndex, &params, 1);
10440
10441 /* TODO precac feature */
10442
10443 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10444 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010445}
10446
10447INT wifi_getZeroDFSState(UINT radioIndex, BOOL *enable, BOOL *precac)
10448{
developer58599c22022-09-13 16:40:34 +080010449 char config_file[128] = {0};
10450 char buf[64] = {0};
10451
10452 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10453 if (NULL == enable || NULL == precac)
10454 return RETURN_ERR;
10455
10456 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radioIndex);
10457 wifi_hostapdRead(config_file, "enable_background_radar", buf, sizeof(buf));
10458 if (strncmp(enable, "1", 1) == 0)
10459 *enable = true;
10460 else
10461 *enable = false;
10462
10463 /* TODO precac feature */
10464
10465 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10466 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010467}
10468
10469INT wifi_isZeroDFSSupported(UINT radioIndex, BOOL *supported)
10470{
developer58599c22022-09-13 16:40:34 +080010471 *supported = TRUE;
10472 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080010473}
10474
developer3e6b1692022-09-30 18:04:05 +080010475INT wifi_setDownlinkMuType(INT radio_index, wifi_dl_mu_type_t mu_type)
10476{
10477 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10478 struct params params = {0};
10479 char config_file[64] = {0};
10480 char buf[64] = {0};
10481 unsigned int set_mu_type = 0;
10482 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10483
10484 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10485 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10486
10487 if (strlen(buf) > 0)
10488 set_mu_type = strtol(buf, NULL, 10);
10489
10490 if (mu_type == WIFI_DL_MU_TYPE_NONE) {
10491 set_mu_type &= ~0x05; // unset bit 0, 2
10492 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10493 set_mu_type |= 0x01;
10494 set_mu_type &= ~0x04;
10495 } else if (mu_type == WIFI_DL_MU_TYPE_MIMO) {
10496 set_mu_type &= ~0x01;
10497 set_mu_type |= 0x04;
10498 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA_MIMO){
10499 set_mu_type |= 0x05; // set bit 0, 2
10500 }
10501
10502 params.name = "hemu_onoff";
10503 sprintf(buf, "%u", set_mu_type);
10504 params.value = buf;
10505 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10506 wifi_hostapdWrite(config_file, &params, 1);
10507 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10508
10509 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10510 return RETURN_OK;
10511}
10512
10513INT wifi_getDownlinkMuType(INT radio_index, wifi_dl_mu_type_t *mu_type)
10514{
10515 struct params params={0};
10516 char config_file[64] = {0};
10517 char buf[64] = {0};
10518 unsigned int get_mu_type = 0;
10519
10520 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10521
10522 if (mu_type == NULL)
10523 return RETURN_ERR;
10524
10525 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10526 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10527 get_mu_type = strtol(buf, NULL, 10);
10528
10529 if (get_mu_type & 0x04 && get_mu_type & 0x01)
10530 *mu_type = WIFI_DL_MU_TYPE_OFDMA_MIMO;
10531 else if (get_mu_type & 0x04)
10532 *mu_type = WIFI_DL_MU_TYPE_MIMO;
10533 else if (get_mu_type & 0x01)
10534 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10535 else
10536 *mu_type = WIFI_DL_MU_TYPE_NONE;
10537
10538 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10539 return RETURN_OK;
10540}
10541
10542INT wifi_setUplinkMuType(INT radio_index, wifi_ul_mu_type_t mu_type)
10543{
10544 // hemu onoff=<val> (bitmap- UL MU-MIMO(bit3), DL MU-MIMO(bit2), UL OFDMA(bit1), DL OFDMA(bit0))
10545 struct params params={0};
10546 char config_file[64] = {0};
10547 char buf[64] = {0};
10548 unsigned int set_mu_type = 0;
10549 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10550
10551 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10552 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10553
10554 if (strlen(buf) > 0)
10555 set_mu_type = strtol(buf, NULL, 10);
10556
10557 // wifi hal only define up link type none and OFDMA, there is NO MU-MIMO.
10558 if (mu_type == WIFI_UL_MU_TYPE_NONE) {
10559 set_mu_type &= ~0x0a;
10560 } else if (mu_type == WIFI_DL_MU_TYPE_OFDMA) {
10561 set_mu_type |= 0x02;
10562 set_mu_type &= ~0x08;
10563 }
10564
10565 params.name = "hemu_onoff";
10566 sprintf(buf, "%u", set_mu_type);
10567 params.value = buf;
10568 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10569 wifi_hostapdWrite(config_file, &params, 1);
10570 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10571
10572 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10573 return RETURN_OK;
10574}
10575
10576INT wifi_getUplinkMuType(INT radio_index, wifi_ul_mu_type_t *mu_type)
10577{
10578 struct params params={0};
10579 char config_file[64] = {0};
10580 char buf[64] = {0};
10581 unsigned int get_mu_type = 0;
10582
10583 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10584
10585 if (mu_type == NULL)
10586 return RETURN_ERR;
10587
10588 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10589 wifi_hostapdRead(config_file, "hemu_onoff", buf, sizeof(buf));
10590
10591 get_mu_type = strtol(buf, NULL, 10);
10592 if (get_mu_type & 0x02)
10593 *mu_type = WIFI_DL_MU_TYPE_OFDMA;
10594 else
10595 *mu_type = WIFI_DL_MU_TYPE_NONE;
10596
10597 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10598 return RETURN_OK;
10599}
10600
10601
developer454b9462022-09-13 15:29:16 +080010602INT wifi_setGuardInterval(INT radio_index, wifi_guard_interval_t guard_interval)
10603{
10604 char cmd[128] = {0};
10605 char buf[64] = {0};
10606 char band_str[8] = {0};
10607 char GI[8] = {0};
10608 int tmp = 0;
10609 BOOL ax_mode = FALSE;
10610 BOOL short_GI = FALSE;
10611 FILE *f = NULL;
10612 wifi_band band;
10613
10614 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10615
10616 if (wifi_getRadioMode(radio_index, buf, &tmp) == RETURN_ERR) {
10617 wifi_dbg_printf("%s: wifi_getRadioMode return error\n", __func__);
10618 return RETURN_ERR;
10619 }
10620 if (strstr(buf, "ax") != NULL)
10621 ax_mode = TRUE;
10622
10623 if (guard_interval == wifi_guard_interval_400 && ax_mode != TRUE) {
10624 short_GI = TRUE;
10625 strcpy(GI, "0.4");
10626 } else if (guard_interval == wifi_guard_interval_1600 && ax_mode == TRUE)
10627 strcpy(GI, "1.6");
10628 else if (guard_interval == wifi_guard_interval_3200 && ax_mode == TRUE)
10629 strcpy(GI, "3.2");
10630 else // default
10631 strcpy(GI, "0.8");
10632
10633 band = wifi_index_to_band(radio_index);
10634 if (band == band_2_4)
10635 strcpy(band_str, "2.4");
10636 else if (band == band_5)
10637 strcpy(band_str, "5");
10638 else if (band == band_6)
10639 strcpy(band_str, "6");
10640 else {
10641 wifi_dbg_printf("%s: invalid band\n");
10642 return RETURN_ERR;
10643 }
10644
10645 if (ax_mode == TRUE)
10646 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates he-gi-%s %s", AP_PREFIX, radio_index, band_str, GI);
10647 else
10648 snprintf(cmd, sizeof(cmd), "iw dev %s%d set bitrates %sgi-%s", AP_PREFIX, radio_index, (short_GI)?"s":"l", band_str);
10649 _syscmd(cmd, buf, sizeof(buf));
10650
10651 // Record GI for get GI function
10652 snprintf(buf, sizeof(buf), "%s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10653 f = fopen(buf, "w");
10654 if (f != NULL) {
10655 fprintf(f, "%s", GI);
10656 }
10657 fclose(f);
10658 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10659 return RETURN_OK;
10660}
10661
10662INT wifi_getGuardInterval(INT radio_index, wifi_guard_interval_t *guard_interval)
10663{
10664 char buf[32] = {0};
10665 char cmd[64] = {0};
10666
10667 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10668
10669 if (guard_interval == NULL)
10670 return RETURN_ERR;
10671
10672 snprintf(cmd, sizeof(cmd), "cat %s%d.txt", GUARD_INTERVAL_FILE, radio_index);
10673 _syscmd(cmd, buf, sizeof(buf));
10674
10675 if (strncmp(buf, "0.4", 3) == 0)
10676 *guard_interval = wifi_guard_interval_400;
10677 else if (strncmp(buf, "0.8", 3) == 0)
10678 *guard_interval = wifi_guard_interval_800;
10679 else if (strncmp(buf, "1.6", 3) == 0)
10680 *guard_interval = wifi_guard_interval_1600;
10681 else if (strncmp(buf, "3.2", 3) == 0)
10682 *guard_interval = wifi_guard_interval_3200;
10683 else
10684 *guard_interval = wifi_guard_interval_auto;
10685
10686 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10687 return RETURN_OK;
10688}
10689
developer3cc61d12022-09-13 16:36:05 +080010690INT wifi_setBSSColor(INT radio_index, UCHAR color)
10691{
10692 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10693 struct params params = {0};
10694 char config_file[128] = {0};
10695 char bss_color[4] ={0};
10696
10697 params.name = "he_bss_color";
10698 snprintf(bss_color, sizeof(bss_color), "%hhu", color);
10699 params.value = bss_color;
10700 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10701 wifi_hostapdWrite(config_file, &params, 1);
10702 wifi_hostapdProcessUpdate(radio_index, &params, 1);
10703
10704 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
10705 return RETURN_OK;
10706}
10707
10708INT wifi_getBSSColor(INT radio_index, UCHAR *color)
10709{
10710 char config_file[128] = {0};
10711 char buf[64] = {0};
10712 char temp_output[128] = {'\0'};
10713
10714 wifi_dbg_printf("\nFunc=%s\n", __func__);
10715 if (NULL == color)
10716 return RETURN_ERR;
10717
10718 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, radio_index);
10719 wifi_hostapdRead(config_file, "he_bss_color", buf, sizeof(buf));
10720
10721 if(strlen(buf) > 0) {
10722 snprintf(temp_output, sizeof(temp_output), "%s", buf);
10723 } else {
10724 snprintf(temp_output, sizeof(temp_output), "1"); // default value
10725 }
10726
10727 *color = (UCHAR)strtoul(temp_output, NULL, 10);
10728 wifi_dbg_printf("\noutput_string=%s\n", color);
10729
10730 return RETURN_OK;
10731}
10732
developer06a01d92022-09-07 16:32:39 +080010733/* multi-psk support */
10734INT wifi_getMultiPskClientKey(INT apIndex, mac_address_t mac, wifi_key_multi_psk_t *key)
10735{
10736 char cmd[256];
10737
10738 sprintf(cmd, "hostapd_cli -i %s%d sta %x:%x:%x:%x:%x:%x |grep '^keyid' | cut -f 2 -d = | tr -d '\n'",
10739 AP_PREFIX,
10740 apIndex,
10741 mac[0],
10742 mac[1],
10743 mac[2],
10744 mac[3],
10745 mac[4],
10746 mac[5]
10747 );
10748 printf("DEBUG LOG wifi_getMultiPskClientKey(%s)\n",cmd);
10749 _syscmd(cmd, key->wifi_keyId, 64);
10750
10751
10752 return RETURN_OK;
10753}
10754
10755INT wifi_pushMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10756{
10757 FILE *fd = NULL;
10758 char fname[100];
10759 char cmd[128] = {0};
10760 char out[64] = {0};
10761 wifi_key_multi_psk_t * key = NULL;
10762 if(keysNumber < 0)
10763 return RETURN_ERR;
10764
10765 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10766 fd = fopen(fname, "w");
10767 if (!fd) {
10768 return RETURN_ERR;
10769 }
10770 key= (wifi_key_multi_psk_t *) keys;
10771 for(int i=0; i<keysNumber; ++i, key++) {
10772 fprintf(fd, "keyid=%s 00:00:00:00:00:00 %s\n", key->wifi_keyId, key->wifi_psk);
10773 }
10774 fclose(fd);
10775
10776 //reload file
10777 sprintf(cmd, "hostapd_cli -i%s%d raw RELOAD_WPA_PSK", AP_PREFIX, apIndex);
10778 _syscmd(cmd, out, 64);
10779 return RETURN_OK;
10780}
10781
10782INT wifi_getMultiPskKeys(INT apIndex, wifi_key_multi_psk_t *keys, INT keysNumber)
10783{
10784 FILE *fd = NULL;
10785 char fname[100];
10786 char * line = NULL;
10787 char * pos = NULL;
10788 size_t len = 0;
10789 ssize_t read = 0;
10790 INT ret = RETURN_OK;
10791 wifi_key_multi_psk_t *keys_it = NULL;
10792
10793 if (keysNumber < 1) {
10794 return RETURN_ERR;
10795 }
10796
10797 snprintf(fname, sizeof(fname), "/tmp/hostapd%d.psk", apIndex);
10798 fd = fopen(fname, "r");
10799 if (!fd) {
10800 return RETURN_ERR;
10801 }
10802
10803 if (keys == NULL) {
10804 ret = RETURN_ERR;
10805 goto close;
10806 }
10807
10808 keys_it = keys;
10809 while ((read = getline(&line, &len, fd)) != -1) {
10810 //Strip trailing new line if present
10811 if (read > 0 && line[read-1] == '\n') {
10812 line[read-1] = '\0';
10813 }
10814
10815 if(strcmp(line,"keyid=")) {
10816 sscanf(line, "keyid=%s", &(keys_it->wifi_keyId));
10817 if (!(pos = index(line, ' '))) {
10818 ret = RETURN_ERR;
10819 goto close;
10820 }
10821 pos++;
10822 //Here should be 00:00:00:00:00:00
10823 if (!(strcmp(pos,"00:00:00:00:00:00"))) {
10824 printf("Not supported MAC: %s\n", pos);
10825 }
10826 if (!(pos = index(pos, ' '))) {
10827 ret = RETURN_ERR;
10828 goto close;
10829 }
10830 pos++;
10831
10832 //The rest is PSK
10833 snprintf(&keys_it->wifi_psk[0], sizeof(keys_it->wifi_psk), "%s", pos);
10834 keys_it++;
10835
10836 if(--keysNumber <= 0)
10837 break;
10838 }
10839 }
10840
10841close:
10842 free(line);
10843 fclose(fd);
10844 return ret;
10845}
10846/* end of multi-psk support */
10847
10848INT wifi_setNeighborReports(UINT apIndex,
10849 UINT numNeighborReports,
10850 wifi_NeighborReport_t *neighborReports)
10851{
10852 char cmd[256] = { 0 };
10853 char hex_bssid[13] = { 0 };
10854 char bssid[18] = { 0 };
10855 char nr[256] = { 0 };
10856 char ssid[256];
10857 char hex_ssid[256];
10858 INT ret;
10859
10860 /*rmeove all neighbors*/
10861 wifi_dbg_printf("\n[%s]: removing all neighbors from %s%d",__func__,AP_PREFIX,apIndex);
10862 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);
10863 system(cmd);
10864
10865 for(unsigned int i = 0; i < numNeighborReports; i++)
10866 {
10867 memset(ssid, 0, sizeof(ssid));
10868 ret = wifi_getSSIDName(apIndex, ssid);
10869 if (ret != RETURN_OK)
10870 return RETURN_ERR;
10871
10872 memset(hex_ssid, 0, sizeof(hex_ssid));
10873 for(size_t j = 0,k = 0; ssid[j] != '\0' && k < sizeof(hex_ssid); j++,k+=2 )
10874 sprintf(hex_ssid + k,"%02x", ssid[j]);
10875
10876 snprintf(hex_bssid, sizeof(hex_bssid),
10877 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
10878 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10879 snprintf(bssid, sizeof(bssid),
10880 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
10881 neighborReports[i].bssid[0], neighborReports[i].bssid[1], neighborReports[i].bssid[2], neighborReports[i].bssid[3], neighborReports[i].bssid[4], neighborReports[i].bssid[5]);
10882
10883 snprintf(nr, sizeof(nr),
10884 "%s" // bssid
10885 "%02hhx%02hhx%02hhx%02hhx" // bssid_info
10886 "%02hhx" // operclass
10887 "%02hhx" // channel
10888 "%02hhx", // phy_mode
10889 hex_bssid,
10890 neighborReports[i].info & 0xff, (neighborReports[i].info >> 8) & 0xff,
10891 (neighborReports[i].info >> 16) & 0xff, (neighborReports[i].info >> 24) & 0xff,
10892 neighborReports[i].opClass,
10893 neighborReports[i].channel,
10894 neighborReports[i].phyTable);
10895
10896 snprintf(cmd, sizeof(cmd),
10897 "hostapd_cli set_neighbor "
10898 "%s " // bssid
10899 "ssid=%s " // ssid
10900 "nr=%s " // nr
10901 "-i %s%d",
10902 bssid,hex_ssid,nr,AP_PREFIX,apIndex);
10903
10904 if (WEXITSTATUS(system(cmd)) != 0)
10905 {
10906 wifi_dbg_printf("\n[%s]: %s failed",__func__,cmd);
10907 }
10908 }
10909
10910 return RETURN_OK;
10911}
10912
10913INT wifi_getApInterworkingElement(INT apIndex, wifi_InterworkingElement_t *output_struct)
10914{
10915 return RETURN_OK;
10916}
10917
10918#ifdef _WIFI_HAL_TEST_
10919int main(int argc,char **argv)
10920{
10921 int index;
10922 INT ret=0;
10923 char buf[1024]="";
10924
10925 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
10926 if(argc<3)
10927 {
10928 if(argc==2)
10929 {
10930 if(!strcmp(argv[1], "init"))
10931 return wifi_init();
10932 if(!strcmp(argv[1], "reset"))
10933 return wifi_reset();
10934 if(!strcmp(argv[1], "wifi_getHalVersion"))
10935 {
10936 char buffer[64];
10937 if(wifi_getHalVersion(buffer)==RETURN_OK)
10938 printf("Version: %s\n", buffer);
10939 else
10940 printf("Error in wifi_getHalVersion\n");
10941 return RETURN_OK;
10942 }
10943 }
10944 printf("wifihal <API> <radioIndex> <arg1> <arg2> ...\n");
10945 exit(-1);
10946 }
10947
10948 index = atoi(argv[2]);
10949 if(strstr(argv[1], "wifi_getApName")!=NULL)
10950 {
10951 wifi_getApName(index,buf);
10952 printf("Ap name is %s \n",buf);
10953 return 0;
10954 }
10955 if(strstr(argv[1], "wifi_getRadioAutoChannelEnable")!=NULL)
10956 {
10957 BOOL b = FALSE;
10958 BOOL *output_bool = &b;
10959 wifi_getRadioAutoChannelEnable(index,output_bool);
10960 printf("Channel enabled = %d \n",b);
10961 return 0;
10962 }
10963 if(strstr(argv[1], "wifi_getApWpaEncryptionMode")!=NULL)
10964 {
10965 wifi_getApWpaEncryptionMode(index,buf);
10966 printf("encryption enabled = %s\n",buf);
10967 return 0;
10968 }
10969 if(strstr(argv[1], "wifi_getApSsidAdvertisementEnable")!=NULL)
10970 {
10971 BOOL b = FALSE;
10972 BOOL *output_bool = &b;
10973 wifi_getApSsidAdvertisementEnable(index,output_bool);
10974 printf("advertisment enabled = %d\n",b);
10975 return 0;
10976 }
10977 if(strstr(argv[1],"wifi_getApAssociatedDeviceTidStatsResult")!=NULL)
10978 {
10979 if(argc <= 3 )
10980 {
10981 printf("Insufficient arguments \n");
10982 exit(-1);
10983 }
10984
10985 char sta[20] = {'\0'};
10986 ULLONG handle= 0;
10987 strcpy(sta,argv[3]);
10988 mac_address_t st;
10989 mac_addr_aton(st,sta);
10990
10991 wifi_associated_dev_tid_stats_t tid_stats;
10992 wifi_getApAssociatedDeviceTidStatsResult(index,&st,&tid_stats,&handle);
10993 for(int tid_index=0; tid_index<PS_MAX_TID; tid_index++) //print tid stats
10994 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);
10995 }
10996
10997 if(strstr(argv[1], "getApEnable")!=NULL) {
10998 BOOL enable;
10999 ret=wifi_getApEnable(index, &enable);
11000 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11001 }
11002 else if(strstr(argv[1], "setApEnable")!=NULL) {
11003 BOOL enable = atoi(argv[3]);
11004 ret=wifi_setApEnable(index, enable);
11005 printf("%s %d: %d, returns %d\n", argv[1], index, enable, ret);
11006 }
11007 else if(strstr(argv[1], "getApStatus")!=NULL) {
11008 char status[64];
11009 ret=wifi_getApStatus(index, status);
11010 printf("%s %d: %s, returns %d\n", argv[1], index, status, ret);
11011 }
11012 else if(strstr(argv[1], "wifi_getSSIDNameStatus")!=NULL)
11013 {
11014 wifi_getSSIDNameStatus(index,buf);
11015 printf("%s %d: active ssid : %s\n",argv[1], index,buf);
11016 return 0;
11017 }
11018 else if(strstr(argv[1], "getSSIDTrafficStats2")!=NULL) {
11019 wifi_ssidTrafficStats2_t stats={0};
11020 ret=wifi_getSSIDTrafficStats2(index, &stats); //Tr181
11021 printf("%s %d: returns %d\n", argv[1], index, ret);
11022 printf(" ssid_BytesSent =%lu\n", stats.ssid_BytesSent);
11023 printf(" ssid_BytesReceived =%lu\n", stats.ssid_BytesReceived);
11024 printf(" ssid_PacketsSent =%lu\n", stats.ssid_PacketsSent);
11025 printf(" ssid_PacketsReceived =%lu\n", stats.ssid_PacketsReceived);
11026 printf(" ssid_RetransCount =%lu\n", stats.ssid_RetransCount);
11027 printf(" ssid_FailedRetransCount =%lu\n", stats.ssid_FailedRetransCount);
11028 printf(" ssid_RetryCount =%lu\n", stats.ssid_RetryCount);
11029 printf(" ssid_MultipleRetryCount =%lu\n", stats.ssid_MultipleRetryCount);
11030 printf(" ssid_ACKFailureCount =%lu\n", stats.ssid_ACKFailureCount);
11031 printf(" ssid_AggregatedPacketCount =%lu\n", stats.ssid_AggregatedPacketCount);
11032 printf(" ssid_ErrorsSent =%lu\n", stats.ssid_ErrorsSent);
11033 printf(" ssid_ErrorsReceived =%lu\n", stats.ssid_ErrorsReceived);
11034 printf(" ssid_UnicastPacketsSent =%lu\n", stats.ssid_UnicastPacketsSent);
11035 printf(" ssid_UnicastPacketsReceived =%lu\n", stats.ssid_UnicastPacketsReceived);
11036 printf(" ssid_DiscardedPacketsSent =%lu\n", stats.ssid_DiscardedPacketsSent);
11037 printf(" ssid_DiscardedPacketsReceived =%lu\n", stats.ssid_DiscardedPacketsReceived);
11038 printf(" ssid_MulticastPacketsSent =%lu\n", stats.ssid_MulticastPacketsSent);
11039 printf(" ssid_MulticastPacketsReceived =%lu\n", stats.ssid_MulticastPacketsReceived);
11040 printf(" ssid_BroadcastPacketsSent =%lu\n", stats.ssid_BroadcastPacketsSent);
11041 printf(" ssid_BroadcastPacketsRecevied =%lu\n", stats.ssid_BroadcastPacketsRecevied);
11042 printf(" ssid_UnknownPacketsReceived =%lu\n", stats.ssid_UnknownPacketsReceived);
11043 }
11044 else if(strstr(argv[1], "getNeighboringWiFiDiagnosticResult2")!=NULL) {
11045 wifi_neighbor_ap2_t *neighbor_ap_array=NULL, *pt=NULL;
11046 UINT array_size=0;
11047 UINT i=0;
11048 ret=wifi_getNeighboringWiFiDiagnosticResult2(index, &neighbor_ap_array, &array_size);
11049 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11050 for(i=0, pt=neighbor_ap_array; i<array_size; i++, pt++) {
11051 printf(" neighbor %d:\n", i);
11052 printf(" ap_SSID =%s\n", pt->ap_SSID);
11053 printf(" ap_BSSID =%s\n", pt->ap_BSSID);
11054 printf(" ap_Mode =%s\n", pt->ap_Mode);
11055 printf(" ap_Channel =%d\n", pt->ap_Channel);
11056 printf(" ap_SignalStrength =%d\n", pt->ap_SignalStrength);
11057 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11058 printf(" ap_EncryptionMode =%s\n", pt->ap_EncryptionMode);
11059 printf(" ap_SupportedStandards =%s\n", pt->ap_SupportedStandards);
11060 printf(" ap_OperatingStandards =%s\n", pt->ap_OperatingStandards);
11061 printf(" ap_OperatingChannelBandwidth =%s\n", pt->ap_OperatingChannelBandwidth);
11062 printf(" ap_SecurityModeEnabled =%s\n", pt->ap_SecurityModeEnabled);
11063 printf(" ap_BeaconPeriod =%d\n", pt->ap_BeaconPeriod);
11064 printf(" ap_Noise =%d\n", pt->ap_Noise);
11065 printf(" ap_BasicDataTransferRates =%s\n", pt->ap_BasicDataTransferRates);
11066 printf(" ap_SupportedDataTransferRates =%s\n", pt->ap_SupportedDataTransferRates);
11067 printf(" ap_DTIMPeriod =%d\n", pt->ap_DTIMPeriod);
11068 printf(" ap_ChannelUtilization =%d\n", pt->ap_ChannelUtilization);
11069 }
11070 if(neighbor_ap_array)
11071 free(neighbor_ap_array); //make sure to free the list
11072 }
11073 else if(strstr(argv[1], "getApAssociatedDeviceDiagnosticResult")!=NULL) {
11074 wifi_associated_dev_t *associated_dev_array=NULL, *pt=NULL;
11075 UINT array_size=0;
11076 UINT i=0;
11077 ret=wifi_getApAssociatedDeviceDiagnosticResult(index, &associated_dev_array, &array_size);
11078 printf("%s %d: array_size=%d, returns %d\n", argv[1], index, array_size, ret);
11079 for(i=0, pt=associated_dev_array; i<array_size; i++, pt++) {
11080 printf(" associated_dev %d:\n", i);
11081 printf(" cli_OperatingStandard =%s\n", pt->cli_OperatingStandard);
11082 printf(" cli_OperatingChannelBandwidth =%s\n", pt->cli_OperatingChannelBandwidth);
11083 printf(" cli_SNR =%d\n", pt->cli_SNR);
11084 printf(" cli_InterferenceSources =%s\n", pt->cli_InterferenceSources);
11085 printf(" cli_DataFramesSentAck =%lu\n", pt->cli_DataFramesSentAck);
11086 printf(" cli_DataFramesSentNoAck =%lu\n", pt->cli_DataFramesSentNoAck);
11087 printf(" cli_BytesSent =%lu\n", pt->cli_BytesSent);
11088 printf(" cli_BytesReceived =%lu\n", pt->cli_BytesReceived);
11089 printf(" cli_RSSI =%d\n", pt->cli_RSSI);
11090 printf(" cli_MinRSSI =%d\n", pt->cli_MinRSSI);
11091 printf(" cli_MaxRSSI =%d\n", pt->cli_MaxRSSI);
11092 printf(" cli_Disassociations =%d\n", pt->cli_Disassociations);
11093 printf(" cli_AuthenticationFailures =%d\n", pt->cli_AuthenticationFailures);
11094 }
11095 if(associated_dev_array)
11096 free(associated_dev_array); //make sure to free the list
11097 }
11098
11099 if(strstr(argv[1],"wifi_getRadioChannelStats")!=NULL)
11100 {
11101#define MAX_ARRAY_SIZE 64
11102 int i, array_size;
11103 char *p, *ch_str;
11104 wifi_channelStats_t input_output_channelStats_array[MAX_ARRAY_SIZE];
11105
11106 if(argc != 5)
11107 {
11108 printf("Insufficient arguments, Usage: wifihal wifi_getRadioChannelStats <AP-Index> <Array-Size> <Comma-seperated-channel-numbers>\n");
11109 exit(-1);
11110 }
11111 memset(input_output_channelStats_array, 0, sizeof(input_output_channelStats_array));
11112
11113 for (i=0, array_size=atoi(argv[3]), ch_str=argv[4]; i<array_size; i++, ch_str=p)
11114 {
11115 strtok_r(ch_str, ",", &p);
11116 input_output_channelStats_array[i].ch_number = atoi(ch_str);
11117 }
11118 wifi_getRadioChannelStats(atoi(argv[2]), input_output_channelStats_array, array_size);
11119 if(!array_size)
11120 array_size=1;//Need to print current channel statistics
11121 for(i=0; i<array_size; i++)
11122 printf("chan num = %d \t, noise =%d\t ch_utilization_busy_rx = %lld \t,\
11123 ch_utilization_busy_tx = %lld \t,ch_utilization_busy = %lld \t,\
11124 ch_utilization_busy_ext = %lld \t, ch_utilization_total = %lld \t \n",\
11125 input_output_channelStats_array[i].ch_number,\
11126 input_output_channelStats_array[i].ch_noise,\
11127 input_output_channelStats_array[i].ch_utilization_busy_rx,\
11128 input_output_channelStats_array[i].ch_utilization_busy_tx,\
11129 input_output_channelStats_array[i].ch_utilization_busy,\
11130 input_output_channelStats_array[i].ch_utilization_busy_ext,\
11131 input_output_channelStats_array[i].ch_utilization_total);
11132 }
11133
11134 if(strstr(argv[1],"wifi_getAssociatedDeviceDetail")!=NULL)
11135 {
11136 if(argc <= 3 )
11137 {
11138 printf("Insufficient arguments \n");
11139 exit(-1);
11140 }
11141 char mac_addr[20] = {'\0'};
11142 wifi_device_t output_struct;
11143 int dev_index = atoi(argv[3]);
11144
11145 wifi_getAssociatedDeviceDetail(index,dev_index,&output_struct);
11146 mac_addr_ntoa(mac_addr,output_struct.wifi_devMacAddress);
11147 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);
11148 }
11149
11150 if(strstr(argv[1],"wifi_setNeighborReports")!=NULL)
11151 {
11152 if (argc <= 3)
11153 {
11154 printf("Insufficient arguments\n");
11155 exit(-1);
11156 }
11157 char args[256];
11158 wifi_NeighborReport_t *neighborReports;
11159
11160 neighborReports = calloc(argc - 2, sizeof(neighborReports));
11161 if (!neighborReports)
11162 {
11163 printf("Failed to allocate memory");
11164 exit(-1);
11165 }
11166
11167 for (int i = 3; i < argc; ++i)
11168 {
11169 char *val;
11170 int j = 0;
11171 memset(args, 0, sizeof(args));
11172 strncpy(args, argv[i], sizeof(args));
11173 val = strtok(args, ";");
11174 while (val != NULL)
11175 {
11176 if (j == 0)
11177 {
11178 mac_addr_aton(neighborReports[i - 3].bssid, val);
11179 } else if (j == 1)
11180 {
11181 neighborReports[i - 3].info = strtol(val, NULL, 16);
11182 } else if (j == 2)
11183 {
11184 neighborReports[i - 3].opClass = strtol(val, NULL, 16);
11185 } else if (j == 3)
11186 {
11187 neighborReports[i - 3].channel = strtol(val, NULL, 16);
11188 } else if (j == 4)
11189 {
11190 neighborReports[i - 3].phyTable = strtol(val, NULL, 16);
11191 } else {
11192 printf("Insufficient arguments]n\n");
11193 exit(-1);
11194 }
11195 val = strtok(NULL, ";");
11196 j++;
11197 }
11198 }
11199
11200 INT ret = wifi_setNeighborReports(index, argc - 3, neighborReports);
11201 if (ret != RETURN_OK)
11202 {
11203 printf("wifi_setNeighborReports ret = %d", ret);
11204 exit(-1);
11205 }
11206 }
11207 if(strstr(argv[1],"wifi_getRadioIfName")!=NULL)
11208 {
11209 if((ret=wifi_getRadioIfName(index, buf))==RETURN_OK)
11210 printf("%s.\n", buf);
11211 else
11212 printf("Error returned\n");
11213 }
11214 if(strstr(argv[1],"wifi_getApSecurityModesSupported")!=NULL)
11215 {
11216 if((ret=wifi_getApSecurityModesSupported(index, buf))==RETURN_OK)
11217 printf("%s.\n", buf);
11218 else
11219 printf("Error returned\n");
11220 }
11221 if(strstr(argv[1],"wifi_getRadioOperatingChannelBandwidth")!=NULL)
11222 {
11223 if (argc <= 2)
11224 {
11225 printf("Insufficient arguments\n");
11226 exit(-1);
11227 }
11228 char buf[64]= {'\0'};
11229 wifi_getRadioOperatingChannelBandwidth(index,buf);
11230 printf("Current bandwidth is %s \n",buf);
11231 return 0;
11232 }
11233 if(strstr(argv[1],"pushRadioChannel2")!=NULL)
11234 {
11235 if (argc <= 5)
11236 {
11237 printf("Insufficient arguments\n");
11238 exit(-1);
11239 }
11240 UINT channel = atoi(argv[3]);
11241 UINT width = atoi(argv[4]);
11242 UINT beacon = atoi(argv[5]);
11243 INT ret = wifi_pushRadioChannel2(index,channel,width,beacon);
11244 printf("Result = %d", ret);
11245 }
11246
11247 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11248 return 0;
11249}
11250
11251#endif
11252
11253#ifdef WIFI_HAL_VERSION_3
11254
developer1e5aa162022-09-13 16:06:24 +080011255INT BitMapToTransmitRates(UINT bitMap, char *BasicRate)
11256{
11257 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11258 if (bitMap & WIFI_BITRATE_1MBPS)
11259 strcat(BasicRate, "1,");
11260 if (bitMap & WIFI_BITRATE_2MBPS)
11261 strcat(BasicRate, "2,");
11262 if (bitMap & WIFI_BITRATE_5_5MBPS)
11263 strcat(BasicRate, "5.5,");
11264 if (bitMap & WIFI_BITRATE_6MBPS)
11265 strcat(BasicRate, "6,");
11266 if (bitMap & WIFI_BITRATE_9MBPS)
11267 strcat(BasicRate, "9,");
11268 if (bitMap & WIFI_BITRATE_11MBPS)
11269 strcat(BasicRate, "11,");
11270 if (bitMap & WIFI_BITRATE_12MBPS)
11271 strcat(BasicRate, "12,");
11272 if (bitMap & WIFI_BITRATE_18MBPS)
11273 strcat(BasicRate, "18,");
11274 if (bitMap & WIFI_BITRATE_24MBPS)
11275 strcat(BasicRate, "24,");
11276 if (bitMap & WIFI_BITRATE_36MBPS)
11277 strcat(BasicRate, "36,");
11278 if (bitMap & WIFI_BITRATE_48MBPS)
11279 strcat(BasicRate, "48,");
11280 if (bitMap & WIFI_BITRATE_54MBPS)
11281 strcat(BasicRate, "54,");
11282 if (strlen(BasicRate) != 0) // remove last comma
11283 BasicRate[strlen(BasicRate) - 1] = '\0';
11284 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11285 return RETURN_OK;
11286}
11287
11288INT TransmitRatesToBitMap (char *BasicRatesList, UINT *basicRateBitMap)
11289{
11290 UINT BitMap = 0;
11291 char *rate;
11292
11293 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11294 rate = strtok(BasicRatesList, ",");
11295 while(rate != NULL)
11296 {
11297 if (strcmp(rate, "1") == 0)
11298 BitMap |= WIFI_BITRATE_1MBPS;
11299 else if (strcmp(rate, "2") == 0)
11300 BitMap |= WIFI_BITRATE_2MBPS;
11301 else if (strcmp(rate, "5.5") == 0)
11302 BitMap |= WIFI_BITRATE_5_5MBPS;
11303 else if (strcmp(rate, "6") == 0)
11304 BitMap |= WIFI_BITRATE_6MBPS;
11305 else if (strcmp(rate, "9") == 0)
11306 BitMap |= WIFI_BITRATE_9MBPS;
11307 else if (strcmp(rate, "11") == 0)
11308 BitMap |= WIFI_BITRATE_11MBPS;
11309 else if (strcmp(rate, "12") == 0)
11310 BitMap |= WIFI_BITRATE_12MBPS;
11311 else if (strcmp(rate, "18") == 0)
11312 BitMap |= WIFI_BITRATE_18MBPS;
11313 else if (strcmp(rate, "24") == 0)
11314 BitMap |= WIFI_BITRATE_24MBPS;
11315 else if (strcmp(rate, "36") == 0)
11316 BitMap |= WIFI_BITRATE_36MBPS;
11317 else if (strcmp(rate, "48") == 0)
11318 BitMap |= WIFI_BITRATE_48MBPS;
11319 else if (strcmp(rate, "54") == 0)
11320 BitMap |= WIFI_BITRATE_54MBPS;
11321 rate = strtok(NULL, ",");
11322 }
11323 *basicRateBitMap = BitMap;
11324 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11325 return RETURN_OK;
11326}
11327
11328// 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 +080011329INT wifi_setRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11330{
developer1e5aa162022-09-13 16:06:24 +080011331 char buf[128] = {0};
11332 char cmd[128] = {0};
11333 char config_file[64] = {0};
11334 int bandwidth;
11335 int set_mode;
11336 wifi_radio_operationParam_t current_param;
11337
11338 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11339
11340 multiple_set = TRUE;
11341 if (wifi_getRadioOperatingParameters(index, &current_param) != RETURN_OK) {
11342 fprintf(stderr, "%s: wifi_getRadioOperatingParameters return error.\n", __func__);
11343 return RETURN_ERR;
11344 }
11345 if (current_param.autoChannelEnabled != operationParam->autoChannelEnabled) {
11346 if (wifi_setRadioAutoChannelEnable(index, operationParam->autoChannelEnabled) != RETURN_OK) {
11347 fprintf(stderr, "%s: wifi_setRadioAutoChannelEnable return error.\n", __func__);
11348 return RETURN_ERR;
11349 }
11350 }
11351 if (current_param.channelWidth != operationParam->channelWidth || (current_param.channel != operationParam->channel && !operationParam->autoChannelEnabled)) {
11352 if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_20MHZ)
11353 bandwidth = 20;
11354 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_40MHZ)
11355 bandwidth = 40;
11356 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80MHZ)
11357 bandwidth = 80;
11358 else if (operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_160MHZ || operationParam->channelWidth == WIFI_CHANNELBANDWIDTH_80_80MHZ)
11359 bandwidth = 160;
11360 if (wifi_pushRadioChannel2(index, operationParam->channel, bandwidth, operationParam->csa_beacon_count) != RETURN_OK) {
11361 fprintf(stderr, "%s: wifi_pushRadioChannel2 return error.\n", __func__);
11362 return RETURN_ERR;
11363 }
11364 }
11365 if (current_param.variant != operationParam->variant) {
11366 // Two different definition bit map, so need to check every bit.
11367 if (operationParam->variant & WIFI_80211_VARIANT_A)
11368 set_mode |= WIFI_MODE_A;
11369 if (operationParam->variant & WIFI_80211_VARIANT_B)
11370 set_mode |= WIFI_MODE_B;
11371 if (operationParam->variant & WIFI_80211_VARIANT_G)
11372 set_mode |= WIFI_MODE_G;
11373 if (operationParam->variant & WIFI_80211_VARIANT_N)
11374 set_mode |= WIFI_MODE_N;
11375 if (operationParam->variant & WIFI_80211_VARIANT_AC)
11376 set_mode |= WIFI_MODE_AC;
11377 if (operationParam->variant & WIFI_80211_VARIANT_AX)
11378 set_mode |= WIFI_MODE_AX;
11379 // Second parameter is to set channel band width, it is done by wifi_pushRadioChannel2 if changed.
11380 memset(buf, 0, sizeof(buf));
11381 if (wifi_setRadioMode(index, buf, set_mode) != RETURN_OK) {
11382 fprintf(stderr, "%s: wifi_setRadioMode return error.\n", __func__);
11383 return RETURN_ERR;
11384 }
11385 }
11386 if (current_param.dtimPeriod != operationParam->dtimPeriod) {
11387 if (wifi_setApDTIMInterval(index, operationParam->dtimPeriod) != RETURN_OK) {
11388 fprintf(stderr, "%s: wifi_setApDTIMInterval return error.\n", __func__);
11389 return RETURN_ERR;
11390 }
11391 }
11392 if (current_param.beaconInterval != operationParam->beaconInterval) {
11393 if (wifi_setRadioBeaconPeriod(index, operationParam->beaconInterval) != RETURN_OK) {
11394 fprintf(stderr, "%s: wifi_setRadioBeaconPeriod return error.\n", __func__);
11395 return RETURN_ERR;
11396 }
11397 }
11398 if (current_param.operationalDataTransmitRates != operationParam->operationalDataTransmitRates) {
11399 BitMapToTransmitRates(operationParam->operationalDataTransmitRates, buf);
11400 if (wifi_setRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11401 fprintf(stderr, "%s: wifi_setRadioBasicDataTransmitRates return error.\n", __func__);
11402 return RETURN_ERR;
11403 }
11404 }
11405 if (current_param.fragmentationThreshold != operationParam->fragmentationThreshold) {
11406 if (wifi_setRadioFragmentationThreshold(index, operationParam->fragmentationThreshold) != RETURN_OK) {
11407 fprintf(stderr, "%s: wifi_setRadioFragmentationThreshold return error.\n", __func__);
11408 return RETURN_ERR;
11409 }
11410 }
11411 if (current_param.guardInterval != operationParam->guardInterval) {
11412 if (wifi_setGuardInterval(index, operationParam->guardInterval) != RETURN_OK) {
11413 fprintf(stderr, "%s: wifi_setGuardInterval return error.\n", __func__);
11414 return RETURN_ERR;
11415 }
11416 }
11417 if (current_param.transmitPower != operationParam->transmitPower) {
11418 if (wifi_setRadioTransmitPower(index, operationParam->transmitPower) != RETURN_OK) {
11419 fprintf(stderr, "%s: wifi_setRadioTransmitPower return error.\n", __func__);
11420 return RETURN_ERR;
11421 }
11422 }
11423 if (current_param.rtsThreshold != operationParam->rtsThreshold) {
11424 if (wifi_setApRtsThreshold(index, operationParam->rtsThreshold) != RETURN_OK) {
11425 fprintf(stderr, "%s: wifi_setApRtsThreshold return error.\n", __func__);
11426 return RETURN_ERR;
11427 }
11428 }
11429 if (current_param.obssCoex != operationParam->obssCoex) {
11430 if (wifi_setRadioObssCoexistenceEnable(index, operationParam->obssCoex) != RETURN_OK) {
11431 fprintf(stderr, "%s: wifi_setRadioObssCoexistenceEnable return error.\n", __func__);
11432 return RETURN_ERR;
11433 }
11434 }
11435 if (current_param.stbcEnable != operationParam->stbcEnable) {
11436 if (wifi_setRadioSTBCEnable(index, operationParam->stbcEnable) != RETURN_OK) {
11437 fprintf(stderr, "%s: wifi_setRadioSTBCEnable return error.\n", __func__);
11438 return RETURN_ERR;
11439 }
11440 }
11441 if (current_param.greenFieldEnable != operationParam->greenFieldEnable) {
11442 if (wifi_setRadio11nGreenfieldEnable(index, operationParam->greenFieldEnable) != RETURN_OK) {
11443 fprintf(stderr, "%s: wifi_setRadio11nGreenfieldEnable return error.\n", __func__);
11444 return RETURN_ERR;
11445 }
11446 }
11447
11448 // if enable is true, then restart the radio
11449 wifi_setRadioEnable(index, FALSE);
11450 if (operationParam->enable == TRUE)
11451 wifi_setRadioEnable(index, TRUE);
11452 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11453
developer06a01d92022-09-07 16:32:39 +080011454 return RETURN_OK;
11455}
11456
11457INT wifi_getRadioOperatingParameters(wifi_radio_index_t index, wifi_radio_operationParam_t *operationParam)
11458{
developer1e5aa162022-09-13 16:06:24 +080011459 char band[64] = {0};
11460 char buf[256] = {0};
11461 char config_file[64] = {0};
11462 char cmd[128] = {0};
11463 int ret = RETURN_ERR;
11464 int mode = 0;
11465 ULONG channel = 0;
11466 BOOL enabled = FALSE;
developer06a01d92022-09-07 16:32:39 +080011467
11468 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11469 printf("Entering %s index = %d\n", __func__, (int)index);
11470
developer1e5aa162022-09-13 16:06:24 +080011471 memset(operationParam, 0, sizeof(wifi_radio_operationParam_t));
11472 snprintf(config_file, sizeof(config_file), "%s%d.conf", CONFIG_PREFIX, index);
11473 if (wifi_getRadioEnable(index, &enabled) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011474 {
developer1e5aa162022-09-13 16:06:24 +080011475 fprintf(stderr, "%s: wifi_getRadioEnable return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011476 return RETURN_ERR;
11477 }
11478 operationParam->enable = enabled;
11479
11480 memset(band, 0, sizeof(band));
developer1e5aa162022-09-13 16:06:24 +080011481 if (wifi_getRadioOperatingFrequencyBand(index, band) != RETURN_OK)
developer06a01d92022-09-07 16:32:39 +080011482 {
developer1e5aa162022-09-13 16:06:24 +080011483 fprintf(stderr, "%s: wifi_getRadioOperatingFrequencyBand return error.\n", __func__);
developer06a01d92022-09-07 16:32:39 +080011484 return RETURN_ERR;
11485 }
11486
11487 if (!strcmp(band, "2.4GHz"))
developer06a01d92022-09-07 16:32:39 +080011488 operationParam->band = WIFI_FREQUENCY_2_4_BAND;
developer06a01d92022-09-07 16:32:39 +080011489 else if (!strcmp(band, "5GHz"))
developer06a01d92022-09-07 16:32:39 +080011490 operationParam->band = WIFI_FREQUENCY_5_BAND;
developer1e5aa162022-09-13 16:06:24 +080011491 else if (!strcmp(band, "6GHz"))
11492 operationParam->band = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011493 else
11494 {
developer1e5aa162022-09-13 16:06:24 +080011495 fprintf(stderr, "%s: cannot decode band for radio index %d ('%s')\n", __func__, index,
developer06a01d92022-09-07 16:32:39 +080011496 band);
11497 }
11498
developer1e5aa162022-09-13 16:06:24 +080011499 wifi_hostapdRead(config_file, "channel", buf, sizeof(buf));
11500 if (strcmp(buf, "0") == 0 || strcmp(buf, "acs_survey") == 0) {
11501 operationParam->channel = 0;
11502 operationParam->autoChannelEnabled = TRUE;
11503 } else {
11504 operationParam->channel = strtol(buf, NULL, 10);
11505 operationParam->autoChannelEnabled = FALSE;
11506 }
11507
developer06a01d92022-09-07 16:32:39 +080011508 memset(buf, 0, sizeof(buf));
developer1e5aa162022-09-13 16:06:24 +080011509 if (wifi_getRadioOperatingChannelBandwidth(index, buf) != RETURN_OK) {
11510 fprintf(stderr, "%s: wifi_getRadioOperatingChannelBandwidth return error.\n", __func__);
11511 return RETURN_ERR;
11512 }
developer06a01d92022-09-07 16:32:39 +080011513 if (!strcmp(buf, "20MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_20MHZ;
11514 else if (!strcmp(buf, "40MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_40MHZ;
11515 else if (!strcmp(buf, "80MHz")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80MHZ;
developer1e5aa162022-09-13 16:06:24 +080011516 else if (!strcmp(buf, "160")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_160MHZ;
11517 else if (!strcmp(buf, "80+80")) operationParam->channelWidth = WIFI_CHANNELBANDWIDTH_80_80MHZ;
developer06a01d92022-09-07 16:32:39 +080011518 else
11519 {
developer1e5aa162022-09-13 16:06:24 +080011520 fprintf(stderr, "Unknown channel bandwidth: %s\n", buf);
11521 return false;
developer06a01d92022-09-07 16:32:39 +080011522 }
11523
developer1e5aa162022-09-13 16:06:24 +080011524 if (wifi_getRadioMode(index, buf, &mode) != RETURN_OK) {
11525 fprintf(stderr, "%s: wifi_getRadioMode return error.\n", __func__);
11526 return RETURN_ERR;
11527 }
11528 // Two different definition bit map, so need to check every bit.
11529 if (mode & WIFI_MODE_A)
11530 operationParam->variant |= WIFI_80211_VARIANT_A;
11531 if (mode & WIFI_MODE_B)
11532 operationParam->variant |= WIFI_80211_VARIANT_B;
11533 if (mode & WIFI_MODE_G)
11534 operationParam->variant |= WIFI_80211_VARIANT_G;
11535 if (mode & WIFI_MODE_N)
11536 operationParam->variant |= WIFI_80211_VARIANT_N;
11537 if (mode & WIFI_MODE_AC)
11538 operationParam->variant |= WIFI_80211_VARIANT_AC;
11539 if (mode & WIFI_MODE_AX)
11540 operationParam->variant |= WIFI_80211_VARIANT_AX;
11541 if (wifi_getRadioDCSEnable(index, &operationParam->DCSEnabled) != RETURN_OK) {
11542 fprintf(stderr, "%s: wifi_getRadioDCSEnable return error.\n", __func__);
11543 return RETURN_ERR;
developer06a01d92022-09-07 16:32:39 +080011544 }
developer1e5aa162022-09-13 16:06:24 +080011545 if (wifi_getApDTIMInterval(index, &operationParam->dtimPeriod) != RETURN_OK) {
11546 fprintf(stderr, "%s: wifi_getApDTIMInterval return error.\n", __func__);
11547 return RETURN_ERR;
11548 }
11549 if (wifi_getRadioBeaconPeriod(index, &operationParam->dtimPeriod) != RETURN_OK) {
11550 fprintf(stderr, "%s: wifi_getRadioBeaconPeriod return error.\n", __func__);
11551 return RETURN_ERR;
11552 }
developer06a01d92022-09-07 16:32:39 +080011553
developer1e5aa162022-09-13 16:06:24 +080011554 memset(buf, 0, sizeof(buf));
11555 if (wifi_getRadioSupportedDataTransmitRates(index, buf) != RETURN_OK) {
11556 fprintf(stderr, "%s: wifi_getRadioSupportedDataTransmitRates return error.\n", __func__);
11557 return RETURN_ERR;
11558 }
11559 TransmitRatesToBitMap(buf, &operationParam->basicDataTransmitRates);
11560
11561 memset(buf, 0, sizeof(buf));
11562 if (wifi_getRadioBasicDataTransmitRates(index, buf) != RETURN_OK) {
11563 fprintf(stderr, "%s: wifi_getRadioBasicDataTransmitRates return error.\n", __func__);
11564 return RETURN_ERR;
11565 }
11566 TransmitRatesToBitMap(buf, &operationParam->operationalDataTransmitRates);
11567
11568 memset(buf, 0, sizeof(buf));
11569 wifi_hostapdRead(config_file, "fragm_threshold", buf, sizeof(buf));
11570 operationParam->fragmentationThreshold = strtoul(buf, NULL, 10);
11571
11572 if (wifi_getGuardInterval(index, &operationParam->guardInterval) != RETURN_OK) {
11573 fprintf(stderr, "%s: wifi_getGuardInterval return error.\n", __func__);
11574 return RETURN_ERR;
11575 }
11576 if (wifi_getRadioPercentageTransmitPower(index, &operationParam->transmitPower) != RETURN_OK) {
11577 fprintf(stderr, "%s: wifi_getRadioPercentageTransmitPower return error.\n", __func__);
11578 return RETURN_ERR;
11579 }
11580
11581 memset(buf, 0, sizeof(buf));
11582 wifi_hostapdRead(config_file, "rts_threshold", buf, sizeof(buf));
11583 if (strcmp(buf, "-1") == 0) {
11584 operationParam->rtsThreshold = (UINT)-1; // maxuimum unsigned integer value
11585 operationParam->ctsProtection = FALSE;
11586 } else {
11587 operationParam->rtsThreshold = strtoul(buf, NULL, 10);
11588 operationParam->ctsProtection = TRUE;
11589 }
11590
11591 memset(buf, 0, sizeof(buf));
11592 wifi_hostapdRead(config_file, "ht_coex", buf, sizeof(buf));
11593 if (strcmp(buf, "0") == 0)
11594 operationParam->obssCoex = FALSE;
11595 else
11596 operationParam->obssCoex = TRUE;
11597
11598 snprintf(cmd, sizeof(cmd), "cat %s | grep STBC", config_file);
11599 _syscmd(cmd, buf, sizeof(buf));
11600 if (strlen(buf) != 0)
11601 operationParam->stbcEnable = TRUE;
11602 else
11603 operationParam->stbcEnable = FALSE;
11604
11605 if (wifi_getRadio11nGreenfieldEnable(index, &operationParam->greenFieldEnable) != RETURN_OK) {
11606 fprintf(stderr, "%s: wifi_getRadio11nGreenfieldEnable return error.\n", __func__);
11607 return RETURN_ERR;
11608 }
11609
11610 // Below value is hardcoded
11611
11612 operationParam->numSecondaryChannels = 0;
11613 for (int i = 0; i < MAXNUMSECONDARYCHANNELS; i++) {
11614 operationParam->channelSecondary[i] = 0;
11615 }
11616 operationParam->csa_beacon_count = 15;
11617 operationParam->countryCode = wifi_countrycode_US; // hard to convert string to corresponding enum
developer06a01d92022-09-07 16:32:39 +080011618
11619 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11620 return RETURN_OK;
11621}
11622
11623static int array_index_to_vap_index(UINT radioIndex, int arrayIndex)
11624{
11625 if (radioIndex != 0 && radioIndex != 1)
11626 {
11627 printf("%s: Wrong radio index (%d)\n", __func__, index);
11628 return -1;
11629 }
11630
11631 // XXX: hardcode vap indexes for now (0,1 - home, 2,3 - backhaul 6,7 - onboard)
11632 // XXX : assumed radioIndex for 2.4 is 0 radioIndex for 5G is 1
11633
11634 return (arrayIndex * 2) + radioIndex;
11635}
11636
11637INT wifi_getRadioVapInfoMap(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11638{
11639 INT ret;
11640 int i;
11641 BOOL enabled = false;
11642 char buf[256];
11643 wifi_secur_list *secur_item;
11644 int vap_index;
11645 INT mode;
11646 map->num_vaps = 5; // XXX: this is a hack. For both radio let's support 5 vaps for now
11647
11648 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11649 printf("Entering %s index = %d\n", __func__, (int)index);
11650
11651 map->vap_array[index].radio_index = index;
11652 for (i = 0; i < 5; i++)
11653 {
11654 vap_index = array_index_to_vap_index(index, i);
11655 if (vap_index < 0)
11656 {
11657 return RETURN_ERR;
11658 }
11659
11660 strncpy(map->vap_array[i].bridge_name, "brlan0", sizeof(map->vap_array[i].bridge_name) - 1);
11661
11662 map->vap_array[i].vap_index = vap_index;
11663
11664 memset(buf, 0, sizeof(buf));
11665 wifi_getApName(vap_index, buf); // XXX: error handling
11666 strncpy(map->vap_array[i].vap_name, buf, sizeof(map->vap_array[i].vap_name) - 1);
11667
11668 ret = wifi_getSSIDEnable(vap_index, &enabled);
11669 if (ret != RETURN_OK)
11670 {
11671 printf("%s: failed to get SSIDEnable for index %d\n", __func__, i);
11672 return RETURN_ERR;
11673 }
11674 map->vap_array[i].u.bss_info.enabled = enabled;
11675
11676 memset(buf, 0, sizeof(buf));
11677 wifi_getBaseBSSID(vap_index, buf);
11678 sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
11679 &map->vap_array[i].u.bss_info.bssid[0],
11680 &map->vap_array[i].u.bss_info.bssid[1],
11681 &map->vap_array[i].u.bss_info.bssid[2],
11682 &map->vap_array[i].u.bss_info.bssid[3],
11683 &map->vap_array[i].u.bss_info.bssid[4],
11684 &map->vap_array[i].u.bss_info.bssid[5]); // XXX: handle error
11685
11686 wifi_getApSsidAdvertisementEnable(vap_index, &enabled); // XXX: error handling
11687 map->vap_array[i].u.bss_info.showSsid = enabled;
11688
11689 wifi_getApMacAddressControlMode(vap_index, &mode); // XXX: handle errors
11690 if (mode == 0) map->vap_array[i].u.bss_info.mac_filter_enable = false;
11691 else map->vap_array[i].u.bss_info.mac_filter_enable = true;
11692
11693 if (mode == 1) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_white_list;
11694 else if (mode == 2) map->vap_array[i].u.bss_info.mac_filter_mode = wifi_mac_filter_mode_black_list; // XXX: handle wrong mode
11695
11696 memset(buf, 0, sizeof(buf));
11697 wifi_getSSIDNameStatus(vap_index, buf); // XXX: error handling
11698 strncpy(map->vap_array[i].u.bss_info.ssid, buf, sizeof(map->vap_array[i].u.bss_info.ssid) - 1);
11699
11700 wifi_getApSecurityModeEnabled(vap_index, buf);
11701
11702 if (!(secur_item = wifi_get_item_by_str(ARRAY_AND_SIZE(map_security), buf)))
11703 {
11704 printf("%s: ssid_index %d: Failed to decode security mode (%s)\n", __func__, vap_index, buf);
11705 return RETURN_ERR;
11706 }
11707 map->vap_array[i].u.bss_info.security.mode = secur_item->key;
11708
11709 memset(buf, 0, sizeof(buf));
11710 wifi_getApSecurityKeyPassphrase(vap_index, buf); // XXX: error handling
11711 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);
11712
11713 wifi_getNeighborReportActivation(vap_index, &enabled); // XXX: error handling
11714 map->vap_array[i].u.bss_info.nbrReportActivated = enabled;
11715
11716 wifi_getBSSTransitionActivation(vap_index, &enabled); // XXX: error handling
11717 map->vap_array[i].u.bss_info.bssTransitionActivated = enabled;
11718
11719 wifi_getApIsolationEnable(vap_index, &enabled);
11720 map->vap_array[i].u.bss_info.isolation = enabled;
11721 }
11722 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11723 return RETURN_OK;
11724}
11725
11726INT wifi_createVAP(wifi_radio_index_t index, wifi_vap_info_map_t *map)
11727{
11728 unsigned int i;
11729 wifi_vap_info_t *vap_info = NULL;
11730 int acl_mode;
11731 char *sec_str = NULL;
11732
11733 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11734 printf("Entering %s index = %d\n", __func__, (int)index);
11735 for (i = 0; i < map->num_vaps; i++)
11736 {
11737 vap_info = &map->vap_array[i];
11738 printf("Create VAP for ssid_index=%d (vap_num=%d)\n", vap_info->vap_index, i);
11739
11740 if (vap_info->u.bss_info.mac_filter_enable == false) acl_mode = 0;
11741 else
11742 {
11743 if (vap_info->u.bss_info.mac_filter_mode == wifi_mac_filter_mode_black_list) acl_mode = 2;
11744 else acl_mode = 1;
11745 }
11746 wifi_setApMacAddressControlMode(vap_info->vap_index, acl_mode); // XXX: handle errors
11747 wifi_setApSsidAdvertisementEnable(vap_info->vap_index, vap_info->u.bss_info.showSsid); // XXX: handle errors
11748 wifi_setSSIDName(vap_info->vap_index, vap_info->u.bss_info.ssid); // XXX: handle errors
11749
11750 sec_str = wifi_get_str_by_key(ARRAY_AND_SIZE(map_security), vap_info->u.bss_info.security.mode);
11751 if (sec_str)
11752 {
11753 wifi_setApSecurityModeEnabled(vap_info->vap_index, sec_str); // XXX: handle errors
11754 }
11755 else
11756 {
11757 printf("Cannot map security mode: %d\n", (int)vap_info->u.bss_info.security.mode);
11758 }
11759
11760 wifi_setApSecurityKeyPassphrase(vap_info->vap_index, vap_info->u.bss_info.security.u.key.key); // XXX: handle errors, handle radius
11761 wifi_setApIsolationEnable(vap_info->vap_index, vap_info->u.bss_info.isolation);
11762
11763 wifi_setNeighborReportActivation(vap_info->vap_index, vap_info->u.bss_info.nbrReportActivated); // XXX: handle errors
11764 wifi_setBSSTransitionActivation(vap_info->vap_index, vap_info->u.bss_info.bssTransitionActivated); // XXX: handle errors
11765
11766 printf("Calling wifi_applySSIDSettings for index: %d\n", vap_info->vap_index);
11767
11768 wifi_setSSIDEnable(vap_info->vap_index, vap_info->u.bss_info.enabled); // XXX: handle errors
11769 wifi_applySSIDSettings(vap_info->vap_index); // XXX: handle errors, don't call if no changes.
11770 }
11771 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11772 return RETURN_OK;
11773}
11774
11775int parse_channel_list_int_arr(char *pchannels, wifi_channels_list_t* chlistptr)
11776{
11777 char *token, *next;
11778 const char s[2] = ",";
11779 int count =0;
11780
11781 /* get the first token */
11782 token = strtok_r(pchannels, s, &next);
11783
11784 /* walk through other tokens */
11785 while( token != NULL && count < MAX_CHANNELS) {
11786 chlistptr->channels_list[count++] = atoi(token);
11787 token = strtok_r(NULL, s, &next);
11788 }
11789
11790 return count;
11791}
11792
11793static int getRadioCapabilities(int radioIndex, wifi_radio_capabilities_t *rcap)
11794{
11795 INT status;
11796 wifi_channels_list_t *chlistp;
11797 CHAR output_string[64];
11798 CHAR pchannels[128];
developer1e5aa162022-09-13 16:06:24 +080011799 wifi_band band;
developer06a01d92022-09-07 16:32:39 +080011800
11801 if(rcap == NULL)
11802 {
11803 return RETURN_ERR;
11804 }
11805
11806 rcap->numSupportedFreqBand = 1;
developer1e5aa162022-09-13 16:06:24 +080011807 band = wifi_index_to_band(radioIndex);
developer06a01d92022-09-07 16:32:39 +080011808
developer1e5aa162022-09-13 16:06:24 +080011809 if (band == band_2_4)
11810 rcap->band[0] = WIFI_FREQUENCY_2_4_BAND;
11811 else if (band == band_5)
11812 rcap->band[0] = WIFI_FREQUENCY_5_BAND;
11813 else if (band == band_6)
11814 rcap->band[0] = WIFI_FREQUENCY_6_BAND;
developer06a01d92022-09-07 16:32:39 +080011815
11816 chlistp = &(rcap->channel_list[0]);
11817 memset(pchannels, 0, sizeof(pchannels));
11818
11819 /* possible number of radio channels */
11820 status = wifi_getRadioPossibleChannels(radioIndex, pchannels);
11821 {
11822 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, pchannels);
11823 }
11824 /* Number of channels and list*/
11825 chlistp->num_channels = parse_channel_list_int_arr(pchannels, chlistp);
11826
11827 /* autoChannelSupported */
11828 /* always ON with wifi_getRadioAutoChannelSupported */
11829 rcap->autoChannelSupported = TRUE;
11830
11831 /* DCSSupported */
11832 /* always ON with wifi_getRadioDCSSupported */
11833 rcap->DCSSupported = TRUE;
11834
11835 /* zeroDFSSupported - TBD */
11836 rcap->zeroDFSSupported = FALSE;
11837
11838 /* Supported Country List*/
11839 memset(output_string, 0, sizeof(output_string));
11840 status = wifi_getRadioCountryCode(radioIndex, output_string);
11841 if( status != 0 ) {
11842 printf("[wifi_hal dbg] : func[%s] line[%d] error_ret[%d] radio_index[%d] output[%s]\n", __FUNCTION__, __LINE__, status, radioIndex, output_string);
11843 return RETURN_ERR;
11844 } else {
11845 printf("[wifi_hal dbg] : func[%s] line[%d], output [%s]\n", __FUNCTION__, __LINE__, output_string);
11846 }
11847 if(!strcmp(output_string,"US")){
11848 rcap->countrySupported[0] = wifi_countrycode_US;
11849 rcap->countrySupported[1] = wifi_countrycode_CA;
11850 } else if (!strcmp(output_string,"CA")) {
11851 rcap->countrySupported[0] = wifi_countrycode_CA;
11852 rcap->countrySupported[1] = wifi_countrycode_US;
11853 } else {
11854 printf("[wifi_hal dbg] : func[%s] line[%d] radio_index[%d] Invalid Country [%s]\n", __FUNCTION__, __LINE__, radioIndex, output_string);
11855 }
11856
11857 rcap->numcountrySupported = 2;
11858
11859 /* csi */
11860 rcap->csi.maxDevices = 8;
11861 rcap->csi.soudingFrameSupported = TRUE;
11862
11863 snprintf(rcap->ifaceName, 64, "wlan%d", radioIndex);
11864
11865 /* channelWidth - all supported bandwidths */
11866 int i=0;
11867 rcap->channelWidth[i] = 0;
11868 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11869 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11870 WIFI_CHANNELBANDWIDTH_40MHZ);
11871
11872 }
developer1e5aa162022-09-13 16:06:24 +080011873 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) || rcap->band[i] & (WIFI_FREQUENCY_6_BAND)) {
developer06a01d92022-09-07 16:32:39 +080011874 rcap->channelWidth[i] |= (WIFI_CHANNELBANDWIDTH_20MHZ |
11875 WIFI_CHANNELBANDWIDTH_40MHZ |
11876 WIFI_CHANNELBANDWIDTH_80MHZ | WIFI_CHANNELBANDWIDTH_160MHZ);
11877 }
11878
11879
11880 /* mode - all supported variants */
11881 // rcap->mode[i] = WIFI_80211_VARIANT_H;
11882 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011883 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 +080011884 }
11885 else if (rcap->band[i] & WIFI_FREQUENCY_5_BAND ) {
developer1e5aa162022-09-13 16:06:24 +080011886 rcap->mode[i] = ( WIFI_80211_VARIANT_A | WIFI_80211_VARIANT_N | WIFI_80211_VARIANT_AC | WIFI_80211_VARIANT_AX );
11887 }
11888 else if (rcap->band[i] & WIFI_FREQUENCY_6_BAND) {
11889 rcap->mode[i] = ( WIFI_80211_VARIANT_AX );
developer06a01d92022-09-07 16:32:39 +080011890 }
11891 rcap->maxBitRate[i] = ( rcap->band[i] & WIFI_FREQUENCY_2_4_BAND ) ? 300 :
11892 ((rcap->band[i] & WIFI_FREQUENCY_5_BAND) ? 1734 : 0);
11893
11894 /* supportedBitRate - all supported bitrates */
11895 rcap->supportedBitRate[i] = 0;
11896 if (rcap->band[i] & WIFI_FREQUENCY_2_4_BAND) {
11897 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11898 WIFI_BITRATE_11MBPS | WIFI_BITRATE_12MBPS);
11899 }
developer1e5aa162022-09-13 16:06:24 +080011900 else if (rcap->band[i] & (WIFI_FREQUENCY_5_BAND ) | rcap->band[i] & (WIFI_FREQUENCY_6_BAND )) {
developer06a01d92022-09-07 16:32:39 +080011901 rcap->supportedBitRate[i] |= (WIFI_BITRATE_6MBPS | WIFI_BITRATE_9MBPS |
11902 WIFI_BITRATE_12MBPS | WIFI_BITRATE_18MBPS | WIFI_BITRATE_24MBPS |
11903 WIFI_BITRATE_36MBPS | WIFI_BITRATE_48MBPS | WIFI_BITRATE_54MBPS);
11904 }
11905
11906
11907 rcap->transmitPowerSupported_list[i].numberOfElements = 5;
11908 rcap->transmitPowerSupported_list[i].transmitPowerSupported[0]=12;
11909 rcap->transmitPowerSupported_list[i].transmitPowerSupported[1]=25;
11910 rcap->transmitPowerSupported_list[i].transmitPowerSupported[2]=50;
11911 rcap->transmitPowerSupported_list[i].transmitPowerSupported[3]=75;
11912 rcap->transmitPowerSupported_list[i].transmitPowerSupported[4]=100;
11913 rcap->cipherSupported = 0;
11914 rcap->cipherSupported |= WIFI_CIPHER_CAPA_ENC_TKIP | WIFI_CIPHER_CAPA_ENC_CCMP;
11915 rcap->maxNumberVAPs = MAX_NUM_VAP_PER_RADIO;
11916
11917 return RETURN_OK;
11918}
11919
11920INT wifi_getHalCapability(wifi_hal_capability_t *cap)
11921{
11922 INT status, radioIndex;
11923 char cmd[MAX_BUF_SIZE], output[MAX_BUF_SIZE];
11924 int iter = 0;
11925 unsigned int j;
11926 wifi_interface_name_idex_map_t *iface_info;
11927
11928 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11929
11930 memset(cap, 0, sizeof(wifi_hal_capability_t));
11931
11932 /* version */
11933 cap->version.major = WIFI_HAL_MAJOR_VERSION;
11934 cap->version.minor = WIFI_HAL_MINOR_VERSION;
11935
11936 /* number of radios platform property */
11937 snprintf(cmd, sizeof(cmd), "ls -d /sys/class/net/wlan* | wc -l");
11938 _syscmd(cmd, output, sizeof(output));
11939 cap->wifi_prop.numRadios = atoi(output);
11940
11941 for(radioIndex=0; radioIndex < cap->wifi_prop.numRadios; radioIndex++)
11942 {
11943 status = getRadioCapabilities(radioIndex, &(cap->wifi_prop.radiocap[radioIndex]));
11944 if (status != 0) {
11945 printf("%s: getRadioCapabilities idx = %d\n", __FUNCTION__, radioIndex);
11946 return RETURN_ERR;
11947 }
11948
11949 for (j = 0; j < cap->wifi_prop.radiocap[radioIndex].maxNumberVAPs; j++)
11950 {
11951 if (iter >= MAX_NUM_RADIOS * MAX_NUM_VAP_PER_RADIO)
11952 {
11953 printf("%s: to many vaps for index map (%d)\n", __func__, iter);
11954 return RETURN_ERR;
11955 }
11956 iface_info = &cap->wifi_prop.interface_map[iter];
11957 iface_info->phy_index = radioIndex; // XXX: parse phyX index instead
11958 iface_info->rdk_radio_index = radioIndex;
11959 memset(output, 0, sizeof(output));
11960 if (wifi_getRadioIfName(radioIndex, output) == RETURN_OK)
11961 {
11962 strncpy(iface_info->interface_name, output, sizeof(iface_info->interface_name) - 1);
11963 }
11964 // TODO: bridge name
11965 // TODO: vlan id
11966 // TODO: primary
11967 iface_info->index = array_index_to_vap_index(radioIndex, j);
11968 memset(output, 0, sizeof(output));
11969 if (iface_info >= 0 && wifi_getApName(iface_info->index, output) == RETURN_OK)
11970 {
11971 strncpy(iface_info->vap_name, output, sizeof(iface_info->vap_name) - 1);
11972 }
11973 iter++;
11974 }
11975 }
11976
11977 cap->BandSteeringSupported = FALSE;
11978 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
11979 return RETURN_OK;
11980}
11981
11982INT wifi_setApSecurity(INT ap_index, wifi_vap_security_t *security)
11983{
developer587c1b62022-09-27 15:58:59 +080011984 char buf[128] = {0};
11985 char config_file[128] = {0};
11986 char password[64] = {0};
11987 char mfp[32] = {0};
11988 char wpa_mode[32] = {0};
11989 struct params params = {0};
11990
11991 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
11992
11993 multiple_set = TRUE;
11994 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
11995 if (security->mode == wifi_security_mode_none) {
11996 strcpy(wpa_mode, "None");
11997 } else if (security->mode == wifi_security_mode_wpa_personal)
11998 strcpy(wpa_mode, "WPA-Personal");
11999 else if (security->mode == wifi_security_mode_wpa2_personal)
12000 strcpy(wpa_mode, "WPA2-Personal");
12001 else if (security->mode == wifi_security_mode_wpa_wpa2_personal)
12002 strcpy(wpa_mode, "WPA-WPA2-Personal");
12003 else if (security->mode == wifi_security_mode_wpa_enterprise)
12004 strcpy(wpa_mode, "WPA-Enterprise");
12005 else if (security->mode == wifi_security_mode_wpa2_enterprise)
12006 strcpy(wpa_mode, "WPA2-Enterprise");
12007 else if (security->mode == wifi_security_mode_wpa_wpa2_enterprise)
12008 strcpy(wpa_mode, "WPA-WPA2-Enterprise");
12009 else if (security->mode == wifi_security_mode_wpa3_personal || security->mode == wifi_security_mode_wpa3_transition)
12010 strcpy(wpa_mode, "WPA3-Personal");
12011 else if (security->mode == wifi_security_mode_wpa3_enterprise)
12012 strcpy(wpa_mode, "WPA3-Enterprise");
12013
12014 wifi_setApSecurityModeEnabled(ap_index, wpa_mode);
12015
12016 strncpy(password, security->u.key.key, 63);
12017 password[63] = '\0';
12018 wifi_setApSecurityKeyPassphrase(ap_index, password);
12019
12020 if (security->mode != wifi_security_mode_none) {
12021 memset(&params, 0, sizeof(params));
12022 params.name = "wpa_pairwise";
12023 if (security->encr == wifi_encryption_tkip)
12024 params.value = "TKIP";
12025 else if (security->encr == wifi_encryption_aes)
12026 params.value = "CCMP";
12027 else if (security->encr == wifi_encryption_aes_tkip)
12028 params.value = "TKIP CCMP";
12029 wifi_hostapdWrite(config_file, &params, 1);
12030 }
12031
12032 if (security->mfp == wifi_mfp_cfg_disabled)
12033 strcpy(mfp, "Disable");
12034 else if (security->mfp == wifi_mfp_cfg_optional)
12035 strcpy(mfp, "Optional");
12036 else if (security->mfp == wifi_mfp_cfg_required)
12037 strcpy(mfp, "Required");
12038 wifi_setApSecurityMFPConfig(ap_index, mfp);
12039
12040 memset(&params, 0, sizeof(params));
12041 params.name = "transition_disable";
12042 if (security->wpa3_transition_disable == TRUE)
12043 params.value = "0x01";
12044 else
12045 params.value = "0x00";
12046 wifi_hostapdWrite(config_file, &params, 1);
12047
12048 memset(&params, 0, sizeof(params));
12049 params.name = "wpa_group_rekey";
12050 snprintf(buf, sizeof(buf), "%d", security->rekey_interval);
12051 params.value = buf;
12052 wifi_hostapdWrite(config_file, &params, 1);
12053
12054 memset(&params, 0, sizeof(params));
12055 params.name = "wpa_strict_rekey";
12056 params.value = security->strict_rekey?"1":"0";
12057 wifi_hostapdWrite(config_file, &params, 1);
12058
12059 memset(&params, 0, sizeof(params));
12060 params.name = "wpa_pairwise_update_count";
12061 snprintf(buf, sizeof(buf), "%u", security->eapol_key_retries);
12062 params.value = buf;
12063 wifi_hostapdWrite(config_file, &params, 1);
12064
12065 memset(&params, 0, sizeof(params));
12066 params.name = "disable_pmksa_caching";
12067 params.value = security->disable_pmksa_caching?"1":"0";
12068 wifi_hostapdWrite(config_file, &params, 1);
12069
12070 wifi_setApEnable(ap_index, FALSE);
12071 wifi_setApEnable(ap_index, TRUE);
12072
12073 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12074
developer06a01d92022-09-07 16:32:39 +080012075 return RETURN_OK;
12076}
12077
12078INT wifi_getApSecurity(INT ap_index, wifi_vap_security_t *security)
12079{
developer587c1b62022-09-27 15:58:59 +080012080 char buf[128] = {0};
12081 char config_file[128] = {0};
12082 int disable = 0;
12083 // struct params params = {0};
12084
12085 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12086 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, ap_index);
12087 wifi_getApSecurityModeEnabled(ap_index, buf); // Get wpa config
12088 security->mode = wifi_security_mode_none;
12089 if (strlen(buf) != 0) {
12090 if (strcmp(buf, "WPA-Personal"))
12091 security->mode = wifi_security_mode_wpa_personal;
12092 else if (strcmp(buf, "WPA2-Personal"))
12093 security->mode = wifi_security_mode_wpa2_personal;
12094 else if (strcmp(buf, "WPA-WPA2-Personal"))
12095 security->mode = wifi_security_mode_wpa_wpa2_personal;
12096 else if (strcmp(buf, "WPA-Enterprise"))
12097 security->mode = wifi_security_mode_wpa_enterprise;
12098 else if (strcmp(buf, "WPA2-Enterprise"))
12099 security->mode = wifi_security_mode_wpa2_enterprise;
12100 else if (strcmp(buf, "WPA-WPA2-Enterprise"))
12101 security->mode = wifi_security_mode_wpa_wpa2_enterprise;
12102 else if (strcmp(buf, "WPA3-Personal"))
12103 security->mode = wifi_security_mode_wpa3_personal;
12104 else if (strcmp(buf, "WPA3-Transition"))
12105 security->mode = wifi_security_mode_wpa3_transition;
12106 else if (strcmp(buf, "WPA3-Enterprise"))
12107 security->mode = wifi_security_mode_wpa3_enterprise;
12108 }
12109
12110 wifi_hostapdRead(config_file,"wpa_pairwise",buf,sizeof(buf));
12111 if (security->mode == wifi_security_mode_none)
12112 security->encr = wifi_encryption_none;
12113 else {
12114 if (strcmp(buf, "TKIP") == 0)
12115 security->encr = wifi_encryption_tkip;
12116 else if (strcmp(buf, "CCMP") == 0)
12117 security->encr = wifi_encryption_aes;
12118 else
12119 security->encr = wifi_encryption_aes_tkip;
12120 }
12121
12122 memset(buf, 0, sizeof(buf));
12123 wifi_getApSecurityMFPConfig(ap_index, buf);
12124 if (strcmp(buf, "Disabled") == 0)
12125 security->mfp = wifi_mfp_cfg_disabled;
12126 else if (strcmp(buf, "Optional") == 0)
12127 security->mfp = wifi_mfp_cfg_optional;
12128 else if (strcmp(buf, "Required") == 0)
12129 security->mfp = wifi_mfp_cfg_required;
12130
12131 memset(buf, 0, sizeof(buf));
12132 security->wpa3_transition_disable = FALSE;
12133 wifi_hostapdRead(config_file, "transition_disable", buf, sizeof(buf));
12134 disable = strtol(buf, NULL, 16);
12135 if (disable != 0)
12136 security->wpa3_transition_disable = TRUE;
12137
12138 memset(buf, 0, sizeof(buf));
12139 wifi_hostapdRead(config_file, "wpa_group_rekey", buf, sizeof(buf));
12140 if (strlen(buf) == 0)
12141 security->rekey_interval = 86400;
12142 else
12143 security->rekey_interval = strtol(buf, NULL, 10);
12144
12145 memset(buf, 0, sizeof(buf));
12146 wifi_hostapdRead(config_file, "wpa_strict_rekey", buf, sizeof(buf));
12147 if (strlen(buf) == 0)
12148 security->strict_rekey = 1;
12149 else
12150 security->strict_rekey = strtol(buf, NULL, 10);
12151
12152 memset(buf, 0, sizeof(buf));
12153 wifi_hostapdRead(config_file, "wpa_pairwise_update_count", buf, sizeof(buf));
12154 if (strlen(buf) == 0)
12155 security->eapol_key_retries = 4;
12156 else
12157 security->eapol_key_retries = strtol(buf, NULL, 10);
12158
12159 memset(buf, 0, sizeof(buf));
12160 wifi_hostapdRead(config_file, "disable_pmksa_caching", buf, sizeof(buf));
12161 if (strlen(buf) == 0)
12162 security->disable_pmksa_caching = FALSE;
12163 else
12164 security->disable_pmksa_caching = strtol(buf, NULL, 10)?TRUE:FALSE;
12165
12166 /* TODO
12167 eapol_key_timeout, eap_identity_req_timeout, eap_identity_req_retries, eap_req_timeout, eap_req_retries
12168 */
12169 security->eapol_key_timeout = 1000; // Unit is ms. The default value in protocol.
12170 security->eap_identity_req_timeout = 0;
12171 security->eap_identity_req_retries = 0;
12172 security->eap_req_timeout = 0;
12173 security->eap_req_retries = 0;
12174 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
developer06a01d92022-09-07 16:32:39 +080012175 return RETURN_OK;
12176}
12177
12178#endif /* WIFI_HAL_VERSION_3 */
12179
12180#ifdef WIFI_HAL_VERSION_3_PHASE2
12181INT wifi_getApAssociatedDevice(INT ap_index, mac_address_t *output_deviceMacAddressArray, UINT maxNumDevices, UINT *output_numDevices)
12182{
developer13df9332022-09-27 16:53:22 +080012183 char cmd[128] = {0};
12184 char buf[128] = {0};
12185 char *mac_addr = NULL;
12186 BOOL status = FALSE;
12187 size_t len = 0;
12188
12189 if(ap_index > MAX_APS)
12190 return RETURN_ERR;
12191
12192 *output_numDevices = 0;
12193 wifi_getApEnable(ap_index, &status);
12194 if (status == FALSE)
12195 return RETURN_OK;
12196
12197 sprintf(cmd, "hostapd_cli -i %s%d list_sta", AP_PREFIX, ap_index);
12198 _syscmd(cmd, buf, sizeof(buf));
12199
12200 mac_addr = strtok(buf, "\n");
12201 for (int i = 0; i < maxNumDevices && mac_addr != NULL; i++) {
12202 *output_numDevices = i + 1;
12203 fprintf(stderr, "mac_addr: %s\n", mac_addr);
12204 addr_ptr = output_deviceMacAddressArray[i];
12205 mac_addr_aton(addr_ptr, mac_addr);
12206 mac_addr = strtok(NULL, "\n");
12207 }
12208
12209 return RETURN_OK;
developer06a01d92022-09-07 16:32:39 +080012210}
12211#else
12212INT wifi_getApAssociatedDevice(INT ap_index, CHAR *output_buf, INT output_buf_size)
12213{
12214 char cmd[128];
12215 BOOL status = false;
12216
12217 if(ap_index > MAX_APS || output_buf == NULL || output_buf_size <= 0)
12218 return RETURN_ERR;
12219
12220 output_buf[0] = '\0';
12221
12222 wifi_getApEnable(ap_index,&status);
12223 if (!status)
12224 return RETURN_OK;
12225
12226 sprintf(cmd, "hostapd_cli -i %s%d list_sta | tr '\\n' ',' | sed 's/.$//'", AP_PREFIX, ap_index);
12227 _syscmd(cmd, output_buf, output_buf_size);
12228
12229 return RETURN_OK;
12230}
12231#endif
developer2f513ab2022-09-13 14:26:06 +080012232
12233INT wifi_getProxyArp(INT apIndex, BOOL *enable)
12234{
12235 char output[16]={'\0'};
12236 char config_file[MAX_BUF_SIZE] = {0};
12237
12238 if (!enable)
12239 return RETURN_ERR;
12240
12241 sprintf(config_file, "%s%d.conf", CONFIG_PREFIX, apIndex);
12242 wifi_hostapdRead(config_file, "proxy_arp", output, sizeof(output));
12243
12244 if (strlen(output) == 0)
12245 *enable = FALSE;
12246 else if (strncmp(output, "1", 1) == 0)
12247 *enable = TRUE;
12248 else
12249 *enable = FALSE;
12250
12251 wifi_dbg_printf("\n[%s]: proxy_arp is : %s", __func__, output);
12252 return RETURN_OK;
12253}
developer2d9c30f2022-09-13 15:06:14 +080012254
12255INT wifi_getRadioStatsEnable(INT radioIndex, BOOL *output_enable)
12256{
12257 if (NULL == output_enable || !(radioIndex==0 || radioIndex==1))
12258 return RETURN_ERR;
12259 *output_enable=TRUE;
12260 return RETURN_OK;
12261}
developerfd7d2892022-09-13 16:44:53 +080012262
12263INT wifi_getTWTsessions(INT ap_index, UINT maxNumberSessions, wifi_twt_sessions_t *twtSessions, UINT *numSessionReturned)
12264{
12265 char cmd[128] = {0};
12266 char buf[128] = {0};
12267 char line[128] = {0};
12268 size_t len = 0;
12269 ssize_t read = 0;
12270 FILE *f = NULL;
12271 int index = 0;
12272 int exp = 0;
12273 int mantissa = 0;
12274 int duration = 0;
12275 int radio_index = 0;
12276 int max_radio_num = 0;
12277 uint twt_wake_interval = 0;
12278
12279 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
12280
12281 wifi_getMaxRadioNumber(&max_radio_num);
12282 radio_index = ap_index % max_radio_num;
12283 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | wc -l", radio_index);
12284 _syscmd(cmd, buf, sizeof(buf));
12285 *numSessionReturned = strtol(buf, NULL, 10) - 1;
12286 if (*numSessionReturned > maxNumberSessions)
12287 *numSessionReturned = maxNumberSessions;
12288 else if (*numSessionReturned < 1) {
12289 *numSessionReturned = 0;
12290 return RETURN_OK;
12291 }
12292
12293 sprintf(cmd, "cat /sys/kernel/debug/ieee80211/phy%d/mt76/twt_stats | tail -n %d | tr '|' ' ' | tr -s ' '", radio_index, *numSessionReturned);
12294 if ((f = popen(cmd, "r")) == NULL) {
12295 wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
12296 return RETURN_ERR;
12297 }
12298
12299 // the format of each line is "[wcid] [id] [flags] [exp] [mantissa] [duration] [tsf]"
12300 while((read = fgets(line, sizeof(line), f)) != NULL) {
12301 char *tmp = NULL;
12302 strcpy(buf, line);
12303 tmp = strtok(buf, " ");
12304 twtSessions[index].numDevicesInSession = strtol(tmp, NULL, 10);
12305 tmp = strtok(NULL, " ");
12306 twtSessions[index].twtParameters.operation.flowID = strtol(tmp, NULL, 10);
12307 tmp = strtok(NULL, " ");
12308 if (strstr(tmp, "t")) {
12309 twtSessions[index].twtParameters.operation.trigger_enabled = TRUE;
12310 }
12311 if (strstr(tmp, "a")) {
12312 twtSessions[index].twtParameters.operation.announced = TRUE;
12313 }
12314 tmp = strtok(NULL, " ");
12315 exp = strtol(tmp, NULL, 10);
12316 tmp = strtok(NULL, " ");
12317 mantissa = strtol(tmp, NULL, 10);
12318 tmp = strtok(NULL, " ");
12319 duration = strtol(tmp, NULL, 10);
12320
12321 // only implicit supported
12322 twtSessions[index].twtParameters.operation.implicit = TRUE;
12323 // only individual agreement supported
12324 twtSessions[index].twtParameters.agreement = wifi_twt_agreement_type_individual;
12325
12326 // wakeInterval_uSec is a unsigned integer, but the maximum TWT wake interval could be 2^15 (mantissa) * 2^32 = 2^47.
12327 twt_wake_interval = mantissa * (1 << exp);
12328 if (twt_wake_interval/mantissa != (1 << exp)) {
12329 // Overflow handling
12330 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = -1; // max unsigned int
12331 } else {
12332 twtSessions[index].twtParameters.params.individual.wakeInterval_uSec = twt_wake_interval;
12333 }
12334 twtSessions[index].twtParameters.params.individual.minWakeDuration_uSec = duration * 256;
12335 index++;
12336 }
12337
12338 pclose(f);
12339 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
12340 return RETURN_OK;
12341}